LED灯闪烁10次
基本框架是基于用Verilog编写的定时器,每0.5s计数满,cnt_flag置位,LED翻转一次,那么如果要求只闪烁10次,就需要一个计数变量count,这里采用的方法是,每次cnt_flag置位的时候,都让count加一,因为需要闪烁10次,也就是有10个LED周期,那么就需要翻转20次,所以需要一个5位的计数count。
module flash_ten
#(
parameter CNT_MAX = 25'd24_999_999
)
(
input wire sys_clk ,
input wire sys_rst_n ,
output reg led_out
);
reg [24:0] cnt ;//计数器
reg cnt_flag;//计数满标志位
reg [4:0] count ;//led闪烁次数10次,即cnt_flag需要20次到达计数次数,所以需要5位
//计数器
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
cnt <= 25'b0;
else if(cnt == CNT_MAX)
cnt <= 25'b0;
else
cnt <= cnt + 1'b1;
end
//计数满标志位
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
cnt_flag <= 1'b0;
else if(cnt == CNT_MAX - 1'b1)
cnt_flag <= 1'b1;
else
cnt_flag <= 1'b0;
end
以上部分是之前的常规代码,最终就是cnt_flag每0.5s置一。
//count控制
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
count <= 5'b0;
else if((cnt_flag == 1'b1) && (count <= 5'd19))
count <= count + 1'b1;
else
count <= count; //这样即可实现到达20次之后不再改变
end
而对于count,只要cnt_flag=1,并且没有超过19,就继续加1,否则就不变!!!!!!
这就是关键,else分支是需要保持不变,而不是等于0。
//led控制
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
led_out <= 1'b0;
else if(cnt_flag == 1'b1 && count <= 5'd19)
led_out <= ~led_out;
else if(count == 5'd20) //这里必须要有这个条件,不然不亮,因为只有在那么一瞬间会点亮,所以led<=led_out这一句很重要
led_out <= 1'b1;
else
led_out <= led_out;
end
endmodule
注意,这里一定要加else if(count == 5'd20)
这个分支,不能直接else里面就让led_out <= 1'b1;
,这样人眼根本观察不到LED亮。
Testbench
`timescale 1ns/1ns
module flash_ten_tb();
//wire define
wire led_out;
//reg define
reg sys_clk;
reg sys_rst_n;
//初始化系统时钟、全局复位
initial begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
#20
sys_rst_n <= 1'b1;
end
always #10 sys_clk <= ~sys_clk;
flash_ten
#(
.CNT_MAX (25'd24) //20ns * 50 = 1000ns = 1us,10个周期就是10us,所以仿真至少10us
)
flash_ten_inst
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n ),
.led_out (led_out )
);
endmodule
注意在最后有一个小脉冲,
因为计数到19的时候,继续计数,当cntflag=1时,count在下一个计数周期加一。而此时,由于延一拍的效果,sysclk取到的count依旧是19,只有到了下一个周期的时候,sysclk取到的count才为20,才让ledout=1。
调试参数
- count改为计数到18,可以避免最后的小脉冲。仿真以及下载实验都正确。
一个modelsim的小问题
这个count变量我明明设置的是5位,为啥仿真的时候到15之后就成负数了
解决:
右键radix,不要选择decimal,而是选择unsigned,就可显示无符号数了。