「通信工程」拓展汉明码(16,11) eHamming(16,11) 编解码

Table of Contents

生成多项式

g(x) = [1 1 0 0 1]

编码

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Fansen
// Engineer: Fansen
// 
// Create Date: 2022/05/05 19:56:59
// Design Name: 
// Module Name: eHamming_n16_k11_encoder_v3
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description:  g(x) = 【1 1 0 0 1】
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module eHamming_n16_k11_encoder(
    clk,
    rst,
    start,
    din,
    din_clk_p,
    dout,
    dout_clk_p
    );
    input clk;
    input rst;
    input start;
    input din;
    input din_clk_p;
    output dout;
    output dout_clk_p;
//////////////////////////////////////////////////////////////////////////////////
// eHamming parameter
    parameter N = 16;
    parameter K = 11;
//////////////////////////////////////////////////////////////////////////////////
reg delay_din;
always @ (posedge clk or posedge rst)
begin
    if(rst)
    begin
    delay_din<=1'd0;
    end
    
    else
    begin
    delay_din<=din;//对输入信号延时一拍
    end
end

reg delay_din_clk_p;
always @ (posedge clk or posedge rst)
begin
    if(rst)
    begin
    delay_din_clk_p<=1'd0;
    end
    
    else
    begin
    delay_din_clk_p<=din_clk_p;//对输入信号延时一拍
    end
end
//////////////////////////////////////////////////////////////////////////////////
// Control
reg [7:0] cnts;
always @ (posedge clk or posedge rst) 
begin
    if (rst) 
    begin
    cnts <= 8'hff;
    end
    
    else if (start) 
    begin
    cnts <= 8'd0; 
    end
    
    else if(cnts <= N)
    begin
    cnts <= cnts + 1'b1;
    end
    
    else
    begin
    cnts <= cnts;
    end
end
//////////////////////////////////////////////////////////////////////////////////
reg [3:0] Reg;
always @ (posedge clk or posedge rst) 
begin
    if (rst) 
    begin
    Reg <= 4'h0;
    end
    
    else if (start) 
    begin
    Reg <= 4'h0;
    end
    
    else if(cnts < K)
    begin
        Reg[0] <= Reg[3] ^ delay_din;
        Reg[1] <= Reg[0] ^ Reg[3] ^ delay_din;
        Reg[2] <= Reg[1];
        Reg[3] <= Reg[2];
    end
    
    else
    begin
    Reg <= Reg;
    end
end
reg Check;
always @ (posedge clk or posedge rst)
begin
    if (rst) 
    begin
    Check <= 1'b0;
    end
    
    else if (start) 
    begin
    Check <= 1'b0;
    end
    
    else
    begin
    case (cnts)
        16'd0: begin Check <= Check ^ delay_din; end
        16'd1: begin Check <= Check ^ delay_din; end
        16'd2: begin Check <= Check ^ delay_din; end
        16'd3: begin Check <= Check ^ delay_din; end
        16'd4: begin Check <= Check ^ delay_din; end
        16'd5: begin Check <= Check ^ delay_din; end
        16'd6: begin Check <= Check ^ delay_din; end
        16'd7: begin Check <= Check ^ delay_din; end
        16'd8: begin Check <= Check ^ delay_din; end
        16'd9: begin Check <= Check ^ delay_din; end
        16'd10: begin Check <= Check ^ delay_din;end

        16'd11: begin Check <= Check ^ Reg[3]; end
        16'd12: begin Check <= Check ^ Reg[2]; end
        16'd13: begin Check <= Check ^ Reg[1]; end
        16'd14: begin Check <= Check ^ Reg[0]; end
        default: begin  Check <= Check;    end
    endcase
    end 
end

reg dout;  
always @ (posedge clk or posedge rst)
begin
    if (rst) 
    begin
    dout <= 1'b0;
    end
    
    else
    begin
    case (cnts)
        16'd0: begin dout <= delay_din; end
        16'd1: begin dout <= delay_din; end
        16'd2: begin dout <= delay_din; end
        16'd3: begin dout <= delay_din; end
        16'd4: begin dout <= delay_din; end
        16'd5: begin dout <= delay_din; end
        16'd6: begin dout <= delay_din; end
        16'd7: begin dout <= delay_din; end
        16'd8: begin dout <= delay_din; end
        16'd9: begin dout <= delay_din; end
        16'd10: begin dout <= delay_din; end

        16'd11: begin dout <= Reg[3]; end
        16'd12: begin dout <= Reg[2]; end
        16'd13: begin dout <= Reg[1]; end
        16'd14: begin dout <= Reg[0]; end
        16'd15: begin dout <= Check; end
        default: begin dout <= 1'b0; end
    endcase
    end
end

reg dout_clk_p;
always @ (posedge clk or posedge rst)
begin
    if (rst) 
    begin
    dout_clk_p <= 1'b0;
    end
    
    else
    begin
    case (cnts)
        16'd0: begin dout_clk_p <= 1'b1; end
        16'd16: begin dout_clk_p <= 1'b0; end
        default: begin dout_clk_p <= dout_clk_p; end
    endcase
    end
end

endmodule

解码

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2022/05/09 17:41:18
// Design Name: 
// Module Name: eHamming_n16_k11_decoder_v31
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module eHamming_n16_k11_decoder(
    clk,
    rst,
    start,
    din,
    din_clk_p,
    dout,
    dout_clk_p,
    code_num
    );
    input clk;
    input rst;
    input start;
    input din;
    input din_clk_p;
    output dout;
    output dout_clk_p;
    output [1:0] code_num;
//////////////////////////////////////////////////////////////////////////////////
// eHamming parameter
parameter N = 16;
parameter K = 11;
// ECC
reg pa_news; reg [3:0] temp; reg [1:0] code_num;
//////////////////////////////////////////////////////////////////////////////////
reg delay_din;
always @ (posedge clk or posedge rst)
begin
    if(rst)
    begin
    delay_din <= 1'd0;
    end
    
    else
    begin
    delay_din <= din;//对输入信号延时一拍
    end
end
reg delay_din_clk_p;
always @ (posedge clk or posedge rst)
begin
    if(rst)
    begin
    delay_din_clk_p <= 1'd0;
    end
    
    else
    begin
    delay_din_clk_p <= din_clk_p;//对输入信号延时一拍
    end
end
//////////////////////////////////////////////////////////////////////////////////
// Control
reg [7:0] cnts;
always @ (posedge clk or posedge rst) 
begin
    if (rst) 
    begin
    cnts <= 8'hff;
    end
    
    else if (start) 
    begin
    cnts <= 8'd0; 
    end
    
    else if(cnts <= 35)
    begin
    cnts <= cnts + 1'b1;
    end
    
    else
    begin
    cnts <= cnts;
    end
end
//////////////////////////////////////////////////////////////////////////////////
// din_m
reg [15:0] din_m;
always @ (posedge clk or posedge rst)
begin
    if (rst) 
    begin
    din_m <= 16'd0;
    end
    
    else
    begin
    case (cnts)
        16'd0: begin din_m[15] <= delay_din;end
        16'd1: begin din_m[14] <= delay_din;end
        16'd2: begin din_m[13] <= delay_din;end
        16'd3: begin din_m[12] <= delay_din;end
        16'd4: begin din_m[11] <= delay_din;end
        16'd5: begin din_m[10] <= delay_din;end
        16'd6: begin din_m[9] <= delay_din;end
        16'd7: begin din_m[8] <= delay_din;end
        16'd8: begin din_m[7] <= delay_din;end
        16'd9: begin din_m[6] <= delay_din;end
        16'd10: begin din_m[5] <= delay_din;end
        16'd11: begin din_m[4] <= delay_din;end
        16'd12: begin din_m[3] <= delay_din;end
        16'd13: begin din_m[2] <= delay_din;end
        16'd14: begin din_m[1] <= delay_din;end
        16'd15: begin din_m[0] <= delay_din;end
        default: begin din_m <= din_m; end
    endcase
    end
end
//////////////////////////////////////////////////////////////////////////////////
reg [3:0] Reg; // 1 1 0 0 1
always @ (posedge clk or posedge rst) 
begin
    if (rst) 
    begin
    Reg <= 4'h0;
    end
    
    else if (start) 
    begin
    Reg <= 4'h0;
    end
    
    else if(cnts < 15)
    begin
        Reg[0] <= Reg[3] ^ delay_din;
        Reg[1] <= Reg[0] ^ Reg[3] ^ delay_din ;
        Reg[2] <= Reg[1];
        Reg[3] <= Reg[2];
    end
    
    else
    begin
    Reg <= Reg;
    end
end
reg Check;
always @ (posedge clk or posedge rst)
begin
    if (rst) 
    begin
    Check <= 1'b0;
    end
    
    else if (start) 
    begin
    Check <= 1'b0;
    end
    
    else
    begin
    case (cnts)
        16'd0: begin Check <= Check ^ delay_din; end
        16'd1: begin Check <= Check ^ delay_din; end
        16'd2: begin Check <= Check ^ delay_din; end
        16'd3: begin Check <= Check ^ delay_din; end
        16'd4: begin Check <= Check ^ delay_din; end
        16'd5: begin Check <= Check ^ delay_din; end
        16'd6: begin Check <= Check ^ delay_din; end
        16'd7: begin Check <= Check ^ delay_din; end
        16'd8: begin Check <= Check ^ delay_din; end
        16'd9: begin Check <= Check ^ delay_din; end
        16'd10: begin Check <= Check ^ delay_din;end
        16'd11: begin Check <= Check ^ delay_din; end
        16'd12: begin Check <= Check ^ delay_din; end
        16'd13: begin Check <= Check ^ delay_din; end
        16'd14: begin Check <= Check ^ delay_din; end
        default: begin  Check <= Check;    end
    endcase
    end 
end
//////////////////////////////////////////////////////////////////////////////////
reg [15:0] din_trt;
always @ (posedge clk or posedge rst)
begin
    if (rst) 
    begin
    din_trt <= 16'd0;
    end
    
    else if (start) 
    begin
    din_trt <= 16'd0;
    end
    
    else
    begin
    case (cnts)
        16'd15: 
        begin
            case(Reg) 
                4'b0000:din_trt<=16'b000_0000_0000_0000;//1
                4'b0001:din_trt<=16'b000_1000_0000_0000;//2
                4'b0010:din_trt<=16'b001_0000_0000_0000;//3
                4'b0011:din_trt<=16'b000_0000_0000_0001;//4
                4'b0100:din_trt<=16'b010_0000_0000_0000;//5
                4'b0101:din_trt<=16'b000_0000_0001_0000;//6
                4'b0110:din_trt<=16'b000_0000_0000_0010;//7
                4'b0111:din_trt<=16'b000_0000_0100_0000;//8
                4'b1000:din_trt<=16'b100_0000_0000_0000;//9
                4'b1001:din_trt<=16'b000_0100_0000_0000;//10
                4'b1010:din_trt<=16'b000_0000_0010_0000;//11
                4'b1011:din_trt<=16'b000_0000_0000_1000;//12
                4'b1100:din_trt<=16'b000_0000_0000_0100;//13
                4'b1101:din_trt<=16'b000_0010_0000_0000;//14
                4'b1110:din_trt<=16'b000_0000_1000_0000;//15
                4'b1111:din_trt<=16'b000_0001_0000_0000;//16
                default: begin  din_trt <= din_trt; end
            endcase
        end
        16'd16: begin din_trt <= din_trt << 1; end // 上文造成的
    default: begin  din_trt <= din_trt;    end
    endcase
    end 
end
//////////////////////////////////////////////////////////////////////////////////
// dout_m
reg [15:0] dout_m;
always @ (posedge clk or posedge rst)
begin
    if (rst) 
    begin
    dout_m <= 16'd0;
    end
    
    else
    begin
    case (cnts)
        16'd18: 
        begin
            if(code_num == 2'b01) // 错一位 进行纠错
            begin
            dout_m <= din_m ^ din_trt;
            end
            
            else if(code_num == 2'b11) // 错一位 校验位纠错
            begin
            dout_m <= din_m ^ 1'b1;
            end
            
            else
            begin
            dout_m <= din_m;     // 保持
            end
        end
        default: begin  dout_m <= dout_m;    end
    endcase
    end 
end
//////////////////////////////////////////////////////////////////////////////////
// dout
reg dout;
always @ (posedge clk or posedge rst)
begin
    if (rst) 
    begin
    dout <= 1'b0;
    end
    
    else
    begin
    case (cnts)
        16'd19: begin dout <= dout_m[15]; end
        16'd20: begin dout <= dout_m[14]; end
        16'd21: begin dout <= dout_m[13]; end
        16'd22: begin dout <= dout_m[12]; end
        16'd23: begin dout <= dout_m[11]; end
        16'd24: begin dout <= dout_m[10]; end
        16'd25: begin dout <= dout_m[9];  end
        16'd26: begin dout <= dout_m[8];  end
        16'd27: begin dout <= dout_m[7];  end
        16'd28: begin dout <= dout_m[6];  end
        16'd29: begin dout <= dout_m[5];  end
        16'd30: begin dout <= dout_m[4];  end
        16'd31: begin dout <= dout_m[3];  end
        16'd32: begin dout <= dout_m[2];  end
        16'd33: begin dout <= dout_m[1];  end
        16'd34: begin dout <= dout_m[0];  end
        default: begin  dout <= 1'b0;     end
    endcase
    end 
end
// dout_clk_p
reg dout_clk_p;
always @ (posedge clk or posedge rst)
begin
    if (rst) 
    begin
    dout_clk_p <= 1'b0;
    end
    
    else
    begin
    case (cnts)
        16'd19: begin dout_clk_p <= 1'b1; end
//        16'd30: begin dout_clk_p <= 1'b0; end
        16'd35: begin dout_clk_p <= 1'b0; end
        default: begin dout_clk_p <= dout_clk_p; end
    endcase
    end 
end
//////////////////////////////////////////////////////////////////////////////////
// ECC
// pa_news
always @ (posedge clk or posedge rst)
begin
    if (rst) 
    begin
    pa_news <= 1'b0;
    end
    
    else
    begin
    case (cnts)
        16'd16: begin pa_news <= Check ^ din_m[0];  end
        default: begin pa_news <= pa_news; end
    endcase
    end 
end
// temp
always @ (posedge clk or posedge rst)
begin
    if (rst) 
    begin
    temp <= 4'b0;
    end
    
    else
    begin
    case (cnts)
        16'd15: begin temp <= Reg;  end
        default: begin temp <= temp; end
    endcase
    end 
end
// code_num
always @ (posedge clk or posedge rst)
begin
    if (rst) 
    begin
    code_num <= 2'd0;
    end
    
    else
    begin
    case (cnts)
        16'd17: 
            begin  
                if (pa_news == 1'b0) 
                begin
                    if (temp == 4'b0) 
                    begin
                    code_num <= 2'b00;// 无错误
                    end
                    
                    else 
                    begin 
                    code_num <= 2'b10;// 错误2个
                    end
                end
                
                else
                begin 
                    if (temp == 4'b0)
                    begin
                    code_num <= 2'b11;// 校验位错误
                    end
                    
                    else 
                    begin
                    code_num <= 2'b01; // 错误1个
                    end
                end
            end
        default: begin code_num <= code_num; end
    endcase
    end
end
 
endmodule

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注