library ieee; library unisim; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; -- Xilinx primitives (obufds) use unisim.VComponents.all; entity terminal is generic ( clk_f: integer := 48_000_000 ); port ( sys_clk: in std_logic; sys_reset: in std_logic; write_enable: in std_logic; write_data: in std_logic_vector(7 downto 0); dvi_d: out std_logic_vector(11 downto 0); dvi_clk_p: out std_logic; dvi_clk_n: out std_logic; dvi_hsync: out std_logic; dvi_vsync: out std_logic; dvi_de: out std_logic; dvi_reset: out std_logic; dvi_i2c_scl: inout std_logic; dvi_i2c_sda: inout std_logic ); end terminal; architecture syn of terminal is signal image_x: std_logic_vector(9 downto 0); signal image_y: std_logic_vector(8 downto 0); signal pixel_rgb: std_logic_vector(23 downto 0); -- the cursor points to the position where the next char will be written signal cursor_row: unsigned(5 downto 0); signal cursor_col: unsigned(6 downto 0); signal charbuf_we: std_logic; signal charbuf_wa: std_logic_vector(12 downto 0); signal charbuf_di: std_logic_vector(7 downto 0); signal rowlen_we: std_logic; signal rowlen_wa: std_logic_vector(5 downto 0); signal rowlen_di: std_logic_vector(6 downto 0); signal last_written_char: std_logic_vector(7 downto 0); signal last_cursor_col: unsigned(6 downto 0); begin -- writes the next character, advances the cursor and saves the length of -- the current row before jumping to the next one process(sys_clk) variable next_line: unsigned(5 downto 0); variable previous_col: unsigned(6 downto 0); begin if rising_edge(sys_clk) then -- we write to the current cursor position and simply pass the data -- through (but CR and LF are ignored, so charbuf_we is 0 by default) charbuf_we <= '0'; charbuf_wa <= std_logic_vector(cursor_col) & std_logic_vector(cursor_row); charbuf_di <= write_data; -- we save the length of the current row before advancing to the -- next row (the current row length is the cursor column when using -- LF the go to the next line or one more when wrapping around) rowlen_we <= '0'; rowlen_wa <= std_logic_vector(cursor_row); rowlen_di <= std_logic_vector(cursor_col); -- calculate next line if cursor_row = 59 then next_line := (others => '0'); else next_line := cursor_row + 1; end if; -- calculate previous column (saturating) if cursor_col = 0 then previous_col := (others => '0'); else previous_col := cursor_col - 1; end if; if write_enable = '1' then -- save last written char and column for correct CR, LF handling last_written_char <= write_data; last_cursor_col <= cursor_col; -- backspace if write_data = x"08" then cursor_col <= previous_col; -- carriage return elsif write_data = x"0d" then cursor_col <= (others => '0'); -- line feed (implicit CR) elsif write_data = x"0a" then cursor_col <= (others => '0'); cursor_row <= next_line; rowlen_we <= '1'; -- save row length -- write the row length with was valid before CR reset the -- cursor (for consecutive CR, LF) if last_written_char = x"0d" then rowlen_di <= std_logic_vector(last_cursor_col); end if; -- normal characters else charbuf_we <= '1'; -- write normal characters if cursor_col = 79 then cursor_col <= (others => '0'); cursor_row <= next_line; rowlen_we <= '1'; -- save row length rowlen_di <= "1010000"; -- 80 (cursor_col is only 79) else cursor_col <= cursor_col + 1; end if; end if; end if; end if; end process; dvi_clk_ds: obufds port map ( I => sys_clk, O => dvi_clk_p, OB => dvi_clk_n ); init_ch7301c: entity work.init_ch7301c generic map ( input_clk => clk_f ) port map ( clk => sys_clk, reset => sys_reset, finished => open, error => open, i2c_scl => dvi_i2c_scl, i2c_sda => dvi_i2c_sda, dvi_reset => dvi_reset ); vga: entity work.vga port map ( clk => sys_clk, x => image_x, y => image_y, pixel_rgb => pixel_rgb, dvi_d => dvi_d, dvi_hsync => dvi_hsync, dvi_vsync => dvi_vsync, dvi_de => dvi_de ); framebuffer: entity work.framebuffer generic map ( input_clk => clk_f ) port map ( clk => sys_clk, x => image_x, y => image_y, rgb => pixel_rgb, cursor_row => cursor_row, cursor_col => cursor_col, charbuf_we => charbuf_we, charbuf_wa => charbuf_wa, charbuf_di => charbuf_di, rowlen_we => rowlen_we, rowlen_wa => rowlen_wa, rowlen_di => rowlen_di ); end syn;