交织器/解交织器设计
卷积交织: 交织深度I=12,形成相互交迭的误码保护数据包,以抵抗信道中突发的干扰。
1 卷积交织和解交织的原理
交织过程可算作一个编码过程,他把经过纠错编码的数据进行一定的
排列组合,提高原有纠错编码的纠突发错误的能力。数字通信中一般采取
的同步交织有2 种:
(1) 块交织
也叫矩阵行列转置法。可以表述为一个二维存储器阵列 ( N × B ) 。
交织过程是数据先按行写入,再按列读出;解交织过程则相反,是数据先按
列写入,再按行读出。块交织结构简单, 但数据延时时间长而且所需的存储器比较大。
(2) 卷积交织
交织器的输入端的输入符号数据按顺序分别进入 B 条支路延时器,每一路延时不同的符号周期。第一路无延时,第二路延时M个符号周期,第三路延时2M个符号周期,…,第B路延时( B - 1 )M 个符号周期。交织器的输出端按输入端的工作节拍分别同步输出对应支路经延时的数据。卷积交织每条支路符号数据的延时节拍为 di = ( i - 1)M B , i = 1,2, …, B 。解交织器的延时数与交织器相反。
在仔细对比块交织和卷积交织两种方法之后,考虑到缩短延时和减小器件体积,小组决定采用卷积交织的方法来设计。然而实现卷积交织的延时方法有多种,一是采用移位寄存器法,直接利用FIFO实现每条支路的延时, 这种方法实现简单, 但是当B与M值较大时,需要消耗大量的寄存器(图2所示);二是利用RAM来实现移位寄存器的功能,通过控制读/写地址来实现每条支路延迟。
第一种方法,因为其设计思路和做法都相对简单,但是当需要较大的延时数时,移位寄存器变得很大,占用大量的编译时间和芯片空间,实际中并不可取,最终采用了RAM来实现移位,合理地设计读写地址按规律变化,即可实现所要的延时。下面将阐述设计细节
设计要求,交织深度 B=12,M=17,即有 12 条数据通路。采用 RAM 来实现输入数据的时延,按照一定的读写地址规律同时读写 RAM 中。交织器各通道的写地址如图 4 所示,读地址则在写地址的数值上加 1,通过计算可以知道,第 0 通道无延时;第 1 通道延时 17*1 个时钟周期;第 2 通道延时 17*2 个时钟周期......依此类推,第 11 通道延时 17*11 个时钟周期。总共所需存储单元数为 1+18+....+188=1134,相应的要用到地址总线为 11b。也就是说要用到 2k 的 RAM。
交织器的设计:
交织器由以上四个模块构成:AddrGen(交织器读写地址),RAM,WRcon(产生读写控制信号),DataLock(数据锁存),工作过程是clk一个上升沿到来时,AddrGen产生了读写地址AddrW和AddrR,与此同时WRcon模块WE=0,RE=’1’ ,产生写入控制信号,RAM便在AddrW地址单元存储发送过来的数据DataIn。接着clk下降沿到来,WRcon模块WE=’1’ ,RE=‘0’,产生读取控制信号,RAM便读取AddrR地址单元内的数据, DataLock模块进行数据锁存。 接着clk又是上升沿到来, 如此循环。
交织器模块的代码:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity InterLeaver is
port(clk:in std_logic;
DataIn:in std_logic_vector(7 downto 0);
DataOut:out std_logic_vector(7 downto 0));
end entity;
architecture stru of InterLeaver is
component AddrGen is
port(clk:in std_logic;
AddrR:out integer range 0 to 2047;
AddrW:out integer range 0 to 2047
);
end component;
component RAM is
port(AddrR:in integer range 0 to 2047;
AddrW:in integer range 0 to 2047;
DataIn:in std_logic_vector(7 downto 0);
DataOut:out std_logic_vector(7 downto 0);
CS,RE,WE:in std_logic);
end component;
component WRcon is
port(clk:in std_logic;
WE,RE:out std_logic);
end component;
component DataLock is
port(Data:in std_logic_vector(7 downto 0);
DataLock:out std_logic_vector(7 downto 0);
RE:in std_logic);
end component;
signal adr,adw:integer range 0 to 2047;
signal we,re:std_logic;
signal d:std_logic_vector(7 downto 0);
begin
u0:AddrGen port map(clk,adr,adw);
u1:WRcon port map(clk,we,re);
u2:RAM port map(adr,adw,DataIn,d,'0',re,we);
u3:DataLock port map(d,DataOut,re);
end stru;
交织器读写地址模块:
RAM读写地址产生的一种办法就是将读写地址映射到ROM 里,另一种办法就是通过电路计算得到读写地址。这里采用后一方法设计交织器/解交织器读写地址产生模块,但其中应用了ROM存储读写地址的思想。
交织器读写地址VHDL代码:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity AddrGen is
port(clk:in std_logic;
AddrR:out integer range 0 to 2047;
AddrW:out integer range 0 to 2047
);
end AddrGen;
architecture behav of AddrGen is
signal count:integer range 0 to 11:=0;
begin
C:process(clk)
variable c:integer range 0 to 11:=0;
begin
if(rising_edge(clk)) then
c:=(c+1)mod 12;
end if;
count<=c;
end process;
addr:process(clk)
constant a0:integer:=0;
constant a1:integer:=1;
constant c1:integer:=18;
constant a2:integer:=19;
constant c2:integer:=53;
constant a3:integer:=54;
constant c3:integer:=105;
constant a4:integer:=106;
constant c4:integer:=174;
constant a5:integer:=175;
constant c5:integer:=260;
constant a6:integer:=261;
constant c6:integer:=363;
constant a7:integer:=364;
constant c7:integer:=483;
constant a8:integer:=484;
constant c8:integer:=620;
constant a9:integer:=621;
constant c9:integer:=774;
constant a10:integer:=775;
constant c10:integer:=945;
constant a11:integer:=946;
constant c11:integer:=1133;
variable b1:integer range 0 to 17:=0;
variable b2:integer range 0 to 34:=0;
variable b3:integer range 0 to 51:=0;
variable b4:integer range 0 to 68:=0;
variable b5:integer range 0 to 85:=0;
variable b6:integer range 0 to 102:=0;
variable b7:integer range 0 to 119:=0;
variable b8:integer range 0 to 136:=0;
variable b9:integer range 0 to 153:=0;
variable b10:integer range 0 to 170:=0;
variable b11:integer range 0 to 187:=0;
begin
if(rising_edge(clk)) then
case count is
when 0=> AddrW<=a0;AddrR<=a0;
when 1=>
b1:=(b1+1)mod 18;
if(b1=0) then
AddrW<=c1;
AddrR<=a1;
else
AddrR<=a1+b1;
AddrW<=a1+b1-1;
end if;
when 2=>
b2:=(b2+1)mod 35;
if(b2=0) then
AddrW<=c2;
AddrR<=a2;
else
AddrR<=a2+b2;
AddrW<=a2+b2-1;
end if;
when 3=>
b3:=(b3+1)mod 52;
if(b3=0) then
AddrW<=c3;
AddrR<=a3;
else
AddrR<=a3+b3;
AddrW<=a3+b3-1;
end if;
when 4=>
b4:=(b4+1)mod 69;
if(b4=0) then
AddrW<=c4;
AddrR<=a4;
else
AddrR<=a4+b4;
AddrW<=a4+b4-1;
end if;
when 5=>
b5:=(b5+1)mod 86;
if(b5=0) then
AddrW<=c5;
AddrR<=a5;
else
AddrR<=a5+b5;
AddrW<=a5+b5-1;
end if;
when 6=>
b6:=(b6+1)mod 103;
if(b6=0) then
AddrW<=c6;
AddrR<=a6;
else
AddrR<=a6+b6;
AddrW<=a6+b6-1;
end if;
when 7=>
b7:=(b7+1)mod 120;
if(b7=0) then
AddrW<=c7;
AddrR<=a7;
else
AddrR<=a7+b7;
AddrW<=a7+b7-1;
end if;
when 8=>
b8:=(b8+1)mod 137;
if(b8=0) then
AddrW<=c8;
AddrR<=a8;
else
AddrR<=a8+b8;
AddrW<=a8+b8-1;
end if;
when 9=>
b9:=(b9+1)mod 154;
if(b9=0) then
AddrW<=c9;
AddrR<=a9;
else
AddrR<=a9+b9;
AddrW<=a9+b9-1;
end if;
when 10=>
b10:=(b10+1)mod 171;
if(b10=0) then
AddrW<=c10;
AddrR<=a10;
else
AddrR<=a10+b10;
AddrW<=a10+b10-1;
end if;
when 11=>
b11:=(b11+1)mod 188;
if(b11=0) then
AddrW<=c11;
AddrR<=a11;
else
AddrR<=a11+b11;
AddrW<=a11+b11-1;
end if;
end case;
end if;
end process;
end behav;
产生读写控制信号模块:
有了读写地址,还需要有读写控制信号。在一个时钟周期内,令clk=’1’时,将待发送数据写入RAM地址为AddrW的单元, clk=’0’时, 读取RAM地址为AddrR的单元里的数据并发送。
VHDL代码:
library ieee;
use ieee.std_logic_1164.all;
entity WRCon is
port(clk:in std_logic;
WE,RE:out std_logic);
end entity;
architecture behav of WRcon is
begin
process(clk)
begin
if(clk'event and clk='1')then
WE<='0';RE<='1';
else
WE<='1';RE<='0';
end if;
end process;
end behav;
RAM模块如下:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity RAM is
port(AddrR:in integer range 0 to 2047;
AddrW:in integer range 0 to 2047;
DataIn:in std_logic_vector(7 downto 0);
DataOut:out std_logic_vector(7 downto 0);
CS,RE,WE:in std_logic);
end RAM;
architecture behav of RAM is
begin
process(AddrW,RE,WE)
type ram_array is array(0 to 2047) of std_logic_vector(7 downto 0);
variable mem:ram_array:=(others=>"00000000");
begin
if(CS='0') then
if(RE='0') then DataOut<=mem(AddrR);
elsif(WE='0') then mem(AddrW):=DataIn;
end if;
end if;
end process;
end behav;
数据锁存模块:
由于数据读取控制信号RE只占半个时钟周期,故需要将输出数据进行锁存,保证输出信号稳定。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity DataLock is
port(Data:in std_logic_vector(7 downto 0);
DataLock:out std_logic_vector(7 downto 0);
RE:in std_logic);
end DataLock;
architecture behav of DataLock is
begin
process(Data,RE)
begin
if(RE='0') then DataLock<=Data;
end if;
end process;
end behav;
解交织器
解交织器也又四个模块组成:DeAddrGen,WRcon,RAM,DataLock。DeAddrGen模块根据图5产生读写地址。接着便要验证从解交织器得到的数据是否与发送数据DataIn相同。经过分析发现,交织器输出的第一个数据是无效数据(RAM还没有输出,是DataLock初始输出信号),故解交织器应该比交织器延迟一个时钟。
解交织器模块代码:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity DeInterLeaver is
port(clk:in std_logic;
DataIn:in std_logic_vector(7 downto 0);
DataOut:out std_logic_vector(7 downto 0));
end entity;
architecture stru of DeInterLeaver is
component DeAddrGen is
port(clk:in std_logic;
AddrR:out integer range 0 to 2047;
AddrW:out integer range 0 to 2047
);
end component;
component RAM is
port(AddrR:in integer range 0 to 2047;
AddrW:in integer range 0 to 2047;
DataIn:in std_logic_vector(7 downto 0);
DataOut:out std_logic_vector(7 downto 0);
CS,RE,WE:in std_logic);
end component;
component WRcon is
port(clk:in std_logic;
WE,RE:out std_logic);
end component;
component DataLock is
port(Data:in std_logic_vector(7 downto 0);
DataLock:out std_logic_vector(7 downto 0);
RE:in std_logic);
end component;
signal adr,adw:integer range 0 to 2047;
signal we,re:std_logic;
signal d:std_logic_vector(7 downto 0);
begin
u0:DeAddrGen port map(clk,adr,adw);
u1:WRcon port map(clk,we,re);
u2:RAM port map(adr,adw,DataIn,d,'0',re,we);
u3:DataLock port map(d,DataOut,re);
end stru;
解交织器读写地址VHDL代码:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity DeAddrGen is
port(clk:in std_logic;
AddrR:out integer range 0 to 2047;
AddrW:out integer range 0 to 2047
);
end DeAddrGen;
architecture behav of DeAddrGen is
signal count:integer range 0 to 11:=0;
begin
C:process(clk)
variable c:integer range 0 to 11:=0;
begin
if(rising_edge(clk)) then
c:=(c+1)mod 12;
end if;
count<=c;
end process;
addr:process(clk)
constant a11:integer:=0;
constant a10:integer:=1;
constant c10:integer:=18;
constant a9:integer:=19;
constant c9:integer:=53;
constant a8:integer:=54;
constant c8:integer:=105;
constant a7:integer:=106;
constant c7:integer:=174;
constant a6:integer:=175;
constant c6:integer:=260;
constant a5:integer:=261;
constant c5:integer:=363;
constant a4:integer:=364;
constant c4:integer:=483;
constant a3:integer:=484;
constant c3:integer:=620;
constant a2:integer:=621;
constant c2:integer:=774;
constant a1:integer:=775;
constant c1:integer:=945;
constant a0:integer:=946;
constant c0:integer:=1133;
variable b10:integer range 0 to 17:=0;
variable b9:integer range 0 to 34:=0;
variable b8:integer range 0 to 51:=0;
variable b7:integer range 0 to 68:=0;
variable b6:integer range 0 to 85:=0;
variable b5:integer range 0 to 102:=0;
variable b4:integer range 0 to 119:=0;
variable b3:integer range 0 to 136:=0;
variable b2:integer range 0 to 153:=0;
variable b1:integer range 0 to 170:=0;
variable b0:integer range 0 to 187:=0;
begin
if(rising_edge(clk)) then
case count is
when 0=>
b0:=(b0+1)mod 188;
if(b0=0) then
AddrW<=c0;
AddrR<=a0;
else
AddrR<=a0+b0;
AddrW<=a0+b0-1;
end if;
when 1=>
b1:=(b1+1)mod 171;
if(b1=0) then
AddrW<=c1;
AddrR<=a1;
else
AddrR<=a1+b1;
AddrW<=a1+b1-1;
end if;
when 2=>
b2:=(b2+1)mod 154;
if(b2=0) then
AddrW<=c2;
AddrR<=a2;
else
AddrR<=a2+b2;
AddrW<=a2+b2-1;
end if;
when 3=>
b3:=(b3+1)mod 137;
if(b3=0) then
AddrW<=c3;
AddrR<=a3;
else
AddrR<=a3+b3;
AddrW<=a3+b3-1;
end if;
when 4=>
b4:=(b4+1)mod 120;
if(b4=0) then
AddrW<=c4;
AddrR<=a4;
else
AddrR<=a4+b4;
AddrW<=a4+b4-1;
end if;
when 5=>
b5:=(b5+1)mod 103;
if(b5=0) then
AddrW<=c5;
AddrR<=a5;
else
AddrR<=a5+b5;
AddrW<=a5+b5-1;
end if;
when 6=>
b6:=(b6+1)mod 86;
if(b6=0) then
AddrW<=c6;
AddrR<=a6;
else
AddrR<=a6+b6;
AddrW<=a6+b6-1;
end if;
when 7=>
b7:=(b7+1)mod 69;
if(b7=0) then
AddrW<=c7;
AddrR<=a7;
else
AddrR<=a7+b7;
AddrW<=a7+b7-1;
end if;
when 8=>
b8:=(b8+1)mod 52;
if(b8=0) then
AddrW<=c8;
AddrR<=a8;
else
AddrR<=a8+b8;
AddrW<=a8+b8-1;
end if;
when 9=>
b9:=(b9+1)mod 35;
if(b9=0) then
AddrW<=c9;
AddrR<=a9;
else
AddrR<=a9+b9;
AddrW<=a9+b9-1;
end if;
when 10=>
b10:=(b10+1)mod 18;
if(b10=0) then
AddrW<=c10;
AddrR<=a10;
else
AddrR<=a10+b10;
AddrW<=a10+b10-1;
end if;
when 11=>
AddrW<=a11;AddrR<=a11;
end case;
end if;
end process;
end behav;
时钟延迟模块:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ClockDelay is
port(clk:in std_logic;
clk_de:out std_logic);
end ClockDelay;
architecture behav of ClockDelay is
signal c,d:std_logic:='0';
begin
clk_de<=clk and d;
process(clk)
begin
if(clk'event and clk='1') then
if(c='0') then c<='1';
end if;
elsif(clk'event and clk='0') then
if(c='1') then d<='1';
end if;
end if;
end process;
end behav;
仿真部分:
交织、解交织模型:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity In_DeIn is
port(clk:in std_logic;
DataIn:in std_logic_vector(7 downto 0);
DataOut:Out std_logic_vector(7 downto 0));
end entity;
architecture stru of In_DeIn is
component InterLeaver is
port(clk:in std_logic;
DataIn:in std_logic_vector(7 downto 0);
DataOut:out std_logic_vector(7 downto 0));
end component;
component DeInterLeaver is
port(clk:in std_logic;
DataIn:in std_logic_vector(7 downto 0);
DataOut:out std_logic_vector(7 downto 0));
end component;
component ClockDelay is
port(clk:in std_logic;
clk_de:out std_logic);
end component;
signal d:std_logic_vector(7 downto 0);
signal clk_de:std_logic;
begin
u0:InterLeaver port map(clk,DataIn,d);
u1:ClockDelay port map(clk,clk_de);
u2:DeInterLeaver port map(clk_de,d,DataOut);
end stru;
交织、解交织模型仿真:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity In_DeIn_tb is
end entity;
architecture simu of In_DeIn_tb is
component In_DeIn
port(clk:in std_logic;
DataIn:in std_logic_vector(7 downto 0);
DataOut:Out std_logic_vector(7 downto 0));
end component;
constant t:time:=5us;
constant t2:time:=10us;
signal clk:std_logic:='0';
signal DataOut:std_logic_vector(7 downto 0);
signal DataIn:std_logic_vector(7 downto 0):="00000000";
begin
u0:
In_DeIn port map
(clk=>clk,DataIn=>DataIn,DataOut=>DataOut);
process
begin
wait for t;
clk<=not clk;
end process;
process
begin
wait for t2;
DataIn<=DataIn+'1';
end process;
end simu;
从交织\解交织输出数据波形图可以看出, 在交织器RAM数据未填充完成前,解交织出的数据都是随机的,然后在延时12 * (12-1)*17 =2244个时钟周期之后,解交织出正确的数据。仿真结果与设计初衷一致。
本文来源:https://www.2haoxitong.net/k/doc/73975079de80d4d8d05a4f46.html
文档为doc格式