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


    写在前面的

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

    基本概念

    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(十六进制表达)输出的值,所以本次设计是成功的。

  • 相关阅读:
    软件工程实践总结
    beta答辩总结
    beta冲刺(6/7)
    beta 冲刺(5/7)
    beta冲刺(4/7)
    beta冲刺(3/7)
    beta冲刺(2/7)
    beta冲刺(1/7)
    CentOS7安装新版git
    NameError: name 'reload' is not defined
  • 原文地址:https://www.cnblogs.com/mengyi1989/p/11518326.html
Copyright © 2020-2023  润新知