ZYNQ FPGA实验报告——DAC FIFO实验

DAC FIFO实验

ZYNQ FPGA实验报告——DDS IP.和ZYNQ FPGA实验报告——ADDA测试.基础上进行。

实验要求

1.基于“DDS IP 数字波形合成DAC ” “ ADDA测试” 实验方案
2.用MMCM 把 合成出100MHz的时钟,让DDS工作在100MHz时钟
3.让DAC和DAC的接口电路工作在50MHz,此时DAC的采样率为50MHz
4.在DDS和DAC接口电路之间,放置一个带独立时钟的AXI-Stream-Data FIFO,FIFO两端的时钟分别为DDS的工作时钟100MHz和DAC的工作时钟50MHz
5.生成FIFO需要带data count信号(本实验仅用于观察,以后的实验中这些信号有用。)
6.DDS的数据输出接口需要有TREADY信号
7.DAC接口电路需要将FIFO输出端的AXI-S接口转换成DAC的接口格式,自行编写RTL代码完成该功能。另外由于DAC的工作频率小于DDS工作频率,所以DAC接口控制器给FIFO的RDY信号应该一直为高。
8.以上结构的意义在于,把接口电路和信号处理电路分离在不同的时钟域,从而使得各部分保持独立
9.本实验添加2个system ILA,分别观察FIFO两端接口的信号时序,注意观察 data count端口的变化。
10.用VIO配置频率字,分别生成1MHz和3MHz的DDS正弦波形,用system ILA抓取DAC的输入数据,用Matlab分析频谱,验证频率正确。
11.本实验是一个典型的带反向流控的跨时钟域传输信号的例子

实验步骤

DDS IP核

DDS IP核工作在100MHz时钟;选择Hardware Parameters,硬件参数这里选择8位的输出宽度,因为ADDA模块最大只能传输8位宽度的数据。使用50MHz时钟频率。
在这里插入图片描述
DDS需要能够配置频率字(相位增量)
在这里插入图片描述
DDS的数据输出接口需要有TREADY信号
在这里插入图片描述

Clock IP核

使用MMCM分频,让DAC和DAC的接口电路工作在50MHz。
在这里插入图片描述
在这里插入图片描述
让DDS工作在100MHz时钟
在这里插入图片描述

FIFO IP核

在DDS和DAC接口电路之间,放置一个带独立时钟的AXI-Stream-Data FIFO,FIFO两端的时钟分别为DDS的工作时钟100MHz和DAC的工作时钟50MHz。生成FIFO需要带data count信号。
独立时钟选择异步时钟,同步阶数选择2。
在这里插入图片描述
输出有使能写/读数据计数,分别同步于写/读时钟。
在这里插入图片描述

ILA IP核

第一个ILA设置4个探针,分别观察频率字控制位(2位)、fifo的输入和输出(8位)和data count端口(32位)。
在这里插入图片描述
在这里插入图片描述
第二个ILA设置2个探针,分别观察频率字控制位(2位)和da数据(8位)。
在这里插入图片描述
在这里插入图片描述

VIO IP核

VIO IP核与实验ZYNQ FPGA实验报告——DDS IP.设置一致。
在这里插入图片描述

程序设计

顶层模块ADDA_test如下:
增加了时钟和DA发送模块的例化。

`timescale 1ns / 1ps

module dac_fifo(
    input           sys_clk,        //系统时钟 50MHz  T=20ns
    input           rst_n,           //系统复位  
     //DA芯片接口
    output                da_clk,  //DA(AD9708)驱动时钟,最大支持125Mhz时钟
    output    [7:0]       da_data,  //输出给DA的数据
    //AD芯片接口
    input     [7:0]       ad_data,  //AD输入数据
    //模拟输入电压超出量程标志(本次试验未用到)
    //input                 ad_otr      ,  //0:在量程范围 1:超出量程
    output                ad_clk         //AD(AD9280)驱动时钟,最大支持32Mhz时钟 
    );
 
//----------VIO按键控制频率控制字(key_PINC)--------------//
 wire [1:0] key_PINC;
 vio_0 vio_0_inst (
      .clk(sys_clk),                // input wire clk
      .probe_out0(key_PINC)  // output wire [1 : 0] probe_out0
);

//---------------信号频率控制模块--------------//
wire  [23:0]   Fword ;  //频率字
Fword_set Fword_set_inst(
   //input
   .clk        (sys_clk),
   .rst_n      (rst_n),
   .key_PINC   (key_PINC),
   //output
   .Fword      (Fword)
);

//---------------PLL模块--------------//
wire  clk_100M;
//例化PL
clk_wiz_0 pll_inst
(
    // Clock out ports
    .clk_out1(clk_100M),     // output clk_out1
    // Status and control signals
    .reset(~rst_n), // input reset
    .locked(locked),       // output locked
   // Clock in ports
    .clk_in1( sys_clk)   // input clk_in1
);  

//---------------DDS模块--------------//
//input
wire [0:0]   fre_ctrl_word_en;  
wire         m_axis_data_tready;
wire         m_axis_phase_tready;  
//output
wire [0:0]   m_axis_data_tvalid;
wire [7:0]   m_axis_data_tdata;
wire [0:0]   m_axis_phase_tvalid;
wire [23:0]  m_axis_phase_tdata;
wire [0:0]   s_axis_config_tready;

assign fre_ctrl_word_en=1'b1;

//---------------AXIS-DATA-FIFO模块--------------//
//output
wire        fifo_s_axis_tready;
wire        fifo_m_axis_tvalid;
wire        da_m_axis_tready;
wire [7:0]  fifo_m_axis_tdata;
wire [31:0] fifo_axis_wr_data_count;
wire [31:0] fifo_axis_rd_data_count;

assign  s_axis_aresetn = 1'b1;

//例化DDS IP
dds_compiler_0 dds_compiler_0_inst (
  .aclk(clk_100M),        // input wire aclk  DDS的工作频率为100MHz
  .s_axis_config_tvalid(fre_ctrl_word_en),  // input wire s_axis_config_tvalid
  .s_axis_config_tready(s_axis_config_tready),  // output wire s_axis_config_tready
  .s_axis_config_tdata(Fword),    // input wire [23 : 0] s_axis_config_tdata
  .m_axis_data_tvalid(m_axis_data_tvalid),      // output wire m_axis_data_tvalid
  .m_axis_data_tready(fifo_s_axis_tready),      // input wire m_axis_data_tready
  .m_axis_data_tdata(m_axis_data_tdata),        // output wire [15 : 0] m_axis_data_tdata
  .m_axis_phase_tvalid(m_axis_phase_tvalid),    // output wire m_axis_phase_tvalid
  .m_axis_phase_tready(fifo_s_axis_tready),    // input wire m_axis_phase_tready
  .m_axis_phase_tdata(m_axis_phase_tdata)      // output wire [23 : 0] m_axis_phase_tdata
);

//例化AXIS-DATA-FIFO
axis_data_fifo_0 axis_data_fifo_inst (
  .s_axis_aresetn(s_axis_aresetn),          // input wire s_axis_aresetn
  .s_axis_aclk(clk_100M),                 // input wire s_axis_aclk  给100MHz
  .s_axis_tvalid(m_axis_data_tvalid),            // input wire s_axis_tvalid
  .s_axis_tready(fifo_s_axis_tready),            // output wire s_axis_tready
  .s_axis_tdata(m_axis_data_tdata),              // input wire [7 : 0] s_axis_tdata
  .m_axis_aclk(sys_clk),                        // input wire m_axis_aclk 系统时钟频率50MHz
  .m_axis_tvalid(fifo_m_axis_tvalid),            // output wire m_axis_tvalid
  .m_axis_tready(s_axis_config_tready),            // input wire m_axis_tready
  .m_axis_tdata(fifo_m_axis_tdata),              // output wire [7 : 0] m_axis_tdata
  .axis_wr_data_count(fifo_axis_wr_data_count),  // output wire [31 : 0] axis_wr_data_count
  .axis_rd_data_count(fifo_axis_rd_data_count)  // output wire [31 : 0] axis_rd_data_count
);

//DA数据发送
da_wave_send u_da_wave_send(
    .clk         (sys_clk), 
    .rst_n       (rst_n),
    .rd_data     (m_axis_data_tdata),
    .da_clk      (da_clk),  
    .da_data     (da_data),
    .da_m_axis_tready   (da_m_axis_tready)
);

//ILA采集AD数据
ila_0 ila_0_inst (
	.clk(sys_clk), // input wire clk

	.probe0(key_PINC), // input wire [1:0]  probe0  
	.probe1(m_axis_data_tdata), // input wire [7:0]  probe1 
	.probe2(fifo_m_axis_tdata), // input wire [7:0]  probe2 
	.probe3(fifo_axis_rd_data_count) // input wire [31:0]  probe3
);

ila_1 ila_1_inst (
	.clk(sys_clk), // input wire clk

	.probe0(key_PINC), // input wire [1:0]  probe0  
	.probe1(da_data) // input wire [7:0]  probe1
);
       
endmodule

da_wave_send模块:

module da_wave_send(
    input                 clk    ,  //时钟
    input                 rst_n  ,  //复位信号,低电平有效    
    input        [7:0]    rd_data,  //读出的数据
    //DA芯片接口
    output                da_clk ,  //DA(AD9708)驱动时钟,最大支持125Mhz时钟
    output       [7:0]    da_data,   //输出给DA的数据  
   
    output da_m_axis_tready    // 由于DAC的工作频率小于DDS工作频率,所以DAC接口控制器给FIFO的RDY信号应该一直为高
);

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

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

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

assign  da_m_axis_tready = 1'b1;

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

endmodule

Fwordset模块:

`timescale 1ns / 1ps

module Fword_set(
    input               clk         ,
    input               rst_n       ,
    input  [1:0]        key_PINC    ,
    
    output reg [23:0]   Fword
    );
          
always@(*)
begin
    case(key_PINC)
        0:  Fword <= 'h51eb;     //1Mhz 20971.52 取整20971
        1:  Fword <= 'ha3d7;     //2Mhz 41943.04 取整41943
        2:  Fword <= 'hf5c2;     //3Mhz 62914.56 取整62914
        //3:  Fword <= 'h33333;    //10Mhz 209715.2 取整209715
    endcase
end

endmodule

添加约束文件

set_property PACKAGE_PIN U18 [get_ports sys_clk]
set_property PACKAGE_PIN N15 [get_ports rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]

set_property PACKAGE_PIN F20 [get_ports da_clk]
set_property IOSTANDARD LVCMOS33 [get_ports da_clk]
set_property PACKAGE_PIN F19 [get_ports {da_data[7]}]
set_property PACKAGE_PIN G20 [get_ports {da_data[6]}]
set_property PACKAGE_PIN G19 [get_ports {da_data[5]}]
set_property PACKAGE_PIN H18 [get_ports {da_data[4]}]
set_property PACKAGE_PIN J18 [get_ports {da_data[3]}]
set_property PACKAGE_PIN L20 [get_ports {da_data[2]}]
set_property PACKAGE_PIN L19 [get_ports {da_data[1]}]
set_property PACKAGE_PIN M20 [get_ports {da_data[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {da_data[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {da_data[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {da_data[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {da_data[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {da_data[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {da_data[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {da_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {da_data[6]}]
set_property PACKAGE_PIN G18 [get_ports ad_clk]
set_property IOSTANDARD LVCMOS33 [get_ports ad_clk]
set_property IOSTANDARD LVCMOS33 [get_ports {ad_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ad_data[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ad_data[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ad_data[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ad_data[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ad_data[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ad_data[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ad_data[0]}]
set_property PACKAGE_PIN E18 [get_ports {ad_data[7]}]
set_property PACKAGE_PIN E19 [get_ports {ad_data[6]}]
set_property PACKAGE_PIN D19 [get_ports {ad_data[5]}]
set_property PACKAGE_PIN D20 [get_ports {ad_data[4]}]
set_property PACKAGE_PIN M17 [get_ports {ad_data[3]}]
set_property PACKAGE_PIN M18 [get_ports {ad_data[2]}]
set_property PACKAGE_PIN L16 [get_ports {ad_data[1]}]
set_property PACKAGE_PIN L17 [get_ports {ad_data[0]}]

比特流文件输出波形

生成比特流文件,PROGRAM AND DEBUG—Generate Bitstream。
1MHz输出
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2MHz输出
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3MHz输出
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用Matlab分析频谱并验证

选中要分析的信号,右键Export ILA Data,Format选择CSV,导入到指定目录中。
在Matlab中读出csv文件(主页——导入数据),并导入(注意导入类型为表),导入成功工作区内会显示。
在这里插入图片描述

csv1_row5 = iladata1{:,5};  %取出iladata1.csv文件中的第五列数据
csv2_row5 = iladata2{:,5};  %取出iladata2.csv文件中的第五列数据
csv3_row5 = iladata3{:,5};  %取出iladata3.csv文件中的第五列数据
fs=50000000;    %设置采样频率为50MHz
N=4096;         %采样点
n=0:N-1;
t=n/fs;
f=n*fs/N;       %频率序列
figure;
subplot(2,1,1);plot(t,csv1_row5);grid on;title('1MHz-时域波形');
y=abs(fft(csv1_row5,N)); 
subplot(2,1,2);plot(f,y,'r');grid on;title('1MHz-频谱');
figure;
subplot(2,1,1);plot(t,csv2_row5);grid on;title('2MHz-时域波形');
y=abs(fft(csv2_row5,N)); 
subplot(2,1,2);plot(f,y,'r');grid on;title('2MHz-频谱');
figure;
subplot(2,1,1);plot(t,csv3_row5);grid on;title('3MHz-时域波形');
y=abs(fft(csv3_row5,N)); 
subplot(2,1,2);plot(f,y,'r');grid on;title('3MHz-频谱');

输出1MHz的频谱数据
在这里插入图片描述
输出2MHz的频谱数据
在这里插入图片描述
输出3MHz的频谱数据
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwt_csdn_edu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值