有限状态机(FSM)写法的个人总结(一段式,二段式,三段式),附实例代码

      状态机描述时关键是要描述清楚几个状态机的要素,即如何进行状态转移,每个状态的输出是什么,状态转移的条件等。具体描述时方法各种各样,最常见的有三种描述方式:

     (1)一段式:整个状态机写到一个always模块里面,在该模块中既描述状态转移,又描述状态的输入和输出;

     (2)二段式:用两个always模块来描述状态机,其中一个always模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出;

     (3)三段式:在两个always模块描述方法基础上,使用三个always模块,一个always模块采用同步时序描述状态转移,一个always采用组合逻辑判断状态转移条件,描述状态转移规律,另一个always模块描述状态输出(可以用组合电路输出,也可以时序电路输出)。

三段式状态机示例模板:

//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器

always @ (posedge clk or negedge rst_n)   //异步复位

if(!rst_n)

         current_state <= IDLE;

else

         current_state <= next_state; //注意,使用的是非阻塞赋值

//第二个进程,组合逻辑always模块,描述状态转移条件判断

always @ (current_state) //电平触发,现存状态为敏感信号

begin

case(current_state)

        S1: if(...)

                next_state = S2; //阻塞赋值

        S2: if(...)

                next_state = S3; //阻塞赋值

...

endcase

end

//第三个进程,同步时序always模块,格式化描述次态寄存器输出

always @ (posedge clk or negedge rst_n)

begin

...//初始化

case(next_state)

       S1:

              out1 <= 1'b1; //注意是非阻塞逻辑

        S2:

              out2 <= 1'b1;

         default:... //default的作用是免除综合工具综合出锁存器

endcase

end

10010序列检测器的三种状态机写法如下

1,一段式

module sn_detector (
				 rst_n		,
				 clk		,
				 sn_i		,
				 sn_check_o
				  ) ;

 
 input      rst_n,clk   ;
 input      sn_i	  ;
 output     sn_check_o ;
 
 reg        sn_check_o ;
 
 reg   [2:0]     state ;

 
  parameter		st_idle  = 3'd0,					//对应原始状态 
         		st_1     = 3'd1,					//对应起始状态1 
  		        st_10    = 3'd2,					//对应中间状态10 
  		        st_100   = 3'd3,					//对应中间状态100
  		        st_1001  = 3'd4,					//对应中间状态1001
                st_10010 = 3'd5;


always @(posedge clk or negedge rst_n)
begin
  if(!rst_n) 
  begin
  	state <= st_idle;
  	sn_check_o <= 0;
  end
  else
  begin	  
  	case(state)
   	st_idle:begin
    	 if (sn_i==1)
    	   state <=st_1; 
    	 sn_check_o <= 1'b0;
    end	  
	  st_1:begin
	     if (sn_i==0)
 	      state <=st_10; 
 	     sn_check_o <= 1'b0;
 	  end   
 	  st_10:begin
	     if (sn_i==0)
  	     state <=st_100; 
	     else
 	      state <=st_1; 
 	     sn_check_o <= 1'b0; 
 	   end
	   st_100:begin
 	    if (sn_i==1)
 	      state <=st_1001; 
  	  else
  	     state <=st_idle; 
  	  sn_check_o <= 1'b0;
  	 end   
 	  st_1001:begin
  	   if (sn_i==1)
  	     state <=st_1; 
  	   else
  	     state <=st_10010;
  	   sn_check_o <= 1'b0;
  	end
 	  st_10010:begin
 	    if (sn_i==1)
 	      state <=st_1; 
  	  else
 	      state <=st_100;
 	    sn_check_o <= 1'b1;
 	  end        
	  default:begin
	   	 state <=st_idle;    //缺省值
	     sn_check_o <= 1'b0;
	  end
 	 endcase
	end
end
 
 


endmodule	

2,二段式

module sn_detector (
				 rst_n		,
				 clk		,
				 sn_i		,
				 sn_check_o
				  ) ;

 
 input      rst_n,clk   ;
 input      sn_i	  ;
 output     sn_check_o ;
 
 reg        sn_check_o ;
 
 reg   [2:0]     state ;

 
  parameter		st_idle  = 3'd0,					//对应原始状态 
         		st_1     = 3'd1,					//对应起始状态1 
  		        st_10    = 3'd2,					//对应中间状态10 
  		        st_100   = 3'd3,					//对应中间状态100
  		        st_1001  = 3'd4,					//对应中间状态1001
                st_10010 = 3'd5;


always @(posedge clk or negedge rst_n)
begin
  if(!rst_n) 
  	state <= st_idle;
  else
  begin	  
  	case(state)
   	st_idle:
    	 if (sn_i==1)
    	   state <=st_1; 
    	  
	   st_1:
	     if (sn_i==0)
 	      state <=st_10; 
 	     
 	  st_10:
	     if (sn_i==0)
  	     state <=st_100; 
	     else
 	      state <=st_1;  
	   st_100:
 	    if (sn_i==1)
 	      state <=st_1001; 
  	   else
  	     state <=st_idle;    
 	  st_1001:
  	   if (sn_i==1)
  	     state <=st_1; 
  	   else
  	     state <=st_10010;
 	  st_10010:
 	    if (sn_i==1)
 	      state <=st_1; 
  	   else
 	      state <=st_100;        
	   default:
	       state <=st_idle;    //缺省值
 	 endcase
	end
end
 
 
always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)   
	  sn_check_o <= 0;
	else if(state==st_10010)
	  sn_check_o <= 1;
	else
	  sn_check_o <= 0;
end

endmodule	

3,三段式

module sn_detector (
				 rst_n		,
				 clk		,
				 sn_i		,
				 sn_check_o
				  ) ;

 
 input      rst_n,clk   ;
 input      sn_i	  ;
 output     sn_check_o ;
 
 reg        sn_check_o ;
 
 reg   [2:0]     curr_state ;
 reg   [2:0]     Next_state ;
 
  parameter		st_idle  = 3'd0,					//对应原始状态 
         		st_1     = 3'd1,					//对应起始状态1 
  		        st_10    = 3'd2,					//对应中间状态10 
  		        st_100   = 3'd3,					//对应中间状态100
  		        st_1001  = 3'd4,					//对应中间状态1001
                st_10010 = 3'd5;
 
 always @(posedge clk or negedge rst_n)
 begin
   if (!rst_n)
     curr_state <= st_idle;
   else
     curr_state <= Next_state;
 end  
 
always @(*)
begin
  case(curr_state)
   st_idle:
     if (sn_i==1)
       Next_state = st_1; 
     else
       Next_state = st_idle;  
   st_1:
     if (sn_i==0)
       Next_state = st_10; 
     else
       Next_state = st_1;    
   st_10:
     if (sn_i==0)
       Next_state = st_100; 
     else
       Next_state = st_1;  
   st_100:
     if (sn_i==1)
       Next_state = st_1001; 
     else
       Next_state = st_idle;    
   st_1001:
     if (sn_i==1)
       Next_state = st_1; 
     else
       Next_state = st_10010;
   st_10010:
     if (sn_i==1)
       Next_state = st_1; 
     else
       Next_state = st_100;        
   default:
       Next_state = st_idle;    //缺省值
  endcase
end
 
 
always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)   
	  sn_check_o <= 1'b0;
	else if(curr_state==st_10010)
	  sn_check_o <= 1'b1;
	else
	  sn_check_o <= 1'b0;
end

endmodule	

 

  • 2
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值