概述
本系列的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信号的产生。
最后
以上就是淡定水壶为你收集整理的FPGA数字信号处理(22)FSK调制技术FSK调制MATLAB设计FSK的FPGA设计CPFSK的FPGA设计仿真测试Quartus环境下实现的全部内容,希望文章能够帮你解决FPGA数字信号处理(22)FSK调制技术FSK调制MATLAB设计FSK的FPGA设计CPFSK的FPGA设计仿真测试Quartus环境下实现所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复