FPGA流水灯Demo
说明
8个led灯依次点亮,形成流水效果
分析
框图
状态机FSM
Verilog代码
`timescale 1ns / 1ps
//
// Create Date: 2022/11/20 20:41:08
// Design Name: wkk
// Module Name: water_led
// Description: running 8 water leds
// Revision 0.01 - File Created
// Additional Comments:
//
module water_led(
input sys_clk, // 50M
input sys_rst_n,
output reg [7:0] led_out
);
parameter SYS_CLK = 50_000_000;
parameter TIME_MAX_COUNT = 500_000;
localparam S0 = 8'b0000_0001;
localparam S1 = 8'b0000_0010;
localparam S2 = 8'b0000_0100;
localparam S3 = 8'b0000_1000;
localparam S4 = 8'b0001_0000;
localparam S5 = 8'b0010_0000;
localparam S6 = 8'b0100_0000;
localparam S7 = 8'b1000_0000;
wire time_en;
reg [19:0] time_count;
reg [7:0] curr_state;
reg [7:0] next_state;
assign time_en = (time_count == TIME_MAX_COUNT -1) ? (1'b1) :(1'b0);
// clock division
// create time_en signal
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
time_count <= 20'b0;
else if(time_count == TIME_MAX_COUNT-1)
time_count <= 20'b0;
else
time_count <= time_count +1'b1;
end
// update current state from next state
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
curr_state <= 8'b0;
else
curr_state <= next_state;
end
// update fsm next state
always @(*) begin
if(!sys_rst_n)
next_state <= 8'b0;
else if(time_en)
case(curr_state)
S0: next_state <= S1;
S1: next_state <= S2;
S2: next_state <= S3;
S3: next_state <= S4;
S4: next_state <= S5;
S5: next_state <= S6;
S6: next_state <= S7;
S7: next_state <= S0;
default: next_state <= S0;
endcase
else ;
end
// create output signal
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
led_out <= 8'b0;
else
led_out <= curr_state;
end
endmodule
testbench
`timescale 1ns / 1ns
// Create Date: 2022/11/20 21:15:13
// Design Name: wkk
// Module Name: water_led_tb
// Description: water_led testbench
// Revision 0.01 - File Created
// Additional Comments:
//
module water_led_tb;
reg sys_clk;
reg sys_rst_n;
wire [7:0] led_out;
water_led #(
.TIME_MAX_COUNT (2)
)u_water_led(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.led_out (led_out)
);
initial begin
sys_clk = 0;
sys_rst_n = 0;
#20 sys_rst_n = 1;
end
always begin
#5 sys_clk = !sys_clk;
end
initial begin
# 2000;
$stop;
end
endmodule
仿真结果
通用代码
// author : wkk
module WaterLed#(
parameter INPUT_CLK = 27_000_000 , // input clk frequency
parameter LED_NUM = 6 , // led quantity
parameter COUNT_WIDTH = 36 , // time counter bit quantity
parameter COUNT_MAX = 27_000_000 , // max count value
// LED MODE 1 ? 0 -> on
parameter LED_MODE = 0 // led control mode: if 1 --> led on or 0 --> led on
)(
input clk ,
input rst_n ,
output [LED_NUM-1:0] led
);
reg [LED_NUM-1: 0] curr_state ;
reg [LED_NUM-1: 0] next_state ;
reg [LED_NUM-1:0] led_out ;
reg time_en ;
reg [COUNT_WIDTH-1:0] time_count ;
always @(posedge clk or negedge rst_n) begin
if( !rst_n ) begin
time_count <= {COUNT_WIDTH{1'b0}};
time_en <= 1'b0;
end
else begin
if( time_count == COUNT_MAX-1) begin
time_count <= {COUNT_WIDTH{1'b0}};
time_en <= 1'b1;
end
else begin
time_en <= 1'b0;
time_count <= time_count + 1'b1;
end
end
end
always @(posedge clk or negedge rst_n) begin
if( !rst_n )
curr_state <= {{(LED_NUM-1){1'b0}},1'b1};
else
curr_state <= next_state;
end
always @(*) begin
if(!rst_n )
next_state = {{(LED_NUM-1){1'b0}},1'b1};
else begin
if( time_en )
next_state = {curr_state[LED_NUM-2:0],curr_state[LED_NUM-1]};
else
next_state = curr_state;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n )
led_out <= {LED_NUM{1'b0}};
else begin
if( LED_MODE == 1)
led_out <= curr_state;
else
led_out <= ~curr_state;
end
end
assign led = led_out;
endmodule