基于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)

(2)陪您一起学习FPGA-郝旭帅团队_哔哩哔哩_bilibili

posted @ 2021-08-29 17:40  豌豆茶  阅读(1475)  评论(0编辑  收藏  举报