99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

電子發(fā)燒友App

硬聲App

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示
創(chuàng)作
電子發(fā)燒友網(wǎng)>電子資料下載>電子資料>Eclypse Z7上的Zmod ADC和DAC:正弦波環(huán)回

Eclypse Z7上的Zmod ADC和DAC:正弦波環(huán)回

2022-11-23 | zip | 0.84 MB | 次下載 | 2積分

資料介紹

描述

這個(gè)項(xiàng)目是我完整詳細(xì)介紹帶有 ADCDAC ZMOD 的 Eclypse Z7 的延續(xù)。正如我在那個(gè)項(xiàng)目中提到的那樣,我通過(guò)將 DDS Complier IP 模塊集成到模塊設(shè)計(jì)中并使用它來(lái)生成數(shù)字 1 MHz 正弦波數(shù)據(jù)以供 DAC ZMOD 輸出到其通道之一,從而添加到設(shè)計(jì)中。為了驗(yàn)證數(shù)據(jù),它將在 ADC ZMOD 的一個(gè)通道上讀取。我還將把它連接到我的信號(hào)分析儀上,看看物理 1MHz 波是什么樣子的。

首先,我將 DAC ZMOD 的第一個(gè)通道連接到 ADC ZMOD 的第一個(gè)通道:

作為參考的旁注,我再次使用 Vivado 和 Vitis 2019.2 版,并且我使用的項(xiàng)目與我在上一篇關(guān)于Eclypse Z7 的項(xiàng)目帖子中詳細(xì)介紹了如何創(chuàng)建的項(xiàng)目完全相同。

從 Vivado 中現(xiàn)有的硬件設(shè)計(jì)開(kāi)始,首先需要修改的是塊設(shè)計(jì)。我非常喜歡使用 DDS 編譯器生成正弦波,因?yàn)樗鼈兪墙Y(jié)構(gòu)資源利用率和輸出波精度之間的最佳折衷。

打開(kāi)模塊設(shè)計(jì)并將 DDS 編譯器添加到 IP 模塊設(shè)計(jì),雙擊它以打開(kāi)其定制窗口。

使用 DDS 編譯器 IP 的最大優(yōu)勢(shì)之一是在更改輸出信號(hào)的頻率/相位時(shí)平滑/無(wú)縫過(guò)渡(因此您不必?fù)?dān)心相位不連續(xù))。這就是為什么我喜歡使用流選項(xiàng)來(lái)實(shí)現(xiàn)輸出頻率/相位的可編程性。

我現(xiàn)在選擇只關(guān)注更改輸出頻率(通過(guò)相位增量可編程性)并將相位偏移可編程性設(shè)置為無(wú):

pYYBAGN7JTOAROY2AABLEL_skMc914.png
將相位增量可編程性設(shè)置為流式傳輸。
?

對(duì)于帶有 DMA 的 AXI 流協(xié)議與 DAC ZMOD 接口以將正弦波寫出,流需要被打包,輸出tready,并在正弦波的每個(gè)周期結(jié)束時(shí)斷言 tlast。在 Data has TLAST 下選擇“Packet Framing”選項(xiàng),并選中“Output TREADY”復(fù)選框。

poYBAGN7JTeAVKB7AABP1UKmDgo814.png
將數(shù)據(jù)包成幀添加到 AXI 通道選項(xiàng)。
?

DDS 編譯器會(huì)將其輸出寫入 Eclypse 的 DDR 內(nèi)存,供 DAC 通過(guò) DMA 引擎讀取。為了使集成盡可能簡(jiǎn)單,我只是為 DDS 的輸出啟用了 DMA 引擎的寫入通道。由于數(shù)據(jù)一次傳輸一個(gè)周期的正弦波,因此還需要為寫入通道啟用 DRE(數(shù)據(jù)重新對(duì)齊引擎)。選中寫入通道的“允許未對(duì)齊傳輸”框(僅適用于寫入通道,因?yàn)槁銠C(jī) Zmod 庫(kù)負(fù)責(zé)對(duì)齊數(shù)據(jù)以在讀取通道上傳輸)。

pYYBAGN7JTqALkb0AABazKJagk8075.png
啟用 DAC 的 DMA 引擎的寫入通道以供 DDS 編譯器寫入。
?

手動(dòng)將 DDS 編譯器的 M_AXIS_DATA 輸出連接到 DAC 的 DMA 引擎的 S_AXIS_S2MM。DMA 的 S_AXIS_S2MM 端口的 tkeep 信號(hào)需要在其總線上保持高電平,以表示所有傳入數(shù)據(jù)都是有效的(包括任何零值數(shù)據(jù)字節(jié))。為此,在設(shè)計(jì)中添加一個(gè)常量 IP 塊,將輸出寬度設(shè)置為與 DMA 的 S_AXIS_S2MM 端口的 tkeep 匹配,并將該值設(shè)置為總線上的高電平(在這種情況下,tkeep 信號(hào)為兩位寬,因此常數(shù)值將設(shè)置為 3,即 2'b11)。然后手動(dòng)將其輸出連接到 DMA 的 S_AXIS_S2MM 端口。

poYBAGN7JT2AOLWTAALMXVm10vQ127.png
手動(dòng)將 DDS 輸出連接到 DAC 的 DMA 的 S2MM。
?

我認(rèn)為從 Zynq 芯片的可編程邏輯控制 DDS 編譯器的輸入會(huì)更容易。為了做到這一點(diǎn),DDS 編譯器的相位輸入端口需要在框圖外部可用,方法是右鍵單擊端口名稱并選擇“Make external”選項(xiàng)。您將看到 DDS 編譯器輸入的 AXI 流總線端口出現(xiàn)。

來(lái)自 Zynq 處理系統(tǒng)的 FCLK_CLK1 時(shí)鐘也需要引出到模塊設(shè)計(jì)中的端口,以便在 Zynq 芯片的可編程邏輯中可供 HDL 使用。只需右鍵單擊 Zynq 處理系統(tǒng) IP 塊上的 FCLK_CLK1 端口名稱并選擇“創(chuàng)建端口...”:

poYBAGN7JUCAZa5mAAOEyG_QfF8128.png
將 FCLK_CLK1 引出到 exrenal 端口。
?

塊設(shè)計(jì)現(xiàn)在應(yīng)該類似于以下內(nèi)容:

pYYBAGN7JUWAYrSrAAVDlLeWx2g416.png
修改后的框圖,將 DDS 編譯器添加到 DAC DMA S2MM(寫入)通道。
?

后面要添加邏輯分析儀進(jìn)行調(diào)試,標(biāo)記DDS的相位輸入,連同DDS數(shù)據(jù)輸出,DAC的DMA的AXIS_MM2S和ADC的DMA的AXIS_S2MM進(jìn)行調(diào)試。只需右鍵單擊每一行并選擇“調(diào)試”:

poYBAGN7JUeAcu2aAACQf3ttVCg579.png
標(biāo)記 AXI Stream 線以進(jìn)行調(diào)試。
?

片刻之后,將出現(xiàn)連接自動(dòng)化選項(xiàng)。選擇它并確保選中 AXI 協(xié)議檢查器選項(xiàng)的復(fù)選框。

連接自動(dòng)化完成運(yùn)行后,驗(yàn)證模塊設(shè)計(jì)以檢查是否存在任何錯(cuò)誤或嚴(yán)重警告,然后保存并關(guān)閉它。

由于已添加新的外部端口,因此需要為模塊設(shè)計(jì)創(chuàng)建新的 HDL 實(shí)例化。只需右鍵單擊 Sources Hierarchy 選項(xiàng)卡中的塊設(shè)計(jì)文件并選擇“Create HDL Wrapper...”選項(xiàng)即可完成此操作。它只會(huì)使用新的框圖實(shí)例化更新現(xiàn)有的框圖(就像在上一個(gè)項(xiàng)目中一樣,選擇讓 Vivado 自動(dòng)更新和管理它的選項(xiàng))。

pYYBAGN7JUqAZ0XkAADgnb3sONo482.png
?

然而,由于沒(méi)有一個(gè)新的外部端口將路由到 Zynq 芯片上的實(shí)際封裝引腳,并且還需要添加其他自定義 HDL,因此需要從頭開(kāi)始創(chuàng)建一個(gè)新的頂級(jí)文件。即使有一個(gè)選項(xiàng)允許用戶在最后一步管理包裝器,我發(fā)現(xiàn)使用 Vivado 最好始終選擇自動(dòng)管理選項(xiàng),然后從頭開(kāi)始創(chuàng)建自己的頂級(jí)文件并簡(jiǎn)單地復(fù)制+粘貼來(lái)自自動(dòng)生成的包裝器的框圖實(shí)例化。

對(duì)于這個(gè)設(shè)計(jì),我正在創(chuàng)建我自己的三個(gè)設(shè)計(jì)源:新的自定義頂層文件、用于生成相位增量值以發(fā)送到 DDS 編譯器的邏輯,以及用于 AXI 流協(xié)議以與 DDS 編譯器通信的狀態(tài)機(jī).

從 Flow Navigator 中選擇 Add Sources 選項(xiàng),然后在彈出窗口中選擇 Add or create design sources。然后,該窗口將為您提供創(chuàng)建所需文件數(shù)量的選項(xiàng)(在本例中為三個(gè) Verilog 模塊文件)。

pYYBAGN7JUyADswXAACpjz0TMrw846.png
?

我將頂層文件命名為“eclypse_top”,將相位增量邏輯文件命名為“bb_logic”,并將 AXI 流狀態(tài)機(jī)文件命名為“axis_sm”。

頂層文件主要是為塊設(shè)計(jì)實(shí)例化自動(dòng)生成的 design_wrapper 文件的復(fù)制 + 粘貼。它還將實(shí)例化相位增量邏輯模塊。請(qǐng)注意,用于 DDS 編譯器和 FCLK_CLK1 的從 AXI 流信號(hào)從模塊端口說(shuō)明符中被注釋掉,因?yàn)樗鼈儽恢囟ㄏ虻较辔辉隽窟壿嬆K,而不是被路由到 Zynq 芯片上的封裝引腳。然后相位增量邏輯模塊負(fù)責(zé)例化 AXI 流狀態(tài)機(jī)模塊。

自定義頂級(jí)文件 Verilog:

module eclypse_top(
    inout [14:0]DDR_addr,
    inout [2:0]DDR_ba,
    inout DDR_cas_n,
    inout DDR_ck_n,
    inout DDR_ck_p,
    inout DDR_cke,
    inout DDR_cs_n,
    inout [3:0]DDR_dm,
    inout [31:0]DDR_dq,
    inout [3:0]DDR_dqs_n,
    inout [3:0]DDR_dqs_p,
    inout DDR_odt,
    inout DDR_ras_n,
    inout DDR_reset_n,
    inout DDR_we_n,
//    input [31:0]DDS_S_AXIS_PHASE_tdata,
//    input DDS_S_AXIS_PHASE_tlast,
//    output DDS_S_AXIS_PHASE_tready,
//    input DDS_S_AXIS_PHASE_tvalid,
    input DcoClk_0,
//    output FCLK_CLK1,
    inout FIXED_IO_ddr_vrn,
    inout FIXED_IO_ddr_vrp,
    inout [53:0]FIXED_IO_mio,
    inout FIXED_IO_ps_clk,
    inout FIXED_IO_ps_porb,
    inout FIXED_IO_ps_srstb,
    output adcClkIn_n_0,
    output adcClkIn_p_0,
    output adcSync_0,
    input [1:0]btn_2bits_tri_i,
    input [13:0]dADC_Data_0,
    inout pmod_ja_pin10_io,
    inout pmod_ja_pin1_io,
    inout pmod_ja_pin2_io,
    inout pmod_ja_pin3_io,
    inout pmod_ja_pin4_io,
    inout pmod_ja_pin7_io,
    inout pmod_ja_pin8_io,
    inout pmod_ja_pin9_io,
    inout pmod_jb_pin10_io,
    inout pmod_jb_pin1_io,
    inout pmod_jb_pin2_io,
    inout pmod_jb_pin3_io,
    inout pmod_jb_pin4_io,
    inout pmod_jb_pin7_io,
    inout pmod_jb_pin8_io,
    inout pmod_jb_pin9_io,
    output [5:0]rgbled_6bits_tri_o,
    output sADC_CS_0,
    inout sADC_SDIO_0,
    output sADC_Sclk_0,
    output sCh1CouplingH_0,
    output sCh1CouplingL_0,
    output sCh1GainH_0,
    output sCh1GainL_0,
    output sCh2CouplingH_0,
    output sCh2CouplingL_0,
    output sCh2GainH_0,
    output sCh2GainL_0,
    output sDAC_CS_0,
    output sDAC_ClkIO_0,
    output sDAC_Clkin_0,
    output [13:0]sDAC_Data_0,
    output sDAC_EnOut_0,
    output sDAC_Reset_0,
    output sDAC_SCLK_0,
    inout sDAC_SDIO_0,
    output sDAC_SetFS1_0,
    output sDAC_SetFS2_0,
    output sRelayComH_0,
    output sRelayComL_0,
    input sys_clock
    );
    
    wire FCLK_CLK1;
    wire [31:0]DDS_S_AXIS_PHASE_tdata;
    wire DDS_S_AXIS_PHASE_tlast;
    wire DDS_S_AXIS_PHASE_tready;
    wire DDS_S_AXIS_PHASE_tvalid;
    
    // block diagram instantiation
    design_1 design_1_i(
        .DDR_addr(DDR_addr),
        .DDR_ba(DDR_ba),
        .DDR_cas_n(DDR_cas_n),
        .DDR_ck_n(DDR_ck_n),
        .DDR_ck_p(DDR_ck_p),
        .DDR_cke(DDR_cke),
        .DDR_cs_n(DDR_cs_n),
        .DDR_dm(DDR_dm),
        .DDR_dq(DDR_dq),
        .DDR_dqs_n(DDR_dqs_n),
        .DDR_dqs_p(DDR_dqs_p),
        .DDR_odt(DDR_odt),
        .DDR_ras_n(DDR_ras_n),
        .DDR_reset_n(DDR_reset_n),
        .DDR_we_n(DDR_we_n),
        .DDS_S_AXIS_PHASE_tdata(DDS_S_AXIS_PHASE_tdata),
        .DDS_S_AXIS_PHASE_tlast(DDS_S_AXIS_PHASE_tlast),
        .DDS_S_AXIS_PHASE_tready(DDS_S_AXIS_PHASE_tready),
        .DDS_S_AXIS_PHASE_tvalid(DDS_S_AXIS_PHASE_tvalid),
        .DcoClk_0(DcoClk_0),
        .FCLK_CLK1(FCLK_CLK1),
        .FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),
        .FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),
        .FIXED_IO_mio(FIXED_IO_mio),
        .FIXED_IO_ps_clk(FIXED_IO_ps_clk),
        .FIXED_IO_ps_porb(FIXED_IO_ps_porb),
        .FIXED_IO_ps_srstb(FIXED_IO_ps_srstb),
        .adcClkIn_n_0(adcClkIn_n_0),
        .adcClkIn_p_0(adcClkIn_p_0),
        .adcSync_0(adcSync_0),
        .btn_2bits_tri_i(btn_2bits_tri_i),
        .dADC_Data_0(dADC_Data_0),
        .pmod_ja_pin10_i(pmod_ja_pin10_i),
        .pmod_ja_pin10_o(pmod_ja_pin10_o),
        .pmod_ja_pin10_t(pmod_ja_pin10_t),
        .pmod_ja_pin1_i(pmod_ja_pin1_i),
        .pmod_ja_pin1_o(pmod_ja_pin1_o),
        .pmod_ja_pin1_t(pmod_ja_pin1_t),
        .pmod_ja_pin2_i(pmod_ja_pin2_i),
        .pmod_ja_pin2_o(pmod_ja_pin2_o),
        .pmod_ja_pin2_t(pmod_ja_pin2_t),
        .pmod_ja_pin3_i(pmod_ja_pin3_i),
        .pmod_ja_pin3_o(pmod_ja_pin3_o),
        .pmod_ja_pin3_t(pmod_ja_pin3_t),
        .pmod_ja_pin4_i(pmod_ja_pin4_i),
        .pmod_ja_pin4_o(pmod_ja_pin4_o),
        .pmod_ja_pin4_t(pmod_ja_pin4_t),
        .pmod_ja_pin7_i(pmod_ja_pin7_i),
        .pmod_ja_pin7_o(pmod_ja_pin7_o),
        .pmod_ja_pin7_t(pmod_ja_pin7_t),
        .pmod_ja_pin8_i(pmod_ja_pin8_i),
        .pmod_ja_pin8_o(pmod_ja_pin8_o),
        .pmod_ja_pin8_t(pmod_ja_pin8_t),
        .pmod_ja_pin9_i(pmod_ja_pin9_i),
        .pmod_ja_pin9_o(pmod_ja_pin9_o),
        .pmod_ja_pin9_t(pmod_ja_pin9_t),
        .pmod_jb_pin10_i(pmod_jb_pin10_i),
        .pmod_jb_pin10_o(pmod_jb_pin10_o),
        .pmod_jb_pin10_t(pmod_jb_pin10_t),
        .pmod_jb_pin1_i(pmod_jb_pin1_i),
        .pmod_jb_pin1_o(pmod_jb_pin1_o),
        .pmod_jb_pin1_t(pmod_jb_pin1_t),
        .pmod_jb_pin2_i(pmod_jb_pin2_i),
        .pmod_jb_pin2_o(pmod_jb_pin2_o),
        .pmod_jb_pin2_t(pmod_jb_pin2_t),
        .pmod_jb_pin3_i(pmod_jb_pin3_i),
        .pmod_jb_pin3_o(pmod_jb_pin3_o),
        .pmod_jb_pin3_t(pmod_jb_pin3_t),
        .pmod_jb_pin4_i(pmod_jb_pin4_i),
        .pmod_jb_pin4_o(pmod_jb_pin4_o),
        .pmod_jb_pin4_t(pmod_jb_pin4_t),
        .pmod_jb_pin7_i(pmod_jb_pin7_i),
        .pmod_jb_pin7_o(pmod_jb_pin7_o),
        .pmod_jb_pin7_t(pmod_jb_pin7_t),
        .pmod_jb_pin8_i(pmod_jb_pin8_i),
        .pmod_jb_pin8_o(pmod_jb_pin8_o),
        .pmod_jb_pin8_t(pmod_jb_pin8_t),
        .pmod_jb_pin9_i(pmod_jb_pin9_i),
        .pmod_jb_pin9_o(pmod_jb_pin9_o),
        .pmod_jb_pin9_t(pmod_jb_pin9_t),
        .rgbled_6bits_tri_o(rgbled_6bits_tri_o),
        .sADC_CS_0(sADC_CS_0),
        .sADC_SDIO_0(sADC_SDIO_0),
        .sADC_Sclk_0(sADC_Sclk_0),
        .sCh1CouplingH_0(sCh1CouplingH_0),
        .sCh1CouplingL_0(sCh1CouplingL_0),
        .sCh1GainH_0(sCh1GainH_0),
        .sCh1GainL_0(sCh1GainL_0),
        .sCh2CouplingH_0(sCh2CouplingH_0),
        .sCh2CouplingL_0(sCh2CouplingL_0),
        .sCh2GainH_0(sCh2GainH_0),
        .sCh2GainL_0(sCh2GainL_0),
        .sDAC_CS_0(sDAC_CS_0),
        .sDAC_ClkIO_0(sDAC_ClkIO_0),
        .sDAC_Clkin_0(sDAC_Clkin_0),
        .sDAC_Data_0(sDAC_Data_0),
        .sDAC_EnOut_0(sDAC_EnOut_0),
        .sDAC_Reset_0(sDAC_Reset_0),
        .sDAC_SCLK_0(sDAC_SCLK_0),
        .sDAC_SDIO_0(sDAC_SDIO_0),
        .sDAC_SetFS1_0(sDAC_SetFS1_0),
        .sDAC_SetFS2_0(sDAC_SetFS2_0),
        .sRelayComH_0(sRelayComH_0),
        .sRelayComL_0(sRelayComL_0),
        .sys_clock(sys_clock));
    
    IOBUF pmod_ja_pin10_iobuf(
        .I(pmod_ja_pin10_o),
        .IO(pmod_ja_pin10_io),
        .O(pmod_ja_pin10_i),
        .T(pmod_ja_pin10_t));
    IOBUF pmod_ja_pin1_iobuf(
        .I(pmod_ja_pin1_o),
        .IO(pmod_ja_pin1_io),
        .O(pmod_ja_pin1_i),
        .T(pmod_ja_pin1_t));
    IOBUF pmod_ja_pin2_iobuf(
        .I(pmod_ja_pin2_o),
        .IO(pmod_ja_pin2_io),
        .O(pmod_ja_pin2_i),
        .T(pmod_ja_pin2_t));
    IOBUF pmod_ja_pin3_iobuf(
        .I(pmod_ja_pin3_o),
        .IO(pmod_ja_pin3_io),
        .O(pmod_ja_pin3_i),
        .T(pmod_ja_pin3_t));
    IOBUF pmod_ja_pin4_iobuf(
        .I(pmod_ja_pin4_o),
        .IO(pmod_ja_pin4_io),
        .O(pmod_ja_pin4_i),
        .T(pmod_ja_pin4_t));
    IOBUF pmod_ja_pin7_iobuf(
        .I(pmod_ja_pin7_o),
        .IO(pmod_ja_pin7_io),
        .O(pmod_ja_pin7_i),
        .T(pmod_ja_pin7_t));
    IOBUF pmod_ja_pin8_iobuf(
        .I(pmod_ja_pin8_o),
        .IO(pmod_ja_pin8_io),
        .O(pmod_ja_pin8_i),
        .T(pmod_ja_pin8_t));
    IOBUF pmod_ja_pin9_iobuf(
        .I(pmod_ja_pin9_o),
        .IO(pmod_ja_pin9_io),
        .O(pmod_ja_pin9_i),
        .T(pmod_ja_pin9_t));
    IOBUF pmod_jb_pin10_iobuf(
        .I(pmod_jb_pin10_o),
        .IO(pmod_jb_pin10_io),
        .O(pmod_jb_pin10_i),
        .T(pmod_jb_pin10_t));
    IOBUF pmod_jb_pin1_iobuf(
        .I(pmod_jb_pin1_o),
        .IO(pmod_jb_pin1_io),
        .O(pmod_jb_pin1_i),
        .T(pmod_jb_pin1_t));
    IOBUF pmod_jb_pin2_iobuf(
        .I(pmod_jb_pin2_o),
        .IO(pmod_jb_pin2_io),
        .O(pmod_jb_pin2_i),
        .T(pmod_jb_pin2_t));
    IOBUF pmod_jb_pin3_iobuf(
        .I(pmod_jb_pin3_o),
        .IO(pmod_jb_pin3_io),
        .O(pmod_jb_pin3_i),
        .T(pmod_jb_pin3_t));
    IOBUF pmod_jb_pin4_iobuf(
        .I(pmod_jb_pin4_o),
        .IO(pmod_jb_pin4_io),
        .O(pmod_jb_pin4_i),
        .T(pmod_jb_pin4_t));
    IOBUF pmod_jb_pin7_iobuf(
        .I(pmod_jb_pin7_o),
        .IO(pmod_jb_pin7_io),
        .O(pmod_jb_pin7_i),
        .T(pmod_jb_pin7_t));
    IOBUF pmod_jb_pin8_iobuf(
        .I(pmod_jb_pin8_o),
        .IO(pmod_jb_pin8_io),
        .O(pmod_jb_pin8_i),
        .T(pmod_jb_pin8_t));
    IOBUF pmod_jb_pin9_iobuf(
        .I(pmod_jb_pin9_o),
        .IO(pmod_jb_pin9_io),
        .O(pmod_jb_pin9_i),
        .T(pmod_jb_pin9_t));
        
    // phase increment logic module instantiation
    bb_logic bb_logic_i(
        .clk(FCLK_CLK1),
        .DDS_S_AXIS_PHASE_tdata(DDS_S_AXIS_PHASE_tdata),
        .DDS_S_AXIS_PHASE_tlast(DDS_S_AXIS_PHASE_tlast),
        .DDS_S_AXIS_PHASE_tready(DDS_S_AXIS_PHASE_tready),
        .DDS_S_AXIS_PHASE_tvalid(DDS_S_AXIS_PHASE_tvalid));
    
endmodule

對(duì)于 DDS 的輸出頻率,我暫時(shí)選擇對(duì)其進(jìn)行硬核,以確保模塊設(shè)計(jì)中的 DDS 編譯器集成是正確的。由于 DAC 和 ADC 的最大采樣率為 100Ms/s,因此按照 Nyquist 的最大輸出頻率為 50MHz。我決定將 1MHz 作為一個(gè)簡(jiǎn)單的數(shù)字(請(qǐng)參閱我最初的DDS 編譯器教程,了解我如何計(jì)算 1MHz 的十六進(jìn)制值相位增量輸入)。

相位增量邏輯模塊文件 Verilog:

module bb_logic(
    input clk,
    output [31:0] DDS_S_AXIS_PHASE_tdata, // input to block design 
    output DDS_S_AXIS_PHASE_tlast,        // input to block design
    input DDS_S_AXIS_PHASE_tready,        // output from block design
    output DDS_S_AXIS_PHASE_tvalid        // input to block design
    );
    
    wire [31:0] Freq;
    wire [31:0] Freq_period;
    
    // setting the phase increment value to static for now
    assign Freq = 32'h28f5c2;
    assign Freq_period = 32'd100; // 1000ns/10ns = 100 --> max value here is 16384
    
    wire latch_tdata;
    
    // AXI stream state machine instantiation
    axis_sm axis_sm_i(
        .clk(clk),
        .reset(1'b1),
        .start(1'b1),
        .latch_tdata(latch_tdata),
        .s_phase_tvalid(DDS_S_AXIS_PHASE_tvalid), // output 
        .s_phase_tlast(DDS_S_AXIS_PHASE_tlast),   // output
        .s_phase_tready(DDS_S_AXIS_PHASE_tready), // input
        .s_phase_tdata(DDS_S_AXIS_PHASE_tdata),   // output
        .carrier_freq(Freq),
        .carrier_period(Freq_period)
    );
endmodule

AXI Stream 協(xié)議狀態(tài)機(jī):

module axis_sm(
    input clk,
    input reset,
    input start,
    output reg latch_tdata,
    output reg s_phase_tvalid,
    output reg s_phase_tlast,
    input s_phase_tready,
    output reg [31:0] s_phase_tdata,
    input [31:0] carrier_freq,
    input [31:0] carrier_period
    );
    
    reg [4:0] state_reg;
    reg [31:0] period_wait_cnt;
    
    parameter init               = 5'd0;
    parameter WaitForStart       = 5'd1;
    parameter SetTvalidHigh      = 5'd2;
    parameter SetSlavePhaseValue = 5'd3;
    parameter LatchTdata         = 5'd4;
    parameter CheckTready        = 5'd5;
    parameter WaitState          = 5'd6;   
    parameter SetTlastHigh       = 5'd7;
    parameter WaitOneState       = 5'd8;
    parameter SetTlastLow        = 5'd9;
    
    parameter set_freq           = 1'b0;
    parameter set_phase          = 1'b1; 
    
    parameter default_tdata      = 32'h0;
    
    always @ (posedge clk or posedge reset)
        begin                    
            // Default Outputs   
            latch_tdata          <= 1'b0;
            
            if (reset == 1'b0)
                begin
                    s_phase_tdata[31:0] <= default_tdata;
                    state_reg <= init;
                end
            else
                begin
                    case(state_reg)
                        init : //0
                            begin
                                latch_tdata <= 1'b0;
                                s_phase_tlast <= 1'b0;
                                s_phase_tvalid <= 1'b0;
                                period_wait_cnt <= 32'd0;
                                state_reg <= WaitForStart;
                            end
                            
                        WaitForStart : //1
                            begin
                                if (start == 1'b1)
                                    begin
                                        state_reg <= SetTvalidHigh;
                                    end
                                else
                                    begin
                                        state_reg <= WaitForStart;
                                    end
                            end
                            
                        SetTvalidHigh : //2
                            begin
                                s_phase_tvalid <= 1'b1;
                                state_reg <= SetSlavePhaseValue;
                            end
                            
                        SetSlavePhaseValue : //3
                            begin
                                s_phase_tdata[31:0] <= carrier_freq;
                                state_reg <= LatchTdata;
                            end
                            
                        LatchTdata : //4
                            begin
                                latch_tdata <= 1'b1;
                                state_reg <= CheckTready;
                            end
                            
                        CheckTready : //5
                            begin
                                if (s_phase_tready == 1'b1)
                                    begin
                                        state_reg <= WaitState;
                                    end
                                else if (start == 1'b0)
                                    begin
                                        state_reg <= init;
                                    end
                                else    
                                    begin
                                        state_reg <= CheckTready;
                                    end
                            end
                            
                        WaitState : //6
                            begin
                                if (period_wait_cnt >= carrier_period)
                                    begin
                                        period_wait_cnt <= 32'd0; 
                                        state_reg <= SetTlastHigh;
                                    end
                                else
                                    begin
                                        period_wait_cnt <= period_wait_cnt + 1;
                                        state_reg <= WaitState;
                                    end
                            end
                            
                        SetTlastHigh : //7
                            begin
                                s_phase_tlast <= 1'b1;
                                state_reg <= WaitOneState;
                            end
                            
                        WaitOneState : //8
                            begin
                                state_reg <= SetTlastLow;
                            end
                            
                        SetTlastLow : //9
                            begin
                                s_phase_tlast <= 1'b0;
                                state_reg <= WaitForStart;
                            end
                            
                    endcase 
                end
        end
endmodule

新的頂級(jí)文件與其他兩個(gè)文件一起完成后,保存所有文件,您將看到 Sources Hierarchy 自動(dòng)更新。通過(guò)右鍵單擊 Sources Hierarchy 選項(xiàng)卡中的 eclypse_top 文件并選擇“設(shè)置為頂部”選項(xiàng),將 eclypse_top 文件設(shè)置為項(xiàng)目的新頂部文件。

有了新的自定義頂級(jí)文件,暫時(shí)不再需要自動(dòng)生成的文件。不過(guò)我發(fā)現(xiàn)如果以后再更新積木設(shè)計(jì),還是有它就好了。再加上我多次了解到刪除 Vivado 自動(dòng)生成的文件會(huì)導(dǎo)致工具出現(xiàn)未定義行為這一事實(shí),我只是禁用了該文件。在 Sources Hierarchy 選項(xiàng)卡中右鍵單擊它,然后選擇“Disable”。更新后,您的 Sources Hierarchy 選項(xiàng)卡應(yīng)類似于以下內(nèi)容:

poYBAGN7JVCAFKr8AAIdsT9E52I531.png
?

正如我在之前的項(xiàng)目中提到的那樣,基礎(chǔ)項(xiàng)目的時(shí)間安排已經(jīng)結(jié)束。輸出到 SYZYGY 連接器上的 DAC Zmod 的數(shù)據(jù)線的保持時(shí)間不夠長(zhǎng)。我在之前的項(xiàng)目中沒(méi)有修復(fù)它,因?yàn)槲抑牢以谶@個(gè)項(xiàng)目中的添加會(huì)在實(shí)現(xiàn)過(guò)程中改變?cè)O(shè)計(jì)的位置和布線,并最終在一定程度上改變時(shí)序。幸運(yùn)的是,這個(gè)項(xiàng)目中的添加增加了足夠的延遲,我能夠簡(jiǎn)單地延長(zhǎng)約束文件中 DAC 數(shù)據(jù)線的保持時(shí)間(最后四行):

set_output_delay -clock [get_clocks sDAC_Clkin_0] -clock_fall -min -add_delay 0.330 [get_ports {sDAC_Data_0[*]}] 
set_output_delay -clock [get_clocks sDAC_Clkin_0] -clock_fall -max -add_delay 0.250 [get_ports {sDAC_Data_0[*]}]  
set_output_delay -clock [get_clocks sDAC_Clkin_0] -min -add_delay 0.330 [get_ports {sDAC_Data_0[*]}]           
set_output_delay -clock [get_clocks sDAC_Clkin_0] -max -add_delay 0.150 [get_ports {sDAC_Data_0[*]}]

約束文件更新后,運(yùn)行綜合、實(shí)現(xiàn)并生成比特流。完成后,驗(yàn)證沒(méi)有錯(cuò)誤或嚴(yán)重警告并導(dǎo)出硬件以在 Vitis 中使用。在“文件”菜單下,選擇“導(dǎo)出”下的“導(dǎo)出硬件...”選項(xiàng)。確認(rèn)您正在導(dǎo)出到與 Vitis 工作區(qū)中現(xiàn)有硬件平臺(tái)(XSA 文件)相同的位置,并選中包含比特流的選項(xiàng)。

poYBAGN7JVSALlxCAASJe-oaaQA694.png
將新硬件平臺(tái)導(dǎo)出到現(xiàn)有的 Vitis 工作區(qū)。
?

從 Vivado 的工具菜單中啟動(dòng) Vitis,然后選擇項(xiàng)目的現(xiàn)有工作區(qū)。同樣,我只是在此處修改我上一個(gè)項(xiàng)目教程中的現(xiàn)有裸機(jī)應(yīng)用程序,因此請(qǐng)參閱創(chuàng)建新的 Vitis 項(xiàng)目和應(yīng)用程序。

ZMOD 裸機(jī)庫(kù)對(duì) ADC 和 DAC 起作用的方式是,它們通過(guò) DMA 交換從 Eclypse 上的 DDR 存儲(chǔ)器填充緩沖區(qū)。對(duì)于 DAC,Digilent 的原始設(shè)計(jì)僅啟用了讀取通道(內(nèi)存映射到流或 MM2S)。由于我們啟用了寫入通道(流到內(nèi)存映射或 S2MM),因此還需要更新庫(kù)以反映現(xiàn)在有一個(gè)雙向的 DMA 實(shí)例。

pYYBAGN7JVeASmFLAAJk12N6x6w849.png
?

//zmodlib/Zmod/中的 DMA 文件開(kāi)始,我向 dma.h 中的 dma_direction 枚舉器添加了一個(gè)新類型,以指定一個(gè)能夠讀取和寫入事務(wù)的 DMA 實(shí)例。單向 DMA 傳輸?shù)墓δ茉?ZMOD 實(shí)例創(chuàng)建后不允許改變方向,因此我為雙向類型 DMA 添加了兩個(gè)函數(shù),一個(gè)用于 S2MM 傳輸,一個(gè)用于 MM2S 傳輸。

修改dma.h:

#ifndef DMA_H_
#define DMA_H_
#include 

/**
* Direction of a DMA transfer.
*/
enum dma_direction {
DMA_DIRECTION_TX, ///< TX transfer
DMA_DIRECTION_RX, ///< RX transfer
DMA_DIRECTION_TRX ///< TX & RX transfer
};

uint32_t fnInitDMA(uintptr_t addr, enum dma_direction direction, int dmaInterrupt);
void fnDestroyDMA(uintptr_t addr);
int fnOneWayDMATransfer(uintptr_t addr, uint32_t *buf, size_t length);
int fnS2MM_DMATransferCont(uintptr_t addr, uint32_t *buf, size_t transfer_size, int num_transfers);
int fnMM2S_DMATransfer(uintptr_t addr, uint32_t *buf, size_t transfer_size);
uint8_t fnIsDMATransferComplete(uintptr_t addr);
void* fnAllocBuffer(uintptr_t addr, size_t size);
void fnFreeBuffer(uintptr_t addr, void *buf, size_t size);

#endif /* DMA_H_ */

dma.c 中添加了新的 DMA 傳輸函數(shù):

S2MM DMA傳輸功能:

int fnS2MM_DMATransferCont(uintptr_t addr, uint32_t *buf, size_t transfer_size, int num_transfers){

    DMAEnv *dmaEnv = (DMAEnv *)addr;
    if (!dmaEnv)
        return -1;

    dmaEnv->complete_flag = 0;

    if(dmaEnv->direction != DMA_DIRECTION_TRX){
    return -1;
    } else {
        // S2MM - read in DDS data
        // Associate data buffer
        writeDMAReg(dmaEnv->base_addr, AXIDMA_REG_ADDR_S2MM_DA, (uint32_t)buf);

        // Set DMA RX Run bit, value 1, DMA register
        writeDMARegFld(dmaEnv->base_addr, AXIDMA_REGFLD_S2MM_DMACR_RUNSTOP, 1);

        for (int i=0;i<num_transfers;i++){
            // Start DMA Transfer
            writeDMAReg(dmaEnv->base_addr, AXIDMA_REG_ADDR_S2MM_DA_LENGTH, transfer_size);
        }
    }

    return 0;
}

MM2S DMA傳輸功能:

int fnMM2S_DMATransfer(uintptr_t addr, uint32_t *buf, size_t transfer_size){
DMAEnv *dmaEnv = (DMAEnv *)addr;
    if (!dmaEnv)
        return -1;

    dmaEnv->complete_flag = 0;

    if(dmaEnv->direction != DMA_DIRECTION_TRX){
        return -1;
    } else {
        // MM2S - write out to DAC
        // Associate data buffer
        writeDMAReg(dmaEnv->base_addr, AXIDMA_REG_ADDR_MM2S_SA, (uint32_t)buf);
        
        // Set DMA RX Run bit, value 1, DMA register
        writeDMARegFld(dmaEnv->base_addr, AXIDMA_REGFLD_MM2S_DMACR_RUNSTOP, 1);

        // Start DMA Transfer
        writeDMAReg(dmaEnv->base_addr, AXIDMA_REG_ADDR_MM2S_SA_LENGTH, transfer_size);
    }

    return 0;
}

DMA 函數(shù)是從 ZMOD 基礎(chǔ)庫(kù)中調(diào)用的,因此還需要添加兩個(gè)函數(shù)。一個(gè)啟動(dòng) MM2S DMA 事務(wù),一個(gè)啟動(dòng) S2MM DMA 事務(wù)(不要忘記將這些函數(shù)原型也添加到 Zmod.h)。

新的 Zmod.cpp 功能:

/**
* Start a DMA S2MM transfer using the transfer length configured previously.
*
* @return 0 on success, any other number on failure
*/
int ZMOD::startS2MMTransferCont(uint32_t* buffer, int num_transfers){
    // transfer length is not configured
    if (transferSize < 1) {
        return ERR_FAIL;
    }
    return fnS2MM_DMATransferCont(dmaAddr, buffer, transferSize, num_transfers);
}

/**
* Start a DMA MM2S transfer using the transfer length configured previously.
*
* @return 0 on success, any other number on failure
*/
int ZMOD::startMM2STransfer(uint32_t* buffer){
    // transfer length is not configured
    if (transferSize < 1) {
        return ERR_FAIL;
    }

    return fnMM2S_DMATransfer(dmaAddr, buffer, transferSize);
}

最后,在 DAC ZMOD 特定庫(kù)中,需要兩個(gè)新函數(shù)通過(guò) DMA S2MM 事務(wù)從 DDS 編譯器向 DDR 寫入一段正弦波,并將該數(shù)據(jù)從 DDR 讀取到緩沖區(qū)以通過(guò) DMA 發(fā)送到 DAC MM2S 交易。還需要修改 DAC 實(shí)例的初始化,以指示附加到它的 DMA 現(xiàn)在是雙向的(能夠進(jìn)行讀取/MM2S 和寫入/S2MM 事務(wù))。

修改了 DAC ZMOD 的 init 實(shí)例函數(shù)以對(duì) DMA 使用新的雙向類型:

ZMODDAC1411::ZMODDAC1411(uintptr_t baseAddress, uintptr_t dmaAddress, uintptr_t iicAddress, uintptr_t flashAddress, int dmaInterrupt)
: ZMOD(baseAddress, dmaAddress, iicAddress, flashAddress, DMA_DIRECTION_TRX, -1, dmaInterrupt)
{
    ZMOD::initCalib(sizeof(CALIBECLYPSEDAC), ZMODDAC1411_CALIB_ID, ZMODDAC1411_CALIB_USER_ADDR, ZMODDAC1411_CALIB_FACT_ADDR);
}

將 DDS 編譯器輸出寫入 DDR 內(nèi)存的函數(shù):

/*
* Reads in the data values being output by the DDS Compiler and writes them to a
* memory location in the DDR
* @param none
* @return the status: ERR_SUCCESS for success*/
int ZMODDAC1411::readInDDSdata(uint32_t* buffer, size_t &length, int num_transfers){
    uint8_t Status;
    if(length > ZmodDAC1411_MAX_BUFFER_LEN){
        length = ZmodDAC1411_MAX_BUFFER_LEN;
    }

    // DMA TX transfer length in number of elements
    // multiply by the size of the data
    setTransferSize(length * sizeof(uint32_t));

    // Start DMA Transfer
    Status = startS2MMTransferCont(buffer, num_transfers);
    if (Status) {
        return ERR_FAIL;
    }

    return ERR_SUCCESS;
}

將 DDS 輸出數(shù)據(jù)從 DDR 讀取到 DAC ZMOD 緩沖區(qū)的函數(shù):

int ZMODDAC1411::sendDDSdataToDAC(uint32_t* buffer, size_t &length){
    uint8_t Status;
    if(length > ZmodDAC1411_MAX_BUFFER_LEN)
{
length = ZmodDAC1411_MAX_BUFFER_LEN;
}
// DMA TX transfer length in number of elements
// multiply by the size of the data
setTransferSize(length * sizeof(uint32_t));
// Start DMA Transfer
Status = startMM2STransfer(buffer);
if (Status) {
return ERR_FAIL;
}
// // Wait for DMA to Complete transfer
// while(!isDMATransferComplete()) {}
return ERR_SUCCESS;
}

隨著 ZMOD 裸機(jī)庫(kù)的更新,主要功能相當(dāng)簡(jiǎn)單。主函數(shù)首先創(chuàng)建 DAC ZMOD 的實(shí)例,然后設(shè)置 14 位輸出采樣分頻器和通道一的增益值。然后為緩沖區(qū)分配內(nèi)存,以 DMA 能夠達(dá)到的最大長(zhǎng)度(0x3fff 或 16384)將數(shù)據(jù)從 DDS 讀取到 DDR,并分配另一個(gè)緩沖區(qū)以將數(shù)據(jù)發(fā)送到 DAC。

一個(gè)周期的 1MHz 正弦波正從 DDR 內(nèi)存(相當(dāng)于 50 個(gè)樣本)讀取到第一個(gè)緩沖區(qū)中。然后將其冗余復(fù)制到第二個(gè)緩沖區(qū)中,直到緩沖區(qū)已滿。然后將該緩沖區(qū)發(fā)送到 DAC 并啟動(dòng) DAC。一旦數(shù)據(jù)成功發(fā)送到 DAC,兩個(gè)緩沖區(qū)的內(nèi)存都會(huì)被釋放,DAC 會(huì)無(wú)限運(yùn)行,輸出 1MHz 正弦波。

對(duì)于 ADC,我只是重用了我在上一個(gè)項(xiàng)目中使用的 Digilent 的 ADC 演示功能。此 ADC 演示功能啟動(dòng) ADC 以連續(xù)捕獲和無(wú)限循環(huán)并格式化數(shù)據(jù)以輸出到 UART 控制臺(tái)。

主要功能代碼:

#include 
#include 
#include 
#include "xaxidma.h"
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"

#include "./zmodlib/Zmod/zmod.h"
#include "./zmodlib/ZmodADC1410/zmodadc1410.h"
#include "./zmodlib/ZmodDAC1411/zmoddac1411.h"
#include "./zmodlib/Zmod/dma.h"

#define TRANSFER_LEN  0x400

// ZMOD ADC parameters
#define ZMOD_ADC_BASE_ADDR  XPAR_AXI_ZMODADC1410_0_S00_AXI_BASEADDR
#define DMA_ADC_BASE_ADDR  XPAR_AXI_DMA_ADC_BASEADDR
#define IIC_BASE_ADDR  XPAR_PS7_I2C_1_BASEADDR
#define FLASH_ADDR_ADC   0x30
#define ZMOD_ADC_IRQ  XPAR_FABRIC_AXI_ZMODADC1410_0_LIRQOUT_INTR
#define DMA_ADC_IRQ  XPAR_FABRIC_AXI_DMA_ADC_S2MM_INTROUT_INTR

//ZMOD DAC parameters
#define ZMOD_DAC_BASE_ADDR  XPAR_AXI_ZMODDAC1411_V1_0_0_BASEADDR
#define DMA_DAC_BASE_ADDR  XPAR_AXI_DMA_DAC_BASEADDR
#define FLASH_ADDR_DAC   0x31
#define DMA_DAC_IRQ  XPAR_FABRIC_AXI_DMA_DAC_MM2S_INTROUT_INTR
#define IIC_BASE_ADDR  XPAR_PS7_I2C_1_BASEADDR

//DMA for DDS output - XPAR_AXI_DMA_DDS_DEVICE_ID
#define MEM_BASE_ADDR (XPAR_PS7_DDR_0_S_AXI_BASEADDR + 0x1000000)
#define TRX_BUFFER_BASE (MEM_BASE_ADDR + 0x00100000)
#define TRX_BUFFER_HIGH (MEM_BASE_ADDR + 0x004FFFFF)

/*
* Simple ADC test, puts the ADC in the test mode (ramp),
* performs an acquisition under specific trigger conditions
* and verifies the acquired data to be consistent with these conditions.
*/
void testZMODADC1410Ramp_Auto(){

    ZMODADC1410 adcZmod(ZMOD_ADC_BASE_ADDR, DMA_ADC_BASE_ADDR, IIC_BASE_ADDR, FLASH_ADDR_ADC,
ZMOD_ADC_IRQ, DMA_ADC_IRQ);

    if(adcZmod.autoTestRamp(1, 0, 0, 4, TRANSFER_LEN) == ERR_SUCCESS){
        xil_printf("Success autotest ADC ramp\r\n");
    } else {
        xil_printf("Error autotest ADC ramp\r\n");
    }
}

/*
* Format data contained in the buffer and sends it over UART.
* It displays the acquired value (in mV), raw value (as 14 bits hexadecimal value)
* and time stamp within the buffer (in time units).
* @param padcZmod - pointer to the ZMODADC1410 object
* @param acqBuffer - the buffer containing acquired data
* @param channel - the channel where samples were acquired
* @param gain - the gain for the channel
* @param length - the buffer length to be used
*/
void formatADCDataOverUART(ZMODADC1410 *padcZmod, uint32_t *acqBuffer, uint8_t channel, uint8_t gain, size_t length){

    char val_formatted[15];
    char time_formatted[15];
    uint32_t valBuf;
    int16_t valCh;
    float val;

    xil_printf("New acquisition ------------------------\r\n");
    xil_printf("Ch1\tRaw\tTime\t\r\n");

    for (size_t i = 0; i < length; i++){
        valBuf = acqBuffer[i];
        valCh = padcZmod->signedChannelData(channel, valBuf);
        val = padcZmod->getVoltFromSignedRaw(valCh, gain);
        padcZmod->formatValue(val_formatted, 1000.0*val, "mV");

        if (i < 100){
            padcZmod->formatValue(time_formatted, i*10, "ns");
        } else {
            padcZmod->formatValue(time_formatted, (float)(i)/100.0, "us");
        }

        xil_printf("%s\t%X\t%s\r\n", val_formatted, (uint32_t)(valCh&0x3FFF), time_formatted);
    }
}

/*
* Simple ADC test, acquires data and sends it over UART.
* @param channel - the channel where samples will be acquired
* @param gain - the gain for the channel
* @param length - the buffer length to be used
*/
void adcDemo(uint8_t channel, uint8_t gain, size_t length){
    ZMODADC1410 adcZmod(ZMOD_ADC_BASE_ADDR, DMA_ADC_BASE_ADDR, IIC_BASE_ADDR, FLASH_ADDR_ADC,
ZMOD_ADC_IRQ, DMA_ADC_IRQ);

    uint32_t *acqBuffer;
    adcZmod.setGain(channel, gain);

    while(1){
        acqBuffer = adcZmod.allocChannelsBuffer(length);
        adcZmod.acquireImmediatePolling(acqBuffer, length);
        formatADCDataOverUART(&adcZmod, acqBuffer, channel, gain, length);
        adcZmod.freeChannelsBuffer(acqBuffer, length);
        sleep(2);
    }
}

int main(){
    init_platform();
    xil_printf("Eclypse Z7 SDR baseband data generator...\r\n");

    // init DAC Zmod
    ZMODDAC1411 dacZmod(ZMOD_DAC_BASE_ADDR, DMA_DAC_BASE_ADDR, IIC_BASE_ADDR, FLASH_ADDR_DAC, DMA_DAC_IRQ);

    // max buffer length:
    size_t length = 0x3fff; 

    dacZmod.setOutputSampleFrequencyDivider(2);
    dacZmod.setGain(0, 1);

    int Status = 0;
    uint32_t *TrxBufferPtr;
    TrxBufferPtr = dacZmod.allocChannelsBuffer(length);

    for (int i=0;i<16383;i++){
        TrxBufferPtr[i] = 0;
    }

    uint32_t *acqBufferPtr;
    acqBufferPtr = dacZmod.allocChannelsBuffer(length);

    Status = dacZmod.readInDDSdata(TrxBufferPtr, length, 1);
    if (Status) {
        xil_printf("DMA MM2S error!...\r\n");
    }

    int start_index = 0;

    // copy the one period of sine wave into the buffer until its full    
    while (start_index<16000){
        for (int i=0;i<50;i++){
            acqBufferPtr[start_index+i] = TrxBufferPtr[i];
        }

        start_index = start_index + 50;
    }

    Status = dacZmod.sendDDSdataToDAC(acqBufferPtr, length);
        if (Status) {
            xil_printf("DMA S2MM error!...\r\n");
        }

    // start the instrument
    dacZmod.start();

    // free the buffers since it's been transferred to the DAC
    dacZmod.freeChannelsBuffer(TrxBufferPtr, length);
    dacZmod.freeChannelsBuffer(acqBufferPtr, length);

    // start channel 0 of the ADC collecting infinitely
    adcDemo(0, 0, length);

    cleanup_platform();

    return 0;
}

保存所有文件并構(gòu)建項(xiàng)目。

要運(yùn)行應(yīng)用程序并同時(shí)查看 ILA,首先通過(guò)右鍵單擊資源管理器窗口中的應(yīng)用程序名稱并選擇“Program FPGA”來(lái)對(duì) Eclypse 進(jìn)行編程。

poYBAGN7JVqAMTt6AAOr4GfJjXk489.png
?

請(qǐng)務(wù)必將比特流更改為新的比特流。當(dāng)您單擊比特流字段旁邊的“搜索...”按鈕時(shí),您會(huì)看到 Vitis 在項(xiàng)目中檢測(cè)到這兩者。

pYYBAGN7JV2AYSrHAABP2y7wYEE186.png
?

對(duì) Ecylpse 進(jìn)行編程后,再次右鍵單擊資源管理器窗口中的應(yīng)用程序名稱并在“調(diào)試為”下選擇“在硬件上啟動(dòng)(單個(gè)應(yīng)用程序調(diào)試)”,啟動(dòng)應(yīng)用程序的調(diào)試運(yùn)行。

pYYBAGN7JWCALEfFAAO6MdL4PAs982.png
?

一旦應(yīng)用程序遇到主函數(shù)入口斷點(diǎn),使用 Vitis 串行終端連接到 Eclypse 的 UART。

poYBAGN7JWKAYnlJAAAqaMEWKGs546.png
?

在單步執(zhí)行或運(yùn)行應(yīng)用程序之前,切換回 Vivado 并從 Flow Navigator 打開(kāi)硬件管理器。從 Open Target 選項(xiàng)中選擇自動(dòng)連接。

如果 ILA 窗口打開(kāi)并且不存在調(diào)試內(nèi)核,您可能需要從硬件管理器重新編程 FPGA。我發(fā)現(xiàn)這是 Vivado 版本 2019.2 的一個(gè)錯(cuò)誤。

在任何感興趣的 AXI 流協(xié)議上觸發(fā) ILA 中的觸發(fā)器并在 Vitis 中運(yùn)行應(yīng)用程序。我監(jiān)視了 DDS 編譯器的主 AXI 流端口和 DAC 的 DMA 的 AXI 流 S2MM 端口,以便在這個(gè)項(xiàng)目上進(jìn)行調(diào)試。

poYBAGN7JWaAHz_YAAYcwI1M6-U833.png
驗(yàn)證 DAC 緩沖區(qū)是否已填充將獲得 1MHz 正弦波的數(shù)據(jù)點(diǎn)。
?

一旦我能夠看到 ILA 中的正弦波環(huán)回工作以及 ADC ZMOD 的 UART 控制臺(tái)中的打印輸出,我決定啟動(dòng)我的老式頻譜分析儀,它位于我書柜的頂部架子上,看看 1MHz 正弦波是什么波實(shí)際上看起來(lái)像是從 DAC 端口的 SMA 端口出來(lái)的。

我的頻譜分析儀實(shí)際上是用于電視維修的,因此射頻輸入為 75 歐姆,因此使用 75 至 50 歐姆的巴倫和一些適配器電纜將其 BNC 輸入轉(zhuǎn)換為 ZMOD 的 SMA 端口并獲得日蝕相連。

正如你所看到的,對(duì)于一個(gè)應(yīng)該是單一頻率的純連續(xù)正弦波,它與一系列額外的頻率分量相當(dāng)混亂。我確信這與我荒謬的長(zhǎng) SMA 電纜和破解連接轉(zhuǎn)換有關(guān)。該頻譜分析儀自 1984 年以來(lái)還沒(méi)有進(jìn)行過(guò)正確校準(zhǔn),但使用它仍然可以很好地看到 DAC ZMOD 確實(shí)以 1MHz 的頻率發(fā)出了模擬信號(hào)。

我發(fā)現(xiàn)我擁有的 SMA 電纜比我擁有的任何 USB 電纜都長(zhǎng)得多,所以我最終將信號(hào)分析儀留在了我的書架頂部,并將 Eclypse 板放在我的辦公桌窩上,放在我的電腦上。

為什么我擁有比 USB 電纜更長(zhǎng)的 SMA 電纜???好問(wèn)題。我自己剛剛發(fā)現(xiàn)了這個(gè)異常。

總體而言,可以以非常簡(jiǎn)單的方式修改設(shè)計(jì),使 DDS 編譯器的相位增量和偏移輸入可編程,并最終使用 ZMOD 制作出 Eclypse 的基帶數(shù)據(jù)生成器。我會(huì)把它保存到另一個(gè)項(xiàng)目教程中!


下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評(píng)論

查看更多

下載排行

本周

  1. 1山景DSP芯片AP8248A2數(shù)據(jù)手冊(cè)
  2. 1.06 MB  |  532次下載  |  免費(fèi)
  3. 2RK3399完整板原理圖(支持平板,盒子VR)
  4. 3.28 MB  |  339次下載  |  免費(fèi)
  5. 3TC358743XBG評(píng)估板參考手冊(cè)
  6. 1.36 MB  |  330次下載  |  免費(fèi)
  7. 4DFM軟件使用教程
  8. 0.84 MB  |  295次下載  |  免費(fèi)
  9. 5元宇宙深度解析—未來(lái)的未來(lái)-風(fēng)口還是泡沫
  10. 6.40 MB  |  227次下載  |  免費(fèi)
  11. 6迪文DGUS開(kāi)發(fā)指南
  12. 31.67 MB  |  194次下載  |  免費(fèi)
  13. 7元宇宙底層硬件系列報(bào)告
  14. 13.42 MB  |  182次下載  |  免費(fèi)
  15. 8FP5207XR-G1中文應(yīng)用手冊(cè)
  16. 1.09 MB  |  178次下載  |  免費(fèi)

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234315次下載  |  免費(fèi)
  3. 2555集成電路應(yīng)用800例(新編版)
  4. 0.00 MB  |  33566次下載  |  免費(fèi)
  5. 3接口電路圖大全
  6. 未知  |  30323次下載  |  免費(fèi)
  7. 4開(kāi)關(guān)電源設(shè)計(jì)實(shí)例指南
  8. 未知  |  21549次下載  |  免費(fèi)
  9. 5電氣工程師手冊(cè)免費(fèi)下載(新編第二版pdf電子書)
  10. 0.00 MB  |  15349次下載  |  免費(fèi)
  11. 6數(shù)字電路基礎(chǔ)pdf(下載)
  12. 未知  |  13750次下載  |  免費(fèi)
  13. 7電子制作實(shí)例集錦 下載
  14. 未知  |  8113次下載  |  免費(fèi)
  15. 8《LED驅(qū)動(dòng)電路設(shè)計(jì)》 溫德?tīng)栔?/a>
  16. 0.00 MB  |  6656次下載  |  免費(fèi)

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935054次下載  |  免費(fèi)
  3. 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
  4. 78.1 MB  |  537798次下載  |  免費(fèi)
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420027次下載  |  免費(fèi)
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234315次下載  |  免費(fèi)
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費(fèi)
  11. 6電路仿真軟件multisim 10.0免費(fèi)下載
  12. 340992  |  191187次下載  |  免費(fèi)
  13. 7十天學(xué)會(huì)AVR單片機(jī)與C語(yǔ)言視頻教程 下載
  14. 158M  |  183279次下載  |  免費(fèi)
  15. 8proe5.0野火版下載(中文版免費(fèi)下載)
  16. 未知  |  138040次下載  |  免費(fèi)