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.

Sunday, 22 July 2012

Seven Segment LED Multiplexing Circuit in Verilog

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

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.

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.

The code for the LED multiplexing is shown below:

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


Tuesday, 10 July 2012

Simple Button Debouncing Code in Verilog

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

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 always @ (posedge clock) 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.

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.

To better understand the bouncing problem of the button consider the following input waveform from the button:


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.

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

Sunday, 8 July 2012

Blocking vs Non Blocking Assignments

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

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.

Blocking Assignment:


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:

(variable) = (expression);

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.

Consider the example:

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 


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.

Non Blocking Assignment:


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:

(variable) <= (expression);

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.

Now consider the same example again, but this time for clarity suppose x has a value of 10.

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


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;

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.

Wednesday, 20 June 2012

Binary Counter in Verilog | BASYS2

Now that we have the blinking LED in Verilog up and running, we can do an advanced version of the same project; a binary counter using the LED's.
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.

The code for the program is shown below:
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

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.

I will design the de-bouncing circuit in a later post.

The .ucf file for the above design for the basys2 board is shown below:

# 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"; 

The working of the above code is shown below:

Tuesday, 12 June 2012

Code to Make the LED Blink

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


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


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.

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.

The above code has been tested and can be programed onto the BASYS2 board, using the BASYS2 .ucf 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:


# 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"; 

The above code can be seen working in the video here:

Monday, 11 June 2012

User Constraint File .UCF for BASYS2 Board

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



# 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";