m基于FPGA的217卷积编码维特比译码verilog实现,包含testbench不使用IP核

133 阅读3分钟

1.算法仿真效果

Vivado2019.2

db0e1155208774f454316041e970882f_watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=.png  

编码部分:

f52bac1b3977be8c75bf7a68e0142825_watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=.png

译码部分输出:

 

8e1cf763e465f6755444e9be88f79c2d_watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=.png

 

RTL图:

901561361b94f8aa22360375092ea807_watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=.png

 

2.算法涉及理论知识概要

2.1 卷积编码

       卷积编码是一种前向纠错编码方式,特别适用于无线通信和其他信道条件恶劣的应用场景。它主要通过卷积算子将信息序列映射成冗余度更高的码字序列。典型的卷积编码器由两个移位寄存器和一个加法器构成,遵循一定的生成多项式进行编码。

 

       设信息序列是 u(n),卷积编码器的两个生成多项式为 G1​(D) 和 G2​(D),则编码输出v(n) 可以表示为:

 

v(n)=u(n)G1​(D)+u(n−1)G2​(D)+…

 

此处D 是延迟算子,实际表达形式取决于具体选择的生成多项式阶数及系数。

 

2.2 维特比译码

       维特比译码是用于最大似然序列估计的一种动态规划算法,广泛应用于卷积编码以及其他序列编码的译码过程中。在卷积编码中,维特比译码器通过构造一棵称为“状态转移图”或“trellis”的树状结构来寻找最有可能的原始信息序列路径。

 

       在 Viterbi 译码算法中,每一步都需要计算分支量度,路径量度,以及更新幸存路径,同时还需要知道状态转移网格图,时序控制等信息,其原理图如图:

 

9fe9e63afce11a8fc09970cd18949d9e_watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=.png

 

       假设维特比译码器面对的是接收到的带有噪声的码字序列y(n),其目标是最小化汉明距离或最大化似然性。维特比算法的核心在于维护每一步的状态概率以及从起始状态到达当前状态的最佳路径累积代价。

 

      状态转移方程: 对于每个时刻n 和每一个状态Sj​,其下一状态Sk​ 的最佳路径累积代价C(n,Sk​) 可以递归地表示为所有前一状态Sj​ 的累积代价加上相应路径的概率增益:

 

C(n,Sk​)=Sj​∈prev(Sk​)min​[C(n−1,Sj​)+P(y(n)∣Sk​)]

 

       其中,prev(Sk​) 表示状态Sk​ 的前驱状态集合,P(y(n)∣Sk​) 是给定当前状态Sk​ 下观测到y(n) 的概率。

 

       终止状态判决: 译码结束时,选取累积代价最小的终止状态对应的路径作为最优解,回溯此路径即得到最优译码结果。

 

3.Verilog核心程序 ``timescale 1ns / 1ps

 

 

// Company:

// Engineer:

 

//

 

 

module TEST;

 

// Inputs

reg i_clk;

reg i_reset;

reg i_x;

 

// Outputs

wire [1:0] o_enc;

    wire o_dec;

// Instantiate the Unit Under Test (UUT)

conv_217_code uut (

.i_clk   (i_clk),

.i_reset (~i_reset),

.i_x     (i_x),

.o_enc   (o_enc)

);

 

 

conv_217_decode uut2 (

.i_clk    (i_clk),

.i_reset  (~i_reset),

.i_enc    (o_enc),

.o_dec    (o_dec)

);

 

 

always #10 i_clk = ~i_clk;

initial begin

// Initialize Inputs

i_clk = 0;

i_reset = 0;

i_x = 0;

 

// Wait 100 ns for global i_reset to finish

#100;

      i_reset = 1;  

// Add stimulus here

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 1;

#20

i_x = 0;

#20

i_x = 0;

#20

i_x = 1;

#20

i_x = 0;

 

 

end

      

endmodule`