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( REG_ADDR_CMD_LOWER_BYTE : integer := 54; REG_ADDR_CMD_UPPER_BYTE : integer := 55; REG_ADDR_WORD_8_LOWER_BYTE : integer := 56; REG_ADDR_WORD_8_UPPER_BYTE : integer := 57; REG_ADDR_WORD_7_LOWER_BYTE : integer := 58; REG_ADDR_WORD_7_UPPER_BYTE : integer := 59; REG_ADDR_WORD_6_LOWER_BYTE : integer := 60; REG_ADDR_WORD_6_UPPER_BYTE : integer := 61; REG_ADDR_WORD_5_LOWER_BYTE : integer := 62; REG_ADDR_WORD_5_UPPER_BYTE : integer := 63; REG_ADDR_WORD_4_LOWER_BYTE : integer := 64; REG_ADDR_WORD_4_UPPER_BYTE : integer := 65; REG_ADDR_WORD_3_LOWER_BYTE : integer := 66; REG_ADDR_WORD_3_UPPER_BYTE : integer := 67; REG_ADDR_WORD_2_LOWER_BYTE : integer := 68; REG_ADDR_WORD_2_UPPER_BYTE : integer := 69; REG_ADDR_WORD_1_LOWER_BYTE : integer := 70; REG_ADDR_WORD_1_UPPER_BYTE : 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 = REG_ADDR_CMD_UPPER_BYTE or addr = REG_ADDR_CMD_LOWER_BYTE or addr = REG_ADDR_WORD_8_UPPER_BYTE or addr = REG_ADDR_WORD_8_LOWER_BYTE or addr = REG_ADDR_WORD_7_UPPER_BYTE or addr = REG_ADDR_WORD_7_LOWER_BYTE or addr = REG_ADDR_WORD_6_UPPER_BYTE or addr = REG_ADDR_WORD_6_LOWER_BYTE or addr = REG_ADDR_WORD_5_UPPER_BYTE or addr = REG_ADDR_WORD_5_LOWER_BYTE or addr = REG_ADDR_WORD_4_UPPER_BYTE or addr = REG_ADDR_WORD_4_LOWER_BYTE or addr = REG_ADDR_WORD_3_UPPER_BYTE or addr = REG_ADDR_WORD_3_LOWER_BYTE or addr = REG_ADDR_WORD_2_UPPER_BYTE or addr = REG_ADDR_WORD_2_LOWER_BYTE or addr = REG_ADDR_WORD_1_UPPER_BYTE or addr = REG_ADDR_WORD_1_LOWER_BYTE) then if (oe = '0' and we = '1') then -- Если сигнал чтения активен, а записи нет case addr is when REG_ADDR_CMD_UPPER_BYTE => data <= cmdBuf(15 downto 8); when REG_ADDR_CMD_LOWER_BYTE => data <= cmdBuf(7 downto 0); when REG_ADDR_WORD_8_UPPER_BYTE => data <= dataBuf(127 downto 120); when REG_ADDR_WORD_8_LOWER_BYTE => data <= dataBuf(119 downto 112); when REG_ADDR_WORD_7_UPPER_BYTE => data <= dataBuf(111 downto 104); when REG_ADDR_WORD_7_LOWER_BYTE => data <= dataBuf(103 downto 96); when REG_ADDR_WORD_6_UPPER_BYTE => data <= dataBuf(95 downto 88); when REG_ADDR_WORD_6_LOWER_BYTE => data <= dataBuf(87 downto 80); when REG_ADDR_WORD_5_UPPER_BYTE => data <= dataBuf(79 downto 72); when REG_ADDR_WORD_5_LOWER_BYTE => data <= dataBuf(71 downto 64); when REG_ADDR_WORD_4_UPPER_BYTE => data <= dataBuf(63 downto 56); when REG_ADDR_WORD_4_LOWER_BYTE => data <= dataBuf(55 downto 48); when REG_ADDR_WORD_3_UPPER_BYTE => data <= dataBuf(47 downto 40); when REG_ADDR_WORD_3_LOWER_BYTE => data <= dataBuf(39 downto 32); when REG_ADDR_WORD_2_UPPER_BYTE => data <= dataBuf(31 downto 24); when REG_ADDR_WORD_2_LOWER_BYTE => data <= dataBuf(23 downto 16); when REG_ADDR_WORD_1_UPPER_BYTE => data <= dataBuf(15 downto 8); when REG_ADDR_WORD_1_LOWER_BYTE => data <= dataBuf(7 downto 0); when others => data <= (others => 'Z'); -- Запретить запись на шину end case; elsif (oe = '1' and we = '0') then -- Если сигнал записи активен, а чтения нет case addr is when REG_ADDR_CMD_UPPER_BYTE => cmdBuf(15 downto 8) <= data; when REG_ADDR_CMD_LOWER_BYTE => cmdBuf(7 downto 0) <= data; when REG_ADDR_WORD_8_UPPER_BYTE => dataBuf(127 downto 120) <= data; when REG_ADDR_WORD_8_LOWER_BYTE => dataBuf(119 downto 112) <= data; when REG_ADDR_WORD_7_UPPER_BYTE => dataBuf(111 downto 104) <= data; when REG_ADDR_WORD_7_LOWER_BYTE => dataBuf(103 downto 96) <= data; when REG_ADDR_WORD_6_UPPER_BYTE => dataBuf(95 downto 88) <= data; when REG_ADDR_WORD_6_LOWER_BYTE => dataBuf(87 downto 80) <= data; when REG_ADDR_WORD_5_UPPER_BYTE => dataBuf(79 downto 72) <= data; when REG_ADDR_WORD_5_LOWER_BYTE => dataBuf(71 downto 64) <= data; when REG_ADDR_WORD_4_UPPER_BYTE => dataBuf(63 downto 56) <= data; when REG_ADDR_WORD_4_LOWER_BYTE => dataBuf(55 downto 48) <= data; when REG_ADDR_WORD_3_UPPER_BYTE => dataBuf(47 downto 40) <= data; when REG_ADDR_WORD_3_LOWER_BYTE => dataBuf(39 downto 32) <= data; when REG_ADDR_WORD_2_UPPER_BYTE => dataBuf(31 downto 24) <= data; when REG_ADDR_WORD_2_LOWER_BYTE => dataBuf(23 downto 16) <= data; when REG_ADDR_WORD_1_UPPER_BYTE => dataBuf(15 downto 8) <= data; when REG_ADDR_WORD_1_LOWER_BYTE => dataBuf(7 downto 0) <= data; when others => data <= (others => 'Z'); -- Запретить запись на шину end case; if (addr = REG_ADDR_WORD_1_UPPER_BYTE) 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;