本次做的题目是:基于FPGA的倒计时显示电路设计,
题目要求如下:
详细要求如下:
本次设计的代码通过了仿真。(用的是quartus自带的仿真器)
这次设计分为两个模块,一个是倒计时的控制模块,另一个是数码管的显示模块。在倒计时控制模块中调用(例化)显示模块,从而实现分层设计。
关于数码管动态显示,可以参考我的这篇博客:
FPGA项目(5)--FPGA控制数码管动态显示的原理_fpga数码管显示实验原理_嵌入式小李的博客-CSDN博客https://blog.csdn.net/guangali/article/details/130754726?spm=1001.2014.3001.5501
唯一的区别就是 这次使用的数码管是4位数码管。经过稍加修改就可以直接使用。
下面重点讲解倒计时模块的逻辑设计:
首先是模块的接口设计:
各按键的作用如注释所示,其中minute_out 和 sec_out信号主要是为了在仿真的时候观察输出的时间数值(如果没有这个信号,就需要从数码管的输出段码和位选信号来判断当前倒计时的时间数值,会比较麻烦。用这个信号观察就会比较直观)。
内部使用到的信号如下:
其中hz_num是分频数值。仿真时,此值不应太大。因为quartus自带的仿真器在仿真时,所能观测的最大时间也才几百微秒。如果不缩小分频数值,那么仿真时就观察不到试验现象。其他各信号的含义如注释所示。
接着就是分频模块。这种分频非常简单,就不具体解释了,直接给出代码:
下面重点来了
首先,要实现k2按下数值清0的效果,这个非常简单。直接在if语句里面判断,符合条件直接清0就行。然后要实现时间的预设功能,那么假定只有在倒计时暂停的情况下才可以进行时间设定,倒计时运行过程中不能对时间进行修改。所以在设定时间时首先要判断k1的状态,如果k1为0,才可以进行时间预设。当k1为1时,就是正常的倒计时状态。Sec信号在1HZ脉冲的驱动下(clk_hz信号每隔1S会置1一次)减1,每次减到0都判断一次minute是否为0,如果minute不为0,说明倒计时过程还未结束,应该重新给sec赋值并且minute减1,否则说明倒计时结束了,蜂鸣器报警,同时暂停倒计时的过程。这部分的逻辑代码如下:
需要注意这里使用的是 if else if 语句,里面的条件是有优先级顺序的。复位信号的优先级最高,然后的清0按键k2,然后是k1.
最后就是将所得的时间数值,取出来,送给显示模块进行显示。
仿真图如下:
这是不加数码管显示的,为的是更清楚的看到时间的变化。一开始我令k3按下去一个周期 K5按下去2个周期,那么对应的效果就是minute+1,sec+2。从仿真的结果看,确实是这样。随后当k1置为高电平以后,分钟和秒钟在进行倒计时的过程。当时间减完以后,可以看到蜂鸣器输出了高电平,倒计时过程暂停了!
接下来给出一张完整的仿真图:
完整代码如下:
module count_down( inputclk,// 时钟信号假设时钟信号为50M inputrst_n ,// 复位信号 input k1,//用于控制计时的启动和停止1表示启动0表示停止 input k2,//用于控制计数时间的归零 input k3,//用于设置倒计时时间时 对分钟的+ input k4,//用于设置倒计时时间时 对分钟的- input k5,//用于设置倒计时时间时 对秒钟的+ input k6,//用于设置倒计时时间时 对秒钟的-//所有按键都假设 不按下为1按下为0output[5:0] minut_out,//将时间输出 便于观察 output[5:0] sec_out, output reg beep,//蜂鸣器报警高电平报警 output[3:0] seg_sel,// 数码管位选,最左侧数码管为最高位 output[6:0] seg_led // 数码管段选);//parameterhz_num=32'd50_000_000;parameterhz_num=32'd50;//将50M时钟分频到1HZ所需要的分频系数仿真时取50实物取50_000_000reg [5:0]minute;//预设时间的分钟reg[5:0]sec;//预设时间的秒钟regclk_hz;//分频后的1hz信号reg[31:0]hz_cnt;//分频模块使用的寄存器wire [3:0] minute_ge;//保存分钟的个位 用于输出到数码管显示wire [3:0] minute_shi;//保存分钟的十位 用于输出到数码管显示wire [3:0] sec_ge;//保存秒钟的个位 用于输出到数码管显示wire [3:0] sec_shi;//保存秒钟的时位 用于输出到数码管显示wire [15:0] data_out;//要传递到数码管显示的数据//产生1hz的模块always @(posedge clk) beginif(hz_cnt==hz_num-1)beginhz_cnt