一、设计要求
所使用开发板的系统时钟频率为50MHz,使用计数器,将LED灯每隔1s闪烁。
解析
计数器是实现计数运算的逻辑电路,其可以通过对脉冲个数计数从而实现计数、分频、控制、测量等功能。
计数器设计需要注意以下几点内容:
(1)计数器初始值(可以为0,或其他值);
(2)计数器计数条件(这是计数器重要的逻辑);
(3)计数器结束条件(可以是自身计数值为一个特定值,可以为其他逻辑控制);
二、模块设计
计数器需要输入为系统时钟(clk)和电平复位(rst_n为低电平复位,rst为高电平复位,复位是为了防止程序跑飞,因此需要一个机制将其恢复到初始状态),输出通过LED灯显示。
三、波形设计
分析
(1)首先在两个输入信号sys_clk和sys_rst_n 的基础上添加一个计数器(cnt)以及一个脉冲标志信号(Led_flag)。
(2)计数个数计算:
时钟频率:f=50MHz=5*10^4KHz=5*10^7Hz
一个时钟脉冲信号时间:t=1/f=(1/5*10^7)s=20ns
1s所需时钟脉冲:M=1s/20ns=5*10^7
设计要求为每隔1S闪烁,因此只需计数0.5S:M/2=2.5*10^7,又因为cnt从0开始计数,所以N=M/2-1=24_999_999;
(3)使用脉冲标志信号优点:
1.可以使计数时间更为准确;2.更节约逻辑资源。
四、代码编写
module led(
input wire sys_clk ,
input wire rst_n ,
output reg led_out
);
reg [24:0] cnt ;
reg led_flag ;
//计数器计数,到达最大值时归0
always@(posedge sys_clk or negedge rst_n)
begin
if(!rst_n)
cnt <= 25'd0;
else if(cnt == 25'd24_999_999)
cnt <= 25'd0;
else
cnt <= cnt + 1'b1;
end
//led_flag信号在最大值减一时拉高,因为此为异步时序,延迟一拍
always@(posedge sys_clk or negedge rst_n)
begin
if(!rst_n)
led_flag <= 1'b0;
else if(cnt == (25'd24_999_999-1'b1))
led_flag <= 1'b1;
else
led_flag <= 1'b0;
end
//led_out输出信号
always@(posedge sys_clk or negedge rst_n)
begin
if(!rst_n)
led_out <= 1'b0;
else if(led_flag == 1'b1)
led_out <= ~led_out;
else
led_out <= led_out;
end
endmodule
五、RTL视图
六、Testbench编写
module tb_led();
reg sys_clk ;
reg sys_rst_n ;
wire led_out ;
initial
begin
sys_clk <= 1'b1;
sys_rst_n <= 1'b0;
#20
sys_rst_n <= 1'b1;
end
always#10 sys_clk <= ~sys_clk;
led led_inst(
.sys_clk (sys_clk),
.rst_n (sys_rst_n),
.led_out (led_out)
);
endmodule
七、仿真结果
观察 仿真波形发现与我们最初所画波形一致。
八、上板实测
无法上传视频,引脚约束后成功运行。
云程发轫,踵事增华。