📄 lancelot_vga.vhd
字号:
---------------------------------
-- Lancelot --
---------------------------------
-- Excalibur Video Controller --
---------------------------------
-- Written by Marco Groeneveld --
---------------------------------
-- History
---------------------------------
-- v5.0 : Avalon Master Lock
-- v4.1 : Proper Line Missed Status Added
-- v4.0 : Updated for Nios II
-- v3.2 : Removed internal reset_int state machine
-- v3.1 : Added DMA length and line length
-- v3.0 : Excalibur ARM version
-- v2.8 : Instantiating dual-port ram in stead of inferring
-- v2.5 : Fixed problem with line buffer fifo status bits
-- v2.3 : Added line missed and new line status bits
-- v2.2 : Implemented native fifos and dpram
-- v2.1 : Added vsync state machine for better timing result
-- v2.0 : Modified for Nios 2.0
-- v1.1 : Changed DAC mode
-- v1.0 : Added resolution, hsync and vsync timing registers
-- v0.9 : Added internal reset_int signal
-- v0.5 : Added two line buffers to solve bandwidth issue
-- v0.1 : Initial version
---------------------------------
-- The Lancelot consists of two main state machines, two fifo's and one dual-ported ram.
-- The two state machines are responsable for the hsync, vsync timing and controlling the fifo's.
-- After activating the dma request line, DMA controller will AVALON_SLAVE_WR video data in the first line buffer.
-- At the same time video data is read out from the second line buffer and feed to the colour table.
-- If the first line buffer is full and the second is empty, then the line buffers are swapped and the process repeats.
-----
-- Library
-----
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;
-----
-- Entity
-----
ENTITY lancelot_vga IS
PORT
(
RESET : IN std_logic;
VIDEO_CLK : IN std_logic;
AVALON_CLK : IN std_logic;
-- Avalon Master Port
AVALON_MASTER_ADDR : OUT std_logic_vector(31 DOWNTO 0);
AVALON_MASTER_DATA_IN : IN std_logic_vector(31 DOWNTO 0);
AVALON_MASTER_RD : OUT std_logic;
AVALON_MASTER_WAITREQ : IN std_logic;
AVALON_MASTER_LOCK : OUT std_logic;
-- Avalon Slave Port
AVALON_SLAVE_CS : IN std_logic;
AVALON_SLAVE_ADDR : IN std_logic_vector(2 DOWNTO 0);
AVALON_SLAVE_DATA_OUT : OUT std_logic_vector(31 DOWNTO 0);
AVALON_SLAVE_DATA_IN : IN std_logic_vector(31 DOWNTO 0);
AVALON_SLAVE_RD : IN std_logic;
AVALON_SLAVE_WR : IN std_logic;
-- Analog Video
R, G, B : OUT std_logic_vector(7 DOWNTO 0);
HS, VS : OUT std_logic;
M1, M2 : OUT std_logic;
BLANK_N : OUT std_logic;
SYNC_N : OUT std_logic;
SYNC_T : OUT std_logic
);
END lancelot_vga;
-----
-- Architecture
-----
ARCHITECTURE behavior OF lancelot_vga IS
---
-- Components
---
COMPONENT lancelot_fifo
GENERIC
(
fifo_depth : natural;
fifo_width : natural
);
PORT
(
rst, wprst, rprst : IN std_logic;
wrclk, rdclk : IN std_logic;
wrreq, rdreq : IN std_logic;
wrdata : IN std_logic_vector(fifo_width - 1 DOWNTO 0);
rddata : OUT std_logic_vector(fifo_width - 1 DOWNTO 0);
wptop, wpbottom, rptop, rpbottom : OUT std_logic;
line_length : IN std_logic_vector(10 DOWNTO 0)
);
END COMPONENT;
COMPONENT lancelot_dpram_256x24
PORT
(
data : IN STD_LOGIC_VECTOR (23 DOWNTO 0);
wraddress : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
rdaddress : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
wren : IN STD_LOGIC := '1';
wrclock : IN STD_LOGIC ;
rdclock : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (23 DOWNTO 0)
);
END COMPONENT;
---
-- State Machines
---
-- Hsync State Machine
TYPE hsync_state_type IS
(
hsync_reset,
hsync_front_porch, hsync_front_porch1,
hsync_pulse, hsync_pulse1,
hsync_back_porch, hsync_back_porch1,
hsync_active_video1, hsync_active_video2, hsync_active_video3, hsync_active_video4,
hsync_blank, hsync_blank1,
hsync_line_missed
);
SIGNAL hsync_current_state, hsync_next_state : hsync_state_type;
-- Vsync State Machine
TYPE vsync_state_type IS
(
vsync_reset,
vsync_front_porch,
vsync_pulse,
vsync_back_porch,
vsync_active_video
);
SIGNAL vsync_current_state, vsync_next_state : vsync_state_type;
-- DMA State Machine
TYPE dma_state_type IS
(
start_dma,
clear_dma,
set_dma
);
SIGNAL dma_current_state, dma_next_state : dma_state_type;
-- DAC State Machine
TYPE dac_mode_state_type IS
(
ds0, ds1, ds2, ds3, ds4
);
SIGNAL dac_mode_current_state, dac_mode_next_state : dac_mode_state_type;
-- Avalon Master State Machine
TYPE avalon_master_state_type IS (master_idle, master_request_bus, master_burst, master_release);
SIGNAL avalon_master_current_state, avalon_master_next_state : avalon_master_state_type;
---
-- Signals
---
-- Reset
SIGNAL reset_int : std_logic;
SIGNAL reset_counter : INTEGER RANGE 0 TO 15;
SIGNAL reset_reg_sel : std_logic;
-- Colour Table
SIGNAL colour_table_address : std_logic_vector(7 DOWNTO 0);
SIGNAL colour_byte_sel : INTEGER RANGE 0 TO 3;
SIGNAL colour_byte_sel_int : INTEGER RANGE 0 TO 3;
SIGNAL colour_byte_sel0 : INTEGER RANGE 0 TO 3;
SIGNAL colour_byte_sel1 : INTEGER RANGE 0 TO 3;
SIGNAL colour_byte_sel2 : INTEGER RANGE 0 TO 3;
SIGNAL colour_byte_sel3 : INTEGER RANGE 0 TO 3;
SIGNAL colour_table_wr : std_logic;
SIGNAL colour_table_reg_sel : std_logic;
-- Line Buffer
SIGNAL line_buffer_wr1 : std_logic;
SIGNAL line_buffer_wr2 : std_logic;
SIGNAL line_buffer_reg_sel : std_logic;
SIGNAL line_buffer_data_in : std_logic_vector(31 DOWNTO 0);
SIGNAL line_buffer_data1 : std_logic_vector(31 DOWNTO 0);
SIGNAL line_buffer_data2 : std_logic_vector(31 DOWNTO 0);
SIGNAL video_data : std_logic_vector(31 DOWNTO 0);
SIGNAL line_buffer_dma_empty : std_logic;
SIGNAL line_buffer_dma_full : std_logic;
SIGNAL line_buffer_video_empty : std_logic;
SIGNAL line_buffer_video_full : std_logic;
SIGNAL line_buffer_rd1 : std_logic;
SIGNAL line_buffer_rd2 : std_logic;
SIGNAL line_buffer_rd : std_logic;
SIGNAL line_buffer_toggle : std_logic;
SIGNAL line_buffer_sel : INTEGER RANGE 0 TO 1;
SIGNAL line_buffer_rptop1 : std_logic;
SIGNAL line_buffer_rpbottom1 : std_logic;
SIGNAL line_buffer_wptop1 : std_logic;
SIGNAL line_buffer_wpbottom1 : std_logic;
SIGNAL line_buffer_rptop2 : std_logic;
SIGNAL line_buffer_rpbottom2 : std_logic;
SIGNAL line_buffer_wptop2 : std_logic;
SIGNAL line_buffer_wpbottom2 : std_logic;
SIGNAL line_begin, line_end : std_logic;
SIGNAL line_buffer_wprst1 : std_logic;
SIGNAL line_buffer_wprst2 : std_logic;
SIGNAL line_buffer_rprst1 : std_logic;
SIGNAL line_buffer_rprst2 : std_logic;
SIGNAL line_length : std_logic_vector(10 DOWNTO 0);
SIGNAL line_missed : std_logic;
-- Pixel Counter
SIGNAL pixel_counter_data : INTEGER RANGE 0 TO 1024;
SIGNAL pixel_counter_load : std_logic;
SIGNAL pixel_counter_zero : std_logic;
-- Vsync Counter
SIGNAL vsync_counter_reset : std_logic;
SIGNAL vsync_counter_inc : std_logic;
SIGNAL vsync_counter : INTEGER RANGE 0 TO 1024;
SIGNAL vsync_top1 : INTEGER RANGE 0 TO 1024;
SIGNAL vsync_top2 : INTEGER RANGE 0 TO 1024;
SIGNAL vsync_bottom : INTEGER RANGE 0 TO 1024;
-- Control Register
SIGNAL control_reg : std_logic_vector(31 DOWNTO 0);
SIGNAL status_reg : std_logic_vector(31 DOWNTO 0);
SIGNAL control_reg_sel : std_logic;
SIGNAL control_reg_wr : std_logic;
ALIAS start_video : std_logic IS control_reg(2);
ALIAS dac_mode : std_logic IS control_reg(3);
ALIAS hsync_pol : std_logic IS control_reg(4);
ALIAS vsync_pol : std_logic IS control_reg(5);
ALIAS force_blanking : std_logic IS control_reg(6);
-- Video Signals
SIGNAL hs_int : std_logic;
SIGNAL vs_int : std_logic;
SIGNAL blank_hs : std_logic;
SIGNAL blank_vs : std_logic;
SIGNAL blank_int : std_logic;
SIGNAL blank_int1 : std_logic;
SIGNAL blank0 : std_logic;
SIGNAL blank1 : std_logic;
SIGNAL blank2 : std_logic;
SIGNAL blank3 : std_logic;
SIGNAL blank4 : std_logic;
SIGNAL rgb : std_logic_vector(23 DOWNTO 0);
-- Resolution Register
SIGNAL resolution_reg : std_logic_vector(31 DOWNTO 0);
SIGNAL resolution_reg_sel : std_logic;
SIGNAL resolution_reg_wr : std_logic;
SIGNAL horizontal_resolution : INTEGER RANGE 0 TO 1024;
SIGNAL vertical_resolution : INTEGER RANGE 0 TO 1024;
-- Hsync Timing Register
SIGNAL hsync_timing_reg : std_logic_vector(31 DOWNTO 0);
SIGNAL hsync_timing_reg_sel : std_logic;
SIGNAL hsync_timing_reg_wr : std_logic;
SIGNAL hsync_pulse_width : INTEGER RANGE 0 TO 255;
SIGNAL hsync_back_porch_width : INTEGER RANGE 0 TO 255;
SIGNAL hsync_front_porch_width : INTEGER RANGE 0 TO 255;
-- Vsync Timing Register
SIGNAL vsync_timing_reg : std_logic_vector(31 DOWNTO 0);
SIGNAL vsync_timing_reg_sel : std_logic;
SIGNAL vsync_timing_reg_wr : std_logic;
SIGNAL vsync_pulse_width : INTEGER RANGE 0 TO 255;
SIGNAL vsync_back_porch_width : INTEGER RANGE 0 TO 255;
SIGNAL vsync_front_porch_width : INTEGER RANGE 0 TO 255;
-- DMA
SIGNAL dma_address_reg : std_logic_vector(31 DOWNTO 0);
SIGNAL dma_address_reg_sel : std_logic;
SIGNAL dma_address_reg_wr : std_logic;
SIGNAL video_dma_first : std_logic;
SIGNAL video_dma_request : std_logic;
SIGNAL avalon_dma_first : std_logic;
SIGNAL avalon_dma_request : std_logic;
SIGNAL dma_address_load : std_logic;
SIGNAL dma_address_inc : std_logic;
SIGNAL dma_address_dec : std_logic;
SIGNAL dma_transfer_begin : std_logic;
SIGNAL dma_transfer_end : std_logic;
SIGNAL dma_write : std_logic;
SIGNAL dma_request : std_logic;
SIGNAL dma_first : std_logic;
SIGNAL dma_address : std_logic_vector(31 DOWNTO 0);
SIGNAL dma_count : integer RANGE 0 TO 1024;
BEGIN
colour_table : lancelot_dpram_256x24
PORT MAP
(
data => AVALON_SLAVE_DATA_IN(23 DOWNTO 0),
wraddress => AVALON_SLAVE_DATA_IN(31 DOWNTO 24),
rdaddress => colour_table_address,
wren => colour_table_wr,
wrclock => AVALON_CLK,
rdclock => video_clk,
q => rgb
);
line_buffer1 : lancelot_fifo
GENERIC MAP
(
fifo_depth => 160,
fifo_width => 32
)
PORT MAP
(
rst => reset_int,
wprst => line_buffer_wprst1,
rprst => line_buffer_rprst1,
wrclk => AVALON_CLK,
rdclk => video_clk,
wrreq => line_buffer_wr1,
rdreq => line_buffer_rd1,
wrdata => line_buffer_data_in,
rddata => line_buffer_data1,
wptop => line_buffer_wptop1,
wpbottom => line_buffer_wpbottom1,
rptop => line_buffer_rptop1,
rpbottom => line_buffer_rpbottom1,
line_length => line_length
);
line_buffer2 : lancelot_fifo
GENERIC MAP
(
fifo_depth => 160,
fifo_width => 32
)
PORT MAP
(
rst => reset_int,
wprst => line_buffer_wprst2,
rprst => line_buffer_rprst2,
wrclk => AVALON_CLK,
rdclk => video_clk,
wrreq => line_buffer_wr2,
rdreq => line_buffer_rd2,
wrdata => line_buffer_data_in,
rddata => line_buffer_data2,
wptop => line_buffer_wptop2,
wpbottom => line_buffer_wpbottom2,
rptop => line_buffer_rptop2,
rpbottom => line_buffer_rpbottom2,
line_length => line_length
);
line_buffer_data_in <= AVALON_MASTER_DATA_IN;
-------------------
-- Avalon Master --
-------------------
-- The Avalon master reads video data from the external SDRAM and stores it in the Lancelot FIFO's
PROCESS(AVALON_CLK, reset_int)
BEGIN
IF reset_int = '1' THEN
avalon_master_current_state <= master_idle;
ELSIF (AVALON_CLK'event AND AVALON_CLK = '1') THEN
avalon_master_current_state <= avalon_master_next_state AFTER 5 ns;
END IF;
END PROCESS;
PROCESS(avalon_master_current_state, dma_request, dma_address, dma_first, dma_transfer_end, AVALON_MASTER_WAITREQ)
BEGIN
AVALON_MASTER_ADDR <= (others => '0');
AVALON_MASTER_RD <= '0';
dma_address_load <= '0';
dma_address_inc <= '0';
dma_address_dec <= '0';
dma_transfer_begin <= '0';
dma_write <= '0';
AVALON_MASTER_LOCK <= '0';
CASE avalon_master_current_state IS
WHEN master_idle =>
IF dma_request = '1' THEN
avalon_master_next_state <= master_request_bus;
ELSE
avalon_master_next_state <= master_idle;
END IF;
WHEN master_request_bus =>
dma_transfer_begin <= '1';
IF dma_first = '1' THEN
dma_address_load <= '1';
END IF;
avalon_master_next_state <= master_burst;
WHEN master_burst =>
AVALON_MASTER_ADDR <= dma_address;
AVALON_MASTER_RD <= '1';
AVALON_MASTER_LOCK <= '1';
IF AVALON_MASTER_WAITREQ = '1' THEN
avalon_master_next_state <= master_burst;
ELSE
dma_address_inc <= '1';
dma_write <= '1';
IF dma_transfer_end = '0' THEN
avalon_master_next_state <= master_burst;
ELSE
avalon_master_next_state <= master_release;
END IF;
END IF;
WHEN master_release =>
AVALON_MASTER_ADDR <= dma_address;
AVALON_MASTER_RD <= '1';
avalon_master_next_state <= master_idle;
WHEN others =>
avalon_master_next_state <= master_idle;
END CASE;
END PROCESS;
-- DMA address register
PROCESS(AVALON_CLK, reset_int, dma_address_load, dma_address_inc, dma_address_dec, dma_address_reg)
BEGIN
IF reset_int = '1' THEN
dma_address <= (others => '0');
ELSIF (AVALON_CLK'event AND AVALON_CLK = '1') THEN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -