整理于2023-10-08

0.0 前言:

前面介绍了使用matlab中的Filter Designer工具箱进行CIC抽取滤波器设计的仿真过程与结果。下面在前面的基础上针对现有的【正点原子ZYNQ】平台,进行CIC实际设计实验测试。

0.1 平台简介

所使用的演示平台为【正点原子】的领航者ZYNQ开发板以及高速adda模块

1. 实验设计

adc以25MSPS采集一混频(比如:1.25MHz+62.5kHz)信号,经cic抽取滤波后,数据速率降至500kHz,之后由dac输出,通过示波器观察滤波前后波形。

2. matlab 中仿真

步骤:

  1. 生成待滤波的混频信号信号
  2. 生成相应的CIC抽取滤波器(见:CIC滤波器设计仿真)
  3. 进行滤波
  4. 做图对比
%% 生成信号
Fs = 25e6;
Ts = 1/Fs;
Ts2 = 50/Fs;
T = 1e-2;
N = T*Fs;
N2 = T * (Fs/50);
n = (0:N-1)';
n2 = (0:N2-1)';
t = Ts * n;
t2 = Ts2 * n2;
f = Fs/N*n;
R = 50; f1 = 1.25e6;
f2 = 50e3;
f3 = 125e3; s1 = sin(2*pi*f1*t);
s2 = sin(2*pi*f2*t);
s3 = s1 + s2;
% 计算混叠频率
Aliasingf = (1 - (f1/(Fs/R/2) - floor(f1/(Fs/2/50))))*(Fs/R/2) % 使用cic filtersigner 进行50倍抽取滤波
y3 = H_CIC50(s3); % 信号s3 50倍降采样后得到信号y
y3 = double(y3)/(50^3); % 增益调整,此处未进行补偿滤波器设计

仿真计算结果:

上面两幅图为生成的高采样率混频信号以及其频谱;下面两幅图为滤波后信号及其频谱。可以观察到,经过cic抽取滤波器后,高采样率混频信号得到了显著的降采样和滤波效果,且降采样符合预期;但是波形或者说频谱分布,与预期相差较大,怀疑原因是滤波过程有相位延迟造成的数据点移位而引入的,需要进一步确认。

3. vivado 中仿真

版本:vivado2019.1

3.1 vivado 中 CIC ip核调用

参考来源

FPGA数字信号处理(十九)Vivado CIC IP核实现-CSDN博客

xilinx 官方手册:

DS845_cic_compiler

PG140-cic-compiler

IP Catalog 中搜索CIC,打开CIC Compiler,配置cic ip核相关参数。

下图为实现50倍降采样配置。

Filter Options

  1. Filter Specification
  • 滤波器类型 - 抽取 Filter Type : Decimation
  • 滤波器级数 - 3 Number Of Stages : 3
  • 滤波器延迟因子 - 1 Differential Delay : 1
  • 通道数 - 1 Number Of Channels : 1
  1. Sample Rate Change Specification
  • 选择固定采样率倍数,设置为 50

另外,还需注意数据位宽设置,根据所需数据特性设置,最终设计结果可以在 Summary 中查看。

左侧可以选择到频响窗口,观察频响特性

生成CIC ip核后,在主程序中例化调用

 cic_compiler_0 u_cic_compiler_0 (
.aclk(sys_clk), // input wire aclk
.s_axis_data_tdata(ad_data), // input wire [7 : 0] s_axis_data_tdata
.s_axis_data_tvalid(s_axis_data_tvalid), // input wire s_axis_data_tvalid
.s_axis_data_tready(), // output wire s_axis_data_tready
.m_axis_data_tdata(cic_out_data), // output wire [31 : 0] m_axis_data_tdata
.m_axis_data_tvalid(m_axis_data_tvalid) // output wire m_axis_data_tvalid
);

3.2 程序设计

本次实验例程主要参考【正点原子】教程中关于高速adda部分的例程。

程序设计顶层原理图:

3.3 仿真结果

编写testbench文件,调用由matlab生成的波形文件作为仿真输入,观察滤波输出。

3.3.1 matlab生成波形文件

参考来源

verilog--使用FIR滤波器IP对数据降采样 - 知乎 (zhihu.com)

基本步骤简述:

  1. 生成波形(如上所述)
  2. 按要求位宽做量化处理
  3. 按16进制写入文件保存

参考程序:

sig2 = s2;						% 输入信号
sig2=sig2/max(abs(sig2)); % 归一化处理
sig2=round(sig2*(2^(N-1)-1)); % N比特量化 此处 N = 8
fid=fopen('fitFliterTestData2.txt','w'); % 写入文件保存
data2_i = real(sig2); % 按照指数法生成信号时,提取实部信号
data2_q = imag(sig2); % 按照指数法生成信号时,提取虚部信号
for n=1:length(sig2) % 进行补码替换操作
if data2_i(n) <0
data2_i(n) = 2^N + data2_i(n);
end
if data2_q(n) <0
data2_q(n) = 2^N + data2_q(n);
end
end
fprintf(fid,'%x \n',data2_i); % 按照16进制保存文件
fclose(fid);

3.3.2 vivado 中仿真调用外部数据文件

参考内容

vivado仿真 文件读取和写入-小李干净又卫生的博客-CSDN博客

VIVADO仿真读写文件方式_vivado readmemh-CSDN博客

读取文件

$readmemb$readmemh 用来从文件中读取数据到存储器中。其中 readmemb 要求每个数字是二进制数,readmemh 要求每个数字必须是十六进制数字。数字不能包含位宽说明,数字中可以有不定值x或X,高阻值z或Z,和下划线(_),和Verilog语法中的用法是一样的。

一共有下边6种用法:

(1)$readmemb("<数据文件名>",<存储器名>);

(2)$readmemb("<数据文件名>",<存储器名>,<起始地址>);

(3)$readmemb("<数据文件名>",<存储器名>,<起始地址>,<终止地址>);

(4)$readmemh("<数据文件名>",<存储器名>);

(5)$readmemh("<数据文件名>",<存储器名>,<起始地址>);

(6)$readmemh("<数据文件名>",<存储器名>,<起始地址>,<终止地址>);

写入文件

写入文件的操作与C语言类似,首先打开文件,写入数据之后关闭文件。

outputfile = $fopen("file2.txt","w"); 打开文件

$fwrite(outputfile,"%b\n",memory); 写入数据

$fclose(outputfile); 关闭文件

注意:

在写入数据的时候,写入的数据不能是一个数组,必须是单个的数字,因此想写入数组的时候必须要循环单个写入数据,写入数据的数据格式可以是2进制10进制16进制,方式与C语言类似,%控制写入的类型。

代码参考:

//** 数据来源:MATLAB
//** 函数:$readmemh 【以读取16进制形式读取TXT文件】 localparam DATA_NUM = 25000; // 数据量, 也就是txt文件的行数, 如果此参数大于数据行数, 读取到的内容为不定态
reg [7:0] memory[0:DATA_NUM-1] ;//申请250000个8位的存储单元
reg [4:0] n; initial
begin
$readmemh("../../../../fitFliterTestData3.txt",memory); //fitFliterTestData2.txt中的数字到memory
for(n=0;n<=15;n=n+1) //把15个存储单元的数字打印到 Tcl Console
$display("%h",memory[n]); // outputfile = $fopen("file2.txt","w");
// for(n=0;n<=7;n=n+1)
// $fwrite(outputfile,"%b\n",filter_out[n]);
// $fclose(outputfile);
end
//<<-- 导入数据 --------------------------------------------------- //>>-- 传递数据至输入 控制仿真结束 ---------------------
//** 传递数据
//** 数据传递结束 10 个时钟周期后 停止仿真
reg[$clog2(DATA_NUM)-1:0] i=0;
initial
begin ad_data = 8'd0;
#(clk_period * 10)
for (i = 0; i < DATA_NUM; i=i+1) begin ad_data = memory[i][7:0];
#(clk_period*2);
end #(clk_period * 10) $stop;
end
//<<-- 传递数据至 fir_filter 输入 控制仿真结束 -------------------

仿真结果

图中 sys_clk 为系统时钟,50MHz;sys_rst_n 为系统复位信号;ad_data 为输入信号; da_data 为输出信号。可以看出,经过混频信号经过CIC抽取滤波器后,实现了滤波和降采样。

3.4 下载验证

程序编写完成,经vivado编译综合布局布线,生成比特流文件,连接开发板下载,实验验证。本程序中还例化有一个ila,观察采集信号与滤波后信号。

ila探针结果-00:此结果存在有bug,经CIC滤波器输出数据为补码,但是所使用的dac码值使用原码,需要做一下转换

assign da_din = (cic_to_da[7] == 1'b0) ? (cic_to_da + 8'b0111_1111) : (cic_to_da - 8'b0111_1111) ;

修正后的ila结果,可以看出数据正常,并且符合预期。

示波器观察对比:黄色为输入信号,绿色为输出信号。可以看出,此程序实现了滤波和降采样操作。

4. 问题

  1. 如同在matlab仿真小节中看到的结果一样,经过CIC抽取滤波器后的数据出现了预期之外的谐波峰,后面需要讨论;

  1. 在进行单频信号做输入时,低频(低于50kHz)信号严重失真;高频(接近截至频率fc=250kHz)信号幅度衰减严重

  1. 叠加有高频信号时,上述现象会消失,尤其是低频段的现象

上述两种原因怀疑是因为数据长度选择不恰当和滤波器带宽内增益变化大引起,后面需要讨论验证。

CIC滤波器仿真与实验过程及结果记录的更多相关文章

  1. CIC滤波器

    CIC滤波器是滑动平均滤波器的非常高效的迭代实现,只需要一个减法和一个加法,而滑动平均需要N-1个加法. cic滤波器相当于一个梳状滤波器y(n)=x(n)-x(n-D),H(z)=1-z-D,和一个 ...

  2. Audrion小车实验过程

    Audrion小车实验过程 一.实验过程 拷贝光盘文件,安装驱动及Arduino软件,观看了教学视频,明白了软件操作界面的各类按钮的含义,进行了事例的上传实验. 接下来就进行了小车的安装工作,这部分不 ...

  3. Kettle 实现mysql数据库不同表之间数据同步——实验过程

    下面是试验的主要步骤: 在上一篇文章中LZ已经介绍了,实验的环境和实验目的. 在本篇文章中主要介绍侧重于对Kettle ETL的相应使用方法, 在这里LZ需要说明一下,LZ成为了避免涉及索引和表连接等 ...

  4. VS项目属性配置实验过程

    (原创,转载注明出处:http://www.cnblogs.com/binxindoudou/p/4017975.html ) 一.实验背景 cocos2d-x已经发展的相对完善了,从项目的创建.编译 ...

  5. S3C6410裸奔之旅——RVDS2.2编译、仿真、调试过程 LED流水灯---转的

    S3C6410裸奔之旅——RVDS2.2编译.仿真.调试过程 LED流水灯 (2012-10-13 23:56:30) 转载▼ 标签: s3c6410裸奔 ok6410 rvds2.2 rvds2.2 ...

  6. Mysql: pt-table-checksum 和 pt-table-sync 检查主从一致性,实验过程

    一.安装 percona 包 1.安装仓库的包 https://www.percona.com/doc/percona-repo-config/yum-repo.html sudo yum insta ...

  7. linux中LVM介绍及实验过程

    LVM LVM这个词不仅一次出现过,在安装Centos时,磁盘分区时,默认分区就是使用LVM方式分区:再一个就是在OpenStack部署时候用到LVM作为后端存储.对LVM的理解还是不太清晰,查询资料 ...

  8. 搭建一套简单的web服务器,记录实验过程

    搭建web服务器 一.实验内容: 实验要求: 1.完成一个简单的web服务器,web服务器从mysql里读取数据进行返回 2.Mysql需要有一个单独的数据盘,每个mysql虚拟机的磁盘挂载方式需要都 ...

  9. lab_1 清华大学ucore bootload启动ucore os(预备基础知识+实验过程)

    实验1 :bootload启动ucore os 1.0实验内容: lab1中包含一个bootloader和一个OS.这个bootloader可以切换到X86保护模式,能够读磁盘并加载ELF执行文件格式 ...

  10. Vertica集群扩容实验过程记录

    需求: 将3个节点的Vertica集群扩容,额外增加3个节点,即扩展到6个节点的Vertica集群. 实验环境: RHEL 6.5 + Vertica 7.2.2-2 步骤: 1.三节点Vertica ...

随机推荐

  1. 云上使用 Stable Diffusion ,模型数据如何共享和存储

    随着人工智能技术的爆发,内容生成式人工智能(AIGC)成为了当下热门领域.除了 ChatGPT 之外,文本生成图像技术更令人惊艳. Stable Diffusion,是一款开源的深度学习模型.与 Mi ...

  2. Python潮流周刊#8:Python 3.13 计划将解释器提速 50%!

    你好,我是猫哥.这里每周分享优质的 Python 及通用技术内容,部分为英文,已在小标题注明.(标题取自其中一则分享,不代表全部内容都是该主题,特此声明.) 首发于我的博客:https://pytho ...

  3. 一文了解Go语言的I/O接口设计

    1. 引言 I/O 操作在编程中扮演着至关重要的角色.它涉及程序与外部世界之间的数据交换,允许程序从外部,如键盘.文件.网络等地方读取数据,也能够将外界输入的数据重新写入到目标位置中.使得程序能够与外 ...

  4. Github的一个彩蛋

    点击新建仓库 项目名称为自己的昵称 下方提示意思说: 你发现了一个秘密 这是一个特别的仓库 你可以为你的首页增加README.md 就像给项目介绍一样,这是你的自我介绍 点击编辑,里面会与建议模板 以 ...

  5. ZEGO 即构音乐场景降噪技术解析

    随着线上泛娱乐的兴起,语聊房.在线 KTV 以及直播等场景在人们的日常生活中占据越来越重要的地位,用户对于音质的要求也越来越高,因此超越传统语音降噪算法的 AI 降噪算法应运而生,所以目前各大 RTC ...

  6. Java扩展Nginx之六:两大filter

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<Java扩展Nginx> ...

  7. CocosCreator基础

    跳转到底部 目录 CocosCreator项目结构: 资源文件夹(assets) 资源库(library) 本地设置(local) 项目设置(settings) project.json 构建目标(b ...

  8. vue基本操作[2] 续更----让世界感知你的存在

    Vue文件解析 什么是<template/>标签 template是html5新元素,主要用于保存客户端中的内容,表现为浏览器解析该内容但不渲染出来,可以将一个模板视为正在被存储以供随后在 ...

  9. AMH安装Nextcloud出现Access denied

    AMH部署了LAMP或者LNMP,然后常规安装Nextcloud,安装完成后跳转到首页就出现Access denied.Nextcloud的文件夹权限已经修改,可读写.http://127.0.0.1 ...

  10. Postgresql: 常用配置

    允许远程链接postgresql 要允许 PostgreSQL 数据库允许远程连接,需要进行以下配置步骤: 打开 PostgreSQL 的主配置文件 postgresql.conf.通常,该文件位于以 ...