打印
[verilog]

倒计时系统设计(下)之数码管显示和顶层

[复制链接]
1309|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 zhangyuhua 于 2017-3-19 15:22 编辑

      今天接着写倒计时系统的最后一个子模块之数码管显示模块。现在一般使用的是七段的数码管,再加上一个小数点位,共八段。
      这个模块比较简单,直接看下代码。
(1)数码管模块框图

(2)源代码
//`define         SIM
`define        SMG_NUM                6        //six smg

module        smg_display(
                                        //System Signals
                                        input                                                                sclk                ,
                                        input                                                                rst_n                ,
                                        //Others
                                        input                        [`SMG_NUM*4-1:0]        bcd_din                ,        //[23:0]
                                        //Interface
                                        output        reg                [2:0]                                smg_sel                ,
                                        output        reg                [7:0]                                smg_seg
                                );
//========================================================================\
// **********Define Parameter and Internal Signals*******************
//========================================================================/
//light is 0
parameter        NUM_0                =        8'b1100_0000        ;        //c0                //dp,g,f,e,d,c,b,a
parameter        NUM_1                =        8'b1111_1001        ;        //f9
parameter        NUM_2                =        8'b1010_0100        ;        //a4
parameter        NUM_3                =        8'b1011_0000        ;        //b0
parameter        NUM_4                =        8'b1001_1001        ;        //99
parameter        NUM_5                =        8'b1001_0010        ;        //92
parameter        NUM_6                =        8'b1000_0010        ;        //82
parameter        NUM_7                =        8'b1111_1000        ;        //f8
parameter        NUM_8                =        8'b1000_0000        ;        //80
parameter        NUM_9                =        8'b1001_0000        ;        //90
parameter        NUM_ERR                =        8'b1111_1111        ;        //ff

//`ifndef        SIM
parameter        TIME_20US        =        1000                        ;
//`else
//parameter        TIME_20US        =        20                                ;
//`endif

//time 20us
reg                [9:0]        cnt_20us                ;
wire                        add_cnt_20us        ;
wire                        end_cnt_20us        ;

//smg sel
reg                [2:0]        cnt_sel                        ;
wire                        add_cnt_sel                ;
wire                        end_cnt_sel                ;

reg                [2:0]        smg_sel_r                ;
reg                [3:0]        smg_seg_temp        ;
//========================================================================\
// **********Main Code*******************
//========================================================================/
//time 20us
always @(posedge sclk or negedge rst_n)
        begin
                if(!rst_n)
                        cnt_20us<='d0;
                else        if(add_cnt_20us)
                                        if(end_cnt_20us)
                                                cnt_20us<='d0;
                                        else        cnt_20us<=cnt_20us+1'b1;
        end
assign        add_cnt_20us=1'b1;
assign        end_cnt_20us=add_cnt_20us && cnt_20us==TIME_20US-1;

//smg sel
always @(posedge sclk or negedge rst_n)
        begin
                if(!rst_n)
                        cnt_sel<=3'd1;
                else        if(add_cnt_sel)
                                        if(end_cnt_sel)
                                                cnt_sel<='d0;
                                        else        cnt_sel<=cnt_sel+1'b1;
        end
assign        add_cnt_sel=end_cnt_20us;
assign        end_cnt_sel=add_cnt_sel && cnt_sel==3'd7;


always @(posedge sclk or negedge rst_n)
        begin
                if(!rst_n)
                        begin
                                smg_sel_r<=3'd0;
                                smg_sel<=3'd0;
                        end
                else        if(end_cnt_20us)
                                        begin
                                                smg_sel_r<=cnt_sel;
                                                smg_sel<=~cnt_sel;
                                        end
        end
//smg_seg
always @(posedge sclk or negedge rst_n )
        begin
                if(!rst_n)
                        smg_seg_temp<='d0;
                else        if(end_cnt_20us)
                                        begin
                                                case(smg_sel_r)
                                                        'd1:smg_seg_temp<=bcd_din[3:0];
                                                        'd2:smg_seg_temp<=bcd_din[7:4];
                                                        'd3:smg_seg_temp<=bcd_din[11:8];
                                                        'd4:smg_seg_temp<=bcd_din[15:12];
                                                        'd5:smg_seg_temp<=bcd_din[19:16];
                                                        'd6:smg_seg_temp<=bcd_din[23:20];
                                                        default:smg_seg_temp<=smg_seg_temp;
                                                endcase
                                        end
        end         


always@(posedge sclk or negedge rst_n)
        begin
                if(!rst_n)
                        smg_seg<=NUM_0;
                else          case (smg_seg_temp)
                                        0 : smg_seg <= NUM_0;
                                        1 : smg_seg <= NUM_1;
                                        2 : smg_seg <= NUM_2;
                                        3 : smg_seg <= NUM_3;
                                        4 : smg_seg <= NUM_4;
                                        5 : smg_seg <= NUM_5;
                                        6 : smg_seg <= NUM_6;
                                        7 : smg_seg <= NUM_7;
                                        8 : smg_seg <= NUM_8;
                                        9 : smg_seg <= NUM_9;
                                        default : smg_seg <= NUM_ERR;
                                endcase
    end


endmodule
(3)源代码讲解
     这个模块的重点有两部分。一是,6个数码如何实现同时亮多个数码管;二是,如何实现某个特定数码管,来显示输入数据bcd_din[23:0]的某4位数。下面详细介绍这两部分内容。
    A.    6个独立的数码管如何同时多个被点亮
        本质上6个数码管是一个一个被点亮的,但由于人眼的余光效应,扫描数码管的频率足够快,这样人眼就会看到多个数码管同时被点亮。查阅资料可知,当扫描周期T=20us时,人眼余光开始起作用。由于使用的晶振为50MHZ,所以这里使用了一个计满1000的计数器。(即是,每20us选中一个数码管)
    B.   输入数据bcd_din[23:0]如何每4位一组被分别显示
        由于数码管从左至右的编号依次是smg_sel[2:0]=0,1,2,3,4,5.而要求smg_sel[2:0]=5显示bcd_din[3:0]、smg_sel[2:0]=4显示bcd_din[7:4]、smg_sel[2:0]=3显示bcd_din[11:8]、smg_sel[2:0]=2显示bcd_din[15:12]、smg_sel[2:0]=1显示bcd_din[19:16]、smg_sel[2:0]=0显示bcd_din[23:20].为了实现上述功能,使用了一次翻转操作。具体看源代码。
(4)顶层模块
      一般顶层模块中,只包含例化模块,不需要复杂的代码编写。例化模块的关键是,将各个端口正确的连接。
module top(
                        //System Signals
                        input                                sclk                ,
                        input                                rst_n                ,
                        //Interface
                        input                [1:0]        key                        ,
                        output                [2:0]        smg_sel                ,
                        output                [7:0]        smg_seg
                );
//========================================================================\
// **********Define Parameter and Internal Signals*******************
//========================================================================/


wire                        dout_vld2bcd_trig        ;
wire        [7:0]        cnt_ms2din                        ;
wire        [7:0]        cnt_s2din                        ;       

wire        [7:0]        bcd_cnt_s2smg                ;
wire        [7:0]        bcd_cnt_ms2smg                ;
//========================================================================\
// **********Main Code*******************
//========================================================================/

//-------------Inst------------
cnt                        inst_cnt(
                                        //System Signals
                                        .sclk                        (sclk                                ),
                                        .rst_n                        (rst_n                                ),
                                        //Others                           
                                        .key                        (key                                ),        //key[1]---Start/Stop
                                                                                                                        //key=1----The key is not pressed;
                                                                                                                        //key=0----The key is pressed
                                                                                                                        //key[0]---Rst
                                        .dout_vld                (dout_vld2bcd_trig        ),        //to tell next module start work
                                        .cnt_s                        (cnt_s2din                        ),
                                        .cnt_ms                        (cnt_ms2din                        )
                                );
bcd                        inst_bcd_cnt_ms(
                                        //System Signals
                                        .sclk                        (sclk                                ),
                                        .rst_n                        (rst_n                                ),
                                        //Others        
                                        .bcd_trig                (dout_vld2bcd_trig        ),
                                        .din                        (cnt_ms2din                        ),        //max is 99
                                                                                                                        //cnt_ms[7:0],cnt_s[7:0]
                                        .bcd_data                (bcd_cnt_ms2smg                ),        //two smg:4bit+4bit
                                                                                                                        //bcd_cnt_ms[7:0],bcd_cnt_s[7:0]
                                        .bcd_data_vld        (bcd_data_vld                )
                                );
bcd                        inst_bcd_cnt_s(
                                        //System Signals
                                        .sclk                        (sclk                                ),
                                        .rst_n                        (rst_n                                ),
                                        //Others        
                                        .bcd_trig                (dout_vld2bcd_trig        ),
                                        .din                        (cnt_s2din                        ),        //max is 99
                                                                                                                        //cnt_ms[7:0],cnt_s[7:0]
                                        .bcd_data                (bcd_cnt_s2smg                ),        //two smg:4bit+4bit
                                                                                                                        //bcd_cnt_ms[7:0],bcd_cnt_s[7:0]
                                        .bcd_data_vld        (bcd_data_vld                )
                                );
smg_display        inst_smg_display(
                                        //System Signals
                                        .sclk                        (sclk                                ),
                                        .rst_n                        (rst_n                                ),
                                        //Others   
                                        .bcd_din                ({8'h00,bcd_cnt_s2smg,bcd_cnt_ms2smg}),        //[23:0]
                                        //Interface
                                        .smg_sel                (smg_sel                        ),
                                        .smg_seg            (smg_seg                    )
                                );

endmodule

(5)总结
      到这,整个倒计时系统算设计完成,下板调试成功。
      良好的代码编写风格,在设计复杂系统中,体现的优势越明显。所以为了以后再次修改或使用以前编写的代码。一定要有良好的编写代码风格。

相关帖子

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

本版积分规则

14

主题

26

帖子

1

粉丝