原题复现
代码
刚开始的错误思路是,把IDLE状态设置为输入为0时候的初始状态,结果发现这样做是不可行的,原因很简单:
假设IDLE状态是初始状态,根据题意,复位后的初始状态即是0,并不是依靠in输入0来判断作为初始位,也是以第一个1作为起始位来进行判断。也就是说,本身是不需要判断in是否为0,从而进入连续读取状态的。因为给出了默认值就是0,直接判断in是否为1,从而决定是否进入下一个状态。
错误思路想法1: 换句话说,不需要判断in为1的上一个节拍的in输入是否为0,我们只是要求判断出连续的5个1或者6个1甚至7个及以上的1。in=1时候开始计数,本身就是默认了上一个节拍的in输入的为0.
验证自己的错误思路想法2:见代码注释
module top_module(
input clk,
input reset, // Synchronous reset
input in,
output disc,
output flag,
output err);
parameter IDLE=0,S1=1,S2=2,S3=3,S4=4,S5=5,S6=6,S7=7,S8=8,S9=9,S10=10;
reg [3:0]state,next_state;
always@(*)begin
case(state)
IDLE: next_state = in?IDLE:S1;//这个状态是多余的,(判断第一个1)
S1: next_state = in?S2:IDLE;//(判断第二个1)
S2: next_state = in?S3:IDLE;//(判断第三个1)
S3: next_state = in?S4:IDLE;//(判断第四个1)
S4: next_state = in?S5:IDLE;//(判断第五个1)
S5: next_state = in?S6:IDLE;//(判断第六个1)
S6: next_state = in?S7:S10; //(判断第六个1后,如果等于0,就进入丢弃,如果等于1,就进入第七个1了,与题目要求不符合了)
S7: next_state = in?S8:S9;
S8: next_state = in?S8:S1;
S9: next_state = in?IDLE:S1;//因为自己是思路是0作为判断是起始位置,因此这里也错误了
S10: next_state = in?IDLE:S1; //第一个1才是起始位置。
endcase
end
always@(posedge clk)begin
if(reset)begin
state<=IDLE;
end
else begin
state<=next_state;
end
end
assign disc = state==S10;
assign flag = state==S9;
assign err = state==S8;
endmodule
正确代码
module top_module(
input clk,
input reset, // Synchronous reset
input in,
output disc,
output flag,
output err);
parameter IDLE=0,S1=1,S2=2,S3=3,S4=4,S5=5,S6=6,S7=7,ERR=8,FLAG=9,DISC=10;
reg [3:0]state,next_state;
always@(*)begin
case(state)
IDLE: next_state = in?S1:IDLE;
S1: next_state = in?S2:IDLE;
S2: next_state = in?S3:IDLE;
S3: next_state = in?S4:IDLE;
S4: next_state = in?S5:IDLE;
S5: next_state = in?S7:DISC;
S7: next_state = in?ERR:FLAG;
ERR: next_state = in?ERR:IDLE;
FLAG: next_state = in?S1:IDLE;
DISC: next_state = in?S1:IDLE;
endcase
end
always@(posedge clk)begin
if(reset)begin
state<=IDLE;
end
else begin
state<=next_state;
end
end
assign disc = state==DISC;
assign flag = state==FLAG;
assign err = state==ERR;
endmodule
总结:自己对于最初的状态,特别是in的判断是作为第几个输入时候的时序判断不够准确,要加强对in的输入的判断。