📄 videocontroller.vhd
字号:
--Video controller. Includes:
-- - Sync generator
-- - Char generator
-- - Video memory (character code + attributes)
-- - Palette
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity VideoController is
Port ( CLK : in std_logic;
RESET : in std_logic;
R : out std_logic;
G : out std_logic;
B : out std_logic;
HS, VS : out std_logic;
--Designate the coordinate for which to read/write the charcode/attribute
COLUMN : in std_logic_vector(5 downto 0);
ROW : in std_logic_vector(3 downto 0);
CHAR_CODE_READ : out std_logic_vector(7 downto 0);
CHAR_CODE_WRITE : in std_logic_vector(7 downto 0);
CHAR_ATTRIBUTES_READ : out std_logic_vector(7 downto 0);
CHAR_ATTRIBUTES_WRITE : in std_logic_vector(7 downto 0);
--On the rising edge charcode / attribute is written to the memory
CHAR_WRITE_STROBE : in std_logic;
PALETTE_INDEX : in std_logic_vector(2 downto 0);
PALETTE_READ : out std_logic_vector(7 downto 0);
PALETTE_WRITE : in std_logic_vector(7 downto 0);
PALETTE_WRITE_STROBE : in std_logic);
end VideoController;
architecture Behavioral of VideoController is
component VGASyncGen is
Port ( CLK : in std_logic;
HS : out std_logic;
VS : out std_logic;
VIDEO_ON : out std_logic;
X : out std_logic_vector(9 downto 0);
Y : out std_logic_vector(9 downto 0));
end component;
component CharMap is
Port ( CLK: std_logic;
CHAR_CODE : in std_logic_vector(7 downto 0);
ROW : in std_logic_vector(3 downto 0);
COL : in std_logic_vector(2 downto 0);
CHAR_BIT : out std_logic);
end component;
component DPortVidRam is
Port ( ADDRESS_A : in std_logic_vector(9 downto 0);
ADDRESS_B : in std_logic_vector(9 downto 0);
DATA_READ_A : out std_logic_vector(15 downto 0);
DATA_READ_B : out std_logic_vector(15 downto 0);
DATA_WRITE_A : in std_logic_vector(15 downto 0);
ENABLE_A : in std_logic;
ENABLE_B : in std_logic;
WRITE_STROBE_A : in std_logic;
CLK : in std_logic;
RESET : in std_logic);
end component;
component PaletteMemory is
Port ( RESET : in std_logic;
READ_INDEX_A : in std_logic_vector(2 downto 0);
READ_VALUE_A : out std_logic_vector(7 downto 0);
READ_INDEX_B : in std_logic_vector(2 downto 0);
READ_VALUE_B : out std_logic_vector(7 downto 0);
WRITE_INDEX : in std_logic_vector(2 downto 0);
WRITE_VALUE : in std_logic_vector(7 downto 0);
WRITE_STROBE : in std_logic);
end component;
component LimitCounter is
generic ( element_width: positive := 2);
Port ( RESET : in std_logic;
CLK : in std_logic;
SWITCH_LIMIT : in std_logic_vector(element_width-1 downto 0);
OUTPUT_SIGNAL : out std_logic);
end component;
component FreqDivider is
generic ( division_factor: positive := 20);
Port ( CLK : in std_logic;
DIVIDED_CLK : out std_logic);
end component;
signal X, Y: std_logic_vector(9 downto 0);
signal VIDEO_ON: std_logic;
signal ADDRESS_A, ADDRESS_B: std_logic_vector(9 DOWNTO 0);
signal MemoryElementRead_A, MemoryElementRead_B,
MemoryElementWrite: std_logic_vector(15 downto 0);
signal CharBit, CharBit_Underline, Underline_Zone, CharBit_Blink, Blink_Zone, BlinkBlink: std_logic;
signal PaletteReadIndex: std_logic_vector(2 downto 0);
signal PaletteDisplayEntry: std_logic_vector(7 downto 0);
signal RR, GG, BB, LastCol: std_logic;
begin
--Generate synch signals
SyncGen: VGASyncGen port map (CLK, HS, VS, VIDEO_ON, X, Y);
--Address A - the address the user modifies
ADDRESS_A <= ROW(3 downto 0) & COLUMN(5 downto 0);
--Address B - the address the screen drawer uses
ADDRESS_B <= Y(8 downto 5) & X(9 downto 4);
--Actual data written in the memory
MemoryElementWrite <= CHAR_CODE_WRITE & CHAR_ATTRIBUTES_WRITE;
VidRAM: DPortVidRam port map (
ADDRESS_A, ADDRESS_B, MemoryElementRead_A, MemoryElementRead_B,
MemoryElementWrite, not(RESET), not(RESET), CHAR_WRITE_STROBE,
CLK, RESET);
CHAR_CODE_READ <= MemoryElementRead_A(15 downto 8);
CHAR_ATTRIBUTES_READ <= MemoryElementRead_A(7 downto 0);
--Character map
CM: CharMap port map (CLK, MemoryElementRead_B(15 downto 8), Y(4 downto 1), X(3 downto 1), CharBit);
--Generate underline if attribute set
Underline_Zone <= '1' when (Y(4 downto 1) >= X"0E") else '0';
CharBit_Underline <= '1' when (MemoryElementRead_B(0) and Underline_Zone) = '1'
else CharBit;
--Blink the elmenent is attribute set
FDBLINK: FreqDivider generic map (division_factor => 26 ) port map (CLK, Blink_Zone);
BlinkBlink <= not(Blink_Zone) and MemoryElementRead_B(1);
CharBit_Blink <= '0' when (BlinkBlink = '1') else CharBit_Underline;
--Select to display background or foreground color depending on the resulting pixel
with CharBit_Blink select
PaletteReadIndex <= MemoryElementRead_B(7 downto 5) when '1',
MemoryElementRead_B(4 downto 2) when others;
--Read the given color from the palette memory
PM: PaletteMemory port map (RESET, PALETTE_INDEX, PALETTE_READ, PaletteReadIndex, PaletteDisplayEntry,
PALETTE_INDEX, PALETTE_WRITE, PALETTE_WRITE_STROBE);
--Ugly hack: Do not display the first column of each character because of some timing mismatch
--it displays extra pixels sometimes
with X(3 downto 1) select
LastCol <= '0' when "000",
'1' when others;
--The PWMs modulating the colors
LCR: LimitCounter port map (RESET, CLK, PaletteDisplayEntry(5 downto 4), RR);
LCG: LimitCounter port map (RESET, CLK, PaletteDisplayEntry(3 downto 2), GG);
LCB: LimitCounter port map (RESET, CLK, PaletteDisplayEntry(1 downto 0), BB);
--The final output of the colors
R <= RR and LastCol and VIDEO_ON;
G <= GG and LastCol and VIDEO_ON;
B <= BB and LastCol and VIDEO_ON;
end Behavioral;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -