模版输入输出部分,必须有clk和rst_n复位功能。基本所有代码都要有复位功能,即使在实际使用中用不到。
module LED#(parameter TIME_500MS = 25000000)( //跨模块传递参数
input clk,
input rst_n,
output reg [3:0] led
);
reg [24:0] cnt;
wire add_cnt;
wire end_cnt;
reg x;
always计数模块,always本身是并行语句,但always内部是顺序语句,内部被赋值的变量必须是reg型变量。
always @(*)相当于在敏感列表中包含always语句内部所有变量。
//计数器
always @( posedge clk or negedge rst_n ) begin
if(!rst_n)begin //复位信号,当rst_n为低电平时复位
cnt <= 25'd0;
end
else if (add_cnt) begin //当add_cnt=1时,开始计数
if (end_cnt) begin //如果end_cnt=1,即已经计数到最大值后,计数器归零
cnt <= 25'd0;
end
else begin //其他情况下就是+1'b1
cnt <= cnt + 1'b1;
end
end
else begin //保障机制,类似于default
cnt <= cnt;
end
end
assign add_cnt = 1'b1; //给add_cnt直接赋值1
assign end_cnt = add_cnt&&cnt == TIME_500MS - 1'b1; //当计数到TIME_500MS - 1'b1时end_cnt=1,计数器在下一个时钟到来后清零
assign是并行语句,无论有多少语句,都是同时执行,assign右侧的驱动表达式中一旦有变量发生了变化,都会重新计算并赋值。
后续运用计数器主要使用end_cnt变量。
Test Bench代码:
`timescale 1ns/1ns //用于指定仿真时间单位和时间精度。
module LED_tb (); //仿真文件没有输入输出 只是模拟源文件输入看输出和预期是否相符
reg tb_clk; //输入信号定义为寄存器类型
reg tb_rst_n;
wire [3:0] tb_led; //输入信号定义为线网类型
LED#(.TIME_500MS(250)) u_LED( //实例化,把两个模块联系起来
.clk (tb_clk ),
.rst_n (tb_rst_n ),
.led (tb_led )
);
parameter CYCLE = 20; //时钟周期 20ns
always #(CYCLE / 2) tb_clk =~ tb_clk; //每次过了半个时钟周期 clk进行取反 高低电平各占10ns
//#延时语句
initial begin //产生激励 对reg类型进行描述
tb_clk = 1'b0; //
tb_rst_n = 1'b0; //开始复位
#(CYCLE * 3); //延时3个时钟周期
tb_rst_n = 1'b1; //停止复位
#(CYCLE * 250 * 8); //看四次反转
$stop; //系统任务停止仿真
end
endmodule
端口名关联法:.X1(X2)
X1:是例化原件端口
X2:是例化原件外接端口
例化元件就是指调用的其他模块