FPGA实现汉明码的编解码

详细的文字解释可以参考这个小伙伴写的→详细解释看这里

1. “奇偶校验”

我们规定好,一串编码里1的个数是偶数个,那么这串编码里携带的信息就是对的,否则就是错的。(这里统一用偶校验为例)

我们可以在开头对这串编码加一位校验码实现奇偶校验。

我们想传输10010这串码,那么在传输的时候,就传010010,其中在开头的0就是校验位。(不用凑,1已经为偶数

我们想传输10000这串码,那么在传输的时候,就传110000,其中在开头的1就是校验位。(凑个1,成偶数

2. 汉明码检错原理

 汉明码默认一串数据只错一位,所以检错纠错的个数都是1

在这里我们假设我们传输的信息是1234567,然后按一定的规则他们分成三组

分别是

P1:1,2,3,4

P2:2,4,5,6

P3:3,4 ,6,7

那么我们来看几种情况:

(1)如果只有第一组有数错误了,那肯定是1错了。

(2)如果第一第二组错了,而第三组没有错,那肯定是2错了。

(3)然后三组都错,那肯定是4错了。

这就是汉明码的检错原理了,我们找到错误的那个码,又因为二进制里面只有两个选项1和0,给错误的码改成相反的信息就完成了纠错

3. 分组原理

上面是把七个数分成了三组,具体方法是把位置1234567(这里刚好和值是一样的,不要理解错了,是位置!位置!位置!)换成二进制

 P0第一组就是二进制低位为1的,P1第二组就是第二位为1的,后面类似....

(先把校验位加进去原数据,才能得到编码分组)

4. 汉明码编码

下面的内容需要记一记,就是汉明码=数据码+校验码。

记1:校验码个数k→2^k >= n+k+1

假如有n个数据码,k个校验码,那么码错误的位置就会有n+k个,再加上一个没有错误的可能性,就有n+k+1种可能性。

那么k的个数只要满足  2^k >= n+k+1  即可(其实就是记这个公式。上面7个数,就是2^4=>=7+4+1=12,其实是需要4个校验码的)

记2:校验码位置→2的次方位置,2^0,2^1,2^3......,也就是1/2/4/8/16.........

 就是一串数据,校验位是固定的,我们的有效信息也是固定的

1=p0,2=p1,3=p2......

记3:分完组后每个组里面只有一个校验码

除了这个校验码,外面的都是有效信息

(先把校验位加进去原数据,才能得到编码分组)

5. 汉明码解码

 我们都知道怎么分组了,也知道校验码和信息的具体位置了,只要看看接收的数据有没有错就行了。(偶校验为例)

将分组按大到小 P3/P2/P1,排列,然后看每个组的有效信息是不是都是偶数,不是就是1,是的话就是0。然后得到下图

 然后根据最开始说的,就可以判断出哪个数是错了的,再取反纠正即可。

6.FPGA代码

因为我们的传输主要是以字节为单位,所以规定的输入是8bit(一个字节)

2^4>=8+4+1,所以有4个校验码,得到的编码后的数据是12位的。

(然后注意,代码中的位置是从0开始的,与上面位置1开始的不一样哦,注意)

编码部分:

发送data={0,1,2,3,4,5,6,7}              8bit数据

8变12,对应的应该是encode={p0,p1,0,1,p2,2,3,4,p3,5,6,7,8}

所以分组的时候对应的位置应该是{3,5,6,7,9,10,11,12}(位置从1开始的)

然后按二进制分类,得到p0 = 1,2,4,5,7(位置),对应的是data[0,1,3,4,6]

p1,p2,p3类似

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

译码部分:

8变12,对应的应该是encode={p0,p1,0,1,p2,2,3,4,p3,5,6,7,8}

所以按照1-12分组,就会得到g0_error = {1,3,5,7,9,11}(位置),对应的是encode=[0,2,4,6,8,10]

g1_error...... 类似

然后根据排列组合,把错纠正过来就OK了

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

 仿真结果:

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值