一、状态机的原理分析
三段式状态机编写
1、第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器,即描述状态转移
2、第二个进程,组合逻辑always模块,描述判断状态转移条件,描述状态转移规律
3、第三个进程,同步时序always模块,格式化描述次态寄存器输出,其它always(个数与输出信号个数有关)使用同步时序电路设计每一个状态的输出
二、状态机实验
通过状态机编写,串口接收字符串并检测“HELLO”,若检测到则LED灯翻转。
FSM代码
`timescale 1ns / 1ps
//
// Description: 状态机检测字符串"HELLO" 每一个字母都对应一个8位的16进制数 (a~z/A~Z)----8’hXX
//
module FSM(
input clk ,
input rst_n ,
input[7:0] i_data ,
input i_data_valid,
output reg check_ok
);
localparam H = 5'b0_0001,
E = 5'b0_0010,
L_1 = 5'b0_0100,
L_2 = 5'b0_1000,
O = 5'b1_0000;
reg[4:0] state,n_state;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
state <= H;
else
state <= n_state;
end
always@(*)begin
case(state)
H: if(i_data_valid && i_data == "H")
n_state = E;
else
n_state = H;
E: if(i_data_valid && i_data == "E")
n_state = L_1;
else if(i_data_valid && i_data == "H")
n_state = E;
else if(i_data_valid)
n_state = H;
else
n_state = E;
L_1:if(i_data_valid && i_data == "L")
n_state = L_2;
else if(i_data_valid && i_data == "H")
n_state = E;
else if(i_data_valid)
n_state = H;
else
n_state = L_1;
L_2:if(i_data_valid && i_data == "L")
n_state = O;
else if(i_data_valid && i_data == "H")
n_state = E;
else if(i_data_valid)
n_state = H;
else
n_state = L_2;
O: if(i_data_valid && i_data == "H")
n_state = E;
else if(i_data_valid)
n_state = H;
else
n_state = O;
default: n_state = H;
endcase
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
check_ok <= 'd0;
else if(state == O && (i_data == "O" && i_data_valid))
check_ok <= 'd1;
else
check_ok <= 'd0;
end
endmodule
top顶层文件
`timescale 1ns / 1ps
module uart_hello(
Clk ,
Reset_n ,
uart_rx ,
led
);
input Clk ;
input Reset_n ;
input uart_rx ;
output reg led ;
wire[7:0] Data ;
wire rx_done ;
wire check_ok;
uart_byte_rx uart_byte_rx_u0(
.Clk (Clk ) ,
.Reset_n (Reset_n) ,
.Baud_Set ( 'd4 ) ,
.uart_rx (uart_rx) ,
.Data (Data ) ,
.Rx_Done (rx_done)
);
FSM FSM_u0(
.clk (Clk ),
.rst_n (Reset_n ),
.i_data (Data ),
.i_data_valid (rx_done ),
.check_ok (check_ok )
);
always @(posedge Clk or negedge Reset_n) begin
if(!Reset_n)
led <= 'd0;
else if(check_ok)
led <= ~led;
else
led <= led;
end
endmodule
通过仿真,我们可以完全实现