实验的功能很简单,就是让4个数码管每隔1s递增显示,使用动态扫描的方式来实现。
从这个功能的描述可以看出,我们首先要写一个计数器模块,来让计数值每隔1s增加1,暂时实现的是16进制的东西,从0到f,之后10到1f等等。
我们的实验平台的系统时钟是25MHz,不是25MHz的实验平台,可以通过PLL来分频或倍频得到25MHz的时钟。
其次,写一个模块来控制数码管的位选和段选。
实验平台的数码管是共阴极的,也就是片选端低电平有效。
还需要注意的一个问题是:
片选控制信号的刷新速度必须足够快才能避免闪烁感,但也不能太快,以免影响数码管的开关切换,最佳的工作频率为1000Hz左右。如果FPGA的时钟为50MHz,那么至少跑5*10^4个周期,也即50000个周期刷新一次才行,我们知道2^16=65536,2^15=32768。
当然,这里的时钟是25Mhz,所以我们需要计数大概25000个周期才能刷新一次。
上面的最佳工作频率是1000hz的说法是否权威呢?我不知道,但是实验证明能用。
先给出计数模块的Verilog描述:
/
//工程硬件平台: Xilinx Spartan 6 FPGA
/
module counter(
input clk,//时钟信号,25MHz
input rst_n,//复位信号,低电平有效
output reg[15:0] display_num//数码管显示数据,[15:12]--数码管千位,[11:8]--数码管百位,[7:4]--数码管十位,[3:0]--数码管个位
);
//-------------------------------------------------
//1s定时产生逻辑
reg[24:0] timer_cnt;//1s计数器,0-24999999
//1s定时计数
always @(posedge clk or negedge rst_n)
if(!rst_n) timer_cnt <= 25'd0;
else if(timer_cnt < 25'd24_999_999) timer_cnt <= timer_cnt+1'b1;
else timer_cnt <= 25'd0;
wire timer_1s_flag = (timer_cnt == 25'