10PL讀寫PS端DDR(FDMA AXI4總線實戰)


軟件版本:vitis2020.2(vivado2020.2)

操作系統:WIN10 64bit

硬件平台:適用XILINX A7/K7/Z7/ZU/KU系列FPGA(米聯客(milianke)MZU07A-EG硬件開發平台)

登錄"米聯客"FPGA社區-www.uisrc.com視頻課程、答疑解惑!

10.1概述

FDMA是米聯客的基於AXI4總線協議定制的一個DMA控制器。有了這個IP我們可以統一實現用FPGA代碼直接讀寫PL的DDR或者PS的DDR。本文中FDMA的IP是開源的,在配套FPGA工程的uisrc/ip路徑下可以找到源碼。本文的IP已經利用VIVADO做了圖形化的封裝,所以可以直接通過圖形化連線設計,使用非常方便。

本文實驗目的:

1:利用米聯客自定一定FDMA2.0/3.0版本搭建SOC工程(最新發布的版本是3.0)

2:編寫FPGA測試代碼實現,PL寫入數據到PS DDR然后再讀出PS DDR中的數據,對比是否正確。

 

為了讓PS的DDR可以運行,必須新建一個vitis-sdk工程,這個工程主要是為了初始化PS DDR,我們可以簡單新建一個自帶的hello工程。

10.2搭建SOC系統工程

新建一個名為為zu_prj的工程,之后創建一個BD文件,並命名為system,添加並且配置好ZYNQ Ultrascale+ MPSOC IP。讀者需要根據自己的硬件類型配置好輸入時鍾頻率、內存型號、串口,連接時鍾等。新手不清楚這些內容個,請參考"3-2-01_ex_soc_base_07a-eg .pdf" "01 HelloWold/DDR/網口測試"這篇文章。

10.2.1PS部分設置

1:PS復位設置

2:PS AXI HP0 FPD設置

3:PL輸出時鍾設置

10.2.2添加自定義IP

1:設置IP路徑

本文中是我們第一次在BD圖形化設計中添加自定義的IP,自定義的IP需要設置IP路徑才能被識別到。默認情況下,我們自定的IP在配套工程的uisrc/ip路徑下:

2:添加IP

10.2.3PL圖像化編程

10.2.4添加FPGA FDMA讀寫代碼

上圖中源碼在配套fpga工程的uisrc/rtl路徑中,本文中我們修改了默認的system_wrapper.v文件名為system_wrapper_fdma.v這樣的好處是對默認文件和手動修改過的文件加以區分,以免幸苦修改的代碼一不小心,被軟件自動更新替換掉。

關鍵的代碼為fdma_test.v。在這個程序中,寫入一定數據到DDR中,然后再讀出,對比是否有錯誤,幾個關鍵參數:

TEST_MEM_SIZE:定義了測試內從空間的大小,以byte為單位,是整數倍的FDMA_BURST_LEN *(fdma_wdata/8)。

FDMA_BURST_LEN:定義每次FDMA傳輸的長度,這個長度是整數倍的fdma_wdata或者fdma_rdata。

ADDR_MEM_OFFSET:代碼了內從訪問的起始地址。

`timescale 1ns / 1ns

/*

Company : Liyang Milian Electronic Technology Co., Ltd.

Brand: 米聯客(milianke)

Technical forum:uisrc.com

taobao: https://milianke.taobao.com https://osrc.taobao.com

jd:https://milianke.jd.com

Create Date: 2019/12/17

Module Name: fdma_test

Description:

Copyright: Copyright (c) milianke

Revision: 1.0

Signal description:

1) _i input

2) _o output

3) _n activ lowpai

4) _dg debug signal

5) _r delay or register

6) _s state mechine

*/

//////////////////////////////////////////////////////////////////////////////////

 

module fdma_test#

(

parameter TEST_MEM_SIZE = 32'd40960,

parameter FDMA_BURST_LEN = 16'd1024,

parameter ADDR_MEM_OFFSET = 1024*1024*500

)

(

input ui_clk,

input fdma_rstn,

output [31: 0] fdma_waddr,

output reg fdma_wareq,

output [15: 0] fdma_wsize,

input fdma_wbusy,        

output reg [127:0] fdma_wdata,

input fdma_wvalid,

output reg fdma_wready,

 

output [31: 0] fdma_raddr,

output reg fdma_rareq,

output [15: 0] fdma_rsize,

input fdma_rbusy,            

input [127:0] fdma_rdata,

input fdma_rvalid,

output reg fdma_rready    

);

parameter WRITE1 = 0;

parameter WRITE2 = 1;

parameter READ1 = 2;

parameter READ2 = 3;

 

reg [31: 0] fdma_waddr_r;

reg [16 :0] fdma_rcnt = 0;

reg [2 :0] T_S = 0;

 

assign fdma_waddr = fdma_waddr_r + ADDR_MEM_OFFSET;

assign fdma_raddr = fdma_waddr;

 

assign fdma_wsize = FDMA_BURST_LEN;

assign fdma_rsize = FDMA_BURST_LEN;

 

reg [10:0] rst_cnt = 0;

 

always @(posedge ui_clk)

if(fdma_rstn == 1'b0)begin

rst_cnt <=0;

end

else begin

if(rst_cnt[10] == 1'b0)

rst_cnt <= rst_cnt + 1'b1;

else

rst_cnt <= rst_cnt;

end

 

always @(posedge ui_clk)begin

if(rst_cnt[10] == 1'b0)begin

T_S <=0;

fdma_wareq <= 1'b0;

fdma_rareq <= 1'b0;

fdma_wready <= 1'b0;

fdma_rready <= 1'b0;

fdma_wdata <=0;

fdma_waddr_r <=0;

end

else begin

case(T_S)

WRITE1:begin

if(fdma_waddr_r>TEST_MEM_SIZE) fdma_waddr_r<=0;

if(!fdma_wbusy)begin

fdma_wareq <= 1'b1;

fdma_wready <= 1;

fdma_wdata <= 0;

end

if(fdma_wareq&&fdma_wbusy)begin

fdma_wareq <= 1'b0;

T_S <= WRITE2;

end

end

WRITE2:begin

if(!fdma_wbusy) begin

T_S <= READ1;

fdma_wready <= 0;

fdma_wdata <= 32'd0;

end

else if(fdma_wvalid) begin

fdma_wdata <= fdma_wdata + 1'b1;

end

end

 

READ1:begin

if(!fdma_rbusy)begin

fdma_rareq <= 1'b1;

fdma_rready <= 1;

fdma_rcnt <= 0;

end

if(fdma_rareq&&fdma_rbusy)begin

fdma_rareq <= 1'b0;

T_S <= READ2;

end

end

READ2:begin

if(!fdma_rbusy) begin

T_S <= WRITE1;

fdma_rready <= 0;

fdma_rcnt <= 32'd0;

fdma_waddr_r <= fdma_waddr_r + FDMA_BURST_LEN*128/8;

end

else if(fdma_rvalid) begin

fdma_rcnt <= fdma_rcnt + 1'b1;

end

end

default:

T_S <= WRITE1;

endcase

end

end

 

wire test_error = ((fdma_rready&&fdma_rvalid) && (fdma_rcnt[15:0] != fdma_rdata[15:0]));

 

ila_0 ila_dbg (

    .clk(ui_clk),

    .probe0({fdma_waddr[15:0],fdma_wdata[15:0],fdma_wareq,fdma_wvalid,fdma_wready,fdma_wbusy}),

    .probe1({fdma_rdata[15:0],fdma_rcnt[15:0],fdma_rvalid,fdma_rready,fdma_rbusy,T_S,test_error})

);

 

endmodule 

10.2.5設置地址分配

10.2.6編譯並導出平台文件

1:單擊Block文件à右鍵àGenerate the Output ProductsàGlobalàGenerate。

2:單擊Block文件à右鍵à Create a HDL wrapper(生成HDL頂層文件)àLet vivado manager wrapper and auto-update(自動更新)。

3:生成Bit文件。

4:導出到硬件: FileàExport HardwareàInclude bitstream

5:導出完成后,對應工程路徑的zu_hw路徑下有硬件平台文件:system_wrapper.xsa的文件。根據硬件平台文件system_wrapper.xsa來創建需要Platform平台。

10.3搭建Vitis-sdk工程

創建zu_base sdk platform和APP工程的過程不再重復,可以閱讀本章節01~05相關demo。以下給出創建好zu_base sdk platform的截圖和對應工程APP的截圖。

10.3.1創建SDK Platform工程

10.3.2創建hello APP工程

10.4實驗結果

1:先運行hello app

2:打開設備

3:如果沒有出來下圖的hw_ila 波形窗口,右擊刷新

4:觀察在線邏輯分析結果

5:寫入過程

6:讀出過程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM