123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- -------------------------------------------------------------------------------
- --
- -- A VGA line-doubler for an Apple ][
- --
- -- Stephen A. Edwards, sedwards.cs.columbia.edu
- --
- -- The Apple ][ uses a 14.31818 MHz master clock. It outputs a new
- -- horizontal line every 65 * 14 + 2 = 912 14M cycles. The extra two
- -- are from the "extended cycle" used to keep the 3.579545 MHz
- -- colorburst signal in sync. Of these, 40 * 14 = 560 are active video.
- --
- -- In graphics mode, the Apple effectively generates 140 four-bit pixels
- -- output serially (i.e., with 3.579545 MHz pixel clock). In text mode,
- -- it generates 280 one-bit pixels (i.e., with a 7.15909 MHz pixel clock).
- --
- -- We capture 140 four-bit nibbles for each line and interpret them in
- -- one of the two modes. In graphics mode, each is displayed as a
- -- single pixel of one of 16 colors. In text mode, each is displayed
- -- as two black or white pixels.
- --
- -- The VGA display is nominally 640 X 480, but we use a 14.31818 MHz
- -- dot clock. To stay in sync with the Apple, we generate a new line
- -- every 912 / 2 = 456 14M cycles= 31.8 us, a 31.4 kHz horizontal
- -- refresh rate. Of these, 280 will be active video.
- --
- -- One set of suggested VGA timings:
- --
- -- ______________________ ________
- -- ________| VIDEO |________| VIDEO
- -- |-C-|----------D-----------|-E-|
- -- __ ______________________________ ___________
- -- |_| |_|
- -- |B|
- -- |---------------A----------------|
- --
- -- A = 31.77 us Scanline time
- -- B = 3.77 us Horizontal sync time
- -- C = 1.89 us Back porch
- -- D = 25.17 us Active video
- -- E = 0.94 us Front porch
- --
- -- We use A = 456 / 14.31818 MHz = 31.84 us
- -- B = 54 / 14.31818 MHz = 3.77 us
- -- C = 106 / 14.31818 MHz = 7.40 us
- -- D = 280 / 14.31818 MHz = 19.56 us
- -- E = 16 / 14.31818 MHz = 1.12 us
- -------------------------------------------------------------------------------
- library ieee;
- use ieee.std_logic_1164.all;
- use ieee.numeric_std.all;
- entity vga_controller is
-
- port (
- CLK_14M : in std_logic; -- 14.31818 MHz master clock
- nVIDEO : in std_logic;
- COLOR_LINE : in std_logic;
- CBL : in std_logic;
- SRAM_nWE : out std_logic;
- SRAM_nOE : out std_logic;
- SRAM_nCE : out std_logic;
- SRAM_addr : out unsigned(8 downto 0);
- SRAM_data : inout unsigned(3 downto 0);
-
- VGA_HS : out std_logic; -- Active low
- VGA_VS : out std_logic; -- Active low
- VGA_R : out std_logic_vector(1 downto 0);
- VGA_G : out std_logic_vector(1 downto 0);
- VGA_B : out std_logic_vector(1 downto 0);
-
- MODE : in std_logic
- );
-
- end vga_controller;
- architecture rtl of vga_controller is
- --GE
- signal HBL : std_logic := '0';
- signal VBL : std_logic := '0';
- signal SRAM_rd_data : unsigned(5 downto 0);
- signal SRAM_wr_data : unsigned(3 downto 0);
- signal SRAM_nWEi : std_logic;
- signal SRAM_nOEi : std_logic;
- signal SRAM_nCEi : std_logic;
- signal RCOL : std_logic_vector(1 downto 0) := "00";
- signal GCOL : std_logic_vector(1 downto 0) := "00";
- signal BCOL : std_logic_vector(1 downto 0) := "00";
- signal R : std_logic_vector(1 downto 0);
- signal G : std_logic_vector(1 downto 0);
- signal B : std_logic_vector(1 downto 0);
- signal PIXPAT : unsigned(3 downto 0);
- signal RAMPIXPAT : unsigned(5 downto 0);
- signal COLPAT : unsigned(3 downto 0);
- signal TEXT : std_logic;
- signal ram_write_addr : unsigned(8 downto 0);
- signal ram_we : std_logic;
- signal ram_read_addr : unsigned(8 downto 0);
- signal hcount : unsigned(9 downto 0);
- signal hcount2 : unsigned(9 downto 0);
- --GE signal vcount : unsigned(5 downto 0);
- signal vcount : unsigned(6 downto 0);
-
- signal even_line : std_logic := '0';
- signal hactive : std_logic;
- constant VGA_SCANLINE : integer := 456; -- Must be 456 (set by the Apple)
-
- constant VGA_HSYNC : integer := 54;
- constant VGA_BACK_PORCH : integer := 66;
- constant VGA_ACTIVE : integer := 282; -- Must be 280 (set by the Apple)
- constant VGA_FRONT_PORCH : integer := 54;
- -- VGA_HSYNC + VGA_BACK_PORCH + VGA_ACTIVE + VGA_FRONT_PORCH = VGA_SCANLINE
- --GE (org) constant VBL_TO_VSYNC : integer := 33;
- --GE constant VBL_TO_VSYNC : integer := 80;
- constant VBL_TO_VSYNC : integer := 55;
- constant VGA_VSYNC_LINES : integer := 3;
- signal VGA_VS_I, VGA_HS_I : std_logic;
- signal video_active : std_logic;
- signal vbl_delayed : std_logic;
- signal color_line_delayed_1, color_line_delayed_2 : std_logic;
- --GE 10/02/2009
- signal cbl_last : std_logic;
- signal cbl_count : unsigned(9 downto 0);
- begin
- --GE 10/02/2009
- blank_sep2 : process(CLK_14M, CBL, cbl_last, cbl_count)
- begin
- if falling_edge(CLK_14M) then
- cbl_count <= cbl_count + 1;
- cbl_last <= CBL;
- if (cbl_last = '0' and CBL = '1') then
- cbl_count <= "1000100101"; -- 549
- end if;
- if (cbl_count = 911) then
- cbl_count <= (others => '0');
- VBL <= CBL;
- color_line_delayed_2 <= color_line_delayed_1;
- color_line_delayed_1 <= COLOR_LINE;
- vbl_delayed <= VBL;
- if VBL = '1' then
- even_line <= '0';
- vcount <= vcount + 1;
- else
- vcount <= (others => '0');
- even_line <= not even_line;
- end if;
- end if;
- if (cbl_count >= 549) and (cbl_count <= 899) then
- HBL <= '1';
- else
- HBL <= '0';
- end if;
- end if;
- end process;
- hcount <= cbl_count;
- hsync_gen : process (CLK_14M)
- begin
- if falling_edge(CLK_14M) then
- if hcount = VGA_ACTIVE + VGA_FRONT_PORCH or
- hcount = VGA_SCANLINE + VGA_ACTIVE + VGA_FRONT_PORCH then
- VGA_HS_I <= '0';
- elsif hcount = VGA_ACTIVE + VGA_FRONT_PORCH + VGA_HSYNC or
- hcount = VGA_SCANLINE + VGA_ACTIVE + VGA_FRONT_PORCH + VGA_HSYNC then
- VGA_HS_I <= '1';
- end if;
- if hcount = VGA_SCANLINE - 1 or
- hcount = VGA_SCANLINE + VGA_SCANLINE - 1 then
- hactive <= '1';
- elsif hcount = VGA_ACTIVE or
- hcount = VGA_ACTIVE + VGA_SCANLINE then
- hactive <= '0';
- end if;
- end if;
- end process hsync_gen;
- VGA_HS <= VGA_HS_I;
- vsync_gen : process (CLK_14M)
- begin
- if falling_edge(CLK_14M) then
- if vcount = VBL_TO_VSYNC then
- VGA_VS_I <= '0';
- elsif vcount = VBL_TO_VSYNC + VGA_VSYNC_LINES then
- VGA_VS_I <= '1';
- end if;
- end if;
- end process vsync_gen;
- VGA_VS <= VGA_VS_I;
- -- Shift in the incoming bits to reconstruct four-bit groups
- input_shift_register : process (CLK_14M)
- begin
- if falling_edge(CLK_14M) then
- PIXPAT <= PIXPAT(2 downto 0) & nVIDEO;
- end if;
- end process input_shift_register;
- hcount2 <= hcount - VGA_SCANLINE;
- ram_read_addr <=
- even_line & hcount(8 downto 1) when hcount < VGA_SCANLINE else
- even_line & hcount2(8 downto 1);
-
- ram_write_addr <= (not even_line) & hcount(9 downto 2);
- ram_we <= '1' when hcount(1 downto 0) = "00" else '0';
- video_active <= hactive and not vbl_delayed;
- -- RGB values from Linards Ticmanis,
- -- http://newsgroups.derkeiler.com/Archive/Comp/comp.sys.apple2/2005-09/msg00534.html
- colorgen: process(COLPAT)
- begin
- case COLPAT is
- when "1110" => -- 1 - 0x90 17 40
- RCOL <= "10";
- GCOL <= "00";
- BCOL <= "01";
- when "0111" => -- 2 - 0x40 2c a5
- RCOL <= "01";
- GCOL <= "00";
- BCOL <= "10";
- when "0110" => -- 3 - 0xd0 43 e5
- RCOL <= "11";
- GCOL <= "01";
- BCOL <= "11";
- when "1011" => -- 4 - 0x00 69 40
- RCOL <= "00";
- GCOL <= "01";
- BCOL <= "01";
- when "1010" => -- 5 - 0x80 80 80
- RCOL <= "10";
- GCOL <= "10";
- BCOL <= "10";
- when "0011" => -- 6 - 0x2f 95 e5
- RCOL <= "00";
- GCOL <= "10";
- BCOL <= "11";
- when "0010" => -- 7 - 0xbf ab ff
- RCOL <= "11";
- GCOL <= "10";
- BCOL <= "11";
- when "1101" => -- 8 - 0x40 54 00
- RCOL <= "01";
- GCOL <= "01";
- BCOL <= "00";
- when "1100" => -- 9 - 0xd0 6a 1a
- RCOL <= "11";
- GCOL <= "01";
- BCOL <= "00";
- when "0101" => -- 10 - 0x80 80 80
- RCOL <= "01";
- GCOL <= "01";
- BCOL <= "01";
- when "0100" => -- 11 - 0xff 96 bf
- RCOL <= "11";
- GCOL <= "10";
- BCOL <= "11";
- when "1001" => -- 12 - 0x2f bc 1a
- RCOL <= "00";
- GCOL <= "11";
- BCOL <= "00";
- when "1000" => -- 13 - 0xbf d3 5a
- RCOL <= "11";
- GCOL <= "11";
- BCOL <= "01";
- when "0001" => -- 14 - 0x6f e8 bf
- RCOL <= "01";
- GCOL <= "11";
- BCOL <= "11";
- when "0000" => -- 15 - 0xff ff ff
- RCOL <= "11";
- GCOL <= "11";
- BCOL <= "11";
- when others => -- 0 - 0x00 00 00
- RCOL <= "00";
- GCOL <= "00";
- BCOL <= "00";
- end case;
- end process;
- TEXT <= '1' when hcount(0) = '0' and CLK_14M = '0' and RAMPIXPAT(3) = '0'
- else '1' when hcount(0) = '0' and CLK_14M = '1' and RAMPIXPAT(2) = '0'
- else '1' when hcount(0) = '1' and CLK_14M = '0' and RAMPIXPAT(1) = '0'
- else '1' when hcount(0) = '1' and CLK_14M = '1' and RAMPIXPAT(0) = '0'
- else '0';
- COLPAT <= RAMPIXPAT(3 downto 0) when hcount(0) = '1'
- else RAMPIXPAT(3 downto 2) & RAMPIXPAT(5 downto 4);
- --GE
- SRAM_addr <= ram_read_addr when hcount(0) = '1' else ram_write_addr;
- SRAM_nWEi <= not ram_we;
- SRAM_nOEi <= '0' when hcount(0) = '1' else '1';
- SRAM_nCEi <= CLK_14M;
- process(CLK_14M)
- begin
- if rising_edge(CLK_14M) and SRAM_nOEi = '0' then
- SRAM_rd_data <= SRAM_rd_data(1 downto 0) & SRAM_data;
- end if;
- end process;
- process(CLK_14M)
- begin
- if falling_edge(CLK_14M) then
- RAMPIXPAT <= SRAM_rd_data;
- end if;
- end process;
- SRAM_wr_data <= PIXPAT;
- SRAM_data <= SRAM_wr_data when SRAM_nCEi = '0' and SRAM_nWEi = '0' else "ZZZZ";
- SRAM_nCE <= SRAM_nCEi;
- SRAM_nOE <= SRAM_nOEi;
- SRAM_nWE <= SRAM_nWEi;
- R <= RCOL when video_active = '1' and color_line_delayed_2 = '1'
- else TEXT & TEXT when video_active = '1' and color_line_delayed_2 = '0'
- else "00";
- G <= GCOL when video_active = '1' and color_line_delayed_2 = '1'
- else TEXT & TEXT when video_active = '1' and color_line_delayed_2 = '0'
- else "00";
- B <= BCOL when video_active = '1' and color_line_delayed_2 = '1'
- else TEXT & TEXT when video_active = '1' and color_line_delayed_2 = '0'
- else "00";
- VGA_R <= R when MODE = '1' else "00";
- VGA_G <= G when MODE = '1' else TEXT & TEXT when video_active = '1' else "00";
- VGA_B <= B when MODE = '1' else "00";
- end rtl;
|