📄 vdu8.vhd
字号:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
--
--
-- Video Display terminal
-- John Kent
-- 11th February 2004
-- Assumes a pixel chock of 19.8 MHz
-- with a character display of 64 characters across
-- by 30 characters down.
--
entity vdu is
port(
-- control register interface
vdu_clk_in : in std_logic;
vdu_clk_out : out std_logic;
vdu_rst : in std_logic;
vdu_cs : in std_logic;
vdu_rw : in std_logic;
vdu_addr : in std_logic_vector(2 downto 0);
vdu_data_in : in std_logic_vector(7 downto 0);
vdu_data_out : out std_logic_vector(7 downto 0);
-- vga port connections
vga_red0_o : out std_logic;
vga_red1_o : out std_logic;
vga_green0_o : out std_logic;
vga_green1_o : out std_logic;
vga_blue0_o : out std_logic;
vga_blue1_o : out std_logic;
vga_hsync_o : out std_logic;
vga_vsync_o : out std_logic
);
end vdu;
architecture arch of vdu is
constant HI: std_logic := '1';
constant LO: std_logic := '0';
signal horiz_sync : std_logic;
signal vert_sync : std_logic;
signal cursor_on_v : std_logic;
signal cursor_on_h : std_logic;
signal video_on_v : std_logic;
signal video_on_h : std_logic;
signal h_count : std_logic_vector(9 downto 0);
signal v_count : std_logic_vector(9 downto 0);
signal blink_count : std_logic_vector(22 downto 0);
--
-- Character generator ROM
--
signal char_cs : std_logic;
signal char_rw : std_logic;
signal char_addr : std_logic_vector(9 downto 0);
signal char_data_in : std_logic_vector(7 downto 0);
signal char_data_out : std_logic_vector(7 downto 0);
--
-- Control Registers
--
signal reg_character : std_logic_vector(7 downto 0);
signal reg_colour : std_logic_vector(7 downto 0);
signal reg_hcursor : std_logic_vector(5 downto 0); -- 64 columns
signal reg_vcursor : std_logic_vector(4 downto 0); -- 32 rows
signal reg_voffset : std_logic_vector(4 downto 0); -- 32 rows
--
-- Video Shift register
--
signal vga_shift : std_logic_vector(7 downto 0);
signal vga_colour : std_logic_vector(7 downto 0);
signal vga_colour1 : std_logic_vector(7 downto 0);
signal cursor_on : std_logic;
signal cursor_on1 : std_logic;
signal video_on : std_logic;
signal video_on1 : std_logic;
--
-- vga character ram access bus
--
signal vga_cs : std_logic;
signal vga_rw : std_logic;
signal vga_addr : std_logic_vector(10 downto 0); -- 2K byte character buffer
signal vga_data_out : std_logic_vector(7 downto 0);
signal attr_data_out : std_logic_vector(7 downto 0); -- 2K byte atrribute buffer
--
-- Character write handshake signals
--
signal req_write : std_logic; -- request character/attribute write
signal ack_write : std_logic;
component char_rom
port (
clk : in std_logic;
rst : in std_logic;
cs : in std_logic;
rw : in std_logic;
addr : in std_logic_vector (9 downto 0);
wdata : in std_logic_vector (7 downto 0);
rdata : out std_logic_vector (7 downto 0)
);
end component;
component ram_2k
port (
clk : in std_logic;
rst : in std_logic;
cs : in std_logic;
rw : in std_logic;
addr : in std_logic_vector (10 downto 0);
wdata : in std_logic_vector (7 downto 0);
rdata : out std_logic_vector (7 downto 0)
);
end component;
component BUFG
port (
i: in std_logic;
o: out std_logic
);
end component;
begin
--
-- instantiate Character generator ROM
--
vdu_char_rom: char_rom
port map(
clk => vdu_clk_in,
rst => vdu_rst,
cs => char_cs,
rw => char_rw,
addr => char_addr,
wdata => char_data_in,
rdata => char_data_out
);
--
-- Character buffer RAM
--
char_buff_ram: ram_2k
port map(
clk => vdu_clk_in,
rst => vdu_rst,
cs => vga_cs,
rw => vga_rw,
addr => vga_addr,
wdata => reg_character,
rdata => vga_data_out
);
--
-- Attribute (colour) RAM buffer
--
attr_buff_ram: ram_2k
port map(
clk => vdu_clk_in,
rst => vdu_rst,
cs => vga_cs,
rw => vga_rw,
addr => vga_addr,
wdata => reg_colour,
rdata => attr_data_out
);
clk_buffer : BUFG port map(
i => h_count(0),
o => vdu_clk_out
);
--
-- CPU Write interface
--
vga_cpu_write : process( vdu_clk_in, vdu_rst, vdu_cs, vdu_rw, vdu_addr, vdu_data_in,
reg_character, reg_colour, reg_hcursor, reg_vcursor,
req_write, ack_write )
begin
if( vdu_rst = '1' ) then
reg_character <= "00000000";
reg_colour <= "00001111";
reg_hcursor <= "000000";
reg_vcursor <= "00000";
reg_voffset <= "00000";
req_write <= '0';
elsif vdu_clk_in'event and vdu_clk_in='0' then
if (vdu_cs = '1') and (vdu_rw = '0') then
case vdu_addr is
when "000" =>
reg_character <= vdu_data_in;
reg_colour <= reg_colour;
reg_hcursor <= reg_hcursor;
reg_vcursor <= reg_vcursor;
reg_voffset <= reg_voffset;
req_write <= '1';
when "001" =>
reg_character <= reg_character;
reg_colour <= vdu_data_in;
reg_hcursor <= reg_hcursor;
reg_vcursor <= reg_vcursor;
reg_voffset <= reg_voffset;
req_write <= '1';
when "010" =>
reg_character <= reg_character;
reg_colour <= reg_colour;
reg_hcursor <= vdu_data_in(5 downto 0);
reg_vcursor <= reg_vcursor;
reg_voffset <= reg_voffset;
req_write <= req_write;
when "011" =>
reg_character <= reg_character;
reg_colour <= reg_colour;
reg_hcursor <= reg_hcursor;
reg_vcursor <= vdu_data_in(4 downto 0);
reg_voffset <= reg_voffset;
req_write <= req_write;
when others =>
reg_character <= reg_character;
reg_colour <= reg_colour;
reg_hcursor <= reg_hcursor;
reg_vcursor <= reg_vcursor;
reg_voffset <= vdu_data_in(4 downto 0);
req_write <= req_write;
end case;
else
reg_character <= reg_character;
reg_colour <= reg_colour;
reg_hcursor <= reg_hcursor;
reg_vcursor <= reg_vcursor;
reg_voffset <= reg_voffset;
if (req_write = '1') and (ack_write = '1') then
req_write <= '0';
else
req_write <= req_write;
end if;
end if;
end if;
end process;
--
-- CPU Read interface
--
vga_cpu_read : process( vdu_addr, vdu_cs,
reg_character, reg_colour, reg_hcursor, reg_vcursor )
begin
case vdu_addr is
when "000" =>
vdu_data_out <= reg_character;
when "001" =>
vdu_data_out <= reg_colour;
when "010" =>
vdu_data_out <= "00" & reg_hcursor;
when "011" =>
vdu_data_out <= "000" & reg_vcursor;
when others =>
vdu_data_out <= "000" & reg_voffset;
end case;
end process;
--
-- Video memory access
--
vga_addr_proc : process( reg_hcursor, reg_vcursor, reg_character, reg_colour,
h_count, v_count, req_write )
begin
case h_count(2 downto 0) is
when "001" => -- always write cursor data on 1 count
vga_cs <= req_write;
vga_rw <= '0';
vga_addr(5 downto 0) <= reg_hcursor;
vga_addr(10 downto 6) <= reg_vcursor;
when "110" => -- always read display character on 6 count
vga_cs <= '1';
vga_rw <= '1';
vga_addr(5 downto 0) <= h_count(8 downto 3);
vga_addr(10 downto 6) <= v_count(8 downto 4) + reg_voffset(4 downto 0);
when others => -- other 6 cycles free
vga_cs <= '0';
vga_rw <= '1';
vga_addr(5 downto 0) <= h_count(8 downto 3);
vga_addr(10 downto 6) <= v_count(8 downto 4) + reg_voffset(4 downto 0);
end case;
end process;
--
-- Video shift register
--
vga_shift_proc : process( vdu_clk_in, char_data_out,
video_on, video_on1, cursor_on, cursor_on1,
vga_colour, vga_colour1, vga_shift,
reg_hcursor, reg_vcursor, reg_character, reg_colour,
h_count, v_count,
req_write, ack_write )
begin
if (vdu_rst = '1') then
ack_write <= '0';
vga_colour <= "00001111";
vga_shift <= "00000000";
vga_red0_o <= '0';
vga_green0_o <= '0';
vga_blue0_o <= '0';
vga_red1_o <= '0';
vga_green1_o <= '0';
vga_blue1_o <= '0';
-- Put all video signals through DFFs to elminate any delays that cause a blurry image
elsif vdu_clk_in'event and vdu_clk_in='0' then
case h_count(2 downto 0) is
when "001" => -- always write cursor data on 1 count
if (req_write = '1') and (ack_write = '0') then
ack_write <= '1';
else
ack_write <= '0';
end if;
when others => -- other 4 cycles CPU is free to run.
ack_write <= ack_write;
end case;
if h_count(2 downto 0) = "111" then
vga_colour1 <= attr_data_out;
else
vga_colour1 <= vga_colour1;
end if;
if h_count(2 downto 0) = "000" then
video_on <= video_on1;
cursor_on <= cursor_on1;
vga_colour <= vga_colour1;
vga_shift <= char_data_out;
else
video_on <= video_on;
cursor_on <= cursor_on;
vga_colour <= vga_colour;
vga_shift <= vga_shift(6 downto 0) & '0';
end if;
--
-- Colour mask is
-- 7 6 5 4 3 2 1 0
-- BI BG BB BR FI FG FB FR
--
if vga_shift(7) = (not cursor_on) then
if vga_colour(3) = '0' then
vga_red0_o <= video_on and vga_colour(0);
vga_green0_o <= video_on and vga_colour(1);
vga_blue0_o <= video_on and vga_colour(2);
vga_red1_o <= '0';
vga_green1_o <= '0';
vga_blue1_o <= '0';
else
vga_red0_o <= '0';
vga_green0_o <= '0';
vga_blue0_o <= '0';
vga_red1_o <= video_on and vga_colour(0);
vga_green1_o <= video_on and vga_colour(1);
vga_blue1_o <= video_on and vga_colour(2);
end if;
else
if vga_colour(7) = '0' then
vga_red0_o <= video_on and vga_colour(4);
vga_green0_o <= video_on and vga_colour(5);
vga_blue0_o <= video_on and vga_colour(6);
vga_red1_o <= '0';
vga_green1_o <= '0';
vga_blue1_o <= '0';
else
vga_red0_o <= '0';
vga_green0_o <= '0';
vga_blue0_o <= '0';
vga_red1_o <= video_on and vga_colour(4);
vga_green1_o <= video_on and vga_colour(5);
vga_blue1_o <= video_on and vga_colour(6);
end if;
end if;
end if;
end process;
--
-- Sync generator & timing process
-- Generate Horizontal and Vertical Timing Signals for Video Signal
--
vga_sync: PROCESS(vdu_clk_in, h_count, v_count, horiz_sync, vert_sync )
BEGIN
if vdu_clk_in'event and vdu_clk_in='0' then
--
-- H_count counts pixels (256 + extra time for sync signals)
--
-- Horiz_sync ------------------------------------__________--------
-- H_count 0 512 528 604 639
--
IF (h_count = 639) THEN
h_count <= "0000000000";
ELSE
h_count <= h_count + 1;
END IF;
--
-- Generate Horizontal Sync Signal using H_count
--
IF (h_count <= 604) AND (h_count >= 528) THEN
horiz_sync <= '0';
ELSE
horiz_sync <= '1';
END IF;
--
-- V_count counts rows of pixels (480 + extra time for sync signals)
--
-- Vert_sync -----------------------------------------------_______------------
-- V_count 0 480 493-494 524
--
IF (v_count >= 588) AND (h_count >= 566) THEN
v_count <= "0000000000";
ELSIF (h_count = 283) THEN
v_count <= v_count + 1;
END IF;
--
-- Generate Vertical Sync Signal using V_count
--
IF (v_count <= 558) AND (v_count >= 557) THEN
vert_sync <= '0';
ELSE
vert_sync <= '1';
END IF;
-- Generate Video on Screen Signals for Pixel Data
IF (h_count <= 511) THEN
video_on_h <= '1';
ELSE
video_on_h <= '0';
END IF;
IF (v_count <= 511) THEN
video_on_v <= '1';
ELSE
video_on_v <= '0';
END IF;
if (h_count(8 downto 3) = reg_hcursor(5 downto 0)) then
cursor_on_h <= '1';
else
cursor_on_h <= '0';
end if;
if (v_count(8 downto 4) = reg_vcursor(4 downto 0)) then
cursor_on_v <= '1';
else
cursor_on_v <= '0';
end if;
-- cursor_on is only active when on selected character
blink_count <= blink_count + 1;
end if;
END PROCESS;
char_cs <= '1';
char_rw <= '1';
char_addr(2 downto 0) <= v_count(3 downto 1);
char_addr(9 downto 3) <= vga_data_out(6 downto 0);
char_data_in <= "00000000";
-- video_on is high only when RGB data is displayed
video_on1 <= video_on_H AND video_on_V;
cursor_on1 <= cursor_on_h and cursor_on_v and blink_count(21);
vga_hsync_o <= horiz_sync;
vga_vsync_o <= vert_sync;
end arch;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -