卷积编码
Shannon提出了当信息速率小于信道容量时,可以通过编码的方式实现可靠的通信。而卷积码作为一种常用的信道编码技术,具有优良的性能,其为一种前向纠错编码(FEC),卷积码是一种有记忆性编码,可以通过卷积公式计算得到编码符号,每个编码符号不仅和当其得码元信息有关还和之前一些时刻得码元信息有关。
BLE5.0最新的协议就要求卷积编码为传输格式的可选类型之一,这里以BLE5.0的规范为例,介绍卷积码的硬件实现,卷积码的硬件实现比较简单,和前面的PN序列生成模块类型,只要得到其生成多项式的硬件结构就可以简单的通过verilog来实现:
上图是BLE5.0的(2,1,4)编码要求,如图所示其实现代码如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/07/28 17:27:07
// Design Name:
// Module Name: FEC_encode
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module FEC_encode(
input clk,
input rst_n,
input bits_in,
input bits_in_vld,
input code_en,
output [8-1:0] code_data,
output code_data_vld
);
// coded
reg [3-1:0] shift_reg;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
shift_reg <= 3'd0;
end
else
begin
shift_reg <= (bits_in_vld && code_en) ? ({
shift_reg[1:0],bits_in}) : shift_reg;
end
end
wire coded_a0;
wire coded_a1;
assign coded_a0 = bits_in ^ shift_reg[0] ^ shift_reg[1] ^ shift_reg[2]; // G0(x) = 1 + x + x^2 + x^3
assign coded_a1 = bits_in ^ shift_reg[1] ^ shift_reg[2]; // G1(x) = 1 + x^2 + x^3
// pattern mapper
wire [4-1:0] map_code_data_a0;
wire [4-1:0] map_code_data_a1;
assign map_code_data_a0 = (coded_a0) ? 4'b1100 : 4'b0011;
assign map_code_data_a1 = (coded_a1) ? 4'b1100 : 4'b0011;
// out
assign code_data_vld = bits_in_vld && code_en;
assign code_data = {
map_code_data_a0,map_code_data_a1};
endmodule
viterbi译码
- 基础理论
- 具体实现方法(硬判决)
由前面的卷积编码方法我们知道,可以将卷积编码用状态和时间的格图表示,viterbi译码算法就是根据格图中的路径度量信息来寻找路径度量最小的那条路径,从而达到译码的效果,如下所示:
这里以BLE5.0规范中的(2,1,4)卷积编码为例,这里的State指的就是卷积编码器中移位寄存器的数值,假设我们的原始数据为{1,1,1,0},经过卷积编码器后的编码序列为:{11,01,10,10},我们将这个编码序列输入viterbi译码器,计算步骤如下:
- 首先,state从(0,0,0)出发,若路径输入为0,输出1则为00,state跳转到(0,0,0)不变,和输入编码序列11进行异或运算得到第一个分支度量为2,存下这个变量。若路径输入为1,输出为11,跳转到state(1,0,0),计算分支度量为0,存下这个变量。其中路径的输出可以根据编码表一开始计算出来,无需再进行一次卷积计算。
- 由1得到的两个路径继续出发,终点即为time 3处的四个终点,可以发现这时候有4条路径,对于4个分支度量。
- 继续出发,在time4的时候得到8条路径,存储8个路径度量值。
- 到time5时刻后,出现16条路径,但是终点只有8个,以最上面的state(0,0,0)节点为例,上面一条输入恒定为0的序列可以到达这个节点,下面一条路径为{1,0,0,0}的路径也能够到达这个节点,这时候就需要进行比较两条分支度量的和,上面一条为d1_sum = 2+1+