项目名称
流水灯
具体要求
4个led每隔0.5s循环点亮,1-2-3-4-3-2-1,假设高电平状态下流水灯点亮,初始值led=1000
设计架构
需要计数500_000_000/20=25000_000次,由于仿真时间较长,将计数值改为10
代码设计
verilog代码设计
采用状态机实现,从左到右和从右到左两个显示状态
需要注意的是从左到右显示到最后一个0001的时候,要在此状态下将显示状态改变为0010才可以跳转从右到左显示
同样从右到左显示到1000的时候,也需要在此状态下将显示状态改变为0100
module led_water
#(parameter delay_top=25'd25000000)
(
input clk,
input rst_n,
output reg[3:0]led
);
//延迟电路设计计数25000000
reg [24:0] cnt;
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt<=25'd0;
else if(cnt<delay_top)
cnt<=cnt+1'd1;
else
cnt<=25'd0;
//延迟完成标志信号
wire delay_done=(cnt==delay_top)?1'd1:1'd0;
reg state;
always@(posedge clk or negedge rst_n)
if(!rst_n)
begin
state<=0;
led<=4'b1000;
end
else begin
case(state)
0: begin //从左到右显示
if(delay_done)
begin
if(led==4'b0001)
begin
state<=1;
led<={led[2:0],led[3]};
end
else
led<={led[0],led[3:1]};
end
else
led<=led;
end
1: begin //从右到左显示
if(delay_done)
begin
if(led==4'b1000)
begin
state<=0;
led<={led[0],led[3:1]};
end
else
led<={led[2:0],led[3]};
end
else
led<=led;
end
default:;
endcase
end
//always@(posedge clk or negedge rst_n)
// if(!rst_n)
// led<=4'b1000;
// else if(delay_done)
// led<={led[0],led[3:1]};
// else
// led<=led;
endmodule
仿真代码
仿真时间较长,将仿真时间计数改为10
`timescale 1ns/1ns
module led_water_tb;
reg clk;
reg rst_n;
wire [3:0]led;
led_water
#(.delay_top(25'd10))
led_water
(
.clk(clk),
.rst_n(rst_n),
.led(led)
);
initial clk=0;
always #10 clk=~clk;
initial begin
rst_n=0;
#100
rst_n=1;
#20000;
$stop;
end
endmodule
仿真结果
每计数到10的时候led的显示状态发生改变
led显示从1-2-3-4-3-2-1不断循环改变