1.原题复现
2.思路以及代码
给出自己画的状态图:
把复位后的状态设为状态A,经过一个时钟后,将会拉高f置位1,但是f只能保持一个时钟周期内为1,之后又被拉低,因此把状态B分解为B1和B2,避免计数。在f为0之后,便开始对输入X开始计数,计数的规律就相当于序列检测一样,把整个序列检测过程设定为状态C,又细分为C1,C2,C3。在检测到连续的101之后,将输出g在下一个时钟设为高电平。当g置为高电平之后,便开始对接下来的两个周期开始进行计数,但是我将计数转换成了状态D。分为D1,D2,D3,D4。
D1的作用为,第一个时钟周期到来时候,输入y已经置位1,因此,可以一直保持输出g为1
D2表示,第一个时钟周期到来时候,输入y为0,开始对第二个时钟周期开始计数,第二个时钟周期又分为两种状态,一个是y仍然为低电平,另一个是y变为高电平,也就形成了相应的状态D3,和D4。
代码:
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
parameter A=0,B1=1,C1=2,C2=3,C3=4,D1=5,D2=6,D3=7,D4=8,B2=9;
reg[3:0]state,next_state;
reg cout;
always@(*)begin
case (state)
A:next_state = B1;
B1:next_state = B2;
B2:next_state = x?C1:B2;
C1:next_state = x?C1:C2;
C2:next_state = x?C3:B2;
C3:next_state =y?D1:D2;
D1:next_state =D1;
D2:next_state =y?D4:D3;
D3:next_state =D3;
D4:next_state =D4;
endcase
end
always@(posedge clk)begin
if(~resetn)begin
state<=A;
end
else begin
state<=next_state;
end
end
assign f = (state==B1);
assign g = (state==C3)||(state==D1)||(state==D2)||(state==D4);
endmodule