论述:Verilog中的奇偶校验
更新历史
20200123:
- 首次发布
在用Verilog写UART通信的逻辑代码时,遇到了"对数据做奇偶校验"的需求,网上一搜就得到了解决办法。感谢万能的网友之余,我还是想把Verilog中奇偶校验的原理用更加易于理解的方式描述一遍,故发此文。
奇偶校验的定义如下图所示:
对数据做奇偶校验的Verilog模块代码如下:
module generate_parity_bit
#(
parameter DATA_WIDTH = 8,
parameter PARITY_TYPE = "even parity" //允许的取值:"even parity" 或 "odd parity"
)
(
input [DATA_WIDTH-1:0] data_in,
output parity_bit_out
);
wire even_bit;//偶校验需求下计算出来的校验位
wire odd_bit; //奇校验需求下计算出来的校验位
assign even_bit = ^data_in;
assign odd_bit = ~even_bit;
if(PARITY_TYPE == "even parity")
begin
assign parity_bit_out = even_bit;
end
else
begin
assign parity_bit_out = odd_bit;
end
endmodule
举例来说明generate_parity_bit 模块的工作原理:
data_in | 校验方式 | data_in中"1"的数量 | parity_bit_out输出结果 | data_in 和 parity_bit_out 中"1"的总数 | |
---|---|---|---|---|---|
8’b0000_1111 | 偶校验(PARITY_TYPE = “even parity”) | 偶数 | 1’b0 | 偶数(该结果与校验方式一致) | |
8’b0000_1111 | 奇校验(PARITY_TYPE = “odd parity”) | 偶数 | 1’b1 | 奇数(该结果与校验方式一致) | |
8’b0000_1110 | 偶校验(PARITY_TYPE = “even parity”) | 奇数 | 1’b1 | 偶数(该结果与校验方式一致) | |
8’b0000_1110 | 奇校验(PARITY_TYPE = “odd parity”) | 奇数 | 1’b0 | 奇数(该结果与校验方式一致) |
从上面的例子中,不难看出Verilog模块代码中assign odd_bit = ~even_bit;
的原理,即:
- 若数据和校验位合起来能满足偶校验的需求,则数据和取反后的校验位合起来能满足奇校验的需求
相比之下,assign even_bit = ^data_in;
则没有那么直观易懂,这里对其进行解释。在Verilog中,^
运算符作为单目运算符时的功能是"按位异或",作为双目运算符时的功能是"异或"。当data_in是一个8 bit的数据时,^data_in = data_in[0] ^ data_in[1] ^ data_in[2] ^ data_in[3] ^ data_in[4] ^ data_in[5] ^ data_in[6] ^ data_in[7]
。表2给出了 ^data_in的值与data_in二进制码中"1"的个数之间的关系,表3给出了偶校验位(偶校验情况下的校验位)的值与data_in二进制码中"1"的个数之间的关系。通过观察表2和表3,我们不难得出一个结论,那就是:^data_in
的值和偶校验位的值是相同的。
data_in二进制码中"1"的个数 | ^data_in 的值 |
---|---|
奇数 | 1 |
偶数 | 0 |
data_in二进制码中"1"的个数 | 偶校验位的值 |
---|---|
奇数 | 1 |
偶数 | 0 |
那么问题来了,我们该怎样理解^data_in
和偶校验位之间的关系呢?难道两者的值相同纯属巧合吗?其实不是。我们可以来看看下图:
从上图中可以看到:
- 二进制码求和运算的结果与常理相符:奇数个1的求和结果最低位是奇数,偶数个1的求和结果最低位是偶数。对于二进制来说,“一比特的数据是奇数” 等效于 “该比特为1”,“一比特的数据是偶偶数” 等效于 “该比特为0”。
- A、B、……、N为一比特的数据时,
(A^B^...^N)的结果
跟(A+B+...+N)结果的最低位
相同——所以,k个一比特数据的异或运算可以被视为"k个一比特数据在不考虑进位和溢出问题时的求和运算"。
因此,^data_in
和偶校验位之间的关系可以理解为:对data_in二进制码中所有的比特位进行求和,
- 若求和结果的最低位为1(表现为
^data_in = 1
),说明data_in中"1"的数量为奇数,偶校验位应当为1 (从而使得data_in和校验位中"1"的总数为偶数); - 若求和结果的最低位为0(表现为
^data_in = 0
),说明data_in中"1"的数量为偶数,偶校验位应当为0 (从而使得data_in和校验位中"1"的总数为偶数)。