# 数学模型

1、进行校验位的交织操作
2、对整个码组进行交织操作

## 校验位交织

d i = u i      f o r     0 < = i < = K 1 d_i=u_i\ \ \ \ for\ \ \ 0<=i<=K1
d K 1 + 360 t + s = u K 1 + Q l d p c s + t       f o r      0 < = s < 360 , 0 < = t < = Q l d p c d_{K1+360t+s}=u_{K1+Q_{ldpc}s+t}\ \ \ \ \ for \ \ \ \ 0<=s<360,0<=t<=Q_{ldpc}

## 码组的列旋转交织

1、校验位交织只有码组的校验位参与交织操作，而列旋转交织是整个码组进行交织操作
2、校验位交织的行是固定的360个元素，而列旋转交织则不是固定值
3、列旋转交织在转置的基础上，每一行均有一个tc的偏移，这也使得在书写FPGA代码的时候要比校验位交织难一点

tc01234567
16QAM00017202021

c m = i / 2025 c_m=i/2025
r n = ( i − t c ) % 2025 r_n=(i-tc)\%2025

# 交织的MATLAB实现

sim_options = struct(...
'CRATE_DATA',       '3/5', ...        %业务编码码率1/2 3/5 2/3 3/4 4/5 5/6
'CONSTELLATION', '16-QAM' ...
);
tx_nFrame =1;

fid1 = fopen('bint_data_in.txt','r');
DataIn = fscanf(fid1,'%d');

switch sim_options.CRATE_DATA
case '1/2',
Q = 25;
CR=4/9;
case '3/5',
Q = 18;
CR=3/5;
case '2/3',
Q = 15;
CR=2/3;
case '3/4',
Q = 12;
CR=11/15;
case '4/5',
Q = 10;
CR=7/9;
case '5/6',
Q = 8;
CR=37/45;
otherwise
error('sim_options UNKNOWN CODING RATE');
end
%------------------------------------------------------------------------------
% PLP-specific Parameters Definition
%------------------------------------------------------------------------------
CONSTEL  = sim_options.CONSTELLATION;     % modulation constellation
COD_RATE = CR;
S        = 360;   % The S of the code
CRATE    = sim_options.CRATE_DATA;             % The code rate
%------------------------------------------------------------------------------
% Procedure
%---------------------------------------
data = DataIn';
nbint_len  = 16200  ; %  block size, need to pass this in
int_type = 2;
parity_only = false;
Nc = 8;
switch CONSTEL
case 'QPSK'
int_type = 0;
case '16-QAM'
Tc = [0	0	0	1	7	20	20	21];
end
Nr = nbint_len / Nc;
numIntlvBlocks = floor(length(data)/nbint_len); % Number of interleaving blocks
data = data(1:numIntlvBlocks*nbint_len); %clip the length of the input data
bitIntlvOut = zeros(1,length(data),'single'); %mem preallocation

if int_type == 0
%do no interleaving
bitIntlvOut = data;
elseif  int_type == 2
%the type B interleaver
plen = round(nbint_len * (1 - COD_RATE));
%make the parity interleaving table
parity_table = zeros(1,plen);

count = 1;
for scount = 0:S-1
for t = 0:Q-1
parity_table(count) = S * t + scount + 1;
count = count + 1;
end
end

%compare data
fprintf(fid1,'%d\n',parity_table);

%make the Sony interleaving table
if ~parity_only;
code_table = zeros(Nc, Nr);

for cols = 1:Nc
tc = Tc(cols);
rw = (0:Nr-1)  -  tc;
rwm = mod(rw, Nr) + 1;
rwm = rwm + (cols - 1) * Nr;

code_table(cols, :) = rwm;
end

code_table = reshape(code_table, Nr, []);% + 1;
code_table = reshape(code_table, nbint_len, []);% + 1;
end

intered_parity = zeros(1, plen);

for it=1:numIntlvBlocks
%pick off the parity bits
parity = data( (it * nbint_len) - plen + 1:it * nbint_len);

%interleave the parity bits
intered_parity(parity_table) = parity;

%tack on the parity bits and interleave the whole lot
bitIntlvWr = [data((it-1)*nbint_len+1:it* nbint_len - plen) intered_parity];

%interleave the code word
if ~parity_only; bitIntlvWr = bitIntlvWr(code_table); end

% LDPC block append
bitIntlvOut((it-1)*nbint_len+1:it*nbint_len) = bitIntlvWr;
end

end %if int_type == 1

DataOut.data = bitIntlvOut;
save bitIntlvOut.mat   bitIntlvOut


1、引入输入码元
2、根据全局变量的定义选择不同的参数列表

1、输入码组的个数
2、根据全局变量的设置选择相应tc的值
3、其实这个程序不光可以对一个码组进行交织操作，同时可以对多个码组进行相应的交织操作。看起来程序处理的那么复杂，其实有绝大多数程序是对这方面进行相应的处理，本来博主想更改成一个码组进行处理，这样方便理解一点，但是一想，这是对源代码的不尊重，因为源代码明明功能多，自己非得降低他的功能。

1、计算校验位的个数
2、对校验位进行交织

1、计算列旋交织的输出地址

# 交织的FPGA实现

## FPGA代码

timescale 1ns/1ps

//
//Company: MYMINIEYE
//Engineer: rp lv
//
//Create Date: 2016/03/14 09:41:00
//Design name:
//Module name: tx_Bit_interleaver
//Project name: tx_dvb_t2
//Target Devices: zc706
//Description:
//
//Dependencies:
//
//Revision: v_01
//Revision 0.01 -File Created
//
//
define UD #1

module tx_Bit_interleaver
(
input       sclk                      ,
input       rst_n                     ,
input       s_config_tvalid          ,
input [3:0] s_config_tdata           ,
input       s_data_tvalid            ,
input       s_data_tdata             ,
input       s_data_tlast             ,

output reg  m_data_tvalid            ,
output reg  m_data_tdata             ,
output reg  m_data_tlast
);

//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/

reg             mode_type                   ;
reg     [2:0]   code_rate                   ;
reg     [5:0]   Qldpc                       ;
reg     [13:0]  Nbch                        ;
reg     [13:0]  Pldpc                       ;
reg     		bitInter_enb                ;
reg     [13:0]  s_data_cnt                  ;
reg     		start_parity                ;

reg             bitInter_ram_wren           ;
reg             bitInter_ram_dina           ;

reg 	        bitInter_ram_wren_reg       ;
reg 	        store_over                  ;
reg 	        start_colrot_reg            ;
reg 	        start_colrot_reg2           ;
wire  	        start_colrot                ;

wire            bitInter_ram_doutb          ;
reg             colrot_valid_reg            ;
reg             colrot_valid_reg2           ;

wire 		    parity_valid                ;
wire 		    colrot_valid                ;

reg             s_data_tvalid_reg           ;
wire            start_data_invld            ;

//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/

//====================================================================================
// configure parameter
//====================================================================================
always@(posedge sclk)
begin
if(~rst_n)
begin
mode_type <=UD 0;
code_rate <= UD 0;
end
else if (s_config_tvalid)
begin
mode_type <= UD s_config_tdata[0];
code_rate <= UD s_config_tdata[3:1];
end
end

always@(posedge sclk)
begin
if(~rst_n)
Qldpc <= UD 0;
else
begin
case (code_rate)
3'b000 : Qldpc <= UD 6'd36; // Code Rate = 1/4;
3'b001 : Qldpc <= UD 6'd25; // Code Rate = 1/2;
3'b010 : Qldpc <= UD 6'd18; // Code Rate = 3/5;
3'b011 : Qldpc <= UD 6'd15; // Code Rate = 2/3;
3'b100 : Qldpc <= UD 6'd12; // Code Rate = 3/4;
3'b101 : Qldpc <= UD 6'd10; // Code Rate = 4/5;
3'b110 : Qldpc <= UD 6'd8;  // Code Rate = 5/6;
default: Qldpc <= UD 6'd25; // Code Rate = 1/2;
endcase
end
end

//====================================================================================
// Processing Parity_Interleaver
//====================================================================================
always@(posedge sclk)
begin
if(~rst_n)
Nbch <= UD 0;
else
begin
case(code_rate)
3'd0 : Nbch <= UD 14'd3240;
3'd1 : Nbch <= UD 14'd7200;
3'd2 : Nbch <= UD 14'd9720;
3'd3 : Nbch <= UD 14'd10800;
3'd4 : Nbch <= UD 14'd11880;
3'd5 : Nbch <= UD 14'd12600;
3'd6  : Nbch <= UD 14'd13320;
default:Nbch <= UD 14'd7200;
endcase
end
end

always@(posedge sclk)
begin
if(~rst_n)
Pldpc <= UD 0;
else
begin
case(code_rate)
3'd0 : Pldpc <= UD 14'd12960;
3'd1 : Pldpc <= UD 14'd9000;
3'd2 : Pldpc <= UD 14'd6480;
3'd3 : Pldpc <= UD 14'd5400;
3'd4 : Pldpc <= UD 14'd4320;
3'd5 : Pldpc <= UD 14'd3600;
3'd6  : Pldpc <= UD 14'd2880;
default:Pldpc <= UD 14'd9000;
endcase
end
end

always@(posedge sclk)
begin
bitInter_enb <=UD s_data_tvalid;
end

always@(posedge sclk)
begin
if(bitInter_enb)
s_data_cnt <= UD s_data_cnt + 1'b1;
else
s_data_cnt <= UD 0;
end

always@(posedge sclk)
begin
if(s_data_cnt == Nbch-5'd4) // consider latency
start_parity <= UD 1'b1;
else
start_parity <= UD 1'b0;
end

always@(posedge sclk)
begin
if(~rst_n)
bitInter_ram_addra <= UD 0;
else if(bitInter_enb)
begin
if(parity_valid && mode_type == 1)
else if(mode_type == 1)
bitInter_ram_addra <= UD bitInter_ram_addra + 1'b1;
else if(mode_type == 0)
end
else
begin
bitInter_ram_addra <= UD 0;
end
end

always@(posedge sclk)
begin
bitInter_ram_wren <=UD s_data_tvalid;
bitInter_ram_dina <=UD s_data_tdata;
end

always@(posedge sclk)
begin
bitInter_ram_wren_reg <=UD bitInter_ram_wren;
end
always@(posedge sclk)
begin
if(~rst_n || start_colrot)
store_over <= UD 1'b0;
else if(~bitInter_ram_wren && bitInter_ram_wren_reg)
store_over <= UD 1'b1;
end

always@(posedge sclk)
begin
if(~rst_n)
start_colrot_reg <= UD 0;
start_colrot_reg <= UD 1;
else
start_colrot_reg <= UD 0;
end

always@(posedge sclk)
begin
start_colrot_reg2 <=UD start_colrot_reg;
end

assign start_colrot = ~start_colrot_reg2 && start_colrot_reg;

always@(posedge sclk)
begin
if(~rst_n)
bitInter_ram_addrb <=UD 0;
else if(mode_type == 0 && colrot_valid_reg && bitInter_ram_addrb < 14'd16199) // QPSK
else if(mode_type == 1) //16 QAM
bitInter_ram_addrb <=UD colrot_addr;
else
end

always@(posedge sclk)
begin
colrot_valid_reg <= UD colrot_valid;
colrot_valid_reg2 <= UD colrot_valid_reg;
m_data_tvalid <= UD colrot_valid_reg2;
end
always@(posedge sclk)
begin
m_data_tdata <= UD bitInter_ram_doutb;
end

always@(posedge sclk)
begin
if(~colrot_valid_reg && colrot_valid_reg2)
m_data_tlast <= UD 1'b1;
else
m_data_tlast <= UD 1'b0;
end

always@(posedge sclk)
begin
s_data_tvalid_reg <= UD s_data_tvalid;
end

assign start_data_invld = ~s_data_tvalid_reg && s_data_tvalid;

always@(posedge sclk)
begin
if(~rst_n)
else if(s_config_tvalid)
s_data_tready <= UD 1;
else if(start_data_invld)
else if(m_data_tlast)
s_data_tready <= UD 1;
end

(
.sclk(sclk),            //input
.rst_n(rst_n),           //input
.Qldpc(Qldpc),          //input [5:0]
.Pldpc(Pldpc),          //input [13:0]
.start_parity(start_parity),   //input
.parity_valid(parity_valid)    //output reg
);

(
.sclk(sclk),             // input
.rst_n(rst_n),             //input
.start_colrot(start_colrot),    // input
.colrot_valid(colrot_valid)    //  output reg
);

ldpc_ram ldpc_ram
(
.clka(sclk), // input clka
.wea(bitInter_ram_wren), // input [0 : 0] wea
.dina(bitInter_ram_dina), // input [0 : 0] dina
.clkb(sclk), // input clkb
.doutb(bitInter_ram_doutb) // output [0 : 0] doutb
);

endmodule


timescale 1ns/1ps

//
//Company: MYMINIEYE
//Engineer: rp lv
//
//Create Date: 2016/03/14 09:41:00
//Design name:
//Project name: tx_dvb_t2
//Target Devices: zc706
//Description:
//
//Dependencies:
//
//Revision: v_01
//Revision 0.01 -File Created
//
//
define UD #1
(
input  			  sclk 			,
input  			  rst_n 		,
input [5:0] 	  Qldpc 		,
input [13:0]      Pldpc 		,
input  			  start_parity 	,
output reg        parity_valid
);

//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/

reg 				parity_enb 		;
reg [13:0]			parity_cnt 		;
reg [4:0] 			s_cnt 			;
reg [13:0]			S 				;
reg [13:0]			T 				;

//========================================================================================\
//************** 	Main  	Code		**********************************
//========================================================================================/
always@(posedge sclk)
begin
if(~rst_n)
parity_enb <= UD 1'b0;
else if(start_parity)
parity_enb <= UD 1'b1;
else if(parity_cnt == Pldpc - 1)
parity_enb <= UD 1'b0;
end

always@(posedge sclk)
begin
if(~rst_n)
parity_cnt <= UD 0;
else if(parity_enb)
parity_cnt <= UD parity_cnt + 1'b1;
else
parity_cnt <= UD 0;
end

always@(posedge sclk)
begin
if(~rst_n)
begin
s_cnt <= UD 0;
S <= UD 0;
end
else if(parity_enb)
begin
if(s_cnt < Qldpc - 1)
begin
s_cnt <= UD s_cnt + 1'b1;
S <= UD  S + 14'd360;
end
else
begin
s_cnt <= UD 0;
S <= UD 0;
end
end
else
begin
s_cnt <= UD 0;
S <= UD 0;
end
end

always@(posedge sclk)
begin
if(~rst_n)
T <= UD 0;
else if(parity_enb)
begin
if(s_cnt == Qldpc -1)
T <= UD T + 1;
end
else
T <= UD 0;
end

always@(posedge sclk)
begin
if(parity_enb)
parity_addr <= UD S + T;
else
end

always@(posedge sclk)
begin
parity_valid <= UD parity_enb;
end

endmodule


timescale 1ns/1ps

//
//Company: MYMINIEYE
//Engineer: rp lv
//
//Create Date: 2016/03/14 13:54:00
//Design name:
//Project name: tx_dvb_t2
//Target Devices: zc706
//Description:
//**************************************
//  0 2050 4050 8099 10118 12130 14155 16179
//  1 2026 4051 6075 10119 12131 14156 16180
//  2 2027 4052 6076 10120 12132 14157 16181
//  ......
//**************************************
//Dependencies:
//
//Revision: v_01
//Revision 0.01 -File Created
//
//
define UD #1
(
input             sclk  			,
input             rst_n 			,
input             start_colrot		,
output reg        colrot_valid
);

//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/

parameter  Nc  = 3'd7;
parameter  Lcr = 14'd16033;//lcr = ldpc - Nc*21=16200 - 8*21 = 16032;
parameter  Nr  = 11'd2025;

parameter  Idle  = 24'b0000_0000_0000_0000_0000_0000;
parameter  Row_1 = 24'b0000_0000_0000_0000_0000_0001;
parameter  Row_2 = 24'b0000_0000_0000_0000_0000_0010;
parameter  Row_3 = 24'b0000_0000_0000_0000_0000_0100;
parameter  Row_4 = 24'b0000_0000_0000_0000_0000_1000;
parameter  Row_5 = 24'b0000_0000_0000_0000_0001_0000;
parameter  Row_6 = 24'b0000_0000_0000_0000_0010_0000;
parameter  Row_7 = 24'b0000_0000_0000_0000_0100_0000;
parameter  Row_8 = 24'b0000_0000_0000_0000_1000_0000;
parameter  Row_9 = 24'b0000_0000_0000_0001_0000_0000;
parameter  Row_10 = 24'b0000_0000_0000_0100_0000_0000;
parameter  Row_11 = 24'b0000_0000_0000_1000_0000_0000;
parameter  Row_12 = 24'b0000_0000_0001_0000_0000_0000;
parameter  Row_13 = 24'b0000_0000_0010_0000_0000_0000;
parameter  Row_14 = 24'b0000_0000_0100_0000_0000_0000;
parameter  Row_15 = 24'b0000_0000_1000_0000_0000_0000;
parameter  Row_16 = 24'b0000_0001_0000_0000_0000_0000;
parameter  Row_17 = 24'b0000_0010_0000_0000_0000_0000;
parameter  Row_18 = 24'b0000_0100_0000_0000_0000_0000;
parameter  Row_19 = 24'b0000_1000_0000_0000_0000_0000;
parameter  Row_20 = 24'b0001_0000_0000_0000_0000_0000;
parameter  Row_21 = 24'b0010_0000_0000_0000_0000_0000;
parameter  Row_last = 24'b0100_0000_0000_0000_0000_0000;
parameter  Gen_end  = 24'b1000_0000_0000_0000_0000_0000;

parameter  Idle1 = 2'b00;
parameter  gen1  = 2'b01;
parameter  gen2  = 2'b10;

reg [23:0]  state=0;
reg [23:0]  state_n=0;
reg [2:0]  Col_cal;
reg [13:0] Row_cal;

reg start_colrot_reg;
reg start_colrot_cal;

reg colrot_enb;
reg [13:0]colrot_cnt;
reg [2:0] col_cnt;

//====================================================================================
// Generate addr for ColRot bit and valid signal
//====================================================================================

always@(posedge sclk)
begin
if(~rst_n)
state <= UD 0;
else
state <= UD state_n;
end

always@(posedge sclk)
begin
start_colrot_reg <= UD start_colrot;
start_colrot_cal <= UD start_colrot_reg;
end

always@(*)
begin
state_n = state;
case(state)
Idle : if(start_colrot_cal)    state_n = Row_1;  else state_n = Idle;
Row_1: if(Col_cal < Nc)       state_n = Row_1;  else state_n = Row_2;
Row_2: if(Col_cal < Nc)       state_n = Row_2;  else state_n = Row_3;
Row_3: if(Col_cal < Nc)       state_n = Row_3;  else state_n = Row_4;
Row_4: if(Col_cal < Nc)       state_n = Row_4;  else state_n = Row_5;
Row_5: if(Col_cal < Nc)       state_n = Row_5;  else state_n = Row_6;
Row_6: if(Col_cal < Nc)       state_n = Row_6;  else state_n = Row_7;
Row_7: if(Col_cal < Nc)       state_n = Row_7;  else state_n = Row_8;
Row_8: if(Col_cal < Nc)       state_n = Row_8;  else state_n = Row_9;
Row_9: if(Col_cal < Nc)       state_n = Row_9;  else state_n = Row_10;
Row_10: if(Col_cal < Nc)       state_n = Row_10;  else state_n = Row_11;
Row_11: if(Col_cal < Nc)       state_n = Row_11;  else state_n = Row_12;
Row_12: if(Col_cal < Nc)       state_n = Row_12;  else state_n = Row_13;
Row_13: if(Col_cal < Nc)       state_n = Row_13;  else state_n = Row_14;
Row_14: if(Col_cal < Nc)       state_n = Row_14;  else state_n = Row_15;
Row_15: if(Col_cal < Nc)       state_n = Row_15;  else state_n = Row_16;
Row_16: if(Col_cal < Nc)       state_n = Row_16;  else state_n = Row_17;
Row_17: if(Col_cal < Nc)       state_n = Row_17;  else state_n = Row_18;
Row_18: if(Col_cal < Nc)       state_n = Row_18;  else state_n = Row_19;
Row_19: if(Col_cal < Nc)       state_n = Row_19;  else state_n = Row_20;
Row_20: if(Col_cal < Nc)       state_n = Row_20;  else state_n = Row_21;
Row_21: if(Col_cal < Nc)       state_n = Row_21;  else state_n = Row_last;
Row_last:  if(Row_cal < Lcr)   state_n = Row_last;  else state_n = Gen_end;
Gen_end : state_n = Idle;
default : state_n = Idle;
endcase
end

always@(posedge sclk)
begin
if(~rst_n)
Row_cal <= UD 0;
else if (state_n == Row_last)
Row_cal <= UD Row_cal + 1'b1;
else
Row_cal <=UD  0;
end

always @(posedge sclk)
begin
case(state_n)
Idle :  Col_cal <= UD 0;
Row_1: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_2: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_3: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_4: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_5: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_6: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_7: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_8: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_9: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_10: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_11: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_12: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_13: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_14: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_15: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_16: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_17: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_18: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_19: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_20: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_21: if(Col_cal == Nc)       Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
Row_last:if(Row_cal == Lcr)     Col_cal <=UD 0; else Col_cal <=UD Col_cal + 1'b1;
default : Col_cal <=UD 0;
endcase
end

//====================================================================================
// Generate Rotate addr for Ldpc Block
//====================================================================================
always@(posedge sclk)
begin
case(state)
Idle: colrot_addr <=UD 0;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd1;
else if (Col_cal == 3'd4) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd7;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd4) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd7;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;

else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd4) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd7;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;

else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd4) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd7;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;

else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd4) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd7;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;

else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd4) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd7;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;

else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd4) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd7;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;

else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd6) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr  - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr + 12'd2025 - 5'd21;
else if (Col_cal == 3'd3) colrot_addr <=UD gen_taddr  - 5'd1;
else if (Col_cal == 3'd5) colrot_addr <=UD gen_taddr  - 5'd20;
else if (Col_cal == 3'd7) colrot_addr <=UD gen_taddr  - 5'd21;
default : colrot_addr <=UD 0;
endcase
end

//====================================================================================
// Generate normal addr , so that easy to get rotate addr
//====================================================================================
always@(posedge sclk)
begin
if(~rst_n)
colrot_enb <= UD 1'b0;
else if(start_colrot)
colrot_enb <= UD 1'b1;
else if(colrot_cnt == 14'd16199)
colrot_enb <= UD 1'b0;
end

always@(posedge sclk)
begin
if(~rst_n)
colrot_cnt <= UD 0;
else if(colrot_enb)
colrot_cnt <= UD colrot_cnt + 1'b1;
else
colrot_cnt <= UD 0;
end

always@(posedge sclk)
begin
if(~rst_n)
begin
col_cnt <= UD 0;
col_addr <= UD 0;
end
else if(colrot_enb)
begin
if(col_cnt < Nc)
begin
col_cnt <= UD col_cnt + 1'b1;
col_addr <= UD  col_addr + 14'd2025;
end
else
begin
col_cnt <= UD 0;
col_addr <= UD 0;
end
end
else
begin
col_cnt <= UD 0;
col_addr <= UD 0;
end
end

always@(posedge sclk)
begin
if(~rst_n)
else if(colrot_enb )
begin
if(col_cnt == Nc)
row_addr <= UD row_addr + 1;
end
else
begin
end
end

always@(posedge sclk)
begin
if(colrot_enb)
gen_taddr <= UD col_addr + row_addr;
else
end
//====================================================================================
// Generate Rotate addr  valid signal
//====================================================================================

always @(posedge sclk)
begin
if(~rst_n)
colrot_valid <= UD 0;
else if(state_n == Idle || state_n ==Gen_end)
colrot_valid <=UD 0;
else
colrot_valid <=UD 1;
end

endmodule



## 交织的GPGA测试代码

timescale 1ns / 1ps

// Company: MYMINEYE
// Engineer:rplv
//
// Create Date:   11:32:55 03/15/2016
// Design Name:   tx_Bit_interleaver
// Module Name:   tb_tx_Bit_interleaver.v
// Project Name:  tx_dvb_t2
// Target Device: zc706
// Description:
//
//
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
//

define UD #1

module tb_tx_Bit_interleaver;

// Inputs
reg clk;
reg rstn;
reg s_config_tvalid;
wire [3:0] s_config_tdata;
reg s_data_tvalid;
reg s_data_tdata;
reg s_data_tlast;

// Outputs
wire m_data_tvalid;
wire m_data_tdata;
wire m_data_tlast;

reg s_data_tvalid1;
reg s_data_tlast1;

// Instantiate the Unit Under Test (UUT)
tx_Bit_interleaver uut (
.clk(clk),
.rstn(rstn),
.s_config_tvalid(s_config_tvalid),
.s_config_tdata(s_config_tdata),
.s_data_tvalid(s_data_tvalid1),
.s_data_tdata(s_data_tdata),
.s_data_tlast(s_data_tlast1),
.m_data_tvalid(m_data_tvalid),
.m_data_tdata(m_data_tdata),
.m_data_tlast(m_data_tlast)
);

//=========================================================================
//   config parameter
//=========================================================================
reg  mode_type = 1'b1;
reg  [2:0]code_rate = 3'd2;

assign s_config_tdata [0] = mode_type;
assign s_config_tdata [3:1] = code_rate;

//=========================================================================
//   initial
//=========================================================================
initial begin
s_config_tvalid = 0;
s_data_tvalid = 0;
rstn = 0;
clk = 0;

repeat(10) @(posedge clk);#1;
rstn = 1;
repeat(5) @(posedge clk);#1;
s_config_tvalid = 1;
repeat(1) @(posedge clk);#1;
s_config_tvalid = 0;
repeat(1) @(posedge clk);#1;
s_data_tvalid = 1;
s_data_tlast = 0;
repeat(16200*1-1) @(posedge clk);#1;//QPSK = 8100,
//repeat(4049) @(posedge clk);#1;//QAM = 4050;
s_data_tvalid = 1;
s_data_tlast = 1;
repeat(1) @(posedge clk);#1;//
s_data_tvalid = 0;
s_data_tlast = 0;
end

always@(posedge clk)
begin
s_data_tvalid1 <= UD s_data_tvalid;
s_data_tlast1  <= UD s_data_tlast;
end

//=========================================================================
//   input
//=========================================================================

integer fid1;
initial

begin
fid1 = $fopen("bint_data_in.txt","r"); end always@(posedge clk) begin if(s_data_tvalid)$fscanf(fid1,"%d",s_data_tdata);
end

//=========================================================================
// output
//=========================================================================

integer fid2;
initial
begin
fid2 = $fopen("ms_bitInter_sim.txt","w"); end always@(posedge clk) begin if(m_data_tvalid)$fwrite(fid2,"%b\n",m_data_tdata);
end

always #5 clk = ~clk;
//=========================================================================
//=========================================================================
wire            parity_valid = tb_tx_Bit_interleaver.uut.parity_valid;

integer fid3;
initial
begin
fid3 = $fopen("ms_parity_addr.txt","w"); end always@(posedge clk) begin if(parity_valid)$fwrite(fid3,"%d\n",parity_addr+1'b1);
end

endmodule



MATLAB验证代码如下：

clc ;
clear all;
data_lab = bitIntlvOut;
tx_nFrame =1;

bitInter_data_lab = [data_lab'];

fid1 = fopen('ms_bitInter_sim.txt','r');
bitInter_data_sim = fscanf(fid1,'%d');

start_Idx = length(bitInter_data_lab)*(tx_nFrame - 1);
if(isempty(bitInter_data_sim))
bitInter_data_result = 0;
else
bitInter_data_result = sum(abs(bitInter_data_lab - bitInter_data_sim(start_Idx+1:start_Idx+length(bitInter_data_lab))));
end
a = bitInter_data_result

`

[1]、电子发烧友学院

04-07

04-12 2980
09-09 2180
03-28
03-05
09-16 2543
12-24
12-24
12-12
09-05 2218
09-28