打印
[verilog]

倒计时系统设计(中)之BCD编码模块

[复制链接]
962|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
      上篇写了倒计时系统的计时模块,这篇接着写倒计时系统的BCD编码模块。首先介绍下,BCD码的定义。      BCD码是指用4位二进制数来表示1位十进制数0——9中的一个。
      设计此模块的原因:假如上一篇计时模块的输出cnt_s=21、cnt_ms=45(即21.45),它是二进制数;而数码管显示是将cnt_s=21/cnt_ms=45的个位和十位分别显示的。故此需要将二进制数转化成BCD码。
      (一)二进制数转BCD码的原理(加3移位算法)
                首先,定义一个4*N位的BCD码,如bcd_data[7:0]=8'h00,需被转换的二进制数定义成din[7:0]。
                然后,将din[7]移入bcd_data[0],将bcd_data[7:0]每四位分成一组,这4位组成的二进制数若>=5,则加3后再赋值于bcd_data[7:0];若<5,则将bcd_data[7:0]保持不变。依次进行上步操作,直至将din[7:0]的数值全部移入bcd_data[7:0]中。
             需要注意的是,被转换的二进制数din是N位,则需要转移的次数就是N次,判断的次数是(N-1)次。
      (二) BCD编码的模块框图:

      (三)源代码:
module bcd(
                        //System Signals
                        input                                        sclk                        ,
                        input                                        rst_n                        ,
                        //Others
                        input                                        bcd_trig                ,
                        input                        [7:0]        din                                ,        //max is 99
                                                                                                                //cnt_ms[7:0],cnt_s[7:0]
                        output                reg        [7:0]        bcd_data                ,        //two smg:4bit+4bit
                                                                                                                //bcd_cnt_ms[7:0],bcd_cnt_s[7:0]
                        output                reg                        bcd_data_vld       
                );
//========================================================================\
// **********Define Parameter and Internal Signals*******************
//========================================================================/
parameter        END_SHIFT        =        8                ;        //din is 8 bit
parameter        IDLE                =        3'b001        ;
parameter        SHIFT                =        3'b010        ;
parameter        ADD                        =        3'b100        ;

reg                [7:0]        din_temp                ;       
reg                [3:0]        bcd_data_r1                ;        //unit
reg                [3:0]        bcd_data_r2                ;        //ten
reg                [2:0]        state                        ;
reg                [3:0]        cnt_shift                ;
reg                                flag_bcd                ;
//========================================================================\
// **********Main Code*******************
//========================================================================/
//flag_bcd
always @(posedge sclk or negedge rst_n)
        begin
                if(!rst_n)
                        flag_bcd<=1'b0;
                else        if(bcd_trig==1'b1)
                                        flag_bcd<=1'b1;
                                else        if(bcd_data_vld==1'b1)
                                                        flag_bcd<=1'b0;
        end
always @(posedge sclk or negedge rst_n)
        begin
                if(!rst_n)
                        begin
                                bcd_data_r1<=4'b0000;
                                bcd_data_r2<=4'b0000;
                                bcd_data<=8'd0;
                                bcd_data_vld<=1'b0;
                                cnt_shift<=4'd0;
                                din_temp<=8'd0;
                                state<=IDLE;
                        end
                else        //if(flag_bcd)
                                        begin
                                                case(state)
                                                        IDLE:        begin
                                                                                bcd_data_vld<=1'b0;
                                                                                if(flag_bcd==1'b1)
                                                                                        begin
                                                                                                din_temp<=din;
                                                                                                bcd_data_r1<=4'b0000;
                                                                                                bcd_data_r2<=4'b0000;
                                                                                                state<=SHIFT;
                                                                                        end
                                                                                else        state=IDLE;
                                                                        end
                                                        SHIFT:        begin
                                                                                if(cnt_shift<END_SHIFT)
                                                                                        begin
                                                                                                bcd_data_r1<={bcd_data_r1[2:0],din_temp[7]};
                                                                                                bcd_data_r2<={bcd_data_r2[2:0],bcd_data_r1[3]};
                                                                                                din_temp<={din_temp[6:0],1'b0};
                                                                                                cnt_shift<=cnt_shift+1'b1;
                                                                                                state<=ADD;
                                                                                        end
                                                                                else        begin
bcd_data_vld<=1'b0;
state<=IDLE;
end
                                                                        end
                                                        ADD:        begin
                                                                                if(cnt_shift<END_SHIFT)
                                                                                        begin
                                                                                                if(bcd_data_r1>='d5)
                                                                                                        bcd_data_r1<=bcd_data_r1+'d3;
                                                                                                else        bcd_data_r1<=bcd_data_r1;
                                                                                               
                                                                                                if(bcd_data_r2>='d5)
                                                                                                        bcd_data_r2<=bcd_data_r2+'d3;
                                                                                                else        bcd_data_r2<=bcd_data_r2;
                                                                                               
                                                                                                state<=SHIFT;
                                                                                        end                                                                                        
                                                                                else        begin
                                                                                                        bcd_data<={bcd_data_r2,bcd_data_r1};
                                                                                                        bcd_data_vld<=1'b1;
                                                                                                        cnt_shift<='d0;
                                                                                                        state<=IDLE;
                                                                                                end
                                                                        end
                                                        default:        begin
                                                                                        state<=IDLE;
                                                                                        cnt_shift<='d0;
                                                                                end
                                                endcase
                                        end
        end

endmodule
    (四)这个模块主要使用了一个状态机。这个状态机也比较简单,一共三个状态,分别是初始态(IDLE)、移位态(SHIFT)和判断加3态(ADD)。下面是其状态转移图:

     (五)总结
           在这个模块中也使用了自己代码的一贯风格:
               A.   定义了此模块被触发的开始信号bcd_trig;
               B.   BCD编码正在工作状态的信号flag_bcd;
               C.   BCD编码完成信号bcd_data_vld.






相关帖子

沙发
teleagle| | 2017-3-25 23:35 | 只看该作者
学习了,但代码怎么这么乱,可能是我的编辑器出问题了.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

26

帖子

1

粉丝