目录
状态转移图
Verilog 描述序列检测器一般采用有限状态机FSM,而状态机(时序电路)又分为Mealy型和Moore型。
Mealy型:状态机的输出不仅与当前的状态有关,还与输入信号有关,即输出是输入和当前状态的函数
Moore型:状态机的输出仅仅与当前状态有关。
两者在状态转移图上的差异体现在,Moore型的输出在状态圆圈内,因为输出仅与状态有关;而Mealy型的输出是在转移曲线上,因为该型机的输出不仅与当前状态有关,还与输入有关。同时要注意的是,Moore型完全描述的状态转移图会比Mealy型多一个状态,这是因为Moore型的输出是与当前状态有关,因此FSM的输出逻辑要求状态必须到达最终的某个序列的状态比如10011以后才会有输出,而Melay型不用。比如Mealy型FSM当前状态为1001时,并且此刻的输入为1,那么输出逻辑就会根据这两个条件输出完成检测标志,而Moore型必须还得多占一个状态即10011的状态,将10011的状态送给输出逻辑,这时输出逻辑才会输出完成检测标志。
1、确定状态编码的长度,即二进制代码的位数,也就是触发器的个数。
状态编码的长度是由最小化状态表中的状态个数确定。设最小化状态表的状态数为N,状态编码的长度为m,状态数N与状态编码长度m的关系为:2^m-1 < N ≤2^m。
2、最佳的或者接近最佳的状态分配方案,
这使所设计的同步时序逻辑电路的输出函数和激励函数最简单。
状态编码方案的好坏还与所采用的触发器类型有关。也就是,某种状态编码方案,对某种触发器是最佳的编码方案,然而换成另一种触发器就不一定是最佳的状态编码方案。由此可见,一种最佳状态编码方案涉及的因素很多。
1、状态表中的两个现态,如果在相同外部输入(X=0或X=1)条件下,这两个现态的次态相同,则尽可能给这两个现态分配相邻的代码。
2、状态表中的一个现态,如果在不同外部输入(X=0且X=1)条件下,这个现态的两个次态不相同,则尽可能给这两个次态分配相邻的代码。
3、状态表中两个现态,如果在不同外部输入条件下,这个次态有相同的外部输出,则尽可能给两个现态分配相邻的代码。
4、 状态表中出现次数最多的状态在状态编码上为逻辑0。
以检测10010序列为例
Mealy型:
状态机输出不仅与当前状态有关,还与输入信号有关,因此,输出信号Y单独表示在状态转移图的转移曲线上,而不与状态编码一起。Mealy型状态机的状态数一般为:序列长度。编码方式有多种,二进制编码,独热码,甚至是格雷码,只是用于区别状态,通常采用one-hot码
S0:00000 ; S1 ; S10; S100 ; S1001 ; S10010;
输入信号A,输出信号Y: A/Y
初始状态为S0: 若输入信号A=0,则输出Y=0 ,下一状态依旧为S0;若输入信号A=1,输出Y=0,下一状态为S1;
状态S1 :若输入信号A=0,则输出Y=0,下一状态为S10 ;若输入信号A=1, 输出Y=0,下一状态依旧为S1;
状态S10 :若输入信号A=0,则输出Y=0,下一状态为S100 ;若输入信号A=1,输出Y=0,下一状态为S1;
状态S100 :若输入信号A=0,则输出Y=0,下一状态为S0 ;若输入信号A=1,输出Y=0,下一状态为S1001;
状态S1001 :若输入信号A=0,则输出Y=1,下一状态为S10010;若输入信号A=1,输出Y=0,下一状态为S1 ;
对于状态S10010的处理:
状态S10010 :若输入信号A=0,则输出Y=0,下一状态为S0 ;若输入信号A=1,输出Y=1,下一状态为S1。
现态 | 次态/输出 | |
输入A=0 | 输入A=1 | |
IDLE | IDLE/0 | S1/0 |
S1 | S10/0 | S1/0 |
S10 | S100/0 | S1/0 |
S100 | IDLE/0 | S100/0 |
S1001 | S | |
S10010 | ||
Moore型:
该型FSM的输出仅仅与FSM的当前状态有关,与输入无关,
module sequence_det(
clk
, rst
, din
, moore_o
, mealy_o
);
input clk ;
input rst ;
input din ;
output reg moore_o ;
output reg mealy_o ;
reg [4:0] cur_state,nxt_state;
//=====================================================\
//**************** Define Parameter **************
//======================================================/
//状态编码:one-hot
localparam Idle = 5'b00000;
localparam S1 = 5'b00001;
localparam S10 = 5'b00010;
localparam S100 = 5'b00100;
localparam S100 = 5'b01000;
localparam S1001 = 5'b10000;
//状态转移
always@(posedge clk or posedge rst)
begin
if(rst)
cur_state <= Idle;
else begin
cur_state <= nxt_state ;
end
end
//次态生成
always@(*)
begin
if(rst)
begin
nxt_state <= Idle;
end
else begin
case(state)
Idle : nxt_state = din? S1 :Idle ;
S1 : nxt_state = din? S1 : S10 ;
S10 : nxt_state = din? S1 : S100 ;
S100 : nxt_state = din? S1001 : Idle ;
S1001 : nxt_state = din? S1 : S10010 ;
S10010 : nxt_state = din? S1 : S100 ;
default: nxt_state = Idle ;
endcase
end
end
end
end
//Moore Machine
always@(posedge clk or posedge rst)
begin
if(rst)
begin
moore_o <= 1'b0 ;
end
else begin
case(cur_state)
S10010: moore_o <= 1'b1 ;
default: moore_o <= 1'b0 ;
endcase
end
//Mealy Machine
always@(posedge clk or posedge rst)
begin
if(rst)
begin
mealy_o <= 1'b0 ;
end
else begin //输出不仅与当前状态state有关,还与当前的输入有关
mealy_o <= (state = S1001&& din ==0)?1'b1:1'b0;
end
end
endmodule