Files
PSX_MiSTer/rtl/gpu.vhd
kuba-j 5db42b67aa add old GPU option
Add old GPU option
- Simulates GPU (CXD8514Q) Gouraud shading limitations (Old GPU crops 8:8:8 bit gouraud shading color to 5:5:5 bit before multiplying it with the texture color)
- Toggleable in video settings
2025-11-09 12:42:11 +01:00

2133 lines
93 KiB
VHDL

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use STD.textio.all;
library mem;
use work.pGPU.all;
entity gpu is
port
(
clk1x : in std_logic;
clk2x : in std_logic;
clk2xIndex : in std_logic;
clkvid : in std_logic;
ce : in std_logic;
reset : in std_logic;
allowunpause : out std_logic;
savestate_busy : in std_logic;
system_paused : in std_logic;
ditherOff : in std_logic;
interlaced480pHack : in std_logic;
REPRODUCIBLEGPUTIMING: in std_logic;
videoout_on : in std_logic;
isPal : in std_logic;
pal60 : in std_logic;
fpscountOn : in std_logic;
noTexture : in std_logic;
textureFilter : in std_logic_vector(1 downto 0);
textureFilterStrength: in std_logic_vector(1 downto 0);
textureFilter2DOff : in std_logic;
dither24 : in std_logic;
render24 : in std_logic;
drawSlow : in std_logic;
debugmodeOn : in std_logic;
syncVideoOut : in std_logic;
syncInterlace : in std_logic;
rotate180 : in std_logic;
fixedVBlank : in std_logic;
vCrop : in std_logic_vector(1 downto 0);
hCrop : in std_logic;
oldGPU : in std_logic;
Gun1CrosshairOn : in std_logic;
Gun1X : in unsigned(7 downto 0);
Gun1Y_scanlines : in unsigned(8 downto 0);
Gun1offscreen : in std_logic;
Gun1IRQ10 : out std_logic;
Gun2CrosshairOn : in std_logic;
Gun2X : in unsigned(7 downto 0);
Gun2Y_scanlines : in unsigned(8 downto 0);
Gun2offscreen : in std_logic;
Gun2IRQ10 : out std_logic;
cdSlow : in std_logic;
errorOn : in std_logic;
errorEna : in std_logic;
errorCode : in unsigned(3 downto 0);
LBAOn : in std_logic;
LBAdisplay : in unsigned(19 downto 0);
errorLINE : out std_logic;
errorRECT : out std_logic;
errorPOLY : out std_logic;
errorGPU : out std_logic;
errorMASK : out std_logic;
errorFIFO : out std_logic;
bus_addr : in unsigned(3 downto 0);
bus_dataWrite : in std_logic_vector(31 downto 0);
bus_read : in std_logic;
bus_write : in std_logic;
bus_dataRead : out std_logic_vector(31 downto 0);
bus_stall : out std_logic := '0';
dmaOn : in std_logic;
gpu_dmaRequest : out std_logic;
DMA_GPU_waiting : in std_logic;
DMA_GPU_writeEna : in std_logic;
DMA_GPU_readEna : in std_logic;
DMA_GPU_write : in std_logic_vector(31 downto 0);
DMA_GPU_read : out std_logic_vector(31 downto 0);
irq_VBLANK : out std_logic := '0';
irq_GPU : out std_logic := '0';
vram_pause : in std_logic;
vram_paused : out std_logic := '0';
vram_BUSY : in std_logic;
vram_DOUT : in std_logic_vector(63 downto 0);
vram_DOUT_READY : in std_logic;
vram_BURSTCNT : out std_logic_vector(7 downto 0) := (others => '0');
vram_ADDR : out std_logic_vector(27 downto 0) := (others => '0');
vram_DIN : out std_logic_vector(63 downto 0) := (others => '0');
vram_BE : out std_logic_vector(7 downto 0) := (others => '0');
vram_WE : out std_logic := '0';
vram_RD : out std_logic := '0';
hblank_tmr : out std_logic := '0';
vblank_tmr : out std_logic := '0';
dotclock : out std_logic;
video_hsync : out std_logic := '0';
video_vsync : out std_logic := '0';
video_hblank : out std_logic := '0';
video_vblank : out std_logic := '0';
video_DisplayWidth : out unsigned(10 downto 0);
video_DisplayHeight : out unsigned( 9 downto 0);
video_DisplayOffsetX : out unsigned( 9 downto 0) := (others => '0');
video_DisplayOffsetY : out unsigned( 8 downto 0) := (others => '0');
video_ce : out std_logic;
video_interlace : out std_logic;
video_r : out std_logic_vector(7 downto 0);
video_g : out std_logic_vector(7 downto 0);
video_b : out std_logic_vector(7 downto 0);
video_isPal : out std_logic;
video_fbmode : out std_logic;
video_fb24 : out std_logic;
video_hResMode : out std_logic_vector(2 downto 0);
video_frameindex : out std_logic_vector(3 downto 0);
-- synthesis translate_off
export_gtm : out unsigned(11 downto 0);
export_line : out unsigned(11 downto 0);
export_gpus : out unsigned(31 downto 0);
export_gobj : out unsigned(15 downto 0) := (others => '0');
-- synthesis translate_on
loading_savestate : in std_logic;
SS_reset : in std_logic;
SS_DataWrite : in std_logic_vector(31 downto 0);
SS_Adr : in unsigned(2 downto 0);
SS_wren_GPU : in std_logic;
SS_wren_Timing : in std_logic;
SS_rden_GPU : in std_logic;
SS_rden_Timing : in std_logic;
SS_DataRead_GPU : out std_logic_vector(31 downto 0);
SS_DataRead_Timing : out std_logic_vector(31 downto 0);
SS_Idle : out std_logic
);
end entity;
architecture arch of gpu is
signal softReset : std_logic := '0';
signal drawer_reset : std_logic := '0';
signal videoout_settings : tvideoout_settings;
signal videoout_reports : tvideoout_reports;
signal videoout_out : tvideoout_out;
signal GPUREAD : std_logic_vector(31 downto 0) := (others => '0');
signal GPUSTAT : std_logic_vector(31 downto 0) := (others => '0');
signal GPUSTAT_TextPageX : std_logic_vector(3 downto 0);
signal GPUSTAT_TextPageY : std_logic;
signal GPUSTAT_Transparency : std_logic_vector(1 downto 0);
signal GPUSTAT_TextPageColors : std_logic_vector(1 downto 0);
signal GPUSTAT_Dither : std_logic;
signal GPUSTAT_DrawToDisplay : std_logic;
signal GPUSTAT_SetMask : std_logic;
signal GPUSTAT_DrawPixelsMask : std_logic;
signal GPUSTAT_ReverseFlag : std_logic;
signal GPUSTAT_TextureDisable : std_logic;
signal GPUSTAT_HorRes2 : std_logic := '0';
signal GPUSTAT_HorRes1 : std_logic_vector(1 downto 0) := "00";
signal GPUSTAT_VerRes : std_logic := '0';
signal GPUSTAT_PalVideoMode : std_logic := '0';
signal GPUSTAT_ColorDepth24 : std_logic := '0';
signal GPUSTAT_VertInterlace : std_logic := '0';
signal GPUSTAT_DisplayDisable : std_logic := '1';
signal GPUSTAT_IRQRequest : std_logic;
signal GPUSTAT_DMADataRequest : std_logic;
signal GPUSTAT_ReadyRecCmd : std_logic;
signal GPUSTAT_ReadySendVRAM : std_logic;
signal GPUSTAT_ReadyRecDMA : std_logic;
signal GPUSTAT_DMADirection : std_logic_vector(1 downto 0);
signal vramRange : unsigned(18 downto 0) := (others => '0');
signal hDisplayRange : unsigned(23 downto 0) := x"C60260";
signal vDisplayRange : unsigned(19 downto 0) := x"3FC10";
signal drawMode : unsigned(13 downto 0) := (others => '0');
signal textureWindow : unsigned(19 downto 0) := (others => '0');
signal textureWindow_AND_X : unsigned(7 downto 0) := (others => '0');
signal textureWindow_AND_Y : unsigned(7 downto 0) := (others => '0');
signal textureWindow_OR_X : unsigned(7 downto 0) := (others => '0');
signal textureWindow_OR_Y : unsigned(7 downto 0) := (others => '0');
signal drawingAreaLeft : unsigned(9 downto 0) := (others => '0');
signal drawingAreaRight : unsigned(9 downto 0) := (others => '0');
signal drawingAreaTop : unsigned(8 downto 0) := (others => '0');
signal drawingAreaBottom : unsigned(8 downto 0) := (others => '0');
signal drawingOffsetX : signed(10 downto 0) := (others => '0');
signal drawingOffsetY : signed(10 downto 0) := (others => '0');
signal interlacedDrawing : std_logic;
-- FIFO IN
signal fifoIn_reset : std_logic;
signal fifoIn_Din : std_logic_vector(31 downto 0);
signal fifoIn_Wr : std_logic;
signal fifoIn_Dout : std_logic_vector(31 downto 0);
signal fifoIn_Rd : std_logic;
signal fifoIn_Empty : std_logic;
signal fifoIn_Valid : std_logic;
-- Processing
signal proc_idle : std_logic;
signal proc_done : std_logic;
--signal proc_CmdDone : std_logic;
signal proc_requestFifo : std_logic;
signal timeout : integer range 0 to 67108863 := 0;
signal pixelStall : std_logic;
signal pixelColor : std_logic_vector(15 downto 0);
signal pixelColor2 : std_logic_vector(15 downto 0);
signal pixelAddr : unsigned(19 downto 0);
signal pixelWrite : std_logic;
signal pixel64data : std_logic_vector(63 downto 0) := (others => '0');
signal pixel64data2 : std_logic_vector(63 downto 0) := (others => '0');
signal pixel64wordEna : std_logic_vector(3 downto 0) := (others => '0');
signal pixel64addr : std_logic_vector(16 downto 0) := (others => '0');
signal pixel64filled : std_logic := '0';
signal pixel64source : std_logic := '0';
signal pixel64timeout : integer range 0 to 15;
-- workers
type t_div_array is array(0 to 5) of div_type;
signal div_array : t_div_array;
signal vramFill_requestFifo : std_logic;
signal vramFill_done : std_logic;
--signal vramFill_CmdDone : std_logic;
signal vramFill_pixelColor : std_logic_vector(15 downto 0);
signal vramFill_pixelAddr : unsigned(19 downto 0);
signal vramFill_pixelWrite : std_logic;
signal cpu2vram_requestFifo : std_logic;
signal cpu2vram_done : std_logic;
--signal cpu2vram_CmdDone : std_logic;
signal cpu2vram_pixelColor : std_logic_vector(15 downto 0);
signal cpu2vram_pixelAddr : unsigned(19 downto 0);
signal cpu2vram_pixelWrite : std_logic;
signal vram2vram_requestFifo : std_logic;
signal vram2vram_done : std_logic;
--signal vram2vram_CmdDone : std_logic;
signal vram2vram_pixelColor : std_logic_vector(15 downto 0);
signal vram2vram_pixelAddr : unsigned(19 downto 0);
signal vram2vram_pixelWrite : std_logic;
signal vram2vram_reqVRAMEnable : std_logic;
signal vram2vram_reqVRAMXPos : unsigned(9 downto 0);
signal vram2vram_reqVRAMYPos : unsigned(8 downto 0);
signal vram2vram_reqVRAMSize : unsigned(10 downto 0);
signal vram2vram_vramLineEna : std_logic;
signal vram2vram_vramLineAddr : unsigned(9 downto 0);
signal vram2cpu_requestFifo : std_logic;
signal vram2cpu_done : std_logic;
--signal vram2cpu_CmdDone : std_logic;
signal vram2cpu_reqVRAMEnable : std_logic;
signal vram2cpu_reqVRAMXPos : unsigned(9 downto 0);
signal vram2cpu_reqVRAMYPos : unsigned(8 downto 0);
signal vram2cpu_reqVRAMSize : unsigned(10 downto 0);
signal vram2cpu_vramLineEna : std_logic;
signal vram2cpu_vramLineAddr : unsigned(9 downto 0);
signal vram2cpu_Fifo_Dout : std_logic_vector(31 downto 0);
signal vram2cpu_Fifo_Rd : std_logic;
signal vram2cpu_Fifo_Empty : std_logic;
signal vram2cpu_Fifo_ready : std_logic;
signal line_requestFifo : std_logic;
signal line_done : std_logic;
--signal line_CmdDone : std_logic;
signal line_div : t_div_array;
signal line_pipeline_new : std_logic;
signal line_pipeline_transparent : std_logic;
signal line_pipeline_x : unsigned(9 downto 0);
signal line_pipeline_y : unsigned(8 downto 0);
signal line_pipeline_cr : unsigned(7 downto 0);
signal line_pipeline_cg : unsigned(7 downto 0);
signal line_pipeline_cb : unsigned(7 downto 0);
signal line_reqVRAMEnable : std_logic;
signal line_reqVRAMXPos : unsigned(9 downto 0);
signal line_reqVRAMYPos : unsigned(8 downto 0);
signal line_reqVRAMSize : unsigned(10 downto 0);
signal line_vramLineEna : std_logic;
signal line_vramLineAddr : unsigned(9 downto 0);
signal rect_requestFifo : std_logic;
signal rect_done : std_logic;
--signal rect_CmdDone : std_logic;
signal rect_pipeline_new : std_logic;
signal rect_pipeline_texture : std_logic;
signal rect_pipeline_transparent : std_logic;
signal rect_pipeline_rawTexture : std_logic;
signal rect_pipeline_x : unsigned(9 downto 0);
signal rect_pipeline_y : unsigned(8 downto 0);
signal rect_pipeline_cr : unsigned(7 downto 0);
signal rect_pipeline_cg : unsigned(7 downto 0);
signal rect_pipeline_cb : unsigned(7 downto 0);
signal rect_pipeline_u : unsigned(7 downto 0);
signal rect_pipeline_v : unsigned(7 downto 0);
signal rect_reqVRAMEnable : std_logic;
signal rect_reqVRAMXPos : unsigned(9 downto 0);
signal rect_reqVRAMYPos : unsigned(8 downto 0);
signal rect_reqVRAMSize : unsigned(10 downto 0);
signal rect_vramLineEna : std_logic;
signal rect_vramLineAddr : unsigned(9 downto 0);
signal rect_textPalNew : std_logic;
signal rect_textPalX : unsigned(9 downto 0);
signal rect_textPalY : unsigned(8 downto 0);
signal poly_requestFifo : std_logic;
signal poly_done : std_logic;
--signal poly_CmdDone : std_logic;
signal poly_div : t_div_array;
signal poly_pipeline_new : std_logic;
signal poly_pipeline_texture : std_logic;
signal poly_pipeline_transparent : std_logic;
signal poly_pipeline_rawTexture : std_logic;
signal poly_pipeline_dithering : std_logic;
signal poly_pipeline_x : unsigned(9 downto 0);
signal poly_pipeline_y : unsigned(8 downto 0);
signal poly_pipeline_cr : unsigned(7 downto 0);
signal poly_pipeline_cg : unsigned(7 downto 0);
signal poly_pipeline_cb : unsigned(7 downto 0);
signal poly_pipeline_u : unsigned(7 downto 0);
signal poly_pipeline_v : unsigned(7 downto 0);
signal poly_pipeline_u11 : unsigned(7 downto 0);
signal poly_pipeline_v11 : unsigned(7 downto 0);
signal poly_reqVRAMEnable : std_logic;
signal poly_reqVRAMXPos : unsigned(9 downto 0);
signal poly_reqVRAMYPos : unsigned(8 downto 0);
signal poly_reqVRAMSize : unsigned(10 downto 0);
signal poly_vramLineEna : std_logic;
signal poly_vramLineAddr : unsigned(9 downto 0);
signal poly_drawModeRec : unsigned(11 downto 0);
signal poly_drawModeNew : std_logic;
signal poly_textPalNew : std_logic;
signal poly_textPalX : unsigned(9 downto 0);
signal poly_textPalY : unsigned(8 downto 0);
signal pipeline_pixelColor : std_logic_vector(15 downto 0);
signal pipeline_pixelColor2 : std_logic_vector(15 downto 0);
signal pipeline_pixelAddr : unsigned(19 downto 0);
signal pipeline_pixelWrite : std_logic;
signal pipeline_reqVRAMEnable : std_logic;
signal pipeline_reqVRAMXPos : unsigned(9 downto 0);
signal pipeline_reqVRAMYPos : unsigned(8 downto 0);
signal pipeline_reqVRAMSize : unsigned(10 downto 0);
signal pipeline_busy : std_logic;
signal pipeline_stall : std_logic;
signal pipeline_new : std_logic;
signal pipeline_texture : std_logic;
signal pipeline_transparent : std_logic;
signal pipeline_rawTexture : std_logic;
signal pipeline_dithering : std_logic;
signal pipeline_x : unsigned(9 downto 0);
signal pipeline_y : unsigned(8 downto 0);
signal pipeline_cr : unsigned(7 downto 0);
signal pipeline_cg : unsigned(7 downto 0);
signal pipeline_cb : unsigned(7 downto 0);
signal pipeline_u : unsigned(7 downto 0);
signal pipeline_v : unsigned(7 downto 0);
signal pipeline_filter : std_logic;
signal pipeline_u11 : unsigned(7 downto 0);
signal pipeline_v11 : unsigned(7 downto 0);
signal pipeline_uAcc : unsigned(7 downto 0);
signal pipeline_vAcc : unsigned(7 downto 0);
signal pipeline_clearCacheTexture: std_logic := '0';
signal pipeline_clearCachePalette: std_logic := '0';
signal pipeline_textPalNew : std_logic;
signal pipeline_textPalX : unsigned(9 downto 0);
signal pipeline_textPalY : unsigned(8 downto 0);
-- FIFO OUT
signal fifoOut_reset : std_logic;
signal fifoOut_Din : std_logic_vector(85 downto 0);
signal fifoOut_Wr : std_logic;
signal fifoOut_Wr_1 : std_logic;
signal fifoOut_NearFull : std_logic;
signal fifoOut_Dout : std_logic_vector(85 downto 0);
signal fifoOut_Rd : std_logic;
signal fifoOut_Empty : std_logic;
signal fifoOut_idle : std_logic;
signal fifoOut2_Din : std_logic_vector(63 downto 0);
signal fifoOut2_Dout : std_logic_vector(63 downto 0);
signal fifoOut2_Dout_1 : std_logic_vector(63 downto 0);
-- vram access
type tvramState is
(
IDLE,
WRITESECOND,
READSECOND,
READVRAM,
CLEARLINESTART,
CLEARLINE
);
signal vramState : tvramState := IDLE;
signal VRAMIdle : std_logic;
signal reqVRAMIdle : std_logic;
signal reqVRAMDone : std_logic;
signal vram_pauseCnt : integer range 0 to 3;
signal reqVRAMEnable : std_logic;
signal reqVRAMXPos : unsigned(9 downto 0);
signal reqVRAMYPos : unsigned(8 downto 0);
signal reqVRAMSize : unsigned(10 downto 0);
signal reqVRAMremain : unsigned(7 downto 0);
signal reqVRAMremain2 : unsigned(7 downto 0);
signal reqVRAMwait : unsigned(7 downto 0);
signal reqVRAMwrap : unsigned(7 downto 0);
signal reqVRAMnext : unsigned(7 downto 0);
signal reqVRAMaddr : unsigned(7 downto 0) := (others => '0');
signal reqVRAMaddr2 : unsigned(7 downto 0) := (others => '0');
signal reqVRAMStore : std_logic := '0';
signal reqVRAMStore2 : std_logic := '0';
signal reqVRAMtwice : std_logic := '0';
signal vramLineAddr : unsigned(9 downto 0);
signal vramLineData : std_logic_vector(15 downto 0);
signal vramLineData2 : std_logic_vector(15 downto 0);
-- videoout
signal videoout_reqVRAMEnable : std_logic;
signal videoout_reqRAMMirror : std_logic;
signal videoout_reqVRAMXPos : unsigned(9 downto 0);
signal videoout_reqVRAMYPos : unsigned(8 downto 0);
signal videoout_reqVRAMSize : unsigned(10 downto 0);
-- direct framebuffer mode
signal frameindex_current : unsigned(1 downto 0) := (others => '0');
signal frameindex_last : unsigned(1 downto 0) := (others => '0');
signal irq_VBLANK_1 : std_logic := '0';
signal poly_requestFifo_1 : std_logic := '0';
signal frameWriteCount : integer := 0;
signal framePolyCount : integer range 0 to 16777215 := 0;
signal frameFastCount : integer range 0 to 3 := 0;
signal frameFastmode : std_logic := '0';
signal frameVramType : std_logic := '0';
signal frameFirstChangedLine : unsigned(8 downto 0) := (others => '0');
signal frameLastChangedLine : unsigned(8 downto 0) := (others => '0');
signal frameClearRequest : std_logic := '0';
signal frameClearYPos : unsigned(8 downto 0) := (others => '0');
signal frameClearCnt : unsigned(8 downto 0) := (others => '0');
signal frameClearPosLow : unsigned(8 downto 0) := (others => '0');
signal frameClearPosHigh : unsigned(8 downto 0) := (others => '0');
signal frameClearXPos : unsigned(9 downto 0) := (others => '0');
-- fps counter
signal fpscountBCD : unsigned(7 downto 0) := (others => '0');
signal fpscountBCD_next : unsigned(7 downto 0) := (others => '0');
signal fps_SecondCounter : integer range 0 to 33868799 := 0;
signal fps_vramRange_last : unsigned(18 downto 0) := (others => '0');
-- savestates
type t_ssarray is array(0 to 7) of std_logic_vector(31 downto 0);
signal ss_gpu_in : t_ssarray := (others => (others => '0'));
signal ss_timing_in : t_ssarray := (others => (others => '0'));
signal ss_gpu_out : t_ssarray := (others => (others => '0'));
signal ss_timing_out : t_ssarray := (others => (others => '0'));
signal videoout_ss_in : tvideoout_ss;
signal videoout_ss_out : tvideoout_ss;
begin
-- synthesis translate_off
export_gtm <= unsigned(videoout_ss_out.nextHCount);
export_line <= "000" & unsigned(videoout_ss_out.vpos);
export_gpus <= unsigned(GPUSTAT);
-- synthesis translate_on
gpu_dmaRequest <= GPUSTAT_DMADataRequest;
GPUSTAT(3 downto 0) <= GPUSTAT_TextPageX;
GPUSTAT(4) <= GPUSTAT_TextPageY;
GPUSTAT(6 downto 5) <= GPUSTAT_Transparency;
GPUSTAT(8 downto 7) <= GPUSTAT_TextPageColors;
GPUSTAT(9) <= GPUSTAT_Dither;
GPUSTAT(10) <= GPUSTAT_DrawToDisplay;
GPUSTAT(11) <= GPUSTAT_SetMask;
GPUSTAT(12) <= GPUSTAT_DrawPixelsMask;
GPUSTAT(13) <= not videoout_reports.GPUSTAT_InterlaceField;
GPUSTAT(14) <= GPUSTAT_ReverseFlag;
GPUSTAT(15) <= GPUSTAT_TextureDisable;
GPUSTAT(16) <= GPUSTAT_HorRes2;
GPUSTAT(18 downto 17) <= GPUSTAT_HorRes1;
GPUSTAT(19) <= GPUSTAT_VerRes;
GPUSTAT(20) <= GPUSTAT_PalVideoMode;
GPUSTAT(21) <= GPUSTAT_ColorDepth24;
GPUSTAT(22) <= GPUSTAT_VertInterlace;
GPUSTAT(23) <= GPUSTAT_DisplayDisable;
GPUSTAT(24) <= GPUSTAT_IRQRequest;
GPUSTAT(25) <= GPUSTAT_DMADataRequest;
GPUSTAT(26) <= GPUSTAT_ReadyRecCmd and ((not gpu_dmaRequest) or (not DMA_GPU_waiting));
GPUSTAT(27) <= GPUSTAT_ReadySendVRAM;
GPUSTAT(28) <= GPUSTAT_ReadyRecDMA;
GPUSTAT(30 downto 29) <= GPUSTAT_DMADirection;
GPUSTAT(31) <= videoout_reports.GPUSTAT_DrawingOddline;
GPUSTAT_DMADataRequest <= '0' when (GPUSTAT_DMADirection = "00") else
GPUSTAT_ReadyRecDMA when (GPUSTAT_DMADirection = "01") else
GPUSTAT_ReadyRecDMA when (GPUSTAT_DMADirection = "10") else
not vram2cpu_Fifo_Empty; -- GPUSTAT_ReadySendVRAM cannot be used, because data is read earlier
-- video out
irq_VBLANK <= videoout_reports.irq_VBLANK;
hblank_tmr <= videoout_reports.hblank_tmr;
-- savestates
ss_gpu_out(0) <= GPUREAD;
ss_gpu_out(1) <= GPUSTAT;
ss_timing_out(4)(19) <= videoout_ss_out.interlacedDisplayField;
ss_timing_out(2)(18 downto 0) <= std_logic_vector(vramRange);
ss_timing_out(1)(23 downto 0) <= std_logic_vector(hDisplayRange);
ss_timing_out(0)(19 downto 0) <= std_logic_vector(vDisplayRange);
ss_timing_out(4)(11 downto 0) <= videoout_ss_out.nextHCount;
ss_timing_out(3)(24 downto 16) <= videoout_ss_out.vpos;
ss_timing_out(4)(17) <= videoout_ss_out.inVsync;
ss_timing_out(4)(20) <= videoout_ss_out.activeLineLSB;
ss_timing_out(4)(29 downto 21) <= videoout_ss_out.vdisp;
process (clk1x)
variable cmdNew : unsigned(7 downto 0);
variable frameWriteLineY : unsigned(8 downto 0);
begin
if rising_edge(clk1x) then
fifoIn_reset <= '0';
fifoOut_reset <= '0';
drawer_reset <= '0';
vblank_tmr <= videoout_reports.inVsync;
if (reset = '1') then
softReset <= not loading_savestate;
bus_stall <= '0';
fifoIn_reset <= '1';
fifoOut_reset <= '1';
vramRange <= unsigned(ss_timing_in(2)(18 downto 0));
hDisplayRange <= unsigned(ss_timing_in(1)(23 downto 0)); -- x"C60260";
vDisplayRange <= unsigned(ss_timing_in(0)(19 downto 0)); -- x"3FC10";
GPUSTAT_ReverseFlag <= ss_gpu_in(1)(14);
GPUSTAT_HorRes2 <= ss_gpu_in(1)(16);
GPUSTAT_HorRes1 <= ss_gpu_in(1)(18 downto 17);
GPUSTAT_VerRes <= ss_gpu_in(1)(19);
GPUSTAT_PalVideoMode <= ss_gpu_in(1)(20); --isPal;
GPUSTAT_ColorDepth24 <= ss_gpu_in(1)(21);
GPUSTAT_VertInterlace <= ss_gpu_in(1)(22);
GPUSTAT_DisplayDisable <= ss_gpu_in(1)(23);
GPUSTAT_IRQRequest <= ss_gpu_in(1)(24);
GPUSTAT_DMADirection <= ss_gpu_in(1)(30 downto 29);
GPUREAD <= ss_gpu_in(0);
fpscountBCD_next <= (others => '0');
frameFastCount <= 0;
frameFastmode <= '0';
elsif (ce = '1') then
bus_dataRead <= (others => '0');
softReset <= '0';
-- bus read
if (bus_read = '1') then
if (bus_addr(3 downto 2) = "00") then
if (vram2cpu_Fifo_Empty = '0') then
bus_dataRead <= vram2cpu_Fifo_Dout;
GPUREAD <= vram2cpu_Fifo_Dout;
else
bus_dataRead <= GPUREAD;
end if;
if (vram2cpu_Fifo_ready = '0') then
bus_stall <= '1';
end if;
elsif (bus_addr(3 downto 2) = "01") then
bus_dataRead <= GPUSTAT;
else
bus_dataRead <= x"FFFFFFFF";
end if;
end if;
if (bus_stall = '1' and vram2cpu_Fifo_ready = '1') then
bus_dataRead <= vram2cpu_Fifo_Dout;
GPUREAD <= vram2cpu_Fifo_Dout;
bus_stall <= '0';
end if;
-- bus write
if (bus_write = '1') then
if (bus_addr = 4) then
case (to_integer(unsigned(bus_dataWrite(29 downto 24)))) is
when 16#00# => -- reset
softReset <= '1';
fifoIn_reset <= '1';
when 16#01# => -- clear fifo
fifoIn_reset <= '1';
drawer_reset <= '1';
-- todo: must reset drawing units to idle? -> ridge racer triggers that in the middle of a rectangle command clearing the screen
-- reset CLUT cache?
when 16#02# => -- ack irq
GPUSTAT_IRQRequest <= '0';
when 16#03# => -- display on/off
GPUSTAT_DisplayDisable <= bus_dataWrite(0);
when 16#04# => -- DMA direction
GPUSTAT_DMADirection <= bus_dataWrite(1 downto 0);
when 16#05# => -- Start of Display area (in VRAM)
vramRange <= unsigned(bus_dataWrite(18 downto 1)) & '0';
when 16#06# => -- horizontal diplay range
hDisplayRange <= unsigned(bus_dataWrite(23 downto 0));
when 16#07# => -- vertical diplay range
vDisplayRange <= unsigned(bus_dataWrite(19 downto 0));
when 16#08# => -- Set display mode
GPUSTAT_HorRes1 <= bus_dataWrite(1 downto 0);
GPUSTAT_VerRes <= bus_dataWrite(2);
GPUSTAT_PalVideoMode <= bus_dataWrite(3);
GPUSTAT_ColorDepth24 <= bus_dataWrite(4);
GPUSTAT_VertInterlace <= bus_dataWrite(5);
GPUSTAT_HorRes2 <= bus_dataWrite(6);
GPUSTAT_ReverseFlag <= bus_dataWrite(7);
when 16#09# => -- Allow texture disable
-- todo
when 16#10# | 16#11# | 16#12# | 16#13# | 16#14# | 16#15# | 16#16# | 16#17# | 16#18# | 16#19# | 16#1A# | 16#1B# | 16#1C# | 16#1D# | 16#1E# | 16#1F# => -- GPUInfo
case (to_integer(unsigned(bus_dataWrite(2 downto 0)))) is
when 2 => --Get Texture Window
GPUREAD <= x"000" & std_logic_vector(textureWindow);
when 3 => --Get Draw Area Top Left
GPUREAD <= x"000" & '0' & std_logic_vector(drawingAreaTop) & std_logic_vector(drawingAreaLeft);
when 4 => --Get Draw Area Bottom Right
GPUREAD <= x"000" & '0' & std_logic_vector(drawingAreaBottom) & std_logic_vector(drawingAreaRight);
when 5 => --Get Drawing Offset
GPUREAD <= x"00" & "00" & std_logic_vector(drawingOffsetY) & std_logic_vector(drawingOffsetX);
when others => null;
end case;
when others => report "GP1 Command not implemented" severity failure;
end case;
end if;
end if;
if (irq_GPU = '1') then
GPUSTAT_IRQRequest <= '1';
end if;
-- 480i framebuffer logic
frameWriteLineY := unsigned(vram_ADDR(19 downto 11)) - videoout_out.DisplayOffsetY;
if (vram_we = '1' and frameVramType = '1') then
if (unsigned(vram_ADDR(19 downto 11)) >= videoout_out.DisplayOffsetY) then
if (unsigned(vram_ADDR(19 downto 11)) < (videoout_out.DisplayOffsetY + videoout_out.DisplayHeightReal)) then
if (frameWriteLineY < frameFirstChangedLine) then
frameFirstChangedLine <= frameWriteLineY;
end if;
if (frameWriteLineY > frameLastChangedLine) then
frameLastChangedLine <= frameWriteLineY;
end if;
if (unsigned(vram_ADDR(10 downto 1)) >= videoout_out.DisplayOffsetX) then
if (unsigned(vram_ADDR(10 downto 1)) < (videoout_out.DisplayOffsetX + videoout_out.DisplayWidthReal)) then
frameWriteCount <= frameWriteCount + 1;
end if;
end if;
end if;
end if;
end if;
poly_requestFifo_1 <= poly_requestFifo;
if (poly_requestFifo_1 = '0' and poly_requestFifo = '1') then
framePolyCount <= framePolyCount + 1;
end if;
irq_VBLANK_1 <= videoout_reports.irq_VBLANK;
if (videoout_reports.irq_VBLANK = '1' and irq_VBLANK_1 = '0') then
frameFastmode <= '0';
frameWriteCount <= 0;
framePolyCount <= 0;
frameFirstChangedLine <= (others => '1');
frameLastChangedLine <= (others => '0');
if (GPUSTAT_VertInterlace = '1' and GPUSTAT_VerRes = '1') then
-- condition to allow 480p hack: game is in 480i mode and draws most of the screen every frame
if (frameWriteCount > 40000 and framePolyCount > 31 and frameFirstChangedLine < 40 and (videoout_out.DisplayHeightReal - frameLastChangedLine) < 30) then
if (frameFastCount < 3) then
frameFastCount <= frameFastCount + 1;
else
frameFastmode <= interlaced480pHack;
end if;
frameindex_last <= frameindex_current;
if (frameindex_current = 2) then
frameindex_current <= (others => '0');
else
frameindex_current <= frameindex_current + 1;
end if;
end if;
else
frameFastCount <= 0;
frameFastmode <= '0';
end if;
end if;
-- fps counter
if (videoout_reports.irq_VBLANK = '1') then
fps_vramRange_last <= vramRange;
if (vramRange /= fps_vramRange_last) then
if (fpscountBCD_next(3 downto 0) = x"9") then
fpscountBCD_next(7 downto 4) <= fpscountBCD_next(7 downto 4) + 1;
fpscountBCD_next(3 downto 0) <= x"0";
else
fpscountBCD_next(3 downto 0) <= fpscountBCD_next(3 downto 0) + 1;
end if;
end if;
end if;
if (fps_SecondCounter = 33868799) then
fps_SecondCounter <= 0;
fpscountBCD <= fpscountBCD_next;
fpscountBCD_next <= (others => '0');
else
fps_SecondCounter <= fps_SecondCounter + 1;
end if;
-- softreset
if (softReset = '1') then
vramRange <= (others => '0');
hDisplayRange <= x"C60260";
vDisplayRange <= x"3FC10";
GPUSTAT_ReverseFlag <= '0';
GPUSTAT_HorRes2 <= '0';
GPUSTAT_HorRes1 <= "00";
GPUSTAT_VerRes <= '0';
GPUSTAT_PalVideoMode <= isPal;
GPUSTAT_ColorDepth24 <= '0';
GPUSTAT_VertInterlace <= '0';
GPUSTAT_DisplayDisable <= '1';
GPUSTAT_IRQRequest <= '0';
GPUSTAT_DMADirection <= "00";
end if;
end if;
end if;
end process;
video_fbmode <= frameFastmode;
video_fb24 <= frameFastmode and GPUSTAT_ColorDepth24;
iSyncFifo_IN: entity mem.SyncFifo
generic map
(
--SIZE => 32, -- 16 is correct, but only allows 15 entries -> use nearfull or allow this big for broken homebrew -> some games seem to exceed it also with DMA, how is that possible?
SIZE => 256, -- using larger fifo because of broken homebrew depending on it, shouldn't matter for official games, simply unused there and the full blockram is free anyway
DATAWIDTH => 32,
NEARFULLDISTANCE => 16
)
port map
(
clk => clk2x,
reset => fifoIn_reset,
Din => fifoIn_Din,
Wr => fifoIn_Wr,
Full => ERRORFIFO,
NearFull => open,
Dout => fifoIn_Dout,
Rd => fifoIn_Rd,
Empty => fifoIn_Empty
);
fifoIn_Rd <= '1' when (ce = '1' and (proc_idle = '1' or proc_requestFifo = '1') and pipeline_busy = '0' and fifoIn_Empty = '0' and fifoIn_Valid = '0' and (clk2xIndex = '0' or REPRODUCIBLEGPUTIMING = '0')) else '0';
process (clk2x)
begin
if rising_edge(clk2x) then
if (reset = '1') then
elsif (ce = '1') then
fifoIn_Wr <= '0';
if (clk2xIndex = '1' and bus_write = '1' and bus_addr = 0) then
fifoIn_Wr <= '1';
fifoIn_Din <= bus_dataWrite;
end if;
if (clk2xIndex = '1' and DMA_GPU_writeEna = '1') then
fifoIn_Wr <= '1';
fifoIn_Din <= DMA_GPU_write;
end if;
end if;
end if;
end process;
ss_gpu_out(2)(19 downto 0) <= std_logic_vector(textureWindow);
ss_gpu_out(4)(9 downto 0) <= std_logic_vector(drawingAreaLeft);
ss_gpu_out(5)(9 downto 0) <= std_logic_vector(drawingAreaRight);
ss_gpu_out(4)(24 downto 16) <= std_logic_vector(drawingAreaTop);
ss_gpu_out(5)(24 downto 16) <= std_logic_vector(drawingAreaBottom);
ss_gpu_out(6)(10 downto 0) <= std_logic_vector(drawingOffsetX);
ss_gpu_out(6)(26 downto 16) <= std_logic_vector(drawingOffsetY);
ss_gpu_out(3)(13 downto 0) <= std_logic_vector(drawMode);
ss_gpu_out(3)(16) <= GPUSTAT_DrawPixelsMask;
ss_gpu_out(3)(17) <= GPUSTAT_TextureDisable;
process (clk2x)
variable cmdNew : unsigned(7 downto 0);
begin
if rising_edge(clk2x) then
textureWindow_AND_X <= not (textureWindow(4 downto 0) & "000");
textureWindow_AND_Y <= not (textureWindow(9 downto 5) & "000");
textureWindow_OR_X <= (textureWindow(4 downto 0) and textureWindow(14 downto 10)) & "000";
textureWindow_OR_Y <= (textureWindow(9 downto 5) and textureWindow(19 downto 15)) & "000";
errorGPU <= '0';
if (proc_idle = '1') then
timeout <= 0;
elsif (timeout < 67108863) then
timeout <= timeout + 1;
else
errorGPU <= '1';
end if;
if (reset = '1') then
proc_idle <= '1';
textureWindow <= unsigned(ss_gpu_in(2)(19 downto 0));
drawingAreaLeft <= unsigned(ss_gpu_in(4)(9 downto 0));
drawingAreaRight <= unsigned(ss_gpu_in(5)(9 downto 0));
drawingAreaTop <= unsigned(ss_gpu_in(4)(24 downto 16));
drawingAreaBottom <= unsigned(ss_gpu_in(5)(24 downto 16));
drawingOffsetX <= signed(ss_gpu_in(6)(10 downto 0));
drawingOffsetY <= signed(ss_gpu_in(6)(26 downto 16));
drawMode <= unsigned(ss_gpu_in(3)(13 downto 0));
--GPUSTAT_DrawPixelsMask <= ss_gpu_in(3)(16);
--GPUSTAT_TextureDisable <= ss_gpu_in(3)(17);
GPUSTAT_TextPageX <= ss_gpu_in(1)(3 downto 0);
GPUSTAT_TextPageY <= ss_gpu_in(1)(4);
GPUSTAT_Transparency <= ss_gpu_in(1)(6 downto 5);
GPUSTAT_TextPageColors <= ss_gpu_in(1)(8 downto 7);
GPUSTAT_Dither <= ss_gpu_in(1)(9);
GPUSTAT_DrawToDisplay <= ss_gpu_in(1)(10);
GPUSTAT_SetMask <= ss_gpu_in(1)(11);
GPUSTAT_DrawPixelsMask <= ss_gpu_in(1)(12);
GPUSTAT_TextureDisable <= ss_gpu_in(1)(15);
GPUSTAT_ReadyRecCmd <= '1'; --ss_gpu_in(1)(26); -- in savestate should never be busy
GPUSTAT_ReadyRecDMA <= '1'; --ss_gpu_in(1)(28);
fifoIn_Valid <= '0';
elsif (ce = '1') then
fifoIn_Valid <= fifoIn_Rd and not fifoIn_reset;
pipeline_clearCacheTexture <= '0';
pipeline_clearCachePalette <= '0';
if (poly_drawModeNew = '1') then
drawMode(8 downto 0) <= poly_drawModeRec(8 downto 0);
drawMode(11) <= poly_drawModeRec(11);
end if;
if (clk2xIndex = '1') then
irq_GPU <= '0';
end if;
if (fifoIn_Valid = '1' and proc_idle = '1') then
cmdNew := unsigned(fifoIn_Dout(31 downto 24));
if ((cmdNew >= 16#20# and cmdNew <=16#DF#) or cmdNew = 16#02#) then
proc_idle <= '0';
GPUSTAT_ReadyRecCmd <= '0';
elsif (cmdNew = 16#01#) then -- clear cache
pipeline_clearCacheTexture <= '1';
pipeline_clearCachePalette <= '1';
elsif (cmdNew = 16#1F#) then -- irq request
if (GPUSTAT_IRQRequest = '0') then
irq_GPU <= '1';
end if;
elsif (cmdNew = 16#E1#) then -- Draw Mode setting
GPUSTAT_TextPageX <= fifoIn_Dout(3 downto 0);
GPUSTAT_TextPageY <= fifoIn_Dout(4);
GPUSTAT_Transparency <= fifoIn_Dout(6 downto 5);
GPUSTAT_TextPageColors <= fifoIn_Dout(8 downto 7);
GPUSTAT_Dither <= fifoIn_Dout(9);
GPUSTAT_DrawToDisplay <= fifoIn_Dout(10);
GPUSTAT_TextureDisable <= fifoIn_Dout(11);
drawMode <= unsigned(fifoIn_Dout(13 downto 0));
elsif (cmdNew = 16#E2#) then -- Set Texture window
textureWindow <= unsigned(fifoIn_Dout(19 downto 0));
elsif (cmdNew = 16#E3#) then -- Set Drawing Area top left (X1,Y1)
drawingAreaLeft <= unsigned(fifoIn_Dout(9 downto 0));
drawingAreaTop <= unsigned(fifoIn_Dout(18 downto 10));
elsif (cmdNew = 16#E4#) then -- Set Drawing Area bottom right (X2,Y2)
drawingAreaRight <= unsigned(fifoIn_Dout(9 downto 0));
drawingAreaBottom <= unsigned(fifoIn_Dout(18 downto 10));
elsif (cmdNew = 16#E5#) then -- Set Drawing Offset (X,Y)
drawingOffsetX <= signed(fifoIn_Dout(10 downto 0));
drawingOffsetY <= signed(fifoIn_Dout(21 downto 11));
elsif (cmdNew = 16#E6#) then -- Mask Bit Setting
GPUSTAT_SetMask <= fifoIn_Dout(0);
GPUSTAT_DrawPixelsMask <= fifoIn_Dout(1);
end if;
end if;
if (proc_idle = '1') then
interlacedDrawing <= GPUSTAT_VertInterlace and GPUSTAT_VerRes and not GPUSTAT_DrawToDisplay;
end if;
GPUSTAT_ReadyRecDMA <= fifoIn_Empty;
if (proc_done = '1') then
-- synthesis translate_off
export_gobj <= export_gobj + 1;
-- synthesis translate_on
proc_idle <= '1';
GPUSTAT_ReadyRecCmd <= '1';
end if;
if (vramFill_done = '1' or cpu2vram_done = '1' or vram2vram_done = '1') then
pipeline_clearCacheTexture <= '1';
end if;
if (softReset = '1') then
proc_idle <= '1';
drawMode <= (others => '0');
GPUSTAT_TextPageX <= "0000";
GPUSTAT_TextPageY <= '0';
GPUSTAT_Transparency <= "00";
GPUSTAT_TextPageColors <= "00";
GPUSTAT_Dither <= '0';
GPUSTAT_DrawToDisplay <= '0';
GPUSTAT_SetMask <= '0';
GPUSTAT_DrawPixelsMask <= '0';
GPUSTAT_TextureDisable <= '0';
GPUSTAT_ReadyRecCmd <= '1';
GPUSTAT_ReadyRecDMA <= '1';
drawingAreaLeft <= (others => '0');
drawingAreaTop <= (others => '0');
drawingAreaRight <= (others => '0');
drawingAreaBottom <= (others => '0');
drawingOffsetX <= (others => '0');
drawingOffsetY <= (others => '0');
end if;
end if;
end if;
end process;
proc_done <= vramFill_done or cpu2vram_done or vram2vram_done or vram2cpu_done or line_done or rect_done or poly_done ;
--proc_CmdDone <= vramFill_CmdDone or cpu2vram_CmdDone or vram2vram_CmdDone or vram2cpu_CmdDone or line_CmdDone or rect_CmdDone or poly_CmdDone ;
proc_requestFifo <= vramFill_requestFifo or cpu2vram_requestFifo or vram2vram_requestFifo or vram2cpu_requestFifo or line_requestFifo or rect_requestFifo or poly_requestFifo;
pixelStall <= fifoOut_NearFull;
-- workers
igpu_fillVram : entity work.gpu_fillVram
port map
(
clk2x => clk2x,
clk2xIndex => clk2xIndex,
ce => ce,
reset => softreset or SS_reset,
REPRODUCIBLEGPUTIMING=> REPRODUCIBLEGPUTIMING,
interlacedDrawing => interlacedDrawing and (not interlaced480pHack),
activeLineLSB => videoout_reports.activeLineLSB,
proc_idle => proc_idle,
fifo_Valid => fifoIn_Valid,
fifo_data => fifoIn_Dout,
requestFifo => vramFill_requestFifo,
done => vramFill_done,
--CmdDone => vramFill_CmdDone,
pixelStall => pixelStall,
pixelColor => vramFill_pixelColor,
pixelAddr => vramFill_pixelAddr,
pixelWrite => vramFill_pixelWrite
);
igpu_cpu2vram : entity work.gpu_cpu2vram
port map
(
clk2x => clk2x,
clk2xIndex => clk2xIndex,
ce => ce,
reset => softreset or SS_reset,
drawer_reset => drawer_reset,
DrawPixelsMask => GPUSTAT_DrawPixelsMask,
SetMask => GPUSTAT_SetMask,
errorMASK => errorMASK,
proc_idle => proc_idle,
fifo_Valid => fifoIn_Valid,
fifo_data => fifoIn_Dout,
requestFifo => cpu2vram_requestFifo,
done => cpu2vram_done,
--CmdDone => cpu2vram_CmdDone,
pixelStall => pixelStall,
pixelColor => cpu2vram_pixelColor,
pixelAddr => cpu2vram_pixelAddr,
pixelWrite => cpu2vram_pixelWrite
);
igpu_vram2vram : entity work.gpu_vram2vram
port map
(
clk2x => clk2x,
clk2xIndex => clk2xIndex,
ce => ce,
reset => softreset or SS_reset,
DrawPixelsMask => GPUSTAT_DrawPixelsMask,
SetMask => GPUSTAT_SetMask,
REPRODUCIBLEGPUTIMING=> REPRODUCIBLEGPUTIMING,
proc_idle => proc_idle,
fifo_Valid => fifoIn_Valid,
fifo_data => fifoIn_Dout,
requestFifo => vram2vram_requestFifo,
done => vram2vram_done,
--CmdDone => vram2vram_CmdDone,
pipeline_busy => pipeline_busy,
fifoOut_idle => fifoOut_idle,
requestVRAMEnable => vram2vram_reqVRAMEnable,
requestVRAMXPos => vram2vram_reqVRAMXPos,
requestVRAMYPos => vram2vram_reqVRAMYPos,
requestVRAMSize => vram2vram_reqVRAMSize,
requestVRAMIdle => reqVRAMIdle,
requestVRAMDone => reqVRAMDone,
vramLineEna => vram2vram_vramLineEna,
vramLineAddr => vram2vram_vramLineAddr,
vramLineData => vramLineData,
pixelEmpty => fifoOut_Empty,
pixelStall => pixelStall,
pixelColor => vram2vram_pixelColor,
pixelAddr => vram2vram_pixelAddr,
pixelWrite => vram2vram_pixelWrite
);
vram2cpu_Fifo_Rd <= '1' when (vram2cpu_Fifo_Empty = '0' and clk2xIndex = '0' and DMA_GPU_readEna = '1') else
'1' when (vram2cpu_Fifo_Empty = '0' and clk2xIndex = '0' and bus_read = '1' and bus_addr(3 downto 2) = "00") else
'1' when (vram2cpu_Fifo_Empty = '0' and clk2xIndex = '0' and bus_stall = '1') else
'0';
DMA_GPU_read <= vram2cpu_Fifo_Dout when (vram2cpu_Fifo_Empty = '0') else (others => '1');
GPUSTAT_ReadySendVRAM <= not vram2cpu_Fifo_Empty;
igpu_vram2cpu : entity work.gpu_vram2cpu
port map
(
clk2x => clk2x,
ce => ce,
reset => softreset or SS_reset,
drawer_reset => drawer_reset,
REPRODUCIBLEGPUTIMING=> REPRODUCIBLEGPUTIMING,
proc_idle => proc_idle,
fifo_Valid => fifoIn_Valid,
fifo_data => fifoIn_Dout,
requestFifo => vram2cpu_requestFifo,
done => vram2cpu_done,
--CmdDone => vram2cpu_CmdDone,
pipeline_busy => pipeline_busy,
fifoOut_idle => fifoOut_idle,
requestVRAMEnable => vram2cpu_reqVRAMEnable,
requestVRAMXPos => vram2cpu_reqVRAMXPos,
requestVRAMYPos => vram2cpu_reqVRAMYPos,
requestVRAMSize => vram2cpu_reqVRAMSize,
requestVRAMIdle => reqVRAMIdle,
requestVRAMDone => reqVRAMDone,
vramLineEna => vram2cpu_vramLineEna,
vramLineAddr => vram2cpu_vramLineAddr,
vramLineData => vramLineData,
Fifo_Dout => vram2cpu_Fifo_Dout,
Fifo_Rd => vram2cpu_Fifo_Rd,
Fifo_Empty => vram2cpu_Fifo_Empty,
Fifo_ready => vram2cpu_Fifo_ready
);
igpu_line : entity work.gpu_line
port map
(
clk2x => clk2x,
clk2xIndex => clk2xIndex,
ce => ce,
reset => softreset or SS_reset,
REPRODUCIBLEGPUTIMING=> REPRODUCIBLEGPUTIMING,
error => errorLINE,
DrawPixelsMask => GPUSTAT_DrawPixelsMask,
interlacedDrawing => interlacedDrawing and (not interlaced480pHack),
activeLineLSB => videoout_reports.activeLineLSB,
drawingOffsetX => drawingOffsetX,
drawingOffsetY => drawingOffsetY,
drawingAreaLeft => drawingAreaLeft,
drawingAreaRight => drawingAreaRight,
drawingAreaTop => drawingAreaTop,
drawingAreaBottom => drawingAreaBottom,
div1 => line_div(0),
div2 => line_div(1),
div3 => line_div(2),
div4 => line_div(3),
div5 => line_div(4),
div6 => line_div(5),
fifoOut_idle => fifoOut_idle,
pipeline_busy => pipeline_busy,
pipeline_stall => pipeline_stall,
pipeline_new => line_pipeline_new,
pipeline_transparent => line_pipeline_transparent,
pipeline_x => line_pipeline_x,
pipeline_y => line_pipeline_y,
pipeline_cr => line_pipeline_cr,
pipeline_cg => line_pipeline_cg,
pipeline_cb => line_pipeline_cb,
proc_idle => proc_idle,
fifo_Valid => fifoIn_Valid,
fifo_data => fifoIn_Dout,
requestFifo => line_requestFifo,
done => line_done,
--CmdDone => line_CmdDone,
requestVRAMEnable => line_reqVRAMEnable,
requestVRAMXPos => line_reqVRAMXPos,
requestVRAMYPos => line_reqVRAMYPos,
requestVRAMSize => line_reqVRAMSize,
requestVRAMIdle => reqVRAMIdle,
requestVRAMDone => reqVRAMDone,
vramLineEna => line_vramLineEna,
vramLineAddr => line_vramLineAddr
);
igpu_rect : entity work.gpu_rect
port map
(
clk2x => clk2x,
clk2xIndex => clk2xIndex,
ce => ce,
reset => softreset or SS_reset,
REPRODUCIBLEGPUTIMING=> REPRODUCIBLEGPUTIMING,
error => errorRECT,
DrawPixelsMask => GPUSTAT_DrawPixelsMask,
interlacedDrawing => interlacedDrawing and (not interlaced480pHack),
activeLineLSB => videoout_reports.activeLineLSB,
drawingOffsetX => drawingOffsetX,
drawingOffsetY => drawingOffsetY,
drawingAreaLeft => drawingAreaLeft,
drawingAreaRight => drawingAreaRight,
drawingAreaTop => drawingAreaTop,
drawingAreaBottom => drawingAreaBottom,
fifoOut_idle => fifoOut_idle,
pipeline_busy => pipeline_busy,
pipeline_stall => pipeline_stall,
pipeline_new => rect_pipeline_new,
pipeline_texture => rect_pipeline_texture,
pipeline_transparent => rect_pipeline_transparent,
pipeline_rawTexture => rect_pipeline_rawTexture,
pipeline_x => rect_pipeline_x,
pipeline_y => rect_pipeline_y,
pipeline_cr => rect_pipeline_cr,
pipeline_cg => rect_pipeline_cg,
pipeline_cb => rect_pipeline_cb,
pipeline_u => rect_pipeline_u,
pipeline_v => rect_pipeline_v,
proc_idle => proc_idle,
fifo_Valid => fifoIn_Valid,
fifo_data => fifoIn_Dout,
requestFifo => rect_requestFifo,
done => rect_done,
--CmdDone => rect_CmdDone,
requestVRAMEnable => rect_reqVRAMEnable,
requestVRAMXPos => rect_reqVRAMXPos,
requestVRAMYPos => rect_reqVRAMYPos,
requestVRAMSize => rect_reqVRAMSize,
requestVRAMIdle => reqVRAMIdle,
requestVRAMDone => reqVRAMDone,
textPalNew => rect_textPalNew,
textPalX => rect_textPalX,
textPalY => rect_textPalY,
vramLineEna => rect_vramLineEna,
vramLineAddr => rect_vramLineAddr
);
igpu_poly : entity work.gpu_poly
port map
(
clk2x => clk2x,
clk2xIndex => clk2xIndex,
ce => ce,
reset => softreset or SS_reset,
REPRODUCIBLEGPUTIMING=> REPRODUCIBLEGPUTIMING,
textureFilter => textureFilter,
textureFilterStrength=> textureFilterStrength,
textureFilter2DOff => textureFilter2DOff,
error => errorPOLY,
DrawPixelsMask => GPUSTAT_DrawPixelsMask,
interlacedDrawing => interlacedDrawing and (not interlaced480pHack),
activeLineLSB => videoout_reports.activeLineLSB,
drawingOffsetX => drawingOffsetX,
drawingOffsetY => drawingOffsetY,
drawingAreaLeft => drawingAreaLeft,
drawingAreaRight => drawingAreaRight,
drawingAreaTop => drawingAreaTop,
drawingAreaBottom => drawingAreaBottom,
drawModeRec => poly_drawModeRec,
drawModeNew => poly_drawModeNew,
drawmode_dithering => drawMode(9),
div1 => poly_div(0),
div2 => poly_div(1),
div3 => poly_div(2),
div4 => poly_div(3),
div5 => poly_div(4),
div6 => poly_div(5),
fifoOut_idle => fifoOut_idle,
pipeline_busy => pipeline_busy,
pipeline_stall => pipeline_stall,
pipeline_new => poly_pipeline_new,
pipeline_texture => poly_pipeline_texture,
pipeline_transparent => poly_pipeline_transparent,
pipeline_rawTexture => poly_pipeline_rawTexture,
pipeline_dithering => poly_pipeline_dithering,
pipeline_x => poly_pipeline_x,
pipeline_y => poly_pipeline_y,
pipeline_cr => poly_pipeline_cr,
pipeline_cg => poly_pipeline_cg,
pipeline_cb => poly_pipeline_cb,
pipeline_u => poly_pipeline_u,
pipeline_v => poly_pipeline_v,
pipeline_filter => pipeline_filter,
pipeline_u11 => poly_pipeline_u11,
pipeline_v11 => poly_pipeline_v11,
pipeline_uAcc => pipeline_uAcc,
pipeline_vAcc => pipeline_vAcc,
proc_idle => proc_idle,
fifo_Valid => fifoIn_Valid,
fifo_data => fifoIn_Dout,
requestFifo => poly_requestFifo,
done => poly_done,
--CmdDone => poly_CmdDone,
requestVRAMEnable => poly_reqVRAMEnable,
requestVRAMXPos => poly_reqVRAMXPos,
requestVRAMYPos => poly_reqVRAMYPos,
requestVRAMSize => poly_reqVRAMSize,
requestVRAMIdle => reqVRAMIdle,
requestVRAMDone => reqVRAMDone,
textPalNew => poly_textPalNew,
textPalX => poly_textPalX,
textPalY => poly_textPalY,
vramLineEna => poly_vramLineEna,
vramLineAddr => poly_vramLineAddr
);
pipeline_new <= line_pipeline_new or rect_pipeline_new or poly_pipeline_new ;
pipeline_texture <= '0' or rect_pipeline_texture or poly_pipeline_texture ;
pipeline_transparent <= line_pipeline_transparent or rect_pipeline_transparent or poly_pipeline_transparent;
pipeline_rawTexture <= '0' or rect_pipeline_rawTexture or poly_pipeline_rawTexture ;
pipeline_dithering <= (line_pipeline_new or '0' or poly_pipeline_dithering ) and drawMode(9) and (not ditherOff);
pipeline_x <= line_pipeline_x or rect_pipeline_x or poly_pipeline_x ;
pipeline_y <= line_pipeline_y or rect_pipeline_y or poly_pipeline_y ;
pipeline_cr <= line_pipeline_cr or rect_pipeline_cr or poly_pipeline_cr ;
pipeline_cg <= line_pipeline_cg or rect_pipeline_cg or poly_pipeline_cg ;
pipeline_cb <= line_pipeline_cb or rect_pipeline_cb or poly_pipeline_cb ;
pipeline_u <= ((rect_pipeline_u or poly_pipeline_u) and textureWindow_AND_X) or textureWindow_OR_X;
pipeline_v <= ((rect_pipeline_v or poly_pipeline_v) and textureWindow_AND_Y) or textureWindow_OR_Y;
pipeline_u11 <= (poly_pipeline_u11 and textureWindow_AND_X) or textureWindow_OR_X;
pipeline_v11 <= (poly_pipeline_v11 and textureWindow_AND_Y) or textureWindow_OR_Y;
pipeline_textPalNew <= rect_textPalNew or poly_textPalNew;
pipeline_textPalX <= rect_textPalX or poly_textPalX ;
pipeline_textPalY <= rect_textPalY or poly_textPalY ;
igpu_pixelpipeline : entity work.gpu_pixelpipeline
port map
(
clk2x => clk2x,
clk2xIndex => clk2xIndex,
ce => ce,
reset => softreset or SS_reset,
noTexture => noTexture,
render24 => render24,
drawSlow => drawSlow,
oldGPU => oldGPU,
drawMode_in => drawMode,
DrawPixelsMask_in => GPUSTAT_DrawPixelsMask,
SetMask_in => GPUSTAT_SetMask,
clearCacheTexture => pipeline_clearCacheTexture,
clearCachePalette => pipeline_clearCachePalette,
fifoOut_idle => fifoOut_idle,
pipeline_busy => pipeline_busy,
pipeline_stall => pipeline_stall,
pipeline_new => pipeline_new,
pipeline_texture => pipeline_texture,
pipeline_transparent => pipeline_transparent,
pipeline_rawTexture => pipeline_rawTexture,
pipeline_dithering => pipeline_dithering,
pipeline_x => pipeline_x,
pipeline_y => pipeline_y,
pipeline_cr => pipeline_cr,
pipeline_cg => pipeline_cg,
pipeline_cb => pipeline_cb,
pipeline_u => pipeline_u,
pipeline_v => pipeline_v,
pipeline_filter => pipeline_filter,
pipeline_u11 => pipeline_u11,
pipeline_v11 => pipeline_v11,
pipeline_uAcc => pipeline_uAcc,
pipeline_vAcc => pipeline_vAcc,
requestVRAMEnable => pipeline_reqVRAMEnable,
requestVRAMXPos => pipeline_reqVRAMXPos,
requestVRAMYPos => pipeline_reqVRAMYPos,
requestVRAMSize => pipeline_reqVRAMSize,
requestVRAMIdle => reqVRAMIdle,
requestVRAMDone => reqVRAMDone,
vram_DOUT => vram_DOUT,
vram_DOUT_READY => vram_DOUT_READY,
vramLineData => vramLineData,
vramLineData2 => vramLineData2,
textPalInNew => pipeline_textPalNew,
textPalInX => pipeline_textPalX,
textPalInY => pipeline_textPalY,
pixelStall => pixelStall,
pixelColor => pipeline_pixelColor,
pixelColor2 => pipeline_pixelColor2,
pixelAddr => pipeline_pixelAddr,
pixelWrite => pipeline_pixelWrite
);
gdividers: for i in 0 to 5 generate
begin
div_array(i).start <= line_div(i).start or poly_div(i).start;
div_array(i).dividend <= line_div(i).dividend or poly_div(i).dividend;
div_array(i).divisor <= line_div(i).divisor or poly_div(i).divisor;
line_div(i).done <= div_array(i).done;
line_div(i).quotient <= div_array(i).quotient;
line_div(i).remainder <= div_array(i).remainder;
poly_div(i).done <= div_array(i).done;
poly_div(i).quotient <= div_array(i).quotient;
poly_div(i).remainder <= div_array(i).remainder;
idivider : entity work.divider
port map
(
clk => clk2x,
start => div_array(i).start,
done => div_array(i).done,
dividend => div_array(i).dividend,
divisor => div_array(i).divisor,
quotient => div_array(i).quotient,
remainder => div_array(i).remainder
);
end generate;
pixelColor <= cpu2vram_pixelColor or vram2vram_pixelColor or pipeline_pixelColor;
pixelColor2 <= pipeline_pixelColor2;
pixelAddr <= cpu2vram_pixelAddr or vram2vram_pixelAddr or pipeline_pixelAddr ;
pixelWrite <= cpu2vram_pixelWrite or vram2vram_pixelWrite or pipeline_pixelWrite;
-- pixel writing fifo
iSyncFifo_OUT: entity mem.SyncFifoFallThrough
generic map
(
SIZE => 256,
DATAWIDTH => 64 + 17 + 4 + 1, -- 64bit data + 17 bit address + 4bit word enable + 1bit source=pipeline
NEARFULLDISTANCE => 250
)
port map
(
clk => clk2x,
reset => fifoOut_reset,
Din => fifoOut_Din,
Wr => fifoOut_Wr,
Full => open,
NearFull => fifoOut_NearFull,
Dout => fifoOut_Dout,
Rd => fifoOut_Rd,
Empty => fifoOut_Empty
);
iSyncFifo_OUT2: entity mem.SyncFifoFallThrough
generic map
(
SIZE => 256,
DATAWIDTH => 64,
NEARFULLDISTANCE => 250
)
port map
(
clk => clk2x,
reset => fifoOut_reset,
Din => fifoOut2_Din,
Wr => fifoOut_Wr,
Full => open,
NearFull => open,
Dout => fifoOut2_Dout,
Rd => fifoOut_Rd,
Empty => open
);
process (clk2x)
begin
if rising_edge(clk2x) then
fifoOut_Wr_1 <= fifoOut_Wr;
fifoOut_Wr <= '0';
fifoOut_Din <= pixel64source & pixel64wordEna & pixel64Addr & pixel64data;
fifoOut2_Din <= pixel64data2;
if (reset = '1') then
pixel64filled <= '0';
elsif (ce = '1') then
if (vramFill_pixelWrite = '1') then
fifoOut_Wr <= '1';
fifoOut_Din <= '1' & "1111" & std_logic_vector(vramFill_pixelAddr(19 downto 3)) & vramFill_pixelColor & vramFill_pixelColor & vramFill_pixelColor & vramFill_pixelColor;
pixel64filled <= '0';
fifoOut2_Din <= x"0000000000000000";
elsif (pixelWrite = '1') then
pixel64timeout <= 15;
if (pixel64filled = '0' or pixelAddr(19 downto 3) /= unsigned(pixel64Addr)) then
fifoOut_Wr <= pixel64filled;
pixel64Addr <= std_logic_vector(pixelAddr(19 downto 3));
case (pixelAddr(2 downto 1)) is
when "00" => pixel64data(15 downto 0) <= pixelColor; pixel64data2(15 downto 0) <= pixelColor2; pixel64wordEna <= "0001";
when "01" => pixel64data(31 downto 16) <= pixelColor; pixel64data2(31 downto 16) <= pixelColor2; pixel64wordEna <= "0010";
when "10" => pixel64data(47 downto 32) <= pixelColor; pixel64data2(47 downto 32) <= pixelColor2; pixel64wordEna <= "0100";
when "11" => pixel64data(63 downto 48) <= pixelColor; pixel64data2(63 downto 48) <= pixelColor2; pixel64wordEna <= "1000";
when others => null;
end case;
pixel64filled <= '1';
else
case (pixelAddr(2 downto 1)) is
when "00" => pixel64data(15 downto 0) <= pixelColor; pixel64data2(15 downto 0) <= pixelColor2; pixel64wordEna(0) <= '1';
when "01" => pixel64data(31 downto 16) <= pixelColor; pixel64data2(31 downto 16) <= pixelColor2; pixel64wordEna(1) <= '1';
when "10" => pixel64data(47 downto 32) <= pixelColor; pixel64data2(47 downto 32) <= pixelColor2; pixel64wordEna(2) <= '1';
when "11" => pixel64data(63 downto 48) <= pixelColor; pixel64data2(63 downto 48) <= pixelColor2; pixel64wordEna(3) <= '1';
when others => null;
end case;
end if;
pixel64source <= pipeline_pixelWrite;
elsif (pixel64timeout > 0) then
pixel64timeout <= pixel64timeout - 1;
if (pixel64timeout = 1 or pipeline_busy = '0') then
pixel64filled <= '0';
fifoOut_Wr <= '1';
pixel64timeout <= 0;
end if;
end if;
end if;
end if;
end process;
fifoOut_Rd <= '1' when (ce = '1' and vramState = IDLE and (vram_WE = '0' or vram_BUSY = '0') and fifoOut_Empty = '0' and reqVRAMEnable = '0' and vram_pause = '0') else '0';
fifoOut_idle <= '1' when (fifoOut_Empty = '1' and fifoOut_Wr = '0' and fifoOut_Wr_1 = '0' and pixel64filled = '0') else '0';
VRAMIdle <= '1' when (vramState = IDLE and (vram_WE = '0' or vram_BUSY = '0')) else '0';
reqVRAMIdle <= VRAMIdle and (not videoout_reqVRAMEnable) and (not vram_pause);
reqVRAMEnable <= vram2vram_reqVRAMEnable or vram2cpu_reqVRAMEnable or line_reqVRAMEnable or rect_reqVRAMEnable or poly_reqVRAMEnable or pipeline_reqVRAMEnable or videoout_reqVRAMEnable;
reqVRAMXPos <= vram2vram_reqVRAMXPos or vram2cpu_reqVRAMXPos or line_reqVRAMXPos or rect_reqVRAMXPos or poly_reqVRAMXPos or pipeline_reqVRAMXPos or videoout_reqVRAMXPos ;
reqVRAMYPos <= vram2vram_reqVRAMYPos or vram2cpu_reqVRAMYPos or line_reqVRAMYPos or rect_reqVRAMYPos or poly_reqVRAMYPos or pipeline_reqVRAMYPos or videoout_reqVRAMYPos ;
reqVRAMSize <= vram2vram_reqVRAMSize or vram2cpu_reqVRAMSize or line_reqVRAMSize or rect_reqVRAMSize or poly_reqVRAMSize or pipeline_reqVRAMSize or videoout_reqVRAMSize ;
vramLineAddr <= vram2vram_vramLineAddr when vram2vram_vramLineEna else
vram2cpu_vramLineAddr when vram2cpu_vramLineEna else
line_vramLineAddr when line_vramLineEna else
rect_vramLineAddr when rect_vramLineEna else
poly_vramLineAddr when poly_vramLineEna else
(others => '0');
video_frameindex <= "01" & std_logic_vector(frameindex_last) when (interlaced480pHack = '1') else x"0";
-- vram access
process (clk2x)
variable reqVRAMSizeRounded : unsigned(10 downto 0);
begin
if rising_edge(clk2x) then
if (vram_BUSY = '0') then
vram_WE <= '0';
vram_RD <= '0';
end if;
vram_paused <= '0';
if (VRAMIdle = '1' and vram_pause = '1' and vram_WE = '0') then
if (vram_pauseCnt = 3) then
vram_paused <= '1';
else
vram_pauseCnt <= vram_pauseCnt + 1;
end if;
else
vram_pauseCnt <= 0;
end if;
if (videoout_reports.irq_VBLANK = '1' and irq_VBLANK_1 = '0') then
if (frameFastCount > 0 and interlaced480pHack = '1') then
frameClearRequest <= '1';
frameClearYPos <= videoout_out.DisplayOffsetY;
frameClearCnt <= (others => '0');
frameClearPosLow <= frameFirstChangedLine;
frameClearPosHigh <= frameLastChangedLine;
end if;
end if;
if (reset = '1') then
vramState <= IDLE;
reqVRAMDone <= '0';
else
reqVRAMDone <= '0';
case (vramState) is
when IDLE =>
if ((ce = '1' or (videoout_reqVRAMEnable = '1' and savestate_busy = '0')) and (vram_WE = '0' or vram_BUSY = '0') and vram_pause = '0') then
if (reqVRAMEnable = '1') then
reqVRAMStore <= (not pipeline_reqVRAMEnable) and (not videoout_reqVRAMEnable);
reqVRAMSizeRounded := reqVRAMSize;
if (reqVRAMSize(1 downto 0) /= "00") then -- round up read size to full 4*16bit
reqVRAMSizeRounded(10 downto 2) := reqVRAMSizeRounded(10 downto 2) + 1;
end if;
if (reqVRAMXPos(1 downto 0) /= "00" and ((to_integer(reqVRAMXPos(1 downto 0)) + to_integer(reqVRAMSize) > 4))) then
reqVRAMSizeRounded(10 downto 2) := reqVRAMSizeRounded(10 downto 2) + 1;
end if;
if (reqVRAMSizeRounded > 1024) then reqVRAMSizeRounded := to_unsigned(1024, 11); end if;
vramState <= READVRAM;
vram_ADDR <= x"00" & std_logic_vector(reqVRAMYPos) & std_logic_vector(reqVRAMXPos(9 downto 2)) & "000";
if (videoout_reqVRAMEnable = '1' and videoout_reqRAMMirror = '1') then
vram_ADDR(27 downto 20) <= x"04";
end if;
reqVRAMtwice <= '0';
reqVRAMStore2 <= '0';
if (render24 = '1' and (line_reqVRAMEnable = '1' or rect_reqVRAMEnable = '1' or poly_reqVRAMEnable = '1')) then
vramState <= READSECOND;
reqVRAMStore2 <= '1';
reqVRAMtwice <= '1';
vram_ADDR(27 downto 20) <= x"04";
end if;
vram_RD <= '1';
reqVRAMaddr <= reqVRAMXPos(9 downto 2);
reqVRAMaddr2 <= reqVRAMXPos(9 downto 2);
if (reqVRAMSizeRounded > 512) then
vram_BURSTCNT <= x"80";
reqVRAMremain <= x"80" - 1;
reqVRAMremain2 <= x"80" - 1;
reqVRAMnext <= resize((reqVRAMSizeRounded - 512) / 4, 8);
else
vram_BURSTCNT <= std_logic_vector(reqVRAMSizeRounded(9 downto 2));
reqVRAMremain <= reqVRAMSizeRounded(9 downto 2) - 1;
reqVRAMremain2 <= reqVRAMSizeRounded(9 downto 2) - 1;
reqVRAMnext <= (others => '0');
end if;
reqVRAMwrap <= (others => '0');
if (vram2vram_reqVRAMEnable = '1' or vram2cpu_reqVRAMEnable = '1') then
if (reqVRAMXPos + reqVRAMSizeRounded > 1024) then
reqVRAMwrap <= resize(((reqVRAMXPos + reqVRAMSizeRounded) - 1024) / 4, 8);
end if;
end if;
elsif (fifoOut_Empty = '0') then
if (render24 = '1' or interlaced480pHack = '1') then
vramState <= WRITESECOND;
end if;
vram_WE <= '1';
vram_ADDR <= x"00" & fifoOut_Dout(80 downto 64) & "000";
vram_BE <= fifoOut_Dout(84) & fifoOut_Dout(84) & fifoOut_Dout(83) & fifoOut_Dout(83) & fifoOut_Dout(82) & fifoOut_Dout(82) & fifoOut_Dout(81) & fifoOut_Dout(81);
vram_DIN <= fifoOut_Dout(63 downto 0);
vram_BURSTCNT <= x"01";
frameVramType <= fifoOut_Dout(85);
fifoOut2_Dout_1 <= fifoOut2_Dout;
if (interlacedDrawing = '1' and interlaced480pHack = '1' and videoout_reports.activeLineLSB = fifoOut_Dout(72) and fifoOut_Dout(85) = '1') then
vram_WE <= '0';
end if;
elsif (frameClearRequest = '1' and SS_Idle = '1') then
vramState <= CLEARLINESTART;
end if;
end if;
when WRITESECOND =>
if (vram_BUSY = '0') then
vramState <= IDLE;
vram_WE <= '1';
if (render24 = '1') then
vram_ADDR(27 downto 20) <= x"04";
vram_DIN <= fifoOut2_Dout_1;
elsif (interlaced480pHack = '1') then
vram_ADDR(27 downto 20) <= "000001" & std_logic_vector(frameindex_current);
end if;
end if;
when READSECOND =>
if (vram_DOUT_READY = '1') then
reqVRAMaddr2 <= reqVRAMaddr2 + 1;
if (reqVRAMremain2 > 0) then
reqVRAMremain2 <= reqVRAMremain2 - 1;
else
vramState <= READVRAM;
reqVRAMStore2 <= '0';
vram_RD <= '1';
vram_ADDR(27 downto 20) <= x"00";
end if;
end if;
when READVRAM =>
if (vram_DOUT_READY = '1') then
reqVRAMaddr <= reqVRAMaddr + 1;
if (reqVRAMremain > 0) then
reqVRAMremain <= reqVRAMremain - 1;
else
if (reqVRAMtwice = '1') then
vramState <= READSECOND;
reqVRAMStore2 <= '1';
vram_ADDR(27 downto 20) <= x"04";
end if;
if (reqVRAMnext > 0) then
vram_ADDR(10) <= '1';
vram_RD <= '1';
vram_BURSTCNT <= std_logic_vector(reqVRAMnext);
reqVRAMnext <= (others => '0');
reqVRAMremain <= (reqVRAMnext - 1);
reqVRAMremain2 <= (reqVRAMnext - 1);
elsif (reqVRAMwrap > 0) then
vram_ADDR(10 downto 0) <= (others => '0');
vram_RD <= '1';
vram_BURSTCNT <= std_logic_vector(reqVRAMwrap);
reqVRAMwrap <= (others => '0');
reqVRAMaddr <= (others => '0');
reqVRAMremain <= (reqVRAMwrap - 1);
reqVRAMremain2 <= (reqVRAMwrap - 1);
if (reqVRAMwrap > 128) then
vram_BURSTCNT <= x"80";
reqVRAMremain <= x"80" - 1;
reqVRAMremain2 <= x"80" - 1;
reqVRAMnext <= reqVRAMwrap - 128;
end if;
else
vramState <= IDLE;
reqVRAMDone <= '1';
end if;
end if;
end if;
when CLEARLINESTART =>
vramState <= IDLE;
frameClearCnt <= frameClearCnt + 1;
frameClearXPos <= videoout_out.DisplayOffsetX(9 downto 2) & "00";
if (frameClearCnt = videoout_out.DisplayHeightReal) then
frameClearRequest <= '0';
elsif (frameClearCnt < frameClearPosLow or frameClearCnt > frameClearPosHigh) then
vramState <= CLEARLINE;
else
frameClearYPos <= frameClearYPos + 1;
end if;
when CLEARLINE =>
if (frameClearXPos > videoout_out.DisplayWidthReal + 3) then
vramState <= IDLE;
frameClearYPos <= frameClearYPos + 1;
elsif (vram_BUSY = '0') then
vram_WE <= '1';
vram_ADDR <= "000001" & std_logic_vector(frameindex_current) & std_logic_vector(frameClearYPos) & std_logic_vector(frameClearXPos(9 downto 2)) & "000";
vram_BE <= x"FF";
vram_DIN <= (others => '0');
vram_BURSTCNT <= x"01";
frameClearXPos <= frameClearXPos + 4;
end if;
end case;
end if;
end if;
end process;
ilineram: entity mem.dpram_dif
generic map
(
addr_width_a => 8,
data_width_a => 64,
addr_width_b => 10,
data_width_b => 16
)
port map
(
clock_a => clk2x,
address_a => std_logic_vector(reqVRAMaddr),
data_a => vram_DOUT,
wren_a => (vram_DOUT_READY and reqVRAMStore and (not reqVRAMStore2)),
clock_b => clk2x,
address_b => std_logic_vector(vramLineAddr),
data_b => x"0000",
wren_b => '0',
q_b => vramLineData
);
ilineram2: entity mem.dpram_dif
generic map
(
addr_width_a => 8,
data_width_a => 64,
addr_width_b => 10,
data_width_b => 16
)
port map
(
clock_a => clk2x,
address_a => std_logic_vector(reqVRAMaddr2),
data_a => vram_DOUT,
wren_a => (vram_DOUT_READY and reqVRAMStore2),
clock_b => clk2x,
address_b => std_logic_vector(vramLineAddr),
data_b => x"0000",
wren_b => '0',
q_b => vramLineData2
);
--##############################################################
--############################### video out
--##############################################################
videoout_settings.GPUSTAT_VerRes <= GPUSTAT_VerRes;
videoout_settings.GPUSTAT_PalVideoMode <= GPUSTAT_PalVideoMode;
videoout_settings.GPUSTAT_VertInterlace <= GPUSTAT_VertInterlace;
videoout_settings.GPUSTAT_HorRes2 <= GPUSTAT_HorRes2;
videoout_settings.GPUSTAT_HorRes1 <= GPUSTAT_HorRes1;
videoout_settings.GPUSTAT_ColorDepth24 <= GPUSTAT_ColorDepth24;
videoout_settings.GPUSTAT_DisplayDisable <= GPUSTAT_DisplayDisable;
videoout_settings.vramRange <= vramRange;
videoout_settings.hDisplayRange <= hDisplayRange;
videoout_settings.vDisplayRange <= vDisplayRange;
videoout_settings.pal60 <= pal60;
videoout_settings.syncInterlace <= syncInterlace;
videoout_settings.rotate180 <= rotate180;
videoout_settings.fixedVBlank <= fixedVBlank;
videoout_settings.vCrop <= vCrop;
videoout_settings.hCrop <= hCrop;
videoout_settings.dither24 <= dither24;
videoout_settings.render24 <= render24;
videoout_ss_in.interlacedDisplayField <= ss_timing_in(4)(19);
videoout_ss_in.nextHCount <= ss_timing_in(4)(11 downto 0);
videoout_ss_in.vpos <= ss_timing_in(3)(24 downto 16);
videoout_ss_in.vdisp <= ss_timing_in(4)(29 downto 21);
videoout_ss_in.inVsync <= ss_timing_in(4)(17);
videoout_ss_in.activeLineLSB <= ss_timing_in(4)(20);
videoout_ss_in.GPUSTAT_InterlaceField <= ss_gpu_in(1)(13);
videoout_ss_in.GPUSTAT_DrawingOddline <= ss_gpu_in(1)(31);
igpu_videoout : entity work.gpu_videoout
port map
(
clk1x => clk1x,
clk2x => clk2x,
clkvid => clkvid,
ce => ce,
reset => reset,
softReset => softReset,
allowunpause => allowunpause,
savestate_pause => savestate_busy,
system_paused => system_paused,
videoout_settings => videoout_settings,
videoout_reports => videoout_reports,
videoout_on => videoout_on,
syncVideoOut => syncVideoOut,
debugmodeOn => debugmodeOn,
fpscountOn => fpscountOn,
fpscountBCD => fpscountBCD,
Gun1CrosshairOn => Gun1CrosshairOn,
Gun1X => Gun1X,
Gun1Y_scanlines => Gun1Y_scanlines,
Gun1offscreen => Gun1offscreen,
Gun1IRQ10 => Gun1IRQ10,
Gun2CrosshairOn => Gun2CrosshairOn,
Gun2X => Gun2X,
Gun2Y_scanlines => Gun2Y_scanlines,
Gun2offscreen => Gun2offscreen,
Gun2IRQ10 => Gun2IRQ10,
cdSlow => cdSlow,
errorOn => errorOn,
errorEna => errorEna,
errorCode => errorCode,
LBAOn => LBAOn,
LBAdisplay => LBAdisplay,
requestVRAMEnable => videoout_reqVRAMEnable,
requestVRAMMirror => videoout_reqRAMMirror,
requestVRAMXPos => videoout_reqVRAMXPos,
requestVRAMYPos => videoout_reqVRAMYPos,
requestVRAMSize => videoout_reqVRAMSize,
requestVRAMIdle => VRAMIdle and (not vram_pause),
requestVRAMDone => reqVRAMDone,
vram_DOUT => vram_DOUT,
vram_DOUT_READY => vram_DOUT_READY,
videoout_out => videoout_out,
videoout_ss_in => videoout_ss_in,
videoout_ss_out => videoout_ss_out
);
video_hsync <= videoout_out.hsync;
video_vsync <= videoout_out.vsync;
video_hblank <= videoout_out.hblank;
video_vblank <= videoout_out.vblank;
video_DisplayOffsetX <= videoout_out.DisplayOffsetX;
video_DisplayOffsetY <= videoout_out.DisplayOffsetY;
video_DisplayWidth <= videoout_out.DisplayWidthReal;
video_DisplayHeight <= videoout_out.DisplayHeightReal;
video_ce <= videoout_out.ce;
video_interlace <= videoout_out.interlace;
video_r <= videoout_out.r;
video_g <= videoout_out.g;
video_b <= videoout_out.b;
video_isPal <= videoout_out.isPal;
video_hResMode <= videoout_out.hResMode;
dotclock <= videoout_reports.dotclock;
--##############################################################
--############################### savestates
--##############################################################
process (clk1x)
begin
if (rising_edge(clk1x)) then
if (SS_reset = '1') then
for i in 0 to 7 loop
ss_gpu_in(i) <= (others => '0');
ss_timing_in(i) <= (others => '0');
end loop;
ss_timing_in(0) <= x"0003FC10"; -- vDisplayRange
ss_timing_in(1) <= x"00C60260"; -- hDisplayRange
else
if (SS_wren_GPU = '1') then
ss_gpu_in(to_integer(SS_Adr)) <= SS_DataWrite;
end if;
if (SS_wren_Timing = '1') then
ss_timing_in(to_integer(SS_Adr)) <= SS_DataWrite;
end if;
end if;
SS_Idle <= '0';
if (proc_idle = '1' and fifoIn_Empty = '1' and fifoOut_Empty = '1' and vramState = IDLE and pipeline_busy = '0' and fifoOut_Wr = '0' and pixelWrite = '0') then
SS_Idle <= '1';
end if;
if (SS_rden_GPU = '1') then
SS_DataRead_GPU <= ss_gpu_out(to_integer(SS_Adr));
end if;
if (SS_rden_Timing = '1') then
SS_DataRead_Timing <= ss_timing_out(to_integer(SS_Adr));
end if;
end if;
end process;
-- synthesis translate_off
goutput : if 1 = 1 generate
signal gpuFifoCount : integer := 0;
signal gpuDMAFifoCount : integer := 0;
signal gpuCPUFifoCount : integer := 0;
begin
process
file outfile : text;
variable f_status : FILE_OPEN_STATUS;
variable line_out : line;
begin
file_open(f_status, outfile, "R:\\debug_gpufifo_sim.txt", write_mode);
file_close(outfile);
file_open(f_status, outfile, "R:\\debug_gpufifo_sim.txt", append_mode);
while (true) loop
wait until rising_edge(clk1x);
if (DMA_GPU_writeEna = '1' and gpuFifoCount >= 0 and gpuDMAFifoCount >= 0) then
write(line_out, string'("Fifo: "));
write(line_out, to_hstring(DMA_GPU_write));
writeline(outfile, line_out);
gpuFifoCount <= gpuFifoCount + 1;
gpuDMAFifoCount <= gpuDMAFifoCount + 1;
end if;
if (bus_write = '1' and bus_addr = 0 and gpuCPUFifoCount >= 0) then
write(line_out, string'("Fifo: "));
write(line_out, to_hstring(bus_dataWrite));
writeline(outfile, line_out);
gpuFifoCount <= gpuFifoCount + 1;
gpuCPUFifoCount <= gpuCPUFifoCount + 1;
end if;
end loop;
end process;
end generate goutput;
goutput2 : if 1 = 1 generate
signal pixelCount : integer := 0;
begin
process
file outfile : text;
variable f_status : FILE_OPEN_STATUS;
variable line_out : line;
begin
file_open(f_status, outfile, "R:\\debug_pixel_sim.txt", write_mode);
file_close(outfile);
file_open(f_status, outfile, "R:\\debug_pixel_sim.txt", append_mode);
while (true) loop
wait until rising_edge(clk2x);
if (pixelWrite = '1' and pixelCount >= 0) then
write(line_out, to_integer(pixelAddr(10 downto 1)));
write(line_out, string'(" "));
write(line_out, to_integer(pixelAddr(19 downto 11)));
write(line_out, string'(" "));
write(line_out, to_integer(unsigned(pixelColor)));
writeline(outfile, line_out);
pixelCount <= pixelCount + 1;
if (render24 = '1') then
write(line_out, to_integer(pixelAddr(10 downto 1)));
write(line_out, string'(" "));
write(line_out, to_integer(pixelAddr(19 downto 11)));
write(line_out, string'(" "));
write(line_out, to_integer(unsigned(pixelColor(4 downto 0)) & unsigned(pixelColor2(2 downto 0))));
writeline(outfile, line_out);
write(line_out, to_integer(pixelAddr(10 downto 1)));
write(line_out, string'(" "));
write(line_out, to_integer(pixelAddr(19 downto 11)));
write(line_out, string'(" "));
write(line_out, to_integer(unsigned(pixelColor(9 downto 5)) & unsigned(pixelColor2(5 downto 3))));
writeline(outfile, line_out);
write(line_out, to_integer(pixelAddr(10 downto 1)));
write(line_out, string'(" "));
write(line_out, to_integer(pixelAddr(19 downto 11)));
write(line_out, string'(" "));
write(line_out, to_integer(unsigned(pixelColor(14 downto 10)) & unsigned(pixelColor2(8 downto 6))));
writeline(outfile, line_out);
pixelCount <= pixelCount + 4;
end if;
end if;
end loop;
end process;
end generate goutput2;
-- synthesis translate_on
end architecture;