状态机分类
根据状态机输出产生的类型,可以将状态机分成两类。
第一个是Moore状态机,输出只是当前状态的函数,
第二个是Mealy状态机,其中一个或多个输出是当前状态和一个或多个输入的函数。
除了通过输出生成类型对状态机进行分类之外,还可以根据状态机使用的状态编码方式进行分类。一些常见的状态编码样式有二进制码,格雷码,独热码等。
状态机应该被编码成一个单独的Verilog模块。
保持状态机与其他逻辑分离可以简化状态机的定义,修改和调试。
状态名称应该用parameters定义成容易辨识的符号。
这使Verilog代码更具可读性。
下面分别是用二进制和独热码定义的状态:
binary encoding:
parameter [2:0] // synopsys enum code
IDLE = 3'd0,
S1 = 3'd1,
S2 = 3'd2,
S3 = 3'd3,
ERROR = 3'd4;
one-hot encoding:
parameter [4:0] IDLE = 5'b00001,
S1 = 5'b00010,
S2 = 5'b00100,
S3 = 5'b01000,
ERROR = 5'b10000;
还可以使用宏定义指令定义状态名称(\`define),但\`define创建的是一个全局定义。与\`define常量不同,parameters是声明它们的模块的局部常量,它允许设计中存在多个具有重复状态名称的状态机。
Two-Always状态机
可综合的状态机有多种编码方式。最常见的是two-always状态机和one-always状态机。
在two-always状态机中,输出逻辑在组合always逻辑,或者单独的assign语句中实现,即two-always状态机包含present-state时序逻辑、next-state组合逻辑和输出生成组合逻辑。
present-state时序逻辑
指南:在时序逻辑中仅使用非阻塞赋值。
Verilog非阻塞赋值用来建模实际硬件的流水线寄存器行为,消除了许多潜在的Verilog竞争冒险。
always @(posedge clkor posedge rst)
if (rst) state <= 4'b0;
else state <= next;
next-state组合逻辑
指南:在组合逻辑中仅使用Verilog阻塞赋值来更新next-state值。next-state组合逻辑通过敏感列表来触发组合always语句。敏感列表为present-state时序逻辑的输出和状态机的输入。
在always语句块后面是一个默认的next-state赋值,将next-state赋值为全x或者IDLE。通过对next-state进行默认赋值,如果有些情况没有明确状态转换,next-state将是默认状态。
always @(state or i1 or i2 or i3 or i4) begin
next = IDLE;
case (state)
IDLE: begin
next = ERROR;
if (!i1) next = IDLE;
if (i1 & i2) next = S1;
if (i1 & !i2 & i3) next = S2;
end
S1: ...
输出生成组合逻辑
状态机的输出可以在组合always逻辑或者单独的assign语句中生成。
对于Mealy状态机来说,其输出同样也可以在组合always逻辑或者单独的assign语句中生成
assign rd_out = (state == READ) & !rd_strobe_n;
或者
case (state)
...
READ: if (!rd_strobe_n) rd_out = 1'b1;
在该状态机中,还可以通过添加一个时序逻辑always语句来实现寄存器输出。
作者:iwonder
链接:https://mp.weixin.qq.com/s/IVFoSqOuwZZkUJph1WPY7g
https://mp.weixin.qq.com/s/uA35-vqZD_m3N3jODXoRkA
推荐阅读
- 高扇出网络综合需要考虑的因素
- 总结我的验证思路:“开门红” Test Case
- 总结我的思路:发现Bug,发现所有的Bug,或者证明没有Bug,是验证存在的唯一目的
- 总结我的验证思路系列二:心有多大,舞台就有多大
更多数字IC设计技术干货等请关注数字芯片实验室专栏。添加极术小姐姐(微信:aijishu20)微信可申请加入IC设计交流群。