Verilog Coding Tips and Tricks: case statements
Showing posts with label case statements. Show all posts
Showing posts with label case statements. Show all posts

Tuesday, October 27, 2015

Verilog code for BCD to 7-segment display converter

A seven-segment display (SSD) is a form of electronic display device for displaying decimal numbers. They can be used as an alternative to complex display's such as dot matrix.

A SSD has 7 segments and theoretically we can use it to display 2^7 = 128 combinations of characters. But most of these combinations, doesn't make sense to a human eye. Decimal numbers can be displayed correctly on a 7 segment panel as shown below:

 



The image on the right indicates the order in which the panels are accessed normally. This is done using a 7 bit vector.

Here, I have written a Verilog code which takes in a BCD number and converts it into a 6 bit vector format, which the seven segment panel understands. Note that, to light up an individual panel, we have to switch it OFF(pass '0' through it).

Seven segment display Code:

//Verilog module.
module segment7(
     bcd,
     seg
    );
     
     //Declare inputs,outputs and internal variables.
     input [3:0] bcd;
     output [6:0] seg;
     reg [6:0] seg;

//always block for converting bcd digit into 7 segment format
    always @(bcd)
    begin
        case (bcd) //case statement
            0 : seg = 7'b0000001;
            1 : seg = 7'b1001111;
            2 : seg = 7'b0010010;
            3 : seg = 7'b0000110;
            4 : seg = 7'b1001100;
            5 : seg = 7'b0100100;
            6 : seg = 7'b0100000;
            7 : seg = 7'b0001111;
            8 : seg = 7'b0000000;
            9 : seg = 7'b0000100;
            //switch off 7 segment character when the bcd digit is not a decimal number.
            default : seg = 7'b1111111; 
        endcase
    end
    
endmodule

Testbench:

module tb_segment7;

    reg [3:0] bcd;
    wire [6:0] seg;
    integer i;

    // Instantiate the Unit Under Test (UUT)
    segment7 uut (
        .bcd(bcd), 
        .seg(seg)
    );

//Apply inputs
    initial begin
        for(= 0;< 16;= i+1) //run loop for 0 to 15.
        begin
            bcd = i; 
            #10; //wait for 10 ns
        end     
    end
      
endmodule

Simulation Waveform:

The codes were correctly simulated in Xilinx ISE 13.1. Check the waveform below:


Friday, October 23, 2015

Verilog code for a simple ALU

ALU(Arithmetic Logic Unit) is a digital circuit which does arithmetic and logical operations. Its a basic block in any processor. 

In this article I have shared Verilog code for a simple ALU. Note that this is one of the simplest architecture of an ALU. Most of the ALU's used in practical designs are far more complicated and requires good design experience. 

The block diagram of the ALU is given below. As you can see, it receives two input operands 'A' and 'B' which are 8 bits long. The result is denoted by 'R' which is also 8 bit long. The input signal 'Op' is a 3 bit value which tells the ALU what operation has to be performed by the ALU. Since 'Op' is 3 bits long we can have a maximum of 2^3=8 operations.




Our ALU is capable of doing the following operations:


ALU OperationDescription
Add SignedR = A + B : Treating A, B, and R as signed two's complement integers.
Subtract SignedR = A - B : Treating A, B, and R as signed  two's complement integers.
Bitwise ANDR(i) = A(i) AND B(i).
Bitwise NORR(i) = A(i) NOR B(i).
Bitwise ORR(i) = A(i) OR B(i).
Bitwise NANDR(i) = A(i) NAND B(i).
Bitwise XORR(i) = A(i) XOR B(i).
Biwise NOTR(i) = NOT A(i).

These functions are implemented using a case statement. The ALU calculates the outputs, whenever there is a change in the input operands A or B or in the operation to be performed Op . As soon as the outputs are calculated it is available at the port signal 'R'. 

8 bit ALU:

//Verilog module for an ALU
module ALU(
    A,
    B,
    Op,
    R   );
    
    //inputs,outputs and internal variables declared here
    input [7:0] A,B;
    input [2:0] Op;
    output [7:0] R;
    wire [7:0] Reg1,Reg2;
    reg [7:0] Reg3;
    
    //Assign A and B to internal variables for doing operations
    assign Reg1 = A;
    assign Reg2 = B;
    //Assign the output 
    assign R = Reg3;

    //Always block with inputs in the sensitivity list.
    always @(Op or Reg1 or Reg2)
    begin
        case (Op)
            0 : Reg3 = Reg1 + Reg2;  //addition
         1 : Reg3 = Reg1 - Reg2; //subtraction
         2 : Reg3 = ~Reg1;  //NOT gate
         3 : Reg3 = ~(Reg1 & Reg2); //NAND gate 
         4 : Reg3 = ~(Reg1 | Reg2); //NOR gate               
         5 : Reg3 = Reg1 & Reg2;  //AND gate
         6 : Reg3 = Reg1 | Reg2;  //OR gate    
         7 : Reg3 = Reg1 ^ Reg2; //XOR gate  
        endcase 
    end
    
endmodule

Testbench for ALU:

module tb_alu;

    // Inputs
    reg [7:0] A;
    reg [7:0] B;
    reg [2:0] Op;

    // Outputs
    wire [7:0] R;

    // Instantiate the Unit Under Test (UUT)
    ALU uut ( 
        .A(A), 
        .B(B), 
        .Op(Op), 
        .R(R)
    );
    
    initial begin
        // Apply inputs.
        A = 8'b01101010;
        B = 8'b00111011;
        Op = 0; #100;
        Op = 1; #100;
        Op = 2; #100;
        Op = 3; #100;
        Op = 4; #100;
        Op = 5; #100;
        Op = 6; #100;
        Op = 7; #100;
    end
      
endmodule

Simulation waveform:

The codes are simulated in Xilinx ISE 13.1 to get the following waveform:



Few years back, I have implemented the same ALU design using VHDL. You can check out that code here.