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

Wednesday, November 4, 2015

Verilog Code for BCD addition - Behavioral level

BCD or Binary coded decimal is a way of representing decimal digits in binary form. Generally 4 bits are used to represent values 0 to 9.

Decimal
Digit
BCD
8 4 2 1
00 0 0 0
10 0 0 1
20 0 1 0
30 0 1 1
40 1 0 0
50 1 0 1
60 1 1 0
70 1 1 1
81 0 0 0
91 0 0 1

In this post, I want to discuss about, how two BCD digits can be added. Later, I write the code in Verilog, implementing a basic BCD adder. 
A BCD adder, takes in two BCD numbers as inputs, and outputs a BCD digit along with a carry output. If the sum of the BCD digits is less than or equal to 9, then we don't have a problem. But if its greater than 9, we have to convert it into BCD format. This is done by adding 6 to the sum and taking only the least significant 4 bits. The MSB bit is output as carry.

Consider the below BCD addition :

1001 + 1000 = 10001
   9 +    8 =    17

The output 17 is more than 9. So we add 6 to it. So we get,
17+6 = 23 (in binary 23 is 10111)
Now the least significant 4 bits(which is "0111") represent the units digit and the MSB(4th bit which is '1') bit represents the tens digit.

Since the range of input is 0 to 9, the maximum output is 18. If you consider a carry it becomes 19. This means at the output side we need a 4 bit sum and a 1 bit carry to represent the most significant digit.

For multiple digit addition , you can connect the carry_out to the carry input of the next adder. A simple cascading network of these small adders is enough to realize the multiple digit BCD addition. I suggest you try to implement a 4 digit BCD adder as homework, using the below module.

Verilog code for BCD addition:

//module declaration with inputs and outputs
module bcd_adder(a,b,carry_in,sum,carry);

//declare the inputs and outputs of the module with their sizes.
    input [3:0] a,b;
    input carry_in;
    output [3:0] sum;
    output carry;
    //Internal variables
    reg [4:0] sum_temp;
    reg [3:0] sum;
    reg carry;  

//always block for doing the addition
    always @(a,b,carry_in)
    begin
        sum_temp = a+b+carry_in; //add all the inputs
        if(sum_temp > 9)    begin
            sum_temp = sum_temp+6; //add 6, if result is more than 9.
            carry = 1;  //set the carry output
            sum = sum_temp[3:0];    end
        else    begin
            carry = 0;
            sum = sum_temp[3:0];
        end
    end     

endmodule

Testbench for BCD adder:

module tb_bcdadder;

    // Inputs
    reg [3:0] a;
    reg [3:0] b;
    reg carry_in;

    // Outputs
    wire [3:0] sum;
    wire carry;

    // Instantiate the Unit Under Test (UUT)
    bcd_adder uut (
        .a(a), 
        .b(b), 
        .carry_in(carry_in), 
        .sum(sum), 
        .carry(carry)
    );

    initial begin
        // Apply Inputs
        a = 0;  b = 0;  carry_in = 0;   #100;
        a = 6;  b = 9;  carry_in = 0;   #100;
        a = 3;  b = 3;  carry_in = 1;   #100;
        a = 4;  b = 5;  carry_in = 0;   #100;
        a = 8;  b = 2;  carry_in = 0;   #100;
        a = 9;  b = 9;  carry_in = 1;   #100;
    end
      
endmodule

Simulation waveform:


When the codes are simulated in Xilinx ISE 13.1, you should get the above waveform. 

Monday, October 26, 2015

Verilog code for 8 bit Binary to BCD using Double Dabble algorithm

BCD or Binary-coded decimal is a class of binary encodings of decimal numbers where each decimal digit is represented by four bits. This format is useful for displaying a value in a seven segment display or LCD panel. 

To convert a binary number to BCD format, we can use an algorithm called Double Dabble. In this post I have written a Verilog code for converting a 8 bit binary number into BCD format. The maximum value of a 8 bit binary number is 255 in decimal. This means we need 3 BCD digits in the output. So I have chosen the size of the output as 3 digits*4 bits = 12 bits.

Note that I am not using a clock in this module. Everything is combinational. As the binary input gets bigger in size, this might use up a lot of resources and will result in more combinational path delay. I suggest as a home work, try to re-write the below code by adding a Clock to the module.

Binary to BCD converter:

module bin2bcd(
    bin,
     bcd
    );

    
    //input ports and their sizes
    input [7:0] bin;
    //output ports and, their size
    output [11:0] bcd;
    //Internal variables
    reg [11 : 0] bcd; 
     reg [3:0] i;   
     
     //Always block - implement the Double Dabble algorithm
     always @(bin)
        begin
            bcd = 0; //initialize bcd to zero.
            for (= 0; i < 8; i = i+1) //run for 8 iterations
            begin
                bcd = {bcd[10:0],bin[7-i]}; //concatenation
                    
                //if a hex digit of 'bcd' is more than 4, add 3 to it.  
                if(< 7 && bcd[3:0] > 4) 
                    bcd[3:0] = bcd[3:0] + 3;
                if(< 7 && bcd[7:4] > 4)
                    bcd[7:4] = bcd[7:4] + 3;
                if(< 7 && bcd[11:8] > 4)
                    bcd[11:8] = bcd[11:8] + 3;  
            end
        end     
                
endmodule

Testbench Code:

module tb_bin2bcd;

    // Input
    reg [7:0] bin;
    // Output
    wire [11:0] bcd;
    // Extra variables
    reg [8:0] i;

    // Instantiate the Unit Under Test (UUT)
    bin2bcd uut (
        .bin(bin), 
        .bcd(bcd)
    );

//Simulation - Apply inputs
    initial begin
    //A for loop for checking all the input combinations.
        for(i=0;i<256;i=i+1)
        begin
            bin = i; 
            #10; //wait for 10 ns.
        end 
        $finish; //system function for stoping the simulation.
    end
      
endmodule

Simulation Waveform:

The code was synthesised and simulated using Xilinx ISE 13.1. A part of the waveform looked like this:


Some sample inputs and the corresponding outputs are shown below:

bin = "01100011" , output = "0000 1001 1001" (99).
bin = "11111110" , output = "0010 0101 0100" (254).
bin = "10111011" , output = "0001 1000 0111" (187).

Note :- The code can be modified to convert any length binary number to BCD digits.This require only very little change in the code.