(2,1,2)卷积码BCJR译码matlab仿真_matlab bcjr-程序员宅基地

技术标签: matlab  信息处理与编码  


前言

仿真(2,1,2)卷积码的性能,每个码块信息比特长度为1000,要求编码最终状态归0。要求输出的结果为译码后信息比特的BER。级联的调制方式采用QPSK。
在这里插入图片描述

(2,1,2)卷积码示意图

代码侧重于BCJR译码算法的编写过程

一、卷积码

1.1 卷积码状态转移图

黑色分支代表信息比特为0的状态转移分支,红色分支代表信息比特为1的状态转移分支。
在这里插入图片描述假设在实际的传输过程中,0映射成-1,1映射成+1。

1.2 分支度量

卷积码基于接收比特似然比的分支计算:

在这里插入图片描述第i级Trellis格图对应的分支为δi,在(2,1,2)编码中,每一个状态转移分支对应两个比特,假设从解调器获得的接收比特似然比分别为ai bi , 则对应不同分支的似然比可以根据以上公式计算

1.3 前向状态度量

在这里插入图片描述第i级前向度量用αi表示,第i+1级前向度量用αi+1表示,基于第i级α度量计算第i+1级α度量。
前向状态度量计算示例(递推)
在这里插入图片描述
其中max*()运算如下,在这里插入图片描述赋初值:
在这里插入图片描述
负无穷在实际的译码中可以取较大的负数值,例如可以取-1e6;
由于是前向度量,因此赋值是对第1级Trellis的4个状态赋值。

每个码块长1000比特,要求最终状态归0,需要1002比特(最后两位为0),所以总的状态数位1003。但是第1003个状态的前向状态度量不会被使用。

每一步做归一化:
通过第i级前向状态度量可以计算得到第i+1级前向状态度量
在这里插入图片描述
在这里插入图片描述每一步进行归一化操作,以免溢出。

1.4 后向状态度量

在这里插入图片描述
后向状态度量计算示例:
第i级前向度量用βi表示,第i+1级前向度量用βi+1表示,基于第i+1级β度量计算第i级β度量。

在这里插入图片描述在这里插入图片描述

寄存器状态在最后需要归0,通过在发送序列最后补2个0,使得寄存器状态最终归0。第1个状态的后向状态度量也未被使用。

后向状态度量初值赋值:
在这里插入图片描述负无穷在实际的译码中可以取较大的负数值,例如可以取-1e6,由于是后向度量,因此赋值是对最后1级Trellis的4个状态赋值。

后向状态度量每一步做归一化:
通过第i+1级后向状态度量可以计算得到第i级后向状态度量
在这里插入图片描述在这里插入图片描述每一步进行归一化操作

1.5 比特似然计算

信息比特计算分组:
在这里插入图片描述信息比特计算分组示例-1
在这里插入图片描述在这里插入图片描述总的分支度量:
在这里插入图片描述

4个数求max*( )可以先将前2个数做一个max*(),得到的结果和第3个做max*(),然后得到的结果再和第4个做max*()。 也有其他方法,可查阅资料

信息比特计算分组示例-2
在这里插入图片描述在这里插入图片描述总的分支度量:

在这里插入图片描述信息比特译码似然比

在这里插入图片描述

二、仿真代码

卷积码编码 -> QPSK调制 -> 通过高斯噪声信道 -> 接收端软解调

1.设置仿真参数

代码如下:

clear;
close all;
M = 4; % 调制方式QPSK
k = log2(M); % Bits/symbol
N = 1000; %每个码块信息比特长度
maxBitErrors = 100;    % 最大误比特数
maxNumBits = 1e6;      % 最大传输比特数

2.仿真所需系统对象

代码如下:

%设置QPSK调制和解调器,使它们接受二进制输入
qpskMod = comm.QPSKModulator("BitInput",true);
%qpskDemod = comm.QPSKDemodulator("BitOutput",true);
%将AWGN通道对象的NoiseMethod属性设置为Variance,并定义VarianceSource属性,以便可以从输入端口设置噪声功率。
channel = comm.AWGNChannel('NoiseMethod','Variance','VarianceSource','Input port');
%将ResetInputPort属性设置为true,以便在模拟期间重置错误率计算器。
errorRate = comm.ErrorRate('ResetInputPort',true);

3.定义星座点,用于计算软信息

a = -1/sqrt(2);

%定义星座点,用于计算软信息
cons_bit = zeros(k,M); %2行,4列的数组,每一列代表一个星座点
cons_sym = zeros(1,M);
cons_p = zeros(1,M);
for loop_modu = 1:1:k %星座点的实现
    temp_1 = [ones(1,2^(k-loop_modu)),-ones(1,2^(k-loop_modu))];
    cons_bit(loop_modu,:) = kron(ones(1,2^(loop_modu-1)),temp_1);
    clear temp_1
end
if k == 2  %假定第一列为虚部,第二列为实部
    cons_sym = a * (cons_bit(2,:) + 1i.*cons_bit(1,:)); %调制,格雷映射
    cons_p = abs(cons_sym).^2; %验证星座点功率,发送符号功率归一化p_ave=sum(cons_p)/2^Modu_t=1,峰值功率1.8;平均功率1;峰均比1.8
end

4.模拟通信链路

在Es/No值的范围内模拟通信链路,对于每个Es/No值,模拟运行直到记录maxBitErrors且传输的总位数超过maxNumBits。 ,横坐标步长为1dB

a = -1/sqrt(2);

%定义星座点,用于计算软信息
cons_bit = zeros(k,M); %2行,4列的数组,每一列代表一个星座点
cons_sym = zeros(1,M);
cons_p = zeros(1,M);
for loop_modu = 1:1:k %星座点的实现
    temp_1 = [ones(1,2^(k-loop_modu)),-ones(1,2^(k-loop_modu))];
    cons_bit(loop_modu,:) = kron(ones(1,2^(loop_modu-1)),temp_1);
    clear temp_1
end
if k == 2  %假定第一列为虚部,第二列为实部
    cons_sym = a * (cons_bit(2,:) + 1i.*cons_bit(1,:)); %调制,格雷映射
    cons_p = abs(cons_sym).^2; %验证星座点功率,发送符号功率归一化p_ave=sum(cons_p)/2^Modu_t=1,峰值功率1.8;平均功率1;峰均比1.8
end
在Es/No值的范围内模拟通信链路,对于每个Es/No值,模拟运行直到记录maxBitErrors且传输的总位数超过maxNumBits。 ,横坐标步长为1dB
%在符号信噪比0dB到5dB的情况下进行讨论
%根据所需的Es/No范围设置信噪比矢量。
EsN0_dB = (0:1:5)';
%初始化误码率和错误统计数组。
ber = zeros(length(EsN0_dB),3); %硬判决,comm.ErrorRate
errorStats = zeros(1,3);
%创建一个网格结构,以表示码率为1/2卷积编码器
trellis = poly2trellis(3,[5 7]) %记忆长度为3,生成多项式的二进制向量[101][111]分别表示八进制57

for snr = 0:1:5
    delta = zeros(4,N+2); %分支度量
    alpha = zeros(4,N+2); %前向状态度量,加上初始状态和结束状态一共有N+3个状态,但是结束状态的前向状态度量未被使用,未进行赋值
    beta = zeros(4,N+2);  %后向状态度量,初始状态的后向状态度量未被使用,未进行赋值
    Delta = zeros(8,N+2); %总的分支度量

    while errorStats(2) <= maxBitErrors || errorStats(3) <= maxNumBits
        data = randi([0 1],N,1); %生成二进制数据
        dataIn = [data' [0,0]]'; %使编码最终状态归零
        codedData = convenc(dataIn,trellis); %使用指定的网格结构对数据进行卷积编码
        qpskTx = qpskMod(codedData); %QPSK调制
      
        noiseVar = 10^(0.1*(-snr)); %计算噪声方差
        rxSig = channel(qpskTx,noiseVar); %通过高斯噪声信道
        

        %QPSK生成LLR的过程需要调用函数
        %获取接收比特似然比,参数:调制阶数、符号长度、星座点、星座点对应的比特序列、接收序列、噪声方差
        [llr_det] = euc_soft_sym_det(k,N+2,cons_sym,cons_bit,rxSig.',noiseVar); %A.'转置不共轭,A'共轭转置

        llr = reshape(llr_det,2,N+2);
        %计算分支度量(1-4行分别代表编码比特00,01,10,11)
        delta(1,:) = [-1,-1]*llr./2;
        delta(2,:) = [-1,1]*llr./2;
        delta(3,:) = [1,-1]*llr./2;
        delta(4,:) = [1,1]*llr./2;

        %计算前向状态度量(1-4行分别代表状态00,01,10,11)
        alpha(:,1) = [0,-10^6,-10^6,-10^6]'; %初始化第一列,默认初始状态为00
        for p = 2:1:N+2 %循环,每一次循环计算格图的一级
            %max*运算调用函数 max*(a,b) =  max(a,b)+log( 1 + exp( min(a,b)-max(a,b) ) )
            alpha(1,p) = max_(2,[alpha(1,p-1)+delta(1,p-1),alpha(2,p-1)+delta(4,p-1)]); %第一行,状态00
            alpha(2,p) = max_(2,[alpha(3,p-1)+delta(2,p-1),alpha(4,p-1)+delta(3,p-1)]); %状态01
            alpha(3,p) = max_(2,[alpha(1,p-1)+delta(4,p-1),alpha(2,p-1)+delta(1,p-1)]); %状态10
            alpha(4,p) = max_(2,[alpha(3,p-1)+delta(3,p-1),alpha(4,p-1)+delta(2,p-1)]); %状态11
            %每一步进行归一化操作
            alpha(:,p) = alpha(:,p)-max(alpha(:,p));
        end

        %计算后向状态度量(1-4行分别代表状态00,01,10,11)
        beta(:,N+2) = [0,-10^6,-10^6,-10^6]'; %初始化最后一列,默认初始状态为00
        for q = N+1:-1:1 %循环,每一次循环计算格图的一级
            %max*运算调用函数 max*(a,b) =  max(a,b)+log( 1 + exp( min(a,b)-max(a,b) ) )
            beta(1,q) = max_(2,[beta(1,q+1)+delta(1,q+1),beta(3,q+1)+delta(4,q+1)]); %第一行,状态00
            beta(2,q) = max_(2,[beta(1,q+1)+delta(4,q+1),beta(3,q+1)+delta(1,q+1)]); %状态01
            beta(3,q) = max_(2,[beta(2,q+1)+delta(2,q+1),beta(4,q+1)+delta(3,q+1)]); %状态10
            beta(4,q) = max_(2,[beta(2,q+1)+delta(3,q+1),beta(4,q+1)+delta(2,q+1)]); %状态11
            %每一步进行归一化操作
            beta(:,q) = beta(:,q)-max(beta(:,q));
        end

        %计算信息比特
        %计算总的分支度量,信息比特为0对应分支
        Delta(1,:) = alpha(1,:) + delta(1,:) + beta(1,:);
        Delta(2,:) = alpha(2,:) + delta(4,:) + beta(1,:);
        Delta(3,:) = alpha(3,:) + delta(2,:) + beta(2,:);
        Delta(4,:) = alpha(4,:) + delta(3,:) + beta(2,:);
        D0 = zeros(1,N+2);
        for t = 1:1:N+2
            D0(t) = max_(4,[Delta(1,t),Delta(2,t),Delta(3,t),Delta(4,t)]);
        end
        %信息比特为1对应分支
        Delta(5,:) = alpha(1,:) + delta(4,:) + beta(3,:);
        Delta(6,:) = alpha(2,:) + delta(1,:) + beta(3,:);
        Delta(7,:) = alpha(3,:) + delta(3,:) + beta(4,:);
        Delta(8,:) = alpha(4,:) + delta(2,:) + beta(4,:);
        D1 = zeros(1,N+2);
        for r = 1:1:N+2
            D1(r) = max_(4,[Delta(5,r),Delta(6,r),Delta(7,r),Delta(8,r)]);
        end

        %信息比特译码似然比
        L = D1-D0;

        %信息比特的似然比(若取+1的概率大于取-1的概率,LLR为正,反之为负)
        output = (sign(L)+1)/2; %判断正负,-1,+1映射到0,1

        %统计误比特率
        errorStats = errorRate(dataIn,output',0);  %收集错误统计数据

      
    end
    ber(snr+1,:) = errorStats; %保存BER数据
    errorStats = errorRate(dataIn,output',1);%重置错误率计算器

end

1.5 仿真结果图

semilogy(EsN0_dB,ber(:,1),'-*'); %对数函数,Es_N0单位为dB
title('卷积码BCJR译码误比特率性能曲线');
xlabel('E_s/N_0(dB)');
ylabel('BER');
grid

1.6 自定义接收比特似然比函数

%解调的软信息,可求比特的似然比
function [llr_det] = euc_soft_sym_det(Modu_t,N_sample,cons_sym,cons_bit,s_con_mat,sigma_hard)
%参数:Modu_t调制阶数,N_sample解调的符号长度,cons_sym星座点(const)(const)cons_bit星座点bit序列,s_con_mat接收信号,sigma_hard噪声方差
euc_det = zeros(2^Modu_t,N_sample); %欧氏距离(对于每一个符号,都要计算其与每一个星座点的欧式距离)
for loop_modu_det = 1:1:2^Modu_t 
    %每一次循环计算所有的符号到一个某一个星座点的欧氏距离,按行计算
    euc_det(loop_modu_det,:) = - abs( s_con_mat - cons_sym(1,loop_modu_det)).^2./sigma_hard;
end
llr_det = zeros(1,Modu_t*N_sample);

if Modu_t == 2  %调制阶数为2,QPSK
    for loop_llr_det = 1:1:N_sample %外层循环,对每一个符号进行判决
        for loop_llr_bit = 1:1:Modu_t %遍历星座点每一个比特
            ind_temp_plus = cons_bit(loop_llr_bit,:) == 1; %符号星座点第loop_llr_bit个比特为+1的序号
            ind_temp_minus = cons_bit(loop_llr_bit,:) == -1;
            a_temp_plus = euc_det(ind_temp_plus,loop_llr_det);
            a_temp_minus = euc_det(ind_temp_minus,loop_llr_det);
            llr_det(1,(loop_llr_det-1)*Modu_t+loop_llr_bit) = max(a_temp_plus)+log(sum(exp(a_temp_plus-max(a_temp_plus))))-max(a_temp_minus)-log(sum(exp(a_temp_minus-max(a_temp_minus))));
            %这里euc_det是负数,本来不易溢出,但这样计算更不容易溢出
        end
    end
end

1.7 自定义max*()函数

这个函数写复杂了,可以省略num这个参数,num可以用list.length得到。

%max*函数,递归函数
function log_max = max_(num,list)
%参数:num输入的个数,list待比较的数组
if num == 2
    a = list(1); b = list(2);
    log_max = max(a,b)+log( 1 + exp( min(a,b)-max(a,b) ) );
else
    log_max = max_(2,[list(num),max_(num-1,list(1:num-1))]);
end
    
end

三、仿真结果

在这里插入图片描述

Es_N0(dB) BER 误比特数 传输比特数
0 0.087209964 87297 1000998
1 0.039613466 39653 1000998
2 0.013881147 13895 1000998
3 0.003566441 3570 1000998
4 0.000580421 581 1000998
5 8.51E-05 101 1187370

总结

仿真结果图如上,随着符号信噪比Es_N0的增加,误比特率BER降低。在信噪比为5dB时,误比特率BER达到10^-4量级,说明使用BCJR算法对卷积码进行译码的误码性能较好。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/beryl4134/article/details/125454726

智能推荐

while循环&CPU占用率高问题深入分析与解决方案_main函数使用while(1)循环cpu占用99-程序员宅基地

文章浏览阅读3.8k次,点赞9次,收藏28次。直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方。使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器)。因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题。具体项目代码就不贴了,类似于下面这段代码。​​​​​​while(flag) {//your code;}这里的flag._main函数使用while(1)循环cpu占用99

【无标题】jetbrains idea shift f6不生效_idea shift +f6快捷键不生效-程序员宅基地

文章浏览阅读347次。idea shift f6 快捷键无效_idea shift +f6快捷键不生效

node.js学习笔记之Node中的核心模块_node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是-程序员宅基地

文章浏览阅读135次。Ecmacript 中没有DOM 和 BOM核心模块Node为JavaScript提供了很多服务器级别,这些API绝大多数都被包装到了一个具名和核心模块中了,例如文件操作的 fs 核心模块 ,http服务构建的http 模块 path 路径操作模块 os 操作系统信息模块// 用来获取机器信息的var os = require('os')// 用来操作路径的var path = require('path')// 获取当前机器的 CPU 信息console.log(os.cpus._node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是

数学建模【SPSS 下载-安装、方差分析与回归分析的SPSS实现(软件概述、方差分析、回归分析)】_化工数学模型数据回归软件-程序员宅基地

文章浏览阅读10w+次,点赞435次,收藏3.4k次。SPSS 22 下载安装过程7.6 方差分析与回归分析的SPSS实现7.6.1 SPSS软件概述1 SPSS版本与安装2 SPSS界面3 SPSS特点4 SPSS数据7.6.2 SPSS与方差分析1 单因素方差分析2 双因素方差分析7.6.3 SPSS与回归分析SPSS回归分析过程牙膏价格问题的回归分析_化工数学模型数据回归软件

利用hutool实现邮件发送功能_hutool发送邮件-程序员宅基地

文章浏览阅读7.5k次。如何利用hutool工具包实现邮件发送功能呢?1、首先引入hutool依赖<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.19</version></dependency>2、编写邮件发送工具类package com.pc.c..._hutool发送邮件

docker安装elasticsearch,elasticsearch-head,kibana,ik分词器_docker安装kibana连接elasticsearch并且elasticsearch有密码-程序员宅基地

文章浏览阅读867次,点赞2次,收藏2次。docker安装elasticsearch,elasticsearch-head,kibana,ik分词器安装方式基本有两种,一种是pull的方式,一种是Dockerfile的方式,由于pull的方式pull下来后还需配置许多东西且不便于复用,个人比较喜欢使用Dockerfile的方式所有docker支持的镜像基本都在https://hub.docker.com/docker的官网上能找到合..._docker安装kibana连接elasticsearch并且elasticsearch有密码

随便推点

Python 攻克移动开发失败!_beeware-程序员宅基地

文章浏览阅读1.3w次,点赞57次,收藏92次。整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)近年来,随着机器学习的兴起,有一门编程语言逐渐变得火热——Python。得益于其针对机器学习提供了大量开源框架和第三方模块,内置..._beeware

Swift4.0_Timer 的基本使用_swift timer 暂停-程序员宅基地

文章浏览阅读7.9k次。//// ViewController.swift// Day_10_Timer//// Created by dongqiangfei on 2018/10/15.// Copyright 2018年 飞飞. All rights reserved.//import UIKitclass ViewController: UIViewController { ..._swift timer 暂停

元素三大等待-程序员宅基地

文章浏览阅读986次,点赞2次,收藏2次。1.硬性等待让当前线程暂停执行,应用场景:代码执行速度太快了,但是UI元素没有立马加载出来,造成两者不同步,这时候就可以让代码等待一下,再去执行找元素的动作线程休眠,强制等待 Thread.sleep(long mills)package com.example.demo;import org.junit.jupiter.api.Test;import org.openqa.selenium.By;import org.openqa.selenium.firefox.Firefox.._元素三大等待

Java软件工程师职位分析_java岗位分析-程序员宅基地

文章浏览阅读3k次,点赞4次,收藏14次。Java软件工程师职位分析_java岗位分析

Java:Unreachable code的解决方法_java unreachable code-程序员宅基地

文章浏览阅读2k次。Java:Unreachable code的解决方法_java unreachable code

标签data-*自定义属性值和根据data属性值查找对应标签_如何根据data-*属性获取对应的标签对象-程序员宅基地

文章浏览阅读1w次。1、html中设置标签data-*的值 标题 11111 222222、点击获取当前标签的data-url的值$('dd').on('click', function() { var urlVal = $(this).data('ur_如何根据data-*属性获取对应的标签对象

推荐文章

热门文章

相关标签