使用軟件: Vivado
開發(fā)板: EGO1采用Xilinx Artix-7系列XC7A35T-1CSG324C FPGA
BRAM介紹
BRAM 即塊 RAM, 是 FPGA 的固有硬件資源。 另一種形式的 RAM 是分布RAM(Distribution RAM), 是由 FPGA 邏輯資源查找表 LUT 拼起來的 。這兩種 RAM 最本質(zhì)的區(qū)別是塊RAM 默認輸入有寄存器,所以它在讀、寫使能信號后的下個時鐘邊沿返回數(shù)據(jù),而分布式RAM就沒有,就是個組合邏輯,讀、寫使能的同一時刻返回數(shù)據(jù)。從時序的角度上來說,塊RAM更好,唯一不足的是,它是珍貴的硬件資源。一般來說,芯片越高級,塊RAM資源越多。
Artix- - 7 FPGA 的最高型號具有可分配的 13Mbit雙端口BRAM, 而實驗電路板選型的XC7A35T具備 18Kbit 的BRAM100 個 ,36Kbit 的BRAM 50 個,共1800Kbit 。 Xilinx 7系列 FPGA 可將 BRAM 配置為同步雙端口 RAM或單端口 RAM。
同步雙端口BRAM
方便通過一個端口寫的同時可以從另一個端口進行讀取
每個真正的雙端口的36Kbit BRAM 包含 36Kbit 個存儲單元以及2個完全獨立的訪問接口A 和B 。每個 18Kbit BRAM 雙端口內(nèi)存包含18Kbit 個存儲單元以及2個完全獨立的訪問接口A和B 。內(nèi)存的結(jié)構(gòu)完全對稱, 雙端口可互換。
BRAM讀寫操作
(1)讀操作
讀操作是在一個時鐘邊沿完成讀取RAM指定單元(讀地址)內(nèi)容的操作。首先將讀取地址寄存在讀端口,并在RAM讀取時間之后將存儲的數(shù)據(jù)加載到輸出鎖存器中。當(dāng)使用輸出寄存器時,讀操作需要一個額外的等待周期。
(2)寫操作
寫操作是一個時鐘邊沿寫入RAM的操作。寫地址寄存在寫入端口,數(shù)據(jù)輸入存儲在內(nèi)存中。
(3)寫模式
寫模式有三種,決定了寫入時鐘邊沿后,有效數(shù)據(jù)出現(xiàn)在輸出鎖存器的時間。
三種模式是: 寫優(yōu)先模式WRITE_FIRST、讀優(yōu)先模式READ_FIRST和不變模式。每個端口的寫模式可以通過配置過程單獨配置。
默認模式是寫優(yōu)先模式,在這種模式總是將最新寫入的數(shù)據(jù)送到輸出總線上。
在讀優(yōu)先模式,當(dāng)新的數(shù)據(jù)被寫入時,仍然輸出先前存儲的數(shù)據(jù)。
在不變模式,輸出總線上保持先前的輸出。
寫優(yōu)先模式
在第一個時鐘的上升沿,將地址aa的數(shù)據(jù)MEM(aa)讀出放在數(shù)據(jù)總線DO上。在第二個時鐘的上升沿,寫有效,因此將DI上的1111寫入地址bb。因為寫優(yōu)先,所以出現(xiàn)在數(shù)據(jù)總線上的是新寫入的1111。
讀優(yōu)先模式
在第一個時鐘的上升沿,將地址aa的數(shù)據(jù)MEM(aa)讀出放在數(shù)據(jù)總線DO上。在第二
個時鐘的上升沿,寫有效,因此將DI上的1111寫入地址bb。因為讀優(yōu)先,所以出現(xiàn)在數(shù)據(jù)總線上的不是新寫入的1111,而是原來地址bb的內(nèi)存的值old MEM(bb)。
不變模式
在第一個時鐘的上升沿,將地址aa的數(shù)據(jù)MEM(aa)讀出放在數(shù)據(jù)總線DO上。在第二個時鐘的上升沿,寫有效,因此將DI上的1111寫入地址bb。因為不變模式,所以在寫有效的時候出現(xiàn)在數(shù)據(jù)總線上的數(shù)據(jù)是不變的,仍然是MEM(aa),直到寫無效后的第一個時鐘上升沿才變?yōu)镸EM(dd)。
雙端口塊內(nèi)存接口
BRAM IP的使用及仿真驗證
IP核使用
coe文件
使用matlab生成.coe文件:
l.coe文件內(nèi)容如下,注意前兩行要添加~
將IP核添加到工程
- 在工程管理欄下點擊[IP Catalog],然后搜索RAM,找到塊RAM生成器[Block Memory Generator],如下圖所示:
- 將組件名稱改為“ram”,其他設(shè)置如下圖所示:
讀寫模式改為讀優(yōu)先“Read First”
取消勾選Primitives Output Register,不然輸出會滯后一個時鐘周期文章來源:http://www.zghlxwxcb.cn/news/detail-790899.html
- 在[Other Options]選項中勾選Load Init File,點擊Browse添加前面用matlab生成的要存入RAM的初始數(shù)據(jù)。
代碼
verilog代碼
`timescale 1ns / 1ps
//
// Module Name: BRAM_test
// Revision 0.01 - File Created
// Additional Comments:
//
//
module BRAM_test(clk,ena,wea,addra,dina,douta);
input clk,ena,wea;
input[9:0] addra;
input[14:0] dina;
output[14:0] douta;
ram ram(clk,ena,wea,addra,dina,douta);
endmodule
仿真代碼
`timescale 1ns / 1ps
//
// Create Date: 2022/10/20 10:59:14
// Design Name:
// Module Name: sim_bram
// Revision 0.01 - File Created
// Additional Comments:
//
//
module sim_bram();
reg clk;//時鐘輸入
reg wea;//寫使能
reg[9:0] addra;//地址輸入
reg[14:0] dina;//數(shù)據(jù)輸入
wire[14:0] douta;//數(shù)據(jù)輸出
reg[9:0] cnt1,cnt2;
initial begin
clk=0;
wea=0;
cnt1=0;
cnt2=0;
end
BRAM_test uut(//調(diào)用被仿真的模塊完成內(nèi)存讀寫
.clk(clk),
.ena(1),
.wea(wea),
.addra(addra),
.dina(dina),
.douta(douta)
);
always #10 clk=~clk;//周期20ns,模擬50M時鐘
always@(posedge clk)
begin
if(cnt1==8)
begin
cnt1=0;
cnt2=cnt2+1;//cnt2低位每9個周期翻轉(zhuǎn)一次
end
else
cnt1=cnt1+1;
end
//負邊沿寫地址,寫數(shù)據(jù)輸入,寫使能信號,保證時鐘上升沿時這些值是穩(wěn)定的
always@(negedge clk)
begin
dina=cnt1;//數(shù)據(jù)輸入總線是哪個的值是計數(shù)值cnt1
addra=cnt1;
if(cnt2[0]==0) wea=0;//每9個周期寫使能翻轉(zhuǎn)
else wea=1;
end
endmodule
仿真結(jié)果
仿真結(jié)果如下圖所示:
初始時,在時鐘上升沿讀取RAM中addra地址(000 ~ 008)下存儲的值(100 ~ 108)。
在寫使能wea=1之后,因為是讀優(yōu)先,所以先讀出該地址的值,再將dina內(nèi)容寫入,所以看到douta的值還是(100 ~ 108)。
寫使能結(jié)束之后,再讀取ram對應(yīng)地址中的內(nèi)容,可以看出douta結(jié)果為寫入的數(shù)值(0 ~ 8)。文章來源地址http://www.zghlxwxcb.cn/news/detail-790899.html
到了這里,關(guān)于FPGA — BRAM學(xué)習(xí)筆記—讀寫操作的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!