参考链接:HDLBits导学
Problem 138 Q8: Design a Mealy FSM
问题:实现一个Mealy类型的有限状态机,识别序列“101”,输入信号为x 。您的 FSM 应该有一个输出信号z,当检测到“101”序列时,该信号输出逻辑 1。您的 FSM 还应该有一个低电平有效的异步复位。您的状态机中可能只有 3 个状态。您的 FSM 应该识别重叠序列
解决:
module top_module (
input clk,
input aresetn, // Asynchronous active-low reset
input x,
output z );
parameter s0=0,s1=1,s2=2;
reg[1:0] state,next_state;
always @(*) begin
case(state)
s0: next_state = x ? s1 : s0;
s1: next_state = x ? s1 : s2;
s2: next_state = x ? s1 : s0;
endcase
end
always @(posedge clk,negedge aresetn) begin
if(!aresetn)
state <= s0;
else
state <= next_state;
end
assign z = (state==s2 && next_state==s1);
endmodule
注意:第一次写的时候我加了一个done状态,也就是四个状态,然后发现输出总是比参考答案晚一个时钟周期,然后怎么看时序图都感觉自己的那种写法是对的,后面又仔细看了一下才发现答案中输出不只是看当前状态,下一个状态也要考虑进去
然后百度了一下moore型和mealy型状态机有什么区别就明白了 (图片来源)
Problem 139 Q5a: Serial two's complementer (Moore FSM)
问题:您将设计一个单输入单输出串行 2进制 的补码摩尔状态机。输入 (x) 是从数字的最低有效位开始的一系列位(每个时钟周期一个),输出 (Z) 是输入的 2 进制补码。机器将接受任意长度的输入数字。该电路需要异步复位。当转换开始复位释放后,停止复位有效
思路:详细解释参考上面的链接
解决:
module top_module (
input clk,
input areset,
input x,
output z
);
parameter S0=0,S1=1,Done=2;
reg[1:0] state,next_state;
always @(*) begin
case(state)
S0: next_state = x ? Done : S0;
S1: next_state = x ? S1 : Done;
Done: next_state = x ? S1 : Done;
endcase
end
always @(posedge clk,posedge areset) begin
if(areset)
state <= S0;
else
state <= next_state;
end
assign z = (state==Done);
endmodule
注意:moore型,输出只看当前状态
Problem 140 Serial two's complementer (Mealy FSM)
问题:这个题和上一个题一样,都是实现二进制补码的输出,只是状态机使用mealy型
状态转换图:
解决:
module top_module (
input clk,
input areset,
input x,
output z
);
parameter S0=0,S1=1;
reg[1:0] state,next_state;
always @(*) begin
case(state)
S0: next_state = x ? S1 : S0;
S1: next_state = S1;
endcase
end
always @(posedge clk,posedge areset) begin
if(areset)
state <= S0;
else
state <= next_state;
end
assign z = ((next_state == S1 && ~x) || (state == S0 && next_state==S1));
endmodule
三状态写法(能通过 但不符合题意)
module top_module (
input clk,
input areset,
input x,
output z
);
parameter S0=0,S1=1,Done=2;
reg[1:0] state,next_state;
always @(*) begin
case(state)
S0: next_state = x ? Done : S0;
S1: next_state = x ? S1 : Done;
Done: next_state = x ? S1 : Done;
endcase
end
always @(posedge clk,posedge areset) begin
if(areset)
state <= S0;
else
state <= next_state;
end
assign z = (next_state==Done);
endmodule
和上一个题几乎一样的代码,只是最后的输出使用了下一个状态
Problem 141 Q3a:FSM
问题:下面是状态转换图
当输入s为0的时候一直处在状态A中,当s为1则进入B状态,一旦进入B状态,则检测接下来的三个时钟周期中w的输入,如果三个时钟周期内刚好两个周期w都是高电平,则输出高电平,否则输出低电平。然后持续检测接下来的三个时钟周期w的输入。
解决:
module top_module (
input clk,
input reset, // Synchronous reset
input s,
input w,
output z
);
parameter A=0,B=1;
reg[1:0] state,next_state;
reg[1:0] cnt;
reg[2:0] one;
always @(*) begin
case(state)
A: next_state = s ? B : A;
B: next_state = B;
endcase
end
always @(posedge clk) begin
if(reset)
state <= A;
else
state <= next_state;
end
always @(posedge clk) begin
if(reset)
cnt <= 2'd0;
else begin
if(state==B) begin
if(cnt<2'd3) begin
one[cnt] = w ? 1'b1 : 1'b0;
cnt <= cnt + 1'b1;
end
else begin
one[0] = w ? 1'b1 : 1'b0;
cnt <= 2'd1;
end
end
else
cnt <= 2'd0;
end
end
assign z = (cnt==2'd3&&(one[0]+one[1]+one[2])==2'd2);
endmodule
这种写法其实是参考了下面这种多状态的写法(我是先写了下面这种多状态机才想起来如何改良上面的代码的,刚开始怎么写都是错的),只是状态机变成了使用计数器,cnt3就和下面的done状态很像,多出来用来输出。
module top_module (
input clk,
input reset, // Synchronous reset
input s,
input w,
output z
);
parameter A=0,B1=1,B2=2,B3=3,Done=4;
reg[2:0] state,next_state;
reg[2:0] one;
always @(*) begin
case(state)
A: next_state = s ? B1 : A;
B1: next_state = B2;
B2: next_state = B3;
B3: next_state = Done;
Done: next_state = B2;//这里其实就相当于B1
endcase
end
always @(posedge clk) begin
if(reset)
state <= A;
else
state <= next_state;
end
always @(posedge clk) begin
if(reset)
one <= 3'd0;
else begin
case(state)//保存每一位的值
B1: one[0] = w ? 1'b1 : 1'b0;
B2: one[1] = w ? 1'b1 : 1'b0;
B3: one[2] = w ? 1'b1 : 1'b0;
Done: one[0] = w ? 1'b1 : 1'b0;
endcase
end
end
assign z = (state==Done&&(one[0]+one[1]+one[2]==2'd2));
endmodule
写得有点笨,用了好几个状态才写出来
Problem 142 Q3b:FSM
问题:给定下面状态转换表,实现有限状态机。复位应将 FSM 复位为状态 000
解决:
module top_module (
input clk,
input reset, // Synchronous reset
input x,
output z
);
parameter S0=3'b000,S1=3'b001,S2=3'b010,S3=3'b011,S4=3'b100;
reg[2:0] state,next_state;
always @(*) begin
case(state)
S0: next_state = x ? S1 : S0;
S1: next_state = x ? S4 : S1;
S2: next_state = x ? S1 : S2;
S3: next_state = x ? S2 : S1;
S4: next_state = x ? S4 : S3;
endcase
end
always @(posedge clk) begin
if(reset)
state <= S0;
else
state <= next_state;
end
assign z = (state == S3 || state == S4);
endmodule
Problem 143 Q3c:FSM logic
问题:给定如下图所示的状态转换表,实现逻辑函数 Y[0] 和 z
状态转换图和上一个题是一样的,而且只需要实现组合逻辑
解决:
module top_module (
input clk,
input [2:0] y,
input x,
output Y0,
output z
);
parameter S0=3'b000,S1=3'b001,S2=3'b010,S3=3'b011,S4=3'b100;
reg[2:0] next_state;
always @(*) begin
case(y)
S0: next_state = x ? S1 : S0;
S1: next_state = x ? S4 : S1;
S2: next_state = x ? S1 : S2;
S3: next_state = x ? S2 : S1;
S4: next_state = x ? S4 : S3;
endcase
end
assign Y0 = next_state[0];
assign z = (y >= S3);
endmodule
Problem 144 Q6b:FSM next-state logic
问题:考虑下面显示的状态机,它有一个输入w和一个输出z
假设您希望使用三个触发器和状态代码y[3:1] = 000, 001, ... , 101 分别为状态 A、B、...、F实现 FSM 。显示此 FSM 的状态分配表。推导出触发器y[2]的下一个状态表达式。
仅实现y[2]的下一个状态逻辑。(这更像是 FSM 问题而不是 Verilog 编码问题)
解决:
module top_module (
input [3:1] y,
input w,
output Y2);
parameter A=3'b000,B=3'b001,C=3'b010,D=3'b011,E=3'b100,F=3'b101;
reg[2:0] next_state;
always @(*) begin
case(y)
A: next_state = w ? A : B;
B: next_state = w ? D : C;
C: next_state = w ? D : E;
D: next_state = w ? A : F;
E: next_state = w ? D : E;
F: next_state = w ? D : C;
endcase
end
assign Y2 = next_state[1];
endmodule
Problem 145 Q6c FSM one-hot next-state logic
问题:这个题的状态转换图和上一个一样,但是这一次的状态编码采用独热码,然后输出Y2和Y4的次态方程
解决:
module top_module (
input [6:1] y,
input w,
output Y2,
output Y4);
parameter A=3'd1,B=3'd2,C=3'd3,D=3'd4,E=3'd5,F=3'd6;
reg[6:1] next_state;
assign next_state[A] = (y[D]&w) || (y[A]&w);
assign next_state[B] = (y[A]&~w);
assign next_state[C] = (y[B]&~w) || (y[F]&~w);
assign next_state[D] = (y[E]&w) || (y[F]&w) || (y[B]&w) || (y[C]&w);
assign next_state[E] = (y[C]&~w) || (y[E]&~w);
assign next_state[F] = (y[D]&~w);
assign Y2 = next_state[2];
assign Y4 = next_state[4];
endmodule
Problem 146 Q6 FSM
问题:本题的状态转移图和上一题相同,但此题需要实现一个完整的状态机,并根据图中的标识产生正确的输出 z
解决:
module top_module (
input clk,
input reset, // synchronous reset
input w,
output z);
parameter A=3'b000,B=3'b001,C=3'b010,D=3'b011,E=3'b100,F=3'b101;
reg[2:0] state,next_state;
always @(*) begin
case(state)
A: next_state = w ? A : B;
B: next_state = w ? D : C;
C: next_state = w ? D : E;
D: next_state = w ? A : F;
E: next_state = w ? D : E;
F: next_state = w ? D : C;
endcase
end
always @(posedge clk) begin
if(reset)
state <= A;
else
state <= next_state;
end
assign z = (state>=E);
endmodule
Problem 147 Q2a FSM
问题:编写 Verilog 代码实现下图中的状态机。这道测试题要求分别使用两个 always 块来实现状态跳转以及状态触发器逻辑。输出逻辑可以使用 assign 连续赋值也可以使用 always 块实现,随你的便。状态编码方式也随你的便
注意状态转换图和上一题不一样(其实就是上一个题的输入反了一下)
解决:
module top_module (
input clk,
input reset, // synchronous reset
input w,
output z);
parameter A=3'b000,B=3'b001,C=3'b010,D=3'b011,E=3'b100,F=3'b101;
reg[2:0] state,next_state;
always @(*) begin
case(state)
A: next_state = w ? B : A;
B: next_state = w ? C : D;
C: next_state = w ? E : D;
D: next_state = w ? F : A;
E: next_state = w ? E : D;
F: next_state = w ? C : D;
endcase
end
always @(posedge clk) begin
if(reset)
state <= A;
else
state <= next_state;
end
assign z = (state>=E);
endmodule
Problem 148 Q2b One-hot FSM equations
问题:状态转换图和上一个题是一样的,但是状态编码使用独热码
写出信号Y1的逻辑表达式,它是状态触发器y[1] 的输入。
写出信号Y3的逻辑表达式,它是状态触发器y[3] 的输入
解决:
module top_module (
input [5:0] y,
input w,
output Y1,
output Y3
);
parameter A=3'd0,B=3'd1,C=3'd2,D=3'd3,E=3'd4,F=3'd5;
reg[5:0] next_state;
assign next_state[A] = (y[D]&~w) || (y[A]&~w);
assign next_state[B] = (y[A]&w);
assign next_state[C] = (y[B]&w) || (y[F]&w);
assign next_state[D] = (y[E]&~w) || (y[F]&~w) || (y[B]&~w) || (y[C]&~w);
assign next_state[E] = (y[C]&w) || (y[E]&w);
assign next_state[F] = (y[D]&w);
assign Y1 = next_state[1];
assign Y3 = next_state[3];
endmodule
Problem 149 Q2a FSM (Exams/2013 q2afsm)
问题:实现下图所示的状态机
本状态机扮演一个仲裁电路,控制三个设备对于某种资源的访问权限。
每个设备通过置起 r[i] 信号为 1'b1 来表示对这种资源的请求。r[1],r[2].r[3]分别对应三个设备的请求信号。三个请求信号作为 FSM 的输入信号。
FSM 在没有任何请求时处于状态 A。当出现了一个或多项请求时,由 FSM 决定哪台设备获得资源的,并向其发出许可信号 g[i],置为 1'b1。g[i] 信号是 FSM 的输出信号。
本系统存在优先级,设备 1 拥有最高权限,设备 2 次之,设备 3 的权限最低。因此设备 3 只能在系统处于状态 A 的情况下才能获得资源访问权限。一旦设备获得 FSM 给出的许可信号后,将持续持有资源直至其将请求信号置低为止,请求信号为高期间不能被打断。
编写 Verilog 代码实现这个 FSM。分别使用两个 always 块来实现状态跳转以及状态触发器逻辑。输出逻辑可以使用 assign 连续赋值也可以使用 always 块实现,随你的便。状态编码方式也随你的便。
解决:
module top_module (
input clk,
input resetn, // active-low synchronous reset
input [3:1] r, // request
output [3:1] g // grant
);
parameter A=0,B=1,C=2,D=3;
reg [1:0] state,next_state;
always @(*) begin
case(state)
A: next_state = r[1] ? B : (r[2] ? C : (r[3] ? D : A));
B: next_state = r[1] ? B : A;
C: next_state = r[2] ? C : A;
D: next_state = r[3] ? D : A;
endcase
end
always @(posedge clk) begin
if(!resetn)
state <= A;
else
state <= next_state;
end
assign g = {state==D,state==C,state==B};
endmodule
Problem 150 Q2b Another FSM (Exams/2013 q2bfsm)
问题:想象你这会儿需要开发一个控制电机的状态机。FSM 有两个来自电机的输入信号 x 和 y,产生两个输出信号 f 和 g 控制电机,此外还有时钟信号 clk 以及低电平的复位信号 resetn。
状态机电路的工作原理如下:
- 在复位信号有效的情况下,FSM 处于初始状态。
- 在复位信号移除后,FSM 在下一个时钟沿输出 f = 1,持续一个时钟周期。
- 接下来的,FSM 监视输入信号 x,当 x 在连续 3 个时钟周期内输出 3'b101 时,在下一周期将信号 g 置 1。
- 在信号 g 置 1 期间,FSM 监视输入信号 y ,如果
- 在接下来 2 个周期内,输入信号 y 跳变为 1'b1,那么 FSM 保持信号 g = 1 (直到复位信号到来)
- 输入信号 y 在 2 个时钟周期内未跳变为 1'b1,那么 FSM 保持信号 g = 0 (直到复位信号到来)
解决:
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
//状态说明
//等待复位信号撤销 F输出1 检查x序列的三个状态 检查y信号的连个状态
//g保持高电平状态 g保持低电平状态
parameter waitRst=0,outF=1,checkX1=2,checkX2=3,checkX3=4,checkY1=5,checkY2=6,holdGH=7,holdGL=8;
reg[3:0] state,next_state;
always @(*) begin
case(state)
waitRst: next_state = resetn ? outF : waitRst;
outF: next_state = checkX1;
checkX1: next_state = x ? checkX2 : checkX1;
checkX2: next_state = x ? checkX2 : checkX3;
checkX3: next_state = x ? checkY1 : checkX1;
checkY1: next_state = y ? holdGH : checkY2;
checkY2: next_state = y ? holdGH : holdGL;
holdGH: next_state = holdGH;
holdGL: next_state = holdGL;
endcase
end
always @(posedge clk) begin
if(!resetn)
state <= waitRst;
else
state <= next_state;
end
assign f = (state == outF);
assign g = (state == holdGH || state == checkY1 || state == checkY2);
endmodule
状态比较多,但是理解起来应该不是很复杂。