vga/ps/2: ip-core hinzugefuegt
authorBernhard Urban <lewurm@gmail.com>
Sun, 16 May 2010 00:25:40 +0000 (02:25 +0200)
committerBernhard Urban <lewurm@gmail.com>
Sun, 16 May 2010 00:25:40 +0000 (02:25 +0200)
27 files changed:
src/math_pkg.vhd [new file with mode: 0644]
src/ps2/ps2_keyboard_controller.vhd [new file with mode: 0644]
src/ps2/ps2_keyboard_controller_beh.vhd [new file with mode: 0644]
src/ps2/ps2_keyboard_controller_pkg.vhd [new file with mode: 0644]
src/ps2/ps2_transceiver.vhd [new file with mode: 0644]
src/ps2/ps2_transceiver_beh.vhd [new file with mode: 0644]
src/ps2/ps2_transceiver_pkg.vhd [new file with mode: 0644]
src/textmode_vga/console_sm.vhd [new file with mode: 0644]
src/textmode_vga/console_sm_beh.vhd [new file with mode: 0644]
src/textmode_vga/console_sm_sync.vhd [new file with mode: 0644]
src/textmode_vga/console_sm_sync_beh.vhd [new file with mode: 0644]
src/textmode_vga/font_pkg.vhd [new file with mode: 0644]
src/textmode_vga/font_rom.vhd [new file with mode: 0644]
src/textmode_vga/font_rom_beh.vhd [new file with mode: 0644]
src/textmode_vga/interval.vhd [new file with mode: 0644]
src/textmode_vga/interval_beh.vhd [new file with mode: 0644]
src/textmode_vga/mjl_stratix/textmode_vga_platform_dependent_pkg.vhd [new file with mode: 0644]
src/textmode_vga/textmode_vga.vhd [new file with mode: 0644]
src/textmode_vga/textmode_vga_component_pkg.vhd [new file with mode: 0644]
src/textmode_vga/textmode_vga_h_sm.vhd [new file with mode: 0644]
src/textmode_vga/textmode_vga_h_sm_beh.vhd [new file with mode: 0644]
src/textmode_vga/textmode_vga_pkg.vhd [new file with mode: 0644]
src/textmode_vga/textmode_vga_struct.vhd [new file with mode: 0644]
src/textmode_vga/textmode_vga_v_sm.vhd [new file with mode: 0644]
src/textmode_vga/textmode_vga_v_sm_beh.vhd [new file with mode: 0644]
src/textmode_vga/video_memory.vhd [new file with mode: 0644]
src/textmode_vga/video_memory_beh.vhd [new file with mode: 0644]

diff --git a/src/math_pkg.vhd b/src/math_pkg.vhd
new file mode 100644 (file)
index 0000000..ee0e443
--- /dev/null
@@ -0,0 +1,53 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: math_pkg.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Utility Package defining often used mathematical functions\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+package math_pkg is\r
+  -- Calculates the logarithm dualis of the operand and rounds up\r
+  -- the result to the next integer value.
+  function log2c(constant value : in integer) return integer;\r
+  -- Returns the maximum of the two operands
+  function max(constant value1, value2 : in integer) return integer;\r
+  -- 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 (file)
index 0000000..bdb2335
--- /dev/null
@@ -0,0 +1,33 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: ps2_keyboard_controller.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   PS/2 keyboard controller entity declaration.\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+\r
+entity ps2_keyboard_controller is\r
+  generic\r
+  (\r
+    -- System clock frequency\r
+    CLK_FREQ : integer;\r
+    -- Number of stages used in synchronizers\r
+    SYNC_STAGES : integer\r
+  );\r
+  port\r
+  (\r
+    -- User logic interface\r
+    sys_clk, sys_res_n : in std_logic;\r
+    new_data : out std_logic;\r
+    data : out std_logic_vector(7 downto 0);\r
+    \r
+    -- External PS/2 interface\r
+    ps2_clk, ps2_data : inout std_logic\r
+  );\r
+end entity ps2_keyboard_controller;\r
diff --git a/src/ps2/ps2_keyboard_controller_beh.vhd b/src/ps2/ps2_keyboard_controller_beh.vhd
new file mode 100644 (file)
index 0000000..ca9ca7d
--- /dev/null
@@ -0,0 +1,201 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: ps2_keyboard_controller_beh.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Behavioral implementation of the PS/2 keyboard controller.\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use work.ps2_transceiver_pkg.all;\r
+\r
+architecture beh of ps2_keyboard_controller is\r
+  type KEYBOARD_STATE_TYPE is\r
+  (\r
+    INIT, INIT_WAIT_ACK, INIT_WAIT_BAT, SET_INDICATORS_CMD, SET_INDICATORS_CMD_WAIT_ACK, SET_INDICATORS_VALUE,\r
+    SET_INDICATORS_VALUE_WAIT_ACK, ENABLE, ENABLE_WAIT_ACK, OPERATIONAL, NEW_DATA_AVAILABLE,\r
+    ERROR\r
+  );\r
+  signal keyboard_state, keyboard_state_next : KEYBOARD_STATE_TYPE;  \r
+  \r
+  signal keyboard_data : std_logic_vector(7 downto 0);\r
+  signal keyboard_new_data : std_logic;\r
+  \r
+  signal input_data : std_logic_vector(7 downto 0);\r
+  signal input_data_send_ok, input_data_send_finished, send_request : std_logic;\r
+  \r
+  signal new_data_next : std_logic;\r
+  signal data_next, data_internal : std_logic_vector(7 downto 0);\r
+begin\r
+  ps2_transceiver_inst : ps2_transceiver\r
+    generic map\r
+    (\r
+      CLK_FREQ => CLK_FREQ,\r
+      SYNC_STAGES => SYNC_STAGES\r
+    )\r
+    port map\r
+    (\r
+      sys_clk => sys_clk,\r
+      sys_res_n => sys_res_n,\r
+      ps2_clk => ps2_clk,\r
+      ps2_data => ps2_data,\r
+      send_request => send_request,\r
+      input_data => input_data,\r
+      input_data_send_ok => input_data_send_ok,\r
+      input_data_send_finished => input_data_send_finished,\r
+      output_data => keyboard_data,\r
+      new_data => keyboard_new_data\r
+    );\r
+\r
+  process(keyboard_state, keyboard_new_data, keyboard_data, input_data_send_ok, input_data_send_finished)\r
+  begin\r
+    keyboard_state_next <= keyboard_state;\r
+    \r
+    case keyboard_state is\r
+      when INIT =>\r
+        if input_data_send_finished = '1' then\r
+          if input_data_send_ok = '1' then\r
+            keyboard_state_next <= INIT_WAIT_ACK;\r
+          else\r
+            keyboard_state_next <= ERROR;\r
+          end if;\r
+        end if;\r
+\r
+      when INIT_WAIT_ACK =>\r
+        if keyboard_new_data = '1' then\r
+          if keyboard_data = x"FA" then\r
+            keyboard_state_next <= INIT_WAIT_BAT;\r
+          else\r
+            keyboard_state_next <= ERROR;\r
+          end if;\r
+        end if;\r
+\r
+      when INIT_WAIT_BAT =>\r
+        if keyboard_new_data = '1' then\r
+          if keyboard_data = x"AA" then\r
+            keyboard_state_next <= SET_INDICATORS_CMD;\r
+          else\r
+            keyboard_state_next <= ERROR;\r
+          end if;\r
+        end if;\r
+        \r
+      when SET_INDICATORS_CMD =>\r
+        if input_data_send_finished = '1' then\r
+          if input_data_send_ok = '1' then\r
+            keyboard_state_next <= SET_INDICATORS_CMD_WAIT_ACK;\r
+          else\r
+            keyboard_state_next <= ERROR;\r
+          end if;\r
+        end if;\r
+      when SET_INDICATORS_CMD_WAIT_ACK =>\r
+        if keyboard_new_data = '1' then\r
+          if keyboard_data = x"FA" then\r
+            keyboard_state_next <= SET_INDICATORS_VALUE;\r
+          else\r
+            keyboard_state_next <= ERROR;\r
+          end if;          \r
+        end if;\r
+      when SET_INDICATORS_VALUE =>\r
+        if input_data_send_finished = '1' then\r
+          if input_data_send_ok = '1' then\r
+            keyboard_state_next <= SET_INDICATORS_VALUE_WAIT_ACK;\r
+          else\r
+            keyboard_state_next <= ERROR;\r
+          end if;\r
+        end if;\r
+      when SET_INDICATORS_VALUE_WAIT_ACK =>\r
+        if keyboard_new_data = '1' then\r
+          if keyboard_data = x"FA" then\r
+            keyboard_state_next <= ENABLE;\r
+          else\r
+            keyboard_state_next <= ERROR;\r
+          end if;\r
+        end if;\r
+        \r
+      when ENABLE =>\r
+        if input_data_send_finished = '1' then\r
+          if input_data_send_ok = '1' then\r
+            keyboard_state_next <= ENABLE_WAIT_ACK;\r
+          else\r
+            keyboard_state_next <= ERROR;\r
+          end if;\r
+        end if;\r
+      when ENABLE_WAIT_ACK =>\r
+        if keyboard_new_data = '1' then\r
+          if keyboard_data = x"FA" then\r
+            keyboard_state_next <= OPERATIONAL;\r
+          else\r
+            keyboard_state_next <= ERROR;\r
+          end if;\r
+        end if;        \r
+\r
+      when OPERATIONAL =>\r
+        if keyboard_new_data = '1' then\r
+          keyboard_state_next <= NEW_DATA_AVAILABLE;\r
+        end if;\r
+        \r
+      when NEW_DATA_AVAILABLE =>\r
+        keyboard_state_next <= OPERATIONAL;\r
+        \r
+      when ERROR =>\r
+        null;\r
+    end case;\r
+  end process;\r
+  \r
+  process(keyboard_state, keyboard_data, data_internal)\r
+  begin\r
+    send_request <= '0';\r
+    input_data <= x"00";\r
+    new_data_next <= '0';\r
+    data_next <= data_internal;\r
+    \r
+    case keyboard_state is\r
+      when INIT =>\r
+        send_request <= '1';\r
+        input_data <= x"FF";\r
+      when INIT_WAIT_ACK =>\r
+        null;\r
+      when INIT_WAIT_BAT =>\r
+        null;\r
+      when SET_INDICATORS_CMD =>\r
+        send_request <= '1';\r
+        input_data <= x"ED";\r
+      when SET_INDICATORS_CMD_WAIT_ACK =>\r
+        null;\r
+      when SET_INDICATORS_VALUE =>\r
+        send_request <= '1';\r
+        input_data <= x"02";\r
+      when SET_INDICATORS_VALUE_WAIT_ACK =>\r
+        null;\r
+      when ENABLE =>\r
+        send_request <= '1';\r
+        input_data <= x"F4";\r
+      when ENABLE_WAIT_ACK =>\r
+        null;\r
+      when OPERATIONAL =>\r
+        null;\r
+      when NEW_DATA_AVAILABLE =>\r
+        new_data_next <= '1';\r
+        data_next <= keyboard_data;\r
+      when ERROR =>\r
+    end case;\r
+  end process;\r
+\r
+  process(sys_clk, sys_res_n)\r
+  begin\r
+    if sys_res_n = '0' then\r
+      keyboard_state <= INIT;\r
+      new_data <= '0';\r
+      data_internal <= (others => '0');\r
+    elsif rising_edge(sys_clk) then\r
+      keyboard_state <= keyboard_state_next;\r
+      new_data <= new_data_next;\r
+      data_internal <= data_next;\r
+    end if;\r
+  end process;\r
+  data <= data_internal;\r
+end architecture beh;\r
diff --git a/src/ps2/ps2_keyboard_controller_pkg.vhd b/src/ps2/ps2_keyboard_controller_pkg.vhd
new file mode 100644 (file)
index 0000000..c0b4906
--- /dev/null
@@ -0,0 +1,31 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: ps2_keyboard_controller_pkg.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Component declaration of the PS/2 keyboard controller\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+library ieee;
+use ieee.std_logic_1164.all;
+
+package ps2_keyboard_controller_pkg is
+  component ps2_keyboard_controller is
+    generic
+    (
+      CLK_FREQ : integer;\r
+      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 (file)
index 0000000..2768d3e
--- /dev/null
@@ -0,0 +1,35 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: ps2_transceiver.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   PS/2 transceiver entity\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+\r
+entity ps2_transceiver is\r
+  generic\r
+  (\r
+    CLK_FREQ : integer;\r
+    SYNC_STAGES : integer\r
+  );\r
+  port\r
+  (\r
+    sys_clk, sys_res_n       : in    std_logic;\r
+    \r
+    ps2_clk, ps2_data        : inout std_logic;\r
+    \r
+    send_request             : in    std_logic;\r
+    input_data               : in    std_logic_vector(7 downto 0);\r
+    input_data_send_ok       : out   std_logic;\r
+    input_data_send_finished : out   std_logic;\r
+    \r
+    output_data              : out   std_logic_vector(7 downto 0);\r
+    new_data                 : out   std_logic\r
+  );\r
+end entity ps2_transceiver;\r
diff --git a/src/ps2/ps2_transceiver_beh.vhd b/src/ps2/ps2_transceiver_beh.vhd
new file mode 100644 (file)
index 0000000..8706c52
--- /dev/null
@@ -0,0 +1,396 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: ps2_transceiver_beh.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Behavioral implementation of the PS/2 transceiver\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+\r
+architecture beh of ps2_transceiver is\r
+  constant PREPARE_TIMEOUT1_MAX : integer := CLK_FREQ / 5000; -- 200 us\r
+  constant PREPARE_TIMEOUT2_MAX : integer := CLK_FREQ / 100000; -- 10 us\r
+  type PS2_TRANSCEIVER_STATE_TYPE is\r
+  (\r
+    IDLE,\r
+\r
+    PREPARE_SEND_ASSIGN_CLK, PREPARE_SEND_WAIT1, PREPARE_SEND_DATA, PREPARE_SEND_WAIT2,\r
+    PREPARE_SEND_RELEASE_CLK, SEND_WAIT_DATA0, SEND_DATA0, SEND_WAIT_DATA1, SEND_DATA1,\r
+    SEND_WAIT_DATA2, SEND_DATA2, SEND_WAIT_DATA3, SEND_DATA3, SEND_WAIT_DATA4, SEND_DATA4,\r
+    SEND_WAIT_DATA5, SEND_DATA5, SEND_WAIT_DATA6, SEND_DATA6, SEND_WAIT_DATA7, SEND_DATA7,\r
+    SEND_WAIT_PARITY, SEND_PARITY, SEND_WAIT_STOP, SEND_STOP, SEND_WAIT_ACK1, SEND_WAIT_ACK2,\r
+    SEND_READ_ACK, SEND_FINISH,\r
+     \r
+    RECEIVE_START, RECEIVE_WAIT_DATA0, RECEIVE_DATA0, RECEIVE_WAIT_DATA1, RECEIVE_DATA1,\r
+    RECEIVE_WAIT_DATA2, RECEIVE_DATA2, RECEIVE_WAIT_DATA3, RECEIVE_DATA3, RECEIVE_WAIT_DATA4,\r
+    RECEIVE_DATA4, RECEIVE_WAIT_DATA5, RECEIVE_DATA5, RECEIVE_WAIT_DATA6, RECEIVE_DATA6,\r
+    RECEIVE_WAIT_DATA7, RECEIVE_DATA7, RECEIVE_WAIT_PARITY, RECEIVE_PARITY, RECEIVE_WAIT_STOP,\r
+    RECEIVE_STOP\r
+  );\r
+  signal ps2_transceiver_state, ps2_transceiver_state_next : PS2_TRANSCEIVER_STATE_TYPE;\r
+  signal ps2_clk_last, ps2_clk_internal, ps2_clk_next, ps2_clk_hz, ps2_clk_hz_next : std_logic;\r
+  signal ps2_data_internal, ps2_data_next, ps2_data_hz, ps2_data_hz_next : std_logic;\r
+  signal ps2_clk_sync, ps2_data_sync : std_logic_vector(1 to SYNC_STAGES);\r
+  signal output_data_next, output_data_internal : std_logic_vector(7 downto 0);\r
+  signal parity, parity_next : std_logic;\r
+  signal new_data_next : std_logic;\r
+  signal prepare_timeout1, prepare_timeout1_next : integer range 0 to PREPARE_TIMEOUT1_MAX;\r
+  signal prepare_timeout2, prepare_timeout2_next : integer range 0 to PREPARE_TIMEOUT2_MAX;\r
+begin\r
+\r
+  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)\r
+  begin\r
+    ps2_transceiver_state_next <= ps2_transceiver_state;\r
+   \r
+    case ps2_transceiver_state is\r
+      when IDLE =>        \r
+        if ps2_clk_sync(SYNC_STAGES) = '1' and ps2_clk_last = '0' then\r
+          if ps2_data_sync(SYNC_STAGES) = '0' then\r
+            ps2_transceiver_state_next <= RECEIVE_START;\r
+          end if;\r
+        elsif send_request = '1' then\r
+          ps2_transceiver_state_next <= PREPARE_SEND_ASSIGN_CLK;\r
+        end if;\r
+\r
+\r
+      when PREPARE_SEND_ASSIGN_CLK =>\r
+        ps2_transceiver_state_next <= PREPARE_SEND_WAIT1;\r
+      when PREPARE_SEND_WAIT1 =>\r
+        if prepare_timeout1 = PREPARE_TIMEOUT1_MAX - 1 then\r
+          ps2_transceiver_state_next <= PREPARE_SEND_DATA;\r
+        end if;\r
+      when PREPARE_SEND_DATA =>\r
+        ps2_transceiver_state_next <= PREPARE_SEND_WAIT2;\r
+      when PREPARE_SEND_WAIT2 =>\r
+        if prepare_timeout2 = PREPARE_TIMEOUT2_MAX - 1 then\r
+          ps2_transceiver_state_next <= PREPARE_SEND_RELEASE_CLK;\r
+        end if;\r
+      when PREPARE_SEND_RELEASE_CLK =>\r
+        ps2_transceiver_state_next <= SEND_WAIT_DATA0;\r
+      when SEND_WAIT_DATA0 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= SEND_DATA0;\r
+        end if;\r
+      when SEND_DATA0 =>\r
+        ps2_transceiver_state_next <= SEND_WAIT_DATA1;\r
+      when SEND_WAIT_DATA1 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= SEND_DATA1;\r
+        end if;\r
+      when SEND_DATA1 =>\r
+        ps2_transceiver_state_next <= SEND_WAIT_DATA2;\r
+      when SEND_WAIT_DATA2 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= SEND_DATA2;\r
+        end if;\r
+      when SEND_DATA2 =>\r
+        ps2_transceiver_state_next <= SEND_WAIT_DATA3;\r
+      when SEND_WAIT_DATA3 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= SEND_DATA3;\r
+        end if;\r
+      when SEND_DATA3 =>\r
+        ps2_transceiver_state_next <= SEND_WAIT_DATA4;\r
+      when SEND_WAIT_DATA4 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= SEND_DATA4;\r
+        end if;\r
+      when SEND_DATA4 =>\r
+        ps2_transceiver_state_next <= SEND_WAIT_DATA5;\r
+      when SEND_WAIT_DATA5 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= SEND_DATA5;\r
+        end if;\r
+      when SEND_DATA5 =>\r
+        ps2_transceiver_state_next <= SEND_WAIT_DATA6;\r
+      when SEND_WAIT_DATA6 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= SEND_DATA6;\r
+        end if;\r
+      when SEND_DATA6 =>\r
+        ps2_transceiver_state_next <= SEND_WAIT_DATA7;\r
+      when SEND_WAIT_DATA7 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= SEND_DATA7;\r
+        end if;\r
+      when SEND_DATA7 =>\r
+        ps2_transceiver_state_next <= SEND_WAIT_PARITY;\r
+      when SEND_WAIT_PARITY =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= SEND_PARITY;\r
+        end if;\r
+      when SEND_PARITY =>\r
+        ps2_transceiver_state_next <= SEND_WAIT_STOP;\r
+      when SEND_WAIT_STOP =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= SEND_STOP;\r
+        end if;\r
+      when SEND_STOP =>\r
+        ps2_transceiver_state_next <= SEND_WAIT_ACK1;      \r
+      when SEND_WAIT_ACK1 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then -- ACK is written by device\r
+          ps2_transceiver_state_next <= SEND_WAIT_ACK2;\r
+        end if;\r
+      when SEND_WAIT_ACK2 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '1' and ps2_clk_last = '0' then -- ACK is valid\r
+          ps2_transceiver_state_next <= SEND_READ_ACK;\r
+        end if;\r
+      when SEND_READ_ACK =>\r
+        ps2_transceiver_state_next <= SEND_FINISH;\r
+      when SEND_FINISH =>\r
+        ps2_transceiver_state_next <= IDLE;\r
+\r
+      \r
+      \r
+      when RECEIVE_START =>\r
+        ps2_transceiver_state_next <= RECEIVE_WAIT_DATA0;\r
+      when RECEIVE_WAIT_DATA0 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= RECEIVE_DATA0;\r
+        end if;\r
+      when RECEIVE_DATA0 =>\r
+        ps2_transceiver_state_next <= RECEIVE_WAIT_DATA1;\r
+      when RECEIVE_WAIT_DATA1 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= RECEIVE_DATA1;\r
+        end if;\r
+      when RECEIVE_DATA1 =>\r
+        ps2_transceiver_state_next <= RECEIVE_WAIT_DATA2;\r
+      when RECEIVE_WAIT_DATA2 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= RECEIVE_DATA2;\r
+        end if;\r
+      when RECEIVE_DATA2 =>\r
+        ps2_transceiver_state_next <= RECEIVE_WAIT_DATA3;\r
+      when RECEIVE_WAIT_DATA3 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= RECEIVE_DATA3;\r
+        end if;\r
+      when RECEIVE_DATA3 =>\r
+        ps2_transceiver_state_next <= RECEIVE_WAIT_DATA4;\r
+      when RECEIVE_WAIT_DATA4 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= RECEIVE_DATA4;\r
+        end if;\r
+      when RECEIVE_DATA4 =>\r
+        ps2_transceiver_state_next <= RECEIVE_WAIT_DATA5;\r
+      when RECEIVE_WAIT_DATA5 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= RECEIVE_DATA5;\r
+        end if;\r
+      when RECEIVE_DATA5 =>\r
+        ps2_transceiver_state_next <= RECEIVE_WAIT_DATA6;\r
+      when RECEIVE_WAIT_DATA6 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= RECEIVE_DATA6;\r
+        end if;\r
+      when RECEIVE_DATA6 =>\r
+        ps2_transceiver_state_next <= RECEIVE_WAIT_DATA7;\r
+      when RECEIVE_WAIT_DATA7 =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= RECEIVE_DATA7;\r
+        end if;\r
+      when RECEIVE_DATA7 =>\r
+        ps2_transceiver_state_next <= RECEIVE_WAIT_PARITY;\r
+      when RECEIVE_WAIT_PARITY =>\r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= RECEIVE_PARITY;\r
+        end if;\r
+      when RECEIVE_PARITY =>\r
+        ps2_transceiver_state_next <= RECEIVE_WAIT_STOP;\r
+      when RECEIVE_WAIT_STOP =>     \r
+        if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
+          ps2_transceiver_state_next <= RECEIVE_STOP;\r
+        end if;\r
+      when RECEIVE_STOP =>\r
+        ps2_transceiver_state_next <= IDLE;\r
+    end case;\r
+  end process;\r
+  \r
+  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)\r
+  begin\r
+    input_data_send_ok <= '0';\r
+    input_data_send_finished <= '0';\r
+    ps2_data_next <= ps2_data_internal;\r
+    ps2_data_hz_next <= ps2_data_hz;\r
+    ps2_clk_next <= ps2_clk_internal;\r
+    ps2_clk_hz_next <= ps2_clk_hz;\r
+    parity_next <= parity;\r
+    output_data_next <= output_data_internal;\r
+    new_data_next <= '0';\r
+    prepare_timeout1_next <= prepare_timeout1;\r
+    prepare_timeout2_next <= prepare_timeout2;\r
+    \r
+    case ps2_transceiver_state is\r
+      when IDLE =>        \r
+        ps2_clk_next <= '1';\r
+        ps2_clk_hz_next <= '1';\r
+        ps2_data_next <= '1';\r
+        ps2_data_hz_next <= '1';\r
+\r
+      when PREPARE_SEND_ASSIGN_CLK =>\r
+        ps2_clk_next <= '0';\r
+        ps2_clk_hz_next <= '0';\r
+        parity_next <= '1';\r
+        prepare_timeout1_next <= 0;\r
+      when PREPARE_SEND_WAIT1 =>\r
+        prepare_timeout1_next <= prepare_timeout1 + 1;\r
+      when PREPARE_SEND_DATA =>\r
+        ps2_data_next <='0';\r
+        ps2_data_hz_next <= '0';\r
+        prepare_timeout2_next <= 0;\r
+      when PREPARE_SEND_WAIT2 =>\r
+        prepare_timeout2_next <= prepare_timeout2 + 1;\r
+      when PREPARE_SEND_RELEASE_CLK =>\r
+        ps2_clk_next <= '1';\r
+        ps2_clk_hz_next <= '1';\r
+      when SEND_WAIT_DATA0 =>\r
+        null;\r
+      when SEND_DATA0 =>\r
+        ps2_data_next <= input_data(0);\r
+        parity_next <= parity xor input_data(0);\r
+      when SEND_WAIT_DATA1 =>\r
+        null;\r
+      when SEND_DATA1 =>\r
+        ps2_data_next <=input_data(1);\r
+        parity_next <= parity xor input_data(1);\r
+      when SEND_WAIT_DATA2 =>\r
+        null;\r
+      when SEND_DATA2 =>\r
+        ps2_data_next <=input_data(2);\r
+        parity_next <= parity xor input_data(2);\r
+      when SEND_WAIT_DATA3 =>\r
+        null;\r
+      when SEND_DATA3 =>\r
+        ps2_data_next <=input_data(3);\r
+        parity_next <= parity xor input_data(3);\r
+      when SEND_WAIT_DATA4 =>\r
+        null;\r
+      when SEND_DATA4 =>\r
+        ps2_data_next <=input_data(4);\r
+        parity_next <= parity xor input_data(4);\r
+      when SEND_WAIT_DATA5 =>\r
+        null;\r
+      when SEND_DATA5 =>\r
+        ps2_data_next <=input_data(5);\r
+        parity_next <= parity xor input_data(5);\r
+      when SEND_WAIT_DATA6 =>\r
+        null;\r
+      when SEND_DATA6 =>\r
+        ps2_data_next <=input_data(6);\r
+        parity_next <= parity xor input_data(6);\r
+      when SEND_WAIT_DATA7 =>\r
+        null;\r
+      when SEND_DATA7 =>\r
+        ps2_data_next <=input_data(7);\r
+        parity_next <= parity xor input_data(7);\r
+      when SEND_WAIT_PARITY =>\r
+        null;\r
+      when SEND_PARITY =>\r
+        ps2_data_next <= parity;\r
+      when SEND_WAIT_STOP =>\r
+        null;\r
+      when SEND_STOP =>\r
+        ps2_data_next <='1';\r
+        ps2_data_hz_next <='1';\r
+      when SEND_WAIT_ACK1 =>\r
+        null;\r
+      when SEND_WAIT_ACK2 =>\r
+        null;\r
+      when SEND_READ_ACK =>\r
+        input_data_send_ok <= not ps2_data_sync(SYNC_STAGES);\r
+        input_data_send_finished <= '1';\r
+      when SEND_FINISH =>\r
+            \r
+      when RECEIVE_START =>\r
+        null;\r
+      when RECEIVE_WAIT_DATA0 =>\r
+        null;\r
+      when RECEIVE_DATA0 =>\r
+        output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
+      when RECEIVE_WAIT_DATA1 =>\r
+        null;\r
+      when RECEIVE_DATA1 =>\r
+        output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
+      when RECEIVE_WAIT_DATA2 =>\r
+        null;\r
+      when RECEIVE_DATA2 =>\r
+        output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
+      when RECEIVE_WAIT_DATA3 =>\r
+        null;\r
+      when RECEIVE_DATA3 =>\r
+        output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
+      when RECEIVE_WAIT_DATA4 =>\r
+        null;\r
+      when RECEIVE_DATA4 =>\r
+        output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
+      when RECEIVE_WAIT_DATA5 =>\r
+        null;\r
+      when RECEIVE_DATA5 =>\r
+        output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
+      when RECEIVE_WAIT_DATA6 =>\r
+        null;\r
+      when RECEIVE_DATA6 =>\r
+        output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
+      when RECEIVE_WAIT_DATA7 =>\r
+        null;\r
+      when RECEIVE_DATA7 =>\r
+        output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
+      when RECEIVE_WAIT_PARITY =>\r
+        null;\r
+      when RECEIVE_PARITY =>\r
+        null; -- Currently igonring parity\r
+      when RECEIVE_WAIT_STOP =>\r
+        null;\r
+      when RECEIVE_STOP =>\r
+        new_data_next <= '1';\r
+    end case;\r
+  end process;\r
+  \r
+  process(sys_clk, sys_res_n)\r
+  begin\r
+    if sys_res_n = '0' then\r
+      ps2_transceiver_state <= IDLE;\r
+      ps2_clk_last <= '1';\r
+      ps2_clk_internal <= '1';\r
+      ps2_clk_hz <= '1';\r
+      ps2_data_internal <= '1';\r
+      ps2_data_hz <= '1';\r
+      output_data_internal <= (others => '0');\r
+      parity <= '0';\r
+      new_data <= '0';\r
+      prepare_timeout1 <= 0;\r
+      prepare_timeout2 <= 0;\r
+      ps2_clk_sync <= (others => '1');\r
+      ps2_data_sync <= (others => '1');\r
+    elsif rising_edge(sys_clk) then\r
+      ps2_transceiver_state <= ps2_transceiver_state_next;\r
+      ps2_clk_last <= ps2_clk_sync(SYNC_STAGES);\r
+      ps2_clk_internal <= ps2_clk_next;\r
+      ps2_clk_hz <= ps2_clk_hz_next;\r
+      ps2_data_internal <= ps2_data_next;\r
+      ps2_data_hz <= ps2_data_hz_next;\r
+      output_data_internal <= output_data_next;\r
+      parity <= parity_next;\r
+      new_data <= new_data_next;\r
+      prepare_timeout1 <= prepare_timeout1_next;\r
+      prepare_timeout2 <= prepare_timeout2_next;\r
+      ps2_clk_sync(1) <= ps2_clk;\r
+      ps2_data_sync(1) <= ps2_data;\r
+      for i in 2 to SYNC_STAGES loop\r
+        ps2_clk_sync(i) <= ps2_clk_sync(i - 1);\r
+        ps2_data_sync(i) <= ps2_data_sync(i - 1);\r
+      end loop;\r
+    end if;\r
+  end process;\r
+  ps2_clk <= ps2_clk_internal when ps2_clk_hz = '0'\r
+             else 'Z';\r
+  ps2_data <= ps2_data_internal when ps2_data_hz = '0'\r
+             else 'Z';\r
+  output_data <= output_data_internal;\r
+end architecture beh;\r
diff --git a/src/ps2/ps2_transceiver_pkg.vhd b/src/ps2/ps2_transceiver_pkg.vhd
new file mode 100644 (file)
index 0000000..5b29633
--- /dev/null
@@ -0,0 +1,37 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: ps2_transceiver_pkg.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Component declaration of the PS/2 transceiver\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+\r
+package ps2_transceiver_pkg is\r
+  component ps2_transceiver is
+    generic
+    (
+      CLK_FREQ : integer;\r
+      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;\r
+end package ps2_transceiver_pkg;\r
diff --git a/src/textmode_vga/console_sm.vhd b/src/textmode_vga/console_sm.vhd
new file mode 100644 (file)
index 0000000..2666647
--- /dev/null
@@ -0,0 +1,37 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: console_sm.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Console mode finite state machine entity declaration\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+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 (file)
index 0000000..c4f2f3b
--- /dev/null
@@ -0,0 +1,291 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: console_sm_beh.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Console mode finite state machine behavioral implementation\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+use work.textmode_vga_pkg.all;\r
+use work.textmode_vga_platform_dependent_pkg.all;\r
+\r
+architecture beh of console_sm is\r
+  type STATE_TYPE is\r
+  (\r
+    STATE_IDLE, STATE_ACK_UNKNOWN, STATE_WAIT_REQ_RELEASE, STATE_NEW_LINE_SIMPLE,\r
+    STATE_NEW_LINE_SCROLL, STATE_CARRIAGE_RETURN, STATE_SET_CHAR,\r
+    STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SIMPLE,\r
+    STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SCROLL,\r
+    STATE_SET_BACKGROUND, STATE_SCROLL_NEXT, STATE_SCROLL_TOP,\r
+    STATE_SCROLL_CLEAR_LINE, STATE_SCROLL_CLEAR_LINE_LOOP,\r
+    STATE_SCROLL_CLEAR_LINE_FINISH, STATE_SET_CURSOR_STATE,\r
+    STATE_SET_CURSOR_COLOR, STATE_SET_CURSOR_COLUMN,\r
+    STATE_SET_CURSOR_LINE, STATE_SET_CURSOR_STATE_OFF,\r
+    STATE_SET_CURSOR_STATE_ON, STATE_SET_CURSOR_STATE_BLINK\r
+  );\r
+\r
+  signal state, state_next : STATE_TYPE;\r
+  signal line_int : integer range 0 to LINE_COUNT - 1;\r
+  signal line_next : integer range 0 to LINE_COUNT;\r
+  signal column_int : integer range 0 to COLUMN_COUNT - 1;\r
+  signal column_save, column_save_next : integer range 0 to COLUMN_COUNT - 1;\r
+  signal column_next : integer range 0 to COLUMN_COUNT;\r
+  signal scroll_int : integer range 0 to LINE_COUNT - 1;\r
+  signal scroll_next : integer range 0 to LINE_COUNT;  \r
+  signal ack_next : std_logic;  \r
+  signal background_color_int, background_color_next : std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0);\r
+  signal cursor_color_int, cursor_color_next : std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0);\r
+  signal cursor_state_int, cursor_state_next : CURSOR_STATE_TYPE;\r
+begin\r
+  column_address <= std_logic_vector(to_unsigned(column_int, log2c(COLUMN_COUNT)));\r
+  row_address <= std_logic_vector(to_unsigned(line_int, log2c(LINE_COUNT)));\r
+  scroll_address <= std_logic_vector(to_unsigned(scroll_int, log2c(LINE_COUNT)));\r
+  background_color <= background_color_int;\r
+  cursor_color <= cursor_color_int;\r
+  cursor_state <= cursor_state_int;\r
+\r
+  process(state, line_int, column_int, scroll_int, command, command_data, command_req)\r
+  begin\r
+    state_next <= state;\r
+    \r
+    case state is\r
+      when STATE_IDLE =>\r
+        if command_req = '1' then\r
+          if command = COMMAND_SET_CHAR then\r
+            if command_data(CHAR_SIZE - 1 downto 0) = CHAR_NEW_LINE then\r
+              if line_int < LINE_COUNT - 1 then\r
+                state_next <= STATE_NEW_LINE_SIMPLE;\r
+              else  \r
+                state_next <= STATE_NEW_LINE_SCROLL;\r
+              end if;\r
+            elsif command_data(CHAR_SIZE - 1 downto 0) = CHAR_CARRIAGE_RETURN then\r
+              state_next <= STATE_CARRIAGE_RETURN;\r
+            else\r
+              if column_int < COLUMN_COUNT - 1 then\r
+                state_next <= STATE_SET_CHAR;\r
+              else\r
+                if line_int < LINE_COUNT - 1 then\r
+                  state_next <= STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SIMPLE;\r
+                else\r
+                  state_next <= STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SCROLL;\r
+                end if;\r
+              end if;\r
+            end if;      \r
+          elsif command = COMMAND_SET_BACKGROUND then\r
+            state_next <= STATE_SET_BACKGROUND;\r
+          elsif command = COMMAND_SET_CURSOR_STATE then\r
+            state_next <= STATE_SET_CURSOR_STATE;\r
+          elsif command = COMMAND_SET_CURSOR_COLOR then\r
+            state_next <= STATE_SET_CURSOR_COLOR;\r
+          elsif command = COMMAND_SET_CURSOR_COLUMN then\r
+            state_next <= STATE_SET_CURSOR_COLUMN;\r
+          elsif command = COMMAND_SET_CURSOR_LINE then\r
+            state_next <= STATE_SET_CURSOR_LINE;\r
+          else\r
+            state_next <= STATE_ACK_UNKNOWN;\r
+          end if;\r
+        end if;\r
+      when STATE_ACK_UNKNOWN =>\r
+        state_next <= STATE_WAIT_REQ_RELEASE;\r
+      when STATE_NEW_LINE_SIMPLE =>\r
+        state_next <= STATE_WAIT_REQ_RELEASE;\r
+      when STATE_NEW_LINE_SCROLL =>\r
+        if scroll_int < LINE_COUNT - 1 then\r
+          state_next <= STATE_SCROLL_NEXT;\r
+        else\r
+          state_next <= STATE_SCROLL_TOP;\r
+        end if;        \r
+      when STATE_CARRIAGE_RETURN =>\r
+        state_next <= STATE_WAIT_REQ_RELEASE;\r
+      when STATE_SET_CHAR =>\r
+        state_next <= STATE_WAIT_REQ_RELEASE;\r
+      when STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SIMPLE =>\r
+        state_next <= STATE_WAIT_REQ_RELEASE;\r
+      when STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SCROLL =>\r
+        if scroll_int < LINE_COUNT - 1 then\r
+          state_next <= STATE_SCROLL_NEXT;\r
+        else\r
+          state_next <= STATE_SCROLL_TOP;\r
+        end if;\r
+      when STATE_SCROLL_NEXT =>\r
+        state_next <= STATE_SCROLL_CLEAR_LINE;\r
+      when STATE_SCROLL_TOP =>\r
+        state_next <= STATE_SCROLL_CLEAR_LINE;\r
+      when STATE_SCROLL_CLEAR_LINE =>\r
+        state_next <= STATE_SCROLL_CLEAR_LINE_LOOP;\r
+      when STATE_SCROLL_CLEAR_LINE_LOOP =>\r
+        if column_int = COLUMN_COUNT - 2 then\r
+          state_next <= STATE_SCROLL_CLEAR_LINE_FINISH;\r
+        end if;\r
+      when STATE_SCROLL_CLEAR_LINE_FINISH =>\r
+        state_next <= STATE_WAIT_REQ_RELEASE;\r
+      when STATE_WAIT_REQ_RELEASE =>\r
+        if command_req = '0' then\r
+          state_next <= STATE_IDLE;\r
+        end if;\r
+      when STATE_SET_BACKGROUND =>\r
+        state_next <= STATE_WAIT_REQ_RELEASE;\r
+      when STATE_SET_CURSOR_STATE =>\r
+        if command_data(1 downto 0) = "00" then\r
+          state_next <= STATE_SET_CURSOR_STATE_OFF;\r
+        elsif command_data(1 downto 0) = "01" then\r
+          state_next <= STATE_SET_CURSOR_STATE_ON;\r
+        else\r
+          state_next <= STATE_SET_CURSOR_STATE_BLINK;\r
+        end if;\r
+      when STATE_SET_CURSOR_STATE_OFF =>\r
+        state_next <= STATE_WAIT_REQ_RELEASE;\r
+      when STATE_SET_CURSOR_STATE_ON =>\r
+        state_next <= STATE_WAIT_REQ_RELEASE;\r
+      when STATE_SET_CURSOR_STATE_BLINK =>\r
+        state_next <= STATE_WAIT_REQ_RELEASE;\r
+      when STATE_SET_CURSOR_COLOR =>\r
+        state_next <= STATE_WAIT_REQ_RELEASE;\r
+      when STATE_SET_CURSOR_COLUMN =>\r
+        state_next <= STATE_WAIT_REQ_RELEASE;\r
+      when STATE_SET_CURSOR_LINE =>\r
+        state_next <= STATE_WAIT_REQ_RELEASE;\r
+    end case;\r
+  end process;\r
+\r
+  process(state, line_int, column_int, scroll_int, column_save, background_color_int, cursor_color_int, cursor_state_int, command_data)\r
+  begin\r
+    line_next <= line_int;\r
+    column_next <= column_int;\r
+    scroll_next <= scroll_int;\r
+    column_save_next <= column_save;\r
+    data <= std_logic_vector(to_unsigned(0, RED_BITS + GREEN_BITS + BLUE_BITS + CHAR_SIZE));\r
+    ack_next <= '0';\r
+    wr <= '0';\r
+    background_color_next <= background_color_int;\r
+    cursor_color_next <= cursor_color_int;\r
+    cursor_state_next <= cursor_state_int;\r
+        \r
+    case state is\r
+      when STATE_IDLE =>\r
+        null;\r
+      when STATE_ACK_UNKNOWN =>\r
+        ack_next <= '1';\r
+      when STATE_NEW_LINE_SIMPLE =>\r
+        line_next <= line_int + 1;\r
+        ack_next <= '1';\r
+      when STATE_NEW_LINE_SCROLL =>\r
+        null;\r
+      when STATE_CARRIAGE_RETURN =>\r
+        column_next <= 0;\r
+        ack_next <= '1';\r
+      when STATE_SET_CHAR =>\r
+        data <= command_data(CHAR_SIZE + 3 * COLOR_SIZE - 1 downto CHAR_SIZE + 3 * COLOR_SIZE - RED_BITS) &\r
+                command_data(CHAR_SIZE + 2 * COLOR_SIZE - 1 downto CHAR_SIZE + 2 * COLOR_SIZE - GREEN_BITS) &\r
+                command_data(CHAR_SIZE + COLOR_SIZE - 1 downto CHAR_SIZE + COLOR_SIZE - BLUE_BITS) &\r
+                command_data(CHAR_SIZE - 1 downto 0);\r
+        wr <= '1';\r
+        column_next <= column_int + 1;\r
+        ack_next <= '1';\r
+      when STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SIMPLE =>\r
+        data <= command_data(CHAR_SIZE + 3 * COLOR_SIZE - 1 downto CHAR_SIZE + 3 * COLOR_SIZE - RED_BITS) &\r
+                command_data(CHAR_SIZE + 2 * COLOR_SIZE - 1 downto CHAR_SIZE + 2 * COLOR_SIZE - GREEN_BITS) &\r
+                command_data(CHAR_SIZE + COLOR_SIZE - 1 downto CHAR_SIZE + COLOR_SIZE - BLUE_BITS) &\r
+                command_data(CHAR_SIZE - 1 downto 0);\r
+        wr <= '1';\r
+        line_next <= line_int + 1;\r
+        column_next <= 0;\r
+        ack_next <= '1';\r
+      when STATE_SET_CHAR_NEW_LINE_AND_CARRIAGE_RETURN_SCROLL =>\r
+        data <= command_data(CHAR_SIZE + 3 * COLOR_SIZE - 1 downto CHAR_SIZE + 3 * COLOR_SIZE - RED_BITS) &\r
+                command_data(CHAR_SIZE + 2 * COLOR_SIZE - 1 downto CHAR_SIZE + 2 * COLOR_SIZE - GREEN_BITS) &\r
+                command_data(CHAR_SIZE + COLOR_SIZE - 1 downto CHAR_SIZE + COLOR_SIZE - BLUE_BITS) &\r
+                command_data(CHAR_SIZE - 1 downto 0);\r
+        wr <= '1';\r
+        column_next <= 0;\r
+      when STATE_SCROLL_NEXT =>\r
+        scroll_next <= scroll_int + 1;\r
+      when STATE_SCROLL_TOP =>\r
+        scroll_next <= 0;\r
+      when STATE_SCROLL_CLEAR_LINE =>\r
+        column_save_next <= column_int;\r
+        column_next <= 0;\r
+      when STATE_SCROLL_CLEAR_LINE_LOOP =>\r
+        data <= COLOR_BLACK(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) &\r
+                COLOR_BLACK(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) &\r
+                COLOR_BLACK(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS) &\r
+                CHAR_NULL;\r
+        wr <= '1';\r
+        column_next <= column_int + 1;\r
+      when STATE_SCROLL_CLEAR_LINE_FINISH =>\r
+        data <= COLOR_BLACK(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) &\r
+                COLOR_BLACK(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) &\r
+                COLOR_BLACK(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS) &\r
+                CHAR_NULL;\r
+        wr <= '1';\r
+        column_next <= column_save;\r
+        ack_next <= '1';\r
+      when STATE_WAIT_REQ_RELEASE =>\r
+        ack_next <= '1';\r
+      when STATE_SET_BACKGROUND =>\r
+        background_color_next <=\r
+          command_data(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) &\r
+          command_data(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) &\r
+          command_data(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS);\r
+        ack_next <= '1';\r
+      when STATE_SET_CURSOR_STATE =>\r
+        null;\r
+      when STATE_SET_CURSOR_STATE_OFF =>\r
+        cursor_state_next <= CURSOR_OFF;\r
+        ack_next <= '1';\r
+      when STATE_SET_CURSOR_STATE_ON =>\r
+        cursor_state_next <= CURSOR_ON;\r
+        ack_next <= '1';\r
+      when STATE_SET_CURSOR_STATE_BLINK =>\r
+        cursor_state_next <= CURSOR_BLINK;\r
+        ack_next <= '1';\r
+      when STATE_SET_CURSOR_COLOR =>\r
+        cursor_color_next <=\r
+          command_data(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) &\r
+          command_data(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) &\r
+          command_data(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS);\r
+        ack_next <= '1';\r
+      when STATE_SET_CURSOR_COLUMN =>\r
+        column_next <= to_integer(unsigned(command_data(log2c(COLUMN_COUNT) - 1 downto 0)));\r
+        ack_next <= '1';\r
+      when STATE_SET_CURSOR_LINE =>\r
+        line_next <= to_integer(unsigned(command_data(log2c(LINE_COUNT) - 1 downto 0)));\r
+        ack_next <= '1';\r
+    end case;\r
+  end process;\r
+\r
+  process(vga_clk, vga_res_n)\r
+  begin\r
+    if vga_res_n = '0' then\r
+      state <= STATE_IDLE;\r
+      line_int <= 0;\r
+      column_int <= 0;\r
+      scroll_int <= 0;\r
+      column_save <= 0;\r
+      ack <= '0';\r
+      background_color_int <= COLOR_BLACK(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) &\r
+                              COLOR_BLACK(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) &\r
+                              COLOR_BLACK(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS);\r
+      cursor_color_int <= COLOR_WHITE(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) &\r
+                          COLOR_WHITE(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) &\r
+                          COLOR_WHITE(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS);\r
+      cursor_state_int <= CURSOR_BLINK;\r
+    elsif rising_edge(vga_clk) then\r
+      state <= state_next;\r
+      line_int <= line_next;\r
+      column_int <= column_next;\r
+      scroll_int <= scroll_next;\r
+      column_save <= column_save_next;\r
+      ack <= ack_next;\r
+      background_color_int <= background_color_next;\r
+      cursor_color_int <= cursor_color_next;\r
+      cursor_state_int <= cursor_state_next;\r
+    end if;\r
+  end process;\r
+end architecture beh;\r
diff --git a/src/textmode_vga/console_sm_sync.vhd b/src/textmode_vga/console_sm_sync.vhd
new file mode 100644 (file)
index 0000000..2e5050f
--- /dev/null
@@ -0,0 +1,36 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: console_sm_sync.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Entity declaration of the synchronizer for the cosole mode\r
+--   finite state machine.\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+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 (file)
index 0000000..00151b6
--- /dev/null
@@ -0,0 +1,121 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: console_sm_sync_beh.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Behavioral implementation of the synchronizer for the cosole mode\r
+--   finite state machine. It synchronizes all signal crossing\r
+--   from the system and the VGA clock domain and vice versa.\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+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;\r
+        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 (file)
index 0000000..aa2b2b4
--- /dev/null
@@ -0,0 +1,4126 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: font_pkg.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Constant declaration of the font ROM. The number of\r
+--   defined encodings, the character dimension and the\r
+--   encoding itself are defiend in this package.\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+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 (file)
index 0000000..ddbfc97
--- /dev/null
@@ -0,0 +1,25 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: font_rom.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Font ROM entity declaraton\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+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 (file)
index 0000000..c01a3c0
--- /dev/null
@@ -0,0 +1,27 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: font_rom_beh.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Behavioral architecture of the font ROM entity.\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+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 (file)
index 0000000..f8c8aca
--- /dev/null
@@ -0,0 +1,27 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: interval.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Interval timer entity declaraton.\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+\r
+entity interval is\r
+  generic\r
+  (\r
+    CLK_FREQ : integer;\r
+    INTERVAL_TIME_MS : integer\r
+  );\r
+  port\r
+  (\r
+    clk : in std_logic;\r
+    res_n : in std_logic;\r
+    active : out std_logic\r
+  );\r
+end entity interval;\r
diff --git a/src/textmode_vga/interval_beh.vhd b/src/textmode_vga/interval_beh.vhd
new file mode 100644 (file)
index 0000000..e8da284
--- /dev/null
@@ -0,0 +1,36 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: interval_beh.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Behavioral implementaiton of the interval timer\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+\r
+architecture beh of interval is\r
+  constant CNT_MAX : integer := INTERVAL_TIME_MS * (CLK_FREQ / 1000);\r
+  signal cnt : integer range 0 to CNT_MAX - 1;\r
+  signal active_int : std_logic;\r
+begin\r
+  active <= active_int;\r
+  process(clk, res_n)\r
+  begin\r
+    if res_n = '0' then\r
+      cnt <= 0;\r
+      active_int <= '0';\r
+    elsif rising_edge(clk) then\r
+      if cnt < CNT_MAX - 1 then\r
+        cnt <= cnt + 1;\r
+      else\r
+        cnt <= 0;\r
+        active_int <= not active_int;\r
+      end if;\r
+    end if;\r
+  end process;\r
+end architecture beh;\r
+            
\ 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 (file)
index 0000000..32ae139
--- /dev/null
@@ -0,0 +1,20 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: textmode_vga_platform_dependent_pkg.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Platform depnded declarations used within the textmode\r
+--   VGA controller implementation.\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+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 (file)
index 0000000..26cf04c
--- /dev/null
@@ -0,0 +1,43 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: textmode_vga.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Toplevel entity of the textmode VGA controller.\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+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
+  (\r
+    -- Clock frequency used as basis for the VGA timing
+    VGA_CLK_FREQ : integer;\r
+    -- Blink interval of the cursor give in miliseconds
+    BLINK_INTERVAL_MS : integer;\r
+    -- Number of stages used in synchronizers
+    SYNC_STAGES : integer
+  );
+  port
+  (\r
+    -- 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;
+\r
+    -- 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 (file)
index 0000000..1ff5c3e
--- /dev/null
@@ -0,0 +1,176 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: textmode_vga_component_pkg.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   This package contains the declaration of all componets\r
+--   used within the textmode VGA controller implementation.\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+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 (file)
index 0000000..785e786
--- /dev/null
@@ -0,0 +1,42 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: textmode_vga_h_sm.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Entity declaration of the horizontal VGA timing finite state machine\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+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 (file)
index 0000000..5314bdd
--- /dev/null
@@ -0,0 +1,243 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: textmode_vga_h_sm_beh.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Behavioural implementation of the horizontal VGA timing finite state machine\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+use work.math_pkg.all;\r
+use work.textmode_vga_pkg.all;\r
+use work.font_pkg.all;\r
+\r
+architecture beh of textmode_vga_h_sm is\r
+  type TEXTMODE_VGA_H_SM_STATE_TYPE is\r
+  (\r
+    HSYNC_FIRST, HSYNC, HBACK_FIRST, HBACK, BLACK_CHAR_NEW,\r
+    BLACK_PIXEL, CHAR_NEW_FG, PIXEL_FG, CHAR_NEW_BG, PIXEL_BG,\r
+    HFRONT_FIRST, HFRONT, HFRONT_LAST, CHAR_NEW_CURSOR, PIXEL_CURSOR\r
+  );\r
+  signal textmode_vga_h_sm_state, textmode_vga_h_sm_state_next : TEXTMODE_VGA_H_SM_STATE_TYPE;\r
+  signal hcnt, hcnt_next : integer range 0 to max(HSYNC_CYCLES, HBACK_CYCLES, HFRONT_CYCLES);\r
+  signal current_char, current_char_next : std_logic_vector(0 to CHAR_WIDTH - 1);\r
+  signal current_color, current_color_next : std_logic_vector(RED_BITS + GREEN_BITS + BLUE_BITS - 1 downto 0);\r
+  signal char_width_pixel, char_width_pixel_next : integer range 0 to CHAR_WIDTH;\r
+  signal char_cnt_int, char_cnt_next : integer range 0 to COLUMN_COUNT;\r
+begin\r
+  char_cnt <= std_logic_vector(to_unsigned(char_cnt_int, log2c(COLUMN_COUNT)));\r
+  \r
+  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)\r
+  begin\r
+    textmode_vga_h_sm_state_next <= textmode_vga_h_sm_state;\r
+    case textmode_vga_h_sm_state is\r
+      when HSYNC_FIRST =>\r
+        textmode_vga_h_sm_state_next <= HSYNC;\r
+      when HSYNC =>\r
+        if hcnt = HSYNC_CYCLES - 1 then\r
+          textmode_vga_h_sm_state_next <= HBACK_FIRST;\r
+        end if;\r
+      when HBACK_FIRST =>\r
+        textmode_vga_h_sm_state_next <= HBACK;\r
+      when HBACK =>\r
+        if hcnt = HBACK_CYCLES - 1 then\r
+          if is_data_line = '0' then\r
+            textmode_vga_h_sm_state_next <= BLACK_CHAR_NEW;\r
+          else\r
+            if (cursor_state = CURSOR_ON or\r
+               (cursor_state = CURSOR_BLINK and blink = '0')) and\r
+               char_line_cnt = cursor_line and\r
+               std_logic_vector(to_unsigned(char_cnt_int, log2c(COLUMN_COUNT))) = cursor_column then\r
+              textmode_vga_h_sm_state_next <= CHAR_NEW_CURSOR;\r
+            elsif decoded_char(0) = '1' then\r
+              textmode_vga_h_sm_state_next <= CHAR_NEW_FG;\r
+            else\r
+              textmode_vga_h_sm_state_next <= CHAR_NEW_BG;\r
+            end if;\r
+          end if;\r
+        end if;\r
+      when BLACK_CHAR_NEW =>\r
+        textmode_vga_h_sm_state_next <= BLACK_PIXEL;\r
+      when BLACK_PIXEL =>\r
+        if char_width_pixel = CHAR_WIDTH - 1 then\r
+          if char_cnt_int = COLUMN_COUNT then\r
+            textmode_vga_h_sm_state_next <= HFRONT_FIRST;\r
+          else\r
+            textmode_vga_h_sm_state_next <= BLACK_CHAR_NEW;\r
+          end if;\r
+        end if;\r
+      when CHAR_NEW_FG =>\r
+        if decoded_char(1) = '1' then\r
+          textmode_vga_h_sm_state_next <= PIXEL_FG;\r
+        else\r
+          textmode_vga_h_sm_state_next <= PIXEL_BG;\r
+        end if;\r
+      when CHAR_NEW_CURSOR =>\r
+        textmode_vga_h_sm_state_next <= PIXEL_CURSOR;\r
+      when PIXEL_FG =>\r
+        if char_width_pixel = CHAR_WIDTH - 1 then\r
+          if char_cnt_int = COLUMN_COUNT then\r
+            textmode_vga_h_sm_state_next <= HFRONT_FIRST;  \r
+          else\r
+            if (cursor_state = CURSOR_ON or\r
+               (cursor_state = CURSOR_BLINK and blink = '0')) and\r
+               char_line_cnt = cursor_line and\r
+               std_logic_vector(to_unsigned(char_cnt_int, log2c(COLUMN_COUNT))) = cursor_column then\r
+              textmode_vga_h_sm_state_next <= CHAR_NEW_CURSOR;\r
+            elsif decoded_char(0) = '1' then\r
+              textmode_vga_h_sm_state_next <= CHAR_NEW_FG;  \r
+            else\r
+              textmode_vga_h_sm_state_next <= CHAR_NEW_BG;  \r
+            end if;\r
+          end if;\r
+        else\r
+          if current_char(char_width_pixel + 1) = '1' then\r
+            textmode_vga_h_sm_state_next <= PIXEL_FG;\r
+          else\r
+            textmode_vga_h_sm_state_next <= PIXEL_BG;\r
+          end if;\r
+        end if;\r
+      when PIXEL_CURSOR =>\r
+        if char_width_pixel = CHAR_WIDTH - 1 then\r
+          if char_cnt_int = COLUMN_COUNT then\r
+            textmode_vga_h_sm_state_next <= HFRONT_FIRST;  \r
+          else\r
+            if decoded_char(0) = '1' then\r
+              textmode_vga_h_sm_state_next <= CHAR_NEW_FG;  \r
+            else\r
+              textmode_vga_h_sm_state_next <= CHAR_NEW_BG;  \r
+            end if;\r
+          end if;\r
+        end if;\r
+      when CHAR_NEW_BG =>\r
+        if decoded_char(1) = '1' then\r
+          textmode_vga_h_sm_state_next <= PIXEL_FG;\r
+        else\r
+          textmode_vga_h_sm_state_next <= PIXEL_BG;\r
+        end if;\r
+      when PIXEL_BG =>\r
+        if char_width_pixel = CHAR_WIDTH - 1 then\r
+          if char_cnt_int = COLUMN_COUNT then\r
+            textmode_vga_h_sm_state_next <= HFRONT_FIRST;  \r
+          else\r
+            if (cursor_state = CURSOR_ON or\r
+               (cursor_state = CURSOR_BLINK and blink = '0')) and\r
+               char_line_cnt = cursor_line and\r
+              std_logic_vector(to_unsigned(char_cnt_int, log2c(COLUMN_COUNT))) = cursor_column then\r
+              textmode_vga_h_sm_state_next <= CHAR_NEW_CURSOR;\r
+            elsif decoded_char(0) = '1' then\r
+              textmode_vga_h_sm_state_next <= CHAR_NEW_FG;  \r
+            else\r
+              textmode_vga_h_sm_state_next <= CHAR_NEW_BG;  \r
+            end if;\r
+          end if;\r
+        else\r
+          if current_char(char_width_pixel + 1) = '1' then\r
+            textmode_vga_h_sm_state_next <= PIXEL_FG;\r
+          else\r
+            textmode_vga_h_sm_state_next <= PIXEL_BG;\r
+          end if;\r
+        end if;\r
+      when HFRONT_FIRST =>\r
+        textmode_vga_h_sm_state_next <= HFRONT;\r
+      when HFRONT =>\r
+        if hcnt = HFRONT_CYCLES - 2 then\r
+          textmode_vga_h_sm_state_next <= HFRONT_LAST;\r
+        end if;\r
+      when HFRONT_LAST =>\r
+        textmode_vga_h_sm_state_next <= HSYNC_FIRST;\r
+    end case;\r
+  end process h_sm_next_state;\r
+  \r
+  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)\r
+  begin\r
+    hsync_n <= '1';\r
+    rgb <= COLOR_BLACK(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) &\r
+           COLOR_BLACK(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) &\r
+           COLOR_BLACK(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS);\r
+    is_eol <= '0';\r
+    hcnt_next <= hcnt;\r
+    char_cnt_next <= char_cnt_int;\r
+    char_width_pixel_next <= char_width_pixel;\r
+    current_char_next <= current_char;\r
+    current_color_next <= current_color;\r
+\r
+    case textmode_vga_h_sm_state is\r
+      when HSYNC_FIRST =>\r
+        hsync_n <= '0';\r
+        hcnt_next <= 0;\r
+        char_cnt_next <= 0;\r
+      when HSYNC =>\r
+        hsync_n <= '0';\r
+        hcnt_next <= hcnt + 1;\r
+      when HBACK_FIRST =>\r
+        hcnt_next <= 0;\r
+      when HBACK =>\r
+        hcnt_next <= hcnt + 1;\r
+      when BLACK_CHAR_NEW =>\r
+        char_cnt_next <= char_cnt_int + 1;\r
+        char_width_pixel_next <= 1;\r
+      when BLACK_PIXEL =>\r
+        char_width_pixel_next <= char_width_pixel + 1;\r
+      when CHAR_NEW_FG =>\r
+        rgb <= color;\r
+        char_cnt_next <= char_cnt_int + 1;\r
+        char_width_pixel_next <= 1;\r
+        current_char_next <= decoded_char;\r
+        current_color_next <= color;\r
+      when PIXEL_FG =>\r
+        rgb <= current_color;\r
+        char_width_pixel_next <= char_width_pixel + 1;\r
+      when CHAR_NEW_CURSOR =>\r
+        rgb <= cursor_color;\r
+        char_cnt_next <= char_cnt_int + 1;\r
+        char_width_pixel_next <= 1;\r
+        current_char_next <= decoded_char;\r
+        current_color_next <= color;\r
+      when PIXEL_CURSOR =>\r
+        rgb <= cursor_color;\r
+        char_width_pixel_next <= char_width_pixel + 1;\r
+      when CHAR_NEW_BG =>\r
+        rgb <= background_color;\r
+        char_cnt_next <= char_cnt_int + 1;\r
+        char_width_pixel_next <= 1;\r
+        current_char_next <= decoded_char;\r
+        current_color_next <= color;\r
+      when PIXEL_BG =>\r
+        rgb <= background_color;\r
+        char_width_pixel_next <= char_width_pixel + 1;\r
+      when HFRONT_FIRST =>\r
+        hcnt_next <= 0;\r
+      when HFRONT =>\r
+        hcnt_next <= hcnt + 1;\r
+      when HFRONT_LAST =>\r
+        is_eol <= '1';\r
+    end case;\r
+  end process h_sm_output;\r
+\r
+  sync : process(sys_clk, sys_res_n)\r
+  begin\r
+    if sys_res_n = '0' then\r
+      textmode_vga_h_sm_state <= HSYNC_FIRST;\r
+      hcnt <= 0;\r
+      char_cnt_int <= 0;\r
+      char_width_pixel <= 0;\r
+      current_char <= (others => '0');\r
+      current_color <= COLOR_WHITE(3 * COLOR_SIZE - 1 downto 3 * COLOR_SIZE - RED_BITS) &\r
+                       COLOR_WHITE(2 * COLOR_SIZE - 1 downto 2 * COLOR_SIZE - GREEN_BITS) &\r
+                       COLOR_WHITE(COLOR_SIZE - 1 downto COLOR_SIZE - BLUE_BITS);\r
+    elsif rising_edge(sys_clk) then\r
+      textmode_vga_h_sm_state <= textmode_vga_h_sm_state_next;\r
+      hcnt <= hcnt_next;\r
+      char_cnt_int <= char_cnt_next;\r
+      char_width_pixel <= char_width_pixel_next;\r
+      current_char <= current_char_next;\r
+      current_color <= current_color_next;\r
+    end if;\r
+  end process sync;\r
+end architecture beh;\r
diff --git a/src/textmode_vga/textmode_vga_pkg.vhd b/src/textmode_vga/textmode_vga_pkg.vhd
new file mode 100644 (file)
index 0000000..7646bad
--- /dev/null
@@ -0,0 +1,78 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: textmode_vga_pkg.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Global declaration needed by the VGA interface.\r
+--   This package contains the declaration of the VGA timing values,\r
+--   the VGA dimensions and the supported commands.\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use work.textmode_vga_platform_dependent_pkg.all;\r
+--\r
+-- 640x480x60Hz\r
+--\r
+--     >=144           <784\r
+--   >=33 ---------------\r
+--        |             |\r
+--        |             |\r
+--        |             |\r
+--   <513 ---------------\r
+--\r
+-- PixelClock: 25,175 MHz\r
+--\r
+-- HSync   96\r
+-- BackP   48\r
+-- Data   640\r
+-- FrontP  16\r
+--        ---\r
+--        800\r
+--\r
+-- Vsync    2\r
+-- BackP   31\r
+-- Data   480\r
+-- FrontP  11\r
+--        ---\r
+--        524\r
+--\r
+\r
+package textmode_vga_pkg is\r
+  constant COLOR_SIZE : integer := 8;\r
+  constant CHAR_SIZE : integer := 8;\r
+\r
+  constant COLOR_BLACK : std_logic_vector(3 * COLOR_SIZE - 1 downto 0) := (others => '0');\r
+  constant COLOR_WHITE : std_logic_vector(3 * COLOR_SIZE - 1 downto 0) := (others => '1');\r
+\r
+  constant PIXEL_WIDTH : integer := 640;\r
+  constant PIXEL_HEIGHT : integer := 480;\r
+  constant HSYNC_CYCLES : integer := 96;\r
+  constant HBACK_CYCLES : integer := 48;\r
+  constant HFRONT_CYCLES : integer := 16;\r
+  constant VSYNC_LINES : integer := 2;\r
+  constant VBACK_LINES : integer := 31;\r
+  constant VFRONT_LINES : integer := 11;\r
+\r
+  subtype COLOR_RANGE is natural range COLOR_SIZE + CHAR_SIZE - 1 downto CHAR_SIZE;\r
+  subtype VGA_MEMORY_RANGE is natural range COLOR_SIZE + CHAR_SIZE - 1 downto 0;\r
+  \r
+  constant COMMAND_SIZE : integer := 8;\r
+  constant COMMAND_NOP : std_logic_vector(COMMAND_SIZE - 1 downto 0) := x"00";\r
+  constant COMMAND_SET_CHAR : std_logic_vector(COMMAND_SIZE - 1 downto 0) := x"01";\r
+  constant COMMAND_SET_BACKGROUND : std_logic_vector(COMMAND_SIZE - 1 downto 0) := x"02";\r
+  constant COMMAND_SET_CURSOR_STATE : std_logic_vector(COMMAND_SIZE - 1 downto 0) := x"03";\r
+  constant COMMAND_SET_CURSOR_COLOR : std_logic_vector(COMMAND_SIZE - 1 downto 0) := x"04";\r
+  constant COMMAND_SET_CURSOR_COLUMN : std_logic_vector(COMMAND_SIZE - 1 downto 0) := x"05";\r
+  constant COMMAND_SET_CURSOR_LINE : std_logic_vector(COMMAND_SIZE - 1 downto 0) := x"06";\r
+  \r
+  constant CHAR_NEW_LINE : std_logic_vector(CHAR_SIZE - 1 downto 0) := x"0A";\r
+  constant CHAR_CARRIAGE_RETURN : std_logic_vector(CHAR_SIZE - 1 downto 0) := x"0D";\r
+  constant CHAR_NULL : std_logic_vector(CHAR_SIZE - 1 downto 0) := x"00";\r
+  \r
+  type CURSOR_STATE_TYPE is (CURSOR_OFF, CURSOR_ON, CURSOR_BLINK);\r
+  constant CURSOR_BLINK_INTERVAL_MS : integer := 500;\r
+end package textmode_vga_pkg;\r
diff --git a/src/textmode_vga/textmode_vga_struct.vhd b/src/textmode_vga/textmode_vga_struct.vhd
new file mode 100644 (file)
index 0000000..69cea9b
--- /dev/null
@@ -0,0 +1,156 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: textmode_vga_struct.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Structual implementation of the toplevel entity.\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+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 (file)
index 0000000..694d95f
--- /dev/null
@@ -0,0 +1,30 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: textmode_vga_v_sm.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Entity declaration of the vertical VGA timing finite state machine\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+library ieee;
+use ieee.std_logic_1164.all;
+use work.math_pkg.all;
+use work.textmode_vga_pkg.all;\r
+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 (file)
index 0000000..a076930
--- /dev/null
@@ -0,0 +1,155 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: textmode_vga_v_sm_beh.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Behavioural implementation of the vertical VGA timing finite state machine\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+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 (file)
index 0000000..314a74a
--- /dev/null
@@ -0,0 +1,34 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: video_memory.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Video memory entity declaraton\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+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 (file)
index 0000000..094026d
--- /dev/null
@@ -0,0 +1,52 @@
+-------------------------------------------------------------------------\r
+--\r
+-- Filename: video_memory_beh.vhd\r
+-- =========\r
+--\r
+-- Short Description:\r
+-- ==================\r
+--   Behavioral implementation of the video memory. The access time\r
+--   is exactly one clock cycle.\r
+--\r
+-------------------------------------------------------------------------\r
+\r
+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;