Friday, 22 March 2013

Reaction Timer | Reflex Tester in Verilog and FPGA

This 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.

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.

Here we will be using three inputs; reset, start, stop and one output led along with displaying the time on the seven segment display.

  • When the reset 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.
  • When the start button is pressed the output led will turn on after a random interval between 0 seconds and 10 seconds. The random time is achieved using the random number generator 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.
  • After the random delay is achieved the led will turn on along with the timer.
  • The user is now to press the stop button. This will stop the timer and display your reaction time. The normal reaction time should be between 0.15s and 0.30s.
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.


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

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: 7 Segment LED multiplexing in Verilog.

And now for the code  of the reaction / reflex tester:

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


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
(* KEEP = "TRUE" *)
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 sel signal entirely after giving this warning:
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.
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.

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.


And here is the simulation of the above code:

Sunday, 10 February 2013

Random Number Generator in Verilog | FPGA

In 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 shift register with some of its bits (known as taps) XOR'd with themselves to create a feedback term.

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 (2**N) - 1 random bits before it starts repeating. For example a 30 bit LFSR will have 1073741823 random states before repeating, so for most practical purposes this can be considered true random.

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 XOR). 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.

LFSR random number tap locations


An LFSR is good for generating a stream of random bits. It does not 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.

Below is a code for a 13 bit LFSR. Notice my selection of taps is taken from the table above:

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

As requested, below is the test bench for the above code, not much stimulus in it, its just a simple reset.
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

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 ;)


Wednesday, 16 January 2013

Universal Shift Left - Right Register/Circuit in Verilog

A 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.

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.

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 

Saturday, 22 December 2012

Scrolling or Moving Text Using 7 Segment LED's in Verilog | FPGA

This 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.

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: Create accurate delay in Verilog. 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.

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.

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: 7 Segment LED Multiplexing in Verilog. Be sure to read and understand it.

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.

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.

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

Wednesday, 19 December 2012

FIFO(First In First Out) Buffer in Verilog

A 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:

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.

Implementation of FIFO in Verilog

To implement FIFO in verilog imagine the memory components to be arranged in a circular queue fashion with two pointers; write and read. The write pointer points to the start of the circle whereas the read pointer points to the end of the circle. Both these pointers increment themselves by one after each read or write operation.
This buffer will also consist of two flags; empty and full. These will help in indicating when the FIFO is full (cannot be written to) or empty (cannot be read from). This circular implementation can be seen from the following figure:


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:

module fifo # (parameter abits = 4, dbits = 3)

At reset the empty flag is set to high whereas the full flag is set to low to allow new data to be written. The positions of the read and write 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.

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

Friday, 27 July 2012

To Code a Stopwatch in Verilog

The 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.

How to Create an Accurate Delay in Verilog:


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 decimal counter in verilog post. But since it is of great importance to the design will be explained in more detail here.

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:

50MHz * 0.1 sec = 5000000

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:

2exp(x) = 5000000

Taking log on both sides:

log 2exp(x) = log 5000000

(x) log (2) = log 5000000

x = log 5000000 / log 2

x = 22.3

Hence a 23 bit wide register will be able to hold a count of 5000000.

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: Display LED Multiplexing in 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




Test bench below:


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

Video demonstration below:

00 to 99 Two Digit Decimal Counter via 7 Segment Display Using Verilog

Since I have already made a detailed post regarding 7 segment LED multiplexing, this post is going to be a short one, in which I will only explain the code via comments in code.

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.

How to make a 0.1 second accurate delay in Verilog


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.

The code for this counter is given below:

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

The multiplexing circuit has been explained and commended in detail in my previous post here : Verilog LED Multiplexing Circuit.