m基于FPGA的viterbi译码verilog实现,包含testbench和MATLAB配套验证仿真程序

目录

1.算法仿真效果

2.verilog核心程序

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

4.完整verilog工程


1.算法仿真效果

vivado2019.2/matlab2022a仿真结果如下:

对比matlab仿真结果如下:

可以看到编码后的结果和matlab的编码结果完全相同。 

2.verilog核心程序

MATLAB

.....................................................................
for i = 3:s+2
 
        if val_a + dis(gra(1,:), x(2*i-1:2*i)) >= val_c + dis(gra(5,:),x(2*i-1:2*i))
            tempa = mc; 
            val_a_t = val_c + dis(gra(5,:),x(2*i-1:2*i));
            tempa(i)=0;
        else
            val_a_t = val_a + dis(gra(1,:),x(2*i-1:2*i));
            tempa = ma;
            tempa(i)=0;
        end
.....................................................................
    val_a =val_a_t;        
    val_b =val_b_t;
    val_c =val_c_t;
    val_d =val_d_t;
    ma = tempa;
    mb = tempb;
    mc = tempc;
    md = tempd;        
end

if val_a <= val_b
    m = ma;
    t = val_a;
else
    m = mb;
   t = val_a;
end

if val_c <= t
    m = mc;
    t =val_c;
end

if val_d <= t
    m = md;
    t = val_d;
end
%% 去掉最开始的00
m = m(3:s+2);


end


function d = dis(x, y)   
d = sum(xor(x,y));
end

fpga

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
//


module tops(clock,din,dout_code,dout_decode);
input  clock;
input  din;
output [1:0]dout_code;
output dout_decode;


	
Conv_coder Conv_coder_U(
.clock    (clock),
.din      (din),
.dout     (dout_code)                               
);

Viterbi Viterbi_U(
                   .clock(clock),
                   .dcodes(dout_code), 
                   .dout(dout_decode)
                   );

endmodule

14_018_m

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

       viterbi译码算法是一种卷积码的解码算法。优点不说了。缺点就是随着约束长度的增加算法的复杂度增加很快。约束长度N为7时要比较的路径就有64条,为8时路径变为128条。 (2<<(N-1))。所以viterbi译码一般应用在约束长度小于10的场合中。
        先说编码(举例约束长度为7):编码器7个延迟器的状态(0,1)组成了整个编码器的64个状态。每个状态在编码器输入0或1时,会跳转到另一个之中。比如110100输入1时,变成101001(其实就是移位寄存器)。并且输出也是随之而改变的。
        这样解码的过程就是逆过程。算法规定t时刻收到的数据都要进行64次比较,就是64个状态每条路有两条分支(因为输入0或1),同时,跳传到不同的两个状态中去,将两条相应的输出和实际接收到的输出比较,量度值大的抛弃(也就是比较结果相差大的),留下来的就叫做幸存路径,将幸存路径加上上一时刻幸存路径的量度然后保存,这样64条幸存路径就增加了一步。在译码结束的时候,从64条幸存路径中选出一条量度最小的,反推出这条幸存路径(叫做回溯),得出相应的译码输出。

       卷积码是把k个信息比特的序列编成n个比特的码组,每个码组的n-k个校验位与本码组的k个信息位有关,而与其他码组无关。为了达到一定的纠错能力和编码效率,分组码的长度一般都比较大。编译码时必须把整个信息码组存储起来,由此产生的译码延时随n的增加而增加。

      卷积码是一个有限记忆系统,它也将信息序列分割成长度k的一个个分组,然后将k个信息比特编成n个比特,但k和n通常很小,特别适合以串行形式进行传输,时延小。与分组码不同的是在某一分组编码时,不仅参看本时刻的分组而且参看以前的N-1个分组,编码过程中互相关联的码元个数为nN。N称为约束长度。常把卷积码写成(n,k,N-1)卷积码。正因为卷积码在编码过程中,充分利用了各级之间的相关性,无论是从理论上还是实际上均已证明其性能要优于分组码。

        本次设计以(2,1,2)卷积码为例。图2-1为这种卷积编码器的结构,它的编码方法是:序列依次移入一个两级移位寄存器,编码器每输入一位信息b,输出端的开关就在c和c之间来回切换一次,输出为c和c,其中

c=b+b+b

c=b+b

设寄存器m、m的起始状态为全零,则编码器的输入输出时序关系可用图2-2表示。 

       要使最后1 位输入同样影响3对输出,并且使编码器回到全零状态,还需使编码器多输出2对信息,为了做到这一点,需要增加2个时钟循环,并且在此期间保持输入为0,这一过程叫做“点亮”编码器。如果不执行“点亮”操作,最后2位输入信息的纠错能力就会下降。 

        因为卷积码的编码器的记忆性是有限的,所以可以使用状态转移图来表示其转移过程。在状态转移图中,卷积编码器的每一个状态对应于一个椭圆,状态的转移用两个椭圆间的有向线段表示,在线上标出状态转移的输入和对应的输出。图中(2,1,2)卷积码的状态转移图如图所示。

4.完整verilog工程

V

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Viterbi译码卷积码译码的一种算法,用于译码卷积码编码后的数字序列。在Verilog实现Viterbi译码需要以下步骤: 1. 定义输入和输出:输入为卷积码编码后的数字序列,输出为解码后的信息序列。 2. 定义状态机:Viterbi译码是一种基于状态机的算法,需要定义状态机的状态和状态转移。 3. 定义度量值计算模块:Viterbi译码需要计算每个可能状态的度量值,需要定义一个模块计算度量值。 4. 定义路径记忆器:Viterbi译码需要记忆最优路径,需要定义一个模块实现路径记忆器。 5. 定义决策模块:Viterbi译码需要在所有可能路径中选择一条最优路径,需要定义一个模块实现决策模块。 以下是一个基于Verilog实现Viterbi译码的示例代码: ``` module viterbi_decoder( input clk, input reset, input [N-1:0] encoded_data, output [K-1:0] decoded_data ); parameter K = 4; //信息位数 parameter N = 7; //编码位数 parameter M = 2; //码元数 parameter [M-1:0] G1 = 2'b11; //生成多项式G1 parameter [M-1:0] G2 = 2'b10; //生成多项式G2 //状态机定义 reg [K-1:0] state [0:(1<<N)-1]; reg [N-1:0] next_state [0:(1<<N)-1][0:M-1]; reg [N-1:0] output [0:(1<<N)-1][0:M-1]; //度量值计算模块 reg [K-1:0] metric [0:(1<<N)-1][0:M-1]; //路径记忆器模块 reg [N-1:0] path [0:(1<<N)-1][0:M-1]; //决策模块 reg [K-1:0] best_path [0:M-1]; reg [K-1:0] decoded_output; //状态机初始化 initial begin for (int s=0; s<(1<<N); s++) begin for (int i=0; i<M; i++) begin next_state[s][i] = {s[N-2:0],i}; output[s][i] = {(s[K-1]^s[K-2])^i, s[K-1]}; end end end //度量值计算模块 always @(posedge clk) begin for (int s=0; s<(1<<N); s++) begin for (int i=0; i<M; i++) begin metric[s][i] = 0; for (int j=0; j<K; j++) begin metric[s][i] = metric[s][i] + ((encoded_data[j]^output[s][i][j])?1:0); end end end end //路径记忆器模块 always @(posedge clk) begin for (int s=0; s<(1<<N); s++) begin for (int i=0; i<M; i++) begin int min_metric = 1000; int min_state = 0; for (int j=0; j<M; j++) begin int next_s = next_state[s][j]; int metric_value = metric[next_s][j] + metric[s][i]; if (metric_value < min_metric) begin min_metric = metric_value; min_state = next_s; end end path[min_state][i] = s; metric[min_state][i] = min_metric; end end end //决策模块 always @(posedge clk) begin int min_metric = 1000; for (int i=0; i<M; i++) begin if (metric[(1<<N)-1][i] < min_metric) begin min_metric = metric[(1<<N)-1][i]; best_path[i] = path[(1<<N)-1][i]; end end decoded_output = best_path[0][K-1:0]; end //输出模块 assign decoded_data = decoded_output; endmodule ``` 需要注意的是,以上代码仅为示例代码,实际使用时需要根据具体的卷积码生成多项式进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我爱C编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值