library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity RAM9X8_HWPBusMaster is generic( REG_ADDR_CMD_2_UPPER_BYTE : integer := 44; REG_ADDR_CMD_2_LOWER_BYTE : integer := 45; REG_ADDR_CMD_1_UPPER_BYTE : integer := 46; REG_ADDR_CMD_1_LOWER_BYTE : integer := 47; REG_ADDR_DATA_2_UPPER_BYTE : integer := 48; REG_ADDR_DATA_2_LOWER_BYTE : integer := 49; REG_ADDR_DATA_1_UPPER_BYTE : integer := 50; REG_ADDR_DATA_1_LOWER_BYTE : integer := 51; 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; hwpdataout : out std_logic; hwpclk : out std_logic; hwpdatain : in std_logic_vector(1 downto 0) ); end entity; architecture behavorial of RAM9X8_HWPBusMaster is signal cmdBuf : std_logic_vector(31 downto 0) := (others => '0'); signal dataBuf : std_logic_vector(31 downto 0) := (others => '0'); signal tempBuf : std_logic_vector(31 downto 0) := (others => '0'); signal dataToSend : std_logic_vector(33 downto 0) := (others => '0'); signal cmdBuf_0_prev : std_logic := '0'; signal done : std_logic := '1'; type HWPSt is (Waiting, SendingData, ReceivingData, Checking); signal HWPState : HWPSt := Waiting; 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_2_UPPER_BYTE or addr = REG_ADDR_CMD_2_LOWER_BYTE or addr = REG_ADDR_CMD_1_UPPER_BYTE or addr = REG_ADDR_CMD_1_LOWER_BYTE or addr = REG_ADDR_DATA_2_UPPER_BYTE or addr = REG_ADDR_DATA_2_LOWER_BYTE or addr = REG_ADDR_DATA_1_UPPER_BYTE or addr = REG_ADDR_DATA_1_LOWER_BYTE) then if (oe = '0' and we = '1') then -- Если сигнал чтения активен, а записи нет case addr is when REG_ADDR_CMD_2_UPPER_BYTE => data <= cmdBuf(31 downto 24); when REG_ADDR_CMD_2_LOWER_BYTE => data <= cmdBuf(23 downto 16); when REG_ADDR_CMD_1_UPPER_BYTE => data <= cmdBuf(15 downto 8); when REG_ADDR_CMD_1_LOWER_BYTE => data(7 downto 1) <= cmdBuf(7 downto 1); data(0) <= done; when REG_ADDR_DATA_2_UPPER_BYTE => data <= tempBuf(29 downto 22); when REG_ADDR_DATA_2_LOWER_BYTE => data <= tempBuf(21 downto 14); when REG_ADDR_DATA_1_UPPER_BYTE => data <= tempBuf(13 downto 6); when REG_ADDR_DATA_1_LOWER_BYTE => data(7 downto 2) <= tempBuf(5 downto 0); data(1 downto 0) <= (others => '0'); when others => data <= (others => 'Z'); -- Запретить запись на шину end case; elsif (oe = '1' and we = '0') then -- Если сигнал записи активен, а чтения нет case addr is when REG_ADDR_CMD_2_UPPER_BYTE => cmdBuf(31 downto 24) <= data; when REG_ADDR_CMD_2_LOWER_BYTE => cmdBuf(23 downto 16) <= data; when REG_ADDR_CMD_1_UPPER_BYTE => cmdBuf(15 downto 8) <= data; when REG_ADDR_CMD_1_LOWER_BYTE => cmdBuf(7 downto 0) <= data; when REG_ADDR_DATA_2_UPPER_BYTE => dataBuf(31 downto 24) <= data; when REG_ADDR_DATA_2_LOWER_BYTE => dataBuf(23 downto 16) <= data; when REG_ADDR_DATA_1_UPPER_BYTE => dataBuf(15 downto 8) <= data; when REG_ADDR_DATA_1_LOWER_BYTE => dataBuf(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 511 := 0; variable state : integer range 0 to 1 := 0; variable countBit : integer range 0 to 32 := 0; begin if rising_edge(clk) then case HWPState is when Waiting => if cmdBuf(0) = '1' and cmdBuf_0_prev = '0' then done <= '1'; if cmdBuf(14) = '0' then if cmdBuf(13) = '0' then dataToSend(33 downto 22) <= (others => '0'); dataToSend(21 downto 16) <= cmdBuf(15 downto 10); dataToSend(15 downto 0) <= cmdBuf(31 downto 16); countBit := 21; else dataToSend(33) <= '0'; dataToSend(32 downto 30) <= cmdBuf(15 downto 13); dataToSend(29 downto 0) <= dataBuf(31 downto 2); countBit := 32; end if; else dataToSend(33) <= '1'; dataToSend(32 downto 2) <= (others => '0'); dataToSend(1 downto 0) <= cmdBuf(15 downto 14); countBit := 1; end if; HWPState <= SendingData; count := 0; state := 0; end if; when SendingData => if count < 511 and state = 0 then if count = 0 then hwpdataout <= dataToSend(countBit); end if; count := count + 1; elsif count = 511 and state = 0 then hwpclk <= '0'; count := 0; state := 1; elsif count < 511 and state = 1 then count := count + 1; elsif count = 511 and state = 1 then hwpclk <= '1'; count := 0; state := 0; if countBit > 0 then countBit := countBit - 1; else if dataToSend(33) = '1' then HWPState <= ReceivingData; countBit := 29; else HWPState <= Checking; end if; end if; end if; when ReceivingData => if count < 511 and state = 0 then count := count + 1; elsif count = 511 and state = 0 then hwpclk <= '0'; count := 0; state := 1; if dataToSend(1) = '0' then tempBuf(countBit) <= hwpdatain(0); hwpdataout <= hwpdatain(0); else tempBuf(countBit) <= hwpdatain(1); hwpdataout <= hwpdatain(1); end if; elsif count < 511 and state = 1 then count := count + 1; elsif count = 511 and state = 1 then hwpclk <= '1'; count := 0; state := 0; if countBit > 0 then countBit := countBit - 1; else HWPState <= Checking; end if; end if; when Checking => done <= '0'; HWPState <= Waiting; when others => HWPState <= Waiting; end case; cmdBuf_0_prev <= cmdBuf(0); end if; end process; end behavorial;