HDLBits: Fsm serialdp 刷题记录

See also: Serial receiver and datapath

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.

Some timing diagrams

No framing errors. Odd parity passes for first byte, fails for second byte.

Module Declaration

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

这道题需要注意的点是,当接收完 8 bits 数据后,还需要接收 1 bit 的校验位。这个校验位需要先经过校验模块处理(经历一个时钟周期),然后再被主模块采样。因此,主模块对校验位和停止位的采样发生在同一个时钟周期。

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

  parameter IDLE                           = 6'b0000_01;
  parameter SAMPLE_START                   = 6'b0000_10;
  parameter BITSTREAM                      = 6'b0001_00;
  parameter WAIT                           = 6'b0010_00;
  parameter SAMPLE_PARITY_STOP             = 6'b0100_00;
  parameter ERROR                          = 6'b1000_00;

  reg [5:0] cur_state, nxt_state;
  reg [3:0] bits_cnt;
  reg [7:0] out_byte_q;

  wire odd;
  reg parity_reset;

  parity u_parity(
           clk,
           parity_reset,
           in,
           odd
         );

  //fms
  always @(*)
  begin
    case (cur_state)
      IDLE:
      begin
        nxt_state = in?IDLE:SAMPLE_START;
      end

      SAMPLE_START:
      begin
        nxt_state = BITSTREAM;
      end

      BITSTREAM:
      begin
        nxt_state = (bits_cnt == 4'h8)?WAIT:BITSTREAM;
      end

      WAIT:
      begin
        case({odd,in})
          2'b00:
            nxt_state = ERROR;
          2'b01:
            nxt_state = IDLE;
          2'b10:
            nxt_state = ERROR;
          2'b11:
            nxt_state = SAMPLE_PARITY_STOP;
          default:
            nxt_state = IDLE;
        endcase
      end

      SAMPLE_PARITY_STOP:
      begin
        nxt_state = in?IDLE:SAMPLE_START;
      end

      ERROR:
      begin
        nxt_state = in?IDLE:ERROR;
      end

      default:
      begin
        nxt_state = IDLE;
      end
    endcase
  end

  always @(posedge clk)
  begin
    if(reset)
      cur_state <= IDLE;
    else
      cur_state<= nxt_state;
  end
  //

  //bits_cnt
  always @(posedge clk)
  begin
    if(reset)
      bits_cnt <= 4'h0;
    else if(bits_cnt == 4'h8)
      bits_cnt <= 4'h0;
    else if(cur_state == SAMPLE_START || cur_state == BITSTREAM)
      bits_cnt <= bits_cnt + 1'h1;
    else
      bits_cnt <= 4'h0;
  end

  always @(posedge clk)
  begin
    if(reset)
      out_byte_q <= 8'h0;
    else if(cur_state == SAMPLE_PARITY_STOP)
      out_byte_q <= 8'h0;
    else if(cur_state == SAMPLE_START || (cur_state == BITSTREAM && bits_cnt < 8'h8))
      out_byte_q <= {in,out_byte_q[7:1]};
    else
      out_byte_q <= out_byte_q;
  end

  always @(posedge clk)
  begin
    if(reset)
      parity_reset <= 1'h1;
    else
    begin
      case(cur_state)
        IDLE:
        begin
          parity_reset = in?1'h1:1'h0;
        end

        SAMPLE_START:
        begin
          parity_reset = 1'h0;
        end

        BITSTREAM:
        begin
          parity_reset = 1'h0;
        end

        WAIT:
        begin
          parity_reset = 1'h1;
        end

        SAMPLE_PARITY_STOP:
        begin
          parity_reset = 1'h1;
        end

        ERROR:
        begin
          parity_reset = 1'h1;
        end

        default:
        begin
          parity_reset = 1'h1;
        end
      endcase
    end
  end

  assign done = cur_state == SAMPLE_PARITY_STOP;
  assign out_byte = out_byte_q;

  // Modify FSM and datapath from Fsm_serialdata

  // New: Add parity checking.

endmodule

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值