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.
AI翻译如下:
另请参阅:串行接收器和数据路径
我们想向串行接收器添加奇偶校验。奇偶校验在每个数据字节后添加一个额外的位。我们将使用奇数奇偶校验,其中接收的 9 位中的 1秒数必须是奇数。例如,101001011满足奇数奇偶校验(有 5 个 1秒),但 001001011 个不满足。
更改 FSM 和数据路径以执行奇偶校验。仅当正确接收到字节并且其奇偶校验通过时,才断言完成的信号。像串行接收器 FSM,则此 FSM 需要识别起始位,等待所有 9 个(数据和奇偶校验)位,然后验证停止位是否正确。如果停止位未按预期出现,则 FSM 必须等到找到停止位后再尝试接收下一个字节。
您将获得以下模块,可用于计算输入流的奇偶校验(它是具有重置功能的 TFF)。预期用途是应为其提供输入比特流,并在适当的时间重置,以便计算每个字节中的 1 位数。
module parity (
input clk,
input reset,
input in,
output reg odd);
always @(posedge clk)
if (reset) odd <= 0;
else if (in) odd <= ~odd;
endmodule
请注意,串行协议首先发送最低有效位,并在 8 个数据位之后发送奇偶校验位。
一些时序图
无取景错误。奇数奇偶校验对第一个字节通过,对第二个字节失败。
状态转换图:
这边不使用题目所给的函数,而是自行构造always语句块
代码如下
module top_module( input clk, input in, input reset, output [7:0] out_byte, output done ); //设置状态空间 parameter IDLE = 4'd0 ; parameter START = 4'd1 ; parameter BIT1 = 4'd2 ; parameter BIT2 = 4'd3 ; parameter BIT3 = 4'd4 ; parameter BIT4 = 4'd5 ; parameter BIT5 = 4'd6 ; parameter BIT6 = 4'd7 ; parameter BIT7 = 4'd8 ; parameter BIT8 = 4'd9 ; parameter STOP = 4'd10; parameter WAIT = 4'd11; parameter ODD_0 = 4'd12; parameter ODD_1 = 4'd13; //设置变量 reg [3:0] state; reg [3:0] next_state; reg [7:0] out_byte_reg;//输出寄存器 reg odd;//奇偶校验寄存 //状态如何跳转 always @(*) begin case(state) IDLE:next_state=in?IDLE:START; 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=(odd^in)?ODD_1 :ODD_0; ODD_0 :next_state=in ?IDLE :WAIT; ODD_1 :next_state=in ?STOP :WAIT ; STOP :next_state=in ?IDLE :START; WAIT :next_state=in ?IDLE:WAIT ; default:; endcase end //状态何时跳转 always@(posedge clk)begin if(reset)begin state<=IDLE; end else begin state<=next_state; end end //输出 assign done=(state==STOP); assign out_byte=done?out_byte_reg:out_byte; //数据储存,串转并 always@(posedge clk)begin if(reset) out_byte_reg<=8'd0; else begin case(state) START:out_byte_reg[0]<=in; BIT1 :out_byte_reg[1]<=in; BIT2 :out_byte_reg[2]<=in; BIT3 :out_byte_reg[3]<=in; BIT4 :out_byte_reg[4]<=in; BIT5 :out_byte_reg[5]<=in; BIT6 :out_byte_reg[6]<=in; BIT7 :out_byte_reg[7]<=in; default:; endcase end end //奇偶校验码转换 always@(posedge clk)begin if(reset) odd<=1'b0; else begin case(state) START:if(in) odd<=~odd;else odd<=odd; BIT1 :if(in) odd<=~odd;else odd<=odd; BIT2 :if(in) odd<=~odd;else odd<=odd; BIT3 :if(in) odd<=~odd;else odd<=odd; BIT4 :if(in) odd<=~odd;else odd<=odd; BIT5 :if(in) odd<=~odd;else odd<=odd; BIT6 :if(in) odd<=~odd;else odd<=odd; BIT7 :if(in) odd<=~odd;else odd<=odd; IDLE:odd<=1'b0;//复位 default:odd<=odd; endcase end end endmodule