Vivdao FFT IP核调试记录

news2025/1/19 17:22:07

       最近一时兴起,看了下Vivado版本下的FFT  IP核,发现和ISE版本下的FFT IP核有一些差别,貌似还不小。做了个简单的仿真,Vivado仿真结果竟然和Matlab仿真结果对不上,废了九牛二虎之力研究datasheet、做仿真,终于使两个仿真结果对上了!着实花费了我不少脑细胞,也再一次证明了我不适合做算法(虽然总想证明一下自己可以的),还是老老实实做好我的FPGA工程师吧!至于算法的事情还是交给那些脑细胞发达的同仁们。

         最开始我也是在网上找了不少例程,自己照着做的仿真,无一例外,Vivado仿真结果和Matlab仿真结果都对不上。然后各种怀疑,各种看时序,翻看信号与系统的书本,都没找到答案。但是我真的很想知道为什么,在求知欲的催促下最后还舔着脸皮问了几个朋友,有的现在不做算法了所以没有时间和精力专门帮我看问题,有的没有做过FFT,有的做过了给我讲了一下,也许问题太简单了,他们说的太过于精简,我也听得马马虎虎,最后还是不知道原因。放了几天之后,我就做了一个最简单的8点[0 1 2 3 4 5 6 7]FFT变换,结果竟然和matlab仿真结果对上了。下面给出FFT IP核配置以及相关代码。

       一开始怀疑config接口配置完成后,会不会有个生效时间,所以还特意在代码里做了处理,后来证实根本没有影响,这个问题也在pg109的pg58页找到了答案,只要给好s_axis_data_tlast       信号就OK。

module top(
    input I_clk,
    input I_rst,
    output O_valid,
    output [23:0] O_re,
    output [23:0] O_im

);


wire [7 : 0]  s_axis_config_tdata        ;
reg           s_axis_config_tvalid       ;
wire          s_axis_config_tready       ;
wire [31 : 0] s_axis_data_tdata          ;
reg           s_axis_data_tvalid         ;
wire          s_axis_data_tready         ;
wire          s_axis_data_tlast             ;
wire [47 : 0] m_axis_data_tdata          ;
wire [7 : 0]  m_axis_data_tuser             ;
wire          m_axis_data_tvalid         ;
wire          m_axis_data_tready         ;
wire          m_axis_data_tlast             ;
wire          event_frame_started         ;
wire          event_tlast_unexpected     ;
wire          event_tlast_missing         ;
wire          event_status_channel_halt     ;
wire          event_data_in_channel_halt ;    
wire          event_data_out_channel_halt;    
assign        m_axis_data_tready = 1;

reg  [7:0]    S_cnt;
reg           s_axis_config_tvalid_d1;
reg           S_flag;
    
always @ (posedge I_clk)    
begin
    if(I_rst)
        s_axis_config_tvalid <= 1'b0;
    else if(s_axis_config_tready)
        s_axis_config_tvalid <= 1'b1;
    else 
        s_axis_config_tvalid <= 1'b0;
end

assign s_axis_config_tdata = 8'd1;


always @ (posedge I_clk)    
begin
    if(I_rst)
        s_axis_config_tvalid_d1 <= 1'b0; 
    else 
        s_axis_config_tvalid_d1 <= s_axis_config_tvalid;
end

always @ (posedge I_clk)    
begin
    if(I_rst)
        S_flag <= 1'b0;
    else if({s_axis_config_tvalid_d1,s_axis_config_tvalid} == 2'b10)
        S_flag <= 1'b1;
end


always @ (posedge I_clk)    
begin
    if(I_rst)
        s_axis_data_tvalid <= 1'b0;
    else if(s_axis_data_tready&&S_flag)
        s_axis_data_tvalid <= 1'b1;
    else 
        s_axis_data_tvalid <= 1'b0;
end

always @ (posedge I_clk)    
begin
    if(I_rst)
        S_cnt <= 'd0;
    else if(s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==7))
        S_cnt <= 'd0;
    else if(s_axis_data_tready&&s_axis_data_tvalid)
        S_cnt <= S_cnt + 1;
end

assign s_axis_data_tlast = (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==7))?1'b1:1'b0;
assign s_axis_data_tdata = (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==0))?0:
                           (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==1))?1:
                           (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==2))?2:
                           (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==3))?3:
                           (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==4))?4:
                           (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==5))?5:
                           (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==6))?6:
                           (s_axis_data_tready&&s_axis_data_tvalid&&(S_cnt==7))?7:0;
    
xfft_0 xfft_0_inst (
  .aclk                       (I_clk                        ),                                                // input wire aclk
  .aresetn                    (!I_rst                       ), 
  .s_axis_config_tdata        (s_axis_config_tdata          ), // input  wire [7 : 0] s_axis_config_tdata
  .s_axis_config_tvalid       (s_axis_config_tvalid         ), // input  wire s_axis_config_tvalid
  .s_axis_config_tready       (s_axis_config_tready         ), // output wire s_axis_config_tready
  .s_axis_data_tdata          (s_axis_data_tdata            ), // input  wire [31 : 0] s_axis_data_tdata
  .s_axis_data_tvalid         (s_axis_data_tvalid           ), // input  wire s_axis_data_tvalid
  .s_axis_data_tready         (s_axis_data_tready           ), // output wire s_axis_data_tready
  .s_axis_data_tlast          (s_axis_data_tlast            ), // input  wire s_axis_data_tlast
  .m_axis_data_tdata          (m_axis_data_tdata            ), // output wire [47 : 0] m_axis_data_tdata
  .m_axis_data_tuser          (m_axis_data_tuser            ), // output wire [7 : 0] m_axis_data_tuser
  .m_axis_data_tvalid         (m_axis_data_tvalid           ), // output wire m_axis_data_tvalid
  .m_axis_data_tready         (m_axis_data_tready           ), // input  wire m_axis_data_tready
  .m_axis_data_tlast          (m_axis_data_tlast            ), // output wire m_axis_data_tlast
  .event_frame_started        (event_frame_started          ), // output wire event_frame_started
  .event_tlast_unexpected     (event_tlast_unexpected       ), // output wire event_tlast_unexpected
  .event_tlast_missing        (event_tlast_missing          ), // output wire event_tlast_missing
  .event_status_channel_halt  (event_status_channel_halt    ), // output wire event_status_channel_halt
  .event_data_in_channel_halt (event_data_in_channel_halt   ), // output wire event_data_in_channel_halt
  .event_data_out_channel_halt(event_data_out_channel_halt  )  // output wire event_data_out_channel_halt
);
    

assign O_valid = (m_axis_data_tvalid&&m_axis_data_tready)?1'b1:1'b0;
assign O_re = m_axis_data_tdata[23:0];
assign O_im = m_axis_data_tdata[47:24];
    
endmodule

仿真结果如下所示,和matlab结果一致。

 

至此,得出如下结论:

(1)首先要确保送给IP核进行傅里叶变换的数是正确的(正整数好像没啥区别,负整数的时候需要做补码转换,如果转换错误则输入给IP核的数据区别好大)。

(2)其次控制好s_axis_data_tlast信号,在仿真过程中 

event_tlast_unexpected信号和 event_tlast_missing信号一直为低电平。 

(3)event_frame_started信号为一个时钟周期的脉冲信号,它并没有和每一帧数据的第一个数对齐,和输入数据没有任何对齐关系。           

后面我又将[0 1 2 3 4 5 6 7]这组数据换成了[0 -1 -2 -3 -4 -5 -6 -7]做了fft变换。Vivado仿真结果都和matlab仿真结果一致。具体代码如下所示。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/427885.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot JSON全局日期格式转换器

参考资料 SpringBoot日期格式转换&#xff0c;SpringBoot配置全局日期格式转换器在Spring Boot中定制Jackson ObjectMapper详解SpringBoot中jackson日期格式化问题(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS not turning off timestamps) 目录需求分析一. 前期准备1.1 …

ARM简单程序设计【嵌入式系统】

ARM简单程序设计【嵌入式系统】前言推荐ARM简单程序设计创建项目注意事项顺序结构程序两数之和分支结构程序符号函数循环结构程序已知循环次数未知循环次数两重循环冒泡排序子程序设计①寄存器传递参数方式②存储区域传递参数方式③ 堆栈传递参数方式最后前言 2023-4-6 20:26:…

一文看懂多模态大型语言模型GPT-4

文章目录前言什么是GPT-4GPT-4 VS GPT-3.5GPT-4与其他模型对比GPT-4视觉输入GPT-4局限性写在最后前言 近日&#xff0c;OpenAI发布了最新版的生成预训练模型GPT-4。据官方介绍&#xff0c;最新一代的模型是一个大模型&#xff0c;性能比CPT-3.5强悍很多&#xff0c;不仅仅是接…

泛微数字化安全管理,实现标准化、智能化管理,数据可视化分析

企业安全管理需求提升&#xff1a; 随着国家政策与技术的双重驱动&#xff0c;企业当前的安全管理需求&#xff0c;从标准化管理&#xff0c;逐步发展到智能、可视、可分析的全程数字化安全管理&#xff0c;落地风险分级管控、隐患排查治理的双重预防机制。 国家发布的《企业…

腾讯云轻量级云服务器Centos7防火墙开放8080端口

腾讯云轻量级云服务器Centos7防火墙开放8080端口 一、centos7防火墙打开端口 因为Centos7以上用firewalld代替了iptables,也就是说firewalld开通了8080端口应该就行了 1.查看8080是否已经放开 sudo firewall-cmd --permanent --zonepublic --list-ports2.查看防火墙状态 s…

电子标准院、中信银行、优云牵头!《数据中心服务能力成熟度模型》国标修订研讨会成功举办

4月11日&#xff0c;GB/T 33136 -2016《数据中心服务能力成熟度模型》国标修订第五次研讨会议在广州顺利召开。本次会议由中国电子技术标准化研究院、中信银行、广通优云牵头发起&#xff0c;广州赛宝认证中心承办&#xff0c;云下科技协办。 来自政府、金融、电信、能源、交通…

SQL Server 连接查询和子查询

提示&#xff1a; 利用单表简单查询和多表高级查询技能&#xff0c;并且根据查询要求灵活使用内连接查询、外连接查询或子查询等。同时还利用内连接查询的两种格式、三种外连接查询语法格式和子查询的语法格式。 文章目录前言1.查询所有学生的学号、姓名、选修课程号和成绩方法…

Python零基础自学

很多零基础想做程序员的同学&#xff0c;最开始接触的基本上都是 Python 作为常年霸榜的 “最好上手的编程语言” ——Python&#xff0c;深受互联网大厂的喜爱。 而很多小伙伴反应&#xff0c;在刚开始学Python时遇到不少问题&#xff1a; 比如找不到学习资源&#xff0c;不…

多态--遗失的子类析构函数(重要)

通过阅读下面的代码以及将其置于编译器上编译运行: #include<iostream> using namespace std;class Father { public:Father(const char* addr"中国") {cout << "执行Father类构造函数" << endl;int len strlen(addr) 1;this->add…

.Net Forms Resize V12.0 Crack

.Net Forms Resize V12.0 添加对 .NET 7 的支持并改进调整大小引擎。2023 年 4 月 14 日 - 10:27新版本特征 添加了对 Microsoft Visual Studio 2022 (v17.5.3) 及更高版本的支持。添加了对 Microsoft Windows Server 2019 和 2022 的支持。改进和调整引擎大小&#xff08;快约…

认识JVM

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录JVM 内存区域划分栈程序计数器堆元数据区JVM 类加载机制加载验证准备解析初始化双亲委派模型JVM 垃圾回收机制GC 实际工作过程…

Java基础之哈希表与红黑树

文章目录一、哈希表1.1 JDK1.7版本之前哈希表&#xff08;数组链表&#xff0c;头插法&#xff09;1.2 JDK1.8版本之后哈希表&#xff08;数组链表红黑树&#xff0c;尾插法&#xff09;二、红黑树2.1 使红黑树再次满足红黑规则2.1.1 使红黑树满足红黑规则方法一2.1.2 使红黑树…

JavaSE学习进阶day03_01 多态

第一章 多态 1.1 多态的形式 直接说什么是多态性太抽象了&#xff0c;我们先引入一个例子&#xff1a; 现在我定义了一个feed方法&#xff0c;在不同的类的对象调用这个方法时&#xff0c;都要改变形参&#xff0c;即每当我的对象不同时&#xff0c;都要重载该方法&#xff0…

【Java基础】day13

day13 一、Spring Bean 生命周期是怎样的&#xff1f; 详细过程分为以下几个步骤&#xff1a; ① 初始化 Bean 容器通过获取 BeanDefinition 中的信息进行实例化&#xff0c;这一步仅仅是简单的实例化&#xff0c;并没有进行依赖注入。 实例化的对象被包装在 BeanWrapper 对…

Qt音视频开发38-ffmpeg视频暂停录制的设计

一、前言 基本上各种播放器提供的录制视频接口&#xff0c;都是只有开始录制和结束录制两个&#xff0c;当然一般用的最多的也是这两个接口&#xff0c;但是实际使用过程中&#xff0c;还有一种可能需要中途暂停录制&#xff0c;暂停以后再次继续录制&#xff0c;将中间部分视…

RabbitMq架构设计原理

文章目录1、消息中间件1.1、什么是消息中间件1.2、传统的HTTP请求有什么缺点1.3、MQ的应用场景2、同步、多线程、以及MQ处理业务逻辑的区别2.1、同步发送Http 请求2.2、多线程处理业务逻辑2.3、MQ实现业务逻辑Mq和多线程之间的区别3、Mq消息中间件名词4、简单实现Mq的思路4.1、…

MySQL索引15连问,你能坚持到第几问?

目录 1.索引是什么? 2.MySQL索引有哪些类型 3.索引什么时候会失效? 4.哪些场景不适合建立索引? 5.为什么要用 B树&#xff0c;为什么不用二叉树? 6.一次B树索引树查找过程 7.什么是回表? 如何减少回表? 8.什么是覆盖索引? 9.聊聊索引的最左前缀原则 10.索引下…

Phind——一款面向开发人员的AI搜索引擎

目录前言一、Phind优点二、使用方法总结前言 Phind是一款面向开发人员的AI搜索引擎&#xff0c;它由大语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;驱动 。相比于传统的搜索引擎&#xff0c;Phind有以下优势&#xff1a;自然语言搜索、面向开发者、AI…

【数据结构】期中考试一把梭(通宵版上)

前言 红中(Hong_zhong) CSDN内容合伙人、2023年新星计划web安全方向导师、 吉林师范大学网安大一的一名普通学生、摸鱼拿过大挑校二、 华为MindSpore截至目前最年轻的优秀开发者、IK&N战队队长、 阿里云专家博主、华为网络安全云享专家、腾讯云自媒体分享计划博主、 划了…

URL 和 HandlerMapping建立映射(11)

上一篇https://blog.csdn.net/chen_yao_kerr/article/details/130194864 我们已经分析了Spring MVC的配置&#xff0c;并且说明了如何通过注解的方式去替换各种各样的xml配置文件。本篇将更深入分析&#xff1a; 取代 springmvc.xml 配置 之前我们说过&#xff0c;定义一个类…