串行接收的Verilog实现思路(HDLbits_Fsm serial)

一、题目说明——HDLbits_Fsm serial

        In many (older) serial communications protocols, each data byte is sent along with a start bit and a stop bit, to help the receiver delimit bytes from the stream of bits. One common scheme is to use one start bit (0), 8 data bits, and 1 stop bit (1). The line is also at logic 1 when nothing is being transmitted (idle).

        Design a finite state machine that will identify when bytes have been correctly received when given a stream of bits. It needs to identify the start bit, wait for all 8 data bits, then verify that the stop bit was correct. If the stop bit does not appear when expected, the FSM must wait until it finds a stop bit before attempting to receive the next byte.

二、题目分析

分析题目可知,我们需要设计的电路应满足以下特征:

1)功能:实现串行接收,分为等待开始(idle)、接收(byte_receive)、停止(stop)、错误(error)四个过程。

2)端口:输入时钟clk、复位信号reset、串行接收输入in,输出接收成功信号done。

3)触发方式:时钟上升沿触发,reset同步且高电平有效。

4)时序解释说明:

        1>时钟上升时触发电路复位后,进入等待开始状态(idle)。

        2>时钟上升时若处于等待开始状态(idle),则检测当前输入in,如果in为低则进入接收(byte_receive),否则仍在等待开始状态。

        3>时钟上升时若处于接收(byte_receive)状态,则接下来8个时钟周期内的输入in为需要接收内容,8个时钟周期结束后若当前输入为高进入停止状态(stop),若当前输入in是低则进入错误(error)状态。

        4>时钟上升时若处于停止(stop)状态,则检测输入in是否为低,若是则进入接收(byte_receive)状态;若否,则进入等待开始状态(idle)

        5>时钟上升时若处于错误(error)状态,则检测输入in是否为高,若是则进入等待开始状态(idle);若否,则仍为错误(error)状态。

        5>无论何时,只要处于停止状态,就输出done为高。

状态转移图如下:

三、实现与总结

        这里需要注意的是,在接收状态,我们通常将八位比特的接收看作是八个不同的状态bit_0、bit_1、bit_2、...、bit_7,严格来说,他们确实是不同的状态,只是他们的转移关系只与时钟周期有关,与输入in无关。如果是八位比特的接收,我们可以写出八种状态的转移,但对于中间过程很多的情况,我们无法全部写出,这时候可以使用循环整型变量来计数当前的时钟周期,从而描述复杂状态的转移。以下代码采用变量i记录过去的个时钟周期数,而不是使用八个状态描述接收过程。

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 

    reg [1:0] state;
    localparam idle=0,byte_receive=1,stop=2,error=3;
    integer i;
    
    always@(posedge clk)begin
        if(reset)
            state<=idle;
        else begin
            case(state)
                idle:begin 
                    state<=in?idle:byte_receive;
                    i<=0;end
                byte_receive:begin
                    if(i==8)begin
                        state<=in?stop:error;i<=0;end
                    else
                        i<=i+1;end
                stop:state<=in?idle:byte_receive;
                error:state<=in?idle:error;
            endcase
        end
    end
                
    assign done = (state==stop);
    
endmodule

        这里容易错误的是判断跳出的条件,下图为时序图,我们可以分析一下这一整个过程。

        这里使用的是非阻塞赋值语句,这会产生一个类似滞后的效果。具体来讲,如果在当前上升沿触发对i累加,那这个被更新的i只能在下次上升沿触发时被使用,当前时刻被使用的i是上一次触发更新后的值(旧值)。这和阻塞赋值不同的是,每条语句都是并行执行的,没有先后的顺序,所有语句使用的都是旧值,本次更新的值会在下次触发时生效

        事实上,若在某时刻触发,那所有的值都会在当前时刻被更新,但是这一时刻做的事已经做过了,若想要这次更新的值被使用,只能等到下次触发。但是,因为所有的值都已经在这个时刻更新,所以所有类似于assign的赋值语句在这一个时刻就会生效,而不是等到下一个时钟上升沿。因为assign语句只要右侧值发生变化就会执行,也可以理解是所有时刻都触发的语句。

        因此非阻塞赋值只是产生了类似滞后的效果,而不是真的滞后(对于时序逻辑是滞后,对组合逻辑不滞后)。除此之外,我们可以理解为i为8等同于“从i=0开始到现在时刻为止,过去了9个时钟循环”,那么接下来需要做的就是判断是否in为高,若是则为stop状态;若in为低,则进入错误状态。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值