This adds an explicit terminal_buffer entity to help with the blockram inference. Both read and write are completely independent, although they run with the same clock for now.
130 lines
3.6 KiB
VHDL
130 lines
3.6 KiB
VHDL
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;
|
|
|
|
entity font_rom is
|
|
generic (
|
|
input_clk: integer
|
|
);
|
|
port (
|
|
clk: in std_logic;
|
|
x: in std_logic_vector(9 downto 0);
|
|
y: in std_logic_vector(8 downto 0);
|
|
|
|
rgb: out std_logic_vector(23 downto 0)
|
|
);
|
|
end font_rom;
|
|
|
|
architecture logic of font_rom is
|
|
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");
|
|
|
|
signal current_char: std_logic_vector(7 downto 0);
|
|
|
|
signal current_glyph: std_logic_vector(63 downto 0);
|
|
|
|
-- 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;
|
|
|
|
signal write_x: unsigned(6 downto 0);
|
|
signal write_y: unsigned(5 downto 0);
|
|
signal write_value: std_logic_vector(7 downto 0);
|
|
|
|
signal ra: std_logic_vector(12 downto 0);
|
|
signal wa: std_logic_vector(12 downto 0);
|
|
begin
|
|
|
|
ra <= x(9 downto 3) & y(8 downto 3);
|
|
wa <= std_logic_vector(write_x) & std_logic_vector(write_y);
|
|
|
|
write_value <= "0" & std_logic_vector(write_x + 32);
|
|
|
|
cycle_write_location:
|
|
process(clk)
|
|
constant max_delay: integer := 2000000;
|
|
variable delay: integer range 0 to max_delay;
|
|
begin
|
|
if rising_edge(clk) then
|
|
if delay = max_delay then
|
|
delay := 0;
|
|
|
|
if write_x = 79 then
|
|
write_x <= (others => '0');
|
|
if write_y = 59 then
|
|
write_y <= (others => '0');
|
|
else
|
|
write_y <= write_y + 1;
|
|
end if;
|
|
else
|
|
write_x <= write_x + 1;
|
|
end if;
|
|
else
|
|
delay := delay + 1;
|
|
end if;
|
|
end if;
|
|
end process cycle_write_location;
|
|
|
|
terminal_buffer: entity work.terminal_buffer port map (
|
|
clk => clk,
|
|
ra => ra,
|
|
do => current_char,
|
|
we => '1',
|
|
wa => wa,
|
|
di => write_value
|
|
);
|
|
|
|
process(clk)
|
|
variable current_glyph_pos: integer range 0 to 127;
|
|
begin
|
|
if rising_edge(clk) then
|
|
current_glyph_pos := to_integer(unsigned(current_char));
|
|
current_glyph <= font(current_glyph_pos);
|
|
end if;
|
|
end process;
|
|
|
|
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;
|
|
|
|
-- actually currently BRG
|
|
rgb <=
|
|
"111111111111111111111111" when current_glyph(glyph_pos(1)) = '1' else
|
|
"000000000000000000000000";
|
|
|
|
end logic;
|