2016-08-18 43 views
0

我試圖推斷VHDL二維塊RAM。但詳細的電路原來是寄存器和MUX的電路。對於有關RAM中的代碼的主要文件是:推斷2D塊RAM賽靈思vivado

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 
use work.shared_resources.all; 

entity weight_ram is 
    port (clk : in std_logic; 
      write_enable : in std_logic; 
      row_addr : in natural range 0 to max_NR-1; 
      data_in : in neuron_weight_array; 
      data_out : out neuron_weight_array); 
end weight_ram; 

architecture rtl of weight_ram is 
    signal ram : weight_ram_array; 
begin 
    ram_process : process (clk) 
     variable f : integer; 
    begin 
     if (rising_edge (clk)) then 
      if (write_enable = '1') then 
       for f in 0 to n_feature-1 loop 
        ram (row_addr, f) <= data_in (f); 
       end loop; 
      end if; 
      for f in 0 to n_feature-1 loop 
       data_out (f) <= ram (row_addr, f); 
      end loop; 
     end if; 
    end process; 
end rtl; 

含有使用的常量的文件是:

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 

package shared_resources is 
    constant n_feature : integer := 24; 
    constant max_NR : integer := 10; -- maximum number of neurons allowed 
    constant weightw : integer := 10; -- width of the weight (1:0:9) 

    subtype weight_type is signed (weightw-1 downto 0); 
    type neuron_weight_array is array (0 to n_feature-1) of weight_type; 
    type weight_ram_array is array (0 to max_NR-1, 0 to n_feature-1) of weight_type; 
end shared_resources; 

我怎樣才能確保代碼被推斷爲一個塊RAM?

更新:更新了代碼以從2d數組中讀取單個元素(基於morten zilmer的回答)。但它仍然不會被推斷爲Block RAM。

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 
use work.shared_resources.all; 

entity weight_ram is 
    port (clk : in std_logic; 
      write_enable : in std_logic; 
      row_addr : in natural range 0 to max_NR-1; 
      col_addr : in natural range 0 to n_feature-1; 
      data_in : in weight_type; 
      data_out : out weight_type); 
end weight_ram; 

architecture rtl of weight_ram is 
    signal ram : weight_ram_array; 
begin 
    ram_process : process (clk) 
     variable f : integer; 
    begin 
     if (rising_edge (clk)) then 
      if (write_enable = '1') then 
       ram (row_addr, col_addr) <= data_in; 
      end if; 
      data_out <= ram (row_addr, col_addr); 
     end if; 
    end process; 
end rtl; 
+0

你或許應該嘗試使用一維數組。內存推斷是棘手的。如果您沒有完全遵守供應商模板,則合成器無法達到您想要的效果。 –

回答

0

當訪問一個塊RAM,則每個時鐘允許數據字的讀出在單個地址,並且每個時鐘允許在一個單一地址的數據字的寫入。

在提供的設計中,每個時鐘都讀取所有位置,然後在每個時鐘寫入所有位置。

這樣的設計沒有實現的塊RAM和工具,因此不能使用塊RAM。

+0

即使我嘗試讀取RAM中的單個元素,該電路仍然不會被推斷爲塊RAM。我在上面的問題中添加了更新後的電路 – user3575732

+0

該工具可以使用Block RAM或分佈式FF和多路複用器實現設計,因爲這允許根據約束進行優化。如果由於某種原因你真的想要一個塊RAM,那麼直接實例化它。 –

0

如果您試圖推斷FPGA中的特定硬件,最好的方法是查看您正在使用的任何設備和/或工具鏈的綜合用戶指南。對於Vivado,這是「Vivado Design Suite用戶指南:綜合(UG901)」。我不會鏈接到這個網址,因爲隨着Vivado的每個新版本URL的變化,但如果你去the Xilinx web site,並搜索UG901,最新版本應該是最好的結果。

本文檔(或Xilinx ISE,Altera Quartus等的相應文檔)將包含有關如何推斷各種FPGA元素的示例部分,這些部分稱爲「推理模板」。在這種情況下,第3章有一個「RAM HDL編碼指南」一節,這裏有所有推斷各種RAM樣式的方法的例子,包括您的要求,即「單端口Block RAM」。

我想說的一些推理模板的一件事是,他們不使用ieee.numeric_std.all。當他們使用「舊」風格的功能,如conv_integer,你可以沒有問題替代numeric_std當量(即to_integer)。

回到你的二維數組,你應該在寫入寬度爲10的內存時,通過連接行和列號來形成一個地址,沿着address <= column & row行。

另一個需要注意的是,如果存儲深度很小,這些工具可能會自動將推斷塊RAM轉換爲分佈式RAM。根據我的經驗,如果這些工具做到了這一點,無論如何它都是最好的,但是您可以很容易地看到,通過在Vivado中打開「Elaborated Design」,可以推斷出至少有一個「內存塊」,並查看原理圖。在此範圍內,您應該能夠找到您的內存繪製爲無法展開的單個塊。這可能會在合成期間使用分佈式RAM或塊RAM,具體取決於內存深度。

0

此:

subtype weight_type is signed (weightw-1 downto 0); 
type weight_ram_array is array (0 to max_NR-1, 0 to n_feature-1) of weight_type; 

不會被合成爲對Xilinx器件的BRAM。我假設你看到如下消息:「它不會映射到BRAM,它太稀疏」或類似。然而,你可以做一個小竅門。如果要使用單獨的ROW_ADDRCOL_ADDR爲您的地址計算,你可以改變你的內存並連接所有的地址,如:

architecture rtl of weight_ram is 

type my_weight_type_array is array(0 to max_NR*n_feature-1) of weight_type; 
signal ram : my_weight_type_array; 

signal row_and_col : natural range 0 to max_NR*n_feature-1 ; 

begin 
    row_and_col <= to_integer(to_unsigned(row_addr,4) & to_unsigned(col_addr,5));                              

    ram_process : process (clk) 
     variable f : integer; 
    begin 
     if (rising_edge (clk)) then 
      if (write_enable = '1') then 
       ram (row_and_col) <= data_in; 
      end if; 
      data_out <= ram (row_and_col); 
     end if; 
    end process; 
end rtl; 

注:VHDL爲過去5年,所以我沒有寫任何東西你應該模擬它並檢查它的行爲是否正確。特別是這部分:

row_and_col <= to_integer(to_unsigned(row_addr,4) & to_unsigned(col_addr,5)); 

Ekhm ...強類型語言...

+0

'row_and_col <=((2 ** 5)* row_addr)+ col_addr;'?我看到的大多數長鏈類型轉換都很容易避免。 –

+0

@scary_jeff是的,這應該做的工作。 –