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

[复制链接]
1501|0
 楼主| zhangyuhua 发表于 2017-3-19 15:21 | 显示全部楼层 |阅读模式
本帖最后由 zhangyuhua 于 2017-3-19 15:22 编辑

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

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

  3. module        smg_display(
  4.                                         //System Signals
  5.                                         input                                                                sclk                ,
  6.                                         input                                                                rst_n                ,
  7.                                         //Others
  8.                                         input                        [`SMG_NUM*4-1:0]        bcd_din                ,        //[23:0]
  9.                                         //Interface
  10.                                         output        reg                [2:0]                                smg_sel                ,
  11.                                         output        reg                [7:0]                                smg_seg
  12.                                 );
  13. //========================================================================\
  14. // **********Define Parameter and Internal Signals*******************
  15. //========================================================================/
  16. //light is 0
  17. parameter        NUM_0                =        8'b1100_0000        ;        //c0                //dp,g,f,e,d,c,b,a
  18. parameter        NUM_1                =        8'b1111_1001        ;        //f9
  19. parameter        NUM_2                =        8'b1010_0100        ;        //a4
  20. parameter        NUM_3                =        8'b1011_0000        ;        //b0
  21. parameter        NUM_4                =        8'b1001_1001        ;        //99
  22. parameter        NUM_5                =        8'b1001_0010        ;        //92
  23. parameter        NUM_6                =        8'b1000_0010        ;        //82
  24. parameter        NUM_7                =        8'b1111_1000        ;        //f8
  25. parameter        NUM_8                =        8'b1000_0000        ;        //80
  26. parameter        NUM_9                =        8'b1001_0000        ;        //90
  27. parameter        NUM_ERR                =        8'b1111_1111        ;        //ff

  28. //`ifndef        SIM
  29. parameter        TIME_20US        =        1000                        ;
  30. //`else
  31. //parameter        TIME_20US        =        20                                ;
  32. //`endif

  33. //time 20us
  34. reg                [9:0]        cnt_20us                ;
  35. wire                        add_cnt_20us        ;
  36. wire                        end_cnt_20us        ;

  37. //smg sel
  38. reg                [2:0]        cnt_sel                        ;
  39. wire                        add_cnt_sel                ;
  40. wire                        end_cnt_sel                ;

  41. reg                [2:0]        smg_sel_r                ;
  42. reg                [3:0]        smg_seg_temp        ;
  43. //========================================================================\
  44. // **********Main Code*******************
  45. //========================================================================/
  46. //time 20us
  47. always @(posedge sclk or negedge rst_n)
  48.         begin
  49.                 if(!rst_n)
  50.                         cnt_20us<='d0;
  51.                 else        if(add_cnt_20us)
  52.                                         if(end_cnt_20us)
  53.                                                 cnt_20us<='d0;
  54.                                         else        cnt_20us<=cnt_20us+1'b1;
  55.         end
  56. assign        add_cnt_20us=1'b1;
  57. assign        end_cnt_20us=add_cnt_20us && cnt_20us==TIME_20US-1;

  58. //smg sel
  59. always @(posedge sclk or negedge rst_n)
  60.         begin
  61.                 if(!rst_n)
  62.                         cnt_sel<=3'd1;
  63.                 else        if(add_cnt_sel)
  64.                                         if(end_cnt_sel)
  65.                                                 cnt_sel<='d0;
  66.                                         else        cnt_sel<=cnt_sel+1'b1;
  67.         end
  68. assign        add_cnt_sel=end_cnt_20us;
  69. assign        end_cnt_sel=add_cnt_sel && cnt_sel==3'd7;


  70. always @(posedge sclk or negedge rst_n)
  71.         begin
  72.                 if(!rst_n)
  73.                         begin
  74.                                 smg_sel_r<=3'd0;
  75.                                 smg_sel<=3'd0;
  76.                         end
  77.                 else        if(end_cnt_20us)
  78.                                         begin
  79.                                                 smg_sel_r<=cnt_sel;
  80.                                                 smg_sel<=~cnt_sel;
  81.                                         end
  82.         end
  83. //smg_seg
  84. always @(posedge sclk or negedge rst_n )
  85.         begin
  86.                 if(!rst_n)
  87.                         smg_seg_temp<='d0;
  88.                 else        if(end_cnt_20us)
  89.                                         begin
  90.                                                 case(smg_sel_r)
  91.                                                         'd1:smg_seg_temp<=bcd_din[3:0];
  92.                                                         'd2:smg_seg_temp<=bcd_din[7:4];
  93.                                                         'd3:smg_seg_temp<=bcd_din[11:8];
  94.                                                         'd4:smg_seg_temp<=bcd_din[15:12];
  95.                                                         'd5:smg_seg_temp<=bcd_din[19:16];
  96.                                                         'd6:smg_seg_temp<=bcd_din[23:20];
  97.                                                         default:smg_seg_temp<=smg_seg_temp;
  98.                                                 endcase
  99.                                         end
  100.         end         


  101. always@(posedge sclk or negedge rst_n)
  102.         begin
  103.                 if(!rst_n)
  104.                         smg_seg<=NUM_0;
  105.                 else          case (smg_seg_temp)
  106.                                         0 : smg_seg <= NUM_0;
  107.                                         1 : smg_seg <= NUM_1;
  108.                                         2 : smg_seg <= NUM_2;
  109.                                         3 : smg_seg <= NUM_3;
  110.                                         4 : smg_seg <= NUM_4;
  111.                                         5 : smg_seg <= NUM_5;
  112.                                         6 : smg_seg <= NUM_6;
  113.                                         7 : smg_seg <= NUM_7;
  114.                                         8 : smg_seg <= NUM_8;
  115.                                         9 : smg_seg <= NUM_9;
  116.                                         default : smg_seg <= NUM_ERR;
  117.                                 endcase
  118.     end


  119. 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)顶层模块
      一般顶层模块中,只包含例化模块,不需要复杂的代码编写。例化模块的关键是,将各个端口正确的连接。
  1. module top(
  2.                         //System Signals
  3.                         input                                sclk                ,
  4.                         input                                rst_n                ,
  5.                         //Interface
  6.                         input                [1:0]        key                        ,
  7.                         output                [2:0]        smg_sel                ,
  8.                         output                [7:0]        smg_seg
  9.                 );
  10. //========================================================================\
  11. // **********Define Parameter and Internal Signals*******************
  12. //========================================================================/


  13. wire                        dout_vld2bcd_trig        ;
  14. wire        [7:0]        cnt_ms2din                        ;
  15. wire        [7:0]        cnt_s2din                        ;       

  16. wire        [7:0]        bcd_cnt_s2smg                ;
  17. wire        [7:0]        bcd_cnt_ms2smg                ;
  18. //========================================================================\
  19. // **********Main Code*******************
  20. //========================================================================/

  21. //-------------Inst------------
  22. cnt                        inst_cnt(
  23.                                         //System Signals
  24.                                         .sclk                        (sclk                                ),
  25.                                         .rst_n                        (rst_n                                ),
  26.                                         //Others                           
  27.                                         .key                        (key                                ),        //key[1]---Start/Stop
  28.                                                                                                                         //key=1----The key is not pressed;
  29.                                                                                                                         //key=0----The key is pressed
  30.                                                                                                                         //key[0]---Rst
  31.                                         .dout_vld                (dout_vld2bcd_trig        ),        //to tell next module start work
  32.                                         .cnt_s                        (cnt_s2din                        ),
  33.                                         .cnt_ms                        (cnt_ms2din                        )
  34.                                 );
  35. bcd                        inst_bcd_cnt_ms(
  36.                                         //System Signals
  37.                                         .sclk                        (sclk                                ),
  38.                                         .rst_n                        (rst_n                                ),
  39.                                         //Others        
  40.                                         .bcd_trig                (dout_vld2bcd_trig        ),
  41.                                         .din                        (cnt_ms2din                        ),        //max is 99
  42.                                                                                                                         //cnt_ms[7:0],cnt_s[7:0]
  43.                                         .bcd_data                (bcd_cnt_ms2smg                ),        //two smg:4bit+4bit
  44.                                                                                                                         //bcd_cnt_ms[7:0],bcd_cnt_s[7:0]
  45.                                         .bcd_data_vld        (bcd_data_vld                )
  46.                                 );
  47. bcd                        inst_bcd_cnt_s(
  48.                                         //System Signals
  49.                                         .sclk                        (sclk                                ),
  50.                                         .rst_n                        (rst_n                                ),
  51.                                         //Others        
  52.                                         .bcd_trig                (dout_vld2bcd_trig        ),
  53.                                         .din                        (cnt_s2din                        ),        //max is 99
  54.                                                                                                                         //cnt_ms[7:0],cnt_s[7:0]
  55.                                         .bcd_data                (bcd_cnt_s2smg                ),        //two smg:4bit+4bit
  56.                                                                                                                         //bcd_cnt_ms[7:0],bcd_cnt_s[7:0]
  57.                                         .bcd_data_vld        (bcd_data_vld                )
  58.                                 );
  59. smg_display        inst_smg_display(
  60.                                         //System Signals
  61.                                         .sclk                        (sclk                                ),
  62.                                         .rst_n                        (rst_n                                ),
  63.                                         //Others   
  64.                                         .bcd_din                ({8'h00,bcd_cnt_s2smg,bcd_cnt_ms2smg}),        //[23:0]
  65.                                         //Interface
  66.                                         .smg_sel                (smg_sel                        ),
  67.                                         .smg_seg            (smg_seg                    )
  68.                                 );

  69. endmodule

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

26

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部