Memory ISE自动推断ram块需要满足哪些要求?

Memory ISE自动推断ram块需要满足哪些要求?,memory,ip,vhdl,xilinx,hdl,Memory,Ip,Vhdl,Xilinx,Hdl,我有一个IP,应该是一个32位字节的可寻址内存。但我不能让它推断方块公羊,它推断了大量的人字拖 它应该安装在只有双端口块RAM的Spartan3e(xc3s1200e-4fg320)上,实际上,内存以奇偶排列分成两个阵列 这是代码,我希望这可能有助于理解我做错了什么 library IEEE; use IEEE.STD_LOGIC_1164.ALL; package mem_types is type memory_t is array (natural range <>)

我有一个IP,应该是一个32位字节的可寻址内存。但我不能让它推断方块公羊,它推断了大量的人字拖

它应该安装在只有双端口块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;
IEEE库;
使用IEEE.STD_LOGIC_1164.ALL;
包成员类型为
类型存储器是标准逻辑向量(7到0)的数组(自然范围);
末端成员类型;
图书馆IEEE;
使用IEEE.STD_LOGIC_1164.ALL;
使用IEEE.STD_LOGIC_ARITH.ALL;
使用IEEE.STD_LOGIC_UNSIGNED.ALL;
使用work.mem_types.all;
----如果正在实例化,请取消对以下库声明的注释
----此代码中的任何Xilinx原语。
--UNISIM图书馆;
--使用UNISIM.VComponents.all;
实体ram是
一般的(
INIT:memory_t(0到4095):=(其他=>(其他=>'0'))
);
端口(时钟,rst:标准逻辑中;
地址:在标准逻辑向量中(11到0);
din:标准逻辑向量(31到0);
dout:输出标准逻辑向量(31到0);
we:std_逻辑_向量(3到0)
);
端头闸板;
ram的体系结构是
类型ramport\t为记录
地址:标准逻辑向量(10到0);
dout:std_逻辑_向量(7到0);
din:标准逻辑向量(7到0);
wea:std_逻辑;
结束记录;
信号端口0A、端口0B、端口1A、端口1B:ramport;
信号地址a、地址b、地址c、地址d:标准逻辑向量(11到0);
信号存储器0,存储器1:存储器t(0到2047);
开始
addr_a这在FPGA流程的编码部分中进行了描述。我几乎可以肯定的是,重置循环导致了触发器的推断。该代码要求同时访问内存的所有元素,这在块RAM中是不可能的。

您不能这样做:

process (clk, rst)
begin
    if rst = '1' then
        for a in 0 to 2047 loop
            memory0(a) <= INIT(a*2);
        end loop;
您当前的操作方式(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);

这一切都适用于模拟。XST合成器推断INIT值可能会成功,也可能不会成功——我还没有尝试过。检查合成日志文件以查看它报告了什么-请向我们报告它是否有效以及您尝试使用的XST版本。

首先,您可能希望使用ieee.NUMERIC_STD.all,而不是非标准库STD_LOGIC_ARITH和STD_LOGIC_UNSIGNED。这就解释了为什么:我显式地使用IP向导生成的IP块,而不用担心试图推断这些块。如果您需要优化注册的输入和输出以达到硬IP块的开关限制,那么这将有很大帮助。(与所有其他硬IP块一样,块ram需要额外的延迟才能以最快的速度运行)
signal memory0 : memory_t(0 to 2047) := init_mem(INIT);