Search code examples
verilogsystem-verilogfpgaxilinxbcd

If statement is not executing properly while trying to create double dabble to convert binary to BCD


I am trying to build a binary to BCD converter using the double dabble algorithm. I wrote the code for the same, and when I simulated the entire thing, it was observed that my if statement is not getting executed properly.

`timescale 1ns / 1ps

module test_6( input [13:0] bin ,
                    output reg [3:0] ones,  // ones value of the input number
                    output reg [3:0] tens,  // tens value of the input number
                    output reg [3:0] hundreds, // hundreds value of the input nnumber
                    output reg [3:0] thousands // thousands value of the input number
    );

integer i;
reg [15:0] scratch; // 16 bit register 
reg [29:0] combined; // 30 bit concatenated register bin and scratch

always @(bin) begin
scratch = 0;
combined = {scratch[15:0], bin[13:0]};  // concatenating scratch and bin into combined

for (i=0; i<14; i=i+1) begin 
combined = combined<<1;    // left shift by 1     

    if (combined[17:14] > 4) begin 
        combined[17:14] = combined[17:14] + 4'b0011;  //check if >4, if yes add 3
        
        end
    if (combined[21:18] > 4) begin 
        combined[21:18] = combined[21:18] + 4'b0011;  //check if >4, if yes add 3
        
        end
    if (combined[25:22] > 4) begin
        combined[25:22] = combined[25:22] + 4'b0011;  //check if >4, if yes add 3
        
        end
    if (combined[29:26] > 4) begin 
        combined[29:26] = combined[29:26] + 4'b0011;  //check if >4, if yes add 3
        
        end
        
end
thousands = combined[29:26];  
hundreds = combined[25:22];
tens = combined[21:18];
ones = combined[17:14];

$display(ones);
$display(tens);
$display(hundreds);
$display(thousands);
end

endmodule

The testbench is given below.

module test_6_tb;

    // Inputs
    reg [13:0] bin;
    // Outputs
    wire [3:0] ones;
    wire [3:0] tens;
    wire [3:0] hundreds;
    wire [3:0] thousands;
    // Instantiate the Unit Under Test (UUT)
    test_6 uut (
        .bin(bin), 
        .ones(ones), 
        .tens(tens), 
        .hundreds(hundreds), 
        .thousands(thousands)
    );

    initial begin
        // Initialize Inputs
            bin = 14'd1157;
        // Wait 100 ns for global reset to finish
        #100;
        
        // Add stimulus here

    end
      
endmodule

The output on the simulation window was as shown: enter image description here

The output I am expecting is:

Thousands should have the value 1, hundreds should have the value 1, tens should have the value 5, ones should have the value 7.


Solution

  • The mistake in your code is that you did not follow the double dabble algorithm. From Wikipedia:

    The algorithm then iterates n times. On each iteration, any BCD digit which is at least 5 (0101 in binary) is incremented by 3 (0011); then the entire scratch space is left-shifted one bit.

    You performed the left shift before the add-by-3, but it should be done after.

    for (i=0; i<14; i=i+1) begin 
    
        if (combined[17:14] > 4) begin 
            combined[17:14] = combined[17:14] + 4'b0011;  //check if >4, if yes add 3
            
            end
        if (combined[21:18] > 4) begin 
            combined[21:18] = combined[21:18] + 4'b0011;  //check if >4, if yes add 3
            
            end
        if (combined[25:22] > 4) begin
            combined[25:22] = combined[25:22] + 4'b0011;  //check if >4, if yes add 3
            
            end
        if (combined[29:26] > 4) begin 
            combined[29:26] = combined[29:26] + 4'b0011;  //check if >4, if yes add 3
            
            end
    
        combined = combined<<1;    // left shift by 1     
            
    end
    

    Now I get the expected output: 1157.


    After I posted my other answer, I was curious as to how the algorithm worked. So, I decided to try to follow the description as you did.