tag:blogger.com,1999:blog-45777598864218502502024-02-19T05:50:24.426+00:00Learn Verilog by ExampleEasy FPGA Code Using VerilogUnknownnoreply@blogger.comBlogger14125tag:blogger.com,1999:blog-4577759886421850250.post-87070823385359029442020-06-16T16:18:00.000+01:002020-06-16T16:18:04.149+01:00Serial Receiver and Transmitter (UART) in Verilog | FPGA<div><b><u><font size="5">Note:</font></u></b> <i>This was a post I wrote back in 2014 as I was teaching myself Verilog, but never got around to finishing the code for it and thus this post remained as a draft. I apologize that this is not in line with my other previous blog posts as it does not have a working code and is not demonstrated working in a video. But I am publishing this in hopes that someone researching this topic may find my introductory text on the topic useful.</i></div><div><i><br /></i></div><div><br /></div>UART stands for Universal Asynchronous Receiver and Transmitter. It is a system that is a capable of sending parallel data using a serial line. As the name indicates, the UART consists of a transmitter and a receiver. The transmitter accepts data in parallel and then by using a shift register send the data out bit by bit using predetermined parameters. Similarly the receiver accepts the data serially and then compiles the data using a shift register. Data is recognized by following a fixed format while transmitting and receiving, data sent consists of a <i>start </i>bit, <i>data </i>bits an optional <i>parity </i>bit and finally a <i>stop </i>bit. The transmission line will stay at 1 when it is idle, transmission starts when a 0 (start bit) is detected. This is followed by 8 data bits, followed by an optional parity bit. The parity bit is used for error detection, it can either be even parity or odd parity. The optional parity bit is followed by the stop bit(s) which marks the end of transmission for that word. The number of stop bits can be 1, 1.5 or 2.<br />
<br />
The 'set parameters' that I mentioned earlier are important because no clock information is sent over the transmission line and smooth operations are ensured by these parameters, which are the baud rate (bits per second), the number of data bits (some systems use 6 or 7 data bits instead of the standard 8) and the number of stop bits. The commonly used baud rates are 2400, 4800, 9600 and 19,200.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmmAFXvOVuBhTccvo-Jz2jn4UWGfP8SteTyH139FVLdiXETxPUQku8XXXtqc-ffcXJHDBAxGGR6PZWzR2I-m922wWQCAQ1ezklG-_bSzWdSu-qNBC0SxFpVjW1HYBwoF7jByP9Gi5GvwCV/s1600/Serial_character_transmission.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="137" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmmAFXvOVuBhTccvo-Jz2jn4UWGfP8SteTyH139FVLdiXETxPUQku8XXXtqc-ffcXJHDBAxGGR6PZWzR2I-m922wWQCAQ1ezklG-_bSzWdSu-qNBC0SxFpVjW1HYBwoF7jByP9Gi5GvwCV/s400/Serial_character_transmission.png" width="400" /></a></div>
<br />
For example the above image shows data transfer that starts with the start bit, followed by 8 data bits, the optional parity bit and finally stop bit. Do note that the least significant bit (LSB) is always sent first.<br />
<br />
As mentioned before no clock information is sent during data transmission and the receiver is still able to detect every bit. It achieves this by using an oversampling procedure. Oversampling procedure is to sample every incoming bits multiple times. For 1 stop bit the most common oversampling rate is 16, which means that each incoming bit is sampled 16 times. For 1.5 stop bits the over sampling rate will be 24 and for 2 stop bits the oversampling rate will be 36. Understanding the oversampling procedure is essential to grasping the concept of serial communication.<br />
<br />
<h3>
Oversampling Procedure in Serial Communication</h3>
<br />
Since I will be using 1 stop bit the oversampling rate will be 16. I am going to use a couple counters to keep track of the sampling process. Now assume that the parameters we are using consists of 'x' data bits. The oversampling will proceed as follows:<br />
<ul>
<li>As soon as the start bit is detected at the receiver, the sampling counter will start and count till 7 (half of 16). This ensures that the middle of the start bit is reached.</li>
<li>Now using another counter start counting till 15 (starting from 0, this makes it 16 counts). When 15 is reached we can be sure that the receiver has reached the middle of the first data bit. Move this bit to a shift register and restart this counter. Repeat this step until all data bits are accepted or repeat it 'x - 1' times.</li>
<li>Use the same counter procedure to accept the optional parity bit and the stop bit.</li>
</ul>
Because of this oversampling procedure the baud rate will be very low as compared to the clock rate. And that is why this method is not recommended for high data rate transmission.<br />
<br />
<h3>
Designing the Baud Rate Generator </h3>
<br />
The next step is to design the baud rate generator. As mentioned above the commonly used baud rates are 2400, 4800, 9600 and 19,200. Here I will be using the 19,200 baud rate. To design a counter for our designated baud rate is connected to the selected oversampling rate and since our over sampling rate is 16 ( 16 times the baud rate) we have <i>19,200 * 16 = 307,200</i>. Now since I know the board I am using (BASYS2) has a 50 MHz clock, I can calculate the counter length needed for this by:<br />
<br />
<i>50M / 307,200 = 162.7 ~~ 163.</i><br />
<br />
The width of the register that will count to 163 can be calculated by using the method explain here: To calculate an accurate time delay in verilog. So by using the log method I know that I need an 8 bit wide register to count up to 163.<br />
<br />
Based on the nature of this design I will be using Finite State Machine with Data path (FSMD) to code this receiver. The finite states will follow the same procedure as explained above.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4577759886421850250.post-33866357381070608912013-03-22T17:10:00.000+00:002013-03-22T18:04:10.893+00:00Reaction Timer | Reflex Tester in Verilog and FPGAThis post will be about programming a reaction timer in verilog and make it ready for FPGA implementation which in our case will be on the BASYS2 (Spartan 3E) board but can be programmed for any other board by simply changing the .ucf file. The reaction timer or reflex tester will check and time how fast you can respond after seeing a visual stimulus or in other words it will test your hand eye co-ordination.<br />
<br />
The code for this is a bit more busy than any of my other projects, but it has been heavily commented so just by reading the code you can easily understand what is going on. The code will be followed by a video demonstration in Isim along with it working on the FPGA board.<br />
<br />
Here we will be using three inputs; <i>reset</i>, <i>start</i>, <i>stop </i>and one output <i>led </i>along with displaying the time on the <i>seven segment display</i>.<br />
<br />
<ul>
<li>When the <i>reset </i>button is pressed it will obviously reset all registers and counters and will make the system ready for the next reflex test. Also when in this state it will display a "Hi" message on the seven segment display to welcome the user and to show that it is ready for the next input.</li>
<li>When the <i>start </i>button is pressed the output <i>led </i>will turn on after a random interval between 0 seconds and 10 seconds. The random time is achieved using the <a href="http://simplefpga.blogspot.co.uk/2013/02/random-number-generator-in-verilog-fpga.html">random number generator</a> which I have explained in detail in my previous post. Randomness here is very important, if the test did not have a random delay we could mentally memorize the delay between reset and the stimulus thus ruining the test. </li>
<li>After the random delay is achieved the led will turn on along with the timer.</li>
<li>The user is now to press the <i>stop </i>button. This will stop the timer and display your reaction time. The normal reaction time should be between 0.15s and 0.30s.</li>
</ul>
Something to note here is that since I will be using the seven segment to display the "Hi" as well as the time so in order to make it work I would have to use a multiplexing circuit. The multiplexing circuit will use a decision based code to decide what to display on the 7-segment and at what time. It was instantiated into the main module. So I think it would be best to explain the multiplexing circuit first.<br />
<br />
<br />
<pre class="brush:verilog">module muxer(
input clock,
input reset,
input [3:0] fourth,
input [3:0] third,
input [3:0] second,
input [3:0] first,
output a_m,
output b_m,
output c_m,
output d_m,
output e_m,
output f_m,
output g_m,
output dp_m,
output [3:0] an_m
);
//The Circuit for 7 Segment Multiplexing -
localparam N = 18;
reg [N-1:0]count; //the 18 bit counter which allows us to multiplex at 1000Hz
always @ (posedge clock or posedge reset)
begin
if (reset)
count <= 0;
else
count <= count + 1;
end
reg [3:0]sseg; //the 4 bit register to hold the data that is to be output
reg [3:0]an_temp; //register for the 4 bit enable
reg reg_dp;
always @ (*)
begin
case(count[N-1:N-2]) //MSB and MSB-1 for multiplexing
2'b00 :
begin
sseg = first;
an_temp = 4'b1110;
reg_dp = 1'b1;
end
2'b01:
begin
sseg = second;
an_temp = 4'b1101;
reg_dp = 1'b0;
end
2'b10:
begin
sseg = third;
an_temp = 4'b1011;
reg_dp = 1'b0;
end
2'b11:
begin
sseg = fourth;
an_temp = 4'b0111;
reg_dp = 1'b1;
end
endcase
end
assign an_m = an_temp;
reg [6:0] sseg_temp;
always @ (*)
begin
case(sseg)
4'd0 : sseg_temp = 7'b1000000; //display 0
4'd1 : sseg_temp = 7'b1111001; //display 1
4'd2 : sseg_temp = 7'b0100100; //display 2
4'd3 : sseg_temp = 7'b0110000; //display 3
4'd4 : sseg_temp = 7'b0011001; //display 4
4'd5 : sseg_temp = 7'b0010010; //display 5
4'd6 : sseg_temp = 7'b0000010; //display 6
4'd7 : sseg_temp = 7'b1111000; //display 7
4'd8 : sseg_temp = 7'b0000000; //display 8
4'd9 : sseg_temp = 7'b0010000; //display 9
4'd10 : sseg_temp = 7'b0001001; //to display H
4'd11 : sseg_temp = 7'b1001111; //to display I
default : sseg_temp = 7'b0111111; //dash
endcase
end
assign {g_m, f_m, e_m, d_m, c_m, b_m, a_m} = sseg_temp;
assign dp_m = reg_dp;
endmodule</pre>
<br />
The multiplexer module has 4 inputs which will have data passed to them from the main module. The outputs are connected to the 7 segment display. For detailed explanation on the above code visit the post: <a href="http://simplefpga.blogspot.co.uk/2012/07/seven-segment-led-multiplexing-circuit.html">7 Segment LED multiplexing in Verilog</a>.<br />
<br />
And now for the code of the reaction / reflex tester:<br />
<br />
<pre class="brush:verilog">module reaction_main(
input clock, reset, start, stop,
output led,
output [3:0] an,
output a, b, c, d, e, f, g, dp
);
reg [3:0] regd3, regd2, regd1, regd0; //the main output registers
wire db_start, db_stop;
reg dffstr1, dffstr2, dffstp1, dffstp2;
always @ (posedge clock) dffstr1 <= start;
always @ (posedge clock) dffstr2 <= dffstr1;
assign db_start = ~dffstr1 & dffstr2; //monostable multivibrator to detect only one pulse of the button
always @ (posedge clock) dffstp1 <= stop;
always @ (posedge clock) dffstp2 <= dffstp1;
assign db_stop = ~dffstp1 & dffstp2; //monostable multivibrator to detect only one pulse of the button
// Instantiate the 7 segment multiplexing module
muxer display (
.clock(clock),
.reset(reset),
.fourth(regd3),
.third(regd2),
.second(regd1),
.first(regd0),
.a_m(a),
.b_m(b),
.c_m(c),
.d_m(d),
.e_m(e),
.f_m(f),
.g_m(g),
.dp_m(dp),
.an_m(an)
);
//Block for LFSR random number generator
reg [28:0] random, random_next, random_done; //**29 bit register to keep track upto 10 seconds.
reg [4:0] count_r, count_next_r; //to keep track of the shifts. 5 bit register to count up to 30
wire feedback = random[28] ^ random[26];
always @ (posedge clock or posedge reset)
begin
if (reset)
begin
random <= 29'hF; //An LFSR cannot have an all 0 state, thus reset to FF.
count_r <= 0;
end
else
begin
random <= random_next;
count_r <= count_next_r;
end
end
always @ (*)
begin
random_next = random; //default state stays the same
count_next_r = count_r;
random_next = {random[27:0], feedback}; //shift left the xor'd every posedge clock
if (count_r == 29)
begin
count_next_r = 0;
random_done = random; //assign the random number to output after 30 shifts
end
else
begin
count_next_r = count_r + 1;
random_done = random; //keep previous value of random
end
end
//random number block ends
reg [3:0] reg_d0, reg_d1, reg_d2, reg_d3; //registers that will hold the individual counts
(* KEEP = "TRUE" *)reg [1:0] sel, sel_next; //for KEEP attribute see note below
localparam [1:0]
idle = 2'b00,
starting = 2'b01,
time_it = 2'b10,
done = 2'b11;
reg [1:0] state_reg, state_next;
reg [28:0] count_reg, count_next;
always @ (posedge clock or posedge reset)
begin
if(reset)
begin
state_reg <= idle;
count_reg <= 0;
sel <=0;
end
else
begin
state_reg <= state_next;
count_reg <= count_next;
sel <= sel_next;
end
end
reg go_start;
always @ (*)
begin
state_next = state_reg; //default state stays the same
count_next = count_reg;
sel_next = sel;
case(state_reg)
idle:
begin
//DISPLAY HI HERE
sel_next = 2'b00;
if(db_start)
begin
count_next = random_done; //get the random number from LFSR module
state_next = starting; //go to next state
end
end
starting:
begin
if(count_next == 500000000) // **500M equals a delay of 10 seconds. and starting from 'rand' ensures a random delay
begin
state_next = time_it; //go to next state
end
else
begin
count_next = count_reg + 1;
end
end
time_it:
begin
sel_next = 2'b01; //start the timer
state_next = done;
end
done:
begin
if(db_stop)
begin
sel_next = 2'b10; //stop the timer
end
end
endcase
case(sel_next) //this case statement that will control what is sent to the 7 segment based on the sel signal
2'b00: //hi
begin
go_start = 0; //make sure timer module is off
regd0 = 4'd12;
regd1 = 4'd11;
regd2 = 4'd10;
regd3 = 4'd12;
end
2'b01: //timer
begin
go_start = 1'b1; //enable start signal to start timer
regd0 = reg_d0;
regd1 = reg_d1;
regd2 = reg_d2;
regd3 = reg_d3;
end
2'b10: //stop timer
begin
go_start = 1'b0;
regd0 = reg_d0;
regd1 = reg_d1;
regd2 = reg_d2;
regd3 = reg_d3;
end
2'b11: //Although this condition is of no use to us it is placed here for the sake of completion, case statements left uncompleted will create a latch in implementation
begin
regd0 = 4'd12; //4'd12 to siplay '-'
regd1 = 4'd12;
regd2 = 4'd12;
regd3 = 4'd12;
go_start = 1'b0;
end
default:
begin
regd0 = 4'd12;
regd1 = 4'd12;
regd2 = 4'd12;
regd3 = 4'd12;
go_start = 1'b0;
end
endcase
end
//the stopwatch block
reg [18:0] ticker; //19 bits needed to count up to 500K bits
wire click;
//the mod 500K clock to generate a tick ever 0.01 second
always @ (posedge clock or posedge reset)
begin
if(reset)
ticker <= 0;
else if(ticker == 500000) //if it reaches the desired max value of 500K reset it
ticker <= 0;
else if(go_start) //only start if the input is set high
ticker <= ticker + 1;
end
assign click = ((ticker == 500000)?1'b1:1'b0); //click to be assigned high every 0.01 second
always @ (posedge clock or posedge reset)
begin
if (reset)
begin
reg_d0 <= 0;
reg_d1 <= 0;
reg_d2 <= 0;
reg_d3 <= 0;
end
else if (click) //increment at every click
begin
if(reg_d0 == 9) //xxx9 - the 0.001 second digit
begin //if_1
reg_d0 <= 0;
if (reg_d1 == 9) //xx99
begin // if_2
reg_d1 <= 0;
if (reg_d2 == 5) //x599 - the two digit seconds digits
begin //if_3
reg_d2 <= 0;
if(reg_d3 == 9) //9599 - The minute digit
reg_d3 <= 0;
else
reg_d3 <= reg_d3 + 1;
end
else //else_3
reg_d2 <= reg_d2 + 1;
end
else //else_2
reg_d1 <= reg_d1 + 1;
end
else //else_1
reg_d0 <= reg_d0 + 1;
end
end
//If count_reg == 500M - check if 'stop' key is pressed, if yes disable led, otherwise enable it. If count_reg ~= 500M keep led off.
assign led = ((count_reg == 500000000)?((db_stop == 1)?1'b0:1'b1):1'b0);
endmodule</pre>
<br />
<br />
If you go through the above code you will note that its pretty self explanatory as all steps have been commented. The only thing worth mentioning here is the <br />
<pre class="brush:verilog">(* KEEP = "TRUE" *)</pre>
attribute. This attribute has nothing to do with the working of the code, it is needed for implementation only. If you are going to simulate this code you can remove this attribute as it wont have any effect on its working. The reason I felt to add it was because during implementation and synthesis Xilinx for some reason decided to remove the <i>sel </i>signal entirely after giving this warning:<br />
<blockquote class="tr_bq">
<pre class="brush:verilog">Xst:1710 - FF/Latch <sel_3> (without init value) has a constant value of 0 in block <reaction_main>. This FF/Latch will be trimmed during the optimization process.</pre>
</blockquote>
I checked it up with Xilinx documentation and it was a known problem with the version of Xilinx I am using. For some reason Xilinx thought it would optimize the design by removing one of my most vital signals :) So in order to force Xilinx to keep the signal the KEEP attribute must be used.<br />
<br />
I tried to write the code in a very easy way and commented it in detail so its easy to read and understand. Below is the video demonstration of this code working.<br />
<iframe width="560" height="315" src="http://www.youtube.com/embed/iGwyzf0vI_Y" frameborder="0" allowfullscreen></iframe><br />
<br />
And here is the simulation of the above code:<br />
<iframe allowfullscreen="" frameborder="0" height="360" src="http://www.youtube.com/embed/CsbzoVykYkQ" width="480"></iframe><br />Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-4577759886421850250.post-39843625943361957542013-02-10T16:04:00.000+00:002014-05-27T09:16:59.806+01:00Random Number Generator in Verilog | FPGAIn verilog a random number can be generated by using the $random keyword but that works only for simulation purposes and cannot be implemented. So when we need a random number for implementation i.e. in hardware it can be achieved using an LFSR (Liner Feedback Shift Register). An LFSR is simply a <a href="http://simplefpga.blogspot.co.uk/2013/02/universal-shift-left-right.html">shift register</a> with some of its bits (known as taps) <span style="font-family: "Courier New",Courier,monospace;">XOR'd</span> with themselves to create a feedback term.<br />
<br />
When implementing an LFSR it's width and it's repeatability must be kept under consideration .An N-bit LFSR will be able to generate <span style="font-family: "Courier New",Courier,monospace;">(2**N) - 1</span> random bits before it starts repeating. For example a 30 bit LFSR will have <span style="font-family: "Courier New",Courier,monospace;">1073741823 </span>random states before repeating, so for most practical purposes this can be considered true random.<br />
<br />
In an LFSR the MSB will always be the feedback point also the main thing to take care of while coding an LFSR is to know which bits are the taps (to be selected for <span style="font-family: "Courier New",Courier,monospace;">XOR</span>). This is confusing as the taps are different for different size registers. For example an 8 bit LFSR will have its 8th, 6th, 5th and 4th bits XOR'd with each other whereas a 10 bit LFSR will have its 10th and 7th bits XOR'd to create the random numbers. So clearly there is no pattern to this, but thankfully Xilinx has calculated all of this and made it available to us in its online documentation. The table below shows the tap locations for LFSR's upto 168 bits.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXyj4XRZCGC2g-JeGLnoL5StAtVS5UOkrvM7QFN-NqgpSWIynxidI5X-wb9lnMT0EY79iJRqmq5cKosfdTuz10PmRZvWxP8aQLS9WFsAyY3ECdrhSA-NkfNVWVPBl98eMO5thNEUcUapn5/s1600/LFSR.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="LFSR random number tap locations" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXyj4XRZCGC2g-JeGLnoL5StAtVS5UOkrvM7QFN-NqgpSWIynxidI5X-wb9lnMT0EY79iJRqmq5cKosfdTuz10PmRZvWxP8aQLS9WFsAyY3ECdrhSA-NkfNVWVPBl98eMO5thNEUcUapn5/s640/LFSR.jpg" height="640" title="LFSR random number tap locations" width="576" /></a></div>
<br />
<br />
An LFSR is good for generating a stream of random bits. It <b>does not</b> generate a random number by itself but only the feedback bit is random. However that does not mean that we cannot use this fact to generate a random number. In my code below I have an output of 13 bits and a 13 bit random number is accomplished by shifting the feedback bit enough times to equal the desired output size. In my case when it has shifted 13 times it will be assigned to the output. This way every bit is random thus making the whole number pretty random if you ask me.<br />
<br />
Below is a code for a 13 bit LFSR. Notice my selection of taps is taken from the table above:<br />
<br />
<pre class="brush:verilog">module LFSR (
input clock,
input reset,
output [12:0] rnd
);
wire feedback = random[12] ^ random[3] ^ random[2] ^ random[0];
reg [12:0] random, random_next, random_done;
reg [3:0] count, count_next; //to keep track of the shifts
always @ (posedge clock or posedge reset)
begin
if (reset)
begin
random <= 13'hF; //An LFSR cannot have an all 0 state, thus reset to FF
count <= 0;
end
else
begin
random <= random_next;
count <= count_next;
end
end
always @ (*)
begin
random_next = random; //default state stays the same
count_next = count;
random_next = {random[11:0], feedback}; //shift left the xor'd every posedge clock
count_next = count + 1;
if (count == 13)
begin
count = 0;
random_done = random; //assign the random number to output after 13 shifts
end
end
assign rnd = random_done;
endmodule</pre>
<br />
As requested, below is the test bench for the above code, not much stimulus in it, its just a simple reset.<br />
<pre class="brush:verilog">module test;
// Inputs
reg clock;
reg reset;
// Outputs
wire [12:0] rnd;
// Instantiate the Unit Under Test (UUT)
LFSR uut (
.clock(clock),
.reset(reset),
.rnd(rnd)
);
initial begin
clock = 0;
forever
#50 clock = ~clock;
end
initial begin
// Initialize Inputs
reset = 0;
// Wait 100 ns for global reset to finish
#100;
reset = 1;
#200;
reset = 0;
// Add stimulus here
end
initial begin
$display("clock rnd");
$monitor("%b,%b", clock, rnd);
end
endmodule</pre>
<br />
Do note that this is not pure random, this number can be predicted if the algorithm is known. Thus don't use this for security purposes ;)<br />
<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="360" src="http://www.youtube.com/embed/xfiVK_phfsk" width="480"></iframe>Unknownnoreply@blogger.com20tag:blogger.com,1999:blog-4577759886421850250.post-15563115020856855592013-01-16T18:05:00.001+00:002020-06-16T16:13:30.529+01:00Universal Shift Left - Right Register/Circuit in VerilogA shift register will "shift" itself to the left or right by one position every clock cycle. A shift left - shift left circuit, as simple as it sounds is a very important part of many circuits and will be a part of many of my future projects and that is why it needs to be addressed. The code for this circuit in verilog is written below. It is very simple and does not need any detailed explanation.<br />
<br />
It is controlled by 2 control signals which determines whether the circuit will shift right or left. If control[0] is high the circuit will shift right and if control[1] is high the circuit will shift left and if both are low stay with the default value. The data shifted is stored in an internal register and is output as a bus. I have coded it using if - else statements. This can also be coded using a case block if further control is required.<br />
<br /><pre style="text-align: left;">module shift(
input clock,
input reset,
input [1:0] control,
input in,
output [7:0] out
);
reg [7:0] r_reg, r_next; //a 7 bit shift register which will be output as is, this can be changed to any size
always @ (posedge clock or posedge reset)
begin
if(reset)
r_reg <= 0;
else
r_reg <= r_next;
end
always @ (*)
begin
if(control[0]) //shift right
r_next = {in, r_reg[7:1]};
else if(control[1]) //shift left
r_next = {r_reg[6:0], in};
else
r_next = r_reg; //default state stays the same
end
assign out = r_reg;
endmodule
<br /></pre><pre style="text-align: left;"><b>Testbench code below:</b></pre><pre style="text-align: left;"><br /></pre><pre style="text-align: left;">module test;
// Inputs
reg clock;
reg reset;
reg [1:0] control;
reg in;
// Outputs
wire [7:0] out;
// Instantiate the Unit Under Test (UUT)
shift uut (
.clock(clock),
.reset(reset),
.control(control),
.in(in),
.out(out)
);
initial begin
clock = 0;
forever
#50 clock = ~clock;
end
initial begin
// Initialize Inputs
reset = 0;
control = 0;
in = 0;
// Wait 100 ns for global reset to finish
#100;
reset = 1;
#200;
reset = 0;
in = 1'b1;
#200;
control = 2'b01;
#300;
control = 2'b10;
#300;
control = 2'b00;
#300;
control = 2'b11;
#200
$stop;
// Add stimulus here
end
initial begin
$display("clock control r_reg");
$monitor("%b,%b,%b", clock, control, out);
end
endmodule</pre><div><br />
<iframe allowfullscreen="" frameborder="0" height="360" src="http://www.youtube.com/embed/sVTawZy86WY" width="480"></iframe></div>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-4577759886421850250.post-51126802280059573642012-12-22T00:25:00.000+00:002012-12-22T00:27:39.376+00:00Scrolling or Moving Text Using 7 Segment LED's in Verilog | FPGAThis one is going to be a quick easy project. The objective here is to get use the 7-segment LED display on the board to display a scrolling text. it should be slow enough so that it can be easily read.<br />
<br />
I have made the delay between each word shift to be 1 second. This is long enough to read the text comfortably without missing anything. I have explained in my previous post how to create an accurate delay using verilog, you can read about it there: <a href="http://simplefpga.blogspot.co.uk/2012/07/to-code-stopwatch-in-verilog.html">Create accurate delay in Verilog</a>. Now since I need a 1 second delay here the counter monitoring this count must count to 50,000,000. And the register needed to hold this count must be 29 bits wide.<br />
<br />
Using this method you can scroll and display anything. Here I have chosen to display the text "Hello There" to scroll across the LED's and appear to be continuous without any stops. The concept is pretty simple. I create a separate counter that increments every time a count of 50,000,000 is reached. This counter will count till 8, display the entire text, and then reset back to 0 so that the text can be scrolled again. For every count increment it will match it with a case statement. This case will instruct the display for that second.<br />
<br />
Now since 7 segment LED's are being used here you must have a proper understanding of them before trying to read and understand the code. I have detailed the topic in detail here: <a href="http://simplefpga.blogspot.co.uk/2012/07/seven-segment-led-multiplexing-circuit.html">7 Segment LED Multiplexing in Verilog</a>. Be sure to read and understand it.<br />
<br />
So instead of displaying numbers the plan is to display letters on the LED's. This can be achieved by changing the case statement to our requirements.<br />
<br />
As usual the code is commented in detail and should be self explanatory even without the above rant. A video demonstration has been added at the end.<br />
<br />
<pre class="brush:verilog">module scrolling_name(
input clock,
input reset,
output a,
output b,
output c,
output d,
output e,
output f,
output g,
output dp,
output [3:0] an
);
reg [28:0] ticker; //to hold a count of 50M
wire click;
reg [3:0] fourth, third, second, first; // registers to hold the LED values
always @ (posedge clock or posedge reset) //always block for the ticker
begin
if(reset)
ticker <= 0;
else if(ticker == 50000000) //reset after 1 second
ticker <= 0;
else
ticker <= ticker + 1;
end
reg [3:0] clickcount; //register to hold the count upto 9. That is why a 4 bit register is used. 3 bit would not have been enough.
assign click = ((ticker == 50000000)?1'b1:1'b0); //click every second
always @ (posedge click or posedge reset)
begin
if(reset)
clickcount <= 0;
else if(clickcount == 8)
clickcount <= 0;
else
clickcount <= clickcount + 1;
end
always @ (*) //always block that will scroll or move the text. Accomplished with case
begin
case(clickcount)
0:
begin
fourth = 4; //H
third = 3; //E
second = 7; //L
first = 7; //L
end
1:
begin
fourth = 3; //E
third = 7; //L
second = 7; //L
first = 0; //O
end
2:
begin
fourth = 7; //L
third = 7; //L
second = 0; //O
first = 2; //-
end
3:
begin
fourth = 7; //L
third = 0; //O
second = 2; //-
first = 1; //T
end
4:
begin
fourth = 0; //O
third = 2; //-
second = 1; //T
first = 4; //H
end
5:
begin
fourth = 2; //-
third = 1; //T
second = 4; //H
first = 3; //E
end
6:
begin
fourth = 1; //T
third = 4; //H
second = 3; //E
first = 8; //R
end
7:
begin
fourth = 4; //H
third = 3; //E
second = 8; //R
first = 3; //E
end
8:
begin
fourth = 3; //E
third = 8; //R
second = 3; //E
first = 2; //blank
end
endcase
end
//see my other post on explanation of LED multiplexing.
localparam N = 18;
reg [N-1:0]count;
always @ (posedge clock or posedge reset)
begin
if (reset)
count <= 0;
else
count <= count + 1;
end
reg [6:0]sseg;
reg [3:0]an_temp;
always @ (*)
begin
case(count[N-1:N-2])
2'b00 :
begin
sseg = first;
an_temp = 4'b1110;
end
2'b01:
begin
sseg = second;
an_temp = 4'b1101;
end
2'b10:
begin
sseg = third;
an_temp = 4'b1011;
end
2'b11:
begin
sseg = fourth;
an_temp = 4'b0111;
end
endcase
end
assign an = an_temp;
reg [6:0] sseg_temp;
always @ (*)
begin
case(sseg)
4 : sseg_temp = 7'b0001001; //to display H
3 : sseg_temp = 7'b0000110; //to display E
7 : sseg_temp = 7'b1000111; //to display L
0 : sseg_temp = 7'b1000000; //to display O
1 : sseg_temp = 7'b0000111; //to display T
8 : sseg_temp = 7'b0001000; //to display R
default : sseg_temp = 7'b1111111; //blank
endcase
end
assign {g, f, e, d, c, b, a} = sseg_temp;
assign dp = 1'b1;
endmodule
</pre>
<br />
<iframe width="560" height="315" src="http://www.youtube.com/embed/I_lnbiihMGg" frameborder="0" allowfullscreen></iframe>Unknownnoreply@blogger.com21tag:blogger.com,1999:blog-4577759886421850250.post-49523728928425690192012-12-19T05:25:00.000+00:002012-12-23T22:13:14.445+00:00FIFO(First In First Out) Buffer in VerilogA FIFO(First in First Out) buffer is an elastic storage usually used between two subsystems. As the name indicates the memory that is first written into the FIFO is the first to be read or processed. A FIFO has two control signals i.e. write and read. When write is enabled data is written into the buffer and when read is enabled data is "removed" from the buffer to make room for more data. This concept of write and read (remove) can be best understood from the conceptual diagram of a FIFO below:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3r-f1WIB4nqHhD-xfcM7qXQRXG8MbErGHdAN_MlT3WlZfAk62ovfcybS5JpOQEaupkdz4QsI92X4X_udJ_D2kDGb3J4bgj__VDmd_KymIRKWuqNRAZ3afUxBUGFlpu1T9CiK_wXg8ARKO/s1600/FIFO+Buffer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3r-f1WIB4nqHhD-xfcM7qXQRXG8MbErGHdAN_MlT3WlZfAk62ovfcybS5JpOQEaupkdz4QsI92X4X_udJ_D2kDGb3J4bgj__VDmd_KymIRKWuqNRAZ3afUxBUGFlpu1T9CiK_wXg8ARKO/s1600/FIFO+Buffer.png" /></a></div>
As can be seen, once the data is read, it can be considered as removed and thus allowing more data to be written into the buffer.<br />
<br />
<h3>
Implementation of FIFO in Verilog</h3>
To implement FIFO in verilog imagine the memory components to be arranged in a circular queue fashion with two pointers; <i>write </i>and <i>read</i>. The <i>write </i>pointer points to the start of the circle whereas the <i>read </i>pointer points to the end of the circle. Both these pointers increment themselves by one after each read or write operation.<br />
This buffer will also consist of two flags; <i>empty </i>and <i>full</i>. These will help in indicating when the FIFO is <i>full </i>(cannot be written to) or <i>empty </i>(cannot be read from). This circular implementation can be seen from the following figure:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioT0C-HJObKXOKxFfUz0WBpe62dCHVqKRk8ZmPJ21mvq8OKgumgeE6faurmgHwHZC5ikoxRFznGMV4OUj0dzPGrP-XkPBMeoVlf808F43C-RK_HU_QF5W3FWFb6qRoPlA1Ned8ZSG-GGn-/s1600/FIFO+Verilog.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioT0C-HJObKXOKxFfUz0WBpe62dCHVqKRk8ZmPJ21mvq8OKgumgeE6faurmgHwHZC5ikoxRFznGMV4OUj0dzPGrP-XkPBMeoVlf808F43C-RK_HU_QF5W3FWFb6qRoPlA1Ned8ZSG-GGn-/s640/FIFO+Verilog.png" width="505" /></a></div>
<br />
The size of the FIFO buffer greatly depends on the number of address bits. As the number of words in fifo = 2^(number of address bits). The FIFO I will be coding here will consist of 16 memory elements ( 4 bits in each memory element and 3 address bits). This can be easily changed by changing the parameters in the code, by doing so you can create a buffer of any size. The parameters can be changed from the following line:<br />
<br />
<pre class="brush:verilog">module fifo # (parameter abits = 4, dbits = 3)</pre>
<br />
At reset the <i>empty </i>flag is set to high whereas the <i>full </i>flag is set to low to allow new data to be written. The positions of the <i>read </i>and <i>write </i>pointers are also initialized to 0. The verilog code is shown below. It has been commented in detail so I hope each step is clear.<br />
<br />
<pre class="brush:verilog">module fifo # (parameter abits = 4, dbits = 3)(
input clock,
input reset,
input wr,
input rd,
input [dbits-1:0] din,
output empty,
output full,
output [dbits-1:0] dout
);
wire db_wr, db_rd;
reg dffw1, dffw2, dffr1, dffr2;
reg [dbits-1:0] out;
always @ (posedge clock) dffw1 <= wr;
always @ (posedge clock) dffw2 <= dffw1;
assign db_wr = ~dffw1 & dffw2; //monostable multivibrator to detect only one pulse of the button
always @ (posedge clock) dffr1 <= rd;
always @ (posedge clock) dffr2 <= dffr1;
assign db_rd = ~dffr1 & dffr2; //monostable multivibrator to detect only one pulse of the button
reg [dbits-1:0] regarray[2**abits-1:0]; //number of words in fifo = 2^(number of address bits)
reg [abits-1:0] wr_reg, wr_next, wr_succ; //points to the register that needs to be written to
reg [abits-1:0] rd_reg, rd_next, rd_succ; //points to the register that needs to be read from
reg full_reg, empty_reg, full_next, empty_next;
assign wr_en = db_wr & ~full; //only write if write signal is high and fifo is not full
//always block for write operation
always @ (posedge clock)
begin
if(wr_en)
regarray[wr_reg] <= din; //at wr_reg location of regarray store what is given at din
end
//always block for read operation
always @ (posedge clock)
begin
if(db_rd)
out <= regarray[rd_reg];
end
always @ (posedge clock or posedge reset)
begin
if (reset)
begin
wr_reg <= 0;
rd_reg <= 0;
full_reg <= 1'b0;
empty_reg <= 1'b1;
end
else
begin
wr_reg <= wr_next; //created the next registers to avoid the error of mixing blocking and non blocking assignment to the same signal
rd_reg <= rd_next;
full_reg <= full_next;
empty_reg <= empty_next;
end
end
always @(*)
begin
wr_succ = wr_reg + 1; //assigned to new value as wr_next cannot be tested for in same always block
rd_succ = rd_reg + 1; //assigned to new value as rd_next cannot be tested for in same always block
wr_next = wr_reg; //defaults state stays the same
rd_next = rd_reg; //defaults state stays the same
full_next = full_reg; //defaults state stays the same
empty_next = empty_reg; //defaults state stays the same
case({db_wr,db_rd})
//2'b00: do nothing LOL..
2'b01: //read
begin
if(~empty) //if fifo is not empty continue
begin
rd_next = rd_succ;
full_next = 1'b0;
if(rd_succ == wr_reg) //all data has been read
empty_next = 1'b1; //its empty again
end
end
2'b10: //write
begin
if(~full) //if fifo is not full continue
begin
wr_next = wr_succ;
empty_next = 1'b0;
if(wr_succ == (2**abits-1)) //all registers have been written to
full_next = 1'b1; //its full now
end
end
2'b11: //read and write
begin
wr_next = wr_succ;
rd_next = rd_succ;
end
//no empty or full flag will be checked for or asserted in this state since data is being written to and read from together it can not get full in this state.
endcase
end
assign full = full_reg;
assign empty = empty_reg;
assign dout = out;
endmodule
</pre>
<br />
<iframe allowfullscreen="allowfullscreen" frameborder="0" height="315" src="http://www.youtube.com/embed/HSViuO23CUQ" width="560"></iframe>Unknownnoreply@blogger.com9tag:blogger.com,1999:blog-4577759886421850250.post-86119554518709586242012-07-27T20:55:00.000+01:002014-04-15T10:44:08.086+01:00To Code a Stopwatch in VerilogThe stopwatch coded here will be able to keep time till 10 minutes. It will be a 4 digit stopwatch counting from 0:00:0 till 9:59:9. The right most digit will be incremented every 0.1 second, when it reaches 9 it will increment the middle two digits, which represent the second count. When it reaches 59 seconds it will increment the right most minute display. The stopwatch will be in the format M:SS:D.<br />
<br />
<h3>
How to Create an Accurate Delay in Verilog:</h3>
<br />
To make the stop watch an accurate device we need to be able to produce an accurate 0.1 second delay. I have already explained how to do this before in my <a href="http://simplefpga.blogspot.co.uk/2012/07/00-to-99-two-digit-decimal-counter-via.html">decimal counter in verilog</a> post. But since it is of great importance to the design will be explained in more detail here.<br />
<br />
Since we know that the BASYS2 (the one I am using, yours may be different) has a 50 MHz clock which means that the clock cycle is repeated 50M times in one second. So to create a 0.1 second delay we multiply the clock with the required time:<br />
<br />
50MHz * 0.1 sec = 5000000<br />
<br />
So the clock cycle is repeated 5M times in 0.1 second. The next step is to calculate the size of the register that will hold this count. This is done by using the log formulas. Here x is the unknown:<br />
<br />
2exp(x) = 5000000<br />
<br />
Taking log on both sides:<br />
<br />
log 2exp(x) = log 5000000<br />
<br />
(x) log (2) = log 5000000<br />
<br />
x = log 5000000 / log 2<br />
<br />
x = 22.3<br />
<br />
Hence a 23 bit wide register will be able to hold a count of 5000000.<br />
<br />
The code for the stopwatch is given below, as with all other posts involving the seven segment display LED multiplexing is performed here. I will not comment or explain it here as I have already made a detailed post regarding that here: <a href="http://simplefpga.blogspot.co.uk/2012/07/seven-segment-led-multiplexing-circuit.html">Display LED Multiplexing in Verilog</a><br />
<br />
<pre class="brush:verilog">module stopwatch(
input clock,
input reset,
input start,
output a, b, c, d, e, f, g, dp,
output [3:0] an
);
reg [3:0] reg_d0, reg_d1, reg_d2, reg_d3; //registers that will hold the individual counts
reg [22:0] ticker; //23 bits needed to count up to 5M bits
wire click;
//the mod 5M clock to generate a tick ever 0.1 second
always @ (posedge clock or posedge reset)
begin
if(reset)
ticker <= 0;
else if(ticker == 5000000) //if it reaches the desired max value reset it
ticker <= 0;
else if(start) //only start if the input is set high
ticker <= ticker + 1;
end
assign click = ((ticker == 5000000)?1'b1:1'b0); //click to be assigned high every 0.1 second
always @ (posedge clock or posedge reset)
begin
if (reset)
begin
reg_d0 <= 0;
reg_d1 <= 0;
reg_d2 <= 0;
reg_d3 <= 0;
end
else if (click) //increment at every click
begin
if(reg_d0 == 9) //xxx9 - the 0.1 second digit
begin //if_1
reg_d0 <= 0;
if (reg_d1 == 9) //xx99
begin // if_2
reg_d1 <= 0;
if (reg_d2 == 5) //x599 - the two digit seconds digits
begin //if_3
reg_d2 <= 0;
if(reg_d3 == 9) //9599 - The minute digit
reg_d3 <= 0;
else
reg_d3 <= reg_d3 + 1;
end
else //else_3
reg_d2 <= reg_d2 + 1;
end
else //else_2
reg_d1 <= reg_d1 + 1;
end
else //else_1
reg_d0 <= reg_d0 + 1;
end
end
//The Circuit for Multiplexing - Look at my other post for details on this
localparam N = 18;
reg [N-1:0]count;
always @ (posedge clock or posedge reset)
begin
if (reset)
count <= 0;
else
count <= count + 1;
end
reg [6:0]sseg;
reg [3:0]an_temp;
reg reg_dp;
always @ (*)
begin
case(count[N-1:N-2])
2'b00 :
begin
sseg = reg_d0;
an_temp = 4'b1110;
reg_dp = 1'b1;
end
2'b01:
begin
sseg = reg_d1;
an_temp = 4'b1101;
reg_dp = 1'b0;
end
2'b10:
begin
sseg = reg_d2;
an_temp = 4'b1011;
reg_dp = 1'b1;
end
2'b11:
begin
sseg = reg_d3;
an_temp = 4'b0111;
reg_dp = 1'b0;
end
endcase
end
assign an = an_temp;
reg [6:0] sseg_temp;
always @ (*)
begin
case(sseg)
4'd0 : sseg_temp = 7'b1000000;
4'd1 : sseg_temp = 7'b1111001;
4'd2 : sseg_temp = 7'b0100100;
4'd3 : sseg_temp = 7'b0110000;
4'd4 : sseg_temp = 7'b0011001;
4'd5 : sseg_temp = 7'b0010010;
4'd6 : sseg_temp = 7'b0000010;
4'd7 : sseg_temp = 7'b1111000;
4'd8 : sseg_temp = 7'b0000000;
4'd9 : sseg_temp = 7'b0010000;
default : sseg_temp = 7'b0111111; //dash
endcase
end
assign {g, f, e, d, c, b, a} = sseg_temp;
assign dp = reg_dp;
endmodule</pre>
<br />
<br />
<br />
<br />
Test bench below:<br />
<br />
<input class="spoilerbutton" onclick="this.value=this.value=='Show'?'Hide':'Show';" type="button" value="Show" />
<br />
<div class="spoiler">
<div>
<pre class="brush:verilog">module test;
// Inputs
reg clock;
reg reset;
reg start;
// Outputs
wire [3:0] d0;
wire [3:0] d1;
wire [3:0] d2;
// Instantiate the Unit Under Test (UUT)
stopwatch uut (
.clock(clock),
.reset(reset),
.start(start),
.d0(d0),
.d1(d1),
.d2(d2)
);
initial
begin
clock = 0;
forever
#50 clock = ~clock;
end
initial begin
// Initialize Inputs
reset = 0;
start = 0;
// Wait 100 ns for global reset to finish
#100;
reset = 1;
#100;
reset = 0;
#100;
start = 1;
// Add stimulus here
end
endmodule
</pre>
</div>
</div>
<br />
Video demonstration below:<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/_kHISqsuXUE" width="560"></iframe>Unknownnoreply@blogger.com42tag:blogger.com,1999:blog-4577759886421850250.post-6148587182420185712012-07-27T01:04:00.002+01:002012-11-10T23:30:23.558+00:0000 to 99 Two Digit Decimal Counter via 7 Segment Display Using VerilogSince I have already made a detailed post regarding <a href="http://simplefpga.blogspot.co.uk/2012/07/seven-segment-led-multiplexing-circuit.html">7 segment LED multiplexing</a>, this post is going to be a short one, in which I will only explain the code via comments in code.<br />
<br />
Here I am going to make a 2 digit counter that counts from 00 to 99 and then rolls over back to 00. The counter will increment every 0.1 second. The 0.1 second interval is produced by another counter that will produce an enable tick every 0.1 second to increment our main counter.<br />
<br />
<h3>
How to make a 0.1 second accurate delay in Verilog</h3>
<br />
We know that the board being used has a 50 MHz clock. So to produce a 0.1 second delay simply multiply the two.. 50Mhz * 0.1 sec = 5000000. So every 5M ticks is equal to 0.1 second. So using the simple log formula ( (x)log(2) = log(5000000) ) we can calculate that a 23 bit wide register will be able to hold a count of 5000000.<br />
<br />
The code for this counter is given below:<br />
<br />
<pre class="brush:verilog">module twodigit_onefile(
input clock,
input reset,
output a,
output b,
output c,
output d,
output e,
output f,
output g,
output dp,
output [3:0]an
);
reg [3:0]first; //register for the first digit
reg [3:0]second; //register for the second digit
reg [22:0] delay; //register to produce the 0.1 second delay
wire test;
always @ (posedge clock or posedge reset)
begin
if (reset)
delay <= 0;
else
delay <= delay + 1;
end
assign test = &delay; //AND each bit of delay with itself; test will be high only when all bits of delay are high
always @ (posedge test or posedge reset)
begin
if (reset) begin
first <= 0;
second <= 0;
end
else if (first==4'd9) begin //x9 reached
first <= 0;
if (second == 4'd9) //99 reached
second <= 0;
else
second <= second + 1;
end
else
first <= first + 1;
end
//Multiplexing circuit below
localparam N = 18;
reg [N-1:0]count;
always @ (posedge clock or posedge reset)
begin
if (reset)
count <= 0;
else
count <= count + 1;
end
reg [6:0]sseg;
reg [3:0]an_temp;
always @ (*)
begin
case(count[N-1:N-2])
2'b00 :
begin
sseg = first;
an_temp = 4'b1110;
end
2'b01:
begin
sseg = second;
an_temp = 4'b1101;
end
2'b10:
begin
sseg = 6'ha; //unknown sent to produce '-'
an_temp = 4'b1011;
end
2'b11:
begin
sseg = 6'ha; //unknown sent to produce '-'
an_temp = 4'b0111;
end
endcase
end
assign an = an_temp;
reg [6:0] sseg_temp;
always @ (*)
begin
case(sseg)
4'd0 : sseg_temp = 7'b1000000; //0
4'd1 : sseg_temp = 7'b1111001; //1
4'd2 : sseg_temp = 7'b0100100; //2
4'd3 : sseg_temp = 7'b0110000; //3
4'd4 : sseg_temp = 7'b0011001; //4
4'd5 : sseg_temp = 7'b0010010; //5
4'd6 : sseg_temp = 7'b0000010; //6
4'd7 : sseg_temp = 7'b1111000; //7
4'd8 : sseg_temp = 7'b0000000; //8
4'd9 : sseg_temp = 7'b0010000; //9
default : sseg_temp = 7'b0111111; //dash
endcase
end
assign {g, f, e, d, c, b, a} = sseg_temp;
assign dp = 1'b1; //we dont need the decimal here so turn all of them off
endmodule
</pre>
<br />
The multiplexing circuit has been explained and commended in detail in my previous post here : <a href="http://simplefpga.blogspot.co.uk/2012/07/seven-segment-led-multiplexing-circuit.html">Verilog LED Multiplexing Circuit</a>.<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/U4neziwo7OY" width="560"></iframe>Unknownnoreply@blogger.com35tag:blogger.com,1999:blog-4577759886421850250.post-5391480782475203012012-07-22T17:39:00.002+01:002013-03-21T08:10:50.319+00:00Seven Segment LED Multiplexing Circuit in VerilogThe seven segment LED circuit uses seven different and individual LED's to display a hexadecimal symbol. It has 7 wires to control the individual LED's one wire to control the decimal point and one enable wire. The demo board I am using here consists of four such 7-segment LED's(As do any other demo board). To reduce the number of wires a multiplexing circuit is used to control the display. Using the multiplexing circuit the number of wires required to light up all 4 displays are reduced from 32 to 12 (8 data bits and 4 enable bits). All bits here are active low, such that to enable them a '0' is required. For example the figure below shows how to display a 3 on the seven segment.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTAeclJ_F_R74Euw49OHV7AkYcC0nIiagpjL_qny8kA32CWerP5Z4eojfB08sQqdHrYcZoCugXYeT1vbnSbXFe-_WF04alyR1Gaf3JnhoMs7YKtR89ZZ-ahIlbeBzPltJVLl5Bg0fevnUy/s1600/12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTAeclJ_F_R74Euw49OHV7AkYcC0nIiagpjL_qny8kA32CWerP5Z4eojfB08sQqdHrYcZoCugXYeT1vbnSbXFe-_WF04alyR1Gaf3JnhoMs7YKtR89ZZ-ahIlbeBzPltJVLl5Bg0fevnUy/s320/12.png" width="320" /></a></div>
The multiplexing circuit can take 4 inputs and have only one output. But the inputs should be displayed on the output fast enough to fool the viewer into thinking all outputs are enabled individually and simultaneously. This is achieved by having an enable signal that changes so fast that it appears that all displays are on simultaneously. The refreshing rate of the enable signal should be around 1000Hz to achieve this desired effect. Since the BASYS2 board has a 50Mhz clock and if an 18 bit counter is used and only the 2 MSB's are used to generate the enable signal then the refreshing rate of an individual enable bit will be 50MHz/(2^16) which comes to about 800 Hz.<br />
<br />
Once the multiplexing is done the next code block is always the data bits for the seven segment. This is usually a case statement which encodes the hexadecimal digits into binary format. Since the LED's here are active low the segments that need to be enabled must be low.<br />
<br />
The code for the LED multiplexing is shown below:<br />
<br />
<pre class="brush:verilog">module sevenseg(
input clock, reset,
input in0, in1, in2, in3, //the 4 inputs for each display
output a, b, c, d, e, f, g, dp, //the individual LED output for the seven segment along with the digital point
output [3:0] an // the 4 bit enable signal
);
localparam N = 18;
reg [N-1:0]count; //the 18 bit counter which allows us to multiplex at 1000Hz
always @ (posedge clock or posedge reset)
begin
if (reset)
count <= 0;
else
count <= count + 1;
end
reg [6:0]sseg; //the 7 bit register to hold the data to output
reg [3:0]an_temp; //register for the 4 bit enable
always @ (*)
begin
case(count[N-1:N-2]) //using only the 2 MSB's of the counter
2'b00 : //When the 2 MSB's are 00 enable the fourth display
begin
sseg = in0;
an_temp = 4'b1110;
end
2'b01: //When the 2 MSB's are 01 enable the third display
begin
sseg = in1;
an_temp = 4'b1101;
end
2'b10: //When the 2 MSB's are 10 enable the second display
begin
sseg = in2;
an_temp = 4'b1011;
end
2'b11: //When the 2 MSB's are 11 enable the first display
begin
sseg = in3;
an_temp = 4'b0111;
end
endcase
end
assign an = an_temp;
reg [6:0] sseg_temp; // 7 bit register to hold the binary value of each input given
always @ (*)
begin
case(sseg)
4'd0 : sseg_temp = 7'b1000000; //to display 0
4'd1 : sseg_temp = 7'b1111001; //to display 1
4'd2 : sseg_temp = 7'b0100100; //to display 2
4'd3 : sseg_temp = 7'b0110000; //to display 3
4'd4 : sseg_temp = 7'b0011001; //to display 4
4'd5 : sseg_temp = 7'b0010010; //to display 5
4'd6 : sseg_temp = 7'b0000010; //to display 6
4'd7 : sseg_temp = 7'b1111000; //to display 7
4'd8 : sseg_temp = 7'b0000000; //to display 8
4'd9 : sseg_temp = 7'b0010000; //to display 9
default : sseg_temp = 7'b0111111; //dash
endcase
end
assign {g, f, e, d, c, b, a} = sseg_temp; //concatenate the outputs to the register, this is just a more neat way of doing this.
// I could have done in the case statement: 4'd0 : {g, f, e, d, c, b, a} = 7'b1000000;
// its the same thing.. write however you like it
assign dp = 1'b1; //since the decimal point is not needed, all 4 of them are turned off
endmodule
</pre>
<br />Unknownnoreply@blogger.com12tag:blogger.com,1999:blog-4577759886421850250.post-62918934053888149892012-07-10T04:12:00.001+01:002012-07-22T17:37:56.807+01:00Simple Button Debouncing Code in VerilogSo you have made a counter and after programming it onto your board you realize that every button press increments the counter by 30 or 40 units. This problem is knows as bouncing and to overcome this a debouncing circuit is needed to compensate for the mechanical button bounces.<br />
<br />
The push buttons and switches on the FPGA boards are mechanical devices and tend to bounce multiple times when pressed. And since the code related to the button is usually placed in the <i>always @ (posedge clock)</i> block, every bounce of the button is picked up and processed. It has been found that the bounces last around 20 ms after which it stabilizes. The debouner circuit should be able to filter out these bounces and only pick up the stabilized state of the button.<br />
<br />
Since it is known that the bounces last around 20 ms the first thing the code should have is a timer, a timer that will outlast the 20 ms of instability. I will use a 10 ms counter and after every 10 ms will check the state of the button, if it has stabilized it should process the button press, if not the value from the button is to be ignored.<br />
<br />
To better understand the bouncing problem of the button consider the following input waveform from the button:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbURUm8aZ7f9y9ytOl-vuOieq1wtixqAlA86-8OxmSYWW46g8uXGjVvBF3uDj-sriFLNxZqN2SeN_E261lHwioXcBuDJn53s-zgsc70BMSG6MkGA5GPwjcoQHhMlz2WiMd_vkBKZ8QYYjv/s1600/debounce.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="106" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbURUm8aZ7f9y9ytOl-vuOieq1wtixqAlA86-8OxmSYWW46g8uXGjVvBF3uDj-sriFLNxZqN2SeN_E261lHwioXcBuDJn53s-zgsc70BMSG6MkGA5GPwjcoQHhMlz2WiMd_vkBKZ8QYYjv/s320/debounce.png" width="320" /></a></div>
<br />
The code for the debouncing circuit is given below. I have used FSM to code it and it has been commented in detail to explain each step. I hope it is clear enough. I have tested this and it works in simulation and on the basys2 board. I will be using this code for every project I do from now on.<br />
<br />
<pre class="brush:verilog">module debouncing(
input clock,
input reset,
input button,
output reg out
);
localparam N = 19; //for a 10ms tick
reg [N-1:0]count;
wire tick;
// the counter that will generate the tick.
always @ (posedge clock or posedge reset)
begin
if(reset)
count <= 0;
else
count <= count + 1;
end
assign tick = &count; //AND every bit of count with itself. Tick will only go high when all 19 bits of count are 1, i.e. after 10ms
// now for the debouncing FSM
localparam[2:0] //defining the various states to be used
zero = 3'b000,
high1 = 3'b001,
high2 = 3'b010,
high3 = 3'b011,
one = 3'b100,
low1 = 3'b101,
low2 = 3'b110,
low3 = 3'b111;
reg [2:0]state_reg;
reg [2:0]state_next;
always @ (posedge clock or posedge reset)
begin
if (reset)
state_reg <= zero;
else
state_reg <= state_next;
end
always @ (*)
begin
state_next <= state_reg; // to make the current state the default state
out <= 1'b0; // default output low
case(state_reg)
zero:
if (button) //if button is detected go to next state high1
state_next <= high1;
high1:
if (~button) //while here if button goes back to zero then input is not yet stable and go back to state zero
state_next <= zero;
else if (tick) //but if button remains high even after 10 ms, go to next state high2.
state_next <= high2;
high2:
if (~button) //while here if button goes back to zero then input is not yet stable and go back to state zero
state_next <= zero;
else if (tick) //else if after 20ms (10ms + 10ms) button is still high go to high3
state_next <= high3;
high3:
if (~button) //while here if button goes back to zero then input is not yet stable and go back to state zero
state_next <= zero;
else if (tick) //and finally even after 30 ms input stays high then it is stable enough to be considered a valid input, go to state one
state_next <= one;
one: //debouncing eliminated make output high, now here I'll check for bouncing when button is released
begin
out <= 1'b1;
if (~button) //if button appears to be released go to next state low1
state_next <= low1;
end
low1:
if (button) //while here if button goes back to high then input is not yet stable and go back to state one
state_next <= one;
else if (tick) //else if after 10ms it is still high go to next state low2
state_next <= low2;
low2:
if (button) //while here if button goes back to high then input is not yet stable and go back to state one
state_next <= one;
else if (tick) //else if after 20ms it is still high go to next state low3
state_next <= low3;
low3:
if (button) //while here if button goes back to high then input is not yet stable and go back to state one
state_next <= one;
else if (tick) //after 30 ms if button is low it has actually been released and bouncing eliminated, go back to zero state to wait for next input.
state_next <= zero;
default state_next <= zero;
endcase
end
endmodule</pre>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-4577759886421850250.post-62002767722722869092012-07-08T03:25:00.000+01:002012-07-10T04:43:15.703+01:00Blocking vs Non Blocking AssignmentsI did not initially plan on adding such topics to this blog but the reason I'm covering this is because I had a great deal of difficulty coding a FIFO buffer as I also was not clear regarding this concept. I was writing writing combinational logic in sequential blocks, which I read is not a good idea.<br />
<br />
In an always block expressions and variables can be connected using either a blocking or non-blocking statement. Knowing when to use which will make the code work. As a general rule blocking assignments are used to describe combinational logic and non-blocking are used to describe sequential logic.<br />
<br />
<h3>
<b>Blocking Assignment:</b></h3>
<br />
Simply put this follows more of a C and C++ style, that is the lines of code are processed one after an other. The syntax for this blocking assignment is:<br />
<br />
<pre class="brush:verilog">(variable) = (expression);</pre>
<br />
So when this line is executed the expression on the right hand side is calculated and the value is assigned to the variable on the left hand side. While this expression is being evaluated it will block the calculation of any other expression. That is untill this line is completed it will block the calculation of any other expression. That is why it is known as blocking assignment. It will only move to the next line when the expression has been calculated and the value assigned to the variable.<br />
<br />
Consider the example:<br />
<br />
<pre class="brush:verilog">module blocking(
input x,y,z,
output c
);
always @ (*)
begin
c = x; // c takes value of x
c = c & y; // c takes the value of x & y
c = c & z; // c takes the value of x & y & z
end
endmodule
</pre>
<br />
So the above code will run in a C style, the expressions are evaluated step by step. Such that in the end we get a logical AND of all three inputs. The assignments of the variables on the left hand side are explained in the comments.<br />
<br />
<h3>
<b>Non Blocking Assignment:</b></h3>
<br />
The non blocking assignments are much different that the blocking ones. They are usually used in sequential always blocks. These assignments truly describe how hardware works. The syntax for non blocking assignment is:<br />
<br />
<pre class="brush:verilog">(variable) <= (expression);</pre>
<br />
An always block using non blocking assignments can be thought of as hardware. When an always block with non blocking assignments is executed, the right hand sides of all the expressions contained within it are calculated at the start of the block. And at the end of the this always block the calculated values of these expressions are assigned to the variables on the left hand side, all at the same time. These are called non blocking because the calculation of one expression does not prevent the calculation of the next. It is not a good idea to mix blocking and non blocking in the same always block.<br />
<br />
Now consider the same example again, but this time for clarity suppose x has a value of 10.<br />
<br />
<pre class="brush:verilog">module blocking(
input x,y,z,
output c
);
always @ (*)
begin // c will take its old/previous value, whatever it may be, for clarity suppose it is 0.
c <= x; // at the end of this always block c will take the value of x
c <= c & y; // at the end of this always block c will tale the value of c old value (0) AND'd with y
c <= c & z; // at the end of this always block c will tale the value of c old value (0) AND'd with z
end
endmodule
</pre>
<br />
In this case the first two lines are meaningless and the above code can be replaced by the last line i.e. c <= c & z;<br />
<br />
Note that one method is not better than the other and both have their importance. One cannot complete some designs without using both assignments in their code. As can be seen from my next updates.<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4577759886421850250.post-26117369463656268802012-06-20T15:19:00.001+01:002012-07-10T04:43:41.890+01:00Binary Counter in Verilog | BASYS2Now that we have the <a href="http://simplefpga.blogspot.co.uk/2012/06/code-to-make-led-blink.html">blinking LED in Verilog</a> up and running, we can do an advanced version of the same project; a binary counter using the LED's. <br />
Also this time I will be using the push button to increment the counter. So every time the push button is pressed the counter will be incremented by 1, the LED's will present the binary counter.<br />
<br />
The code for the program is shown below:<br />
<pre class="brush:verilog">module button_binary(
input clock,
input reset,
input button,
output led,
output led2,
output led3,
output led4,
output led5,
output led6,
output led7,
output led8
);
reg [7:0]count;
always @ (posedge button or posedge reset)
begin
if (reset)
count <= 0;
else if (button)
count <= count + 1;
end
assign led = count[0];
assign led2 = count[1];
assign led3 = count[2];
assign led4 = count[3];
assign led5 = count[4];
assign led6 = count[5];
assign led7 = count[6];
assign led8 = count[7];
endmodule
</pre>
<br />
The above program is so simple it needs no commenting, the thing to note here though is the always block. In place of the usual clock I used the push button (always @ posedge button). This is not the best method, but if I use clock here without any debouncing mechanism the counter will not be accurate, i.e. every time the push button is pressed due to the bouncing problem related to push buttons the counter will be incremented many times for each time it is pressed.<br />
<br />
I will design the de-bouncing circuit in a later post.<br />
<br />
The .ucf file for the above design for the basys2 board is shown below:<br />
<br />
<pre class="brush:verilog"># Pin assignment for LEDs
NET "led8" LOC = "g1" ;
NET "led7" LOC = "p4" ;
NET "led6" LOC = "n4" ;
NET "led5" LOC = "n5" ;
NET "led4" LOC = "p6" ;
NET "led3" LOC = "p7" ;
NET "led2" LOC = "m11" ;
NET "led" LOC = "m5" ;
# Pin assignment for pushbutton switches
NET "reset" LOC = "a7";
NET "button" LOC = "m4";
# Pin assignment for clock
NET "clock" LOC = "b8";
</pre>
<br />
The working of the above code is shown below:<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="360" src="http://www.youtube.com/embed/JtDYJRCN0s4" width="640"></iframe>Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-4577759886421850250.post-88785828249141785562012-06-12T02:29:00.000+01:002012-07-10T04:44:17.395+01:00Code to Make the LED BlinkThis is a very simple program, the desired target is to make the LED's on the BASYS2 board blink, and by blinking I mean a very visible turning on and off. This can be very easily achieved in verilog. The code can be found below:<br />
<br />
<br />
<pre class="brush:verilog">module led_simple(
input clock,
input reset,
output led, led2, led3, led4, led5
);
reg [26:0] count; //A sizable 27 bit register so that the blink can be seen and is visible, too small a register will make the
//register stay on as it will blink extremely fast.
always@ (posedge clock or posedge reset)
begin
if (reset)
count <= 0; //if reset button is pressed, initialize or reset the register
else
count <= count + 1; //otherwise increment the register
end
assign led = count[26]; //MSB connected to output led. and the other outputes conncted as below
assign led2 = count[25];
assign led3 = count[24];
assign led4 = count[23];
assign led5 = count[22];
endmodule
</pre>
<br />
<br />
The concept is very simple. I defined a 27 bit register to count from 27'b0 till 27'b1. Every time the MSB and the MSB-1, MSB-2... become 1 the LED connected to that bit will turn on, otherwise it will stay off.<br />
<br />
The register can be of any size, but it should be large enough for it to take some time to activate the MSB thus making the blink nice and visible.<br />
<br />
The above code has been tested and can be programed onto the BASYS2 board, using the <a href="http://simplefpga.blogspot.co.uk/2012/06/user-constraint-file-ucf-for-basys2.html">BASYS2 .ucf</a> file I posted. Ofcourse the file must be edited for it to work, only the required pins must be used. For example the original .ucf file for this code will be:<br />
<br />
<br />
<pre class="brush:verilog"># Pin assignment for LEDs
NET "led5" LOC = "n5" ;
NET "led4" LOC = "p6" ;
NET "led3" LOC = "p7" ;
NET "led2" LOC = "m11" ;
NET "led" LOC = "m5" ;
# Pin assignment for pushbutton switches
NET "reset" LOC = "a7";
# Pin assignment for clock
NET "clock" LOC = "b8";
</pre>
The above code can be seen working in the video here:<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="360" src="http://www.youtube.com/embed/bZ96ZdoF7-s" width="480"></iframe>Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-4577759886421850250.post-27872586616701961692012-06-11T14:40:00.002+01:002012-07-10T04:44:28.276+01:00User Constraint File .UCF for BASYS2 BoardHere is the user constraint file (.ucf) file that shows every pin location on the board. This file will be used in every project here as without it programming the FPGA is impossible.<br />
<br />
<pre class="prettyprint prettyprinted">
</pre>
<pre class="brush:verilog">
<br />
# Pin assignment for LEDs
NET "ld<7>" LOC = "g1" ;
NET "ld<6>" LOC = "p4" ;
NET "ld<5>" LOC = "n4" ;
NET "ld<4>" LOC = "n5" ;
NET "ld<3>" LOC = "p6" ;
NET "ld<2>" LOC = "p7" ;
NET "ld<1>" LOC = "m11" ;
NET "ld<0>" LOC = "m5" ;
# Pin assignment for slide switches
NET "sw<7>" LOC = "n3";
NET "sw<6>" LOC = "e2";
NET "sw<5>" LOC = "f3";
NET "sw<4>" LOC = "g3";
NET "sw<3>" LOC = "b4";
NET "sw<2>" LOC = "k3";
NET "sw<1>" LOC = "l3";
NET "sw<0>" LOC = "p11";
# Pin assignment for pushbutton switches
NET "btn<3>" LOC = "a7";
NET "btn<2>" LOC = "m4";
NET "btn<1>" LOC = "c11";
NET "btn<0>" LOC = "g12";
# Pin assignment for 7-segment displays
NET "a_to_g<6>" LOC = "l14" ;
NET "a_to_g<5>" LOC = "h12" ;
NET "a_to_g<4>" LOC = "n14" ;
NET "a_to_g<3>" LOC = "n11" ;
NET "a_to_g<2>" LOC = "p12" ;
NET "a_to_g<1>" LOC = "l13" ;
NET "a_to_g<0>" LOC = "m12" ;
NET "dp" LOC = "n13" ;
NET "an<3>" LOC = "k14";
NET "an<2>" LOC = "m13";
NET "an<1>" LOC = "j12";
NET "an<0>" LOC = "f12";
# Pin assignment for clock
NET "clk" LOC = "b8";
</pre>Unknownnoreply@blogger.com0