FPGA数字信号处理(22)FSK调制技术

本系列的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信号的产生。

猜你喜欢

转载自blog.csdn.net/FPGADesigner/article/details/81166187