library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity RAM9X8_LedController is generic( REG_ADDR_ACTIVE_DEVICE_LOWER_BYTE : integer := 38; REG_ADDR_ACTIVE_DEVICE_UPPER_BYTE : integer := 39; REG_ADDR_TEST_LOWER_BYTE : integer := 40; REG_ADDR_TEST_UPPER_BYTE : integer := 41; REG_ADDR_VERSION_LOWER_BYTE : integer := 42; REG_ADDR_VERSION_UPPER_BYTE : integer := 43; 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; asyncline : out std_logic := '1'; divclk : out std_logic := '1'; error : in std_logic; init : out std_logic := '0' ); end entity; architecture behavorial of RAM9X8_LedController is signal activeDeviceBuf : std_logic_vector(15 downto 0) := (others => '0'); signal testBuf : std_logic_vector(15 downto 0) := (others => '0'); signal versionBuf : std_logic_vector(15 downto 0) := x"0004"; signal initBuf : std_logic := '0'; signal divClkBuf : std_logic := '0'; signal divClkBufPWM : std_logic := '0'; signal addrBuf : std_logic_vector(3 downto 0) := (others => '0'); signal ledBuf : std_logic := '0'; signal LedState : std_logic_vector(1 downto 0) := (others => '0'); type BusSt is (Waiting, A3, A2, A1, A0, Dt, Finish); signal BusState : BusSt := Waiting; signal countBuf : std_logic_vector(3 downto 0) := (others => '0'); signal countBufPWM : std_logic_vector(3 downto 0) := (others => '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_ACTIVE_DEVICE_UPPER_BYTE or addr = REG_ADDR_ACTIVE_DEVICE_LOWER_BYTE or addr = REG_ADDR_TEST_UPPER_BYTE or addr = REG_ADDR_TEST_LOWER_BYTE or addr = REG_ADDR_VERSION_UPPER_BYTE or addr = REG_ADDR_VERSION_LOWER_BYTE) then if (oe = '0' and we = '1') then -- Если сигнал чтения активен, а записи нет case addr is when REG_ADDR_ACTIVE_DEVICE_UPPER_BYTE => data <= activeDeviceBuf(15 downto 8); when REG_ADDR_ACTIVE_DEVICE_LOWER_BYTE => data <= activeDeviceBuf(7 downto 0); when REG_ADDR_TEST_UPPER_BYTE => data <= not testBuf(15 downto 8); when REG_ADDR_TEST_LOWER_BYTE => data <= not testBuf(7 downto 0); when REG_ADDR_VERSION_UPPER_BYTE => data <= versionBuf(15 downto 8); when REG_ADDR_VERSION_LOWER_BYTE => data <= versionBuf(7 downto 0); when others => data <= (others => 'Z'); -- Запретить запись на шину end case; elsif (oe = '1' and we = '0') then -- Если сигнал записи активен, а чтения нет case addr is when REG_ADDR_ACTIVE_DEVICE_UPPER_BYTE => activeDeviceBuf(15 downto 8) <= data; when REG_ADDR_ACTIVE_DEVICE_LOWER_BYTE => activeDeviceBuf(7 downto 0) <= data; when REG_ADDR_TEST_UPPER_BYTE => testBuf(15 downto 8) <= data; when REG_ADDR_TEST_LOWER_BYTE => testBuf(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 begin if rising_edge(clk) then if testBuf = x"5AA5" then initBuf <= '1'; end if; end if; end process; init <= initBuf; process(clk) is variable count50000 : integer range 0 to 50000 := 0; variable count50 : integer range 0 to 50 := 0; begin if rising_edge(clk) then if count50000 < 50000 then count50000 := count50000 + 1; else divClkBufPWM <= not divClkBufPWM; count50000 := 0; if count50 < 50 then count50 := count50 + 1; else count50 := 0; divClkBuf <= not divClkBuf; end if; end if; end if; end process; process(divClkBufPWM) is begin if conv_integer(countBufPWM) < 15 then countBufPWM <= conv_std_logic_vector(conv_integer(countBufPWM) + 1, 4); else countBufPWM <= (others => '0'); end if; end process; process(divClkBuf) is variable direction : integer range 0 to 1 := 0; begin if direction = 0 then if conv_integer(countBuf) < 15 then countBuf <= conv_std_logic_vector(conv_integer(countBuf) + 1, 4); else direction := 1; end if; else if conv_integer(countBuf) > 0 then countBuf <= conv_std_logic_vector(conv_integer(countBuf) - 1, 4); else direction := 0; end if; end if; end process; process(divClkBuf) is variable count15 : integer range 0 to 15 := 0; begin case LedState is when b"00" => if count15 < 15 then count15 := count15 + 1; else count15 := 0; LedState <= b"01"; end if; divclk <= '0'; when b"01" => if count15 < 7 then count15 := count15 + 1; else count15 := 0; LedState <= b"10"; end if; divclk <= '1'; when b"10" => if count15 < 15 then count15 := count15 + 1; else count15 := 0; LedState <= b"11"; end if; divclk <= '0'; when b"11" => if count15 < 4 then count15 := count15 + 1; else count15 := 0; LedState <= b"00"; end if; divclk <= '1'; when others => LedState <= b"00"; end case; end process; process(clk) is variable count50 : integer range 0 to 50 := 0; variable count15 : integer range 0 to 15 := 15; begin if rising_edge(clk) then if initBuf = '0' then case BusState is when Waiting => if count50 < 38 then count50 := count50 + 1; else if count15 < 15 then count15 := count15 + 1; else count15 := 0; end if; if activeDeviceBuf(count15) = '1' then addrBuf <= conv_std_logic_vector(count15, 4); asyncline <= '0'; count50 := 0; BusState <= A3; end if; end if; when A3 => if count50 < 18 then count50 := count50 + 1; else count50 := 0; asyncline <= addrBuf(3); BusState <= A2; end if; when A2 => if count50 < 38 then count50 := count50 + 1; else count50 := 0; asyncline <= addrBuf(2); BusState <= A1; end if; when A1 => if count50 < 38 then count50 := count50 + 1; else count50 := 0; asyncline <= addrBuf(1); BusState <= A0; end if; when A0 => if count50 < 38 then count50 := count50 + 1; else count50 := 0; asyncline <= addrBuf(0); BusState <= Dt; end if; when Dt => if count50 < 38 then count50 := count50 + 1; else count50 := 0; asyncline <= divClkBuf; BusState <= Finish; end if; when Finish => if count50 < 38 then count50 := count50 + 1; else count50 := 0; asyncline <= '1'; BusState <= Finish; end if; when others => BusState <= Waiting; count50 := 0; count15 :=15; end case; else BusState <= Waiting; count50 := 0; count15 := 15; if error = '0' then if countBuf < countBufPWM then asyncline <= '1'; else asyncline <= '0'; end if; else asyncline <= '1'; end if; end if; end if; end process; end behavorial;