verilog实现简单的ecc检验与纠错

以4bit数据为例

编码数据

原理看上一篇总结

2024-02-03T07:34:30.png
2024-02-03T07:34:30.png

PP的值是前面全部数据的奇偶校验值
最终数据以{PP,P2,P1,P0,D3,D2,D1,D0}的顺序传输。

解码数据

获取到数据后,重新计算出检验码,得到新的检验码,并与旧的检验码进行异或,异或得到的4bit数据称命名为syndrome。

  1. 当syndrome最高位为0时
    若syndrome其余位为0,则没有错误。
    若非0,则存在两个错误。
  2. 当syndrome最高位为1时
    数据存在1个错误,错误的位置在H[syndrome[2:0]](除了syndrome最高位的其余位)。

    //检验数据并纠错,输出正确的数据
    module decoder(
     input [7:0]data_in,
     output reg [3:0]data_out
    );
     //根据接收的数据重新计算检验值
     //选择奇偶检验的数据位
     wire [3:0] check_bit2_sel=4'b1011;
     wire [3:0] check_bit3_sel=4'b1101;
     wire [3:0] check_bit4_sel=4'b1110;
     //计算检验位数据
     wire [2:0]ecc_data_without_pp_new;
     assign ecc_data_without_pp_new[0]=^(data_in[3:0] & check_bit2_sel);
     assign ecc_data_without_pp_new[1]=^(data_in[3:0] & check_bit3_sel);
     assign ecc_data_without_pp_new[2]=^(data_in[3:0] & check_bit4_sel);
     
     reg pp;//全部数据的奇偶检验
     always @(ecc_data_without_pp_new) begin
         pp=^{ecc_data_without_pp_new[2:0],data_in[3:0]};
     end
    
     wire [3:0]syn;//比较两次检验值差异
     assign syn=data_in[7:4]^{pp,ecc_data_without_pp_new};
     reg [3:0]where;//错误的位置
     always @(syn) begin
         if(syn[3]==0)
             begin
               if(syn[2:0]==3'd0)
                 data_out=data_in[3:0];
               else
                 data_out=4'd0;
             end
         else
             case (syn[2:0])
                 3'd3:where=4'b0001;
                 3'd5:where=4'b0010;
                 3'd6:where=4'b0100;
                 3'd7:where=4'b1000;
                 default :where=4'b0000;
             endcase
     end
     always @(where) begin
         data_out=data_in[3:0]^where;
     end
    endmodule
    //为接收到的数据计算ecc检验值
    module encoder(
     input [3:0]data,
     output [7:0] out
    );//选择奇偶检验的数据位
     wire [3:0] check_bit2_sel=4'b1011;
     wire [3:0] check_bit3_sel=4'b1101;
     wire [3:0] check_bit4_sel=4'b1110;
     //计算检验位数据
     reg pp;
     wire [2:0]ecc_data_without_pp;
     assign ecc_data_without_pp[0]=^(data & check_bit2_sel);
     assign ecc_data_without_pp[1]=^(data & check_bit3_sel);
     assign ecc_data_without_pp[2]=^(data & check_bit4_sel);
     
     always @(ecc_data_without_pp) begin
         pp=^{ecc_data_without_pp,data};
     end
    
     assign out={pp,ecc_data_without_pp,data};
    endmodule

安装Ubuntu

在电脑实体机上重新安装了ubuntu,在屏蔽核显之后总算不会自动重启了。安装了常用的软件如QQ,clash,vscode等,使用wine装了微信。甚至装了steam后使用proton兼容层可以玩盗版的Windows游戏。