精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于FPGA BRAM的多端口地址查找表與FPGA BRAM的資源分析

網絡交換FPGA ? 來源:網絡交換FPGA ? 2024-05-01 14:03 ? 次閱讀

一、背景

在多端口交換機的設計中,交換機的每個端口都會各自維護一張查找表,數據幀進入到交換機后,需要進行查表和轉發。但隨著端口數量和表項需求的增加,每個端口都單獨維護一張表使得FPGA的資源變得非常緊張。因此,需要一張查找表(本質是可讀可寫的RAM),能夠滿足多讀多寫的功能。但在Xilinx FPGA上,Xilinx提供的BRAM IP最高只能實現真雙端口RAM。不能滿足多讀多寫的需求。

補充:這里不使用其他RAM類型如URAM的原因是,BRAM擁有更好的時序,更適合在高速交換中用于查找表。

二、手寫Multiport Ram

Multiport Ram,即多讀多寫存儲器,本工程實現的是1個口寫,同時滿足11個口讀的BRAM。

為了讓vivado在綜合的時候把手寫ram例化為BRAM,我們需要按照官方手冊的要求編寫multiport ram。這時需要通過(*ram_style="block"*)對array進行修飾。

查看Vivado的官方手冊ug901可知,對于Distributed RAM(LUTRAM)和Dedicated Block RAM(BRAM),二者都是寫同步的。主要區別在于讀數據,前者為異步,后者為同步的。

1eb9cb74-0065-11ef-a297-92fbcf53809c.png

下面給出一種手寫多端口bram的方案并給出一種優化FPGA bram資源利用的方法。

Multiport RAM 代碼方案

實現多端口bram最簡單的方法就是把讀數據部分的邏輯復制11份,寫數據部分的邏輯保留1份。

部分代碼如下,實現位寬73bit,深度為16K的multiport ram:

(*ram_style="block"*)reg [DATA_WIDTH-1:0] bram [0:DEPTH-1];
/*-------------復制讀端口11份---------------*/
    always @(posedge clk)
    begin
        if(re1)
            rd_data1 <= bram[rd_addr1];
        else
            rd_data1 <= rd_data1;
????end
/*-----------------------------------------*/
    //write
    always @(posedge clk)
    begin
        if(we)
            bram[wr_addr]<=wr_data;
    end
endmodule

資源評估

利用vivado綜合實現后,消耗的資源如下

1ee47342-0065-11ef-a297-92fbcf53809c.png

MultiportRAM16K深度,73位寬的單口寫,11口讀的RAM消耗的BRAM數為192個。

普通真雙口RAM:利用vivado IP核生成的16K深度,73bit位寬的真雙口RAM消耗的BRAM數為32個。即如果11個端口各自維護一張地址查找表共使用352個RAM。

對比發現,在滿足11個端口同時讀地址查找表的條件下,多端口RAM比普通RAM節約了45%左右的BRAM資源

三、Multiport RAM 資源利用的優化

可能有的同學說,在某些大工程里面,192個BRAM還是有點多。下面我給出了一種降低BRAM資源消耗的方法。

首先我們把例化的ram array的位寬翻倍

//原本
(*ram_style="block"*)reg [DATA_WIDTH-1:0] bram [0:DEPTH-1];
//現在
(*ram_style="block"*)reg [DATA_WIDTH+DATA_WIDTH-1:0] bram [0:DEPTH-1];

(有同學會問了,這樣資源消耗不是翻倍了嗎?···別急?。?/p>

我們把需要寫入RAM的數據,73位寫data復制成兩份,同時寫進bram的高73位和低73位,地址不變,其中multi_wdata是我們要寫進表中的73位表項,代碼如下:

//bram例化模塊的寫使能、地址和數據
    .we       (   multi_wr),
    .wr_addr  (multi_waddr),
.wr_data({multi_wdata,multi_wdata})

在bram輸出中,每兩個端口共用一個143位的bram行,并根據使能情況賦值:

   //read1
    assign rd_data1_wire = rd_data1[72:0]  ;
    assign rd_data2_wire = rd_data2[145:73];
    always @(posedge clk)
    begin
        if (re1 & re2) begin
            rd_data1 <=  bram[rd_addr1];
            rd_data2 <=  bram[rd_addr2];
        end
        else 
        if(re1) begin
             rd_data1 <=  bram [rd_addr1];
        end
        else if (re2) begin
            rd_data2 <= bram [rd_addr2];
        end 


    end

***補充:具體代碼在文章開頭鏈接

資源評估

利用vivado綜合實現后,消耗的資源如下

1efb0be8-0065-11ef-a297-92fbcf53809c.png

MultiportRAM:16K深度,146位寬的單口寫,11口讀的RAM消耗的BRAM數為112個。

普通真雙口RAM:利用vivado IP核生成的16K深度,73bit位寬的真雙口RAM消耗的BRAM數為32個。即如果11個端口各自維護一張表共使用352個RAM

對比發現,在滿足11個端口同時讀地址查找表的條件下,多端口RAM比普通RAM節約了68%左右的BRAM資源

四、防止讀寫沖突的組合邏輯設計(寫優先)

代碼原理,利用組合邏輯時序,當寫入地址和讀地址相同時,寫入地址、數據正常進行,但讀端口不對RAM進行讀取,而是將寫入端的數據直接賦值給讀出端的數據。

下一拍,即讀寫沖突結束后的下一拍,再讀一拍RAM中的數據,使得讀端口數據保持這一次讀的結果(因為組合邏輯在讀寫沖突時沒有真正讀RAM,所以RAM輸出data會保持上一次輸出的data),但這一步不是必要的,純粹為了好看。

部分代碼如下:

//防止讀寫沖突,且為寫優先邏輯
assign multi_rdata0 =(multi_raddr0_f ==multi_waddr_f && multi_raddr0_f !='b0 )?multi_wdata_f:multi_rdata0_ram ;
assign multi_rdata1 =(multi_raddr1_f ==multi_waddr_f && multi_raddr1_f !='b0 )?multi_wdata_f:multi_rdata1_ram ;
assign multi_rdata2 =(multi_raddr2_f ==multi_waddr_f && multi_raddr2_f !='b0 )?multi_wdata_f:multi_rdata2_ram ;
assign multi_rdata3 =(multi_raddr3_f ==multi_waddr_f && multi_raddr3_f !='b0 )?multi_wdata_f:multi_rdata3_ram ;
assign multi_rdata4 =(multi_raddr4_f ==multi_waddr_f && multi_raddr4_f !='b0 )?multi_wdata_f:multi_rdata4_ram ;
assign multi_rdata5 =(multi_raddr5_f ==multi_waddr_f && multi_raddr5_f !='b0 )?multi_wdata_f:multi_rdata5_ram ;
assign multi_rdata6 =(multi_raddr6_f ==multi_waddr_f && multi_raddr6_f !='b0 )?multi_wdata_f:multi_rdata6_ram ;
assign multi_rdata7 =(multi_raddr7_f ==multi_waddr_f && multi_raddr7_f !='b0 )?multi_wdata_f:multi_rdata7_ram ;
assign multi_rdata8 =(multi_raddr8_f ==multi_waddr_f && multi_raddr8_f !='b0 )?multi_wdata_f:multi_rdata8_ram ;
assign multi_rdata9 =(multi_raddr9_f ==multi_waddr_f && multi_raddr9_f !='b0 )?multi_wdata_f:multi_rdata9_ram ;
assign multi_rdata10=(multi_raddr10_f==multi_waddr_f && multi_raddr10_f!='b0 )?multi_wdata_f:multi_rdata10_ram;


assign multi_raddr0_ram =(multi_raddr0_f ==multi_waddr_f && multi_raddr0_f !='b0 )?multi_waddr_f: multi_raddr0;
assign multi_raddr1_ram =(multi_raddr1_f ==multi_waddr_f && multi_raddr1_f !='b0 )?multi_waddr_f: multi_raddr1;
assign multi_raddr2_ram =(multi_raddr2_f ==multi_waddr_f && multi_raddr2_f !='b0 )?multi_waddr_f: multi_raddr2;
assign multi_raddr3_ram =(multi_raddr3_f ==multi_waddr_f && multi_raddr3_f !='b0 )?multi_waddr_f: multi_raddr3;
assign multi_raddr4_ram =(multi_raddr4_f ==multi_waddr_f && multi_raddr4_f !='b0 )?multi_waddr_f: multi_raddr4;
assign multi_raddr5_ram =(multi_raddr5_f ==multi_waddr_f && multi_raddr5_f !='b0 )?multi_waddr_f: multi_raddr5;
assign multi_raddr6_ram =(multi_raddr6_f ==multi_waddr_f && multi_raddr6_f !='b0 )?multi_waddr_f: multi_raddr6;
assign multi_raddr7_ram =(multi_raddr7_f ==multi_waddr_f && multi_raddr7_f !='b0 )?multi_waddr_f: multi_raddr7;
assign multi_raddr8_ram =(multi_raddr8_f ==multi_waddr_f && multi_raddr8_f !='b0 )?multi_waddr_f: multi_raddr8;
assign multi_raddr9_ram =(multi_raddr9_f ==multi_waddr_f && multi_raddr9_f !='b0 )?multi_waddr_f: multi_raddr9;
assign multi_raddr10_ram=(multi_raddr10_f==multi_waddr_f && multi_raddr10_f!='b0 )?multi_waddr_f: multi_raddr10;






assign multi_rd0_ram =(multi_raddr0 ==multi_waddr && multi_raddr0!='b0  )?  1'b0:((multi_raddr0_f ==multi_waddr_f && multi_raddr0_f !='b0  )?multi_rd0_f :multi_rd0 );
assign multi_rd1_ram =(multi_raddr1 ==multi_waddr && multi_raddr1!='b0  )?  1'b0:((multi_raddr1_f ==multi_waddr_f && multi_raddr1_f !='b0  )?multi_rd1_f :multi_rd1 );
assign multi_rd2_ram =(multi_raddr2 ==multi_waddr && multi_raddr2!='b0  )?  1'b0:((multi_raddr2_f ==multi_waddr_f && multi_raddr2_f !='b0  )?multi_rd2_f :multi_rd2 );
assign multi_rd3_ram =(multi_raddr3 ==multi_waddr && multi_raddr3!='b0  )?  1'b0:((multi_raddr3_f ==multi_waddr_f && multi_raddr3_f !='b0  )?multi_rd3_f :multi_rd3 );
assign multi_rd4_ram =(multi_raddr4 ==multi_waddr && multi_raddr4!='b0  )?  1'b0:((multi_raddr4_f ==multi_waddr_f && multi_raddr4_f !='b0  )?multi_rd4_f :multi_rd4 );
assign multi_rd5_ram =(multi_raddr5 ==multi_waddr && multi_raddr5!='b0  )?  1'b0:((multi_raddr5_f ==multi_waddr_f && multi_raddr5_f !='b0  )?multi_rd5_f :multi_rd5 );
assign multi_rd6_ram =(multi_raddr6 ==multi_waddr && multi_raddr6!='b0  )?  1'b0:((multi_raddr6_f ==multi_waddr_f && multi_raddr6_f !='b0  )?multi_rd6_f :multi_rd6 );
assign multi_rd7_ram =(multi_raddr7 ==multi_waddr && multi_raddr7!='b0  )?  1'b0:((multi_raddr7_f ==multi_waddr_f && multi_raddr7_f !='b0  )?multi_rd7_f :multi_rd7 );
assign multi_rd8_ram =(multi_raddr8 ==multi_waddr && multi_raddr8!='b0  )?  1'b0:((multi_raddr8_f ==multi_waddr_f && multi_raddr8_f !='b0  )?multi_rd8_f :multi_rd8 );
assign multi_rd9_ram =(multi_raddr9 ==multi_waddr && multi_raddr9!='b0  )?  1'b0:((multi_raddr9_f ==multi_waddr_f && multi_raddr9_f !='b0  )?multi_rd9_f :multi_rd9 );
assign multi_rd10_ram=(multi_raddr10==multi_waddr && multi_raddr1!='b0  )?  1'b0:((multi_raddr10_f==multi_waddr_f && multi_raddr10_f!='b0  )?multi_rd10_f:multi_rd10);

***補充:具體代碼在文章開頭鏈接

讀寫沖突的仿真結果如下:

1f15203c-0065-11ef-a297-92fbcf53809c.png

五、Multiport RAM仿真和時序

所有寫端口都是一拍寫入。讀端口是第一拍讀使能,讀地址,第二拍讀出數據。

1.單口寫數據

1f45b6b6-0065-11ef-a297-92fbcf53809c.png

2.單端口讀數據

1f601862-0065-11ef-a297-92fbcf53809c.png

3.多口讀相同數據

1f7fb438-0065-11ef-a297-92fbcf53809c.png

4.多口同時讀不同數據

1fb0918e-0065-11ef-a297-92fbcf53809c.png


審核編輯:劉清
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • FPGA
    +關注

    關注

    1620

    文章

    21507

    瀏覽量

    598845
  • 存儲器
    +關注

    關注

    38

    文章

    7365

    瀏覽量

    163083
  • 交換機
    +關注

    關注

    20

    文章

    2570

    瀏覽量

    98218
  • BRAM
    +關注

    關注

    0

    文章

    41

    瀏覽量

    10914
  • Vivado
    +關注

    關注

    19

    文章

    797

    瀏覽量

    65850

原文標題:Multiport RAM,多讀多寫寄存器-——基于FPGA BRAM的多端口地址查找表與FPGA BRAM的資源分析

文章出處:【微信號:gh_cb8502189068,微信公眾號:網絡交換FPGA】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    FPGA ZYNQ Ultrascale+ MPSOC教程】33.BRAM實現PS與PL交互

    有時CPU需要與PL進行小批量的數據交換,可以通過BRAM模塊,也就是Block RAM實現此要求。本章通過Zynq的GP Master接口讀寫PL端的BRAM,實現與PL的交互。在本實驗中加入了自定義的FPGA程序,并利用AX
    的頭像 發表于 02-22 13:51 ?7937次閱讀
    【<b class='flag-5'>FPGA</b> ZYNQ Ultrascale+ MPSOC教程】33.<b class='flag-5'>BRAM</b>實現PS與PL交互

    FPGA設計中BRAM的知識科普

    FPGA設計中,BRAM是一項非常關鍵的內置存儲資源,FPGA開發需要熟練使用BRAM,今天再復習一下B
    發表于 08-15 15:44 ?4170次閱讀
    <b class='flag-5'>FPGA</b>設計中<b class='flag-5'>BRAM</b>的知識科普

    怎么從Virtex 6的FPGA中取出BRAM轉儲

    大家好請任何人告訴我。是否有任何方法可以從Virtex 6的FPGA中取出BRAM轉儲。提前致謝問候Vir_1602以上來自于谷歌翻譯以下為原文Hi all would anyone please
    發表于 03-20 15:37

    如何在不使用DDR內存控制器的情況下設計FPGA BRAM大容量存儲單元?

    來修改我的設計。我刪除了mig_7series IP并將BRAM連接到AXI總線。我還將Microblaze M_AXI_IC和M_AXI_DC端口連接到BRAM,并檢查了MB緩存地址
    發表于 04-04 15:10

    無法正確寫入雙端口BRAM

    嗨,我正在嘗試使用自定義IP寫入vhdl中的雙端口BRAM,該IP生成地址并啟用所有信號,但我無法正確寫入雙端口BRAM。
    發表于 04-17 08:15

    在Virtex-5 FPGA中如何使用BRAM代替SRAM

    嗨,我正在開發一個項目,我們正在使用Virtex-5 FPGA從ADC捕獲信號,樣本存儲在128K x 256 SRAM上,數據樣本由PC采集。我相信Virtex-5為BRAM提供了一個選項,雖然我
    發表于 06-17 11:31

    URAM和BRAM的區別是什么

    。  工作模式  BRAM 可配置為單端口、簡單雙端口和真雙端口,但對于 URAM,不能簡單地將這三種模式映射過來,其工作行為如下圖所示??梢钥吹?,A/B
    發表于 12-23 16:57

    FPGA實現基于Vivado的BRAM IP核的使用

    的使用。 ? ? BRAMFPGA定制的RAM資源,有著較大的存儲空間,且在日常的工程中使用較為頻繁。BRAM以陣列的方式排布于FPGA
    的頭像 發表于 12-29 15:59 ?1.1w次閱讀

    使用FPGA調用RAM資源的詳細說明

    RAM),其中BRAM是block ram,是存在FPGA中的大容量的RAM,DRAM是FPGA中有LUT(look-up table 查找
    發表于 12-30 16:27 ?9次下載

    URAM和BRAM有哪些區別

    無論是7系列FPGA、UltraScale還是UltraScale Plus系列FPGA,都包含Block RAM(BRAM),但只有UltraScale Plus芯片有UltraRAM也就是我們所說的URAM。
    的頭像 發表于 07-25 17:54 ?5487次閱讀
    URAM和<b class='flag-5'>BRAM</b>有哪些區別

    URAM和BRAM有什么區別

    無論是7系列FPGA、UltraScale還是UltraScale Plus系列FPGA,都包含Block RAM(BRAM),但只有UltraScale Plus芯片有UltraRAM也就是我們所說的URAM。
    發表于 01-27 06:55 ?12次下載
    URAM和<b class='flag-5'>BRAM</b>有什么區別

    Vivado中BRAM IP的配置方式和使用技巧

    FPGA開發中使用頻率非常高的兩個IP就是FIFO和BRAM,上一篇文章中已經詳細介紹了Vivado FIFO IP,今天我們來聊一聊BRAM IP。
    的頭像 發表于 08-29 16:41 ?4907次閱讀
    Vivado中<b class='flag-5'>BRAM</b> IP的配置方式和使用技巧

    FPGABRAM資源使用優化策略

    FPGABRAM和LUT等資源都是有限的,在FPGA開發過程中,可能經常遇到BRAM或者LUT資源
    的頭像 發表于 08-30 16:12 ?2089次閱讀
    <b class='flag-5'>FPGA</b>的<b class='flag-5'>BRAM</b><b class='flag-5'>資源</b>使用優化策略

    FPGA實現基于Vivado的BRAM IP核的使用

    定制的RAM資源,有著較大的存儲空間,且在日常的工程中使用較為頻繁。BRAM以陣列的方式排布于FPGA的內部,是FPGA實現各種存儲功能的主要部分,是真正的雙讀/寫
    的頭像 發表于 12-05 15:05 ?1252次閱讀

    基于FPGA設計的BRAM內部結構

    再看末級觸發器對BRAM時序性能的影響,下圖依次展示了7系列FPGA、UltraScale+和Versal芯片在未使用和使用末級觸發器兩種情形下時鐘到輸出的延遲。
    發表于 04-25 10:42 ?289次閱讀
    基于<b class='flag-5'>FPGA</b>設計的<b class='flag-5'>BRAM</b>內部結構