本帖最后由 zhangyuhua 于 2017-3-18 20:29 编辑
一周才完成了一个倒计时系统的设计。效率太低了,即使有点低,但也总结下。 此系统实现的功能介绍。
a. 两个按键key1/key2。key1是复位按键,此按键被按下,系统复位;key2按键是停止/开始按键,即当首次按下,系统开始计时,再次被按下,系统停止计时;再次按下,系统再次计时。
b. 选用6个数码管的板子,来实现此功能系统。
整个系统可分三个子系统,分别是计时模块、BCD转码模块和数码管显示模块这三个模块。下图是整个系统架构:
下面分别详细介绍下,三个子系统是如何实现的。
(1)计时模块
(其中: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信号)。
|