目录
- 一、模块框图
- 二、波形图
- 1、时钟与复位信号
- 2、计数器
- 3、脉冲信号
- 4、输出信号
- 5、理想结果
- 三、代码部分
- 1、Verilog代码
- (1)法1:拼接运算符
- (2)法2:移位运算符,再取反
- 2、tb仿真代码
- 四、仿真波形
一、模块框图
包含两个输入信号:系统时钟(sys_clk)以及复位信号(sys_rst_n)。
一个输出信号:led_out (因有4个led灯组成流水灯,故位宽为4,每一个比特位控制一个led灯)
二、波形图
1、时钟与复位信号
2、计数器
因每一个流水灯点亮的时间为0.5s,板子频率为50Mhz(20ns)
0.5s = 5X10^8ns
故计数个数为 (5X10^8)/ 20 = 2.5x10^7
3、脉冲信号
当计数器计数到最大值减一时,保持一个时钟周期的高脉冲,其余时刻保持低电平
4、输出信号
当复位信号有效时,对其赋初值为 4’b1110 (第一个灯亮,其余三个灭),并在第一个周期内保持
检测到脉冲标志信号时,值变为4’b1101(第二个灯亮,其余三个灭),并在这一周期内保持
后面同理
5、理想结果
与led_out波形相对应,间隔为0.5s
三、代码部分
1、Verilog代码
(1)法1:拼接运算符
module water_led
#(
parameter CNT_MAX = 25'd24_999_999 //声明计数最大值参数,24999999二进制为25位
)
(
input wire sys_clk,
input wire sys_rst_n,
output reg [3:0] led_out //端口列表
);
reg [24:0] cnt;
reg cnt_flag; //声明寄存器
always@(posedge sys_clk or negedge sys_rst_n) //计数器赋值
if(sys_rst_n == 1'b0)
cnt <= 25'd0;
else if (cnt == CNT_MAX)
cnt <= 25'd0;
else
cnt <= cnt + 25'd1;
always@(posedge sys_clk or negedge sys_rst_n) //脉冲标志信号赋值
if(sys_rst_n == 1'b0)
cnt_flag <= 1'b0;
else if (cnt == (CNT_MAX - 25'd1 ))
cnt_flag <= 1'b1;
else
cnt_flag <= 1'b0;
always@(posedge sys_clk or negedge sys_rst_n) //输出信号赋值
if(sys_rst_n == 1'b0)
led_out <= 4'b1110
else if(cnt_flag == 1'b1)
led_out <= {led_out[2:0],led_out[3]}; //拼接运算符(例如上一状态为1110,现状态为1101,将上一状态的后三位110放在现状态的前三位,
else //上一状态的第一位1放在现状态的最后一位,再将110与1进行拼接运算,即可得到现状态1101)
led_out <= led_out;
endmodule
其中拼接运算符详情见下:
(2)法2:移位运算符,再取反
先添加led_out_reg [3:0]寄存器
将输出信号赋值部分的代码进行如下修改,再进行取反
2、tb仿真代码
`timescale 1ns/1ns
module tb_water_led(); //端口列表
reg sys_clk;
reg sys_rst_n;
wire [3:0] 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; //生成时钟
water_led //实例化
#(
.CNT_MAX(25'd24)
)
water_led_inst
(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.led_out(led_out)
);
endmodule
四、仿真波形
经分析,与开始手动绘制的波形图吻合,结果正确,此处不再上传上版验证结果。