1.演算法模擬效果
vivado2019.2模擬結果如下(完整程式碼執行後無水印):
設定SNR=1db
設定SNR=5db
設定SNR=10db
和之前開發的普通QPSK調製解調系統相比,軟解調誤位元速率更低。
基於FPGA的QPSK調製解調系統,包含testbench,高斯通道模組,誤位元速率統計模組,可以設定不同SNR_fpga qpsk-CSDN部落格
模擬操作步驟可參考程式配套的操作影片。
2.演算法涉及理論知識概要
QPSK是一種常用的調製方式,透過將兩個位元對映到一個複平面上的相位點,實現了高效的訊號傳輸。軟解調是一種基於接收訊號的機率估計進行解調的方法,能夠提供更好的效能。本文將逐步介紹QPSK軟解調的實現過程,包括訊號取樣、相位估計、判決和解調等方面。軟解調是一種透過機率估計實現解調的方法,能夠在通道噪聲存在的情況下提供更好的效能。QPSK是一種常用的調製方式,透過將兩個位元對映到相位點,實現了高效的訊號傳輸。本文旨在詳細介紹QPSK軟解調的實現過程,包括訊號取樣、相位估計、判決和解調等步驟。
2.1 訊號取樣
接收到的QPSK訊號經過取樣操作,得到離散時間訊號序列。取樣率需要滿足奈奎斯特取樣定理,通常為位元速率的兩倍。
2.2 判決
在QPSK訊號解調中,判決過程用於確定每個訊號符號的二進位制位元值。判決過程根據接收訊號的相位進行劃分,將其對映到不同的位元值。
假設接收到的訊號序列為r[n],判決過程的結果為判決符號d_hat。常見的判決公式為:
if theta_hat > -pi/4 && theta_hat <= pi/4
d_hat = [1, 1]
elseif theta_hat > pi/4 && theta_hat <= 3pi/4
d_hat = [0, 1]
elseif theta_hat > 3pi/4 || theta_hat <= -3*pi/4
d_hat = [0, 0]
else
d_hat = [1, 0]
end
2.3 解調
解調過程將判決的位元值轉換為原始資料位元。解調過程根據對映表將判決位元值轉換為原始資料位元。假設判決位元值為d_hat,解調過程的結果為解調位元d。常見的解調公式為:
if d_hat == [1, 1]
d = [0, 0]
elseif d_hat == [0, 1]
d = [0, 1]
elseif d_hat == [0, 0]
d = [1, 0]
else
d = [1, 1]
end
2.4 軟解調
軟解調是QPSK軟解調的關鍵步驟,它利用判決符號和相位估計的結果進行機率估計,以提高解調的準確性。假設判決符號為d_hat,軟解調過程的結果為軟解調符號d。常見的軟解調公式為: d = d_hat / P(d_hat|r[n])
其中P(d_hat|r[n])表示在接收到訊號r[n]的條件下,判決符號d_hat為d_hat的機率。該機率可以透過估計訊號點的機率分佈函式或使用最大似然估計等方法得到。軟解調過程需要進行機率估計,以提高解調的準確性。這涉及到估計訊號點的機率分佈函式或使用其他機率估計方法,其中噪聲的影響需要被適當地考慮。
3.Verilog核心程式
//QPSK調製 TQPSK TQPSKU( .i_clk (i_clk), .i_rst (i_rst), .i_Ibits(i_Ibits), .i_Qbits(i_Qbits), .o_Ifir (o_Ifir), .o_Qfir (o_Qfir), .o_cos (), .o_sin (), .o_modc (), .o_mods (), .o_mod (o_mod_T) ); //加入通道 awgns awgns_u( .i_clk(i_clk), .i_rst(i_rst), .i_SNR(i_SNR), //這個地方可以設定訊雜比,數值大小從-10~50, .i_din(o_mod_T[30:15]+o_mod_T[31:16]), .o_noise(), .o_dout(o_Nmod_T) ); //QPSK解調 wire signed[15:0]o_b1; wire signed[15:0]o_b2; RQPSK RQPSKU( .i_clk (i_clk), .i_clkSYM(i_clkSYM), .i_rst (i_rst), .i_med (o_Nmod_T), .o_cos (), .o_sin (), .o_modc (o_modc), .o_mods (o_mods), .o_Ifir (o_rIfir), .o_Qfir (o_rQfir), .o_b1(o_b1), .o_b2(o_b2) ); //計算誤位元速率 //I,Q兩路分別計算,最後統計平均值作為誤位元速率 //error calculate wire [31:0]w_error_num1; wire [31:0]w_error_num2; Error_Chech Error_Chech_u1( .i_clk(i_clk), .i_rst(i_rst), .i_trans({~i_Ibits,1'b1}), .i_rec({~o_b1[15],1'b1}), .o_error_num(w_error_num1), .o_total_num() ); //error calculate Error_Chech Error_Chech_u2( .i_clk(i_clk), .i_rst(i_rst), .i_trans({~i_Qbits,1'b1}), .i_rec({o_b2[15],1'b1}), .o_error_num(w_error_num2), .o_total_num(o_total_num) ); assign o_error_num={w_error_num1[31],w_error_num1[31:1]} + {w_error_num2[31],w_error_num2[31:1]} ; endmodule 0sj_019m