原創(chuàng)聲明:
本原創(chuàng)教程由芯驛電子科技(上海)有限公司(ALINX)創(chuàng)作,版權(quán)歸本公司所有,如需轉(zhuǎn)載,需授權(quán)并注明出處。
適用于板卡型號:
AXU2CGA/AXU2CGB/AXU3EG/AXU4EV-E/AXU4EV-P/AXU5EV-E/AXU5EV-P /AXU9EG/AXU15EG
實驗Vivado工程為“ram_test”。
RAM是FPGA中常用的基礎(chǔ)模塊,可廣泛用于緩存數(shù)據(jù)的情況,同樣它也是ROM,F(xiàn)IFO的基礎(chǔ)。本實驗將為大家介紹如何使用FPGA內(nèi)部的RAM以及程序?qū)υ揜AM的數(shù)據(jù)讀寫操作。
1.實驗原理
Xilinx在VIVADO里為我們已經(jīng)提供了RAM的IP核, 我們只需通過IP核例化一個RAM,根據(jù)RAM的讀寫時序來寫入和讀取RAM中存儲的數(shù)據(jù)。實驗中會通過VIVADO集成的在線邏輯分析儀ila,我們可以觀察RAM的讀寫時序和從RAM中讀取的數(shù)據(jù)。
2.創(chuàng)建Vivado工程
在添加RAM IP之前先新建一個ram_test的工程, 然后在工程中添加RAM IP,方法如下:
2.1 點擊下圖中IP Catalog,在右側(cè)彈出的界面中搜索ram,找到Block Memory Generator,雙擊打開。
2.2 將Component Name改為ram_ip,在Basic欄目下,將Memory Type改為Simple Dual Prot RAM,也就是偽雙口RAM。一般來講"Simple Dual Port RAM"是最常用的,因為它是兩個端口,輸入和輸出信號獨立。
2.3 切換到Port A Options欄目下,將RAM位寬Port A Width改為16,也就是數(shù)據(jù)寬度。將RAM深度Port A Depth改為512,深度指的是RAM里可以存放多少個數(shù)據(jù)。使能管腳Enable Port Type改為Always Enable。
2.4 切換到Port B Options欄目下,將RAM位寬Port B Width改為16,使能管腳Enable Port Type改為Always Enable,當然也可以Use ENB Pin,相當于讀使能信號。而Primitives Output Register取消勾選,其功能是在輸出數(shù)據(jù)加上寄存器,可以有效改善時序,但讀出的數(shù)據(jù)會落后地址兩個周期。很多情況下,不使能這項功能,保持數(shù)據(jù)落后地址一個周期。
2.5 在Other Options欄目中,這里不像ROM那樣需要初始化RAM的數(shù)據(jù),我們可以在程序中寫入,所以配置默認即可,直接點擊OK。
2.6 點擊“Generate”生成RAM IP。
3. RAM的端口定義和時序
Simple Dual Port RAM 模塊端口的說明如下:
信號名稱 | 方向 | 說明 |
clka | in | 端口A時鐘輸入 |
wea | in | 端口A使能 |
addra | in | 端口A地址輸入 |
dina | in | 端口A數(shù)據(jù)輸入 |
clkb | in | 端口B時鐘輸入 |
addrb | in | 端口B地址輸入 |
doutb | out | 端口B數(shù)據(jù)輸輸出 |
RAM的數(shù)據(jù)寫入和讀出都是按時鐘的上升沿操作的,端口A數(shù)據(jù)寫入的時候需要置高wea信號,同時提供地址和要寫入的數(shù)據(jù)。下圖為輸入寫入到RAM的時序圖。
RAM寫時序
而端口B是不能寫入數(shù)據(jù)的,只能從RAM中讀出數(shù)據(jù),只要提供地址就可以了,一般情況下可以在下一個周期采集到有效的數(shù)據(jù)。
RAM讀時序
4. 測試程序編寫
下面進行RAM的測試程序的編寫,由于測試RAM的功能,我們向RAM的端口A寫入一串連續(xù)的數(shù)據(jù),只寫一次,并從端口B中讀出,使用邏輯分析儀查看數(shù)據(jù)。代碼如下
`timescale1ns/1ps//////////////////////////////////////////////////////////////////////////////////moduleram_test( inputclk, //25MHz時鐘 inputrst_n //復(fù)位信號,低電平有效 );//-----------------------------------------------------------reg [8:0] w_addr; //RAMPORTA寫地址reg [15:0] w_data; //RAMPORTA寫數(shù)據(jù)reg wea; //RAMPORTA使能reg [8:0] r_addr; //RAMPORTB讀地址wire [15:0] r_data; //RAMPORTB讀數(shù)據(jù)//產(chǎn)生RAMPORTB讀地址always@(posedgeclkornegedgerst_n)beginif(!rst_n) r_addr<=9'd0;elseif(|w_addr) //w_addr位或,不等于0????r_addr?<=?r_addr+1'b1;else r_addr?<=9'd0; end//產(chǎn)生RAM?PORTA寫使能信號always@(posedge?clk?ornegedge?rst_n)begin if(!rst_n) ??wea?<=#11'b0;elsebeginif(&w_addr)//w_addr的bit位全為1,共寫入512個數(shù)據(jù),寫入完成????????wea?<=#11'b0;else ????????wea <=#11'b1;//ram寫使能endend//產(chǎn)生RAM?PORTA寫入的地址及數(shù)據(jù)always@(posedge?clk?ornegedge?rst_n)begin if(!rst_n)begin ??w_addr?<=9'd0; ??w_data?<=16'd1;endelsebeginif(wea) //ram寫使能有效 begin if(&w_addr)//w_addr的bit位全為1,共寫入512個數(shù)據(jù),寫入完成 begin w_addr?<=?w_addr?;//將地址和數(shù)據(jù)的值保持住,只寫一次RAM w_data?<=?w_data?; end else begin w_addr?<=?w_addr?+1'b1; w_data?<=?w_data?+1'b1; end endendend//-----------------------------------------------------------//實例化RAM ram_ip?ram_ip_inst?(.clka??????(clk??????????),//?input?clka.wea???????(wea??????????),//?input?[0?:?0]?wea.addra?????(w_addr???????),//?input?[8?:?0]?addra.dina??????(w_data???????),//?input?[15?:?0]?dina.clkb??????(clk??????????),//?input?clkb.addrb?????(r_addr???????),//?input?[8?:?0]?addrb.doutb?????(r_data???????)//?output?[15?:?0]?doutb);//實例化ila邏輯分析儀ila_0?ila_0_inst?( .clk (clk ), .probe0 (r_data ), .probe1 (r_addr )); endmodule
為了能實時看到RAM中讀取的數(shù)據(jù)值,我們這里添加了ila工具來觀察RAM PORTB的數(shù)據(jù)信號和地址信號。關(guān)于如何生成ila大家請參考”PL的”Hello World”LED實驗”。
程序結(jié)構(gòu)如下:
綁定引腳
##################Compress Bitstream############################ set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]set_property PACKAGE_PIN AB11 [get_ports clk]set_property IOSTANDARD LVCMOS33 [get_ports clk]create_clock -period 40.000 -name clk -waveform {0.000 20.000} [get_ports clk]set_property PACKAGE_PIN AA13 [get_ports rst_n]set_property IOSTANDARD LVCMOS33 [get_ports rst_n] |
5. 仿真
仿真方法參考”PL的”Hello World”LED實驗”,仿真結(jié)果如下,從圖中可以看出地址1寫入的數(shù)據(jù)是0002,在下個周期,也就是時刻2,有效數(shù)據(jù)讀出。
6. 板上驗證
生成bitstream,并下載bit文件到FPGA。接下來我們通過ila來觀察一下從RAM中讀出的數(shù)據(jù)是否為我們初始化的數(shù)據(jù)。
在Waveform的窗口設(shè)置r_addr地址為0作為觸發(fā)條件,我們可以看到r_addr在不斷的從0累加到1ff, 隨著r_addr的變化, r_data也在變化, r_data的數(shù)據(jù)正是我們寫入到RAM中的512個數(shù)據(jù),這里需要注意,r_addr出現(xiàn)新地址時,r_data對應(yīng)的數(shù)據(jù)要延時兩個時鐘周期才會出現(xiàn),數(shù)據(jù)比地址出現(xiàn)晚兩個時鐘周期,與仿真結(jié)果一致。
-
FPGA
+關(guān)注
關(guān)注
1626文章
21670瀏覽量
601875 -
ROM
+關(guān)注
關(guān)注
4文章
562瀏覽量
85676 -
RAM
+關(guān)注
關(guān)注
8文章
1367瀏覽量
114533 -
Zynq
+關(guān)注
關(guān)注
9文章
608瀏覽量
47128 -
MPSoC
+關(guān)注
關(guān)注
0文章
198瀏覽量
24252
發(fā)布評論請先 登錄
相關(guān)推薦
評論