library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use IEEE.NUMERIC_STD.ALL; entity AVGA is port( AVR_AD: inout std_logic_vector(7 downto 0); AVR_AH: in std_logic_vector(7 downto 0); AVR_AL: out std_logic_vector(7 downto 0); -- gelatchte untere Addressen AVR_ALE: in std_logic; AVR_WR: in std_logic; AVR_RD: in std_logic; AVR_Clock: out std_logic; -- Clock/2 für AVR == 16MHz -- CPLD Clock: in std_logic; -- 32MHz Reset: in std_logic; -- Reset low active -- SRAM, 512Kb 10-15ns SRAM_Addr: out std_logic_vector(18 downto 0); SRAM_Data: inout std_logic_vector(7 downto 0); SRAM_WR: out std_logic; SRAM_OE: out std_logic; SRAM_CS: out std_logic; -- VGA VGA_RGB: out std_logic_vector(5 downto 0); -- 3x2Bit DACs VGA_HSync: out std_logic; VGA_VSync: out std_logic; VGA_CSync: out std_logic; VGA_Trace: out std_logic; -- Retrace Signal -- externe geräte Ext_CS: out std_logic_vector(2 downto 0) -- Chip Selects low active ); end AVGA; -- Addressmap -- 0x0000-0x???? AVR internal -- 0x????-0x7BFF 32Kb Page 0 externer SRAM -- 0x7C00-0x7CFF memory mapped Device 0 -- 0x7D00-0x7DFF memory mapped Device 1 -- 0x7E00-0x7EFF memory mapped Device 2 -- 0x7F00-0x7FFF CPLD Register -- 0x7F00.0 1 Bit VGA Mode -- 0x7F00.1 1 Bit VGA Mode -- 0x7F00.2 1 Bit VGA Enable -- 0x7F01 4 Bit Bank Register -- 0x8000-0xFFFF VGA banked SRAM Pages 0-15 -- VGA Mode 640x480 -- 0 = 64 Colors , 1 Pixel per Byte, 307.200 Bytes, 2 MSB not used -- 1 = 16 Colors , 2 Pixel per Byte, 152.600 Bytes -- 2 = 4 Gray , 4 Pixel per Byte, 76.800 Bytes -- 3 = 2 Monochrome, 8 Pixel per Byte, 38.400 Bytes architecture behavioral of AVGA is signal Flag: std_logic_vector(2 downto 0); signal Bank: std_logic_vector(3 downto 0); signal Latch: std_logic_vector(7 downto 0); signal Data: std_logic_vector(7 downto 0); signal Clock2: std_logic; signal HCounter: std_logic_vector(9 downto 0); signal VCounter: std_logic_vector(6 downto 0); signal Addr: std_logic_vector(18 downto 0); signal HSync: std_logic; signal VSync: std_logic; signal CS_SRAM: std_logic; signal CS_CPLD: std_logic; alias Mode: std_logic_vector(1 downto 0) is Flag(1 downto 0); alias Enable: std_logic is Flag(2); begin process(Clock) begin if Clock'Event and Clock = '1' then Clock2 <= not Clock2; end if; end process; process(Clock2) begin AVR_Clock <= Clock2; end process; process(AVR_ALE) -- address latch A[0..7] begin if AVR_ALE'Event and AVR_ALE = '1' then Latch <= AVR_AD; end if; end process; process(Reset, Latch) begin if Reset = '0' then AVR_AL <= (others => 'Z'); else AVR_AL <= Latch; end if; end process; process(Reset, AVR_AH) -- address decoding begin if Reset = '0' then CS_SRAM <= '1'; CS_CPLD <= '1'; Ext_CS <= (others => '1'); else if AVR_AH(7) = '1' then CS_SRAM <= '0'; CS_CPLD <= '1'; Ext_CS <= (others => '1'); else if AVR_AH(6 downto 2) = "11111" then CS_SRAM <= '1'; case AVR_AH(1 downto 0) is when "00" => Ext_CS <= "110"; when "01" => Ext_CS <= "101"; when "10" => Ext_CS <= "011"; when "11" => CS_CPLD <= '0'; when others => NULL; end case; else CS_SRAM <= '0'; CS_CPLD <= '1'; Ext_CS <= (others => '1'); end if; end if; end if; end process; process(Reset, AVR_WR) -- write access to VGA registers begin if Reset = '0' then Bank <= (others => '0'); Flag <= (others => '0'); else if AVR_WR'Event and AVR_WR = '0' and CS_CPLD = '0' then if Latch(0) = '0' then Bank <= AVR_AD(3 downto 0); else Flag <= AVR_AD(2 downto 0); end if; end if; end if; end process; process(Enable, Clock) -- horizontal sync begin if Enable = '0' then HCounter <= (others => '0'); else if Clock'Event and Clock = '1' then if HCounter < 824 then HCounter <= HCounter + 1; else HCounter <= (others => '0'); end if; end if; end if; end process; process(Enable, Clock) -- generate horizontal sync impulse begin if Enable = '0' then HSync <= '1'; else if Clock'Event and Clock = '1' then if HCounter >= 672 and HCounter < 792 then HSync <= '0'; else HSync <= '1'; end if; end if; end if; end process; process(Enable, HSync) -- vertical sync begin if Enable = '0' then VCounter <= (others => '0'); else if HSync'Event and HSync = '1' then if VCounter < 506 then VCounter <= VCounter + 1; else VCounter <= (others => '0'); end if; end if; end if; end process; process(Enable, HSync) -- generate vertical sync impulse begin if Enable = '0' then VSync <= '1'; else if HSync'Event and HSync = '1' then if VCounter >= 490 and VCounter < 496 then VSync <= '0'; else VSync <= '1'; end if; end if; end if; end process; Data <= SRAM_Data; SRAM_Data <= AVR_AD when Clock = '0' and AVR_WR = '0' and Reset = '1' else (others => 'Z'); SRAM_Addr <= (others => 'Z') when Reset = '0' else Addr when Clock = '1' else "000" & AVR_AH & Latch when AVR_AH(7) = '0' else Bank & AVR_AH(6 downto 0) & Latch; SRAM_CS <= '1' when Reset = '0' else '0' when Clock = '1' else CS_SRAM; SRAM_OE <= '1' when Reset = '0' else '0' when Clock = '1' else AVR_RD; SRAM_WR <= '1' when Reset = '0' else '1' when Clock = '1' else AVR_WR; process(Enable, Clock) -- pixel decoding, retrace signal, pixeladdress variable IsOn: std_logic; variable Val: std_logic_vector(1 downto 0); variable NextAddr: boolean; variable Color: std_logic_vector(5 downto 0); begin if Enable = '0' then VGA_Trace <= '1'; VGA_RGB <= (others => '0'); Addr <= "0001000000000000000"; else if Clock'Event and Clock = '0' then if VCounter < 480 and HCounter < 640 then NextAddr := False; case Mode is when "00" => Color := Data(5 downto 0); NextAddr := True; when "01" => if HCounter(0) = '0' then Color(0) := Data(0); Color(1) := Data(3); Color(2) := Data(1); Color(3) := Data(3); Color(4) := Data(2); Color(5) := Data(3); else Color(0) := Data(4); Color(1) := Data(7); Color(2) := Data(5); Color(3) := Data(7); Color(4) := Data(6); Color(5) := Data(7); NextAddr := True; end if; when "10" => case HCounter(1 downto 0) is when "00" => Val := Data(1 downto 0); when "01" => Val := Data(3 downto 2); when "10" => Val := Data(5 downto 4); when others => Val := Data(7 downto 6); NextAddr := True; end case; case Val is when "00" => Color := "000000"; when "01" => Color := "010101"; when "10" => Color := "101010"; when others => Color := "111111"; end case; when "11" => case HCounter(2 downto 0) is when "000" => IsOn := Data(0); when "001" => IsOn := Data(1); when "010" => IsOn := Data(2); when "011" => IsOn := Data(3); when "100" => IsOn := Data(4); when "101" => IsOn := Data(5); when "110" => IsOn := Data(6); when others => IsOn := Data(7); NextAddr := True; end case; if IsOn = '0' then Color := "000000"; else Color := "111111"; end if; when others => NULL; end case; if NextAddr then Addr <= Addr +1; end if; VGA_Trace <= '0'; VGA_RGB <= Color; else VGA_Trace <= '1'; VGA_RGB <= (others => '0'); Addr <= "0001000000000000000"; end if; end if; end if; end process; VGA_HSync <= '1' when Enable = '0' else HSync; VGA_VSync <= '1' when Enable = '0' else VSync; VGA_CSync <= '0' when Enable = '0' else HSync xor VSync; AVR_AD <= (others => 'Z') when Reset = '0' else Data when Clock = '0' and AVR_RD = '0' and CS_SRAM = '0' else "0000" & Bank when Clock = '0' and AVR_RD = '0' and CS_CPLD = '0' and Latch(0) = '0' else "00000" & Flag when Clock = '0' and AVR_RD = '0' and CS_CPLD = '0' and Latch(0) = '1'; end behavioral;