概述
卷积编码与译码
信号在信道间传输主要会受到三个方面的影响:
- 信道本身对信号产生衰落,这是由于信道本身的频率响应特性就不理想,对信号造成破坏;
- 信道中的各种噪声,叠加在信号上改变了信号的幅度、相位、频率,造成解调错误;
- 多径效应,信号在传输过程中的反射、折射、沿不同路径传播造成的叠加效应。
通常会采用信道编码,在发送端插入一些冗余码元,接收端利用这些冗余码元检测并纠正信号在传输过程中产生的错误。目前常用的有卷积码、Turbo码和LDPC码,本文先介绍卷积码的编码和译码方式。
卷积码通常称作非分组码,其含义是每个码组的校验位不仅与本码组中的信息位有关,而且还和之前的m(通常称作约束长度)段码组的信息位有关。与之相对地,分组码的含义是每个码组中的校验位只与本码组中的信息位有关。卷积码通常用(n,k,m)表示,k表示编码前位宽,n表示编码后位宽,通常称k/n为编码效率。如一个(3,1,7)卷积编码结构如下:
卷积码的每一个输出通常用生成多项式来表示,如上图中A、B、C对应的生成多项式分别为g1=(133)8、g2=(165)8、g3(171)8。通常用8进制或2进制表示,为1表示该移位寄存器中的对应位置与异或门相连;为0表示不相连。另外还有其它的状态图、网格图等卷积码表示方式,本设计中不会用到,因此不予描述。
输出数据A、B、C可以串行或并行地输出,如果是串行输出还涉及到时钟速率的转换,如上图中输出时钟速率应是输入时钟的3倍。接收端需要作相应的译码,卷积译码不像第26篇中介绍的加扰、解扰那样采用逆运算即可,卷积译码还要考虑修复传输过程中产生的错误,因此是个相当复杂的过程。
目前应用最为广泛的是一种概率译码方法,Viterbi译码,是基于最大似然准则实现的。该算法原理也很复杂,如果想要自己设计Verilog实现,很耗费时间,本文设计采用现成的IP核实现。《基于OFDM的卷积编译码与自适应传输技术的研究_孙婷》这篇论文中给出了详细的Viterbi译码原理,以及Verilog实现方法,供各位参考研究。
MATLAB设计
使用MATLAB仿真卷积编码和Viterbi译码的过程,MATLAB提供了现成的函数convenc和vitdec,生成多项式采用网格trellis结构表述,可以用poly2trellis函数将多项式转换为trellis结构。本设计仿真时和第26篇中的加扰器、解扰器结合,数据流为:原始序列->加扰器->卷积编码->Viterbi译码->解扰器。与卷积编译码相关的核心代码如下:
%----------------------------------------%
%%% ------- (3,1,7)卷积编码 -------- %%%
%----------------------------------------%
%将生成多项式转换为网格表达式,g1=o133,g2=o165,g3=o171
% trellis = poly2trellis(7,{'1+x^2+x^3+x^5+x^6', ...
% '1+x^1+x^2+x^4+x^6','1+x^1+x^2+x^3+x^6'});
trellis = poly2trellis(7,[133 165 171]);
%上面给出了两种转换方式,7为约束长度
codeData = convenc(y_scrambler,trellis); %对加扰后数据卷积编码
%----------------------------------------%
%%% --------- Viterbi译码 ---------- %%%
%----------------------------------------%
decodeData = vitdec(receive,trellis,34,'trunc','hard');
Viterbi译码有硬决策hard和软决策soft两种译码方式,后者由于会采用额外的位宽描述信号强度,因此性能更好,具体可以参考MATLAB文档,这里就不再展开。卷积编码与Viterbi译码结果对比如下(无噪声情况下),可以看到编码前数据与译码后数据完全一致:
MATLAB帮助文档的Convenc和Vitdec函数说明中还有更多的实例,包括不同编解码方式在不同数字通信信噪比Eb/No下的误码率测试,各位可以自行查阅。
FPGA设计
在Vivado中完成算法设计及仿真。卷积编码的设计很简单,仅仅包含移位寄存器和异或门,和第25篇中加扰器、解扰器的设计非常相似。另外Xilinx还提供了Convolution Encoder这个IP核用于完成卷积编码。本文设计采用自行设计Verilog代码,代码如下:
`timescale 1ns / 1ps
//-------------------------------------------------------------------------
// (3,1,7)卷积编码器设计,written by刘奇,2018.09.16
//-------------------------------------------------------------------------
module Convenc
(
input clk,
input rst_n,
input din,
output [2:0]dout
);
//-------------------------------------------------------------------------
// 移位寄存器部分
//-------------------------------------------------------------------------
reg [6:0] conv_reg;
always @ (posedge clk or negedge rst_n)
if (!rst_n) conv_reg <= 7'b0000000;
else conv_reg <= {din,conv_reg[6:1]};
//-------------------------------------------------------------------------
// 模2加法器设计
//-------------------------------------------------------------------------
reg [2:0] dout_reg;
always @ (posedge clk or negedge rst_n)
if (!rst_n) dout_reg <= 3'b000;
else begin
dout_reg[2] <= conv_reg[6]^conv_reg[4]^conv_reg[3]^conv_reg[1]^conv_reg[0]; //o133
dout_reg[1] <= conv_reg[6]^conv_reg[5]^conv_reg[4]^conv_reg[2]^conv_reg[0]; //o165
dout_reg[0] <= conv_reg[6]^conv_reg[5]^conv_reg[4]^conv_reg[3]^conv_reg[0]; //o171
end
assign dout = dout_reg;
endmodule
Viterbi译码过程相当复杂,理解原理和完成Verilog代码设计都需要不少的时间,本设计采用Vivado提供的Viterbi Decoder IP核。这个IP核可以实现的功能非常强大,本设计只使用了最基本的功能。IP核配置界面如下:
Viterbi Type选择Standard,即标准的Viterbi算法结构。约束长度设置为7(与编码方式相同),回溯长度设置为42(越高译码正确率越高,Latency和消耗资源也增加)。Viterbi结构可以选择并行Parallell(更高的数据吞吐量,每个时钟可以得到一个输出)和Serial(占用更少的资源,每N个时钟得到一个输出)。
State标签下选择Hard Coding方式。Convolution 0标签下设置编码速率和生成多项式,如上图所示,应与编码方式对应。Viterbi译码采用并行输入方式,如编码速率设置为3,则输入数据信号为[23:0]共3*8比特位宽,每8个比特为一路编码的输入,实例化时注意输入的信号要与设置的生成多项式顺序对应。
仿真时与MATLAB中相同,按加扰器->卷积编码->Viterbi译码->解扰器的顺序级联在一起。原始序列由MATLAB生成并存储在txt文件中,在testbench中读取调用。仿真结果如下图所示,看到加扰后数据scrambler_out(即卷积编码的输入数据)和Viterbi译码后输出deconv_out完全一致;加扰前数据din与解扰后数据descrambler_out也完全一致,只是输入与输出之间有计算导致的延迟:
最后
以上就是聪慧花卷为你收集整理的FPGA数字信号处理(27)卷积编码器与Viterbi译码器设计卷积编码与译码MATLAB设计FPGA设计的全部内容,希望文章能够帮你解决FPGA数字信号处理(27)卷积编码器与Viterbi译码器设计卷积编码与译码MATLAB设计FPGA设计所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复