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

📄 npi_vga.vhd

📁 Genode FX is a composition of hardware and software components that enable the creation of fully fl
💻 VHD
📖 第 1 页 / 共 2 页
字号:
			heal_the_world <= '0';

		elsif clk'event and clk = '1' then

			heal_the_world <= '0';
			XIL_NPI_RdFIFO_Flush <= '0';

			-- start running the VGA timing when the first pixel data is already available
			if run_timing = '0' and shadow_reg_filled = '1' then
				run_timing <= '1';
				shadow_reg_filled <= '0';
				pixel_shift_register <= shadow_reg;
				pixel_shift_register_content <= to_unsigned(C_PI_DATA_WIDTH/16-1,3); -- two or four new pixels!
			end if;
			x_pos_t <= x_pos;
			if vsync = '0' then
				low_x_resolution_set_dis <= low_x_resolution_set;
			end if;

			-- in case there is space for new pixel data in the rdFIFO
			-- and we are currently not waiting for an request acknowledge 
			-- request new pixel data!
			if pixels_requested < PIXEL_REQUEST_LOW and 
			   wait_for_addr_ack = '0' and wait_for_addr_ack_wr = '0' then
				-- set the request and correct address
				XIL_NPI_AddrReq <= '1';
				XIL_NPI_RNW <= '1';
				-- remember that we are waiting for an acknowledge
				-- such that we do not enter this if branch again the next clk
				wait_for_addr_ack <= '1';
				-- and handle update the address of the frame buffer for the next time
				if screen_address_offset = frame_buffer_size then
					-- only update this bound after a whole picture was requested
					-- like this we stay synchronous even if the screen address is not set in the vsync
					XIL_NPI_Addr <= frame_buffer_address;
					screen_address_offset <= to_unsigned(REQUEST_SIZE*2, 22);
					pixel_counter_x <= to_unsigned(REQUEST_SIZE, 11);
					line_displayed_once <= '0';
					-- set the new resolution
					low_x_resolution_set <= low_x_resolution;
					low_y_resolution_set <= low_y_resolution;
				else
					XIL_NPI_Addr <= std_logic_vector(unsigned(frame_buffer_address) + screen_address_offset);
					screen_address_offset <= screen_address_offset + REQUEST_SIZE*2;
					-- in case we have to display each line twice
					-- test whether one line was displayed twice or not
					if low_y_resolution_set = '1' then
						-- test whether a whole line was displayed
						if (low_x_resolution_set = '0' and pixel_counter_x = x_res - REQUEST_SIZE) or
						   (low_x_resolution_set = '1' and pixel_counter_x = x_res/2 - REQUEST_SIZE) then
							pixel_counter_x <= (others => '0');
							if line_displayed_once = '0' then
								-- this was the first time the line was displayed
								-- so display it another time and reset the screen offset counter
								if low_x_resolution_set = '1' then
									screen_address_offset <= screen_address_offset - x_res + REQUEST_SIZE*2;
								else
									screen_address_offset <= screen_address_offset - x_res*2 + REQUEST_SIZE*2;
								end if;
								line_displayed_once <= '1';
							else
								line_displayed_once <= '0';
							end if;
						else
							pixel_counter_x <= pixel_counter_x + REQUEST_SIZE;
						end if;
					end if;
				end if;
			-----------------------------------------
			-- FAST CLEARING OF SCREEN FUNCTIONALITY
			-----------------------------------------
			elsif fast_clear_pending = '1' and wait_for_addr_ack = '0' and wait_for_addr_ack_wr = '0'
			        and fast_clear_pixels_cleared < unsigned(fast_clear_pixels) then
				XIL_NPI_AddrReq <= '1';
				XIL_NPI_Addr <= std_logic_vector(unsigned(fast_clear_start_address) + fast_clear_offset);
				XIL_NPI_RNW <= '0';
				fast_clear_offset <= fast_clear_offset + to_unsigned(REQUEST_SIZE*2,22);
				wait_for_addr_ack_wr <= '1';
			end if;

			if fast_clear_init = '1' then
				fast_clear_pending <= '1';
				fast_clear_done    <= '0';
			end if;

			if wait_for_addr_ack_wr = '1' and XIL_NPI_AddrAck = '1' then
				wait_for_addr_ack_wr <= '0';
				XIL_NPI_AddrReq <= '0';
				if fast_clear_pixels_cleared + REQUEST_SIZE >= unsigned(fast_clear_pixels) then
					fast_clear_pending <= '0';
					fast_clear_done <= '1'; -- initialize an interrupt
					fast_clear_pixels_cleared <= (others => '0');
					fast_clear_offset <= (others => '0');
				else
					fast_clear_pixels_cleared <= fast_clear_pixels_cleared + REQUEST_SIZE;
				end if;
			end if;
			-- fill the output FIFO as much as possible with zeros (black)
			if XIL_NPI_WrFIFO_AlmostFull = '0' and XIL_NPI_InitDone = '1' then
				XIL_NPI_WrFIFO_Push  <= '1';
			else
				XIL_NPI_WrFIFO_Push  <= '0';
			end if;

			-- are we reading an entry of the FIFO? 
			-- If so: four pixels are read (64 bit entries, 16 bit pixels)
			-- make this clocked, in mpmc3 empty-flag seems to be asynchronous
			-- we thus need to do this to achieve the target clock frequency
			XIL_NPI_RdFIFO_Pop_int_reg <= XIL_NPI_RdFIFO_Pop_int;
			if XIL_NPI_RdFIFO_Pop_int_reg = '1' then
				pixels_requested <= pixels_requested - C_PI_DATA_WIDTH/16;
			end if;
			-- was the read request acknowledged?
			if wait_for_addr_ack = '1' and XIL_NPI_AddrAck = '1' then
				-- yes: remove the request signal at once!
				XIL_NPI_AddrReq <= '0';
				wait_for_addr_ack <= '0';
				-- and there is new data in the FIFO soon!
				if XIL_NPI_RdFIFO_Pop_int_reg = '1' then
					-- when reading in the same clock cycle some pixels are removed at the same time
					pixels_requested <= pixels_requested + REQUEST_SIZE - C_PI_DATA_WIDTH/16;
				else
					pixels_requested <= pixels_requested + REQUEST_SIZE;
				end if;
			end if;

			-- check whether the FIFO is empty for a long time
			-- this happens when something is loaded with xmd
			-- for unknown reasons
			if XIL_NPI_RdFIFO_Empty = '1' and run_timing = '1' then
				time_out_counter <= time_out_counter + 1;
			else
				time_out_counter <= (others => '0');
			end if;


			-- READING FIFO OF MPMC2/3/4
			-- this is a small FSM that handles the latency of the rdFIFO
			-- according to the MPMC2-XIL_NPI manual three values for the latency are possible:
			-- 0: No latency at all
			-- 1: 1 clock cycle
			-- 2: 2 clock cycles
			case reading_FSM is

				when FIFO_REQ_0 =>
					-- if our shadow register is empty and data is available in the FIFO
					-- read data from the FIFO and store it in the shadow register
					if shadow_reg_filled = '0' and XIL_NPI_RdFIFO_Empty = '0' then
						-- here we also pop from the rdFIFO (async)
						-- in case of zero latency we are done here
						if XIL_NPI_RdFIFO_Latency = "00" then
							shadow_reg_filled <= '1';
							shadow_reg <= XIL_NPI_RdFIFO_Data;
						else
							-- else wait one or two clock cycles
							reading_FSM <= FIFO_REQ_1;
						end if;
					end if;

				when FIFO_REQ_1 =>
					-- one clock latency? Yes: we are done
					if XIL_NPI_RdFIFO_Latency = "01" then
						shadow_reg_filled <= '1';
						shadow_reg <= XIL_NPI_RdFIFO_Data;
						reading_FSM <= FIFO_REQ_0;
					else
						-- else wait another clock cycle
						reading_FSM <= FIFO_REQ_2;
					end if;

				when FIFO_REQ_2 =>
					-- two clock cycles latency is the maximum
					if XIL_NPI_RdFIFO_Latency = "10" then
						shadow_reg_filled <= '1';
						shadow_reg <= XIL_NPI_RdFIFO_Data;
						reading_FSM <= FIFO_REQ_0;
					end if;

			end case;

			-- TIMEOUT!!!!
			-- SO HEAL THE WORLD!
			if enable_screen = '0' or heal_the_world = '1' or time_out_counter = 1023 then
				time_out_counter <= (others => '0');
				wait_for_addr_ack <= '0';
				XIL_NPI_AddrReq <= '0';
				pixels_requested <= (others => '0');
				-- this resets the VGA timing
				run_timing <= '0';
				XIL_NPI_RdFIFO_Flush <= '1';
				screen_address_offset <= (others => '0');
				reading_fsm <= FIFO_REQ_0;
				x_pos_t <= (others => '0');
				pixel_counter_x <= (others => '0');
				line_displayed_once <= '0';
				shadow_reg_filled <= '0';
				reading_FSM <= FIFO_REQ_0;
			end if;
			blank_t <= blank;

			tft_lcd_de <= '0';
			-- display black only when a sync applies
			-- we take the delayed blank to guarantee a constant time for all pixels
			if blank_t = '1' or run_timing = '0' then
				tft_lcd_r <= (others => '0');
				tft_lcd_g <= (others => '0');
				tft_lcd_b <= (others => '0');
				-- or take the background color where possible
				-- switch of the background color when the electron ray runs to the start position
				if run_timing = '1' and hsync = '1' and (unsigned(y_pos) < bgnd_high or unsigned(y_pos) > bgnd_low) then
					tft_lcd_r <= background_color(15 downto 11);
					tft_lcd_g <= background_color(10 downto 5);
					tft_lcd_b <= background_color( 4 downto 0);
				end if;
			else
				-- we now display a new x, so display a new pixel
				-- the data enable flag has to be set in any case, since we want to display one pixel twice!
				if x_pos /= x_pos_t and run_timing = '1' then
					tft_lcd_de <= '1';
				end if;
				-- we now display a new x, so display a new pixel
				if (low_x_resolution_set_dis = '0' and x_pos /= x_pos_t and run_timing = '1') or
				   (low_x_resolution_set_dis = '1' and x_pos(10 downto 1) /= x_pos_t(10 downto 1) and run_timing = '1') then
					-- thus, shift the 64 bit wide pixel shift register by 16 bits
					-- and remember that one pixel less is pending in it
					pixel_shift_register(C_PI_DATA_WIDTH-16-1 downto 0) <= pixel_shift_register(C_PI_DATA_WIDTH-1 downto 16);
					pixel_shift_register_content <= pixel_shift_register_content - 1;
					-- read two/four new pixels from shadow register if we display the very last pixel of the pixel shift register
					if pixel_shift_register_content = 0 then
						if shadow_reg_filled = '1' then
							shadow_reg_filled <= '0';
							pixel_shift_register <= shadow_reg;
							pixel_shift_register_content <= to_unsigned(C_PI_DATA_WIDTH/16-1,3); -- two or four new pixels!
						else
							-- ERROR!! We need to use new pixels but they are not yet available!
							-- So initialize a reset of the screen display!
							heal_the_world <= '1';
						end if;
					end if;
				end if;
				-- inverse the bytes, due to little endianess
				pixel_endian_inverse := pixel_shift_register(7 downto 0) & pixel_shift_register(15 downto 8);
				tft_lcd_r <= pixel_endian_inverse(15 downto 11);
				tft_lcd_g <= pixel_endian_inverse(10 downto 5);
				tft_lcd_b <= pixel_endian_inverse(4 downto 0);
			end if;

		end if;
	end process;

end rtl;

⌨️ 快捷键说明

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