Verilog 二进制转BCD码

Binary to BCD Converter

From: Binary to BCD Converter (johnloomis.org)

Shift and Add-3 Algorithm

  1. Shift the binary number left one bit.
  2. If 8 shifts have taken place, the BCD number is in the Hundreds, Tens, and Units column.
  3. If the binary value in any of the BCD columns is 5 or greater, add 3 to that value in that BCD column.
  4. Go to 1.

Example 1: Convert hex:0xE to BCD

img

Example 2: Convert hex:0xFF to BCD

在这里插入图片描述

Truth table for Add-3 Module

img

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

img

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

### Vivado 中数管译测试代示例 在 Vivado 平台上实现数管译功能通常涉及编写 Verilog 或 VHDL 代。以下是基于 Verilog 的一个简单例子,用于将 BCD换为七段数管显示所需的信号。 #### 1. 主模块定义 首先创建主模块 `seven_segment_decoder` 来处理 BCD 到七段显示器的映射: ```verilog // seven_segment_decoder.v module seven_segment_decoder( input [3:0] bcd, // 输入BCD (4位) output reg [6:0] seg // 输出到7段LED (a-g) ); always @(*) begin case(bcd) 4'b0000 : seg = 7'b1000000; // 显示 '0' 4'b0001 : seg = 7'b1111001; // 显示 '1' 4'b0010 : seg = 7'b0100100; // 显示 '2' 4'b0011 : seg = 7'b0110000; // 显示 '3' 4'b0100 : seg = 7'b0011001; // 显示 '4' 4'b0101 : seg = 7'b0010010; // 显示 '5' 4'b0110 : seg = 7'b0000010; // 显示 '6' 4'b0111 : seg = 7'b1111000; // 显示 '7' 4'b1000 : seg = 7'b0000000; // 显示 '8' 4'b1001 : seg = 7'b0010000; // 显示 '9' default : seg = 7'bz; // 默认状态(高阻态) endcase end endmodule ``` 此部分实现了基本的功能——接收四位二进制数作为输入并将其翻译成适合驱动共阴极型七段 LED 所需的形式[^1]。 #### 2. 测试平台设置 为了验证上述设计,在同一项目内建立另一个名为 `tb_seven_segment_decoder` 的测试平台文件来进行行为级仿真: ```verilog // tb_seven_segment_decoder.v module tb_seven_segment_decoder; reg [3:0] bcd_in; wire [6:0] seg_out; seven_segment_decoder uut ( .bcd(bcd_in), .seg(seg_out) ); initial begin $monitor("Time=%t\tInput_BCD=%b\tOutput_Segments=%b", $time, bcd_in, seg_out); // 初始化输入向量 bcd_in = 4'd0; #10 // 循环遍历所有可能的BCD值 for(int i=0;i<10;i=i+1)begin bcd_in = i; #10; end $finish; end endmodule ``` 这段脚本模拟了一系列不同的 BCD 值传递给解器的过程,并观察输出的变化情况以确认其工作正常[^2]。 通过这种方式可以在不依赖具体硬件的情况下快速评估和调试逻辑电路的行为特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

whik1194

如果对你有帮助,欢迎打赏。谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值