FPGA教程系列-Vivado中实现简单正弦波

FPGA教程系列-Vivado中实现简单正弦波

采用DDS的IP核,具体IP核设置见ip核的解析。

编写top文件:

`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:

`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

运行仿真:

image

过程很简单

工程文件链接:https://download.youkuaiyun.com/download/fantasygwh2015/92261250

在Xilinx Vivado中,对正弦波进行初始化通常是在设计数字信号处理系统或者模拟电路时,特别是在使用硬件描述语言(如Verilog或VHDL)进行FPGA或ASIC设计的时候。对于软件来说,这涉及到创建一个波形数据文件,并将其加载到硬件IP块或自定义模块的寄存器中。 以下是基本步骤: 1. **生成正弦波数据**:你可以使用数学库函数(如Matlab、Python或其他数值计算工具)生成一段特定频率和幅度的正弦波数组。例如,在Python里可以这样做: ```python import numpy as np fs = 1000000 # 设定采样率 t = np.arange(0, 1, 1/fs) # 时间轴 freq = 10 # 正弦波频率 (Hz) sin_wave = np.sin(2 * np.pi * freq * t) ``` 2. **将数据转换为适配的格式**:将生成的数据转换为二进制位流或者适合存储到硬件的结构体形式。如果是直接存储到寄存器,需要考虑其字宽和存储顺序。 3. **编写硬件描述**:在Verilog或VHDL中,创建一个初始化模块或者触发器,这个模块会在系统启动时加载预设好的正弦波数据。例如,如果你有一个连续缓冲区的IP核,可能有这样的结构: ```vhdl entity sine_generator is port( data_out : out std_logic_vector(N - 1 downto 0); reset : in std_logic; start : in std_logic ); end entity; architecture Behavioral of sine_generator is signal sine_data : unsigned(N - 1 downto 0); begin process(reset, start) variable i : integer := 0; begin if (reset = '1') then sine_data <= (others => '0'); elsif (start = '1') then for i in 0 to N - 1 loop sine_data(i) <= to_unsigned(sin_wave(i), N); end loop; end if; data_out <= sine_data; end process; end architecture; ``` 4. **配置和实施**:在Vivado IDE中,使用Synthesis工具将设计转化为硬件描述语言( HDL),然后在Place & Route阶段将数据加载寄存器映射到具体的硬件资源上。 5. **验证和下载**:最后,进行功能仿真和硬件仿真,确认正弦波是否按预期工作,然后下载到目标板上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值