目录
前言
3.2.5 Finite State Machines
3.2.5.27 Q6b: FSM next-state logic(Exams/m2014 q6b)
3.2.5.28 Q6c: FSM one-hot next-state logic(Exams/m2014 q6c)
3.2.5.29 Q6: FSM(Exams/m2014 q6)
3.2.5.30 Q2a: FSM(Exams/2012 q2fsm)
3.2.5.31 Q2b: One-hot FSM equations(Exams/2012 q2b)
3.2.5.32 Q2a: FSM(Exams/2013 q2afsm)
3.2.5.33 Q2b: Another FSM(Exams/2013 q2bfsm)
结语
HDLbits网站链接
今天更新状态机这节的最后几道题目,这个网站的“大老虎”状态机小节终于要完结啦。
module top_module (
input [3:1] y,
input w,
output Y2);
assign Y2 = (y == 3'b001 | y == 3'b101) & ~w |
(y == 3'b001 | y == 3'b010 | y == 3'b100 | y == 3'b101) & w;
endmodule
这道题目作者说用y[3:1]来表示ABCDEF几个状态,我的答案纯粹是为了解题,大家看看就好。
module top_module (
input [6:1] y,
input w,
output Y2,
output Y4);
parameter A = 3'd1, B = 3'd2, C = 3'd3;
parameter D = 3'd4, E = 3'd5, F = 3'd6;
assign Y2 = ~w & y[A];
assign Y4 = w & (y[B] | y[C] | y[E] | y[F]);
//assign Y2 = ~w & y[1];
//assign Y4 = w & (y[2] | y[3] | y[5] | y[6]);
endmodule
这道题和上一道题目差不多,只不过这里作者让我们使用one-hot编码来完成。
module top_module (
input clk,
input reset, // synchronous reset
input w,
output z);
parameter A = 3'd0, B = 3'd1, C = 3'd2, D = 3'd3, E = 3'd4, F = 3'd5;
reg [2:0] current_state;
reg [2:0] next_state;
always@(posedge clk)begin
if(reset)begin
current_state <= A;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
A:begin
next_state = w ? A : B;
end
B:begin
next_state = w ? D : C;
end
C:begin
next_state = w ? D : E;
end
D:begin
next_state = w ? A : F;
end
E:begin
next_state = w ? D : E;
end
F:begin
next_state = w ? D : C;
end
default:begin
next_state = A;
end
endcase
end
assign z = (current_state == E || current_state == F);
endmodule
这是一道无比正宗的FSM题目,大家看着状态转移图完成就好了,正宗地不需要任何解题思路。
module top_module (
input clk,
input reset, // Synchronous active-high reset
input w,
output z
);
parameter A = 3'd0, B = 3'd1, C = 3'd2, D = 3'd3, E = 3'd4, F = 3'd5;
reg [2:0] current_state;
reg [2:0] next_state;
always@(posedge clk)begin
if(reset)begin
current_state <= A;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
A:begin
next_state = w ? B : A;
end
B:begin
next_state = w ? C : D;
end
C:begin
next_state = w ? E : D;
end
D:begin
next_state = w ? F : A;
end
E:begin
next_state = w ? E : D;
end
F:begin
next_state = w ? C : D;
end
default:begin
next_state = A;
end
endcase
end
assign z = (current_state == E || current_state == F);
endmodule
和上一道题目一样,相当正宗,不过大家要注意,这里的状态转移图和上一道题目不一样,比如w为1的时候才从A状态跳到B状态。
module top_module (
input [5:0] y,
input w,
output Y1,
output Y3
);
parameter A = 3'd0, B = 3'd1, C = 3'd2;
parameter D = 3'd3, E = 3'd4, F = 3'd5;
assign Y1 = w & y[A];
assign Y3 = ~w & (y[B] | y[C] | y[E] | y[F]);
endmodule
这道题目又是要使用one-hot编码逻辑,大家也看出来了,这个系列,作者给出的one-hot编码思想和我们平时的思想不太一样,我们的习惯是将状态定义为one-hot编码。不过,one-hot编码的优点就在于只需要判断一位的数据就可以判定状态,速度快,这点作者和我们的思想相同,所以大家也不用太过纠结,学习作者的思想,然后完成题目就好。另一种可能性,由于我们写状态机用的one-hot编码和正常的二进制编码,输出波形都是一致的,作者的tb检查不出来我们是否使用了one-hot编码,所以只好按照这种方式了。
module top_module (
input clk,
input resetn, // active-low synchronous reset
input [3:1] r, // request
output [3:1] g // grant
);
parameter A = 2'd0, B = 2'd1, C = 2'd2, D = 2'd3;
reg [1:0] current_state;
reg [1:0] next_state;
always@(posedge clk)begin
if(resetn == 1'b0)begin
current_state <= A;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
A:begin
if(r[1])begin
next_state = B;
end
else if(r == 3'd0)begin
next_state = A;
end
else if(r[2:1] == 2'd2)begin
next_state = C;
end
else if(r == 3'd4)begin
next_state = D;
end
else begin
next_state = A;
end
end
B:begin
if(r[1])begin
next_state = B;
end
else if(r[1] == 1'b0)begin
next_state = A;
end
else begin
next_state = A;
end
end
C:begin
if(r[2])begin
next_state = C;
end
else if(r[2] == 1'b0)begin
next_state = A;
end
else begin
next_state = A;
end
end
D:begin
if(r[3])begin
next_state = D;
end
else if(r[3] == 1'b0)begin
next_state = A;
end
else begin
next_state = A;
end
end
default:begin
next_state = A;
end
endcase
end
always@(*)begin
if(current_state == B)begin
g[1] = 1'b1;
end
else begin
g[1] = 1'b0;
end
if(current_state == C)begin
g[2] = 1'b1;
end
else begin
g[2] = 1'b0;
end
if(current_state == D)begin
g[3] = 1'b1;
end
else begin
g[3] = 1'b0;
end
end
endmodule
这道题目和前面的题目又不一样了,前面只需要判断in为0或者为1就可以判定状态的转移了,这道题目需要判定3位输入,大家对着状态转移图完成题目就好了。
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
parameter IDLE = 4'd0, S1 = 4'd1, S2 = 4'd2, S3 = 4'd3, S4 = 4'd4;
parameter S5 = 4'd5, FOREVER_ONE = 4'd6, FOREVER_ZERO = 4'd7;
parameter F_OUT = 4'd8;
reg [3:0] current_state;
reg [3:0] next_state;
always@(posedge clk)begin
if(resetn == 1'b0)begin
current_state <= IDLE;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
IDLE:begin
next_state = F_OUT;
end
F_OUT:begin
next_state = S1;
end
S1:begin
next_state = x ? S2 : S1;
end
S2:begin
next_state = x ? S2 : S3;
end
S3:begin
next_state = x ? S4 : S1;
end
S4:begin
next_state = y ? FOREVER_ONE : S5;
end
S5:begin
next_state = y ? FOREVER_ONE : FOREVER_ZERO;
end
FOREVER_ONE:begin
next_state = FOREVER_ONE;
end
FOREVER_ZERO:begin
next_state = FOREVER_ZERO;
end
default:begin
next_state = IDLE;
end
endcase
end
assign f = (current_state == F_OUT);
assign g = (current_state == S4 || current_state == S5 || current_state == FOREVER_ONE);
endmodule
题意中说,复位信号撤销时,在下一个周期内将f输出为1,注意f为1只保持一个周期,然后状态机取决于x的值,当x在连续的三个周期中产生值为1、0、1时,下一周期将g输出为1,在保持g为1时判断y的输入,如果y在两个周期中有任意一个周期为1了,那么g永久保持1;如果两个周期都没有1,那么g将永久保持0。
我在这里增加了几个状态,比如FOREVER_ONE和FOREVER_ZERO状态,这两个状态完全是根据题意增加的。
状态机这个小节终于更新完啦,这个小节的内容真的是非常多,涉及到的思想不论在工程中还是面试中都是必须要掌握的,这个小节完成后,后面的内容就基本没有特别难的了,希望大家可以好好温习这个小节内容,争取多用几种方法完成,感受每种方法的异同点,完成这个小节,对状态机的了解会加深不少。最后,如果哪里代码或者解析有误,欢迎大家留言~
https://hdlbits.01xz.net/wiki/Main_Page