当前位置: 首页 > news >正文

【FPGA】——DDS信号发生器设计

目录

一 、IP核的使用

(1)RAM IP核

(2)FIFO IP核

二、DDS信号发生器设计

(1)代码

(2)仿真波形


一 、IP核的使用

IP核:ASIC或FPGA中预先设计好具有某种功能的电路模块,参数可修改,目的在于提高开发效率。

QuartusII软件下IP核调用方式:Mega Wizard插件管理器(常用)、SOPC构造器、DSP构造器、Qsys设计系统例化。

(1)RAM IP核

RAM的英文全称是Random Access Memory,即随机存取存储器,它可以随时把数据写入任一指定地址的存储单元,也可以随时从任一指定地址中读出数据。其读写速度是由时钟频率决定的。RAM主要用来存放程序及程序执行过程中产生的中间数据、运算结果等。其特点适合双向交换数据。

打开Quartus软件,新建一个项目后,在界面的最右侧,可以看见一个IP Catalog的栏目,在这里有很多的IP核可以供我们选择使用

 在IP Catalog中搜索RAM

双击选择RAM:1-PORT,保存在ip文件夹下,命名为RAM_1port.v

选择数据位大小,以及数据深度

之后选择NEXT

勾选RAM_1port_inst.v和RAM_1port_bb.v文件

(2)FIFO IP核

FPGA使用的FIFO一般指的是对数据的存储具有先进先出特性的一个缓存器,常被用于数据的缓存或者高速异步数据的交互,也即所谓的跨时钟域信号传递。

FIFO的IP核调用(读写共用时钟)

选择读写使用同一个时钟,勾选下面的信号

之后选择Next

二、DDS信号发生器设计

(1)代码

DDS技术的基本原理是利用相位累加器和波形查找表来合成所需频率的波形:

  1. 相位累加器:在每个时钟周期累加频率控制字(Frequency Control Word, FCW)

  2. 相位-幅度转换:通过查找表将相位信息转换为对应的幅度值

  3. 数模转换:将数字幅度值转换为模拟信号

输出频率计算公式:fout = (FCW × fclk) / 2^N,其中N为相位累加器位数。

顶层模块DDS_top .v

module DDS_top (input CLOCK_50,input [1:0] KEY,          // KEY[0]-复位,KEY[1]-波形选择input [3:0] SW,           // SW[0]-增频,SW[1]-减频output [7:0] LEDG,        // 显示当前状态output [7:0] DAC_DATA,    // 波形数据输出output DAC_CLK,           // DAC时钟output DAC_CS,output DAC_MODE,// 用于SignalTap II监测的信号output [9:0] DEBUG_PHASE,output [7:0] DEBUG_WAVE
);wire reset_n = KEY[0];wire wave_select = KEY[1];wire [31:0] freq_word;wire [15:0] freq_display;// 频率控制模块frequency_control freq_ctrl (.clk_50MHz(CLOCK_50),.reset_n(reset_n),.key_in(SW[1:0]),.freq_word(freq_word),.freq_display(freq_display));// DDS核心模块enhanced_dds dds_core (.clk_50MHz(CLOCK_50),.reset_n(reset_n),.wave_select(wave_select),.freq_word(freq_word),.wave_out(DAC_DATA),.phase_out(DEBUG_PHASE));// DAC控制信号assign DAC_CLK = CLOCK_50;assign DAC_CS = 1'b0;assign DAC_MODE = 1'b1;// 调试信号连接assign DEBUG_WAVE = DAC_DATA;// LED显示assign LEDG = {wave_select, 3'b0, freq_display[15:12]};endmodule

debounce .v

module debounce (input clk,input button_in,output reg button_out
);reg [19:0] counter;reg button_state;always @(posedge clk) beginif (button_in != button_state) beginbutton_state <= button_in;counter <= 20'd0;endelse if (counter < 20'd1_000_000) begincounter <= counter + 1'b1;endelse beginbutton_out <= button_state;endendendmodule

enhanced_dds.v

module enhanced_dds (input clk_50MHz,          // 50MHz系统时钟input reset_n,            // 低电平复位input wave_select,        // 0-正弦波,1-方波input [31:0] freq_word,   // 频率控制字output reg [7:0] wave_out, // 波形输出output reg [9:0] phase_out // 相位输出(用于SignalTap)
);// 32位相位累加器reg [31:0] phase_accum;// 正弦波ROM(10位地址,8位数据)wire [9:0] rom_addr = phase_accum[31:22]; // 取高10位wire [7:0] sine_data;// 方波信号定义(修正位宽)wire [7:0] square_data = phase_accum[31] ? 8'hFF : 8'h00;// 相位累加always @(posedge clk_50MHz or negedge reset_n) beginif (!reset_n)phase_accum <= 32'd0;elsephase_accum <= phase_accum + freq_word;end// 正弦波ROM实例化sine_rom_1024 sine_rom (.address(rom_addr),.clock(clk_50MHz),.q(sine_data));// 波形选择always @(*) begincase (wave_select)1'b0: wave_out = sine_data;1'b1: wave_out = square_data;default: wave_out = sine_data;endcaseend// 相位输出用于SignalTap监测always @(posedge clk_50MHz) beginphase_out <= rom_addr;endendmodule

frequency_control.v

module frequency_control (input clk_50MHz,input reset_n,input [1:0] key_in,       // 按键输入[0]-增,[1]-减output reg [31:0] freq_word,output reg [15:0] freq_display // 频率显示值(Hz)
);// 频率控制参数parameter MIN_FREQ = 10;      // 10Hzparameter MAX_FREQ = 5_000_000; // 5MHzparameter STEP_1KHZ = 85899;  // 1kHz对应的FCW// 按键消抖实例化wire [1:0] key_pressed;debounce deb0(.clk(clk_50MHz), .button_in(key_in[0]), .button_out(key_pressed[0]));debounce deb1(.clk(clk_50MHz), .button_in(key_in[1]), .button_out(key_pressed[1]));// 频率控制always @(posedge clk_50MHz or negedge reset_n) beginif (!reset_n) beginfreq_word <= 32'd85899; // 默认1kHzfreq_display <= 16'd1000;endelse beginif (key_pressed[0] && freq_display < MAX_FREQ) beginfreq_word <= freq_word + STEP_1KHZ;freq_display <= freq_display + 16'd1000;endelse if (key_pressed[1] && freq_display > MIN_FREQ) beginfreq_word <= freq_word - STEP_1KHZ;freq_display <= freq_display - 16'd1000;endendendendmodule

sine_rom_1024 .v

module sine_rom_1024 (input [9:0] address,input clock,output reg [7:0] q
);reg [7:0] rom [0:1023];initial begin// 预计算的1024点正弦波表(8位有符号)rom[0] = 8'd128; rom[1] = 8'd131; rom[2] = 8'd134; rom[3] = 8'd137;rom[4] = 8'd140; rom[5] = 8'd143; rom[6] = 8'd146; rom[7] = 8'd149;rom[8] = 8'd152; rom[9] = 8'd155; rom[10] = 8'd158; rom[11] = 8'd162;rom[12] = 8'd165; rom[13] = 8'd168; rom[14] = 8'd171; rom[15] = 8'd174;// ... 填写完整的1024个点 ...rom[1020] = 8'd114; rom[1021] = 8'd117; rom[1022] = 8'd120; rom[1023] = 8'd123;endalways @(posedge clock) beginq <= rom[address];endendmodule

引脚配置

(2)仿真波形

Tools-》SignalTap ll Logic Analyzer,查看波形

 

总结

IP核的运用是一个新接触的内容,第一次使用时需要借鉴不同资料,明白其道理。

相关文章:

  • 单位门户网站被攻击后的安全防护策略
  • P12130 [蓝桥杯 2025 省 B] 移动距离
  • Python Django基于协同过滤算法的招聘信息推荐系统【附源码、文档说明】
  • 深入解析TCP Keep-Alive机制:原理、作用与最佳实践
  • SSM考研助手管理系统
  • 基于MFC 的链接库
  • vue项目打包部署到maven仓库
  • 如何针对游戏、金融行业定制CC攻击防护规则?
  • 如何配置环境变量HADOOP_HOMEM、AVEN_HOME?不配置会怎么样
  • RCEP框架下eBay日本站选品战略重构:五维解析关税红利机遇
  • java使用 ​Stream 流对自定义对象数组去重的
  • 欧拉服务器操作系统安装MySQL
  • Ollama、vLLM、LMDeploy选型指南
  • 什么是ETF跟踪误差?场内基金佣金最低是多少?
  • 批量将不同位置的多个文件复制到一个文件夹
  • Oracle查询大表的全部数据
  • JDBC 初认识、速了解
  • 谷云科技iPaaS集成平台4月发布新版本V7.4
  • 谷歌发布统一安全平台:让企业安全防护更简单
  • Spring如何解决项目中的循环依赖问题?
  • 北京顺义:做好潮白河大桥事故善后处置,举一反三排查风险
  • 中纪报刊文:新时代反腐败斗争为党赢得历史主动
  • 佩斯科夫:俄美总统会晤正在筹备中,未设定停火最后期限
  • 习近平在气候和公正转型领导人峰会上的致辞(全文)
  • 神二十瞄准明日17时17分发射
  • 匈牙利总理投票反对乌克兰加入欧盟