ZYNQ学习之路4.ZYNQ通过GP口读取PL内部RAM数据
實(shí)驗(yàn)環(huán)境:window 7 64 bit, vivado 2017.1, ZTURN board.
參考手冊(cè):Xilinx Distributed Memory Generator
? ? ? ? 在ZYNQ開(kāi)發(fā)中,經(jīng)常需要PS與PL進(jìn)行數(shù)據(jù)交互。當(dāng)數(shù)據(jù)量比較大時(shí)往往需要先緩存一部分然后批量傳輸?shù)絃inux系統(tǒng),否則中斷響應(yīng)時(shí)間無(wú)法滿足要求,使用雙端口RAM或許是一種不錯(cuò)的方法。本文詳細(xì)描述PS端讀寫(xiě)PL端片的雙端口RAM數(shù)據(jù)的實(shí)驗(yàn)過(guò)程。本次實(shí)驗(yàn)使用FPGA內(nèi)部的Block Memory,PS端通過(guò)Master GP0端口向RAM寫(xiě)數(shù)據(jù),通過(guò)Master GP1端口讀出數(shù)據(jù),本次實(shí)驗(yàn)涉及到AXI BRAM Controller和Block Memory Generator等IP核。
一. SRAM介紹
1.1 雙端口RAM結(jié)構(gòu)
? ? ? ? Xilinx的ZYNQ7Z010內(nèi)部FPGA是virtex7系列,內(nèi)部有32KB的Block Memory,可以用它作為ROM,Single-Port RAM, Dual-Port RAM或Simple Dual-Port RAM, RAM的區(qū)別在于讀寫(xiě)數(shù)據(jù)線與地址總線的數(shù)量的區(qū)別,根據(jù)自己的需求進(jìn)行選擇。
| RAM類型 | 功能 | 數(shù)據(jù)總線數(shù)量 | 地址總線數(shù)量 |
| Single-Port | 通過(guò)一個(gè)端口進(jìn)行數(shù)據(jù)的讀寫(xiě)操作 | 1 | 1 |
| Dual-Port | 通過(guò)兩個(gè)端口讀寫(xiě)數(shù)據(jù) | 2 | 2 |
| Simple Dual-Port | 一個(gè)端口進(jìn)行寫(xiě)操作,另一個(gè)端口進(jìn)行讀操作 | 1 | 2 |
? ? ? ? 雙端口RAM示意圖如下:
圖1-1.雙端口RAM示意圖題? ? ? ? 雙端口RAM相比其他幾種RAM更復(fù)雜,所以本文只介紹雙端口RAM的使用。
1.2 雙端口RAM控制信號(hào)
? ? ? ? 上文中的示意圖中只列出了基本且常用的信號(hào),其他特殊信號(hào)在次不做介紹。常用控制信號(hào)功能定義如下:
| 信號(hào) | 方向 | 描述 |
| din[31:0] | Input | 數(shù)據(jù)總線輸入,32位寬 |
| addr[31:0] | Input | 地址總線輸入,32位寬,地址從0開(kāi)始,有效至容量大小 |
| clk | Input | 時(shí)鐘信號(hào)輸入,1位,寫(xiě)同步時(shí)鐘 |
| en | Input | 使能讀,寫(xiě),復(fù)位選項(xiàng) |
| rst | Input | 復(fù)位或置位讀出鎖存寄存器,如果要讀出需要置置 |
| wea[3:0] | Input | 寫(xiě)使能 |
| dout[31:0] | Output | 數(shù)據(jù)輸出,32位寬 |
? ? ? ? 雙端口RAM的工作模式有三種,寫(xiě)優(yōu)先、讀優(yōu)先和無(wú)變化模式。
寫(xiě)優(yōu)先模式:數(shù)據(jù)同時(shí)寫(xiě)入到內(nèi)存并輸出到數(shù)據(jù)端口,時(shí)序如圖1-2所示:
圖1-2: Write First Mode Example讀優(yōu)先模式:當(dāng)要寫(xiě)入內(nèi)存數(shù)據(jù)時(shí),先前存儲(chǔ)的數(shù)據(jù)在寫(xiě)地址有效前存儲(chǔ)到數(shù)據(jù)輸出總線上。時(shí)序圖如圖1-3所示:
圖1-3:Read First Mode Example無(wú)變化模式: 輸出鎖存器在寫(xiě)入內(nèi)存期間不改變值。時(shí)序圖如圖1-4所示:
圖1-4:No Change Mode Example1.3 字節(jié)寫(xiě)操作
在使用32為數(shù)據(jù)總線時(shí),數(shù)據(jù)按32位同時(shí)變化,如果只寫(xiě)入8,16,24位的數(shù)據(jù)或者間隔一個(gè)字節(jié)寫(xiě)入兩個(gè)不連續(xù)的字節(jié),這是可以使用WE信號(hào),首先看看圖1-5時(shí)序圖。
圖1-5: Byte-write Example標(biāo)題圖中第一個(gè)上升沿到來(lái)之時(shí),數(shù)據(jù)輸入0xFFEEDD,WEA=0x011,寫(xiě)入內(nèi)容變?yōu)?x00FFDD,只有后面兩個(gè)字節(jié)寫(xiě)入成功,可以發(fā)現(xiàn)WEA的某個(gè)bit位置1時(shí)對(duì)應(yīng)數(shù)據(jù)輸入的字節(jié)將被寫(xiě)入,其他字節(jié)屏蔽寫(xiě)操作,32為數(shù)據(jù)總線時(shí)WEA為4位,從低到高依次對(duì)應(yīng)數(shù)據(jù)總線低到高的四個(gè)字節(jié)的掩碼,置位可寫(xiě),復(fù)位屏蔽,也就是說(shuō)寫(xiě)32位數(shù)據(jù)時(shí)WEA[3:0]=b1111.
二. PL端硬件設(shè)計(jì)
2.1 新建一個(gè)vivado工程,選擇開(kāi)發(fā)板所對(duì)應(yīng)的芯片型號(hào)。
2.2 Add IP, 添加ZYNQ,雙擊設(shè)置屬性,保留uart1,選擇M AXI GP0 interface和M AXI GP1 interface
圖2-1: ZYNQ IP核GP端口設(shè)置2.3 Add IP, 添加一個(gè)Block memory Generator,選擇true dual Port RAM類型。
圖2-2: Block Ram設(shè)置2.4 Add IP,添加兩個(gè)AXI BRAM Controller,把number of BRAM interfaces改成1。
圖2-3: AXI BRAM Controler設(shè)置2.5 點(diǎn)擊run connection automation,把a(bǔ)xi_bram_ctl_0的Master選擇為GP0, axi_bram_ctl_1的Master選擇為GP1,interconnect ip都選擇為 new AXI Interconnect。
圖2-4: 設(shè)置AXI連接2.6 點(diǎn)擊重新布局,最后得到如下結(jié)構(gòu)。
圖2-5: 雙端口RAM系統(tǒng)結(jié)構(gòu)2.7 點(diǎn)擊Address Editor,可以看到GP0和GP1的地址已經(jīng)自動(dòng)分配好。
圖2-6: RAM地址分配2.8 在sources下選擇block design右擊,點(diǎn)擊Create HDL wrapper,生成系統(tǒng)的頂層模塊,在system_wrapper上右擊,選擇generate output products...。
2.9 編譯綜合工程,最后generate bitstream,導(dǎo)出硬件(包含bitstream),launch SDK。
?
三. PS端軟件的編寫(xiě)與測(cè)試
3.1 新建一個(gè)以helloworld為模板的工程,SDK自動(dòng)創(chuàng)建了硬件的bsp,設(shè)置終端串口為uart1。
?
3.2 在main函數(shù)中編寫(xiě)代碼如下:
#include <stdio.h> #include "platform.h" #include "xil_printf.h" #include <sleep.h> #include "xil_io.h" #include "xparameters.h"int main() {int a[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};int b[16] = {0};init_platform();print("------The test is start...------\n\r");xil_printf( "Write data:\n\r");memcpy((void *)0x40000000, a, 16*4);for(int i = 0;i<16;i++){xil_printf( "%x ",a[i]);}xil_printf( "\n\r");sleep(1);xil_printf( "Read data:\n\r");memcpy(b, (void*)0x80000000, 4*16);for(int i = 0;i<16;i++){xil_printf( "%x ",b[i]);}xil_printf( "\n\r");xil_printf("------The test is end!------\n\r");cleanup_platform();return 0; }程序開(kāi)始向地址0x40000000處復(fù)制數(shù)組a的內(nèi)容,并打印數(shù)組a,然后將地址0x80000000開(kāi)始的64字節(jié)(數(shù)組a大小)內(nèi)容復(fù)制到數(shù)組b中,然后打印數(shù)組b。如果不復(fù)制到數(shù)組b,顯然數(shù)組b是全零數(shù)組,上電啟動(dòng)初始狀態(tài)內(nèi)存中全部為為0。0x40000000和0x80000000分別是雙端口RAM的兩個(gè)端口的起始地址,如果寫(xiě)入與讀取的內(nèi)容一致,則說(shuō)明雙端口RAM的兩套讀寫(xiě)地址操作的是同一個(gè)存儲(chǔ)空間,說(shuō)明實(shí)驗(yàn)是成功的。
3.3 連接好仿真器和串口終端,先下載FPGA程序,然后運(yùn)行PS的軟件,在終端顯示如下:
可以看出讀取的與寫(xiě)入的數(shù)據(jù)完全一樣,然而讀取的地址不一樣,說(shuō)明實(shí)驗(yàn)是成功的。
說(shuō)明:由于BRAM是連接在GP0和GP1接口上通過(guò)AXI總線進(jìn)行讀寫(xiě)操作,在地址空間上尋址可以直接使用指針操作,因此memcpy這樣的C基本庫(kù)函數(shù)可以直接對(duì)GP0和GP1地址空間進(jìn)行操作,在訪問(wèn)速度上比使用循環(huán)指針操作要快很多。
歡迎關(guān)注亦夢(mèng)云煙的微信公眾號(hào): 亦夢(mèng)智能計(jì)算
?
總結(jié)
以上是生活随笔為你收集整理的ZYNQ学习之路4.ZYNQ通过GP口读取PL内部RAM数据的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 正则表达式 '^[a-zA-Z0-9''
- 下一篇: 中专在学校里考的计算机四级证属于中级职业