错题集:HDLBits 状态机 fsm_serial

错题笔记:

这道题是关于串行通信协议,接收数据流的的一种状态机。包括前面几道状态机的题在内,出错了很多次,主要原因有两点:

(1)时序理解不到位

(2)题目理解不到位

题目:

在许多(较旧的)串行通信协议中,每个数据字节都与起始位和停止位一起发送,以帮助接收者从位流中划分字节。一种常见的方案是使用一个起始位 (0)、8 个数据位和 1 个停止位 (1)。当没有传输任何内容(空闲)时,该行也位于逻辑 1 处。

设计一个有限的状态机,当给定位流时,它将识别何时正确接收字节。它需要识别起始位,等待所有8个数据位,然后验证停止位是否正确。如果停止位未按预期出现,则 FSM 必须等到找到停止位后再尝试接收下一个字节。

 做题过程:

1.一开始写读取接收数据流的这种状态机时,对时序理解不到位,以为是先有现状态(时刻1),再有输入(时刻2),在输入的同时,产生次状态(时刻2);但是这种理解是错误的,因为次状态,是通过结合现状态输入两者,判断而出的,所以输入现状态一定是同步的,否则就无法同时操作他俩来进行判断(这个错误对我来说,很典型)。

2.一开始的思路(思路一)有问题,还是和对时序的理解有关,我下意识认为到了S8,就已经流过了8位data,所以,我认为在S8时,输入若为1,则到S9状态,就可以输出done=1了。

但是实际上,在S8时,输入信号并不是代表的stop信号,而是代表的bit[8]。

 3.在意识到上述错误以后,我增加了一个状态(思路二),在这个状态图的理解下,我卡了很久。从Done状态,输入为1时,下一状态为ELSE,用来代表,上述时序图中,最右侧红框的变化,但后来我发现这一个ELSE状态是多余的,因为如果在DONE下输入为1,可以直接令其,回到S0状态,于是我又修改了状态图(思路三)。

4.修改之后,还是输出不对,done信号始终为0,这让我很疑惑。对比别人的答案后,我发现我漏掉了时序图中下侧红框中所表示的变化,所以就增加了ERROR的状态。在ERROR状态下,如果输入为0,保持ERROR;如果输入为1,则跳转到S0状态。而我原来的写法是,如果在S9下,输入为0,就直接跳转到S0, 这和题目的要求是不符合的,题目的S0指的是输入要为1(如时序图中左侧红框所示)。所以正确的状态转换图如下:

但还是很疑惑,为什么done信号在思路三的代码下,会始终为0,感觉上,S9到Done的跳转应该是正常的才对,那done信号就应该在Done状态下输出1,但仿真结果却和我设想的不一样。

正确答案:

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 
    reg [3:0] state,next_state;
    parameter S0=0,S1=1,S2=2,S3=3,S4=4,S5=5,S6=6,S7=7,S8=8,S9=9,DONE=10,ERROR=11;
    
    always@(*)begin
        case(state)
            S0: next_state = in?S0:S1;
            S1: next_state = S2;
            S2: next_state = S3;
            S3: next_state = S4;
            S4: next_state = S5;
            S5: next_state = S6;
            S6: next_state = S7;
            S7: next_state = S8;
            S8: next_state = S9;
            S9: next_state = in?DONE:ERROR;//一开始写的S0,理解有误
          DONE: next_state = in?S0:S1;
         ERROR: next_state = in?S0:ERROR;//一开始理解的是ELSE
        endcase
    end
    
    always@(posedge clk)begin
        if(reset)
            state <= S0;
        else
            state <= next_state;
    end
    
    assign done = (state==DONE);
	
endmodule

卡了很久的错误答案: 

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 
    reg [3:0] state,next_state;
    parameter S0=0,S1=1,S2=2,S3=3,S4=4,S5=5,S6=6,S7=7,S8=8,S9=9,DONE=10;
    
    always@(*)begin
        case(state)
            S0: next_state = in?S0:S1;
            S1: next_state = S2;
            S2: next_state = S3;
            S3: next_state = S4;
            S4: next_state = S5;
            S5: next_state = S6;
            S6: next_state = S7;
            S7: next_state = S8;
            S8: next_state = S9;
            S9: next_state = in?DONE:S0;//问题就出在如果in为0,并不是跳转到S0;
          DONE: next_state = in?S0:S1;
        endcase
    end
    
    always@(posedge clk)begin
        if(reset)
            state <= S0;
        else
            state <= next_state;
    end
    
    assign done = (state==DONE);
	
endmodule

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值