library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; -- Блок памяти (8х32) способен принимать данные с двух устройств одновременно; -- Со стороны контроллера - постфикс "0" - данные грузятся в ячейку памяти четырьмя транзакциями, поскольку шина данных здесь всего 8 бит; -- Со стороны ПЛИС - постфикс "1" - данные грузятся за одну транзакцию (шина данных 32х разрядная); -- Для работы с контроллером дополнительно введены два бита BL для определения с какой частью ячейки памяти работаем; -- Когда в комментариях говорю "со стороны ПЛИС" - это значит, что есть IP блок диспетчеризации, -- который получает свежайшие данные от остальных IP блоков на ПЛИС, создает приоритетную очередь и грузит эти данные в ячейки памяти; entity RAM is port( clk : in std_logic; data0 : inout std_logic_vector(7 downto 0); address0 : in std_logic_vector(7 downto 0); we0 : in std_logic; oe0 : in std_logic; ce0 : in std_logic; bl0 : in std_logic_vector(1 downto 0); data1 : inout std_logic_vector(31 downto 0); address1 : in std_logic_vector(7 downto 0); we1 : in std_logic; oe1 : in std_logic; ce1 : in std_logic ); end entity; architecture behavorial of RAM is type mem is array (255 downto 0) of std_logic_vector(31 downto 0); signal memory : mem; signal we0Prev : std_logic := '0'; signal oe0Prev : std_logic := '0'; signal ce0Prev : std_logic := '0'; signal we1Prev : std_logic := '0'; signal oe1Prev : std_logic := '0'; signal ce1Prev : std_logic := '0'; type MemoryMachine is (Waiting, Writing, Reading); signal stateMM0 : MemoryMachine := Waiting; signal stateMM1 : MemoryMachine := Waiting; begin process(clk) variable addr0 : integer range 0 to 255 := 0; variable part0 : integer range 0 to 3 := 0; variable addr1 : integer range 0 to 255 := 0; begin if rising_edge(clk) then case stateMM0 is when Waiting => if ce0 = '0' and ce0Prev = '1' then addr0 := conv_integer(address0); part0 := conv_integer(bl0); if oe0 = '0' then -- этот if можно перенести на следующий такт, чтобы успела установиться ножка output enable stateMM0 <= Reading; else stateMM0 <= Writing; end if; else data0 <= (others => 'Z'); end if; when Reading => data0 <= memory(addr0)(7 + part0*8 downto part0*8); if oe0 = '1' and oe0Prev = '0' then stateMM0 <= Waiting; elsif ce0 = '1' then stateMM0 <= Waiting; end if; when Writing => if we0 = '0' and we0Prev = '1' then memory(addr0)(7 + part0*8 downto part0*8) <= data0; stateMM0 <= Waiting; elsif ce0 = '1' then stateMM0 <= Waiting; end if; when others => end case; oe0Prev <= oe0; ce0Prev <= ce0; we0Prev <= we0; case stateMM1 is when Waiting => if ce1 = '0' and ce1Prev = '1' then addr1 := conv_integer(address1); if oe1 = '0' then -- этот if можно перенести на следующий такт, чтобы успела установиться ножка output enable stateMM1 <= Reading; else stateMM1 <= Writing; end if; else data1 <= (others => 'Z'); end if; when Reading => data1 <= memory(addr1); if oe1 = '1' and oe1Prev = '0' then stateMM1 <= Waiting; elsif ce0 = '1' then stateMM1 <= Waiting; end if; when Writing => if we1 = '0' and we1Prev = '1' then memory(addr1) <= data1; stateMM1 <= Waiting; elsif ce0 = '1' then stateMM1 <= Waiting; end if; when others => end case; oe1Prev <= oe1; ce1Prev <= ce1; we1Prev <= we1; end if; end process; -- process(clk) -- variable addr : integer range 0 to 255; -- begin -- if rising_edge(clk) then -- if clk = '1' and clkPrev = '0' then -- addr := conv_integer(address1); -- переменной addr1 присваивается новое значение сразу. Удобно для преобразования типов. -- if (wr1 = '0') then -- memory(addr1) <= data1; -- тут уже новое значение переменной addr1 -- else -- data1 <= memory(addr1); -- end if; -- end if; -- if clk1 = '0' and clk1Prev = '1' then -- data1 <= (others => 'Z'); -- end if; -- -- clk1Prev <= clk1; -- -- if clk0 = '1' and clk0Prev = '0' then -- addr0 := conv_integer(address0); -- переменной addr0 присваивается новое значение сразу. Удобно для преобразования типов. -- if (wr0 = '0') then -- memory(addr0) <= data0; -- тут уже новое значение переменной addr0 -- else -- data0 <= memory(addr0); -- end if; -- end if; -- if clk0 = '0' and clk0Prev = '1' then -- data0 <= (others => 'Z'); -- end if; -- -- clk0Prev <= clk0; -- -- end if; -- end process; end behavorial;