2018-04-24 21:58:42 +02:00
|
|
|
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 (
|
2018-04-25 23:47:50 +02:00
|
|
|
clk_f: integer := 48_000_000
|
2018-04-24 21:58:42 +02:00
|
|
|
);
|
|
|
|
port (
|
|
|
|
clk: in std_logic;
|
|
|
|
reset: in std_logic;
|
|
|
|
|
2018-04-24 23:44:13 +02:00
|
|
|
write_enable: in std_logic;
|
|
|
|
write_data: in std_logic_vector(7 downto 0);
|
|
|
|
|
2018-04-24 21:58:42 +02:00
|
|
|
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;
|
|
|
|
i2c_scl: inout std_logic;
|
|
|
|
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);
|
2018-04-24 23:44:13 +02:00
|
|
|
|
2018-04-25 23:50:09 +02:00
|
|
|
-- 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);
|
2018-04-24 23:44:13 +02:00
|
|
|
|
2018-04-25 23:50:09 +02:00
|
|
|
signal charbuf_we: std_logic;
|
|
|
|
signal charbuf_wa: std_logic_vector(12 downto 0);
|
|
|
|
signal charbuf_di: std_logic_vector(7 downto 0);
|
2018-04-24 21:58:42 +02:00
|
|
|
|
2018-04-25 23:50:09 +02:00
|
|
|
signal rowlen_we: std_logic;
|
|
|
|
signal rowlen_wa: std_logic_vector(5 downto 0);
|
|
|
|
signal rowlen_di: std_logic_vector(6 downto 0);
|
|
|
|
begin
|
2018-04-24 23:44:13 +02:00
|
|
|
|
2018-04-25 23:50:09 +02:00
|
|
|
-- writes the next character, advances the cursor and saves the length of
|
|
|
|
-- the current row before jumping to the next one
|
2018-04-24 23:44:13 +02:00
|
|
|
process(clk)
|
|
|
|
variable next_line: unsigned(5 downto 0);
|
|
|
|
begin
|
|
|
|
if rising_edge(clk) then
|
2018-04-25 23:50:09 +02:00
|
|
|
-- 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);
|
2018-04-24 23:44:13 +02:00
|
|
|
|
|
|
|
-- calculate next line
|
2018-04-25 23:50:09 +02:00
|
|
|
if cursor_row = 59 then
|
2018-04-24 23:44:13 +02:00
|
|
|
next_line := (others => '0');
|
|
|
|
else
|
2018-04-25 23:50:09 +02:00
|
|
|
next_line := cursor_row + 1;
|
2018-04-24 23:44:13 +02:00
|
|
|
end if;
|
|
|
|
|
|
|
|
if write_enable = '1' then
|
|
|
|
-- carriage return
|
|
|
|
if write_data = x"0d" then
|
2018-04-25 23:50:09 +02:00
|
|
|
cursor_col <= (others => '0');
|
2018-04-24 23:44:13 +02:00
|
|
|
|
|
|
|
-- line feed (implicit CR)
|
2018-04-25 23:50:09 +02:00
|
|
|
elsif write_data = x"0a" then
|
|
|
|
cursor_col <= (others => '0');
|
|
|
|
cursor_row <= next_line;
|
|
|
|
rowlen_we <= '1'; -- save row length
|
|
|
|
|
|
|
|
-- 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;
|
2018-04-24 23:44:13 +02:00
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
2018-04-24 21:58:42 +02:00
|
|
|
dvi_clk_ds: obufds port map (
|
|
|
|
I => clk,
|
|
|
|
O => dvi_clk_p,
|
|
|
|
OB => dvi_clk_n
|
|
|
|
);
|
|
|
|
|
|
|
|
init_ch7301c: entity work.init_ch7301c generic map (
|
|
|
|
input_clk => clk_f
|
|
|
|
) port map (
|
|
|
|
clk => clk,
|
|
|
|
reset => reset,
|
|
|
|
finished => open,
|
|
|
|
error => open,
|
|
|
|
i2c_scl => i2c_scl,
|
|
|
|
i2c_sda => i2c_sda,
|
|
|
|
dvi_reset => dvi_reset
|
|
|
|
);
|
|
|
|
|
|
|
|
vga: entity work.vga port map (
|
|
|
|
clk => 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 => clk,
|
|
|
|
x => image_x,
|
|
|
|
y => image_y,
|
2018-04-24 23:44:13 +02:00
|
|
|
rgb => pixel_rgb,
|
2018-04-25 23:50:09 +02:00
|
|
|
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
|
2018-04-24 21:58:42 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
end syn;
|
|
|
|
|