From c277013ff527af6b7951add2934084bb5e4e3a25 Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Sun, 16 May 2010 02:25:40 +0200 Subject: [PATCH] vga/ps/2: ip-core hinzugefuegt --- src/math_pkg.vhd | 53 + src/ps2/ps2_keyboard_controller.vhd | 33 + src/ps2/ps2_keyboard_controller_beh.vhd | 201 + src/ps2/ps2_keyboard_controller_pkg.vhd | 31 + src/ps2/ps2_transceiver.vhd | 35 + src/ps2/ps2_transceiver_beh.vhd | 396 ++ src/ps2/ps2_transceiver_pkg.vhd | 37 + src/textmode_vga/console_sm.vhd | 37 + src/textmode_vga/console_sm_beh.vhd | 291 ++ src/textmode_vga/console_sm_sync.vhd | 36 + src/textmode_vga/console_sm_sync_beh.vhd | 121 + src/textmode_vga/font_pkg.vhd | 4126 +++++++++++++++++ src/textmode_vga/font_rom.vhd | 25 + src/textmode_vga/font_rom_beh.vhd | 27 + src/textmode_vga/interval.vhd | 27 + src/textmode_vga/interval_beh.vhd | 36 + .../textmode_vga_platform_dependent_pkg.vhd | 20 + src/textmode_vga/textmode_vga.vhd | 43 + .../textmode_vga_component_pkg.vhd | 176 + src/textmode_vga/textmode_vga_h_sm.vhd | 42 + src/textmode_vga/textmode_vga_h_sm_beh.vhd | 243 + src/textmode_vga/textmode_vga_pkg.vhd | 78 + src/textmode_vga/textmode_vga_struct.vhd | 156 + src/textmode_vga/textmode_vga_v_sm.vhd | 30 + src/textmode_vga/textmode_vga_v_sm_beh.vhd | 155 + src/textmode_vga/video_memory.vhd | 34 + src/textmode_vga/video_memory_beh.vhd | 52 + 27 files changed, 6541 insertions(+) create mode 100644 src/math_pkg.vhd create mode 100644 src/ps2/ps2_keyboard_controller.vhd create mode 100644 src/ps2/ps2_keyboard_controller_beh.vhd create mode 100644 src/ps2/ps2_keyboard_controller_pkg.vhd create mode 100644 src/ps2/ps2_transceiver.vhd create mode 100644 src/ps2/ps2_transceiver_beh.vhd create mode 100644 src/ps2/ps2_transceiver_pkg.vhd create mode 100644 src/textmode_vga/console_sm.vhd create mode 100644 src/textmode_vga/console_sm_beh.vhd create mode 100644 src/textmode_vga/console_sm_sync.vhd create mode 100644 src/textmode_vga/console_sm_sync_beh.vhd create mode 100644 src/textmode_vga/font_pkg.vhd create mode 100644 src/textmode_vga/font_rom.vhd create mode 100644 src/textmode_vga/font_rom_beh.vhd create mode 100644 src/textmode_vga/interval.vhd create mode 100644 src/textmode_vga/interval_beh.vhd create mode 100644 src/textmode_vga/mjl_stratix/textmode_vga_platform_dependent_pkg.vhd create mode 100644 src/textmode_vga/textmode_vga.vhd create mode 100644 src/textmode_vga/textmode_vga_component_pkg.vhd create mode 100644 src/textmode_vga/textmode_vga_h_sm.vhd create mode 100644 src/textmode_vga/textmode_vga_h_sm_beh.vhd create mode 100644 src/textmode_vga/textmode_vga_pkg.vhd create mode 100644 src/textmode_vga/textmode_vga_struct.vhd create mode 100644 src/textmode_vga/textmode_vga_v_sm.vhd create mode 100644 src/textmode_vga/textmode_vga_v_sm_beh.vhd create mode 100644 src/textmode_vga/video_memory.vhd create mode 100644 src/textmode_vga/video_memory_beh.vhd diff --git a/src/math_pkg.vhd b/src/math_pkg.vhd new file mode 100644 index 0000000..ee0e443 --- /dev/null +++ b/src/math_pkg.vhd @@ -0,0 +1,53 @@ +------------------------------------------------------------------------- +-- +-- Filename: math_pkg.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Utility Package defining often used mathematical functions +-- +------------------------------------------------------------------------- + +package math_pkg is + -- Calculates the logarithm dualis of the operand and rounds up + -- the result to the next integer value. + function log2c(constant value : in integer) return integer; + -- Returns the maximum of the two operands + function max(constant value1, value2 : in integer) return integer; + -- Returns the maximum of the three operands + function max(constant value1, value2, value3 : in integer) return integer; +end math_pkg; + +package body math_pkg is + function log2c(constant value : in integer) return integer is + variable ret_value : integer; + variable cur_value : integer; + begin + ret_value := 0; + cur_value := 1; + + while cur_value < value loop + ret_value := ret_value + 1; + cur_value := cur_value * 2; + end loop; + return ret_value; + end function log2c; + + function max(constant value1, value2 : in integer) return integer is + variable ret_value : integer; + begin + if value1 > value2 then + ret_value := value1; + else + ret_value := value2; + end if; + return ret_value; + end function max; + + function max(constant value1, value2, value3 : in integer) return integer is + begin + return max(max(value1, value2), value3); + end function max; + end package body math_pkg; + \ No newline at end of file diff --git a/src/ps2/ps2_keyboard_controller.vhd b/src/ps2/ps2_keyboard_controller.vhd new file mode 100644 index 0000000..bdb2335 --- /dev/null +++ b/src/ps2/ps2_keyboard_controller.vhd @@ -0,0 +1,33 @@ +------------------------------------------------------------------------- +-- +-- Filename: ps2_keyboard_controller.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- PS/2 keyboard controller entity declaration. +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity ps2_keyboard_controller is + generic + ( + -- System clock frequency + CLK_FREQ : integer; + -- Number of stages used in synchronizers + SYNC_STAGES : integer + ); + port + ( + -- User logic interface + sys_clk, sys_res_n : in std_logic; + new_data : out std_logic; + data : out std_logic_vector(7 downto 0); + + -- External PS/2 interface + ps2_clk, ps2_data : inout std_logic + ); +end entity ps2_keyboard_controller; diff --git a/src/ps2/ps2_keyboard_controller_beh.vhd b/src/ps2/ps2_keyboard_controller_beh.vhd new file mode 100644 index 0000000..ca9ca7d --- /dev/null +++ b/src/ps2/ps2_keyboard_controller_beh.vhd @@ -0,0 +1,201 @@ +------------------------------------------------------------------------- +-- +-- Filename: ps2_keyboard_controller_beh.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Behavioral implementation of the PS/2 keyboard controller. +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use work.ps2_transceiver_pkg.all; + +architecture beh of ps2_keyboard_controller is + type KEYBOARD_STATE_TYPE is + ( + INIT, INIT_WAIT_ACK, INIT_WAIT_BAT, SET_INDICATORS_CMD, SET_INDICATORS_CMD_WAIT_ACK, SET_INDICATORS_VALUE, + SET_INDICATORS_VALUE_WAIT_ACK, ENABLE, ENABLE_WAIT_ACK, OPERATIONAL, NEW_DATA_AVAILABLE, + ERROR + ); + signal keyboard_state, keyboard_state_next : KEYBOARD_STATE_TYPE; + + signal keyboard_data : std_logic_vector(7 downto 0); + signal keyboard_new_data : std_logic; + + signal input_data : std_logic_vector(7 downto 0); + signal input_data_send_ok, input_data_send_finished, send_request : std_logic; + + signal new_data_next : std_logic; + signal data_next, data_internal : std_logic_vector(7 downto 0); +begin + ps2_transceiver_inst : ps2_transceiver + generic map + ( + CLK_FREQ => CLK_FREQ, + SYNC_STAGES => SYNC_STAGES + ) + port map + ( + sys_clk => sys_clk, + sys_res_n => sys_res_n, + ps2_clk => ps2_clk, + ps2_data => ps2_data, + send_request => send_request, + input_data => input_data, + input_data_send_ok => input_data_send_ok, + input_data_send_finished => input_data_send_finished, + output_data => keyboard_data, + new_data => keyboard_new_data + ); + + process(keyboard_state, keyboard_new_data, keyboard_data, input_data_send_ok, input_data_send_finished) + begin + keyboard_state_next <= keyboard_state; + + case keyboard_state is + when INIT => + if input_data_send_finished = '1' then + if input_data_send_ok = '1' then + keyboard_state_next <= INIT_WAIT_ACK; + else + keyboard_state_next <= ERROR; + end if; + end if; + + when INIT_WAIT_ACK => + if keyboard_new_data = '1' then + if keyboard_data = x"FA" then + keyboard_state_next <= INIT_WAIT_BAT; + else + keyboard_state_next <= ERROR; + end if; + end if; + + when INIT_WAIT_BAT => + if keyboard_new_data = '1' then + if keyboard_data = x"AA" then + keyboard_state_next <= SET_INDICATORS_CMD; + else + keyboard_state_next <= ERROR; + end if; + end if; + + when SET_INDICATORS_CMD => + if input_data_send_finished = '1' then + if input_data_send_ok = '1' then + keyboard_state_next <= SET_INDICATORS_CMD_WAIT_ACK; + else + keyboard_state_next <= ERROR; + end if; + end if; + when SET_INDICATORS_CMD_WAIT_ACK => + if keyboard_new_data = '1' then + if keyboard_data = x"FA" then + keyboard_state_next <= SET_INDICATORS_VALUE; + else + keyboard_state_next <= ERROR; + end if; + end if; + when SET_INDICATORS_VALUE => + if input_data_send_finished = '1' then + if input_data_send_ok = '1' then + keyboard_state_next <= SET_INDICATORS_VALUE_WAIT_ACK; + else + keyboard_state_next <= ERROR; + end if; + end if; + when SET_INDICATORS_VALUE_WAIT_ACK => + if keyboard_new_data = '1' then + if keyboard_data = x"FA" then + keyboard_state_next <= ENABLE; + else + keyboard_state_next <= ERROR; + end if; + end if; + + when ENABLE => + if input_data_send_finished = '1' then + if input_data_send_ok = '1' then + keyboard_state_next <= ENABLE_WAIT_ACK; + else + keyboard_state_next <= ERROR; + end if; + end if; + when ENABLE_WAIT_ACK => + if keyboard_new_data = '1' then + if keyboard_data = x"FA" then + keyboard_state_next <= OPERATIONAL; + else + keyboard_state_next <= ERROR; + end if; + end if; + + when OPERATIONAL => + if keyboard_new_data = '1' then + keyboard_state_next <= NEW_DATA_AVAILABLE; + end if; + + when NEW_DATA_AVAILABLE => + keyboard_state_next <= OPERATIONAL; + + when ERROR => + null; + end case; + end process; + + process(keyboard_state, keyboard_data, data_internal) + begin + send_request <= '0'; + input_data <= x"00"; + new_data_next <= '0'; + data_next <= data_internal; + + case keyboard_state is + when INIT => + send_request <= '1'; + input_data <= x"FF"; + when INIT_WAIT_ACK => + null; + when INIT_WAIT_BAT => + null; + when SET_INDICATORS_CMD => + send_request <= '1'; + input_data <= x"ED"; + when SET_INDICATORS_CMD_WAIT_ACK => + null; + when SET_INDICATORS_VALUE => + send_request <= '1'; + input_data <= x"02"; + when SET_INDICATORS_VALUE_WAIT_ACK => + null; + when ENABLE => + send_request <= '1'; + input_data <= x"F4"; + when ENABLE_WAIT_ACK => + null; + when OPERATIONAL => + null; + when NEW_DATA_AVAILABLE => + new_data_next <= '1'; + data_next <= keyboard_data; + when ERROR => + end case; + end process; + + process(sys_clk, sys_res_n) + begin + if sys_res_n = '0' then + keyboard_state <= INIT; + new_data <= '0'; + data_internal <= (others => '0'); + elsif rising_edge(sys_clk) then + keyboard_state <= keyboard_state_next; + new_data <= new_data_next; + data_internal <= data_next; + end if; + end process; + data <= data_internal; +end architecture beh; diff --git a/src/ps2/ps2_keyboard_controller_pkg.vhd b/src/ps2/ps2_keyboard_controller_pkg.vhd new file mode 100644 index 0000000..c0b4906 --- /dev/null +++ b/src/ps2/ps2_keyboard_controller_pkg.vhd @@ -0,0 +1,31 @@ +------------------------------------------------------------------------- +-- +-- Filename: ps2_keyboard_controller_pkg.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Component declaration of the PS/2 keyboard controller +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package ps2_keyboard_controller_pkg is + component ps2_keyboard_controller is + generic + ( + CLK_FREQ : integer; + SYNC_STAGES : integer + ); + port + ( + sys_clk, sys_res_n : in std_logic; + + ps2_clk, ps2_data : inout std_logic; + new_data : out std_logic; + data : out std_logic_vector(7 downto 0) + ); + end component ps2_keyboard_controller; +end package ps2_keyboard_controller_pkg; diff --git a/src/ps2/ps2_transceiver.vhd b/src/ps2/ps2_transceiver.vhd new file mode 100644 index 0000000..2768d3e --- /dev/null +++ b/src/ps2/ps2_transceiver.vhd @@ -0,0 +1,35 @@ +------------------------------------------------------------------------- +-- +-- Filename: ps2_transceiver.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- PS/2 transceiver entity +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity ps2_transceiver is + generic + ( + CLK_FREQ : integer; + SYNC_STAGES : integer + ); + port + ( + sys_clk, sys_res_n : in std_logic; + + ps2_clk, ps2_data : inout std_logic; + + send_request : in std_logic; + input_data : in std_logic_vector(7 downto 0); + input_data_send_ok : out std_logic; + input_data_send_finished : out std_logic; + + output_data : out std_logic_vector(7 downto 0); + new_data : out std_logic + ); +end entity ps2_transceiver; diff --git a/src/ps2/ps2_transceiver_beh.vhd b/src/ps2/ps2_transceiver_beh.vhd new file mode 100644 index 0000000..8706c52 --- /dev/null +++ b/src/ps2/ps2_transceiver_beh.vhd @@ -0,0 +1,396 @@ +------------------------------------------------------------------------- +-- +-- Filename: ps2_transceiver_beh.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Behavioral implementation of the PS/2 transceiver +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +architecture beh of ps2_transceiver is + constant PREPARE_TIMEOUT1_MAX : integer := CLK_FREQ / 5000; -- 200 us + constant PREPARE_TIMEOUT2_MAX : integer := CLK_FREQ / 100000; -- 10 us + type PS2_TRANSCEIVER_STATE_TYPE is + ( + IDLE, + + PREPARE_SEND_ASSIGN_CLK, PREPARE_SEND_WAIT1, PREPARE_SEND_DATA, PREPARE_SEND_WAIT2, + PREPARE_SEND_RELEASE_CLK, SEND_WAIT_DATA0, SEND_DATA0, SEND_WAIT_DATA1, SEND_DATA1, + SEND_WAIT_DATA2, SEND_DATA2, SEND_WAIT_DATA3, SEND_DATA3, SEND_WAIT_DATA4, SEND_DATA4, + SEND_WAIT_DATA5, SEND_DATA5, SEND_WAIT_DATA6, SEND_DATA6, SEND_WAIT_DATA7, SEND_DATA7, + SEND_WAIT_PARITY, SEND_PARITY, SEND_WAIT_STOP, SEND_STOP, SEND_WAIT_ACK1, SEND_WAIT_ACK2, + SEND_READ_ACK, SEND_FINISH, + + RECEIVE_START, RECEIVE_WAIT_DATA0, RECEIVE_DATA0, RECEIVE_WAIT_DATA1, RECEIVE_DATA1, + RECEIVE_WAIT_DATA2, RECEIVE_DATA2, RECEIVE_WAIT_DATA3, RECEIVE_DATA3, RECEIVE_WAIT_DATA4, + RECEIVE_DATA4, RECEIVE_WAIT_DATA5, RECEIVE_DATA5, RECEIVE_WAIT_DATA6, RECEIVE_DATA6, + RECEIVE_WAIT_DATA7, RECEIVE_DATA7, RECEIVE_WAIT_PARITY, RECEIVE_PARITY, RECEIVE_WAIT_STOP, + RECEIVE_STOP + ); + signal ps2_transceiver_state, ps2_transceiver_state_next : PS2_TRANSCEIVER_STATE_TYPE; + signal ps2_clk_last, ps2_clk_internal, ps2_clk_next, ps2_clk_hz, ps2_clk_hz_next : std_logic; + signal ps2_data_internal, ps2_data_next, ps2_data_hz, ps2_data_hz_next : std_logic; + signal ps2_clk_sync, ps2_data_sync : std_logic_vector(1 to SYNC_STAGES); + signal output_data_next, output_data_internal : std_logic_vector(7 downto 0); + signal parity, parity_next : std_logic; + signal new_data_next : std_logic; + signal prepare_timeout1, prepare_timeout1_next : integer range 0 to PREPARE_TIMEOUT1_MAX; + signal prepare_timeout2, prepare_timeout2_next : integer range 0 to PREPARE_TIMEOUT2_MAX; +begin + + process(ps2_transceiver_state, ps2_clk_sync(SYNC_STAGES), ps2_clk_last, ps2_data_sync(SYNC_STAGES), send_request, prepare_timeout1, prepare_timeout2, output_data_internal) + begin + ps2_transceiver_state_next <= ps2_transceiver_state; + + case ps2_transceiver_state is + when IDLE => + if ps2_clk_sync(SYNC_STAGES) = '1' and ps2_clk_last = '0' then + if ps2_data_sync(SYNC_STAGES) = '0' then + ps2_transceiver_state_next <= RECEIVE_START; + end if; + elsif send_request = '1' then + ps2_transceiver_state_next <= PREPARE_SEND_ASSIGN_CLK; + end if; + + + when PREPARE_SEND_ASSIGN_CLK => + ps2_transceiver_state_next <= PREPARE_SEND_WAIT1; + when PREPARE_SEND_WAIT1 => + if prepare_timeout1 = PREPARE_TIMEOUT1_MAX - 1 then + ps2_transceiver_state_next <= PREPARE_SEND_DATA; + end if; + when PREPARE_SEND_DATA => + ps2_transceiver_state_next <= PREPARE_SEND_WAIT2; + when PREPARE_SEND_WAIT2 => + if prepare_timeout2 = PREPARE_TIMEOUT2_MAX - 1 then + ps2_transceiver_state_next <= PREPARE_SEND_RELEASE_CLK; + end if; + when PREPARE_SEND_RELEASE_CLK => + ps2_transceiver_state_next <= SEND_WAIT_DATA0; + when SEND_WAIT_DATA0 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= SEND_DATA0; + end if; + when SEND_DATA0 => + ps2_transceiver_state_next <= SEND_WAIT_DATA1; + when SEND_WAIT_DATA1 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= SEND_DATA1; + end if; + when SEND_DATA1 => + ps2_transceiver_state_next <= SEND_WAIT_DATA2; + when SEND_WAIT_DATA2 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= SEND_DATA2; + end if; + when SEND_DATA2 => + ps2_transceiver_state_next <= SEND_WAIT_DATA3; + when SEND_WAIT_DATA3 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= SEND_DATA3; + end if; + when SEND_DATA3 => + ps2_transceiver_state_next <= SEND_WAIT_DATA4; + when SEND_WAIT_DATA4 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= SEND_DATA4; + end if; + when SEND_DATA4 => + ps2_transceiver_state_next <= SEND_WAIT_DATA5; + when SEND_WAIT_DATA5 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= SEND_DATA5; + end if; + when SEND_DATA5 => + ps2_transceiver_state_next <= SEND_WAIT_DATA6; + when SEND_WAIT_DATA6 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= SEND_DATA6; + end if; + when SEND_DATA6 => + ps2_transceiver_state_next <= SEND_WAIT_DATA7; + when SEND_WAIT_DATA7 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= SEND_DATA7; + end if; + when SEND_DATA7 => + ps2_transceiver_state_next <= SEND_WAIT_PARITY; + when SEND_WAIT_PARITY => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= SEND_PARITY; + end if; + when SEND_PARITY => + ps2_transceiver_state_next <= SEND_WAIT_STOP; + when SEND_WAIT_STOP => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= SEND_STOP; + end if; + when SEND_STOP => + ps2_transceiver_state_next <= SEND_WAIT_ACK1; + when SEND_WAIT_ACK1 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then -- ACK is written by device + ps2_transceiver_state_next <= SEND_WAIT_ACK2; + end if; + when SEND_WAIT_ACK2 => + if ps2_clk_sync(SYNC_STAGES) = '1' and ps2_clk_last = '0' then -- ACK is valid + ps2_transceiver_state_next <= SEND_READ_ACK; + end if; + when SEND_READ_ACK => + ps2_transceiver_state_next <= SEND_FINISH; + when SEND_FINISH => + ps2_transceiver_state_next <= IDLE; + + + + when RECEIVE_START => + ps2_transceiver_state_next <= RECEIVE_WAIT_DATA0; + when RECEIVE_WAIT_DATA0 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= RECEIVE_DATA0; + end if; + when RECEIVE_DATA0 => + ps2_transceiver_state_next <= RECEIVE_WAIT_DATA1; + when RECEIVE_WAIT_DATA1 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= RECEIVE_DATA1; + end if; + when RECEIVE_DATA1 => + ps2_transceiver_state_next <= RECEIVE_WAIT_DATA2; + when RECEIVE_WAIT_DATA2 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= RECEIVE_DATA2; + end if; + when RECEIVE_DATA2 => + ps2_transceiver_state_next <= RECEIVE_WAIT_DATA3; + when RECEIVE_WAIT_DATA3 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= RECEIVE_DATA3; + end if; + when RECEIVE_DATA3 => + ps2_transceiver_state_next <= RECEIVE_WAIT_DATA4; + when RECEIVE_WAIT_DATA4 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= RECEIVE_DATA4; + end if; + when RECEIVE_DATA4 => + ps2_transceiver_state_next <= RECEIVE_WAIT_DATA5; + when RECEIVE_WAIT_DATA5 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= RECEIVE_DATA5; + end if; + when RECEIVE_DATA5 => + ps2_transceiver_state_next <= RECEIVE_WAIT_DATA6; + when RECEIVE_WAIT_DATA6 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= RECEIVE_DATA6; + end if; + when RECEIVE_DATA6 => + ps2_transceiver_state_next <= RECEIVE_WAIT_DATA7; + when RECEIVE_WAIT_DATA7 => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= RECEIVE_DATA7; + end if; + when RECEIVE_DATA7 => + ps2_transceiver_state_next <= RECEIVE_WAIT_PARITY; + when RECEIVE_WAIT_PARITY => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= RECEIVE_PARITY; + end if; + when RECEIVE_PARITY => + ps2_transceiver_state_next <= RECEIVE_WAIT_STOP; + when RECEIVE_WAIT_STOP => + if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then + ps2_transceiver_state_next <= RECEIVE_STOP; + end if; + when RECEIVE_STOP => + ps2_transceiver_state_next <= IDLE; + end case; + end process; + + process(ps2_transceiver_state, ps2_data_internal, ps2_clk_internal, parity, input_data, ps2_data_sync(SYNC_STAGES), output_data_internal, prepare_timeout1, prepare_timeout2, ps2_clk_hz, ps2_data_hz) + begin + input_data_send_ok <= '0'; + input_data_send_finished <= '0'; + ps2_data_next <= ps2_data_internal; + ps2_data_hz_next <= ps2_data_hz; + ps2_clk_next <= ps2_clk_internal; + ps2_clk_hz_next <= ps2_clk_hz; + parity_next <= parity; + output_data_next <= output_data_internal; + new_data_next <= '0'; + prepare_timeout1_next <= prepare_timeout1; + prepare_timeout2_next <= prepare_timeout2; + + case ps2_transceiver_state is + when IDLE => + ps2_clk_next <= '1'; + ps2_clk_hz_next <= '1'; + ps2_data_next <= '1'; + ps2_data_hz_next <= '1'; + + when PREPARE_SEND_ASSIGN_CLK => + ps2_clk_next <= '0'; + ps2_clk_hz_next <= '0'; + parity_next <= '1'; + prepare_timeout1_next <= 0; + when PREPARE_SEND_WAIT1 => + prepare_timeout1_next <= prepare_timeout1 + 1; + when PREPARE_SEND_DATA => + ps2_data_next <='0'; + ps2_data_hz_next <= '0'; + prepare_timeout2_next <= 0; + when PREPARE_SEND_WAIT2 => + prepare_timeout2_next <= prepare_timeout2 + 1; + when PREPARE_SEND_RELEASE_CLK => + ps2_clk_next <= '1'; + ps2_clk_hz_next <= '1'; + when SEND_WAIT_DATA0 => + null; + when SEND_DATA0 => + ps2_data_next <= input_data(0); + parity_next <= parity xor input_data(0); + when SEND_WAIT_DATA1 => + null; + when SEND_DATA1 => + ps2_data_next <=input_data(1); + parity_next <= parity xor input_data(1); + when SEND_WAIT_DATA2 => + null; + when SEND_DATA2 => + ps2_data_next <=input_data(2); + parity_next <= parity xor input_data(2); + when SEND_WAIT_DATA3 => + null; + when SEND_DATA3 => + ps2_data_next <=input_data(3); + parity_next <= parity xor input_data(3); + when SEND_WAIT_DATA4 => + null; + when SEND_DATA4 => + ps2_data_next <=input_data(4); + parity_next <= parity xor input_data(4); + when SEND_WAIT_DATA5 => + null; + when SEND_DATA5 => + ps2_data_next <=input_data(5); + parity_next <= parity xor input_data(5); + when SEND_WAIT_DATA6 => + null; + when SEND_DATA6 => + ps2_data_next <=input_data(6); + parity_next <= parity xor input_data(6); + when SEND_WAIT_DATA7 => + null; + when SEND_DATA7 => + ps2_data_next <=input_data(7); + parity_next <= parity xor input_data(7); + when SEND_WAIT_PARITY => + null; + when SEND_PARITY => + ps2_data_next <= parity; + when SEND_WAIT_STOP => + null; + when SEND_STOP => + ps2_data_next <='1'; + ps2_data_hz_next <='1'; + when SEND_WAIT_ACK1 => + null; + when SEND_WAIT_ACK2 => + null; + when SEND_READ_ACK => + input_data_send_ok <= not ps2_data_sync(SYNC_STAGES); + input_data_send_finished <= '1'; + when SEND_FINISH => + + when RECEIVE_START => + null; + when RECEIVE_WAIT_DATA0 => + null; + when RECEIVE_DATA0 => + output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1); + when RECEIVE_WAIT_DATA1 => + null; + when RECEIVE_DATA1 => + output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1); + when RECEIVE_WAIT_DATA2 => + null; + when RECEIVE_DATA2 => + output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1); + when RECEIVE_WAIT_DATA3 => + null; + when RECEIVE_DATA3 => + output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1); + when RECEIVE_WAIT_DATA4 => + null; + when RECEIVE_DATA4 => + output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1); + when RECEIVE_WAIT_DATA5 => + null; + when RECEIVE_DATA5 => + output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1); + when RECEIVE_WAIT_DATA6 => + null; + when RECEIVE_DATA6 => + output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1); + when RECEIVE_WAIT_DATA7 => + null; + when RECEIVE_DATA7 => + output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1); + when RECEIVE_WAIT_PARITY => + null; + when RECEIVE_PARITY => + null; -- Currently igonring parity + when RECEIVE_WAIT_STOP => + null; + when RECEIVE_STOP => + new_data_next <= '1'; + end case; + end process; + + process(sys_clk, sys_res_n) + begin + if sys_res_n = '0' then + ps2_transceiver_state <= IDLE; + ps2_clk_last <= '1'; + ps2_clk_internal <= '1'; + ps2_clk_hz <= '1'; + ps2_data_internal <= '1'; + ps2_data_hz <= '1'; + output_data_internal <= (others => '0'); + parity <= '0'; + new_data <= '0'; + prepare_timeout1 <= 0; + prepare_timeout2 <= 0; + ps2_clk_sync <= (others => '1'); + ps2_data_sync <= (others => '1'); + elsif rising_edge(sys_clk) then + ps2_transceiver_state <= ps2_transceiver_state_next; + ps2_clk_last <= ps2_clk_sync(SYNC_STAGES); + ps2_clk_internal <= ps2_clk_next; + ps2_clk_hz <= ps2_clk_hz_next; + ps2_data_internal <= ps2_data_next; + ps2_data_hz <= ps2_data_hz_next; + output_data_internal <= output_data_next; + parity <= parity_next; + new_data <= new_data_next; + prepare_timeout1 <= prepare_timeout1_next; + prepare_timeout2 <= prepare_timeout2_next; + ps2_clk_sync(1) <= ps2_clk; + ps2_data_sync(1) <= ps2_data; + for i in 2 to SYNC_STAGES loop + ps2_clk_sync(i) <= ps2_clk_sync(i - 1); + ps2_data_sync(i) <= ps2_data_sync(i - 1); + end loop; + end if; + end process; + ps2_clk <= ps2_clk_internal when ps2_clk_hz = '0' + else 'Z'; + ps2_data <= ps2_data_internal when ps2_data_hz = '0' + else 'Z'; + output_data <= output_data_internal; +end architecture beh; diff --git a/src/ps2/ps2_transceiver_pkg.vhd b/src/ps2/ps2_transceiver_pkg.vhd new file mode 100644 index 0000000..5b29633 --- /dev/null +++ b/src/ps2/ps2_transceiver_pkg.vhd @@ -0,0 +1,37 @@ +------------------------------------------------------------------------- +-- +-- Filename: ps2_transceiver_pkg.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Component declaration of the PS/2 transceiver +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package ps2_transceiver_pkg is + component ps2_transceiver is + generic + ( + CLK_FREQ : integer; + SYNC_STAGES : integer + ); + port + ( + sys_clk, sys_res_n : in std_logic; + + ps2_clk, ps2_data : inout std_logic; + + send_request : in std_logic; + input_data : in std_logic_vector(7 downto 0); + input_data_send_ok : out std_logic; + input_data_send_finished : out std_logic; + + output_data : out std_logic_vector(7 downto 0); + new_data : out std_logic + ); + end component ps2_transceiver; +end package ps2_transceiver_pkg; diff --git a/src/textmode_vga/console_sm.vhd b/src/textmode_vga/console_sm.vhd new file mode 100644 index 0000000..2666647 --- /dev/null +++ b/src/textmode_vga/console_sm.vhd @@ -0,0 +1,37 @@ +------------------------------------------------------------------------- +-- +-- Filename: console_sm.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Console mode finite state machine entity declaration +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use work.textmode_vga_pkg.all; +use work.textmode_vga_platform_dependent_pkg.all; +use work.font_pkg.all; +use work.math_pkg.all; + +entity console_sm is + port + ( + vga_clk, vga_res_n : in std_logic; + command : in std_logic_vector(COMMAND_SIZE - 1 downto 0); + command_data : in std_logic_vector(3 * COLOR_SIZE + CHAR_SIZE - 1 downto 0); + command_req : in std_logic; + ack : out std_logic; + + column_address : out std_logic_vector(log2c(COLUMN_COUNT) - 1 downto 0); + row_address : out std_logic_vector(log2c(LINE_COUNT) - 1 downto 0); + data : out std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS + CHAR_SIZE - 1 downto 0); + wr : out std_logic; + scroll_address : out std_logic_vector(log2c(LINE_COUNT) - 1 downto 0); + background_color : out std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + cursor_color : out std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + cursor_state : out CURSOR_STATE_TYPE + ); +end entity console_sm; \ No newline at end of file diff --git a/src/textmode_vga/console_sm_beh.vhd b/src/textmode_vga/console_sm_beh.vhd new file mode 100644 index 0000000..c4f2f3b --- /dev/null +++ b/src/textmode_vga/console_sm_beh.vhd @@ -0,0 +1,291 @@ +------------------------------------------------------------------------- +-- +-- Filename: console_sm_beh.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Console mode finite state machine behavioral implementation +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.textmode_vga_pkg.all; +use work.textmode_vga_platform_dependent_pkg.all; + +architecture beh of console_sm is + type STATE_TYPE is + ( + STATE_IDLE, STATE_ACK_UNKNOWN, STATE_WAIT_REQ_RELEASE, STATE_NEW_LINE_SIMPLE, + STATE_NEW_LINE_SCROLL, STATE_CARRIAGE_RETURN, STATE_SET_CHAR, + STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SIMPLE, + STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SCROLL, + STATE_SET_BACKGROUND, STATE_SCROLL_NEXT, STATE_SCROLL_TOP, + STATE_SCROLL_CLEAR_LINE, STATE_SCROLL_CLEAR_LINE_LOOP, + STATE_SCROLL_CLEAR_LINE_FINISH, STATE_SET_CURSOR_STATE, + STATE_SET_CURSOR_COLOR, STATE_SET_CURSOR_COLUMN, + STATE_SET_CURSOR_LINE, STATE_SET_CURSOR_STATE_OFF, + STATE_SET_CURSOR_STATE_ON, STATE_SET_CURSOR_STATE_BLINK + ); + + signal state, state_next : STATE_TYPE; + signal line_int : integer range 0 to LINE_COUNT - 1; + signal line_next : integer range 0 to LINE_COUNT; + signal column_int : integer range 0 to COLUMN_COUNT - 1; + signal column_save, column_save_next : integer range 0 to COLUMN_COUNT - 1; + signal column_next : integer range 0 to COLUMN_COUNT; + signal scroll_int : integer range 0 to LINE_COUNT - 1; + signal scroll_next : integer range 0 to LINE_COUNT; + signal ack_next : std_logic; + signal background_color_int, background_color_next : std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + signal cursor_color_int, cursor_color_next : std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + signal cursor_state_int, cursor_state_next : CURSOR_STATE_TYPE; +begin + column_address <= std_logic_vector(to_unsigned(column_int, log2c(COLUMN_COUNT))); + row_address <= std_logic_vector(to_unsigned(line_int, log2c(LINE_COUNT))); + scroll_address <= std_logic_vector(to_unsigned(scroll_int, log2c(LINE_COUNT))); + background_color <= background_color_int; + cursor_color <= cursor_color_int; + cursor_state <= cursor_state_int; + + process(state, line_int, column_int, scroll_int, command, command_data, command_req) + begin + state_next <= state; + + case state is + when STATE_IDLE => + if command_req = '1' then + if command = COMMAND_SET_CHAR then + if command_data(CHAR_SIZE - 1 downto 0) = CHAR_NEW_LINE then + if line_int < LINE_COUNT - 1 then + state_next <= STATE_NEW_LINE_SIMPLE; + else + state_next <= STATE_NEW_LINE_SCROLL; + end if; + elsif command_data(CHAR_SIZE - 1 downto 0) = CHAR_CARRIAGE_RETURN then + state_next <= STATE_CARRIAGE_RETURN; + else + if column_int < COLUMN_COUNT - 1 then + state_next <= STATE_SET_CHAR; + else + if line_int < LINE_COUNT - 1 then + state_next <= STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SIMPLE; + else + state_next <= STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SCROLL; + end if; + end if; + end if; + elsif command = COMMAND_SET_BACKGROUND then + state_next <= STATE_SET_BACKGROUND; + elsif command = COMMAND_SET_CURSOR_STATE then + state_next <= STATE_SET_CURSOR_STATE; + elsif command = COMMAND_SET_CURSOR_COLOR then + state_next <= STATE_SET_CURSOR_COLOR; + elsif command = COMMAND_SET_CURSOR_COLUMN then + state_next <= STATE_SET_CURSOR_COLUMN; + elsif command = COMMAND_SET_CURSOR_LINE then + state_next <= STATE_SET_CURSOR_LINE; + else + state_next <= STATE_ACK_UNKNOWN; + end if; + end if; + when STATE_ACK_UNKNOWN => + state_next <= STATE_WAIT_REQ_RELEASE; + when STATE_NEW_LINE_SIMPLE => + state_next <= STATE_WAIT_REQ_RELEASE; + when STATE_NEW_LINE_SCROLL => + if scroll_int < LINE_COUNT - 1 then + state_next <= STATE_SCROLL_NEXT; + else + state_next <= STATE_SCROLL_TOP; + end if; + when STATE_CARRIAGE_RETURN => + state_next <= STATE_WAIT_REQ_RELEASE; + when STATE_SET_CHAR => + state_next <= STATE_WAIT_REQ_RELEASE; + when STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SIMPLE => + state_next <= STATE_WAIT_REQ_RELEASE; + when STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SCROLL => + if scroll_int < LINE_COUNT - 1 then + state_next <= STATE_SCROLL_NEXT; + else + state_next <= STATE_SCROLL_TOP; + end if; + when STATE_SCROLL_NEXT => + state_next <= STATE_SCROLL_CLEAR_LINE; + when STATE_SCROLL_TOP => + state_next <= STATE_SCROLL_CLEAR_LINE; + when STATE_SCROLL_CLEAR_LINE => + state_next <= STATE_SCROLL_CLEAR_LINE_LOOP; + when STATE_SCROLL_CLEAR_LINE_LOOP => + if column_int = COLUMN_COUNT - 2 then + state_next <= STATE_SCROLL_CLEAR_LINE_FINISH; + end if; + when STATE_SCROLL_CLEAR_LINE_FINISH => + state_next <= STATE_WAIT_REQ_RELEASE; + when STATE_WAIT_REQ_RELEASE => + if command_req = '0' then + state_next <= STATE_IDLE; + end if; + when STATE_SET_BACKGROUND => + state_next <= STATE_WAIT_REQ_RELEASE; + when STATE_SET_CURSOR_STATE => + if command_data(1 downto 0) = "00" then + state_next <= STATE_SET_CURSOR_STATE_OFF; + elsif command_data(1 downto 0) = "01" then + state_next <= STATE_SET_CURSOR_STATE_ON; + else + state_next <= STATE_SET_CURSOR_STATE_BLINK; + end if; + when STATE_SET_CURSOR_STATE_OFF => + state_next <= STATE_WAIT_REQ_RELEASE; + when STATE_SET_CURSOR_STATE_ON => + state_next <= STATE_WAIT_REQ_RELEASE; + when STATE_SET_CURSOR_STATE_BLINK => + state_next <= STATE_WAIT_REQ_RELEASE; + when STATE_SET_CURSOR_COLOR => + state_next <= STATE_WAIT_REQ_RELEASE; + when STATE_SET_CURSOR_COLUMN => + state_next <= STATE_WAIT_REQ_RELEASE; + when STATE_SET_CURSOR_LINE => + state_next <= STATE_WAIT_REQ_RELEASE; + end case; + end process; + + process(state, line_int, column_int, scroll_int, column_save, background_color_int, cursor_color_int, cursor_state_int, command_data) + begin + line_next <= line_int; + column_next <= column_int; + scroll_next <= scroll_int; + column_save_next <= column_save; + data <= std_logic_vector(to_unsigned(0, RED_BITS + GREEN_BITS + BLUE_BITS + CHAR_SIZE)); + ack_next <= '0'; + wr <= '0'; + background_color_next <= background_color_int; + cursor_color_next <= cursor_color_int; + cursor_state_next <= cursor_state_int; + + case state is + when STATE_IDLE => + null; + when STATE_ACK_UNKNOWN => + ack_next <= '1'; + when STATE_NEW_LINE_SIMPLE => + line_next <= line_int + 1; + ack_next <= '1'; + when STATE_NEW_LINE_SCROLL => + null; + when STATE_CARRIAGE_RETURN => + column_next <= 0; + ack_next <= '1'; + when STATE_SET_CHAR => + data <= command_data(CHAR_SIZE + 3 * COLOR_SIZE - 1 downto CHAR_SIZE + 3 * COLOR_SIZE - RED_BITS) & + command_data(CHAR_SIZE + 2 * COLOR_SIZE - 1 downto CHAR_SIZE + 2 * COLOR_SIZE - GREEN_BITS) & + command_data(CHAR_SIZE + COLOR_SIZE - 1 downto CHAR_SIZE + COLOR_SIZE - BLUE_BITS) & + command_data(CHAR_SIZE - 1 downto 0); + wr <= '1'; + column_next <= column_int + 1; + ack_next <= '1'; + when STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SIMPLE => + data <= command_data(CHAR_SIZE + 3 * COLOR_SIZE - 1 downto CHAR_SIZE + 3 * COLOR_SIZE - RED_BITS) & + command_data(CHAR_SIZE + 2 * COLOR_SIZE - 1 downto CHAR_SIZE + 2 * COLOR_SIZE - GREEN_BITS) & + command_data(CHAR_SIZE + COLOR_SIZE - 1 downto CHAR_SIZE + COLOR_SIZE - BLUE_BITS) & + command_data(CHAR_SIZE - 1 downto 0); + wr <= '1'; + line_next <= line_int + 1; + column_next <= 0; + ack_next <= '1'; + when STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SCROLL => + data <= command_data(CHAR_SIZE + 3 * COLOR_SIZE - 1 downto CHAR_SIZE + 3 * COLOR_SIZE - RED_BITS) & + command_data(CHAR_SIZE + 2 * COLOR_SIZE - 1 downto CHAR_SIZE + 2 * COLOR_SIZE - GREEN_BITS) & + command_data(CHAR_SIZE + COLOR_SIZE - 1 downto CHAR_SIZE + COLOR_SIZE - BLUE_BITS) & + command_data(CHAR_SIZE - 1 downto 0); + wr <= '1'; + column_next <= 0; + when STATE_SCROLL_NEXT => + scroll_next <= scroll_int + 1; + when STATE_SCROLL_TOP => + scroll_next <= 0; + when STATE_SCROLL_CLEAR_LINE => + column_save_next <= column_int; + column_next <= 0; + when STATE_SCROLL_CLEAR_LINE_LOOP => + data <= COLOR_BLACK(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) & + COLOR_BLACK(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) & + COLOR_BLACK(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS) & + CHAR_NULL; + wr <= '1'; + column_next <= column_int + 1; + when STATE_SCROLL_CLEAR_LINE_FINISH => + data <= COLOR_BLACK(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) & + COLOR_BLACK(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) & + COLOR_BLACK(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS) & + CHAR_NULL; + wr <= '1'; + column_next <= column_save; + ack_next <= '1'; + when STATE_WAIT_REQ_RELEASE => + ack_next <= '1'; + when STATE_SET_BACKGROUND => + background_color_next <= + command_data(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) & + command_data(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) & + command_data(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS); + ack_next <= '1'; + when STATE_SET_CURSOR_STATE => + null; + when STATE_SET_CURSOR_STATE_OFF => + cursor_state_next <= CURSOR_OFF; + ack_next <= '1'; + when STATE_SET_CURSOR_STATE_ON => + cursor_state_next <= CURSOR_ON; + ack_next <= '1'; + when STATE_SET_CURSOR_STATE_BLINK => + cursor_state_next <= CURSOR_BLINK; + ack_next <= '1'; + when STATE_SET_CURSOR_COLOR => + cursor_color_next <= + command_data(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) & + command_data(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) & + command_data(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS); + ack_next <= '1'; + when STATE_SET_CURSOR_COLUMN => + column_next <= to_integer(unsigned(command_data(log2c(COLUMN_COUNT) - 1 downto 0))); + ack_next <= '1'; + when STATE_SET_CURSOR_LINE => + line_next <= to_integer(unsigned(command_data(log2c(LINE_COUNT) - 1 downto 0))); + ack_next <= '1'; + end case; + end process; + + process(vga_clk, vga_res_n) + begin + if vga_res_n = '0' then + state <= STATE_IDLE; + line_int <= 0; + column_int <= 0; + scroll_int <= 0; + column_save <= 0; + ack <= '0'; + background_color_int <= COLOR_BLACK(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) & + COLOR_BLACK(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) & + COLOR_BLACK(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS); + cursor_color_int <= COLOR_WHITE(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) & + COLOR_WHITE(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) & + COLOR_WHITE(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS); + cursor_state_int <= CURSOR_BLINK; + elsif rising_edge(vga_clk) then + state <= state_next; + line_int <= line_next; + column_int <= column_next; + scroll_int <= scroll_next; + column_save <= column_save_next; + ack <= ack_next; + background_color_int <= background_color_next; + cursor_color_int <= cursor_color_next; + cursor_state_int <= cursor_state_next; + end if; + end process; +end architecture beh; diff --git a/src/textmode_vga/console_sm_sync.vhd b/src/textmode_vga/console_sm_sync.vhd new file mode 100644 index 0000000..2e5050f --- /dev/null +++ b/src/textmode_vga/console_sm_sync.vhd @@ -0,0 +1,36 @@ +------------------------------------------------------------------------- +-- +-- Filename: console_sm_sync.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Entity declaration of the synchronizer for the cosole mode +-- finite state machine. +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use work.textmode_vga_pkg.all; +use work.font_pkg.all; + +entity console_sm_sync is + generic + ( + SYNC_STAGES : integer + ); + port + ( + sys_clk, sys_res_n : in std_logic; + command_sys : in std_logic_vector(COMMAND_SIZE - 1 downto 0); + command_data_sys : in std_logic_vector(3 * COLOR_SIZE + CHAR_SIZE - 1 downto 0); + free_sys : out std_logic; + + vga_clk, vga_res_n : in std_logic; + command_vga : out std_logic_vector(COMMAND_SIZE - 1 downto 0); + command_data_vga : out std_logic_vector(3 * COLOR_SIZE + CHAR_SIZE - 1 downto 0); + command_req_vga : out std_logic; + ack_vga : in std_logic + ); +end entity console_sm_sync; diff --git a/src/textmode_vga/console_sm_sync_beh.vhd b/src/textmode_vga/console_sm_sync_beh.vhd new file mode 100644 index 0000000..00151b6 --- /dev/null +++ b/src/textmode_vga/console_sm_sync_beh.vhd @@ -0,0 +1,121 @@ +------------------------------------------------------------------------- +-- +-- Filename: console_sm_sync_beh.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Behavioral implementation of the synchronizer for the cosole mode +-- finite state machine. It synchronizes all signal crossing +-- from the system and the VGA clock domain and vice versa. +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.textmode_vga_pkg.all; +use work.textmode_vga_platform_dependent_pkg.all; +use work.font_pkg.all; + +architecture beh of console_sm_sync is + type SYNC_STATE_TYPE is (STATE_IDLE, STATE_WAIT_ACK, STATE_FINISHED, STATE_WAIT_ACK_RELEASE); + signal sync_state, sync_state_next : SYNC_STATE_TYPE; + signal command_req_sync : std_logic_vector(0 to SYNC_STAGES - 1); + signal command_req_sys : std_logic; + signal ack_sync : std_logic_vector(0 to SYNC_STAGES - 1); + signal ack_sys : std_logic; + signal command_latched, command_latched_next : std_logic_vector(COMMAND_SIZE - 1 downto 0); + signal command_data_latched, command_data_latched_next : std_logic_vector(3 * COLOR_SIZE + CHAR_SIZE - 1 downto 0); + signal command_req_next : std_logic; +begin + command_vga <= command_latched; + command_data_vga <= command_data_latched; + command_req_vga <= command_req_sync(SYNC_STAGES - 1); + synchronizer_sys_vga : process(vga_clk, vga_res_n) + begin + if vga_res_n = '0' then + command_req_sync <= (others => '0'); + elsif rising_edge(vga_clk) then + command_req_sync(0) <= command_req_sys; + for i in 1 to SYNC_STAGES - 1 loop + command_req_sync(i) <= command_req_sync(i - 1); + end loop; + end if; + end process synchronizer_sys_vga; + + ack_sys <= ack_sync(SYNC_STAGES - 1); + synchronizer_vga_sys : process(sys_clk, sys_res_n) + begin + if sys_res_n = '0' then + ack_sync <= (others => '0'); + elsif rising_edge(sys_clk) then + ack_sync(0) <= ack_vga; + for i in 1 to SYNC_STAGES - 1 loop + ack_sync(i) <= ack_sync(i - 1); + end loop; + end if; + end process synchronizer_vga_sys; + + process(sync_state, command_sys, ack_sys) + begin + sync_state_next <= sync_state; + + case sync_state is + when STATE_IDLE => + if command_sys /= COMMAND_NOP then + if ack_sys = '0' then + sync_state_next <= STATE_WAIT_ACK; + else + sync_state_next <= STATE_WAIT_ACK_RELEASE; + end if; + end if; + when STATE_WAIT_ACK => + if ack_sys = '1' then + sync_state_next <= STATE_FINISHED; + end if; + when STATE_FINISHED => + sync_state_next <= STATE_IDLE; + when STATE_WAIT_ACK_RELEASE => + if ack_sys = '0' then + sync_state_next <= STATE_WAIT_ACK; + end if; + end case; + end process; + + process(sync_state, command_latched, command_data_latched, command_sys, command_data_sys) + begin + command_latched_next <= command_latched; + command_data_latched_next <= command_data_latched; + command_req_next <= '0'; + free_sys <= '0'; + + case sync_state is + when STATE_IDLE => + command_latched_next <= command_sys; + command_data_latched_next <= command_data_sys; + free_sys <= '1'; + when STATE_WAIT_ACK => + command_req_next <= '1'; + when STATE_FINISHED => + null; + when STATE_WAIT_ACK_RELEASE => + null; + end case; + end process; + + process(sys_clk, sys_res_n) + begin + if sys_res_n = '0' then + command_latched <= COMMAND_NOP; + command_data_latched <= COLOR_BLACK & CHAR_NULL; + sync_state <= STATE_IDLE; + command_req_sys <= '0'; + elsif rising_edge(sys_clk) then + command_latched <= command_latched_next; + command_data_latched <= command_data_latched_next; + sync_state <= sync_state_next; + command_req_sys <= command_req_next; + end if; + end process; +end architecture beh; diff --git a/src/textmode_vga/font_pkg.vhd b/src/textmode_vga/font_pkg.vhd new file mode 100644 index 0000000..aa2b2b4 --- /dev/null +++ b/src/textmode_vga/font_pkg.vhd @@ -0,0 +1,4126 @@ +------------------------------------------------------------------------- +-- +-- Filename: font_pkg.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Constant declaration of the font ROM. The number of +-- defined encodings, the character dimension and the +-- encoding itself are defiend in this package. +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.textmode_vga_pkg.all; +use work.math_pkg.all; + +package font_pkg is + constant CHAR_COUNT : integer := 256; + constant CHAR_WIDTH : integer := 8; + constant CHAR_HEIGHT : integer := 16; + constant COLUMN_COUNT : integer := PIXEL_WIDTH / CHAR_WIDTH; + constant LINE_COUNT : integer := PIXEL_HEIGHT / CHAR_HEIGHT; + type FONT_TYPE is array (0 to 2 ** (log2c(CHAR_COUNT) + log2c(CHAR_HEIGHT)) - 1) of std_logic_vector(0 to CHAR_WIDTH - 1); + constant FONT_TABLE : FONT_TYPE := + ( + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111110", + "10000001", + "10100101", + "10000001", + "10000001", + "10111101", + "10011001", + "10000001", + "10000001", + "01111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111110", + "11111111", + "11011011", + "11111111", + "11111111", + "11000011", + "11100111", + "11111111", + "11111111", + "01111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01101100", + "11111110", + "11111110", + "11111110", + "11111110", + "01111100", + "00111000", + "00010000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00010000", + "00111000", + "01111100", + "11111110", + "01111100", + "00111000", + "00010000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00111100", + "00111100", + "11100111", + "11100111", + "11100111", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00111100", + "01111110", + "11111111", + "11111111", + "01111110", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00111100", + "00111100", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11100111", + "11000011", + "11000011", + "11100111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111100", + "01100110", + "01000010", + "01000010", + "01100110", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11000011", + "10011001", + "10111101", + "10111101", + "10011001", + "11000011", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "00000000", + "00000000", + "00011110", + "00001110", + "00011010", + "00110010", + "01111000", + "11001100", + "11001100", + "11001100", + "11001100", + "01111000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111100", + "01100110", + "01100110", + "01100110", + "01100110", + "00111100", + "00011000", + "01111110", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111111", + "00110011", + "00111111", + "00110000", + "00110000", + "00110000", + "00110000", + "01110000", + "11110000", + "11100000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111111", + "01100011", + "01111111", + "01100011", + "01100011", + "01100011", + "01100011", + "01100111", + "11100111", + "11100110", + "11000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "11011011", + "00111100", + "11100111", + "00111100", + "11011011", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "10000000", + "11000000", + "11100000", + "11110000", + "11111000", + "11111110", + "11111000", + "11110000", + "11100000", + "11000000", + "10000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000010", + "00000110", + "00001110", + "00011110", + "00111110", + "11111110", + "00111110", + "00011110", + "00001110", + "00000110", + "00000010", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00111100", + "01111110", + "00011000", + "00011000", + "00011000", + "01111110", + "00111100", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100110", + "01100110", + "01100110", + "01100110", + "01100110", + "01100110", + "01100110", + "00000000", + "01100110", + "01100110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111111", + "11011011", + "11011011", + "11011011", + "01111011", + "00011011", + "00011011", + "00011011", + "00011011", + "00011011", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "01100000", + "00111000", + "01101100", + "11000110", + "11000110", + "01101100", + "00111000", + "00001100", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111110", + "11111110", + "11111110", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00111100", + "01111110", + "00011000", + "00011000", + "00011000", + "01111110", + "00111100", + "00011000", + "01111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00111100", + "01111110", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "01111110", + "00111100", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00001100", + "11111110", + "00001100", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00110000", + "01100000", + "11111110", + "01100000", + "00110000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000000", + "11000000", + "11000000", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00101000", + "01101100", + "11111110", + "01101100", + "00101000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00010000", + "00111000", + "00111000", + "01111100", + "01111100", + "11111110", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111110", + "11111110", + "01111100", + "01111100", + "00111000", + "00111000", + "00010000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00111100", + "00111100", + "00111100", + "00011000", + "00011000", + "00011000", + "00000000", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100110", + "01100110", + "01100110", + "00100100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01101100", + "01101100", + "11111110", + "01101100", + "01101100", + "01101100", + "11111110", + "01101100", + "01101100", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "01111100", + "11000110", + "11000010", + "11000000", + "01111100", + "00000110", + "00000110", + "10000110", + "11000110", + "01111100", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000010", + "11000110", + "00001100", + "00011000", + "00110000", + "01100000", + "11000110", + "10000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111000", + "01101100", + "01101100", + "00111000", + "01110110", + "11011100", + "11001100", + "11001100", + "11001100", + "01110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00110000", + "00110000", + "00110000", + "01100000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00001100", + "00011000", + "00110000", + "00110000", + "00110000", + "00110000", + "00110000", + "00110000", + "00011000", + "00001100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00110000", + "00011000", + "00001100", + "00001100", + "00001100", + "00001100", + "00001100", + "00001100", + "00011000", + "00110000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100110", + "00111100", + "11111111", + "00111100", + "01100110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "01111110", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "00011000", + "00110000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000010", + "00000110", + "00001100", + "00011000", + "00110000", + "01100000", + "11000000", + "10000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111000", + "01101100", + "11000110", + "11000110", + "11010110", + "11010110", + "11000110", + "11000110", + "01101100", + "00111000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00111000", + "01111000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "01111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "00000110", + "00001100", + "00011000", + "00110000", + "01100000", + "11000000", + "11000110", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "00000110", + "00000110", + "00111100", + "00000110", + "00000110", + "00000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00001100", + "00011100", + "00111100", + "01101100", + "11001100", + "11111110", + "00001100", + "00001100", + "00001100", + "00011110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111110", + "11000000", + "11000000", + "11000000", + "11111100", + "00000110", + "00000110", + "00000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111000", + "01100000", + "11000000", + "11000000", + "11111100", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111110", + "11000110", + "00000110", + "00000110", + "00001100", + "00011000", + "00110000", + "00110000", + "00110000", + "00110000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "01111110", + "00000110", + "00000110", + "00000110", + "00001100", + "01111000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "00110000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000110", + "00001100", + "00011000", + "00110000", + "01100000", + "00110000", + "00011000", + "00001100", + "00000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111110", + "00000000", + "00000000", + "01111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100000", + "00110000", + "00011000", + "00001100", + "00000110", + "00001100", + "00011000", + "00110000", + "01100000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "11000110", + "00001100", + "00011000", + "00011000", + "00011000", + "00000000", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "11000110", + "11011110", + "11011110", + "11011110", + "11011100", + "11000000", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00010000", + "00111000", + "01101100", + "11000110", + "11000110", + "11111110", + "11000110", + "11000110", + "11000110", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111100", + "01100110", + "01100110", + "01100110", + "01111100", + "01100110", + "01100110", + "01100110", + "01100110", + "11111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111100", + "01100110", + "11000010", + "11000000", + "11000000", + "11000000", + "11000000", + "11000010", + "01100110", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111000", + "01101100", + "01100110", + "01100110", + "01100110", + "01100110", + "01100110", + "01100110", + "01101100", + "11111000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111110", + "01100110", + "01100010", + "01101000", + "01111000", + "01101000", + "01100000", + "01100010", + "01100110", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111110", + "01100110", + "01100010", + "01101000", + "01111000", + "01101000", + "01100000", + "01100000", + "01100000", + "11110000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111100", + "01100110", + "11000010", + "11000000", + "11000000", + "11011110", + "11000110", + "11000110", + "01100110", + "00111010", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "11000110", + "11000110", + "11000110", + "11111110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111100", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011110", + "00001100", + "00001100", + "00001100", + "00001100", + "00001100", + "11001100", + "11001100", + "11001100", + "01111000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11100110", + "01100110", + "01100110", + "01101100", + "01111000", + "01111000", + "01101100", + "01100110", + "01100110", + "11100110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11110000", + "01100000", + "01100000", + "01100000", + "01100000", + "01100000", + "01100000", + "01100010", + "01100110", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "11101110", + "11111110", + "11111110", + "11010110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "11100110", + "11110110", + "11111110", + "11011110", + "11001110", + "11000110", + "11000110", + "11000110", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111100", + "01100110", + "01100110", + "01100110", + "01111100", + "01100000", + "01100000", + "01100000", + "01100000", + "11110000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11010110", + "11011110", + "01111100", + "00001100", + "00001110", + "00000000", + "00000000", + "00000000", + "00000000", + "11111100", + "01100110", + "01100110", + "01100110", + "01111100", + "01101100", + "01100110", + "01100110", + "01100110", + "11100110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "11000110", + "01100000", + "00111000", + "00001100", + "00000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111110", + "01111110", + "01011010", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01101100", + "00111000", + "00010000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "11000110", + "11000110", + "11000110", + "11010110", + "11010110", + "11010110", + "11111110", + "11101110", + "01101100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "11000110", + "01101100", + "01111100", + "00111000", + "00111000", + "01111100", + "01101100", + "11000110", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100110", + "01100110", + "01100110", + "01100110", + "00111100", + "00011000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111110", + "11000110", + "10000110", + "00001100", + "00011000", + "00110000", + "01100000", + "11000010", + "11000110", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111100", + "00110000", + "00110000", + "00110000", + "00110000", + "00110000", + "00110000", + "00110000", + "00110000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "10000000", + "11000000", + "11100000", + "01110000", + "00111000", + "00011100", + "00001110", + "00000110", + "00000010", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111100", + "00001100", + "00001100", + "00001100", + "00001100", + "00001100", + "00001100", + "00001100", + "00001100", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00010000", + "00111000", + "01101100", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111111", + "00000000", + "00000000", + "00000000", + "00110000", + "00011000", + "00001100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111000", + "00001100", + "01111100", + "11001100", + "11001100", + "11001100", + "01110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11100000", + "01100000", + "01100000", + "01111000", + "01101100", + "01100110", + "01100110", + "01100110", + "01100110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "11000000", + "11000000", + "11000000", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011100", + "00001100", + "00001100", + "00111100", + "01101100", + "11001100", + "11001100", + "11001100", + "11001100", + "01110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "11111110", + "11000000", + "11000000", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011100", + "00110110", + "00110010", + "00110000", + "01111000", + "00110000", + "00110000", + "00110000", + "00110000", + "01111000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01110110", + "11001100", + "11001100", + "11001100", + "11001100", + "11001100", + "01111100", + "00001100", + "11001100", + "01111000", + "00000000", + "00000000", + "00000000", + "11100000", + "01100000", + "01100000", + "01101100", + "01110110", + "01100110", + "01100110", + "01100110", + "01100110", + "11100110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "00000000", + "00111000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000110", + "00000110", + "00000000", + "00001110", + "00000110", + "00000110", + "00000110", + "00000110", + "00000110", + "00000110", + "01100110", + "01100110", + "00111100", + "00000000", + "00000000", + "00000000", + "11100000", + "01100000", + "01100000", + "01100110", + "01101100", + "01111000", + "01111000", + "01101100", + "01100110", + "11100110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11101100", + "11111110", + "11010110", + "11010110", + "11010110", + "11010110", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11011100", + "01100110", + "01100110", + "01100110", + "01100110", + "01100110", + "01100110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11011100", + "01100110", + "01100110", + "01100110", + "01100110", + "01100110", + "01111100", + "01100000", + "01100000", + "11110000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01110110", + "11001100", + "11001100", + "11001100", + "11001100", + "11001100", + "01111100", + "00001100", + "00001100", + "00011110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11011100", + "01110110", + "01100110", + "01100000", + "01100000", + "01100000", + "11110000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "01100000", + "00111000", + "00001100", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00010000", + "00110000", + "00110000", + "11111100", + "00110000", + "00110000", + "00110000", + "00110000", + "00110110", + "00011100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11001100", + "11001100", + "11001100", + "11001100", + "11001100", + "11001100", + "01110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01101100", + "00111000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "11000110", + "11010110", + "11010110", + "11010110", + "11111110", + "01101100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "01101100", + "00111000", + "00111000", + "00111000", + "01101100", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111110", + "00000110", + "00001100", + "11111000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111110", + "11001100", + "00011000", + "00110000", + "01100000", + "11000110", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00001110", + "00011000", + "00011000", + "00011000", + "01110000", + "00011000", + "00011000", + "00011000", + "00011000", + "00001110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01110000", + "00011000", + "00011000", + "00011000", + "00001110", + "00011000", + "00011000", + "00011000", + "00011000", + "01110000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01110110", + "11011100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00010000", + "00111000", + "01101100", + "11000110", + "11000110", + "11000110", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111100", + "01100110", + "11000010", + "11000000", + "11000000", + "11000000", + "11000000", + "11000010", + "01100110", + "00111100", + "00011000", + "01110000", + "00000000", + "00000000", + "00000000", + "00000000", + "11001100", + "00000000", + "00000000", + "11001100", + "11001100", + "11001100", + "11001100", + "11001100", + "11001100", + "01110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00001100", + "00011000", + "00110000", + "00000000", + "01111100", + "11000110", + "11111110", + "11000000", + "11000000", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00010000", + "00111000", + "01101100", + "00000000", + "01111000", + "00001100", + "01111100", + "11001100", + "11001100", + "11001100", + "01110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11001100", + "00000000", + "00000000", + "01111000", + "00001100", + "01111100", + "11001100", + "11001100", + "11001100", + "01110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100000", + "00110000", + "00011000", + "00000000", + "01111000", + "00001100", + "01111100", + "11001100", + "11001100", + "11001100", + "01110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111000", + "01101100", + "00111000", + "00000000", + "01111000", + "00001100", + "01111100", + "11001100", + "11001100", + "11001100", + "01110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "11000000", + "11000000", + "11000000", + "11000110", + "01111100", + "00011000", + "01110000", + "00000000", + "00000000", + "00000000", + "00010000", + "00111000", + "01101100", + "00000000", + "01111100", + "11000110", + "11111110", + "11000000", + "11000000", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "00000000", + "00000000", + "01111100", + "11000110", + "11111110", + "11000000", + "11000000", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100000", + "00110000", + "00011000", + "00000000", + "01111100", + "11000110", + "11111110", + "11000000", + "11000000", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100110", + "00000000", + "00000000", + "00111000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00111100", + "01100110", + "00000000", + "00111000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100000", + "00110000", + "00011000", + "00000000", + "00111000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "00000000", + "00010000", + "00111000", + "01101100", + "11000110", + "11000110", + "11111110", + "11000110", + "11000110", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00111000", + "01101100", + "00111000", + "00010000", + "00111000", + "01101100", + "11000110", + "11000110", + "11111110", + "11000110", + "11000110", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00001100", + "00011000", + "00000000", + "11111110", + "01100110", + "01100010", + "01101000", + "01111000", + "01101000", + "01100010", + "01100110", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11101100", + "00110110", + "00110110", + "01111110", + "11011000", + "11011000", + "01101110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111110", + "01101100", + "11001100", + "11001100", + "11111110", + "11001100", + "11001100", + "11001100", + "11001100", + "11001110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00010000", + "00111000", + "01101100", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "00000000", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100000", + "00110000", + "00011000", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00110000", + "01111000", + "11001100", + "00000000", + "11001100", + "11001100", + "11001100", + "11001100", + "11001100", + "11001100", + "01110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100000", + "00110000", + "00011000", + "00000000", + "11001100", + "11001100", + "11001100", + "11001100", + "11001100", + "11001100", + "01110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "00000000", + "00000000", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111110", + "00000110", + "00001100", + "01111000", + "00000000", + "00000000", + "11000110", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "00000000", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11001110", + "11011110", + "11110110", + "11100110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111000", + "01101100", + "01100100", + "01100000", + "11110000", + "01100000", + "01100000", + "01100000", + "01100000", + "11100110", + "11111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000100", + "01111100", + "11001110", + "11001110", + "11010110", + "11010110", + "11010110", + "11010110", + "11100110", + "11100110", + "01111100", + "01000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "01101100", + "00111000", + "00111000", + "01101100", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00001110", + "00011011", + "00011000", + "00011000", + "00011000", + "01111110", + "00011000", + "00011000", + "00011000", + "11011000", + "01110000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00110000", + "01100000", + "00000000", + "01111000", + "00001100", + "01111100", + "11001100", + "11001100", + "11001100", + "01110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00001100", + "00011000", + "00110000", + "00000000", + "00111000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00110000", + "01100000", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00110000", + "01100000", + "00000000", + "11001100", + "11001100", + "11001100", + "11001100", + "11001100", + "11001100", + "01110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01110110", + "11011100", + "00000000", + "11011100", + "01100110", + "01100110", + "01100110", + "01100110", + "01100110", + "01100110", + "00000000", + "00000000", + "00000000", + "00000000", + "01110110", + "11011100", + "00000000", + "11000110", + "11100110", + "11110110", + "11111110", + "11011110", + "11001110", + "11000110", + "11000110", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111100", + "01101100", + "01101100", + "00111110", + "00000000", + "01111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111000", + "01101100", + "01101100", + "00111000", + "00000000", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00110000", + "00110000", + "00000000", + "00110000", + "00110000", + "01100000", + "11000000", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "10000010", + "10110010", + "10101010", + "10110010", + "10101010", + "10101010", + "10000010", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111110", + "00000110", + "00000110", + "00000110", + "00000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100000", + "11100000", + "01100010", + "01100110", + "01101100", + "00011000", + "00110000", + "01100000", + "11011100", + "10000110", + "00001100", + "00011000", + "00111110", + "00000000", + "00000000", + "00000000", + "01100000", + "11100000", + "01100010", + "01100110", + "01101100", + "00011000", + "00110000", + "01100110", + "11001110", + "10011010", + "00111111", + "00000110", + "00000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "00000000", + "00011000", + "00011000", + "00011000", + "00111100", + "00111100", + "00111100", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00110110", + "01101100", + "11011000", + "01101100", + "00110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11011000", + "01101100", + "00110110", + "01101100", + "11011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00010001", + "01000100", + "00010001", + "01000100", + "00010001", + "01000100", + "00010001", + "01000100", + "00010001", + "01000100", + "00010001", + "01000100", + "00010001", + "01000100", + "00010001", + "01000100", + "01010101", + "10101010", + "01010101", + "10101010", + "01010101", + "10101010", + "01010101", + "10101010", + "01010101", + "10101010", + "01010101", + "10101010", + "01010101", + "10101010", + "01010101", + "10101010", + "11011101", + "01110111", + "11011101", + "01110111", + "11011101", + "01110111", + "11011101", + "01110111", + "11011101", + "01110111", + "11011101", + "01110111", + "11011101", + "01110111", + "11011101", + "01110111", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "11111000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "01100000", + "11000000", + "00010000", + "00111000", + "01101100", + "11000110", + "11000110", + "11111110", + "11000110", + "11000110", + "11000110", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "00010000", + "00111000", + "01101100", + "11000110", + "11000110", + "11111110", + "11000110", + "11000110", + "11000110", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00001100", + "00000110", + "00010000", + "00111000", + "01101100", + "11000110", + "11000110", + "11111110", + "11000110", + "11000110", + "11000110", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "10000010", + "10011010", + "10100010", + "10100010", + "10100010", + "10011010", + "10000010", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "11110110", + "00000110", + "11110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111110", + "00000110", + "11110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "11110110", + "00000110", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "01111100", + "11000110", + "11000000", + "11000000", + "11000110", + "01111100", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100110", + "01100110", + "00111100", + "00011000", + "01111110", + "00011000", + "01111110", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011111", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "11111111", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111111", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011111", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111111", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "11111111", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00000000", + "00000000", + "01110110", + "11011100", + "00000000", + "01111000", + "00001100", + "01111100", + "11001100", + "11001100", + "11001100", + "01110110", + "00000000", + "00000000", + "00000000", + "00000000", + "01110110", + "11011100", + "00000000", + "00111000", + "01101100", + "11000110", + "11000110", + "11111110", + "11000110", + "11000110", + "11000110", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110111", + "00110000", + "00111111", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111111", + "00110000", + "00110111", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "11110111", + "00000000", + "11111111", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111111", + "00000000", + "11110111", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110111", + "00110000", + "00110111", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111111", + "00000000", + "11111111", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "11110111", + "00000000", + "11110111", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00110110", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00110100", + "00011000", + "00101100", + "00000110", + "00111110", + "01100110", + "01100110", + "01100110", + "01100110", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111000", + "01101100", + "01100110", + "01100110", + "11110110", + "01100110", + "01100110", + "01100110", + "01101100", + "11111000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111000", + "01101100", + "00000000", + "11111110", + "01100110", + "01100010", + "01101000", + "01111000", + "01101000", + "01100010", + "01100110", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "00000000", + "11111110", + "01100110", + "01100010", + "01101000", + "01111000", + "01101000", + "01100010", + "01100110", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00110000", + "00011000", + "00000000", + "11111110", + "01100110", + "01100010", + "01101000", + "01111000", + "01101000", + "01100010", + "01100110", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00001100", + "00011000", + "00000000", + "00111100", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00111100", + "01100110", + "00000000", + "00111100", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100110", + "00000000", + "00111100", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "11111000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011111", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "00000000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00000000", + "00000000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00000000", + "00000000", + "00000000", + "00110000", + "00011000", + "00000000", + "00111100", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "11111111", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00110000", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111000", + "11001100", + "11001100", + "11001100", + "11011000", + "11001100", + "11000110", + "11000110", + "11000110", + "11001100", + "00000000", + "00000000", + "00000000", + "00000000", + "00111000", + "01101100", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00110000", + "00011000", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01110110", + "11011100", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "01110110", + "11011100", + "00000000", + "01111100", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01100110", + "01100110", + "01100110", + "01100110", + "01100110", + "01100110", + "01111100", + "01100000", + "01100000", + "11000000", + "00000000", + "00000000", + "00000000", + "11100000", + "01100000", + "01100000", + "01111100", + "01100110", + "01100110", + "01100110", + "01100110", + "01100110", + "01111100", + "01100000", + "01100000", + "11110000", + "00000000", + "00000000", + "00000000", + "11110000", + "01100000", + "01111100", + "01100110", + "01100110", + "01100110", + "01100110", + "01111100", + "01100000", + "11110000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00110000", + "00000000", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00111000", + "01101100", + "00000000", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00110000", + "00011000", + "00000000", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00001100", + "00011000", + "00110000", + "00000000", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "11000110", + "01111110", + "00000110", + "00001100", + "11111000", + "00000000", + "00001100", + "00011000", + "00000000", + "01100110", + "01100110", + "01100110", + "01100110", + "00111100", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111111", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00001100", + "00011000", + "00110000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00011000", + "01111110", + "00011000", + "00011000", + "00000000", + "00000000", + "01111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11111111", + "00000000", + "11111111", + "00000000", + "00000000", + "11100000", + "00110000", + "01100010", + "00110110", + "11101100", + "00011000", + "00110000", + "01100110", + "11001110", + "10011010", + "00111111", + "00000110", + "00000110", + "00000000", + "00000000", + "00000000", + "00000000", + "01111111", + "11011011", + "11011011", + "11011011", + "01111011", + "00011011", + "00011011", + "00011011", + "00011011", + "00011011", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "11000110", + "01100000", + "00111000", + "01101100", + "11000110", + "11000110", + "01101100", + "00111000", + "00001100", + "11000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00000000", + "01111110", + "00000000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00001100", + "01111000", + "00000000", + "00000000", + "00000000", + "00111000", + "01101100", + "01101100", + "00111000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "11000110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00011000", + "00111000", + "00011000", + "00011000", + "00011000", + "00111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111100", + "00000110", + "00111100", + "00000110", + "00000110", + "01111100", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00111100", + "01100110", + "00001100", + "00011000", + "00110010", + "01111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "01111110", + "01111110", + "01111110", + "01111110", + "01111110", + "01111110", + "01111110", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000", + "00000000" + ); +end package font_pkg; diff --git a/src/textmode_vga/font_rom.vhd b/src/textmode_vga/font_rom.vhd new file mode 100644 index 0000000..ddbfc97 --- /dev/null +++ b/src/textmode_vga/font_rom.vhd @@ -0,0 +1,25 @@ +------------------------------------------------------------------------- +-- +-- Filename: font_rom.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Font ROM entity declaraton +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use work.font_pkg.all; +use work.math_pkg.all; + +entity font_rom is + port + ( + vga_clk : in std_logic; + char : in std_logic_vector(log2c(CHAR_COUNT) - 1 downto 0); + char_height_pixel : in std_logic_vector(log2c(CHAR_HEIGHT) - 1 downto 0); + decoded_char : out std_logic_vector(0 to CHAR_WIDTH - 1) + ); +end entity font_rom; diff --git a/src/textmode_vga/font_rom_beh.vhd b/src/textmode_vga/font_rom_beh.vhd new file mode 100644 index 0000000..c01a3c0 --- /dev/null +++ b/src/textmode_vga/font_rom_beh.vhd @@ -0,0 +1,27 @@ +------------------------------------------------------------------------- +-- +-- Filename: font_rom_beh.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Behavioral architecture of the font ROM entity. +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.font_pkg.all; + +architecture beh of font_rom is +begin + process(vga_clk) + variable address : std_logic_vector(log2c(CHAR_COUNT) + log2c(CHAR_HEIGHT) - 1 downto 0); + begin + if rising_edge(vga_clk) then + address := char & char_height_pixel; + decoded_char <= FONT_TABLE(to_integer(unsigned(address))); + end if; + end process; +end architecture beh; diff --git a/src/textmode_vga/interval.vhd b/src/textmode_vga/interval.vhd new file mode 100644 index 0000000..f8c8aca --- /dev/null +++ b/src/textmode_vga/interval.vhd @@ -0,0 +1,27 @@ +------------------------------------------------------------------------- +-- +-- Filename: interval.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Interval timer entity declaraton. +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity interval is + generic + ( + CLK_FREQ : integer; + INTERVAL_TIME_MS : integer + ); + port + ( + clk : in std_logic; + res_n : in std_logic; + active : out std_logic + ); +end entity interval; diff --git a/src/textmode_vga/interval_beh.vhd b/src/textmode_vga/interval_beh.vhd new file mode 100644 index 0000000..e8da284 --- /dev/null +++ b/src/textmode_vga/interval_beh.vhd @@ -0,0 +1,36 @@ +------------------------------------------------------------------------- +-- +-- Filename: interval_beh.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Behavioral implementaiton of the interval timer +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +architecture beh of interval is + constant CNT_MAX : integer := INTERVAL_TIME_MS * (CLK_FREQ / 1000); + signal cnt : integer range 0 to CNT_MAX - 1; + signal active_int : std_logic; +begin + active <= active_int; + process(clk, res_n) + begin + if res_n = '0' then + cnt <= 0; + active_int <= '0'; + elsif rising_edge(clk) then + if cnt < CNT_MAX - 1 then + cnt <= cnt + 1; + else + cnt <= 0; + active_int <= not active_int; + end if; + end if; + end process; +end architecture beh; + \ No newline at end of file diff --git a/src/textmode_vga/mjl_stratix/textmode_vga_platform_dependent_pkg.vhd b/src/textmode_vga/mjl_stratix/textmode_vga_platform_dependent_pkg.vhd new file mode 100644 index 0000000..32ae139 --- /dev/null +++ b/src/textmode_vga/mjl_stratix/textmode_vga_platform_dependent_pkg.vhd @@ -0,0 +1,20 @@ +------------------------------------------------------------------------- +-- +-- Filename: textmode_vga_platform_dependent_pkg.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Platform depnded declarations used within the textmode +-- VGA controller implementation. +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package textmode_vga_platform_dependent_pkg is + constant RED_BITS : integer := 3; + constant GREEN_BITS : integer := 3; + constant BLUE_BITS : integer := 2; +end package textmode_vga_platform_dependent_pkg; diff --git a/src/textmode_vga/textmode_vga.vhd b/src/textmode_vga/textmode_vga.vhd new file mode 100644 index 0000000..26cf04c --- /dev/null +++ b/src/textmode_vga/textmode_vga.vhd @@ -0,0 +1,43 @@ +------------------------------------------------------------------------- +-- +-- Filename: textmode_vga.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Toplevel entity of the textmode VGA controller. +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use work.textmode_vga_pkg.all; +use work.textmode_vga_platform_dependent_pkg.all; + +entity textmode_vga is + generic + ( + -- Clock frequency used as basis for the VGA timing + VGA_CLK_FREQ : integer; + -- Blink interval of the cursor give in miliseconds + BLINK_INTERVAL_MS : integer; + -- Number of stages used in synchronizers + SYNC_STAGES : integer + ); + port + ( + -- Interface to user logic + sys_clk, sys_res_n : in std_logic; + command : in std_logic_vector(COMMAND_SIZE - 1 downto 0); + command_data : in std_logic_vector(3 * COLOR_SIZE + CHAR_SIZE - 1 downto 0); + free : out std_logic; + + -- External VGA interface + vga_clk, vga_res_n : in std_logic; + vsync_n : out std_logic; + hsync_n : out std_logic; + r : out std_logic_vector(RED_BITS - 1 downto 0); + g : out std_logic_vector(GREEN_BITS - 1 downto 0); + b : out std_logic_vector(BLUE_BITS - 1 downto 0) + ); +end entity textmode_vga; diff --git a/src/textmode_vga/textmode_vga_component_pkg.vhd b/src/textmode_vga/textmode_vga_component_pkg.vhd new file mode 100644 index 0000000..1ff5c3e --- /dev/null +++ b/src/textmode_vga/textmode_vga_component_pkg.vhd @@ -0,0 +1,176 @@ +------------------------------------------------------------------------- +-- +-- Filename: textmode_vga_component_pkg.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- This package contains the declaration of all componets +-- used within the textmode VGA controller implementation. +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.math_pkg.all; +use work.textmode_vga_pkg.all; +use work.font_pkg.all; +use work.textmode_vga_platform_dependent_pkg.all; + +package textmode_vga_component_pkg is + component textmode_vga_h_sm is + port + ( + sys_clk, sys_res_n : in std_logic; + + background_color : in std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + + char_cnt : out std_logic_vector(log2c(COLUMN_COUNT) - 1 downto 0); + char_line_cnt : in std_logic_vector(log2c(LINE_COUNT) - 1 downto 0); + cursor_column : in std_logic_vector(log2c(COLUMN_COUNT) - 1 downto 0); + cursor_line : in std_logic_vector(log2c(LINE_COUNT) - 1 downto 0); + cursor_color : in std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + cursor_state : in CURSOR_STATE_TYPE; + decoded_char : in std_logic_vector(0 to CHAR_WIDTH - 1); + color : in std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + + is_data_line : in std_logic; + is_eol : out std_logic; + + hsync_n : out std_logic; + rgb : out std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + blink : in std_logic + ); + end component textmode_vga_h_sm; + + component textmode_vga_v_sm is + port + ( + sys_clk, sys_res_n : in std_logic; + + is_data_line : out std_logic; + char_line_cnt : out std_logic_vector(log2c(LINE_COUNT) - 1 downto 0); + char_height_pixel : out std_logic_vector(log2c(CHAR_HEIGHT) - 1 downto 0); + is_eol : in std_logic; + + vsync_n : out std_logic + ); + end component textmode_vga_v_sm; + + component textmode_vga is + generic + ( + VGA_CLK_FREQ : integer; + BLINK_INTERVAL_MS : integer; + SYNC_STAGES : integer + ); + port + ( + sys_clk, sys_res_n : in std_logic; + command : in std_logic_vector(COMMAND_SIZE - 1 downto 0); + command_data : in std_logic_vector(3 * COLOR_SIZE + CHAR_SIZE - 1 downto 0); + free : out std_logic; + + vga_clk, vga_res_n : in std_logic; + vsync_n : out std_logic; + hsync_n : out std_logic; + r : out std_logic_vector(RED_BITS - 1 downto 0); + g : out std_logic_vector(GREEN_BITS - 1 downto 0); + b : out std_logic_vector(BLUE_BITS - 1 downto 0) + ); + end component textmode_vga; + + component video_memory is + generic + ( + DATA_WIDTH : integer; + ROW_ADDR_WIDTH : integer; + COL_ADDR_WIDTH : integer + ); + port + ( + vga_clk : in std_logic; + vga_row_address : in std_logic_vector(ROW_ADDR_WIDTH - 1 downto 0); + vga_col_address : in std_logic_vector(COL_ADDR_WIDTH - 1 downto 0); + vga_data : out std_logic_vector(DATA_WIDTH - 1 downto 0); + sm_row_address : in std_logic_vector(ROW_ADDR_WIDTH - 1 downto 0); + sm_col_address : in std_logic_vector(COL_ADDR_WIDTH - 1 downto 0); + sm_data : in std_logic_vector(DATA_WIDTH - 1 downto 0); + sm_wr : in std_logic; + sm_scroll_address : in std_logic_vector(ROW_ADDR_WIDTH - 1 downto 0) + ); + end component video_memory; + + component pll is + port + ( + inclk0 : in std_logic; + c0 : out std_logic + ); + end component pll; + + component console_sm is + port + ( + vga_clk, vga_res_n : in std_logic; + command : in std_logic_vector(COMMAND_SIZE - 1 downto 0); + command_data : in std_logic_vector(3 * COLOR_SIZE + CHAR_SIZE - 1 downto 0); + command_req : in std_logic; + ack : out std_logic; + + column_address : out std_logic_vector(log2c(COLUMN_COUNT) - 1 downto 0); + row_address : out std_logic_vector(log2c(LINE_COUNT) - 1 downto 0); + data : out std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS + CHAR_SIZE - 1 downto 0); + wr : out std_logic; + scroll_address : out std_logic_vector(log2c(LINE_COUNT) - 1 downto 0); + background_color : out std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + cursor_color : out std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + cursor_state : out CURSOR_STATE_TYPE + ); + end component console_sm; + + component font_rom is + port + ( + vga_clk : in std_logic; + char : in std_logic_vector(log2c(CHAR_COUNT) - 1 downto 0); + char_height_pixel : in std_logic_vector(log2c(CHAR_HEIGHT) - 1 downto 0); + decoded_char : out std_logic_vector(0 to CHAR_WIDTH - 1) + ); + end component font_rom; + + component console_sm_sync is + generic + ( + SYNC_STAGES : integer + ); + port + ( + sys_clk, sys_res_n : in std_logic; + command_sys : in std_logic_vector(COMMAND_SIZE - 1 downto 0); + command_data_sys : in std_logic_vector(3 * COLOR_SIZE + CHAR_SIZE - 1 downto 0); + free_sys : out std_logic; + + vga_clk, vga_res_n : in std_logic; + command_vga : out std_logic_vector(COMMAND_SIZE - 1 downto 0); + command_data_vga : out std_logic_vector(3 * COLOR_SIZE + CHAR_SIZE - 1 downto 0); + command_req_vga : out std_logic; + ack_vga : in std_logic + ); + end component console_sm_sync; + + component interval is + generic + ( + CLK_FREQ : integer; + INTERVAL_TIME_MS : integer + ); + port + ( + clk : in std_logic; + res_n : in std_logic; + active : out std_logic + ); + end component interval; +end package textmode_vga_component_pkg; \ No newline at end of file diff --git a/src/textmode_vga/textmode_vga_h_sm.vhd b/src/textmode_vga/textmode_vga_h_sm.vhd new file mode 100644 index 0000000..785e786 --- /dev/null +++ b/src/textmode_vga/textmode_vga_h_sm.vhd @@ -0,0 +1,42 @@ +------------------------------------------------------------------------- +-- +-- Filename: textmode_vga_h_sm.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Entity declaration of the horizontal VGA timing finite state machine +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use work.math_pkg.all; +use work.textmode_vga_pkg.all; +use work.textmode_vga_platform_dependent_pkg.all; +use work.font_pkg.all; + +entity textmode_vga_h_sm is + port + ( + sys_clk, sys_res_n : in std_logic; + + background_color : in std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + + char_cnt : out std_logic_vector(log2c(COLUMN_COUNT) - 1 downto 0); + char_line_cnt : in std_logic_vector(log2c(LINE_COUNT) - 1 downto 0); + cursor_column : in std_logic_vector(log2c(COLUMN_COUNT) - 1 downto 0); + cursor_line : in std_logic_vector(log2c(LINE_COUNT) - 1 downto 0); + cursor_color : in std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + cursor_state : in CURSOR_STATE_TYPE; + decoded_char : in std_logic_vector(0 to CHAR_WIDTH - 1); + color : in std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + + is_data_line : in std_logic; + is_eol : out std_logic; + + hsync_n : out std_logic; + rgb : out std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + blink : in std_logic + ); +end entity textmode_vga_h_sm; diff --git a/src/textmode_vga/textmode_vga_h_sm_beh.vhd b/src/textmode_vga/textmode_vga_h_sm_beh.vhd new file mode 100644 index 0000000..5314bdd --- /dev/null +++ b/src/textmode_vga/textmode_vga_h_sm_beh.vhd @@ -0,0 +1,243 @@ +------------------------------------------------------------------------- +-- +-- Filename: textmode_vga_h_sm_beh.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Behavioural implementation of the horizontal VGA timing finite state machine +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.math_pkg.all; +use work.textmode_vga_pkg.all; +use work.font_pkg.all; + +architecture beh of textmode_vga_h_sm is + type TEXTMODE_VGA_H_SM_STATE_TYPE is + ( + HSYNC_FIRST, HSYNC, HBACK_FIRST, HBACK, BLACK_CHAR_NEW, + BLACK_PIXEL, CHAR_NEW_FG, PIXEL_FG, CHAR_NEW_BG, PIXEL_BG, + HFRONT_FIRST, HFRONT, HFRONT_LAST, CHAR_NEW_CURSOR, PIXEL_CURSOR + ); + signal textmode_vga_h_sm_state, textmode_vga_h_sm_state_next : TEXTMODE_VGA_H_SM_STATE_TYPE; + signal hcnt, hcnt_next : integer range 0 to max(HSYNC_CYCLES, HBACK_CYCLES, HFRONT_CYCLES); + signal current_char, current_char_next : std_logic_vector(0 to CHAR_WIDTH - 1); + signal current_color, current_color_next : std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + signal char_width_pixel, char_width_pixel_next : integer range 0 to CHAR_WIDTH; + signal char_cnt_int, char_cnt_next : integer range 0 to COLUMN_COUNT; +begin + char_cnt <= std_logic_vector(to_unsigned(char_cnt_int, log2c(COLUMN_COUNT))); + + h_sm_next_state : process(textmode_vga_h_sm_state, hcnt, is_data_line, decoded_char, char_width_pixel, current_char, char_cnt_int, char_line_cnt, blink, cursor_line, cursor_column, cursor_state) + begin + textmode_vga_h_sm_state_next <= textmode_vga_h_sm_state; + case textmode_vga_h_sm_state is + when HSYNC_FIRST => + textmode_vga_h_sm_state_next <= HSYNC; + when HSYNC => + if hcnt = HSYNC_CYCLES - 1 then + textmode_vga_h_sm_state_next <= HBACK_FIRST; + end if; + when HBACK_FIRST => + textmode_vga_h_sm_state_next <= HBACK; + when HBACK => + if hcnt = HBACK_CYCLES - 1 then + if is_data_line = '0' then + textmode_vga_h_sm_state_next <= BLACK_CHAR_NEW; + else + if (cursor_state = CURSOR_ON or + (cursor_state = CURSOR_BLINK and blink = '0')) and + char_line_cnt = cursor_line and + std_logic_vector(to_unsigned(char_cnt_int, log2c(COLUMN_COUNT))) = cursor_column then + textmode_vga_h_sm_state_next <= CHAR_NEW_CURSOR; + elsif decoded_char(0) = '1' then + textmode_vga_h_sm_state_next <= CHAR_NEW_FG; + else + textmode_vga_h_sm_state_next <= CHAR_NEW_BG; + end if; + end if; + end if; + when BLACK_CHAR_NEW => + textmode_vga_h_sm_state_next <= BLACK_PIXEL; + when BLACK_PIXEL => + if char_width_pixel = CHAR_WIDTH - 1 then + if char_cnt_int = COLUMN_COUNT then + textmode_vga_h_sm_state_next <= HFRONT_FIRST; + else + textmode_vga_h_sm_state_next <= BLACK_CHAR_NEW; + end if; + end if; + when CHAR_NEW_FG => + if decoded_char(1) = '1' then + textmode_vga_h_sm_state_next <= PIXEL_FG; + else + textmode_vga_h_sm_state_next <= PIXEL_BG; + end if; + when CHAR_NEW_CURSOR => + textmode_vga_h_sm_state_next <= PIXEL_CURSOR; + when PIXEL_FG => + if char_width_pixel = CHAR_WIDTH - 1 then + if char_cnt_int = COLUMN_COUNT then + textmode_vga_h_sm_state_next <= HFRONT_FIRST; + else + if (cursor_state = CURSOR_ON or + (cursor_state = CURSOR_BLINK and blink = '0')) and + char_line_cnt = cursor_line and + std_logic_vector(to_unsigned(char_cnt_int, log2c(COLUMN_COUNT))) = cursor_column then + textmode_vga_h_sm_state_next <= CHAR_NEW_CURSOR; + elsif decoded_char(0) = '1' then + textmode_vga_h_sm_state_next <= CHAR_NEW_FG; + else + textmode_vga_h_sm_state_next <= CHAR_NEW_BG; + end if; + end if; + else + if current_char(char_width_pixel + 1) = '1' then + textmode_vga_h_sm_state_next <= PIXEL_FG; + else + textmode_vga_h_sm_state_next <= PIXEL_BG; + end if; + end if; + when PIXEL_CURSOR => + if char_width_pixel = CHAR_WIDTH - 1 then + if char_cnt_int = COLUMN_COUNT then + textmode_vga_h_sm_state_next <= HFRONT_FIRST; + else + if decoded_char(0) = '1' then + textmode_vga_h_sm_state_next <= CHAR_NEW_FG; + else + textmode_vga_h_sm_state_next <= CHAR_NEW_BG; + end if; + end if; + end if; + when CHAR_NEW_BG => + if decoded_char(1) = '1' then + textmode_vga_h_sm_state_next <= PIXEL_FG; + else + textmode_vga_h_sm_state_next <= PIXEL_BG; + end if; + when PIXEL_BG => + if char_width_pixel = CHAR_WIDTH - 1 then + if char_cnt_int = COLUMN_COUNT then + textmode_vga_h_sm_state_next <= HFRONT_FIRST; + else + if (cursor_state = CURSOR_ON or + (cursor_state = CURSOR_BLINK and blink = '0')) and + char_line_cnt = cursor_line and + std_logic_vector(to_unsigned(char_cnt_int, log2c(COLUMN_COUNT))) = cursor_column then + textmode_vga_h_sm_state_next <= CHAR_NEW_CURSOR; + elsif decoded_char(0) = '1' then + textmode_vga_h_sm_state_next <= CHAR_NEW_FG; + else + textmode_vga_h_sm_state_next <= CHAR_NEW_BG; + end if; + end if; + else + if current_char(char_width_pixel + 1) = '1' then + textmode_vga_h_sm_state_next <= PIXEL_FG; + else + textmode_vga_h_sm_state_next <= PIXEL_BG; + end if; + end if; + when HFRONT_FIRST => + textmode_vga_h_sm_state_next <= HFRONT; + when HFRONT => + if hcnt = HFRONT_CYCLES - 2 then + textmode_vga_h_sm_state_next <= HFRONT_LAST; + end if; + when HFRONT_LAST => + textmode_vga_h_sm_state_next <= HSYNC_FIRST; + end case; + end process h_sm_next_state; + + h_sm_output : process(textmode_vga_h_sm_state, decoded_char, current_char, background_color, hcnt, char_cnt_int, char_width_pixel, current_color, color, cursor_color) + begin + hsync_n <= '1'; + rgb <= COLOR_BLACK(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) & + COLOR_BLACK(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) & + COLOR_BLACK(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS); + is_eol <= '0'; + hcnt_next <= hcnt; + char_cnt_next <= char_cnt_int; + char_width_pixel_next <= char_width_pixel; + current_char_next <= current_char; + current_color_next <= current_color; + + case textmode_vga_h_sm_state is + when HSYNC_FIRST => + hsync_n <= '0'; + hcnt_next <= 0; + char_cnt_next <= 0; + when HSYNC => + hsync_n <= '0'; + hcnt_next <= hcnt + 1; + when HBACK_FIRST => + hcnt_next <= 0; + when HBACK => + hcnt_next <= hcnt + 1; + when BLACK_CHAR_NEW => + char_cnt_next <= char_cnt_int + 1; + char_width_pixel_next <= 1; + when BLACK_PIXEL => + char_width_pixel_next <= char_width_pixel + 1; + when CHAR_NEW_FG => + rgb <= color; + char_cnt_next <= char_cnt_int + 1; + char_width_pixel_next <= 1; + current_char_next <= decoded_char; + current_color_next <= color; + when PIXEL_FG => + rgb <= current_color; + char_width_pixel_next <= char_width_pixel + 1; + when CHAR_NEW_CURSOR => + rgb <= cursor_color; + char_cnt_next <= char_cnt_int + 1; + char_width_pixel_next <= 1; + current_char_next <= decoded_char; + current_color_next <= color; + when PIXEL_CURSOR => + rgb <= cursor_color; + char_width_pixel_next <= char_width_pixel + 1; + when CHAR_NEW_BG => + rgb <= background_color; + char_cnt_next <= char_cnt_int + 1; + char_width_pixel_next <= 1; + current_char_next <= decoded_char; + current_color_next <= color; + when PIXEL_BG => + rgb <= background_color; + char_width_pixel_next <= char_width_pixel + 1; + when HFRONT_FIRST => + hcnt_next <= 0; + when HFRONT => + hcnt_next <= hcnt + 1; + when HFRONT_LAST => + is_eol <= '1'; + end case; + end process h_sm_output; + + sync : process(sys_clk, sys_res_n) + begin + if sys_res_n = '0' then + textmode_vga_h_sm_state <= HSYNC_FIRST; + hcnt <= 0; + char_cnt_int <= 0; + char_width_pixel <= 0; + current_char <= (others => '0'); + current_color <= COLOR_WHITE(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) & + COLOR_WHITE(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) & + COLOR_WHITE(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS); + elsif rising_edge(sys_clk) then + textmode_vga_h_sm_state <= textmode_vga_h_sm_state_next; + hcnt <= hcnt_next; + char_cnt_int <= char_cnt_next; + char_width_pixel <= char_width_pixel_next; + current_char <= current_char_next; + current_color <= current_color_next; + end if; + end process sync; +end architecture beh; diff --git a/src/textmode_vga/textmode_vga_pkg.vhd b/src/textmode_vga/textmode_vga_pkg.vhd new file mode 100644 index 0000000..7646bad --- /dev/null +++ b/src/textmode_vga/textmode_vga_pkg.vhd @@ -0,0 +1,78 @@ +------------------------------------------------------------------------- +-- +-- Filename: textmode_vga_pkg.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Global declaration needed by the VGA interface. +-- This package contains the declaration of the VGA timing values, +-- the VGA dimensions and the supported commands. +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use work.textmode_vga_platform_dependent_pkg.all; +-- +-- 640x480x60Hz +-- +-- >=144 <784 +-- >=33 --------------- +-- | | +-- | | +-- | | +-- <513 --------------- +-- +-- PixelClock: 25,175 MHz +-- +-- HSync 96 +-- BackP 48 +-- Data 640 +-- FrontP 16 +-- --- +-- 800 +-- +-- Vsync 2 +-- BackP 31 +-- Data 480 +-- FrontP 11 +-- --- +-- 524 +-- + +package textmode_vga_pkg is + constant COLOR_SIZE : integer := 8; + constant CHAR_SIZE : integer := 8; + + constant COLOR_BLACK : std_logic_vector(3 * COLOR_SIZE - 1 downto 0) := (others => '0'); + constant COLOR_WHITE : std_logic_vector(3 * COLOR_SIZE - 1 downto 0) := (others => '1'); + + constant PIXEL_WIDTH : integer := 640; + constant PIXEL_HEIGHT : integer := 480; + constant HSYNC_CYCLES : integer := 96; + constant HBACK_CYCLES : integer := 48; + constant HFRONT_CYCLES : integer := 16; + constant VSYNC_LINES : integer := 2; + constant VBACK_LINES : integer := 31; + constant VFRONT_LINES : integer := 11; + + subtype COLOR_RANGE is natural range COLOR_SIZE + CHAR_SIZE - 1 downto CHAR_SIZE; + subtype VGA_MEMORY_RANGE is natural range COLOR_SIZE + CHAR_SIZE - 1 downto 0; + + constant COMMAND_SIZE : integer := 8; + constant COMMAND_NOP : std_logic_vector(COMMAND_SIZE - 1 downto 0) := x"00"; + constant COMMAND_SET_CHAR : std_logic_vector(COMMAND_SIZE - 1 downto 0) := x"01"; + constant COMMAND_SET_BACKGROUND : std_logic_vector(COMMAND_SIZE - 1 downto 0) := x"02"; + constant COMMAND_SET_CURSOR_STATE : std_logic_vector(COMMAND_SIZE - 1 downto 0) := x"03"; + constant COMMAND_SET_CURSOR_COLOR : std_logic_vector(COMMAND_SIZE - 1 downto 0) := x"04"; + constant COMMAND_SET_CURSOR_COLUMN : std_logic_vector(COMMAND_SIZE - 1 downto 0) := x"05"; + constant COMMAND_SET_CURSOR_LINE : std_logic_vector(COMMAND_SIZE - 1 downto 0) := x"06"; + + constant CHAR_NEW_LINE : std_logic_vector(CHAR_SIZE - 1 downto 0) := x"0A"; + constant CHAR_CARRIAGE_RETURN : std_logic_vector(CHAR_SIZE - 1 downto 0) := x"0D"; + constant CHAR_NULL : std_logic_vector(CHAR_SIZE - 1 downto 0) := x"00"; + + type CURSOR_STATE_TYPE is (CURSOR_OFF, CURSOR_ON, CURSOR_BLINK); + constant CURSOR_BLINK_INTERVAL_MS : integer := 500; +end package textmode_vga_pkg; diff --git a/src/textmode_vga/textmode_vga_struct.vhd b/src/textmode_vga/textmode_vga_struct.vhd new file mode 100644 index 0000000..69cea9b --- /dev/null +++ b/src/textmode_vga/textmode_vga_struct.vhd @@ -0,0 +1,156 @@ +------------------------------------------------------------------------- +-- +-- Filename: textmode_vga_struct.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Structual implementation of the toplevel entity. +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use work.math_pkg.all; +use work.textmode_vga_pkg.all; +use work.textmode_vga_component_pkg.all; +use work.font_pkg.all; + +architecture struct of textmode_vga is + signal is_data_line : std_logic; + signal is_eol : std_logic; + signal char_line_cnt : std_logic_vector(log2c(LINE_COUNT) - 1 downto 0); + signal char_height_pixel : std_logic_vector(log2c(CHAR_HEIGHT) - 1 downto 0); + signal rgb : std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + signal char_cnt : std_logic_vector(log2c(COLUMN_COUNT) - 1 downto 0); + + signal mem_data, char_data : std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS + CHAR_SIZE - 1 downto 0); + signal mem_col_address : std_logic_vector(log2c(COLUMN_COUNT) - 1 downto 0); + signal mem_row_address : std_logic_vector(log2c(LINE_COUNT) - 1 downto 0); + signal mem_scroll_address : std_logic_vector(log2c(LINE_COUNT) - 1 downto 0); + signal mem_wr : std_logic; + signal ack_vga, command_req_vga : std_logic; + signal command_vga : std_logic_vector(CHAR_SIZE - 1 downto 0); + signal command_data_vga : std_logic_vector(3 * COLOR_SIZE + CHAR_SIZE - 1 downto 0); + signal decoded_char : std_logic_vector(0 to CHAR_WIDTH - 1); + signal blink : std_logic; + signal background_color, cursor_color : std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0); + signal cursor_state : CURSOR_STATE_TYPE; +begin + textmode_vga_h_sm_inst : textmode_vga_h_sm + port map + ( + sys_clk => vga_clk, + sys_res_n => vga_res_n, + background_color => background_color, + char_cnt => char_cnt, + char_line_cnt => char_line_cnt, + cursor_column => mem_col_address, + cursor_line => mem_row_address, + cursor_color => cursor_color, + cursor_state => cursor_state, + decoded_char => decoded_char, + color => char_data(RED_BITS + GREEN_BITS + BLUE_BITS + CHAR_SIZE - 1 downto CHAR_SIZE), + is_data_line => is_data_line, + is_eol => is_eol, + hsync_n => hsync_n, + rgb => rgb, + blink => blink + ); + r <= rgb(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto GREEN_BITS + BLUE_BITS); + g <= rgb(GREEN_BITS + BLUE_BITS - 1 downto BLUE_BITS); + b <= rgb(BLUE_BITS - 1 downto 0); + + textmode_vga_v_sm_inst : textmode_vga_v_sm + port map + ( + sys_clk => vga_clk, + sys_res_n => vga_res_n, + is_data_line => is_data_line, + char_line_cnt => char_line_cnt, + char_height_pixel => char_height_pixel, + is_eol => is_eol, + vsync_n => vsync_n + ); + + video_memory_inst : video_memory + generic map + ( + DATA_WIDTH => RED_BITS + GREEN_BITS + BLUE_BITS + CHAR_SIZE, + ROW_ADDR_WIDTH => log2c(LINE_COUNT), + COL_ADDR_WIDTH => log2c(COLUMN_COUNT) + ) + port map + ( + vga_clk => vga_clk, + vga_col_address => char_cnt, + vga_row_address => char_line_cnt, + vga_data => char_data, + sm_col_address => mem_col_address, + sm_row_address => mem_row_address, + sm_data => mem_data, + sm_wr => mem_wr, + sm_scroll_address => mem_scroll_address + ); + + font_rom_inst : font_rom + port map + ( + vga_clk => vga_clk, + char => char_data(CHAR_SIZE - 1 downto 0), + char_height_pixel => char_height_pixel, + decoded_char => decoded_char + ); + + console_sm_inst : console_sm + port map + ( + vga_clk => vga_clk, + vga_res_n => vga_res_n, + command => command_vga, + command_data => command_data_vga, + command_req => command_req_vga, + ack => ack_vga, + column_address => mem_col_address, + row_address => mem_row_address, + data => mem_data, + wr => mem_wr, + scroll_address => mem_scroll_address, + background_color => background_color, + cursor_color => cursor_color, + cursor_state => cursor_state + ); + + console_sm_sync_inst : console_sm_sync + generic map + ( + SYNC_STAGES => SYNC_STAGES + ) + port map + ( + sys_clk => sys_clk, + sys_res_n => sys_res_n, + command_sys => command, + command_data_sys => command_data, + free_sys => free, + vga_clk => vga_clk, + vga_res_n => vga_res_n, + command_vga => command_vga, + command_data_vga => command_data_vga, + command_req_vga => command_req_vga, + ack_vga => ack_vga + ); + + blink_interval_inst : interval + generic map + ( + CLK_FREQ => VGA_CLK_FREQ, + INTERVAL_TIME_MS => BLINK_INTERVAL_MS + ) + port map + ( + clk => vga_clk, + res_n => vga_res_n, + active => blink + ); +end architecture struct; diff --git a/src/textmode_vga/textmode_vga_v_sm.vhd b/src/textmode_vga/textmode_vga_v_sm.vhd new file mode 100644 index 0000000..694d95f --- /dev/null +++ b/src/textmode_vga/textmode_vga_v_sm.vhd @@ -0,0 +1,30 @@ +------------------------------------------------------------------------- +-- +-- Filename: textmode_vga_v_sm.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Entity declaration of the vertical VGA timing finite state machine +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use work.math_pkg.all; +use work.textmode_vga_pkg.all; +use work.font_pkg.all; + +entity textmode_vga_v_sm is + port + ( + sys_clk, sys_res_n : in std_logic; + + is_data_line : out std_logic; + char_line_cnt : out std_logic_vector(log2c(LINE_COUNT) - 1 downto 0); + char_height_pixel : out std_logic_vector(log2c(CHAR_HEIGHT) - 1 downto 0); + is_eol : in std_logic; + + vsync_n : out std_logic + ); +end entity textmode_vga_v_sm; diff --git a/src/textmode_vga/textmode_vga_v_sm_beh.vhd b/src/textmode_vga/textmode_vga_v_sm_beh.vhd new file mode 100644 index 0000000..a076930 --- /dev/null +++ b/src/textmode_vga/textmode_vga_v_sm_beh.vhd @@ -0,0 +1,155 @@ +------------------------------------------------------------------------- +-- +-- Filename: textmode_vga_v_sm_beh.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Behavioural implementation of the vertical VGA timing finite state machine +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.math_pkg.all; +use work.textmode_vga_pkg.all; + +architecture beh of textmode_vga_v_sm is + type TEXTMODE_VGA_V_SM_STATE_TYPE is + ( + VSYNC_FIRST, VSYNC, VSYNC_NEXT, + VBACK_FIRST, VBACK, VBACK_NEXT, + VDATA_FIRST, VDATA, VDATA_NEXTLINE, VDATA_NEXTCHAR, + VFRONT_FIRST, VFRONT, VFRONT_NEXT + ); + signal textmode_vga_v_sm_state, textmode_vga_v_sm_state_next : TEXTMODE_VGA_V_SM_STATE_TYPE; + signal vcnt, vcnt_next : integer range 0 to max(VSYNC_LINES, VBACK_LINES, VFRONT_LINES); + signal char_height_pixel_int, char_height_pixel_int_next : integer range 0 to CHAR_HEIGHT; + signal char_line_cnt_int, char_line_cnt_int_next : integer range 0 to LINE_COUNT; +begin + char_height_pixel <= std_logic_vector(to_unsigned(char_height_pixel_int, log2c(CHAR_HEIGHT))); + char_line_cnt <= std_logic_vector(to_unsigned(char_line_cnt_int, log2c(LINE_COUNT))); + + v_sm_next_state : process(textmode_vga_v_sm_state, is_eol, vcnt, char_height_pixel_int, char_line_cnt_int) + begin + textmode_vga_v_sm_state_next <= textmode_vga_v_sm_state; + + case textmode_vga_v_sm_state is + when VSYNC_FIRST => + textmode_vga_v_sm_state_next <= VSYNC; + when VSYNC => + if is_eol = '1' then + if vcnt = VSYNC_LINES - 1 then + textmode_vga_v_sm_state_next <= VBACK_FIRST; + else + textmode_vga_v_sm_state_next <= VSYNC_NEXT; + end if; + end if; + when VSYNC_NEXT => + textmode_vga_v_sm_state_next <= VSYNC; + when VBACK_FIRST => + textmode_vga_v_sm_state_next <= VBACK; + when VBACK => + if is_eol = '1' then + if vcnt = VBACK_LINES - 1 then + textmode_vga_v_sm_state_next <= VDATA_FIRST; + else + textmode_vga_v_sm_state_next <= VBACK_NEXT; + end if; + end if; + when VBACK_NEXT => + textmode_vga_v_sm_state_next <= VBACK; + when VDATA_FIRST => + textmode_vga_v_sm_state_next <= VDATA; + when VDATA => + if is_eol = '1' then + if char_height_pixel_int = CHAR_HEIGHT - 1 then + if char_line_cnt_int = LINE_COUNT - 1 then + textmode_vga_v_sm_state_next <= VFRONT_FIRST; + else + textmode_vga_v_sm_state_next <= VDATA_NEXTCHAR; + end if; + else + textmode_vga_v_sm_state_next <= VDATA_NEXTLINE; + end if; + end if; + when VDATA_NEXTLINE => + textmode_vga_v_sm_state_next <= VDATA; + when VDATA_NEXTCHAR => + textmode_vga_v_sm_state_next <= VDATA; + when VFRONT_FIRST => + textmode_vga_v_sm_state_next <= VFRONT; + when VFRONT => + if is_eol = '1' then + if vcnt = VFRONT_LINES - 1 then + textmode_vga_v_sm_state_next <= VSYNC_FIRST; + else + textmode_vga_v_sm_state_next <= VFRONT_NEXT; + end if; + end if; + when VFRONT_NEXT => + textmode_vga_v_sm_state_next <= VFRONT; + end case; + end process v_sm_next_state; + + v_sm_output : process(textmode_vga_v_sm_state, vcnt, char_height_pixel_int, char_line_cnt_int) + begin + vcnt_next <= vcnt; + is_data_line <= '0'; + vsync_n <= '1'; + char_height_pixel_int_next <= char_height_pixel_int; + char_line_cnt_int_next <= char_line_cnt_int; + + case textmode_vga_v_sm_state is + when VSYNC_FIRST => + vsync_n <= '0'; + vcnt_next <= 0; + when VSYNC => + vsync_n <= '0'; + when VSYNC_NEXT => + vsync_n <= '0'; + vcnt_next <= vcnt + 1; + when VBACK_FIRST => + vcnt_next <= 0; + when VBACK => + null; + when VBACK_NEXT => + vcnt_next <= vcnt + 1; + when VDATA_FIRST => + is_data_line <= '1'; + char_height_pixel_int_next <= 0; + char_line_cnt_int_next <= 0; + when VDATA => + is_data_line <= '1'; + when VDATA_NEXTLINE => + is_data_line <= '1'; + char_height_pixel_int_next <= char_height_pixel_int + 1; + when VDATA_NEXTCHAR => + is_data_line <= '1'; + char_height_pixel_int_next <= 0; + char_line_cnt_int_next <= char_line_cnt_int + 1; + when VFRONT_FIRST => + vcnt_next <= 0; + when VFRONT => + null; + when VFRONT_NEXT => + vcnt_next <= vcnt + 1; + end case; + end process v_sm_output; + + sync : process(sys_clk, sys_res_n) + begin + if sys_res_n = '0' then + textmode_vga_v_sm_state <= VSYNC_FIRST; + vcnt <= 0; + char_height_pixel_int <= 0; + char_line_cnt_int <= 0; + elsif rising_edge(sys_clk) then + textmode_vga_v_sm_state <= textmode_vga_v_sm_state_next; + vcnt <= vcnt_next; + char_height_pixel_int <= char_height_pixel_int_next; + char_line_cnt_int <= char_line_cnt_int_next; + end if; + end process sync; +end architecture beh; diff --git a/src/textmode_vga/video_memory.vhd b/src/textmode_vga/video_memory.vhd new file mode 100644 index 0000000..314a74a --- /dev/null +++ b/src/textmode_vga/video_memory.vhd @@ -0,0 +1,34 @@ +------------------------------------------------------------------------- +-- +-- Filename: video_memory.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Video memory entity declaraton +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity video_memory is + generic + ( + DATA_WIDTH : integer; + ROW_ADDR_WIDTH : integer; + COL_ADDR_WIDTH : integer + ); + port + ( + vga_clk : in std_logic; + vga_row_address : in std_logic_vector(ROW_ADDR_WIDTH - 1 downto 0); + vga_col_address : in std_logic_vector(COL_ADDR_WIDTH - 1 downto 0); + vga_data : out std_logic_vector(DATA_WIDTH - 1 downto 0); + sm_row_address : in std_logic_vector(ROW_ADDR_WIDTH - 1 downto 0); + sm_col_address : in std_logic_vector(COL_ADDR_WIDTH - 1 downto 0); + sm_data : in std_logic_vector(DATA_WIDTH - 1 downto 0); + sm_wr : in std_logic; + sm_scroll_address : in std_logic_vector(ROW_ADDR_WIDTH - 1 downto 0) + ); +end entity video_memory; diff --git a/src/textmode_vga/video_memory_beh.vhd b/src/textmode_vga/video_memory_beh.vhd new file mode 100644 index 0000000..094026d --- /dev/null +++ b/src/textmode_vga/video_memory_beh.vhd @@ -0,0 +1,52 @@ +------------------------------------------------------------------------- +-- +-- Filename: video_memory_beh.vhd +-- ========= +-- +-- Short Description: +-- ================== +-- Behavioral implementation of the video memory. The access time +-- is exactly one clock cycle. +-- +------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.textmode_vga_pkg.all; +use work.font_pkg.all; + +architecture beh of video_memory is + subtype RAM_ENTRY is std_logic_vector(DATA_WIDTH - 1 downto 0); + type RAM_TYPE is array(0 to (2 ** (ROW_ADDR_WIDTH + COL_ADDR_WIDTH)) - 1) of RAM_ENTRY; + signal ram : RAM_TYPE := + ( + others => (others => '0') + ); +begin + process(vga_clk) + variable vga_row_address_int, sm_row_address_int : integer range 0 to 2 * LINE_COUNT - 2; + variable vga_row_address_vector, sm_row_address_vector : std_logic_vector(ROW_ADDR_WIDTH - 1 downto 0); + variable vga_address, sm_address : std_logic_vector(COL_ADDR_WIDTH + ROW_ADDR_WIDTH - 1 downto 0); + begin + if rising_edge(vga_clk) then + vga_row_address_int := to_integer(unsigned(vga_row_address)) + to_integer(unsigned(sm_scroll_address)); + if vga_row_address_int > LINE_COUNT - 1 then + vga_row_address_int := vga_row_address_int - LINE_COUNT; + end if; + vga_row_address_vector := std_logic_vector(to_unsigned(vga_row_address_int, ROW_ADDR_WIDTH)); + vga_address := vga_row_address_vector & vga_col_address; + vga_data <= ram(to_integer(unsigned(vga_address))); + + if sm_wr = '1' then + sm_row_address_int := to_integer(unsigned(sm_row_address)) + to_integer(unsigned(sm_scroll_address)); + if sm_row_address_int > LINE_COUNT - 1 then + sm_row_address_int := sm_row_address_int - LINE_COUNT; + end if; + sm_row_address_vector := std_logic_vector(to_unsigned(sm_row_address_int, ROW_ADDR_WIDTH)); + sm_address := sm_row_address_vector & sm_col_address; + ram(to_integer(unsigned(sm_address))) <= sm_data; + end if; + end if; + end process; +end architecture beh; -- 2.25.1