NCO ip核生成正弦波并用FIR滤波器输出滤波波形
NCO ip核生成正弦波并用FIR滤波器输出滤波波形
- 一、认识ip核
- 1、数字振荡器(NCO)
- 2、FIR滤波器
- 二、quartus调用ip核
- 1、NCO产生正弦波
- 2、FIR ip核调用
- 3、乘法器 ip核调用
- 三、项目源码
- 四、modelsim仿真
- 1、启动仿真
- 2、效果查看
- 五、参考资料
一、认识ip核
实验任务:使用NCO ip核分别生成1Mhz和10Mhz正弦波,叠加两个列波作为输入数据,通过FIR滤波器处理得到输出波形,分析FIR输入输出两列波形,查看FIR滤波器效果。
1、数字振荡器(NCO)
- 英文:numerically controlled oscillator;
- 是软件无线电、直接数据频率合成器(DDS,Direct digital synthesizer)、快速傅立叶变换(FFT,Fast Fourier Transform) 等的重要组成部分;
- 同时也是决定其性能的主要因素之一,用于产生可控的正弦波或余弦波。随着芯片集成度的提高、在信号处理、数字通信领域、调制解调、变频调速、制导控制、电力电子等方面得到越来越广泛的应用。
基本原理
数控振荡器的作用是产生正交的正弦和余弦样本。传统方法是采用查表法(LUT),即事先根据各个正余弦波相位计算好相位的正余弦值,并按相位角度作为地址存储该相位的正余弦值,构成一个幅度P相位转换电路(即波形存储器)。在系统时钟的控制下,由相位累加器对输入频率字不断累加,得到以该频率字为步进的数字相位,再通过相位相加模块进行初始相位偏移,得到要输出的当前相位,将该值作为取样地址值送入幅度P相位转换电路,查表获得正余弦信号样本。
FPGA实现
频率控制字寄存器将接收到的的频率控制字送入相位累加器,相位累加器对系统时钟进行计数,每到达输入频率控制字的值即对相位进行累加,随后将累加值送入相位相加器,与相位控制字寄存器接收到的初始相位进行相加,得到当前的相位值。
有关更多的NCO认识,可参考链接:
NCO (数字振荡器)
2、FIR滤波器
- 广泛应用于数字信号处理中,主要功能就是将不感兴趣的信号滤除,留下有用信号;
- FIR滤波器是全零点结构,系统永远稳定;
- 具有线性相位的特征,在有效频率范围内所有信号相位上不失真;
- 在无线通信收发机中的DDC/DUC模块,抽取和内插都需要加入滤波器以防止信号在频谱上混叠,最典型的是采用FIR滤波器实现半带滤波器。
FIR滤波处理如下式所示,其中x(n)为输入信号,h(n)为FIR滤波系数,y(n)为经过滤波后的信号;N表示FIR滤波器的抽头数,滤波器阶数为N-1;
FIR滤波器在FPGA中的实现结构
主要由延迟单元Z-1、乘法器和累加器组成。此结构为直接型FIR滤波器结构,也称横向结构(transverse)。
二、quartus调用ip核
1、NCO产生正弦波
调用ip核
进入配置界面,修改ip名称以及保存路径
界面认识
Generation ALgorithm:
- Small ROM(消耗存储空间少,精准度低);
- Large ROM(消耗存储空间大,精准度高);
- CORDIC(不消耗存储空间,但占用大量逻辑块,精准度最低);
- Multiplier-based(使用更少的存储空间,同时使用逻辑块和DSP块)。
Outputs:
- Single Output:只产生sin wave;
- Dual Output: 产生sin wave and cos wave。
界面认识
(1)32bits 是累加器的精度。因为FPGA产生的是数字信号,故精度越高,产生的波形肉眼看上去越平滑;
(2)18bits是输出数据的位宽;
(3)Dither Level,用于提高输出信号质量,默认4即可;
(4)Clock Rate 是时钟频率,根据板子上的频率自由选择;
(5)Desired Output Frequency:理想输出信号的频率;
(6)Phase Increment Value:是后续计数器需要计数的值,在后续编写testbench时需要把这个数据在initial语句中赋值给[31:0]phi_inc_i。
频畴图
时域图
界面认识
相关信号以及位宽
将.sip文件和.qip文件添加到工程中
2、FIR ip核调用
调用IP核
进入配置界面
界面认识
界面认识
界面认识
界面认识
界面认识(保持默认)
界面认识 保持默认
3、乘法器 ip核调用
调用ip核
界面认识
界面认识
时钟与时钟使能
点击NEXT,勾选方框文件,点击Finish
ip核查看
三、项目源码
例化NCO数字振荡器以及FIR滤波器模块,并进行正弦信号叠加
fir.v
module fir(input sys_clk ,//系统时钟input sys_rst_n ,//系统复位 低电平有效output signed[11:0] sin1 ,//1Mhz正弦波output sin1_vld ,//数据输出有效output signed[11:0] sin10 ,//10Mhz正弦波output sin10_vld ,//输出数据有效output signed[12:0] add_sin ,//正弦波叠加输出output add_vld ,//叠加输出有效output signed[34:0] fir_out //滤波输出
);//信号定义reg signed[12:0] sum_sin ;//叠加结果寄存wire signed[11:0] sin1_do ;wire signed[11:0] sin10_do ;wire out_en ;wire s_val ;wire s_err ;//结果赋值assign sin1 = sin1_do;assign sin10 = sin10_do;assign add_sin = sum_sin;assign add_vld = sin1_vld & sin10_vld;//波形叠加always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)beginsum_sin <= 13'd0;endelse beginif(sin1_vld & sin10_vld)sum_sin <= sin1 + sin10;elsesum_sin <= sum_sin;endend//模块例化//1Mhzsin1 u_sin1(.clk ( sys_clk ),.reset_n ( sys_rst_n ),.clken ( 1'b1 ),.phi_inc_i ( 11'd41 ),.fsin_o ( sin1_do ),.out_valid ( sin1_vld ));//10Mhzsin10 u_sin10(.clk ( sys_clk ),.reset_n ( sys_rst_n ),.clken ( 1'b1 ),.phi_inc_i ( 11'd410 ),.fsin_o ( sin10_do ),.out_valid ( sin10_vld ));//firfir_do u_fir_do(.clk ( sys_clk ), .reset_n ( sys_rst_n ), .ast_sink_data ( add_sin ), .ast_sink_valid ( add_vld ), .ast_sink_error ( 2'b0 ), .ast_source_data ( fir_out ), .ast_source_valid ( s_val ), .ast_source_error ( s_err ));endmodule
通过FIR滤波器,进行滤波处理
fir_lb.v
module fir_lb(input sys_clk ,//系统时钟input sys_rst_n ,//系统复位 低电平有效input [12:0] fir_sin ,//输入叠加的正弦波信号input fir_vld ,//输入数据有效output reg [33:0] fir_out ,//滤波输出output reg out_vld //输出有效
);//信号定义reg [20:0] vld_r ;//对数据有效进行打拍reg [12:0] fir_data_in [22:0] ;//输入数据寄存reg [13:0] add_data [11:0] ;//加法寄存器reg [29:0] mult_data [11:0] ;//乘法寄存器reg [30:0] sum [5:0] ;//第一次求和reg [31:0] s6,s7,s8 ;//第二次求和reg [32:0] s9,s10 ;//第三次求和wire mult_en ;//乘法器使能assign mult_en = (vld_r[1] | vld_r[2] |vld_r[3]);//抽头系数定义wire [15:0]h[11:0];assign h[ 0] = 16'd623 ; assign h[ 1] = 16'd1370 ;assign h[ 2] = 16'd3469 ;assign h[ 3] = 16'd6495 ;assign h[ 4] = 16'd9481 ;assign h[ 5] = 16'd11332 ;assign h[ 6] = 16'd11332 ;assign h[ 7] = 16'd9481 ; assign h[ 8] = 16'd6495 ;assign h[ 9] = 16'd3469 ;assign h[10] = 16'd1370 ;assign h[11] = 16'd623 ;//对输入有效数据打拍always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)beginvld_r <= 6'b0;endelse beginvld_r <= {vld_r[19:0],fir_vld};endend//循环变量定义integer i,j;//输入数据 移位寄存always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)beginfor(i=0;i<23;i=i+1)beginfir_data_in[i] <= 8'd0;endendelse beginif(fir_vld)beginfir_data_in[i] <= fir_sin;for(j=1;j<23;j=j+1)beginfir_data_in[j] <= fir_data_in[j-1];//移位寄存endendendend//对称相加always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)beginfor(i=0;i<12;i=i+1)beginadd_data[i] <= 9'd0;endendelse beginadd_data[11] <= fir_data_in[11];if(vld_r[0])beginfor(j=0;j<10;j=j+1)beginadd_data[j] <= fir_data_in[j] + fir_data_in[22-j];endendendend//乘法器genvar k;generatefor(k=0;k<12;k=k+1)begin:bitmult_do u_mult_do(.clock ( sys_clk ),.clken ( 1'b1 ),.dataa ( h[k] ),.datab ( add_data[k] ),.result ( mult_data[k] ));endendgenerate//s0~s5always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)beginfor(i=0;i<6;i=i+1)beginsum[i] <= 26'd0;endendelse beginif(vld_r[16])beginfor(j=0;j<6;j=j+1)beginsum[j] <= mult_data[j*2] + mult_data[j*2+1];endendendend//s6~s8always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)begins6 <= 27'd0;s7 <= 27'd0;s8 <= 27'd0;endelse beginif(vld_r[17])begins6 <= sum[0] + sum[1];s7 <= sum[2] + sum[3];s8 <= sum[4] + sum[5];endendend//s9~s10always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)begins9 <= 26'd0;s10 <= 26'd0;endelse beginif(vld_r[18])begins9 <= s6 + s7 ;s10 <= s8;endendend//结果输出always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)beginfir_out <= 30'd0;endelse beginif(vld_r[19])beginfir_out <= s9 + s10;out_vld <= 1'b1;endelseout_vld <= 1'b0;endendendmodule
仿真文件
fir_tb.v
//时间尺度
`timescale 1ns/1nsmodule fir_tb();//激励信号
reg sys_clk ;
reg sys_rst_n ;//输出信号
wire [11:0] sin1 ;
wire sin1_vld ;
wire [11:0] sin10 ;
wire sin10_vld ;
wire [12:0] add_sin ;
wire add_vld ;
wire [34:0] fir_out ;//模块例化fir u_fir_nco(.sys_clk ( sys_clk ),.sys_rst_n ( sys_rst_n ),.sin1 ( sin1 ),.sin1_vld ( sin1_vld ),.sin10 ( sin10 ),.sin10_vld ( sin10_vld ),.add_sin ( add_sin ),.add_vld ( add_vld ),.fir_out ( fir_out ));//产生时钟parameter CLK_PRE = 20;//时钟周期always #(CLK_PRE/2) sys_clk = ~sys_clk;integer i;//循环变量//产生激励initial beginsys_clk = 1'b1;sys_rst_n = 1'b0;i=0;#(CLK_PRE*10);sys_rst_n = 1'b1;forever begin#(CLK_PRE);i=i+1;if(i==4000)$stop;endend
endmodule
编译工程
四、modelsim仿真
1、启动仿真
添加仿真文件
启动仿真
添加波形
2、效果查看
显示正弦波
sin 1Mhz波形
sin 10Mhz波形(采样点太少)
叠加波形
滤除后的波形
五、参考资料
quartus FIR II IP核使用 【FIR II】
FPGA十二步产生正弦波:基于quartus CON ip核
NCO ip核生成正弦波并用FIR滤波器输出滤波波形相关推荐
- 手撕IP核系列——Xilinx FIR IP核之一
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 手撕IP核系列--Xilinx FIR IP核之一 前言 FIR 滤波器模块的设置 实现分析 前言 在Xilinx和Intel平台的F ...
- (多图) 基于并行流水线结构的可重配FIR滤波器的FPGA实现
1 并行流水结构FIR的原理 在用FPGA或专用集成电路实现数字信号处理算法时,计算速度和芯片面积是两个相互制约的主要问题.实际应用FIR滤波器时,要获得良好的滤波效果,滤波器的阶数可能会显著增加,有 ...
- 【FPGA】: ip核——Fir滤波器
文章目录 一.简介 二. ip核的端口说明 三. ip核的生成 四. 典型示例 五.结果展示 六. 参考资料 一.简介 FIR 滤波器之内插 FIR 滤波器Interpolated FIR Filte ...
- 二相并行FIR滤波器的matlab及使用FIR IP 核的FPGA实现
二相并行FIR滤波器的matlab及modelsim仿真 二相FIR滤波器即并行FIR滤波器,以面积换取速度,可以在同样的时钟频率下,提高原始滤波器的有效吞吐量,或者降低原始滤波器的功耗. 1 并行F ...
- Verilog 串行FIR滤波器、并行FIR滤波器设计、FIR IP核实现
fpga设计 使用MATLAB设计一个2kHz采样,500Hz截止的15阶低通滤波器(h(n)长度为16),量化位数为12bit,输入信号位宽也为12bit. 根据FIR直接型结构可知,滤波器实际上就 ...
- 音频(八)——C语言生成正弦波并用 I2S 输出
文章目录 I2S 输出正弦波 PC 端 C 语言生成正弦波数组 原理 代码实现 源码 编译 运行结果 波形 固定采样率下的正弦波数组 源码实现 编译 运行结果 波形 I2S 输出 数据通路 USB 麦 ...
- 结构化设计向导与IP核生成工具——IP核生成时.xaw与.xco的区别
结构化设计向导(Architecture Wizard)和IP核生成工具(Core Generator)分别是两个独立的模块,可以单独运行,也可以在ISE集成化开发平台中作为一个整体的模块来调用.由于 ...
- FPGA数字信号处理(十五)多速率FIR滤波器
该篇是FPGA数字信号处理的第15篇,选题为多速率信号处理系统中用到的多速率FIR滤波器.本文将简单介绍多速率信号处理系统的基本概念,以及使用Quartus和Vivado的IP核设计多速率FIR滤波器 ...
- 数字信号处理——串行FIR滤波器MATLAB与FPGA实现
前言 本文介绍了设计滤波器的FPGA实现步骤,并结合杜勇老师的书籍中的串行FIR滤波器部分进行一步步实现硬件设计,对书中的架构做了简单的优化,并进行了仿真验证. FIR滤波器的FPGA实现步骤 从工程 ...
最新文章
- MyCat读写分离-笔记(四)
- 2009年全球最佳IT十大认证
- 入住两年的CSDN,在今天2020年8月27日,成为CSDN博客专家
- 深度学习之 BP 算法
- Collection和Collections有什么区别?
- Android 应用基础知识(5)
- flex布局实现叠在另一个div之上_CSS3 flex弹性伸缩布局[上]
- 2017-2018-1 20155317《信息安全系统设计基础》 实验五 通讯协议设计
- 用HTml+csss实现优惠券
- 光吹牛可不行 无人驾驶何时才能实现真正无人? | 观察
- python绘图--由逐日风场数据计算月平均风场数据并绘制二维填色图
- 拆解下3个大厂(抖音,滴滴,拼多多)的数据分析案例
- 阿里企业云邮箱怎么申请?企业云邮箱登录界面在哪?
- 极客兔兔 TensorFlow入门教程
- Kali 2022.2 安装
- 亲测用APICloud打包vue项目
- String类的用法
- 教你长高 男的没有1米8的 女的没1.65都要看啊
- RUST error: linking with `x86_64-w64-mingw32-gcc` failed: exit code: 1
- 10分钟解读《财富自由之路》