OpenCores
URL https://opencores.org/ocsvn/forth-cpu/forth-cpu/trunk

Subversion Repositories forth-cpu

[/] [forth-cpu/] [trunk/] [vga.vhd] - Rev 5

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
--| @file vga.vhd
--| @brief      Text Mode Video Controller VHDL Module and VT100
--|             Terminal Emulator
--| @author     Javier Valcarce García
--| @author     Richard James Howe (vt100, vt100_tb, atoi, color attributes)
--| @copyright  Copyright 2007 Javier Valcarce García, 2017, 2019 Richard James Howe
--| @license    LGPL version 3
--| @email      javier.valcarce@gmail.com
--| @note       (Modifications and repackaging by Richard James Howe)
--|
--| This is a modified version of the text terminal available at
--| <https://opencores.org/project,interface_vga80x40>. Additions include per
--| character attribute information (color, bold, reverse video, blink text)
--| and a VT100 terminal interface.
--|
--| See also <http://www.javiervalcarce.eu/html/vhdl-vga80x40-en.html>.
--|
-------------------------------------------------------------------------------
 
----- VGA Package -------------------------------------------------------------
library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.util.common_generics;
 
package vga_pkg is
	type vga_physical_interface is record
		red:   std_ulogic_vector(2 downto 0);
		green: std_ulogic_vector(2 downto 0);
		blue:  std_ulogic_vector(1 downto 0);
		hsync: std_ulogic;
		vsync: std_ulogic;
	end record;
 
	type vga_control_registers_we_interface is record
		crx: std_ulogic; -- Write enable for cursor X position register
		cry: std_ulogic; -- Write enable for VGA control register
		ctl: std_ulogic; -- Write enable for cursor Y position register
	end record;
 
	type vga_control_registers_interface is record
		crx:    std_ulogic_vector(6 downto 0); -- Cursor position X
		cry:    std_ulogic_vector(5 downto 0); -- Cursor position Y
		ctl:    std_ulogic_vector(4 downto 0); -- Control register
	end record;
 
	constant vga_control_registers_initialize: vga_control_registers_interface := (
			cry => (others => '0'),
			crx => (others => '0'),
			ctl => (others => '0'));
 
	constant vga_control_registers_we_initialize: vga_control_registers_we_interface := (
			cry => '0',
			crx => '0',
			ctl => '0');
 
	component vga_top is
	generic(g: common_generics);
	port(
		clk:         in  std_ulogic;
		clk25MHz:    in  std_ulogic;
		rst:         in  std_ulogic;
 
		-- VGA Text buffer interface
		vga_we_ram:  in  std_ulogic; -- Write enable RAM
		vga_din:     in  std_ulogic_vector(15 downto 0);
		vga_addr:    in  std_ulogic_vector(12 downto 0);
		base:        in  std_ulogic_vector(12 downto 0);
 
		-- VGA control registers
		i_font_sel:       in std_ulogic_vector(0 downto 0);
		i_vga_control_we: in vga_control_registers_we_interface;
		i_vga_control:    in vga_control_registers_interface;
 
		o_vga:    out vga_physical_interface);
	end component;
 
	component vga_core is
	generic(g: common_generics);
	port (
		rst:       in  std_ulogic;
		clk25MHz:  in  std_ulogic;
		text_a:    out std_ulogic_vector(11 downto 0); -- text buffer
		text_d:    in  std_ulogic_vector(15 downto 0);
		font_a:    out std_ulogic_vector(12 downto 0); -- font buffer
		font_d:    in  std_ulogic_vector( 7 downto 0);
		font_sel:  in  std_ulogic_vector(0 downto 0);
		 --
		ocrx:      in  std_ulogic_vector(6 downto 0);
		ocry:      in  std_ulogic_vector(5 downto 0);
		octl:      in  std_ulogic_vector(4 downto 0);
		--
		o_vga: out vga_physical_interface);
	end component;
 
	component losr is
	generic (g: common_generics; N: positive := 4);
	port
	(
		rst:  in  std_ulogic;
		clk:  in  std_ulogic;
		load: in  std_ulogic;
		ce:   in  std_ulogic;
		do:   out std_ulogic := '0';
		di:   in  std_ulogic_vector(N - 1 downto 0));
	end component;
 
	component ctrm is
	generic (g: common_generics; M: positive := 8);
	port (
		rst: in  std_ulogic; -- asynchronous rst
		clk: in  std_ulogic;
		ce:  in  std_ulogic; -- enable counting
		rs:  in  std_ulogic; -- synchronous rst
		do:  out integer range (M-1) downto 0 := 0);
	end component;
 
	component vt100 is
	generic (g: common_generics);
	port(
		clk:        in  std_ulogic;
		clk25MHz:   in  std_ulogic;
		rst:        in  std_ulogic;
		we:         in  std_ulogic;
		char:       in  std_ulogic_vector(7 downto 0);
 
		busy:       out std_ulogic;
		o_vga:      out vga_physical_interface);
	end component;
 
	-- VGA test bench, not-synthesizeable
	component vt100_tb is
		generic(g: common_generics);
	end component;
 
	component atoi is
		generic(g: common_generics; N: positive := 16);
		port(
			clk:    in  std_ulogic;
			rst:    in  std_ulogic;
			we:     in  std_ulogic;
			init:   in  std_ulogic;
			char:   in  std_ulogic_vector(7 downto 0);
			char_o: out std_ulogic_vector(7 downto 0);
			done_o: out std_ulogic;
			-- ready:  out std_ulogic;
			n_o:    out unsigned(N - 1 downto 0));
	end component;
end package;
 
----- VGA Package -------------------------------------------------------------
 
----- VGA Test Bench ----------------------------------------------------------
 
library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
use work.vga_pkg.all;
use work.util.all;
 
entity vt100_tb is
	generic(g: common_generics);
end entity;
 
architecture behav of vt100_tb is
	constant clock_period: time := 1000 ms / g.clock_frequency;
	signal clk, rst: std_ulogic := '0';
	signal stop:     std_ulogic := '0';
	signal clk25MHz, rst25MHz: std_ulogic := '0';
 
	signal char:     std_ulogic_vector(7 downto 0);
	signal we:       std_ulogic := '0';
	signal busy:     std_ulogic := '0';
	signal physical: vga_physical_interface;
 
	-- NB. 'string' range is (1 to X), not (X-1 downto 0)
	-- HT = Horizontal Tab
	-- LF = Line Feed
	-- CR = Carriage Return
	-- ESC = Escape
	constant CSI:   string := ESC & "[";
	constant RESET: string := CSI & "0m";
	constant RED:   string := CSI & "31m";
	constant GREEN: string := CSI & "32m";
	constant NL:    string := CR & LF;
	constant test_string: string := "Hello!" & HT & "World!" & RED & NL & "How are you?" & RESET & NL ;
	shared variable test_vector: ulogic_string(test_string'range) := to_std_ulogic_vector(test_string);
	shared variable index: integer := 1; -- starts at '1' due to string range
 
	constant g_cs25MHz: common_generics := (clock_frequency => 25_000_000, asynchronous_reset => g.asynchronous_reset, delay => g.delay);
begin
	cs: entity work.clock_source_tb
		generic map(g => g, hold_rst => 2)
		port map(stop => stop, clk => clk, rst => rst);
 
	cs25MHz: entity work.clock_source_tb
		generic map(g => g_cs25MHz, hold_rst => 2)
		port map(stop => stop, clk => clk25MHz, rst => rst25MHz);
 
 
	uut: work.vga_pkg.vt100
	generic map(g => g)
	port map(
		clk      => clk,
		clk25MHz => clk25MHz,
		rst      => rst,
		we       => we,
		char     => char,
		busy     => busy,
		o_vga    => physical);
 
	stimulus_process: process
	begin
		char <= test_vector(index);
		we <= '0';
		wait for clock_period * 20;
 
		for i in test_vector'range loop
			we <= '1';
			char <= test_vector(index);
			wait for clock_period;
			we <= '0';
			wait for clock_period;
 
			while busy = '1' loop
				wait until busy = '0';
				wait for clock_period;
			end loop;
 
			-- wait for clock_period * 20;
			-- wait until busy = '0';
			-- report integer'image(index);
			if index < (test_vector'high - 1) then
				index := index + 1;
			else
				index := 1;
			end if;
		end loop;
 
		stop <= '1';
		wait;
	end process;
end architecture;
 
----- VGA Test Bench ----------------------------------------------------------
 
----- ATOI --------------------------------------------------------------------
-- The purpose of this module is to read in numeric characters ('0' through
-- '9') and convert the string into a binary number ('n_o'). On the first non-
-- numeric character the module stops and outputs that non-numeric character
-- as well as the converted number string. The module waits in the FINISHED
-- state until the module is reset by an external signal ('init').
--
-- The module is named after the C function, 'atoi', for converting a string
-- into an integer.
--
 
library ieee,work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.vga_pkg.all;
use work.util.common_generics;
 
entity atoi is
	generic(g: common_generics; N: positive := 16);
	port(
		clk:    in  std_ulogic;
		rst:    in  std_ulogic;
		we:     in  std_ulogic;
		init:   in  std_ulogic;
		char:   in  std_ulogic_vector(7 downto 0);
		char_o: out std_ulogic_vector(7 downto 0);
		done_o: out std_ulogic;
		-- ready:  out std_ulogic;
		n_o:    out unsigned(N - 1 downto 0));
end entity;
 
architecture rlt of atoi is
	type state_type is (RESET, WAITING, COMMAND, ACCUMULATE, WRITE, FINISHED);
	signal state_c, state_n: state_type   := RESET;
	signal c_c, c_n: unsigned(char'range) := (others => '0');
	signal n_c, n_n: unsigned(n_o'range)  := (others => '0');
	signal f_c, f_n: boolean              := true;
begin
	char_o <= std_ulogic_vector(c_c);
	n_o    <= n_c;
	-- ready  <= '1' when state_c = WAITING else '0';
 
	process(clk, rst)
		variable akk: unsigned((2 * N) - 1 downto 0) := (others => '0');
	begin
		if rst = '1' and g.asynchronous_reset then
			state_n   <= RESET;
		elsif rising_edge(clk) then
			if rst = '1' and not g.asynchronous_reset then
				state_n <= RESET;
			else
				state_c <= state_n;
				c_c     <= c_n;
				n_c     <= n_n;
				f_c     <= f_n;
				done_o  <= '0';
 
				if state_c = RESET then
					c_n     <= (others => '0');
					n_n     <= (others => '0');
					f_n     <= true;
					state_n <= WAITING;
				elsif state_c = WAITING then
					if we = '1' then
						c_n     <= unsigned(char);
						state_n <= COMMAND;
					end if;
				elsif state_c = COMMAND then
					state_n <= ACCUMULATE;
					case c_c is
					when x"30"  =>
					when x"31"  =>
					when x"32"  =>
					when x"33"  =>
					when x"34"  =>
					when x"35"  =>
					when x"36"  =>
					when x"37"  =>
					when x"38"  =>
					when x"39"  =>
					when others =>
						state_n <= WRITE;
					end case;
				elsif state_c = ACCUMULATE then
					if f_c then
						f_n <= false;
						n_n <= n_c + (c_c - x"30");
					else
						akk := n_c * to_unsigned(10, N);
						n_n <= akk(N - 1 downto 0) + (c_c - x"30");
					end if;
					state_n <= WAITING;
				elsif state_c = WRITE then
					done_o  <= '1';
					state_n <= FINISHED;
				elsif state_c = FINISHED then
					null; -- wait for a reset
				else
					state_n <= RESET;
					report "Invalid State" severity failure;
				end if;
 
				if init = '1' then
					assert state_c = FINISHED report "Lost Conversion" severity error;
					state_n <= RESET;
				end if;
			end if;
		end if;
	end process;
 
end architecture;
----- ATOI --------------------------------------------------------------------
 
----- VT100 Terminal Emulator -------------------------------------------------
-- This module contains the VGA module and wraps it in a terminal emulator,
-- based on the VT100 <https://en.wikipedia.org/wiki/VT100>, it only implements
-- a subset of the commands supplied by the VT100. This simplifies the usage
-- of the VGA text mode display, other VHDL components only have to write bytes
-- and do not have to worry about cursor position or implementing new lines,
-- tabs, and other very basic features.
--
-- The interface is designed to act like a UART, simply write a byte to it
-- and so long as the interface is not busy, it will be written to the screen
-- (or interpreter as part of a command sequence).
 
library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.vga_pkg.all;
use work.util.common_generics;
 
entity vt100 is
	generic(g: common_generics);
	port(
		clk:        in  std_ulogic;
		clk25MHz:   in  std_ulogic;
		rst:        in  std_ulogic;
		we:         in  std_ulogic;
		char:       in  std_ulogic_vector(7 downto 0);
 
		busy:       out std_ulogic;
		o_vga:      out vga_physical_interface);
end entity;
 
-- A better way of structuring this would be to process numbers in parallel
-- with different components, one processing potential attributes, one holding
-- one to two numbers - the results are then used. This would deal with runs
-- of attributes, which is allowed.
architecture rtl of vt100 is
	constant width:  positive := 80;
	constant height: positive := 40;
	constant number: positive := 8;
 
	type state_type is (RESET, ACCEPT, NORMAL, WRAP, LIMIT, CSI, COMMAND,
	NUMBER1, NUMBER2, COMMAND1, COMMAND2, WRITE, ERASING, ATTRIB, ADVANCE);
	signal state_c, state_n: state_type := RESET;
 
	constant tab:          unsigned(char'range) := x"09";
	constant backspace:    unsigned(char'range) := x"08";
	constant ascii_bell:   unsigned(char'range) := x"07";
	constant lf:           unsigned(char'range) := x"0a";
	constant cr:           unsigned(char'range) := x"0d";
	constant esc:          unsigned(char'range) := x"1b";
	constant blank:        unsigned(char'range) := x"20";
	constant asterisk:     unsigned(char'range) := x"2A";
	constant ascii_7:      unsigned(char'range) := x"37"; -- '7'
	constant ascii_8:      unsigned(char'range) := x"38"; -- '8'
	constant lsqb:         unsigned(char'range) := x"5b"; -- '['
	constant ascii_c:      unsigned(char'range) := x"63"; -- 'c'
	constant attr_default: unsigned(7 downto 0) := "00111000";
	constant ctl_default:  unsigned(4 downto 0) := "01111";
 
	signal addr:           std_ulogic_vector(12 downto 0) := (others => '0');
	signal data_we:        std_ulogic                     := '0';
	signal x:              std_ulogic_vector(6 downto 0)  := (others => '0');
	signal y:              std_ulogic_vector(5 downto 0)  := (others => '0');
	signal cursor_we:      std_ulogic                     := '0';
 
	signal x_n, x_c:       unsigned(x'range)    := (others => '0');
	signal y_n, y_c:       unsigned(y'range)    := (others => '0');
	signal c_n, c_c:       unsigned(char'range) := (others => '0');
 
	signal attr_c, attr_n: unsigned(attr_default'range) := attr_default;
	signal ctl_c, ctl_n:   unsigned(ctl_default'range)  := ctl_default;
 
	signal n1_n, n1_c:     unsigned(7 downto 0) := (others => '0');
	signal n2_n, n2_c:     unsigned(6 downto 0) := (others => '0');
 
	signal conceal_n, conceal_c: boolean := false;
 
	signal x_minus_one:         unsigned(x'range) := (others => '0');
	signal x_minus_one_limited: unsigned(x'range) := (others => '0');
	signal x_underflow:         boolean           := false;
	signal x_plus_one:          unsigned(x'range) := (others => '0');
	signal x_plus_one_limited:  unsigned(x'range) := (others => '0');
	signal x_overflow:          boolean           := false;
 
	signal y_minus_one:         unsigned(y'range) := (others => '0');
	signal y_minus_one_limited: unsigned(y'range) := (others => '0');
	signal y_underflow:         boolean           := false;
	signal y_plus_one:          unsigned(y'range) := (others => '0');
	signal y_plus_one_limited:  unsigned(y'range) := (others => '0');
	signal y_overflow:          boolean           := false;
 
	signal count_c, count_n:    unsigned(addr'range) := (others => '0');
	signal limit_c, limit_n:    unsigned(addr'high - 3 downto 0) := (others => '0');
 
	signal akk_done_o:  std_ulogic := '0';
	-- signal akk_ready_o: std_ulogic := '0';
	signal akk_init:    std_ulogic := '0';
	signal n_o:         unsigned(number - 1 downto 0) := (others => '0');
	signal akk_char_o:  std_ulogic_vector(char'range) := (others => '0');
 
	signal font_sel_c, font_sel_n: std_ulogic_vector(0 downto 0) := (others => '0');
 
	signal saved_x_n, saved_x_c:       unsigned(x'range)    := (others => '0');
	signal saved_y_n, saved_y_c:       unsigned(y'range)    := (others => '0');
	signal saved_attr_n, saved_attr_c: unsigned(attr_default'range) := (others => '0');
 
	signal reverse_video_c, reverse_video_n: boolean := false;
	signal base_n, base_c: unsigned(addr'high downto 4) := (others => '0');
	signal addr_sel:       unsigned(addr'range) := (others => '0');
 
	signal saved_base_n, saved_base_c: unsigned(base_c'range) := (others => '0');
	signal is_base_saved_n, is_base_saved_c: boolean := false;
 
begin
	accumulator_0: work.vga_pkg.atoi
		generic map(g => g, N => number)
		port map(
			clk    => clk,
			rst    => rst,
			we     => we,
			init   => akk_init,
			char   => char,
			char_o => akk_char_o,
			done_o => akk_done_o,
			-- ready  => akk_ready_o,
			n_o    => n_o);
 
	address: block
		signal mul: unsigned(15 downto 0)     := (others => '0');
		signal addr_int: unsigned(addr'range) := (others => '0');
	begin
		mul      <= to_unsigned(to_integer(y_c) * width, mul'length);
		addr_int <= mul(addr_int'range) + ("000000" & x_c);
		addr_sel <= addr_int when state_c /= ERASING else count_c;
		addr     <= std_ulogic_vector(addr_sel + (base_c & "0000"));
	end block;
 
	x_minus_one         <= x_c - 1;
	x_plus_one          <= x_c + 1;
	x_overflow          <= x_c         >  (width  - 1);
	x_underflow         <= x_minus_one >= (width  - 1);
	x_minus_one_limited <= (others => '0') when x_underflow else x_minus_one;
	x_plus_one_limited  <= to_unsigned(width - 1, x_c'length) when x_overflow else x_plus_one;
 
	y_plus_one          <= y_c + 1;
	y_minus_one         <= y_c - 1;
	y_overflow          <= y_c         >= (height - 1); -- NB. > for 1 more row, slightly off edge of screen
	y_underflow         <= y_minus_one >  (height - 1);
	y_minus_one_limited <= (others => '0') when y_underflow else y_minus_one;
	y_plus_one_limited  <= to_unsigned(height - 1, y_c'length) when y_overflow else y_plus_one;
 
	busy <= '1' when state_c = ERASING
			or state_c = WRITE
			or state_c = RESET
			or state_c = WRAP
			or state_c = ATTRIB
			or state_c = ADVANCE
			else '0';
 
	vga_blk: block
		signal vga_din:    std_ulogic_vector(15 downto 0)     := (others => '0');
		signal vga_ctr_we: vga_control_registers_we_interface := vga_control_registers_we_initialize;
		signal vga_ctr:    vga_control_registers_interface    := vga_control_registers_initialize;
		signal attr:       unsigned(attr_c'range)             := attr_default;
		signal ch:         std_ulogic_vector(c_c'range)       := (others => '0');
	begin
		ch             <= std_ulogic_vector(asterisk) when conceal_c else std_ulogic_vector(c_c);
		attr           <= attr_c when state_c /= ERASING else attr_default;
		vga_din        <= std_ulogic_vector(attr) & ch;
		vga_ctr.crx    <= std_ulogic_vector(x_plus_one); -- not limited, goes off screen edge
		vga_ctr.cry    <= std_ulogic_vector(y_c);
		vga_ctr.ctl    <= std_ulogic_vector(ctl_c);
		vga_ctr_we.crx <= cursor_we;
		vga_ctr_we.cry <= cursor_we;
		vga_ctr_we.ctl <= cursor_we;
 
		vga_0: work.vga_pkg.vga_top
		generic map(g => g)
		port map(
			clk               =>  clk,
			clk25MHz          =>  clk25MHz,
			rst               =>  rst,
			vga_we_ram        =>  data_we,
			vga_din           =>  vga_din,
			vga_addr          =>  addr,
			base(base_c'range)=>  std_ulogic_vector(base_c),
			base(3 downto 0)  =>  "0000",
			i_font_sel        =>  font_sel_c,
			i_vga_control_we  =>  vga_ctr_we,
			i_vga_control     =>  vga_ctr,
			o_vga             =>  o_vga);
	end block;
 
	-- Subset of commands implemented:
	-- ED  - Erase Display, CSI n 'J'
	-- RIS - Erase Display, ESC 'c'
	-- SGR - Select Graphic Rendition - for colors, CSI n 'm'
	-- HVP - Horizontal and Vertical Position - CSI n ; m 'f'
	-- The cursor commands are also supported: CUU, CUD, CUF,
	-- CUB, CNL, CPL and CHA
	fsm: process(clk, rst)
		variable limit_value: unsigned(addr'range) := (others => '0');
		variable repeat:      boolean    := false;
		variable exit_repeat: state_type := RESET;
		procedure reverse_video(a: unsigned(2 downto 0); foreground: boolean) is
		begin
			if foreground then
				if reverse_video_c then
					attr_n(2 downto 0) <= a;
				else
					attr_n(5 downto 3) <= a;
				end if;
			else
				if reverse_video_c then
					attr_n(5 downto 3) <= a;
				else
					attr_n(2 downto 0) <= a;
				end if;
			end if;
		end procedure;
	begin
		if rst = '1' and g.asynchronous_reset then
			state_c <= RESET;
		elsif rising_edge(clk) then
			if rst = '1' and not g.asynchronous_reset then
				state_c <= RESET;
			else
				x_c             <= x_n;
				y_c             <= y_n;
				c_c             <= c_n;
				count_c         <= count_n;
				limit_c         <= limit_n;
				state_c         <= state_n;
				n1_c            <= n1_n;
				n2_c            <= n2_n;
				data_we         <= '0';
				cursor_we       <= '0';
				akk_init        <= '0';
				attr_c          <= attr_n;
				ctl_c           <= ctl_n;
				conceal_c       <= conceal_n;
				font_sel_c      <= font_sel_n;
				saved_x_c       <= saved_x_n;
				saved_y_c       <= saved_y_n;
				saved_attr_c    <= saved_attr_n;
				reverse_video_c <= reverse_video_n;
				base_c          <= base_n;
				saved_base_c    <= saved_base_n;
				is_base_saved_c <= is_base_saved_n;
 
				if state_c = RESET then
					n1_n         <= (others => '0');
					n2_n         <= (others => '0');
					x_n          <= (others => '0');
					y_n          <= (others => '0');
					c_n          <= (others => '0');
					count_n      <= (others => '0');
					limit_n      <= (others => '0');
					saved_x_n    <= (others => '0');
					saved_y_n    <= (others => '0');
					saved_attr_n <= (others => '0');
					font_sel_n   <= (others => '0');
					state_n      <= ACCEPT;
					attr_n       <= attr_default;
					ctl_n        <= ctl_default;
					conceal_n    <= false;
					reverse_video_n <= false;
					base_n       <= (others => '0');
					is_base_saved_n <= false;
					saved_base_n <= (others => '0');
				elsif state_c = ACCEPT then
					if we = '1' then
						c_n     <= unsigned(char);
						state_n <= NORMAL;
					end if;
					-- This behavior does not really mix well
					-- with the eForth interpreter.
					--
					-- if is_base_saved_c then
					--	is_base_saved_n <= false;
					--	base_n          <= saved_base_c;
					-- end if;
				elsif state_c = NORMAL then
					case c_c is
					when tab =>
						x_n     <= (x_c and "1111000") + 8;
						state_n <= ERASING;
						c_n     <= blank;
						limit_value := unsigned(addr and "1111111111000") + 8;
						limit_n <= limit_value(limit_n'high + 3 downto limit_n'low + 3);
						count_n <= unsigned(addr);
					when ascii_bell =>
						ctl_n(4) <= not ctl_c(4); -- ctr_n(4) goes to edge triggered logic
						state_n  <= ACCEPT;
					when cr =>
						y_n     <= y_plus_one;
						state_n <= WRAP;
					when lf =>
						x_n     <= (others => '0');
						state_n <= WRITE;
					when backspace =>
						x_n     <= x_minus_one_limited;
						state_n <= WRITE;
					when esc =>
						state_n <= CSI;
					when others =>
						data_we <= '1';
						state_n <= ADVANCE;
					end case;
				elsif state_c = ADVANCE then
					x_n     <= x_plus_one;
					state_n <= WRAP;
				elsif state_c = CSI then
					if we = '1' then
						c_n     <= unsigned(char);
						state_n <= COMMAND;
					end if;
				elsif state_c = COMMAND then
					case c_c is
					when ascii_c =>
						x_n     <= (others => '0');
						y_n     <= (others => '0');
						c_n     <= blank;
						count_n <= (others => '0');
						limit_n <= "1000000000";
						state_n <= ERASING;
						base_n  <= (others => '0');
					when lsqb =>
						state_n  <= NUMBER1;
						akk_init <= '1';
 
					when ascii_7 => -- 'ESC 7'; Save Cursor and Attributes
						saved_x_n    <= x_c;
						saved_y_n    <= y_c;
						saved_attr_n <= attr_c;
						state_n      <= ACCEPT;
					when ascii_8 => -- 'ESC 8'; Restore Cursor and Attributes
						x_n          <= saved_x_c;
						y_n          <= saved_y_c;
						attr_n       <= saved_attr_c;
						state_n      <= ACCEPT;
					when others => -- Error
						state_n <= ACCEPT;
					end case;
				elsif state_c = NUMBER1 then
					if akk_done_o = '1' then
						state_n <= COMMAND1;
						n1_n    <= n_o(n1_n'range);
					end if;
				elsif state_c = COMMAND1 then
					repeat := false;
					case akk_char_o is
					when x"41" => -- CSI n 'A' : CUU Cursor up
						y_n         <= y_minus_one_limited;
						exit_repeat := WRITE;
						repeat      := true;
					when x"42" => -- CSI n 'B' : CUD Cursor Down
						y_n         <= y_plus_one_limited;
						exit_repeat := LIMIT;
						repeat      := true;
					when x"43" => -- CSI n 'C' : CUF Cursor Forward
						x_n         <= x_plus_one_limited;
						exit_repeat := LIMIT;
						repeat      := true;
					when x"44" => -- CSI n 'D' : CUB Cursor Back
						x_n         <= x_minus_one_limited;
						exit_repeat := WRITE;
						repeat      := true;
					when x"45" => -- CSI n 'E'
						y_n         <= y_minus_one_limited;
						x_n         <= (others => '0');
						exit_repeat := WRITE;
						repeat      := true;
					when x"46" => -- CSI n 'F'
						y_n         <= y_plus_one_limited;
						x_n         <= (others => '0');
						exit_repeat := LIMIT;
						repeat      := true;
					when x"47" => -- CSI n 'G' : CHA Cursor Horizontal Absolute
						x_n      <= n1_c(x_n'range);
						state_n  <= LIMIT;
					when x"4a" => -- CSI n 'J'
						x_n       <= (others => '0');
						y_n       <= (others => '0');
						base_n    <= (others => '0');
						cursor_we <= '1';
						state_n   <= ERASING;
						c_n       <= blank;
						count_n   <= (others => '0');
						limit_n   <= "1000000000";
					when x"3b" => -- ESC n ';' ...
						state_n <= NUMBER2;
						akk_init <= '1';
					when x"6d" => -- CSI n 'm' : SGR
						state_n <= ATTRIB;
 
					-- NB. Number parameter does nothing.
					when x"53" => -- CSI n 'S' : scroll up
						saved_base_n <= base_c;
						is_base_saved_n <= true;
						base_n   <= (others => '0');
						state_n  <= WRITE;
					when x"54" => -- CSI n 'T' : scroll down
						state_n  <= WRITE;
						if is_base_saved_c then
							base_n <= saved_base_c;
							is_base_saved_n <= false;
						end if;
					when x"73" => -- CSI 's': SCP (Secure, Contain, Protect the Cursor Position)
						saved_x_n    <= x_c;
						saved_y_n    <= y_c;
						state_n      <= ACCEPT;
					when x"75" => -- CSI 'u': RCP Restore Cursor Position
						x_n          <= saved_x_c;
						y_n          <= saved_y_c;
						state_n      <= ACCEPT;
 
					-- This is an extension, it is for setting the
					-- control lines of the VGA module directly.
					when x"78" => -- ESC n 'x' : Set VGA control registers directly
						ctl_n    <= n1_c(ctl_n'range);
						state_n  <= WRITE;
					when others => -- Error
						state_n <= ACCEPT;
					end case;
 
					if repeat then
						if n1_c <= 1 then
							state_n <= exit_repeat;
						else
							n1_n <= n1_c - 1;
						end if;
					end if;
				elsif state_c = NUMBER2 then
					if akk_done_o = '1' then
						state_n <= COMMAND2;
						n2_n    <= n_o(n2_n'range);
					end if;
				elsif state_c = COMMAND2 then
					case akk_char_o is
					when x"66" => -- f
						y_n       <= n1_c(y_n'range) - 1;
						x_n       <= n2_c(x_n'range) - 1;
						cursor_we <= '1';
						state_n   <= LIMIT;
					when x"48" => -- H
						y_n       <= n1_c(y_n'range) - 1;
						x_n       <= n2_c(x_n'range) - 1;
						cursor_we <= '1';
						state_n   <= LIMIT;
					when x"6d" => -- ESC n ';' m 'm'
						state_n <= ATTRIB;
					when others =>
						state_n <= ACCEPT;
					end case;
				elsif state_c = WRAP then
					if x_overflow then
						x_n <= (others => '0');
						y_n <= y_plus_one;
					elsif y_overflow then
						x_n     <= (others => '0');
						y_n     <= y_minus_one;
						state_n <= ERASING;
						c_n     <= blank;
						count_n <= unsigned(addr_sel);
						limit_value := unsigned(addr_sel) + (3*width);
						limit_n <= limit_value(limit_n'high + 3 downto limit_n'low + 3);
						base_n  <= base_c + (width / 16);
					else
						state_n <= WRITE;
					end if;
				elsif state_c = LIMIT then
					if x_overflow then
						x_n <= to_unsigned(width - 1, x_n'high + 1);
					end if;
					if y_overflow then
						y_n <= to_unsigned(height - 1, y_n'high + 1);
					end if;
					state_n <= WRITE;
				elsif state_c = WRITE then
					state_n   <= ACCEPT;
					cursor_we <= '1';
				elsif state_c = ERASING then
					if count_c(limit_c'high + 3 downto limit_c'low + 3) /= limit_c then
						count_n <= count_c + 1;
						data_we <= '1';
					else
						state_n <= WRAP;
					end if;
				elsif state_c = ATTRIB then
					case n1_c is
					when x"00"  =>
						attr_n          <= attr_default;
						conceal_n       <= false;
						reverse_video_n <= false;
					when x"01"  => attr_n(6) <= '1'; -- bold
					-- when x"02"  => -- faint
					when x"16"  => attr_n(6) <= '0'; -- normal brightness
					when x"05"  => attr_n(7) <= '1'; -- slow blink
					when x"19"  => attr_n(7) <= '0'; -- blink off
					when x"07"  =>
						if not reverse_video_c then
							attr_n    <= attr_c(7 downto 6) & attr_c(2 downto 0) & attr_c(5 downto 3);
						end if;
						reverse_video_n <= true;
					when x"1B" =>
						if reverse_video_c then
							attr_n    <= attr_c(7 downto 6) & attr_c(2 downto 0) & attr_c(5 downto 3);
						end if;
						reverse_video_n <= false;
					when x"08"  => conceal_n <= true;
					when x"1C"  => conceal_n <= false;
 
					when x"0A"  => font_sel_n <= (others => '0');
					when x"0B"  => font_sel_n <= "1";
 
					when x"1E"  => reverse_video("000", true); -- 30
					when x"1F"  => reverse_video("001", true);
					when x"20"  => reverse_video("010", true);
					when x"21"  => reverse_video("011", true);
					when x"22"  => reverse_video("100", true);
					when x"23"  => reverse_video("101", true);
					when x"24"  => reverse_video("110", true);
					when x"25"  => reverse_video("111", true);
 
					when x"28"  => reverse_video("000", false); -- 40
					when x"29"  => reverse_video("001", false);
					when x"2A"  => reverse_video("010", false);
					when x"2B"  => reverse_video("011", false);
					when x"2C"  => reverse_video("100", false);
					when x"2D"  => reverse_video("101", false);
					when x"2E"  => reverse_video("110", false);
					when x"2F"  => reverse_video("111", false);
 
					when others =>
					end case;
					state_n <= ACCEPT;
				else
					state_n <= RESET;
					report "Invalid State" severity failure;
				end if;
			end if;
		end if;
	end process;
end architecture;
----- VT100 Terminal Emulator -------------------------------------------------
 
----- VGA Top Level Component -------------------------------------------------
library ieee,work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.vga_pkg.all;
use work.util.file_format;
use work.util.file_hex;
use work.util.file_binary;
use work.util.common_generics;
 
entity vga_top is
	generic(g: common_generics);
	port(
		clk:              in  std_ulogic;
		clk25MHz:         in  std_ulogic;
		rst:              in  std_ulogic;
 
		-- VGA Text buffer interface
		vga_we_ram:       in  std_ulogic; -- Write enable RAM
		vga_din:          in  std_ulogic_vector(15 downto 0);
		vga_addr:         in  std_ulogic_vector(12 downto 0);
		base:             in  std_ulogic_vector(12 downto 0);
 
		-- VGA control registers
		i_font_sel:       in std_ulogic_vector(0 downto 0);
		i_vga_control_we: in vga_control_registers_we_interface;
		i_vga_control:    in vga_control_registers_interface;
 
		o_vga:            out vga_physical_interface);
end;
 
architecture behav of vga_top is
	-- Setup for text buffer memory
	constant text_addr_length: positive    := 13;
	constant text_data_length: positive    := 16;
	constant text_file_name:   string      := "text.hex";
	constant text_file_type:   file_format := FILE_HEX;
 
	-- Setup for font buffer memory
	constant font_addr_length: positive    := 13;
	constant font_data_length: positive    := 8;
	constant font_file_name:   string      := "font.bin";
	constant font_file_type:   file_format := FILE_BINARY;
 
	-- Internal signals for mapping output <--> VGA module
	signal  foreground_draw_internal:      std_ulogic := '0';
 
	-- Text RAM signals, RAM <--> VGA module
	signal  text_dout:       std_ulogic_vector(15 downto 0) := (others => '0');
	signal  text_din:        std_ulogic_vector(15 downto 0) := (others => '0');
	signal  text_addr:       std_ulogic_vector(11 downto 0) := (others => '0');
	signal  text_addr_full:  std_ulogic_vector(12 downto 0) := (others => '0');
 
	-- Font ROM signals, ROM<-->VGA module
	signal  font_addr:       std_ulogic_vector(12 downto 0) := (others => '0');
	signal  font_dout:       std_ulogic_vector( 7 downto 0) := (others => '0');
 
	signal  control_c, control_n: vga_control_registers_interface := vga_control_registers_initialize;
 
	signal  foreground_draw: std_ulogic := '0';
	signal  background_draw: std_ulogic := '0';
begin
 
	vga_ns: process(clk, rst)
	begin
		if rst = '1' and g.asynchronous_reset then
			control_c   <= vga_control_registers_initialize;
		elsif rising_edge(clk) then
			if rst = '1' and not g.asynchronous_reset then
				control_c <= vga_control_registers_initialize;
			else
				control_c <= control_n;
			end if;
		end if;
	end process;
 
	vga_creg_we: process(
		control_c,
		i_vga_control,
		i_vga_control_we)
	begin
		control_n <= control_c;
 
		if i_vga_control_we.crx = '1' then control_n.crx <= i_vga_control.crx; end if;
		if i_vga_control_we.cry = '1' then control_n.cry <= i_vga_control.cry; end if;
		if i_vga_control_we.ctl = '1' then control_n.ctl <= i_vga_control.ctl; end if;
	end process;
 
	u_vga: work.vga_pkg.vga_core
		generic map(g => g)
		port map (
		rst       => rst,
		clk25MHz  => clk25MHz,
 
		text_a    => text_addr,
		text_d    => text_dout,
 
		font_a    => font_addr,
		font_d    => font_dout,
 
		font_sel  => i_font_sel,
 
		ocrx      => control_c.crx,
		ocry      => control_c.cry,
		octl      => control_c.ctl,
 
		o_vga     => o_vga);
 
	text_addr_full <= std_ulogic_vector(unsigned(base) + unsigned(text_addr));
 
	u_text_memory: entity work.dual_port_block_ram -- holds at least 80x40 characters
	generic map(g => g,
		addr_length => text_addr_length,
		data_length => text_data_length,
		file_name   => text_file_name,
		file_type   => text_file_type)
	port map (
		a_clk   => clk,
		-- External interface
		a_dwe   => vga_we_ram,
		a_dre   => '1',
		a_addr  => vga_addr,
		a_din   => vga_din,
		a_dout  => open,
		-- Internal interface
		b_clk   => clk25MHz,
		b_dwe   => '0',
		b_dre   => '1',
		b_addr  => text_addr_full,
		b_din   => (others => '0'),
		b_dout  => text_dout);
 
	u_font_memory: entity work.single_port_block_ram
	generic map(g => g,
		addr_length => font_addr_length,
		data_length => font_data_length,
		file_name   => font_file_name,
		file_type   => font_file_type)
	port map (
		clk  => clk25MHz,
		dwe  => '0',
		dre  => '1',
		addr => font_addr,
		din  => (others => '0'),
		dout => font_dout);
 
end architecture;
 
----- VGA Top Level Component -------------------------------------------------
 
----- VGA Core ----------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.vga_pkg.all;
use work.util.common_generics;
 
entity vga_core is
	generic(g: common_generics);
	port (
		rst:      in  std_ulogic;
		clk25MHz: in  std_ulogic;
		text_a:   out std_ulogic_vector(11 downto 0); -- text buffer
		text_d:   in  std_ulogic_vector(15 downto 0);
		font_a:   out std_ulogic_vector(12 downto 0); -- font buffer
		font_d:   in  std_ulogic_vector( 7 downto 0);
		font_sel: in  std_ulogic_vector(0 downto 0);
		--
		ocrx:     in  std_ulogic_vector(6 downto 0);
		ocry:     in  std_ulogic_vector(5 downto 0);
		octl:     in  std_ulogic_vector(4 downto 0);
		--
		o_vga:    out vga_physical_interface);
end entity;
 
architecture rtl of vga_core is
	signal foreground_draw_int, background_draw_int: std_ulogic := '0';
	signal hsync_int: std_ulogic := '1';
	signal vsync_int: std_ulogic := '1';
 
	signal blank: std_ulogic := '0';
	signal hctr:  integer range 793 downto 0 := 0;
	signal vctr:  integer range 524 downto 0 := 0;
 
	-- character/pixel position on the screen
	signal scry_text:  integer range 39 downto 0 := 0; -- chr row   < 40 (6 bits)
	signal scrx_text:  integer range 79 downto 0 := 0; -- chr col   < 80 (7 bits)
	signal chry:  integer range 11 downto 0 := 0; -- chr hight < 12 (4 bits)
	signal chrx:  integer range 7  downto 0 := 0; -- chr width < 08 (3 bits)
 
	signal losr_ce: std_ulogic := '0';
	signal losr_ld: std_ulogic := '0';
	signal losr_do: std_ulogic := '0';
	signal y:       std_ulogic := '0';  -- character luminance pixel value (0 or 1)
 
	-- control io register
	signal bell:      std_ulogic := '0';
	signal vga_en:    std_ulogic := '0';
	signal cur_en:    std_ulogic := '0';
	signal cur_mode:  std_ulogic := '0';
	signal cur_blink: std_ulogic := '0';
 
	signal background_draw, foreground_draw: std_ulogic := '0';
	signal attr:          std_ulogic_vector(7 downto 0) := (others =>'0');
	signal attr_we_delay: std_ulogic := '0';
	signal slowclk, slowclk_cr: std_ulogic := '0';
 
	signal bell_c, bell_n: std_ulogic := '0';
	signal bell_on_c, bell_on_n: std_ulogic := '0';
begin
	-- Control register. Individual control signal
	bell_n    <= octl(4);
	bell      <= bell_c xor bell_n;
	vga_en    <= octl(3);
	cur_en    <= octl(2);
	cur_blink <= octl(1);
	cur_mode  <= octl(0);
 
	-- bell register
	process (rst, clk25MHz)
	begin
		if rst = '1' and g.asynchronous_reset then
			bell_c    <= '0';
			bell_on_c <= '0';
		elsif rising_edge(clk25MHz) then
			if rst = '1' and not g.asynchronous_reset then
				bell_c    <= '0';
				bell_on_c <= '0';
			else
				bell_c    <= bell_n;
				bell_on_c <= bell_on_n;
			end if;
		end if;
	end process;
 
	process (bell_on_c, slowclk, bell)
	begin
		bell_on_n <= bell_on_c;
		slowclk_cr <= '0';
		if bell = '1' then
			bell_on_n  <= '1';
			slowclk_cr <= '1';
		elsif slowclk = '1' then
			bell_on_n <= '0';
		end if;
	end process;
 
	-- hsync generator, initialized with '1'
	process (rst, clk25MHz)
	begin
		if rst = '1' and g.asynchronous_reset then
			hsync_int <= '1';
		elsif rising_edge(clk25MHz) then
			if rst = '1' and not g.asynchronous_reset then
				hsync_int <= '1';
			else
				if (hctr > 663) and (hctr < 757) then
					hsync_int <= '0';
				else
					hsync_int <= '1';
				end if;
			end if;
		end if;
	end process;
 
	-- vsync generator, initialized with '1'
	process (rst, clk25MHz)
	begin
		if rst = '1' and g.asynchronous_reset then
			vsync_int <= '1';
		elsif rising_edge(clk25MHz) then
			if rst = '1' and not g.asynchronous_reset then
				vsync_int <= '1';
			else
				if (vctr > 499) and (vctr < 502) then
					vsync_int <= '0';
				else
					vsync_int <= '1';
				end if;
			end if;
		end if;
	end process;
 
	-- Blank signal, 0 = no draw, 1 = visible/draw zone
 
	-- Proboscide99 31/08/08
	blank <= '0' when (hctr < 8) or (hctr > 647) or (vctr > 479) else '1';
 
	-- flip-flops for sync of R, G y B signal, initialized with '0'
	process (rst, clk25MHz)
	begin
		if rst = '1' and g.asynchronous_reset then
			foreground_draw <= '0';
		elsif rising_edge(clk25MHz) then
			if rst = '1' and not g.asynchronous_reset then
				foreground_draw <= '0';
			else
				foreground_draw <= foreground_draw_int;
				background_draw <= background_draw_int;
			end if;
		end if;
	end process;
 
	-- counters, hctr, vctr, srcx, srcy, chrx, chry
	counters: block
		signal hctr_ce: std_ulogic := '0';
		signal hctr_rs: std_ulogic := '0';
		signal vctr_ce: std_ulogic := '0';
		signal vctr_rs: std_ulogic := '0';
 
		signal chrx_ce: std_ulogic := '0';
		signal chrx_rs: std_ulogic := '0';
		signal chry_ce: std_ulogic := '0';
		signal chry_rs: std_ulogic := '0';
		signal scrx_ce: std_ulogic := '0';
		signal scrx_rs: std_ulogic := '0';
		signal scry_ce: std_ulogic := '0';
		signal scry_rs: std_ulogic := '0';
 
		signal hctr_639: std_ulogic := '0';
		signal vctr_479: std_ulogic := '0';
		signal chrx_007: std_ulogic := '0';
		signal chry_011: std_ulogic := '0';
 
		-- RAM read, ROM read
		signal ram_tmp: unsigned(11 downto 0) := (others => '0'); -- range 3199 downto 0
		signal mul:     unsigned(15 downto 0) := (others => '0');
		signal rom_tmp: unsigned(11 downto 0) := (others => '0'); -- range 3071 downto 0;
 
		signal text_d_tmp: std_ulogic_vector(7 downto 0) := (others => '0');
	begin
		u_hctr: work.vga_pkg.ctrm generic map (g => g, M => 794)
					port map (rst, clk25MHz, hctr_ce, hctr_rs, hctr);
		u_vctr: work.vga_pkg.ctrm generic map (g => g, M => 525)
					port map (rst, clk25MHz, vctr_ce, vctr_rs, vctr);
 
		hctr_ce <= '1';
		hctr_rs <= '1' when hctr = 793 else '0';
		vctr_ce <= '1' when hctr = 663 else '0';
		vctr_rs <= '1' when vctr = 524 else '0';
 
		u_chrx: work.vga_pkg.ctrm generic map (g => g, M => 8) 
					port map (rst, clk25MHz, chrx_ce, chrx_rs, chrx);
		u_chry: work.vga_pkg.ctrm generic map (g => g, M => 12)
					port map (rst, clk25MHz, chry_ce, chry_rs, chry);
		u_scrx: work.vga_pkg.ctrm generic map (g => g, M => 80)
					port map (rst, clk25MHz, scrx_ce, scrx_rs, scrx_text);
		u_scry: work.vga_pkg.ctrm generic map (g => g, M => 40)
					port map (rst, clk25MHz, scry_ce, scry_rs, scry_text);
 
		hctr_639 <= '1' when hctr = 639 else '0';
		vctr_479 <= '1' when vctr = 479 else '0';
		chrx_007 <= '1' when chrx = 7 else '0';
		chry_011 <= '1' when chry = 11 else '0';
 
		chrx_rs <= chrx_007 or hctr_639;
		chry_rs <= chry_011 or vctr_479;
		scrx_rs <= hctr_639;
		scry_rs <= vctr_479;
 
		chrx_ce <= '1' and blank;
		scrx_ce <= chrx_007;
		chry_ce <= hctr_639 and blank;
		scry_ce <= chry_011 and hctr_639;
 
		ram_tmp <=  (to_unsigned(scry_text, ram_tmp'length) sll 4) +
				(to_unsigned(scry_text, ram_tmp'length) sll 6) +
				to_unsigned(scrx_text, ram_tmp'length);
 
		text_d_tmp <= text_d(7 downto 0);
		text_a  <= std_ulogic_vector(ram_tmp);
		mul     <= unsigned(text_d_tmp) * 12;
		rom_tmp <= mul(rom_tmp'range) + chry;
		font_a  <= font_sel & std_ulogic_vector(rom_tmp);
	end block;
 
	color_block: block
		signal red_on:   std_ulogic := '0';
		signal green_on: std_ulogic := '0';
		signal blue_on:  std_ulogic := '0';
		signal bold:     std_ulogic := '0';
		signal reverse:  std_ulogic := '0';
		signal final:    std_ulogic_vector(2 downto 0) := "111";
	begin
		reverse     <= bell_on_c when attr(7) = '0' else slowclk;
		bold        <= attr(6);
		final       <= "100" when bold = '0' else "111";
 
		red_on      <= (reverse   xor attr(3)) when foreground_draw = '1' else
			       (bell_on_c xor attr(0)) when background_draw = '1' else '0';
		green_on    <= (reverse   xor attr(4)) when foreground_draw = '1' else
			       (bell_on_c xor attr(1)) when background_draw = '1' else '0';
		blue_on     <= (reverse   xor attr(5)) when foreground_draw = '1' else
			       (bell_on_c xor attr(2)) when background_draw = '1' else '0';
 
		o_vga.red   <= final             when red_on    = '1' else "000";
		o_vga.green <= final             when green_on  = '1' else "000";
		o_vga.blue  <= final(2 downto 1) when blue_on   = '1' else "00";
	end block;
 
	u_reg_delay: work.util.reg generic map (g => g, N => 1)
	port map(clk => clk25MHz, rst => rst, we => '1', di(0) => losr_ld, do(0) => attr_we_delay);
 
	u_reg_attr: work.util.reg generic map (g => g, N => 8)
	port map(clk => clk25MHz, rst => rst, we => attr_we_delay, di => text_d(15 downto 8), do => attr);
 
	u_losr: work.vga_pkg.losr generic map (g => g, N => font_d'length)
	port map (rst => rst, clk => clk25MHz, load => losr_ld, ce => losr_ce, do => losr_do, di => font_d);
 
	losr_ce <= blank;
	losr_ld <= '1' when (chrx = 7) else '0';
 
	-- video out, vga_en control signal enable/disable vga signal
	foreground_draw_int <=      y  and blank;
	background_draw_int <= (not y) and blank;
 
	o_vga.hsync <= hsync_int and vga_en;
	o_vga.vsync <= vsync_int and vga_en;
 
	-- Hardware Cursor
	hw_cursor: block
		signal small:   std_ulogic := '0';
		signal curen2:  std_ulogic := '0';
		signal curpos:  std_ulogic := '0';
		signal yint:    std_ulogic := '0';
		signal crx:     integer range 127 downto 0;
		signal cry:     integer range 64 downto 0;
		signal counter: unsigned(24 downto 0) := (others => '0');
		signal cursorclk: std_ulogic := '0';
	begin
		process (counter, slowclk_cr, clk25MHz)
		begin
			counter <= counter;
			if rising_edge(clk25MHz) then
				if slowclk_cr = '1' then
					counter <= (others => '0');
				else
					counter <= counter + 1;
				end if;
			end if;
		end process;
 
		cursorclk <= counter(22); -- 2.98Hz
		slowclk   <= counter(24); -- 0.745Hz
 
		crx <= to_integer(unsigned(ocrx(6 downto 0)));
		cry <= to_integer(unsigned(ocry(5 downto 0)));
 
		--
		curpos <= '1' when scry_text = cry and scrx_text = crx else '0';
		small  <= '1' when (chry > 8)                else '0';
		curen2 <= (cursorclk or (not cur_blink)) and cur_en;
		yint   <= '1' when cur_mode = '0'            else small;
		y      <= (yint and curpos and curen2) xor losr_do;
	end block;
end;
----- VGA Core ----------------------------------------------------------------
 
-------------------------------------------------------------------------------
--| @file ctrm.vhd
--| @brief Counter, asynchronous *and* synchronous reset, up only.
--|        (ctrm.vhd, original filename)
--| @author         Javier Valcarce García
--| @copyright      Copyright 2007 Javier Valcarce García
--| @license        LGPL version 3
--| @email          javier.valcarce@gmail.com
-------------------------------------------------------------------------------
library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.util.common_generics;
 
entity ctrm is
	generic (g: common_generics; M: positive := 8);
	port (
		rst: in  std_ulogic; -- asynchronous rst
		clk: in  std_ulogic;
		ce:  in  std_ulogic; -- enable counting
		rs:  in  std_ulogic; -- synchronous rst
		do:  out integer range (M-1) downto 0 := 0);
end entity;
 
architecture rtl of ctrm is
	signal c: integer range (M-1) downto 0:= 0;
begin
	do <= c;
	process(rst, clk)
	begin
		if rst = '1' and g.asynchronous_reset then
			c <= 0 after g.delay;
		elsif rising_edge(clk) then
			if rst = '1' and not g.asynchronous_reset then
				c <= 0 after g.delay;
			else
				if ce = '1' then
					if rs = '1' then
						c <= 0 after g.delay;
					else
					-- elsif c /= (M - 1) then
						c <= c + 1 after g.delay;
					end if;
				end if;
			end if;
		end if;
	end process;
end;
 
-------------------------------------------------------------------------------
--| @file util.vhd
--| @brief Shift register N-bit, asynchronous reset, synchronous load,
--|        and enable
--| @author         Javier Valcarce García
--| @copyright      Copyright 2007 Javier Valcarce García
--| @license        LGPL version 3
--| @email          javier.valcarce@gmail.com
-------------------------------------------------------------------------------
 
library ieee, work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.util.common_generics;
 
entity losr is
	generic (g: common_generics; N: positive := 4);
	port
	(
		rst:  in  std_ulogic;
		clk:  in  std_ulogic;
		load: in  std_ulogic;
		ce:   in  std_ulogic;
		do:   out std_ulogic := '0';
		di:   in  std_ulogic_vector(N - 1 downto 0));
end entity;
 
architecture rtl of losr is
begin
	process(rst, clk)
		variable data: std_ulogic_vector(N - 1 downto 0) := (others => '0');
	begin
		if rst = '1' and g.asynchronous_reset then
			data := (others => '0');
		elsif rising_edge(clk) then
			if rst = '1' and not g.asynchronous_reset then
				data := (others => '0');
			else
				if load = '1' then
					data := di;
				elsif ce = '1' then
					data := data(N-2 downto 0) & "0";
				end if;
			end if;
		end if;
		do <= data(N-1) after g.delay;
	end process;
end;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.