实现效果:让LED每隔500ms翻转一次。(已知系统时钟是50M,对应的周期是20ns)所以用计数的方式实现。计数的次数:500ms/20ns = 25_000_000。将它转换成16进制,一共需要25位。
设计:代码
module counter(CLK50M,Rst_n,led);
input CLK50M;
input Rst_n;
output reg led;
reg [24:0]cnt;
//计数器的自加进程
always@(posedge CLK50M or negedge Rst_n)
if(Rst_n == 1'b0)
cnt <= 25'd0;
else if(cnt == 25'd24_999_999)
cnt <= 25'd0;
else
cnt <= cnt + 1'b1;
//根据计数器的计数状态控制LED
always@(posedge CLK50M or negedge Rst_n)
if(Rst_n == 1'b0)
led <= 1'b1;
else if(cnt == 25'd24_999_999)
led <=~led;
else
led <=led;
endmodule
接下来功能验证,先写一个testbench:
第一句话首先声明仿真的时间步径和仿真精度。
`timescale 1ns/1ns
//定义一个时钟周期变量,方便更改时钟周期
`define clock_period 20
//定义一个testbench的实体模块
module counter_tb;
//激励信号源
reg clk;
reg rst_n;
wire led;
//端口例化,将激励信号源和端口进行连接
counter counter0(
.CLK50M(clk),
.Rst_n(rst_n),
.led(led)
);
initial clk = 1;
//产生时钟
always #(`clock_period/2) clk = ~clk;
//产生复位信号
initial begin
rst_n = 1'b0;
#(`clock_period*200);
rst_n = 1'b1;
//延时两秒
#2000000000;
$stop;
end
endmodule
接下来设置链接文件,将两个设计文件与modelsim关联起来。
我第一次没有点apply, 导致没有将两个文件关联成功,modelsim里面没有看到波形。
然后打开modelsim
CLK波形加载很慢,并且在这次实验中不重要,可以删除。
观察上升沿,下降沿的时间是不是500ms。
功能仿真后,就可以布局布线,进行时序仿真。
点击全编译,进行布局布线。
再进行IO口的分配。
在后仿真中,低电平变成高电平的时间,和高电平变成低电平的时间不一样。
最后查看RTL视图。