1.演算法模擬效果
本程式工程在我以前寫的《m基於FPGA的16QAM調製解調通訊系統verilog實現,包含testbench,不包含載波同步》基礎上增加了通道模組,誤位元速率統計模組,可以設定不同的SNR,模擬測試該FPGA系統的誤碼效能。
vivado模擬結果如下(完整程式碼執行後無水印):
設定SNR=8db
設定SNR=12db
設定SNR=16db
RTL結構圖:
模擬操作步驟可參考程式配套的操作影片。
2.演算法涉及理論知識概要
16QAM全稱正交幅度調製是英文Quadrature Amplitude Modulation的縮略語簡稱,意思是正交幅度調製,是一種數字調製方式。產生的方法有正交調幅法和複合相移法。16QAM是指包含16種符號的QAM調製方式。
16QAM 調製原理
16QAM 是用兩路獨立的正交 4ASK 訊號疊加而成,4ASK 是用多電平訊號去鍵控載波而得到的訊號。它是 2ASK 調製的推廣,和 2ASK 相比,這種調製的優點在於資訊傳輸速率高。
正交幅度調製是利用多進位制振幅鍵控(MASK)和正交載波調製相結合產生的。
16 進位制的正交振幅調製是一種振幅相位聯合鍵控訊號。16QAM 的產生有 2 種方法:
(1)正交調幅法,它是有 2 路正交的四電平振幅鍵控訊號疊加而成;
(2)複合相移法:它是用 2 路獨立的四相位移相鍵控訊號疊加而成。
這裡採用正交調幅法。
數字訊號是透過FPGA的輸出埠生成的。在16QAM調製中,每個符號包含4個位元,因此需要一個4位二進位制計數器來生成數字訊號。計數器的輸出被對映到星座圖上的一個點,然後透過數字到模擬轉換器(DAC)轉換為模擬訊號。串/並變換器將速率為Rb的二進位制碼元序列分為兩路,速率為Rb/2.2-4電平變換為Rb/2 的二進位制碼元序列變成速率為RS=Rb/log216 的 4 個電平訊號,4 電平訊號與正交載波相乘,完成正交調製,兩路訊號疊加後產生 16QAM訊號.在兩路速率為Rb/2 的二進位制碼元序列中,經 2-4 電平變換器輸出為 4 電平訊號,即M=16.經 4 電平正交幅度調製和疊加後,輸出 16 個訊號狀態,即 16QAM.
16QAM 解調原理
16QAM 訊號採取正交相干解調的方法解調,解調器首先對收到的 16QAM 訊號進行正交相干解調,一路與 cos ω c t 相乘,一路與 sin ω c t 相乘。然後經過低通濾波器,低通濾波器 LPF 濾除乘法器產生的高頻分量,獲得有用訊號,低通濾波器LPF 輸出經抽樣判決可恢復出電平訊號。
3.verilog核心程式
module TOPS_16QAM( input clk, input rst, input start, input signed[7:0]i_SNR, output [3:0] parallel_data, output signed[15:0]sin, output signed[15:0]cos, output signed[15:0] I_com, output signed[15:0] Q_com, output signed[15:0]I_Ncom, output signed[15:0]Q_Ncom, output signed[23:0]I_comcos2, output signed[23:0]Q_comsin2, output signed[7:0]o_Ifir, output signed[7:0]o_Qfir, output [3:0] o_sdout, output signed[31:0]o_error_num, output signed[31:0]o_total_num ); // DUT tops_16QAM_mod top( .clk(clk), .rst(rst), .start(start), .parallel_data(parallel_data), .sin(sin), .cos(cos), .I_com(), .Q_com(), .I_comcos(I_com),//基帶方式輸出,即實際通訊中的複數模式 .Q_comsin(Q_com) ); //加入通道 //實部 awgns awgns_u1( .i_clk(clk), .i_rst(~rst), .i_SNR(i_SNR), //這個地方可以設定訊雜比,數值大小從-10~50, .i_din(I_com), .o_noise(), .o_dout(I_Ncom) ); //虛部 awgns awgns_u2( .i_clk(clk), .i_rst(~rst), .i_SNR(i_SNR), //這個地方可以設定訊雜比,數值大小從-10~50, .i_din(Q_com), .o_noise(), .o_dout(Q_Ncom) ); tops_16QAM_demod top2( .clk(clk), .rst(rst), .start(start), .I_Ncom(I_Ncom), .Q_Ncom(Q_Ncom), .I_comcos2(I_comcos2), .Q_comsin2(Q_comsin2), .o_Ifir(o_Ifir), .o_Qfir(o_Qfir), .o_sdout(o_sdout) ); //4個bit同時統計誤位元速率 wire signed[31:0]o_error_num1; wire signed[31:0]o_total_num1; Error_Chech Error_Chech_u1( .i_clk(clk), .i_rst(~rst), .i_trans(parallel_data), .i_rec(o_sdout), .o_error_num(o_error_num1), .o_total_num(o_total_num1) ); assign o_total_num = o_total_num1; assign o_error_num = o_error_num1; endmodule 0sj_012m