[verilog]

倒计时系统设计(上)之计时模块

[复制链接]
1244|1
手机看帖
扫描二维码
随时随地手机跟帖
zhangyuhua|  楼主 | 2017-3-18 20:29 | 显示全部楼层 |阅读模式
本帖最后由 zhangyuhua 于 2017-3-18 20:29 编辑

      一周才完成了一个倒计时系统的设计。效率太低了,即使有点低,但也总结下。     此系统实现的功能介绍。
        a.  两个按键key1/key2。key1是复位按键,此按键被按下,系统复位;key2按键是停止/开始按键,即当首次按下,系统开始计时,再次被按下,系统停止计时;再次按下,系统再次计时。
        b.  选用6个数码管的板子,来实现此功能系统。

     整个系统可分三个子系统,分别是计时模块、BCD转码模块和数码管显示模块这三个模块。下图是整个系统架构:
系统架构.jpg
       下面分别详细介绍下,三个子系统是如何实现的。
(1)计时模块
计时模块框图.jpg
(其中:cnt_ms代表毫秒信号
              cnt_s秒信号代表
              dout_vld代表此模块输出一个信号,可供下一个模块使用)
源代码:
//`define         SIM
module        cnt(
                        //System Signals
                        input                                sclk                ,
                        input                                rst_n                ,
                        //Others
                        input                [1:0]        key                        ,        //key[1]---Start/Stop
                                                                                                //key=1----The key is not pressed;
                                                                                                //key=0----The key is pressed
                                                                                                //key[0]---Rst
                        output        reg                        dout_vld        ,        //to tell next module start work
                        output        reg        [7:0]        cnt_s                ,
                        output        reg        [7:0]        cnt_ms               
                );
//========================================================================\
// **********Define Parameter and Internal Signals*******************
//========================================================================/
//`ifndef SIM
parameter        DELAY_10ms        =        50_0000                ;
//`else
//parameter        DELAY_10ms        =        100                        ;
//`endif

//relation cnt_10ms
reg        [18:0]        cnt_10ms                ;        //0.01s
wire                add_cnt_10ms        ;
wire                end_cnt_10ms        ;
reg                        flag                        ;
//relation cnt_ms
wire                add_cnt_ms                ;
wire                end_cnt_ms                ;

//relation cnt_s
wire                add_cnt_s                ;
wire                end_cnt_s                ;

//========================================================================\
// **********Main Code*******************
//========================================================================/
//cnt_10ms
always @(posedge sclk or negedge rst_n)
        begin
                if(!rst_n)
                        cnt_10ms<='d0;
                else        if(add_cnt_10ms)
                                        if(end_cnt_10ms)
                                                cnt_10ms<='d0;
                                        else        cnt_10ms<=cnt_10ms+1'b1;        
        end
assign        add_cnt_10ms=flag;
assign        end_cnt_10ms=add_cnt_10ms && (cnt_10ms==DELAY_10ms-1);
always        @(posedge sclk or negedge rst_n)
        begin
                if(!rst_n)
                        flag<=1'b0;
                else        if(key[0]==1'b0 || (end_cnt_s==1'b1))
                                        flag<=1'b0;
                                else        if(key[1]==1'b0)
                                                        flag<=~flag;
        end
//[7:0]cnt_ms
always @(posedge sclk or negedge rst_n)
        begin
                if(!rst_n)
                        cnt_ms<=8'd99;
                else        begin
                                        if(key[0]==1'b0)
                                                cnt_ms<=8'd99;
                                        else        if(add_cnt_ms)
                                                                if(end_cnt_ms)
                                                                        cnt_ms<='d99;
                                                                else        cnt_ms<=cnt_ms-1'b1;
                                end
        end
assign        add_cnt_ms=end_cnt_10ms;
assign        end_cnt_ms=add_cnt_ms && cnt_ms==8'd0 ;        

//cnt_s[7:0]
always        @(posedge sclk or negedge rst_n)
        begin
                if(!rst_n)
                        cnt_s<='d23;
                else        begin
                                        if(key[0]==1'b0)
                                                cnt_s<='d23;
                                        else        if(add_cnt_s)
                                                                if(end_cnt_s)
                                                                        cnt_s<='d23;
                                                                else        cnt_s<=cnt_s-1'b1;
                                end
        end
assign        add_cnt_s=end_cnt_ms;
assign        end_cnt_s=add_cnt_s && cnt_s=='d0 ;

//dout_vld
always @(posedge sclk or negedge rst_n)
        begin
                if(!rst_n)
                        dout_vld<=1'b0;
                else        if(end_cnt_10ms)
                                        dout_vld<=1'b1;
                                else        dout_vld<=1'b0;
        end

endmodule
      为了节省仿真时间,在这里使用了一个宏定义如下:
                            `ifndef   语句1
                             `else     语句2
                             `endif
   在这里不具体介绍这个语法是怎么使用的。可查看一些语法书籍。

(2)总结:      这个计时模块比较简单,内部就使用了3个计数器。
      设计整个倒计时系统,我花费的时间比较长,大概用了一周的时间。过了两天再重新看自己写的代码时,里面一些信号名就不知道它代表的意思了。还得重新看代码。这样会浪费大量的时间。所以,我自己总结了下自己的代码风格。以后都遵循这些规则,可以减少代码的修改时间。
     在模块中要使用三个信号。一是,模块触发信号(eg.此模块中的key_vld);二是,模块输出使能信号(eg.此模块中的dout_vld);三是,模块正在工作状态的信号(eg.此模块中的flag信号)。

相关帖子

fonst| | 2017-3-21 21:26 | 显示全部楼层
命名规范了,信号名就容易记住了

使用特权

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

本版积分规则

14

主题

26

帖子

1

粉丝