2018-01-23 03:02:06 +01:00
|
|
|
library ieee;
|
|
|
|
|
|
|
|
use ieee.std_logic_1164.all;
|
|
|
|
use ieee.std_logic_unsigned.all;
|
|
|
|
use ieee.numeric_std.all;
|
|
|
|
|
|
|
|
use std.textio.all;
|
|
|
|
use ieee.std_logic_textio.all;
|
|
|
|
|
2018-04-24 21:58:42 +02:00
|
|
|
entity framebuffer is
|
2018-01-23 03:02:06 +01:00
|
|
|
generic (
|
|
|
|
input_clk: integer
|
|
|
|
);
|
|
|
|
port (
|
|
|
|
clk: in std_logic;
|
2018-04-24 21:28:02 +02:00
|
|
|
x: in std_logic_vector(9 downto 0);
|
|
|
|
y: in std_logic_vector(8 downto 0);
|
2018-01-23 03:02:06 +01:00
|
|
|
|
2018-04-24 23:44:13 +02:00
|
|
|
rgb: out std_logic_vector(23 downto 0);
|
|
|
|
|
2018-04-25 23:50:09 +02:00
|
|
|
cursor_row: in unsigned(5 downto 0);
|
|
|
|
cursor_col: in unsigned(6 downto 0);
|
|
|
|
|
|
|
|
-- write access to the character and row length rams
|
|
|
|
charbuf_we: in std_logic;
|
|
|
|
charbuf_wa: in std_logic_vector(12 downto 0);
|
|
|
|
charbuf_di: in std_logic_vector(7 downto 0);
|
|
|
|
rowlen_we: in std_logic;
|
|
|
|
rowlen_wa: in std_logic_vector(5 downto 0);
|
|
|
|
rowlen_di: in std_logic_vector(6 downto 0)
|
2018-01-23 03:02:06 +01:00
|
|
|
);
|
2018-04-24 21:58:42 +02:00
|
|
|
end framebuffer;
|
2018-01-23 03:02:06 +01:00
|
|
|
|
2018-04-24 21:58:42 +02:00
|
|
|
architecture logic of framebuffer is
|
2018-01-23 03:02:06 +01:00
|
|
|
type rom_type is array(0 to 127) of std_logic_vector(63 downto 0);
|
|
|
|
|
|
|
|
impure function read_font(filename: in string) return rom_type is
|
|
|
|
file rom_file: text is in filename;
|
|
|
|
variable rom_line: line;
|
|
|
|
variable rom: rom_type;
|
|
|
|
begin
|
|
|
|
-- skip comment in first line
|
|
|
|
readline(rom_file, rom_line);
|
|
|
|
|
|
|
|
for i in rom_type'range loop
|
|
|
|
readline(rom_file, rom_line);
|
|
|
|
hread(rom_line, rom(i));
|
|
|
|
end loop;
|
|
|
|
|
|
|
|
return rom;
|
|
|
|
end function;
|
|
|
|
|
|
|
|
constant font: rom_type := read_font("font.hex");
|
|
|
|
|
2018-04-25 23:50:09 +02:00
|
|
|
signal row: unsigned(5 downto 0);
|
|
|
|
signal col: unsigned(6 downto 0);
|
|
|
|
|
|
|
|
signal eff_row_wide: unsigned(6 downto 0);
|
|
|
|
signal eff_row: unsigned(5 downto 0);
|
|
|
|
|
2018-04-24 23:44:13 +02:00
|
|
|
signal read_address: std_logic_vector(12 downto 0);
|
2018-01-23 03:02:06 +01:00
|
|
|
signal current_char: std_logic_vector(7 downto 0);
|
2018-04-25 23:50:09 +02:00
|
|
|
signal current_row_length: std_logic_vector(6 downto 0);
|
2018-01-23 03:02:06 +01:00
|
|
|
|
|
|
|
signal current_glyph: std_logic_vector(63 downto 0);
|
2018-04-25 23:50:09 +02:00
|
|
|
signal current_glyph_valid: boolean;
|
2018-01-23 03:02:06 +01:00
|
|
|
|
2018-01-24 23:43:41 +01:00
|
|
|
-- delay by 2 cycles to match the delay of x/y -> rgb
|
|
|
|
constant glyph_pos_length: integer := 2;
|
|
|
|
type glyph_pos_type is array(1 to glyph_pos_length) of integer range 0 to 63;
|
|
|
|
signal glyph_pos: glyph_pos_type;
|
2018-01-23 03:02:06 +01:00
|
|
|
begin
|
|
|
|
|
2018-04-25 23:50:09 +02:00
|
|
|
row <= unsigned(y(8 downto 3));
|
|
|
|
col <= unsigned(x(9 downto 3));
|
|
|
|
|
|
|
|
-- calculate effective row with respect to the cursor; this keeps the
|
|
|
|
-- cursor always at the bottom of the screen and old contents scoll up
|
|
|
|
eff_row_wide <= resize(cursor_row, 7) + row + 1;
|
|
|
|
eff_row <= resize(eff_row_wide, 6) when eff_row_wide < "0111100" else -- 60
|
|
|
|
resize(eff_row_wide - "0111100", 6); -- 60
|
|
|
|
|
|
|
|
read_address <= std_logic_vector(col) & std_logic_vector(eff_row);
|
2018-04-24 21:28:02 +02:00
|
|
|
|
2018-04-25 22:55:39 +02:00
|
|
|
terminal_buffer: entity work.ram_2port generic map (
|
|
|
|
WIDTH_BITS => 8,
|
|
|
|
DEPTH_BITS => 13
|
|
|
|
) port map (
|
2018-04-24 21:28:02 +02:00
|
|
|
clk => clk,
|
2018-04-24 23:44:13 +02:00
|
|
|
ra => read_address,
|
2018-04-24 21:28:02 +02:00
|
|
|
do => current_char,
|
2018-04-25 23:50:09 +02:00
|
|
|
we => charbuf_we,
|
|
|
|
wa => charbuf_wa,
|
|
|
|
di => charbuf_di
|
2018-04-24 21:28:02 +02:00
|
|
|
);
|
2018-01-23 03:02:06 +01:00
|
|
|
|
2018-04-25 23:50:09 +02:00
|
|
|
-- store the length of every row so that we don't have to overwrite
|
|
|
|
-- existing rows when wrapping around and can simply disable display
|
|
|
|
-- of non-overwritten characters
|
|
|
|
row_lengths: entity work.ram_2port generic map (
|
|
|
|
WIDTH_BITS => 7,
|
|
|
|
DEPTH_BITS => 6
|
|
|
|
) port map (
|
|
|
|
clk => clk,
|
|
|
|
ra => std_logic_vector(eff_row),
|
|
|
|
do => current_row_length,
|
|
|
|
we => rowlen_we,
|
|
|
|
wa => rowlen_wa,
|
|
|
|
di => rowlen_di
|
|
|
|
);
|
|
|
|
|
|
|
|
-- as the row length is only saved after switching to the next row, we use
|
|
|
|
-- the current cursor col position in the case of the current row, which
|
|
|
|
-- is always at the bottom, so it is always row 59
|
|
|
|
current_glyph_valid <= col < cursor_col when row = "111011" else -- 59
|
|
|
|
col < unsigned(current_row_length);
|
|
|
|
|
2018-01-24 23:43:41 +01:00
|
|
|
process(clk)
|
|
|
|
variable current_glyph_pos: integer range 0 to 127;
|
2018-01-23 03:02:06 +01:00
|
|
|
begin
|
|
|
|
if rising_edge(clk) then
|
2018-01-24 23:43:41 +01:00
|
|
|
current_glyph_pos := to_integer(unsigned(current_char));
|
2018-01-23 03:02:06 +01:00
|
|
|
current_glyph <= font(current_glyph_pos);
|
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
2018-01-24 23:43:41 +01:00
|
|
|
delay_glyph_pos:
|
|
|
|
process(clk)
|
|
|
|
variable combined: std_logic_vector(5 downto 0);
|
|
|
|
begin
|
|
|
|
if rising_edge(clk) then
|
|
|
|
combined := y(2 downto 0) & x(2 downto 0);
|
|
|
|
glyph_pos(glyph_pos_length) <= to_integer(unsigned(combined));
|
|
|
|
|
|
|
|
-- move all elements one index down
|
|
|
|
for i in 1 to glyph_pos_length - 1 loop
|
|
|
|
glyph_pos(i) <= glyph_pos(i + 1);
|
|
|
|
end loop;
|
|
|
|
end if;
|
|
|
|
end process delay_glyph_pos;
|
2018-01-23 03:02:06 +01:00
|
|
|
|
|
|
|
-- actually currently BRG
|
2018-04-25 23:50:09 +02:00
|
|
|
with current_glyph(glyph_pos(1)) = '1' and current_glyph_valid
|
|
|
|
select rgb <=
|
|
|
|
"111111111111111111111111" when true,
|
|
|
|
"000000000000000000000000" when false;
|
2018-01-23 03:02:06 +01:00
|
|
|
|
|
|
|
end logic;
|