初识LTE(三):码率匹配和码率分块

初识LTE(三):码率匹配和码率分块

一.码率匹配

1.码率匹配原理

什么是码率匹配呢?就是Turbo编码原本码率是1/3,如果信道很好,那我可以少发一点1/2就可以了,这就是码率匹配

码率匹配原理如下

image-20220704161133966

image-20220704161058892

image-20220704161201192

那么,如何解码率匹配呢,那些比特可是结结实实的少发了呀!

实际上,就是用0填充,LTE称其为打孔和解打孔操作

image-20220704161406604

image-20220704161418201

image-20220704161437254

image-20220704161500007

image-20220704161509260

2. 码率匹配代码

%------------------------码率匹配-----------------------%
%-----------------------author:lzx-------------------------%
%-----------------------date:2022年7月1日17点45分-----------------%
function y= RateMatcher(in, Kplus, Rate)
% Rate matching per coded block, with and without the bit selection.
% D是发送比特的长度
D = Kplus+4;
if numel(in)~=3*D, error('Kplus (2nd argument) times 3 must be size of input 1.');end 

% Parameters
% 矩阵的列固定为32,然后去满足够的行以放下所有比特
% 多余的Nd个填Null
colTcSb = 32;
rowTcSb = ceil(D/colTcSb);
Kpi = colTcSb * rowTcSb;
Nd = Kpi - D;

% Bit streams
% 取出Turbo编码的三个比特流
d0 = in(1:3:end); % systematic
d1 = in(2:3:end); % parity 1st
d2 = in(3:3:end); % parity 2nd
% 交织
i0=(1:D)';
Index=indexGenerator(i0,colTcSb, rowTcSb, Nd);
Index2=indexGenerator2(i0,colTcSb, rowTcSb, Nd);
% Sub-block interleaving - per stream
v0 = subBlkInterl(d0,Index);
v1 = subBlkInterl(d1,Index);
v2 = subBlkInterl(d2,Index2);
vpre=[v1,v2].';
v12=vpre(:);

%   Concat 0, interleave 1, 2 sub-blk streams
% Bit collection
% 比特收集
wk = zeros(numel(in), 1);
wk(1:D) = v0(~isnan( v0 ));
wk(D+1:end) = v12(~isnan( v12 ));

% Apply rate matching
% 裁剪
N=ceil(D/Rate);
y=wk(1:N);

end


function v = indexGenerator(d, colTcSb, rowTcSb, Nd)
% Sub-block interleaving - for d0 and d1 streams only

colPermPat = [0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30,...
              1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31];

% For 1 and 2nd streams only
y = [NaN*ones(Nd, 1); d];       % null (NaN) filling
inpMat = reshape(y, colTcSb, rowTcSb).';
permInpMat = inpMat(:, colPermPat+1);
v = permInpMat(:);

end

function v = indexGenerator2(d, colTcSb, rowTcSb, Nd)
% Sub-block interleaving - for d2 stream only

colPermPat = [0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30,...
              1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31];
pi = zeros(colTcSb*rowTcSb, 1);
for i = 1 : length(pi)
    pi(i) = colPermPat(floor((i-1)/rowTcSb)+1) + colTcSb*(mod(i-1, rowTcSb)) + 1;
end

% For 3rd stream only
y = [NaN*ones(Nd, 1); d];       % null (NaN) filling
inpMat = reshape(y, colTcSb, rowTcSb).';
ytemp = inpMat.';
y = ytemp(:);
v = y(pi);

end

function out=subBlkInterl(d0,Index)
out=zeros(size(Index));
IndexG=~isnan(Index);
IndexB=isnan(Index);
MyIndex=Index(IndexG);
out(IndexG)=d0(MyIndex);
Nd=sum(IndexB);
out(IndexB)=nan(Nd,1);
end

%------------------------解码率匹配-----------------------%
%-----------------------author:lzx-------------------------%
%-----------------------date:2022年7月1日17点53分-----------------%
function out = RateDematcher(in, Kplus)
% Undoes the Rate matching per coded block.
%#codegen
% 之前被打孔掉的比特用0填充即可,为什么?
% Parameters
colTcSb = 32;
D = Kplus+4;
rowTcSb = ceil(D/colTcSb);
Kpi = colTcSb * rowTcSb;
Nd = Kpi - D;

tmp=zeros(3*D,1);
tmp(1:numel(in))=in;

% no bit selection - assume full buffer passed in
i0=(1:D)';
Index= indexGenerator(i0,colTcSb, rowTcSb, Nd);
Index2= indexGenerator2(i0,colTcSb, rowTcSb, Nd);
Indexpre=[Index,Index2+D].';
Index12=Indexpre(:);

% Bit streams
tmp0=tmp(1:D);
tmp12=tmp(D+1:end);
v0 = subBlkDeInterl(tmp0, Index);
d12=subBlkDeInterl(tmp12, Index12);
v1=d12(1:D);
v2=d12(D+(1:D));

% Interleave 1, 2, 3 sub-blk streams - for turbo decoding
temp = [v0 v1 v2].';
out = temp(:);
end

function v = indexGenerator(d, colTcSb, rowTcSb, Nd)
% Sub-block interleaving - for d0 and d1 streams only

colPermPat = [0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30,...
              1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31];

% For 1 and 2nd streams only
y = [NaN*ones(Nd, 1); d];       % null (NaN) filling
inpMat = reshape(y, colTcSb, rowTcSb).';
permInpMat = inpMat(:, colPermPat+1);
v = permInpMat(:);

end

function v = indexGenerator2(d, colTcSb, rowTcSb, Nd)
% Sub-block interleaving - for d2 stream only

colPermPat = [0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30,...
              1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31];
pi = zeros(colTcSb*rowTcSb, 1);
for i = 1 : length(pi)
    pi(i) = colPermPat(floor((i-1)/rowTcSb)+1) + colTcSb*(mod(i-1, rowTcSb)) + 1;
end

% For 3rd stream only
y = [NaN*ones(Nd, 1); d];       % null (NaN) filling
inpMat = reshape(y, colTcSb, rowTcSb).';
ytemp = inpMat.';
y = ytemp(:);
v = y(pi);

end

function out=subBlkDeInterl(in,Index)
out=zeros(size(in));
IndexG=find(~isnan(Index)==1);
IndexOut=Index(IndexG);
out(IndexOut)=in;
end

二.码块分割

1.码块分割的原理

image-20220704162354095

解码就是逆操作,这里就不展开了

2.代码

%------------------------码块分割-----------------------%
%-----------------------author:lzx-------------------------%
%-----------------------date:2022年7月2日20点35分-----------------%
function  [C, Kplus] = CblkSegParams(tbLen)
%#codegen
%% Code block segmentation
% C: 被分为了多少个码块
% KPlus: 被分割完的会有两个长度,一个是K-一个是K+,详情看我博客
blkSize = tbLen + 24;
maxCBlkLen = 6144;
% 无需分块
if (blkSize <= maxCBlkLen)
    C = 1;          % number of code blocks
    b = blkSize;    % total bits
% 计算C
else
    L = 24;
    C = ceil(blkSize/(maxCBlkLen-L));
    b = blkSize + C*L; 
end

% Values of K from table 5.1.3-3
validK = [40:8:512 528:16:1024 1056:32:2048 2112:64:6144].';
% 找到Kplus
% First segment size
temp = find(validK >= b/C);
Kplus = validK(temp(1), 1);     % minimum K
%------------------------找到分块后每块的长度-----------------------%
%-----------------------author:lzx-------------------------%
%-----------------------date:2022年7月2日20点50分-----------------%
function E = CbBitSelection(C, G, Nl, Qm)
%#codegen
% Bit selection parameters
% G = total number of output bits
% Nl   Number of layers a TB is mapped to (Rel10)
% Qm    modulation bits
Gprime = G/(Nl*Qm);
gamma = mod(Gprime, C);
E=zeros(C,1);
% Rate matching with bit selection
% 余数以下的小一点,大于的大一点
for cbIdx=1:C
        if ((cbIdx-1) <= (C-1-gamma))
            E(cbIdx) = Nl*Qm*floor(Gprime/C);
        else
             E(cbIdx)   = Nl*Qm*ceil(Gprime/C);
        end       
end
    

这里做一个补充,代码中获得总比特数G的式子是

G=ceil((Kplus+4)/CodingRate);

这明显只适用于不分块的情况,正确的应该是

G=ceil((Kplus+4)*C/CodingRate);

分析一下为什么,正常总比特应该如何计算呢

应该是输入数据长度inLen加上CRC和Turbo编码的长度,CRC会增加24比特,Turbo增加四比特

合计就是(inLen+C*(4+24))再进行码率匹配

但是注意,为了方便Kplus的选取,我们的输入长度总是Kplus-24的长度,所有代码都是这样的,或是他的倍数,因此两者殊途同归!

但是要注意把C补上

三.CRC

CRC纠错遍布在整个LTE中,整个TB需要添加CRC,分割后每个码块也要添加CRC

image-20220704162744599

CRC的远离大致是补零后整除,不会的可以在一些通信原理书上学习一下

四.LTE发送总流程

如下图,重组后进行扰码,调制,然后发送,这就是DLSCH的总流程

image-20220704162840938

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值