文章目录

  • 一、芯片手册关键点笔记
    • 1、时序
    • 2、寄存器
  • 二、FPGA控制DAC8532驱动
    • DAC8532_drive_project
    • DAC8532_DATA_Ctrl模块:
    • spi_data_transfer模块:
    • 仿真:
    • 约束:
    • 仿真结果:
    • 门级仿真:
    • signaltap在线调试
  • 三、福利:工程链接

一、芯片手册关键点笔记

1、时序










2、寄存器

看完了,时序部分,我们来看看寄存器部分,通过配置寄存器,可以控制我们的输出,所以寄存器也非常重要。



这里就说了,如果SYNC(取反)信号的突然上升,在数据还没有传完的时候就上升,这种中断的方式,数据缓冲器内容,DAC寄存器内容的更新或操作模式的更改都不会发生,已经写入的这一段数据都会被丢弃,移位寄存器会重新置位。

上图为这几种模式的介绍,我们一般来说用正常模式就行,其余模式,可以根据实际需求更改。



上图是三种powerdown模式,但是我们一般就设置为00,正常模式即可,不需要用到powerdown模式
下面,还给出了操作的例子


例子1是在等待两个24sclk序列加载完毕后,此时,A B 的寄存器都加载了数据后,再同时进行数模转换。
例子2是24个SCLK加载完数据到A后,立马就开始输出,第二个SCLK加载完数据到B后,B开始输出。

二、FPGA控制DAC8532驱动

时隔3天,终于调好了程序,非常适合几乎所有的SPI控制的ADC和DAC芯片。
只需要改动参数parameter即可。
这也是我写程序的一个良好习惯,尽量参数化,尽量让写过的程序以后复用,而不要今天用SPI写一次,隔天换了个DA的时序,也是SPI控制的,又用SPI再写一次,这样效率相当低下,尽量一次就写好,写工整。

软件:quartus 13.1
modelsim 10.1 c

代码:

顶层模块

DAC8532_drive_project

//功能描述:驱动双通道16bit的DAC同时产生正弦波形,或者三角波形
//author: ciscomonkey
//思路分析:组合控制+数据,组合完毕,发出传输指令,SPI模块开始传输,传输完毕信号给控制模块,控制模块接收到传输完毕信号,
//进入等待DA芯片的转换时间,等待结束,再次进入组合状态。
`timescale 1 ns/ 1 ns
module DAC8532_drive_project
#
(
parameter data_width=24,//控制+DAC_data数据长度
parameter DAC_data_width=16,//DAC_data数据长度
parameter wait_conversion_time=10,//转换时间,100M(10ns),100ns
parameter SPI_RATE=10_000_000,
parameter CLOCK_RATE=100_000_000
)
(
input clk,
input rst,
input start,    //触发启动程序input switch,  //波形选择,1为电平1,2为电平2output sclk,    //输出时钟信号output SYNC_n,   //输出同步信号output Din     //输出数据
);
//
//
//
//reg [DAC_data_width-1:0] voltage_1_reg=16'b1010_1010_1010_1010;
reg [DAC_data_width-1:0] voltage_2_reg=16'b0101_0101_0101_0101;
wire [DAC_data_width-1:0] voltage_1;
wire [DAC_data_width-1:0] voltage_2;assign voltage_1=voltage_1_reg;
assign voltage_2=voltage_2_reg;wire [DAC_data_width-1:0] DAC_a_data = switch ? voltage_1 : voltage_2;
wire [DAC_data_width-1:0] DAC_b_data = switch ? voltage_1 : voltage_2;    wire spi_data_done;
wire mosi;
wire start_spi;
wire [data_width-1:0] miso_data_reg;
wire [data_width-1:0] data_reg;
wire write_busy;
wire data_DAC_ab_finish;
//-------------------------------------------------------------
DAC8532_DATA_Ctrl
# (
.data_width(data_width),//控制+DAC_data数据长度.DAC_data_width(DAC_data_width),//DAC_data数据长度.wait_conversion_time(wait_conversion_time)
)DAC8532_DATA_Ctrl_inst
(
.clk(clk),
.rst(rst),
.DAC_a_data(DAC_a_data),
.DAC_b_data(DAC_b_data),
.start(start),                      //启动DAC8532
.spi_data_done(spi_data_done),              //24位宽的数据传输完的标志.data_reg(data_reg), //串行输出一帧数据(控制+数据)
.start_spi(start_spi),                  //组合好一帧数据后开始传输命令
.data_DAC_ab_finish(data_DAC_ab_finish)
);//----------------------------------------------------------------------spi_data_transfer
# (.data_width(data_width)   ,           // SPI一次写入数据长度.SPI_RATE(SPI_RATE)     ,    // SPI时钟速率.CLOCK_RATE(CLOCK_RATE)    // 系统时钟速率)spi_data_transfer_inst
(
.clk(clk),
.rst(rst),
.data_reg(data_reg),                    //输入数据,用于mosi
.start_spi(start_spi),//开启传输指令
.miso_data_reg(miso_data_reg),              //miso,主机(FPGA)接收的数据,从机发送
.miso(0),
.sclk(sclk),            //时钟
.write_busy(write_busy),    //写入繁忙
.spi_data_done(spi_data_done),          //数据传输完的标志
.mosi(mosi),            //主发从收,主机(FPGA)发送,从机接收
.SYNC_n(SYNC_n));
assign Din=mosi;endmodule

DAC8532_DATA_Ctrl模块:

//功能描述:驱动双通道16bit的DAC同时产生正弦波形,或者三角波形
//author: ciscomonkey
//思路分析:组合控制+数据,组合完毕,发出传输指令,SPI模块开始传输,传输完毕信号给控制模块,控制模块接收到传输完毕信号,
//进入等待DA芯片的转换时间,等待结束,再次进入组合状态。
`timescale 1 ns/ 1 ns
module DAC8532_drive_project
#
(
parameter data_width=24,//控制+DAC_data数据长度
parameter DAC_data_width=16,//DAC_data数据长度
parameter wait_conversion_time=15,//转换时间,100M(10ns),100ns
parameter SPI_RATE=10_000_000,
parameter CLOCK_RATE=100_000_000
)
(
input clk,
input rst,
input start,    //触发启动程序input switch,  //波形选择,1为电平1,2为电平2output sclk,    //输出时钟信号output SYNC_n,   //输出同步信号
//
output [5:0] next_state_test,   //状态机测试信号
output [5:0] now_state_test,output Din     //输出数据
);
//
//
//
//reg [DAC_data_width-1:0] voltage_1_reg=16'b1010_1010_1010_1010;
reg [DAC_data_width-1:0] voltage_2_reg=16'b0101_0101_0101_0101;
wire [DAC_data_width-1:0] voltage_1;
wire [DAC_data_width-1:0] voltage_2;assign voltage_1=voltage_1_reg;
assign voltage_2=voltage_2_reg;wire [DAC_data_width-1:0] DAC_a_data = switch ? voltage_1 : voltage_2;
wire [DAC_data_width-1:0] DAC_b_data = switch ? voltage_1 : voltage_2;    wire spi_data_done;
wire mosi;
wire start_spi;
wire [data_width-1:0] miso_data_reg;
wire [data_width-1:0] data;
wire write_busy;
wire data_DAC_ab_finish;
//-------------------------------------------------------------
DAC8532_DATA_Ctrl
# (
.data_width(data_width),//控制+DAC_data数据长度.DAC_data_width(DAC_data_width),//DAC_data数据长度.wait_conversion_time(wait_conversion_time)
)DAC8532_DATA_Ctrl_inst
(
.clk(clk),
.rst(rst),
.DAC_a_data(DAC_a_data),
.DAC_b_data(DAC_b_data),
.start(start),                      //启动DAC8532
.spi_data_done(spi_data_done),              //24位宽的数据传输完的标志
.now_state_test(now_state_test),
.next_state_test(next_state_test),.data(data),  //串行输出一帧数据(控制+数据)
.start_spi(start_spi),                  //组合好一帧数据后开始传输命令
.data_DAC_ab_finish(data_DAC_ab_finish)
);//----------------------------------------------------------------------spi_data_transfer
# (.data_width(data_width)   ,           // SPI一次写入数据长度.SPI_RATE(SPI_RATE)     ,    // SPI时钟速率.CLOCK_RATE(CLOCK_RATE)    // 系统时钟速率)spi_data_transfer_inst
(
.clk(clk),
.rst(rst),
.data_reg(data),                    //输入数据,用于mosi
.start_spi(start_spi),//开启传输指令
.miso_data_reg(miso_data_reg),              //miso,主机(FPGA)接收的数据,从机发送
.miso(0),
.sclk(sclk),            //时钟
.write_busy(write_busy),    //写入繁忙
.spi_data_done(spi_data_done),          //数据传输完的标志
.mosi(mosi),            //主发从收,主机(FPGA)发送,从机接收
.SYNC_n(SYNC_n));
assign Din=mosi;endmodule

spi_data_transfer模块:

//module:DAC8532_DATA_Ctrl
//author:Ciscomonkey
//functional description:提供mosi的数据,用于传输,发出传输指令则可以开启传输,并控制好时序,在传输完毕后,等待转换时间
`timescale 1 ns/ 1 ns
module DAC8532_DATA_Ctrl
# (
parameter data_width=24,//控制+DAC_data数据长度parameter DAC_data_width=16,//DAC_data数据长度parameter wait_conversion_time=15//A通道传输后,转换时间至少100ns(100M(10ns)),实际测试:+1
)
(
input clk,
input rst,
input   [DAC_data_width-1:0] DAC_a_data,
input   [DAC_data_width-1:0] DAC_b_data,
input    start,//启动DAC8532
input   spi_data_done,              //24位宽的数据传输完的标志output   [data_width-1:0] data,  //串行输出一帧数据(控制+数据)
output   start_spi,                     //组合好一帧数据后开始传输命令
output  [5:0]  now_state_test,
output  [5:0]  next_state_test,
output     data_DAC_ab_finish       //conversion转换结束标志
);reg start_spi_reg;
reg [data_width-1:0] data_reg;
reg data_DAC_ab_finish_reg;
//状态机  三段式localparam IDLE_state=6'b000_000;
localparam combine_DAC_a_data_state=6'b000_001;    //控制+DAC_a_data
localparam spi_DAC_A_trans_state=6'b000_010;          //A通道SPI的传输
localparam conversion_DAC_a_data_state=6'b00_100;  //DAC_a_data的转换等待时间
localparam combine_DAC_b_data_state=6'b001_000;       //控制+DAC_b_data
localparam spi_DAC_B_trans_state=6'b010_000;              //B通道SPI的传输
localparam conversion_DAC_b_data_state=6'b100_000;  //DAC_b_data的转换等待时间reg  [5:0] now_state=IDLE_state;
reg  [5:0] next_state=IDLE_state;//----------
assign now_state_test=now_state;
assign next_state_test=next_state;
reg  [DAC_data_width-1:0]  conversion_time_cnt='d0;//1、实现状态转换
always @ (posedge clk or negedge rst)
beginif(!rst)                           //低电平复位now_state<=IDLE_state;elsenow_state<=next_state;
end//2、根据条件产生下一个状态
always@(*)
begincase(now_state)IDLE_state:beginif(start)beginnext_state=combine_DAC_a_data_state;                         endelsebeginnext_state=IDLE_state;endendcombine_DAC_a_data_state:beginnext_state=spi_DAC_A_trans_state;   endspi_DAC_A_trans_state:beginif(spi_data_done)//如果传输完毕,则进入转换状态next_state=conversion_DAC_a_data_state;  elsenext_state=spi_DAC_A_trans_state;endconversion_DAC_a_data_state:beginif(conversion_time_cnt==wait_conversion_time-1)beginnext_state=combine_DAC_b_data_state;                           endelsebeginnext_state=conversion_DAC_a_data_state;                            endendcombine_DAC_b_data_state:beginnext_state=spi_DAC_B_trans_state;endspi_DAC_B_trans_state:beginif(spi_data_done)//如果传输完毕next_state=conversion_DAC_b_data_state;elsenext_state=spi_DAC_B_trans_state;endconversion_DAC_b_data_state:beginif(conversion_time_cnt==wait_conversion_time-1)beginnext_state=IDLE_state;        //如果需要传输多个数据,比如正弦,那么就next_state回到combine_DAC_a_data_state                 endelsebegin    next_state=conversion_DAC_b_data_state;end                             endendcaseend
//3、状态条件输出
always @ (posedge clk)
begincase(next_state)IDLE_state:beginconversion_time_cnt<='d0;data_reg<='d0;//用于组合数据(控制+数据)start_spi_reg<=0;endcombine_DAC_a_data_state:begindata_reg<={2'b00, 2'b00, 1'b0, 1'b0, 2'b0, DAC_a_data};  start_spi_reg<=1;//发出传输数据指令endspi_DAC_A_trans_state:beginstart_spi_reg<=0;endconversion_DAC_a_data_state:beginconversion_time_cnt<=conversion_time_cnt+1'd1;endcombine_DAC_b_data_state:beginconversion_time_cnt<=0;data_reg<={2'b00, 2'b11, 1'b0, 1'b1, 2'b0, DAC_b_data};  start_spi_reg<=1;//发出传输数据指令                         endspi_DAC_B_trans_state:beginstart_spi_reg<=0;endconversion_DAC_b_data_state:beginconversion_time_cnt<=conversion_time_cnt+1'd1;endendcaseend
//4、每个状态输出的值
always @ (posedge clk)//data_DAC_ab_finish转换完毕的标志
beginif(conversion_time_cnt==wait_conversion_time-1)data_DAC_ab_finish_reg<=1;elsedata_DAC_ab_finish_reg<=0;
end//
assign start_spi=start_spi_reg;
assign data=data_reg;
assign data_DAC_ab_finish=data_DAC_ab_finish_reg;
endmodule

仿真:

// Copyright (C) 1991-2013 Altera Corporation
// Your use of Altera Corporation's design tools, logic functions
// and other software and tools, and its AMPP partner logic
// functions, and any output files from any of the foregoing
// (including device programming or simulation files), and any
// associated documentation or information are expressly subject
// to the terms and conditions of the Altera Program License
// Subscription Agreement, Altera MegaCore Function License
// Agreement, or other applicable license agreement, including,
// without limitation, that your use is for the sole purpose of
// programming logic devices manufactured by Altera and sold by
// Altera or its authorized distributors.  Please refer to the
// applicable agreement for further details.// *****************************************************************************
// This file contains a Verilog test bench template that is freely editable to
// suit user's needs .Comments are provided in each section to help the user
// fill out necessary details.
// *****************************************************************************
// Generated on "02/28/2019 16:07:31"// Verilog Test Bench template for design : DAC8532_drive_project
//
// Simulation tool : ModelSim (Verilog)
// `timescale 1 ns/ 1 ns
module DAC8532_drive_project_vlg_tst();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg clk;
reg rst;
reg start;
reg switch;
// wires
wire Din;
wire SYNC_n;
wire [5:0]  next_state_test;
wire [5:0]  now_state_test;
wire sclk;// assign statements (if any)
DAC8532_drive_project i1 (
// port map - connection between master ports and signals/registers   .Din(Din),.SYNC_n(SYNC_n),.clk(clk),.next_state_test(next_state_test),.now_state_test(now_state_test),.rst(rst),.sclk(sclk),.start(start),.switch(switch)
);
initial
begin
#0 clk=0;
#0 rst=0;
#0 start=0;#10 switch=1;
#60 rst=1;
#100 start=1;
#110 start=0;end
always #5
begin
clk<=~clk;
end
endmodule

约束:

create_clock -name {clk} -period 10.000 -waveform {0.000 5.000} [get_ports {clk}]derive_pll_clocks
derive_clock_uncertainty

仿真结果:

两个通道,同时输出一个电压,有两种电压选择(根据switch 0 or 1)
第一个给了一个start,
先给一个start,然后隔了一段时间,再给一个start。
每start一次,就传输一次。
下图,两个通道均输出16‘b1010101010101010的电压

门级仿真:

signaltap在线调试


注意:
//wire start=1;如果要使用signal_tap在线调试没有外部触发,就把这个start一直置位为1即可

经过测试:即使主频时钟设置为跑到200M,也不会出现时序违规

三、福利:工程链接

https://download.csdn.net/download/ciscomonkey/10981766

FPGA进阶篇--SPI控制双通道16bit串行DAC8532相关推荐

  1. 64Mbit SOIC8封装SPI接口的国产串行SRAM EMI7064

    现在的电子系统应用,对SRAM要求越来越高,单片机或ARM内部的RAM越来越不够用.国产EMI公司的64Mbit SPI接口的SRAM芯片EMI7064.这样的IC用途一般是:数据采集或信号处理过程的 ...

  2. FPGA之VGA转HDMI之并行串行转换模块编写

            上节我们使用编码模块可解决图像数据的编码问题,而这次使用的并行转串行模块的主要功能就是实现并行串行转换.单端信号转差分信号.单沿采样转双沿采样.         并行转串行模块框图如下 ...

  3. 用D触发器和必要的门电路设计一个2位双向移位寄存器. 具体要求见下表(A、B为控制端), 左移串行输入信号为L, 右移串行信号为R

    A B 输出 0 0 保持原状态 0 1 右移 1 0 左移 1 1 清零 在开始分析前, 我们要理清以下四个概念: ①保持原状态: 在下一系统CLK信号来临时, 寄存器状态不变. ②右移: 设寄存器 ...

  4. 试用D触发器和4选1数据选择器74153设计一个双向3位移位寄存器, 具体要求见下表(A、B为控制端), 左移串行输入信号为L, 右移串行输入信号为R

    A B 输出 0 0 保持原状态 0 1 右移 1 0 左移 1 1 清零 根据题目的要求, 绘制状态表. 三位双向移位寄存器状态表 A B Q0* Q1* Q2* 输出 0 0 Q0 Q1 Q2 保 ...

  5. 【SRIO】2、RapidIO串行物理层的包与控制符号

    目录 一.RapidIO串行物理层背景介绍 二.RapidIO串行物理层的包格式 2.1 串行物理层包格式与并行物理层包格式的区别 2.2 RapidIO串行物理层包格式 2.3 RapidIO串行物 ...

  6. 【高速接口-RapidIO】2、RapidIO串行物理层的包与控制符号

    总目录:总目录(经验分享) 献上链接: [高速接口-RapidIO]2.RapidIO串行物理层的包与控制符号 [高速接口-RapidIO]3.RapidIO串行物理层的包传输过程 [高速接口-Rap ...

  7. FPGA_进阶篇开篇

    从2018.11.5号起,每周至少发布1篇FPGA进阶篇的实验,不期待有人看系列.... 研究生生涯 欢迎评论

  8. SPI、I2C、UART三种串行总线的原理、区别及应用

    SPI协议解析,链接如下 https://blog.csdn.net/weiqifa0/article/details/82765892 I2C协议解析,链接如下 https://blog.csdn. ...

  9. UART、SPI、I2C串行通讯协议解释 同步/异步 全双工/半双工通信含义

    欢迎加入QQ技术交流群:100479172 一.什么是同步/异步通信? 同步通信:一方发送,另一方应答,否则不进行下一次传输(带时钟同步信号传输). 异步通信:一方发送,不考虑另一方是否收到,直接进行 ...

最新文章

  1. 就业丨得益于AI,这五个行业岗位需求将呈现显著增长趋势
  2. 魅族 虚拟位置服务状态:未运行_神车道具送不停 魅族17x跑跑卡丁车礼盒开启预约...
  3. 文献学习(part12)--GMNN: Graph Markov Neural Networks
  4. Cordova插件中JavaScript代码与Java的交互细节介绍
  5. Java——方法(练习九九乘法表)
  6. 3d 仪表盘_新一代标致2008官图发布 配备3D全息仪表盘
  7. 中国移动互联网流量半年度分析报告
  8. 20190808估值方法
  9. MVC4 下DropDownList使用方法
  10. 调查 20500 名开发者发现,最流行的编程语言不是 Python 和 Java
  11. 为什么有人说Java开发不再吃香
  12. Maven web项目(简单的表单提交) 搭建(eclipse)
  13. Domino部署多台notes server
  14. 51单片机的矩阵键盘、跑马灯和呼吸灯设计
  15. 【机器学习】基于朴树贝叶斯的言论过滤器
  16. C++搭配PCL的Bunny点云
  17. 利用 π/4=1-1/3+1/5+…,编程计算π的近似值,直到最后一项的绝对值小于 10的负5次方为止,输出π的值并统计累加的项数。
  18. Linux视窗系统:QT使用GPU渲染
  19. 以太网适配器和隧道适配器
  20. 从理解开始 谈谈px rem 和 em 的区别与联系

热门文章

  1. [BZOJ2707]走迷宫
  2. 初次树莓派遇到的一些小问题
  3. UA OPTI570 量子力学22 2-D Isotropic Q.H.O.简介
  4. 精算模型1 一元生存分析2 参数生存模型
  5. Linux grep 命令初步学习
  6. CentOS6安装MySQL 2 - yum makecache成功
  7. C#指针使用学习总结
  8. eclipse调试一个struts2例子时遇到的一些问题总结
  9. 树、森林与二叉树的相互转换
  10. mysql知识点回顾(一)