m FPGA ベースの LDPC 最小和デコード アルゴリズムの Verilog 実装 (テストベンチおよび matlab 補助検証プログラムを含む)

目次

1.アルゴリズムシミュレーション効果

2. アルゴリズムには理論的知識の概要が含まれます

3. MATLAB コア プログラム

4. 完全なアルゴリズム コード ファイル


1.アルゴリズムシミュレーション効果

matlab2022a/vivado2019.2 のシミュレーション結果は次のとおりです。

Matlab シミュレーション:

0.5 コード レート、H は 4608×9216 の行列です。

FPGA シミュレーション:

 比較は次のとおりです。

2. アルゴリズムには理論的知識の概要が含まれます

         LDPC 復号は、硬判定復号と軟判定復号に分けられます。

        代数的復号とも呼ばれる硬判定復号は、主に実装が比較的簡単なビット フリップ (BF) 復号アルゴリズムによって表されますが、復号のパフォーマンスは低くなります。硬判定復号化の基本的な前提は、検証式が成立しない場合、その時点でビットエラーが発生しているはずであり、考えられるすべてのエラービットのうち、検証の最大数を満たさないビットは、方程式は、エラーの確率が最も高くなります。各反復で、誤り確率が最も高いビットを反転し、更新されたコードワードで再デコードします。

        軟判定復号化は, 確率論に基づく復号化アルゴリズムです. 通常, 復号化性能の利点を反映するには, 反復復号化と組み合わせる必要があります. 基本的なアルゴリズムは, 確率伝播 (BP) 復号化アルゴリズムです. 復号化方法の複雑さは次のとおりです.はるかに高いですが、デコードのパフォーマンスは非常に優れています。

        BP 復号化アルゴリズムの難しい問題を解決するために、対数領域信念伝搬復号化 (LLR BP) アルゴリズム、最小和 (Min-Sum) 復号化アルゴリズム、正規化された最小和などの最適化アルゴリズムの波が学界で開始されました。復号化アルゴリズムなど 復号化アルゴリズム、Offset Min-Sum 復号化アルゴリズムなどが次々と登場しています。

        反復復号化のプロセスには、フラッド スケジューリングと階層的スケジューリングの 2 つの情報スケジューリング方式があります。フラッド スケジューリングの特徴は、各復号反復プロセスで、変数ノードからチェック ノードまでのすべての軟情報が最初に計算され、次にチェック ノードから変数ノードまでのすべての軟情報が計算されることです。レイヤード スケジューリングの特徴は、各レイヤーの軟情報を計算する際に、次のレイヤーの軟情報計算のために、この繰り返しで該当するノード情報を更新することです。

        最小合計デコーディング (MS、Min-Sum) アルゴリズムは、LLR BP アルゴリズムのデコーディングに基づいており、チェック ノード情報の更新の表現を簡素化し、残りのステップは LLR BP デコーディング アルゴリズムと一致しています。
        LLR BP 復号化アルゴリズムと Min-Sum 復号化アルゴリズムのチェック ノード情報の更新プロセスを比較すると、それらの主な違いは、LLR BP 復号化における tanh(.) 演算と加算演算であることがわかります。アルゴリズムは Min-Sum 復号化アルゴリズムで使用されます. アルゴリズムは最小値と演算記号に置き換えられます. MS 復号化は LLR BP 復号化アルゴリズムを簡素化し、復号化アルゴリズムの複雑さを軽減します.


       それぞれH0、H1、...、H255で表される256個のサブマトリックスに均等に分割します。各サブマトリックスのサイズは18×36です。残りのHもこれに従って分割され、後の結果除算を図 1 に示します。

最小合計アルゴリズムのデコード プロセスは次のとおりです。

最小合計アルゴリズムに基づくデコーダー設計の基本的な考え方は、量子化デコーダーが最高のしきい値に到達できるように、密度進化理論に従って量子化デコーダーのパラメーターを最適化することです。

アルゴリズム全体のプロセスは次のように実行されます。

最初: 各変数ノードの値を初期化し、初期値を割り当てます。

2 番目: 反復回数が事前設定された最大反復回数を超えたかどうかを判断し、超えている場合は反復を終了します。

3 番目: 各反復で、変数ノードの情報が更新されます。

4: 各変数ノード Vn の L 値を計算する

第5に、各変数ノードVnについて、L値を判定し、シーケンスVkを出力し、復号を終了する。

最小和アルゴリズムは、本質的に BP 復号化アルゴリズムに似ています. さらに、アルゴリズム全体が対数領域で実行されます。

以上が復号アルゴリズム全体の基本的な流れです。

       min-sum復号化アルゴリズムはBP復号化アルゴリズムに類似しており, 元の指数演算プロセスを単純化することで復号化器の計算量を削減します. min -sum アルゴリズムは反復更新に使用されます. この更新はチェックノードの更新に分割されます.変数ノードが更新されます。その反復復号化ステップは 2 つのステップに分けられます。システム全体の全体的な構造は次のとおりです。

3.MATLAB/Verilogコアプログラム

......................................................................
for iteration=1:50
    iteration
    %horizontal step
    %横向步骤:由信息节点的先验概率按置信传播算法得出各校验节点的后验概率。
    for i=1:h1num %计算概率差
        newh(h1i(i),h1j(i)).dqmn=newh(h1i(i),h1j(i)).qmn0-newh(h1i(i),h1j(i)).qmn1;
    end

    for i=1:rows
        colind=find(h1i==i);%统计与校验节点相联系的第i行的数据位个数
        colnum=length(colind);
        for j=1:colnum
            drmn=1;
            for k=1:colnum
                if k~=j
                    drmn=drmn*newh(i,h1j(colind(k))).dqmn;
                end
            end
            newh(i,h1j(colind(j))).rmn0=(1+drmn)/2;
            newh(i,h1j(colind(j))).rmn1=(1-drmn)/2;
        end
    end

    %vertical step
    %纵向步骤:由校验节点的后验概率推算出信息节点的后验概率。
    for j=1:cols
        rowind=find(h1j==j);
        rownum=length(rowind);
        for i=1:rownum
            prod_rmn0=1;
            prod_rmn1=1;
            for k=1:rownum
                if k~=j
                    prod_rmn0=prod_rmn0*newh(h1i(rowind(k)),j).rmn0;
                    prod_rmn1=prod_rmn1*newh(h1i(rowind(k)),j).rmn1;
                end
            end
            const1=pl0(j)*prod_rmn0;
            const2=pl1(j)*prod_rmn1;
            newh(h1i(rowind(i)),j).alphamn=1/( const1 + const2 ) ;
            newh(h1i(rowind(i)),j).qmn0=newh(h1i(rowind(i)),j).alphamn*const1;
            newh(h1i(rowind(i)),j).qmn1=newh(h1i(rowind(i)),j).alphamn*const2;
            %update pseudo posterior probability
            %更新伪后验概率
            const3=const1*newh(h1i(rowind(i)),j).rmn0;
            const4=const2*newh(h1i(rowind(i)),j).rmn1;
            alpha_n=1/(const3+const4);
            newh(h1i(rowind(i)),j).qn0=alpha_n*const3;
            newh(h1i(rowind(i)),j).qn1=alpha_n*const4;
            %tentative decoding
            %译码尝试,对信息节点的后验概率作硬判决
            if newh(h1i(rowind(i)),j).qn1>0.5
                vhat(j)=1;
            else
                vhat(j)=0;
            end
        end
    end
    
    if mul_GF2(vhat,H.')==zero
    %如果判决条件满足,译码结束,否则继续迭代
        break;
    end
end

uhat = extract_mesg(vhat,rearranged_cols);

end


function [C]=mul_GF2(A,B)

C=A*B;
C=mod(C, 2);

end
............................................................................
reg[12:0]cnt;
reg[35:0]o_read_select;
reg      o_read_enable;
reg[7:0] o_address;

reg[35:0]dout_tmp_r;


assign Max_lens = i_code_rate ? 13'd6911: 13'd4607;
assign finishs = (cnt == Max_lens);

always @(posedge i_sys_clk or negedge i_sys_rst)
begin 
     if(!i_sys_rst)
     cnt <=  13'h0;
else if(i_state[3])
     begin
	       if(finishs)
	       cnt <=  13'h0;
     else
	       cnt <=  cnt + 1'b1;
     end
end

llr_values llr_values_u(
								.i_clk    (i_sys_clk),
								.i_address(cnt),
								.o_values (dout_tmp)
							  );

always @(posedge i_sys_clk or negedge i_sys_rst)
begin
     if(!i_sys_rst)
     o_address <= 8'd0;
else
     o_address <= dout_tmp[13:6];	    
end

always @(posedge i_sys_clk or negedge i_sys_rst)
begin
     if(!i_sys_rst)
     o_read_select <= 36'd0;
else if(i_state[3])
	  o_read_select <= dout_tmp_r;
else
	  o_read_select <= 36'd0;
end

always @ (posedge i_sys_clk or negedge i_sys_rst)
begin
     if(!i_sys_rst)
     o_read_enable <= 1'b0;
else 
	  o_read_enable <= i_state[3];
end


always @(dout_tmp[5:0])
case(dout_tmp[5:0])
	6'd0  : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0000_0000_0000_0001;	
	6'd1  : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0000_0000_0000_0010;	
	6'd2  : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0000_0000_0000_0100;	
	6'd3  : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0000_0000_0000_1000;	
	
	6'd4  : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0000_0000_0001_0000;		
	6'd5  : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0000_0000_0010_0000;	
	6'd6  : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0000_0000_0100_0000;		
	6'd7  : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0000_0000_1000_0000;	
	
	6'd8  : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0000_0001_0000_0000;	
	6'd9  : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0000_0010_0000_0000;	
	6'd10 : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0000_0100_0000_0000;	
	6'd11 : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0000_1000_0000_0000;	
	
	6'd12 : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0001_0000_0000_0000;	
	6'd13 : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0010_0000_0000_0000;		
	6'd14 : dout_tmp_r = 36'b0000_0000_0000_0000_0000_0100_0000_0000_0000;	
	6'd15 : dout_tmp_r = 36'b0000_0000_0000_0000_0000_1000_0000_0000_0000;	
	
	6'd16 : dout_tmp_r = 36'b0000_0000_0000_0000_0001_0000_0000_0000_0000;	
	6'd17 : dout_tmp_r = 36'b0000_0000_0000_0000_0010_0000_0000_0000_0000;	
	6'd18 : dout_tmp_r = 36'b0000_0000_0000_0000_0100_0000_0000_0000_0000;	
	6'd19 : dout_tmp_r = 36'b0000_0000_0000_0000_1000_0000_0000_0000_0000;	
	
	6'd20 : dout_tmp_r = 36'b0000_0000_0000_0001_0000_0000_0000_0000_0000;	
	6'd21 : dout_tmp_r = 36'b0000_0000_0000_0010_0000_0000_0000_0000_0000;	
	6'd22 : dout_tmp_r = 36'b0000_0000_0000_0100_0000_0000_0000_0000_0000;	
	6'd23 : dout_tmp_r = 36'b0000_0000_0000_1000_0000_0000_0000_0000_0000;	
	
	6'd24 : dout_tmp_r = 36'b0000_0000_0001_0000_0000_0000_0000_0000_0000;	
	6'd25 : dout_tmp_r = 36'b0000_0000_0010_0000_0000_0000_0000_0000_0000;	
	6'd26 : dout_tmp_r = 36'b0000_0000_0100_0000_0000_0000_0000_0000_0000;	
	6'd27 : dout_tmp_r = 36'b0000_0000_1000_0000_0000_0000_0000_0000_0000;	
	
	6'd28 : dout_tmp_r = 36'b0000_0001_0000_0000_0000_0000_0000_0000_0000;	
	6'd29 : dout_tmp_r = 36'b0000_0010_0000_0000_0000_0000_0000_0000_0000;	
	6'd30 : dout_tmp_r = 36'b0000_0100_0000_0000_0000_0000_0000_0000_0000;	
	6'd31 : dout_tmp_r = 36'b0000_1000_0000_0000_0000_0000_0000_0000_0000;	
	
	6'd32 : dout_tmp_r = 36'b0001_0000_0000_0000_0000_0000_0000_0000_0000;	
	6'd33 : dout_tmp_r = 36'b0010_0000_0000_0000_0000_0000_0000_0000_0000;	
	6'd34 : dout_tmp_r = 36'b0100_0000_0000_0000_0000_0000_0000_0000_0000;	
	6'd35 : dout_tmp_r = 36'b1000_0000_0000_0000_0000_0000_0000_0000_0000;	
	
	default:dout_tmp_r = 36'b0000_0000_0000_0000_0000_0000_0000_0000_0000;	
endcase


endmodule
14_033_m

4. 完全なアルゴリズム コード ファイル

おすすめ

転載: blog.csdn.net/hlayumi1234567/article/details/129625620