1 简单的状态机
这是一个Moore型状态机,有两个状态,一个输入,一个输出。实现此状态机。注意重置状态是B。
solution:
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
case (state)
B: if (in) next_state = B;
else next_state = A;
A: if (in) next_state = A;
else next_state = B;
endcase
end
always @(posedge clk, posedge areset) begin // This is a sequential always block
if (areset) // State flip-flops with asynchronous reset
state <= B;
else begin
state <= next_state;
end
end
// Output logic
// assign out = (state == ...);
assign out = (state == B) ? 1 : 0;
endmodule
official solution:
module top_module (
input clk,
input in,
input areset,
output out
);
// Give state names and assignments. I'm lazy, so I like to use decimal numbers.
// It doesn't really matter what assignment is used, as long as they're unique.
parameter A=0, B=1;
reg state; // Ensure state and next are big enough to hold the state encoding.
reg next;
// A finite state machine is usually coded in three parts:
// State transition logic
// State flip-flops
// Output logic
// It is sometimes possible to combine one or more of these blobs of code
// together, but be careful: Some blobs are combinational circuits, while some
// are clocked (DFFs).
// Combinational always block for state transition logic. Given the current state and inputs,
// what should be next state be?
// Combinational always block: Use blocking assignments.
always@(*) begin
case (state)
A: next = in ? A : B;
B: next = in ? B : A;
endcase
end
// Edge-triggered always block (DFFs) for state flip-flops. Asynchronous reset.
always @(posedge clk, posedge areset) begin
if (areset) state <= B; // Reset to state B
else state <= next; // Otherwise, cause the state to transition
end
// Combinational output logic. In this problem, an assign statement is the simplest.
// In more complex circuits, a combinational always block may be more suitable.
assign out = (state==B);
endmodule
这是一个Moore型状态机,有两个状态,两个输入,一个输出。实现此状态机。使用异步重置。
module top_module (
input clk,
input j,
input k,
input areset,
output out
);
parameter A=0, B=1;
reg state;
reg next;
always_comb begin
case (state)
A: next = j ? B : A;
B: next = k ? A : B;
endcase
end
always @(posedge clk, posedge areset) begin
if (areset) state <= A;
else state <= next;
end
assign out = (state==B);
endmodule
2 简单的状态机----状态转换表
下面是Moore型状态机的状态转换表,它有一个输入、一个输出和四个状态。使用以下状态编码:A=2’b00, B=2’b01,C=2’b10, D=2’b11。
仅实现此状态机的状态转换逻辑和输出逻辑(组合逻辑部分)。给定当前状态(state),根据状态转换表计算next_state和output (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);
endmodule
以下是具有一个输入,一个输出和四个状态的Moore状态机的状态转换表。 使用以下独热状态编码:
A = 4’b0001,B = 4’b0010,C = 4’b0100,D = 4’b1000。
通过假设独热码编码的检查推导出状态转换和输出逻辑方程式。 为此状态机仅实现状态转换逻辑和输出逻辑(组合逻辑部分)。(测试台将使用非独热输入进行测试,以确保你没有尝试做更复杂的事情)。
“通过检查推导出方程”是什么意思?
独热状态机编码可确保一个状态位恰好为1。这意味着可以通过仅检查一个状态位而不检查所有状态位来确定状态机是否处于特定状态。通过检查状态转换图中每个状态的输入边缘,可以得出用于状态转换的简单逻辑方程式。
例如,在上述状态机中,状态机如何达到状态A?
它必须使用两个输入边缘之一:“当前处于状态A,in = 0”或“当前处于状态C,in = 0”。由于采用独热编码,因此测试“当前处于状态A”的逻辑方程只是状态A的状态位。这导致了状态位A的下一个状态的最终逻辑方程:next_state [0] =state[0]&(〜in) | state[2]&(〜in)。独热编码可确保一次最多有一个子句(乘积项)处于“active”状态,因此可以将这些子句进行“或”运算。
当练习“通过检查”要求状态转换方程式时,请使用此特定方法。评判系统将使用非独热输入进行测试,以确保你的逻辑方程式遵循此方法,而不是对状态位的非法(非独热编码)组合进行其他操作(例如,重置FSM)。
尽管知道此算法对于RTL级设计不是必需的(逻辑合成器可以解决这个问题),但它说明了为什么独热FSM常常具有更简单的逻辑(以增加状态位存储为代价),并且该主题经常出现数字逻辑课程的考试中。
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]∈
assign next_state[C] = state[B]&~in | state[D]&~in;
assign next_state[D] = state[C]∈
// Output logic:
assign out = (state[D]);
endmodule
以下是具有一个输入,一个输出和四个状态的Moore型状态机的状态转换表。 实现此状态机。 包括一个异步重置,将FSM重置为状态A。
module top_module(
input clk,
input in,
input areset,
output out); //
// State transition logic
reg [3:0] state;
reg [3:0] next;
parameter A=4'b0001,B=4'b0010,C=4'b0100,D=4'b1000;
always @(*) begin
case(state)
A: next = (in) ? B : A;
B: next = (in) ? B : C;
C: next = (in) ? D : A;
D: next = (in) ? B : C;
endcase
end
// State flip-flops with asynchronous reset
always @(posedge clk or posedge areset) begin
if (areset)
state <= A;
else
state <= next;
end
// Output logic
assign out = (state==D);
endmodule
3 简单的状态机----应用
🌟
大型水库可为多个用户提供服务。为了使水位足够高,三个传感器以5英寸的间隔垂直放置。
当水位高于最高传感器(S3)时,输入流量应为零。
当液位低于最低传感器(S1)时,流量应最大(标称流量阀和辅助流量阀均打开)。
当水位在上下传感器之间时,流量由两个因素决定:水位和最后一个传感器之前的水位发生变化。每种水位都有一个与之相关的标称流速,如下表所示。
如果传感器变化表明先前的液位低于当前的液位,则应进行标称流速。
如果先前的水位高于当前的水位,则应通过打开辅助流量阀(由AFR控制)来增加流量。
绘制水库控制器的Moore型状态图。清楚指出每个状态的所有状态转换和输出。 FSM的输入为S1,S2和S3。输出为FR1,FR2,FR3和dFR。
还包括一个高电平有效的同步复位,该复位将状态机复位到与水位已长时间处于低水平(未声明任何传感器,但是声明了所有四个输出)。
这道题关键在于怎么理解这个输入,题中说了未声明任何传感器,不妨将这里的输入s理解为水位变化的指令。
再结合题意,如果传感器变化表明先前的液位低于当前的液位,则应进行标称流速。
如果先前的水位高于当前的水位,则应通过打开辅助流量阀(由AFR控制)来增加流量。
我们知道一共三个传感器,那么从超低水位到超高水位,再到超低水位,从输出的角度来看,我们将一共经历六种状态:
- A:超低水位(s1传感器之下)
- B1:由A上升到了s1和s2传感器之间的一个水位
- B2:由C2或C1下降到s1和s2传感器之间的一个水位
- C1:由B1或B2上升到s2和s3传感器之间的一个水位
- C2:由D下降到s2和s3传感器之间的一个水位
- D:最高水位(s3传感器之上)
solution:
module top_module (
input clk,
input reset,
input [3:1] s,
output fr3,
output fr2,
output fr1,
output dfr
);
parameter A=0,B1=1,B2=2,C1=3,C2=4,D=5;
reg [2:0] state;
reg [2:0] next;
// Edge-triggered always block (DFFs) for state flip-flops.
always @(posedge clk) begin
if(reset)
state <= A;
else
state <= next;
end
// what should be next state be?
always @(*) begin
case(state)
A : next = s[1] ? B1 : A;
B1: next = s[2] ? C1 : (s[1] ? B1 : A);
B2: next = s[2] ? C1 : (s[1] ? B2 : A);
C1: next = s[3] ? D : (s[2] ? C1 : B2);
C2: next = s[3] ? D : (s[2] ? C2 : B2);
D : next = s[3] ? D : C2;
default: next = state;
endcase
end
// Output logic:
always @(*) begin
case(state)
A : {fr3,fr2,fr1,dfr} = 4'b1111;
B1: {fr3,fr2,fr1,dfr} = 4'b0110;
B2: {fr3,fr2,fr1,dfr} = 4'b0111;
C1: {fr3,fr2,fr1,dfr} = 4'b0010;
C2: {fr3,fr2,fr1,dfr} = 4'b0011;
D : {fr3,fr2,fr1,dfr} = 4'b0000;
default:{fr3,fr2,fr1,dfr} <= 4'b0000;
endcase
end
endmodule
由这道题可以知道,状态机的三段式写法中,每一个时钟沿产生一次可能的状态变化的写法基本是用时序逻辑电路书写,而产生下一状态的变化以及产生输出的变化基本是由组合逻辑电路书写。