【DNN Weaver FPGA實(shí)現(xiàn)】Vivado BRAM資源使用

1、BRAM配置測(cè)試

我們知道Vivado中BRAM大小分為18K和36K兩種莉撇,這兩種BRAM在何種配置下會(huì)如何分配資源呢蛤,需要進(jìn)行一定的考量。由于Vivado可以配置生成任意bit數(shù)的IO位寬棍郎,所以我對(duì)BRAM配置進(jìn)行了簡(jiǎn)單的實(shí)驗(yàn)其障,結(jié)果如下所示。


18bit位寬涂佃,1K深度励翼,共18Kb

可以看到,18bit位寬辜荠,1K深度可以正常使用18Kb的小BRAM汽抚。


16bit位寬,1152深度伯病,共18Kb

如果使用16bit訪存位寬造烁,1152深度,依然是18Kb大小來(lái)生成BRAM,會(huì)導(dǎo)致資源無(wú)法映射到18Kb的BRAM中惭蟋,而是使用了36Kb大小的BRAM苗桂,這導(dǎo)致了一半的BRAM被浪費(fèi)。
8bit位寬告组,2304深度煤伟,共18Kb

8bit位寬,2048深度木缝,共16Kb

上面兩張圖可以看到便锨,如果使用較低的8bit位寬實(shí)現(xiàn)18Kb大小的RAM,也無(wú)法調(diào)用18K BRAM我碟。但是如果將深度縮減為2K(經(jīng)過(guò)測(cè)試2049深度也是調(diào)用了36K BRAM放案,所以深度必須是2K以下),即RAM大小減小為16Kb怎囚,則可以調(diào)用18K BRAM卿叽,減少資源浪費(fèi),這就很有意思了恳守。

根據(jù)上述思路考婴,我又對(duì)16bit位寬進(jìn)行測(cè)試,設(shè)定深度為1K催烘,則調(diào)用了18K BRAM沥阱,并且深度也是必須小于等于1K才會(huì)調(diào)用,否則就是36K BRAM伊群,即RAM大小必須小于等于16Kb考杉。依此類推,4bit位寬如果想使用18K BRAM舰始,則必須深度小于等于4K崇棠,即RAM小于等于16Kb。

官方文檔給出的BRAM原型分配

從官方文檔中找到了對(duì)上述內(nèi)容的解釋丸卷,其實(shí)BRAM有16K×1枕稀、8K×2、4K×4谜嫉、2K×9萎坷、1K×18、512×36等6種原型方案沐兰,所有的BRAM配置方案均在這些原型的基礎(chǔ)上進(jìn)行疊加拼接得到哆档。所以說(shuō)如果使用了1152×16的配置方案,則需要至少2塊1K×18串聯(lián)來(lái)滿足深度要求住闯,或者兩塊2K×9并聯(lián)(4個(gè)4K×4并聯(lián)等其他方案也可瓜浸,但太浪費(fèi)BRAM)來(lái)滿足位寬要求澳淑,所以必須要占用36K BRAM。并且如果有更大的深度或者位寬出現(xiàn)時(shí)斟叼,可能會(huì)有很多種不同的解決方案偶惠,Vivado中也提供了相應(yīng)的三種方案,Minimum Area Algorithm朗涩、Low Power Algorithm、Fixed Primitive Algorithm绑改,幫助生成最適合項(xiàng)目需求的RAM形式谢床。詳見(jiàn)文檔pg058-blk-mem-gen,42~45頁(yè)厘线。

Examples of the Minimum Area Algorithm

Examples of the Low Power Algorithm

Examples of the Fixed Primitive Algorithm

2识腿、BRAM讀寫(xiě)時(shí)序

寫(xiě)優(yōu)先

在本文中主要使用了寫(xiě)優(yōu)先模式,以保證讀出數(shù)據(jù)為最新造壮《伤希可以從時(shí)序圖中看到,輸入數(shù)據(jù)耳璧、數(shù)據(jù)地址成箫、Enable信號(hào)等需要在時(shí)鐘上升沿之前就到達(dá)接口位置。

3旨枯、ARM Memory Compiler SRAM時(shí)序

Memory Compiler SRAM時(shí)序

與ASIC實(shí)現(xiàn)中使用Memory Compiler生成的SRAM時(shí)序進(jìn)行對(duì)比蹬昌,可以發(fā)現(xiàn)該SRAM中控制信號(hào)和數(shù)據(jù)寫(xiě)入基本與Xilinx的BRAM是一致的,均需要在時(shí)鐘上升沿之前到來(lái)地址和數(shù)據(jù)攀隔。但是MC SRAM數(shù)據(jù)讀出速度要更快皂贩,在一定的時(shí)間延遲后即可得到有效輸出數(shù)據(jù)嗎,而B(niǎo)RAM則至少有1~3個(gè)周期的延遲才能獲得讀出數(shù)據(jù)昆汹。

4明刷、讀寫(xiě)沖突

轉(zhuǎn)自Xilinx之RAM使用指南

BRAM讀寫(xiě)時(shí)對(duì)端口位寬大小的單元進(jìn)行操作满粗,例如dout位寬為32bit辈末,則每次讀寫(xiě)均為32bit,BRAM深度大小就是有幾個(gè)32bit的數(shù)據(jù)败潦。

因此讀寫(xiě)沖突的可能僅存在于同時(shí)讀寫(xiě)同一個(gè)32bit數(shù)據(jù)本冲,即同時(shí)讀寫(xiě)一個(gè)地址的數(shù)據(jù)。所以我們?cè)谶M(jìn)行OBUF實(shí)現(xiàn)時(shí)劫扒,應(yīng)該不會(huì)有讀寫(xiě)沖突的出現(xiàn)檬洞。下圖中所示為三種端口模式下的讀寫(xiě)沖突情況,其中寫(xiě)優(yōu)先模式的讀寫(xiě)沖突沟饥,是由于前一周期B端口在讀添怔,本周期A端口在寫(xiě)湾戳,導(dǎo)致本周期B端口應(yīng)當(dāng)讀到的舊數(shù)據(jù)被覆蓋。從數(shù)據(jù)讀邏輯上來(lái)說(shuō)广料,只要有一個(gè)端口在本周期寫(xiě)數(shù)據(jù)砾脑,本周期讀到的數(shù)據(jù)必定是亞穩(wěn)態(tài),如果是字節(jié)寫(xiě)模式(有寫(xiě)Mask)艾杏,則寫(xiě)入部分地址的數(shù)據(jù)輸出為亞穩(wěn)態(tài)韧衣。如果是本周期A端口寫(xiě)入、B端口讀出购桑,則可以在下周期讀出最新寫(xiě)入的數(shù)據(jù)畅铭。(本周期讀的數(shù)據(jù)在下周期獲得是在BRAM配置時(shí)設(shè)定的輸出寄存器個(gè)數(shù)決定的,延遲周期數(shù)可以為1~3)


BRAM讀寫(xiě)沖突

各種RAM(雙端RAM勃蜘、DRAM)HDL寫(xiě)法詳見(jiàn)Vivado使用技巧(27):RAM編寫(xiě)技巧尝抖。

5炊林、雙端RAM Ping-Pong Buffer讀寫(xiě)控制

轉(zhuǎn)自FPGA基礎(chǔ)設(shè)計(jì)(7)雙口RAM乒乓操作滩援。
這里的雙端RAM兩個(gè)口接的時(shí)鐘頻率不一樣破衔,寫(xiě)端口CLKA為20MHz,讀端口CLKB為100MHz阳惹,也就是說(shuō)讀速度為寫(xiě)速度的5倍谍失。

`timescale 1ns / 1ps

module DualRAM
(
    input clk_wr,      //寫(xiě)時(shí)鐘速率20Mhz
    input clk_rd,      //讀時(shí)鐘速率100Mhz
    input rst_n,
    input [7:0] din,   
    output reg out_valid,
    output reg [7:0] dout
);

reg [9:0] addr_wr, addr_rd;
reg en_wr1, en_wr2, we_wr1, we_wr2, en_rd1, en_rd2;
wire [7:0] dout1, dout2;

dual_port_ram u1 (
  .clka(clk_wr),      //寫(xiě)端口
  .ena(en_wr1),    
  .wea(we_wr1),      
  .addra(addr_wr),  
  .dina(din),   
  .douta(), 
  .clkb(clk_rd),      //讀端口
  .enb(en_rd1),      
  .web(1'b0),      
  .addrb(addr_rd),  
  .dinb(8'd0),    
  .doutb(dout1) 
);

dual_port_ram u2 (
  .clka(clk_wr),      //寫(xiě)端口
  .ena(en_wr2),    
  .wea(we_wr2),      
  .addra(addr_wr),  
  .dina(din),   
  .douta(), 
  .clkb(clk_rd),      //讀端口
  .enb(en_rd2),      
  .web(1'b0),      
  .addrb(addr_rd),  
  .dinb(8'd0),    
  .doutb(dout2) 
);

//寫(xiě)端口乒乓操作
always @ (posedge clk_wr)     //寫(xiě)地址信號(hào)控制0~1023
    if (!rst_n) addr_wr <= 1023;
    else addr_wr <= addr_wr + 1'b1;

always @ (posedge clk_wr)     //輪流寫(xiě)RAM1與RAM2
    if (!rst_n) begin we_wr1 <= 1'b1; we_wr2 <= 1'b0;
        en_wr1 <= 1'b1; en_wr2 <= 1'b0;  end
    else if (addr_wr == 1023) begin
        we_wr1 <= ~we_wr1; we_wr2 <= ~we_wr2;
        en_wr1 <= ~en_wr1; en_wr2 <= ~en_wr2;
    end 
 
//讀端口乒乓操作
always @ (posedge clk_rd)    //讀地址信號(hào)控制0~1023
    if (!rst_n) addr_rd <= 1021;  //匹配延遲
    else addr_rd <= addr_rd + 1'b1; 
    
reg [15:0] cnt;
always @ (posedge clk_rd)    //讀時(shí)鐘為寫(xiě)時(shí)鐘的5倍
    if (!rst_n) cnt <= 16'hFFFE;  //匹配延遲
    else if (cnt == 5119) cnt <= 0;
    else cnt <= cnt + 1'b1;
    
reg flag1, flag2;
always @ (posedge clk_rd)    //讀RAM標(biāo)志,RAM1或RAM2
    if (!rst_n) begin flag1 <= 1'b1; flag2 <= 1'b0; end
    else if (cnt == 5119) begin flag1 = ~flag1; flag2 = ~flag2; end    
    else begin flag1 <= flag1; flag2 <= flag2; end
    
always @ (posedge clk_rd)    //讀RAM使能穆端,選擇cnt的前1/5時(shí)間讀取
    if (!rst_n) begin en_rd1 <= 1'b1; en_rd2 <= 1'b0; end 
    else if (cnt < 1024) begin en_rd1 <= flag1; en_rd2 <= flag2; end
    else begin en_rd1 <= 1'b0; en_rd2 <= 1'b0; end

reg en_rd1_reg, en_rd2_reg;
always @ (posedge clk_rd)    //延遲一級(jí)袱贮,匹配時(shí)序
    if (!rst_n) begin en_rd1_reg <= 0; en_rd1_reg <= en_rd1_reg; end
    else begin en_rd1_reg <= en_rd1; en_rd2_reg <= en_rd2; end

always @ (posedge clk_rd)    //輸出選擇,RAM1或RAM2体啰;控制輸出使能信號(hào)
    if (!rst_n) begin dout <= 0; out_valid <= 0; end
    else if (en_rd1_reg) begin dout <= dout1; out_valid <= 1; end
    else if (en_rd2_reg) begin dout <= dout2; out_valid <= 1; end
    else begin dout <= 0; out_valid <= 0; end
    
endmodule

上面的代碼中有例化BRAM模塊攒巍,不過(guò)這些端口不一定全部需要,根據(jù)本項(xiàng)目特點(diǎn)荒勇,使用Simple dual-port BRAM就可以柒莉,因此A口寫(xiě),B口讀沽翔,A口沒(méi)有douta信號(hào)兢孝,B口沒(méi)有dinb和web信號(hào),例化的時(shí)候要注意仅偎,如果不清楚可以到Vivado中打開(kāi)diagram看一下跨蟹。

仿真結(jié)果

6、對(duì)比DNN Weaver RAM與BRAM數(shù)據(jù)接口與時(shí)序差別

下面是DNN Weaver RAM模塊代碼橘沥,該RAM使用在IBUF和BBUF中窗轩。與BRAM模塊接口對(duì)比,該RAM的讀寫(xiě)使能信號(hào)分開(kāi)座咆,并且讀通道與寫(xiě)通道分開(kāi)痢艺,可以同時(shí)讀寫(xiě)仓洼,但沒(méi)有解決讀寫(xiě)沖突問(wèn)題,說(shuō)明IBUF和BBUF不會(huì)出現(xiàn)該問(wèn)題堤舒,并且輸出均有1個(gè)寄存器的延遲(例化模塊時(shí)設(shè)定OUTPUT_REG=1)色建。總之使用BRAM對(duì)該模塊可以進(jìn)行很好的代替舌缤,因?yàn)楣δ苌蟻?lái)說(shuō)該RAM是BRAM的子集箕戳。

除了IBUF和BBUF,DNN Weaver中還有個(gè)OBUF友驮。由于OBUF需要大量的讀寫(xiě)漂羊,OBUF設(shè)計(jì)比IBUF等邏輯復(fù)雜很多,并且有兩套讀寫(xiě)接口卸留,模塊名稱為banked_ram。學(xué)姐當(dāng)時(shí)建議使用DRAM(Distributed RAM)實(shí)現(xiàn)OBUF椭豫,不知道會(huì)不會(huì)在綜合的時(shí)候RAM邏輯過(guò)大耻瑟,導(dǎo)致片上資源不足,或者導(dǎo)致綜合時(shí)間過(guò)長(zhǎng)的問(wèn)題赏酥。

`timescale 1ns/1ps
module ram
#(
  parameter integer DATA_WIDTH    = 10,
  parameter integer ADDR_WIDTH    = 12,
  parameter integer OUTPUT_REG    = 0
)
(
  input  wire                         clk,
  input  wire                         reset,

  input  wire                         s_read_req,
  input  wire [ ADDR_WIDTH  -1 : 0 ]  s_read_addr,
  output wire [ DATA_WIDTH  -1 : 0 ]  s_read_data,

  input  wire                         s_write_req,
  input  wire [ ADDR_WIDTH  -1 : 0 ]  s_write_addr,
  input  wire [ DATA_WIDTH  -1 : 0 ]  s_write_data
);

  reg  [ DATA_WIDTH -1 : 0 ] mem [ 0 : 1<<ADDR_WIDTH ];

  always @(posedge clk)
  begin: RAM_WRITE
    if (s_write_req)
      mem[s_write_addr] <= s_write_data;
  end

  generate
    if (OUTPUT_REG == 0)
      assign s_read_data = mem[s_read_addr];
    else begin
      reg [DATA_WIDTH-1:0] _s_read_data;
      always @(posedge clk)
      begin
        if (reset)
          _s_read_data <= 0;
        else if (s_read_req)
          _s_read_data <= mem[s_read_addr];
      end
      assign s_read_data = _s_read_data;
    end
  endgenerate
endmodule
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末喳整,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子裸扶,更是在濱河造成了極大的恐慌框都,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呵晨,死亡現(xiàn)場(chǎng)離奇詭異魏保,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)摸屠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門谓罗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人季二,你說(shuō)我怎么就攤上這事檩咱。” “怎么了胯舷?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵刻蚯,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我桑嘶,道長(zhǎng)炊汹,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任不翩,我火速辦了婚禮兵扬,結(jié)果婚禮上麻裳,老公的妹妹穿的比我還像新娘。我一直安慰自己器钟,他們只是感情好津坑,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著傲霸,像睡著了一般疆瑰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上昙啄,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天穆役,我揣著相機(jī)與錄音,去河邊找鬼梳凛。 笑死耿币,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的韧拒。 我是一名探鬼主播淹接,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼叛溢!你這毒婦竟也來(lái)了塑悼?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤楷掉,失蹤者是張志新(化名)和其女友劉穎厢蒜,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體烹植,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡斑鸦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刊橘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鄙才。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖促绵,靈堂內(nèi)的尸體忽然破棺而出攒庵,到底是詐尸還是另有隱情,我是刑警寧澤败晴,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布浓冒,位于F島的核電站,受9級(jí)特大地震影響尖坤,放射性物質(zhì)發(fā)生泄漏稳懒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一慢味、第九天 我趴在偏房一處隱蔽的房頂上張望场梆。 院中可真熱鬧墅冷,春花似錦、人聲如沸或油。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)顶岸。三九已至腔彰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辖佣,已是汗流浹背霹抛。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留卷谈,地道東北人杯拐。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像世蔗,于是被迫代替她去往敵國(guó)和親藕施。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360