Initial import

git-svn-id: http://moon:8086/svn/vhdl/trunk@5 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
2008-08-23 08:20:30 +00:00
parent bfbeba5129
commit d3bd08bb52
160 changed files with 56260 additions and 0 deletions
+546
View File
@@ -0,0 +1,546 @@
--------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 11:25:45 10/15/05
-- Design Name:
-- Module Name: char_gen - Behavioral
-- Project Name:
-- Target Device:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.vga_types.all;
entity char_gen is
Generic
(
tsvga : vga_timespec_t := ts_vga_800_600_72;
-- User supplied parameters
CHARACTER_SCALE : natural := 1;
CHAR_ROM_SIZE_X : natural := 8; -- Pixels
CHAR_ROM_SIZE_Y : natural := 16; -- Pixels
CHAR_ROM_DEPTH : natural := 256; -- Chars
MAX_CHAR_PER_LINE : natural := 32; -- Chars
MAX_LINE_PER_FRAME : natural := 16; -- Chars
CHAR_SPACING_X : natural := 0; -- Pixels
CHAR_SPACING_Y : natural := 0; -- Pixels
SCREEN_OFFSET_X : natural := 16; -- Pixels
SCREEN_OFFSET_Y : natural := 16 -- Pixels
);
Port
(
-- System signals
rst : in std_logic;
vga_clk : in std_logic;
sys_clk : in std_logic;
ce : in std_logic;
frame_pulse : in std_logic;
-- Host Signals
clr_screen : in std_logic;
clr_line : in std_logic;
ascii_data : in unsigned(7 downto 0);
ascii_data_we : in std_logic;
ascii_posy_we : in std_logic;
ascii_posx_we : in std_logic;
ready : out std_logic;
-- Control signals
pos_x : in natural range 0 to tsvga.ts_h.ncyc_scan-1;
pos_y : in natural range 0 to tsvga.ts_v.ncyc_scan-1;
-- Output
char_draw_en : out std_logic
);
end char_gen;
architecture Behavioral of char_gen is
constant A_RAM_ADDR_WIDTH : integer := 12;
constant A_RAM_DATA_WIDTH : integer := 8;
type offset_rom_t is array (0 to MAX_LINE_PER_FRAME-1) of unsigned(A_RAM_ADDR_WIDTH-1 downto 0);
function gen_offset_rom(num_char_per_line, num_lines : natural) return offset_rom_t is
variable result : offset_rom_t;
variable offset : unsigned(A_RAM_ADDR_WIDTH-1 downto 0) := (others => '0');
begin
for i in 0 to num_lines-1 loop
result(i) := offset;
offset := offset + to_unsigned(num_char_per_line, A_RAM_ADDR_WIDTH-1);
end loop;
return result;
end gen_offset_rom;
constant offset_rom : offset_rom_t := gen_offset_rom(MAX_CHAR_PER_LINE, MAX_LINE_PER_FRAME);
-- Calculated parameters
type cg_state_t is (cg_init, cg_ready, cg_clr_line, cg_clr_screen);
signal s, sn : cg_state_t;
constant CELL_SIZE_X : natural := (CHAR_ROM_SIZE_X+CHAR_SPACING_X)*CHARACTER_SCALE;
constant CELL_SIZE_Y : natural := (CHAR_ROM_SIZE_Y+CHAR_SPACING_Y)*CHARACTER_SCALE;
constant CHAR_SIZE_X : natural := CHAR_ROM_SIZE_X*CHARACTER_SCALE;
constant CHAR_SIZE_Y : natural := CHAR_ROM_SIZE_Y*CHARACTER_SCALE;
signal line_offset : natural range 0 to MAX_LINE_PER_FRAME-1;
signal cell_x_cnt : natural range 0 to MAX_CHAR_PER_LINE-1;
signal cell_y_cnt : natural range 0 to MAX_LINE_PER_FRAME-1;
signal char_x_cnt : natural range 0 to CELL_SIZE_X-1;
signal char_y_cnt : natural range 0 to CELL_SIZE_Y-1;
signal char_rom_row : unsigned(NextExpBaseTwo(CHAR_SIZE_Y)-1 downto 0);
signal char_rom_addr : unsigned(NextExpBaseTwo(CHAR_ROM_DEPTH*CHAR_ROM_SIZE_Y)-1 downto 0);
signal char_rom_data : unsigned(CHAR_ROM_SIZE_X-1 downto 0);
signal char_reg : unsigned((CHARACTER_SCALE*CHAR_ROM_SIZE_X)-1 downto 0);
signal a_addr_rd : unsigned(A_RAM_ADDR_WIDTH-1 downto 0);
signal a_addr_wr : unsigned(A_RAM_ADDR_WIDTH-1 downto 0);
signal a_data_rd : unsigned(A_RAM_DATA_WIDTH-1 downto 0);
signal a_data_wr : unsigned(A_RAM_DATA_WIDTH-1 downto 0);
signal a_ram_we : std_logic;
signal a_cnt : natural range 0 to 2**A_RAM_ADDR_WIDTH-1;
signal a_cnt_rst : std_logic;
signal a_cnt_en : std_logic;
signal csr_posx_reg : natural range 0 to MAX_CHAR_PER_LINE-1;
signal csr_posy_reg : natural range 0 to MAX_LINE_PER_FRAME-1;
signal a_data_reg : unsigned(A_RAM_DATA_WIDTH-1 downto 0);
signal a_data_we : std_logic;
signal csr_posx_overflow : std_logic;
signal csr_posx_cnt_din : natural range 0 to MAX_CHAR_PER_LINE-1;
signal csr_posx_cnt_set : std_logic;
signal csr_posx_cnt_en : std_logic;
signal csr_posy_overflow : std_logic;
signal csr_posy_cnt_din : natural range 0 to MAX_LINE_PER_FRAME-1;
signal csr_posy_cnt_set : std_logic;
signal csr_posy_cnt_en : std_logic;
signal line_addr : unsigned(A_RAM_ADDR_WIDTH-1 downto 0);
signal char_addr : unsigned(A_RAM_ADDR_WIDTH-1 downto 0);
-- Visible Cursor
constant CURSOR_BLINK_INTERVAL : natural := tsvga.nfps/2;
type cursor_rom_t is array (0 to 2*CHAR_ROM_SIZE_Y-1) of unsigned (CHAR_ROM_SIZE_X-1 downto 0);
constant cursor_rom : cursor_rom_t :=
(
-- Cursor off
"00000000",
"00000000",
"00000000",
"00000000",
"00000000",
"00000000",
"00000000",
"00000000",
"00000000",
"00000000",
"00000000",
"00000000",
"00000000",
"11111111",
"11111111",
"11111111",
-- Cursor on
"00000000",
"00000000",
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
"00000000",
"00000000",
"00000000"
);
signal cursor_rom_addr : unsigned(NextExpBaseTwo(2*CHAR_ROM_SIZE_Y)-1 downto 0);
signal cursor_rom_data : unsigned(CHAR_ROM_SIZE_X-1 downto 0);
signal cursor_visible : std_logic;
signal cursor_cnt : natural range 0 to CURSOR_BLINK_INTERVAL-1;
signal csr_posx_synced : natural range 0 to MAX_CHAR_PER_LINE-1;
signal csr_posy_synced : natural range 0 to MAX_LINE_PER_FRAME-1;
-- Scrolling
signal scroll_offset : natural range 0 to MAX_CHAR_PER_LINE-1;
signal scroll_active : std_logic;
begin
a_addr_rd <= to_unsigned(cell_x_cnt, a_addr_rd'length) + offset_rom(line_offset);
line_addr <= offset_rom(csr_posy_reg);
char_addr <= to_unsigned(csr_posx_reg, char_addr'length);
char_rom_addr <= a_data_rd & char_rom_row(NextExpBaseTwo(CHAR_SIZE_Y)-1 downto (CHARACTER_SCALE-1));
cursor_rom_addr <= cursor_visible & char_rom_row(NextExpBaseTwo(CHAR_SIZE_Y)-1 downto (CHARACTER_SCALE-1));
inst_char_rom : entity work.char_rom
PORT MAP
(
CLK => vga_clk,
ADDR => char_rom_addr,
DATA => char_rom_data
);
inst_ascii_ram: entity work.dpram
GENERIC MAP (
addr_width => A_RAM_ADDR_WIDTH,
data_width => A_RAM_DATA_WIDTH
)
PORT MAP(
clka => sys_clk,
clkb => vga_clk,
en_a => '1',
en_b => '1',
we_a => a_ram_we,
addr_a => a_addr_wr,
addr_b => a_addr_rd,
din_a => a_data_wr,
dout_b => a_data_rd
);
---------------------------------------------------------------------------------------------
--- ASCII RAM control
---------------------------------------------------------------------------------------------
asci_ram_fsm:
process (s, a_cnt, clr_line, clr_screen, a_data_we, a_data_reg, char_addr, line_addr)
begin
sn <= s;
a_cnt_rst <= '0';
a_cnt_en <= '0';
a_ram_we <= '0';
a_data_wr <= a_data_reg;
a_addr_wr <= char_addr + line_addr;
ready <= '0';
case s is
when cg_init =>
sn <= cg_clr_screen;
a_cnt_rst <= '1';
when cg_ready =>
ready <= '1';
a_ram_we <= a_data_we;
if clr_screen = '1' then
a_cnt_rst <= '1';
sn <= cg_clr_screen;
elsif clr_line = '1' then
a_cnt_rst <= '1';
sn <= cg_clr_line;
end if;
when cg_clr_line =>
a_ram_we <= '1';
a_cnt_en <= '1';
a_data_wr <= to_unsigned(0, A_RAM_DATA_WIDTH);
a_addr_wr <= to_unsigned(a_cnt + to_integer(line_addr), A_RAM_ADDR_WIDTH);
if a_cnt = MAX_CHAR_PER_LINE-1 then
sn <= cg_ready;
end if;
when cg_clr_screen =>
a_ram_we <= '1';
a_cnt_en <= '1';
a_data_wr <= to_unsigned(0, A_RAM_DATA_WIDTH);
a_addr_wr <= to_unsigned(a_cnt, A_RAM_ADDR_WIDTH);
if a_cnt = (2**A_RAM_ADDR_WIDTH-1) then
sn <= cg_ready;
end if;
when others =>
sn <= cg_ready;
end case;
end process;
asci_ram_fsm_next: process (rst, sys_clk)
begin
if rst = '1' then
s <= cg_init;
elsif rising_edge(sys_clk) then
s <= sn;
end if;
end process;
---------------------------------------------------------------------------------------------
asci_ram_cnt: process (rst, sys_clk)
begin
if rst = '1' then
a_cnt <= 0;
elsif rising_edge(sys_clk) then
if a_cnt_rst = '1' then
a_cnt <= 0;
elsif a_cnt_en = '1' then
if a_cnt < (2**A_RAM_ADDR_WIDTH-1) then
a_cnt <= a_cnt + 1;
end if;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------
asci_addr_reg: process (rst, sys_clk)
begin
if rst = '1' then
csr_posx_cnt_en <= '0';
csr_posx_cnt_set <= '0';
csr_posy_cnt_en <= '0';
csr_posy_cnt_set <= '0';
a_data_reg <= (others => '0');
a_data_we <= '0';
elsif rising_edge(sys_clk) then
a_data_we <= '0';
csr_posx_cnt_en <= '0';
csr_posx_cnt_set <= '0';
csr_posy_cnt_en <= '0';
csr_posy_cnt_set <= '0';
if ascii_posy_we = '1' then
csr_posy_cnt_din <= to_integer(ascii_data);
csr_posy_cnt_set <= '1';
elsif ascii_posx_we = '1' then
csr_posx_cnt_din <= to_integer(ascii_data);
csr_posx_cnt_set <= '1';
elsif ascii_data_we = '1' then
if ascii_data < X"20" then
if ascii_data = X"0D" then
csr_posx_cnt_din <= 0;
csr_posx_cnt_set <= '1';
elsif ascii_data = X"0A" then
csr_posy_cnt_en <= '1';
end if;
else
a_data_reg <= ascii_data - X"20";
a_data_we <= '1';
csr_posx_cnt_en <= '1';
end if;
end if;
end if;
end process;
asci_csr_posx_counter:
process (rst, sys_clk)
begin
if rst = '1' then
csr_posx_reg <= 0;
csr_posx_overflow <= '0';
elsif rising_edge(sys_clk) then
csr_posx_overflow <= '0';
if csr_posx_cnt_set = '1' then
csr_posx_reg <= csr_posx_cnt_din;
elsif csr_posx_cnt_en = '1' then
if csr_posx_reg < MAX_CHAR_PER_LINE-1 then
csr_posx_reg <= csr_posx_reg + 1;
else
csr_posx_reg <= 0;
csr_posx_overflow <= '1';
end if;
end if;
end if;
end process;
asci_csr_posy_counter:
process (rst, sys_clk)
begin
if rst = '1' then
csr_posy_reg <= 0;
csr_posy_overflow <= '0';
elsif rising_edge(sys_clk) then
csr_posy_overflow <= '0';
if csr_posy_cnt_set = '1' then
csr_posy_reg <= csr_posy_cnt_din;
elsif csr_posy_cnt_en = '1' or csr_posx_overflow = '1' then
if csr_posy_reg < MAX_LINE_PER_FRAME-1 then
csr_posy_reg <= csr_posy_reg + 1;
else
csr_posy_reg <= 0;
csr_posy_overflow <= '1';
end if;
end if;
end if;
end process;
scroll_gen: process (rst, sys_clk)
begin
if rst = '1' then
scroll_offset <= 0;
scroll_active <= '0';
elsif rising_edge(sys_clk) then
if clr_screen = '1' then
scroll_offset <= 0;
scroll_active <= '0';
elsif csr_posy_overflow = '1' then
scroll_active <= '1';
scroll_offset <= 1;
end if;
if (csr_posy_cnt_en = '1' or csr_posx_overflow = '1') and scroll_active = '1' then
scroll_offset <= scroll_offset + 1;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------
--- Cursor generator
---------------------------------------------------------------------------------------------
proc_sync_csr_posx:
process(vga_clk)
variable p1, p2 : natural range 0 to MAX_CHAR_PER_LINE-1;
begin
if rising_edge(vga_clk) then
csr_posx_synced <= p2;
p2 := p1;
p1 := csr_posx_reg;
end if;
end process;
proc_sync_csr_posy:
process(vga_clk)
variable p1, p2 : natural range 0 to MAX_LINE_PER_FRAME-1;
begin
if rising_edge(vga_clk) then
csr_posy_synced <= p2;
p2 := p1;
p1 := csr_posy_reg;
end if;
end process;
csr_blink_cnt: process (rst, vga_clk)
begin
if rst = '1' then
cursor_cnt <= 0;
cursor_visible <= '0';
elsif rising_edge(vga_clk) then
if frame_pulse = '1' then
if cursor_cnt < CURSOR_BLINK_INTERVAL-1 then
cursor_cnt <= cursor_cnt + 1;
else
cursor_cnt <= 0;
cursor_visible <= not cursor_visible;
end if;
end if;
end if;
end process;
cursor_rom_read: process (vga_clk)
begin
if rising_edge(vga_clk) then
cursor_rom_data <= (others => '0');
if (cell_x_cnt = csr_posx_synced) and (line_offset = csr_posy_synced) then
cursor_rom_data <= cursor_rom(to_integer(cursor_rom_addr));
end if;
end if;
end process;
---------------------------------------------------------------------------------------------
--- Character generator
---------------------------------------------------------------------------------------------
char_rom_ctrl: process (vga_clk)
begin
if rising_edge(vga_clk) then
char_rom_row <= to_unsigned(char_y_cnt, char_rom_row'length);
end if;
end process;
---------------------------------------------------------------------------------------------
char_reg_ctrl: process (vga_clk)
begin
if rising_edge(vga_clk) and ce = '1' then
if char_x_cnt = 2 then -- +2 delay for ASCII-RAM access and CHAR-ROM access
for i in 0 to CHAR_ROM_SIZE_X-1 loop
for j in 0 to CHARACTER_SCALE-1 loop
char_reg(i*CHARACTER_SCALE + j) <= char_rom_data(i) xor cursor_rom_data(i);
end loop;
end loop;
else
char_reg <= char_reg(char_reg'left-1 downto 0) & '0';
end if;
end if;
end process;
---------------------------------------------------------------------------------------------
cg_ctrl: process (rst, vga_clk)
variable enable_x : std_logic;
variable enable_y : std_logic;
variable char_en : std_logic;
variable char_en2 : std_logic;
begin
if (rst = '1') then
enable_x := '0';
enable_y := '0';
line_offset <= 0;
cell_x_cnt <= 0;
cell_y_cnt <= 0;
char_x_cnt <= 0;
char_y_cnt <= 0;
char_en := '0';
elsif rising_edge(vga_clk) and ce = '1' then
char_draw_en <= char_en2 and char_reg(char_reg'left);
char_en2 := char_en;
char_en := '0';
if pos_y = SCREEN_OFFSET_Y then
enable_y := '1';
cell_y_cnt <= 0;
char_x_cnt <= 0;
line_offset <= scroll_offset;
end if;
if pos_x = SCREEN_OFFSET_X and enable_y = '1' then
enable_x := '1';
cell_x_cnt <= 0;
char_x_cnt <= 0;
elsif enable_x = '1' and enable_y = '1' then
if char_x_cnt < CELL_SIZE_X-1 then
char_x_cnt <= char_x_cnt + 1;
else
char_x_cnt <= 0;
if cell_x_cnt < MAX_CHAR_PER_LINE-1 then
cell_x_cnt <= cell_x_cnt + 1;
else
enable_x := '0';
if char_y_cnt < CELL_SIZE_Y-1 then
char_y_cnt <= char_y_cnt + 1;
else
char_y_cnt <= 0;
if cell_y_cnt < MAX_LINE_PER_FRAME-1 then
cell_y_cnt <= cell_y_cnt + 1;
else
enable_y := '0';
end if;
if line_offset < MAX_LINE_PER_FRAME-1 then
line_offset <= line_offset + 1;
else
line_offset <= 0;
end if;
end if;
end if;
end if;
if (char_x_cnt < CHAR_SIZE_X) and (char_y_cnt < CHAR_SIZE_Y) then
char_en := '1';
end if;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------
end Behavioral;