LDPC码的FPGA实现.docx
- 文档编号:28901093
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:27
- 大小:486.89KB
LDPC码的FPGA实现.docx
《LDPC码的FPGA实现.docx》由会员分享,可在线阅读,更多相关《LDPC码的FPGA实现.docx(27页珍藏版)》请在冰豆网上搜索。
LDPC码的FPGA实现
LDPC码的FPGA实现
4.1FPGA简介
FPGA是一种可编程逻辑器件,一般有两种设计输入方法:
硬件描述语言(HDL)和原理图输入方法,其中VHDL语言和VerilogHDL语言是普遍使用的HDL语言。
设计流程主要包括设计与输入,功能仿真,综合,综合后仿真,布局布线,时序仿真与下板调试六个步骤。
一般来说,FPGA可简化地由可编程输入/输出单元、基本可编程逻辑单元、嵌入式块RAM、丰富的布线资源、底层嵌入功能以及内嵌专用硬核6个部分组成,其结构原理图如图4.1所示
图4.1FPGA的结构原理图
(1)可编程输入/输出单元
可编程输入/输出单元即I/O单元,作为芯片和外接电路的接口部分,其主要功能是完成不同电气特性下对输入/输出信号的驱动与匹配要求。
(2)基本可编程逻辑
基本可编程逻辑单元作为FPGA的主题部分,其主要功能是通过改变其内部连接和配置,来完成不同的逻辑功能。
(3)嵌入块RAM
一般的FPGA都有内嵌的块RAM,通过嵌入块RAM极大地提高了FPGA的应用范围以及使用灵活性。
(4)丰富的布线资源
FPGA内部所有的单元都用布线资源来进行连通,信号在连线上的驱动能力和传输速度直接受到连线的长度和工艺的影响。
(5)底层嵌入功能单元
底层嵌入功能模块主要是指通用程度较高的嵌入式功能模块。
(6)内嵌专用硬核
一般是指通用性差,很少被FPGA器件包含的硬核。
4.2串行译码器的结构
在FPGA实现时需重点考虑译码器的译码速率以及硬件消耗,而译码速率与硬件消耗之间往往存在着正向关系,即译码速率越大硬件消耗越大。
为了适应不同应用环境的需要,先后产生了三种不同硬件结构的译码器,即:
全并行结构,串行结构以及部分并行结构以及部分并行结构。
本文主要介绍比较节省资源的串行译码算法。
图4.2LDPC译码器串行结构
串行译码器结构如图4.2所示,其主要包括变量节点处理器,校验节点处理器,中间信息储存器以及控制单元4各部分。
变量节点处理器即VNP作用是更新变量节点信息;校验节点处理器即CNP作用是更新校验节点信息;中间信息存储器MessageRAM的作用是存储两个节点处理器迭代运算的中间结果;而中置单元重要时用来控制迭代译码过程,协调VNP和CNP的工作顺序以及控制迭代次数;除此之外IOReadROM和IOWriterRAM分别用于存储待译码的数据和译码结果。
4.3串行结构译码器的工作原理
在控制单元的控制下VNP与CNP交替完成所有变量节点和校验节点的运算。
因为VNP和CNP均需从中间信息存储器读取信息并将其处理结果重新写回中间信息存储器,所以中间信息存储器须接受VNP及CNP两个模块的访问。
故需要通过MUX模块合理安排访问使得VNP与CNP交替工作且没有访问冲突。
顺序结构的顺序性主要体现在变量节点以及校验节点是交替进行的,且变量节点处理器和校验节点处理器内部对于变量节点和校验节点的处理是顺序的。
所以串行译码器的缺点在于没有充分利用FPGA在并行数据处理上的优势,但其有点是其结构简单且不会出现VNP和CNP对中间信息存储器的访问冲突。
VNP与CNP的作用均是按其各自的运算规则对中间信息存储器中存储的数据进行更新,其中最重要的步骤就是根据校验矩阵规定的关系(或Tanner图中的连接关系)从中间信息存储器中相应地址取得数据并在运算后将结果写回。
为方便分析本设计,在此用Tanner图来研究其实现原理。
图4.3交织过程示意图
如图4.3所示,Tanner图表示了(3,6)规则码的LDPC码,共包含8个变量节点(圆圈)以及4个校验节点(方框)。
在译码过程中每个信息数据在图中的对应一条连线,由LDPC码原理以及Tanner图表示法可知,中间信息存储器总共需存储24个数据。
在此我们以变量节点为基准对每条线进行编号(图4.3左侧部分),图中连线对应的数据在中间信息存储器中相应的的存储地址用标识的序号表示,这样中间信息存储器的24个单元就与图中每条连线建立了一一对应的关系。
与此同时,在VNP处理过程中只要按照递增的顺序依次对中间信息处理器中的数据进行操作即可,其连接的6条连线编号不是连续的而是根据Tanner图决定的其编号在图4.3的右侧。
不连续的编号使得CVP难以在处理过程中用地址递增的方式直接对中间信息存储器进行寻址操作,而只能先对递增产生的地址进行一次交织,即依次将图4.3所示右侧的序号填入ROM中,这样CNP产生的地址依然为递增的0-23,最后再将新产生的地址作为ROM的地址信号,经过ROM交织后,输出变为3,6,9,12,……
译码器不断从IOReadROM中读取原始数据信息,经过规定次数的迭代后,将译码结果输出到IOWriterRAM中。
4.4串行译码器的FPGA实现
本文的串行译码器的系统结构如图4.2所示,处理过程中的所有数据信息均采用8比特量化。
本设计适用于任何码长为256的二进制(3,6)规则LDPC码。
设计采用的译码算法是最小和(Min-Sum)算法,变量节点处理单元传递的是除自身之外的其他数据的和(经数据截断);校验节点处理单元传递的是除自身之外的最小绝对值的相应处理结果(乘以0.75,符号按照相应规律取)
4.4.1变量处理单元VNP
变量处理单元需完成变量节点的更新以及完成数据的输入输出功能。
初始化阶段,由于中间信息存储器中存储的数据位全0,因而经过求和运算后,写回的数据依次为相应的信道信息。
应注意在从RAM或ROM中读取数据时,从设置好RAM的地址到读到该地址对应的数值会有一个时钟周期的延迟,应在设计中考虑该时序特点。
modulevnp(
Clk,
CE,//clk使能
CNP_ON,//CNP_ON=‘0’,VNP工作;CNP_ON=‘1’,VNP不工作
Process_Finish,//VNP处理过程结束指示,高有效
Last_Iteration,//高有效,最后一次迭代指示
SrcMem_Addr,
SrcMem_Din,
ResultMem_Addr,
ResultMem_Dout,
ResultMem_WE,
Mess_Din,//从Mess_Mem读进的数据
Mess_Dout,//从Mess_Mem写入的数据
Mess_Addra,//从Mess_Mem的A端口地址,该端口只读
Mess_Addrb,//从Mess_Mem的B端口地址,该端口只写
Mess_WEb);
parameterN=256;//变量节点数
inputClk,CE,CNP_ON,Last_Iteration;
outputProcess_Finish,ResultMem_WE,Mess_WEb;
input[7:
0]SrcMem_Din;
output[7:
0]ResultMem_Dout;
output[7:
0]SrcMem_Addr,ResultMem_Addr;
output[9:
0]Mess_Addra,Mess_Addrb;
input[7:
0]Mess_Din;
output[7:
0]Mess_Dout;
reg[1:
0]Cycle;//用于计数每个变量节点的连线
reg[8:
0]cnt;//用于计数变量节点
reg[9:
0]calc_a,calc_b;//数据位扩展,存储数据的和
reg[7:
0]Mess_Buff_a[0:
2];//用于存储每次读入的数据
reg[7:
0]Mess_Buff_b[0:
2];//利用两组存储器,同一时刻,一组读,一组写
regflag;
assignResultMem_WE=Last_Iteration?
(cnt>0&&cnt<(N+1)):
0;
assignResultMem_Addr=Last_Iteration?
(cnt-1):
0;
assignSrcMem_Addr=Last_Iteration?
0:
cnt;
assignResultMem_Dout=Last_Iteration?
(!
cnt[0]?
limit(calc_b):
limit(calc_a)):
0;
assignMess_Addra=flag?
0:
(cnt+cnt+cnt+Cycle+1'd1);//Mess_Mem读地址为(3*cnt+Cycle-3),即(Mess_Addra-3’d4)
assignMess_Addrb=Mess_Addra-3'd4;
assignMess_Dout=Last_Iteration?
0:
(!
cnt[0]?
(limit(calc_b-{Mess_Buff_b[Cycle][7],Mess_Buff_b[Cycle][7],Mess_Buff_b[Cycle]}))
:
(limit(calc_a-{Mess_Buff_a[Cycle][7],Mess_Buff_a[Cycle][7],Mess_Buff_a[Cycle]})));
assignMess_WEb=!
CE?
0:
(!
(cnt==0||cnt==(N+1)));
assignProcess_Finish=!
CE?
0:
(cnt==(N+1));
always@(posedgeClk)
if(CNP_ON||~CE)begin
flag<=1;
Cycle<=0;
cnt<=0;
calc_a<=0;
calc_b<=0;
Mess_Buff_a[0]<=0;
Mess_Buff_a[1]<=0;
Mess_Buff_a[2]<=0;
Mess_Buff_b[0]<=0;
Mess_Buff_b[1]<=0;
Mess_Buff_b[2]<=0;
end
else
if(cnt==0&&flag==1)begin//利用flag解决1个延迟周期的问题
cnt<=0;
flag<=0;
end
else
if(cnt==(N+1))begin
cnt<=0;
flag<=1;
end
else
case(Cycle)
2'b00:
begin
if(!
cnt[0])begin
calc_a<={Mess_Din[7],Mess_Din[7],Mess_Din};
Mess_Buff_a[0]<=Mess_Din;
end
elsebegin
calc_b<={Mess_Din[7],Mess_Din[7],Mess_Din};
Mess_Buff_b[0]<=Mess_Din;
end
Cycle<=Cycle+1;
end
2'b01:
begin//在第2个周期加上信道信息SrcMem_Din
if(!
cnt[0])begin
calc_a<=calc_a+{Mess_Din[7],Mess_Din[7],Mess_Din}
+{SrcMem_Din[7],SrcMem_Din[7],SrcMem_Din};
Mess_Buff_a[1]<=Mess_Din;
end
elsebegin
calc_b<=calc_b+{Mess_Din[7],Mess_Din[7],Mess_Din}
+{SrcMem_Din[7],SrcMem_Din[7],SrcMem_Din};
Mess_Buff_b[1]<=Mess_Din;
end
Cycle<=Cycle+1;
end
2'b10:
begin
if(!
cnt[0])begin
calc_a<=calc_a+{Mess_Din[7],Mess_Din[7],Mess_Din};
Mess_Buff_a[2]<=Mess_Din;
calc_b<=0;
end
elsebegin
calc_b<=calc_b+{Mess_Din[7],Mess_Din[7],Mess_Din};
Mess_Buff_b[2]<=Mess_Din;
calc_a<=0;
end
Cycle<=0;
cnt<=cnt+1;
end
endcase
//数据阶段函数,10比特截断为8比特
function[7:
0]limit;
input[9:
0]data;
limit=data[9]?
(!
(data[8]&data[7])?
8'b1000_0000:
data[7:
0])
:
(data[8]|data[7]?
8'b0111_1111:
data[7:
0]);
endfunction
endmodule
4.4.2校验处理单元CNP
校验节点处理单元用来完成校验节点信息的更新,需注意由于CNP的输出地址先要经过InterleeaverROM后再输入中间信息存储器,因而会带来两个时钟周期的延迟。
modulecnp(
Clk,
CE,//ClkEnable
CNP_ON,//CNP_ON=‘1’,CNP工作;CNP_ON=‘0’,CNP不工作
Process_Finish,//CNP处理过程结束指示,高有效
Mess_Din,//从Mess_Mem读进的数据
Mess_Dout,//从Mess_Mem写入的数据
Mess_Addra,//从Mess_Mem的A端口地址,该端口只读
Mess_Addrb,//从Mess_Mem的B端口地址,该端口只写
Mess_WEb);
parameterC=128;//校验节点数
inputClk,CE,CNP_ON;
outputProcess_Finish,Mess_WEb;
output[9:
0]Mess_Addra,Mess_Addrb;
input[7:
0]Mess_Din;
output[7:
0]Mess_Dout;
reg[2:
0]Cycle;//每个校验节点需要处理6个周期
reg[7:
0]cnt;//计数校验节点
regSign_Buff_a;//存储符号
regSign_Buff_b;
reg[7:
0]Mess_Buff_a[0:
5];//存储输入的数据
reg[7:
0]Mess_Buff_b[0:
5];
reg[7:
0]Min_a_1,Min_a_2,Min_b_1,Min_b_2;//存储绝对值最小的两个数据
regflag,n;
regsign_0,sign_1;
//由于加入Interleaver,存在两个时钟周期的延迟,地址变为(6*cnt+Cycle+2)
assignMess_Addra=flag?
n:
(cnt+cnt+cnt+cnt+cnt+cnt+Cycle+2'd2);
assignMess_Addrb=Mess_Addra-4'd7;
assignMess_Web=!
CE?
0:
((cnt==0||cnt==(C+1))?
0:
1);
assignProcess_Finish=!
CE?
0:
(cnt==(C+1));
assignMess_Dout=!
cnt[0]?
((abs(Mess_Buff_b[Cycle])==Min_b_2)?
(sign_1?
({1'b1,~mult_0_75(Min_b_1[7:
0])}+1'b1):
{1'b0,mult_0_75(Min_b_1[7:
0])})
:
(sign_1?
({1'b1,~mult_0_75(Min_b_2[7:
0])}+1'b1)
:
{1'b0,mult_0_75(Min_b_2[7:
0])}))
:
((abs(Mess_Buff_a[Cycle])==Min_a_2)?
(sign_0?
({1'b1,~mult_0_75(Min_a_1[7:
0])}+1'b1)
:
{1'b0,mult_0_75(Min_a_1[7:
0])})
:
(sign_0?
({1'b1,~mult_0_75(Min_a_2[7:
0])}+1'b1)
:
{1'b0,mult_0_75(Min_a_2[7:
0])}));
always@(Cycle)
if(!
cnt[0])
sign_1<=Sign_Buff_b^Mess_Buff_b[Cycle][7];
else
sign_0<=Sign_Buff_a^Mess_Buff_a[Cycle][7];
always@(posedgeClk)
if(!
CNP_ON||!
CE)
begin
flag<=1;
n<=0;
Cycle<=0;
cnt<=0;
Sign_Buff_a<=0;
Sign_Buff_b<=0;
Min_a_1<=0;
Min_a_2<=0;
Min_b_1<=0;
Min_b_2<=0;
Mess_Buff_a[0]<=0;
Mess_Buff_a[1]<=0;
Mess_Buff_a[2]<=0;
Mess_Buff_a[3]<=0;
Mess_Buff_a[4]<=0;
Mess_Buff_a[5]<=0;
Mess_Buff_b[0]<=0;
Mess_Buff_b[1]<=0;
Mess_Buff_b[2]<=0;
Mess_Buff_b[3]<=0;
Mess_Buff_b[4]<=0;
Mess_Buff_b[5]<=0;
end
else
if(cnt==0&&flag==1)begin//使用flag等待两个时钟周期
cnt<=0;
if(n==1)begin
n<=0;
flag<=0;
end
else
n<=1;
end
else
if(cnt==(C+1))
cnt<=0;
else
case(Cycle)
3'b000:
begin
if(!
cnt[0])begin
Sign_Buff_a<=Sign_Buff_a^Mess_Din[7];
Min_a_1<=abs(Mess_Din);
Min_a_2<=abs(Mess_Din);
Mess_Buff_a[0]<=Mess_Din;
end
elsebegin
Sign_Buff_b<=Sign_Buff_b^Mess_Din[7];
Min_b_1<=abs(Mess_Din);
Min_b_2<=abs(Mess_Din);
Mess_Buff_b[0]<=Mess_Din;
end
Cycle<=Cycle+1;
end
3'b001:
begin
if(!
cnt[0])begin
Sign_Buff_a<=Sign_Buff_a^Mess_Din[7];
if(abs(Mess_Din) if(abs(Mess_Din) Min_a_1<=Min_a_2; Min_a_2<=abs(Mess_Din); end else Min_a_1<=abs(Mess_Din); Mess_Buff_a[1]<=Mess_Din; end elsebegin Sign_Buff_b<=Sign_Buff_b^Mess_Din[7]; if(abs(Mess_Din) if(abs(Mess_Din) Min_b_1<=Min_b_2; Min_b_2<=abs(Mess_Din); end else Min_b_1<=abs(Mess_Din); Mess_Buff_b[1]<=Mess_Din; end Cycle<=Cycle+1; end 3'b010: begin if(! cnt[0])begin Sign_Buff_a<=Sign_Buff_a^Mess_Din[7]; if(abs(Mess_Din) if(abs(Mess_Din) Min_a_1<=Min_a_2; Min_a_2<=abs(Mess_Din); end else Min_a_1<=abs(Mess_Din); Mess_Buff_a[2]<=Mess_Din; end elsebegin Sign_Buff_b<=Sign_Buff_b^Mess_Din[7]; if(abs(Mess_Din) if(abs(Mess_Din) Min_b_1<=Min_b_2; Min_b_2<=abs(Mess_Din); end else Min_b_1<=abs(Mess_Din); Mess_Buff_b[2]<=Mess_Din; end Cycle<=Cycle+1; end 3'b011: begin if(! cnt[0])begin Sign_Buff_a<=Sign_Buff_a^Mess_Din[7]; if(abs(Mess_Din) if(abs(Mess_Din) Min_a_1<=Min_a_2; Min_a_2<=abs(Mess_Din); end else Min_a_1<=abs(Mess_Din); Mess_Buff_a[3]<=Mess_Din; end elsebegin Sign_Buff_b<=Sign_Buff_b^Mess_Din[7]; if(abs(Mess_Din) if(abs(Mess_Din) Min_b_1<=Min_b_2; Min_b_2<=abs(Mess_Din); end else Min_b_1<=abs(Mess_Din); Mess_Buff_b[3]<=Mess_Din; end Cycle<=Cycle+1; end 3'b100: begin if(! cnt[0])begin Sign_Buff_a<=Sign_Buff_a^Mess_Din[7]; if(abs(Mess_Din) if(abs(Mess_Din) Min_a_1<=Min_a_2; Min_a_2<=abs(Mess_Din); end else Min_a_1<=abs(Mess_Din); Mess_Buff_a[4]<=Me
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- LDPC FPGA 实现