forth-cpu
/
vga.vhd
1464 строки · 46.1 Кб
1-------------------------------------------------------------------------------
2--| @file vga.vhd
3--| @brief Text Mode Video Controller VHDL Module and VT100
4--| Terminal Emulator
5--| @author Javier Valcarce García
6--| @author Richard James Howe (vt100, vt100_tb, atoi, color attributes)
7--| @copyright Copyright 2007 Javier Valcarce García, 2017, 2019 Richard James Howe
8--| @license LGPL version 3
9--| @email javier.valcarce@gmail.com
10--| @note (Modifications and repackaging by Richard James Howe)
11--|
12--| This is a modified version of the text terminal available at
13--| <https://opencores.org/project,interface_vga80x40>. Additions include per
14--| character attribute information (color, bold, reverse video, blink text)
15--| and a VT100 terminal interface.
16--|
17--| See also <http://www.javiervalcarce.eu/html/vhdl-vga80x40-en.html>.
18--|
19-------------------------------------------------------------------------------
20
21----- VGA Package -------------------------------------------------------------
22library ieee, work;
23use ieee.std_logic_1164.all;
24use ieee.numeric_std.all;
25use work.util.common_generics;
26
27package vga_pkg is
28type vga_physical_interface is record
29red: std_ulogic_vector(2 downto 0);
30green: std_ulogic_vector(2 downto 0);
31blue: std_ulogic_vector(1 downto 0);
32hsync: std_ulogic;
33vsync: std_ulogic;
34end record;
35
36type vga_control_registers_we_interface is record
37crx: std_ulogic; -- Write enable for cursor X position register
38cry: std_ulogic; -- Write enable for VGA control register
39ctl: std_ulogic; -- Write enable for cursor Y position register
40end record;
41
42type vga_control_registers_interface is record
43crx: std_ulogic_vector(6 downto 0); -- Cursor position X
44cry: std_ulogic_vector(5 downto 0); -- Cursor position Y
45ctl: std_ulogic_vector(4 downto 0); -- Control register
46end record;
47
48constant vga_control_registers_initialize: vga_control_registers_interface := (
49cry => (others => '0'),
50crx => (others => '0'),
51ctl => (others => '0'));
52
53constant vga_control_registers_we_initialize: vga_control_registers_we_interface := (
54cry => '0',
55crx => '0',
56ctl => '0');
57
58component vga_top is
59generic(g: common_generics);
60port(
61clk: in std_ulogic;
62clk25MHz: in std_ulogic;
63rst: in std_ulogic;
64
65-- VGA Text buffer interface
66vga_we_ram: in std_ulogic; -- Write enable RAM
67vga_din: in std_ulogic_vector(15 downto 0);
68vga_addr: in std_ulogic_vector(12 downto 0);
69base: in std_ulogic_vector(12 downto 0);
70
71-- VGA control registers
72i_font_sel: in std_ulogic_vector(0 downto 0);
73i_vga_control_we: in vga_control_registers_we_interface;
74i_vga_control: in vga_control_registers_interface;
75
76o_vga: out vga_physical_interface);
77end component;
78
79component vga_core is
80generic(g: common_generics);
81port (
82rst: in std_ulogic;
83clk25MHz: in std_ulogic;
84text_a: out std_ulogic_vector(11 downto 0); -- text buffer
85text_d: in std_ulogic_vector(15 downto 0);
86font_a: out std_ulogic_vector(12 downto 0); -- font buffer
87font_d: in std_ulogic_vector( 7 downto 0);
88font_sel: in std_ulogic_vector(0 downto 0);
89--
90ocrx: in std_ulogic_vector(6 downto 0);
91ocry: in std_ulogic_vector(5 downto 0);
92octl: in std_ulogic_vector(4 downto 0);
93--
94o_vga: out vga_physical_interface);
95end component;
96
97component losr is
98generic (g: common_generics; N: positive := 4);
99port
100(
101rst: in std_ulogic;
102clk: in std_ulogic;
103load: in std_ulogic;
104ce: in std_ulogic;
105do: out std_ulogic := '0';
106di: in std_ulogic_vector(N - 1 downto 0));
107end component;
108
109component ctrm is
110generic (g: common_generics; M: positive := 8);
111port (
112rst: in std_ulogic; -- asynchronous rst
113clk: in std_ulogic;
114ce: in std_ulogic; -- enable counting
115rs: in std_ulogic; -- synchronous rst
116do: out integer range (M-1) downto 0 := 0);
117end component;
118
119component vt100 is
120generic (g: common_generics);
121port(
122clk: in std_ulogic;
123clk25MHz: in std_ulogic;
124rst: in std_ulogic;
125we: in std_ulogic;
126char: in std_ulogic_vector(7 downto 0);
127
128busy: out std_ulogic;
129o_vga: out vga_physical_interface);
130end component;
131
132-- VGA test bench, not-synthesizeable
133component vt100_tb is
134generic(g: common_generics);
135end component;
136
137component atoi is
138generic(g: common_generics; N: positive := 16);
139port(
140clk: in std_ulogic;
141rst: in std_ulogic;
142we: in std_ulogic;
143init: in std_ulogic;
144char: in std_ulogic_vector(7 downto 0);
145char_o: out std_ulogic_vector(7 downto 0);
146done_o: out std_ulogic;
147-- ready: out std_ulogic;
148n_o: out unsigned(N - 1 downto 0));
149end component;
150end package;
151
152----- VGA Package -------------------------------------------------------------
153
154----- VGA Test Bench ----------------------------------------------------------
155
156library ieee, work;
157use ieee.std_logic_1164.all;
158use ieee.numeric_std.all;
159use ieee.math_real.all;
160use work.vga_pkg.all;
161use work.util.all;
162
163entity vt100_tb is
164generic(g: common_generics);
165end entity;
166
167architecture behav of vt100_tb is
168constant clock_period: time := 1000 ms / g.clock_frequency;
169signal clk, rst: std_ulogic := '0';
170signal stop: std_ulogic := '0';
171signal clk25MHz, rst25MHz: std_ulogic := '0';
172
173signal char: std_ulogic_vector(7 downto 0);
174signal we: std_ulogic := '0';
175signal busy: std_ulogic := '0';
176signal physical: vga_physical_interface;
177
178-- NB. 'string' range is (1 to X), not (X-1 downto 0)
179-- HT = Horizontal Tab
180-- LF = Line Feed
181-- CR = Carriage Return
182-- ESC = Escape
183constant CSI: string := ESC & "[";
184constant RESET: string := CSI & "0m";
185constant RED: string := CSI & "31m";
186constant GREEN: string := CSI & "32m";
187constant NL: string := CR & LF;
188constant test_string: string := "Hello!" & HT & "World!" & RED & NL & "How are you?" & RESET & NL ;
189shared variable test_vector: ulogic_string(test_string'range) := to_std_ulogic_vector(test_string);
190shared variable index: integer := 1; -- starts at '1' due to string range
191
192constant g_cs25MHz: common_generics := (clock_frequency => 25_000_000, asynchronous_reset => g.asynchronous_reset, delay => g.delay);
193begin
194cs: entity work.clock_source_tb
195generic map(g => g, hold_rst => 2)
196port map(stop => stop, clk => clk, rst => rst);
197
198cs25MHz: entity work.clock_source_tb
199generic map(g => g_cs25MHz, hold_rst => 2)
200port map(stop => stop, clk => clk25MHz, rst => rst25MHz);
201
202
203uut: work.vga_pkg.vt100
204generic map(g => g)
205port map(
206clk => clk,
207clk25MHz => clk25MHz,
208rst => rst,
209we => we,
210char => char,
211busy => busy,
212o_vga => physical);
213
214stimulus_process: process
215begin
216char <= test_vector(index);
217we <= '0';
218wait for clock_period * 20;
219
220for i in test_vector'range loop
221we <= '1';
222char <= test_vector(index);
223wait for clock_period;
224we <= '0';
225wait for clock_period;
226
227while busy = '1' loop
228wait until busy = '0';
229wait for clock_period;
230end loop;
231
232-- wait for clock_period * 20;
233-- wait until busy = '0';
234-- report integer'image(index);
235if index < (test_vector'high - 1) then
236index := index + 1;
237else
238index := 1;
239end if;
240end loop;
241
242stop <= '1';
243wait;
244end process;
245end architecture;
246
247----- VGA Test Bench ----------------------------------------------------------
248
249----- ATOI --------------------------------------------------------------------
250-- The purpose of this module is to read in numeric characters ('0' through
251-- '9') and convert the string into a binary number ('n_o'). On the first non-
252-- numeric character the module stops and outputs that non-numeric character
253-- as well as the converted number string. The module waits in the FINISHED
254-- state until the module is reset by an external signal ('init').
255--
256-- The module is named after the C function, 'atoi', for converting a string
257-- into an integer.
258--
259
260library ieee,work;
261use ieee.std_logic_1164.all;
262use ieee.numeric_std.all;
263use work.vga_pkg.all;
264use work.util.common_generics;
265
266entity atoi is
267generic(g: common_generics; N: positive := 16);
268port(
269clk: in std_ulogic;
270rst: in std_ulogic;
271we: in std_ulogic;
272init: in std_ulogic;
273char: in std_ulogic_vector(7 downto 0);
274char_o: out std_ulogic_vector(7 downto 0);
275done_o: out std_ulogic;
276-- ready: out std_ulogic;
277n_o: out unsigned(N - 1 downto 0));
278end entity;
279
280architecture rlt of atoi is
281type state_type is (RESET, WAITING, COMMAND, ACCUMULATE, WRITE, FINISHED);
282signal state_c, state_n: state_type := RESET;
283signal c_c, c_n: unsigned(char'range) := (others => '0');
284signal n_c, n_n: unsigned(n_o'range) := (others => '0');
285signal f_c, f_n: boolean := true;
286begin
287char_o <= std_ulogic_vector(c_c);
288n_o <= n_c;
289-- ready <= '1' when state_c = WAITING else '0';
290
291process(clk, rst)
292variable akk: unsigned((2 * N) - 1 downto 0) := (others => '0');
293begin
294if rst = '1' and g.asynchronous_reset then
295state_n <= RESET;
296elsif rising_edge(clk) then
297if rst = '1' and not g.asynchronous_reset then
298state_n <= RESET;
299else
300state_c <= state_n;
301c_c <= c_n;
302n_c <= n_n;
303f_c <= f_n;
304done_o <= '0';
305
306if state_c = RESET then
307c_n <= (others => '0');
308n_n <= (others => '0');
309f_n <= true;
310state_n <= WAITING;
311elsif state_c = WAITING then
312if we = '1' then
313c_n <= unsigned(char);
314state_n <= COMMAND;
315end if;
316elsif state_c = COMMAND then
317state_n <= ACCUMULATE;
318case c_c is
319when x"30" =>
320when x"31" =>
321when x"32" =>
322when x"33" =>
323when x"34" =>
324when x"35" =>
325when x"36" =>
326when x"37" =>
327when x"38" =>
328when x"39" =>
329when others =>
330state_n <= WRITE;
331end case;
332elsif state_c = ACCUMULATE then
333if f_c then
334f_n <= false;
335n_n <= n_c + (c_c - x"30");
336else
337akk := n_c * to_unsigned(10, N);
338n_n <= akk(N - 1 downto 0) + (c_c - x"30");
339end if;
340state_n <= WAITING;
341elsif state_c = WRITE then
342done_o <= '1';
343state_n <= FINISHED;
344elsif state_c = FINISHED then
345null; -- wait for a reset
346else
347state_n <= RESET;
348report "Invalid State" severity failure;
349end if;
350
351if init = '1' then
352assert state_c = FINISHED report "Lost Conversion" severity error;
353state_n <= RESET;
354end if;
355end if;
356end if;
357end process;
358
359end architecture;
360----- ATOI --------------------------------------------------------------------
361
362----- VT100 Terminal Emulator -------------------------------------------------
363-- This module contains the VGA module and wraps it in a terminal emulator,
364-- based on the VT100 <https://en.wikipedia.org/wiki/VT100>, it only implements
365-- a subset of the commands supplied by the VT100. This simplifies the usage
366-- of the VGA text mode display, other VHDL components only have to write bytes
367-- and do not have to worry about cursor position or implementing new lines,
368-- tabs, and other very basic features.
369--
370-- The interface is designed to act like a UART, simply write a byte to it
371-- and so long as the interface is not busy, it will be written to the screen
372-- (or interpreter as part of a command sequence).
373
374library ieee, work;
375use ieee.std_logic_1164.all;
376use ieee.numeric_std.all;
377use work.vga_pkg.all;
378use work.util.common_generics;
379
380entity vt100 is
381generic(g: common_generics);
382port(
383clk: in std_ulogic;
384clk25MHz: in std_ulogic;
385rst: in std_ulogic;
386we: in std_ulogic;
387char: in std_ulogic_vector(7 downto 0);
388
389busy: out std_ulogic;
390o_vga: out vga_physical_interface);
391end entity;
392
393-- A better way of structuring this would be to process numbers in parallel
394-- with different components, one processing potential attributes, one holding
395-- one to two numbers - the results are then used. This would deal with runs
396-- of attributes, which is allowed.
397architecture rtl of vt100 is
398constant width: positive := 80;
399constant height: positive := 40;
400constant number: positive := 8;
401
402type state_type is (RESET, ACCEPT, NORMAL, WRAP, LIMIT, CSI, COMMAND,
403NUMBER1, NUMBER2, COMMAND1, COMMAND2, WRITE, ERASING, ATTRIB, ADVANCE);
404signal state_c, state_n: state_type := RESET;
405
406constant tab: unsigned(char'range) := x"09";
407constant backspace: unsigned(char'range) := x"08";
408constant ascii_bell: unsigned(char'range) := x"07";
409constant lf: unsigned(char'range) := x"0a";
410constant cr: unsigned(char'range) := x"0d";
411constant esc: unsigned(char'range) := x"1b";
412constant blank: unsigned(char'range) := x"20";
413constant asterisk: unsigned(char'range) := x"2A";
414constant ascii_7: unsigned(char'range) := x"37"; -- '7'
415constant ascii_8: unsigned(char'range) := x"38"; -- '8'
416constant lsqb: unsigned(char'range) := x"5b"; -- '['
417constant ascii_c: unsigned(char'range) := x"63"; -- 'c'
418constant attr_default: unsigned(7 downto 0) := "00111000";
419constant ctl_default: unsigned(4 downto 0) := "01111";
420
421signal addr: std_ulogic_vector(12 downto 0) := (others => '0');
422signal data_we: std_ulogic := '0';
423signal x: std_ulogic_vector(6 downto 0) := (others => '0');
424signal y: std_ulogic_vector(5 downto 0) := (others => '0');
425signal cursor_we: std_ulogic := '0';
426
427signal x_n, x_c: unsigned(x'range) := (others => '0');
428signal y_n, y_c: unsigned(y'range) := (others => '0');
429signal c_n, c_c: unsigned(char'range) := (others => '0');
430
431signal attr_c, attr_n: unsigned(attr_default'range) := attr_default;
432signal ctl_c, ctl_n: unsigned(ctl_default'range) := ctl_default;
433
434signal n1_n, n1_c: unsigned(7 downto 0) := (others => '0');
435signal n2_n, n2_c: unsigned(6 downto 0) := (others => '0');
436
437signal conceal_n, conceal_c: boolean := false;
438
439signal x_minus_one: unsigned(x'range) := (others => '0');
440signal x_minus_one_limited: unsigned(x'range) := (others => '0');
441signal x_underflow: boolean := false;
442signal x_plus_one: unsigned(x'range) := (others => '0');
443signal x_plus_one_limited: unsigned(x'range) := (others => '0');
444signal x_overflow: boolean := false;
445
446signal y_minus_one: unsigned(y'range) := (others => '0');
447signal y_minus_one_limited: unsigned(y'range) := (others => '0');
448signal y_underflow: boolean := false;
449signal y_plus_one: unsigned(y'range) := (others => '0');
450signal y_plus_one_limited: unsigned(y'range) := (others => '0');
451signal y_overflow: boolean := false;
452
453signal count_c, count_n: unsigned(addr'range) := (others => '0');
454signal limit_c, limit_n: unsigned(addr'high - 3 downto 0) := (others => '0');
455
456signal akk_done_o: std_ulogic := '0';
457-- signal akk_ready_o: std_ulogic := '0';
458signal akk_init: std_ulogic := '0';
459signal n_o: unsigned(number - 1 downto 0) := (others => '0');
460signal akk_char_o: std_ulogic_vector(char'range) := (others => '0');
461
462signal font_sel_c, font_sel_n: std_ulogic_vector(0 downto 0) := (others => '0');
463
464signal saved_x_n, saved_x_c: unsigned(x'range) := (others => '0');
465signal saved_y_n, saved_y_c: unsigned(y'range) := (others => '0');
466signal saved_attr_n, saved_attr_c: unsigned(attr_default'range) := (others => '0');
467
468signal reverse_video_c, reverse_video_n: boolean := false;
469signal base_n, base_c: unsigned(addr'high downto 4) := (others => '0');
470signal addr_sel: unsigned(addr'range) := (others => '0');
471
472signal saved_base_n, saved_base_c: unsigned(base_c'range) := (others => '0');
473signal is_base_saved_n, is_base_saved_c: boolean := false;
474
475begin
476accumulator_0: work.vga_pkg.atoi
477generic map(g => g, N => number)
478port map(
479clk => clk,
480rst => rst,
481we => we,
482init => akk_init,
483char => char,
484char_o => akk_char_o,
485done_o => akk_done_o,
486-- ready => akk_ready_o,
487n_o => n_o);
488
489address: block
490signal mul: unsigned(15 downto 0) := (others => '0');
491signal addr_int: unsigned(addr'range) := (others => '0');
492begin
493mul <= to_unsigned(to_integer(y_c) * width, mul'length);
494addr_int <= mul(addr_int'range) + ("000000" & x_c);
495addr_sel <= addr_int when state_c /= ERASING else count_c;
496addr <= std_ulogic_vector(addr_sel + (base_c & "0000"));
497end block;
498
499x_minus_one <= x_c - 1;
500x_plus_one <= x_c + 1;
501x_overflow <= x_c > (width - 1);
502x_underflow <= x_minus_one >= (width - 1);
503x_minus_one_limited <= (others => '0') when x_underflow else x_minus_one;
504x_plus_one_limited <= to_unsigned(width - 1, x_c'length) when x_overflow else x_plus_one;
505
506y_plus_one <= y_c + 1;
507y_minus_one <= y_c - 1;
508y_overflow <= y_c >= (height - 1); -- NB. > for 1 more row, slightly off edge of screen
509y_underflow <= y_minus_one > (height - 1);
510y_minus_one_limited <= (others => '0') when y_underflow else y_minus_one;
511y_plus_one_limited <= to_unsigned(height - 1, y_c'length) when y_overflow else y_plus_one;
512
513busy <= '1' when state_c = ERASING
514or state_c = WRITE
515or state_c = RESET
516or state_c = WRAP
517or state_c = ATTRIB
518or state_c = ADVANCE
519else '0';
520
521vga_blk: block
522signal vga_din: std_ulogic_vector(15 downto 0) := (others => '0');
523signal vga_ctr_we: vga_control_registers_we_interface := vga_control_registers_we_initialize;
524signal vga_ctr: vga_control_registers_interface := vga_control_registers_initialize;
525signal attr: unsigned(attr_c'range) := attr_default;
526signal ch: std_ulogic_vector(c_c'range) := (others => '0');
527begin
528ch <= std_ulogic_vector(asterisk) when conceal_c else std_ulogic_vector(c_c);
529attr <= attr_c when state_c /= ERASING else attr_default;
530vga_din <= std_ulogic_vector(attr) & ch;
531vga_ctr.crx <= std_ulogic_vector(x_plus_one); -- not limited, goes off screen edge
532vga_ctr.cry <= std_ulogic_vector(y_c);
533vga_ctr.ctl <= std_ulogic_vector(ctl_c);
534vga_ctr_we.crx <= cursor_we;
535vga_ctr_we.cry <= cursor_we;
536vga_ctr_we.ctl <= cursor_we;
537
538vga_0: work.vga_pkg.vga_top
539generic map(g => g)
540port map(
541clk => clk,
542clk25MHz => clk25MHz,
543rst => rst,
544vga_we_ram => data_we,
545vga_din => vga_din,
546vga_addr => addr,
547base(base_c'range)=> std_ulogic_vector(base_c),
548base(3 downto 0) => "0000",
549i_font_sel => font_sel_c,
550i_vga_control_we => vga_ctr_we,
551i_vga_control => vga_ctr,
552o_vga => o_vga);
553end block;
554
555-- Subset of commands implemented:
556-- ED - Erase Display, CSI n 'J'
557-- RIS - Erase Display, ESC 'c'
558-- SGR - Select Graphic Rendition - for colors, CSI n 'm'
559-- HVP - Horizontal and Vertical Position - CSI n ; m 'f'
560-- The cursor commands are also supported: CUU, CUD, CUF,
561-- CUB, CNL, CPL and CHA
562fsm: process(clk, rst)
563variable limit_value: unsigned(addr'range) := (others => '0');
564variable repeat: boolean := false;
565variable exit_repeat: state_type := RESET;
566procedure reverse_video(a: unsigned(2 downto 0); foreground: boolean) is
567begin
568if foreground then
569if reverse_video_c then
570attr_n(2 downto 0) <= a;
571else
572attr_n(5 downto 3) <= a;
573end if;
574else
575if reverse_video_c then
576attr_n(5 downto 3) <= a;
577else
578attr_n(2 downto 0) <= a;
579end if;
580end if;
581end procedure;
582begin
583if rst = '1' and g.asynchronous_reset then
584state_c <= RESET;
585elsif rising_edge(clk) then
586if rst = '1' and not g.asynchronous_reset then
587state_c <= RESET;
588else
589x_c <= x_n;
590y_c <= y_n;
591c_c <= c_n;
592count_c <= count_n;
593limit_c <= limit_n;
594state_c <= state_n;
595n1_c <= n1_n;
596n2_c <= n2_n;
597data_we <= '0';
598cursor_we <= '0';
599akk_init <= '0';
600attr_c <= attr_n;
601ctl_c <= ctl_n;
602conceal_c <= conceal_n;
603font_sel_c <= font_sel_n;
604saved_x_c <= saved_x_n;
605saved_y_c <= saved_y_n;
606saved_attr_c <= saved_attr_n;
607reverse_video_c <= reverse_video_n;
608base_c <= base_n;
609saved_base_c <= saved_base_n;
610is_base_saved_c <= is_base_saved_n;
611
612if state_c = RESET then
613n1_n <= (others => '0');
614n2_n <= (others => '0');
615x_n <= (others => '0');
616y_n <= (others => '0');
617c_n <= (others => '0');
618count_n <= (others => '0');
619limit_n <= (others => '0');
620saved_x_n <= (others => '0');
621saved_y_n <= (others => '0');
622saved_attr_n <= (others => '0');
623font_sel_n <= (others => '0');
624state_n <= ACCEPT;
625attr_n <= attr_default;
626ctl_n <= ctl_default;
627conceal_n <= false;
628reverse_video_n <= false;
629base_n <= (others => '0');
630is_base_saved_n <= false;
631saved_base_n <= (others => '0');
632elsif state_c = ACCEPT then
633if we = '1' then
634c_n <= unsigned(char);
635state_n <= NORMAL;
636end if;
637-- This behavior does not really mix well
638-- with the eForth interpreter.
639--
640-- if is_base_saved_c then
641-- is_base_saved_n <= false;
642-- base_n <= saved_base_c;
643-- end if;
644elsif state_c = NORMAL then
645case c_c is
646when tab =>
647x_n <= (x_c and "1111000") + 8;
648state_n <= ERASING;
649c_n <= blank;
650limit_value := unsigned(addr and "1111111111000") + 8;
651limit_n <= limit_value(limit_n'high + 3 downto limit_n'low + 3);
652count_n <= unsigned(addr);
653when ascii_bell =>
654ctl_n(4) <= not ctl_c(4); -- ctr_n(4) goes to edge triggered logic
655state_n <= ACCEPT;
656when cr =>
657y_n <= y_plus_one;
658state_n <= WRAP;
659when lf =>
660x_n <= (others => '0');
661state_n <= WRITE;
662when backspace =>
663x_n <= x_minus_one_limited;
664state_n <= WRITE;
665when esc =>
666state_n <= CSI;
667when others =>
668data_we <= '1';
669state_n <= ADVANCE;
670end case;
671elsif state_c = ADVANCE then
672x_n <= x_plus_one;
673state_n <= WRAP;
674elsif state_c = CSI then
675if we = '1' then
676c_n <= unsigned(char);
677state_n <= COMMAND;
678end if;
679elsif state_c = COMMAND then
680case c_c is
681when ascii_c =>
682x_n <= (others => '0');
683y_n <= (others => '0');
684c_n <= blank;
685count_n <= (others => '0');
686limit_n <= "1000000000";
687state_n <= ERASING;
688base_n <= (others => '0');
689when lsqb =>
690state_n <= NUMBER1;
691akk_init <= '1';
692
693when ascii_7 => -- 'ESC 7'; Save Cursor and Attributes
694saved_x_n <= x_c;
695saved_y_n <= y_c;
696saved_attr_n <= attr_c;
697state_n <= ACCEPT;
698when ascii_8 => -- 'ESC 8'; Restore Cursor and Attributes
699x_n <= saved_x_c;
700y_n <= saved_y_c;
701attr_n <= saved_attr_c;
702state_n <= ACCEPT;
703when others => -- Error
704state_n <= ACCEPT;
705end case;
706elsif state_c = NUMBER1 then
707if akk_done_o = '1' then
708state_n <= COMMAND1;
709n1_n <= n_o(n1_n'range);
710end if;
711elsif state_c = COMMAND1 then
712repeat := false;
713case akk_char_o is
714when x"41" => -- CSI n 'A' : CUU Cursor up
715y_n <= y_minus_one_limited;
716exit_repeat := WRITE;
717repeat := true;
718when x"42" => -- CSI n 'B' : CUD Cursor Down
719y_n <= y_plus_one_limited;
720exit_repeat := LIMIT;
721repeat := true;
722when x"43" => -- CSI n 'C' : CUF Cursor Forward
723x_n <= x_plus_one_limited;
724exit_repeat := LIMIT;
725repeat := true;
726when x"44" => -- CSI n 'D' : CUB Cursor Back
727x_n <= x_minus_one_limited;
728exit_repeat := WRITE;
729repeat := true;
730when x"45" => -- CSI n 'E'
731y_n <= y_minus_one_limited;
732x_n <= (others => '0');
733exit_repeat := WRITE;
734repeat := true;
735when x"46" => -- CSI n 'F'
736y_n <= y_plus_one_limited;
737x_n <= (others => '0');
738exit_repeat := LIMIT;
739repeat := true;
740when x"47" => -- CSI n 'G' : CHA Cursor Horizontal Absolute
741x_n <= n1_c(x_n'range);
742state_n <= LIMIT;
743when x"4a" => -- CSI n 'J'
744x_n <= (others => '0');
745y_n <= (others => '0');
746base_n <= (others => '0');
747cursor_we <= '1';
748state_n <= ERASING;
749c_n <= blank;
750count_n <= (others => '0');
751limit_n <= "1000000000";
752when x"3b" => -- ESC n ';' ...
753state_n <= NUMBER2;
754akk_init <= '1';
755when x"6d" => -- CSI n 'm' : SGR
756state_n <= ATTRIB;
757
758-- NB. Number parameter does nothing.
759when x"53" => -- CSI n 'S' : scroll up
760saved_base_n <= base_c;
761is_base_saved_n <= true;
762base_n <= (others => '0');
763state_n <= WRITE;
764when x"54" => -- CSI n 'T' : scroll down
765state_n <= WRITE;
766if is_base_saved_c then
767base_n <= saved_base_c;
768is_base_saved_n <= false;
769end if;
770when x"73" => -- CSI 's': SCP (Secure, Contain, Protect the Cursor Position)
771saved_x_n <= x_c;
772saved_y_n <= y_c;
773state_n <= ACCEPT;
774when x"75" => -- CSI 'u': RCP Restore Cursor Position
775x_n <= saved_x_c;
776y_n <= saved_y_c;
777state_n <= ACCEPT;
778
779-- This is an extension, it is for setting the
780-- control lines of the VGA module directly.
781when x"78" => -- ESC n 'x' : Set VGA control registers directly
782ctl_n <= n1_c(ctl_n'range);
783state_n <= WRITE;
784when others => -- Error
785state_n <= ACCEPT;
786end case;
787
788if repeat then
789if n1_c <= 1 then
790state_n <= exit_repeat;
791else
792n1_n <= n1_c - 1;
793end if;
794end if;
795elsif state_c = NUMBER2 then
796if akk_done_o = '1' then
797state_n <= COMMAND2;
798n2_n <= n_o(n2_n'range);
799end if;
800elsif state_c = COMMAND2 then
801case akk_char_o is
802when x"66" => -- f
803y_n <= n1_c(y_n'range) - 1;
804x_n <= n2_c(x_n'range) - 1;
805cursor_we <= '1';
806state_n <= LIMIT;
807when x"48" => -- H
808y_n <= n1_c(y_n'range) - 1;
809x_n <= n2_c(x_n'range) - 1;
810cursor_we <= '1';
811state_n <= LIMIT;
812when x"6d" => -- ESC n ';' m 'm'
813state_n <= ATTRIB;
814when others =>
815state_n <= ACCEPT;
816end case;
817elsif state_c = WRAP then
818if x_overflow then
819x_n <= (others => '0');
820y_n <= y_plus_one;
821elsif y_overflow then
822x_n <= (others => '0');
823y_n <= y_minus_one;
824state_n <= ERASING;
825c_n <= blank;
826count_n <= unsigned(addr_sel);
827limit_value := unsigned(addr_sel) + (3*width);
828limit_n <= limit_value(limit_n'high + 3 downto limit_n'low + 3);
829base_n <= base_c + (width / 16);
830else
831state_n <= WRITE;
832end if;
833elsif state_c = LIMIT then
834if x_overflow then
835x_n <= to_unsigned(width - 1, x_n'high + 1);
836end if;
837if y_overflow then
838y_n <= to_unsigned(height - 1, y_n'high + 1);
839end if;
840state_n <= WRITE;
841elsif state_c = WRITE then
842state_n <= ACCEPT;
843cursor_we <= '1';
844elsif state_c = ERASING then
845if count_c(limit_c'high + 3 downto limit_c'low + 3) /= limit_c then
846count_n <= count_c + 1;
847data_we <= '1';
848else
849state_n <= WRAP;
850end if;
851elsif state_c = ATTRIB then
852case n1_c is
853when x"00" =>
854attr_n <= attr_default;
855conceal_n <= false;
856reverse_video_n <= false;
857when x"01" => attr_n(6) <= '1'; -- bold
858-- when x"02" => -- faint
859when x"16" => attr_n(6) <= '0'; -- normal brightness
860when x"05" => attr_n(7) <= '1'; -- slow blink
861when x"19" => attr_n(7) <= '0'; -- blink off
862when x"07" =>
863if not reverse_video_c then
864attr_n <= attr_c(7 downto 6) & attr_c(2 downto 0) & attr_c(5 downto 3);
865end if;
866reverse_video_n <= true;
867when x"1B" =>
868if reverse_video_c then
869attr_n <= attr_c(7 downto 6) & attr_c(2 downto 0) & attr_c(5 downto 3);
870end if;
871reverse_video_n <= false;
872when x"08" => conceal_n <= true;
873when x"1C" => conceal_n <= false;
874
875when x"0A" => font_sel_n <= (others => '0');
876when x"0B" => font_sel_n <= "1";
877
878when x"1E" => reverse_video("000", true); -- 30
879when x"1F" => reverse_video("001", true);
880when x"20" => reverse_video("010", true);
881when x"21" => reverse_video("011", true);
882when x"22" => reverse_video("100", true);
883when x"23" => reverse_video("101", true);
884when x"24" => reverse_video("110", true);
885when x"25" => reverse_video("111", true);
886
887when x"28" => reverse_video("000", false); -- 40
888when x"29" => reverse_video("001", false);
889when x"2A" => reverse_video("010", false);
890when x"2B" => reverse_video("011", false);
891when x"2C" => reverse_video("100", false);
892when x"2D" => reverse_video("101", false);
893when x"2E" => reverse_video("110", false);
894when x"2F" => reverse_video("111", false);
895
896when others =>
897end case;
898state_n <= ACCEPT;
899else
900state_n <= RESET;
901report "Invalid State" severity failure;
902end if;
903end if;
904end if;
905end process;
906end architecture;
907----- VT100 Terminal Emulator -------------------------------------------------
908
909----- VGA Top Level Component -------------------------------------------------
910library ieee,work;
911use ieee.std_logic_1164.all;
912use ieee.numeric_std.all;
913use work.vga_pkg.all;
914use work.util.file_format;
915use work.util.file_hex;
916use work.util.file_binary;
917use work.util.common_generics;
918
919entity vga_top is
920generic(g: common_generics);
921port(
922clk: in std_ulogic;
923clk25MHz: in std_ulogic;
924rst: in std_ulogic;
925
926-- VGA Text buffer interface
927vga_we_ram: in std_ulogic; -- Write enable RAM
928vga_din: in std_ulogic_vector(15 downto 0);
929vga_addr: in std_ulogic_vector(12 downto 0);
930base: in std_ulogic_vector(12 downto 0);
931
932-- VGA control registers
933i_font_sel: in std_ulogic_vector(0 downto 0);
934i_vga_control_we: in vga_control_registers_we_interface;
935i_vga_control: in vga_control_registers_interface;
936
937o_vga: out vga_physical_interface);
938end;
939
940architecture behav of vga_top is
941-- Setup for text buffer memory
942constant text_addr_length: positive := 13;
943constant text_data_length: positive := 16;
944constant text_file_name: string := "text.hex";
945constant text_file_type: file_format := FILE_HEX;
946
947-- Setup for font buffer memory
948constant font_addr_length: positive := 13;
949constant font_data_length: positive := 8;
950constant font_file_name: string := "font.bin";
951constant font_file_type: file_format := FILE_BINARY;
952
953-- Internal signals for mapping output <--> VGA module
954signal foreground_draw_internal: std_ulogic := '0';
955
956-- Text RAM signals, RAM <--> VGA module
957signal text_dout: std_ulogic_vector(15 downto 0) := (others => '0');
958signal text_din: std_ulogic_vector(15 downto 0) := (others => '0');
959signal text_addr: std_ulogic_vector(11 downto 0) := (others => '0');
960signal text_addr_full: std_ulogic_vector(12 downto 0) := (others => '0');
961
962-- Font ROM signals, ROM<-->VGA module
963signal font_addr: std_ulogic_vector(12 downto 0) := (others => '0');
964signal font_dout: std_ulogic_vector( 7 downto 0) := (others => '0');
965
966signal control_c, control_n: vga_control_registers_interface := vga_control_registers_initialize;
967
968signal foreground_draw: std_ulogic := '0';
969signal background_draw: std_ulogic := '0';
970begin
971
972vga_ns: process(clk, rst)
973begin
974if rst = '1' and g.asynchronous_reset then
975control_c <= vga_control_registers_initialize;
976elsif rising_edge(clk) then
977if rst = '1' and not g.asynchronous_reset then
978control_c <= vga_control_registers_initialize;
979else
980control_c <= control_n;
981end if;
982end if;
983end process;
984
985vga_creg_we: process(
986control_c,
987i_vga_control,
988i_vga_control_we)
989begin
990control_n <= control_c;
991
992if i_vga_control_we.crx = '1' then control_n.crx <= i_vga_control.crx; end if;
993if i_vga_control_we.cry = '1' then control_n.cry <= i_vga_control.cry; end if;
994if i_vga_control_we.ctl = '1' then control_n.ctl <= i_vga_control.ctl; end if;
995end process;
996
997u_vga: work.vga_pkg.vga_core
998generic map(g => g)
999port map (
1000rst => rst,
1001clk25MHz => clk25MHz,
1002
1003text_a => text_addr,
1004text_d => text_dout,
1005
1006font_a => font_addr,
1007font_d => font_dout,
1008
1009font_sel => i_font_sel,
1010
1011ocrx => control_c.crx,
1012ocry => control_c.cry,
1013octl => control_c.ctl,
1014
1015o_vga => o_vga);
1016
1017text_addr_full <= std_ulogic_vector(unsigned(base) + unsigned(text_addr));
1018
1019u_text_memory: entity work.dual_port_block_ram -- holds at least 80x40 characters
1020generic map(g => g,
1021addr_length => text_addr_length,
1022data_length => text_data_length,
1023file_name => text_file_name,
1024file_type => text_file_type)
1025port map (
1026a_clk => clk,
1027-- External interface
1028a_dwe => vga_we_ram,
1029a_dre => '1',
1030a_addr => vga_addr,
1031a_din => vga_din,
1032a_dout => open,
1033-- Internal interface
1034b_clk => clk25MHz,
1035b_dwe => '0',
1036b_dre => '1',
1037b_addr => text_addr_full,
1038b_din => (others => '0'),
1039b_dout => text_dout);
1040
1041u_font_memory: entity work.single_port_block_ram
1042generic map(g => g,
1043addr_length => font_addr_length,
1044data_length => font_data_length,
1045file_name => font_file_name,
1046file_type => font_file_type)
1047port map (
1048clk => clk25MHz,
1049dwe => '0',
1050dre => '1',
1051addr => font_addr,
1052din => (others => '0'),
1053dout => font_dout);
1054
1055end architecture;
1056
1057----- VGA Top Level Component -------------------------------------------------
1058
1059----- VGA Core ----------------------------------------------------------------
1060
1061library ieee;
1062use ieee.std_logic_1164.all;
1063use ieee.numeric_std.all;
1064use work.vga_pkg.all;
1065use work.util.common_generics;
1066
1067entity vga_core is
1068generic(g: common_generics);
1069port (
1070rst: in std_ulogic;
1071clk25MHz: in std_ulogic;
1072text_a: out std_ulogic_vector(11 downto 0); -- text buffer
1073text_d: in std_ulogic_vector(15 downto 0);
1074font_a: out std_ulogic_vector(12 downto 0); -- font buffer
1075font_d: in std_ulogic_vector( 7 downto 0);
1076font_sel: in std_ulogic_vector(0 downto 0);
1077--
1078ocrx: in std_ulogic_vector(6 downto 0);
1079ocry: in std_ulogic_vector(5 downto 0);
1080octl: in std_ulogic_vector(4 downto 0);
1081--
1082o_vga: out vga_physical_interface);
1083end entity;
1084
1085architecture rtl of vga_core is
1086signal foreground_draw_int, background_draw_int: std_ulogic := '0';
1087signal hsync_int: std_ulogic := '1';
1088signal vsync_int: std_ulogic := '1';
1089
1090signal blank: std_ulogic := '0';
1091signal hctr: integer range 793 downto 0 := 0;
1092signal vctr: integer range 524 downto 0 := 0;
1093
1094-- character/pixel position on the screen
1095signal scry_text: integer range 39 downto 0 := 0; -- chr row < 40 (6 bits)
1096signal scrx_text: integer range 79 downto 0 := 0; -- chr col < 80 (7 bits)
1097signal chry: integer range 11 downto 0 := 0; -- chr hight < 12 (4 bits)
1098signal chrx: integer range 7 downto 0 := 0; -- chr width < 08 (3 bits)
1099
1100signal losr_ce: std_ulogic := '0';
1101signal losr_ld: std_ulogic := '0';
1102signal losr_do: std_ulogic := '0';
1103signal y: std_ulogic := '0'; -- character luminance pixel value (0 or 1)
1104
1105-- control io register
1106signal bell: std_ulogic := '0';
1107signal vga_en: std_ulogic := '0';
1108signal cur_en: std_ulogic := '0';
1109signal cur_mode: std_ulogic := '0';
1110signal cur_blink: std_ulogic := '0';
1111
1112signal background_draw, foreground_draw: std_ulogic := '0';
1113signal attr: std_ulogic_vector(7 downto 0) := (others =>'0');
1114signal attr_we_delay: std_ulogic := '0';
1115signal slowclk, slowclk_cr: std_ulogic := '0';
1116
1117signal bell_c, bell_n: std_ulogic := '0';
1118signal bell_on_c, bell_on_n: std_ulogic := '0';
1119begin
1120-- Control register. Individual control signal
1121bell_n <= octl(4);
1122bell <= bell_c xor bell_n;
1123vga_en <= octl(3);
1124cur_en <= octl(2);
1125cur_blink <= octl(1);
1126cur_mode <= octl(0);
1127
1128-- bell register
1129process (rst, clk25MHz)
1130begin
1131if rst = '1' and g.asynchronous_reset then
1132bell_c <= '0';
1133bell_on_c <= '0';
1134elsif rising_edge(clk25MHz) then
1135if rst = '1' and not g.asynchronous_reset then
1136bell_c <= '0';
1137bell_on_c <= '0';
1138else
1139bell_c <= bell_n;
1140bell_on_c <= bell_on_n;
1141end if;
1142end if;
1143end process;
1144
1145process (bell_on_c, slowclk, bell)
1146begin
1147bell_on_n <= bell_on_c;
1148slowclk_cr <= '0';
1149if bell = '1' then
1150bell_on_n <= '1';
1151slowclk_cr <= '1';
1152elsif slowclk = '1' then
1153bell_on_n <= '0';
1154end if;
1155end process;
1156
1157-- hsync generator, initialized with '1'
1158process (rst, clk25MHz)
1159begin
1160if rst = '1' and g.asynchronous_reset then
1161hsync_int <= '1';
1162elsif rising_edge(clk25MHz) then
1163if rst = '1' and not g.asynchronous_reset then
1164hsync_int <= '1';
1165else
1166if (hctr > 663) and (hctr < 757) then
1167hsync_int <= '0';
1168else
1169hsync_int <= '1';
1170end if;
1171end if;
1172end if;
1173end process;
1174
1175-- vsync generator, initialized with '1'
1176process (rst, clk25MHz)
1177begin
1178if rst = '1' and g.asynchronous_reset then
1179vsync_int <= '1';
1180elsif rising_edge(clk25MHz) then
1181if rst = '1' and not g.asynchronous_reset then
1182vsync_int <= '1';
1183else
1184if (vctr > 499) and (vctr < 502) then
1185vsync_int <= '0';
1186else
1187vsync_int <= '1';
1188end if;
1189end if;
1190end if;
1191end process;
1192
1193-- Blank signal, 0 = no draw, 1 = visible/draw zone
1194
1195-- Proboscide99 31/08/08
1196blank <= '0' when (hctr < 8) or (hctr > 647) or (vctr > 479) else '1';
1197
1198-- flip-flops for sync of R, G y B signal, initialized with '0'
1199process (rst, clk25MHz)
1200begin
1201if rst = '1' and g.asynchronous_reset then
1202foreground_draw <= '0';
1203elsif rising_edge(clk25MHz) then
1204if rst = '1' and not g.asynchronous_reset then
1205foreground_draw <= '0';
1206else
1207foreground_draw <= foreground_draw_int;
1208background_draw <= background_draw_int;
1209end if;
1210end if;
1211end process;
1212
1213-- counters, hctr, vctr, srcx, srcy, chrx, chry
1214counters: block
1215signal hctr_ce: std_ulogic := '0';
1216signal hctr_rs: std_ulogic := '0';
1217signal vctr_ce: std_ulogic := '0';
1218signal vctr_rs: std_ulogic := '0';
1219
1220signal chrx_ce: std_ulogic := '0';
1221signal chrx_rs: std_ulogic := '0';
1222signal chry_ce: std_ulogic := '0';
1223signal chry_rs: std_ulogic := '0';
1224signal scrx_ce: std_ulogic := '0';
1225signal scrx_rs: std_ulogic := '0';
1226signal scry_ce: std_ulogic := '0';
1227signal scry_rs: std_ulogic := '0';
1228
1229signal hctr_639: std_ulogic := '0';
1230signal vctr_479: std_ulogic := '0';
1231signal chrx_007: std_ulogic := '0';
1232signal chry_011: std_ulogic := '0';
1233
1234-- RAM read, ROM read
1235signal ram_tmp: unsigned(11 downto 0) := (others => '0'); -- range 3199 downto 0
1236signal mul: unsigned(15 downto 0) := (others => '0');
1237signal rom_tmp: unsigned(11 downto 0) := (others => '0'); -- range 3071 downto 0;
1238
1239signal text_d_tmp: std_ulogic_vector(7 downto 0) := (others => '0');
1240begin
1241u_hctr: work.vga_pkg.ctrm generic map (g => g, M => 794)
1242port map (rst, clk25MHz, hctr_ce, hctr_rs, hctr);
1243u_vctr: work.vga_pkg.ctrm generic map (g => g, M => 525)
1244port map (rst, clk25MHz, vctr_ce, vctr_rs, vctr);
1245
1246hctr_ce <= '1';
1247hctr_rs <= '1' when hctr = 793 else '0';
1248vctr_ce <= '1' when hctr = 663 else '0';
1249vctr_rs <= '1' when vctr = 524 else '0';
1250
1251u_chrx: work.vga_pkg.ctrm generic map (g => g, M => 8)
1252port map (rst, clk25MHz, chrx_ce, chrx_rs, chrx);
1253u_chry: work.vga_pkg.ctrm generic map (g => g, M => 12)
1254port map (rst, clk25MHz, chry_ce, chry_rs, chry);
1255u_scrx: work.vga_pkg.ctrm generic map (g => g, M => 80)
1256port map (rst, clk25MHz, scrx_ce, scrx_rs, scrx_text);
1257u_scry: work.vga_pkg.ctrm generic map (g => g, M => 40)
1258port map (rst, clk25MHz, scry_ce, scry_rs, scry_text);
1259
1260hctr_639 <= '1' when hctr = 639 else '0';
1261vctr_479 <= '1' when vctr = 479 else '0';
1262chrx_007 <= '1' when chrx = 7 else '0';
1263chry_011 <= '1' when chry = 11 else '0';
1264
1265chrx_rs <= chrx_007 or hctr_639;
1266chry_rs <= chry_011 or vctr_479;
1267scrx_rs <= hctr_639;
1268scry_rs <= vctr_479;
1269
1270chrx_ce <= '1' and blank;
1271scrx_ce <= chrx_007;
1272chry_ce <= hctr_639 and blank;
1273scry_ce <= chry_011 and hctr_639;
1274
1275ram_tmp <= (to_unsigned(scry_text, ram_tmp'length) sll 4) +
1276(to_unsigned(scry_text, ram_tmp'length) sll 6) +
1277to_unsigned(scrx_text, ram_tmp'length);
1278
1279text_d_tmp <= text_d(7 downto 0);
1280text_a <= std_ulogic_vector(ram_tmp);
1281mul <= unsigned(text_d_tmp) * 12;
1282rom_tmp <= mul(rom_tmp'range) + chry;
1283font_a <= font_sel & std_ulogic_vector(rom_tmp);
1284end block;
1285
1286color_block: block
1287signal red_on: std_ulogic := '0';
1288signal green_on: std_ulogic := '0';
1289signal blue_on: std_ulogic := '0';
1290signal bold: std_ulogic := '0';
1291signal reverse: std_ulogic := '0';
1292signal final: std_ulogic_vector(2 downto 0) := "111";
1293begin
1294reverse <= bell_on_c when attr(7) = '0' else slowclk;
1295bold <= attr(6);
1296final <= "100" when bold = '0' else "111";
1297
1298red_on <= (reverse xor attr(3)) when foreground_draw = '1' else
1299(bell_on_c xor attr(0)) when background_draw = '1' else '0';
1300green_on <= (reverse xor attr(4)) when foreground_draw = '1' else
1301(bell_on_c xor attr(1)) when background_draw = '1' else '0';
1302blue_on <= (reverse xor attr(5)) when foreground_draw = '1' else
1303(bell_on_c xor attr(2)) when background_draw = '1' else '0';
1304
1305o_vga.red <= final when red_on = '1' else "000";
1306o_vga.green <= final when green_on = '1' else "000";
1307o_vga.blue <= final(2 downto 1) when blue_on = '1' else "00";
1308end block;
1309
1310u_reg_delay: work.util.reg generic map (g => g, N => 1)
1311port map(clk => clk25MHz, rst => rst, we => '1', di(0) => losr_ld, do(0) => attr_we_delay);
1312
1313u_reg_attr: work.util.reg generic map (g => g, N => 8)
1314port map(clk => clk25MHz, rst => rst, we => attr_we_delay, di => text_d(15 downto 8), do => attr);
1315
1316u_losr: work.vga_pkg.losr generic map (g => g, N => font_d'length)
1317port map (rst => rst, clk => clk25MHz, load => losr_ld, ce => losr_ce, do => losr_do, di => font_d);
1318
1319losr_ce <= blank;
1320losr_ld <= '1' when (chrx = 7) else '0';
1321
1322-- video out, vga_en control signal enable/disable vga signal
1323foreground_draw_int <= y and blank;
1324background_draw_int <= (not y) and blank;
1325
1326o_vga.hsync <= hsync_int and vga_en;
1327o_vga.vsync <= vsync_int and vga_en;
1328
1329-- Hardware Cursor
1330hw_cursor: block
1331signal small: std_ulogic := '0';
1332signal curen2: std_ulogic := '0';
1333signal curpos: std_ulogic := '0';
1334signal yint: std_ulogic := '0';
1335signal crx: integer range 127 downto 0;
1336signal cry: integer range 64 downto 0;
1337signal counter: unsigned(24 downto 0) := (others => '0');
1338signal cursorclk: std_ulogic := '0';
1339begin
1340process (counter, slowclk_cr, clk25MHz)
1341begin
1342counter <= counter;
1343if rising_edge(clk25MHz) then
1344if slowclk_cr = '1' then
1345counter <= (others => '0');
1346else
1347counter <= counter + 1;
1348end if;
1349end if;
1350end process;
1351
1352cursorclk <= counter(22); -- 2.98Hz
1353slowclk <= counter(24); -- 0.745Hz
1354
1355crx <= to_integer(unsigned(ocrx(6 downto 0)));
1356cry <= to_integer(unsigned(ocry(5 downto 0)));
1357
1358--
1359curpos <= '1' when scry_text = cry and scrx_text = crx else '0';
1360small <= '1' when (chry > 8) else '0';
1361curen2 <= (cursorclk or (not cur_blink)) and cur_en;
1362yint <= '1' when cur_mode = '0' else small;
1363y <= (yint and curpos and curen2) xor losr_do;
1364end block;
1365end;
1366----- VGA Core ----------------------------------------------------------------
1367
1368-------------------------------------------------------------------------------
1369--| @file ctrm.vhd
1370--| @brief Counter, asynchronous *and* synchronous reset, up only.
1371--| (ctrm.vhd, original filename)
1372--| @author Javier Valcarce García
1373--| @copyright Copyright 2007 Javier Valcarce García
1374--| @license LGPL version 3
1375--| @email javier.valcarce@gmail.com
1376-------------------------------------------------------------------------------
1377library ieee, work;
1378use ieee.std_logic_1164.all;
1379use ieee.numeric_std.all;
1380use work.util.common_generics;
1381
1382entity ctrm is
1383generic (g: common_generics; M: positive := 8);
1384port (
1385rst: in std_ulogic; -- asynchronous rst
1386clk: in std_ulogic;
1387ce: in std_ulogic; -- enable counting
1388rs: in std_ulogic; -- synchronous rst
1389do: out integer range (M-1) downto 0 := 0);
1390end entity;
1391
1392architecture rtl of ctrm is
1393signal c: integer range (M-1) downto 0:= 0;
1394begin
1395do <= c;
1396process(rst, clk)
1397begin
1398if rst = '1' and g.asynchronous_reset then
1399c <= 0 after g.delay;
1400elsif rising_edge(clk) then
1401if rst = '1' and not g.asynchronous_reset then
1402c <= 0 after g.delay;
1403else
1404if ce = '1' then
1405if rs = '1' then
1406c <= 0 after g.delay;
1407else
1408-- elsif c /= (M - 1) then
1409c <= c + 1 after g.delay;
1410end if;
1411end if;
1412end if;
1413end if;
1414end process;
1415end;
1416
1417-------------------------------------------------------------------------------
1418--| @file util.vhd
1419--| @brief Shift register N-bit, asynchronous reset, synchronous load,
1420--| and enable
1421--| @author Javier Valcarce García
1422--| @copyright Copyright 2007 Javier Valcarce García
1423--| @license LGPL version 3
1424--| @email javier.valcarce@gmail.com
1425-------------------------------------------------------------------------------
1426
1427library ieee, work;
1428use ieee.std_logic_1164.all;
1429use ieee.numeric_std.all;
1430use work.util.common_generics;
1431
1432entity losr is
1433generic (g: common_generics; N: positive := 4);
1434port
1435(
1436rst: in std_ulogic;
1437clk: in std_ulogic;
1438load: in std_ulogic;
1439ce: in std_ulogic;
1440do: out std_ulogic := '0';
1441di: in std_ulogic_vector(N - 1 downto 0));
1442end entity;
1443
1444architecture rtl of losr is
1445begin
1446process(rst, clk)
1447variable data: std_ulogic_vector(N - 1 downto 0) := (others => '0');
1448begin
1449if rst = '1' and g.asynchronous_reset then
1450data := (others => '0');
1451elsif rising_edge(clk) then
1452if rst = '1' and not g.asynchronous_reset then
1453data := (others => '0');
1454else
1455if load = '1' then
1456data := di;
1457elsif ce = '1' then
1458data := data(N-2 downto 0) & "0";
1459end if;
1460end if;
1461end if;
1462do <= data(N-1) after g.delay;
1463end process;
1464end;
1465
1466