2011-02-14 102 views
1

我有這塊IP應該是一個32位字節的可尋址內存。但我不能推斷塊RAM,它推斷大量的觸發器...爲了ISE自動推斷內存塊,滿足哪些要求?

它應該適合於只有雙端口塊RAM,Spartan3e(xc3s1200e-4fg320),確實是內存分成兩個陣列在一個奇數排列...

這是代碼,我希望這可能有助於理解我做錯了什麼?

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 

package mem_types is 
    type memory_t is array (natural range <>) of std_logic_vector(7 downto 0); 
end mem_types; 

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 
use IEEE.STD_LOGIC_ARITH.ALL; 
use IEEE.STD_LOGIC_UNSIGNED.ALL; 
use work.mem_types.all; 

---- Uncomment the following library declaration if instantiating 
---- any Xilinx primitives in this code. 
--library UNISIM; 
--use UNISIM.VComponents.all; 

entity ram is 
    generic (
     INIT : memory_t(0 to 4095) := (others => (others => '0')) 
    ); 

    port (clk, rst : in std_logic; 
      addr : in std_logic_vector(11 downto 0); 
      din : in std_logic_vector(31 downto 0); 
      dout : out std_logic_vector(31 downto 0); 
      we : std_logic_vector(3 downto 0) 
     ); 
end ram; 

architecture Behavioral of ram is 
    type ramport_t is record 
     addr : std_logic_vector(10 downto 0); 
     dout : std_logic_vector(7 downto 0); 
     din : std_logic_vector(7 downto 0); 
     wea : std_logic; 
    end record; 
    signal port0a, port0b, port1a, port1b : ramport_t; 
    signal addr_a, addr_b, addr_c, addr_d : std_logic_vector(11 downto 0); 
    signal memory0, memory1 : memory_t(0 to 2047); 
begin 

    addr_a <= addr; 
    addr_b <= addr+1; 
    addr_c <= addr+2; 
    addr_d <= addr+3; 

    port0a.addr <= addr_a(11 downto 1) when addr_a(0) = '0' else addr_b(11 downto 1); 
    port1a.addr <= addr_b(11 downto 1) when addr_b(0) = '1' else addr_a(11 downto 1); 
    port0b.addr <= addr_c(11 downto 1) when addr_c(0) = '0' else addr_d(11 downto 1); 
    port1b.addr <= addr_d(11 downto 1) when addr_d(0) = '1' else addr_c(11 downto 1); 

    dout(07 downto 00) <= port0a.dout when addr_a(0) = '0' else port1a.dout; 
    dout(15 downto 08) <= port1a.dout when addr_b(0) = '1' else port0a.dout; 
    dout(23 downto 16) <= port0b.dout when addr_c(0) = '0' else port1b.dout; 
    dout(31 downto 24) <= port1b.dout when addr_d(0) = '1' else port0b.dout; 

    port0a.din <= din(07 downto 00) when addr_a(0) = '0' else din(15 downto 08); 
    port1a.din <= din(15 downto 08) when addr_b(0) = '1' else din(07 downto 00); 
    port0b.din <= din(23 downto 16) when addr_c(0) = '0' else din(31 downto 24); 
    port1b.din <= din(31 downto 24) when addr_d(0) = '1' else din(23 downto 16); 

    port0a.wea <= we(0) when addr_a(0) = '0' else we(1); 
    port1a.wea <= we(1) when addr_b(0) = '1' else we(0); 
    port0b.wea <= we(2) when addr_c(0) = '0' else we(3); 
    port1b.wea <= we(3) when addr_d(0) = '1' else we(2); 

    port0a.dout <= memory0(conv_integer(port0a.addr)); 
    port0b.dout <= memory0(conv_integer(port0b.addr)); 
    port1a.dout <= memory1(conv_integer(port1a.addr)); 
    port1b.dout <= memory1(conv_integer(port1b.addr)); 

    process (clk, rst) 
    begin 
     if rst = '1' then 
      for a in 0 to 2047 loop 
       memory0(a) <= INIT(a*2); 
      end loop; 
     elsif falling_edge(clk) then 
      if (port0a.wea = '1') then 
       memory0(conv_integer(port0a.addr)) <= port0a.din; 
      end if; 

      if (port0b.wea = '1') then 
       memory0(conv_integer(port0b.addr)) <= port0b.din; 
      end if; 
     end if; 
    end process; 

    process (clk, rst) 
    begin 
     if rst = '1' then 
      for a in 0 to 2047 loop 
       memory1(a) <= INIT((a*2)+1); 
      end loop; 
     elsif falling_edge(clk) then 
      if (port1a.wea = '1') then 
       memory1(conv_integer(port1a.addr)) <= port1a.din; 
      end if; 

      if (port1b.wea = '1') then 
       memory1(conv_integer(port1b.addr)) <= port1b.din; 
      end if; 
     end if; 
    end process; 

end Behavioral; 
+1

首先,您可能想要使用ieee.NUMERIC_STD.all而不是非標準庫STD_LOGIC_ARITH和STD_LOGIC_UNSIGNED。這解釋了爲什麼:http://parallelpoints.com/node/3 – Philippe 2011-02-14 09:46:40

回答

2

這在Xilinx Synthesis Guide編碼爲FPGA流說明。我幾乎可以肯定,重置循環會導致觸發器被推斷出來。該代碼要求同時訪問存儲器的所有元素,這對Block RAM是不可能的。

1

你不能做到這一點:

process (clk, rst) 
begin 
    if rst = '1' then 
     for a in 0 to 2047 loop 
      memory0(a) <= INIT(a*2); 
     end loop; 

......作爲被要求一個復位內存,而不是初始化之一。

初始化,您需要更改信號的聲明是形式

signal memory0 : memory_t(0 to 2047) := (some list of integers or something that returns an array of integers); 

的方式目前你正在做它(與你的init的交錯),意味着你將不得不使用功能:

function init_mem(init_values: memory_t) returns memory_t is 
variable retval : memory_t(init_values'high/2)+1 downto 0); 
begin 
    for i in retval'range loop 
     retval(i) := init_values(2*i); 
    end for; 
end function; 

(注意,這是輸入了我的頭頂,我甚至不試圖編譯它,所以道歉,對任何拼寫錯誤和語法錯誤......但我希望你的想法:)

然後您可以使用它來初始化信號:

signal memory0 : memory_t(0 to 2047) := init_mem(INIT); 

這將全部用於仿真。您可能會或可能不會成功推出INIT值的XST合成器 - 我還沒有嘗試過。檢查綜合日誌文件以查看它所報告的內容 - 請向我們報告它是否正常工作以及您嘗試使用哪種版本的XST。

相關問題