题目:https://hdlbits.01xz.net/wiki/Fsm_serialdp
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.
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
// Use FSM from Fsm_serial
parameter IDLE = 0, START = 1, DATA_T = 2, STOP = 3, WRONG = 4, PAR = 5;
reg [2:0] state, next_state;
always @(posedge clk) begin
if(reset)
state <= IDLE;
else
state <= next_state;
end
always @(*) begin
case(state)
IDLE : next_state = !in ? START : IDLE;
START : next_state = DATA_T;
DATA_T : next_state = (cnt < 7) ? DATA_T : PAR;
STOP : next_state = in ? IDLE : START;
WRONG : next_state = in ? IDLE : WRONG;
PAR : next_state = in ? STOP : WRONG;
default : next_state = IDLE;
endcase
end
reg [3:0] cnt;
always @(posedge clk) begin
if(reset)
cnt <= 4'd0;
else begin
if(state == START)
cnt <= 4'd0;
else
cnt <= cnt + 1;
end
end
//output
assign done = (state == STOP) && !odd;
reg [7:0] data_r;
// New: Datapath to latch input bits.
always @(posedge clk) begin
if(reset)
data_r <= 8'd0;
else begin
data_r <= (next_state == DATA_T) ? {in, data_r[7:1]} : data_r;
end
end
always @(*) begin
if(done)
out_byte <= data_r;
else
out_byte <= out_byte;
end
// New: Add parity checking.
wire rst_p;
wire odd;
parity u_dut(.clk(clk), .reset(rst_p), .in(in), .odd(odd));
assign rst_p = (next_state == START) || reset;
endmodule