Проблема с назначением с std_logic_vector
Я пытаюсь написать компонент (mem_interface), который принимает 8-битные входные векторы для адреса и данных, записывает их в определенные позиции в больших векторных буферах в зависимости от индекса, а затем выводит эти большие векторные буферы при запросе. Компонент будет находиться между процессором picoblaze (который может выводить только 8-битные значения) и Artix 7 BRAM, который я настроил с 18-битной шириной порта чтения / записи (так что 11-битные адреса). В качестве конечной цели mem_interface будет накапливать несколько 8-битных выходных сигналов из picoblaze, а затем считывать / записывать BRAM по предоставленному адресу с предоставленными данными.
У меня проблема в том, что запись во внутренний буфер данных mem_interface не вступает в силу.
При 15 нс testbench сначала проверяет запись в адресный буфер компонента, который отлично работает. При 45 нс он пытается выполнить запись в буфер данных, который немедленно отправляет целевые элементы в "X". Я всегда понимал, что "X" означает проблему с несколькими драйверами, но я не могу определить ее в своем коде.
Вот код, в первую очередь mem_interface.vhdl:
library ieee;
use ieee.std_logic_1164.all;
entity mem_interface is
port (
-- data inputs
clk : in std_logic;
idx : in std_logic_vector(1 downto 0);
split_addr_in : in std_logic_vector(7 downto 0);
split_data_in : in std_logic_vector(7 downto 0);
parity_in : in std_logic;
split_data_out : out std_logic_vector(7 downto 0);
parity_out : out std_logic;
-- signals
addr_buf_en : in std_logic;
data_buf_wr : in std_logic;
data_buf_rd : in std_logic;
reset_bufs : in std_logic;
write_to_mem : in std_logic;
read_from_mem : in std_logic;
-- to bram
addr_out : out std_logic_vector(15 downto 0);
data_out : out std_logic_vector(35 downto 0);
data_in : in std_logic_vector(35 downto 0)
);
end mem_interface;
architecture Behavioral of mem_interface is
signal addr_buf : std_logic_vector(15 downto 0) := (others => '0');
signal data_buf : std_logic_vector(35 downto 0) := (others => '0');
begin
handle_addr_buf : process(clk)
begin
if rising_edge(clk) then
if addr_buf_en = '1' then
case idx(0) is
when '0' => addr_buf(7 downto 0) <= split_addr_in;
when '1' => addr_buf(15 downto 8) <= split_addr_in;
when others => addr_buf <= "1010101010101010";
end case;
elsif reset_bufs = '1' then
addr_buf <= (others => '0');
end if;
end if;
end process handle_addr_buf;
handle_data_buf : process(clk)
begin
if rising_edge(clk) then
if data_buf_wr = '1' then
case idx is
when "00" => data_buf(7 downto 0) <= split_data_in;
data_buf(32) <= parity_in;
when "01" => data_buf(15 downto 8) <= split_data_in;
data_buf(33) <= parity_in;
when "10" => data_buf(23 downto 16) <= split_data_in;
data_buf(34) <= parity_in;
when "11" => data_buf(31 downto 24) <= split_data_in;
data_buf(35) <= parity_in;
when others => data_buf <= "101010101010101010101010101010101010";
end case;
elsif data_buf_rd = '1' then
case idx is
when "00" => parity_out <= data_buf(32);
split_data_out <= data_buf(7 downto 0);
when "01" => parity_out <= data_buf(33);
split_data_out <= data_buf(15 downto 8);
when "10" => parity_out <= data_buf(34);
split_data_out <= data_buf(23 downto 16);
when "11" => parity_out <= data_buf(35);
split_data_out <= data_buf(31 downto 24);
when others => split_data_out <= "10101010";
end case;
elsif reset_bufs = '1' then
data_buf <= (others => '0');
end if;
end if;
end process handle_data_buf;
handle_memory : process(clk)
begin
if rising_edge(clk) then
if write_to_mem = '1' then
addr_out <= addr_buf;
data_out <= data_buf;
elsif read_from_mem = '1' then
addr_out <= addr_buf;
data_buf <= data_in;
else
addr_out <= (others => '0');
data_out <= (others => '0');
end if;
end if;
end process handle_memory;
end Behavioral;
А вот и тестовый стенд, mem_interface_tb.vhdl
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity mem_interface_tb is
-- Port ( );
end mem_interface_tb;
architecture Behavioral of mem_interface_tb is
component mem_interface is
port (
-- data inputs
clk : in std_logic;
idx : in std_logic_vector(1 downto 0);
split_addr_in : in std_logic_vector(7 downto 0);
split_data_in : in std_logic_vector(7 downto 0);
parity_in : in std_logic;
split_data_out : out std_logic_vector(7 downto 0);
parity_out : out std_logic;
-- signals
addr_buf_en : in std_logic;
data_buf_wr : in std_logic;
data_buf_rd : in std_logic;
reset_bufs : in std_logic;
write_to_mem : in std_logic;
read_from_mem : in std_logic;
-- to bram
addr_out : out std_logic_vector(15 downto 0);
data_out : out std_logic_vector(35 downto 0);
data_in : in std_logic_vector(35 downto 0)
);
end component;
component sim_clk_wrapper
port (
sim_clk_out : out std_logic;
sim_rst_out : out std_logic
);
end component;
signal sim_clk_sig : std_logic;
signal sim_rst_sig : std_logic;
signal sim_idx : std_logic_vector(1 downto 0) := "00";
signal sim_split_addr_in : std_logic_vector(7 downto 0) := (others => '0');
signal sim_split_data_in : std_logic_vector(7 downto 0) := (others => '0');
signal sim_parity_in : std_logic := '0';
signal sim_split_data_out : std_logic_vector(7 downto 0) := (others => '0');
signal sim_parity_out : std_logic := '0';
signal sim_addr_buf_en : std_logic := '0';
signal sim_data_buf_wr : std_logic := '0';
signal sim_data_buf_rd : std_logic := '0';
signal sim_reset_bufs : std_logic := '0';
signal sim_write_to_mem : std_logic := '0';
signal sim_read_from_mem : std_logic := '0';
signal sim_addr_out : std_logic_vector(15 downto 0) := (others => '0');
signal sim_data_out : std_logic_vector(35 downto 0) := (others => '0');
signal sim_data_in : std_logic_vector(35 downto 0) := (others => '0');
type bram_36k is array (0 to 2048) of std_logic_vector(17 downto 0);
signal sim_bram_36k : bram_36k;
begin
sim_clk_gen : sim_clk_wrapper
port map (
sim_clk_out => sim_clk_sig,
sim_rst_out => sim_rst_sig
);
UUT : mem_interface
port map (
clk => sim_clk_sig,
idx => sim_idx,
split_addr_in => sim_split_addr_in,
split_data_in => sim_split_data_in,
parity_in => sim_parity_in,
split_data_out => sim_split_data_out,
parity_out => sim_parity_out,
addr_buf_en => sim_addr_buf_en,
data_buf_wr => sim_data_buf_wr,
data_buf_rd => sim_data_buf_rd,
reset_bufs => sim_reset_bufs,
write_to_mem => sim_write_to_mem,
read_from_mem => sim_read_from_mem,
addr_out => sim_addr_out,
data_out => sim_data_out,
data_in => sim_data_in
);
-- simulating 18 bit port sizes with 11 bit addresses
manage_sim_bram : process(sim_clk_sig)
begin
if rising_edge(sim_clk_sig) then
if sim_write_to_mem = '1' then
sim_bram_36k(to_integer(unsigned(sim_addr_out(14 downto 4)))) <= sim_data_out(33 downto 32) & sim_data_out(15 downto 0);
elsif sim_read_from_mem = '1' then
sim_data_in(33 downto 32) <= sim_bram_36k(to_integer(unsigned(sim_addr_out(14 downto 4))))(17 downto 16);
sim_data_in(15 downto 0) <= sim_bram_36k(to_integer(unsigned(sim_addr_out(14 downto 4))))(15 downto 0);
end if;
end if;
end process manage_sim_bram;
simulate: process
begin
wait until rising_edge(sim_clk_sig);
sim_reset_bufs <= '1';
wait until rising_edge(sim_clk_sig);
-- first write an address to the buffer
sim_reset_bufs <= '0';
sim_addr_buf_en <= '1';
sim_idx <= "00";
sim_split_addr_in <= "00001111";
wait until rising_edge(sim_clk_sig);
sim_idx <= "01";
sim_split_addr_in <= "10000000";
wait until rising_edge(sim_clk_sig);
-- disable writing to address
sim_addr_buf_en <= '0';
sim_split_addr_in <= "00000000";
sim_idx <= "00";
wait until rising_edge(sim_clk_sig);
-- write to the data
sim_data_buf_wr <= '1';
sim_idx <= "00";
sim_split_data_in <= "11111111";
sim_parity_in <= '1';
wait until rising_edge(sim_clk_sig);
sim_idx <= "01";
sim_split_data_in <= "11111111";
sim_parity_in <= '1';
wait until rising_edge(sim_clk_sig);
-- then write the data to the memory
sim_data_buf_wr <= '0';
sim_split_data_in <= "00000000";
sim_parity_in <= '0';
sim_write_to_mem <= '1';
wait until rising_edge(sim_clk_sig);
wait until rising_edge(sim_clk_sig);
wait until rising_edge(sim_clk_sig);
end process simulate;
end Behavioral;
Буду признателен за любую помощь, я смотрю на это в течение нескольких часов и не знаю, в чем проблема.