1、奇偶校验
奇偶校验(Parity Check)是一种校验代码传输正确性的方法。根据被传输的一组二进制数位中“1”的个数是奇数或偶数来进行校验。采用奇数的称为奇校验,反之,称为偶校验。采用何种校验是事先规定好的。通常专门设置一个奇偶校验位,用它使这组代码中“1”的个数为奇数或偶数。若用奇校验,则当接收端收到这组代码时,校验“1”的个数是否为奇数,从而确定传输代码的正确性。
举例,要输出一组8-bit数据,为“11101000”,该组数据共有4个“1”。若使用奇校验,则校验位应为1,传输数据实际为8-bit数据+1-bit奇校验位,即“111010001”;若使用偶校验,则校验位应为0,传输数据实际为8-bit数据+1-bit偶校验位,即“111010000”。
2、输入数据的校验方法
根据输入串行数据码流,“实时”生成所输入数据的校验位。
2.1、举例
欲串行接收数据“11101000”(传输低位在前,高位在后),则数据线上的数据应为“0-0-0-1-0-1-1-1”
奇校验应为“x-1-1-1-0-0-1-0-1”(采用时序逻辑输出,会落后一个时钟周期)
偶校验应为“x-0-0-0-1-1-0-1-0”(采用时序逻辑输出,会落后一个时钟周期)
校验位刚好落后数据一个时钟周期,方便拼接。
时序图如下:
输出信号odd根据输入信号变化,假如输入数据只输入4-bit,0001,则奇校验位0,偶校验位1,可以看到在输入信号的下一个周期,odd、even的输出符合预期,其他数据相同,这里不赘述。
奇校验实现方式:校验位默认为高电平,每检测到1,则状态翻转
偶校验实现方式:校验位默认为低电平,每检测到1,则状态翻转
2.2、verilog实现
根据上述,编写如下代码:
module odd_even1(
input clk ,
input in , //串行输入
input reset , //同步复位,高电平有效
output reg odd , //奇校验位
output reg even //偶校验位
);
always@(posedge clk)begin
if(reset)begin
odd <= 1'b1;
even <= 1'b0;
end
else if(in)begin
odd <= ~odd;
even <= ~even;
end
else begin
odd <= odd;
even <= even;
end
end
endmodule
2.3、testbench仿真
编写仿真对上述模块进行测试,激励输入随机生成0或1.
`timescale 1ns/1ns //时间单位/精度
//------------<模块及端口声明>----------------------------------------
module tb_odd_even1();
reg clk ;
reg in ;
reg reset ;
wire odd ;
wire even ;
//------------<例化被测试模块>----------------------------------------
odd_even1 odd_even1_inst(
.clk (clk),
.reset (reset),
.in (in),
.odd (odd),
.even (even)
);
//------------<设置初始测试条件>----------------------------------------
initial begin
clk = 1'b1; //初始时钟为1
reset <= 1'b1; //初始复位
#20
reset <= 1'b0;
end
//------------<设置时钟>----------------------------------------------
always #10 clk = ~clk; //系统时钟周期20ns
always #20 in <= {$random}%2; //每20ns随机生成0或1
endmodule
2.4、仿真结果
仿真结果如下:
假设两黄线中间刚好传输了一次8-bit数据,则传输的数据应为1011_1111 (低位在前),那么这组数据的奇校验位应是:0 ;偶校验位应是:1 ;上图中蓝色字体标注与理论一直,而输入数据的第九位为1,则可视为一次偶校验。
通过比对数据码流上的第九位(校验位)与输出的奇偶校验结果,就可以判断这次数据接收是否成功。
3、输出数据的校验方法
除了对接收数据的正确性做奇偶校验外,同时也需要对输出给的外部数据提供一个奇偶校验结果,方便外部模块比对数据是否传输正常。
3.1、举例
仅对输出数据为8-bit的情况做示例,其他位宽原理一致。
欲串行发送数据“11101000”:
奇校验结果应为“1”,实际应传输“111010001”:
偶校验结果应为“0”,实际应传输“111010000”:
实现方法:
根据异或的定义:相异为1,相同为0。可推出:偶数个1异或的结果为0,奇数个1异或的结果为1。所以:
偶校验:将输入数据按位异或
奇校验:将输入数据按位异或再取反(与偶校验相反)
3.2、verilog实现
根据上述,编写如下代码:
module odd_even2(
input clk ,
input [7:0] in , //并行输入
input reset , //同步复位,高电平有效
output reg odd , //奇校验位
output reg even //偶校验位
);
always@(posedge clk)begin
if(reset)begin
odd <= 1'b0;
even <= 1'b0;
end
else begin
odd <= ~(^in);
even <= ^in;
end
end
endmodule
3.3、testbench仿真
编写仿真对上述模块进行测试,激励输入随机生成8-bit数据:
`timescale 1ns/1ns //时间单位/精度
//------------<模块及端口声明>----------------------------------------
module tb_odd_even2();
reg clk ;
reg [7:0] in ;
reg reset ;
wire odd ;
wire even ;
//------------<例化被测试模块>----------------------------------------
odd_even2 odd_even2_inst(
.clk (clk),
.reset (reset),
.in (in),
.odd (odd),
.even (even)
);
//------------<设置初始测试条件>----------------------------------------
initial begin
clk = 1'b1; //初始时钟为0
reset <= 1'b1; //初始复位
#20
reset <= 1'b0;
end
//------------<设置时钟>----------------------------------------------
always #10 clk = ~clk; //系统时钟周期20ns
always #20 in <= {$random}%256; //每20ns随机生成8-bit数据
endmodule
3.4、仿真结果
仿真结果如下:
- 由于使用的时序逻辑,所以校验位的输出会落后输入数据一个时钟周期
- 输入数据“00100100”,奇校验位应为:1 偶校验位应为:0 ,仿真结果与分析一致。其他数据不分析了,都时满足要求的
4、总结
- 奇偶校验属于是一种比较简单的校验方式,效率比较低(如果传输过程中偶数个位同时错误,则无法校验出来),但是对于一般要求不严格的场合还是应用的较多,需要熟练掌握
- 需要工程的同学可以评论留下邮箱