- 状态机就是一种能够描述具有逻辑顺序和时序顺序事件的方法
- 状态机有两大类:Mealy型和Moore型
Moore型状态机的输出只与当前状态有关,而Mealy型状态机的输出不仅取决于当前状态,还受到输入的直接控制,并且可能与状态无关.
(1)moore机的输出只与当前状态有关
(2)mealy机的输出与当前状态和输入都有关
(3)体现在状态转移图上就是,moore机的输出在状态圆圈内,mealy机的输出在转移曲线上
(4)moore完全描述状态转移图会比mealy机多一个状态
(5)体现在verilog代码中就是,moore机的最后输出逻辑只判断state,mealy机的输出逻辑中判断state && input
同步时序电路的设计方法
- 逻辑抽象,得出电路的状态转换图或者状态转换表
- 状态化简
- 状态分配(状态编码:Binary,Gray,One-Hot)
- Verilog根据最简状态转换图编程,检查设计的电路能否自启动
四个要素
- 当前输入
- 当前状态
- 下一状态
- 当前输出值
代码风格
一段式
当前状态、下一状态、当前输出值都写在一个always块中
二段式
当前状态、下一状态、当前输出值写在两个always块中
当前状态的输出采用组合逻辑实现,会存在产生毛刺的风险
- 注意:这样三种组合方式,及有三种方式写这两个always块。
三段式(推荐)
当前状态、下一状态、当前输出值分别写在各自的always块中,这样需要3个always块 ;
对当前状态的输出采用一拍寄存,避免了毛刺的产生;
下面以检测10110序列为例说明
序列长度为5,所以对于moore机来说需要6个状态,即增加一个初始状态;对于mealy机来说,只需要5个状态
module sequence_10110(in,clk,rst,moore_y,mealy_y);
input in,clk,rst;
output reg moore_y,mealy_y;
//定义各个状态,采用one-hot编码,需要6位
parameter s0=6'b000001,s1=6'b000010,s2=6'b000100,s3=6'b001000,s4=6'b010000,s5=6'b100000;
//s0为未检测到有效位,s1为检测到1,s2为检测到10,s3为检测到101,s4为检测到1011,s5为检测到10110
parameter s0_pos=3'd0,s1_pos=3'd1,s2_pos=3'd2,s3_pos=3'd3,s4_pos=3'd4,s5_pos=3'd5;//描述有效位在state中的位置
reg [5:0] cs,ns;//cs表示当前状态,ns表示下一个状态
//时序逻辑描述状态转换
always @(posedge clk or negedge rst)//采用异步复位
begin
if(~rst)
cs<=s0;//复位进入初态
else
cs<=ns;//采用非阻塞赋值
end
//组合逻辑描述状态转换条件
always @(*)
begin
if(~rst) ns=s0;//组合逻辑采用阻塞赋值
else begin
case(1'b1)//采用one-hot编码的好处是有效位只有一位,即每次只需要比较1位
cs[s0_pos]:ns=(in==1'b0)?s0:s1;
cs[s1_pos]:ns=(in==1'b0)?s2:s1;
cs[s2_pos]:ns=(in==1'b0)?s0:s3;
cs[s3_pos]:ns=(in==1'b0)?s2:s4;
cs[s4_pos]:ns=(in==1'b0)?s5:s1;
cs[s5_pos]:ns=(in==1'b0)?s0:s1;
default:ns=s0;
endcase
end
end
//输出逻辑
//moore
always @(posedge clk or negedge rst)
begin
if(~rst) moore_y<=1'b0;
else moore_y<=(cs==s5)?1'b1:1'b0;//moore机的输出只与当前状态有关,故在s5输出
end
//mealy
always @(posedge clk or negedge rst)
begin
if(~rst) mealy_y<=1'b0;
else mealy_y<=(cs==s4 && in==1'b0)?1'b1:1'b0;//mealy机的输出不仅取决于当前状态,还与当前输入有关
end
moore机只有在状态在s5时才输出,而mealy机在状态s4且输入为0时就输出,所以moore机比mealy机输出滞后一个周期