2024-04-04 14:15:38 +03:00
|
|
|
|
library ieee;
|
|
|
|
|
use ieee.std_logic_1164.all;
|
|
|
|
|
use ieee.std_logic_arith.all;
|
|
|
|
|
use ieee.std_logic_unsigned.all;
|
|
|
|
|
|
|
|
|
|
entity RAM9X8_OpticalBusMaster is
|
|
|
|
|
generic(
|
2024-06-11 16:21:14 +03:00
|
|
|
|
OB_BASE_ADDRESS : integer := 56;
|
2024-04-04 14:15:38 +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;
|
|
|
|
|
|
|
|
|
|
obclk : out std_logic := '1';
|
|
|
|
|
obdata : out std_logic := '1'
|
|
|
|
|
);
|
|
|
|
|
end entity;
|
|
|
|
|
|
|
|
|
|
architecture behavorial of RAM9X8_OpticalBusMaster is
|
|
|
|
|
|
2024-06-11 16:21:14 +03:00
|
|
|
|
signal OB_CMD_LOWER : integer := OB_BASE_ADDRESS;
|
|
|
|
|
signal OB_CMD_UPPER : integer := OB_BASE_ADDRESS + 1;
|
|
|
|
|
signal OB_WORD_8_LOWER : integer := OB_BASE_ADDRESS + 2;
|
|
|
|
|
signal OB_WORD_8_UPPER : integer := OB_BASE_ADDRESS + 3;
|
|
|
|
|
signal OB_WORD_7_LOWER : integer := OB_BASE_ADDRESS + 4;
|
|
|
|
|
signal OB_WORD_7_UPPER : integer := OB_BASE_ADDRESS + 5;
|
|
|
|
|
signal OB_WORD_6_LOWER : integer := OB_BASE_ADDRESS + 6;
|
|
|
|
|
signal OB_WORD_6_UPPER : integer := OB_BASE_ADDRESS + 7;
|
|
|
|
|
signal OB_WORD_5_LOWER : integer := OB_BASE_ADDRESS + 8;
|
|
|
|
|
signal OB_WORD_5_UPPER : integer := OB_BASE_ADDRESS + 9;
|
|
|
|
|
signal OB_WORD_4_LOWER : integer := OB_BASE_ADDRESS + 10;
|
|
|
|
|
signal OB_WORD_4_UPPER : integer := OB_BASE_ADDRESS + 11;
|
|
|
|
|
signal OB_WORD_3_LOWER : integer := OB_BASE_ADDRESS + 12;
|
|
|
|
|
signal OB_WORD_3_UPPER : integer := OB_BASE_ADDRESS + 13;
|
|
|
|
|
signal OB_WORD_2_LOWER : integer := OB_BASE_ADDRESS + 14;
|
|
|
|
|
signal OB_WORD_2_UPPER : integer := OB_BASE_ADDRESS + 15;
|
|
|
|
|
signal OB_WORD_1_LOWER : integer := OB_BASE_ADDRESS + 16;
|
|
|
|
|
signal OB_WORD_1_UPPER : integer := OB_BASE_ADDRESS + 17;
|
|
|
|
|
|
2024-04-04 14:15:38 +03:00
|
|
|
|
signal dataBuf : std_logic_vector(127 downto 0) := (others => '0');
|
|
|
|
|
signal dataToSend : std_logic_vector(127 downto 0) := (others => '0');
|
2024-04-04 16:27:31 +03:00
|
|
|
|
signal cmdBuf : std_logic_vector(15 downto 0) := x"0004";
|
2024-04-04 14:15:38 +03:00
|
|
|
|
|
|
|
|
|
type CommunicationState_start is (Waiting, DataSending, CRCSending);
|
|
|
|
|
signal CommunicationState : CommunicationState_start := Waiting ;
|
|
|
|
|
|
|
|
|
|
signal resetCRC : std_logic := '1';
|
|
|
|
|
signal CRC : std_logic_vector(3 downto 0) := x"0";
|
|
|
|
|
signal bufCRC : std_logic_vector(3 downto 0) := x"0";
|
|
|
|
|
signal dataCRC : std_logic_vector(127 downto 0) := (others => '0'); -- переключает
|
|
|
|
|
signal readyCRC : std_logic := '0'; -- готовность контрольной суммы
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
begin
|
|
|
|
|
if (ce = '0') then -- Если микросхема выбрана
|
|
|
|
|
addr := conv_integer(address);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
if (addr = OB_CMD_UPPER or addr = OB_CMD_LOWER
|
|
|
|
|
or addr = OB_WORD_8_UPPER or addr = OB_WORD_8_LOWER
|
|
|
|
|
or addr = OB_WORD_7_UPPER or addr = OB_WORD_7_LOWER
|
|
|
|
|
or addr = OB_WORD_6_UPPER or addr = OB_WORD_6_LOWER
|
|
|
|
|
or addr = OB_WORD_5_UPPER or addr = OB_WORD_5_LOWER
|
|
|
|
|
or addr = OB_WORD_4_UPPER or addr = OB_WORD_4_LOWER
|
|
|
|
|
or addr = OB_WORD_3_UPPER or addr = OB_WORD_3_LOWER
|
|
|
|
|
or addr = OB_WORD_2_UPPER or addr = OB_WORD_2_LOWER
|
|
|
|
|
or addr = OB_WORD_1_UPPER or addr = OB_WORD_1_LOWER) then
|
2024-04-04 14:15:38 +03:00
|
|
|
|
if (oe = '0' and we = '1') then -- Если сигнал чтения активен, а записи нет
|
|
|
|
|
case addr is
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_CMD_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= cmdBuf(15 downto 8);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_CMD_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= cmdBuf(7 downto 0);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_8_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(127 downto 120);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_8_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(119 downto 112);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_7_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(111 downto 104);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_7_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(103 downto 96);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_6_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(95 downto 88);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_6_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(87 downto 80);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_5_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(79 downto 72);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_5_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(71 downto 64);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_4_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(63 downto 56);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_4_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(55 downto 48);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_3_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(47 downto 40);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_3_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(39 downto 32);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_2_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(31 downto 24);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_2_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(23 downto 16);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_1_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(15 downto 8);
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_1_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
data <= dataBuf(7 downto 0);
|
|
|
|
|
when others =>
|
|
|
|
|
data <= (others => 'Z'); -- Запретить запись на шину
|
|
|
|
|
end case;
|
|
|
|
|
elsif (oe = '1' and we = '0') then -- Если сигнал записи активен, а чтения нет
|
|
|
|
|
case addr is
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_CMD_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
cmdBuf(15 downto 8) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_CMD_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
cmdBuf(7 downto 0) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_8_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(127 downto 120) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_8_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(119 downto 112) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_7_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(111 downto 104) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_7_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(103 downto 96) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_6_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(95 downto 88) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_6_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(87 downto 80) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_5_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(79 downto 72) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_5_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(71 downto 64) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_4_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(63 downto 56) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_4_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(55 downto 48) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_3_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(47 downto 40) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_3_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(39 downto 32) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_2_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(31 downto 24) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_2_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(23 downto 16) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_1_UPPER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(15 downto 8) <= data;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
when OB_WORD_1_LOWER =>
|
2024-04-04 14:15:38 +03:00
|
|
|
|
dataBuf(7 downto 0) <= data;
|
|
|
|
|
when others =>
|
|
|
|
|
data <= (others => 'Z'); -- Запретить запись на шину
|
|
|
|
|
end case;
|
2024-06-07 10:50:55 +03:00
|
|
|
|
if (addr = OB_WORD_1_UPPER) then
|
2024-04-04 14:15:38 +03:00
|
|
|
|
start <= '1';
|
|
|
|
|
else
|
|
|
|
|
start <= '0';
|
|
|
|
|
end if;
|
|
|
|
|
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 31 := 0;
|
|
|
|
|
variable countValue : integer range 0 to 31 := 25;
|
|
|
|
|
variable state : integer range 0 to 1 := 0;
|
|
|
|
|
variable bitCnt : integer range 0 to 127 := 0;
|
|
|
|
|
begin
|
|
|
|
|
if(rising_edge (clk)) then
|
|
|
|
|
case CommunicationState is
|
|
|
|
|
when Waiting =>
|
|
|
|
|
obclk <= '1';
|
|
|
|
|
obdata <= '1';
|
|
|
|
|
resetCRC <= '1';
|
|
|
|
|
count := 0;
|
|
|
|
|
state := 0;
|
|
|
|
|
if start = '1' and startPrev = '0' then
|
|
|
|
|
dataToSend <= dataBuf;
|
|
|
|
|
dataCRC <= dataBuf;
|
2024-04-04 16:27:31 +03:00
|
|
|
|
if conv_integer(cmdBuf(3 downto 0)) < 9 and conv_integer(cmdBuf(3 downto 0)) > 0 then
|
|
|
|
|
bitCnt := (conv_integer(cmdBuf(3 downto 0)) * 16) - 1;
|
|
|
|
|
else
|
|
|
|
|
bitCnt := 63;
|
|
|
|
|
end if;
|
2024-04-04 14:15:38 +03:00
|
|
|
|
CommunicationState <= DataSending;
|
|
|
|
|
resetCRC <= '0';
|
|
|
|
|
end if;
|
|
|
|
|
when DataSending =>
|
|
|
|
|
if count < countValue and state = 0 then
|
|
|
|
|
if count = 0 then
|
|
|
|
|
obdata <= dataToSend(bitCnt);
|
|
|
|
|
end if;
|
|
|
|
|
count := count + 1;
|
|
|
|
|
elsif count = countValue and state = 0 then
|
|
|
|
|
obclk <= '0';
|
|
|
|
|
count := 0;
|
|
|
|
|
state := 1;
|
|
|
|
|
elsif count < countValue and state = 1 then
|
|
|
|
|
count := count + 1;
|
|
|
|
|
elsif count = countValue and state = 1 then
|
|
|
|
|
obclk <= '1';
|
|
|
|
|
count := 0;
|
|
|
|
|
state := 0;
|
|
|
|
|
if bitCnt > 0 then
|
|
|
|
|
bitCnt := bitCnt - 1;
|
|
|
|
|
else
|
|
|
|
|
bitCnt := 3;
|
|
|
|
|
CommunicationState <= CRCSending;
|
|
|
|
|
end if;
|
|
|
|
|
end if;
|
|
|
|
|
when CRCSending =>
|
|
|
|
|
if count < countValue and state = 0 then
|
|
|
|
|
if count = 0 then
|
|
|
|
|
obdata <= CRC(bitCnt);
|
|
|
|
|
end if;
|
|
|
|
|
count := count + 1;
|
|
|
|
|
elsif count = countValue and state = 0 then
|
|
|
|
|
obclk <= '0';
|
|
|
|
|
count := 0;
|
|
|
|
|
state := 1;
|
|
|
|
|
elsif count < countValue and state = 1 then
|
|
|
|
|
count := count + 1;
|
|
|
|
|
elsif count = countValue and state = 1 then
|
|
|
|
|
obclk <= '1';
|
|
|
|
|
count := 0;
|
|
|
|
|
state := 0;
|
|
|
|
|
if bitCnt > 0 then
|
|
|
|
|
bitCnt := bitCnt - 1;
|
|
|
|
|
else
|
|
|
|
|
CommunicationState <= Waiting;
|
|
|
|
|
end if;
|
|
|
|
|
end if;
|
|
|
|
|
when others =>
|
|
|
|
|
CommunicationState <= Waiting;
|
|
|
|
|
end case;
|
|
|
|
|
startPrev <= start;
|
|
|
|
|
end if;
|
|
|
|
|
end process;
|
|
|
|
|
|
|
|
|
|
process(clk)
|
|
|
|
|
variable lacth : integer range 0 to 1 := 0;
|
|
|
|
|
variable bitCnt : integer range -1 to 127 := 0;
|
|
|
|
|
begin
|
|
|
|
|
if rising_edge(clk) then
|
|
|
|
|
if resetCRC = '1' then
|
2024-04-04 16:27:31 +03:00
|
|
|
|
if conv_integer(cmdBuf(3 downto 0)) < 9 and conv_integer(cmdBuf(3 downto 0)) > 0 then
|
|
|
|
|
bitCnt := (conv_integer(cmdBuf(3 downto 0)) * 16) - 1;
|
|
|
|
|
else
|
|
|
|
|
bitCnt := 63;
|
|
|
|
|
end if;
|
2024-04-04 14:15:38 +03:00
|
|
|
|
CRC <= x"0";
|
|
|
|
|
lacth := 0;
|
|
|
|
|
readyCRC <= '0';
|
|
|
|
|
else
|
|
|
|
|
if readyCRC = '0' then
|
|
|
|
|
if lacth = 0 then
|
|
|
|
|
if bitCnt /= -1 then
|
|
|
|
|
CRC(3) <= CRC(2) xor CRC(3);
|
|
|
|
|
CRC(2) <= CRC(1) xor CRC(0);
|
|
|
|
|
CRC(1) <= CRC(0);
|
|
|
|
|
CRC(0) <= dataCRC(bitCnt) xor CRC(1);
|
|
|
|
|
bitCnt := bitCnt - 1;
|
|
|
|
|
else
|
|
|
|
|
bitCnt := 3;
|
|
|
|
|
lacth := 1;
|
|
|
|
|
end if;
|
|
|
|
|
else
|
|
|
|
|
if bitCnt /= -1 then
|
|
|
|
|
CRC(3) <= CRC(2) xor CRC(3);
|
|
|
|
|
CRC(2) <= CRC(1) xor CRC(0);
|
|
|
|
|
CRC(1) <= CRC(0);
|
|
|
|
|
CRC(0) <= '1' xor CRC(1);
|
|
|
|
|
bitCnt := bitCnt - 1;
|
|
|
|
|
else
|
|
|
|
|
readyCRC <= '1';
|
|
|
|
|
end if;
|
|
|
|
|
end if;
|
|
|
|
|
end if;
|
|
|
|
|
end if;
|
|
|
|
|
end if;
|
|
|
|
|
end process;
|
|
|
|
|
|
|
|
|
|
end behavorial;
|