关注 望森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 B
input 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 reset
if(areset)begin
state <= B;
end
else begin
state <= next_state;
end
end
always @(*) begin // This is a combinational always block
// State transition logic
case(state)
A : begin
if (A_2_B)begin
next_state = B;
end
else begin
next_state = state;
end
end
B : begin
if (B_2_A)begin
next_state = A;
end
else begin
next_state = state;
end
end
default next_state = B;
endcase
end
assign 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@(*) 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
知识点:
我的状态机代码编写风格参考明德扬机构编写的《手把手教你学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 B
input in;
output out;//
reg out;
// Fill in state name declarations
parameter 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 reset
if(reset)begin
present_state <= B;
end
else begin
present_state <= next_state;
end
end
always @(*) begin // This is a combinational always block
// State transition logic
case(present_state)
A : begin
if (A_2_B)begin
next_state = B;
end
else begin
next_state = present_state;
end
end
B : begin
if (B_2_A)begin
next_state = A;
end
else begin
next_state = present_state;
end
end
default next_state = B;
endcase
end
assign 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 OFF
input 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 reset
if(areset)begin
state <= OFF;
end
else begin
state <= next_state;
end
end
always @(*) begin // This is a combinational always block
// State transition logic
case(state)
OFF : begin
if (OFF_2_ON)begin
next_state = ON;
end
else begin
next_state = state;
end
end
ON : begin
if (ON_2_OFF)begin
next_state = OFF;
end
else begin
next_state = state;
end
end
default next_state = OFF;
endcase
end
assign 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 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
4 Simple FSM 2(synchronous reset) | 简单 FSM 2(同步复位)
题目:
这是一个 Moore 状态机,具有两个状态、两个输入和一个输出。实现此状态机。
此练习与 fsm2 相同,但使用同步复位。
提示:
是的,除了编写 FSM 之外还有其他方法可以做到这一点。但这不是本练习的重点。
这是一个 JK 触发器。
答案:
我的答案:
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;
wire OFF_2_ON,ON_2_OFF;
always @(posedge clk) begin // This is a sequential always block
// State flip-flops with asynchronous reset
if(reset)begin
state <= OFF;
end
else begin
state <= next_state;
end
end
always @(*) begin // This is a combinational always block
// State transition logic
case(state)
OFF : begin
if (OFF_2_ON)begin
next_state = ON;
end
else begin
next_state = state;
end
end
ON : begin
if (ON_2_OFF)begin
next_state = OFF;
end
else begin
next_state = state;
end
end
default next_state = OFF;
endcase
end
assign 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 logic
case(state)
A : begin
if (A_2_B)begin
next_state = B;
end
else if (A_2_A)begin
next_state = A;
end
else begin
next_state = state;
end
end
B : begin
if (B_2_C)begin
next_state = C;
end
else if (B_2_B)begin
next_state = B;
end
else begin
next_state = state;
end
end
C : begin
if (C_2_A)begin
next_state = A;
end
else if (C_2_D)begin
next_state = D;
end
else begin
next_state = state;
end
end
D : begin
if (D_2_C)begin
next_state = C;
end
else if (D_2_B)begin
next_state = B;
end
else begin
next_state = state;
end
end
default next_state = state;
endcase
end
assign 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 reset
if(areset)begin
state <= A;
end
else begin
state <= next_state;
end
end
always @(*) begin // This is a combinational always block
// State transition logic
case(state)
A : begin
if (A2A)begin
next_state = A;
end
else if (A2B)begin
next_state = B;
end
else begin
next_state = state;
end
end
B : begin
if (B2C)begin
next_state = C;
end
else if (B2B)begin
next_state = B;
end
else begin
next_state = state;
end
end
C : begin
if (C2A)begin
next_state = A;
end
else if (C2D)begin
next_state = D;
end
else begin
next_state = state;
end
end
D : begin
if (D2C)begin
next_state = C;
end
else if (D2B)begin
next_state = B;
end
else begin
next_state = state;
end
end
default next_state = A;
endcase
end
assign 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@(*) 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
// Edge-triggered always block (DFFs) for state flip-flops. Asynchronous reset.
always @(posedge clk, posedge areset) begin
if (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 reset
if(reset)begin
state <= A;
end
else begin
state <= next_state;
end
end
always @(*) begin // This is a combinational always block
// State transition logic
case(state)
A : begin
if (A2A)begin
next_state = A;
end
else if (A2B)begin
next_state = B;
end
else begin
next_state = state;
end
end
B : begin
if (B2C)begin
next_state = C;
end
else if (B2B)begin
next_state = B;
end
else begin
next_state = state;
end
end
C : begin
if (C2A)begin
next_state = A;
end
else if (C2D)begin
next_state = D;
end
else begin
next_state = state;
end
end
D : begin
if (D2C)begin
next_state = C;
end
else if (D2B)begin
next_state = B;
end
else begin
next_state = state;
end
end
default next_state = A;
endcase
end
assign 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 reset
if(reset)begin
state <= S0;
end
else begin
state <= next_state;
end
end
always @(*) begin // This is a combinational always block
// State transition logic
case(state)
S0 : begin
if (S02S0)begin
next_state = S0;
end
else if (S02S1)begin
next_state = S1;
end
else begin
next_state = state;
end
end
S1 : begin
if (S12S0)begin
next_state = S0;
end
else if (S12S1)begin
next_state = S1;
end
else if (S12S2)begin
next_state = S2;
end
else begin
next_state = state;
end
end
S2 : begin
if (S22S1)begin
next_state = S1;
end
else if (S22S2)begin
next_state = S2;
end
else if (S22S3)begin
next_state = S3;
end
else begin
next_state = state;
end
end
S3 : begin
if (S32S3)begin
next_state = S3;
end
else if (S32S2)begin
next_state = S2;
end
else begin
next_state = state;
end
end
default next_state = S0;
endcase
end
assign 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 logic
if(reset)begin
{fr3,fr2,fr1,dfr} = 4'b1111;
end
else begin
case(state)
S0 : begin
if (s == 3'b000)begin
{fr3,fr2,fr1,dfr} = 4'b1111;
end
else if (s == 3'b001)begin
{fr3,fr2,fr1,dfr} = 4'b0110;
end
end
S1 : begin
if (s == 3'b000)begin
{fr3,fr2,fr1,dfr} = 4'b1111;
end
else if (s == 3'b001)begin
{fr3,fr2,fr1,dfr} = {3'b011,dfr};
end
else if (s == 3'b011)begin
{fr3,fr2,fr1,dfr} = 4'b0010;
end
end
S2 : begin
if (s == 3'b001)begin
{fr3,fr2,fr1,dfr} = 4'b0111;
end
else if (s == 3'b011)begin
{fr3,fr2,fr1,dfr} = {3'b001,dfr};
end
else if (s == 3'b111)begin
{fr3,fr2,fr1,dfr} = 4'b0000;
end
end
S3 : begin
if (s == 3'b011)begin
{fr3,fr2,fr1,dfr} = 4'b0011;
end
else if (s == 3'b111)begin
{fr3,fr2,fr1,dfr} = 4'b0000;
end
end
default {fr3,fr2,fr1,dfr} = {fr3,fr2,fr1,dfr};
endcase
end
end
endmodule
参考答案:
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) begin
if (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@(*) begin
case (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;
endcase
end
// Combinational output logic. In this problem, a procedural block (combinational always block)
// is more convenient. Be careful not to create a latch.
always@(*) begin
case (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;
endcase
end
endmodule
- END -
公z号/CSDN搜索【望森FPGA】,查看更多FPGA资讯~
相关推荐文章,点击跳转: