case statements in Verilog

case statements in Verilog

Like other languages, Verilog supports case statements. It is often more efficient and readable to use case in place of if/else conditions. In this assignment, we’ll make a simple arithmetic unit that selects between four operations:

You will create a module named arithmetic_unit with the behavior specified above. The template file src/arithmetic_unit.v demonstrates the syntax for case statements:

module arithmetic_unit 
(
   input signed  [3:0] A,
   input signed  [3:0] B,
   input      [1:0] sel, 
   output reg [3:0] Q,  
   output reg       overflow
);

   always @(*) begin
      case (sel)
         2'b00:
           begin
              // Place case 00 assignments here
           end
         2'b01:
           begin
             // Place case 01 assignments here
           end
         2'b10:
           begin
              // Place case 10 assignments here
           end
         2'b11:
           begin
              // Place case 11 assignments here
           end
      endcase
   end

endmodule

In each case you fill in the appropriate assignment. Since this is a non-clocked, combinational block (the sensitivity list is @(*)), you should use blocking assignments with the = operator as opposed to the non-blocking <= operator.

For the ADD and SUBTRACT operations, you need to implement the overflow logic. For signed operations, an overflow occurs when A and B have the same sign (both positive or both negative), but the result Q has opposite sign. For example, consider the binary sum 7+2 using four-bit signals:

4'b0111+4'b0010 = 4'b1001

Since the I/O signals are indicated as signed, they are assumed to be in 2’s complement format, where the MSB is the sign bit. In the 2’s complement representation, 4'b1001 is equal to negative 4'b0111, or -7 decimal. Obviously 7+2 is not -7, so an overflow error has occurred. In your module, the overflow output should flag all such errors. For the bitwise operations (AND, OR), overflow should be always zero.

Assigned Tasks

Complete the arithmetic_unit module. A testbench template is provided; you should fill in the CREATE STIMULI block so as to exhaustively test the arithmetic module. Since there are a total of ten input bits, you will need 2^10 unique test cases. Write all the I/O signals to a file named test_result.txt.

Once your design is verified in simulation, edit build.tcl and arithmetic_unit.xdc to implement the design. Your XDC file should make these signal mappings:

Implement the design, create a bitstream and program the Basys3 board. On the Basys3 board, test these cases:

  1. sel=00, A=4'b1010, B=4'b0011
  2. sel=00, A=4'b0110, B=4'b0011
  3. sel=01, A=4'b0110, B=4'b1011
  4. sel=01, A=4'b1110, B=4'b1101
  5. sel=10, A=4'b1010, B=4'b1100
  6. sel=01, A=4'b1010, B=4'b1100

Photograph the test cases and save the photos in the working directory as case1, case2, etc. Turn in your work using git:

git add case* src/*.v *.v *.rpt *.txt *.tcl *.bit *.xdc
git commit . -m "Complete"
git push origin main

Indicate on Canvas that your assignment is done.