Binary to BCD Converter
From: Binary to BCD Converter (johnloomis.org)
Shift and Add-3 Algorithm
- Shift the binary number left one bit.
- If 8 shifts have taken place, the BCD number is in the Hundreds, Tens, and Units column.
- If the binary value in any of the BCD columns is 5 or greater, add 3 to that value in that BCD column.
- Go to 1.
Example 1: Convert hex:0xE to BCD
Example 2: Convert hex:0xFF to BCD
Truth table for Add-3 Module
Here is a Verilog module for this truth table.
module add3(in,out);
input [3:0] in;
output [3:0] out;
reg [3:0] out;
always @ (in) begin
case (in)
4'b0000: out <= 4'b0000;
4'b0001: out <= 4'b0001;
4'b0010: out <= 4'b0010;
4'b0011: out <= 4'b0011;
4'b0100: out <= 4'b0100;
4'b0101: out <= 4'b1000;
4'b0110: out <= 4'b1001;
4'b0111: out <= 4'b1010;
4'b1000: out <= 4'b1011;
4'b1001: out <= 4'b1100;
default: out <= 4'b0000;
endcase
end
/* or */
/*
always @ (*) begin
if(in >= 10) //10-15
out <= 0;
else if(in >= 5) //5-9
out <= in+ 3;
else //0-4
out <= in;
end
*/
endmodule
Binary-to-BCD Converter Module
Here is a structural Verilog module corresponding to the logic diagram.
module binary_to_BCD(A,ONES,TENS,HUNDREDS);
input [7:0] A;
output [3:0] ONES, TENS;
output [1:0] HUNDREDS;
wire [3:0] c1,c2,c3,c4,c5,c6,c7;
wire [3:0] d1,d2,d3,d4,d5,d6,d7;
assign d1 = {1'b0,A[7:5]};
assign d2 = {c1[2:0],A[4]};
assign d3 = {c2[2:0],A[3]};
assign d4 = {c3[2:0],A[2]};
assign d5 = {c4[2:0],A[1]};
assign d6 = {1'b0,c1[3],c2[3],c3[3]};
assign d7 = {c6[2:0],c4[3]};
add3 m1(d1,c1);
add3 m2(d2,c2);
add3 m3(d3,c3);
add3 m4(d4,c4);
add3 m5(d5,c5);
add3 m6(d6,c6);
add3 m7(d7,c7);
assign ONES = {c5[2:0],A[0]};
assign TENS = {c7[2:0],c5[3]};
assign HUNDREDS = {c6[3],c7[3]};
endmodule
两个合并后:
module binary_to_bcd(
//Inputs
input [7:0] bin,
//Outputs
output [3:0] bcd_one,
output [3:0] bcd_ten,
output [3:0] bcd_hun
);
wire [3:0] d1 = {1'b0, bin[7:5]};
wire [3:0] c1 = convert(d1);
wire [3:0] d2 = {c1[2:0], bin[4]};
wire [3:0] c2 = convert(d2);
wire [3:0] d3 = {c2[2:0], bin[3]};
wire [3:0] c3 = convert(d3);
wire [3:0] d4 = {c3[2:0], bin[2]};
wire [3:0] c4 = convert(d4);
wire [3:0] d5 = {c4[2:0], bin[1]};
wire [3:0] c5 = convert(d5);
wire [3:0] d6 = {1'b0, c1[3], c2[3], c3[3]};
wire [3:0] c6 = convert(d6);
wire [3:0] d7 = {c6[2:0], c4[3]};
wire [3:0] c7 = convert(d7);
assign bcd_one = {c5[2:0], bin[0]};
assign bcd_ten = {c7[2:0], c5[3]};
assign bcd_hun = {c6[3], c7[3]};
function [3:0] convert(
input [3:0] in
);
begin
if(in >= 10) //10-15
convert = 0;
else if(in >= 5) //5-9
convert = in + 3;
else //0-4
convert = in;
/*
case (in)
4'b0000: convert = 4'b0000;
4'b0001: convert = 4'b0001;
4'b0010: convert = 4'b0010;
4'b0011: convert = 4'b0011;
4'b0100: convert = 4'b0100;
4'b0101: convert = 4'b1000;
4'b0110: convert = 4'b1001;
4'b0111: convert = 4'b1010;
4'b1000: convert = 4'b1011;
4'b1001: convert = 4'b1100;
default: convert = 4'b0000;
endcase
*/
end
endfunction
endmodule
General Binary-to-BCD Converter
The linked code is a general binary-to-BCD Verilog module, but I have not personally tested the code.
module binary_to_bcd (
clk_i,
ce_i,
rst_i,
start_i,
dat_binary_i,
dat_bcd_o,
done_o
);
parameter BITS_IN_PP = 16; // # of bits of binary input
parameter BCD_DIGITS_OUT_PP = 5; // # of digits of BCD output
parameter BIT_COUNT_WIDTH_PP = 4; // Width of bit counter
// I/O declarations
input clk_i; // clock signal
input ce_i; // clock enable input
input rst_i; // synchronous reset
input start_i; // initiates a conversion
input [BITS_IN_PP - 1: 0] dat_binary_i; // input bus
output [4 * BCD_DIGITS_OUT_PP - 1: 0] dat_bcd_o; // output bus
output done_o; // indicates conversion is done
reg [4 * BCD_DIGITS_OUT_PP - 1: 0] dat_bcd_o;
// Internal signal declarations
reg [BITS_IN_PP - 1: 0] bin_reg;
reg [4 * BCD_DIGITS_OUT_PP - 1: 0] bcd_reg;
wire [BITS_IN_PP - 1: 0] bin_next;
reg [4 * BCD_DIGITS_OUT_PP - 1: 0] bcd_next;
reg busy_bit;
reg [BIT_COUNT_WIDTH_PP - 1: 0] bit_count;
wire bit_count_done;
//--------------------------------------------------------------------------
// Functions & Tasks
//--------------------------------------------------------------------------
function [4 * BCD_DIGITS_OUT_PP - 1: 0] bcd_asl;
input [4 * BCD_DIGITS_OUT_PP - 1: 0] din;
input newbit;
integer k;
reg cin;
reg [3: 0] digit;
reg [3: 0] digit_less;
begin
cin = newbit;
for (k = 0; k < BCD_DIGITS_OUT_PP; k = k + 1) begin
digit[3] = din[4 * k + 3];
digit[2] = din[4 * k + 2];
digit[1] = din[4 * k + 1];
digit[0] = din[4 * k];
digit_less = digit - 5;
if (digit > 4'b0100) begin
bcd_asl[4 * k + 3] = digit_less[2];
bcd_asl[4 * k + 2] = digit_less[1];
bcd_asl[4 * k + 1] = digit_less[0];
bcd_asl[4 * k + 0] = cin;
cin = 1'b1;
end
else begin
bcd_asl[4 * k + 3] = digit[2];
bcd_asl[4 * k + 2] = digit[1];
bcd_asl[4 * k + 1] = digit[0];
bcd_asl[4 * k + 0] = cin;
cin = 1'b0;
end
end // end of for loop
end
endfunction
//--------------------------------------------------------------------------
// Module code
//--------------------------------------------------------------------------
// Perform proper shifting, binary ASL and BCD ASL
assign bin_next = {bin_reg, 1'b0};
always @(bcd_reg or bin_reg) begin
bcd_next <= bcd_asl(bcd_reg, bin_reg[BITS_IN_PP - 1]);
end
// Busy bit, input and output registers
always @(posedge clk_i) begin
if (rst_i) begin
busy_bit <= 0; // Synchronous reset
dat_bcd_o <= 0;
end
else
if (start_i && ~busy_bit) begin
busy_bit <= 1;
bin_reg <= dat_binary_i;
bcd_reg <= 0;
end
else
if (busy_bit && ce_i && bit_count_done && ~start_i) begin
busy_bit <= 0;
dat_bcd_o <= bcd_next;
end
else
if (busy_bit && ce_i && ~bit_count_done) begin
bcd_reg <= bcd_next;
bin_reg <= bin_next;
end
end
assign done_o = ~busy_bit;
// Bit counter
always @(posedge clk_i) begin
if (~busy_bit)
bit_count <= 0;
else
if (ce_i && ~bit_count_done)
bit_count <= bit_count + 1;
end
assign bit_count_done = (bit_count == (BITS_IN_PP - 1));
endmodule
Reference: course materials from Prof. Richard E. Haskell
Maintained by John Loomis, last updated 4 Jan 2004