terminal/terminal.vhd

177 lines
5.6 KiB
VHDL

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;