基于FPGA的二进制转BCD设计与实现(移位加3法)
1 项目介绍
在显示温度、电压、电流等数据时,通常需要将二进制数据转换成十进制进行显示。最常用的方法是将二进制转换成BCD码(8421)。
对于一个两位的数值,对10取除可以得到其十位的数值,对10取余可以得到个位的数值。对于Verilog来说它的标准是支持除法和取余运算的,综合器也会有IP可以进行除法运算。但是这样未免会耗费太多资源,使用移位加3算法就可以实现二进制到BCD码之间的转换。
2 设计要求: 采用移位加3算法实现二进制转BCD码电路。
3 设计分析
(1) 移位加3算法
移位加3算法简单来说就是,有多少位二进制说,就进行多少次移位,以八位的二进制为例,其数值最高可为三位十进制数,进行如下表左移,在移位的过程中,如果移位出的数值大于4,则将改为的数值加3后再进行移位。
这里为什么大于四,BCD码是四位二进制数表示一个十进制数的一位,如果这以为大于4,比如5,4’b0101,下一次移位后变成了4’b1010,BCD码中是没有4’b1010的,所以要加6,向高位进位。这里就是移位后加6和移位前加3,两种方法修正,我这里选择了移位前加3。(4’b0011左移后也是4’b0110,移位前和移位后都是一样的对BCD码的位数进行修正)。
(2)系统结构
系统端口及其意义
- bin[7:0]: 二进制输入信号,其数值范围为0~256;
- bcd[11:0]: BCD码输出信号,bcd[11:8]表示百位,bcd[7:4]表示十位,bcd[3:0]表示个位。8位的二进制能够表示最大的数字为255,共有三个BCD码,输出共有12位。
(3)架构设计
4 设计实现
4.1 移位加3算法模块设计
1 module adjust_shift( 2 input wire [19:0] idata, 3 output wire [19:0] odata 4 ); 5 6 wire [19:0] adjust_data; 7 8 assign adjust_data[19:16] = idata[19:16] > 4'd4 ? idata[19:16] + 4'd3 : idata[19:16]; 9 assign adjust_data[15:12] = idata[15:12] > 4'd4 ? idata[15:12] + 4'd3 : idata[15:12]; 10 assign adjust_data[11:8] = idata[11:8] > 4'd4 ? idata[11:8] + 4'd3 : idata[11:8]; 11 assign adjust_data[7:0] = idata[7:0]; 12 13 assign odata = adjust_data << 1'b1; 14 15 endmodule
4.2 顶层模块
1 module bin2bcd2( 2 input wire [7:0] bin, 3 output wire [11:0] bcd 4 ); 5 6 wire [19:0] part_0; 7 wire [19:0] part_1; 8 wire [19:0] part_2; 9 wire [19:0] part_3; 10 wire [19:0] part_4; 11 wire [19:0] part_5; 12 wire [19:0] part_6; 13 wire [19:0] part_7; 14 15 adjust_shift adjust_shift_inst0(.idata ({12'd0, bin}), .odata(part_0)); 16 adjust_shift adjust_shift_inst1(.idata (part_0), .odata(part_1)); 17 adjust_shift adjust_shift_inst2(.idata (part_1), .odata(part_2)); 18 adjust_shift adjust_shift_inst3(.idata (part_2), .odata(part_3)); 19 adjust_shift adjust_shift_inst4(.idata (part_3), .odata(part_4)); 20 adjust_shift adjust_shift_inst5(.idata (part_4), .odata(part_5)); 21 adjust_shift adjust_shift_inst6(.idata (part_5), .odata(part_6)); 22 adjust_shift adjust_shift_inst7(.idata (part_6), .odata(part_7)); 23 24 assign bcd = part_7[19:8]; 25 26 endmodule
5 仿真验证
1 `timescale 1ns/1ps 2 3 module bin2bcd2_tb(); 4 5 reg [7:0] bin; 6 wire [11:0] bcd; 7 8 wire [7:0] tb_bin; 9 10 assign tb_bin = bcd[3:0] + bcd[7:4]*10 + bcd[11:8]*100; 11 12 bin2bcd2 bin2bcd2_inst( 13 .bin (bin), 14 .bcd (bcd) 15 ); 16 17 initial begin 18 repeat(500)begin 19 bin = {$random}%256; 20 #20; 21 end 22 $display("Test right!!"); 23 $stop; 24 end 25 26 always@(bin)begin 27 #2; 28 if(bin != tb_bin)begin 29 $display("Test error!!"); 30 $stop; 31 end 32 end 33 34 endmodule
6 参考文献
(1)基于Verilog HDL的二进制转BCD码实现 - NingHeChuan - 博客园 (cnblogs.com);