HDLbits---Fsm serialdp

FPGA基础——串行数据接收(Fsm serialdp)
    我们想在串行接收机中加入奇偶校验。奇偶校验检查在每个数据字节后添加一个额外的位。我们将使用奇奇偶校验,其中接收到的9位中的1必须是奇数。例如,101001011个满足奇偶校验(有5个1) ,但001001011个不满足。

    只有在正确接收到一个字节并且它的奇偶校验通过时,才断言完成信号。与串行接收机一样,该有限状态机需要确定开始位,等待所有9位(数据和奇偶校验) ,然后验证停止位是正确的。如果停止位没有在预期的时候出现,FSM 必须等到找到停止位之后才能尝试接收下一个字节。

    注意,串行协议先发送低有效位,奇偶校验位在8个数据位之后,然后是高有效停止位。
在这里插入图片描述
    下面是判断输入的8位数据加上奇偶校验位的1的个数的module

module parity (
    input clk,
    input reset,
    input in,
    output reg odd);

    always @(posedge clk)
        if (reset) odd <= 0;
        else if (in) odd <= ~odd;

endmodule

    下面的是程序的状态图
状态图
    WAIT表示等待开始位的状态,TRANS表示传输的状态,ODD表示奇偶校验的状态,DONE表示接收到停止位的完成态,CRASH表示未正确接收到停止位的错误态。其中Start_TRANS状态只是一个过度的状态,方便表示一个字节接着一个字节传输,这样从当DONE完成态进入下一个接收的状态的时候,有一个状态方便表示下一个字节开始接受了,odd的值需要清空,同时counter的值也需要清零了。

注: 其实这里的Start_TRANS和TRANS对于state而言是一个状态,因为在next_state变为Start_TRANS之后,会迅速的变为TRANS,所以在下一个时钟周期来临的时候,state就等于TRANS了。

在这里插入图片描述
    在next_state=WAIT之后,因为in=0,所以会有一个短暂的时间next_state=Start_TRANS,接着next_state就会变为TRANS。所以在下一个时钟沿的时候,取到的next_state的值就是TRANS,所以state就会变为TRANS状态,相当于直接跳过了Start_TRANS状态。
在这里插入图片描述

c_state为现在的状态,n_state为下一时钟周期的状态

    整体代码如下

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //

    // Modify FSM and datapath from Fsm_serialdata
    parameter WAIT = 3'b000,TRANS = 3'b001,ODD = 3'b010,CRASH = 3'b011,DONE = 3'b100,Start_TRANS = 3'b101;
    reg [2:0] state,next_state;
    
    reg [3:0] counter;
    reg [7:0] out_reg;
    always@(posedge clk)begin
        if(reset)begin
            counter <= 0;
        end 
        else if(counter == 8)begin
            counter <= 0;
        end
        else begin
            if(next_state == TRANS)begin	// 接收数据,并且设置计数器
                counter <= counter + 1;
                out_reg[counter] <= in;
            end
            else begin
                counter <= 0;
            end
        end
    end
    always@(posedge clk)begin
        if(reset)begin
            state <= WAIT;
        end
        else begin
            state <= next_state;
        end
    end
    
    always@(*)begin
        case(state)
            WAIT: next_state = (in == 1)?WAIT:Start_TRANS;
            Start_TRANS: next_state = TRANS;	// 过渡态
            TRANS: next_state = (counter == 8)?ODD:TRANS;
            ODD: next_state = (in == 1)?DONE:CRASH;
            CRASH: next_state = (in == 1)?WAIT:CRASH;
            DONE: next_state = (in == 1)?WAIT:Start_TRANS;
        endcase
    end
    
    
    wire odd;
    wire re;
    assign re = reset || (next_state == WAIT) ||(next_state == Start_TRANS);
    parity parity(clk,re,in,odd);
    
    assign done = (state == DONE) && (~odd);	// 因为在输入奇偶校验位的时候,是next_state=DONE的,所以在state=DONE时,这里的odd多记录了一个位置,所以需要反转
    assign out_byte = (done)?out_reg:8'bz;
    // New: Add parity checking.

endmodule
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小编程员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值