Turbo编译码Matlab仿真解读 -- WuYufei_matlab
吳雨霏博士版本的Turbo編譯碼仿真較為經(jīng)典,以下就原碼進行解讀。
一、仿真代碼架構(gòu)
“turbo_sys_demo.m”是程序的主體框架,Turbo編譯碼均在此程序展開。程序開始需要用戶需要如下幾個參數(shù):
1)譯碼算法:選擇使用0:Log-MAP,1:SOVA
? ? 這是讓用戶選擇使用何種Turbo譯碼算法。若Tubo為多次迭代譯碼,則選用Log-MAP算法;否則選SOVA。默認(rèn)選擇0;
2)選擇幀長:幀長=信息長度+卷尾;
? ? 根據(jù)自己需要選擇幀長,程序默認(rèn)選擇400(396+4);
3)輸入Turbo碼生成多項式g:默認(rèn)為[111 101], 即 [7 5];
有兩點需要注意:
1) 生成多項式為八進制表示;
2)若反饋多項式為7,即RSC分量碼表示,則生成多項式表示形式為:[7 5;7]
?4)選擇Turbo碼是否打孔:0 – punctured;1—unpunctured
LTE Turbo未打孔碼默認(rèn)碼率為1/3,打孔后默認(rèn)碼率為1/2;
- 選擇每幀迭代次數(shù): Turbo譯碼一般迭代5 ~ 7次,程序默認(rèn)選擇5次;
- 選擇終止程序的幀錯誤次數(shù):程序默認(rèn)選擇15幀;
- 選擇系統(tǒng)信噪比Eb/N0:程序默認(rèn)為2.0;
圖1為輸入顯示圖:
圖1? 代碼參數(shù)輸入仿真運行圖
二、編碼程序流程梳理
參數(shù)說明:
errs – 比特錯誤計數(shù)
nferr – 幀錯誤計數(shù)
nfame – 幀計數(shù)
1)產(chǎn)生數(shù)據(jù)源
源碼中使用sort函數(shù)產(chǎn)生Turbo編碼所使用的交織器,仿真時仍傾向采用LTE自帶的交織器,代價是限定碼長(因為每一個交織器都與特定的碼長對應(yīng));
2)Turbo編碼
?output = function encoderm( x, g, alpha, puncture )- 交織器映射采用 alpha數(shù)組;
- puncture = 1,表示不需要Turbo碼打孔,默認(rèn)碼率為1/3;
- puncture = 0,表示對Turbo碼打孔,輸出碼率為1/2;
2.1? Turbo編碼流程梳理
先給出編碼部分總體流程圖
(不管是自己設(shè)計程序還是讀別人程序,強烈建議梳理流程圖這一步驟必不可少。因為認(rèn)識事物的客觀規(guī)律也是從宏觀到微觀,從整體到局部。如果一開始就陷入細(xì)節(jié),對完成目標(biāo)就很困難了):
圖2? 編碼整理流程圖?
根據(jù)生成多項式矩陣g,得到以下參數(shù):
- 寄存器階數(shù) m = 矩陣g 列數(shù) – 1;
- 總編碼信息長度 L_total = 信息長度 + m(加入尾比特處理,迫使寄存器狀態(tài)最終歸0)
程序調(diào)用?rsc_encode(g,input,1)函數(shù):
1)首先,生成系統(tǒng)信息比特 d_k:? ??
% generate the codeword for i = 1:L_totalif terminated<0 | (terminated>0 & i<=L_info)d_k = x(1,i);elseif terminated>0 & i>L_info% terminate the trellisd_k = rem( g(1,2:K)*state', 2 );enda_k = rem( g(1,:)*[d_k state]', 2 );[output_bits, state] = encode_bit(g, a_k, state);? ? ?若歸零標(biāo)志 terminated >0(代碼里terminated = 1)并且編碼序號 i? < 信息長度 L_info)
? ? ?d_k = x(1,i);
? ? ?否則,d_k = rem( g(1,2:K) * state', 2 );
2)a_k = rem( g(1,:) * [d_k state]', 2 );
3)調(diào)用函數(shù) encode_bit,輸出output為總信息長度的2倍,即800bit:
% the rate is 1/n % k is the constraint length % m is the amount of memory [n,k] = size(g); m = k-1;% determine the next output bit for i=1:noutput(i) = g(i,1)*input;for j = 2:koutput(i) = xor(output(i),g(i,j)*state(j-1));end endstate = [input, state(1:m-1)];該函數(shù)詳見流程圖解析。如果對代碼還不是很理解,那就說明對卷積碼編碼原理理解還不到位。這里推薦大家再回顧一下卷積碼編碼原理:
卷積碼編碼原理https://blog.csdn.net/snowman898/article/details/124148068
output1 = rsc_encode(g,input,1);
?
% make a matrix with first row corresponing to info sequence
% second row corresponsing to RSC #1's check bits.
% third row corresponsing to RSC #2's check bits.
?
y(1,:) = output1(1:2:2*L_total);
y(2,:) = output1(2:2:2*L_total);
y 的第一行為系統(tǒng)比特,即信息比特;
y的第二行為校驗比特1;
同樣的方法,? 在encoder.m文件中再次調(diào)用rsc_encode(g,input,-1)函數(shù)。和上次不同的是,歸零標(biāo)志 terminated = -1,即校驗碼2并不歸零。
這時,交織器開始起作用,輸入rsc_encode里面也不再是原始數(shù)據(jù),而是經(jīng)過交織器交織后、長度變?yōu)長_total的數(shù)據(jù):
% interleave input to second encoder
for i = 1:L_total
? ?input1(1,i) = y(1,alpha(i));?
end
output2 = rsc_encode(g, input1(1,1:L_total), -1 );
% third row corresponsing to RSC #2's check bits.
y(3,:) = output2(2:2:2*L_total);
2.2? Turbo碼打孔 (速率匹配)
(1)不打孔,即 puncture = 1
? ? ?rate = 1 / ( 2 + puncture ) ,則不打孔時默認(rèn)速率為1/3;
? ? 最終輸出 en_output 按照 [ sys_data ; parity_data1;? parity_data2 ] 列模式方式輸出,即? ? ? ? ? en_ouput 共有3行,有 L_total 列;
(2)打孔,puncture = 0
? ? ?按照上述公式計算,打孔后 Turbo碼率提高至 1/2;
? ?for i=1:L_total
? ? ? ?en_output(1,n*(i-1)+1) = y(1,i);
? ? ? ?if rem(i,2)
? ? ? % odd check bits from RSC1
? ? ? ? ? en_output(1,n*i) = y(2,i);
? ? ? ?else
? ? ? % even check bits from RSC2
? ? ? ? ? en_output(1,n*i) = y(3,i);
? ? ? ?end?
? ? end ?
即:輸出的奇數(shù)項為 系統(tǒng)信息, 偶數(shù)項 為 RSC1 校驗位 和?RSC2 校驗位。
最終,對en_output進行極性變換輸出:
% antipodal modulation: +1/-1
en_output = 2 * en_output - ones(size(en_output));
三、?Turbo譯碼流程梳理
對下列參數(shù)進行初始化:
nferr , errs = 0,隨后根據(jù)信噪比產(chǎn)生信號和噪聲的疊加 recv signal:
r = en_output+sigma*randn(1,L_total*(2+puncture)); % received bits接下來,我們?nèi)越o出譯碼流程圖:
圖3? 譯碼整理流程圖??
3.1 logmapo 函數(shù)介紹
?L_all = logmapo(rec_s,g,L_a,ind_dec)
輸入?yún)?shù):
1)rec_s:scaled received bits 縮放接收比特
? ? ?rec_s = 0.5 * L_c * yk = ( 2 * a * rate * Eb/N0 ) * yk
2)g:生產(chǎn)碼多項式
3)L_a:先驗 L 值
4)ind_dec:?index of decoder. Either 1 or 2.?Encoder 1 is assumed to be terminated, while? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? encoder 2 is open.
該函數(shù)是turbo譯碼的核心,因此,先給出函數(shù)流程圖:
?圖4? logmapo流程圖?
3.2? Trellis函數(shù)介紹
trellis函數(shù)主要是根據(jù)碼生成多項式,推出以下參數(shù):
- 后向輸出? next_output
- 后向狀態(tài)? next_state
- 前向輸出? last_output
- 前向狀態(tài)? last_state
?1)首先,確定各個初始參數(shù):
% g = [ 1 1 1; 1 0 1];
?[n,K] = size(g);? ? ? ? ? ? ?% n = 2, K = 3
m = K - 1;? ? ? ? ? ? ? ? ? ? ? % m = 2
max_state = 2^m;? ? ? ? ?% max_state = 4
for state=1:max_state
? ??state_vector = bin_state( state-1, m );? % 將整數(shù)向量state轉(zhuǎn)換成 m-bit 向量形式
end
state_vector 四個狀態(tài)為:[ 0, 0 ] ,?[ 0, 1 ] ,?[ 1, 0 ] ,?[ 1, 1 ]?
2)當(dāng)輸入為0時:d_k = 0
a_k = rem( g(1,:)*[0 state_vector]', 2 );
[out_0, state_0] = encode_bit(g, a_k, state_vector);
可以認(rèn)為根據(jù) g, a_k, state_vector 完成一次 Turbo編碼,得到 next_out, next_state;
encode_bit函數(shù)在編碼流程中已詳細(xì)梳理,此次不再贅述。最終,我們給出trellis網(wǎng)格圖:
表1? LTE Turbo Trellis?
| 當(dāng)前狀態(tài) state_vector | 輸入d_k=0 | 輸入d_k=1 | |
| next_vector (bit形式) | [ 0, 0 ] | [ 0, 0 ] | [ 1, 0 ] |
| [ 0, 1 ] | [ 1, 0 ] | [ 0, 0 ] | |
| [ 1, 0 ] | [ 1, 1 ] | [ 0, 1 ] | |
| [ 1, 1 ] | [ 0, 1 ] | [ 1, 1 ] | |
| next_out (bit形式) | [ 0, 0 ] | [ 0, 0 ] | [ 1, 1 ] |
| [ 0, 1 ] | [ 0, 0 ] | [ 1, 1 ] | |
| [ 1, 0 ] | [ 0, 1 ] | [ 1, 0 ] | |
| [ 1, 1 ] | [ 0, 1 ] | [ 1, 0 ] | |
| next_out (雙極性形式) | [ 0, 0 ] | [ -1 ?-1 ?1 ?1 ] | |
| [ 0, 1 ] | [ -1 ?-1 ?1 ?1 ] | ||
| [ 1, 0 ] | [ -1 ?1 ?1 ?-1 ] | ||
| [ 1, 1 ] | [ -1 ?1 ?1 ?-1 ] | ||
| next_state (整數(shù)形式) | [ 0, 0 ] | [ 1 ?3] | |
| [ 0, 1 ] | [ 3 ?1] | ||
| [ 1, 0 ] | [ 4 ?2] | ||
| [ 1, 1 ] | [ 2 ?4] | ||
同時,根據(jù)該表,由當(dāng)前 [d_k, next_out, next_state]?推導(dǎo)出前一時刻的 [ last_out, last_state]:
% find out which two previous states can come to present state
last_state = zeros(max_state,2);
for bit=0:1
? ?for state=1:max_state
? ? ? last_state(next_state(state,bit+1), bit+1)=state;
? ? ? last_out(next_state(state, bit+1), bit*2+1:bit*2+2) ...
? ? ? ? ?= next_out(state, bit*2+1:bit*2+2);
? ?end?
end
表2 LTE Turbo Trellis?
| 當(dāng)前狀態(tài) state_vector | 輸入d_k=0 | 輸入d_k=1 | |
| last_vector (bit形式) | [ 0, 0 ] | [ 0, 0 ] | [ 0, 1 ] |
| [ 0, 1 ] | [ 1, 1 ] | [ 1, 0 ] | |
| [ 1, 0 ] | [ 0, 1 ] | [ 0, 0 ] | |
| [ 1, 1 ] | [ 1, 0 ] | [ 1, 1 ] | |
| last_out (bit形式) | [ 0, 0 ] | [ 0, 0 ] | [ 1, 1 ] |
| [ 0, 1 ] | [ 0, 1 ] | [ 1, 0 ] | |
| [ 1, 0 ] | [ 0, 0 ] | [ 1, 1 ] | |
| [ 1, 1 ] | [ 0, 1 ] | [ 1, 0 ] | |
| last_out (雙極性形式) | [ 0, 0 ] | [ -1 ?-1 ?1 ?1 ] | |
| [ 0, 1 ] | [ -1 ?1 ?1 ?-1 ] | ||
| [ 1, 0 ] | [ -1 ?-1 ?1 ?1 ] | ||
| [ 1, 1 ] | [ -1 ?1 ?1 ?-1 ] | ||
| last_state (整數(shù)形式) | [ 0, 0 ] | [ 1 ?2] | |
| [ 0, 1 ] | [ 4 ?3] | ||
| [ 1, 0 ] | [ 2 ?1] | ||
| [ 1, 1 ] | [ 3 ?4] | ||
p.s. 這里提供另一角度去計算 last_out:
根據(jù)當(dāng)前狀態(tài)和輸入 [ state,d_k ] 查表 last_state, 再由 [last_stae d_k] 查找 next_output;
3.3 前向度量計算
前向度量 α 計算由雙循環(huán)組成:
內(nèi)循環(huán):以所有狀態(tài)為循環(huán):state = 1 : 2^m
外循環(huán):以所有信息數(shù)量為循環(huán):k = 2 : L_total + 1
先計算輸入 d_k = 0時:
% Log_MAP算法計算
gamma( last_state(state2,1) ) = ( -rec_s(2*k-3) + rec_s(2*k-2) * last_out(state2,2) )
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?- log(1+exp(L_a(k-1)));
再計算輸入 d_k = 1時:?
?gamma(last_state(state2,2)) = (rec_s(2*k-3)+rec_s(2*k-2)*last_out(state2,4))
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?+ L_a(k-1) - log(1+exp(L_a(k-1)));
log_map算法目前用的不多,由于計算量較大,主流均采用 max-log-map計算,這里只給出計算公式,詳細(xì)算法不再推導(dǎo);
p.s. 未完,見后續(xù)(2)
? ? ? ?一定要看哈,文末有彩蛋(* ̄︶ ̄)
吳雨霏博士論文集及MATLAB原版程序https://download.csdn.net/download/qq_36756847/12036978?utm_medium=distribute.pc_relevant_download.none-task-download-2~default~BlogCommendFromBaidu~Rate-15-12036978-download-4229931.dl_default&depth_1-utm_source=distribute.pc_relevant_download.none-task-download-2~default~BlogCommendFromBaidu~Rate-15-12036978-download-4229931.dl_default&dest=https%3A%2F%2Fdownload.csdn.net%2Fdownload%2Fqq_36756847%2F12036978&spm=1003.2020.3001.6616.17
總結(jié)
以上是生活随笔為你收集整理的Turbo编译码Matlab仿真解读 -- WuYufei_matlab的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 格拉布斯离群值检验——理论与 Pytho
- 下一篇: 化妆品行业组合解决方案