library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity RAM9X8_SerialBusMaster is generic( REG_ADDR_DATA_UPPER_BYTE : integer := 0; REG_ADDR_DATA_LOWER_BYTE : integer := 1; REG_ADDR_CMD_UPPER_BYTE : integer := 2; REG_ADDR_CMD_LOWER_BYTE : integer := 3; REG_ADDR_CONTROL_UPPER_BYTE : integer := 4; REG_ADDR_CONTROL_LOWER_BYTE : integer := 5; 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; sbclk : out std_logic := '0'; sbdataout : out std_logic := '0'; sbdatain : in std_logic ); end entity; architecture behavorial of RAM9X8_SerialBusMaster is signal dataBufIn : std_logic_vector(15 downto 0) := (others => '0'); signal dataBufOut : std_logic_vector(15 downto 0) := (others => '0'); signal cmdBuf : std_logic_vector(15 downto 0) := (others => '0'); signal controlBuf : std_logic_vector(15 downto 0) := (others => '0'); signal direction : std_logic := '0'; signal addressToTransmit : std_logic_vector(7 downto 0) := x"00"; signal dataToTransmit : std_logic_vector(15 downto 0) := x"0000"; signal dataFromDevices : std_logic_vector(15 downto 0) := x"0000"; type CommunicationState_start is (Waiting, TransmitAddress, TransmitData, TransmitCRC, TransmitCheck, ReceiveData, ReceiveCRC, ReceiveCheck); 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(31 downto 0) := x"00000000"; -- переключает 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_DATA_UPPER_BYTE or addr = REG_ADDR_DATA_LOWER_BYTE or addr = REG_ADDR_CMD_UPPER_BYTE or addr = REG_ADDR_CMD_LOWER_BYTE or addr = REG_ADDR_CONTROL_UPPER_BYTE or addr = REG_ADDR_CONTROL_LOWER_BYTE) then if (oe = '0') then -- Если сигнал чтения активен case addr is when REG_ADDR_DATA_UPPER_BYTE => data <= dataBufOut(15 downto 8); when REG_ADDR_DATA_LOWER_BYTE => data <= dataBufOut(7 downto 0); 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_CONTROL_UPPER_BYTE => data <= controlBuf(15 downto 8); when REG_ADDR_CONTROL_UPPER_BYTE => data <= controlBuf(7 downto 0); when others => data <= (others => 'Z'); -- Запретить запись на шину end case; elsif (we = '0') then -- Если сигнал записи активен case addr is when REG_ADDR_DATA_UPPER_BYTE => dataBufIn(15 downto 8) <= data; when REG_ADDR_DATA_LOWER_BYTE => dataBufIn(7 downto 0) <= data; when REG_ADDR_CMD_UPPER_BYTE => cmdBuf(15 downto 8) <= data; when REG_ADDR_CMD_LOWER_BYTE => cmdBuf(7 downto 0) <= data; start <= '1'; when others => data <= (others => 'Z'); -- Запретить запись на шину end case; 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 state : integer range 0 to 1 := 1; variable bitCnt : integer range -1 to 31 := 0; variable latch : integer range 0 to 1 := 0; begin if(rising_edge (clk)) then case CommunicationState is when Waiting => sbclk <= '0'; bitCnt := 8; latch := 0; resetCRC <= '1'; sbdataout <= '0'; lineBusy <= '0'; count := 0; state := 1; if start = '1' and startPrev = '0' then direction <= cmdBuf(15); dataCRC(24) <= cmdBuf(15); addressToTransmit(7 downto 0) <= cmdBuf(7 downto 0); dataCRC(23 downto 16) <= cmdBuf(7 downto 0); dataToTransmit <= dataBufIn; dataCRC(15 downto 0) <= dataBufIn; CommunicationState <= TransmitAddress; lineBusy <= '1'; controlBuf <= (others => '0'); end if; when TransmitAddress => if bitCnt = -1 then if direction = '1' then CommunicationState <= TransmitData; resetCRC <= '0'; else CommunicationState <= ReceiveData; end if; bitCnt := 15; else if count < countValue and state = 1 then if latch = 0 then sbdataout <= direction; else sbdataout <= addressToTransmit(bitCnt); end if; sbclk <= '0'; count := count + 1; elsif count = countValue and state = 1 then latch := 1; count := 0; state := 0; elsif count < countValue and state = 0 then sbclk <= '1'; count := count + 1; elsif count = countValue and state = 0 then count := 0; state := 1; bitCnt := bitCnt - 1; end if; end if; when TransmitData => if bitCnt = -1 then CommunicationState <= TransmitCRC; bitCnt := 3; else if count < countValue and state = 1 then sbdataout <= data(bitCnt); sbclk <= '0'; count := count + 1; elsif count = countValue and state = 1 then count := 0; state := 0; elsif count < countValue and state = 0 then sbclk <= '1'; count := count + 1; elsif count = countValue and state = 0 then count := 0; state := 1; bitCnt := bitCnt - 1; end if; end if; when TransmitCRC => if readyCRC = '1' then if bitCnt = -1 then CommunicationState <= TransmitCheck; else if count < count and state = 1 then sbdataout <= CRC(bitCnt); sbclk <= '0'; count := count + 1; elsif count = countValue and state = 1 then count := 0; state := 0; elsif count < countValue and state = 0 then sbclk <= '1'; count := count + 1; elsif count = countValue and state = 0 then count := 0; state := 1; bitCnt := bitCnt - 1; end if; end if; else CommunicationState <= Waiting; controlBuf(15) <= '1'; end if; when TransmitCheck => if count < countValue and state = 1 then sbclk <= '0'; count := count + 1; else count := 0; state := 0; if sbdatain = '0' then controlBuf(0) <= '1'; else controlBuf(14) <= '1'; end if; CommunicationState <= Waiting; end if; when ReceiveData => if bitCnt = -1 then CommunicationState <= ReceiveCRC; bitCnt := 3; else if count < countValue and state = 1 then sbclk <= '0'; count := count + 1; elsif count = countValue and state = 1 then dataFromDevices(bitCnt) <= sbdatain; count := 0; state := 0; elsif count < countValue and state = 0 then sbclk <= '1'; count := count + 1; elsif count = countValue and state = 0 then count := 0; state := 1; bitCnt := bitCnt - 1; end if; end if; when ReceiveCRC => if bitCnt = -1 then CommunicationState <= ReceiveCheck; else if count < countValue and state = 1 then sbclk <= '0'; count := count + 1; elsif count = countValue and state = 1 then bufCRC(BitCnt) <= sbdatain; count := 0; state := 0; if bitCnt = 0 then dataCRC(24) <= direction; dataCRC(23 downto 16) <= addressToTransmit; dataCRC(15 downto 0) <= dataFromDevices(15 downto 0); resetCRC <= '0'; end if; elsif count < countValue and state = 0 then sbclk <= '1'; count := count + 1; elsif count = countValue and state = 0 then count := 0; state := 1; bitCnt := bitCnt - 1; end if; end if; when ReceiveCheck => if readyCRC = '1' then if bufCRC = CRC then dataBufOut <= dataFromDevices; controlBuf(0) <= '1'; else controlBuf(13) <= '1'; end if; else controlBuf(12) <= '1'; end if; CommunicationState <= Waiting; when others => end case; startPrev <= start; end if; end process; process(clk) variable lacth : integer range 0 to 1 := 0; variable bitCnt : integer range -1 to 24 := 0; begin if rising_edge(clk) then if resetCRC = '1' then bitCnt := 24; 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'; --countreadyCRC <= countreadyCRC + 1; end if; end if; end if; end if; end if; end process; end behavorial;