├── .gitattributes ├── .gitignore ├── MATLAB ├── H_matrices_802_16e.mat ├── InitializeWiMaxLDPC.m ├── ldpc_decoderFINAL.m ├── ldpc_decoderQ.m ├── old │ ├── ldpc_decoder2.m │ └── ldpc_decoderOLD.m ├── quantize.m └── script_LDPC.m ├── README.md └── verilog ├── H_matrices_802_16e.mat ├── InitializeWiMaxLDPC.m ├── VFiles ├── CheckNode.v ├── Comparator.v ├── LDPC.v ├── QuantizedAdder.v ├── QuantizedSubber.v ├── TreeComparator.v └── VarNode.v ├── ldpc_decoder_v.m ├── quantize.m ├── script_LDPC_v.m └── verigen.m /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /MATLAB/H_matrices_802_16e.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crboth/LDPC_Decoder/b413c76889db1a73e36f213ca8753256e21ab5bb/MATLAB/H_matrices_802_16e.mat -------------------------------------------------------------------------------- /MATLAB/InitializeWiMaxLDPC.m: -------------------------------------------------------------------------------- 1 | % File: InitializeWiMaxLDPC.m 2 | % 3 | % Description: Initializes the WiMax LDPC encoder/decoder 4 | % 5 | % The calling syntax is: 6 | % [H_rows, H_cols, P] = InitializeWiMaxLDPC( rate, size, ind ) 7 | % 8 | % Where: 9 | % H_rows = a M-row matrix containing the indices of the non-zero rows of H excluding the dual-diagonal portion of H. 10 | % H_cols = a (N-M)+z-row matrix containing the indices of the non-zeros rows of H. 11 | % P = a z times z matrix used in encoding 12 | % 13 | % rate = the code rate 14 | % size = the size of the code (number of code bits): 15 | % = 576:96:2304 16 | % ind = Selects either code 'A' or 'B' for rates 2/3 and 3/4 17 | % = 0 for code rate type 'A' 18 | % = 1 for code rate type 'B' 19 | % = [empty array] for all other code rates 20 | % 21 | % Copyright (C) 2007-2008, Rohit Iyer Seshadri and Matthew C. Valenti 22 | % 23 | % Last updated on June. 23, 2007. 24 | % 25 | % Function InitializeWiMaxLDPC is part of the Iterative Solutions 26 | % Coded Modulation Library. The Iterative Solutions Coded Modulation 27 | % Library is free software; you can redistribute it and/or modify it 28 | % under the terms of the GNU Lesser General Public License as published 29 | % by the Free Software Foundation; either version 2.1 of the License, 30 | % or (at your option) any later version. 31 | % 32 | % This library is distributed in the hope that it will be useful, 33 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 34 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 35 | % Lesser General Public License for more details. 36 | % 37 | % You should have received a copy of the GNU Lesser General Public 38 | % License along with this library; if not, write to the Free Software 39 | % Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 40 | 41 | function [H]= InitializeWiMaxLDPC(rate, nldpc, ind) 42 | 43 | epsilon=1e-3; 44 | rt_flag=0; 45 | if (abs(rate-1/2) 0) 137 | if ((rate ==2/3)&(ind ==0)) 138 | H(cnt1:cnt1+z-1, cnt2:cnt2+z-1)=circshift( eye(z),[0,mod(Hbm(i,j),z)]); 139 | else 140 | H(cnt1:cnt1+z-1, cnt2:cnt2+z-1)= circshift( eye(z),[0,floor(Hbm(i,j)*z/z0)]); 141 | end 142 | end 143 | cnt2=cnt2+z; 144 | end 145 | cnt1=cnt1+z; 146 | end 147 | 148 | P =eye(z); 149 | if ((rate ==3/4) & (ind ==1)) 150 | P=inv(circshift( eye(z),[0,floor(80*z/z0)])); 151 | end 152 | -------------------------------------------------------------------------------- /MATLAB/ldpc_decoderFINAL.m: -------------------------------------------------------------------------------- 1 | function [out, num_iterations] = ldpc_decoderFINAL(llr, SpHenc, max_iterations) 2 | 3 | [row, col] = find(SpHenc); 4 | [num_rows, ~] = size(SpHenc); 5 | n = nnz(SpHenc); 6 | k = 1:n; 7 | rowi = 1:num_rows; 8 | Q = zeros(1,n); 9 | R = zeros(1,n); 10 | i = 0; 11 | P_v = llr; 12 | sign_prod = zeros(1,num_rows); 13 | while ( (i < max_iterations) && ~all(mod((P_v < 0)*double(transpose(SpHenc)),2) == zeros(1,num_rows))) 14 | 15 | spR = sparse(row,col,R); 16 | %calculate Q values 17 | sum_of_Rs = sum(spR); 18 | P_v = llr + sum_of_Rs; 19 | Q(k) = P_v(col(k)) - R(k); 20 | 21 | %calculate R values 22 | %find all the negative Q values 23 | sign_Q = logical(Q < 0); 24 | 25 | %to calculate sign product: 26 | %histogram is used to find the number of negatives in each row 27 | %mod is then used to determine if this number is positive or 28 | %negative whish is equivalent to the sign product 29 | sign_prod(rowi) = mod(histc(row(sign_Q(k)),rowi),2); 30 | 31 | %to find the mins first sort all the Q values by absoulte value 32 | abs_Q = abs(Q); 33 | spabs = sparse(col,row,abs_Q); 34 | srtd = sort(spabs); 35 | 36 | %%%%%% 37 | %%%%%% 38 | %This is a cludge which will break on a differently sized matrix or 39 | %one with less than 6 or more than 7 connections to a Check Node, 40 | %the fix is simple but unneccesary for the exercise. 41 | 42 | %For a sorted sparse matrix of dimenstion 576, with 6 or 7 elements in a row, and only absolute values, the min and second min are between elem 570 and 572 43 | 44 | tmp = srtd(570:572,:); 45 | %%%% 46 | mins = tmp(1:2,:); 47 | mins(:,sum(SpHenc,2)==6) = tmp(2:3,sum(SpHenc,2)==6); 48 | %%%%%%% 49 | %%%%%%% 50 | 51 | %Initially assign R to be the abs value minmimums for each row 52 | R(k) = mins(1,row(k)); 53 | %wherever R is equivalent to its corresponding Q, it is known to be 54 | %the minimum for that row 55 | %replace these Rs with the second minimum value 56 | R(abs_Q(k) == R(k)) = mins(2,row(abs_Q(k) == R(k))); 57 | %if the sign product of corresponding Q values is negative, make R negative 58 | R(sign_Q(k)) = -R(sign_Q(k)); 59 | %if the sign product was negative make R negative, this can 60 | %probably be improved to perform both sign calculations in one 61 | %operation 62 | R(sign_prod(row(k)) == 1) = -R(sign_prod(row(k)) == 1); 63 | i = i+1; 64 | end 65 | num_iterations = i; 66 | out = P_v; 67 | end -------------------------------------------------------------------------------- /MATLAB/ldpc_decoderQ.m: -------------------------------------------------------------------------------- 1 | %Quantized simulation 2 | function [out] = ldpc_decoderQ(llr, SpHenc, max_iterations, pad, pbd) 3 | [row, col] = find(SpHenc); 4 | [num_rows, ~] = size(SpHenc); 5 | n = nnz(SpHenc); 6 | k = 1:n; 7 | rowi = 1:num_rows; 8 | Q = zeros(1,n); 9 | R = zeros(1,n); 10 | i = 0; 11 | P_v = llr; 12 | sign_prod = zeros(1,num_rows); 13 | mins = zeros(num_rows, 2); 14 | while ( (i < max_iterations) && ~all(mod((P_v < 0)*double(transpose(SpHenc)),2) == zeros(1,num_rows))) 15 | spR = sparse(row,col,R); 16 | sum_of_Rs = quantize(sum(spR), pad, pbd); 17 | P_v = llr + sum_of_Rs; 18 | P_v = quantize(P_v, pad, pbd); 19 | Q(k) = P_v(col(k)) - R(k); 20 | Q = quantize(Q, pad, pbd); 21 | sign_Q = logical(Q < 0); 22 | sign_prod(rowi) = mod(histc(row(sign_Q(k)),rowi),2); 23 | abs_Q = quantize(abs(Q), pad, pbd); 24 | [~, ind] = sort(abs_Q); 25 | [~, ia ,~] = unique(row(ind)); 26 | mins(rowi,1) = abs_Q(ind(ia(rowi))); 27 | ind(ia) = []; 28 | [~, ia ,~] = unique(row(ind)); 29 | mins(rowi,2) = abs_Q(ind(ia(rowi))); 30 | R(k) = mins(row(k),1); 31 | R(abs_Q(k) == R(k)) = mins(row(abs_Q(k) == R(k)),2); 32 | R(sign_Q(k)) = -R(sign_Q(k)); 33 | R(sign_prod(row(k)) == 1) = -R(sign_prod(row(k)) == 1); 34 | R = quantize(R, pad, pbd); 35 | i = i+1; 36 | end 37 | out = P_v; 38 | end -------------------------------------------------------------------------------- /MATLAB/old/ldpc_decoder2.m: -------------------------------------------------------------------------------- 1 | function [out] = ldpc_decoder2(llr, SpHenc, max_iterations) 2 | [row, col] = find(SpHenc); 3 | [num_rows, ~] = size(SpHenc); 4 | n = nnz(SpHenc); 5 | k = 1:n; 6 | rowi = 1:num_rows; 7 | Q = zeros(1,n); 8 | R = zeros(1,n); 9 | i = 0; 10 | P_v = llr; 11 | sign_prod = zeros(1,num_rows); 12 | mins = zeros(num_rows, 2); 13 | %While a slightly more efficent algorithm might be possible by creating 14 | %classes for the nodes to calculate and calculating their values directly, working on the H matrix format was very easy to do conceptually 15 | while ( (i < max_iterations) && ~all(mod((P_v < 0)*double(transpose(SpHenc)),2) == zeros(1,num_rows))) 16 | spR = sparse(row,col,R); 17 | sum_of_Rs = sum(spR); 18 | P_v = llr + sum_of_Rs; 19 | Q(k) = P_v(col(k)) - R(k); 20 | sign_Q = logical(Q < 0); 21 | sign_prod(rowi) = mod(histc(row(sign_Q(k)),rowi),2); 22 | abs_Q = abs(Q); 23 | 24 | %This was my first stab at trying to find an efficent vectorized 25 | %approach to calculating R values 26 | 27 | %C Nodes send R values to each V node, each R value has the sign 28 | %of the sign product of the input Q values, and the absolute value of 29 | %the minimum Q value excluding its respective one. 30 | 31 | %i.e. odd number of negative Qs means negative Rs, all the Rs have the 32 | %same abs value of the minimum Q except for the R corresponding to the 33 | %minimum Q, in which case it has the second min 34 | 35 | %Efficently finding both the min and the second min was challenging as 36 | %simply calling sort on say the 576x288 matrix is costly, instead the 37 | %list of Q values is sorted,(~1800 elements instead of 165k) and Unique is used to find the first 38 | %instance (and then again to find the second instance) of a Q value 39 | %corresponging to each row, aka the min for that row 40 | 41 | [~, ind] = sort(abs_Q); 42 | %These two unique calls take up ~50% of the runtime 43 | [~, ia ,~] = unique(row(ind)); 44 | mins(rowi,1) = abs_Q(ind(ia(rowi))); 45 | ind(ia) = []; 46 | [~, ia ,~] = unique(row(ind)); 47 | mins(rowi,2) = abs_Q(ind(ia(rowi))); 48 | R(k) = mins(row(k),1); 49 | R(abs_Q(k) == R(k)) = mins(row(abs_Q(k) == R(k)),2); 50 | R(sign_Q(k)) = -R(sign_Q(k)); 51 | R(sign_prod(row(k)) == 1) = -R(sign_prod(row(k)) == 1); 52 | i = i+1; 53 | end 54 | out = P_v; 55 | end -------------------------------------------------------------------------------- /MATLAB/old/ldpc_decoderOLD.m: -------------------------------------------------------------------------------- 1 | function [out] = ldpc_decoderOLD(llr, H, max_iterations) 2 | %This is an iteration of the first decoder simulation I wrote, It's 3 | %already been somewhat optimized over the completley C style original 4 | 5 | 6 | %It's orders of magnitude slower than the final iteration 7 | [row, col] = find(H); 8 | n = nnz(H); 9 | Q = zeros(288,576); 10 | R = zeros(288,576); 11 | i = 0; 12 | P_v = llr; 13 | while ( (i < max_iterations) && ~all(mod((P_v < 0)*transpose(H),2) == zeros(1,288))) 14 | %Calculate Q values 15 | sum_of_Rs = zeros(1,576); 16 | for k = 1:n 17 | sum_of_Rs(1,col(k)) = sum_of_Rs(1,col(k)) + R(row(k),col(k)); 18 | end 19 | 20 | P_v = llr + sum_of_Rs; 21 | 22 | for k = 1:n 23 | Q(row(k,1),col(k,1)) = P_v(1,col(k,1)) - R(row(k,1),col(k,1)); 24 | end 25 | %Calculate R values 26 | for k = 1:n 27 | rowk = row(k,1); 28 | colk = col(k,1); 29 | q_min = Inf;%flintmax; 30 | sign_prod = 1; 31 | for j = 1:576 32 | if ((H(rowk,j)) && ~(j == colk)) 33 | temp_sign = sign(Q(rowk,j)); 34 | if(~temp_sign) 35 | temp_sign = 1; 36 | end 37 | sign_prod = sign_prod*temp_sign; 38 | if abs(Q(rowk,j)) < q_min %bugged 39 | q_min = abs(Q(rowk,j)); 40 | end 41 | end 42 | end 43 | R(rowk,colk) = sign_prod * q_min; 44 | end 45 | i = i+1; 46 | end 47 | out = P_v; 48 | end 49 | %temp_sign = mod(sum(sign(Q(H(rowk,:) != 0) -------------------------------------------------------------------------------- /MATLAB/quantize.m: -------------------------------------------------------------------------------- 1 | function [q] = quantize(in, pad, pbd) 2 | %precision was set as precision above and below decimal the, total number of bits is equal to their sum plus a sign bit 3 | 4 | %Admittedly this is a wonky format, total number of bits and how to 5 | %shift the decimal would clearly be superior 6 | pmax = 2^(pad+pbd) -1; 7 | pmin = -(2^(pad+pbd)); 8 | temp = round(in*(2^(pbd))); 9 | temp(temp > pmax(1,1)) = pmax(1,1); 10 | temp(temp < pmin) = pmin; 11 | q = temp/(2^pbd); 12 | end 13 | 14 | -------------------------------------------------------------------------------- /MATLAB/script_LDPC.m: -------------------------------------------------------------------------------- 1 | clear all, close all; 2 | max_num_frame = 100;%Maximum number of simulations for each SNR, set it high and uncomment the block at the bottom to run until a set number of errors 3 | SNR = 1.0:.2:2.5;%1:.4:2.8; 4 | frac_range = [3]; 5 | 6 | tic; 7 | max_iterations = 12; 8 | biterror = zeros(length(frac_range),length(SNR)); 9 | frameerror = zeros(length(frac_range),length(SNR)); 10 | ber = zeros(length(frac_range),length(SNR)); 11 | fer = zeros(length(frac_range),length(SNR)); 12 | 13 | for SNR_index = 1:length(SNR);%--- Max. LLR For Output of Detector 14 | W = 7; 15 | for F_ind=1:length(frac_range) 16 | F = frac_range(F_ind); 17 | fl = F; 18 | il = W - F; 19 | DetectorMaxLLR=2^(W-F-1); 20 | PacketPeriod=1;%------- Packet Period 21 | BS='576';%------------ LDPC Output Block Size 22 | %%II=25;%---------------- LDPC Max. Num. of Iterations 23 | 24 | rate='1/2';%------------- LDPC Code Rate 25 | switch (BS) 26 | case '576' 27 | BSN=576; 28 | case '1920' 29 | BSN=1920; 30 | otherwise 31 | BSN=2304; 32 | end 33 | load H_matrices_802_16e 34 | % for rate 1/2 code load the following matrix 35 | if (rate=='1/2') 36 | H_load=H_1_2; 37 | % Seting Parity Check Matrix 38 | ind = []; %0:A, 1:B 39 | Rate=1/2; 40 | elseif (rate=='2/3') 41 | H_load=H_2_3; 42 | % Seting Parity Check Matrix 43 | ind = [0]; %0:A, 1:B 44 | Rate=2/3; 45 | elseif (rate=='2B3') 46 | H_load=H_2_3_B; 47 | % Seting Parity Check Matrix 48 | ind = [1]; %0:A, 1:B 49 | Rate=2/3; 50 | elseif (rate=='3A4') 51 | H_load=H_3_4_A; 52 | % Seting Parity Check Matrix 53 | ind = [0]; %0:A, 1:B 54 | Rate=3/4; 55 | elseif (rate=='3B4') 56 | H_load=H_3_4_B; 57 | % Seting Parity Check Matrix 58 | ind = [1]; %0:A, 1:B 59 | Rate=3/4; 60 | elseif (rate=='5/6') 61 | H_load=H_5_6; 62 | % Seting Parity Check Matrix 63 | ind = []; %0:A, 1:B 64 | Rate=5/6; 65 | end 66 | %-------------- Calculationg Values of Model Variables Based on Parameters 67 | BSNr=BSN*Rate; 68 | bP=PacketPeriod/BSNr;%-- bit Period 69 | % target code length is 1920 hence z = 1920/24 = 80 70 | z=BSN/24; 71 | zmat=eye(z); 72 | [no_rows no_cols]=size(H_load); 73 | nullmat=zeros(size(zmat)); 74 | nz = no_cols * z; 75 | mz = no_rows * z; 76 | kz = nz - mz; 77 | n = nz/z; 78 | m = mz/z; 79 | k = kz/z; 80 | % For Cml decoder 81 | % rate should come out as 1/2 82 | rate = kz/nz; 83 | Rate = rate; 84 | [Henc] = InitializeWiMaxLDPC( rate, nz, ind ); 85 | [Mm,Nn]=size(Henc); 86 | NumAdd=sum(Henc); 87 | NumComp=sum(Henc,2); 88 | MaxAddSize=max(NumAdd); 89 | MaxCompSize=max(NumComp); 90 | FnmComp=zeros(Mm,MaxCompSize); 91 | FnmCompIdx=zeros(Mm,MaxCompSize); 92 | EmnComp=zeros(MaxAddSize,Nn); 93 | EmnCompIdx=zeros(MaxAddSize,Nn); 94 | for i=1:Mm 95 | [RF,CF,FnmComp(i,1:NumComp(i))]=find(Henc(i,:)); 96 | FnmCompIdx(i,1:NumComp(i))=(CF(1:NumComp(i))-1)*Mm+i; 97 | end 98 | [FnmCompIdxR,FnmCompIdxC,FnmCompIdxV] = find(FnmCompIdx); 99 | IndxF=sub2ind([Mm,MaxCompSize],FnmCompIdxR,FnmCompIdxC); 100 | for i=1:Nn 101 | [RE,CE,EmnComp(1:NumAdd(i),i)]=find(Henc(:,i)); 102 | EmnCompIdx(1:NumAdd(i),i)=(RE(1:NumAdd(i)))+Mm*(i-1); 103 | end 104 | [EmnCompIdxR,EmnCompIdxC,EmnCompIdxV] = find(EmnCompIdx); 105 | IndxE=sub2ind([MaxAddSize,Nn],EmnCompIdxR,EmnCompIdxC); 106 | MinsumOrder=(NumComp-1).*Mm+(1:Mm)'; 107 | SubMinsumOrder=MinsumOrder-Mm; 108 | [temp,tempIdx]=sort(FnmCompIdxV); 109 | SortedIndxF=IndxF(tempIdx); 110 | [temp,tempIdx]=sort(EmnCompIdxV); 111 | SortedIndxE=IndxE(tempIdx); 112 | Imax=20; 113 | Stop=0; 114 | Offset=0; 115 | H=Henc; 116 | SpHenc=sparse(Henc); 117 | noise_var = 0.5*10^(-SNR(SNR_index)/10)*(1/Rate); 118 | 119 | %% simulating 120 | for frame_index = 1:max_num_frame; 121 | 122 | %---------------Transmitter Encoding----------------------------------- 123 | x_after_enco = zeros(1,BSN); %Pending Convolution Code 124 | modulated = 1-x_after_enco.*2; %Modulating BPSK 125 | 126 | %---------------Channel Transmitting----------------------------------- 127 | received = modulated + sqrt(noise_var)*(randn(1,BSN)); 128 | 129 | %---------------Receiver Detection------------------------------------- 130 | demodulated=real(received); % Detector 131 | llr = 2.*demodulated./noise_var; % LLR Calculation 132 | 133 | %---------------Receiver Decoding-------------------------------------- 134 | 135 | %% 136 | %switch which line is commented out to use the different 137 | %versions 138 | [Output, iterations] = ldpc_decoderFINAL(llr, SpHenc, max_iterations); 139 | %Output = ldpc_decoderOLD(llr, H, max_iterations); 140 | %Output = ldpc_decoder2(llr, SpHenc, max_iterations); 141 | %Output = ldpc_decoderQ(llr,SpHenc,max_iterations, 4,0); 142 | 143 | biterror(F_ind, SNR_index) = biterror(F_ind, SNR_index) + sum(Output < 0); 144 | frameerror(F_ind, SNR_index)= frameerror(F_ind, SNR_index) + any(Output < 0); 145 | %%%% 146 | %Comment this out to just see the results and not the wall of ber xxxxxx fer xxxxxx 147 | if(any(Output < 0)) 148 | fprintf('ber: %f; fer: %f\n',biterror(:, SNR_index)/(BSN*frame_index), frameerror(:, SNR_index)/frame_index); 149 | end 150 | %%%% 151 | %Can uncomment this to allow the simulation to run to a certain 152 | %number of errors instead of fixed number of iterations 153 | %%%% 154 | % if biterror(1, F_ind, SNR_index) >= 10000 && frameerror(F_ind, SNR_index)>= 500 155 | % ber(:, F_ind, SNR_index)= biterror(:, F_ind, SNR_index)/(BSN*frame_index); 156 | % fer(:, F_ind, SNR_index)= frameerror(:, F_ind, SNR_index)/frame_index; 157 | % break; 158 | % end 159 | end 160 | ber(F_ind, SNR_index)= biterror(F_ind, SNR_index)/(BSN*max_num_frame); 161 | fer(F_ind, SNR_index)= frameerror(F_ind, SNR_index)/max_num_frame; 162 | fprintf('Result for SNR of %d:\n', SNR(SNR_index)); 163 | fprintf('ber: %f; fer: %f\n', biterror(:, SNR_index)/(BSN*frame_index), frameerror(:, SNR_index)/frame_index); 164 | % %% output 165 | % fid = fopen('Script_BPSK_LDPC.txt','a+'); 166 | 167 | % fclose(fid); 168 | end 169 | end 170 | toc; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LDPC_Decoder 2 | Low Density Parity Check Decoder 3 | 4 | This is the LDPC decoder I developed for my ECEN 654 final project. It currently impliments a rate .5 code but is nearly fully parameterised so it could generate decoders for arbitrary H matrices with only minor changes. 5 | 6 | It consists of a MATLAB simulation used to verify the algorithm and generate test data for the Verilog implimentation. 7 | 8 | The top level Verilog module is generated by script_LDPC_v, which calls verigen which uses print statements to generate LDPC.v 9 | 10 | The Verilog generating files have not been refactored so they're rather cumbersome, however the rest of the MATLAB simulation files are heavily optimised to allow for rapid evaluation of changes even for high SNR values. 11 | 12 | -------------------------------------------------------------------------------- /verilog/H_matrices_802_16e.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crboth/LDPC_Decoder/b413c76889db1a73e36f213ca8753256e21ab5bb/verilog/H_matrices_802_16e.mat -------------------------------------------------------------------------------- /verilog/InitializeWiMaxLDPC.m: -------------------------------------------------------------------------------- 1 | % File: InitializeWiMaxLDPC.m 2 | % 3 | % Description: Initializes the WiMax LDPC encoder/decoder 4 | % 5 | % The calling syntax is: 6 | % [H_rows, H_cols, P] = InitializeWiMaxLDPC( rate, size, ind ) 7 | % 8 | % Where: 9 | % H_rows = a M-row matrix containing the indices of the non-zero rows of H excluding the dual-diagonal portion of H. 10 | % H_cols = a (N-M)+z-row matrix containing the indices of the non-zeros rows of H. 11 | % P = a z times z matrix used in encoding 12 | % 13 | % rate = the code rate 14 | % size = the size of the code (number of code bits): 15 | % = 576:96:2304 16 | % ind = Selects either code 'A' or 'B' for rates 2/3 and 3/4 17 | % = 0 for code rate type 'A' 18 | % = 1 for code rate type 'B' 19 | % = [empty array] for all other code rates 20 | % 21 | % Copyright (C) 2007-2008, Rohit Iyer Seshadri and Matthew C. Valenti 22 | % 23 | % Last updated on June. 23, 2007. 24 | % 25 | % Function InitializeWiMaxLDPC is part of the Iterative Solutions 26 | % Coded Modulation Library. The Iterative Solutions Coded Modulation 27 | % Library is free software; you can redistribute it and/or modify it 28 | % under the terms of the GNU Lesser General Public License as published 29 | % by the Free Software Foundation; either version 2.1 of the License, 30 | % or (at your option) any later version. 31 | % 32 | % This library is distributed in the hope that it will be useful, 33 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 34 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 35 | % Lesser General Public License for more details. 36 | % 37 | % You should have received a copy of the GNU Lesser General Public 38 | % License along with this library; if not, write to the Free Software 39 | % Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 40 | 41 | function [H]= InitializeWiMaxLDPC(rate, nldpc, ind) 42 | 43 | epsilon=1e-3; 44 | rt_flag=0; 45 | if (abs(rate-1/2) 0) 137 | if ((rate ==2/3)&(ind ==0)) 138 | H(cnt1:cnt1+z-1, cnt2:cnt2+z-1)=circshift( eye(z),[0,mod(Hbm(i,j),z)]); 139 | else 140 | H(cnt1:cnt1+z-1, cnt2:cnt2+z-1)= circshift( eye(z),[0,floor(Hbm(i,j)*z/z0)]); 141 | end 142 | end 143 | cnt2=cnt2+z; 144 | end 145 | cnt1=cnt1+z; 146 | end 147 | 148 | P =eye(z); 149 | if ((rate ==3/4) & (ind ==1)) 150 | P=inv(circshift( eye(z),[0,floor(80*z/z0)])); 151 | end 152 | -------------------------------------------------------------------------------- /verilog/VFiles/CheckNode.v: -------------------------------------------------------------------------------- 1 | `include "Comparator.v" 2 | module CheckNode(Rwires, Qwires, rst, clk); 3 | //num_connections must be at least 2 4 | parameter num_connections = 6; 5 | parameter prec = 4; 6 | 7 | output signed [num_connections*prec-1:0] Rwires; 8 | input signed [num_connections*prec-1:0] Qwires; 9 | input rst; 10 | input clk; 11 | 12 | wire sign_product; 13 | wire [num_connections-1:0] Qsigns; 14 | wire [num_connections-1:0] Rsigns; 15 | wire signed [prec-1:0] abs_Q [num_connections-1:0]; 16 | wire signed [prec-1:0] abs_R [num_connections-1:0]; 17 | wire signed [prec-1:0] Rvalues [num_connections-1:0]; 18 | reg signed [prec-1:0] Rreg [num_connections-1:0]; 19 | wire signed [prec-1:0] min_tree_wires [num_connections*2-2:0]; 20 | wire signed [prec-1:0] sec_min_tree_wires [num_connections*2-2:0]; 21 | wire signed [prec-1:0] min; 22 | wire signed [prec-1:0] second_min; 23 | genvar i; 24 | reg [9:0] j; 25 | 26 | assign sign_product = ^Qsigns; 27 | 28 | assign min = min_tree_wires[num_connections*2-2]; 29 | assign second_min = sec_min_tree_wires[num_connections*2-2]; 30 | 31 | generate 32 | 33 | for(i = 0; i < num_connections; i = i+1) begin :genblk0 34 | assign min_tree_wires[i] = abs_Q[i]; 35 | assign sec_min_tree_wires[i] = {prec{1'b1}}; 36 | end 37 | 38 | for(i=0; i min1) ? {min1, min2}:{min2, min1}; 15 | assign not_max = (sec_min1 <= sec_min2) ? sec_min1:sec_min2; 16 | assign sec_min = (not_min <= not_max) ? not_min:not_max; 17 | 18 | endmodule 19 | 20 | -------------------------------------------------------------------------------- /verilog/VFiles/QuantizedAdder.v: -------------------------------------------------------------------------------- 1 | module QuantizedAdder(sum, in1, in2); 2 | parameter prec = 5; 3 | 4 | output signed [prec - 1 : 0] sum; 5 | input signed [prec - 1 : 0] in1; 6 | input signed [prec - 1 : 0] in2; 7 | wire signed [prec : 0] sum_wire; 8 | 9 | assign sum_wire = in1 + in2; 10 | assign sum = (sum_wire[prec] == sum_wire[prec-1]) ? sum_wire[prec - 1 : 0] : {sum_wire[prec],{(prec - 1){sum_wire[prec - 1]}}}; 11 | 12 | endmodule 13 | -------------------------------------------------------------------------------- /verilog/VFiles/QuantizedSubber.v: -------------------------------------------------------------------------------- 1 | module QuantizedSubber(sum, in1, in2); 2 | parameter prec = 5; 3 | 4 | output signed [prec - 1 : 0] sum; 5 | input signed [prec - 1 : 0] in1; 6 | input signed [prec - 1 : 0] in2; 7 | wire signed [prec : 0] sum_wire; 8 | 9 | assign sum_wire = in1 - in2; 10 | assign sum = (sum_wire[prec] == sum_wire[prec-1]) ? sum_wire[prec - 1 : 0] : {sum_wire[prec],{(prec - 1){sum_wire[prec - 1]}}}; 11 | 12 | endmodule 13 | -------------------------------------------------------------------------------- /verilog/VFiles/TreeComparator.v: -------------------------------------------------------------------------------- 1 | module TreeComparator(min, sec_min, values); 2 | parameter num_values = 3; 3 | parameter prec = 5; 4 | 5 | output [prec-1:0] min; 6 | output [prec-1:0] sec_min; 7 | input [num_values*prec-1:0] values; 8 | 9 | wire [prec-1:0] min1; 10 | wire [prec-1:0] min2; 11 | wire [prec-1:0] sec_min1; 12 | wire [prec-1:0] sec_min2; 13 | 14 | wire [prec-1:0] _min; 15 | wire [prec-1:0] _sec_min; 16 | genvar log_con; 17 | genvar i; 18 | generate 19 | log_con = 0; 20 | for(i = num_values; i > 0; i = i-1) begin 21 | log_con += i; 22 | end 23 | 24 | wire [prec-1:0] min_wires[0:log_con-1]; 25 | wire [prec-1:0] sec_min_wires[0:log_con-1]; 26 | 27 | Comparator JoinTree(min, sec_min, min1, min2, sec_min1, sec_min2); 28 | 29 | generate 30 | for(i=0; i < num_values/2; i=i+1) begin 31 | always@(*) begin 32 | if(values[prec*(i+1)-1:prec*i] < values[prec*(i+2)-1:prec*(i+1)]) begin 33 | min_wires[i] <= values[prec*(i+1)-1:prec*i]; 34 | sec_min_wires[i] <= values[prec*(i+2)-1:prec*(i+1)]; 35 | end 36 | else begin 37 | sec_min_wires[i] <= values[prec*(i+1)-1:prec*i]; 38 | min_wires[i] <= values[prec*(i+2)-1:prec*(i+1)]; 39 | end 40 | end 41 | 42 | min_wires[i] = (values[prec*(i+1)-1:prec*i] < values[prec*(i+2)-1:prec*(i+1)] ? 43 | 44 | 45 | generate 46 | if(num_values == 1) begin 47 | assign min = values; 48 | assign second_min = {prec{1'b1}}; 49 | end 50 | else if(num_values >= 2) begin 51 | assign min = _min; 52 | assign sec_min = _sec_min; 53 | TreeComparator2 #(num_values/2, prec) LeftTree(min1, sec_min1, left_vals); 54 | TreeComparator2 #(num_values-num_values/2, prec) RightTree(min2, sec_min2, right_vals); 55 | end 56 | endgenerate 57 | endmodule 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /verilog/VFiles/VarNode.v: -------------------------------------------------------------------------------- 1 | `include "QuantizedAdder.v" 2 | `include "QuantizedSubber.v" 3 | 4 | module VarNode(P_v, x, Qwires, Rwires, llr, rst, clk); 5 | parameter num_connections = 5; 6 | parameter prec = 4; 7 | 8 | output signed [prec-1:0] P_v; 9 | output x; 10 | output signed [num_connections*prec-1:0] Qwires; 11 | input signed [num_connections*prec-1:0] Rwires; 12 | input signed [prec-1:0] llr; 13 | input rst; 14 | input clk; 15 | reg signed [num_connections*prec-1:0] Qreg; 16 | wire signed [num_connections*prec-1:0] sub_wires; 17 | wire signed [prec-1:0] sum_tree_wires [num_connections*2-2:0]; 18 | 19 | 20 | 21 | genvar i; 22 | generate 23 | for(i=0; i pmax) = pmax; 5 | temp(temp < pmin) = pmin; 6 | q = temp/(2^pbd); 7 | end 8 | 9 | -------------------------------------------------------------------------------- /verilog/script_LDPC_v.m: -------------------------------------------------------------------------------- 1 | clear all, close all, clc; 2 | 3 | max_num_frame = 1000000; 4 | quantized = 1; 5 | SNR = 1;%1:.4:2.6; 6 | frac_range = [3]; 7 | num_tests = 5; 8 | global pad pbd pmax pmin 9 | pad = 3; 10 | pbd = 0; 11 | prec = pad + pbd + 1; 12 | tic; 13 | pmax = 2^(pad+pbd) -1; 14 | pmin = -(2^(pad+pbd)); 15 | is_gend = 0; 16 | 17 | biterror = zeros(length(frac_range),length(SNR)); 18 | frameerror = zeros(length(frac_range),length(SNR)); 19 | ber = zeros(length(frac_range),length(SNR)); 20 | fer = zeros(length(frac_range),length(SNR)); 21 | for SNR_index = 1:length(SNR);%--- Max. LLR For Output of Detector 22 | W = 7; 23 | for F_ind=1:length(frac_range) 24 | F = frac_range(F_ind); 25 | fl = F; 26 | il = W - F; 27 | DetectorMaxLLR=2^(W-F-1); 28 | PacketPeriod=1;%------- Packet Period 29 | BS='576';%------------ LDPC Output Block Size 30 | %%II=25;%---------------- LDPC Max. Num. of Iterations 31 | 32 | rate='1/2';%------------- LDPC Code Rate 33 | switch (BS) 34 | case '576' 35 | BSN=576; 36 | case '1920' 37 | BSN=1920; 38 | otherwise 39 | BSN=2304; 40 | end 41 | load H_matrices_802_16e 42 | % for rate 1/2 code load the following matrix 43 | if (rate=='1/2') 44 | H_load=H_1_2; 45 | % Seting Parity Check Matrix 46 | ind = []; %0:A, 1:B 47 | Rate=1/2; 48 | elseif (rate=='2/3') 49 | H_load=H_2_3; 50 | % Seting Parity Check Matrix 51 | ind = [0]; %0:A, 1:B 52 | Rate=2/3; 53 | elseif (rate=='2B3') 54 | H_load=H_2_3_B; 55 | % Seting Parity Check Matrix 56 | ind = [1]; %0:A, 1:B 57 | Rate=2/3; 58 | elseif (rate=='3A4') 59 | H_load=H_3_4_A; 60 | % Seting Parity Check Matrix 61 | ind = [0]; %0:A, 1:B 62 | Rate=3/4; 63 | elseif (rate=='3B4') 64 | H_load=H_3_4_B; 65 | % Seting Parity Check Matrix 66 | ind = [1]; %0:A, 1:B 67 | Rate=3/4; 68 | elseif (rate=='5/6') 69 | H_load=H_5_6; 70 | % Seting Parity Check Matrix 71 | ind = []; %0:A, 1:B 72 | Rate=5/6; 73 | end 74 | %-------------- Calculationg Values of Model Variables Based on Parameters 75 | BSNr=BSN*Rate; 76 | bP=PacketPeriod/BSNr;%-- bit Period 77 | % target code length is 1920 hence z = 1920/24 = 80 78 | z=BSN/24; 79 | zmat=eye(z); 80 | [no_rows no_cols]=size(H_load); 81 | nullmat=zeros(size(zmat)); 82 | nz = no_cols * z; 83 | mz = no_rows * z; 84 | kz = nz - mz; 85 | n = nz/z; 86 | m = mz/z; 87 | k = kz/z; 88 | % For Cml decoder 89 | % rate should come out as 1/2 90 | rate = kz/nz; 91 | Rate = rate; 92 | [Henc] = InitializeWiMaxLDPC( rate, nz, ind ); 93 | [Mm,Nn]=size(Henc); 94 | NumAdd=sum(Henc); 95 | NumComp=sum(Henc,2); 96 | MaxAddSize=max(NumAdd); 97 | MaxCompSize=max(NumComp); 98 | FnmComp=zeros(Mm,MaxCompSize); 99 | FnmCompIdx=zeros(Mm,MaxCompSize); 100 | EmnComp=zeros(MaxAddSize,Nn); 101 | EmnCompIdx=zeros(MaxAddSize,Nn); 102 | for i=1:Mm 103 | [RF,CF,FnmComp(i,1:NumComp(i))]=find(Henc(i,:)); 104 | FnmCompIdx(i,1:NumComp(i))=(CF(1:NumComp(i))-1)*Mm+i; 105 | end 106 | [FnmCompIdxR,FnmCompIdxC,FnmCompIdxV] = find(FnmCompIdx); 107 | IndxF=sub2ind([Mm,MaxCompSize],FnmCompIdxR,FnmCompIdxC); 108 | for i=1:Nn 109 | [RE,CE,EmnComp(1:NumAdd(i),i)]=find(Henc(:,i)); 110 | EmnCompIdx(1:NumAdd(i),i)=(RE(1:NumAdd(i)))+Mm*(i-1); 111 | end 112 | [EmnCompIdxR,EmnCompIdxC,EmnCompIdxV] = find(EmnCompIdx); 113 | IndxE=sub2ind([MaxAddSize,Nn],EmnCompIdxR,EmnCompIdxC); 114 | MinsumOrder=(NumComp-1).*Mm+(1:Mm)'; 115 | SubMinsumOrder=MinsumOrder-Mm; 116 | [temp,tempIdx]=sort(FnmCompIdxV); 117 | SortedIndxF=IndxF(tempIdx); 118 | [temp,tempIdx]=sort(EmnCompIdxV); 119 | SortedIndxE=IndxE(tempIdx); 120 | Imax=20; 121 | Stop=0; 122 | Offset=0; 123 | H=Henc; 124 | SpHenc=sparse(Henc); 125 | noise_var = 0.5*10^(-SNR(SNR_index)/10)*(1/Rate); 126 | if(~is_gend) 127 | fprintf('generating LDPC.v\n'); 128 | verigen(H,prec); 129 | fprintf('done generating\n'); 130 | is_gend = true; 131 | gend_H = H; 132 | elseif(gend_H ~= H) 133 | fprintf('H has changed\n'); 134 | break;%might want to generate verilog for different H matrices 135 | end 136 | 137 | %% simulating 138 | for frame_index = 1:max_num_frame; 139 | %---------------Transmitter Encoding----------------------------------- 140 | x_after_enco = zeros(1,BSN); %Pending Convolution Code 141 | modulated = 1-x_after_enco.*2; %Modulating BPSK 142 | 143 | %---------------Channel Transmitting----------------------------------- 144 | received = modulated + sqrt(noise_var)*(randn(1,BSN)); 145 | 146 | %---------------Receiver Detection------------------------------------- 147 | demodulated=real(received); % Detector 148 | llr = 2.*demodulated./noise_var; % LLR Calculation 149 | 150 | %---------------Receiver Decoding-------------------------------------- 151 | Qllr = quantize(llr); 152 | v_input_llr = Qllr*(2^pbd);%move the decimal to the end of the input values so verilog doesn't need to sanitize it 153 | 154 | 155 | Output = ldpc_decoder_v(Qllr, H); 156 | 157 | v_output_pv = Output*(2^pbd); 158 | % filename = strcat('VFiles/output_pv',int2str(frame_index),'.txt'); 159 | % outputf_id = fopen(filename,'w'); 160 | % fprintf(outputf_id,'%d\n',v_output_pv); 161 | % fclose(outputf_id); 162 | % 163 | % filename = strcat('VFiles/output_x',int2str(frame_index),'.txt'); 164 | % outputf_id = fopen(filename,'w'); 165 | % fprintf(outputf_id,'%d\n',(Output<0)); 166 | % fclose(outputf_id); 167 | 168 | if(frame_index == num_tests) 169 | break; 170 | end 171 | 172 | %[Output, Itr, NuCkNoEr] = LDPC(llr_pri_polar.', Stop,Mm,Nn, Offset, Imax, H, W, F,MinsumOrder,SubMinsumOrder,MaxCompSize,MaxAddSize,SortedIndxE,SortedIndxF); 173 | 174 | dec = Output < 0; 175 | biterror(F_ind, SNR_index) = biterror(F_ind, SNR_index) + sum(dec); 176 | if sum(dec) ~= 0 177 | frameerror(F_ind, SNR_index)= frameerror(F_ind, SNR_index) + 1; 178 | end 179 | if biterror(F_ind, SNR_index) >= 500 && frameerror(F_ind, SNR_index)>=100 180 | ber(F_ind, SNR_index)=biterror(F_ind, SNR_index)/(BSN*frame_index); 181 | fer(F_ind, SNR_index)=frameerror(F_ind, SNR_index)/frame_index; 182 | fprintf('SNR is %d: ber: %f; fer: %f\n', SNR(SNR_index), biterror(SNR_index)/(BSN*frame_index), frameerror(SNR_index)/frame_index); 183 | break; 184 | end 185 | end 186 | end 187 | end 188 | 189 | toc; 190 | -------------------------------------------------------------------------------- /verilog/verigen.m: -------------------------------------------------------------------------------- 1 | %generates the top level verilog module of the LDPC decoder 2 | function verigen(H, prec) 3 | fID = fopen('VFiles/LDPC.v','w'); 4 | num_rows = 288; 5 | num_cols = 576; 6 | %could have passed these values in from the script 7 | 8 | % num_con_each_Vnode 9 | conV = sum(H,1); %sums all columns into row vector, total number of connections for a Var Node 10 | %num_con_each_Cnode 11 | conC = sum(H,2); %sums all rows into a column vector 12 | 13 | fprintf(fID,'`include "VarNode.v"\n'); 14 | fprintf(fID,'`include "CheckNode.v"\n'); 15 | %These defines could be removed in favor of just directly using the 16 | %value 17 | fprintf(fID,'`define prec %d\n', prec); 18 | for i = 1:576 19 | fprintf(fID,'`define n_con_v%d %d\n', i, conV(i)); 20 | end 21 | for j = 1:288 22 | fprintf(fID,'`define n_con_c%d %d\n', j, conC(j)); 23 | end 24 | fprintf(fID,'\n\nmodule LDPC(out, x, done, llr, clk, rst);\n'); 25 | 26 | fprintf(fID,'output [%d:0] out;\n',num_cols*prec - 1); 27 | fprintf(fID,'output [%d:0] x;\n',num_cols-1); 28 | fprintf(fID,'output done;\n'); 29 | 30 | fprintf(fID,'input [%d:0] llr;\n',576*prec - 1); 31 | fprintf(fID,'input clk;\n'); 32 | fprintf(fID,'input rst;\n'); 33 | fprintf(fID,'reg [4:0] count;\n'); 34 | fprintf(fID,'reg done;\n'); 35 | fprintf(fID,'wire [%d:0] x;\n',num_cols - 1); 36 | fprintf(fID,'wire [%d:0] out_check;\n',num_rows - 1); 37 | 38 | nth_in_c = zeros(num_cols,num_rows); %nth_in_c[a col][n] = The row where the nth 1 in a col is 39 | nth_in_r = zeros(num_rows,num_cols); %nth_in_r[a row][n] = The col where the nth 1 in a row is 40 | 41 | for i = 1:576 42 | for j = 1:288 43 | if(H(j,i)) 44 | k = 1; 45 | while(nth_in_c(i,k) ~= 0) 46 | k = k + 1; 47 | end 48 | nth_in_c(i,k) = j; 49 | k = 1; 50 | while(nth_in_r(j,k) ~= 0) 51 | k = k + 1; 52 | end 53 | nth_in_r(j,k) = i; 54 | 55 | fprintf(fID,'\twire signed [`prec-1:0] Rwire_%d_%d;', i,j); 56 | fprintf(fID,'\twire signed [`prec-1:0] Qwire_%d_%d;\n ',i,j); 57 | end 58 | end 59 | end 60 | 61 | 62 | 63 | %possibly redo this for tristate QR wire 64 | fprintf(fID, '\n\n'); 65 | for i = 1:576 66 | fprintf(fID,'\twire signed [`prec*`n_con_v%d-1:0] Rwires_v%d;', i,i); 67 | fprintf(fID,'\twire signed [`prec*`n_con_v%d-1:0] Qwires_v%d;\n', i,i); 68 | for k = 1:conV(i) 69 | fprintf(fID,'\t\tassign Rwires_v%d[%d:%d] = Rwire_%d_%d;', i, k*prec-1,prec*(k-1), i, nth_in_c(i,k)); % 70 | fprintf(fID,'\tassign Qwire_%d_%d = Qwires_v%d[%d:%d];\n', i, nth_in_c(i,k), i, k*prec-1,prec*(k-1)); %j = nth_in_c[i][k] 71 | end 72 | end 73 | for j = 1:288 74 | fprintf(fID,'\twire signed [`prec*`n_con_c%d-1:0] Rwires_c%d;', j, j); 75 | fprintf(fID,'\twire signed [`prec*`n_con_c%d-1:0] Qwires_c%d;\n', j, j); 76 | for k = 1:conC(j) 77 | fprintf(fID,'\t\tassign Qwires_c%d[%d:%d] = Qwire_%d_%d;', j, k*prec-1,prec*(k-1), nth_in_r(j,k), j); %%%i = nth_in_r[j][k] 78 | fprintf(fID,'\tassign Rwire_%d_%d = Rwires_c%d[%d:%d];\n', nth_in_r(j,k), j, j, k*prec-1,prec*(k-1)); % 79 | end 80 | end 81 | 82 | for j= 1:288 83 | fprintf(fID,'\tCheckNode #(`n_con_c%d, `prec) node_c%d(Rwires_c%d, Qwires_c%d, rst, clk);\n', j, j, j, j); 84 | end 85 | 86 | 87 | for i = 1:576 88 | fprintf(fID,'\tVarNode #(`n_con_v%d, `prec) node_v%d(out[%d:%d], x[%d], Qwires_v%d, Rwires_v%d, llr[%d:%d], rst, clk);\n', i, i, prec*(i)-1, (i-1)*prec, i-1, i, i, i*prec-1,(i-1)*prec); 89 | end 90 | 91 | for j = 1:288 92 | fprintf(fID,'assign out_check[%d] =',j-1); 93 | first = true; 94 | for i = 1:576 95 | if(H(j,i)) 96 | if(first) 97 | first = false; 98 | fprintf(fID,' x[%d]',i-1); 99 | else 100 | fprintf(fID,' + x[%d]',i-1); 101 | end 102 | 103 | end 104 | end 105 | fprintf(fID,';\n'); 106 | end 107 | fprintf(fID, 'always@(posedge clk) begin\n\tif(rst) begin\n\t\tcount <= 0;\n\t\tdone <= 0;\n\tend\n\t else if((count == 25) || (out_check == 0)) begin\n\t\t done <= 1;\n\tend\n\telse if (count < 25) begin\n\t\tcount <= count + 1;\n\tend\nend\n'); 108 | fprintf(fID,'endmodule\n'); 109 | end 110 | --------------------------------------------------------------------------------