FPGA教程系列-Vivado中实现简单正弦波
采用DDS的IP核,具体IP核设置见ip核的解析。
编写top文件:
verilog
`timescale 1ns / 1ps
module dds_top (
input i_clk,
input i_rst, // 高电平复位
output signed [15:0] o_sin,
output signed [15:0] o_cos
);
// =================================================================
// 1. DDS 配置参数
// =================================================================
// 假设 DDS Compiler 配置为:
// - 时钟频率: 100 MHz
// - 相位宽度: 32 bits
// - 输出数据: 16 bits Sine + 16 bits Cosine (Sine in MSBs)
//
// 频率控制字 (FCW) 计算公式:
// FCW = (F_out / F_clk) * 2^Phase_Width
//
// 示例:生成 1 MHz 的正弦波
// F_out = 1,000,000 Hz
// F_clk = 100,000,000 Hz
// Phase_Width = 32
// FCW = (1e6 / 100e6) * 2^32 = 0.01 * 4,294,967,296 ≈ 42,949,673
localparam [31:0] FREQUENCY_CONTROL_WORD = 32'd42949673; // 对应 1MHz
// =================================================================
// 2. DDS Compiler IP 核实例化
// =================================================================
wire [31:0] m_axis_data_tdata;
wire m_axis_data_tvalid;
dds_compiler_0 dds_compiler_u (
.aclk(i_clk),
.aresetn(~i_rst), // DDS核的复位是低电平有效,所以需要反相
// 配置接口
.s_axis_config_tvalid(1'b1), // 因为FCW是常量,所以一直有效
.s_axis_config_tdata(FREQUENCY_CONTROL_WORD), // 直接连接参数
// 波形数据输出接口
.m_axis_data_tvalid(m_axis_data_tvalid), // 连接有效信号
.m_axis_data_tdata(m_axis_data_tdata),
// 相位输出接口 (如果不需要,可以悬空或删除)
.m_axis_phase_tvalid(),
.m_axis_phase_tdata()
);
// =================================================================
// 3. 输出赋值
// =================================================================
// 注意:这里假设DDS IP配置为 [31:16]是Cosine, [15:0]是Sine。
// 请根据你的IP核实际配置修改!
assign o_cos = m_axis_data_tdata[31:16];
assign o_sin = m_axis_data_tdata[15:0];
endmodule
编写testbench:
verilog
`timescale 1ns / 1ps
module dds_top_tb;
// =================================================================
// 1. 测试平台信号声明
// =================================================================
reg i_clk;
reg i_rst;
wire signed [15:0] o_sin;
wire signed [15:0] o_cos;
// =================================================================
// 2. 被测模块实例化
// =================================================================
dds_top uut (
.i_clk (i_clk),
.i_rst (i_rst),
.o_sin (o_sin),
.o_cos (o_cos)
);
// =================================================================
// 3. 时钟生成 (100 MHz)
// =================================================================
// 周期 = 10ns (5ns高电平 + 5ns低电平)
always #5 i_clk = ~i_clk;
// =================================================================
// 4. 主测试过程
// =================================================================
initial begin
// --- 初始化 ---
$display("----------------------------------------------------");
$display("Testbench Started at time = %0t", $time);
$display("Initializing signals...");
i_clk = 1'b1; // 初始化时钟,避免不定态
i_rst = 1'b1; // 复位有效
// --- 复位阶段 ---
$display("Applying reset for 100 ns (10 clock cycles)...");
#100; // 复位保持100ns (足够长)
i_rst = 1'b0; // 释放复位
$display("Reset released at time = %0t", $time);
// --- 监控输出 ---
$display("----------------------------------------------------");
$display("Monitoring DDS output. Sin and Cos values will be printed below.");
$display("Time(ns) | Sin Value | Cos Value");
$display("----------|----------------|----------------");
// $monitor 会在其列表中任何信号发生变化时自动打印
$monitor("%9t | %14d | %14d", $time, o_sin, o_cos);
// --- 运行仿真并结束 ---
// 假设DDS输出频率为1MHz (周期1us = 1000ns)。
// 我们运行5个周期来观察完整的波形。
$display("Running simulation for 5 microseconds to observe the waveform...");
#5000; // 等待5000ns (5us)
// --- 结束仿真 ---
$display("----------------------------------------------------");
$display("Simulation Finished Successfully at time = %0t", $time);
$display("Please check the waveform viewer and console output.");
$display("----------------------------------------------------");
$finish; // 关键:结束仿真
end
endmodule
运行仿真:

过程很简单
工程文件链接:https://download.csdn.net/download/fantasygwh2015/92261250