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