E15A Laboratory 3

Behavioral Coding in Verilog


Useful references for E15 labs

You might want to print out the Synthesizable Verilog Quick Reference (pdf
(originally at http://www.cl.cam.ac.uk/teaching/0910/ECAD+Arch/files/verilogcheatsheet.pdf)


In this lab you will be performing many of the same tasks that you did in the last lab, but using more advanced Verilog, for a much more compact implementation.  Verilog will do much more of the nitty-gritty design work, allowing you to concentrate on higher level problems. You may want to refer to the Verilog Tutorial as you work through this lab, especially for creating a new project and compiling, simulating and dowloading your designs.

Task 0: Cylon Redux

Using an if...then...else construct, we can do the 4 LED cylon circuit as shown below. It performs the same function as the module from the last lab, except the input is a 3 bit vector instead of 3 discrete inputs.

module cylon(d, x);        // Implement a 'cylon' circuit
input [2:0]d;              // 3 bit input (in a vector)
output reg [3:0]x;         // 4 bit output (in a vector)

always@(*)
begin
    if(d == 3'd0)                         // if d equals 0...
        begin 
            x = 4'b0001;                  //   ...turn x[0] on, x[1]=x[2]=x[3]=0
        end
    else if ((d == 3'd1) || (d == 3'd5))  // else if d equals 1 or 5...
        begin
         x = 4'b0010;                     //   ...turn x[1] on.
        end
    else if ((d == 3'd2) || (d == 3'd4))  // else if d equals 2 or 4...
        begin 
            x = 4'b0100;                  //   x[2] is on
        end
    else if (d == 3'd3)                   // else if d equals 3...
        begin
            x = 4'b1000;                  //    ...turn x[3] on
        end
    else                                  // else...
        begin
            x = 4'bxxxx;                  //   ...we don't care about output.
        end
end
 
endmodule

 

We can make it shorter by removing the "begin" and "end" from the "if...else..." since each statment is just a single line.

module cylon(d, x);        // Implement a 'cylon' circuit
input [2:0]d;              // 3 bit input (in a vector)
output reg [3:0]x;         // 4 bit output (in a vector)

always@(*)
begin
    if(d == 3'd0)                         // if d equals 0...
        x = 4'b0001;                      //   ...turn x[0] on, x[1]=x[2]=x[3]=0
    else if ((d == 3'd1) || (d == 3'd5))  // else if d equals 1 or 5...
        x = 4'b0010;                      //   ...turn x[1] on.
    else if ((d == 3'd2) || (d == 3'd4))  // else if d equals 2 or 4...
        x = 4'b0100;                      //   x[2] is on
    else if (d == 3'd3)                   // else if d equals 3...
        x = 4'b1000;                      //    ...turn x[3] on
    else                                  // else...
        x = 4'bxxxx;                      //   ...we don't care about output.
end
 
endmodule

Or even simpler using the "case" construct instead.

module cylon(d, x);   // Implement a 'cylon' circuit
input [2:0]d;         // 3 bit input
output reg [3:0]x;    // 4 bit output(in a vector)

always@(*)
begin
   case(d)                      // change output depending on d
      3'd0: x=4'b0001;          // d==0, x[0]=1, others off
      3'd1, 3'd5: x=4'b0010;    // d==1 or d==5, x[1]=1
      3'd2, 3'd4: x=4'b0100;    // d==2 or d==4, x[2]=1
      3'd3: x=4'b1000;          // d==3, x[3]=1
      default: x=4'bxxxx;       // don't care
   endcase
end
 
endmodule

 

Task 1: Working with 7 segment displays, redux.

Write a module called BCD2Seven that acts as a BCD to 7 segment decoder.  It takes as input a four bit binary number, and as output lights a seven segment LED (the example below shows HEX0). Remember the LED segments are active low (they turn on when you send a low signal to them).

Number (decimal) 0 1 2 3 4 5 6 7 8 9
Number (binary) 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001
Display


Use a case statement or other behavioral constructs. Assume that the 4 bit input represents a number between 0 and 9, and the outputs should be "don't care" for inputs above 9. The block diagram for your module is shown below. A code skeleton is given. Keep the input and output variable names as given.

 

module BCD2Seven(D,L)
input [3:0]D;  // A four bit BCD number
output[6:0]L;  // Seven bits for LED's

//... your code ...

endmodule

Verify that the module works, either by simulation or connecting to hardware.

Task 2: Display two hex digits

Now add the module defined in E15Counter1HzB.v that you used in the previous lab - you can refer to that lab if you want to refresh your memory as to how it works. Use one "bcd2seven" module to drive HEX3 (the leftmost hex digit) and another to drive HEX2. In the drawing I called the leftmost decoder "dig3" and the righmost decoder "dig2". The inputs to "dig3" are the output of the as shown below and make sure it works as expected (that means you need to know what to expect). The first few lines of the module (in a file called "doubleDigits.v") are shown at right. Run the code on the hardware to make sure it works.

 

module doubleDigits (CLOCK_50, SW, HEX3, HEX2);
input CLOCK_50;      // 50 MHz clock
input [3:0] SW;      // 4 switches
output [6:0] HEX3;   // 7 segment output
output [6:0] HEX2;   // 7 segment output

//...your code goes here

endmodule

.

Task 3: BCD Addition

Write a BCD adder (bcdAdder.v) using behavioral code (the algorithm is described in your text, or you can figure it out for yourself). There are two 4 bit inputs, and two 4 bit outputs.

You will probably need an "if" statement. Remember also that this verilog code is not sequential. You can use Verilog to easily add two 4 digit BCD (binary coded decimal) numbers to get a 5 bit binary result. A code snippet demonstrates.

 module bcdAdder(bcdIn1, bcdIn2, bcdOut1, bcdOut2); 
 
 input [3:0] bcdIn1;       // 4 bit inputs
 input [3:0] bcdIn2;
 output reg [3:0] bcdOut1; // 4 bit outputs
 reg [3:0] bcdOut2;
 reg [4:0] sum;            // 5 bit intermediate value.
 
 always @(*)
 begin 
     sum = bcdIn1 + bcdIn2;      // do addition
 //......

You can then use the 5 bit result in "sum" to generate two 4 bit BCD numbers with a simple "if...then...else" construct. I suggest you simulate the module to make sure it works, but it is not required for the report.

Task 4: Putting it all together

Build a module based on the one in Task 2. The 4 switches and the outputs of the counter should go to your bcdAdder module, and the bcdAdder module outputs should drive the rightmost hex digits. In the end, the HEX3 should count from 0 to 9, HEX2 should display the BCD number entered by SW[3:0], HEX1 should show the most significant digit of the result, and HEX0 should show the least significant digit. The result should be from 00 (0 added to 0) to 18 (9 added to 9). Think about the block diagram you need to connect the various modules. You needn't consider erroneous inputs (i.e., 4 bit numbers greater then 9) You should be able to use the modules from above without changing them.

Demonstrate your circuit for me (or send me a video, along with the names of the people in your group). Include the text "E15 Lab 2, Task 4" in the subject line.

 

Task 5: Extra (not required)

Change the design from Task 4 to a circuit that subtracts the number on HEX2 from the number on HEX3 and displays the result on HEX1 and HEX0 (HEX1 is used for a negative sign, if necessary). This does not take a lot of code, but takes a bit more thought than simply adding.

Demonstrate your circuit for me with both positive and negative subtraction results (or send me a video, along with the names of the people in your group). Include the text "E15 Lab 2, Task 5" in the subject line.

 


To Turn in:

Each part of each task should be well labeled and in order. Turn in a single file on moodle.

 

 


← Back to E15 Lab page ←

Please contact me if you find any errors or other problems (e.g., something is unclearly stated) in this web page