HDLBits中文版,标准参考答案 | 3.2.5 Finite State Machines | 有限状态机(1)
关注 望森FPGA 查看更多FPGA资讯
这是望森的第 16 期分享
作者 | 望森
来源 | 望森FPGA
目录
1 Simple FSM 1(asynchronous reset) | 简单 FSM 1(异步复位)
2 Simple FSM 1(synchronous reset) | 简单 FSM 1(同步复位)
3 Simple FSM 2(asynchronous reset) | 简单 FSM 2(异步复位)
4 Simple FSM 2(synchronous reset) | 简单 FSM 2(同步复位)
5 Simple state transitions 3 | 简单状态转换 3
6 Simple one-hot statetransitions 3 | 简单独热状态转换 3
7 Simple FSM 3(asynchronous reset) | 简单 FSM 3(异步复位)
8 Simple FSM 3(synchronous reset) | 简单 FSM 3(同步复位)
9 Design a Moore FSM | 设计 Moore FSM
本文中的代码都能够正常运行,请放心食用😋~
练习的官方网站是:https://hdlbits.01xz.net/
注:作者将每个练习的知识点都放在了题目和答案之后
1 Simple FSM 1(asynchronous reset) | 简单 FSM 1(异步复位)
题目:
这是一个 Moore 状态机,有两个状态,一个输入和一个输出。实现这个状态机。注意,reset 状态是 B。
提示:
是的,除了编写 FSM 之外还有其他方法可以做到这一点。但这不是本练习的重点。
这是 T 输入反转的 T 触发器。
答案:
我的答案:
module top_module(input clk,input areset, // Asynchronous reset to state Binput in,output out);// parameter A=0, B=1; reg state, next_state;wire A_2_B,B_2_A;always @(posedge clk, posedge areset) begin // This is a sequential always block// State flip-flops with asynchronous resetif(areset)beginstate <= B;endelse beginstate <= next_state;endendalways @(*) begin // This is a combinational always block// State transition logiccase(state)A : beginif (A_2_B)beginnext_state = B;endelse beginnext_state = state;endendB : beginif (B_2_A)beginnext_state = A;endelse beginnext_state = state;endenddefault next_state = B;endcaseendassign A_2_B = in == 0;assign B_2_A = in == 0;// Output logic// assign out = (state == ...);assign out = state;endmodule参考答案:
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@(*) begincase (state)A: next = in ? A : B;B: next = in ? B : A;endcaseend// Edge-triggered always block (DFFs) for state flip-flops. Asynchronous reset.always @(posedge clk, posedge areset) beginif (areset) state <= B; // Reset to state Belse state <= next; // Otherwise, cause the state to transitionend// 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
知识点:
我的状态机代码编写风格参考明德扬机构编写的《手把手教你学FPGA设计 —— 基于大道至简的至简设计法》,该书旨在以精简及流程化的方式完成Verilog代码编写,如果你是新手,应该能受到一些启发,推荐大家学习这本书。
2 Simple FSM 1(synchronous reset) | 简单 FSM 1(同步复位)
题目:
这是一个 Moore 状态机,有两个状态,一个输入和一个输出。实现这个状态机。注意,重置状态为 B。
此练习与 fsm1 相同,但使用同步重置。
提示:
是的,除了编写 FSM 之外还有其他方法可以做到这一点。但这不是本练习的重点。
这是 T 输入反转的 T 触发器。
答案:
我的答案:
// Note the Verilog-1995 module declaration syntax here:
module top_module(clk, reset, in, out);input clk;input reset; // Synchronous reset to state Binput in;output out;// reg out;// Fill in state name declarationsparameter A=0, B=1; reg present_state, next_state;wire A_2_B,B_2_A;always @(posedge clk) begin // This is a sequential always block// State flip-flops with asynchronous resetif(reset)beginpresent_state <= B;endelse beginpresent_state <= next_state;endendalways @(*) begin // This is a combinational always block// State transition logiccase(present_state)A : beginif (A_2_B)beginnext_state = B;endelse beginnext_state = present_state;endendB : beginif (B_2_A)beginnext_state = A;endelse beginnext_state = present_state;endenddefault next_state = B;endcaseendassign A_2_B = in == 0;assign B_2_A = in == 0;// Output logic// assign out = (state == ...);assign out = present_state;endmodule
3 Simple FSM 2(asynchronous reset) | 简单 FSM 2(异步复位)
题目:
这是一个 Moore 状态机,具有两个状态、两个输入和一个输出。实现此状态机。
此练习与 fsm2s 相同,但使用异步重置。
提示:
是的,除了编写 FSM 之外还有其他方法可以做到这一点。但这不是本练习的重点。
这是一个JK触发器。
答案:
我的答案:
module top_module(input clk,input areset, // Asynchronous reset to OFFinput j,input k,output out); // parameter OFF=0, ON=1; reg state, next_state;wire OFF_2_ON,ON_2_OFF;always @(posedge clk or posedge areset) begin // This is a sequential always block// State flip-flops with asynchronous resetif(areset)beginstate <= OFF;endelse beginstate <= next_state;endendalways @(*) begin // This is a combinational always block// State transition logiccase(state)OFF : beginif (OFF_2_ON)beginnext_state = ON;endelse beginnext_state = state;endendON : beginif (ON_2_OFF)beginnext_state = OFF;endelse beginnext_state = state;endenddefault next_state = OFF;endcaseendassign OFF_2_ON = j == 1;assign ON_2_OFF = k == 1;// Output logic// assign out = (state == ...);assign out = state;endmodule参考答案:
module top_module (input clk,input j,input k,input areset,output out
);parameter A=0, B=1;reg state;reg next;always_comb begincase (state)A: next = j ? B : A;B: next = k ? A : B;endcaseendalways @(posedge clk, posedge areset) beginif (areset) state <= A;else state <= next;endassign out = (state==B);endmodule
4 Simple FSM 2(synchronous reset) | 简单 FSM 2(同步复位)
题目:
这是一个 Moore 状态机,具有两个状态、两个输入和一个输出。实现此状态机。
此练习与 fsm2 相同,但使用同步复位。
提示:
是的,除了编写 FSM 之外还有其他方法可以做到这一点。但这不是本练习的重点。
这是一个 JK 触发器。
答案:
我的答案:
module top_module(input clk,input reset, // Synchronous reset to OFFinput j,input k,output out); // parameter OFF=0, ON=1; reg state, next_state;wire OFF_2_ON,ON_2_OFF;always @(posedge clk) begin // This is a sequential always block// State flip-flops with asynchronous resetif(reset)beginstate <= OFF;endelse beginstate <= next_state;endendalways @(*) begin // This is a combinational always block// State transition logiccase(state)OFF : beginif (OFF_2_ON)beginnext_state = ON;endelse beginnext_state = state;endendON : beginif (ON_2_OFF)beginnext_state = OFF;endelse beginnext_state = state;endenddefault next_state = OFF;endcaseendassign OFF_2_ON = j == 1;assign ON_2_OFF = k == 1;// Output logic// assign out = (state == ...);assign out = state;endmodule
5 Simple state transitions 3 | 简单状态转换 3
题目:
以下是具有一个输入、一个输出和四个状态的 Moore 状态机的状态转换表。使用以下状态编码:A=2'b00、B=2'b01、C=2'b10、D=2'b11。
仅为此状态机实现状态转换逻辑和输出逻辑(组合逻辑部分)。给定当前状态(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;wire A_2_A,A_2_B,B_2_B,B_2_C,C_2_A,C_2_D,D_2_C,D_2_B;always @(*) begin // This is a combinational always block// State transition logiccase(state)A : beginif (A_2_B)beginnext_state = B;endelse if (A_2_A)beginnext_state = A;endelse beginnext_state = state;endendB : beginif (B_2_C)beginnext_state = C;endelse if (B_2_B)beginnext_state = B;endelse beginnext_state = state;endendC : beginif (C_2_A)beginnext_state = A;endelse if (C_2_D)beginnext_state = D;endelse beginnext_state = state;endendD : beginif (D_2_C)beginnext_state = C;endelse if (D_2_B)beginnext_state = B;endelse beginnext_state = state;endenddefault next_state = state;endcaseendassign A_2_A = in == 0;assign A_2_B = in == 1;assign B_2_C = in == 0;assign B_2_B = in == 1;assign C_2_A = in == 0;assign C_2_D = in == 1;assign D_2_C = in == 0;assign D_2_B = in == 1;assign out = (state == D) ? 1'b1 : 1'b0;endmodule
6 Simple one-hot statetransitions 3 | 简单独热状态转换 3
题目:
以下是具有一个输入、一个输出和四个状态的 Moore 状态机的状态转换表。使用以下独热状态编码:A=4'b0001、B=4'b0010、C=4'b0100、D=4'b1000。
通过检查得出状态转换和输出逻辑方程,假设采用独热编码。仅为此状态机实现状态转换逻辑和输出逻辑(组合逻辑部分)。(测试台 testbench 将使用非独热输入进行测试,以确保您不会尝试执行更复杂的操作)。
答案:
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 == 0 | state[C] & in == 0);assign next_state[B] = (state[A] & in == 1 | state[B] & in == 1 | state[D] & in ==1);assign next_state[C] = (state[B] & in == 0 | state[D] & in == 0);assign next_state[D] = (state[C] & in == 1);// Output logic: assign out = (state[D]) ? 1'b1 : 1'b0;endmodule
知识点:
“通过检查得出方程”是什么意思?
独热状态机编码保证只有一个状态位为 1。这意味着可以通过仅检查一个状态位(而不是所有状态位)来确定状态机是否处于特定状态。这通过检查状态转换图中每个状态的传入边,得出状态转换的简单逻辑方程。
例如,在上面的状态机中,状态机如何达到状态 A?它必须使用两个传入边之一:“当前处于状态 A 并且 in=0”或“当前处于状态 C 并且 in = 0”。由于独热编码,用于测试“当前处于状态 A”的逻辑方程只是状态 A 的状态位。这得出状态位 A 的下一个状态的最终逻辑方程:next_state[0] = state[0]&(~in) | state[2]&(~in)。独热编码保证最多一个子句(乘积项)一次处于“活动”状态,因此这些子句只需进行“或”运算即可。
当练习要求“通过检查”得出状态转换方程时,请使用此特定方法。判决将使用非独热输入进行测试,以确保您的逻辑方程遵循此方法,而不是对状态位的非法(非独热)组合执行其他操作(例如重置 FSM)。
虽然了解此算法对于 RTL 级设计来说不是必需的(逻辑合成器会处理此问题),但它说明了为什么独热 FSM 通常具有更简单的逻辑(以牺牲更多状态位存储为代价),并且这个主题经常出现在数字逻辑课程的考试中。
7 Simple FSM 3(asynchronous reset) | 简单 FSM 3(异步复位)
题目:
以下是 Moore 状态机的状态转换表,该状态机具有一个输入、一个输出和四个状态。实现此状态机。包括将 FSM 重置为状态 A 的异步重置。
答案:
我的答案:
module top_module(input clk,input in,input areset,output out); //parameter A=4'b0001, B=4'b0010 ,C=4'b0100 ,D=4'b1000; reg [3:0] state, next_state;wire A2A,A2B,B2C,B2B,C2A,C2D,D2C,D2B;always @(posedge clk or posedge areset) begin // This is a sequential always block// State flip-flops with asynchronous resetif(areset)beginstate <= A;endelse beginstate <= next_state;endendalways @(*) begin // This is a combinational always block// State transition logiccase(state)A : beginif (A2A)beginnext_state = A;endelse if (A2B)beginnext_state = B;endelse beginnext_state = state;endendB : beginif (B2C)beginnext_state = C;endelse if (B2B)beginnext_state = B;endelse beginnext_state = state;endendC : beginif (C2A)beginnext_state = A;endelse if (C2D)beginnext_state = D;endelse beginnext_state = state;endendD : beginif (D2C)beginnext_state = C;endelse if (D2B)beginnext_state = B;endelse beginnext_state = state;endenddefault next_state = A;endcaseendassign A2A = in == 0;assign A2B = in == 1;assign B2C = in == 0;assign B2B = in == 1;assign C2A = in == 0;assign C2D = in == 1;assign D2C = in == 0;assign D2B = in == 1;// Output logic// assign out = (state == ...);assign out = (state == D) ? 1'b1 : 1'b0;endmodule参考答案:
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, C=2, D=3;reg [1:0] state; // Make sure state and next are big enough to hold the state encodings.reg [1:0] next;// 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@(*) begincase (state)A: next = in ? B : A;B: next = in ? B : C;C: next = in ? D : A;D: next = in ? B : C;endcaseend// Edge-triggered always block (DFFs) for state flip-flops. Asynchronous reset.always @(posedge clk, posedge areset) beginif (areset) state <= A;else state <= next;end// Combinational output logic. In this problem, an assign statement is the simplest. assign out = (state==D);endmodule
知识点:
提示:
8 Simple FSM 3(synchronous reset) | 简单 FSM 3(同步复位)
题目:
以下是 Moore 状态机的状态转换表,该状态机具有一个输入、一个输出和四个状态。实现此状态机。包括一个将 FSM 重置为状态 A 的同步重置。(这是与 Fsm3 相同的问题,但具有同步重置。)
答案:
我的答案:
module top_module(input clk,input in,input reset,output out); //parameter A=4'b0001, B=4'b0010 ,C=4'b0100 ,D=4'b1000; reg [3:0] state, next_state;wire A2A,A2B,B2C,B2B,C2A,C2D,D2C,D2B;always @(posedge clk) begin // This is a sequential always block// State flip-flops with asynchronous resetif(reset)beginstate <= A;endelse beginstate <= next_state;endendalways @(*) begin // This is a combinational always block// State transition logiccase(state)A : beginif (A2A)beginnext_state = A;endelse if (A2B)beginnext_state = B;endelse beginnext_state = state;endendB : beginif (B2C)beginnext_state = C;endelse if (B2B)beginnext_state = B;endelse beginnext_state = state;endendC : beginif (C2A)beginnext_state = A;endelse if (C2D)beginnext_state = D;endelse beginnext_state = state;endendD : beginif (D2C)beginnext_state = C;endelse if (D2B)beginnext_state = B;endelse beginnext_state = state;endenddefault next_state = A;endcaseendassign A2A = in == 0;assign A2B = in == 1;assign B2C = in == 0;assign B2B = in == 1;assign C2A = in == 0;assign C2D = in == 1;assign D2C = in == 0;assign D2B = in == 1;// Output logic// assign out = (state == ...);assign out = (state == D) ? 1'b1 : 1'b0;endmodule
知识点:
提示:
9 Design a Moore FSM | 设计 Moore FSM
题目:
大型水库为多个用户提供服务。为了保持水位足够高,三个传感器以 5 英寸的间隔垂直放置。
当水位高于最高传感器 (S3) 时,输入流量应为零。当水位低于最低传感器 (S1) 时,流量应为最大(标称流量阀和补充流量阀均打开)。当水位处于上部和下部传感器之间时,流量由两个因素决定:当前水位和上次传感器变化之前的水位。
每个水位都有一个与之相关的标称流量,如下表所示。如果传感器变化表明前一个水位低于当前水位,则应采用标称流量。如果前一个水位高于当前水位,则应通过打开补充流量阀(由 ΔFR 控制)来增加流量。绘制水库控制器的 Moore 模型状态图。清楚地指出每个状态的所有状态转换和输出。
FSM 的输入是 S1、S2 和 S3;输出是 FR1、FR2、FR3 和 ΔFR。
还包括一个高电平有效同步复位,可将状态机复位到相当于水位长时间处于低位的状态(无传感器置位,且所有四个输出置位)。
答案:
1.状态划分
S0 表示低于 S1;
S1 表示 S1 到 S2 之间;
S2 表示 S2 到 S3 之间;
S3 表示高于 S3;
2.状态转换图
2.代码
我的答案:
module top_module (input clk,input reset,input [3:1] s,output fr3,output fr2,output fr1,output dfr
); parameter S0=4'b0001, S1=4'b0010 ,S2=4'b0100 ,S3=4'b1000; reg [3:0] state, next_state;wire S02S0,S02S1,S12S0,S12S1,S12S2,S22S1,S22S2,S22S3,S32S3,S32S2;reg [3:0] out;always @(posedge clk) begin // This is a sequential always block// State flip-flops with asynchronous resetif(reset)beginstate <= S0;endelse beginstate <= next_state;endendalways @(*) begin // This is a combinational always block// State transition logiccase(state)S0 : beginif (S02S0)beginnext_state = S0;endelse if (S02S1)beginnext_state = S1;endelse beginnext_state = state;endendS1 : beginif (S12S0)beginnext_state = S0;endelse if (S12S1)beginnext_state = S1;endelse if (S12S2)beginnext_state = S2;endelse beginnext_state = state;endendS2 : beginif (S22S1)beginnext_state = S1;endelse if (S22S2)beginnext_state = S2;endelse if (S22S3)beginnext_state = S3;endelse beginnext_state = state;endendS3 : beginif (S32S3)beginnext_state = S3;endelse if (S32S2)beginnext_state = S2;endelse beginnext_state = state;endenddefault next_state = S0;endcaseendassign S02S0 = s == 3'b000;assign S02S1 = s == 3'b001;assign S12S0 = s == 3'b000;assign S12S1 = s == 3'b001;assign S12S2 = s == 3'b011;assign S22S1 = s == 3'b001;assign S22S2 = s == 3'b011;assign S22S3 = s == 3'b111;assign S32S3 = s == 3'b111;assign S32S2 = s == 3'b011;// Output logic// assign out = (state == ...);always @(posedge clk) begin // This is a combinational always block// State transition logicif(reset)begin{fr3,fr2,fr1,dfr} = 4'b1111;endelse begincase(state)S0 : beginif (s == 3'b000)begin{fr3,fr2,fr1,dfr} = 4'b1111;endelse if (s == 3'b001)begin{fr3,fr2,fr1,dfr} = 4'b0110;endendS1 : beginif (s == 3'b000)begin{fr3,fr2,fr1,dfr} = 4'b1111;endelse if (s == 3'b001)begin{fr3,fr2,fr1,dfr} = {3'b011,dfr};endelse if (s == 3'b011)begin{fr3,fr2,fr1,dfr} = 4'b0010;endendS2 : beginif (s == 3'b001)begin{fr3,fr2,fr1,dfr} = 4'b0111;endelse if (s == 3'b011)begin{fr3,fr2,fr1,dfr} = {3'b001,dfr};endelse if (s == 3'b111)begin{fr3,fr2,fr1,dfr} = 4'b0000;endendS3 : beginif (s == 3'b011)begin{fr3,fr2,fr1,dfr} = 4'b0011;endelse if (s == 3'b111)begin{fr3,fr2,fr1,dfr} = 4'b0000;endenddefault {fr3,fr2,fr1,dfr} = {fr3,fr2,fr1,dfr};endcaseendendendmodule参考答案:
module top_module (input clk,input reset,input [3:1] s,output reg fr3,output reg fr2,output reg fr1,output reg dfr
);// 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.// We have 6 states here.parameter A2=0, B1=1, B2=2, C1=3, C2=4, D1=5;reg [2:0] state, next; // Make sure these are big enough to hold the state encodings.// Edge-triggered always block (DFFs) for state flip-flops. Synchronous reset. always @(posedge clk) beginif (reset) state <= A2;else state <= next;end// 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@(*) begincase (state)A2: next = s[1] ? B1 : A2;B1: next = s[2] ? C1 : (s[1] ? B1 : A2);B2: next = s[2] ? C1 : (s[1] ? B2 : A2);C1: next = s[3] ? D1 : (s[2] ? C1 : B2);C2: next = s[3] ? D1 : (s[2] ? C2 : B2);D1: next = s[3] ? D1 : C2;default: next = 'x;endcaseend// Combinational output logic. In this problem, a procedural block (combinational always block) // is more convenient. Be careful not to create a latch.always@(*) begincase (state)A2: {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;D1: {fr3, fr2, fr1, dfr} = 4'b0000;default: {fr3, fr2, fr1, dfr} = 'x;endcaseendendmodule
- END -
公z号/CSDN搜索【望森FPGA】,查看更多FPGA资讯~
相关推荐文章,点击跳转:
望森FPGA的HDLBits合集