实现汉明纠错码的编码和解码方案设计

编码与解码

54人已加入

描述

本实验的目的是实现汉明纠错码的编码和解码

1.1汉明码简介

汉明码,是在电信领域的一种线性调试码,以发明者理查德 卫斯理 汉明的名字命名。汉明码在传输的消息流中插入验证码,当计算机存储或移动数据时,可能会产生数据位错误,以侦测并更正单一比特错误。由于汉明编码简单,他们被广泛应用于内存。

与其他的错误校验码类似,汉明码也利用了奇偶校验位的概念,通过在数据位后面增加一些比特,可以验证数据的有效性。利用一个以上的校验位,汉明码不仅可以检验数据是否有效,还能在数据出错的情况下指明错误的位置。(汉明码可以检测两位错误,纠正一位错误)。

1.2编码规则

理解汉明码首先要理解奇偶校验,奇校验就是在一串编码里增加一位校验位使这一串编码里的1的个数位奇数。偶校验同理,使编码里1的个数为偶数。

汉明码的编码位数n与纠错码的位数k的关系:2^k >= n+k+1。这里给出常用的n和k的值:

n 1 2-4 5-11 12-26 27-57 58-120
k 2 3 4 5 6 7

我们将纠错码加入到相应的编码里,纠错码的位置必须在2^n位置上。以10101100为例进行编码。这个序列为8位,需要4个纠错码。我们先将序列从1到8编号

1 2 3 4 5 6 7 8
1 0 1 0 1 1 0 0

然后将纠错码(p1,p2,p3,p4)加到这个序列里 的2^n的位置,并用二进制重新编号

0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100
p1 p2 1 p3 0 1 0 p4 1 1 0 0

然后我们要求出p1,p2,p3,p4的值,先将上面的序列分组编号为xxx1的分为一组,xx1x 的分为一组,x1xx的分为一组,1xxx的分为一组:

xxx1:p1,1,0,0,1,0

xx1x:p2,1,1,0,1,0

x1xx:p3,0,1,0,0

1xxx:p4,1,1,0,0

我们采用偶校验,所以p1 = 1,p2 = 1, p3 = 1, p4 = 0。这样我们就得到了10101100的汉明码111101001100。

那么汉明码是如何来纠错的呢?

我们将p4,p3,p2,p1按这个顺序排列得到0111,这个就是出错的位数,由于是二进制传输,所以就将相应位取反就可以得到正确的序列了。

1.3FPGA实现

对于p1,p2,p3,p4的计算在用fpga实现时只需进行按位异或就行。输入数据位8位,需要四个纠错位。

1.3.1 顶层架构
 

汉明码


 

信号说明

信号 功能 说明
clk 工作时钟 外部输入
rst_n 系统复位 外部输入
data 输入数据 外部输入
wren 写使能 外部输入
rden 读使能 外部输入
q 输出数据 输出
hc_out 经过汉明编码后输出 输出
hc_in 输入的汉明码 外部输入

顶层代码

module humming_coder12_8(clk, rst_n, data, q, rden, wren, hc_out, hc_in);


input clk, rst_n;
input [7:0] data;
output [7:0] q;
input rden, wren;
output [11:0] hc_out;
input [11:0] hc_in;


hamming_encoder HE(
.clk(clk),
.rst_n(rst_n),
.wren(wren),
.data(data),
.hc_out(hc_out)
);


hamming_decoder HD(
.clk(clk),
.rst_n(rst_n),
.rden(rden),
.q(q),
.hc_in(hc_in)
);


endmodule


1.3.2 编码模块

编码模块只需将分组之后的每一组数据(不包括p)按位异或后赋值给p就可以

编码模块代码

module hamming_encoder(clk, rst_n, wren, data, hc_out);


input clk, rst_n;
input wren;
input [7:0] data;
output reg [11:0] hc_out;


wire p0, p1, p2, p3;


assign p0 = data[6] ^ data[4] ^ data[3] ^ data[1] ^ data[0];
assign p1 = data[6] ^ data[5] ^ data[3] ^ data[2] ^ data[0];
assign p2 = data[7] ^ data[3] ^ data[2] ^ data[1];
assign p3 = data[7] ^ data[6] ^ data[5] ^ data[4];


always @ (posedge clk or negedge rst_n)begin
IF(!rst_n)
hc_out <= 0;
else if(wren)
hc_out <= {data[7:4], p3, data[3:1],p2, data[0], p1, p0};
else
hc_out <= 0;
end


endmodule

 

1.3.3解码模块

解码模块只需判断哪位出错,然后取反,并将纠错位删除即可

解码模块代码

module hamming_decoder(clk, rst_n, rden, q, hc_in);


input clk, rst_n;
input rden;
output reg [7:0] q;
input [11:0] hc_in;


wire g0_error, g1_error, g2_error,g3_error;


assign g0_error = hc_in[10] ^ hc_in[8] ^ hc_in[6] ^ hc_in[4] ^ hc_in[2] ^ hc_in[0];
assign g1_error = hc_in[10] ^ hc_in[9] ^ hc_in[6] ^ hc_in[5] ^ hc_in[2] ^ hc_in[1];
assign g2_error = hc_in[11] ^ hc_in[6] ^ hc_in[5] ^ hc_in[4] ^ hc_in[3];
assign g3_error = hc_in[11] ^ hc_in[10] ^ hc_in[9] ^ hc_in[8] ^ hc_in[7];


always @ (posedge clk or negedge rst_n)begin
if(!rst_n)
q <= 0;
else if(rden)
case ({g3_error, g2_error, g1_error, g0_error})
4'b0000 : q <= {hc_in[11:8], hc_in[6:4], hc_in[2]};
4'b0001 : q <= {hc_in[11:8], hc_in[6:4], hc_in[2]};
4'b0010 : q <= {hc_in[11:8], hc_in[6:4], hc_in[2]};
4'b0011 : q <= {hc_in[11:8], hc_in[6:4], ~hc_in[2]};
4'b0100 : q <= {hc_in[11:8], hc_in[6:4], hc_in[2]};
4'b0101 : q <= {hc_in[11:8], hc_in[6:5], ~hc_in[4], hc_in[2]};
4'b0110 : q <= {hc_in[11:8], hc_in[6], ~hc_in[5], hc_in[4], hc_in[2]};
4'b0111 : q <= {hc_in[11:8], ~hc_in[6], hc_in[5], hc_in[4], hc_in[2]};
4'b1000 : q <= {hc_in[11:8], hc_in[6], hc_in[5], hc_in[4], hc_in[2]};
4'b1001 : q <= {hc_in[11:9], ~hc_in[8], hc_in[6:4], hc_in[2]};
4'b1010 : q <= {hc_in[11:10], ~hc_in[9], hc_in[8], hc_in[6:4], hc_in[2]};
4'b1011 : q <= {hc_in[11], ~hc_in[10], hc_in[9], hc_in[8], hc_in[6:4], hc_in[2]};
4'b1100 : q <= {~hc_in[11], hc_in[10], hc_in[9], hc_in[8], hc_in[6:4], hc_in[2]};
default : q <= 0;
endcase
else
q <= 0;
end


endmodule


仿真验证

我们用$random系统函数产生的随机数来作为编码模块数据,用$random系统函数产生的随机数来将hc_out的哪一位取反来模拟噪声。并判断输入的数据和输出的数据是否相等,以验证纠错功能。用$display和$error系统函数来生成报告。

测试文件代码

module humming_coder12_8_tb;


reg clk, rst_n;
reg [7:0] data;
reg rden, wren;
wire [11:0] hc_out;
reg [11:0] hc_in;
wire [7:0] q;


reg [7:0] temp1, temp2;


humming_coder12_8 DUT(
.clk(clk),
.rst_n(rst_n),
.data(data),
.wren(wren),
.q(q),
.rden(rden),
.hc_out(hc_out),
.hc_in(hc_in)
);


integer pn, i;


initial begin
pn = 0;
hc_in = 0;


forever begin
@ (posedge clk)
pn = {$random} %12;
#1
for (i=0; i<12; i=i+1) begin
if (i!= pn)
hc_in = hc_out;
else
hc_in = ~hc_out;
end
end
end


always @ (posedge clk)
begin
temp1 <= data;
temp2 <= temp1;
end
always @ (*)
begin
if (wren) begin
#1
if (temp2 == q)
$display("OK:time=%0t data=%0d q=%0d", $time, temp2, q);
else
$error("ERROR:time=%0t data=%0d q=%0d", $time, temp2, q);
end
end


initial begin
clk = 1;
rst_n = 0;
data = 0;
rden = 0;
wren = 0;


#200
@ (posedge clk)
rst_n = 1;


#200
forever begin
@ (posedge clk)
wren = 1;
data = {$random} % 9'b10000_0000;
@ (posedge clk)
wren = 1;
data = {$random} % 9'b10000_0000;
rden = 1;
end
end
always #10 clk = ~clk;
initial #5000 $stop;
endmodule


生成的报告,我们可以看到错误的数据可以被修改成原来正确的数据,证明我们的编码解码模块功能正确

汉明码

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分