【题目】:
一个输入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输入。
【个人思路】:
大概意思是状态机复位状态在A,检测到s为1后进入状态B,在状态B每隔三个时钟周期就检查一次这三个时钟周期内w为高的时钟周期个数是否为2,若是则拉高输出z一个周期。
状态机设计两个状态A、B。在状态B设计一个计数器1从0-2循环计数,这样就把B状态分隔成了每3个周期的小段。再设计一个计数器2,来计数输入w为1的个数。这样就可以根据w为高的次数来对应的拉高输出z。
参考原文链接:https://blog.csdn.net/wuzhikaidetb/article/details/120381765
module top_module (
input clk,
input reset, // Synchronous reset
input s,
input w,
output reg z
);
reg [1:0] cnt;
reg [1:0] clk_cnt;
parameter A='d0;
parameter B='d1;
reg state,next_state;
always@(posedge clk)
begin
if(reset)
state<=A;
else
state<=next_state;
end
always@(*)
begin
case(state)
A: next_state=s?B:A;
B: next_state=B;
default:next_state=A;
endcase
end
//计数器1:计数0-2 3个周期循环计数 :
//第一个周期:0->1;
//第二个周期:1->2;
//第三个周期:2->0;
always@(posedge clk)
begin
if(reset)
clk_cnt<='d0;
else if(state==B)
begin
if(clk_cnt=='d2)
begin
clk_cnt<='d0;
end
else
clk_cnt<=clk_cnt+'d1;
end
else
clk_cnt<='d0;
end
always@(posedge clk)
begin
if(reset)
cnt<='d0;
else if(state==B)
begin
if(clk_cnt=='d2)
begin
cnt<='d0;
end
else if(w)
begin
cnt<=cnt+1;
end
else
cnt<=cnt;
end
else
cnt<='d0;
end
always@(posedge clk)
begin
if(reset)
z<='d0;
else
case(state)
A: z<='d0;
B:
begin
if(clk_cnt=='d2)
begin
if((cnt=='d2&&~w)||(cnt=='d1&&w))//当cnt=2且输入为0,或cnt=1且输入为1
z<='d1;//从而构成3个时钟周期内(clk_cnt=2)实现w输入为2个高电平
else
z<='d0;
end
else
z<='d0;
end
default:z<='d0;
endcase
end