本原創教程由芯驛電子科技(上海)有限公司(ALINX)創做,版權歸本公司全部,如需轉載,需受權並註明出處。node
AXU2CGA/AXU2CGB/AXU3EG/AXU4EV-E/AXU4EV-P/AXU5EV-E/AXU5EV-P /AXU9EG/AXU15EG緩存
RAM是FPGA中經常使用的基礎模塊,可普遍用於緩存數據的狀況,一樣它也是ROM,FIFO的基礎。本實驗將爲你們介紹如何使用FPGA內部的RAM以及程序對該RAM的數據讀寫操做。工具
Xilinx在VIVADO裏爲咱們已經提供了RAM的IP核, 咱們只需經過IP核例化一個RAM,根據RAM的讀寫時序來寫入和讀取RAM中存儲的數據。實驗中會經過VIVADO集成的在線邏輯分析儀ila,咱們能夠觀察RAM的讀寫時序和從RAM中讀取的數據。測試
在添加RAM IP以前先新建一個ram_test的工程, 而後在工程中添加RAM IP,方法以下:spa
2.1 點擊下圖中IP Catalog,在右側彈出的界面中搜索ram,找到Block Memory Generator,雙擊打開。3d
2.2 將Component Name改成ram_ip,在Basic欄目下,將Memory Type改成Simple Dual Prot RAM,也就是僞雙口RAM。通常來說"Simple Dual Port RAM"是最經常使用的,由於它是兩個端口,輸入和輸出信號獨立。code
2.3 切換到Port A Options欄目下,將RAM位寬Port A Width改成16,也就是數據寬度。將RAM深度Port A Depth改成512,深度指的是RAM裏能夠存放多少個數據。使能管腳Enable Port Type改成Always Enable。orm
2.4 切換到Port B Options欄目下,將RAM位寬Port B Width改成16,使能管腳Enable Port Type改成Always Enable,固然也能夠Use ENB Pin,至關於讀使能信號。而Primitives Output Register取消勾選,其功能是在輸出數據加上寄存器,能夠有效改善時序,但讀出的數據會落後地址兩個週期。不少狀況下,不使能這項功能,保持數據落後地址一個週期。blog
2.5 在Other Options欄目中,這裏不像ROM那樣須要初始化RAM的數據,咱們能夠在程序中寫入,因此配置默認便可,直接點擊OK。教程
2.6 點擊「Generate」生成RAM IP。
Simple Dual Port RAM 模塊端口的說明以下:
信號名稱 | 方向 | 說明 |
clka | in | 端口A時鐘輸入 |
wea | in | 端口A使能 |
addra | in | 端口A地址輸入 |
dina | in | 端口A數據輸入 |
clkb | in | 端口B時鐘輸入 |
addrb | in | 端口B地址輸入 |
doutb | out | 端口B數據輸輸出 |
RAM的數據寫入和讀出都是按時鐘的上升沿操做的,端口A數據寫入的時候須要置高wea信號,同時提供地址和要寫入的數據。下圖爲輸入寫入到RAM的時序圖。
RAM寫時序
而端口B是不能寫入數據的,只能從RAM中讀出數據,只要提供地址就能夠了,通常狀況下能夠在下一個週期採集到有效的數據。
RAM讀時序
4. 測試程序編寫
下面進行RAM的測試程序的編寫,因爲測試RAM的功能,咱們向RAM的端口A寫入一串連續的數據,只寫一次,並從端口B中讀出,使用邏輯分析儀查看數據。代碼以下
`timescale1ns/1ps ////////////////////////////////////////////////////////////////////////////////// module ram_test( input clk, //25MHz時鐘 input rst_n //復位信號,低電平有效 ); //----------------------------------------------------------- reg [8:0] w_addr; //RAM PORTA寫地址 reg [15:0] w_data; //RAM PORTA寫數據 reg wea; //RAM PORTA使能 reg [8:0] r_addr; //RAM PORTB讀地址 wire [15:0] r_data; //RAM PORTB讀數據 //產生RAM PORTB讀地址 always@(posedge clk ornegedge rst_n) begin if(!rst_n) r_addr <=9'd0; elseif(|w_addr) //w_addr位或,不等於0 r_addr <= r_addr+1'b1; else r_addr <=9'd0; end //產生RAM PORTA寫使能信號 always@(posedge clk ornegedge rst_n) begin if(!rst_n) wea <=#11'b0; else begin if(&w_addr)//w_addr的bit位全爲1,共寫入512個數據,寫入完成 wea <=#11'b0; else wea <=#11'b1;//ram寫使能 end end //產生RAM PORTA寫入的地址及數據 always@(posedge clk ornegedge rst_n) begin if(!rst_n) begin w_addr <=9'd0; w_data <=16'd1; end else begin if(wea) //ram寫使能有效 begin if(&w_addr)//w_addr的bit位全爲1,共寫入512個數據,寫入完成 begin w_addr <= w_addr ;//將地址和數據的值保持住,只寫一次RAM w_data <= w_data ; end else begin w_addr <= w_addr +1'b1; w_data <= w_data +1'b1; end end end end //----------------------------------------------------------- //實例化RAM ram_ip ram_ip_inst ( .clka (clk ),// input clka .wea (wea ),// input [0 : 0] wea