基础项目(4)二级制转换BCD

我只是一个虾纸丫 提交于 2019-11-29 13:17:48

写在前面的

我们的数据在运算或者存储的时候,一般都是以二进制的格式存在的。但是在很多情况下,我们需要将运算结果显示到某种显示设备上,如果直接以二进制的形式来显示的话,会非常不便于我们查看。因此,我们需要首先将二进制数转换为十进制数再进行显示。二进制到十进制的转换有很多种方法。本节,梦翼师兄和大家一起学习一种国外目前最为流行的转换方法-逐步移位法。通过这种方式,我们不但可以在没有周期差的情况下实现数据格式的转换,同时我们的资源占用量也是相当小的。

基本概念

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码位宽

 逐步移位法的规则:

  1. 准备一个N比特的移位寄存器;
  2. 二进数逐步左移; 
  3. 每次左移之后每个BCD位做大四加三的调整;
  4. 二进数全部移完,得到结果。
  5. 设计任务

我们本次的设计任务是将一个8位的二进制数转换成BCD码

分析如下:输入二进制数据的位宽B=8位,用无符号数来表示的话,输入数据的范围大小就是0~255,我们取最大值255,其中每一个数字需要4位的BCD码来表示,所以BCD码的长度就是D=3x4=12比特。

总结:

  1. 准备一个N=B+D=8+12=20比特的移位寄存器;
  2. 二进数逐步左移; 
  3. 每次左移之后每个BCD位做大四加三的调整;
  4. 二进数全部移完,得到结果。

现在,我们列一个表格来说明逐步移位法:

 

第几次移位

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 顶层框架设计

 

bcd_modify 模块的框设计:

 

cmp模块框架设计:

代码实现

设计好上面的模块框图后,接着我们使用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     

仿真分析

如图所示,输入数据bin(无符号十进制表达)的值等于bcd(十六进制表达)输出的值,所以本次设计是成功的。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!