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( OB_CMD_LOWER : integer := 54; OB_CMD_UPPER : integer := 55; OB_WORD_8_LOWER : integer := 56; OB_WORD_8_UPPER : integer := 57; OB_WORD_7_LOWER : integer := 58; OB_WORD_7_UPPER : integer := 59; OB_WORD_6_LOWER : integer := 60; OB_WORD_6_UPPER : integer := 61; OB_WORD_5_LOWER : integer := 62; OB_WORD_5_UPPER : integer := 63; OB_WORD_4_LOWER : integer := 64; OB_WORD_4_UPPER : integer := 65; OB_WORD_3_LOWER : integer := 66; OB_WORD_3_UPPER : integer := 67; OB_WORD_2_LOWER : integer := 68; OB_WORD_2_UPPER : integer := 69; OB_WORD_1_LOWER : integer := 70; OB_WORD_1_UPPER : integer := 71; 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 signal dataBuf : std_logic_vector(127 downto 0) := (others => '0'); signal dataToSend : std_logic_vector(127 downto 0) := (others => '0'); signal cmdBuf : std_logic_vector(15 downto 0) := x"0004"; 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); 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 if (oe = '0' and we = '1') then -- Если сигнал чтения активен, а записи нет case addr is when OB_CMD_UPPER => data <= cmdBuf(15 downto 8); when OB_CMD_LOWER => data <= cmdBuf(7 downto 0); when OB_WORD_8_UPPER => data <= dataBuf(127 downto 120); when OB_WORD_8_LOWER => data <= dataBuf(119 downto 112); when OB_WORD_7_UPPER => data <= dataBuf(111 downto 104); when OB_WORD_7_LOWER => data <= dataBuf(103 downto 96); when OB_WORD_6_UPPER => data <= dataBuf(95 downto 88); when OB_WORD_6_LOWER => data <= dataBuf(87 downto 80); when OB_WORD_5_UPPER => data <= dataBuf(79 downto 72); when OB_WORD_5_LOWER => data <= dataBuf(71 downto 64); when OB_WORD_4_UPPER => data <= dataBuf(63 downto 56); when OB_WORD_4_LOWER => data <= dataBuf(55 downto 48); when OB_WORD_3_UPPER => data <= dataBuf(47 downto 40); when OB_WORD_3_LOWER => data <= dataBuf(39 downto 32); when OB_WORD_2_UPPER => data <= dataBuf(31 downto 24); when OB_WORD_2_LOWER => data <= dataBuf(23 downto 16); when OB_WORD_1_UPPER => data <= dataBuf(15 downto 8); when OB_WORD_1_LOWER => data <= dataBuf(7 downto 0); when others => data <= (others => 'Z'); -- Запретить запись на шину end case; elsif (oe = '1' and we = '0') then -- Если сигнал записи активен, а чтения нет case addr is when OB_CMD_UPPER => cmdBuf(15 downto 8) <= data; when OB_CMD_LOWER => cmdBuf(7 downto 0) <= data; when OB_WORD_8_UPPER => dataBuf(127 downto 120) <= data; when OB_WORD_8_LOWER => dataBuf(119 downto 112) <= data; when OB_WORD_7_UPPER => dataBuf(111 downto 104) <= data; when OB_WORD_7_LOWER => dataBuf(103 downto 96) <= data; when OB_WORD_6_UPPER => dataBuf(95 downto 88) <= data; when OB_WORD_6_LOWER => dataBuf(87 downto 80) <= data; when OB_WORD_5_UPPER => dataBuf(79 downto 72) <= data; when OB_WORD_5_LOWER => dataBuf(71 downto 64) <= data; when OB_WORD_4_UPPER => dataBuf(63 downto 56) <= data; when OB_WORD_4_LOWER => dataBuf(55 downto 48) <= data; when OB_WORD_3_UPPER => dataBuf(47 downto 40) <= data; when OB_WORD_3_LOWER => dataBuf(39 downto 32) <= data; when OB_WORD_2_UPPER => dataBuf(31 downto 24) <= data; when OB_WORD_2_LOWER => dataBuf(23 downto 16) <= data; when OB_WORD_1_UPPER => dataBuf(15 downto 8) <= data; when OB_WORD_1_LOWER => dataBuf(7 downto 0) <= data; when others => data <= (others => 'Z'); -- Запретить запись на шину end case; if (addr = OB_WORD_1_UPPER) then 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; 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; 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 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; 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;