⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video_vicii_656x_a.vhd

📁 FPGA64的VHDL源代码
💻 VHD
📖 第 1 页 / 共 3 页
字号:
-- For Text/Bitmap BA goes low 3 cycles before real access. So BA starts
-- going low during refresh2 state. See diagram below for timing:
--
-- X               0  0  0  0  0
--                 0  0  0  0  1
--                 0  4  8  C  0
--
-- phi ___   ___   ___   ___   ___   ___   ___   ___...
--        ___   ___   ___   ___   ___   ___   ___   ...
--
--          |     |     |     |     |     |     |...
--     rfr2  rfr3  rfr4  rfr5  char1 char2 char3
--
-- BA _______
--        \\\_______________________________________
--          |  1  |  2  |  3  |
--
-- BACnt 000  001 | 010 | 011 | 100   100   100  ...
--
-- -----------------------------------------------------------------------
	process(clk)
	begin
		if rising_edge(clk) then
			if phi = '0' then
				baChars <= '1';
				case vicCycle is
				when cycleRefresh2 | cycleRefresh3 | cycleRefresh4 | cycleRefresh5 =>
					if badLine then
						baChars <= '0';
					end if;
				when others =>
					if rasterX(9 downto 3) < "0101000"
					and badLine then
						baChars <= '0';
					end if;
				end case;
			end if;
		end if;
	end process;

-- -----------------------------------------------------------------------
-- BA generator (Sprites)
-- -----------------------------------------------------------------------
	process(clk)
	begin
		if rising_edge(clk) then
			if phi = '0' then
				if sprite = 1 then
					baSprite04 <= '1';
				end if;
				if sprite = 2 then
					baSprite15 <= '1';
				end if;
				if sprite = 3 then
					baSprite26 <= '1';
				end if;
				if sprite = 4 then
					baSprite37 <= '1';
				end if;
				if sprite = 5 then
					baSprite04 <= '1';
				end if;
				if sprite = 6 then
					baSprite15 <= '1';
				end if;
				if sprite = 7 then
					baSprite26 <= '1';
				end if;
				if vicCycle = cycleRefresh1 then
					baSprite37 <= '1';
				end if;
				
				if MActive(0) and (vicCycle = cycleCalcSprites) then
					baSprite04 <= '0';
				end if;
				if MActive(1) and (vicCycle = cycleSpriteBa2) then
					baSprite15 <= '0';
				end if;
				if MActive(2) and (vicCycle = cycleSpriteB) and (sprite = 0) then
					baSprite26 <= '0';
				end if;
				if MActive(3) and (vicCycle = cycleSpriteB) and (sprite = 1) then
					baSprite37 <= '0';
				end if;
				if MActive(4) and (vicCycle = cycleSpriteB) and (sprite = 2) then
					baSprite04 <= '0';
				end if;
				if MActive(5) and (vicCycle = cycleSpriteB) and (sprite = 3) then
					baSprite15 <= '0';
				end if;
				if MActive(6) and (vicCycle = cycleSpriteB) and (sprite = 4) then
					baSprite26 <= '0';
				end if;
				if MActive(7) and (vicCycle = cycleSpriteB) and (sprite = 5) then
					baSprite37 <= '0';
				end if;
			end if;
		end if;
	end process;
	baLoc <= baChars and baSprite04 and baSprite15 and baSprite26 and baSprite37;

-- -----------------------------------------------------------------------
-- Address valid?
-- -----------------------------------------------------------------------
	process(clk)
	begin
		if rising_edge(clk) then
			addrValid <= '0';
			if phi = '0'
			or baCnt(2) = '1' then
				addrValid <= '1';
			end if;
		end if;
	end process;

-- -----------------------------------------------------------------------
-- Generate ShiftChars flag
-- -----------------------------------------------------------------------
	process(rasterX)
	begin
		shiftChars <= false;
		if rasterX(9 downto 3) > "0000000"
		and rasterX(9 downto 3) < "0101001" then
			shiftChars <= true;
		end if;
	end process;

-- -----------------------------------------------------------------------
-- RowCounter and ColCounter
-- -----------------------------------------------------------------------
	process(clk)
	begin
		if rising_edge(clk) then
			if phi = '0'
			and enaData = '1'
			and baSync = '0' then
				if shiftChars
				and idle = '0' then
					colCounter <= colCounter + 1;
				end if;
				case vicCycle is
				when cycleRefresh4 =>
					colCounter <= colRestart;
					if badline then
						rowCounter <= (others => '0');
					end if;
				when cycleSpriteA =>
					if sprite = "000" then
						if rowCounter = 7 then
							colRestart <= colCounter;
							idle <= '1';
						else
							rowCounter <= rowCounter + 1;
						end if;
						if badline then
							rowCounter <= rowCounter + 1;
						end if;
					end if;
				when others =>
					null;					
				end case;
				if lastLineFlag then
					-- Reset column counter outside visible range.
					colRestart <= (others => '0');
				end if;

				-- Set display mode (leave idle-mode) as soon as
				-- there is a badline condition.
				if badline then
					idle <= '0';
				end if;
			end if;
		end if;
	end process;

-- -----------------------------------------------------------------------
-- X/Y Raster counter
-- -----------------------------------------------------------------------
rasterCounters: process(clk)
	begin
		if rising_edge(clk) then
			if enaPixel = '1' then
				rasterX(2 downto 0) <= rasterX(2 downto 0) + 1;
			end if;
			if phi = '0'
			and enaData = '1'
			and baSync = '0' then
				rasterX(9 downto 3) <= rasterX(9 downto 3) + 1;
				rasterX(2 downto 0) <= (others => '0');
				if vicCycle = cycleRefresh4 then
					rasterX <= (others => '0');
				end if;
			end if;
			if phi = '1'
			and enaData = '1'
			and baSync = '0' then
				beyondFrameFlag <= false;
				if (vicCycle = cycleSpriteB)
				and (sprite = 2) then
					rasterY <= rasterY + 1;
					beyondFrameFlag <= lastLineFlag;
				end if;
				if beyondFrameFlag then
					rasterY <= (others => '0');
				end if;
			end if;
		end if;
	end process;

-- -----------------------------------------------------------------------
-- Raster IRQ
-- -----------------------------------------------------------------------
	process(clk)
	begin
		if rising_edge(clk) then
			if phi = '1'
			and enaData = '1'
			and baSync = '0'
			and (vicCycle = cycleSpriteB)
			and (sprite = 2) then
				rasterIrqDone <= '0';
			end if;
			if resetRasterIrq = '1' then
				IRST <= '0';
			end if;
			if (rasterIrqDone = '0')
			and (rasterY = rasterCmp) then
				rasterIrqDone <= '1';
				IRST <= '1';
			end if;
		end if;
	end process;


-- -----------------------------------------------------------------------
-- Light pen
-- -----------------------------------------------------------------------
-- On a negative edge on the LP input, the current position of the raster beam
-- is latched in the registers LPX ($d013) and LPY ($d014). LPX contains the
-- upper 8 bits (of 9) of the X position and LPY the lower 8 bits (likewise of
-- 9) of the Y position. So the horizontal resolution of the light pen is
-- limited to 2 pixels.

-- Only one negative edge on LP is recognized per frame. If multiple edges
-- occur on LP, all following ones are ignored. The trigger is not released
-- until the next vertical blanking interval.
-- -----------------------------------------------------------------------
lightPen: process(clk)
	begin
		if rising_edge(clk) then
			if emulateLightpen then
				if resetLightPenIrq = '1' then
					-- Reset light pen interrupt
					ILP <= '0';
				end if;			
				if lastLineFlag then
					-- Reset lightpen state at beginning of frame
					lightPenHit <= '0';
				elsif (lightPenHit = '0') and (lp_n = '0') then
					-- One hit/frame
					lightPenHit <= '1'; 
					-- Toggle Interrupt
					ILP <= '1'; 
					-- Store position of beam
					lpx <= rasterX(8 downto 1);
					lpy <= rasterY(7 downto 0);
				end if;
			else
				ILP <= '0';
				lpx <= (others => '1');
				lpy <= (others => '1');
			end if;
		end if;
	end process;

-- -----------------------------------------------------------------------
-- VSync
-- -----------------------------------------------------------------------
doVBlanking: process(clk, mode6569, mode6567old, mode6567R8)
		variable rasterBlank : integer range 0 to 300;
	begin
		rasterBlank := 300;
		if (mode6567old or mode6567R8) = '1' then
			rasterBlank := 12;
		end if;
		if rising_edge(clk) then
			vBlanking <= '0';
			if rasterY = rasterBlank then
				vBlanking <= '1';
			end if;
		end if;
	end process;

-- -----------------------------------------------------------------------
-- HSync
-- -----------------------------------------------------------------------
doHBlanking: process(clk)
	begin
		if rising_edge(clk) then
			if sprite = 3 then
				hBlack <= '1';
			end if;
			if vicCycle = cycleRefresh1 then
				hBlack <= '0';
			end if;
			if sprite = 5 then
				hBlanking <= '1';
			else
				hBlanking <= '0';
			end if;
		end if;
	end process;

-- -----------------------------------------------------------------------
-- Borders
-- -----------------------------------------------------------------------
calcBorders: process(clk)
		variable newTBBorder: std_logic;
	begin
		if rising_edge(clk) then
			if enaPixel = '1' then
				--
				-- Calc top/bottom border
				newTBBorder := TBBorder;
--				if (rasterY = 55) and (RSEL = '0') and (rasterEnable = '1') then
				if (rasterY = 55) and (rasterEnable = '1') then
					newTBBorder := '0';
				end if;
				if (rasterY = 51) and (RSEL = '1') and (rasterEnable = '1') then
					newTBBorder := '0';
				end if;
				if (rasterY = 247) and (RSEL = '0') then
					newTBBorder := '1';
				end if;
				if (rasterY = 251) and (RSEL = '1') then
					newTBBorder := '1';
				end if;

				--
				-- Calc left/right border
				if (rasterX = (31+1)) and (CSEL = '0') then
					LRBorder <= newTBBorder;
					TBBorder <= newTBBorder;
				end if;
				if (rasterX = (24+1)) and (CSEL = '1') then
					LRBorder <= newTBBorder;
					TBBorder <= newTBBorder;
				end if;
				if (rasterX = (335+1)) and (CSEL = '0') then
					LRBorder <= '1';
				end if;
				if (rasterX = (344+1)) and (CSEL = '1') then
					LRBorder <= '1';
				end if;
			end if;
		end if;
	end process;


-- -----------------------------------------------------------------------
-- Pixel generator for Text/Bitmap screen
-- -----------------------------------------------------------------------
calcBitmap: process(clk)
		variable multiColor : std_logic;
	begin
		if rising_edge(clk) then
			if enaPixel = '1' then
				--
				-- Toggle flipflop for multicolor 2-bits shift.
				shifting_ff <= not shifting_ff;
				
				--
				-- Multicolor mode is active with MCM, but for character
				-- mode it depends on bit3 of color ram too.
				multiColor := MCM and (BMM or ECM or shiftingChar(11));

				--
				-- Reload shift register when xscroll=rasterX
				-- otherwise shift pixels
				if xscroll = rasterX(2 downto 0) then
					shifting_ff <= '0';
					shiftingChar <= waitingChar;
					shiftingPixels <= waitingPixels;
				elsif multiColor = '0' then
					shiftingPixels <= shiftingPixels(6 downto 0) & '0';
				elsif shifting_ff = '1' then
					shiftingPixels <= shiftingPixels(5 downto 0) & "00";
				end if;

				--
				-- Calculate if pixel is in foreground or background
				pixelBgFlag <= shiftingPixels(7);

				--
				-- Calculate color of next pixel				
				pixelColor <= B0C;
				if (BMM = '0') and (ECM='0') then
					if (multiColor = '0') then
						-- normal character mode
						if shiftingPixels(7) = '1' then
							pixelColor <= shiftingChar(11 downto 8);
						end if;
					else
						-- multi-color character mode
						case shiftingPixels(7 downto 6) is
						when "01" => pixelColor <= B1C;
						when "10" => pixelColor <= B2C;
						when "11" => pixelColor <= '0' & shiftingChar(10 downto 8);
						when others => null;
						end case;
					end if;
				elsif (MCM = '0') and (BMM = '0') and (ECM='1') then
					-- extended-color character mode
					-- multiple background colors but only 64 characters
					if shiftingPixels(7) = '1' then
						pixelColor <= shiftingChar(11 downto 8);
					else
						case shiftingChar(7 downto 6) is
						when "01" => pixelColor <= B1C;
						when "10" => pixelColor <= B2C;
						when "11" => pixelColor <= B3C;
						when others	=> null;
						end case;
					end if;
				elsif emulateGraphics and (MCM = '0') and (BMM = '1') and (ECM='0') then
					-- highres bitmap mode
					if shiftingPixels(7) = '1' then
						pixelColor <= shiftingChar(7 downto 4);
					else
						pixelColor <= shiftingChar(3 downto 0);
					end if;
				elsif emulateGraphics and (MCM = '1') and (BMM = '1') and (ECM='0') then
					-- Multi-color bitmap mode
					case shiftingPixels(7 downto 6) is
					when "01" => pixelColor <= shiftingChar(7 downto 4);
					when "10" => pixelColor <= shiftingChar(3 downto 0);
					when "11" => pixelColor <= shiftingChar(11 downto 8);
					when others => null;
					end case;
				else
					-- illegal display mode, the output is black
					pixelColor <= "0000";
				end if;
			end if;

			--
			-- Store fetched pixels, until current pixels are displayed
			-- and shift-register is empty.
			if enaData = '1'
			and phi = '0' then
				readPixels <= (others => '0');
				if shiftChars then
					readPixels <= di;
					readChar <= (others => '0');
					if idle = '0' then
						readChar <= nextChar;
					end if;
				end if;
				-- Store the characters until shiftregister is empty
				waitingPixels <= readPixels;
				waitingChar <= readChar;
			end if;
		end if;
	end process;

-- -----------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -