VHDL信号分配延迟和仿真混乱
VHDL signal assignment delay and simulation confusion
VHDL 新手,正在尝试实现小型缓存。
我的一部分cache.vhd
entity cache is
Port ( clock : in STD_LOGIC;
rw_sel : in STD_LOGIC; --'1' to read from cache ,
--'0' to write to cache
ad_sel: in STD_LOGIC; --'0' to send address, '1' to send data
data_in :in STD_LOGIC_VECTOR (7 downto 0);
--send data or address controled by ad_sel
...
end cache;
architecture Behavioral of cache is
....
signal block_addr_n : integer range 0 to 15;
-- cache block address
signal block_cell_addr_n: integer range 0 to 1;
-- byte-in-cache address
begin
process(clock, init)
begin
case init is
when '0' =>
for i in 0 to 15 loop
cache_memory(i)<="1111111111111111";
tag_memory(i)<="11";
end loop;
when others =>null;
end case;
case ad_sel is
when '0' =>
address<=data_in(6 downto 0);
when '1' => data_cpu_wr<=data_in;
when others =>null;
end case;
block_addr_n <= conv_integer(unsigned(address(4 downto 1)));
block_cell_addr_n<=conv_integer(address(0));
case rw_sel is
....
我的测试台文件的一部分:
....
--Inputs
signal clock : std_logic := '0';
signal rw_sel : std_logic := '1';
signal ad_sel : std_logic := '0';
signal init: std_logic:='1';
signal data_in : std_logic_vector(7 downto 0) := (others => '0');
....
stim_proc: process
begin
-- initialize
init<='0';
wait for 100 ns;
-- read address "0101111"(MSB cut), expecting miss
cache_mem_data<="1100110011001100";
ad_sel<='0';
rw_sel<='1';
data_in<="00101111";
clock <= not clock;
wait for 100 ns;
-- write to address "0101111" but written in "0000000" which is default
data_in<="10101010";
ad_sel<='1';
rw_sel<='0';
clock<=not clock;
wait for 100 ns;
data_in<="00101111";
ad_sel<='0';
rw_sel<='1';
clock<=not clock;
wait;
end process;
END;
而我在 ISim window 中得到的是
为什么block_addr_n
和block_cell_addr_n
在第二个100ns内没有被赋值,因为信号address
在那个时候直接被赋值了?我认为这是导致我的程序出现意外结果的原因,因为缓存块 0 被写入,而我只是将地址 0 设置为默认地址,但在第一个 100 ns 后传入地址“0101111”。
有什么想法吗?
敏感列表不包含进程中使用的所有信号,因为address
是一个信号(在同一进程中分配,但这无关紧要)但信号不在进程的敏感列表。所以当 address
的值改变时,模拟器不会重新执行该过程。工艺部件:
process(clock, init)
begin
...
address<=data_in(6 downto 0);
...
block_addr_n <= conv_integer(unsigned(address(4 downto 1)));
block_cell_addr_n<=conv_integer(address(0));
如果您使用的是 VHDL-2008,那么您可以使用 process (all)
自动制作敏感度列表,但我认为 Xilinx 尚未实现 VHDL-2008,因此您可能必须制作敏感度列表手动将所有使用的信号包含在灵敏度列表中。
顺便说一句,考虑让进程要么是纯粹的组合(门),要么是时钟控制的(触发器或 RAM),这样组合进程不应该在敏感列表中有例如 clock
。
我认为您的实际问题可能是对如何编写时钟进程的误解。
现在编写过程的方式将生成纯组合逻辑和锁存器。
你要的是寄存器、RAM和组合逻辑。
时钟进程可以这样写:
process(clock, init) --A clocked process shall have only the clock and reset signal in the sensitivity list. This is correct.
begin
if init = '0' then --"init" is used as a reset signal
for i in 0 to 15 loop
--This will reset the cache memory. It works, but
--doing it this way prevents the synthesis tool from infering a RAM block.
--To allow RAM inference you can write only one memory location per clock cycle.
cache_memory(i)<="1111111111111111";
tag_memory(i)<="11";
end loop;
elsif rising_edge( clock ) then
case ad_sel is
when '0' =>
address<=data_in(6 downto 0);
when '1' => data_cpu_wr<=data_in;
when others =>null;
end case;
block_addr_n <= conv_integer(unsigned(address(4 downto 1)));
block_cell_addr_n<=conv_integer(address(0));
case rw_sel is
...
end if;
请注意,这不会立即起作用。您的测试台中也存在问题。例如,您的初始信号无限期地低。
对于简单的条件,您可能还想使用 "if" 语句而不是 "case"。示例:
if ad_sel='0' then
address<=data_in(6 downto 0);
else
data_cpu_wr<=data_in;
end if;
VHDL 新手,正在尝试实现小型缓存。
我的一部分cache.vhd
entity cache is
Port ( clock : in STD_LOGIC;
rw_sel : in STD_LOGIC; --'1' to read from cache ,
--'0' to write to cache
ad_sel: in STD_LOGIC; --'0' to send address, '1' to send data
data_in :in STD_LOGIC_VECTOR (7 downto 0);
--send data or address controled by ad_sel
...
end cache;
architecture Behavioral of cache is
....
signal block_addr_n : integer range 0 to 15;
-- cache block address
signal block_cell_addr_n: integer range 0 to 1;
-- byte-in-cache address
begin
process(clock, init)
begin
case init is
when '0' =>
for i in 0 to 15 loop
cache_memory(i)<="1111111111111111";
tag_memory(i)<="11";
end loop;
when others =>null;
end case;
case ad_sel is
when '0' =>
address<=data_in(6 downto 0);
when '1' => data_cpu_wr<=data_in;
when others =>null;
end case;
block_addr_n <= conv_integer(unsigned(address(4 downto 1)));
block_cell_addr_n<=conv_integer(address(0));
case rw_sel is
....
我的测试台文件的一部分:
....
--Inputs
signal clock : std_logic := '0';
signal rw_sel : std_logic := '1';
signal ad_sel : std_logic := '0';
signal init: std_logic:='1';
signal data_in : std_logic_vector(7 downto 0) := (others => '0');
....
stim_proc: process
begin
-- initialize
init<='0';
wait for 100 ns;
-- read address "0101111"(MSB cut), expecting miss
cache_mem_data<="1100110011001100";
ad_sel<='0';
rw_sel<='1';
data_in<="00101111";
clock <= not clock;
wait for 100 ns;
-- write to address "0101111" but written in "0000000" which is default
data_in<="10101010";
ad_sel<='1';
rw_sel<='0';
clock<=not clock;
wait for 100 ns;
data_in<="00101111";
ad_sel<='0';
rw_sel<='1';
clock<=not clock;
wait;
end process;
END;
而我在 ISim window 中得到的是
为什么block_addr_n
和block_cell_addr_n
在第二个100ns内没有被赋值,因为信号address
在那个时候直接被赋值了?我认为这是导致我的程序出现意外结果的原因,因为缓存块 0 被写入,而我只是将地址 0 设置为默认地址,但在第一个 100 ns 后传入地址“0101111”。
有什么想法吗?
敏感列表不包含进程中使用的所有信号,因为address
是一个信号(在同一进程中分配,但这无关紧要)但信号不在进程的敏感列表。所以当 address
的值改变时,模拟器不会重新执行该过程。工艺部件:
process(clock, init)
begin
...
address<=data_in(6 downto 0);
...
block_addr_n <= conv_integer(unsigned(address(4 downto 1)));
block_cell_addr_n<=conv_integer(address(0));
如果您使用的是 VHDL-2008,那么您可以使用 process (all)
自动制作敏感度列表,但我认为 Xilinx 尚未实现 VHDL-2008,因此您可能必须制作敏感度列表手动将所有使用的信号包含在灵敏度列表中。
顺便说一句,考虑让进程要么是纯粹的组合(门),要么是时钟控制的(触发器或 RAM),这样组合进程不应该在敏感列表中有例如 clock
。
我认为您的实际问题可能是对如何编写时钟进程的误解。 现在编写过程的方式将生成纯组合逻辑和锁存器。 你要的是寄存器、RAM和组合逻辑。
时钟进程可以这样写:
process(clock, init) --A clocked process shall have only the clock and reset signal in the sensitivity list. This is correct.
begin
if init = '0' then --"init" is used as a reset signal
for i in 0 to 15 loop
--This will reset the cache memory. It works, but
--doing it this way prevents the synthesis tool from infering a RAM block.
--To allow RAM inference you can write only one memory location per clock cycle.
cache_memory(i)<="1111111111111111";
tag_memory(i)<="11";
end loop;
elsif rising_edge( clock ) then
case ad_sel is
when '0' =>
address<=data_in(6 downto 0);
when '1' => data_cpu_wr<=data_in;
when others =>null;
end case;
block_addr_n <= conv_integer(unsigned(address(4 downto 1)));
block_cell_addr_n<=conv_integer(address(0));
case rw_sel is
...
end if;
请注意,这不会立即起作用。您的测试台中也存在问题。例如,您的初始信号无限期地低。
对于简单的条件,您可能还想使用 "if" 语句而不是 "case"。示例:
if ad_sel='0' then
address<=data_in(6 downto 0);
else
data_cpu_wr<=data_in;
end if;