目录
HDLBits 刷题来到了最为重要的一部分---有限状态机,都说 Verilog 设计的精髓就是状态机的设计,可见状态机设计的重要性,通过三十多道的状态机的练习,可以更加熟悉状态机设计的要点,通常都设计为三段式,这样设计的状态机层次清晰且易于设计,时序上更为易懂。以下的解题方法不一定为最佳解决方案,有更好的方法欢迎提出,共同学习,共同进步!
给定如下所示的状态分配表,实现逻辑函数 Y[0] 和 z。
- module top_module (
- input clk,
- input [2:0] y,
- input x,
- output Y0,
- output z
- );
-
- //状态申明
- parameter A = 3'b000;
- parameter B = 3'b001;
- parameter C = 3'b010;
- parameter D = 3'b011;
- parameter E = 3'b100;
-
- reg [2:0] state;
-
-
- always @(*) begin
- case(y)
- A: begin
- if (x) begin
- state = B;
- end
- else begin
- state = A;
- end
- end
- B: begin
- if (x) begin
- state = E;
- end
- else begin
- state = B;
- end
- end
- C: begin
- if (x) begin
- state = B;
- end
- else begin
- state = C;
- end
- end
- D: begin
- if (x) begin
- state = C;
- end
- else begin
- state = B;
- end
- end
- E: begin
- if (x) begin
- state = E;
- end
- else begin
- state = D;
- end
- end
- default: begin
- state = A;
- end
- endcase
- end
-
- //状态机第三段,结果输出,组合逻辑
- assign Y0 = state[0];
- assign z = (y==D) || (y==E);
-
- endmodule
考虑下面显示的状态机,它有一个输入 w 和一个输出 z。
希望使用三个触发器和状态代码 y[3:1] = 000, 001, ..., 101 分别用于状态 A、B、...、F 来实现 FSM。显示此 FSM 的状态分配表。推导触发器 y[2] 的下一个状态表达式。只实现 y[2] 的下一个状态逻辑。
- module top_module (
- input [3:1] y,
- input w,
- output Y2
- );
-
- //状态定义
- parameter A = 3'b000;
- parameter B = 3'b001;
- parameter C = 3'b010;
- parameter D = 3'b011;
- parameter E = 3'b100;
- parameter F = 3'b101;
-
- reg [3:1] next_state;
-
- always @(*) begin
- case(y[3:1])
- A: begin
- if (w) begin
- next_state = A;
- end
- else begin
- next_state = B;
- end
- end
- B: begin
- if (w) begin
- next_state = D;
- end
- else begin
- next_state = C;
- end
- end
- C: begin
- if (w) begin
- next_state = D;
- end
- else begin
- next_state = E;
- end
- end
- D: begin
- if (w) begin
- next_state = A;
- end
- else begin
- next_state = F;
- end
- end
- E: begin
- if (w) begin
- next_state = D;
- end
- else begin
- next_state = E;
- end
- end
- F: begin
- if (w) begin
- next_state = D;
- end
- else begin
- next_state = C;
- end
- end
- default: begin
- next_state = A;
- end
- endcase
- end
-
- assign Y2 = next_state[2];
-
- endmodule
考虑下面显示的状态机,它有一个输入 w 和一个输出 z。
对于此部分,假设一个单热代码分别与状态赋值 'y[6:1] = 000001, 000010, 000100, 001000, 010000, 100000,...,, 100000 一起使用。
为下一状态信号 Y2 和 Y4 编写逻辑表达式。(通过假设独热编码的检查来推导逻辑方程。测试平台将使用非独热输入进行测试,以确保您不会尝试执行更复杂的操作)。
- module top_module (
- input [6:1] y,
- input w,
- output Y2,
- output Y4
- );
-
- assign Y2 = ~w & y[1];
- assign Y4 = (w&y[2]) | (w&y[3]) | (w&y[5]) | (w&y[6]);
-
- endmodule
考虑下面显示的状态机,它有一个输入 w 和一个输出 z。
- module top_module (
- input clk,
- input reset, // synchronous reset
- input w,
- output z
- );
-
- //状态申明
- parameter A = 6'b000001;
- parameter B = 6'b000010;
- parameter C = 6'b000100;
- parameter D = 6'b001000;
- parameter E = 6'b010000;
- parameter F = 6'b100000;
-
- //定义现态和次态
- reg [5:0] state;
- reg [5:0] next_state;
-
- //状态机第一段,状态初始化,时序逻辑非阻塞赋值
- always @(posedge clk) begin
- if (reset) begin
- state <= A;
- end
- else begin
- state <= next_state;
- end
- end
-
- //状态机第二段,状态跳转,阻塞赋值
- always @(*) begin
- next_state = state;
- case(state)
- A: begin
- if (w) begin
- next_state = A;
- end
- else begin
- next_state = B;
- end
- end
- B: begin
- if (w) begin
- next_state = D;
- end
- else begin
- next_state = C;
- end
- end
- C: begin
- if (w) begin
- next_state = D;
- end
- else begin
- next_state = E;
- end
- end
- D: begin
- if (w) begin
- next_state = A;
- end
- else begin
- next_state = F;
- end
- end
- E: begin
- if (w) begin
- next_state = D;
- end
- else begin
- next_state = E;
- end
- end
- F: begin
- if (w) begin
- next_state = D;
- end
- else begin
- next_state = C;
- end
- end
- endcase
- end
-
- //状态机第三段,结果输出,组合逻辑
- assign z = (state==E | state==F);
-
- endmodule
编写表示此 FSM 的完整 Verilog 代码。对状态表和状态触发器使用单独的 always 块。描述 FSM 输出,称为 z,使用连续赋值语句或 always 块。
- module top_module (
- input clk,
- input reset, // Synchronous active-high reset
- input w,
- output z
- );
-
- //状态申明
- parameter A = 6'b000001;
- parameter B = 6'b000010;
- parameter C = 6'b000100;
- parameter D = 6'b001000;
- parameter E = 6'b010000;
- parameter F = 6'b100000;
-
- //定义现态和次态
- reg [5:0] state;
- reg [5:0] next_state;
-
- //状态机第一段,状态初始化,时序逻辑非阻塞赋值
- always @(posedge clk) begin
- if (reset) begin
- state <= A;
- end
- else begin
- state <= next_state;
- end
- end
-
- //状态机第二段,状态跳转,阻塞赋值
- always @(*) begin
- next_state = state;
- case(state)
- A: begin
- if (w) begin
- next_state = B;
- end
- else begin
- next_state = A;
- end
- end
- B: begin
- if (w) begin
- next_state = C;
- end
- else begin
- next_state = D;
- end
- end
- C: begin
- if (w) begin
- next_state = E;
- end
- else begin
- next_state = D;
- end
- end
- D: begin
- if (w) begin
- next_state = F;
- end
- else begin
- next_state = A;
- end
- end
- E: begin
- if (w) begin
- next_state = E;
- end
- else begin
- next_state = D;
- end
- end
- F: begin
- if (w) begin
- next_state = C;
- end
- else begin
- next_state = D;
- end
- end
- default: begin
- next_state = A;
- end
- endcase
- end
-
- //状态机第三段,结果输出,组合逻辑
- assign z = (state==E | state==F);
-
- endmodule
假设一个独热代码与状态赋值 y[5:0] = 000001(A)、 000010(B)、 000100(C)、 001000(D)、 010000(E)、 100000(F)
为信号Y1编写一个逻辑表达式,它是状态触发器y[1]的输入。
为信号Y3编写一个逻辑表达式,它是状态触发器y[3]的输入。
(通过假设一个热编码的检查来推导逻辑方程。测试平台将使用非一个热输入进行测试,以确保您不会尝试执行更复杂的操作)。
此 FSM 充当仲裁器电路,通过三个请求设备控制对某种类型资源的访问。每个设备通过设置信号 r[i] = 1 来请求资源,其中 r[i] 为 r[1]、r[2] 或 r[3]。每个 r[i] 是 FSM 的输入信号,代表三个器件之一。只要没有请求,FSM 就会保持在状态 A 中。当发生一个或多个请求时,FSM 决定哪个设备接收使用资源的授权,并更改为将该设备的 g[i] 信号设置为 1 的状态。每个 g[i] 都是 FSM 的一个输出。有一个优先级系统,因为设备 1 的优先级高于设备 2,设备 3 的优先级最低。因此,例如,仅当设备 3 是 FSM 处于状态 A 时发出请求的唯一设备时,它才会收到授权。一旦设备 i 被 FSM 授予授权,只要其请求 r[i] = 1,该设备就会继续接收授权。
编写表示此 FSM 的完整 Verilog 代码。对状态表和状态触发器使用单独的 always 块,就像在讲座中所做的那样。描述 FSM 输出 g[i],使用连续赋值语句或 always 块。
- module top_module (
- input clk,
- input resetn, // active-low synchronous reset
- input [3:1] r, // request
- output [3:1] g // grant
- );
-
- //状态定义
- parameter A = 4'b0001;
- parameter B = 4'b0010;
- parameter C = 4'b0100;
- parameter D = 4'b1000;
-
- //定义现态和次态
- reg [3:0] state;
- reg [3:0] next_state;
-
- //状态机第一段,状态初始化,时序逻辑非阻塞赋值
- always @(posedge clk) begin
- if (!resetn) begin
- state <= A;
- end
- else begin
- state <= next_state;
- end
- end
-
- //状态机第二段,状态跳转,非阻塞赋值
- always @(*) begin
- next_state = state;
- case(state)
- A: begin
- if (r[1]) begin
- next_state = B;
- end
- else if (~r[1] & r[2]) begin
- next_state = C;
- end
- else if (~r[1] & ~r[2] & r[3]) begin
- next_state = D;
- end
- else begin
- next_state = A;
- end
- end
- B: begin
- if (~r[1]) begin
- next_state = A;
- end
- else begin
- next_state = B;
- end
- end
- C: begin
- if (~r[2]) begin
- next_state = A;
- end
- else begin
- next_state = C;
- end
- end
- D: begin
- if (~r[3]) begin
- next_state = A;
- end
- else begin
- next_state = D;
- end
- end
- default: begin
- next_state = A;
- end
- endcase
- end
-
- //状态机第三段,结果输出,组合逻辑
- assign g[1] = state==B;
- assign g[2] = state==C;
- assign g[3] = state==D;
-
- endmodule
考虑一个用于控制某种类型电机的有限状态机。FSM具有来自电机的输入x和y,并产生控制电机的输出f和g。还有一个称为clk的时钟输入和一个称为resetn的复位输入。
密克罗尼西亚联邦必须按如下方式工作。只要置位复位输入,FSM 就会保持开始状态,称为状态 A。当复位信号被解除置位时,在下一个时钟边沿之后,FSM必须将输出f设置为1,持续一个时钟周期。然后,FSM 必须监视 x 输入。当 x 在三个连续的时钟周期中生成值 1, 0, 1 时,应在下一个时钟周期中将 g 设置为 1。在保持 g = 1 的同时,FSM 必须监视 y 输入。如果 y 在最多两个时钟周期内具有值 1,则 FSM 应永久保持 g = 1(即,直到重置)。但是,如果 y 在两个时钟周期内未变为 1,则 FSM 应永久设置 g = 0(直到重置)。
- module top_module (
- input clk,
- input resetn, // active-low synchronous reset
- input x,
- input y,
- output f,
- output g
- );
-
- //状态定义
-
- parameter START = 9'b000000001;
- parameter OUT_F = 9'b000000010;
- parameter X_1 = 9'b000000100;
- parameter X_2 = 9'b000001000;
- parameter X_3 = 9'b000010000;
- parameter OUT_G = 9'b000100000;
- parameter G_1 = 9'b001000000;
- parameter WAIT = 9'b010000000;
- parameter G_0 = 9'b100000000;
- //现态和次态
- reg [8:0] state;
- reg [8:0] next_state;
- //状态机第一段,状态初始化,时序逻辑非阻塞赋值
- always @(posedge clk) begin
- if (!resetn) begin
- state <= START;
- end
- else begin
- state <= next_state;
- end
- end
- //状态机第二段,状态跳转,阻塞赋值
- always @(*) begin
- next_state = state;
- case(state)
- START: begin
- next_state = OUT_F;
- end
- OUT_F: begin
- next_state = X_1;
- end
- X_1: begin
- if (x) begin
- next_state = X_2;
- end
- else begin
- next_state = X_1;
- end
- end
- X_2: begin
- if (x) begin
- next_state = X_2;
- end
- else begin
- next_state = X_3;
- end
- end
- X_3: begin
- if (x) begin
- next_state = OUT_G;
- end
- else begin
- next_state = X_1;
- end
- end
- OUT_G: begin
- if (y) begin
- next_state = G_1;
- end
- else begin
- next_state = WAIT;
- end
- end
- WAIT: begin
- if (y) begin
- next_state = G_1;
- end
- else begin
- next_state = G_0;
- end
- end
- G_1: begin
- next_state = G_1;
- end
- G_0: begin
- next_state = G_0;
- end
- default: begin
- next_state = START;
- end
- endcase
- end
- //状态机第三段,结果输出,组合逻辑
- assign f = state==OUT_F;
- assign g = (state==OUT_G) | (state==G_1) | (state==WAIT);
- endmodule