vga_controller.vhd 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. -------------------------------------------------------------------------------
  2. --
  3. -- A VGA line-doubler for an Apple ][
  4. --
  5. -- Stephen A. Edwards, sedwards.cs.columbia.edu
  6. --
  7. -- The Apple ][ uses a 14.31818 MHz master clock. It outputs a new
  8. -- horizontal line every 65 * 14 + 2 = 912 14M cycles. The extra two
  9. -- are from the "extended cycle" used to keep the 3.579545 MHz
  10. -- colorburst signal in sync. Of these, 40 * 14 = 560 are active video.
  11. --
  12. -- In graphics mode, the Apple effectively generates 140 four-bit pixels
  13. -- output serially (i.e., with 3.579545 MHz pixel clock). In text mode,
  14. -- it generates 280 one-bit pixels (i.e., with a 7.15909 MHz pixel clock).
  15. --
  16. -- We capture 140 four-bit nibbles for each line and interpret them in
  17. -- one of the two modes. In graphics mode, each is displayed as a
  18. -- single pixel of one of 16 colors. In text mode, each is displayed
  19. -- as two black or white pixels.
  20. --
  21. -- The VGA display is nominally 640 X 480, but we use a 14.31818 MHz
  22. -- dot clock. To stay in sync with the Apple, we generate a new line
  23. -- every 912 / 2 = 456 14M cycles= 31.8 us, a 31.4 kHz horizontal
  24. -- refresh rate. Of these, 280 will be active video.
  25. --
  26. -- One set of suggested VGA timings:
  27. --
  28. -- ______________________ ________
  29. -- ________| VIDEO |________| VIDEO
  30. -- |-C-|----------D-----------|-E-|
  31. -- __ ______________________________ ___________
  32. -- |_| |_|
  33. -- |B|
  34. -- |---------------A----------------|
  35. --
  36. -- A = 31.77 us Scanline time
  37. -- B = 3.77 us Horizontal sync time
  38. -- C = 1.89 us Back porch
  39. -- D = 25.17 us Active video
  40. -- E = 0.94 us Front porch
  41. --
  42. -- We use A = 456 / 14.31818 MHz = 31.84 us
  43. -- B = 54 / 14.31818 MHz = 3.77 us
  44. -- C = 106 / 14.31818 MHz = 7.40 us
  45. -- D = 280 / 14.31818 MHz = 19.56 us
  46. -- E = 16 / 14.31818 MHz = 1.12 us
  47. -------------------------------------------------------------------------------
  48. library ieee;
  49. use ieee.std_logic_1164.all;
  50. use ieee.numeric_std.all;
  51. entity vga_controller is
  52. port (
  53. CLK_14M : in std_logic; -- 14.31818 MHz master clock
  54. nVIDEO : in std_logic;
  55. COLOR_LINE : in std_logic;
  56. CBL : in std_logic;
  57. SRAM_nWE : out std_logic;
  58. SRAM_nOE : out std_logic;
  59. SRAM_nCE : out std_logic;
  60. SRAM_addr : out unsigned(8 downto 0);
  61. SRAM_data : inout unsigned(3 downto 0);
  62. VGA_HS : out std_logic; -- Active low
  63. VGA_VS : out std_logic; -- Active low
  64. VGA_R : out std_logic_vector(1 downto 0);
  65. VGA_G : out std_logic_vector(1 downto 0);
  66. VGA_B : out std_logic_vector(1 downto 0);
  67. MODE : in std_logic
  68. );
  69. end vga_controller;
  70. architecture rtl of vga_controller is
  71. --GE
  72. signal HBL : std_logic := '0';
  73. signal VBL : std_logic := '0';
  74. signal SRAM_rd_data : unsigned(5 downto 0);
  75. signal SRAM_wr_data : unsigned(3 downto 0);
  76. signal SRAM_nWEi : std_logic;
  77. signal SRAM_nOEi : std_logic;
  78. signal SRAM_nCEi : std_logic;
  79. signal RCOL : std_logic_vector(1 downto 0) := "00";
  80. signal GCOL : std_logic_vector(1 downto 0) := "00";
  81. signal BCOL : std_logic_vector(1 downto 0) := "00";
  82. signal R : std_logic_vector(1 downto 0);
  83. signal G : std_logic_vector(1 downto 0);
  84. signal B : std_logic_vector(1 downto 0);
  85. signal PIXPAT : unsigned(3 downto 0);
  86. signal RAMPIXPAT : unsigned(5 downto 0);
  87. signal COLPAT : unsigned(3 downto 0);
  88. signal TEXT : std_logic;
  89. signal ram_write_addr : unsigned(8 downto 0);
  90. signal ram_we : std_logic;
  91. signal ram_read_addr : unsigned(8 downto 0);
  92. signal hcount : unsigned(9 downto 0);
  93. signal hcount2 : unsigned(9 downto 0);
  94. --GE signal vcount : unsigned(5 downto 0);
  95. signal vcount : unsigned(6 downto 0);
  96. signal even_line : std_logic := '0';
  97. signal hactive : std_logic;
  98. constant VGA_SCANLINE : integer := 456; -- Must be 456 (set by the Apple)
  99. constant VGA_HSYNC : integer := 54;
  100. constant VGA_BACK_PORCH : integer := 66;
  101. constant VGA_ACTIVE : integer := 282; -- Must be 280 (set by the Apple)
  102. constant VGA_FRONT_PORCH : integer := 54;
  103. -- VGA_HSYNC + VGA_BACK_PORCH + VGA_ACTIVE + VGA_FRONT_PORCH = VGA_SCANLINE
  104. --GE (org) constant VBL_TO_VSYNC : integer := 33;
  105. --GE constant VBL_TO_VSYNC : integer := 80;
  106. constant VBL_TO_VSYNC : integer := 55;
  107. constant VGA_VSYNC_LINES : integer := 3;
  108. signal VGA_VS_I, VGA_HS_I : std_logic;
  109. signal video_active : std_logic;
  110. signal vbl_delayed : std_logic;
  111. signal color_line_delayed_1, color_line_delayed_2 : std_logic;
  112. --GE 10/02/2009
  113. signal cbl_last : std_logic;
  114. signal cbl_count : unsigned(9 downto 0);
  115. begin
  116. --GE 10/02/2009
  117. blank_sep2 : process(CLK_14M, CBL, cbl_last, cbl_count)
  118. begin
  119. if falling_edge(CLK_14M) then
  120. cbl_count <= cbl_count + 1;
  121. cbl_last <= CBL;
  122. if (cbl_last = '0' and CBL = '1') then
  123. cbl_count <= "1000100101"; -- 549
  124. end if;
  125. if (cbl_count = 911) then
  126. cbl_count <= (others => '0');
  127. VBL <= CBL;
  128. color_line_delayed_2 <= color_line_delayed_1;
  129. color_line_delayed_1 <= COLOR_LINE;
  130. vbl_delayed <= VBL;
  131. if VBL = '1' then
  132. even_line <= '0';
  133. vcount <= vcount + 1;
  134. else
  135. vcount <= (others => '0');
  136. even_line <= not even_line;
  137. end if;
  138. end if;
  139. if (cbl_count >= 549) and (cbl_count <= 899) then
  140. HBL <= '1';
  141. else
  142. HBL <= '0';
  143. end if;
  144. end if;
  145. end process;
  146. hcount <= cbl_count;
  147. hsync_gen : process (CLK_14M)
  148. begin
  149. if falling_edge(CLK_14M) then
  150. if hcount = VGA_ACTIVE + VGA_FRONT_PORCH or
  151. hcount = VGA_SCANLINE + VGA_ACTIVE + VGA_FRONT_PORCH then
  152. VGA_HS_I <= '0';
  153. elsif hcount = VGA_ACTIVE + VGA_FRONT_PORCH + VGA_HSYNC or
  154. hcount = VGA_SCANLINE + VGA_ACTIVE + VGA_FRONT_PORCH + VGA_HSYNC then
  155. VGA_HS_I <= '1';
  156. end if;
  157. if hcount = VGA_SCANLINE - 1 or
  158. hcount = VGA_SCANLINE + VGA_SCANLINE - 1 then
  159. hactive <= '1';
  160. elsif hcount = VGA_ACTIVE or
  161. hcount = VGA_ACTIVE + VGA_SCANLINE then
  162. hactive <= '0';
  163. end if;
  164. end if;
  165. end process hsync_gen;
  166. VGA_HS <= VGA_HS_I;
  167. vsync_gen : process (CLK_14M)
  168. begin
  169. if falling_edge(CLK_14M) then
  170. if vcount = VBL_TO_VSYNC then
  171. VGA_VS_I <= '0';
  172. elsif vcount = VBL_TO_VSYNC + VGA_VSYNC_LINES then
  173. VGA_VS_I <= '1';
  174. end if;
  175. end if;
  176. end process vsync_gen;
  177. VGA_VS <= VGA_VS_I;
  178. -- Shift in the incoming bits to reconstruct four-bit groups
  179. input_shift_register : process (CLK_14M)
  180. begin
  181. if falling_edge(CLK_14M) then
  182. PIXPAT <= PIXPAT(2 downto 0) & nVIDEO;
  183. end if;
  184. end process input_shift_register;
  185. hcount2 <= hcount - VGA_SCANLINE;
  186. ram_read_addr <=
  187. even_line & hcount(8 downto 1) when hcount < VGA_SCANLINE else
  188. even_line & hcount2(8 downto 1);
  189. ram_write_addr <= (not even_line) & hcount(9 downto 2);
  190. ram_we <= '1' when hcount(1 downto 0) = "00" else '0';
  191. video_active <= hactive and not vbl_delayed;
  192. -- RGB values from Linards Ticmanis,
  193. -- http://newsgroups.derkeiler.com/Archive/Comp/comp.sys.apple2/2005-09/msg00534.html
  194. colorgen: process(COLPAT)
  195. begin
  196. case COLPAT is
  197. when "1110" => -- 1 - 0x90 17 40
  198. RCOL <= "10";
  199. GCOL <= "00";
  200. BCOL <= "01";
  201. when "0111" => -- 2 - 0x40 2c a5
  202. RCOL <= "01";
  203. GCOL <= "00";
  204. BCOL <= "10";
  205. when "0110" => -- 3 - 0xd0 43 e5
  206. RCOL <= "11";
  207. GCOL <= "01";
  208. BCOL <= "11";
  209. when "1011" => -- 4 - 0x00 69 40
  210. RCOL <= "00";
  211. GCOL <= "01";
  212. BCOL <= "01";
  213. when "1010" => -- 5 - 0x80 80 80
  214. RCOL <= "10";
  215. GCOL <= "10";
  216. BCOL <= "10";
  217. when "0011" => -- 6 - 0x2f 95 e5
  218. RCOL <= "00";
  219. GCOL <= "10";
  220. BCOL <= "11";
  221. when "0010" => -- 7 - 0xbf ab ff
  222. RCOL <= "11";
  223. GCOL <= "10";
  224. BCOL <= "11";
  225. when "1101" => -- 8 - 0x40 54 00
  226. RCOL <= "01";
  227. GCOL <= "01";
  228. BCOL <= "00";
  229. when "1100" => -- 9 - 0xd0 6a 1a
  230. RCOL <= "11";
  231. GCOL <= "01";
  232. BCOL <= "00";
  233. when "0101" => -- 10 - 0x80 80 80
  234. RCOL <= "01";
  235. GCOL <= "01";
  236. BCOL <= "01";
  237. when "0100" => -- 11 - 0xff 96 bf
  238. RCOL <= "11";
  239. GCOL <= "10";
  240. BCOL <= "11";
  241. when "1001" => -- 12 - 0x2f bc 1a
  242. RCOL <= "00";
  243. GCOL <= "11";
  244. BCOL <= "00";
  245. when "1000" => -- 13 - 0xbf d3 5a
  246. RCOL <= "11";
  247. GCOL <= "11";
  248. BCOL <= "01";
  249. when "0001" => -- 14 - 0x6f e8 bf
  250. RCOL <= "01";
  251. GCOL <= "11";
  252. BCOL <= "11";
  253. when "0000" => -- 15 - 0xff ff ff
  254. RCOL <= "11";
  255. GCOL <= "11";
  256. BCOL <= "11";
  257. when others => -- 0 - 0x00 00 00
  258. RCOL <= "00";
  259. GCOL <= "00";
  260. BCOL <= "00";
  261. end case;
  262. end process;
  263. TEXT <= '1' when hcount(0) = '0' and CLK_14M = '0' and RAMPIXPAT(3) = '0'
  264. else '1' when hcount(0) = '0' and CLK_14M = '1' and RAMPIXPAT(2) = '0'
  265. else '1' when hcount(0) = '1' and CLK_14M = '0' and RAMPIXPAT(1) = '0'
  266. else '1' when hcount(0) = '1' and CLK_14M = '1' and RAMPIXPAT(0) = '0'
  267. else '0';
  268. COLPAT <= RAMPIXPAT(3 downto 0) when hcount(0) = '1'
  269. else RAMPIXPAT(3 downto 2) & RAMPIXPAT(5 downto 4);
  270. --GE
  271. SRAM_addr <= ram_read_addr when hcount(0) = '1' else ram_write_addr;
  272. SRAM_nWEi <= not ram_we;
  273. SRAM_nOEi <= '0' when hcount(0) = '1' else '1';
  274. SRAM_nCEi <= CLK_14M;
  275. process(CLK_14M)
  276. begin
  277. if rising_edge(CLK_14M) and SRAM_nOEi = '0' then
  278. SRAM_rd_data <= SRAM_rd_data(1 downto 0) & SRAM_data;
  279. end if;
  280. end process;
  281. process(CLK_14M)
  282. begin
  283. if falling_edge(CLK_14M) then
  284. RAMPIXPAT <= SRAM_rd_data;
  285. end if;
  286. end process;
  287. SRAM_wr_data <= PIXPAT;
  288. SRAM_data <= SRAM_wr_data when SRAM_nCEi = '0' and SRAM_nWEi = '0' else "ZZZZ";
  289. SRAM_nCE <= SRAM_nCEi;
  290. SRAM_nOE <= SRAM_nOEi;
  291. SRAM_nWE <= SRAM_nWEi;
  292. R <= RCOL when video_active = '1' and color_line_delayed_2 = '1'
  293. else TEXT & TEXT when video_active = '1' and color_line_delayed_2 = '0'
  294. else "00";
  295. G <= GCOL when video_active = '1' and color_line_delayed_2 = '1'
  296. else TEXT & TEXT when video_active = '1' and color_line_delayed_2 = '0'
  297. else "00";
  298. B <= BCOL when video_active = '1' and color_line_delayed_2 = '1'
  299. else TEXT & TEXT when video_active = '1' and color_line_delayed_2 = '0'
  300. else "00";
  301. VGA_R <= R when MODE = '1' else "00";
  302. VGA_G <= G when MODE = '1' else TEXT & TEXT when video_active = '1' else "00";
  303. VGA_B <= B when MODE = '1' else "00";
  304. end rtl;