library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; -- Блок памяти способен асинхронно принимать данные с двух устройств одновременно 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; data1 : inout std_logic_vector(7 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(7 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 addr : integer range 0 to 255 := 0; begin if rising_edge(clk) then case stateMM0 is when Waiting => if ce0 = '0' and ce0Prev = '1' then addr := conv_integer(address0); if oe0 = '0' then -- этот if можно перенести на следующий такт, чтобы успела установиться ножка output enable stateMM0 <= Reading; else stateMM0 <= Writing; end if; else addr := 0; data0 <= (others => 'Z'); end if; when Reading => data0 <= memory(addr); 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(addr) <= data0; stateMM0 <= Waiting; elsif ce0 = '1' then stateMM0 <= Waiting; end if; when others => end case; oe0Prev <= oe0; ce0Prev <= ce0; we0Prev <= we0; end if; end process; -- автомат для работы с памятью со стороны контроллера process(clk) variable addr : integer range 0 to 255 := 0; begin if rising_edge(clk) then case stateMM1 is when Waiting => if ce1 = '0' and ce1Prev = '1' then addr := conv_integer(address1); if oe1 = '0' then -- этот if можно перенести на следующий такт, чтобы успела установиться ножка output enable stateMM1 <= Reading; else stateMM1 <= Writing; end if; else addr := 0; data1 <= (others => 'Z'); end if; when Reading => data1 <= memory(addr); 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(addr) <= 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;