新闻中心>>正文

Verilog实现16进制到10进制(BCD)转换(1)加减计数法

2021-08-06    来自:IC知识库

由于在数字系统与计算机系统中,数值的表达方式和与计算都是以2进制的方式实现的,由于2进制与16进制一一对应,对应的权值不变,因此2进制运算有时也称为16进制运算。但由于人们已经习惯了10进制的数制方式,特别当表示的数值较大时,以16进制展现方式在普通用户面前几乎没有直观概念,因此本节及后续的几节内容将介绍16进制到10进制转换的算法和程序实现。 16进制到BCD码的转换有多种方法,其中以加减计数法与权值变换法算法结构完善,被广泛使用。本节内容对加减计数法进行介绍,并将算法用Verilog代码实现。

  1. 加减计数法实现16进制到10进制的转换。

一般情况下如果要转换的数值不大,可以直接利用计数的方式实现。通常情况下10进制数据是用来显示的,因此对转换速率要求不高,毕竟显示更换的速度太快,人的眼睛也不能及时反应。 例如对于小于100M的数据,只要在1秒内完成转换就可以满足要求。 加减计数法的实现算法如下,对于一个给定的2进制数,首先将该数减1,同时将设定的BCD的寄存器加1。在加减的过程中,减法以2进制的方式进行,加法以十进制的方式进行,即在加计数的过程中每个位的权都是10(逢9进1)。  

图1

在图1中,分6个步骤完成 (1)变量定义:

临时变量tmpa: 将输入值捕获用于转换

计算变量 tmp0_BCD,tmp1_BCD... 用于计算

输出变量out0_BCD, out1_BCD... 将计算结果输出

输出指示 cal_done,握手信号,通知上层,计算完成,结果可以使用了

(2)捕获,将输入值捕获下来,存入tmpa中 (3)判断tmpa是否为0,如果为0,不用计算,直接更新输出寄存器 (4)计算,tmpa减1,tmp0_BCD,tmp1_BCD...十进制加1 (5)tmpa==0 ?, 为0,更新输出寄存器,否则继续运算 (6)更新输出寄存器,程序返回继续捕获新数并重复上述步骤。

2. 加减计数法程序设计

例1:利用加减计数法实现16进制到10进制的转换,并将转换后的数据缓存。 程序如下:

module add_sub_hex_bcd

       (

           input rst,

           input                       clk,

           input                       cal_req,

           input         [19:0] indata,

           output reg[3:0] out0_BCD,

           output reg[3:0] out1_BCD,

           output reg[3:0] out2_BCD,

           output reg[3:0] out3_BCD,

           output reg[3:0] out4_BCD,

           output reg[3:0] out5_BCD,

           output reg          cal_done

       );

reg [19:0] tmpa;

reg [19:0] tmpa_r;

reg cal_req_r;

reg cal_got;

reg cal_update;

reg [3:0] tmp0_BCD;

reg [3:0] tmp1_BCD;

reg [3:0] tmp2_BCD;

reg [3:0] tmp3_BCD;

reg [3:0] tmp4_BCD;

reg [3:0] tmp5_BCD;

reg [1:0] cal_st;

///========================data capture, assume indata and cal_req are synchronized with clk,

//=========================otherwise synchronization should be done first

always@(posedge clk or posedge rst)

    if(rst)
    begin

        tmpa<=0;

        cal_req_r<=1’b0;

    end

    else
    begin

        if(cal_req)
        begin

            tmpa<=indata;

            cal_req_r<=1’b1;

        end

        else if(cal_got)

            cal_req_r<=0;



    end

//====================

always@(posedge clk or posedge rst)

    if(rst)
    begin

        tmp0_BCD<=0;

        tmp1_BCD<=0;

        tmp2_BCD<=0;

        tmp3_BCD<=0;

        tmp4_BCD<=0;

        tmp5_BCD<=0;

        tmpa_r<=0;

        cal_got<=0;

        cal_update<=0;

        cal_st<=0;

    end

    else
    begin

        case(cal_st)

            0:
            begin

                tmp0_BCD<=0;

                tmp1_BCD<=0;

                tmp2_BCD<=0;

                tmp3_BCD<=0;

                tmp4_BCD<=0;

                tmp5_BCD<=0;

                cal_got<=0;

                cal_update<=0;

                tmpa_r<=0;

                if(cal_req_r)

                    cal_st<=1;

            end

            1:
            begin

                cal_got<=1’b1;

                tmpa_r<=tmpa;

                cal_st<=2;

            end

            2:
            begin

                if(tmpa_r==0)

                    cal_st<=3;

                else
                begin

                    tmpa_r<=tmpa_r-1’b1;

                    if(tmp0_BCD==9)
                    begin

                        tmp0_BCD<=0;

                        if(tmp1_BCD==9)
                        begin

                            tmp1_BCD<=0;

                            if(tmp2_BCD==9)
                            begin

                                tmp2_BCD<=0;

                                if(tmp3_BCD==9)
                                begin

                                    tmp3_BCD<=0;

                                    if(tmp4_BCD==9)
                                    begin

                                        tmp4_BCD<=0;

                                        if(tmp5_BCD==9)

                                            tmp5_BCD<=0;

                                        else

                                            tmp5_BCD<=tmp5_BCD+1’b1;

                                    end

                                    else

                                        tmp4_BCD<=tmp4_BCD+1’b1;

                                end

                                else

                                    tmp3_BCD<=tmp3_BCD+1’b1;

                            end

                            else

                                tmp2_BCD<=tmp2_BCD+1’b1;

                        end

                        else

                            tmp1_BCD<=tmp1_BCD+1’b1;

                    end

                    else

                        tmp0_BCD<=tmp0_BCD+1’b1;

                end

            end

            3:
            begin

                cal_update<=1’b1;

                cal_st<=0;

            end

            default:
                cal_st<=3;

        endcase

    end

//=====================update

always@(posedge clk or posedge rst)

    if(rst)
    begin

        out0_BCD<=0;

        out1_BCD<=0;

        out2_BCD<=0;

        out3_BCD<=0;

        out4_BCD<=0;

        out5_BCD<=0;

        cal_done<=1’b0;

    end

    else
    begin

        cal_done<=1’b0;

        if(cal_update)
        begin

            out0_BCD<=tmp0_BCD;

            out1_BCD<=tmp1_BCD;

            out2_BCD<=tmp2_BCD;

            out3_BCD<=tmp3_BCD;

            out4_BCD<=tmp4_BCD;

            out5_BCD<=tmp5_BCD;

            cal_done<=1’b1;

        end

    end

endmodule

  本程序相对比较简单,但要注意程序的各个过程之间的握手,以及与外界接口之间的握手。 思考题: 分析下面的代码在整体中的作用。

always@(posedge clk or posedge rst)

    if(rst)
    begin

        tmpa<=0;

        cal_req_r<=1'b0;

    end

    else
    begin

        if(cal_req)
        begin

            tmpa<=indata;

            cal_req_r<=1'b1;

        end

        else if(cal_got)

            cal_req_r<=0;




    end

 

上一条: 变量类型及使用范围深入探讨

下一条: RISC-V实验课_数码管显示系列简介