基于FPGA的正弦波和及滤波(已通过仿真和上板)

基于FPGA的正弦波和及滤波


任务要求

现在要完成一个fpga的实验任务,要求是利用ZYNQ开发板FPGA板XILINX 7020 芯片,1.利用dds原理生成三种不同频率的正弦波,2.将生成的三种不同频率的正弦波加在一起3.能通过滤波器提取其中一种。

本文主要展示仿真,上板也没有问题,有问题可以评论区交流。其实就是FPGA实现的功能,只用到了PL端,没有用到PS端。

一、整体架构

该模块主要由以下几个部分组成:

时钟管理模块(PLL):生成系统所需的 200MHz 时钟

3 路 DDS 模块:分别生成 3M、10M 和 20M 频率的正弦波

信号叠加模块:将 3 路正弦波相加

FIR 滤波模块:对叠加后的的信号进行滤波处理

二、verilog代码功能实现

1.时钟模块

通过 PLL IP 核生成 200MHz 工作时钟:

c 复制代码
pll pll_inst (
    .clk_out1(clk_200m),   // 输出200MHz时钟
    .reset(~rst_n),         // 复位信号(高有效)
    .locked(locked),        // 锁定信号,时钟稳定后为高
    .clk_in1(clk)           // 输入时钟
);

采用 PLL 可以提供稳定的高频时钟,有利于提高 DDS 输出波形的精度

rst_nn信号将外部复位和 PLL 锁定信号结合,确保系统在时钟稳定后才开始工作

2.DDS 信号生成模块

实例化了 3 个不同频率的 DDS 模块,频率通过改变频率字的大小来实现:

c 复制代码
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2025/08/18 19:54:32
// Design Name: 
// Module Name: DDS_3M
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module DDS_3M(
    input clk,//50m Hz
    input rst_n,
    output [11:0] data
    );
parameter fre_word = 32'd64424509;     //频率控制字     fre_word = f_out * 2^N / fclk   N为累加器位宽
reg [31:0] addr_sin;

//相位累加器
always @(posedge clk or  negedge rst_n)  
begin
    if(!rst_n)
        addr_sin <= 32'b0;
    else
        addr_sin <= addr_sin + fre_word;
end

wire [11:0]addra = addr_sin[31:20];
//ROM IP核的调用
sin_rom sin_rom1 (
  .clka(clk),    // input wire clk	时钟
  .addra(addra),  // input wire [11 : 0] addra	相位累加器输入给rom的地址
  .douta(data)  // output wire [11 : 0] douta	从ROM返回的数据(3M正弦波的采样点)
);
endmodule
c 复制代码
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2025/08/18 19:54:32
// Design Name: 
// Module Name: DDS_3M
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module DDS_10M(
    input clk,//50m Hz
    input rst_n,
    output [11:0] data
    );
parameter fre_word = 32'd214748364;     //频率控制字     fre_word = f_out * 2^N / fclk   N为累加器位宽
reg [31:0] addr_sin;

//相位累加器
always @(posedge clk or  negedge rst_n)  
begin
    if(!rst_n)
        addr_sin <= 32'b0;
    else
        addr_sin <= addr_sin + fre_word;
end

wire [11:0]addra = addr_sin[31:20];
//ROM IP核的调用
sin_rom sin_rom2 (
  .clka(clk),    // input wire clk	时钟
  .addra(addra),  // input wire [11 : 0] addra	相位累加器输入给rom的地址
  .douta(data)  // output wire [11 : 0] douta	从ROM返回的数据(3M正弦波的采样点)
);
endmodule
c 复制代码
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2025/08/18 19:54:32
// Design Name: 
// Module Name: DDS_3M
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module DDS_20M(
    input clk,//50m Hz
    input rst_n,
    output [11:0] data
    );
parameter fre_word = 32'd429496729;     //频率控制字     fre_word = f_out * 2^N / fclk   N为累加器位宽
reg [31:0] addr_sin;
wire [11:0] addra;
//相位累加器
always @(posedge clk or  negedge rst_n)  
begin
    if(!rst_n)
        addr_sin <= 32'b0;
    else
        addr_sin <= addr_sin + fre_word;
end

assign addra = addr_sin[31:20];
//ROM IP核的调用
sin_rom sin_rom3 (
  .clka(clk),    // input wire clk	时钟
  .addra(addra),  // input wire [11 : 0] addra	相位累加器输入给rom的地址
  .douta(data)  // output wire [11 : 0] douta	从ROM返回的数据(3M正弦波的采样点)
);
endmodule

三个 DDS 模块均工作在 200MHz 时钟下,保证相位同步

分别输出 3M、10M 和 20M 的正弦波信号

3.信号叠加

c 复制代码
// 正弦波和
assign wave_sum1 = data_3M + data_10M + data_20M;

4.FIR滤波

输入为叠加后的 14bit 信号(wave_sum1)

输出为滤波后的信号(sin_data),位宽为 34bit(33:0

m_tvalid2信号指示输出数据有效

滤波器可以设计为低通、高通或带通类型,根据需要提取 3M、10M 或 20M 中的某一频率成分

c 复制代码
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2025/08/20 09:27:54
// Design Name: 
// Module Name: FIR
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module FIR
(
    input clk,                  
    input rst_n,
    input [13:0] Xin1,  
    output m_tvalid2,            
    output signed [33:0] Yout   
);

reg  s_tvalid;

//相位累加器
always @(posedge clk or  negedge rst_n)  
begin
    if(!rst_n)
        s_tvalid <= 1'b0;
    else
        s_tvalid <= 1'b1;
end

wire s_tready2;
wire  [39:0] m_tdata2;
fir_unsig fir_unsig_inst (
  .aclk(clk),                              // input wire aclk
  .s_axis_data_tvalid(s_tvalid),  // input wire s_axis_data_tvalid
  .s_axis_data_tready(s_tready2),  // output wire s_axis_data_tready
  .s_axis_data_tdata({{2{1'b0}},Xin1}),    // input wire [15 : 0] s_axis_data_tdata
  .m_axis_data_tvalid(m_tvalid2),  // output wire m_axis_data_tvalid
  .m_axis_data_tdata(m_tdata2)    // output wire [39 : 0] m_axis_data_tdata
);

assign Yout =  m_tdata2[33:0];
endmodule

5.顶层模块

c 复制代码
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2025/08/18 20:09:54
// Design Name: 
// Module Name: DDS
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps

module DDS(
    input clk,
    input rst_n,
    output wire [11:0] data_3M,
    output wire [11:0] data_10M,
    output wire [11:0] data_20M,
    output wire [13:0] wave_sum1,
    output wire [33:0] sin_data
);

wire clk_200m;
wire locked;
wire rst_nn;
assign rst_nn = rst_n & locked;

// 正弦波和
assign wave_sum1 = data_3M + data_10M + data_20M;


pll pll_inst (
    .clk_out1(clk_200m),   // output clk_out1
    .reset(~rst_n),         // input reset
    .locked(locked),        // output locked
    .clk_in1(clk)           // input clk_in1
);

    
DDS_3M DDS_3M_inst(
    .clk(clk_200m),
    .rst_n(rst_nn),
    .data(data_3M)
);

DDS_10M DDS_10M_inst(
    .clk(clk_200m),
    .rst_n(rst_nn),
    .data(data_10M)
);

DDS_20M DDS_20M_inst(
    .clk(clk_200m),
    .rst_n(rst_nn),
    .data(data_20M)
);
wire m_tvalid;

 FIR FIR_inst (
        .clk(clk),
        .rst_n(rst_nn),
        .Xin1(wave_sum1),
        .m_tvalid2(m_tvalid),
        .Yout(sin_data)
    );
  

endmodule

6.TB仿真测试文件

c 复制代码
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2025/08/18 20:19:30
// Design Name: 
// Module Name: tb_DDS
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module tb_DDS();

// 输入信号
reg clk;
reg rst_n;

// 输出信号
wire [11:0] data_3M;
wire [11:0] data_10M;
wire [11:0] data_20M;
wire [13:0] wave_sum;
wire [33:0] sin_data;
// 实例化 DDS 模块
DDS uut (
    .clk(clk),
    .rst_n(rst_n),
    .data_3M(data_3M),
    .data_10M(data_10M),
    .data_20M(data_20M),
    .wave_sum1(wave_sum),
    .sin_data(sin_data)
);

// 50 MHz 时钟生成 (周期 = 20 ns)
always #10 clk = ~clk;  // 每10ns翻转一次,产生50MHz时钟

// 初始化信号
initial begin
    // 初始化输入
    clk = 0;
    rst_n = 0;  // 初始复位状态
    
    
    // 释放复位
    #20 rst_n = 1;  // 20ns后释放复位
    

end



endmodule

总结

具体的ip核调用就搜一下配置就行,都是最简单的那种,基本都是默认。注意就是fir的话选择有符号系数,但是波形选的无符号输入,我忘了为啥这样了,反正两个都是有符号或者无符号的话,一直不对,也没管原因。

相关推荐
坏孩子的诺亚方舟15 天前
FPGA系统架构设计实践15_高云Arora V系列时钟体系
fpga开发·系统架构
FPGA小徐15 天前
入门 CNN 结构全解析|从流程图理论到 FPGA Verilog 硬件实现(含习题带讲解)
fpga开发
FPGA小徐15 天前
FPGA 数字信号处理:并行 FIR 与串行滤波器设计原理、对比与完整 Verilog 实现
fpga开发
Saniffer_SH16 天前
【高清视频】Gen6 服务器还没到,Gen6 SSD 怎么测?Emily 现场演示三种测试环境
人工智能·驱动开发·测试工具·缓存·fpga开发·计算机外设·压力测试
zlinear数据采集卡16 天前
双核架构深度解析:ARM+FPGA如何让数据采集卡实现500Ksps高性能?
arm开发·fpga开发·架构
9527华安16 天前
FPGA实现GTH Transceivers Wizard传输2路视频,基于aurora 8b10b编解码架构,提供4套工程源码和技术支持
fpga开发·gth·aurora 8b10b·transceivers
FPGA小徐17 天前
FPGA 数字信号处理(二):并行 FIR 滤波器的 Verilog 全流程设计与实现
fpga开发
国科安芯17 天前
基于AS32S601ZIT2型抗辐照MCU的商业航天卫星姿态确定与控制系统研究
单片机·嵌入式硬件·安全·fpga开发·架构·risc-v
ALINX技术博客17 天前
【黑金云课堂】FPGA技术教程FPGA基础:I2C 总线通信技术
fpga开发·i2c
Hello-FPGA17 天前
Xilinx KU040 FPGA Camera Link 图像采集
c++·fpga开发