2.5 Finite State Machines 有限状态机(一)
2.5.1 Simple FSM 1(asynchronous reset) [Fsm1]
问题描述
下图是一个有两个状态的摩尔状态机,一个输入,一个输出。利用电路实现此状态机,异步复位状态置B状态。
提示
这是一个异步复位的输入反相的T触发器。同时根据程序提示内容,有限状态机的描述方式可以用两段式和三段式来表示:
- 两段式通常使用两个always块,一个always块描述状态的转移;一个always块采用同时描述状态转移规律和状态的输出结果。
- 三段式通常使用三个always块,分别描述状态转移、状态转移规律以及输出,三段式的描述在某些情形下能够消除电路中的毛刺现象。
代码
module top_module(
input clk,
input areset, // Asynchronous reset to state B
input in,
output out);//
parameter A=0, B=1;
reg state, next_state;
always @(*) begin // This is a combinational always block
// State transition logic
case(state)
A : next_state = in? A : B;
B : next_state = in? B : A;
endcase
end
always @(posedge clk, posedge areset) begin // This is a sequential always block
// State flip-flops with asynchronous reset
if(areset)
state <= B;
else
state <= next_state;
end
// Output logic
// assign out = (state == ...);
assign out = state;
endmodule
2.5.2 Simple FSM 1(synchronous reset) [Fsm1s]
问题描述
下图是一个有两个状态的摩尔状态机,一个输入,一个输出。利用电路实现此状态机,同步复位状态置B状态。
分析
与上题类似,但同步复位。
代码
// Note the Verilog-1995 module declaration syntax here:
module top_module(
input clk,
input reset, // Synchronous reset to state B
input in,
output out
);//
// Fill in state name declarations
parameter A=0;
parameter B=1;
reg present_state, next_state;
always @(posedge clk) begin
if (reset)
present_state <= B;
else
present_state <= next_state;
end
always @(*) begin
case(present_state)
A: next_state = in ? A : B;
B: next_state = in ? B : A;
endcase
end
assign out = present_state;
endmodule
2.5.3 Simple FSM 2 (asynchronnous reset) [Fsm2]
问题描述
实现下图的具有两个状态的异步复位摩尔状态机。
代码
module top_module(
input clk,
input areset, // Asynchronous reset to OFF
input j,
input k,
output out); //
parameter OFF=0, ON=1;
reg state, next_state;
always @(*) begin
// State transition logic
case(state)
OFF: next_state = j ? ON : OFF;
ON : next_state = k ? OFF : ON;
endcase
end
always @(posedge clk, posedge areset) begin
// State flip-flops with asynchronous reset
if(areset)
state <= OFF;
else
state <= next_state;
end
assign out = state;
// Output logic
// assign out = (state == ...);
endmodule
2.5.4 Simple FSM 2 (synchronnous reset) [Fsm2s]
问题描述
实现下图的具有两个状态的异步复位摩尔状态机。
代码
module top_module(
input clk,
input reset, // Synchronous reset to OFF
input j,
input k,
output out); //
parameter OFF=0, ON=1;
reg state, next_state;
always @(*) begin
// State transition logic
case(state)
OFF: next_state = j ? ON : OFF;
ON : next_state = k ? OFF : ON;
endcase
end
always @(posedge clk) begin
if(reset)
state <= OFF;
else
state <= next_state;
end
assign out = state;
endmodule
2.5.5 Simple state transition 3 [Fsm3comb]
问题描述
下述表格是一个一输入,一输出和四个转换状态的摩尔状态机的状态转换表。使用以下状态编码表示:
A=2’b00 B=2’b01 C=2’b10 D=2’b11
State | Next state | Output | |
in=0 | in=1 | ||
A | A | B | 0 |
B | C | B | 0 |
C | A | D | 0 |
D | C | B | 1 |
仅为该状态机实现状态转换逻辑和输出逻辑。给定当前状态state,根据状态转换表计算next_state和输出out。
分析
按照题意,进需要给出采用逻辑描述状态转移逻辑和输出的部分即可。
代码
module top_module(
input in,
input [1:0] state,
output [1:0] next_state,
output out); //
parameter A=0, B=1, C=2, D=3;
// State transition logic: next_state = f(state, in)
always@(*) begin
case(state)
A : next_state = in ? B : A;
B : next_state = in ? B : C;
C : next_state = in ? D : A;
D : next_state = in ? B : C;
endcase
end
// Output logic: out = f(state) for a Moore state machine
assign out = (state == D)? 1 : 0;
endmodule
2.5.6 Simple one-hot state transitions 3 [Fsm3onehot]
问题描述
以下是具有一个输入、一个输出和四个状态的摩尔状态机的状态转换表。采用独热编码如下:
A=4’b0001 B=4’b0010 C=4’b0100 D=4’b1000
通过检测假设采用独热编码来实现推到状态转移和输出逻辑方程。仅为该状态机实现状态转换逻辑和输出逻辑。(testbench将会用非独热编码的输入进行测试,以确保没有进行更复杂的操作)
State | Next state | Output | |
in=0 | in=1 | ||
A | A | B | 0 |
B | C | B | 0 |
C | A | D | 0 |
D | C | B | 1 |
什么叫“检验方程”?
独热状态机编码保证只有一个状态位为1,这意味着可以通过仅检查一个状态位而不是所有状态位来确定状态机是否处于特定状态。通过检查状态转化图中每个状态的输入边缘,推导出状态转移的简单方程。
例如,在上面的状态机中,状态机如何能够到达状态A?它必须使用两个条件之一:“当前处于A状态且in=0”或“当前处于状态C且in=0”。由于独热编码,用于测试“当前处于状态A”的逻辑等式仅仅是A的状态。这导致用于状态A的下一个状态的最终逻辑等式为next_state[0] = state[0] & (~in) | state[2] & ~(in)
独热编码保证一次最多有一个子句是活动的,因此这些子句可以直接进行或运算。
分析
首先了解度热编码,一位有效编码,用N位寄存器对N个状态进行编码,每个状态都有它独立的寄存器位。按照对题目中提示的学习,就可以得到状态B、C、D对应的最终逻辑等式的描述。
代码
module top_module(
input in,
input [3:0] state,
output [3:0] next_state,
output out); //
parameter A=0, B=1, C=2, D=3;
// State transition logic: Derive an equation for each state flip-flop.
assign next_state[A] = (state[A] & ~in) | (state[C] & ~in);
assign next_state[B] = (state[A] & in) | (state[B] & in) | (state[D] & in);
assign next_state[C] = (state[B] & ~in) | (state[D] & ~in);
assign next_state[D] = (state[C] & in);
// Output logic:
assign out = state[D];
endmodule
2.5.7 Simple FSM 3 (asynchronous reset) [Fsm3]
问题描述
以下是一个具有一个输入、一个输出和四个状态的摩尔状态机的状态转换表。实现此状态机。其中复位为异步复位FSM到状态A。
State | Next state | Output | |
in=0 | in=1 | ||
A | A | B | 0 |
B | C | B | 0 |
C | A | D | 0 |
D | C | B | 1 |
状态转移图
代码
module top_module(
input clk,
input in,
input areset,
output out); //
parameter A=0,B=1,C=2,D=3;
reg [3:0] state,next_state;
// State transition logic
always@(*) begin
case(state)
A : next_state = in ? B : A;
B : next_state = in ? B : C;
C : next_state = in ? D : A;
D : next_state = in ? B : C;
endcase
end
// State flip-flops with asynchronous reset
always@(posedge clk,posedge areset) begin
if(areset)
state <= A;
else
state <= next_state;
end
// Output logic
assign out = (state==D) ? 1 : 0;
endmodule
2.5.8 Simple FSM 3 (synchronous reset) [Fsm3s]
问题描述
以下是一个具有一个输入、一个输出和四个状态的摩尔状态机的状态转换表。实现此状态机。其中复位为同步复位FSM到状态A。
State | Next state | Output | |
in=0 | in=1 | ||
A | A | B | 0 |
B | C | B | 0 |
C | A | D | 0 |
D | C | B | 1 |
状态转移图
原题中给的图就是上一题的图,这里areset应该改成reset
代码
module top_module(
input clk,
input in,
input reset,
output out); //
parameter A=0,B=1,C=2,D=3;
reg [3:0] state,next_state;
// State transition logic
always@(*) begin
case(state)
A : next_state = in ? B : A;
B : next_state = in ? B : C;
C : next_state = in ? D : A;
D : next_state = in ? B : C;
endcase
end
// State flip-flops with asynchronous reset
always@(posedge clk) begin
if(reset)
state <= A;
else
state <= next_state;
end
// Output logic
assign out = (state==D) ? 1 : 0;
endmodule
2.5.9 Design a Moore FSM [Exams/ece241 2013 q4]
问题描述
一个水库为几个用户供水。为了保持水位足够,有三个传感器以5英寸的间隔垂直放置。当水位处于最高的传感器S3时,输入流速应该设置为0。当水位低于最低传感器S1时,流入速度应当设置为最大(Nominal 和 Supplemental控制器均打开)。水位在高低传感器之间时的流速主要由两个因素决定:当前水位和上一次传感器变化之前的水位。每个水位都有一个与其相关的标称流速,如下表所示。如果传感器变化指示之前水平面低于当前水平面,则应该执行标称流速。如果之前的水平面高于当前水平面,则应该通过打开补充流量阀(由△FR控制)来增加流量。
绘制摩尔模型状态转换图,指示清楚每个状态的状态转换和输出。FSM的输入是S1,S2,S3;输出是FR1,FR2,FR3和△FR。
水平面 | 传感器生效 | 待生效的标称流量输入 |
---|---|---|
高于S3 | S1,S2,S3 | 无 |
S3与S2之间 | S1,S2 | FR1 |
S2与S1之间 | S1 | FR1,FR2 |
低于S1 | 无 | FR1,FR2,FR3 |
还包括一个高电平有效同步复位,将状态机复位到相当于水平面长期处于低位的状态(传感器置0,四个输出置1)。
分析
对题意的理解,可以根据表格划分出四种状态:
- S01表示水平面低于S1传感器
- S12表示水平面位于S1与S2两传感器之间
- S23表示水平面位于S2与S3两传感器之间
- S34表示水平面高于S3传感器。
如果传感器输入状态没有发生变化,则没有发生状态转移,对于△FR则保持之前的输出即可。
同时FR在题目中表示,如果之前水位低于现状态水位时(水量增长),FR为低电平;而之前水位高于当前水位时,FR为高电平。
状态转移图
代码
module top_module (
input clk,
input reset,
input [3:1] s,
output reg fr3,
output reg fr2,
output reg fr1,
output reg dfr
);
parameter S01=0,S12=1,S23=2,S34=3;
reg [3:0] state,next_state;
always@(*) begin
case(state)
S01 : begin
if(s==3'b000)
next_state = S01;
else if(s==3'b001)
next_state = S12;
end
S12 :begin
if(s==3'b011)
next_state = S23;
else if(s==3'b001)
next_state = S12;
else if(s==3'b000)
next_state = S01;
end
S23 :begin
if(s==3'b111)
next_state = S34;
else if(s==3'b011)
next_state = S23;
else if(s==3'b001)
next_state = S12;
end
S34 :begin
if(s==3'b111)
next_state = S34;
else if(s==3'b011)
next_state = S23;
end
default:next_state = S01;
endcase
end
always@(posedge clk) begin
if(reset)
state <= S01;
else
state <= next_state;
end
always@(posedge clk) begin
if(reset)
{fr3,fr2,fr1,dfr} = 4'b1111;
else
case(next_state)
S01 :begin
if(state == S01)
{fr3,fr2,fr1,dfr} = {3'b111,dfr};
else if(state == S12)
{fr3,fr2,fr1,dfr} = 4'b1111;
end
S12 :begin
if(state == S01)
{fr3,fr2,fr1,dfr} = 4'b0110;
else if(state == S12)
{fr3,fr2,fr1,dfr} = {3'b011,dfr};
else if(state == S23)
{fr3,fr2,fr1,dfr} = 4'b0111;
end
S23 :begin
if(state == S12)
{fr3,fr2,fr1,dfr} = 4'b0010;
else if(state == S23)
{fr3,fr2,fr1,dfr} = {3'b001,dfr};
else if(state == S34)
{fr3,fr2,fr1,dfr} = 4'b0011;
end
S34 :begin
if(state == S34)
{fr3,fr2,fr1,dfr} = {3'b000,dfr};
else if(state == S23)
{fr3,fr2,fr1,dfr} = 4'b0000;
end
endcase
end
endmodule
2.5.10 Lemmings 1 [Lemmings1]
问题描述
旅鼠游戏非常简单,简单到我们可以使用有限状态机来建模。
在旅鼠的2D世界中,他们可以处于两种状态:向左行走或向右行走。如果遇到障碍物,它会改变方向。特别是当他撞到左边的时候,他会向右走;当他撞到右边的时候,他会向左走;如果他两边同时受到撞击,他仍然会改变方向。
实现一个具有两个状态、两个输入和一个输出的状态机来模拟这个行为。
异步复位,向左侧行走。
状态转移图
代码
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
output walk_left,
output walk_right); //
parameter LEFT=0, RIGHT=1;
reg state, next_state;
always @(*) begin
// State transition logic
case(state)
LEFT :begin
case({bump_left,bump_right})
2'b00 : next_state = LEFT;
2'b01 : next_state = LEFT;
2'b10 : next_state = RIGHT;
2'b11 : next_state = RIGHT;
endcase
end
RIGHT:begin
case({bump_left,bump_right})
2'b00 : next_state = RIGHT;
2'b01 : next_state = LEFT;
2'b10 : next_state = RIGHT;
2'b11 : next_state = LEFT;
endcase
end
endcase
end
always @(posedge clk, posedge areset) begin
// State flip-flops with asynchronous reset
if(areset)
state <= LEFT;
else
state <= next_state;
end
// Output logic
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
endmodule
2.5.11 Lemmings 2 [Lemmings2]
问题描述
在上一问的基础上,增加一个掉落状态。
除了左右行走和发生碰撞时改变行走的方向,当地面ground=0时,旅鼠会掉落并说“aaah!”。当地面重新出面ground=1时,旅鼠将会沿着坠落前的方向继续行走。在跌倒时被碰撞不会影响行走的方向,并且在与地面消失(但尚未跌倒)相同的周期中被碰撞,或者当地面在跌倒状态中重新出现时,也不会影响行走的方向。
构建一个有限状态机来模拟这个行为。
有限状态机
代码
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
output walk_left,
output walk_right,
output aaah ); //
parameter FALL_L=0,LEFT=1,RIGHT=2,FALL_R=3;
reg [1:0] state, next_state;
always @(*) begin
// State transition logic
case(state)
FALL_L :begin
if(ground)
next_state = LEFT;
else
next_state = FALL_L;
end
LEFT :begin
if(ground == 0)
next_state = FALL_L;
else if(bump_left==1)
next_state = RIGHT;
else
next_state = LEFT;
end
RIGHT:begin
if(ground == 0)
next_state = FALL_R;
else if(bump_right==1)
next_state = LEFT;
else
next_state = RIGHT;
end
FALL_R:begin
if(ground)
next_state = RIGHT;
else
next_state = FALL_R;
end
endcase
end
always @(posedge clk, posedge areset) begin
// State flip-flops with asynchronous reset
if(areset)
state <= LEFT;
else
state <= next_state;
end
// Output logic
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
assign aaah = (state==FALL_L)|(state==FALL_R);
endmodule
2.5.12 Lemmings 3 [Lemmings3]
问题描述
除了行走和坠落,旅鼠有时候还被告知做一些事情,比如挖洞(dig=1时开始挖掘)。如果旅鼠目前正在地面上行走(ground=1并且不处于坠落),则可以挖掘,并将继续挖掘直到到达另一边(ground=0)。此时,因为没有地面了,他会坠落(aaah=1),然后当他再次回到地面时继续沿着之前的方向行走,在挖掘时被撞到没有任何影响,同样的在坠落或是没有地面时也不会响应挖掘。
换句话说,fall的优先级高于dig,dig的优先级高于行走
在之前的基础上继续扩展有限状态机来模拟这个行为
状态转移方程
代码
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
input dig,
output walk_left,
output walk_right,
output aaah,
output digging );
parameter FALL_L=0,DIG_L=1,LEFT=2,RIGHT=3,DIG_R=4,FALL_R=5;
reg [2:0] state,next_state;
always@(posedge clk,posedge areset) begin
if(areset)
state <= LEFT;
else
state <= next_state;
end
always@(*) begin
case(state)
FALL_L : begin
if(ground)
next_state = LEFT;
else
next_state = FALL_L;
end
DIG_L : begin
if(ground)
next_state = DIG_L;
else
next_state = FALL_L;
end
LEFT : begin
if(ground == 0)
next_state = FALL_L;
else if(dig)
next_state = DIG_L;
else if(bump_left)
next_state = RIGHT;
else
next_state = LEFT;
end
RIGHT : begin
if(ground == 0)
next_state = FALL_R;
else if(dig)
next_state = DIG_R;
else if(bump_right)
next_state = LEFT;
else
next_state = RIGHT;
end
DIG_R :begin
if(ground)
next_state = DIG_R;
else
next_state = FALL_R;
end
FALL_R : begin
if(ground)
next_state = RIGHT;
else
next_state = FALL_R;
end
endcase
end
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
assign aaah = (state == FALL_L) | (state == FALL_R);
assign digging = (state == DIG_L) | (state == DIG_R);
endmodule
2.5.13 Lemmings 4 [Lemmings4]
问题描述
虽然旅鼠可以行走、坠落和挖掘,但它也不是无敌的,如果他坠落的太久然后接触到了地面,他可能会狗带。尤其是如果旅鼠坠落超过20个周期然后接触地面,它将会狗带,并将会停止步行、坠落、挖掘的行为(即全部的四个输出都为0),一直到FSM得到重置。旅鼠在落地前能坠落多少个周期是没有上限的,只有在撞到地面的时候才会狗带,在半空中的旅鼠是没事的。
扩展有限状态机来模拟这个行为。
状态转换图
代码
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
input dig,
output walk_left,
output walk_right,
output aaah,
output digging );
parameter FALL_L=0,DIG_L=1,LEFT=2,RIGHT=3,DIG_R=4,FALL_R=5,SPLAT=6;
reg [2:0] state,next_state;
reg [7:0] clkNum;
always@(posedge clk,posedge areset) begin
if(areset)
state <= LEFT;
else
state <= next_state;
end
always@(posedge clk) begin
if(ground)
clkNum <= 0;
else
clkNum <= clkNum + 1;
end
always@(*) begin
case(state)
FALL_L : begin
if(ground == 0)
next_state = FALL_L;
else if(clkNum>20)
next_state = SPLAT;
else
next_state = LEFT;
end
DIG_L : begin
if(ground)
next_state = DIG_L;
else
next_state = FALL_L;
end
LEFT : begin
if(ground == 0)
next_state = FALL_L;
else if(dig)
next_state = DIG_L;
else if(bump_left)
next_state = RIGHT;
else
next_state = LEFT;
end
RIGHT : begin
if(ground == 0)
next_state = FALL_R;
else if(dig)
next_state = DIG_R;
else if(bump_right)
next_state = LEFT;
else
next_state = RIGHT;
end
DIG_R :begin
if(ground)
next_state = DIG_R;
else
next_state = FALL_R;
end
FALL_R : begin
if(ground == 0)
next_state = FALL_R;
else if(clkNum>20)
next_state = SPLAT;
else
next_state = RIGHT;
end
SPLAT :
next_state = SPLAT;
endcase
end
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
assign aaah = (state == FALL_L) | (state == FALL_R);
assign digging = (state == DIG_L) | (state == DIG_R);
endmodule
这个系列主要是记录一下自己的学习过程和简单的思考过程,参考了许多他人的思路。题目均为HDLBits上的题目,借助翻译器与自己的理解组织了题目描述,如果有问题欢迎批评指正。