HDLBits(4)--Serial Receiver / with datapath / with parity check

FSM Serial Receiver

题目: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(没有检测到开始有效位时)、START、BIT1、BIT2…BIT8、STOP(成功检测到结束有效位)、ERROR(没有检测到结束有效位);
2.如果进入ERROR状态,即使几个时钟周期过后检测到结束有效位,也不会判断位STOP,而是直接进入IDLE等待下一个开始有效位;
3.STOP状态下如果检测到开始有效位,则不进入IDLE而直接进入START状态,否则再进入IDLE状态;

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 
    reg [3:0] state;
    reg [3:0] next_state;
    parameter IDLE=4'b0000;
    parameter BIT1=4'b0001;
    parameter BIT2=4'b0010;
    parameter BIT3=4'b0011;
    parameter BIT4=4'b0100;
    parameter BIT5=4'b0101;
    parameter BIT6=4'b0110;
    parameter BIT7=4'b0111;
    parameter BIT8=4'b1000;
    parameter STOP=4'b1001;
    parameter START=4'b1011;
    parameter ERROR=4'b1010;
    //flip flops
    always@(posedge clk) begin
        if (reset) state<=IDLE;
        else state<=next_state;
    end
    
    //state transition
    always@(*) begin
        case(state) 
            IDLE: next_state=(in==0)?START:IDLE;
            START: next_state=BIT1;
            BIT1: next_state=BIT2;
            BIT2: next_state=BIT3;
            BIT3: next_state=BIT4;
            BIT4: next_state=BIT5;
            BIT5: next_state=BIT6;
            BIT6: next_state=BIT7;
            BIT7: next_state=BIT8;
            BIT8: next_state=(in==1)?STOP:ERROR;
            STOP: next_state=(in==1)?IDLE:START;
            //ERROR之后即使出现1(停止符),状态也不会变为STOP了,而是变为IDLE
            ERROR: next_state=(in==1)?IDLE:ERROR;
            default: next_state=IDLE;
        endcase
    end
    
    //output logic
    always@(*) begin
        if (reset) done=1'b0;
        //停止符1输入时,next_state变为STOP,在下一个时钟上升沿state变为STOP,因此state变为STOP时,即输出done信号
        else if (state==STOP) done=1'b1;
        else done=1'b0;
    end

endmodule

FSM Serial Receiver with datapath

题目:Now that you have a finite state machine that can identify when bytes are correctly received in a serial bitstream, add a datapath that will output the correctly-received data byte. out_byte needs to be valid when done is 1, and is don’t-care otherwise.

Note that the serial protocol sends the least significant bit first.
在这里插入图片描述
分析:
再添加组合逻辑,使得state==STOP时(或者done等于1时),输出out_byte即可,而out_byte的每一位可以在状态机在BIT1…BIT8的过程中依次进行赋值(和ps2data对比,此处不需要寄存器暂存,因为即使前后两个数据紧密相接,也只是在STOP时接收到下一个数据的开始有效位,并不是真正的数据。

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //
    // Use FSM from Fsm_serial
    reg [3:0] state;
    reg [3:0] next_state;
    parameter IDLE=4'b0000;
    parameter BIT1=4'b0001;
    parameter BIT2=4'b0010;
    parameter BIT3=4'b0011;
    parameter BIT4=4'b0100;
    parameter BIT5=4'b0101;
    parameter BIT6=4'b0110;
    parameter BIT7=4'b0111;
    parameter BIT8=4'b1000;
    parameter STOP=4'b1001;
    parameter START=4'b1011;
    parameter ERROR=4'b1010;
    //flip flops
    always@(posedge clk) begin
        if (reset) state<=IDLE;
        else state<=next_state;
    end
    
    //state transition
    always@(*) begin
        case(state) 
            IDLE: next_state=(in==0)?START:IDLE;
            START: next_state=BIT1;
            BIT1: next_state=BIT2;
            BIT2: next_state=BIT3;
            BIT3: next_state=BIT4;
            BIT4: next_state=BIT5;
            BIT5: next_state=BIT6;
            BIT6: next_state=BIT7;
            BIT7: next_state=BIT8;
            BIT8: next_state=(in==1)?STOP:ERROR;
            STOP: next_state=(in==1)?IDLE:START;
            //ERROR之后即使出现1(停止符),状态也不会变为STOP了,而是变为IDLE
            ERROR: next_state=(in==1)?IDLE:ERROR;
            default: next_state=IDLE;
        endcase
    end
    
    //output logic
    always@(*) begin
        if (reset) done=1'b0;
        //停止符1输入时,next_state变为STOP,在下一个时钟上升沿state变为STOP,因此state变为STOP时,即输出done信号
        else if (state==STOP) done=1'b1;
        else done=1'b0;
    end
    
    // New: Datapath to latch input bits.
    reg [7:0] out_temp;
    /*
    always@(*) begin
        case (state)
    */
    always@(posedge clk) begin
        case(next_state)
            IDLE:;
            START:;
            BIT1:out_temp[0]=in;
            BIT2:out_temp[1]=in;
            BIT3:out_temp[2]=in;
            BIT4:out_temp[3]=in;
            BIT5:out_temp[4]=in;
            BIT6:out_temp[5]=in;
            BIT7:out_temp[6]=in;
            BIT8:out_temp[7]=in;
            STOP:;
            ERROR:;
        endcase
    end
    
    always@(*) begin
        if (reset) begin
            out_temp=8'bx;
            out_byte=8'bx;
        end
        else if (state==STOP) out_byte=out_temp;
        else begin
            out_byte=8'bx;
        end
    end

endmodule

ps: 在这里对out_temp进行赋值时,不知道为什么posedge clk+next_state成功,但是*+state不成功(理论上每个时钟上升沿将next_state赋值给state,这两个逻辑应该相等??)

FSM Serial Receiver with parity chech

题目:We want to add parity checking to the serial receiver. Parity checking adds one extra bit after each data byte. We will use odd parity, where the number of 1s in the 9 bits received must be odd. For example, 101001011 satisfies odd parity (there are 5 1s), but 001001011 does not.

Change your FSM and datapath to perform odd parity checking. Assert the done signal only if a byte is correctly received and its parity check passes. Like the serial receiver FSM, this FSM needs to identify the start bit, wait for all 9 (data and parity) 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.

You are provided with the following module that can be used to calculate the parity of the input stream (It’s a TFF with reset). The intended use is that it should be given the input bit stream, and reset at appropriate times so it counts the number of 1 bits in each byte.

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

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

endmodule

Note that the serial protocol sends the least significant bit first, and the parity bit after the 8 data bits.

分析:
1.由于需要进行奇偶校验(也就是添加第九位数据位),因此状态机的状态需要添加PARITY,在PARITY状态下,完成原来BIT8位完成的工作,即如果检测到结束有效位(in==1),则进入STOP状态,否则进入ERROR状态(至于odd是否判断正确,在output logic中再进行判断);
2.在输出逻辑中,只有state等于STOP且odd为1时,输出done,进而输出out_byte;
3.对于odd判断逻辑(题目中提供),需要重新设定reset信号,因为该逻辑块中,reset信号不止是全局reset有效时有效,除此之外,每完成一个数据输出后,odd需置为0重新进行判断;

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
    // flip flop
    parameter IDLE=4'b0000;
    parameter START=4'b0001;
    parameter BIT1=4'b0010;
    parameter BIT2=4'b0011;
    parameter BIT3=4'b0100;
    parameter BIT4=4'b0101;
    parameter BIT5=4'b0110;
    parameter BIT6=4'b0111;
    parameter BIT7=4'b1000;
    parameter BIT8=4'b1001;
    parameter PARITY=4'b1010;
    parameter STOP=4'b1011;
    parameter ERROR=4'b1100;
    reg [3:0] state;
    reg [3:0] next_state;
    always@(posedge clk) begin
        if (reset) state<=IDLE;
        else state<=next_state;
    end
    
    //transition logic
    wire odd;
    always@(*) begin
        case(state)
            IDLE: next_state=(in==1'b0)?START:IDLE;
            START: next_state=BIT1;
            BIT1: next_state=BIT2;
            BIT2: next_state=BIT3;
            BIT3: next_state=BIT4;
            BIT4: next_state=BIT5;
            BIT5: next_state=BIT6;
            BIT6: next_state=BIT7;
            BIT7: next_state=BIT8;
            BIT8: next_state=PARITY;
            PARITY: next_state=(in)?STOP:ERROR;
            ERROR: next_state=(in)?IDLE:ERROR;
            STOP: next_state=(in==1'b0)?START:IDLE;
        endcase
    end
    
    //output logic
    always@(posedge clk) begin
        if (reset) done=1'b0;
        else if (next_state==STOP && odd) done=1'b1;
        else done=1'b0;
    end
    
    //datapath
    reg [7:0] out_temp;
    always@(posedge clk) begin
        case(next_state)
            BIT1:out_temp[0]<=in;
            BIT2:out_temp[1]<=in;
            BIT3:out_temp[2]<=in;
            BIT4:out_temp[3]<=in;
            BIT5:out_temp[4]<=in;
            BIT6:out_temp[5]<=in;
            BIT7:out_temp[6]<=in;
            BIT8:out_temp[7]<=in;
        endcase
    end
    
    always@(*) begin
        if (reset) begin
            out_byte=8'bx;
            out_temp=8'bx;
        end
        else if (done) out_byte=out_temp;
        else out_byte=8'bx;
    end
        
    // New: Add parity checking.
    wire reset_p;
    assign reset_p=(next_state==START||reset==1'b1);
    parity my_parity(
    .clk(clk),
    .reset(reset_p),
    .in(in),
    .odd(odd));

endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值