2024-03-26 18:54:15 +03:00
|
|
|
|
library ieee;
|
|
|
|
|
use ieee.std_logic_1164.all;
|
2024-03-28 13:47:49 +03:00
|
|
|
|
use ieee.std_logic_arith.all;
|
2024-03-26 18:54:15 +03:00
|
|
|
|
use ieee.std_logic_unsigned.all;
|
|
|
|
|
|
|
|
|
|
entity RAM9X8_ParallelBusMaster is
|
|
|
|
|
generic(
|
2024-06-07 10:50:55 +03:00
|
|
|
|
PB_FIRST_FREE_LOWER : integer := 6;
|
|
|
|
|
PB_FIRST_FREE_UPPER : integer := 7;
|
|
|
|
|
PB_CMD_LOWER : integer := 8;
|
|
|
|
|
PB_CMD_UPPER : integer := 9;
|
|
|
|
|
PB_FILL_ADDRESS_SPACE_LOWER : integer := 10;
|
|
|
|
|
PB_FILL_ADDRESS_SPACE_UPPER : integer := 11;
|
|
|
|
|
PB_CONTROL_LOWER : integer := 12;
|
|
|
|
|
PB_CONTROL_UPPER : integer := 13;
|
2024-03-26 18:54:15 +03:00
|
|
|
|
|
2024-04-04 16:27:31 +03:00
|
|
|
|
ARRAY_LENGTH : integer := 256;
|
2024-03-26 18:54:15 +03:00
|
|
|
|
DATA_BUS_WIDTH : integer := 8;
|
|
|
|
|
ADDRESS_BUS_WIDTH : integer := 9
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
port(
|
|
|
|
|
clk : in std_logic;
|
|
|
|
|
|
|
|
|
|
data : inout std_logic_vector(DATA_BUS_WIDTH - 1 downto 0);
|
|
|
|
|
address : in std_logic_vector(ADDRESS_BUS_WIDTH - 1 downto 0);
|
|
|
|
|
we : in std_logic;
|
|
|
|
|
oe : in std_logic;
|
|
|
|
|
ce : in std_logic;
|
|
|
|
|
|
|
|
|
|
pbclk : out std_logic := '1';
|
|
|
|
|
pbce : out std_logic := '1';
|
|
|
|
|
pbdir : out std_logic_vector(1 downto 0) := (others => '1');
|
|
|
|
|
pbdata : inout std_logic_vector(15 downto 0) := (others => 'Z');
|
|
|
|
|
pback : in std_logic
|
|
|
|
|
);
|
|
|
|
|
end entity;
|
|
|
|
|
|
|
|
|
|
architecture behavorial of RAM9X8_ParallelBusMaster is
|
|
|
|
|
|
|
|
|
|
type mem is array (ARRAY_LENGTH - 1 downto 0) of std_logic_vector(7 downto 0);
|
|
|
|
|
signal memoryAddress : mem;
|
|
|
|
|
signal memoryData : mem;
|
|
|
|
|
|
|
|
|
|
signal firstFreeBuf : std_logic_vector(15 downto 0) := (others => '0');
|
|
|
|
|
signal cmdBuf : std_logic_vector(15 downto 0) := (others => '0');
|
|
|
|
|
signal fasBuf : std_logic_vector(15 downto 0) := (others => '0');
|
2024-03-27 16:40:59 +03:00
|
|
|
|
|
2024-03-28 15:54:34 +03:00
|
|
|
|
signal controlBuf : std_logic_vector(7 downto 0) := (others => '0');
|
2024-03-27 16:40:59 +03:00
|
|
|
|
signal errorBuf : std_logic_vector(7 downto 0) := x"00";
|
2024-03-28 15:54:34 +03:00
|
|
|
|
|
2024-03-28 13:47:49 +03:00
|
|
|
|
signal addrTemp : std_logic_vector(7 downto 0) := x"00";
|
2024-03-27 16:40:59 +03:00
|
|
|
|
signal dataTemp : std_logic_vector(15 downto 0) := x"0000";
|
2024-03-26 18:54:15 +03:00
|
|
|
|
|
|
|
|
|
type CommunicationState_start is (Waiting, TransmiteAddress, TransmiteCheck, PreparingToReceiveData, ReceiveData, ReceiveCheck, Timeout, ReceiveCheckTimeout);
|
|
|
|
|
signal CommunicationState : CommunicationState_start := Waiting ;
|
|
|
|
|
|
|
|
|
|
signal lineBusy : std_logic := '1';
|
|
|
|
|
signal start : std_logic := '0';
|
|
|
|
|
signal startPrev : std_logic := '0';
|
|
|
|
|
|
|
|
|
|
begin
|
|
|
|
|
|
|
|
|
|
process (we, oe, ce)
|
|
|
|
|
variable addr : integer range 0 to 2**ADDRESS_BUS_WIDTH - 1 := 0;
|
|
|
|
|
variable position : integer range 0 to ARRAY_LENGTH - 1 := 0;
|
|
|
|
|
begin
|
|
|
|
|
if (ce = '0') then -- Если микросхема выбрана
|
|
|
|
|
addr := conv_integer(address);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
if (addr = PB_FIRST_FREE_UPPER or addr = PB_FIRST_FREE_LOWER or addr = PB_CMD_UPPER or addr = PB_CMD_LOWER
|
|
|
|
|
or addr = PB_FILL_ADDRESS_SPACE_UPPER or addr = PB_FILL_ADDRESS_SPACE_LOWER or addr = PB_CONTROL_UPPER or addr = PB_CONTROL_LOWER) then
|
2024-03-28 13:47:49 +03:00
|
|
|
|
if (oe = '0' and we = '1') then -- Если сигнал чтения активен, а записи нет
|
2024-03-26 18:54:15 +03:00
|
|
|
|
case addr is
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when PB_FIRST_FREE_UPPER =>
|
2024-03-26 18:54:15 +03:00
|
|
|
|
data <= firstFreeBuf(15 downto 8);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when PB_FIRST_FREE_LOWER =>
|
2024-03-26 18:54:15 +03:00
|
|
|
|
data <= firstFreeBuf(7 downto 0);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when PB_CMD_UPPER =>
|
2024-03-26 18:54:15 +03:00
|
|
|
|
data <= cmdBuf(15 downto 8);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when PB_CMD_LOWER =>
|
2024-03-26 18:54:15 +03:00
|
|
|
|
data <= cmdBuf(7 downto 0);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when PB_FILL_ADDRESS_SPACE_UPPER =>
|
2024-03-26 18:54:15 +03:00
|
|
|
|
data <= fasBuf(15 downto 8);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when PB_FILL_ADDRESS_SPACE_LOWER =>
|
2024-03-26 18:54:15 +03:00
|
|
|
|
data <= fasBuf(7 downto 0);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when PB_CONTROL_UPPER =>
|
2024-03-26 18:54:15 +03:00
|
|
|
|
data <= errorBuf;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when PB_CONTROL_LOWER =>
|
2024-03-26 18:54:15 +03:00
|
|
|
|
data <= controlBuf(7 downto 0);
|
|
|
|
|
when others =>
|
|
|
|
|
data <= (others => 'Z'); -- Запретить запись на шину
|
|
|
|
|
end case;
|
2024-03-28 13:47:49 +03:00
|
|
|
|
elsif (oe = '1' and we = '0') then -- Если сигнал записи активен, а чтения нет
|
2024-03-26 18:54:15 +03:00
|
|
|
|
case addr is
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when PB_FIRST_FREE_UPPER =>
|
2024-03-26 18:54:15 +03:00
|
|
|
|
firstFreeBuf(15 downto 8) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when PB_FIRST_FREE_LOWER =>
|
2024-03-26 18:54:15 +03:00
|
|
|
|
firstFreeBuf(7 downto 0) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when PB_CMD_UPPER =>
|
2024-03-26 18:54:15 +03:00
|
|
|
|
cmdBuf(15 downto 8) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when PB_CMD_LOWER =>
|
2024-03-26 18:54:15 +03:00
|
|
|
|
cmdBuf(7 downto 0) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when PB_FILL_ADDRESS_SPACE_UPPER =>
|
2024-03-26 18:54:15 +03:00
|
|
|
|
fasBuf(15 downto 8) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when PB_FILL_ADDRESS_SPACE_LOWER =>
|
2024-03-26 18:54:15 +03:00
|
|
|
|
fasBuf(7 downto 0) <= data;
|
2024-03-27 16:40:59 +03:00
|
|
|
|
position := conv_integer(data);
|
2024-03-26 18:54:15 +03:00
|
|
|
|
memoryAddress(position) <= fasBuf(15 downto 8);
|
|
|
|
|
when others =>
|
|
|
|
|
data <= (others => 'Z'); -- Запретить запись на шину
|
|
|
|
|
end case;
|
|
|
|
|
else
|
|
|
|
|
data <= (others => 'Z'); -- Запретить запись на шину
|
|
|
|
|
end if;
|
2024-03-28 15:54:34 +03:00
|
|
|
|
elsif (addr >= conv_integer(firstFreeBuf) and addr <= conv_integer(firstFreeBuf) + conv_integer(cmdBuf(7 downto 0))) then
|
2024-03-26 18:54:15 +03:00
|
|
|
|
if (oe = '0') then -- Если сигнал чтения активен
|
2024-03-27 16:40:59 +03:00
|
|
|
|
data <= memoryData(addr - conv_integer(firstFreeBuf));
|
2024-03-26 18:54:15 +03:00
|
|
|
|
else
|
|
|
|
|
data <= (others => 'Z'); -- Запретить запись на шину
|
|
|
|
|
end if;
|
|
|
|
|
else
|
|
|
|
|
data <= (others => 'Z'); -- Запретить запись на шину
|
|
|
|
|
end if;
|
|
|
|
|
else
|
|
|
|
|
data <= (others => 'Z'); -- Запретить запись на шину
|
|
|
|
|
end if;
|
|
|
|
|
end process;
|
|
|
|
|
|
|
|
|
|
process(clk) is
|
|
|
|
|
variable count : integer range 0 to 255 := 0;
|
|
|
|
|
variable countValue : integer range 0 to 255 := 63;
|
|
|
|
|
variable errorCount : integer range 0 to 15 := 0;
|
|
|
|
|
variable position : integer range 0 to ARRAY_LENGTH - 1 := 0;
|
|
|
|
|
begin
|
|
|
|
|
if(rising_edge (clk)) then
|
|
|
|
|
if cmdBuf(15) = '1' then
|
|
|
|
|
case CommunicationState is
|
|
|
|
|
when Waiting =>
|
2024-03-28 13:47:49 +03:00
|
|
|
|
if errorCount < conv_integer(cmdBuf(11 downto 8)) then
|
|
|
|
|
addrTemp <= memoryAddress(position);
|
2024-03-26 18:54:15 +03:00
|
|
|
|
CommunicationState <= TransmiteAddress;
|
|
|
|
|
else
|
2024-03-28 13:47:49 +03:00
|
|
|
|
errorBuf(7 downto 4) <= conv_std_logic_vector(errorCount, 4);
|
2024-03-26 18:54:15 +03:00
|
|
|
|
end if;
|
|
|
|
|
pbclk <= '1';
|
|
|
|
|
pbce <= '1';
|
|
|
|
|
pbdata <= (others =>'Z');
|
2024-03-27 16:40:59 +03:00
|
|
|
|
pbdir <= b"11";
|
|
|
|
|
countValue := 7;
|
|
|
|
|
count := 0;
|
2024-03-26 18:54:15 +03:00
|
|
|
|
when TransmiteAddress =>
|
|
|
|
|
if count < countValue then
|
2024-03-27 16:40:59 +03:00
|
|
|
|
if count = 0 then
|
|
|
|
|
pbdata(15 downto 8) <= addrTemp;
|
|
|
|
|
pbdata(7 downto 0) <= not addrTemp;
|
|
|
|
|
end if;
|
|
|
|
|
count := count + 1;
|
2024-03-26 18:54:15 +03:00
|
|
|
|
else
|
|
|
|
|
pbce <= '0';
|
|
|
|
|
CommunicationState <= TransmiteCheck;
|
2024-03-27 16:40:59 +03:00
|
|
|
|
count := 0;
|
|
|
|
|
countValue := 15;
|
2024-03-26 18:54:15 +03:00
|
|
|
|
end if;
|
|
|
|
|
when TransmiteCheck =>
|
2024-03-27 16:40:59 +03:00
|
|
|
|
if pback = '0' then
|
|
|
|
|
count := 0;
|
|
|
|
|
countValue := 1;
|
|
|
|
|
pbdata <= (others => 'Z');
|
|
|
|
|
CommunicationState <= PreparingToReceiveData;
|
|
|
|
|
else
|
|
|
|
|
if count < countValue then
|
|
|
|
|
count := count + 1;
|
|
|
|
|
else
|
|
|
|
|
CommunicationState <= Waiting;
|
|
|
|
|
errorBuf(0) <= '1';
|
2024-03-26 18:54:15 +03:00
|
|
|
|
end if;
|
|
|
|
|
end if;
|
|
|
|
|
when PreparingToReceiveData =>
|
|
|
|
|
if count < countValue then
|
2024-03-27 16:40:59 +03:00
|
|
|
|
count := count + 1;
|
|
|
|
|
else
|
|
|
|
|
pbdir <= b"00";
|
2024-03-26 18:54:15 +03:00
|
|
|
|
pbclk <= '0';
|
2024-03-27 16:40:59 +03:00
|
|
|
|
count := 0;
|
|
|
|
|
countValue := 15;
|
2024-03-26 18:54:15 +03:00
|
|
|
|
CommunicationState <= ReceiveData;
|
2024-03-27 16:40:59 +03:00
|
|
|
|
end if;
|
2024-03-26 18:54:15 +03:00
|
|
|
|
when ReceiveData =>
|
2024-03-27 16:40:59 +03:00
|
|
|
|
if pback = '1' then
|
|
|
|
|
pbclk <= '1';
|
|
|
|
|
dataTemp <= pbdata;
|
|
|
|
|
CommunicationState <= ReceiveCheck;
|
|
|
|
|
count := 0;
|
|
|
|
|
countValue := 15;
|
|
|
|
|
else
|
|
|
|
|
if count < countValue then
|
|
|
|
|
count := count + 1;
|
|
|
|
|
else
|
|
|
|
|
CommunicationState <= Waiting;
|
|
|
|
|
errorBuf(1) <= '1';
|
2024-03-26 18:54:15 +03:00
|
|
|
|
end if;
|
2024-03-27 16:40:59 +03:00
|
|
|
|
end if;
|
2024-03-26 18:54:15 +03:00
|
|
|
|
when ReceiveCheck =>
|
2024-03-27 16:40:59 +03:00
|
|
|
|
if pback = '0' then
|
|
|
|
|
if pbdata = not dataTemp then
|
|
|
|
|
memoryData(position) <= dataTemp(15 downto 8);
|
|
|
|
|
memoryData(position + 1) <= dataTemp(7 downto 0);
|
2024-03-28 15:54:34 +03:00
|
|
|
|
controlBuf <= memoryAddress(position);
|
2024-03-27 16:40:59 +03:00
|
|
|
|
CommunicationState <= Timeout;
|
|
|
|
|
count := 0;
|
|
|
|
|
pbce <= '1';
|
|
|
|
|
countValue := 5;
|
2024-03-28 13:47:49 +03:00
|
|
|
|
if position + 1 < conv_integer(cmdBuf(7 downto 0)) then
|
2024-03-27 16:40:59 +03:00
|
|
|
|
position := position + 2;
|
2024-03-26 18:54:15 +03:00
|
|
|
|
else
|
2024-03-27 16:40:59 +03:00
|
|
|
|
position := 0;
|
2024-03-26 18:54:15 +03:00
|
|
|
|
end if;
|
|
|
|
|
else
|
2024-03-27 16:40:59 +03:00
|
|
|
|
CommunicationState <= Waiting;
|
|
|
|
|
errorBuf(2) <= '1';
|
|
|
|
|
end if;
|
|
|
|
|
else
|
|
|
|
|
if count < countValue then
|
|
|
|
|
count := count + 1;
|
|
|
|
|
else
|
|
|
|
|
CommunicationState <= Waiting;
|
|
|
|
|
errorBuf(3) <= '1';
|
2024-03-26 18:54:15 +03:00
|
|
|
|
end if;
|
|
|
|
|
end if;
|
|
|
|
|
when Timeout =>
|
|
|
|
|
if count < countValue then
|
2024-03-27 16:40:59 +03:00
|
|
|
|
count := count + 1;
|
2024-03-26 18:54:15 +03:00
|
|
|
|
else
|
|
|
|
|
CommunicationState <= Waiting;
|
|
|
|
|
end if;
|
|
|
|
|
when others => CommunicationState <= Waiting;
|
|
|
|
|
end case;
|
|
|
|
|
else
|
|
|
|
|
pbclk <= '1';
|
|
|
|
|
pbce <= '1';
|
|
|
|
|
pbdata <= (others =>'Z');
|
2024-03-27 16:40:59 +03:00
|
|
|
|
pbdir <= b"11";
|
|
|
|
|
position := 0;
|
2024-03-28 13:47:49 +03:00
|
|
|
|
errorCount := 0;
|
2024-03-26 18:54:15 +03:00
|
|
|
|
errorBuf <= (others => '0');
|
|
|
|
|
end if;
|
|
|
|
|
end if;
|
|
|
|
|
end process;
|
|
|
|
|
|
|
|
|
|
end behavorial;
|