library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity RAM9X8_ParallelBusMaster is generic( PB_BASE_ADDRESS : integer := 6; ARRAY_LENGTH : integer := 256; 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; pbclk : out std_logic := '1'; pbce : out std_logic := '1'; pbdir : out std_logic_vector(1 downto 0) := (others => '1'); pbdata : inout std_logic_vector(15 downto 0) := (others => 'Z'); pback : in std_logic ); end entity; architecture behavorial of RAM9X8_ParallelBusMaster is signal PB_FIRST_FREE_LOWER : integer := PB_BASE_ADDRESS; signal PB_FIRST_FREE_UPPER : integer := PB_BASE_ADDRESS + 1; signal PB_CMD_LOWER : integer := PB_BASE_ADDRESS + 2; signal PB_CMD_UPPER : integer := PB_BASE_ADDRESS + 3; signal PB_FILL_ADDRESS_SPACE_LOWER : integer := PB_BASE_ADDRESS + 4; signal PB_FILL_ADDRESS_SPACE_UPPER : integer := PB_BASE_ADDRESS + 5; signal PB_CONTROL_2_LOWER : integer := PB_BASE_ADDRESS + 6; signal PB_CONTROL_2_UPPER : integer := PB_BASE_ADDRESS + 7; signal PB_CONTROL_1_LOWER : integer := PB_BASE_ADDRESS + 8; signal PB_CONTROL_1_UPPER : integer := PB_BASE_ADDRESS + 9; type mem is array (ARRAY_LENGTH - 1 downto 0) of std_logic_vector(7 downto 0); signal memoryAddress : mem; signal memoryData : mem; signal firstFreeBuf : std_logic_vector(15 downto 0) := (others => '0'); signal cmdBuf : std_logic_vector(15 downto 0) := (others => '0'); signal fasBuf : std_logic_vector(15 downto 0) := (others => '0'); signal controlBuf : std_logic_vector(7 downto 0) := (others => '0'); signal errorBuf : std_logic_vector(7 downto 0) := x"00"; signal addrTemp : std_logic_vector(7 downto 0) := x"00"; signal dataTemp : std_logic_vector(15 downto 0) := x"0000"; signal circleCounterBuf : std_logic_vector(7 downto 0) := x"00"; type CommunicationState_start is (Waiting, TransmiteAddress, TransmiteCheck, PreparingToReceiveData, ReceiveData, ReceiveCheck, Timeout, ReceiveCheckTimeout); signal CommunicationState : CommunicationState_start := Waiting ; 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; variable position : integer range 0 to ARRAY_LENGTH - 1 := 0; begin if (ce = '0') then -- Если микросхема выбрана addr := conv_integer(address); if (addr = PB_FIRST_FREE_UPPER or addr = PB_FIRST_FREE_LOWER or addr = PB_CMD_UPPER or addr = PB_CMD_LOWER or addr = PB_FILL_ADDRESS_SPACE_UPPER or addr = PB_FILL_ADDRESS_SPACE_LOWER or addr = PB_CONTROL_2_UPPER or addr = PB_CONTROL_2_LOWER or addr = PB_CONTROL_1_UPPER or addr = PB_CONTROL_1_LOWER) then if (oe = '0' and we = '1') then -- Если сигнал чтения активен, а записи нет case addr is when PB_FIRST_FREE_UPPER => data <= firstFreeBuf(15 downto 8); when PB_FIRST_FREE_LOWER => data <= firstFreeBuf(7 downto 0); when PB_CMD_UPPER => data <= cmdBuf(15 downto 8); when PB_CMD_LOWER => data <= cmdBuf(7 downto 0); when PB_FILL_ADDRESS_SPACE_UPPER => data <= fasBuf(15 downto 8); when PB_FILL_ADDRESS_SPACE_LOWER => data <= fasBuf(7 downto 0); when PB_CONTROL_2_UPPER => data <= (others => '0'); when PB_CONTROL_2_LOWER => data <= circleCounterBuf; when PB_CONTROL_1_UPPER => data <= errorBuf; when PB_CONTROL_1_LOWER => data <= controlBuf(7 downto 0); when others => data <= (others => 'Z'); -- Запретить запись на шину end case; elsif (oe = '1' and we = '0') then -- Если сигнал записи активен, а чтения нет case addr is when PB_FIRST_FREE_UPPER => firstFreeBuf(15 downto 8) <= data; when PB_FIRST_FREE_LOWER => firstFreeBuf(7 downto 0) <= data; when PB_CMD_UPPER => cmdBuf(15 downto 8) <= data; when PB_CMD_LOWER => cmdBuf(7 downto 0) <= data; when PB_FILL_ADDRESS_SPACE_UPPER => fasBuf(15 downto 8) <= data; when PB_FILL_ADDRESS_SPACE_LOWER => fasBuf(7 downto 0) <= data; position := conv_integer(data); memoryAddress(position) <= fasBuf(15 downto 8); when others => data <= (others => 'Z'); -- Запретить запись на шину end case; else data <= (others => 'Z'); -- Запретить запись на шину end if; elsif (addr >= conv_integer(firstFreeBuf) and addr <= conv_integer(firstFreeBuf) + conv_integer(cmdBuf(7 downto 0))) then if (oe = '0') then -- Если сигнал чтения активен data <= memoryData(addr - conv_integer(firstFreeBuf)); 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 errorCount : integer range 0 to 15 := 0; variable position : integer range 0 to ARRAY_LENGTH - 1 := 0; variable circleCounter : integer range 0 to 255 := 0; begin if(rising_edge (clk)) then if cmdBuf(15) = '1' then case CommunicationState is when Waiting => if errorCount < conv_integer(cmdBuf(11 downto 8)) then addrTemp <= memoryAddress(position); CommunicationState <= TransmiteAddress; else errorBuf(7 downto 4) <= conv_std_logic_vector(errorCount, 4); end if; pbclk <= '1'; pbce <= '1'; pbdata <= (others =>'Z'); pbdir <= b"11"; countValue := 7; count := 0; circleCounterBuf <= conv_std_logic_vector(circleCounter, 8); when TransmiteAddress => if count < countValue then if count = 0 then pbdata(15 downto 8) <= addrTemp; pbdata(7 downto 0) <= not addrTemp; end if; count := count + 1; else pbce <= '0'; CommunicationState <= TransmiteCheck; count := 0; countValue := 15; end if; when TransmiteCheck => if pback = '0' then count := 0; countValue := 1; pbdata <= (others => 'Z'); CommunicationState <= PreparingToReceiveData; else if count < countValue then count := count + 1; else CommunicationState <= Waiting; errorCount := errorCount + 1; errorBuf(0) <= '1'; end if; end if; when PreparingToReceiveData => if count < countValue then count := count + 1; else pbdir <= b"00"; pbclk <= '0'; count := 0; countValue := 15; CommunicationState <= ReceiveData; end if; when ReceiveData => if pback = '1' then pbclk <= '1'; dataTemp <= pbdata; CommunicationState <= ReceiveCheck; count := 0; countValue := 15; else if count < countValue then count := count + 1; else CommunicationState <= Waiting; errorCount := errorCount + 1; errorBuf(1) <= '1'; end if; end if; when ReceiveCheck => if pback = '0' then if pbdata = not dataTemp then memoryData(position) <= dataTemp(15 downto 8); memoryData(position + 1) <= dataTemp(7 downto 0); controlBuf <= memoryAddress(position); CommunicationState <= Timeout; count := 0; pbce <= '1'; countValue := 5; if position + 1 < conv_integer(cmdBuf(7 downto 0)) then position := position + 2; else position := 0; circleCounter := circleCounter + 1; end if; else CommunicationState <= Waiting; errorCount := errorCount + 1; errorBuf(2) <= '1'; end if; else if count < countValue then count := count + 1; else CommunicationState <= Waiting; errorCount := errorCount + 1; errorBuf(3) <= '1'; end if; end if; when Timeout => if count < countValue then count := count + 1; else CommunicationState <= Waiting; end if; when others => CommunicationState <= Waiting; end case; else pbclk <= '1'; pbce <= '1'; pbdata <= (others =>'Z'); pbdir <= b"11"; position := 0; errorCount := 0; errorBuf <= (others => '0'); CommunicationState <= Waiting; end if; end if; end process; end behavorial;