DAC测试实验——FPGA学习笔记7

一、DAC简介

DAC全称Digital to Analog Converter,即数模转换器。它用于将主控芯片产生的数字值(0和1)转换为模拟值(电压值)。

1、DAC参数指标

2、DAC类型

        常用的DAC可大致分为权电阻网络DACT型电阻网络DACT型电阻网络DAC以及权电流型DAC

3、AD9708/3PD9708芯片

        AD9708是ADI公司(Analog DevicesInc.,亚德诺半导体技术有限公司)生产的TxDAC系列数模转换器,具有高性能、低功耗的特点。AD9708的数模转换位数为8位,最大转换速度为125MSPS(每秒采样百万次Million Samples per Second)。

(1)引脚说明

(2)芯片参数

(3)AD9708芯片内部结构图

 DB7-DB0为数字输入端(0-255),当REFLO连接到ACOM端以后,REFIO参考电压作为输出使用(输出内部参考电压1.2V),此时尤其关注RSET电阻,计算此时输出电流

I{_{out}}^{}=\frac{1.2V}{R{_{REST}}^{}}*32

此输出电流不可直接使用,需结合数字DB7-DB0输入端。计算此时输出电流

I{_{A}}^{}=\frac{dadata}{256}*I_{out}

I{_{B}}^{}=\frac{256-da data}{256}*I_{out}

此输出电流经过外接电阻得到需要的电压值!并不是直接输出电压值!!!

(4)AD9708时序图

(5)AD9708数字模拟转换关系

二、硬件设计

1、电源设计

        外部输入VCC_5V先经过LC滤波电路(精度要求高)得到VCC_IN,经过SGM3204得到反相电压,经过RT9193-3.3得到DVCC_3V3和AVCC_3V3。

2、DA端口设计

数字端直连FPGA(FPGA输出),FSADJ端外接电阻为2K,下面计算芯片输出电流:

I_{_{outA}}=\frac{1.2V}{2K}*32*\frac{dadata}{256}

I_{_{outB}}=\frac{1.2V}{2K}*32*\frac{256-dadata}{256}

当外部输入数据为256时,I_{_{outA}}=19.2mA       I_{_{outB}}=0mA

当外部输入数据为000时,I_{_{outA}}=0mA       I_{_{outB}}=19.2mA

 输出电流经过5阶滤波尽可能减小波动使输出变得平滑,下面计算U7B正向输入电压(欧姆定律):

\frac{V1}{100//100}+\frac{V1}{2K} = 19.2mA         V1\approx0.936V(近似去0.9或1V)

即可得知V1电压范围为0~1V,V2电压范围1~0V,下面计算减法器输出:

\frac{V1-V+}{1K}=\frac{V+}{1K} => V1 = 2V+

    \frac{V2-V-}{1K}=\frac{V-Vo}{1K} => V2 -V-= V- -Vo

V2 = 2V- -Vo

因为再虚短时V+ = V-        V2 = V1-Vo      Vo = V1-V2

因此运放输出电压为-1V~1V,继续计算后级反向放大器输出:

\frac{V1-V-}{1K}=\frac{V--Vo}{RF1}

因为再虚短时V+ = V- = 0V   Vo=-\frac{RF1*V1}{1K}因此得到输出为:

Vo=-RF1*V1     (-1V<=V1<=1V)

受限于运放芯片供电为±5V,因此最大只能放大到±5V,无法继续放大!!!

三、程序设计

1、设计目标

使用FPGA产生正弦波信号输出。

2、思维导图

3、系统框图

4、DA时序分析

注意一点rd_data会比rd_addr晚一拍!!!地址每6个周期跳变一次

5、代码设计

(1)顶层模块原理图

FPGA 顶层模块(hs_dual_da) 例化了以下三个模块: DA 数据发送模块(da_wave_send)、 ROM 波形存储模块(rom_1024x10b)和时钟模块(clk_wiz_0)
DA 数据发送模块(da_wave_send) : DA 数据发送模块输出读 ROM 地址, 将输入的 ROM 数据发送至DA 转换芯片的数据端口。

ROM 波形存储模块(rom_1024x10b): ROM 波形存储模块由 Vivado 软件自带的 Block Memory Generator IP 核实现, 其存储的波形数据可以使用波形转存储文件的上位机来生成.coe 文件。

(2)顶层代码

module hs_dual_da(
    input                 sys_clk     ,  //系统时钟
    input                 sys_rst_n   ,  //系统复位,低电平有效
    //DA接口
    output                da_clk      ,  //DA采样时钟
    output    [9:0]       da_data     ,  //DA采样数据
    output                da_clk1     ,  //DA采样时钟
    output    [9:0]       da_data1       //DA采样数据	 
);

//wire define 
wire      [9:0]    rd_addr;              //ROM地址?
wire      [9:0]    rd_data;              //ROM数据

//*****************************************************
//**                    main code
//*****************************************************

assign  da_clk1 = da_clk;
assign  da_data1 = da_data;

//时钟模块
clk_wiz_0  u_clk_wiz_0(
	.clk_in1 (sys_clk),
	.clk_out1 (clk)
);

//DA发送模块
da_wave_send u_da_wave_send(
    .clk         (clk), 
    .rst_n       (sys_rst_n),
    .rd_data     (rd_data),
    .rd_addr     (rd_addr),
    .da_clk      (da_clk),  
    .da_data     (da_data)
    );

//ROM模块 
rom_1024x10b  u_rom_1024x10b(
    .addra     (rd_addr),
    .clka      (clk),
    .douta     (rd_data)
);

endmodule

 (3)COE文件生成

使用正点原子提供的上位机波形转 COE 软件,WaveToMem_V1.2.exe,

正点原子资料下载中心icon-default.png?t=N7T8http://47.111.11.73/docs/index.html

位宽:波形数据的位宽。由于 ATK_DUAL_HS_DA 模块的 DA 芯片数据位宽为 10 位,因此这里将位宽设成 10 位。

深度:一个波形周期包含了多少个数据量。这里将深度设置成 1024。需要说明的是,在用 Block Memory Generator IP 核生成 ROM 时,配置 ROM 的宽度和深度和上位机设置的位宽和深度保持一致。

波形频率设置:对波形倍频,倍数值越大,最终生成的波形频率越快(频率太高,可能导致波形失真),这里保持默认,即设置成 1 位。

波形类型:软件支持将正弦波、方波、锯齿波和三角波的波形转换成存储波形格式的文件。

生成文件:软件支持将波形转换成 COE(Vivado 软件支持的存储格式)和 MIF(Quartus 软件支持的存储格式)格式文件,这里保持默认,即选中 COE 文件格式。

存储路径参考:::D:\FPGA\hs_dual_da\hs_dual_da.srcs\sources_1\new

(4)rom  ip核配置

配置使用Block Memory Generator   IP核,使用单端口RAM模式

配置读写深度以及位宽,勾选Always Enabled,使ROM一直处于使能状态。

添加刚刚生成的的COE文件

点击OK完成配置。

(5)DA发送数据模块

module da_wave_send(
    input                 clk         ,  //系统时钟
    input                 rst_n       ,  //系统复位,低电平有效
    
    input        [9:0]    rd_data     ,  //ROM读出的数据
    output  reg  [9:0]    rd_addr     ,  //读ROM地址
    //DA接口
    output                da_clk      ,  //DA驱动时钟
    output       [9:0]    da_data        //输出给DA的数据  
    );

//parameter
//频率调节控制
parameter  FREQ_ADJ = 10'd5;  //频率调节,FREQ_ADJ的越大,最终输出的频率越低,范围0~255

//reg define
reg    [9:0]    freq_cnt  ;  //频率调节计数器

//*****************************************************
//**                    main code
//*****************************************************

//数据rd_data是在clk的上升沿更新的,所以DA芯片在clk的下降沿锁存数据是稳定的时刻
//而DA实际上在da_clk的上升沿锁存数据,所以时钟取反,这样clk的下降沿相当于da_clk的上升沿
assign  da_clk = ~clk;        
assign  da_data = rd_data;    //将读到的ROM数据赋值给DA数据端口

//频率调节计数器
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        freq_cnt <= 10'd0;
    else if(freq_cnt == FREQ_ADJ)    
        freq_cnt <= 10'd0;
    else         
        freq_cnt <= freq_cnt + 10'd1;
end

//读ROM地址
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        rd_addr <= 10'd0;
    else begin
        if(freq_cnt == FREQ_ADJ) begin
            rd_addr <= rd_addr + 10'd1;
        end    
    end            
end

endmodule

        在代码的第 14 行定义了一个参数 FREQ_ADJ(频率调节),可以通过控制频率调节参数的大小来控制最终输出正弦波的频率大小, 频率调节参数的值越小, 正弦波频率越大。频率调节参数调节正弦波频率的方法是通过控制读 ROM 的速度实现的, 频率调节参数越小, freq_cnt 计数到频率调节参数值的时间越短,读 ROM 数据的速度越快,那么正弦波输出频率也就越高;反过来, 频率调节参数越大, freq_cnt 计数到频率调节参数值的时间越长,读 ROM 数据的速度越慢,那么正弦波输出频率也就越低。由于 freq_cnt 计数器的位宽为 10 位,计数范围是 0~1023, 所以频率调节参数 FREQ_ADJ 支持的调节范围是 0~1023, 可通过修改 freq_cnt 计数器的位宽来修改 FREQ_ADJ 支持的调节范围。

        WaveToMem 软件设置 ROM 深度为 1024, 倍频系数为 1,而输入时钟为 125Mhz,那么一个完整的正弦波周期长度为 1024*8ns = 8192ns, 当 FREQ_ADJ 的值为 0 时, 即正弦波的最快输出频率为 1s/8192ns(1s =1000000000ns) ≈ 122.0Khz。 当我们把 FREQ_ADJ 的值设置为 5 时, 一个完整的正弦波周期长度为5120ns*(5+1) =49152ns,频率约为 20.35KHz。 也可以在 WaveToMem 软件设置中增加倍频系数或者增加 DA的驱动时钟来提高正弦波输出频率。

四、下载验证

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RSA 加密算法的基础数论、基本原理与 Python 实现 (包含扩展欧几里得算法)

Title: RSA 加密算法的基础数论、基本原理与 Python 实现&#xff08;包含扩展欧几里得算法&#xff09; 文章目录 前言I. 数学原理1. 整数环2. 单位元3. 欧拉定理 II. 算法原理1. 扩展欧几里得算法2. RSA 非对称加密算法 III. 算法实现1. 源代码2. 测试结果 总结参考文献 前言…

spdlog生产者消费者模式

spdlog生产者消费者模式 spdlog提供了异步模式&#xff0c;显示的创建async_logger, 配合环形队列实现的消息队列和线程池实现了异步模式。异步logger提交日志信息和自身指针&#xff0c; 任务线程从消息队列中取出消息后执行对应的sink和flush动作。 1. 环形队列 1.1 环形队…

智慧校园综合门户有哪些特点?

智慧校园的门户系统&#xff0c;作为整个智慧校园架构的门户窗口&#xff0c;扮演着至关重要的角色。它如同一座桥梁&#xff0c;将校园内的各种信息资源、应用服务以及管理功能紧密相连&#xff0c;为师生、家长及管理人员提供了一个集中访问的便捷通道。智慧校园门户的设计理…

RPC通信原理以及项目的技术选型

目录 1.引言 2、RPC通信原理 3.图示解析 4.再举个例子 1.引言 根据上一篇博客《单机&#xff0c;集群和分布式》的举的例子。 我们最终合理地通过对大型软件的合理划分&#xff0c;划分成不同模块&#xff0c;按需求&#xff08;硬件需求&#xff0c;高并发需求&#xff09…

Hadoop+Spark大数据技术(微课版)总复习

期末试卷组成 一、选择题(每小题2分&#xff0c;共20分) 二、判断题(每小题2分&#xff0c;共20分) 三、简答题(每小题5分&#xff0c;共20分) 四、程序分析题 (第1-5小题各6分&#xff0c;第6题10分&#xff0c;共40分) 图1 Hadoop开发环境 图2 HDFS 图3 MapReduce 图4 H…

IDEA插件推荐-CodeGeex

功能&#xff1a;这个插件可以实现快速翻译代码&#xff0c;json文件格式转换&#xff0c;代码语言类型转换。 安装方式&#xff1a;File->Settings->Plugins->MarketPlace->搜索“CodeGeex”即可 &#xff08;CodeGeex功能展示&#xff09; &#xff08;CodeGeex…

【科普】半导体制造过程的步骤、技术、流程

在这篇文章中&#xff0c;我们将学习基本的半导体制造过程。为了将晶圆转化为半导体芯片&#xff0c;它需要经历一系列复杂的制造过程&#xff0c;包括氧化、光刻、刻蚀、沉积、离子注入、金属布线、电气检测和封装等。 基本的半导体制造过程 1.晶圆&#xff08;Wafer&#xf…

算法篇-二叉树

二叉树的遍历 分为前序、中序和后续的遍历&#xff0c;思想就是利用递归。 前序遍历-中左右 代码&#xff1a; public void travelTree(TreeNode node, List<Integer> resulst) {if (node null){return;}// 中resulst.add(node.val);// 左travelTree(node.left, resul…

基于springboot websocket和okhttp实现消息中转

1、业务介绍 消息源服务的消息不能直接推给用户侧&#xff0c;用户与中间服务建立websocket连接&#xff0c;中间服务再与源服务建立websocket连接&#xff0c;源服务的消息推给中间服务&#xff0c;中间服务再将消息推送给用户。流程如下图&#xff1a; 此例中我们定义中间服…

Flink Sql Redis Connector

经常做开发的小伙伴肯定知道用flink连接redis的时候比较麻烦&#xff0c;更麻烦的是解析redis数据&#xff0c;如果rdis可以普通数据库那样用flink sql连接并且数据可以像表格那样展示出来就会非常方便。 历时多天&#xff0c;我终于把flink sql redis connector写出来了&…

关于Pytorch转换为MindSpore的一点建议

一、事先准备 必须要对Mindspore有一些了解&#xff0c;因为这个框架确实有些和其它流程不一样的地方&#xff0c;比如算子计算、训练过程中的自动微分&#xff0c;所以这两个课程要好好过一遍&#xff0c;官网介绍文档最好也要过一遍 1、零基础Mindspore&#xff1a;https://…

【MySQL统计函数count详解】

MySQL统计函数count详解 1. count()概述2. count(1)和count(*)和count(列名)的区别3. count(*)的实现方式 1. count()概述 count() 是一个聚合函数&#xff0c;返回指定匹配条件的行数。开发中常用来统计表中数据&#xff0c;全部数据&#xff0c;不为null数据&#xff0c;或…

手持弹幕LED滚动字幕屏夜店表白手灯接机微信抖音小程序开源版开发

手持弹幕LED滚动字幕屏夜店表白手灯接机微信抖音小程序开源版开发 专业版 插件版 手持弹幕小程序通常提供多种功能&#xff0c;以便用户在不同的场合如夜店、表白、接机等使用。以下是一些常见的功能列表&#xff1a; 文本输入&#xff1a; 输入要显示的文字内容&#xff0c;…

独角兽品牌獭崎酱酒:高性价比的酱香之选

在酱香型白酒领域中&#xff0c;獭崎酱酒以其独特的品牌定位和高性价比迅速崛起&#xff0c;成为市场上备受关注的独角兽品牌。作为贵州茅台镇的一款新秀酱香酒&#xff0c;獭崎酱酒不仅传承了百年酿造工艺&#xff0c;还以创新的商业模式和亲民的价格赢得了广大消费者的青睐。…

【C++算法】——高精度(加,减,乘,除)

前言 高精度算法就是为了去解决一些比较大的数&#xff0c;这些数大到long long都存不下。&#xff0c;这里的主要思想就是用字符串来存。 下面的内容有很多用到c的容器&#xff0c;不明白的可以先去学习stl。 一 高精度加法 首先第一步就是去模拟我们自己写的加法&#xff…

活用变量,让Postman的使用飞起来

在 Postman 中使用变量是一种非常强大的功能&#xff0c;它可以极大地增强 API 测试和开发的灵活性和效率。 Postman变量的类型 变量在 Postman 中可以在多个层次设置和使用&#xff0c;包括 全局变量环境变量集合变量局部变量&#xff08;如在脚本中暂时创建的变量&#xf…

表驱动法 -优化逻辑分支

表驱动法 -优化逻辑分支 定义 表驱动法&#xff08;Table-Driven Approach&#xff09;是一种编程模式&#xff0c;可以将输入变量作为直接或间接索引在表里查找所需的结果或处理函数&#xff0c;而不使用逻辑语句&#xff08;if-else 和 switch-case&#xff09;。索引表可以…

安卓中使用ttf字体文件

官方文档中提供的方法要设备能访问google&#xff1f; 官方方法 直接下载字体的fft文件 我要使用的是lexend 需要的格式可以在里面搜索 使用下载的ttf文件 解压出来 可以单独使用static里面的&#xff0c;里面是直接的lexend的各种格式 但是我这里直接使用Lexend-Vari…

连接Huggingface报requests.exceptions.SSLError错误

最近在学习使用 SHAP 算法解释 BERT 模型的输出结果&#xff0c;然而在从 Huggingface 上导入模型和数据集的过程中出现了网络连接相关的错误&#xff0c;本文用于记录错误类型和解决错误的方法。 1 代码示例 SHAP 官方展示的代码如下&#xff1a; import datasets import nu…

Linux应急响应——知攻善防应急靶场-Linux(1)

文章目录 查看history历史指令查看开机自启动项异常连接和端口异常进程定时任务异常服务日志分析账户排查总结 靶场出处是知攻善防 Linux应急响应靶机 1 前景需要&#xff1a; 小王急匆匆地找到小张&#xff0c;小王说"李哥&#xff0c;我dev服务器被黑了",快救救我&…