1

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.

toolic
  • 57,801
  • 17
  • 75
  • 117

2 Answers2

1

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.

toolic
  • 57,801
  • 17
  • 75
  • 117
0

I searched on EE.SE and found this answer. It contains a link to Wikipedia, which has the following code. I had to fix a typo in the code, but this works:

// parametric Verilog implementation of the double dabble binary to BCD converter
// for the complete project, see
// https://github.com/AmeerAbdelhadi/Binary-to-BCD-Converter

module bin2bcd
 #( parameter                W = 14)  // input width
  ( input      [W-1      :0] bin   ,  // binary
    output reg [W+(W-4)/3:0] bcd   ); // bcd {...,thousands,hundreds,tens,ones}

  integer i,j;

  always @(bin) begin
    for(i = 0; i <= W+(W-4)/3; i = i+1) bcd[i] = 0;     // initialize with zeros
    bcd[W-1:0] = bin;                                   // initialize with input vector
    for(i = 0; i <= W-4; i = i+1)                       // iterate on structure depth
      for(j = 0; j <= i/3; j = j+1)                     // iterate on structure width
        if (bcd[W-i+4*j -: 4] > 4)                      // if > 4
          bcd[W-i+4*j -: 4] = bcd[W-i+4*j -: 4] + 4'd3; // add 3
  end
endmodule

module tb;
    reg [13:0] bin;
    reg [17:0] bcd;
    wire [3:0] ones      = bcd[ 3: 0];
    wire [3:0] tens      = bcd[ 7: 4];
    wire [3:0] hundreds  = bcd[11: 8];
    wire [3:0] thousands = bcd[15:12];

    bin2bcd dut (bin, bcd);

initial begin
    $monitor(thousands,,hundreds,,tens,,ones);
    #5 bin = 14'd1157;
    #5 bin = 14'd0045;
    #5 bin = 14'd9876;
end
endmodule

Prints:

 x  x  x  x
 1  1  5  7
 0  0  4  5
 9  8  7  6

The algorithm is thoroughly explained in the article and in the header comments of the Verilog code in github.

toolic
  • 57,801
  • 17
  • 75
  • 117