发 帖  
原厂入驻New
申请华秋企业认证 多层板首单免费打样!
30s提交资料,10分钟通过审核(免费赔付+顺丰包邮)>>立即报名

[经验] 【梦翼师兄今日分享】 二级制转换BCD

2019-12-11 10:28:37  1565 FPGA
分享
0
写在前面的
我们的数据在运算或者存储的时候,一般都是以二进制的格式存在的。但是在很多情况下,我们需要将运算结果显示到某种显示设备上,如果直接以二进制的形式来显示的话,会非常不便于我们查看。因此,我们需要首先将二进制数转换为十进制数再进行显示。二进制到十进制的转换有很多种方法。本节,梦翼师兄和大家一起学习一种国外目前最为流行的转换方法-逐步移位法。通过这种方式,我们不但可以在没有周期差的情况下实现数据格式的转换,同时我们的资源占用量也是相当小的。
基本概念
BCD码(Binary-Coded Decimal‎)也称二进码十进数或二-十进制代码。用4位二进制数来表示1位十进制数中的0~9这10个数码。BCD码这种编码形式利用了四个位元来储存一个十进制的数码,使二进制和十进制之间的转换得以快捷的进行。这种编码技巧在FPGA中经常用到,如矩阵键盘输入的数据需要在数码管上显示的时候,矩阵键盘输入的数字是二进制数,而数码管上需要显示的是十进制数,所以需要将二进制数转换成BCD码,这在我们以后的设计中会经常遇到。
7.3.3逐步移位法原理
在本设计中,我们使用逐步移位法来实现二进制数向BCD码的转换,在设计之前,我们先来了解一下二进制数向BCD码转换的原理-逐步移位法:
变量定义:
B:需要转换的二进制数位宽
D:转换后的BCD码位宽(其中BCD码的位宽计算如下:根据二进制数的位宽,求出它的无符号数能表示的最大值和最小值,如数据位宽是8位则数据范围大小就是0~255,我们取最大值255,每一个数字对应4位BCD码,三个数字就对应3x4=12位的BCD码)
N:需要转换的二进制数位宽加上转换后的BCD码位宽
逐步移位法的规则:
  • 准备一个N比特的移位寄存器;
  • 二进数逐步左移;
  • 每次左移之后每个BCD位做大四加三的调整;
  • 二进数全部移完,得到结果。
  • 设计任务
我们本次的设计任务是将一个8位的二进制数转换成BCD码
分析如下:输入二进制数据的位宽是B=8位,用无符号数来表示的话,输入数据的范围大小就是0~255,我们取最大值255,其中每一个数字需要4位的BCD码来表示,所以BCD码的长度就是D=3x4=12比特。
总结:
  • 准备一个N=B+D=8+12=20比特的移位寄存器;
  • 二进数逐步左移;
  • 每次左移之后每个BCD位做大四加三的调整;
  • 二进数全部移完,得到结果。
现在,我们列一个表格来说明逐步移位法:

第几次移位
BCD[11:8]
BCD[7:4]
BCD[3:0]
Bin[7:0]
Start



10100101
1


1
01001010
2


10
10010100
3


101
00101000
3


1000
00101000
4

1
0000
01010000
5

10
0000
10100000
6

100
0001
01000000
7

1000
0010
10000000
7

1011
0010
10000000
8
1
0110
0101
00000000
BCD
1
6
5


由上表知:
Bin = 10100101 = 165;
BCD = 0001_0110_0101 = 1_6_5 = 165;
由此可知,逐步位移法是可以把二进制数转变成BCD码的。
顶层设计
我们掌握了上面的基本概念和明确了设计任务后,就可以开始设计我们的电路了,梦翼师兄的思路是首先建立一个bin_to_bcd的顶层模块,这个模块的主要功能是将输入的二进制数据进行扩展,然后将扩展后的数据输入到下一层的模块进行移位,最后将最后一次移位的结果取高12位输出即可;然后建立一个bcd_modIFy模块,这个模块的功能是将输入的数据进行移位,并将输入的数据的高12位分成3组分别输入到下一层的比较模块进行比较,每一次比较结束进行一次移位并输出数据;最后建立一个cmp模块,这个模块的主要功能是将输入的数据进行大四加三的调整,然后输出。各个模块的框图设计如下:
bin_to_bcd 顶层框架设计
111.png

bcd_modify 模块的框设计:
111.png

cmp模块框架设计:
111.png
代码实现
设计好上面的模块框图后,接着我们使用Verilog语言,把上述的电路结构描述出来:
bin_to_bcd顶层架构的代码如下:
/****************************************************         
*   Engineer      :   梦翼师兄
*   QQ             :   761664056

*   The module function : 二进制数转8421BCD码顶层模块
*****************************************************/
01  module bin_to_bcd(
02                      bin,    //二进制数输入
03                      bcd     //BCD码输出
04                      );
05                     
06  input [7:0] bin;        //二进制数输入
07  output [11:0] bcd;      //BCD码输出
08
09  wire [19:0] bcd_reg_0,bcd_reg_1,bcd_reg_2,bcd_reg_3,bcd_reg_4,
10              bcd_reg_5,bcd_reg_6,bcd_reg_7,bcd_reg_8;    //8次移位结果输出
11
12  assign bcd_reg_0={12'b000000000000,bin};  //把输入的8位二进制数转换成20位
13  
14  //第一次移位
15  bcd_modify b1(.data_in(bcd_reg_0),.data_out(bcd_reg_1));
16  //第二次移位
17  bcd_modify b2(.data_in(bcd_reg_1),.data_out(bcd_reg_2));
18  //第三次移位
19  bcd_modify b3(.data_in(bcd_reg_2),.data_out(bcd_reg_3));
20  //第四次移位
21  bcd_modify b4(.data_in(bcd_reg_3),.data_out(bcd_reg_4));
22  //第五次移位
23  bcd_modify b5(.data_in(bcd_reg_4),.data_out(bcd_reg_5));
24  //第六次移位
25  bcd_modify b6(.data_in(bcd_reg_5),.data_out(bcd_reg_6));
26  //第七次移位
27  bcd_modify b7(.data_in(bcd_reg_6),.data_out(bcd_reg_7));
28  //第八次移位
29  bcd_modify b8(.data_in(bcd_reg_7),.data_out(bcd_reg_8));
30
31  assign bcd={bcd_reg_8[19:8]};   //取高12位为输出结果
32
33  endmodule
第9~10行我们定义了9个位宽是20的寄存器,第一个寄存器bcd_reg_0我们存放的是输入数据扩展之后的数据,也就是在第12行我们把输入的8位二进制数转换成了20位;第15~29行我们把bcd_modify模块例化了8次,前一个例化模块的输出总是当前模块的输入,比如第23行,输入的数据是bcd_reg_4,在进行了一次移位之后,输出的数据是bcd_reg_5,然后bcd_reg5又作为下一个第25行例化模块的输入,依次向下一级一级传递,进行了8次移位之后,第31行直接取第8次移位之后的结果的高12位作为转换后的BCD码输出。
bcd_modify模块的代码如下:
/****************************************************         
*   Engineer      :   梦翼师兄
*   QQ             :   761664056
*   The module function : 移位模块
*****************************************************/
01  module bcd_modify(
02              data_in,    //需要移位比较数据输入
03              data_out    //移位比较完成数据输出
04              );
05                     
06  input [19:0]data_in;    //需要移位比较数据输入
07  output [19:0]data_out;  //移位比较完成数据输出
08
09  wire [3:0]bcd_reg2,bcd_reg3,bcd_reg1;   //3次移位结果输出
10
11  //data_in[19:16]进行大四加三比较
12  cmp c1(.cmp_in(data_in[19:16]),.cmp_out(bcd_reg1));
13  //data_in[15:12]进行大四加三比较
14  cmp c2(.cmp_in(data_in[15:12]),.cmp_out(bcd_reg2));
15  //data_in[11:8]进行大四加三比较
16  cmp c3(.cmp_in(data_in[11:8]), .cmp_out(bcd_reg3));
17
18  //data_in[19:8]全部比较完之后,左移一位
19  assign data_out={bcd_reg1[2:0],bcd_reg2,bcd_reg3,data_in[7:0],1'b0};
20
21  endmodule
第9行我们定义了3个位宽是4的寄存器,作用是存放比较之后的数据;第11~16行把cmp模块例化了3次,我们把输入数据的高12位分成3组分别送进了这3个例化模块的输入端口,作用是进行大四加三的调整;第19行将第12行~16行输出的数据存放到输出寄存器中进行一次左移操作。

cmp模块的代码如下:
/****************************************************         
*   Engineer      :   梦翼师兄
*   QQ             :   761664056
*   The module function : 大四加三处理模块
*****************************************************/
01  module cmp(
02              cmp_in,     //比较器数据输入
03              cmp_out     //比较器数据输出
04              );
05              
06  input [3:0]cmp_in;       //比较器数据输入
07  output reg [3:0]cmp_out; //比较器数据输出
08
09  always @ (*)
10      begin
11          if (cmp_in > 4)
12              cmp_out = cmp_in + 3;  //输入数据大四加三处理
13          else
14              cmp_out = cmp_in;    //输入数据小于四不做任何处理  
15      end
16
17  endmodule
这个模块挺简单的,第9~15行只是将输入的数据和4进行了比较,大于4输出就是输入数据加三,小于4输入数据不做任何处理直接输出即可。
编写的测试代码如下:
01  `timescale 1ns/1ps      //仿真时间单位是ns,仿真时间精度是ns
02  module bcd_tb;
03
04  reg [7:0]bin;           //仿真激励二进制输入数据
05
06  wire [11:0]bcd;         //仿真输出BCD码
07
08  bin_to_bcd u1(.bin(bin),.bcd(bcd)); //把激励信号送进BCD转换器
09
10  initial begin
11        bin=8'b0;          //bin信号初始化
12        #100  bin=8'b1010_1101;   //输入数据 173
13        #100  bin=8'b0000_1101;   //输入数据 13
14        #100  bin=8'b1010_0100;   //输入数据 164
15        #100  bin=8'b1000_0000;   //输入数据 128
16        #100  bin=8'b1111_1111;   //输入数据 255
17  end
18
19  endmodule     
仿真分析
111.png
如图所示,输入数据bin(无符号十进制表达)的值等于bcd(十六进制表达)输出的值,所以本次设计是成功的。

评论

高级模式
您需要登录后才可以回帖 登录 | 注册

发经验
关闭

站长推荐 上一条 /5 下一条

快速回复 返回顶部 返回列表