基于FPGA交织的实现

  • 项目简述
  • 数学模型
    • 校验位交织
    • 码组的列旋转交织
  • 交织的MATLAB实现
  • 交织的FPGA实现
    • FPGA代码
    • 交织的GPGA测试代码
  • 小结
  • 参考文献
  • 总结

项目简述

交织多么好听的名字,第一次听见这个名字是在移动通信的课程中,当时就对这个名字一亮。交织其实就是把原有的码元顺序打乱进行发送,说白了就是矩阵变换。至于为什么要把原有的码元顺序打乱,是因为现实中传送的码元每一段都有固定的校验位,通过该校验位可以在码元错误较少的情况下进行纠错。而实际中受环境影响的码元是突发性错误,那么我们先经过交织之后传送的码元产生的突发性错误,经过解交织之后就会把原有的突发性错误转变成离散性错误,那么就可以有效的利用校验位进行纠错。这也是交织在通信系统中起到的主要作用,即变突发性错误为随机性错误。

数学模型

从上面我们可以知道交织就是把原有的码元顺序打乱。一般的码组分为信息位和校验位,在交织的过程中,我们一般分为两步:
1、进行校验位的交织操作
2、对整个码组进行交织操作

上面两步的交织的原理并不一样,接下来分别介绍常见的交织操作。

校验位交织

校验位交织的数学公式如下:
d i = u i f o r 0 < = i < = K 1 d_i=u_i\ \ \ \ for\ \ \ 0<=i<=K1 di​=ui​    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} dK1+360t+s​=uK1+Qldpc​s+t​     for    0<=s<360,0<=t<=Qldpc​
其中 i i i是码组中第几个码元, K 1 K1 K1是信息位的个数, u i u_i ui​是交织前的码元, d i d_i di​是交织后的输出码元, Q l d p c = 校 验 位 个 数 / 360 Q_{ldpc}=校验位个数/360 Qldpc​=校验位个数/360。

依据校验位交织地址生成公式可知,校验位交织本质是行进列出,若校验位数据向量重新构成矩阵形式,交织前矩阵为Qldpc*360,即依次将向量数据每行写入 360 个数,第 361 个数为第 2 行第 1 列数,依次类推。存入 Rom 地址如图所示,

我们矩阵的时候都是一行一行的看,这里虽然本质上是列进行出,但是我们读地址是一行一行读的,所以这个就相当于矩阵的转置操作。即取数据依次以如下地址取数据,重新生成新读出矩阵。

这里隐含一个非常重要的FPGA技巧,FPGA中矩阵的转置如何使用硬件语言来描述。 等进行讲解Verilog代码的时候,可以着重注意矩阵转置对应的Verilog代码。

码组的列旋转交织

上面我们已经进行了检验位交织,将校验位交织与原来的信息位组合成的输入 d i d_{i} di​ 按列顺序依次写入列旋转交织器,然后按行依次读出完成列旋转交织,每列写入的起始位置由 t c tc tc 决定 ,整个列旋转交织器:

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

以16QAM为例,上面的列旋交织主要有2025行8列,其中每一列的tc的值如下:

tc 0 1 2 3 4 5 6 7
16QAM 0 0 0 1 7 20 20 21

列旋转交织器的输入为 d i , 0 < = i < = N d_i,0<=i<=N di​,0<=i<=N(其中N是整个码组的长度,在16QAM中N的长度是16200),写入列旋转交织器的 c m c_m cm​ 列, r n r_n rn​ 行,则行和列需要满足下面的情况(以16QAM为例):
c m = i / 2025 c_m=i/2025 cm​=i/2025
r n = ( i − t c ) % 2025 r_n=(i-tc)\%2025 rn​=(i−tc)%2025
由上面的的公式,我们可以写出列旋交织器的输入矩阵与输出矩阵之间的关系,这里同样是按照按照行的顺序写入读出。交织前的地址是:

进行列旋交织之后的地址如下:

这里注意,FPGA的语言叫做硬件描述语言,那么要想才能成功描述上面矩阵的变化,就必须找到上面矩阵的规律,上面的公式规律已经标红,大家可以最终结合相应的FPGA代码进行学习。大家阅读下面的FPGA代码的时候,可以发现一共2025行数据,只有前21行数据是乱的,后面的2000多行数据的计算都是有规律的,这也是FPGA代码中有一个很笨重状态机的原因。大家阅读FPGA代码的时候,一定要联系上面的矩阵,可以便于理解。

交织的MATLAB实现

经过上面的原理介绍,相信大家对交织的操作有了一定的了解,那么接下来我们给出相应的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_DATAcase '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;otherwiseerror('sim_options UNKNOWN CODING RATE');
end%------------------------------------------------------------------------------% PLP-specific Parameters Definition%------------------------------------------------------------------------------CONSTEL  = sim_options.CONSTELLATION;     % modulation constellationCOD_RATE = CR;S        = 360;   % The S of the codeCRATE    = sim_options.CRATE_DATA;             % The code rate%------------------------------------------------------------------------------% Procedure%---------------------------------------data = DataIn';nbint_len  = 16200  ; %  block size, need to pass this inint_type = 2;parity_only = false;Nc = 8;switch CONSTELcase 'QPSK'int_type = 0;case '16-QAM'Tc = [0  0   0   1   7   20  20  21];endNr = nbint_len / Nc;numIntlvBlocks = floor(length(data)/nbint_len); % Number of interleaving blocksdata = data(1:numIntlvBlocks*nbint_len); %clip the length of the input databitIntlvOut = zeros(1,length(data),'single'); %mem preallocationif int_type == 0%do no interleavingbitIntlvOut = data;elseif  int_type == 2%the type B interleaverplen = round(nbint_len * (1 - COD_RATE));%make the parity interleaving tableparity_table = zeros(1,plen);count = 1;for scount = 0:S-1for t = 0:Q-1parity_table(count) = S * t + scount + 1;count = count + 1;endend%compare datafid1 = fopen('mb_parity_addr.txt','w');fprintf(fid1,'%d\n',parity_table);%make the Sony interleaving tableif ~parity_only;code_table = zeros(Nc, Nr);for cols = 1:Nctc = Tc(cols);rw = (0:Nr-1)  -  tc;rwm = mod(rw, Nr) + 1;rwm = rwm + (cols - 1) * Nr;code_table(cols, :) = rwm;endcode_table = reshape(code_table, Nr, []);% + 1;code_table = reshape(code_table, nbint_len, []);% + 1;endintered_parity = zeros(1, plen);for it=1:numIntlvBlocks%pick off the parity bitsparity = data( (it * nbint_len) - plen + 1:it * nbint_len);%interleave the parity bitsintered_parity(parity_table) = parity;%tack on the parity bits and interleave the whole lotbitIntlvWr = [data((it-1)*nbint_len+1:it* nbint_len - plen) intered_parity];%interleave the code wordif ~parity_only; bitIntlvWr = bitIntlvWr(code_table); end% LDPC block appendbitIntlvOut((it-1)*nbint_len+1:it*nbint_len) = bitIntlvWr;endend %if int_type == 1DataOut.data = bitIntlvOut;save bitIntlvOut.mat   bitIntlvOut

接下来对上面的代码进行简单的描述。

上面是是码组的编码率,下面是码元的调制方式,这里定义了一个结构体,进行一些全局定义。

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

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

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

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

根据校验位交织、列旋交织的地址进行数据码元的变化,并取出输出码元。
上面只是简要的介绍了上面程序的大体功能,具体的需要大家联合数学原理与MATLAB代码一一相互验证,便可以真正学会该交织操作。

交织的FPGA实现

上面讲解完了交织的MATLAB实现,接下来讲解交织的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//Tool Versions: vivado 2015.1//Description:////Dependencies:////Revision: v_01//Revision 0.01 -File Created//Additional Comments////`define UD #1module 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             ,output reg  s_data_tready            ,input       s_data_tlast             ,output reg  m_data_tvalid            ,output reg  m_data_tdata             ,input       m_data_tready            ,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     [13:0]  bitInter_ram_addra          ;
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                ;reg     [13:0]  bitInter_ram_addrb          ;
wire            bitInter_ram_doutb          ;
reg             colrot_valid_reg            ;
reg             colrot_valid_reg2           ;wire    [13:0]  parity_addr                 ;
wire            parity_valid                ;
wire    [13:0]  colrot_addr                 ;
wire            colrot_valid                ;reg             s_data_tvalid_reg           ;
wire            start_data_invld            ;//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================///====================================================================================
// configure parameter
//====================================================================================always@(posedge sclk)beginif(~rst_n)beginmode_type <=`UD 0;code_rate <= `UD 0;endelse if (s_config_tvalid) beginmode_type <= `UD s_config_tdata[0];code_rate <= `UD s_config_tdata[3:1];endendalways@(posedge sclk)beginif(~rst_n)Qldpc <= `UD 0;elsebegincase (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;endcaseendend//====================================================================================
// Processing Parity_Interleaver
//====================================================================================always@(posedge sclk) beginif(~rst_n)Nbch <= `UD 0;else begincase(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;endcaseendend  always@(posedge sclk)beginif(~rst_n)Pldpc <= `UD 0;else begincase(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;endcaseendend   always@(posedge sclk)beginbitInter_enb <=`UD s_data_tvalid;endalways@(posedge sclk)beginif(bitInter_enb)s_data_cnt <= `UD s_data_cnt + 1'b1;elses_data_cnt <= `UD 0;endalways@(posedge sclk)beginif(s_data_cnt == Nbch-5'd4) // consider latencystart_parity <= `UD 1'b1;elsestart_parity <= `UD 1'b0;endalways@(posedge sclk)beginif(~rst_n)bitInter_ram_addra <= `UD 0;else if(bitInter_enb)beginif(parity_valid && mode_type == 1)bitInter_ram_addra <= `UD parity_addr + Nbch;else if(mode_type == 1)bitInter_ram_addra <= `UD bitInter_ram_addra + 1'b1;else if(mode_type == 0)bitInter_ram_addra <= `UD bitInter_ram_addra + 1'b1;endelsebeginbitInter_ram_addra <= `UD 0;endendalways@(posedge sclk)beginbitInter_ram_wren <=`UD s_data_tvalid;bitInter_ram_dina <=`UD s_data_tdata;endalways@(posedge sclk)beginbitInter_ram_wren_reg <=`UD bitInter_ram_wren;endalways@(posedge sclk)beginif(~rst_n || start_colrot)store_over <= `UD 1'b0;else if(~bitInter_ram_wren && bitInter_ram_wren_reg)store_over <= `UD 1'b1;endalways@(posedge sclk)beginif(~rst_n)start_colrot_reg <= `UD 0;else if(m_data_tready && store_over)start_colrot_reg <= `UD 1;elsestart_colrot_reg <= `UD 0;endalways@(posedge sclk)beginstart_colrot_reg2 <=`UD start_colrot_reg;endassign start_colrot = ~start_colrot_reg2 && start_colrot_reg;always@(posedge sclk)beginif(~rst_n)bitInter_ram_addrb <=`UD 0;else if(mode_type == 0 && colrot_valid_reg && bitInter_ram_addrb < 14'd16199) // QPSKbitInter_ram_addrb <=`UD bitInter_ram_addrb + 1'b1;else if(mode_type == 1) //16 QAMbitInter_ram_addrb <=`UD colrot_addr;elsebitInter_ram_addrb <=`UD 0;endalways@(posedge sclk)begincolrot_valid_reg <= `UD colrot_valid;colrot_valid_reg2 <= `UD colrot_valid_reg;m_data_tvalid <= `UD colrot_valid_reg2;endalways@(posedge sclk)beginm_data_tdata <= `UD bitInter_ram_doutb;endalways@(posedge sclk)beginif(~colrot_valid_reg && colrot_valid_reg2)m_data_tlast <= `UD 1'b1;elsem_data_tlast <= `UD 1'b0;endalways@(posedge sclk)begins_data_tvalid_reg <= `UD s_data_tvalid;endassign start_data_invld = ~s_data_tvalid_reg && s_data_tvalid;always@(posedge sclk)beginif(~rst_n)s_data_tready <= `UD 0;else if(s_config_tvalid)s_data_tready <= `UD 1;else if(start_data_invld)s_data_tready <= `UD 0;else if(m_data_tlast)s_data_tready <= `UD 1;endparity_bom_addr_gen parity_bom_addr_gen(.sclk(sclk),            //input             .rst_n(rst_n),           //input                .Qldpc(Qldpc),          //input [5:0]       .Pldpc(Pldpc),          //input [13:0]      .start_parity(start_parity),   //input              .parity_addr(parity_addr),    //output reg [13:0] .parity_valid(parity_valid)    //output reg        );ColRot_bom_addr_gen ColRot_bom_addr_gen(.sclk(sclk),             // input                .rst_n(rst_n),             //input          .start_colrot(start_colrot),    // input            .colrot_addr(colrot_addr),    //  output reg [13:0] .colrot_valid(colrot_valid)    //  output reg           );ldpc_ram ldpc_ram
(.clka(sclk), // input clka.wea(bitInter_ram_wren), // input [0 : 0] wea.addra(bitInter_ram_addra), // input [13 : 0] addra.dina(bitInter_ram_dina), // input [0 : 0] dina.clkb(sclk), // input clkb.addrb(bitInter_ram_addrb), // input [13 : 0] addrb.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://Module name: parity_bom_addr_gen//Project name: tx_dvb_t2//Target Devices: zc706//Tool Versions: vivado 2015.1//Description:////Dependencies:////Revision: v_01//Revision 0.01 -File Created//Additional Comments////`define UD #1module parity_bom_addr_gen(input              sclk          ,input                rst_n         ,input [5:0]      Qldpc         ,input [13:0]      Pldpc        ,input                start_parity  ,output reg [13:0] parity_addr  ,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)beginif(~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;endalways@(posedge sclk)beginif(~rst_n)parity_cnt <= `UD 0;else if(parity_enb)parity_cnt <= `UD parity_cnt + 1'b1;elseparity_cnt <= `UD 0;endalways@(posedge sclk)beginif(~rst_n)begins_cnt <= `UD 0;S <= `UD 0;endelse if(parity_enb)beginif(s_cnt < Qldpc - 1)begins_cnt <= `UD s_cnt + 1'b1;S <= `UD  S + 14'd360;endelsebegins_cnt <= `UD 0;S <= `UD 0;endendelsebegins_cnt <= `UD 0;S <= `UD 0;endendalways@(posedge sclk)beginif(~rst_n)T <= `UD 0;else if(parity_enb)beginif(s_cnt == Qldpc -1)T <= `UD T + 1;endelseT <= `UD 0;endalways@(posedge sclk)beginif(parity_enb)parity_addr <= `UD S + T;elseparity_addr <= `UD 0;endalways@(posedge sclk)beginparity_valid <= `UD parity_enb;endendmodule

列旋交织模块:

`timescale 1ns/1ps////Company: MYMINIEYE//Engineer: rp lv////Create Date: 2016/03/14 13:54:00//Design name://Module name: ColRot_bom_addr_gen//Project name: tx_dvb_t2//Target Devices: zc706//Tool Versions: vivado 2015.1//Description://**************************************//  bom_addr_gen//  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//Additional Comments////`define UD #1module ColRot_bom_addr_gen(input             sclk           ,input             rst_n            ,input             start_colrot     ,output reg [13:0] colrot_addr      ,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;reg [13:0]col_addr;reg [13:0]row_addr;reg [13:0]gen_taddr;//====================================================================================
// Generate addr for ColRot bit and valid signal
//====================================================================================  always@(posedge sclk)beginif(~rst_n)state <= `UD 0;elsestate <= `UD state_n;endalways@(posedge sclk)beginstart_colrot_reg <= `UD start_colrot;start_colrot_cal <= `UD start_colrot_reg;endalways@(*) beginstate_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;endcaseendalways@(posedge sclk)beginif(~rst_n)Row_cal <= `UD 0;else if (state_n == Row_last)Row_cal <= `UD Row_cal + 1'b1; else Row_cal <=`UD  0;endalways @(posedge sclk) begincase(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;endcaseend//====================================================================================
// Generate Rotate addr for Ldpc Block
//====================================================================================  always@(posedge sclk)begincase(state)Idle: colrot_addr <=`UD 0;Row_1: if (Col_cal < 3'd3)    colrot_addr <=`UD gen_taddr;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;Row_2: if (Col_cal < 3'd3)    colrot_addr <=`UD gen_taddr;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;Row_3: if (Col_cal < 3'd3)    colrot_addr <=`UD gen_taddr;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;Row_4: if (Col_cal < 3'd3)    colrot_addr <=`UD gen_taddr;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;Row_5: if (Col_cal < 3'd3)    colrot_addr <=`UD gen_taddr;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;Row_6: if (Col_cal < 3'd3)    colrot_addr <=`UD gen_taddr;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;Row_7: if (Col_cal < 3'd3)    colrot_addr <=`UD gen_taddr;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;Row_8: if (Col_cal < 3'd3)    colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 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;Row_9: if (Col_cal < 3'd3)    colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 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;Row_10: if (Col_cal < 3'd3)   colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 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;Row_11: if (Col_cal < 3'd3)   colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 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;Row_12: if (Col_cal < 3'd3)   colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 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;Row_13: if (Col_cal < 3'd3)   colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 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;Row_14: if (Col_cal < 3'd3)   colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 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;Row_15: if (Col_cal < 3'd3)   colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 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;Row_16: if (Col_cal < 3'd3)   colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 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;Row_17: if (Col_cal < 3'd3)   colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 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;Row_18: if (Col_cal < 3'd3)   colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 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;Row_19: if (Col_cal < 3'd3)   colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 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;Row_20: if (Col_cal < 3'd3)   colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 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;Row_21: if (Col_cal < 3'd3)   colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 5'd7;else if (Col_cal == 3'd5) colrot_addr <=`UD gen_taddr  - 5'd20;else if (Col_cal == 3'd6) colrot_addr <=`UD gen_taddr  - 5'd20;else if (Col_cal == 3'd7) colrot_addr <=`UD gen_taddr + 12'd2025 - 5'd21;Row_last: if (Col_cal < 3'd3) colrot_addr <=`UD gen_taddr;else if (Col_cal == 3'd3) colrot_addr <=`UD gen_taddr  - 5'd1;else if (Col_cal == 3'd4) colrot_addr <=`UD gen_taddr  - 5'd7;else if (Col_cal == 3'd5) colrot_addr <=`UD gen_taddr  - 5'd20;else if (Col_cal == 3'd6) colrot_addr <=`UD gen_taddr  - 5'd20;else if (Col_cal == 3'd7) colrot_addr <=`UD gen_taddr  - 5'd21;Gen_end : colrot_addr <=`UD 0;default : colrot_addr <=`UD 0;endcaseend//====================================================================================
// Generate normal addr , so that easy to get rotate addr
//====================================================================================  always@(posedge sclk)beginif(~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;endalways@(posedge sclk)beginif(~rst_n)colrot_cnt <= `UD 0;else if(colrot_enb)colrot_cnt <= `UD colrot_cnt + 1'b1;elsecolrot_cnt <= `UD 0;endalways@(posedge sclk)beginif(~rst_n)begincol_cnt <= `UD 0;col_addr <= `UD 0;endelse if(colrot_enb)beginif(col_cnt < Nc)begincol_cnt <= `UD col_cnt + 1'b1;col_addr <= `UD  col_addr + 14'd2025;endelsebegincol_cnt <= `UD 0;col_addr <= `UD 0;endendelsebegincol_cnt <= `UD 0;col_addr <= `UD 0;endendalways@(posedge sclk)beginif(~rst_n)row_addr <= `UD 0;else if(colrot_enb )beginif(col_cnt == Nc)row_addr <= `UD row_addr + 1;endelsebeginrow_addr <= `UD 0;endendalways@(posedge sclk)beginif(colrot_enb)gen_taddr <= `UD col_addr + row_addr;elsegen_taddr <= `UD 0;end//====================================================================================
// Generate Rotate addr  valid signal
//====================================================================================  always @(posedge sclk)beginif(~rst_n)colrot_valid <= `UD 0;else if(state_n == Idle || state_n ==Gen_end)colrot_valid <=`UD 0;elsecolrot_valid <=`UD 1;endendmodule

上面着重说一下列旋交织模块中的状态机,我认为状态机完全可以用行计数器来代替,可以很好的减少代码的复杂度。上面的代码,博主学习了一天的时间才看懂上面的逻辑流程,但是相信经过前面的框图与原理性的介绍,大家学习可以快点。

交织的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
// Tool versions: vivado.2015.1
// Description:
//
//
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
`define UD #1module tb_tx_Bit_interleaver;// Inputsreg 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;reg m_data_tready;// Outputswire s_data_tready;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_tready(s_data_tready), .s_data_tlast(s_data_tlast1), .m_data_tvalid(m_data_tvalid), .m_data_tdata(m_data_tdata), .m_data_tready(m_data_tready), .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 begins_config_tvalid = 0;s_data_tvalid = 0;rstn = 0;clk = 0;m_data_tready = 1;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; endalways@(posedge clk)begins_data_tvalid1 <= `UD s_data_tvalid;s_data_tlast1  <= `UD s_data_tlast;end//=========================================================================
//   input
//=========================================================================    integer fid1;initial beginfid1 = $fopen("bint_data_in.txt","r");endalways@(posedge clk)beginif(s_data_tvalid)$fscanf(fid1,"%d",s_data_tdata);end//=========================================================================
// output
//=========================================================================    integer fid2;initial beginfid2 = $fopen("ms_bitInter_sim.txt","w");endalways@(posedge clk)beginif(m_data_tvalid)$fwrite(fid2,"%b\n",m_data_tdata);endalways #5 clk = ~clk;//=========================================================================
// compare addr
//=========================================================================
wire            parity_valid = tb_tx_Bit_interleaver.uut.parity_valid;
wire signed   [13:0]   parity_addr  = tb_tx_Bit_interleaver.uut.parity_addr;integer fid3;
initial
beginfid3 = $fopen("ms_parity_addr.txt","w");
endalways@(posedge clk)
beginif(parity_valid)$fwrite(fid3,"%d\n",parity_addr+1'b1);
end endmodule

从上面我们可以看出测试代码将交织后的码元输出到一个txt文件中,然后我们就可以在MATLBA中与MATLAB生成的交织后的码元相互验证,证明FPGA侧交织的正确性。
MATLAB验证代码如下:

clc ;
clear all;
load bitIntlvOut.matdata_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;elsebitInter_data_result = sum(abs(bitInter_data_lab - bitInter_data_sim(start_Idx+1:start_Idx+length(bitInter_data_lab))));enda = bitInter_data_result

最终测试的结果FPGA与MATLAB交织后的码元完全相同。如下图:

小结

相信大家在学习算法的FPGA实现的时候都掌握了上面的流程,就是先在MATLAB中实现,然后再在FPGA中实现,交互验证实现的正确性。

参考文献

[1]、电子发烧友学院

总结

创作不易,认为文章有帮助的同学们可以关注、点赞、转发支持。为行业贡献及其微小的一部分。或者对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群:

基于FPGA交织的实现相关推荐

  1. 基于FPGA的前向纠错算法

    目前,无线产品的广泛应用使无线音频和视频的高质量传输成为可能.蓝牙.无限局域网等无线传输设备比较复杂,成本较高,急需 开发一种简便的.仅用于流媒体的无线传输平台,将音频数据实时地发送到移动终端.由于音 ...

  2. 简谈基于fpga设计9/7小波变换原理

    简谈基于fpga设计9/7小波变换原理 9/7小波变换包括行变换,列变换. 其中行变换包括第一步行变换,第一步行更新,第二步行变换,第二步行更新. 列变换包括第一步列变换,第一步列更新,第二步列变换, ...

  3. 基于FPGA实现的MobileNet V1,FPGA深度学习加速器设计 CNN Accelerators based on FPGAs

    Automatic Generation of Multi-precision Multi-arithmetic CNN Accelerators for FPGAs 最近arXiv上挂出来一篇文章, ...

  4. 基于FPGA系统合成两条视频流实现3D视频效果

    目录 1.概述 2.时钟架构 3.带锁定视频解码器的同步系统 4.异步视频系统 4.1.时钟三态模式 4.2.两条视频流中的数据对齐误差 4.3.行锁定摄像机对齐误差 4.4.不同的连接长度 4.5. ...

  5. 基于fpga的数码管动态扫描电路设计_【至简设计案例系列】基于FPGA的密码锁设计(altera版)...

    秦红凯 明德扬FPGA科教 一.项目背景概述 随着生活质量的不断提高,加强家庭防盗安全变得非常重要,但传统机械锁的构造过于简单,很容易被打开,从而降低了安全性.数字密码锁因为它的保密性很高,安全系数也 ...

  6. 快手团队长文解读:基于FPGA加速的自动语音识别在大规模直播和短视频场景的应用...

    来源:机器之心 本文约6000字,建议阅读10分钟 本文介绍了基于FPGA加速的自动语音识别在大规模直播和短视频场景的应用. 典型的实时流式自动语音识别业务如语音搜索.语音输入等和用户操作相关,直接影 ...

  7. FAST:基于FPGA的SDN交换机开源项目

    自1983年自由软件运动领袖Richard Stallman提出了GNU计划以来,开源为软件开发带来了创造性的革命和商业成功.SDN如今的快速发展也离不开开源社区的力量,比如NOX.Floodligh ...

  8. 基于FPGA的以太网开发

      基于FPGA的以太网开发,在调试过的FPGA玩家开来,其实算不上很难的技术!但是如果只是菜鸟级别的选手,没有调试过的话,就有些头疼了!早在自己在实习的时候,就接触到XAUI(万兆以太网口)接口,但 ...

  9. 基于FPGA的SPI FLASH控制器设计

    1.SPI FLASH的基本特征 本文实现用FPGA来设计SPI FLASH,FLASH型号为W25Q128BV.支持3种通信方式,SPI.Dual SPI和Quad SPI.FLASH的存储单元无法 ...

最新文章

  1. Vue.js 组件基础
  2. 成功解决 ModuleNotFoundError: No module named ‘PyQt5.sip‘
  3. 开发中经常碰到的问题cookie和session问题,今天一并解决
  4. MyBatis Plus——分页插件【PaginationInnerInterceptor】
  5. 递归入门 斐波那契数列
  6. oracle的索引使用方法,在OracleE数据库的字段上建立索引的方法
  7. [置顶] Ubuntu 12.04中文输入法的安装
  8. 虚拟机centOs Linux与Windows之间的文件传输
  9. 【Java学习笔记之三】java中的变量和常量
  10. 松下新一代电力线通信(PLC)技术经IEEE P1901.3工作小组批准成为基准规范
  11. 神经网络ANN——SPSS实现
  12. Android Hook技术的简单实现
  13. MySQL 8.0.27 下载安装与配置详细教程(Windows64位)
  14. JavaScript 进阶 - 第3天
  15. 对校招生培养工作的建议_关于招生工作的一些建议与想法
  16. Naive Bayes
  17. 穆利堂[推荐] WxPM信息化整体解决方案-河南郑州房地产工程项目管理系统软件 穆穆-movno1
  18. Win2003系统部署SSL证书(部署https教程)
  19. 宜信研发邮件POP3/SMTP测试
  20. 面向服务架构SOA相关概念

热门文章

  1. SQL中一些实用的快捷键
  2. android设置路由器,如何在Android手机上设置无线路由器以实现WiFi互联网访问
  3. 高晓松《晓说》为何这么红?
  4. STM32CUBEIDE小技巧: Bookmark 书签
  5. 2021年Vector中国用户大会讲了啥
  6. 常见的数值积分方法_欧拉积分/中值积分/龙格-库塔积分
  7. opencv-contours轮廓提取
  8. csv存储数据代码步骤
  9. 微信 开发诡异的40029错误invalid code错误 443 failed to respond错误的解决办法
  10. chrome运行 Android,告诉你如何在Chrome上运行Android应用!