FPGA Verilog设计之二进制转BCD代码编写

13 篇文章 11 订阅
        BCD 码(Binary-Coded Decimal ),又称二--- 十进制码,使用 4 位二进制数来表示 1 位十进制数中的 0~9 10 个数码,是一种二进制的数字编码形式,用二进制编码的十进制代码。
        
        BCD码根据权值的有无可分为“有权码”和“无权码”。其中的权字表示的是权值,有权码的四位二进制数中的每一位都有一个固定的权值,而无权码是没有权值的。常见的有权码有8421 5421 码和 2421 码, 8421 码它的权值从左到右是 8421 5421 码的权值从左到右是5421 2421 码的权值是 2421 ,其中 8421 码是最为常用的 BCD 编码。常用的无权码有余3 码、余 3 循环码,还有格雷码。各编码方式所对应的十进制数如下图所示。

 十进制数对应的BCD码

        那么如何用 BCD 码来表示我们的十进制数呢?以本次实验我们使用的 8421BCD 编码为例,比如说十进制数 5,它的 8421BCD 码为 0101,那么我们怎么通过 0101 得到我们的数字 5 呢,这里需要用到一个算法,就是将其每位二进制数乘以它的权值然后相加。十进制 5 8421BCD 码为0101,即:1×1 + 0×2 + 1×4+ 0×8 = 5。其它有权码也是这种计算方式,而无权码的计算方式这里就不过多讲解了,感兴趣的读者可自行查找相关资料进行了解。

        我们以234为例子,讲解二进制编码如何转化为8421BCD码。

        我们先看看 234 的十进制数的二进制表示为:1110_1010 234 8421BCD 码为: 0010_0011_0100

 

二进制转BCD码步骤 

        如上图所示,十进制数 234 其对应的二进制数为 1110_1010 ,首先第一步我们在其前面补上若干个 0 ,那么这个 0 的数量是如何决定的呢?参与转换的十进制有多少位,就需要多少个相应的 BCD 码,比如 234 ,该十进制数是 3 位,而一位十进制数的 BCD 码是四位,所以这里我们就需要 12 BCD 码,故我们就在前面补 12 0 。其余位数的十进制补0 数量也是这样进行计算。
        第二步我们需要进行判断运算移位操作,首先判断每一个 BCD 码其对应的十进制数是否大于 4,如果大于 4 就对 BCD 码做加 3 操作,若小于等于 4 就让其值保持不变。当对每一个 BCD 码进行判断运算后,都需要将运算后的数据像左移 1 位。移完位后我们仍按前面所述进行判断运算,判断运算后需再次移位,以此循环,当我们进行 8 次判断移位后的BCD 吗部分数据就是我们转换的数据,如图 26-6 所示,当第 8 次移位后的 8421BCD 码数 据对应的十进制正是 234 。这里需要注意的是我们输入转换的二进制码有多少位我们就需要进行多少次判断移位操作,这里输入的是 8 位二进制,我们就进行 8 次判断移位操作。

模块框图

代码的输入输出信号描述
        输入信号中的时钟复位这里就不过多讲解了,首先是 data 信号,该信号是输入的需要
转换的二进制表示的十进制数,该信号由数据生成模块传来。
        cnt_shift:移位判断计数器,前面我们说到我们输入转换的二进制码有多少位我们就需要进行多少次判断移位操作,这里我们 data 数据的位宽为 20 位,所以这里我们声明移位判断计数器对移位 20 次进行判断控制。
        data_shift:移位判断数据寄存器,该寄存器用于存储移位判断操作过程中的数据,这里我们输入的二进制位宽为 20 位,待转换成的 BCD 码位宽为 24 位,所以这里我们声明该寄存器的位宽为 44 位。根据波形图可知,这里我们设计当移位计数器等于 0 时寄存器的低20 位即为待转换数据,而由于还没开始进行转换,高 24 位的 BCD 码我们补 0 即可。
        shift_flag:移位判断操作标志信号。前面说到我们需要对数据进行移位和判断,判断在前移位在后,所以这里我们声明一个标志信号,用于控制判断和移位的先后顺序,当shift_flag 为低时对数据进行判断,当 shift_flag 为高时对数据进行移位。需要注意的是无论 是移位操作和判断操作都是在单个系统时钟下完成的,故我们判断 20 次移位 20 次在 40 个系统时钟内就能完成。
//16进制转8421模块

module bcd_8421
(
    input wire sys_clk,     //系统时钟
    input wire sys_rst_n,   //复位信号
    input wire [19:0] data, //输入需要转换的数据
    
    output reg [3:0] unit,      //个位BCD码
    output reg [3:0] ten,       //十位BCD码
    output reg [3:0] hun,       //百位BCD码
    output reg [3:0] tho,       //千位BCD码
    output reg [3:0] t_tho,     //万位BCD码
    output reg [3:0] h_hun     //十万位BCD码
);

reg [4:0] cnt_shift;    //移位判断计数器
reg [43:0] data_shift;  //移位判断数据寄存器
reg shift_flag; //移位判断标志信号

//cnt_shift:从0~21循环计数
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_shift <= 5'd0;
    else if((cnt_shift == 5'd21) && (shift_flag == 1'b1))
        cnt_shift <= 1'b0;
    else if(shift_flag == 1'b1)
        cnt_shift <= cnt_shift + 1'b1;
    else    
        cnt_shift <= cnt_shift;
   
//data_shift:计数器为 0 时赋初值,计数器为 1~20 时进行移位判断操作
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_shift <= 44'b0;
    else if(cnt_shift == 5'd0)
        data_shift <= {24'b0,data};
    else if((cnt_shift <= 20) && (shift_flag == 1'b0))
        begin
            data_shift[23:20] <= (data_shift[23:20] > 4) ? 
                (data_shift[23:20] + 2'd3) : (data_shift[23:20]);
            data_shift[27:24] <= (data_shift[27:24] > 4) ? 
                (data_shift[27:24] + 2'd3) : (data_shift[27:24]);
            data_shift[31:28] <= (data_shift[31:28] > 4) ? 
                (data_shift[31:28] + 2'd3) : (data_shift[31:28]);
            data_shift[35:32] <= (data_shift[35:32] > 4) ? 
                (data_shift[35:32] + 2'd3) : (data_shift[35:32]);
            data_shift[39:36] <= (data_shift[39:36] > 4) ? 
                (data_shift[39:36] + 2'd3) : (data_shift[39:36]);
            data_shift[43:40] <= (data_shift[43:40] > 4) ? 
                (data_shift[43:40] + 2'd3) : (data_shift[43:40]);
        end
    else if((cnt_shift <= 20) && (shift_flag == 1'b1))
        data_shift <= data_shift << 1;
    else
        data_shift <= data_shift;

//shift_flag:移位判断标志信号,用于控制移位判断的先后顺序
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        shift_flag <= 1'b0;
    else
        shift_flag <= ~shift_flag;

//当计数器等于 20 时,移位判断操作完成,对各个位数的 BCD 码进行赋值
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        begin
            unit <= 4'b0;
            ten <= 4'b0;
            hun <= 4'b0;
            tho <= 4'b0;
            t_tho <= 4'b0;
            h_hun <= 4'b0;
        end
    else if(cnt_shift == 5'd21)
        begin
            unit <= data_shift[23:20];
            ten <= data_shift[27:24];
            hun <= data_shift[31:28];
            tho <= data_shift[35:32];
            t_tho <= data_shift[39:36];
            h_hun <= data_shift[43:40];
        end

endmodule
     
     
     
     
     
     
     
     
     
     
        
        
        
        
        
        
        

        unit、 ten hum tho t_tho h_hun :六路 BCD 码,前面我们说到我们开发板上有六位数码管,故可以显示的最大值是六位十进制数,随意这里我们声明了六路 BCD 码,一个BCD 码代表十进制的一个位数,其中 unit 代表个位、 ten 代表十位、 hun 代表百位、 tho 代表千位、t_tho 代表万位、 h_hun 代表十万位。当我们的移位判断计数器等于 21 是说明 20位二进制转 BCD 码的移位判断操作已经完成,此时 data_shift 里寄存的数据就是转换的的 寄存数据,该数据的高 24 位即转换完成后的 BCD 码。所以当 cnt_shift 等于 20 是就将寄存的 BCD 码值赋值为相对应的各个位数。

 

  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值