MEALY/MOORE 状态机
定义:
Moore (摩尔)型状态机:输出只由当前状态决定,即次态=f(现状,输入),输出=f(现状);
Mealy (米粒)型状态机:输出不但与当前状态有关,还与当前输入值有关,即次态=f(现状,输入),
输出=f(现状,输入);
二者的不同点:
- Moore 型状态机的输出信号是直接由状态寄存器译码得到,而 Mealy 型状态机则是以 现时的输入信号 结合 即将变成次态的现态,编码成输出信号。
- Mooer 状态机的输出只与当前的状态有关,也就是当前的状态决定输出,而与此时的输入无关,输入只决定状态机的状态改变,不影响电路最终的输出。(注意:这里所说的输出不是状态机的状态输出,而是当前状态的所代表的含义,比如:检测 110 序列的状态机,当状态机跳转到 STA_GOT110 时,电路会有一个输出信号,假如说是 find,此时 find就会为高电平,其他状态时 find 就会为低电平。find 是我们最后电路的输出,find 的值只与我们的状态机当前所处的状态有关,而与输入无关)。
Mealy 状态机的输出不仅与当前的状态有关,还与当前的输入有关(同样,不要误认为状态机的输出只能是状态机的状态),即当前的输入和当前的状态共同决定当前的输入。
有限状态机 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
next_state = x; //要初始化,使得系统复位后能进入正确的状态
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
现学现卖:
代码如下:
`timescale 1ns/1ns
module seq_circuit(
input A ,
input clk ,
input rst_n,
output wire Y
);
reg [1:0] cur_state;
reg [1:0] nex_state;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
cur_state <= 2'b00; //复位
else
cur_state <= nex_state; //次态 给 现态
end
always @ (*) begin
case (cur_state)
2'b00 : nex_state = (A == 1'b0) ? 2'b01 : 2'b11;
2'b01 : nex_state = (A == 1'b0) ? 2'b10 : 2'b00;
2'b10 : nex_state = (A == 1'b0) ? 2'b11 : 2'b01;
2'b11 : nex_state = (A == 1'b0) ? 2'b00 : 2'b10;
default : nex_state = 2'b00;
endcase
end
// reg Y_wire;
// always @ (posedge clk or negedge rst_n) begin
// if(!rst_n)
// Y_wire <= 1'b0;
// else
// if(nex_state == 2'b11)
// Y_wire <= 1'b1;
// end
assign Y = (cur_state == 2'b11) ? 1'b1 : 1'b0;
endmodule
代码如下:
`timescale 1ns/1ns
module seq_circuit(
input C ,
input clk ,
input rst_n,
output wire Y
);
reg [1:0] cur_state, nex_state;
parameter state0 = 2'b00;
parameter state1 = 2'b01;
parameter state2 = 2'b10;
parameter state3 = 2'b11;
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
cur_state <= state0;
else
cur_state <= nex_state;
end
always @ (*)
begin
case(cur_state)
state0 : nex_state = (C == 1'b0) ? state0 : state1;
state1 : nex_state = (C == 1'b0) ? state3 : state1;
state2 : nex_state = (C == 1'b0) ? state0 : state2;
state3 : nex_state = (C == 1'b0) ? state3 : state2;
default : nex_state = state0;
endcase
end
assign Y = (cur_state == state3 | (cur_state == state2 & C == 1'b1)) ? 1'b1 : 1'b0;
endmodule