2024-03-04 17:16:43 +03:00
|
|
|
|
library ieee;
|
|
|
|
|
use ieee.std_logic_1164.all;
|
|
|
|
|
use ieee.std_logic_unsigned.all;
|
2024-03-04 18:16:35 +03:00
|
|
|
|
|
2024-03-14 11:27:47 +03:00
|
|
|
|
-- Блок памяти (8х32) способен принимать данные с двух устройств одновременно;
|
|
|
|
|
-- Со стороны контроллера - постфикс "0" - данные грузятся в ячейку памяти четырьмя транзакциями, поскольку шина данных здесь всего 8 бит;
|
|
|
|
|
-- Со стороны ПЛИС - постфикс "1" - данные грузятся за одну транзакцию (шина данных 32х разрядная);
|
|
|
|
|
-- Для работы с контроллером дополнительно введены два бита BL для определения с какой частью ячейки памяти работаем;
|
|
|
|
|
-- Когда в комментариях говорю "со стороны ПЛИС" - это значит, что есть IP блок диспетчеризации,
|
|
|
|
|
-- который получает свежайшие данные от остальных IP блоков на ПЛИС, создает приоритетную очередь и грузит эти данные в ячейки памяти;
|
|
|
|
|
|
2024-03-04 17:16:43 +03:00
|
|
|
|
entity RAM is
|
2024-03-14 18:30:15 +03:00
|
|
|
|
generic(
|
|
|
|
|
REG_ADDR_FIRST : integer := 0;
|
|
|
|
|
REG_ADDR_LAST : integer := 16;
|
|
|
|
|
TEST : integer := 5
|
|
|
|
|
);
|
|
|
|
|
|
2024-03-04 17:16:43 +03:00
|
|
|
|
port(
|
|
|
|
|
clk : in std_logic;
|
2024-03-04 18:16:35 +03:00
|
|
|
|
|
2024-03-12 16:30:45 +03:00
|
|
|
|
data0 : inout std_logic_vector(7 downto 0);
|
2024-03-04 18:16:35 +03:00
|
|
|
|
address0 : in std_logic_vector(7 downto 0);
|
2024-03-12 17:54:31 +03:00
|
|
|
|
we0 : in std_logic;
|
|
|
|
|
oe0 : in std_logic;
|
|
|
|
|
ce0 : in std_logic;
|
2024-03-14 11:27:47 +03:00
|
|
|
|
bl0 : in std_logic_vector(1 downto 0);
|
2024-03-04 18:16:35 +03:00
|
|
|
|
|
2024-03-14 11:27:47 +03:00
|
|
|
|
data1 : inout std_logic_vector(31 downto 0);
|
2024-03-04 18:16:35 +03:00
|
|
|
|
address1 : in std_logic_vector(7 downto 0);
|
2024-03-12 17:54:31 +03:00
|
|
|
|
we1 : in std_logic;
|
|
|
|
|
oe1 : in std_logic;
|
|
|
|
|
ce1 : in std_logic
|
2024-03-04 17:16:43 +03:00
|
|
|
|
);
|
|
|
|
|
end entity;
|
|
|
|
|
|
|
|
|
|
architecture behavorial of RAM is
|
|
|
|
|
|
2024-03-14 11:27:47 +03:00
|
|
|
|
type mem is array (255 downto 0) of std_logic_vector(31 downto 0);
|
2024-03-04 17:16:43 +03:00
|
|
|
|
signal memory : mem;
|
|
|
|
|
|
2024-03-12 17:54:31 +03:00
|
|
|
|
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;
|
2024-03-04 17:16:43 +03:00
|
|
|
|
|
2024-03-14 18:30:15 +03:00
|
|
|
|
begin
|
2024-03-04 17:16:43 +03:00
|
|
|
|
|
|
|
|
|
process(clk)
|
2024-03-14 11:27:47 +03:00
|
|
|
|
variable addr0 : integer range 0 to 255 := 0;
|
|
|
|
|
variable part0 : integer range 0 to 3 := 0;
|
|
|
|
|
|
|
|
|
|
variable addr1 : integer range 0 to 255 := 0;
|
2024-03-04 17:16:43 +03:00
|
|
|
|
begin
|
|
|
|
|
if rising_edge(clk) then
|
2024-03-12 17:54:31 +03:00
|
|
|
|
case stateMM0 is
|
|
|
|
|
when Waiting =>
|
|
|
|
|
if ce0 = '0' and ce0Prev = '1' then
|
2024-03-14 11:27:47 +03:00
|
|
|
|
addr0 := conv_integer(address0);
|
|
|
|
|
part0 := conv_integer(bl0);
|
2024-03-12 17:54:31 +03:00
|
|
|
|
if oe0 = '0' then -- этот if можно перенести на следующий такт, чтобы успела установиться ножка output enable
|
|
|
|
|
stateMM0 <= Reading;
|
|
|
|
|
else
|
|
|
|
|
stateMM0 <= Writing;
|
|
|
|
|
end if;
|
|
|
|
|
else
|
|
|
|
|
data0 <= (others => 'Z');
|
|
|
|
|
end if;
|
|
|
|
|
when Reading =>
|
2024-03-14 11:27:47 +03:00
|
|
|
|
data0 <= memory(addr0)(7 + part0*8 downto part0*8);
|
2024-03-12 17:54:31 +03:00
|
|
|
|
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
|
2024-03-14 11:27:47 +03:00
|
|
|
|
memory(addr0)(7 + part0*8 downto part0*8) <= data0;
|
2024-03-12 17:54:31 +03:00
|
|
|
|
stateMM0 <= Waiting;
|
|
|
|
|
elsif ce0 = '1' then
|
|
|
|
|
stateMM0 <= Waiting;
|
|
|
|
|
end if;
|
|
|
|
|
when others =>
|
|
|
|
|
end case;
|
2024-03-14 11:27:47 +03:00
|
|
|
|
|
2024-03-12 17:54:31 +03:00
|
|
|
|
oe0Prev <= oe0;
|
|
|
|
|
ce0Prev <= ce0;
|
|
|
|
|
we0Prev <= we0;
|
2024-03-14 11:27:47 +03:00
|
|
|
|
|
2024-03-12 17:54:31 +03:00
|
|
|
|
case stateMM1 is
|
|
|
|
|
when Waiting =>
|
|
|
|
|
if ce1 = '0' and ce1Prev = '1' then
|
2024-03-14 11:27:47 +03:00
|
|
|
|
addr1 := conv_integer(address1);
|
2024-03-12 17:54:31 +03:00
|
|
|
|
if oe1 = '0' then -- этот if можно перенести на следующий такт, чтобы успела установиться ножка output enable
|
|
|
|
|
stateMM1 <= Reading;
|
|
|
|
|
else
|
|
|
|
|
stateMM1 <= Writing;
|
|
|
|
|
end if;
|
|
|
|
|
else
|
|
|
|
|
data1 <= (others => 'Z');
|
|
|
|
|
end if;
|
|
|
|
|
when Reading =>
|
2024-03-14 11:27:47 +03:00
|
|
|
|
data1 <= memory(addr1);
|
2024-03-12 17:54:31 +03:00
|
|
|
|
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
|
2024-03-14 11:27:47 +03:00
|
|
|
|
memory(addr1) <= data1;
|
2024-03-12 17:54:31 +03:00
|
|
|
|
stateMM1 <= Waiting;
|
|
|
|
|
elsif ce0 = '1' then
|
|
|
|
|
stateMM1 <= Waiting;
|
|
|
|
|
end if;
|
|
|
|
|
when others =>
|
|
|
|
|
end case;
|
2024-03-14 11:27:47 +03:00
|
|
|
|
|
2024-03-12 17:54:31 +03:00
|
|
|
|
oe1Prev <= oe1;
|
|
|
|
|
ce1Prev <= ce1;
|
|
|
|
|
we1Prev <= we1;
|
2024-03-14 18:30:15 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memory(0) <= x"AABBCCDD";
|
|
|
|
|
memory(1) <= x"EEFF0011";
|
|
|
|
|
memory(2) <= x"22334455";
|
|
|
|
|
memory(3) <= x"66778899";
|
|
|
|
|
memory(4) <= x"EEFF0011";
|
|
|
|
|
memory(5) <= x"AAAAAAAA";
|
|
|
|
|
memory(6) <= x"55555555";
|
|
|
|
|
memory(7) <= x"BBBBBBBB";
|
|
|
|
|
memory(8) <= x"66666666";
|
|
|
|
|
memory(9) <= memory(9) + 1;
|
2024-03-04 17:16:43 +03:00
|
|
|
|
end if;
|
|
|
|
|
end process;
|
2024-03-14 11:27:47 +03:00
|
|
|
|
|
2024-03-12 17:54:31 +03:00
|
|
|
|
-- 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;
|
2024-03-04 17:16:43 +03:00
|
|
|
|
|
|
|
|
|
end behavorial;
|