有限状态机
21、Q8:设计一个Mealy FSM
米利型状态机
检测输入的X中”101“是否出现,出现的话输出Z为1,否则为0。复位为异步低电平复位;只允许出现3种状态;允许交叠检测:即输入若为10101时,Z应该在时刻3和时刻5各输出一次1。
代码中主要妙在两处:一是如何用3种状态表示,需在第三种状态中将输出与输入关联起来;二是如何进行交叠检测,状态的转移有妙处。
代码实现:
module top_module (
input clk,
input aresetn, // Asynchronous active-low reset
input x,
output z );
parameter S0 = 2'd0,S1 = 2'd1,S2 = 2'd2;
reg [1:0] current_state,next_state;
always @(*) begin
case(current_state)
S0: next_state = x ? S1 : S0;
S1: next_state = x ? S1 : S2;
S2: next_state = x ? S1 : S0;
endcase
end
always @(posedge clk or negedge aresetn) begin
if(~aresetn)
current_state <= S0;
else
current_state <= next_state;
end
always @(*) begin
z = (current_state == S2) ? x : 1'b0;
end
endmodule
验证结果:
22、Q5a:串行二进制补码器(Moor FSM)
您将设计一个单输入单输出串行 2 的补码摩尔状态机。输入 (x) 是从数字的最低有效位开始的一系列位(每个时钟周期一个),输出 (Z) 是输入的 2 的补码。机器将接受任意长度的输入数字。该电路需要异步复位。当转换开始复位释放后,停止复位有效。
注意:假设我们这边输入的都是负数,不用管符号位的问题;即补码全部都是取反加1求得。
以上图为例,输入的左边为低位数据,右边为高位数据;即输入为00110100,则取反加1后得输出为11001100;
取反操作好进行,主要麻烦在加一的操作上,不知道进位到哪一位为止,此时我们用状态机来解决;若最前面的输入都是0的话,取反均为1,低位加1的时候一直进位,则输出都是0,直到输入有个1为止(取反加1不进位),这一阶段我们用一个状态S0来表示;后面阶段就将输入取反进行输出即可,因为进位在S0状态已结束;
代码实现:
module top_module (
input clk,
input areset,
input x,
output z
);
parameter S0=2'd0,S1=2'd1,S2=2'd2;
reg [1:0] current_state,next_state;
always @(*) begin
case(current_state)
S0: next_state = x ? S1 : S0;
S1: next_state = x ? S2 : S1;
S2: next_state = x ? S2 : S1;
endcase
end
always@(posedge clk or posedge areset) begin
if(areset)
current_state <= S0;
else
current_state <= next_state;
end
assign z = (current_state == S1);
endmodule
验证结果:
23、Q5b:串行二进制补码器(Mealy FSM)
下图是2 的补码器的Mealy机实现。使用 one-hot 编码实现。
代码实现:
module top_module (
input clk,
input areset,
input x,
output z
);
parameter S0=1'b0,S1=1'b1;
reg current_state,next_state;
always@(*)begin
case(current_state)
S0: begin
if(x == 1)
next_state = S1;
else
next_state = S0;
end
S1: next_state = S1;
endcase
end
always@(posedge clk or posedge areset) begin
if(areset)
current_state <= S0;
else
current_state <= next_state;
end
assign z = ((current_state == S0) && x) | ((current_state == S1) && ~x);
endmodule
验证结果:
24、Q3a:FSM
考虑一个有输入s和w的有限状态机。假设FSM从一个名为a的重置状态开始,如下所示。当s = 0时,状态为A,当s = 1时,状态为B。一旦进入状态B, FSM就会检查接下来三个时钟周期中输入w的值。如果w在这两个时钟周期中恰好为1,则FSM必须在下一个时钟周期中将输出z设置为1。否则z等于0。FSM继续检查w是否有接下来的三个时钟周期,以此类推。下面的时序图说明了不同的w值所需的z值。
使用尽可能少的状态。注意,s输入只在状态A中使用,所以您需要只考虑w输入。
提示:
当s为0时,进入B状态,然后会检查w的值,如果在接下来的三个周期中w值恰好有两个周期都为1,那么z输出1,否则z输出0。注意,由示例的波形图看应该是不重叠检测。
代码实现:
module top_module (
input clk,
input reset, // Synchronous reset
input s,
input w,
output z
);
parameter S0=1'b0,S1=1'b1;
reg current_state,next_state;
reg [1:0] cnt,num;
always@(*)begin
case(current_state)
S0: begin
if(s == 1)
next_state = S1;
else
next_state = S0;
end
S1: next_state = S1;
default: next_state = S0;
endcase
end
always@(posedge clk) begin
if(reset)
current_state <= S0;
else
current_state <= next_state;
end
always@(posedge clk) begin
if(reset)
cnt <= 2'd0;
else if(cnt == 2'd2)
cnt <= 2'd0;
else if(current_state == S1)
cnt <= cnt + 1'b1;
else
cnt <= cnt;
end
always@(posedge clk) begin
if(reset)
num <= 2'd0;
else if(cnt == 2'd0)
num <= w ? 1'b1 : 1'b0;
else if(current_state == S1)
num <= w ? (num+1'b1) : num;
else
num <= num;
end
assign z = (current_state == S1 && cnt == 2'd0 && num == 2'd2);
endmodule
验证结果:
25、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] current_state,next_state;
always@(*)begin
case(current_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)
current_state <= S0;
else
current_state <= next_state;
end
assign z = (current_state == S3 || current_state == S4);
endmodule
验证结果:
26、Q3c:FSM 逻辑
给定如下所示的状态分配表,实现逻辑函数 Y[0] 和 z。
代码实现:
module top_module (
input clk,
input [2:0] y,
input x,
output Y0,
output z
);
assign z = (y == 3'b011 || y == 3'b100);
assign Y0 = ((~y[2]&y[0])|(y==3'b100))&~x | (~y[2]&~y[0])&x;
endmodule
验证结果:
27、Q6b:FSM 下一状态逻辑
考虑下面显示的状态机,它有一个输入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);
assign Y2 = (y==3'b001)|(y==3'b101)|(((y==3'b010)|(y==3'b100))& w);
endmodule
验证结果:
28、Q6c:FSM one-hot 下一状态逻辑
考虑下面显示的状态机,它有一个输入w和一个输出z。
对于这一部分,假设状态分配 'y[6:1] = 000001, 000010, 000100, 001000, 010000, 100000 分别用于状态 A、B、…、F的独热码。
为下一状态信号 Y2 和 Y4 写一个逻辑表达式。
提示:
y[6:1] | state | w=0 | w=1 |
---|---|---|---|
000001 | A | 000010 | 000001 |
000010 | B | 000100 | 001000 |
000100 | C | 010000 | 001000 |
001000 | D | 100000 | 000001 |
010000 | E | 010000 | 001000 |
100000 | F | 000100 | 001000 |
代码实现:
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
验证结果:
29、Q6:FSM
实现下图显示的状态机,它有一个输入w和一个输出z。
代码实现:
module top_module (
input clk,
input reset, // synchronous reset
input w,
output z);
parameter A=3'd1,B=3'd2,C=3'd3,D=3'd4,E=3'd5,F=3'd6;
reg [2:0] current_state,next_state;
always@(*)begin
case(current_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)
current_state <= A;
else
current_state <= next_state;
end
assign z = (current_state == E || current_state == F);
endmodule
验证结果:
30、Q2a:FSM
实现下面显示的状态图。
代码实现:
module top_module (
input clk,
input reset, // Synchronous active-high reset
input w,
output z
);
parameter A=3'd1,B=3'd2,C=3'd3,D=3'd4,E=3'd5,F=3'd6;
reg [2:0] current_state,next_state;
always@(*)begin
case(current_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)
current_state <= A;
else
current_state <= next_state;
end
assign z = (current_state == E || current_state == F);
endmodule
验证结果:
31、Q2b:One hot FSM方程
状态使用独热编码,将状态中的y[1]和y[3]表示出来。
假设状态分配 y[5:0] = 000001(A), 000010(B), 000100©, 001000(D), 010000(E), 100000(F)
写出信号Y1的逻辑表达式,它是状态触发器y[1] 的输入。
写出信号Y3的逻辑表达式,它是状态触发器y[3] 的输入。
代码实现:
module top_module (
input [5:0] y,
input w,
output Y1,
output Y3
);
assign Y1 = w & y[0];
assign Y3 = (~w & y[1])|(~w & y[2])|(~w & y[4])|(~w & y[5]);
endmodule
验证结果:
32、Q2a:FSM
用状态机实现一个判优器。其中r1、r2、r3分别表示三种设备的request,g1、g2、g3表示资源的分配情况。由下面的状态图可见,设备1,2,3的优先级依次递减。当设备请求到资源时,需等其完成任务才能释放资源。
代码实现:
module top_module (
input clk,
input resetn, // active-low synchronous reset
input [3:1] r, // request
output [3:1] g // grant
);
parameter A=2'd1,B=2'd2,C=2'd3,D=2'd4;
reg [1:0] current_state,next_state;
always@(*)begin
case(current_state)
A: begin
if(r[1]==1'b1)
next_state = B;
else if(r[2]==1'b1)
next_state = C;
else if(r[3]==1'b1)
next_state = D;
else
next_state = A;
end
B: next_state = r[1] ? B : A;
C: next_state = r[2] ? C : A;
D: next_state = r[3] ? D : A;
default:next_state = A;
endcase
end
always@(posedge clk) begin
if(~resetn)
current_state <= A;
else
current_state <= next_state;
end
assign g = {current_state == D,current_state == C,current_state == B};
endmodule
验证结果:
33、Q2b:另一个FSM
考虑一个用于控制某种类型电机的有限状态机。FSM有来自电机的输入x和y,并产生控制电机的输出f和g。还有一个时钟输入称为clk和一个复位输入称为resetn。
FSM 必须按如下方式工作。只要复位输入有效时,FSM停留在一开始的状态,所谓的国家一个。当复位信号无效时,在下一个时钟沿之后,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(直到复位)。
提示:
该题的状态机共2输入2输出;当复位信号撤销时,在下一个周期内将f输出为1,需留意f为1持续一个周期;然后状态机取决于x的值,当x在连续的三个周期中产生值为1、0、1时,下一周期将g输出为1,在保持g为1时判断y的输入,如果y在两个周期中有任意一个周期为1了,那么g永久保持1;如果两个周期都没有1,那么g将永久保持0。
代码实现:
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
parameter IDLE=4'd0,FOUT=4'd1,S1=4'd2,S2=4'd3,S3=4'd4,S4=4'd5,S5=4'd6;
parameter ALL_ZERO=4'd7,ALL_ONE=4'd8;
reg [3:0] current_state,next_state;
always@(*)begin
case(current_state)
IDLE: next_state = FOUT;
FOUT: next_state = S1;
S1: next_state = x ? S2 : S1;
S2: next_state = x ? S2 : S3;
S3: next_state = x ? S4 : S1;
S4: next_state = y ? ALL_ONE : S5;
S5: next_state = y ? ALL_ONE : ALL_ZERO;
ALL_ONE: next_state = ALL_ONE;
ALL_ZERO: next_state = ALL_ZERO;
default:next_state = IDLE;
endcase
end
always@(posedge clk) begin
if(~resetn)
current_state <= IDLE;
else
current_state <= next_state;
end
assign f = (current_state == FOUT);
assign g = (current_state == S4) | (current_state == S5) | (current_state == ALL_ONE);
endmodule
验证结果:
参考资料: Verilog有限状态机.