FPGA數字訊號處理(22)FSK調製技術

FPGADesigner發表於2018-07-23

本系列的10~13篇介紹了數字通訊中ASK調製解調技術的實現。本文將介紹數字通訊系統中FSK調製技術的FPGA實現,後面的文章將介紹FSK解調。


FSK調製

FSK是利用載波的頻率表示基帶資訊,比如在2FSK系統中,採用單頻訊號f1表示資訊0、單頻訊號f2表示資訊1。根據碼元轉換時載波的相位是否連續,分為非連續相位FSK連續相位FSK,如下圖所示:
這裡寫圖片描述
第三幅圖為連續相位FSK調製,也稱作CPFSK,可視作振盪頻率隨基帶訊號線性變化;第四幅圖為非連續相位FSK,在碼元轉換時有一個相位的跳變,可視作兩個ASK調製訊號的疊加。

FSK的一個重要引數是頻移指數h=(f2-f1)*T,T為碼元週期。該引數影響著兩個單頻訊號之間的相關係數ρ。ρ越小,越容易將兩個訊號區分開,即解調系統的解調效能越好。h的幾個特殊取值如下:

  • 當h=0.715時,ρ可以取到最小值-2π/3;
  • 當h=kπ(k≥1)時,ρ為0,即兩訊號正交;
  • 當h=N(整數)時,FSK總是會體現出連續相位特性。

調製訊號的頻譜與相位變化息息相關,如果存在相位突變,訊號頻譜寬度會擴充套件(產生旁瓣)。CPFSK是一種恆包絡調製技術,在碼元速率和h相同時,CPFSK比非連續相位的FSK主瓣寬度更窄,且旁瓣分量更小,通過限帶濾波後訊號包絡起伏小,適合應用於非線性通道


MATLAB設計

MATLAB中可以按照FSK原理完成FSK調製,但是隻能產生非連續相位的FSK調製訊號(除非h=1)。如果想要產生連續相位的FSK調製訊號,必須使用MATLAB提供的fskmod函式,示例程式碼如下:

M = 4;        % Modulation order
freqsep = 8;  % Frequency separation (Hz)
nsamp = 8;    % Number of samples per symbol
Fs = 32;      % Sample rate (Hz)

% Generate random M-ary symbols.
x = randi([0 M-1],1000,1);
% Apply FSK modulation.
y = fskmod(x,M,freqsep,nsamp,Fs);

上面將代表0和1兩個頻率之間的間隔直接設定為8,也可以根據頻移指數h的計算公式來設定。fskmod最後還可以增加一個引數,預設值為’cont’表示連續相位;’discont’表示非連續相位。

需要注意的是,老版本的MATLAB可能會用到randint函式產生隨機序列;而2017以後的版本只能使用randi函式。


FSK的FPGA設計

在Vivado開發環境下完成2FSK(非連續相位)調製技術的設計並進行模擬,系統時鐘32Mhz,碼元速率1Mhz,載波頻率6Mhz,頻移指數h=3.5。模組介面如下:

`timescale 1ns / 1ps
//-----------------------------------------------------
//   FSK調製,非連續相位,頻率選擇法,h=3.5
//-----------------------------------------------------
module FSK_liuqi
(
    input clk,     //32MHz取樣時鐘
    input rst,  
    input din,     //碼元速率1MHz
    output [15:0] dout
);

配置兩個DDS產生兩個代表1和0的單頻訊號。f2-f1=h/T=3.5/1ns=3.5Mhz,則在6Mhz載波頻率的基礎上選擇4.25Mhz和7.75MHz。DDS Compiler IP核使用方法可參考https://blog.csdn.net/fpgadesigner/article/details/80512067。本設計將DDS的無雜散動態範圍設定為95dB,對應的位寬為16bit。例項化程式碼如下:

//-----------------------------------------------------
//   載波Fc=6MHz,h=3.5,則f1=4.25MHz、f2=7.75Mhz
//-----------------------------------------------------
wire [15:0] f1, f2;

dds_f1 dds_f1 (            //4.25MHz
  .aclk(clk),                             
  .m_axis_data_tvalid(), 
  .m_axis_data_tdata(f1)    
);
dds_f2 dds_f2 (            //7.75MHz
  .aclk(clk),                             
  .m_axis_data_tvalid(), 
  .m_axis_data_tdata(f2)    
);  

FSK調製訊號的產生有兩種方法。第一種方法將FSK視作兩路ASK訊號的合成(一路ASK有載波代表1,一路ASK無載波代表1),程式碼如下:

//-----------------------------------------------------
//   方法一:兩路ASK合成法
//-----------------------------------------------------
wire din_inv = ~din;
reg [15:0] dout_reg;

always @ (posedge clk or posedge rst)
    if (rst) dout_reg <= 0;
    else dout_reg <= din*f1 + din_inv*f2;

assign dout =  dout_reg;        

採用此方法的系統原理圖如下:
這裡寫圖片描述
可以看到一路ASK訊號為din與f1的乘法,另一路訊號為din取反後與f2的乘法,兩路加起來便得到FSK調製訊號。另一種方法直接使用多路選擇器對輸入的基帶資料進行判決輸出:

//-----------------------------------------------------
//   方法二:多路選擇器(Mux)判決
//-----------------------------------------------------
reg [15:0] dout_reg;

always @ (posedge clk or posedge rst)
    if (rst) dout_reg <= 0;
    else 
        case (din)
            1'b1 : dout_reg <= f1;
            1'b0 : dout_reg <= f2;
            default : dout_reg <= 'd0;
        endcase

assign dout =  dout_reg;

採用此方法的系統原理圖如下:
這裡寫圖片描述
RTL_MUX即為多路選擇器,明顯第二種方法更加節省資源。


CPFSK的FPGA設計

連續相位的FSK調製訊號產生可以藉助DDS的特性,DDS的實現原理就使其輸出訊號具有連續相位特性,即使頻率突然改變。配置一個DDS,Implementation->Phase Increment Programmability設定為Streaming,可以通過S_AXIS_PHASE介面動態配置DDS的輸出頻率。完整程式碼如下:

`timescale 1ns / 1ps
//-----------------------------------------------------
//   CPFSK調製,連續相位,h=3.5
//-----------------------------------------------------
module CPFSK_liuqi
(
    input clk,     //32MHz取樣時鐘
    input rst,  
    input din,     //碼元速率1MHz
    output [15:0] dout
);

//-----------------------------------------------------
//   載波Fc=6MHz,h=3.5,則f1=4.25MHz、f2=7.75Mhz
//-----------------------------------------------------
wire [14:0] phase;

dds_compiler_0 dds (
  .aclk(clk),                                
  .s_axis_phase_tvalid(1'b1), 
  .s_axis_phase_tdata({1'b0,phase}),    
  .m_axis_data_tvalid(),   
  .m_axis_data_tdata(dout)    
);

assign phase = din ? 'd4351 : 'd7935;

endmodule

DDS的頻率解析度設定為976.5625Hz,正好對應相位位寬為15Bits(Fs/2^B=32MHz/2^15=976.5625Hz)。因此f1=4.25MHz對應的頻率控制字為4351(f1/976.5625-1=4351);f2=7.75MHz對應的頻率控制字為7935(f2/976.5625-1=7935)。

程式碼中根據輸入基帶的情況設定對應的頻率控制字。可見CPFSK只需要使用一個DDS Compiler IP核即可,比FSK要節省不少資源。


模擬測試

編寫testbench,產生一個週期訊號模擬二進位制基帶資料。首先模擬非連續相位的FSK:
這裡寫圖片描述
可以明顯看到在碼元的跳變時刻FSK訊號的相位有明顯的突變。再模擬CPFSK:
這裡寫圖片描述
看到碼元跳變時刻FSK訊號的相位仍保持連續變化。注意由於DDS有一定的Latency,導致上圖FSK訊號相比基帶資料有一定的延遲。


Quartus環境下實現

Quartus中對應的IP核為NCO,在產生FSK訊號時與DDS用法基本相同;但在產生CPFSK訊號時,NCO IP核有獨特的配置方式。

NCO的輸出頻率由phi_inc_i介面控制。需要使用FSK調製功能時,在Implementation標籤下選中“Frequency Modulation Input”:
這裡寫圖片描述
IP核會多出一個freq_mod_i介面,該介面的作用時在phi_inc_i輸出頻率的基礎上進行調整。比如:頻率控制字位寬為25Bits,phi_inc_i輸出頻率6Mhz,系統時鐘32MHz,需要輸出f1=4.25Mhz,則freq_mod_i對應的控制字為(4.25Mhz-6MHz)/(32Mhz/2^25)=-1835008。

根據基帶資料改變freq_mod_i介面的控制字即可實現CPFSK訊號的產生。

相關文章