板级调试小助手(2)ZYNQ自定义IP核构建属于自己的DDS外设

一、前言

        在上期文章中讲述了小助手的系统结构和原理。在PYNQ的框架开发中,我们一般可以将PL端当做PS端的一个外设,通过读写寄存器的方式来操作外设的功能,就类似于在开发ARM和DSP中操作外设一样,不同时的是,我们可以通过FPGA定制我们自己需要的外设结构,例如本次文章需要提到的DDS外设。

二、外设功能介绍

        在开发外设之前首先要明确这个外设的功能:

        1、由于外部电流采用的是八路DA7512单通道DAC所以要实现DDS功能我们就需要再FPGA中搭建一个正弦波发生器,当然正弦波发生器有多种多样的实现方式,可以采用ROM查表的方式,也可以使用DSP实时计算。我这里就直接使用了Vivado提供的DDS IP核了(其本质也是通过ROM查表的方式),IP设置如下图1所示

图1 DDS设置

        2、DDS生成的正弦波需要可以控制其频率和初始相位功能;

        3、虽然有DDS功能但是也同样要兼容普通DA功能;

        4、一共八个通道,所以需要对八个通道的状态进行设置;

        综上,我们可以设计出DAC控制寄存器和DAC波形控制器如下图2和图3所示

图2 DAC控制寄存器
图3 DAC波形控制寄存器

三、外设搭建

        在ZYNQ中,搭建数据传输比较慢的外设时可以使用AXI_GP接口总线;AXI_GP接口总线可以视作为一种寄存器映射总线。最后将总线和逻辑功能封装成一个IP核,如下图4所示(这里就不放具体代码了,详细代码请移步到开源地址)

图4 DDS外设模块

        该模块具有一个AXI_GP接口的从机和七个DAC波形控制器数据,和一个DAC控制器数据,后续的DDS模块就利用这些寄存器数据来对DAC外设控制,DDS顶层代码如下:

//!DAC_DDS顶层,这里用来通过PS端写来的寄存器控制DAC的输出
module dac_dds_Top(input  sysClk,                  //系统时钟input  dacClk,                  //!DAC的时钟,最大为30Minput  sysRst,//DAC外设接口input  [31:0]Dac_Ch2_reg,       //!通道2数据寄存器,详细参考寄存器手册input  [31:0]Dac_Ch3_reg,       //!通道3数据寄存器,详细参考寄存器手册input  [31:0]Dac_Ch4_reg,       //!通道4数据寄存器,详细参考寄存器手册input  [31:0]Dac_Ch5_reg,       //!通道5数据寄存器,详细参考寄存器手册input  [31:0]Dac_Ch6_reg,       //!通道6数据寄存器,详细参考寄存器手册input  [31:0]Dac_Ch7_reg,       //!通道7数据寄存器,详细参考寄存器手册input  [31:0]Dac_Ch8_reg,       //!通道8数据寄存器,详细参考寄存器手册input  [31:0]Dac_Ctrl_reg,      //!DAC控制寄存器,DAC模式:0=关闭DAC;1=普通DAC输出;2=正弦波输出//DAC7512引脚output [5:0]dac_Clk,            //!DAC的时钟output [5:0]dac_Din,            //!DAC数据引脚output [5:0]dac_Syn             //!DAC同步引脚
);localparam  DAC_CHx = 6;  //6个通道//系统时钟域的寄存器和网线
wire [31:0]Dac_chx_wire[0:DAC_CHx-1];               //!输入的寄存器线网数组
reg  DDS_Run_sysClk[0:DAC_CHx-1];                   //!DDS运行-系统时钟域
reg  [15:0]DDS_Fre_sysClk[0:DAC_CHx-1];             //!DDS的频率-系统时钟域
reg  [15:0]DDS_Phase_sysClk[0:DAC_CHx-1];           //!DDS相位-系统时钟域
reg  [15:0]DAC_OutData_sysClk[0:DAC_CHx-1];         //!普通模式下DAC的输出
reg  DAC_enable_sysClk[0:DAC_CHx-1];                //!DAC使能信号-系统时钟域
//DAC时钟域的寄存器和网线
wire DDS_Run_dacClk[0:DAC_CHx-1];                   //!DDS运行-DAC时钟域
wire [15:0]DDS_Fre_dacClk[0:DAC_CHx-1];             //!DDS的频率-DAC时钟域
wire [15:0]DDS_Phase_dacClk[0:DAC_CHx-1];           //!DDS相位-DAC时钟域
wire [15:0]DDS_Phase_out_dacClk[0:DAC_CHx-1];       //!驱动DDS的相位
wire [15:0]DDS2Dac_dacClk[0:DAC_CHx-1];             //!DDS->DAC
wire [15:0]DAC_OutData_dacClk[0:DAC_CHx-1];         //!普通模式下DAC的输出-DAC时钟域
reg  [15:0]DAC_Data[0:DAC_CHx-1];                   //!DAC模块的输入数据
wire DAC_enable_dacClk[0:DAC_CHx-1];                //!DAC使能信号-DAC时钟域
genvar i;//!输入寄存器线网整理 这里的数量与 DAC_CHx 有关
assign Dac_chx_wire[0][31:0] = Dac_Ch3_reg;
assign Dac_chx_wire[1][31:0] = Dac_Ch4_reg;
assign Dac_chx_wire[2][31:0] = Dac_Ch5_reg;
assign Dac_chx_wire[3][31:0] = Dac_Ch6_reg;
assign Dac_chx_wire[4][31:0] = Dac_Ch7_reg;
assign Dac_chx_wire[5][31:0] = Dac_Ch8_reg;//! DDS运行控制和DAC使能控制
generatefor(i=0;i<DAC_CHx;i=i+1)begin:AXI_REG_RUNalways @(posedge sysClk)beginif(sysRst)beginDDS_Run_sysClk[i] <= 1'd0;DAC_enable_sysClk[i] <= 1'd0;endelse beginDDS_Run_sysClk[i] <= Dac_Ctrl_reg[(i+2)*4+:4]==4'd2 ? 1'd1 : 1'd0;            //DDS使能信号DAC_enable_sysClk[i] <= Dac_Ctrl_reg[(i+2)*4+:4]==4'd0 ? 1'd0 : 1'd1;         //DAC使能信号endendend
endgenerate//! DDS频率、相位和普通DAC数据
generatefor(i=0;i<DAC_CHx;i=i+1)begin:AXI_REG_DATAalways @(posedge sysClk)beginif(sysRst)beginDDS_Fre_sysClk[i][15:0] <= 16'd0;DDS_Phase_sysClk[i][15:0] <= 16'd0;DAC_OutData_sysClk[i][15:0] <= 16'd0;endelse beginDDS_Fre_sysClk[i][15:0] <= Dac_chx_wire[i][31:16];      //频率数据DDS_Phase_sysClk[i][15:0] <= Dac_chx_wire[i][15:0];     //相位数据DAC_OutData_sysClk[i][15:0] <= Dac_chx_wire[i][15:0];   //普通DAC数据endendend
endgenerate//!时钟域数据转换--DDS运行信号
generatefor(i=0;i<DAC_CHx;i=i+1)begin:CLOCK_DDS_RUNshift # (.WIDTH(1),.SHIFT_MUN(3))shift_inst (.sysClk(dacClk),.sysRst(sysRst),.inData(DDS_Run_sysClk[i]),.outData(DDS_Run_dacClk[i]));end
endgenerate//!时钟域数据转换--DDS频率
generatefor(i=0;i<DAC_CHx;i=i+1)begin:CLOCK_DDS_FREshift # (.WIDTH(16),.SHIFT_MUN(3))shift_inst (.sysClk(dacClk),.sysRst(sysRst),.inData(DDS_Fre_sysClk[i][15:0]),.outData(DDS_Fre_dacClk[i][15:0]));end
endgenerate//!时钟域数据转换--DDS相位
generatefor(i=0;i<DAC_CHx;i=i+1)begin:CLOCK_DDS_PHASEshift # (.WIDTH(16),.SHIFT_MUN(3))shift_inst (.sysClk(dacClk),.sysRst(sysRst),.inData(DDS_Phase_sysClk[i][15:0]),.outData(DDS_Phase_dacClk[i][15:0]));end
endgenerate//!时钟域数据转换--普通模式下的DAC输出
generatefor(i=0;i<DAC_CHx;i=i+1)begin:CLOCK_OUTDATAshift # (.WIDTH(16),.SHIFT_MUN(3))shift_inst (.sysClk(dacClk),.sysRst(sysRst),.inData(DAC_OutData_sysClk[i][15:0]),.outData(DAC_OutData_dacClk[i][15:0]));end
endgenerate//!时钟域数据转换--DAC使能信号
generatefor(i=0;i<DAC_CHx;i=i+1)begin:CLOCK_DAC_ENABLEshift # (.WIDTH(1),.SHIFT_MUN(3))shift_inst (.sysClk(dacClk),.sysRst(sysRst),.inData(DAC_enable_sysClk[i]),.outData(DAC_enable_dacClk[i]));end
endgenerate//!DDS相位生成
generatefor(i=0;i<DAC_CHx;i=i+1)begin:DdsPhaseDDS_Phase # (.CH_NUM(DAC_CHx))DDS_Phase_u0 (.sysClk(dacClk),.sysRst(sysRst),.Run(DDS_Run_dacClk[i]),.Fre(DDS_Fre_dacClk[i][15:0]),.Phase(DDS_Phase_dacClk[i][15:0]),.DDS_Phase_Data(DDS_Phase_out_dacClk[i][15:0]));end
endgenerate//!DDS输出,该模块输出到DAC
generatefor(i=0;i<DAC_CHx;i=i+1)begin:DDSdds_compiler_0 dds_compiler_u0 (.aclk(dacClk),                                // input wire aclk.s_axis_phase_tvalid(1'd1),  // input wire s_axis_phase_tvalid.s_axis_phase_tdata(DDS_Phase_out_dacClk[i][15:0]),    // input wire [15 : 0] s_axis_phase_tdata.m_axis_data_tvalid(),    // output wire m_axis_data_tvalid.m_axis_data_tdata(DDS2Dac_dacClk[i][15:0])      // output wire [15 : 0] m_axis_data_tdata);end
endgenerate//!DAC数据控制
generatefor(i=0;i<DAC_CHx;i=i+1)begin:DAC_DATAalways @(posedge dacClk)beginif(sysRst)beginDAC_Data[i][15:0] <= 16'd0;end//关闭了DACelse if(DAC_enable_dacClk[i]==0)beginDAC_Data[i][15:0] <= 16'd0;end//DDS模式else if(DDS_Run_dacClk[i])beginDAC_Data[i][15:0] <= 16'h8000 - DDS2Dac_dacClk[i][15:0];end//普通模式else beginDAC_Data[i][15:0] <= DAC_OutData_dacClk[i][15:0];endendend
endgenerate//!DAC7512驱动
generatefor(i=0;i<DAC_CHx;i=i+1)begin:DACDAC7512  DAC7512_inst (.sysClk(dacClk),.sysRst(sysRst),.Data(DAC_Data[i][15:4]),.Start(DAC_enable_dacClk[i]),.Done(),.dac_Clk(dac_Clk[i]),.dac_Din(dac_Din[i]),.dac_Syn(dac_Syn[i]));end
endgenerate
endmodule

        在代码中,DAC使用了30M的时钟,AXI总线是100M时钟,所以控制数据在这里需要做跨时钟域处理,由于是快速时钟到慢速时钟,我们这里对数据进行打拍处理,并且做多周期约束即可,约束如下所示

#创建30M的DAC时钟时钟,主时钟对该时钟做多周期约束。 3个周期
create_clock -period 33.333 -name dacClk -waveform {0.000 16.667} [get_pins design_1_i/clk_wiz_0/clk_30M]
set_multicycle_path -setup -start -from [get_clocks *fpga*] -to [get_clocks *dacClk*] 3
set_multicycle_path -hold -start -from [get_clocks *fpga*] -to [get_clocks *dacClk*] 3

 四、结论

        在使用PYNQ框架开发ZYNQ时,PL端都可以视作PS端的外设。本文章只介绍了一种使用慢速数据的外设,如果你写的外设是一个需要高速数据传输的,例如视频解码等。就可以考虑使用AXI_HP接口配合PL端的DMA来实现。

        下一个一篇文章是讲述小助手项目的OLED显示是如何在PYNQ架构上实现的。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【实战】Nginx+Keepalived高可用部署,后端Tomcat

目录 一、下载Tomcat安装包 二、安装Tomcat 三、 运行测试Tomcat是否安装成功 四、开放8080端口 五、Tomcat服务脚本 一、环境说明&#xff1a; 三、安装Keepalived 3.1、主机安装配置 实战目的是为了Nginx和后端的Tomcat都可以实现高可用&#xff0c;防止单节点故障的…

AWS-S3实现Minio分片上传、断点续传、秒传、分片下载、暂停下载

文章目录 前言一、功能展示上传功能点下载功能点效果展示 二、思路流程上传流程下载流程 三、代码示例四、疑问 前言 Amazon Simple Storage Service&#xff08;S3&#xff09;&#xff0c;简单存储服务&#xff0c;是一个公开的云存储服务。Web应用程序开发人员可以使用它存…

方便好用的C#.Net万能工具库Masuit.Tools

文章目录 简介开发环境安装使用特色功能示例代码1. 检验字符串是否是Email、手机号、URL、IP地址、身份证号等2.硬件监测(需要管理员权限&#xff0c;仅支持Windows&#xff0c;部分函数仅支持物理机模式)3.html的防XSS处理&#xff1a;4.整理Windows系统的内存&#xff1a;5.任…

IAR全面支持芯驰科技E3系列车规MCU产品E3119/E3118

中国上海&#xff0c;2024年7月11日 — 全球领先的嵌入式系统开发软件解决方案供应商IAR与全场景智能车芯引领者芯驰科技宣布进一步扩大合作&#xff0c;最新版IAR Embedded Workbench for Arm已全面支持芯驰科技的E3119/E3118车规级MCU产品。IAR与芯驰科技有着悠久的合作历史&…

docker私有仓库harbor安装

Harbor默认安装 下载harbor https://github.com/goharbor/harbor/releases/download/v2.11.0/harbor-offline-installer-v2.11.0.tgz 目前要求docker版本&#xff0c;docker 20.10.10-ce &#xff0c;和docker-compose 1.18.0 查看 docker-compose版本 docker-compose --ver…

【精品资料】模块化数据中心解决方案(33页PPT)

引言&#xff1a;模块化数据中心解决方案是一种创新的数据中心设计和部署策略&#xff0c;旨在提高数据中心的灵活性、可扩展性和效率。这种方案通过将数据中心的基础设施、计算、存储和网络资源封装到标准化的模块中&#xff0c;实现了快速部署、易于管理和高效运维的目标 方案…

Jetpack Compose学习记录(一)

目录 前言控件实时预览Modifierremember状态提升 前言 学了一段时间的Compose&#xff0c;不得不说声明式UI比原生的开发效率快很多&#xff0c;而且Compose也是Google现在主推的开发模式&#xff0c;可以动态化地更改ui&#xff0c;相比于databinding对数据和布局进行绑定。C…

51单片机4(reg52头文件介绍)

一、头文件作用 #include<reg52.h> #include"reg52.h" 1、在代码中&#xff0c;引用头文件&#xff0c;它的实际意义就是将这个头文件里面的全部内容放到引用的这个文件的位置上&#xff0c;免去我们每次编译&#xff0c;编写同类程序都要将头文件中的语句&…

部署运维之二:虚拟化

摘要&#xff1a; 在21世纪初的曙光中&#xff0c;虚拟化技术悄然萌芽&#xff0c;标志着计算领域的一次革命性飞跃。这一时期&#xff0c;通过引入虚拟化技术&#xff0c;业界实现了在单一物理服务器之上并行运行多个虚拟机的壮举&#xff0c;每个虚拟机均构筑起一个隔离而独…

JVM:SpringBoot TomcatEmbeddedWebappClassLoader

文章目录 一、介绍二、SpringBoot中TomcatEmbeddedWebappClassLoader与LaunchedURLClassLoader的关系 一、介绍 TomcatEmbeddedWebappClassLoader 是 Spring Boot 在其内嵌 Tomcat 容器中使用的一个类加载器&#xff08;ClassLoader&#xff09;。在 Spring Boot 应用中&#…

Vue中插槽的使用

插槽是什么&#xff1f; 插槽就是子组件中的提供给父组件使用的一个占位符&#xff0c;用<slot></slot> 表示&#xff0c;父组件可以在这个占位符中填充任何模板代码&#xff0c;如 HTML、组件等&#xff0c;填充的内容会替换子组件的<slot></slot>标…

AG32 的MCU与FPGA的主频可以达到568MHz吗

Customers: AG32/ AGRV2K 这个芯片主频和定时器最高速度是多少&#xff1f;用户期望 CPLD计时器功能0.1ns以下。 AGM RE: CPLD做不到 0.1ns的速率&#xff0c;这个需要10G以上的时钟。 那AGRV2K最高多少MHz呢&#xff1f; 一般200MHZ比较容易实现。 进一步说明&#xff1…

具有 0.5V 超低输入电压的 3A 升压转换器TPS61021

1 特性 输入电压范围&#xff1a;0.5V 至 4.4V 启动时的最小输入电压为 0.9V 可设置的输出电压范围&#xff1a;1.8V 到 4.0V 效率高达 91%&#xff08;VIN 2.4V、VOUT 3.3V 且 IOUT 1.5A 时&#xff09; 2.0MHz 开关频率 IOUT > 1.5A&#xff0c;VOUT 3.3V&#xff08;V…

记录一次微信小程序申诉定位权限过程

1 小程序接到通知&#xff0c;检测到违规&#xff0c;需要及时处理&#xff0c;给一周的缓冲时间&#xff0c;如果到期未处理&#xff0c;会封禁能力&#xff08;2023-11-17&#xff09; 2 到期后&#xff0c;仍未处理&#xff0c;封禁能力&#xff08;2023-11-24&#xff09; …

密钥管理的流程有哪些

密钥管理是指对密钥进行生成、分发、验证、更新、存储、备份、设置有效期以及销毁等一系列操作的行为&#xff0c;它是保障数据安全的重要机制。以下是对密钥管理的详细解析&#xff1a; 一、密钥管理的概念 密钥&#xff0c;即密匙&#xff0c;是各种加密技术的核心组成部分&a…

FPGA入门-自用

写代码&#xff0c;并将引脚对应到板子相应的引脚上 下载程序到板子上 遇到错误了&#xff0c;不按想的来的了&#xff0c;进行仿真 查看网表图查看问题所在 简化了一些步骤&#xff1a;未使用引脚的设置&#xff0c;电压设置&#xff1b; 通过画网表结构图来构成电路 时钟 …

RocketMQ源码学习笔记:Producer发送消息流程

这是本人学习的总结&#xff0c;主要学习资料如下 马士兵教育rocketMq官方文档 目录 1、Overview2、验证消息3、查找路由4、选择消息发送队列4.1、选择队列的策略4.2、源码阅读4.2.1、轮询规避4.2.2、故障延迟规避4.2.2.1、计算规避时间4.2.2.2、选择队列 4.2.3、ThreadLocal的…

土壤分析仪:解密土壤之奥秘的科技先锋

在农业生产和生态保护的道路上&#xff0c;土壤的质量与状况一直是我们关注的焦点。土壤分析仪&#xff0c;作为现代科技在农业和环保领域的杰出代表&#xff0c;以其高效、精准的分析能力&#xff0c;为我们揭示了土壤的奥秘&#xff0c;为农业生产提供了科学指导&#xff0c;…

一个spring boot项目的启动过程分析

1、web.xml 定义入口类 <context-param><param-name>contextConfigLocation</param-name><param-value>com.baosight.ApplicationBoot</param-value> </context-param> 2、主入口类: ApplicationBoot,SpringBoot项目的mian函数 SpringBo…

阿里云搭建vps服务器的过程

最近突发奇想想要搭建一个阿里云的的vps服务器&#xff0c;下面是搭建的过程&#xff1a; 首先&#xff0c;登录阿里云网站&#xff1a; 搜索&#xff0c;esc控制台&#xff1a; 点击创建实例&#xff1a; 选择地区&#xff1a; 选择实例规格&#xff1a; 选择镜像&#x…