一、实验目标:设计一个以1s频率闪烁的LED灯(亮灭各500ms)
二、实验用开发板:xilinx大学计划EGO1开发板,板载100Mhz时钟
三、实现思路:板载100Mhz,可知时钟周期为10ns。要想实现亮灭各500ms,可设计一个计数器,可通过计数clk脉冲周期个数来达到计时目的。因此可以算出需要连续计数500ms/10ns=50000000个时钟周期。并使用基本D触发器实现LED亮灭状态的存储。
四、实现过程中的问题:
1、从下图中可以看到高电平持续时间不是500ms整,而是500.000010000ms。
由于上述数字太大,下面以模为4的计数器为例,计数应该是0-1、1-2、2-3、3-4,但是实际还多了一个4-0,实际计数到了因此需要N-1,在本文中计数最大值就是50000000-1=49999999.
2、复位信号在代码不同位置的综合问题,如下图,先放正确的
module led_flash(
input clk,
input rst,
output reg led
);
reg [26:0]cnt;
always@(posedge clk or posedge rst)begin
if(rst)begin //复位信号单独列写
cnt <= 0;
end
else if(cnt == 50000000)begin
cnt <= 0;
end
else
cnt <= cnt+1'b1;
end
always@(posedge clk or posedge rst)begin
if(rst)begin
led <= 0;
end
else if(cnt == 50000000)begin
led <= ~led;
end
end
endmodule
综合出的RTL,可以看到复位信号连接到了计数器和D触发器。
下面再放上错误的代码
module led_flash(
input clk,
input rst,
output reg led
);
reg [26:0]cnt;
always@(posedge clk or posedge rst)begin
if(cnt == 50000000 || rst)begin //这里又用软件的思维去写硬件了,想着反正都是计数器清零
cnt <= 0; //为了代码精简点,放一起算了。
end
else
cnt <= cnt+1'b1;
end
always@(posedge clk or posedge rst)begin
if(rst)begin
led <= 0;
end
else if(cnt == 50000000)begin
led <= ~led;
end
end
endmodule
可以看到复位信号连接到一个mux上了,并没有连接到计数器。
调试看来不能只盯着代码看,还要多看看综合后的RTL啊。
说了半天,上面提到的都是异步复位,同步复位的,以后碰到了在写文章吧,今天就到这里。