HDLBits网址:https://hdlbits.01xz.net/wiki/Main_Page
题目
我们要向串行接收器添加奇偶校验。奇偶校验在每个数据字节后增加一个额外的位。将使用奇数奇偶校验,其中接收到的9位中1的数量必须为奇数。例如,101001011满足奇偶校验(有5个1),而001001011不满足。
更改上面的FSM和数据路径以执行奇偶校验。仅当正确接收到一个字节且其奇偶校验通过时,才声明完成信号。像串行接收器FSM一样,该FSM需要标识起始位,等待所有9位(数据和奇偶校验),然后验证终止位是否正确。如果在预期的情况下没有出现停止位,则FSM必须等待直到找到停止位,然后再尝试接收下一个字节。
提供了以下模块,该模块可用于计算输入流的奇偶校验(这是带复位的TFF)。预期的用途是应该为它提供输入位流,并在适当的时间进行重置,以便它计算每个字节中1位的数目。
请注意,串行协议首先发送最低有效位,然后在8个数据位之后发送奇偶校验位。
module parity (
input clk,
input reset,
input in,
output reg odd);
always @(posedge clk)
if (reset) odd <= 0;
else if (in) odd <= ~odd;
endmodule
没有成帧错误。奇偶校验通过第一个字节,通过第二个字节失败,波形如下:
Module Declaration
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
);
我的设计
原理之前的文章一样,本设计采用5个状态,其中IDLE状态是起始状态,当起始位为0的时候,才开始数据传输(即跳到DATA状态),否则保持IDLE状态;DATA状态用一个cnt计数,数到8(即接受到一个字节的数据和一个奇校验位)才跳到下一个状态CHECK;CHECK状态主要主要判断是连续发送(即STOP状态)还是停止位为0的错误等待(即ERROR状态)。数据的发送采用一个右移寄存器进行存放;奇偶校验功能直接调用题目所给的模块,需要注意的是,每次传输结束之后需要复位奇偶模块,因此有一个start寄存器充当复位信号;最后done信号在奇校验正确且数据正常接收结束(停止位为1)的情况下置1,否则置0,代码如下:
?
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
); //
?
parameter IDLE = 0, DATA = 1, CHECK = 2, STOP = 3, ERROR = 4;
reg[2:0] state, next_state;
reg[3:0] cnt;
reg[7:0] out;
reg check;
wire odd, start;
parity parity_inst(
.clk(clk),
.reset(reset | start),
.in(in),
.odd(odd));
//transition
always@(*)begin
start = 0;
case(state)
IDLE:begin
next_state = in?IDLE:DATA;
start=1;
end
DATA:
next_state = (cnt==8)?CHECK:DATA;
CHECK:
next_state = in?STOP:ERROR;
STOP:begin
next_state=in?IDLE:DATA;
start=1;
end
ERROR:
next_state = in?IDLE:ERROR;
endcase
end
//state
always@(posedge clk)begin
if(reset)
state<=IDLE;
else
state<=next_state;
end
//cnt
always@(posedge clk)begin
if(reset)
cnt<=0;
else
case(state)
DATA:cnt<=cnt+1;
default:cnt<=0;
endcase
end
//out
always@(posedge clk)begin
if(reset)
out<=0;
else
case(next_state)
DATA:out<={in,out[7:1]};
endcase
end
//check
always@(posedge clk)begin
if(reset)
check<=0;
else
check<=odd;
end
assign out_byte=out;
assign done=check&(state==STOP);
endmodule
微信公众号
建立了一个微信公众号“Andy的ICer之路”,此公众号主要分享数字IC相关的学习经验,做公众号的目的就是记录自己的学习过程,很多东西回过头来可能就忘记了,为了记住知识和分享知识,希望自己可以保持更新,有兴趣的朋友可以关注一下!