本设计基于ALINX ZYNQ7010核心板, DAC 904和 AD 9226模块,采用 verilog 语言实现AM、ASK、FM、FSK、PSK调制 信号 的解调和对应参数的估计,同时含有部分框图和步骤解答,相信对电赛辅导和指导毕业设计有一定的帮助。本文只粘贴必要代码,不提供源文件,目的为培养大家的自我探知能力,需要源文件需私信我,同时IP核的配置我也是从各大平台自学的,就不一一赘述,本文只贴出配置参数,不含具体配置步骤,不会配置的请借鉴其他帖子经验。
输入信号分别为AM/FM/ASK/FSK/PSK,所有信号的载频均为1MHz,幅度为10Vpp。设计的具体要求如下:
(1)AM 信号,其正弦调制信号频率 F =1-5kHz。Ma为0.3-0.8,测量并显示该 AM 信号的调幅系数Ma,误差不大于0.1 ;输出解调信号Uo 无明显失真,幅度大于200mV。
(2)FM 信号,其正弦调制信号频率 F =1-5kHz,Mf为2-5,估计并显示该 FM波的调频系数Mf ,误差不大于0.3 ;输出解调信号Uo无明显失真,幅度大于200mV。
(3)ASK/FSK/PSK信号,三者均传输二进制不归零(NRZ)码,码速率 Rc 可为 6kbps、8kbps、10kbps 中的一种;要求装置能够自主识别并显示Um的键控方式,并输出解调后的波形。

二、 FPGA 的数据类型简介
在 FPGA 设计中,所有数据均以二进制形式流转。数据位宽的定义需综合考量 算法 动态范围及 接口 器件的物理限制,比如本设计用到的DAC904为14bit(16384深度),就需要开辟[13:0]的位宽,对应模块的14个数据引脚的输出,而AD9226为12bit(4096深度)则需开辟[11:0]的位宽,对应模块的12个数据引脚的输出。此外,在多模块级联传输过程中,由于不同模块对数据精度的要求不同,必须严格进行位宽匹配管理。这通常涉及截位处理以防止数据溢出,或符号位扩展以保留运算精度。合理的位宽规划与截位策略,是保障系统信噪比(SNR)与运算效率的关键。
三、 时钟 (Clocking Wizard IP核)
时钟是FPGA系统的核心。为避免亚稳态并确保数据可靠传输,设计上优先保证各模块时钟同源;对于异步时钟域,则采用FIFO进行缓存处理。针对DAC904与AD9226器件间的频率差异,本设计采取降频策略,将DAC904的工作频率调整至与AD9226一致的65MHz,从而实现全局时钟同步。由于开发板仅提供125MHz板载时钟,因此需利用分频器从中提取所需的65MHz工作时钟。
本设计的Clocking Wizard IP核具体配置参数如下:


本设计的AM/ASK解调采用包络解调的方法,具体为:

AM/ASK解调模块的源码为:
module AM_Demodulation(
input wire clk_65m,
input wire rs t_n,
input wire signed [11:0] data,
output wire [13:0] AM_ASK_data
// ================= 包络提取部分 =================
wire signed [11:0] abs12 = data[11] ? (~data + 1'b1) : data;
wire signed [15:0] abs16 = {abs12, 4'b0000};
wire signed [15:0] lpf_out16;
AM_LPF envelope_fil te r (
.clk_enable(1'b1),
.filter_in(abs16),
.filter_out(lpf_out16)
// assign env_out_16 = lpf_out16;
//================= 输出波形逻辑 =================
reg signed [13:0] AM_ASK_data_reg;
wire signed [13:0] env_for_dac = lpf_out16[15:2];
always @(posedge clk_65m or negedge rst_n) begin
if (!rst_n) begin
AM_ASK_data_reg <= 14'sd0;
AM_ASK_data_reg <= env_for_dac;
wire signed [13:0] AM_g ai n = 14'd20;
wire signed [13:0] AM_ASK_data_reg_out = AM_ASK_data_reg << 4;
assign AM_ASK_data = {~AM_ASK_data_reg_out[13], AM_ASK_data_reg_out[12:0]}-14'd3300;
//.clk(clk_65m), // input wire clk
//.probe0(data), // input wire [11:0] probe0
//.probe1(env_out_16) // input wire [15:0] probe1
整流处理其实非常简单,即取平均值然后补高位到 滤波器 的输入位宽即可。
其中,AM_LPF选用1阶低通IIR巴特沃斯滤波器,采样频率为65000kHz,截止频率为100kHz,具体参数由 matlab 的fdatool工具生成,具体配置已贴出:

注意:要设置为直接Ⅱ型转置,二阶节,点击设计滤波器,得到滤波器后点击上方编辑->转换结构->Direct-Form Ⅱ Transposed,SOS,直到滤波器结构转换完成,点击左下角设置量化参数,滤波器算法设为定点,最后点击应用,直到量化完成后再点击上方目标->生成HDL...,打开滤波器生成工具,language选verilog,在Global Set ti ngs里的Reset asserted level设为 Ac tive-low(因为本系统所有复位都是低电平有效),然后选择滤波器生成的位置,找到对应的.v文件即可

五、VIVADO ROM IP核
ROM 是只读存储器(Read-Only Memory)的简称,是一种只能读出事先所存数据的固态 半导体 存储器。其特性是一旦储存资料就无法再将之改变或删除,且资料不会因为 电源 关闭而消失。而事实上在 FPGA 中通过 IP 核生成的 ROM 或 RAM 调用的都是 FPGA 内部的 RAM 资源,掉电内容都会丢失,用 IP 核生成的 ROM 模块只是提前添加了数据文件(.coe 格式),在 FPGA 运行时通过数据文件给 ROM 模块初始化。https://blog.csdn.net/yishuihanq/article/details/130767125
在基于 DAC904 的正弦波发生架构中,数字域的离散特性决定了 模拟 输出的台阶效应。由于 DAC904 为14bit 分辨率,其数字输入码可表示 =16384个量化等级。结合其 ±5V 的基准量程(峰峰值 10V),系统的最小量化步长(LSB)计算如下:
这意味着,FPGA 每输出一个递增的数字码,模拟电压仅改变约 0.6mV。一个标准的满幅正弦波,其波峰对应 +5V(数字码 16383),波谷对应 -5V(数字码 0 或补码形式),整个周期内将包含 16384 个离散的电平采样点。
波形数据的产生我用的忘记是谁开发的软件了,如有侵权请联系,用matlab直接生成coe文件也可,需注意数据集是有符号类型还是无符号类型。 链接: https://pan.baidu.com/s/1XYoQW VR FX-wA8fMdy-slvA?pwd=1111 提取码: 1111
我们一般用Matlab提前生成需要的波形数据(一般为满幅波形,即与深度相等),存储到coe文件中,在ROM核中进行对应的配置,就可以将波形数据存放到程序之中,之后就可调用了。
该模块采用数字锁相鉴频环路结构,主要包括 数控 振荡器 、鉴相器、低通滤波器以及环路滤波器等部分。
数控振荡器模块:由ROM IP核和相位累加器构成,通过输入的频率控制字和相位控制字控制ROM IP核输出不同频率和相位的余弦参考信号。
鉴相器模块:由乘法器实现,输入信号与本地余弦信号进行相乘运算,产生鉴相器输出,该输出包括低频误差以及两倍频分量,在程序中先对乘法的结果取高位,然后送入滤波器滤去高频部分,只留下相位误差。
低通滤波器模块:依旧1阶低通IIR巴特沃斯滤波器,采样频率为65MHz,截止频率为100kHz。
环路滤波器模块:经过低通滤波后相位误差进入环路滤波器模块,产生频率控制量,此频率控制量同时用于NCO频偏调整以及作为FM/FSK解调结果输出,具体参数(C1、C2)需要根据实际情况进行调节。
module FM_demodulation(
input signed [11:0] data,
output [13:0] FM_FSK_data
// 65MHz采样率下, 1MHz = (1e6/65e6) * 2^32 ≈ 66076419
localparam [31:0] PHASE_STEP_1MHZ = 32'd66076419; // 中心 频率 1MHz
localparam [31:0] INITIAL_FREQ = PHASE_STEP_1MHZ; // 初始频率1MHz
wire [11:0] phase_addra;
wire signed [11:0] cos_out;
wire signed [23:0] pd_mult_out; // 鉴相器(乘法器)输出
wire signed [31:0] freq_control; // 环路滤波器输出(频率控制字)
wire signed [15:0] lpf_out_full; // 低通滤波器输出
wire signed [11:0] phase_error; // 截位后的相位误差
// ================= 环路滤波器模块 =================
// 接收鉴相误差,输出频率控制字控制NCO
loop_filter_FM loop_filter_inst (
.theta(phase_error), // 输入相位误差
.delta(freq_control) // 输出频率调整量 (此信号即为FM解调结果)
// ================= NCO (数控振荡器) =================
PhaseAccumulator nco (
.PhaseOffset(12'd0),
.PhaseStep(INITIAL_FREQ + $unsigned(freq_control)), // 跟踪输入信号频率
.MemAddr(phase_addra)
// 产生本地载波 (FM PLL只需要一路余弦或正弦即可完成鉴相)
rom_sin_12bit cos_rom (
.addra(phase_addra + 12'd1024), // cos相位偏移
.douta(cos_out)
// 将 ROM 输出的无符号偏移二进制码转为有符号二进制补码
本页摘要由 AI 辅助整理,经编辑审核后发布;AI 仅用于提炼与分类,原文均附来源链接。