📄 lancelot_vga.vhd
字号:
IF dma_address_load = '1' THEN
dma_address <= dma_address_reg;
ELSE
IF dma_address_inc = '1' THEN
dma_address <= dma_address + "100";
END IF;
IF dma_address_dec = '1' THEN
dma_address <= dma_address - "100";
END IF;
END IF;
END IF;
END PROCESS;
-- DMA length counter
PROCESS(AVALON_CLK, reset_int, dma_address_inc, dma_address_dec, dma_transfer_begin)
BEGIN
IF reset_int = '1' THEN
dma_count <= 0;
dma_transfer_end <= '0';
ELSIF (AVALON_CLK'event AND AVALON_CLK = '1') THEN
IF dma_transfer_begin = '1' THEN
dma_count <= 0;
dma_transfer_end <= '0';
ELSE
IF dma_address_inc = '1' THEN
dma_count <= dma_count + 4;
END IF;
IF dma_address_dec = '1' THEN
dma_count <= dma_count - 4;
END IF;
END IF;
IF dma_count = horizontal_resolution - 4 THEN
dma_transfer_end <= '1';
END IF;
END IF;
END PROCESS;
-- Transfer DMA signals from video domain to Avalon domain
PROCESS(AVALON_CLK, reset_int, video_dma_first, video_dma_request)
BEGIN
IF reset_int = '1' THEN
avalon_dma_first <= '0';
avalon_dma_request <= '0';
dma_first <= '0';
dma_request <= '0';
ELSIF (AVALON_CLK'event AND AVALON_CLK = '1') THEN
avalon_dma_first <= video_dma_first;
avalon_dma_request <= video_dma_request;
dma_first <= avalon_dma_first;
dma_request <= avalon_dma_request;
END IF;
END PROCESS;
----------------------------------
-- Video DAC Mode state machine --
----------------------------------
-- Set DAC in RGB mode and bias on all three channels
PROCESS(VIDEO_CLK, reset_int)
BEGIN
IF reset_int = '1' THEN
dac_mode_current_state <= ds0;
ELSIF (VIDEO_CLK'event AND VIDEO_CLK = '0') THEN
dac_mode_current_state <= dac_mode_next_state AFTER 5 ns;
END IF;
END PROCESS;
PROCESS(dac_mode_current_state, control_reg)
BEGIN
sync_n <= '0';
m2 <= '0';
m1 <= '0';
sync_t <= '0';
CASE dac_mode_current_state IS
WHEN ds0 =>
IF dac_mode = '1' THEN
dac_mode_next_state <= ds1;
ELSE
dac_mode_next_state <= ds0;
END IF;
WHEN ds1 =>
sync_n <= '1';
m2 <= '0';
m1 <= '0';
sync_t <= '0';
dac_mode_next_state <= ds2;
-- Bias on all three channels
WHEN ds2 =>
sync_n <= '0';
m2 <= '1';
m1 <= '0';
sync_t <= '0';
dac_mode_next_state <= ds3;
WHEN ds3 =>
sync_n <= '0';
m2 <= '1';
m1 <= '0';
sync_t <= '0';
dac_mode_next_state <= ds4;
-- RGB Mode
WHEN ds4 =>
sync_n <= '1';
m2 <= '0';
m1 <= '0';
sync_t <= '0';
dac_mode_next_state <= ds4;
WHEN others =>
sync_n <= '1';
m2 <= '0';
m1 <= '0';
sync_t <= '0';
dac_mode_next_state <= ds0;
END CASE;
END PROCESS;
--------------------------
-- Buffer video signals --
--------------------------
PROCESS(VIDEO_CLK, reset_int)
BEGIN
IF reset_int = '1' THEN
r <= (others => '0');
g <= (others => '0');
b <= (others => '0');
hs <= '1';
vs <= '1';
blank_n <= '0';
ELSIF (VIDEO_CLK'event AND VIDEO_CLK = '1') THEN
r <= rgb(23 DOWNTO 16);
g <= rgb(15 DOWNTO 8);
b <= rgb(7 DOWNTO 0);
IF hsync_pol = '1' THEN
hs <= not hs_int;
ELSE
hs <= hs_int;
END IF;
IF vsync_pol = '1' THEN
vs <= not vs_int;
ELSE
vs <= vs_int;
END IF;
blank_n <= blank_int;
END IF;
END PROCESS;
-----------------
-- Blank delay --
-----------------
-- The blank signal must be delayed for one video clk because of colour table registered inputs and outputs
PROCESS(VIDEO_CLK, reset_int, blank_vs, blank_hs)
BEGIN
IF reset_int = '1' THEN
blank_int <= '0';
blank_int1 <= '0';
blank4 <= '0';
blank3 <= '0';
blank2 <= '0';
blank1 <= '0';
blank0 <= '0';
ELSIF (VIDEO_CLK'event AND VIDEO_CLK = '1') THEN
IF (blank_vs = '1' AND blank_hs = '1') THEN
blank_int1 <= '1';
ELSE
blank_int1 <= '0';
END IF;
blank_int <= blank4;
blank4 <= blank3;
blank3 <= blank2;
blank2 <= blank1;
blank1 <= blank0;
blank0 <= blank_int1;
END IF;
END PROCESS;
-------------------------------
-- Avalon Select Generation --
-------------------------------
-- Avalon Memory Map
-------------------------------
-- 0 : Control / Status Register
-- 1 : Colour Tabel
-- 2 : Line Buffer
-- 3 : Reset Register
-- 4 : Resolution Register
-- 5 : Hsync Timing Register
-- 6 : VSync Timing Register
-- 7 : DMA Register
-------------------------------
control_reg_sel <= '1' WHEN AVALON_SLAVE_CS = '1' AND AVALON_SLAVE_ADDR = "000" ELSE '0';
colour_table_reg_sel <= '1' WHEN AVALON_SLAVE_CS = '1' AND AVALON_SLAVE_ADDR = "001" ELSE '0';
line_buffer_reg_sel <= '1' WHEN AVALON_SLAVE_CS = '1' AND AVALON_SLAVE_ADDR = "010" ELSE '0';
reset_reg_sel <= '1' WHEN AVALON_SLAVE_CS = '1' AND AVALON_SLAVE_ADDR = "011" ELSE '0';
resolution_reg_sel <= '1' WHEN AVALON_SLAVE_CS = '1' AND AVALON_SLAVE_ADDR = "100" ELSE '0';
hsync_timing_reg_sel <= '1' WHEN AVALON_SLAVE_CS = '1' AND AVALON_SLAVE_ADDR = "101" ELSE '0';
vsync_timing_reg_sel <= '1' WHEN AVALON_SLAVE_CS = '1' AND AVALON_SLAVE_ADDR = "110" ELSE '0';
dma_address_reg_sel <= '1' WHEN AVALON_SLAVE_CS = '1' AND AVALON_SLAVE_ADDR = "111" ELSE '0';
------------------------------
-- Avalon Strobe Generation --
------------------------------
control_reg_wr <= '1' WHEN control_reg_sel = '1' AND AVALON_SLAVE_WR = '1' ELSE '0';
colour_table_wr <= '1' WHEN colour_table_reg_sel = '1' AND AVALON_SLAVE_WR = '1' ELSE '0';
line_buffer_wr1 <= '1' WHEN (dma_write = '1' AND line_buffer_sel = 1) ELSE '0';
line_buffer_wr2 <= '1' WHEN (dma_write = '1' AND line_buffer_sel = 0) ELSE '0';
resolution_reg_wr <= '1' WHEN resolution_reg_sel = '1' AND AVALON_SLAVE_WR = '1' ELSE '0';
hsync_timing_reg_wr <= '1' WHEN hsync_timing_reg_sel = '1' AND AVALON_SLAVE_WR = '1' ELSE '0';
vsync_timing_reg_wr <= '1' WHEN vsync_timing_reg_sel = '1' AND AVALON_SLAVE_WR = '1' ELSE '0';
dma_address_reg_wr <= '1' WHEN dma_address_reg_sel = '1' AND AVALON_SLAVE_WR = '1' ELSE '0';
----------------------------
-- Avalon Data output mux --
----------------------------
AVALON_SLAVE_DATA_OUT <= status_reg WHEN control_reg_sel = '1' AND AVALON_SLAVE_RD = '1' ELSE
resolution_reg WHEN resolution_reg_sel = '1' AND AVALON_SLAVE_RD = '1' ELSE
hsync_timing_reg WHEN hsync_timing_reg_sel = '1' AND AVALON_SLAVE_RD = '1' ELSE
vsync_timing_reg WHEN vsync_timing_reg_sel = '1' AND AVALON_SLAVE_RD = '1' ELSE
dma_address_reg WHEN dma_address_reg_sel = '1' AND AVALON_SLAVE_RD = '1' ELSE
(others => '0');
-----------------------------------
-- Control Register (AVALON_SLAVE_WR only) --
-----------------------------------
-- 6 : Force Blanking
-- 5 : Polarity vsync
-- 4 : Polarity hsync
-- 3 : Set DAC mode
-- 2 : Start Video
-- 1 : -
-- 0 : -
-----------------------------------
PROCESS(AVALON_CLK, reset_int, control_reg_wr)
BEGIN
IF reset_int = '1' THEN
control_reg <= (others => '0');
ELSIF (AVALON_CLK'event AND AVALON_CLK = '1') THEN
IF control_reg_wr = '1' THEN
control_reg <= AVALON_SLAVE_DATA_IN;
END IF;
END IF;
END PROCESS;
-- Reset Generator
-- This self clearing reset_int circuit is triggered by writing to the reset_int register.
PROCESS(RESET, AVALON_CLK, reset_reg_sel, AVALON_SLAVE_DATA_IN, AVALON_SLAVE_WR)
BEGIN
IF RESET = '1' THEN
reset_counter <= 0;
reset_int <= '1';
ELSIF (AVALON_CLK'event AND AVALON_CLK = '1') THEN
IF (reset_reg_sel = '1' AND AVALON_SLAVE_WR = '1' AND AVALON_SLAVE_DATA_IN = x"12345678") THEN
reset_counter <= 15;
reset_int <= '1';
ELSIF reset_counter = 0 THEN
reset_int <= '0';
ELSE
reset_counter <= reset_counter - 1;
reset_int <= '1';
END IF;
END IF;
END PROCESS;
---------------------------------
-- Status Register (read only) --
---------------------------------
-- 31 - 16 : MG
-- 9 : New frame
-- 8 : Line missed
-- 7 : Line buffer video full
-- 6 : Line buffer video empty
-- 5 : Line buffer dma full
-- 4 : Line buffer dma empty
-- 3 : Blank vs
-- 2 : Blank hs
-- 1 : Vertical Sync
-- 0 : Horizontal Sync
---------------------------------
PROCESS(AVALON_CLK, reset_int, hs_int, vs_int, blank_vs, blank_hs, line_buffer_dma_empty, line_buffer_dma_full, line_buffer_video_empty, line_buffer_video_full)
BEGIN
IF reset_int = '1' THEN
status_reg <= (others => '0');
ELSIF (AVALON_CLK'event AND AVALON_CLK = '1') THEN
status_reg(31 DOWNTO 16) <= x"5247";
status_reg(15 DOWNTO 9) <= (others => '0');
status_reg(8) <= line_missed;
status_reg(7) <= line_buffer_video_full;
status_reg(6) <= line_buffer_video_empty;
status_reg(5) <= line_buffer_dma_full;
status_reg(4) <= line_buffer_dma_empty;
status_reg(3) <= blank_vs;
status_reg(2) <= blank_hs;
status_reg(1) <= vs_int;
status_reg(0) <= hs_int;
END IF;
END PROCESS;
------------------------------
-- Resolution Register (rw) --
------------------------------
-- 26 - 16 : Horizontal resolution
-- 9 - 0 : Vertical resolution
------------------------------
PROCESS(AVALON_CLK, reset_int, resolution_reg_wr, AVALON_SLAVE_DATA_IN)
BEGIN
IF reset_int = '1' THEN
resolution_reg <= (others => '0');
ELSIF (AVALON_CLK'event AND AVALON_CLK = '1') THEN
IF resolution_reg_wr = '1' THEN
resolution_reg <= AVALON_SLAVE_DATA_IN;
END IF;
END IF;
END PROCESS;
horizontal_resolution <= conv_integer(resolution_reg(26 DOWNTO 16));
vertical_resolution <= conv_integer(resolution_reg(9 DOWNTO 0));
line_length <= resolution_reg(26 DOWNTO 16);
--------------------------------
-- Hsync Timing Register (rw) --
--------------------------------
PROCESS(AVALON_CLK, reset_int, hsync_timing_reg_wr, AVALON_SLAVE_DATA_IN)
BEGIN
IF reset_int = '1' THEN
hsync_timing_reg <= (others => '0');
ELSIF (AVALON_CLK'event AND AVALON_CLK = '1') THEN
IF hsync_timing_reg_wr = '1' THEN
hsync_timing_reg <= AVALON_SLAVE_DATA_IN;
END IF;
END IF;
END PROCESS;
hsync_pulse_width <= conv_integer(hsync_timing_reg(23 DOWNTO 16));
hsync_back_porch_width <= conv_integer(hsync_timing_reg(15 DOWNTO 8));
hsync_front_porch_width <= conv_integer(hsync_timing_reg(7 DOWNTO 0));
--------------------------------
-- Vsync Timing Register (rw) --
--------------------------------
PROCESS(AVALON_CLK, reset_int, vsync_timing_reg_wr, AVALON_SLAVE_DATA_IN)
BEGIN
IF reset_int = '1' THEN
vsync_timing_reg <= (others => '0');
ELSIF (AVALON_CLK'event AND AVALON_CLK = '1') THEN
IF vsync_timing_reg_wr = '1' THEN
vsync_timing_reg <= AVALON_SLAVE_DATA_IN;
END IF;
END IF;
END PROCESS;
vsync_pulse_width <= conv_integer(vsync_timing_reg(23 DOWNTO 16));
vsync_back_porch_width <= conv_integer(vsync_timing_reg(15 DOWNTO 8));
vsync_front_porch_width <= conv_integer(vsync_timing_reg(7 DOWNTO 0));
-----------------------
-- DMA Register (rw) --
-----------------------
PROCESS(AVALON_CLK, reset_int, dma_address_reg_wr, AVALON_SLAVE_DATA_IN)
BEGIN
IF reset_int = '1' THEN
dma_address_reg <= (others => '0');
ELSIF (AVALON_CLK'event AND AVALON_CLK = '1') THEN
IF dma_address_reg_wr = '1' THEN
dma_address_reg <= AVALON_SLAVE_DATA_IN;
END IF;
END IF;
END PROCESS;
-----------------------------
-- line Buffer Output Mux --
-----------------------------
-- 0 - line buffer 1 video out & line buffer 2 dma input
-- 1 - line buffer 2 video out & line buffer 1 dma input
PROCESS(VIDEO_CLK, reset_int, line_buffer_sel)
BEGIN
IF reset_int = '1' THEN
video_data <= (others => '0');
line_buffer_rd1 <= '0';
line_buffer_rd2 <= '0';
line_buffer_video_empty <= '0';
line_buffer_video_full <= '0';
line_buffer_dma_full <= '0';
line_buffer_dma_empty <= '0';
line_buffer_wprst1 <= '0';
line_buffer_wprst2 <= '0';
line_buffer_rprst1 <= '0';
line_buffer_rprst2 <= '0';
ELSIF (VIDEO_CLK'event AND VIDEO_CLK = '1') THEN
IF line_buffer_sel = 0 THEN
-- line buffer 1 video data out
-- line buffer 2 dma data in
video_data <= line_buffer_data1;
line_buffer_rd1 <= line_buffer_rd;
line_buffer_rd2 <= '0';
line_buffer_video_empty <= line_buffer_rptop1;
line_buffer_video_full <= line_buffer_wptop1;
line_buffer_dma_full <= line_buffer_wptop2;
line_buffer_dma_empty <= line_buffer_wpbottom2;
line_buffer_wprst1 <= line_end;
line_buffer_wprst2 <= '0';
line_buffer_rprst1 <= line_begin;
line_buffer_rprst2 <= '0';
ELSE
-- line buffer 1 dma data in
-- line buffer 2 video data out
video_data <= line_buffer_data2;
line_buffer_rd1 <= '0';
line_buffer_rd2 <= line_buffer_rd;
line_buffer_video_empty <= line_buffer_rptop2;
line_buffer_video_full <= line_buffer_wptop2;
line_buffer_dma_full <= line_buffer_wptop1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -