library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity RAM9X8_SerialBusMaster is generic( SB_DATA_LOWER : integer := 0; SB_DATA_UPPER : integer := 1; SB_CMD_LOWER : integer := 2; SB_CMD_UPPER : integer := 3; SB_CONTROL_LOWER : integer := 4; SB_CONTROL_UPPER : 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, Timeout); 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 = SB_DATA_UPPER or addr = SB_DATA_LOWER or addr = SB_CMD_UPPER or addr = SB_CMD_LOWER or addr = SB_CONTROL_UPPER or addr = SB_CONTROL_LOWER) then if (oe = '0' and we = '1') then -- Если сигнал чтения активен, а записи нет case addr is when SB_DATA_UPPER => data <= dataBufOut(15 downto 8); when SB_DATA_LOWER => data <= dataBufOut(7 downto 0); when SB_CMD_UPPER => data <= cmdBuf(15 downto 8); when SB_CMD_LOWER => data <= cmdBuf(7 downto 0); when SB_CONTROL_UPPER => data <= controlBuf(15 downto 8); start <= '0'; when SB_CONTROL_LOWER => data <= controlBuf(7 downto 0); when others => data <= (others => 'Z'); -- Запретить запись на шину end case; elsif (oe = '1' and we = '0') then -- Если сигнал записи активен, а чтения нет case addr is when SB_DATA_UPPER => dataBufIn(15 downto 8) <= data; when SB_DATA_LOWER => dataBufIn(7 downto 0) <= data; when SB_CMD_UPPER => cmdBuf(15 downto 8) <= data; start <= '1'; when SB_CMD_LOWER => cmdBuf(7 downto 0) <= data; 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 halfPeriod : integer range 0 to 255 := 50; variable pause : integer range 0 to 255 := 200; 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'; 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; controlBuf(15 downto 2) <= (others => '0'); controlBuf(1) <= '1'; controlBuf(0) <= '0'; if count < pause then CommunicationState <= Timeout; count := count + 1; else CommunicationState <= TransmitAddress; count:= 0; end if; else if count < pause then count := count + 1; controlBuf(1) <= '1'; else controlBuf(1) <= '0'; end if; end if; when Timeout => if count < pause then count := count + 1; else CommunicationState <= TransmitAddress; count:= 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 < halfPeriod and state = 1 then if count = 0 then if latch = 0 then sbdataout <= direction; else sbdataout <= addressToTransmit(bitCnt); end if; sbclk <= '0'; end if; count := count + 1; elsif count = halfPeriod and state = 1 then latch := 1; count := 0; state := 0; elsif count < halfPeriod and state = 0 then if count = 0 then sbclk <= '1'; end if; count := count + 1; elsif count = halfPeriod 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 < halfPeriod and state = 1 then if count = 0 then sbdataout <= dataToTransmit(bitCnt); sbclk <= '0'; end if; count := count + 1; elsif count = halfPeriod and state = 1 then count := 0; state := 0; elsif count < halfPeriod and state = 0 then if count = 0 then sbclk <= '1'; end if; count := count + 1; elsif count = halfPeriod 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 < halfPeriod and state = 1 then if count = 0 then sbdataout <= CRC(bitCnt); sbclk <= '0'; end if; count := count + 1; elsif count = halfPeriod and state = 1 then count := 0; state := 0; elsif count < halfPeriod and state = 0 then if count = 0 then sbclk <= '1'; end if; count := count + 1; elsif count = halfPeriod and state = 0 then count := 0; state := 1; bitCnt := bitCnt - 1; end if; end if; else count := 0; CommunicationState <= Waiting; controlBuf(15) <= '1'; end if; when TransmitCheck => if count < halfPeriod and state = 1 then if count = 0 then sbclk <= '0'; end if; 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 < halfPeriod and state = 1 then if count = 0 then sbclk <= '0'; end if; count := count + 1; elsif count = halfPeriod and state = 1 then dataFromDevices(bitCnt) <= sbdatain; count := 0; state := 0; elsif count < halfPeriod and state = 0 then if count = 0 then sbclk <= '1'; end if; count := count + 1; elsif count = halfPeriod 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 < halfPeriod and state = 1 then if count = 0 then sbclk <= '0'; end if; count := count + 1; elsif count = halfPeriod 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 < halfPeriod and state = 0 then if count = 0 then sbclk <= '1'; end if; count := count + 1; elsif count = halfPeriod 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; count := 0; CommunicationState <= Waiting; when others => count := 0; 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 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;