ISE 自动推断 RAM 块需要满足哪些要求?
我有一段 IP,它应该是 32 位字节可寻址内存。但我无法让它推断块内存,它正在推断大量的触发器...
它应该适合仅具有双端口块内存的 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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Xilinx 综合指南 下的 FPGA 流程编码。我几乎可以肯定重置循环会导致推断失败。该代码需要同时访问存储器的所有元素,而这对于 Block RAM 来说是不可能的。
This is described in the Xilinx Synthesis Guide under Coding for FPGA Flow. I'm almost certain that reset loop is causing flops to be inferred. That code requires accessing all elements of the memory simultaneously, which is not possible with Block RAM.
你不能这样做:
...因为这需要一个可重置内存,而不是一个初始化内存。
要初始化,您需要将信号声明更改为以下形式
您当前执行此操作的方式(与您的 init 交错)意味着您必须使用一个函数:(
请注意,这是我凭空想象出来的我什至没有尝试编译它,所以对任何拼写错误和语法错误表示歉意......但我希望你明白:)
然后你可以用它来初始化信号:
这将全部用于模拟。您可能会或可能不会成功使用 XST 合成器推断 INIT 值 - 我还没有尝试过。检查综合日志文件以查看其报告的内容 - 请向我们报告它是否有效以及您在哪个版本的 XST 上尝试过它。
You can't do this:
...as that is asking for a resettable memory, rather than an initialised one.
To initialise, you need to change your signal declaration to be of the form
The way you are currently doing it (with your init's interleaved) means you'll have to use a function:
(note that that was typed off the top of my head and I've not even tried to compile it, so apologies for any typos and syntax errors... but I hope you get the idea :)
Then you can use this to init the signal:
This will all work for simulation. You may or may not have success with the XST synthesiser inferring the INIT values - I haven't tried. Check the synthesis logfile to see what it reports - and please do report back to us whether it works and on what version of XST you tried it.