同步状态机的verilog HDL实现:
1、状态编码:
二进制编码:比较简单,使用状态向量较少,但是状态间可能会有毛刺。
格雷码:减少了状态间的位变化,降低了功耗有减少了毛刺,但是不适用于很多状态的跳转实现。
独热编码:多少种状态就用多少位实现,当哪一位为1的时候说明处在哪一种状态。
2、 HDL
描述语言有多种,但是不同的描述电路性能大不相同。
一般有3种描述方法:单always,双always和三always块。
单always使用的是输出逻辑与下一状态逻辑都用reg,没有毛刺,但是导致了寄存器更多,而且代码很难修改和调试。
双always块用于描述mealy状态机和组合输出的moore状态机。一个always用来描述当前状态逻辑,另外一个always块描述次状态并给出输出。这种方法结构清晰,面积和频率都比较好。但是容易产生毛刺,当输入向量作为时钟信号的时候,这些毛刺是致命的。
三always块主要用于mealy状态机,两个always用于当前状态和输出逻辑,还有一个组合逻辑的always用于下一状态逻辑。虽然面积比双always块大,但是输出无毛刺,比单个always更加清晰易读。
// state register
always @ (posedge clk or negedge rst) begin
if (rst) state <= S0;
else state <= nextstate;
end
// next state logic
always @ (*)
case (state)
S0: nextstate = S1;
S1: nextstate = S2;
S2: nextstate = S0;
.......
default: nextstate = S0;
endcase
//output logic
assign out_ = ....;
也可以写成always@(*)把多个输出放在里面。
注意:使用异步状态机是不可以综合的,设计异步状态机的时候建议使用电路输入的方法。
always块尽量避免组合反馈回路。在赋值表达式右端参与赋值的信号都必须出现在敏感信号的列表里,否则在综合的时候,会为没有列入的信号隐含地产生一个透明锁存器。
有一些经验:描述组合逻辑的always块里使用阻塞赋值;描述时序逻辑的always块里使用非阻塞赋值。
有时候我们综合出来的状态机发现综合出来的不是,那么请参考:
http://bbs.eetop.cn/thread-350355-2-1.html