我正在尝试模拟RAM类型的存储器,输入和输出呈现在相同的线路和功能上,并通过3个控制引脚选择。 ceN用于启用器件(否则输出为高Z),weN用于允许写入RAM,而oeN不启用输出到data_io向量。这些控件都是低电平有效类型。
这通过了Quartus II下的编译,但是不能很好地模拟Modelsim或Quartus的内置模拟。
library ieee ;
use ieee.std_logic_1164.all ;
entity ram1 is
port ( address : in integer range 0 to 255 ;
ceN : in std_logic ;
weN : in std_logic ;
oeN : in std_logic ;
data_io : buffer std_logic_vector(7 downto 0) ) ;
end ram1 ;
architecture arc_ram1 of ram1 is
type mem_array is array (0 to 255) of std_logic_vector(7 downto 0) ;
signal ram : mem_array ;
signal data : std_logic_vector(7 downto 0) ;
begin
process ( address , ceN , weN , oeN , data_io )
begin
-- write to RAM
if ceN = '0' then
if weN = '0' then
ram(address) <= to_x01(data_io) ;
elsif oeN = '0' then
data_io <= ram(address) ;
end if ;
else
data_io <= (others => 'Z') ;
end if ;
end process ;
end arc_ram1 ;
答案 0 :(得分:1)
您确实希望将data_io信号的类型切换为inout。当你这样做时,你暗示一个三态缓冲区。这意味着在您的逻辑(包括您的测试平台)中,您必须确保无论何时一方正在驱动接口,另一方正在驱动'Z',否则总线将有两个驱动程序,如果两者都模拟器将显示'X'司机有相同的驱动力。
这是一个简单的测试序列,可以与您的DUT一起使用,以显示RAM读/写逻辑是否正常工作:
test: process is
begin
address <= 0;
data_io <= (others => 'Z');
ceN <= '0';
oeN <= '0';
weN <= '1';
wait for 20 ns;
address <= 0;
data_io <= (others => '1');
oeN <= '1';
weN <= '0';
wait for 20 ns;
address <= 0;
data_io <= (others => 'Z');
oeN <= '0';
weN <= '1';
wait for 20 ns;
address <= 1;
data_io <= (others => '0');
oeN <= '1';
weN <= '0';
wait for 20 ns;
address <= 1;
data_io <= (others => 'Z');
oeN <= '0';
weN <= '1';
wait for 20 ns;
address <= 0;
wait for 20 ns;
end process test;
我必须修改你的逻辑,以确保当测试平台在内存写入期间尝试驱动RAM时,RAM没有驱动data_io总线:
process ( address , ceN , oeN, weN , data_io )
begin
-- write to RAM
if ceN = '0' then
if weN = '0' then
ram(address) <= to_x01(data_io) ;
data_io <= (others => 'Z') ; -- *** Added this ***
elsif oeN = '0' then
data_io <= ram(address) ;
end if ;
else
data_io <= (others => 'Z') ;
end if ;
end process ;
如果以这种方式编写进程代码,我必须在写入期间添加三态data_io总线的原因可能更容易理解:
process ( address , ceN , oeN, weN , data_io )
begin
-- write to RAM
if ((ceN = '0') and (weN = '0')) then
ram(address) <= to_x01(data_io) ;
end if ;
-- read from RAM
if ((ceN = '0') and (oeN = '0')) then
data_io <= ram(address) ;
else
data_io <= (others => 'Z') ;
end if ;
end process ;
答案 1 :(得分:0)
你已经创建了一些透明锁存器!
让您的流程同步,例如
process(clk)
begin
if rising_edge(clk) then
...
end if;
end process;
例如,以下内容之间存在很大差异:
process(en, d)
signal q : std_logic;
begin
if en = '1' then
q <= d;
end if;
end process;
以及以下内容:
process(clk)
signal q : std_logic;
begin
if rising_edge(clk) then
if en = '1' then
q <= d;
end if;
end if;
end process;
这些示例中的第一个是透明锁存器,后者是常规触发器。前者容易受到输入中的短暂错误的影响,并且通常无法映射到真实硬件。后者是设计合适的FPGA逻辑的方法。 Quartus可能会让你通过警告来逃避它,但它肯定不是你想要的!
另外,检查您的警告,看看Quartus是否推断了透明锁存器而不是您想要的RAM块。它仍然可以构建,即使这种行为几乎从来都不是故意的。