一、什么是状态机
英文名为Finite State Machine,指的是在有限个状态之间按照一定规律进行转换的电路。
Mealy型状态机
输出由当前状态和初始输入共同决定
Moore型状态机
输出仅由当前状态决定
二、状态机的编码
二进制编码
使用二进制的编码方式对状态进行编码,特点是编码简单,符合计数规则。例如要对这四个状态进行编码,则可以编码为00 01 10 11。
二进制编码的优点是定义状态时编码所占用的位宽小,缺点是状态变化时发生改变的比特位多,容易产生毛刺。
独热编码
特点是状态寄存器在任何状态时都只有一个比特位为高位,其余全为低位。例如要对这四个状态进行编码,则可以编码为0001 0010 0100 1000。
优点是状态定义中只有一个比特位为1,其余全为0,缺点是有多少个状态就需要多少个位宽,比较占用资源。
格雷编码
特点是相邻的两个状态寄存器的二进制数赋值只有一个比特位不同。例如要对这四个状态进行编码,则可以编码为00 01 11 10。
格雷编码的优点是状态转换时只有一比特发生改变,减少了毛刺的产生,但这种编码的可读性较低
三、如何构建状态机(三段式构建状态机)
第一段,使用时序逻辑对实现现态次态之间的跳转;第二段,使用组合逻辑实现状态转移;第三段使用时序逻辑实现输出。
以HDLBits上面的一题为例,下面是题目描述。题目就不翻译了,不难看懂。
首先画出他的状态转移图,如下:
第一段,格式化描述次态转移到现态
//复位设定
always@(posedge clk)
begin
if(reset)
state<=state_1;
else
state<=next_state;
end
注意现态state要写在赋值语句左边,不然会出现以下报错(debug了半下午才找到错误,没用代码天赋的人是这样的,悲~~~)
第二段,描述状态间的转移。代码如下
always@(*)
begin
case(state)
state_1:
begin
if(s[3:1]==3'b001)
next_state=state_2;
else
next_state=state_1;
end
state_2:
begin
if(s[3:1]==3'b011)
next_state=state_3;
else if(s[3:1]==3'b001)
next_state=state_2;
else
next_state=state_1;
end
state_3:
begin
if(s[3:1]==3'b111)
next_state=state_4;
else if(s[3:1]==3'b001)
next_state=state_2;
else
next_state=state_3;
end
state_4:
begin
if(s[3:1]==3'b111)
next_state = state_4;
else
next_state = state_3;
end
第三段,输出设置,代码如下。
关于dfr的输出,一开始我写的注释块里面的,但是一直输出不正确,后面参考另一位大佬写的代码写成如下形式,这两种写法不是一样吗???没搞懂
// always@(posedge clk)
// begin
// dfr=((state==state_1)||(next_state < state));
// end
reg state_lower;
always@(posedge clk)begin
if(reset||state<next_state)
state_lower <= 1'b0;
else if(state>next_state)
state_lower <= 1'b1;
end
assign dfr = (state==state_1)||(state_lower);
//输出
always@(*)
begin
if(state==state_1)
begin
fr1=1;
fr2=1;
fr3=1;
end
else if(state==state_2)
begin
fr1=1;
fr2=1;
fr3=0;
end
else if(state==state_3)
begin
fr1=1;
fr2=0;
fr3=0;
end
else if(state==state_4)
begin
fr1=0;
fr2=0;
fr3=0;
end
end
endmodule
###参考正点原子视频,《FPGA大道至简的至简设计法》,HDLBits。如有侵权,请联系删除