一、代码设计
`timescale 1ns / 1ps
/*
三段式状态机设计1s流水灯
三段式状态机设计流程
(1)确定状态
(2)画状态转换图
(3)状态编码(二进制、格雷码、独热码)
*/
module stater_led(
input sysclk ,
input rst_n ,
output reg [3:0] led
);
/格雷码 (相邻两个状态之间仅有1位电平变化)
localparam IDLE = 3'b000; //空闲状态
localparam LED1 = 3'b001; //第一个灯亮起来
localparam LED2 = 3'b011; //第二个灯亮起来
localparam LED3 = 3'b111; //第三个灯亮起来
localparam LED4 = 3'b101; //第四个灯亮起来
reg [2:0] cur_state; //现态
reg [2:0] next_state; //次态
reg [25:0] cnt ;
parameter TIME_1s = 50_000_000;
//----state1(时序逻辑电路,非阻塞赋值,进行状态的切换) 对cur_state赋值 固定格式
always@(posedge sysclk)
if(!rst_n)
cur_state <= IDLE;
else
cur_state <= next_state;
//----state2(组合逻辑,根据现态和条件去确定次态) 状态转换图 对next_state赋值
always@(*) 组合逻辑
case(cur_state)
IDLE : begin
next_state = LED1;
end
LED1 :begin
if(cnt == TIME_1s - 1)
next_state = LED2;
else
next_state = cur_state;
end
LED2 :begin
if(cnt == TIME_1s - 1)
next_state = LED3;
else
next_state = cur_state;
end
LED3 :begin
if(cnt == TIME_1s - 1)
next_state = LED4;
else
next_state = cur_state;
end
LED4 :begin
if(cnt == TIME_1s - 1)
next_state = LED1;
else
next_state = cur_state;
end
default:;
endcase
//----state3(确定每个状态的输出,即动作,时序逻辑,非阻塞赋值)
always@(posedge sysclk)
if(!rst_n)begin
led <= 4'b0000;
cnt <= 0;
end
else
case(cur_state) /输出立马执行 next_state:输出会延迟一个时钟周期
IDLE :begin
led <= 4'b0000;
cnt <= 0;
end
LED1 :begin
led <= 4'b0001;
if(cnt == TIME_1s - 1)
cnt <= 0; 清零的目的:为了下一个状态的正常跳转
else
cnt <= cnt + 1;
end
LED2 :begin
led <= 4'b0010;
if(cnt == TIME_1s - 1)
cnt <= 0; 清零的目的:为了下一个状态的正常跳转
else
cnt <= cnt + 1;
end
LED3 :begin
led <= 4'b0100;
if(cnt == TIME_1s - 1)
cnt <= 0; 清零的目的:为了下一个状态的正常跳转
else
cnt <= cnt + 1;
end
LED4 :begin
led <= 4'b1000;
if(cnt == TIME_1s - 1)
cnt <= 0; 清零的目的:为了下一个状态的正常跳转
else
cnt <= cnt + 1;
end
default:;
endcase
endmodule