以下用10010序列检测为例子,写的三种状态机的写法。
module fsm_10010( //运行时,只留一种方法。
input wire clk ,
input wire rst_n ,
input wire data_in , //数据流
output reg flag //检测成功标志
);
//状态编码
parameter idle = 4'd0; //初始状态
parameter s0 = 4'd1; //5'b1
parameter s1 = 4'd2; //5'b10
parameter s2 = 4'd3; //5'b100
parameter s3 = 4'd4; //5'b1001
parameter s4 = 4'd5; //5'b10010
reg [3:0] state ; //状态机 /位
//状态机描述 三种描述方式
//一段式、二段式、三段式
//一段式:一个always语句块,用时序逻辑既描述状态转移,又描述输出。
/* always@ (posedge clk ,negedge rst_n)
begin
if(~rst_n)
begin
flag <= 1'b0; //达到10010就输出1
state <= idle; //赋初值
end
else case(state)
idle:begin
flag <= 0;
if(data_in == 1'b1)
state <= s0 ;
else
state <= idle;
end
s0: begin
flag <= 0;
if(data_in == 0)
state <= s1;
else
state <=s0;
end
s1:begin
flag <= 0;
if(data_in == 0)
state <= s2;
else
state <= s0;
end
s2:begin
flag <= 0;
if(data_in == 1)
state <= s3 ;
else
state <= idle;
end
s3:begin
flag <= 0;
if(data_in == 1'b0)
state <= s4;
else
state <= s0;
end
s4:begin //10010
flag <= 1;
if(data_in == 1)
state <= s0;
else
state <= s2;
end
default :begin
state <= idle; //
flag <= 1'b0;
end
endcase
end
*/
二段式状态机
// 第一段:一个always语块,时序逻辑描述状态转移
// 第二段:一个always语块,组合逻辑描述输出(时序允许的情况下用时序逻辑)
always@ (posedge clk,negedge rst_n) //时序逻辑
begin
if(~rst_n)
begin
state <= idle;
end
else case(state)
idle:begin
if(data_in == 1'b1)
state <= s0 ;
else
state <= idle;
end
s0: begin
if(data_in == 0)
state <= s1;
else
state <=s0;
end
s1:begin
if(data_in == 0)
state <= s2;
else
state <= s0;
end
s2:begin
if(data_in == 1)
state <= s3 ;
else
state <= idle;
end
s3:begin
if(data_in == 1'b0)
state <= s4;
else
state <= s0;
end
s4:begin
if(data_in == 1)
state <= s0;
else
state <= s2;
end
default :begin
state <= idle; //
end
endcase
end
//第二段组合逻辑
always@(*)
begin //判断状态等于s4时,标志位为0;
if(~rst_n)
flag = 0;
else if(state == s4)
flag = 1;
else
flag = 0;
end
//三段式
/*
第一段:时序逻辑描述状态更新,把次态(下一状态)赋值到现态
第二段:一个always语块 组合逻辑描述状态判断,根据现态及输入判断次态
第三段:一个always语块,时序逻辑描述输出。
*/
/*一个*/
reg [3:0] now_state ; //现态
reg [3:0] next_state ; //次态
always@(posedge clk,negedge rst_n)
begin
if(~rst_n)
now_state <= idle;
else
now_state <= next_state;
end
/*二个*/
always@(*)
begin //判断状态
if(~rst_n)
begin
next_state = idle; //复位时就是空闲
end
else case(now_state)
idle:begin
if(data_in == 1)
next_state = s0 ;
else
next_state = idle;
end
s0: begin
if(data_in == 0)
next_state = s1;
else
next_state = s0;
end
s1:begin
if(data_in==1)
next_state = idle;
else
next_state = s0;
end
s2:begin
if(data_in ==1)
next_state = s3 ;
else
next_state = idle;
end
s3: begin
if (data_in == 1'b0)
next_state = s4;
else
next_state = s0;
end
s4:begin
if (data_in == 1'b0)
next_state = s2;
else
next_state = s0;
end
default :begin
next_state = idle;
end
endcase
end
/* 三个 */
/* always@(posedge clk,negedge rst_n) //带延时
begin
if(~rst_n)
flag <= 1'b0;
else if (now_state == s4)
flag <= 1'b1;
else
flag <= 1'b0;
end */
endmodule
以下为状态转移图


4万+

被折叠的 条评论
为什么被折叠?



