diff --git a/GBA.qsf b/GBA.qsf index 688d53a..97d267f 100644 --- a/GBA.qsf +++ b/GBA.qsf @@ -13,7 +13,7 @@ set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top -set_global_assignment -name LAST_QUARTUS_VERSION "17.0.2 Standard Edition" +set_global_assignment -name LAST_QUARTUS_VERSION "17.0.0 Lite Edition" set_global_assignment -name GENERATE_RBF_FILE ON set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files @@ -49,7 +49,8 @@ set_global_assignment -name PERIPHERY_TO_CORE_PLACEMENT_AND_ROUTING_OPTIMIZATION set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON set_global_assignment -name ALM_REGISTER_PACKING_EFFORT LOW set_global_assignment -name PLACEMENT_EFFORT_MULTIPLIER 1.0 -set_global_assignment -name SEED 2 +set_global_assignment -name SEED 3 +set_global_assignment -name VERILOG_MACRO "USE_FB=1" source sys/sys.tcl source sys/sys_analog.tcl diff --git a/GBA.sv b/GBA.sv index c0c7811..71ffc9b 100644 --- a/GBA.sv +++ b/GBA.sv @@ -65,6 +65,7 @@ module emu // b[0]: osd button output [1:0] BUTTONS, + input CLK_AUDIO, // 24.576 MHz output [15:0] AUDIO_L, output [15:0] AUDIO_R, output AUDIO_S, // 1 - signed audio samples, 0 - unsigned @@ -121,7 +122,22 @@ module emu input [6:0] USER_IN, output [6:0] USER_OUT, - input OSD_STATUS + input OSD_STATUS, + + // Use framebuffer from DDRAM (USE_FB=1 in qsf) + // FB_FORMAT: + // [2:0] : 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp + // [3] : 0=16bits 565 1=16bits 1555 + // [4] : 0=RGB 1=BGR (for 16/24/32 modes) + // + // stride is modulo 256 of bytes + output FB_EN, + output [4:0] FB_FORMAT, + output [11:0] FB_WIDTH, + output [11:0] FB_HEIGHT, + output [31:0] FB_BASE, + input FB_VBL, + input FB_LL ); assign ADC_BUS = 'Z; @@ -141,6 +157,12 @@ assign VIDEO_ARY = status[1] ? 8'd9 : 8'd2; assign {SD_SCK, SD_MOSI, SD_CS} = 'Z; +assign FB_EN = status[21] || status[22]; +assign FB_FORMAT = 5'b00110; +assign FB_WIDTH = 12'd480; +assign FB_HEIGHT = 12'd320; + + /////////////////////// CLOCK/RESET /////////////////////////////////// wire pll_locked; @@ -163,7 +185,7 @@ wire reset = RESET | buttons[1] | status[0] | cart_download | bk_loading | hold_ // 0 1 2 3 4 5 6 // 0123456789012345678901234567890123456789012345678901234567890123 // 0123456789ABCDEFGHIJKLMNOPQRSTUV0123456789ABCDEFGHIJKLMNOPQRSTUV -// XXXXXXXXX XXXXXXXXXXXXXXXXXXXXX +// XXXXXXXXXXXXXXXXXXX XXXXXXXXXXXX `include "build_id.v" parameter CONF_STR = { @@ -183,8 +205,9 @@ parameter CONF_STR = { "O1,Aspect Ratio,3:2,16:9;", "O24,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%,CRT 75%;", "OOQ,Modify Colors,Off,GBA 2.2,GBA 1.6,NDS 1.6,VBA 1.4,75%,50%,25%;", - "OJ,Flickerblend,Off,On;", + "O9A,Flickerblend,Off,Blend,30Hz;", "OK,Spritelimit,Off,On;", + "OLM,2XResolution,Off,Background,Sprites,Both;", "O78,Stereo Mix,None,25%,50%,100%;", "-;", "OEF,Storage,Auto,SDRAM,DDR3;", @@ -445,8 +468,10 @@ gba .memory_remap(memory_remap_quirk), .save_state(ss_save), .load_state(ss_load), - .interframe_blend(status[19]), + .interframe_blend(status[10:9]), .maxpixels(status[20]), + .hdmode2x_bg(status[21]), + .hdmode2x_obj(status[22]), .shade_mode(shadercolors), .specialmodule(gpio_quirk), .solar_in(status[31:29]), @@ -516,6 +541,14 @@ gba .pixel_out_data(pixel_data), // RGB data for framebuffer .pixel_out_we(pixel_we), // new pixel for framebuffer + .largeimg_out_base(FB_BASE), + .largeimg_out_addr(fb_addr), + .largeimg_out_data(fb_din), + .largeimg_out_req(fb_req), + .largeimg_out_done(fb_ack), + .largeimg_newframe(FB_VBL), + .largeimg_singlebuf(FB_LL), + .sound_out_left(AUDIO_L), .sound_out_right(AUDIO_R) ); @@ -633,6 +666,11 @@ wire [31:0] sdr_sdram_dout1, sdr_sdram_dout2, sdr_bus_dout; wire [15:0] sdr_bram_din; wire sdr_sdram_ack, sdr_bus_ack, sdr_bram_ack; +wire [27:2] fb_addr; +wire [63:0] fb_din; +wire fb_req; +wire fb_ack; + sdram sdram ( .*, @@ -708,7 +746,13 @@ ddram ddram .ch4_dout(ss_dout), .ch4_req(ss_req), .ch4_rnw(ss_rnw), - .ch4_ready(ss_ack) + .ch4_ready(ss_ack), + + .ch5_addr({fb_addr, 1'b0}), + .ch5_din(fb_din), + .ch5_req(fb_req), + .ch5_ready(fb_ack) + ); wire [127:0] time_din_h = {32'd0, time_din, "RT"}; @@ -718,20 +762,51 @@ wire bram_ack = sdram_en ? sdr_bram_ack : ddr_bram_ack; assign sd_buff_din = extra_data_addr ? (time_din_h[{sd_buff_addr[2:0], 4'b0000} +: 16]) : bram_buff_out; wire [15:0] bram_buff_out; -SyncRamDual #(16,8) bram +altsyncram altsyncram_component ( - .clk(clk_sys), - - .addr_a(bram_addr), - .we_a(~bk_loading & bram_ack), - .datain_a(bram_din), - .dataout_a(bram_dout), - - .addr_b(sd_buff_addr), - .we_b(sd_buff_wr && ~extra_data_addr), - .datain_b(sd_buff_dout), - .dataout_b(bram_buff_out) + .address_a (bram_addr), + .address_b (sd_buff_addr), + .clock0 (clk_sys), + .clock1 (clk_sys), + .data_a (bram_din), + .data_b (sd_buff_dout), + .wren_a (~bk_loading & bram_ack), + .wren_b (sd_buff_wr && ~extra_data_addr), + .q_a (bram_dout), + .q_b (bram_buff_out), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .rden_a (1'b1), + .rden_b (1'b1) ); +defparam + altsyncram_component.address_reg_b = "CLOCK1", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_input_b = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.clock_enable_output_b = "BYPASS", + altsyncram_component.indata_reg_b = "CLOCK1", + altsyncram_component.intended_device_family = "Cyclone V", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 256, + altsyncram_component.numwords_b = 256, + altsyncram_component.operation_mode = "BIDIR_DUAL_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_a = "UNREGISTERED", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", + altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ", + altsyncram_component.widthad_a = 8, + altsyncram_component.widthad_b = 8, + altsyncram_component.width_a = 16, + altsyncram_component.width_b = 16, + altsyncram_component.width_byteena_a = 1, + altsyncram_component.width_byteena_b = 1, + altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1"; reg [7:0] bram_addr; reg bram_tx_start; diff --git a/README.md b/README.md index 585f464..5e5cd12 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ As the BIOS is already replaced at boot time, you must save this settings and ha - Savestates - FastForward - speed up game by factor 2-4 - CPU Turbomode - give games additional CPU power -- Flickerblend - turn on for games like F-Zero, Mario Kart or NES Classics to prevent flickering effects +- Flickerblend - set to blend or 30Hz mode for games like F-Zero, Mario Kart or NES Classics to prevent flickering effects - Spritelimit - turn on to prevent wrong sprites for games that rely on the limit (opt-in) - Cheats - Color optimizations: shader colors and desaturate @@ -40,6 +40,7 @@ As the BIOS is already replaced at boot time, you must save this settings and ha - Solar Sensor: Set brightness in OSD - Gyro: use analog stick (map stick in Mister Main before) - RTC: automatically used, works with RTC board or internet connection +- 2x Resolution: game is rendered at 480x320 instead of 240x160 pixels # Savestates Core provides 4 slots to save the state. The first slot gets saved to disk and automatically loaded (but not applied) @@ -62,6 +63,14 @@ Currently there are only few games known that produce glitches without sprite pi - Gunstar Super Heroes - Famicon Mini Series Vol21 - Vol30 +# 2x Resolution +Improved rendering resolution for: +- Affine background: "Mode7" games, typically racing games like Mario Kart +- Affine sprites: games that scale or rotate sprites +This rendering is experimental and can cause glitches, as not all game behavior can be supported. +Those glitches can not be fixed without gamespecific hacks and therefore will not be fixed. +Please don't add bugs in such cases. + # Cartridge Hardware supported games - RTC: Pokemon Sapphire+Ruby+Emerald, Boktai 1+2+3, Sennen Kazoku, Rockman EXE 4.5 - Solar Sensor: Boktai 1+2+3 diff --git a/rtl/ddram.sv b/rtl/ddram.sv index a6faf68..e8f35dc 100644 --- a/rtl/ddram.sv +++ b/rtl/ddram.sv @@ -60,7 +60,13 @@ module ddram input [63:0] ch4_din, input ch4_req, input ch4_rnw, - output ch4_ready + output ch4_ready, + + // framebuffer + input [27:1] ch5_addr, + input [63:0] ch5_din, + input ch5_req, + output ch5_ready ); reg [7:0] ram_burst; @@ -71,7 +77,7 @@ reg ram_read = 0; reg ram_write = 0; reg [7:0] ram_be; -reg [4:1] ready; +reg [5:1] ready; assign DDRAM_BURSTCNT = ram_burst; assign DDRAM_BE = ram_read ? 8'hFF : ram_be; @@ -88,18 +94,19 @@ assign ch1_ready = ready[1]; assign ch2_ready = ready[2]; assign ch3_ready = ready[3]; assign ch4_ready = ready[4]; +assign ch5_ready = ready[5]; reg [63:0] next_q[2:1]; reg [27:1] cache_addr[2:1]; reg [1:0] state = 0; reg [2:1] cached = 0; reg [2:0] ch = 0; -reg [4:1] ch_rq; +reg [5:1] ch_rq; always @(posedge DDRAM_CLK) begin - ch_rq <= ch_rq | {ch4_req, ch3_req, ch2_req, ch1_req}; + ch_rq <= ch_rq | {ch5_req, ch4_req, ch3_req, ch2_req, ch1_req}; ready <= 0; if(!DDRAM_BUSY) begin @@ -107,7 +114,7 @@ always @(posedge DDRAM_CLK) begin ram_read <= 0; case(state) - 0: if(ch_rq[1]) begin + 0: if(ch_rq[1] || ch1_req) begin ch_rq[1] <= 0; ch <= 1; ram_data <= {4{ch1_din}}; @@ -141,7 +148,7 @@ always @(posedge DDRAM_CLK) begin state <= 1; end end - else if(ch_rq[2]) begin + else if(ch_rq[2] || ch2_req) begin ch_rq[2] <= 0; ch <= 2; ram_data <= {2{ch2_din}}; @@ -175,7 +182,7 @@ always @(posedge DDRAM_CLK) begin state <= 1; end end - else if(ch_rq[3]) begin + else if(ch_rq[3] || ch3_req) begin ch_rq[3] <= 0; ch <= 3; ram_address <= {ch3_addr, 2'b00}; @@ -192,7 +199,7 @@ always @(posedge DDRAM_CLK) begin state <= 1; end end - else if(ch_rq[4]) begin + else if(ch_rq[4] || ch4_req) begin ch_rq[4] <= 0; ch <= 4; ram_data <= ch4_din; @@ -207,6 +214,16 @@ always @(posedge DDRAM_CLK) begin ram_read <= 1; state <= 1; end + end + else if(ch_rq[5] || ch5_req) begin + ch_rq[5] <= 0; + ch <= 5; + ram_data <= ch5_din; + ram_be <= 8'hFF; + ram_address <= ch5_addr; + ram_write <= 1; + ram_burst <= 1; + ready[5] <= 1; end 1: if(DDRAM_DOUT_READY) begin diff --git a/rtl/gba.qip b/rtl/gba.qip index aa0cbc7..2b9d8f5 100644 --- a/rtl/gba.qip +++ b/rtl/gba.qip @@ -7,6 +7,7 @@ set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_dma_mo set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_drawer_merge.vhd ] set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_drawer_mode0.vhd ] set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_drawer_mode2.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_drawer_mode2_2x.vhd ] set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_drawer_mode345.vhd ] set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_drawer_obj.vhd ] set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_gpu.vhd ] diff --git a/rtl/gba_drawer_mode2.vhd b/rtl/gba_drawer_mode2.vhd index 94cab2d..69176cf 100644 --- a/rtl/gba_drawer_mode2.vhd +++ b/rtl/gba_drawer_mode2.vhd @@ -3,6 +3,12 @@ use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity gba_drawer_mode2 is + generic + ( + DXYBITS : integer := 16; + ACCURACYBITS : integer := 28; + PIXELCOUNT : integer := 240 + ); port ( clk100 : in std_logic; @@ -17,16 +23,16 @@ entity gba_drawer_mode2 is wrapping : in std_logic; mosaic : in std_logic; Mosaic_H_Size : in unsigned(3 downto 0); - refX : in signed(27 downto 0); - refY : in signed(27 downto 0); + refX : in signed; + refY : in signed; refX_mosaic : in signed(27 downto 0); refY_mosaic : in signed(27 downto 0); - dx : in signed(15 downto 0); - dy : in signed(15 downto 0); + dx : in signed(DXYBITS - 1 downto 0); + dy : in signed(DXYBITS - 1 downto 0); pixel_we : out std_logic := '0'; pixeldata : buffer std_logic_vector(15 downto 0) := (others => '0'); - pixel_x : out integer range 0 to 239; + pixel_x : out integer range 0 to (PIXELCOUNT - 1); PALETTE_Drawer_addr : out integer range 0 to 127; PALETTE_Drawer_data : in std_logic_vector(31 downto 0); @@ -72,14 +78,14 @@ architecture arch of gba_drawer_mode2 is signal mapbaseaddr : integer; signal tilebaseaddr : integer; - signal realX : signed(27 downto 0); - signal realY : signed(27 downto 0); + signal realX : signed(ACCURACYBITS - 1 downto 0); + signal realY : signed(ACCURACYBITS - 1 downto 0); signal xxx : signed(19 downto 0); signal yyy : signed(19 downto 0); signal xxx_pre : signed(19 downto 0); signal yyy_pre : signed(19 downto 0); - signal x_cnt : integer range 0 to 239; + signal x_cnt : integer range 0 to (PIXELCOUNT - 1); signal scroll_mod : integer range 128 to 1024; signal tileinfo : std_logic_vector(7 downto 0) := (others => '0'); @@ -98,8 +104,8 @@ begin VRAM_Drawer_addr <= to_integer(VRAM_byteaddr(15 downto 2)); PALETTE_Drawer_addr <= to_integer(unsigned(PALETTE_byteaddr(8 downto 2))); - xxx_pre <= realX(27 downto 8); - yyy_pre <= realY(27 downto 8); + xxx_pre <= realX(realX'left downto realX'left - 19); + yyy_pre <= realY(realY'left downto realY'left - 19); -- vramfetch process (clk100) @@ -112,12 +118,14 @@ begin when IDLE => if (line_trigger = '1') then - if (mosaic = '1') then - realX <= refX_mosaic; - realY <= refY_mosaic; + realX <= (others => '0'); + realY <= (others => '0'); + if (mosaic = '1' and unsigned(Mosaic_H_Size) > 0) then + realX(realX'left downto realX'left - refX_mosaic'length + 1) <= refX_mosaic; + realY(realY'left downto realY'left - refY_mosaic'length + 1) <= refY_mosaic; else - realX <= refX; - realY <= refY; + realX(realX'left downto realX'left - refX'length + 1) <= refX; + realY(realY'left downto realY'left - refY'length + 1) <= refY; end if; elsif (drawline = '1') then busy <= '1'; @@ -150,7 +158,7 @@ begin xxx <= xxx_pre; yyy <= yyy_pre; if (xxx_pre < 0 or yyy_pre < 0 or xxx_pre >= scroll_mod or yyy_pre >= scroll_mod) then - if (x_cnt < 239) then + if (x_cnt < (PIXELCOUNT - 1)) then vramfetch <= CALCADDR1; x_cnt <= x_cnt + 1; else @@ -234,7 +242,7 @@ begin when FETCHDONE => if (palettefetch = IDLE) then - if (x_cnt < 239) then + if (x_cnt < (PIXELCOUNT - 1)) then vramfetch <= CALCADDR1; x_cnt <= x_cnt + 1; else diff --git a/rtl/gba_drawer_obj.vhd b/rtl/gba_drawer_obj.vhd index 082eca7..5795bc5 100644 --- a/rtl/gba_drawer_obj.vhd +++ b/rtl/gba_drawer_obj.vhd @@ -3,6 +3,12 @@ use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity gba_drawer_obj is + generic + ( + RESMULT : integer := 1; + PIXELCOUNT : integer := 240; + YMULTOFFSET : integer := 0 + ); port ( clk100 : in std_logic; @@ -26,7 +32,7 @@ entity gba_drawer_obj is pixeldata_color : out std_logic_vector(15 downto 0) := (others => '0'); pixel_we_settings : out std_logic := '0'; pixeldata_settings : out std_logic_vector(2 downto 0) := (others => '0'); - pixel_x : out integer range 0 to 239; + pixel_x : out integer range 0 to (PIXELCOUNT - 1); pixel_objwnd : out std_logic := '0'; OAMRAM_Drawer_addr : buffer integer range 0 to 255; @@ -43,6 +49,8 @@ end entity; architecture arch of gba_drawer_obj is + constant RESMULTACCDIV : integer := 256 * RESMULT; + -- Atr0 constant OAM_Y_HI : integer := 7; constant OAM_Y_LO : integer := 0; @@ -158,13 +166,16 @@ architecture arch of gba_drawer_obj is signal x : integer range 0 to 255; signal realX : integer range -8388608 to 8388607; signal realY : integer range -8388608 to 8388607; - signal target : integer range 0 to 239; + signal target : integer range 0 to (PIXELCOUNT - 1); signal second_pix : std_logic; signal skippixel : std_logic; signal issue_pixel : std_logic; signal pixeladdr_x : unsigned(14 downto 0) := (others => '0'); signal pixeladdr_x_noaff : unsigned(14 downto 0); + signal rescounter : integer range 0 to RESMULT - 1; + signal rescounter_current: integer range 0 to RESMULT - 1; + signal pixeladdr_x_aff0 : unsigned(14 downto 0); signal pixeladdr_x_aff1 : unsigned(14 downto 0); signal pixeladdr_x_aff2 : unsigned(14 downto 0); @@ -182,17 +193,17 @@ architecture arch of gba_drawer_obj is objwnd : std_logic; end record; - type t_pixelarray is array(0 to 239) of tpixel; + type t_pixelarray is array(0 to (PIXELCOUNT - 1)) of tpixel; signal pixelarray : t_pixelarray; signal Pixel_wait : tpixel; signal Pixel_readback : tpixel; signal Pixel_merge : tpixel; - signal target_start : integer range 0 to 239; - signal target_eval : integer range 0 to 239; - signal target_wait : integer range 0 to 239; - signal target_merge : integer range 0 to 239; + signal target_start : integer range 0 to (PIXELCOUNT - 1); + signal target_eval : integer range 0 to (PIXELCOUNT - 1); + signal target_wait : integer range 0 to (PIXELCOUNT - 1); + signal target_merge : integer range 0 to (PIXELCOUNT - 1); signal enable_start : std_logic; signal enable_eval : std_logic; @@ -367,6 +378,7 @@ begin case (PIXELGen) is when WAITOAM => + rescounter <= 0; if (OAMFetch = DONE) then PIXELGen <= CALCMOSAIC; Pixel_data0 <= OAM_data0; @@ -505,8 +517,12 @@ begin end if; -- affine - realX <= pixeladdr_pre_a0 - pixeladdr_pre_a1 - pixeladdr_pre_a2 + pixeladdr_pre_a3; - realY <= pixeladdr_pre_a4 - pixeladdr_pre_a5 - pixeladdr_pre_a6 + pixeladdr_pre_a7; + realX <= (pixeladdr_pre_a0 - pixeladdr_pre_a1 - pixeladdr_pre_a2 + pixeladdr_pre_a3) * resmult; + realY <= (pixeladdr_pre_a4 - pixeladdr_pre_a5 - pixeladdr_pre_a6 + pixeladdr_pre_a7) * resmult; + if (YMULTOFFSET = 1) then + realX <= ((pixeladdr_pre_a0 - pixeladdr_pre_a1 - pixeladdr_pre_a2 + pixeladdr_pre_a3) * resmult) + dmx; + realY <= ((pixeladdr_pre_a4 - pixeladdr_pre_a5 - pixeladdr_pre_a6 + pixeladdr_pre_a7) * resmult) + dmy; + end if; -- non affine if (Pixel_data1(OAM_VFLIP) = '1') then @@ -529,7 +545,13 @@ begin elsif (x >= fieldX) then PIXELGen <= WAITOAM; else - x <= x + 1; + rescounter_current <= rescounter; + if (rescounter = RESMULT - 1) then + x <= x + 1; + rescounter <= 0; + else + rescounter <= rescounter + 1; + end if; if (x + posX > 239) then -- end of line already reached PIXELGen <= WAITOAM; else @@ -552,16 +574,16 @@ begin end if; if (Pixel_data0(OAM_AFFINE) = '1') then - if (realX < 0 or (realX / 256) >= sizeX or realY < 0 or (realY / 256) >= sizeY) then + if (realX < 0 or (realX / RESMULTACCDIV) >= sizeX or realY < 0 or (realY / RESMULTACCDIV) >= sizeY) then skippixel <= '1'; end if; -- synthesis translate_off - if (realX >= 0 and (realX / 256) < sizeX and realY >= 0 and (realY / 256) < sizeY) then + if (realX >= 0 and (realX / RESMULTACCDIV) < sizeX and realY >= 0 and (realY / RESMULTACCDIV) < sizeY) then -- synthesis translate_on - xxx := realX / 256; - yyy := realY / 256; + xxx := realX / RESMULTACCDIV; + yyy := realY / RESMULTACCDIV; if (xxx mod 2 = 1) then second_pix <= '1'; else second_pix <= '0'; end if; pixeladdr_x_aff0 <= to_unsigned(((yyy mod 8) * x_size), 15); @@ -650,7 +672,7 @@ begin -- zero cycle - address for vram is written in this cycle enable_start <= issue_pixel; - target_start <= target; + target_start <= (target * RESMULT) + rescounter_current; readaddr_mux <= pixeladdr_x(1 downto 0); second_pix_start <= second_pix; diff --git a/rtl/gba_gpu.vhd b/rtl/gba_gpu.vhd index f0010c3..b27d9da 100644 --- a/rtl/gba_gpu.vhd +++ b/rtl/gba_gpu.vhd @@ -23,17 +23,24 @@ entity gba_gpu is gb_bus : inout proc_bus_gb_type := ((others => 'Z'), (others => 'Z'), (others => 'Z'), 'Z', 'Z', 'Z', "ZZ", "ZZZZ", 'Z'); lockspeed : in std_logic; - interframe_blend : in std_logic; + interframe_blend : in std_logic_vector(1 downto 0); maxpixels : in std_logic; shade_mode : in std_logic_vector(2 downto 0); + hdmode2x_bg : in std_logic; + hdmode2x_obj : in std_logic; bitmapdrawmode : out std_logic; pixel_out_x : out integer range 0 to 239; + pixel_out_2x : out integer range 0 to 479; pixel_out_y : out integer range 0 to 159; pixel_out_addr : out integer range 0 to 38399; pixel_out_data : out std_logic_vector(17 downto 0); pixel_out_we : out std_logic := '0'; + + pixel2_out_x : out integer range 0 to 479; + pixel2_out_data : out std_logic_vector(17 downto 0); + pixel2_out_we : out std_logic := '0'; new_cycles : in unsigned(7 downto 0); new_cycles_valid : in std_logic; @@ -86,11 +93,15 @@ architecture arch of gba_gpu is signal pixelpos : integer range 0 to 511; signal pixel_x : integer range 0 to 239; + signal pixel_2x : integer range 0 to 479; signal pixel_y : integer range 0 to 159; signal pixel_addr : integer range 0 to 38399; signal pixel_data : std_logic_vector(14 downto 0); signal pixel_we : std_logic := '0'; - + + signal pixel2_2x : integer range 0 to 479; + signal pixel2_data : std_logic_vector(14 downto 0); + signal pixel2_we : std_logic := '0'; signal vram_block_mode : std_logic; begin @@ -147,15 +158,22 @@ begin lockspeed => lockspeed, interframe_blend => interframe_blend, maxpixels => maxpixels, + hdmode2x_bg => hdmode2x_bg , + hdmode2x_obj => hdmode2x_obj, bitmapdrawmode => bitmapdrawmode, vram_block_mode => vram_block_mode, - pixel_out_x => pixel_x, + pixel_out_x => pixel_x, + pixel_out_2x => pixel_2x, pixel_out_y => pixel_y, pixel_out_addr => pixel_addr, pixel_out_data => pixel_data, pixel_out_we => pixel_we, + + pixel2_out_x => pixel2_2x, + pixel2_out_data => pixel2_data, + pixel2_out_we => pixel2_we, linecounter => linecounter_drawer, drawline => drawline, @@ -190,8 +208,8 @@ begin PALETTE_OAM_datain => PALETTE_OAM_datain, PALETTE_OAM_dataout => PALETTE_OAM_dataout, PALETTE_OAM_we => PALETTE_OAM_we - ); - + ); + igba_gpu_colorshade : entity work.gba_gpu_colorshade port map ( @@ -200,16 +218,40 @@ begin shade_mode => shade_mode, pixel_in_x => pixel_x, + pixel_in_2x => pixel_2x, pixel_in_y => pixel_y, pixel_in_addr => pixel_addr, pixel_in_data => pixel_data, pixel_in_we => pixel_we, pixel_out_x => pixel_out_x, + pixel_out_2x => pixel_out_2x, pixel_out_y => pixel_out_y, pixel_out_addr => pixel_out_addr, pixel_out_data => pixel_out_data, pixel_out_we => pixel_out_we + ); + + igba_gpu_colorshade2 : entity work.gba_gpu_colorshade + port map + ( + clk100 => clk100, + + shade_mode => shade_mode, + + pixel_in_x => 0, + pixel_in_2x => pixel2_2x, + pixel_in_y => 0, + pixel_in_addr => 0, + pixel_in_data => pixel2_data, + pixel_in_we => pixel2_we, + + pixel_out_x => open, + pixel_out_2x => pixel2_out_x, + pixel_out_y => open, + pixel_out_addr => open, + pixel_out_data => pixel2_out_data, + pixel_out_we => pixel2_out_we ); end architecture; diff --git a/rtl/gba_gpu_colorshade.vhd b/rtl/gba_gpu_colorshade.vhd index f6f4549..8b9fafd 100644 --- a/rtl/gba_gpu_colorshade.vhd +++ b/rtl/gba_gpu_colorshade.vhd @@ -10,12 +10,14 @@ entity gba_gpu_colorshade is shade_mode : in std_logic_vector(2 downto 0); -- 0 = off, 1..4 modes pixel_in_x : in integer range 0 to 239; + pixel_in_2x : in integer range 0 to 479; pixel_in_y : in integer range 0 to 159; pixel_in_addr : in integer range 0 to 38399; pixel_in_data : in std_logic_vector(14 downto 0); pixel_in_we : in std_logic := '0'; pixel_out_x : out integer range 0 to 239; + pixel_out_2x : out integer range 0 to 479; pixel_out_y : out integer range 0 to 159; pixel_out_addr : out integer range 0 to 38399; pixel_out_data : out std_logic_vector(17 downto 0); @@ -156,6 +158,7 @@ architecture arch of gba_gpu_colorshade is -- shade processing signal pixel_1_x : integer range 0 to 239; + signal pixel_1_2x : integer range 0 to 479; signal pixel_1_y : integer range 0 to 159; signal pixel_1_addr : integer range 0 to 38399; signal pixel_1_data : std_logic_vector(14 downto 0); @@ -165,6 +168,7 @@ architecture arch of gba_gpu_colorshade is signal color_linear_3 : integer range 0 to 1023; signal pixel_2_x : integer range 0 to 239; + signal pixel_2_2x : integer range 0 to 479; signal pixel_2_y : integer range 0 to 159; signal pixel_2_addr : integer range 0 to 38399; signal pixel_2_we : std_logic := '0'; @@ -172,6 +176,7 @@ architecture arch of gba_gpu_colorshade is signal shade_precalc : t_shade_precalc := (others => (others => 0)); signal pixel_3_x : integer range 0 to 239; + signal pixel_3_2x : integer range 0 to 479; signal pixel_3_y : integer range 0 to 159; signal pixel_3_addr : integer range 0 to 38399; signal pixel_3_we : std_logic := '0'; @@ -179,6 +184,7 @@ architecture arch of gba_gpu_colorshade is signal shade_linear : t_shade_linear; signal pixel_4_x : integer range 0 to 239; + signal pixel_4_2x : integer range 0 to 479; signal pixel_4_y : integer range 0 to 159; signal pixel_4_addr : integer range 0 to 38399; signal pixel_4_we : std_logic := '0'; @@ -186,6 +192,7 @@ architecture arch of gba_gpu_colorshade is signal clip_linear : t_clip_linear; signal pixel_5_x : integer range 0 to 239; + signal pixel_5_2x : integer range 0 to 479; signal pixel_5_y : integer range 0 to 159; signal pixel_5_addr : integer range 0 to 38399; signal pixel_5_we : std_logic := '0'; @@ -262,6 +269,7 @@ begin -- clock 1 - lookup linear color pixel_1_x <= pixel_in_x; + pixel_1_2x <= pixel_in_2x; pixel_1_y <= pixel_in_y; pixel_1_addr <= pixel_in_addr; pixel_1_we <= pixel_in_we; @@ -273,6 +281,7 @@ begin -- clock 2 - precalc shades pixel_2_x <= pixel_1_x; + pixel_2_2x <= pixel_1_2x; pixel_2_y <= pixel_1_y; pixel_2_addr <= pixel_1_addr; pixel_2_we <= pixel_1_we; @@ -303,6 +312,7 @@ begin -- clock 3 - apply shading pixel_3_x <= pixel_2_x; + pixel_3_2x <= pixel_2_2x; pixel_3_y <= pixel_2_y; pixel_3_addr <= pixel_2_addr; pixel_3_we <= pixel_2_we; @@ -313,6 +323,7 @@ begin -- clock 4 - clip pixel_4_x <= pixel_3_x; + pixel_4_2x <= pixel_3_2x; pixel_4_y <= pixel_3_y; pixel_4_addr <= pixel_3_addr; pixel_4_we <= pixel_3_we; @@ -329,6 +340,7 @@ begin -- clock 5 - lookup upper 3 bits of color pixel_5_x <= pixel_4_x; + pixel_5_2x <= pixel_4_2x; pixel_5_y <= pixel_4_y; pixel_5_addr <= pixel_4_addr; pixel_5_we <= pixel_4_we; @@ -355,6 +367,7 @@ begin -- clock 6 - lookup lower 3 bits of color pixel_out_x <= pixel_5_x; + pixel_out_2x <= pixel_5_2x; pixel_out_y <= pixel_5_y; pixel_out_addr <= pixel_5_addr; pixel_out_we <= pixel_5_we; @@ -372,6 +385,7 @@ begin else pixel_out_x <= pixel_in_x; + pixel_out_2x <= pixel_in_2x; pixel_out_y <= pixel_in_y; pixel_out_addr <= pixel_in_addr; pixel_out_we <= pixel_in_we; diff --git a/rtl/gba_gpu_drawer.vhd b/rtl/gba_gpu_drawer.vhd index 74c6bb2..4990473 100644 --- a/rtl/gba_gpu_drawer.vhd +++ b/rtl/gba_gpu_drawer.vhd @@ -19,17 +19,24 @@ entity gba_gpu_drawer is gb_bus : inout proc_bus_gb_type := ((others => 'Z'), (others => 'Z'), (others => 'Z'), 'Z', 'Z', 'Z', "ZZ", "ZZZZ", 'Z'); lockspeed : in std_logic; - interframe_blend : in std_logic; + interframe_blend : in std_logic_vector(1 downto 0); maxpixels : in std_logic; + hdmode2x_bg : in std_logic; + hdmode2x_obj : in std_logic; bitmapdrawmode : out std_logic; vram_block_mode : out std_logic; pixel_out_x : out integer range 0 to 239; + pixel_out_2x : out integer range 0 to 479; pixel_out_y : out integer range 0 to 159; pixel_out_addr : out integer range 0 to 38399; pixel_out_data : out std_logic_vector(14 downto 0); pixel_out_we : out std_logic := '0'; + + pixel2_out_x : out integer range 0 to 479; + pixel2_out_data : out std_logic_vector(14 downto 0); + pixel2_out_we : out std_logic := '0'; linecounter : in unsigned(7 downto 0); pixelpos : in integer range 0 to 511; @@ -221,10 +228,18 @@ architecture arch of gba_gpu_drawer is signal enables_wndout : std_logic_vector(5 downto 0); -- ram wiring - signal OAMRAM_Drawer_addr : integer range 0 to 255; - signal OAMRAM_Drawer_data : std_logic_vector(31 downto 0); - signal PALETTE_OAM_Drawer_addr : integer range 0 to 127; - signal PALETTE_OAM_Drawer_data : std_logic_vector(31 downto 0); + signal OAMRAM_Drawer_addr : integer range 0 to 255; + signal OAMRAM_Drawer_addr_hd0 : integer range 0 to 255; + signal OAMRAM_Drawer_addr_hd1 : integer range 0 to 255; + signal OAMRAM_Drawer_data : std_logic_vector(31 downto 0); + signal OAMRAM_Drawer_data_hd0 : std_logic_vector(31 downto 0); + signal OAMRAM_Drawer_data_hd1 : std_logic_vector(31 downto 0); + signal PALETTE_OAM_Drawer_addr : integer range 0 to 127; + signal PALETTE_OAM_Drawer_addr_hd0 : integer range 0 to 127; + signal PALETTE_OAM_Drawer_addr_hd1 : integer range 0 to 127; + signal PALETTE_OAM_Drawer_data : std_logic_vector(31 downto 0); + signal PALETTE_OAM_Drawer_data_hd0 : std_logic_vector(31 downto 0); + signal PALETTE_OAM_Drawer_data_hd1 : std_logic_vector(31 downto 0); signal PALETTE_BG_Drawer_addr : integer range 0 to 127; signal PALETTE_BG_Drawer_addr0 : integer range 0 to 127; @@ -249,6 +264,7 @@ architecture arch of gba_gpu_drawer is signal VRAM_Drawer_cnt_Hi : std_logic := '0'; -- background multiplexing + signal line_trigger_1 : std_logic := '0'; signal drawline_1 : std_logic := '0'; signal hblank_trigger_1 : std_logic := '0'; @@ -257,109 +273,204 @@ architecture arch of gba_gpu_drawer is signal drawline_mode0_2 : std_logic; signal drawline_mode0_3 : std_logic; signal drawline_mode2_2 : std_logic; + signal drawline_mode2_2_hd0 : std_logic; + signal drawline_mode2_2_hd1 : std_logic; signal drawline_mode2_3 : std_logic; + signal drawline_mode2_3_hd0 : std_logic; + signal drawline_mode2_3_hd1 : std_logic; signal drawline_mode345 : std_logic; signal drawline_obj : std_logic; + signal drawline_obj_hd0 : std_logic; + signal drawline_obj_hd1 : std_logic; - signal pixel_we_mode0_0 : std_logic; - signal pixel_we_mode0_1 : std_logic; - signal pixel_we_mode0_2 : std_logic; - signal pixel_we_mode0_3 : std_logic; - signal pixel_we_mode2_2 : std_logic; - signal pixel_we_mode2_3 : std_logic; - signal pixel_we_mode345 : std_logic; - signal pixel_we_modeobj_color : std_logic; - signal pixel_we_modeobj_settings : std_logic; - signal pixel_we_bg0 : std_logic; - signal pixel_we_bg1 : std_logic; - signal pixel_we_bg2 : std_logic; - signal pixel_we_bg3 : std_logic; - signal pixel_we_obj_color : std_logic; - signal pixel_we_obj_settings : std_logic; + signal pixel_we_mode0_0 : std_logic; + signal pixel_we_mode0_1 : std_logic; + signal pixel_we_mode0_2 : std_logic; + signal pixel_we_mode0_3 : std_logic; + signal pixel_we_mode2_2 : std_logic; + signal pixel_we_mode2_2_hd0 : std_logic; + signal pixel_we_mode2_2_hd1 : std_logic; + signal pixel_we_mode2_3 : std_logic; + signal pixel_we_mode2_3_hd0 : std_logic; + signal pixel_we_mode2_3_hd1 : std_logic; + signal pixel_we_mode345 : std_logic; + signal pixel_we_modeobj_color : std_logic; + signal pixel_we_modeobj_color_hd0 : std_logic; + signal pixel_we_modeobj_color_hd1 : std_logic; + signal pixel_we_modeobj_settings : std_logic; + signal pixel_we_modeobj_settings_hd0 : std_logic; + signal pixel_we_modeobj_settings_hd1 : std_logic; + signal pixel_we_bg0 : std_logic; + signal pixel_we_bg1 : std_logic; + signal pixel_we_bg2 : std_logic; + signal pixel_we_bg3 : std_logic; + signal pixel_we_obj_color : std_logic; + signal pixel_we_obj_color_hd0 : std_logic; + signal pixel_we_obj_color_hd1 : std_logic; + signal pixel_we_obj_settings : std_logic; + signal pixel_we_obj_settings_hd0 : std_logic; + signal pixel_we_obj_settings_hd1 : std_logic; - signal pixeldata_mode0_0 : std_logic_vector(15 downto 0); - signal pixeldata_mode0_1 : std_logic_vector(15 downto 0); - signal pixeldata_mode0_2 : std_logic_vector(15 downto 0); - signal pixeldata_mode0_3 : std_logic_vector(15 downto 0); - signal pixeldata_mode2_2 : std_logic_vector(15 downto 0); - signal pixeldata_mode2_3 : std_logic_vector(15 downto 0); - signal pixeldata_mode345 : std_logic_vector(15 downto 0); - signal pixeldata_modeobj_color : std_logic_vector(15 downto 0); - signal pixeldata_modeobj_settings : std_logic_vector( 2 downto 0); - signal pixeldata_bg0 : std_logic_vector(15 downto 0); - signal pixeldata_bg1 : std_logic_vector(15 downto 0); - signal pixeldata_bg2 : std_logic_vector(15 downto 0); - signal pixeldata_bg3 : std_logic_vector(15 downto 0); - signal pixeldata_obj : std_logic_vector(18 downto 0); - signal pixeldata_obj_color : std_logic_vector(15 downto 0); - signal pixeldata_obj_settings : std_logic_vector( 2 downto 0); + signal pixeldata_mode0_0 : std_logic_vector(15 downto 0); + signal pixeldata_mode0_1 : std_logic_vector(15 downto 0); + signal pixeldata_mode0_2 : std_logic_vector(15 downto 0); + signal pixeldata_mode0_3 : std_logic_vector(15 downto 0); + signal pixeldata_mode2_2 : std_logic_vector(15 downto 0); + signal pixeldata_mode2_2_hd0 : std_logic_vector(15 downto 0); + signal pixeldata_mode2_2_hd1 : std_logic_vector(15 downto 0); + signal pixeldata_mode2_3 : std_logic_vector(15 downto 0); + signal pixeldata_mode2_3_hd0 : std_logic_vector(15 downto 0); + signal pixeldata_mode2_3_hd1 : std_logic_vector(15 downto 0); + signal pixeldata_mode345 : std_logic_vector(15 downto 0); + signal pixeldata_modeobj_color : std_logic_vector(15 downto 0); + signal pixeldata_modeobj_color_hd0 : std_logic_vector(15 downto 0); + signal pixeldata_modeobj_color_hd1 : std_logic_vector(15 downto 0); + signal pixeldata_modeobj_settings : std_logic_vector( 2 downto 0); + signal pixeldata_modeobj_settings_hd0 : std_logic_vector( 2 downto 0); + signal pixeldata_modeobj_settings_hd1 : std_logic_vector( 2 downto 0); + signal pixeldata_bg0 : std_logic_vector(15 downto 0); + signal pixeldata_bg1 : std_logic_vector(15 downto 0); + signal pixeldata_bg2 : std_logic_vector(15 downto 0); + signal pixeldata_bg3 : std_logic_vector(15 downto 0); + signal pixeldata_obj : std_logic_vector(18 downto 0); + signal pixeldata_obj_color : std_logic_vector(15 downto 0); + signal pixeldata_obj_color_hd0 : std_logic_vector(15 downto 0); + signal pixeldata_obj_color_hd1 : std_logic_vector(15 downto 0); + signal pixeldata_obj_settings : std_logic_vector( 2 downto 0); + signal pixeldata_obj_settings_hd0 : std_logic_vector( 2 downto 0); + signal pixeldata_obj_settings_hd1 : std_logic_vector( 2 downto 0); - signal pixel_x_mode0_0 : integer range 0 to 239; - signal pixel_x_mode0_1 : integer range 0 to 239; - signal pixel_x_mode0_2 : integer range 0 to 239; - signal pixel_x_mode0_3 : integer range 0 to 239; - signal pixel_x_mode2_2 : integer range 0 to 239; - signal pixel_x_mode2_3 : integer range 0 to 239; - signal pixel_x_mode345 : integer range 0 to 239; - signal pixel_x_modeobj : integer range 0 to 239; - signal pixel_x_bg0 : integer range 0 to 239; - signal pixel_x_bg1 : integer range 0 to 239; - signal pixel_x_bg2 : integer range 0 to 239; - signal pixel_x_bg3 : integer range 0 to 239; - signal pixel_x_obj : integer range 0 to 239; + signal pixel_x_mode0_0 : integer range 0 to 239; + signal pixel_x_mode0_1 : integer range 0 to 239; + signal pixel_x_mode0_2 : integer range 0 to 239; + signal pixel_x_mode0_3 : integer range 0 to 239; + signal pixel_x_mode2_2 : integer range 0 to 239; + signal pixel_x_mode2_2_hd0 : integer range 0 to 479; + signal pixel_x_mode2_2_hd1 : integer range 0 to 479; + signal pixel_x_mode2_3 : integer range 0 to 239; + signal pixel_x_mode2_3_hd0 : integer range 0 to 479; + signal pixel_x_mode2_3_hd1 : integer range 0 to 479; + signal pixel_x_mode345 : integer range 0 to 239; + signal pixel_x_modeobj : integer range 0 to 239; + signal pixel_x_modeobj_hd0 : integer range 0 to 479; + signal pixel_x_modeobj_hd1 : integer range 0 to 479; + signal pixel_x_bg0 : integer range 0 to 239; + signal pixel_x_bg1 : integer range 0 to 239; + signal pixel_x_bg2 : integer range 0 to 239; + signal pixel_x_bg3 : integer range 0 to 239; + signal pixel_x_obj : integer range 0 to 239; + signal pixel_x_obj_hd0 : integer range 0 to 479; + signal pixel_x_obj_hd1 : integer range 0 to 479; - signal pixel_objwnd : std_logic; + signal pixel_objwnd : std_logic; + signal pixel_objwnd_hd0 : std_logic; + signal pixel_objwnd_hd1 : std_logic; + + signal pixel_x_bg2_hd0 : integer range 0 to 479; + signal pixeldata_bg2_hd0 : std_logic_vector(15 downto 0); + signal pixel_we_bg2_hd0 : std_logic; + + signal pixel_x_bg2_hd1 : integer range 0 to 479; + signal pixeldata_bg2_hd1 : std_logic_vector(15 downto 0); + signal pixel_we_bg2_hd1 : std_logic; + + signal pixel_x_bg3_hd0 : integer range 0 to 479; + signal pixeldata_bg3_hd0 : std_logic_vector(15 downto 0); + signal pixel_we_bg3_hd0 : std_logic; + + signal pixel_x_bg3_hd1 : integer range 0 to 479; + signal pixeldata_bg3_hd1 : std_logic_vector(15 downto 0); + signal pixel_we_bg3_hd1 : std_logic; - signal PALETTE_Drawer_addr_mode0_0 : integer range 0 to 127; - signal PALETTE_Drawer_addr_mode0_1 : integer range 0 to 127; - signal PALETTE_Drawer_addr_mode0_2 : integer range 0 to 127; - signal PALETTE_Drawer_addr_mode0_3 : integer range 0 to 127; - signal PALETTE_Drawer_addr_mode2_2 : integer range 0 to 127; - signal PALETTE_Drawer_addr_mode2_3 : integer range 0 to 127; - signal PALETTE_Drawer_addr_mode345 : integer range 0 to 127; + signal PALETTE_Drawer_addr_mode0_0 : integer range 0 to 127; + signal PALETTE_Drawer_addr_mode0_1 : integer range 0 to 127; + signal PALETTE_Drawer_addr_mode0_2 : integer range 0 to 127; + signal PALETTE_Drawer_addr_mode0_3 : integer range 0 to 127; + signal PALETTE_Drawer_addr_mode2_2 : integer range 0 to 127; + signal PALETTE_Drawer_addr_mode2_2_hd0 : integer range 0 to 127; + signal PALETTE_Drawer_addr_mode2_2_hd1 : integer range 0 to 127; + signal PALETTE_Drawer_addr_mode2_3 : integer range 0 to 127; + signal PALETTE_Drawer_addr_mode2_3_hd0 : integer range 0 to 127; + signal PALETTE_Drawer_addr_mode2_3_hd1 : integer range 0 to 127; + signal PALETTE_Drawer_addr_mode345 : integer range 0 to 127; - signal VRAM_Drawer_addr_mode0_0 : integer range 0 to 16383; - signal VRAM_Drawer_addr_mode0_1 : integer range 0 to 16383; - signal VRAM_Drawer_addr_mode0_2 : integer range 0 to 16383; - signal VRAM_Drawer_addr_mode0_3 : integer range 0 to 16383; - signal VRAM_Drawer_addr_mode2_2 : integer range 0 to 16383; - signal VRAM_Drawer_addr_mode2_3 : integer range 0 to 16383; - signal VRAM_Drawer_addr_345_Lo : integer range 0 to 16383; - signal VRAM_Drawer_addr_345_Hi : integer range 0 to 8191; - signal VRAM_Drawer_addrobj : integer range 0 to 8191; + signal VRAM_Drawer_addr_mode0_0 : integer range 0 to 16383; + signal VRAM_Drawer_addr_mode0_1 : integer range 0 to 16383; + signal VRAM_Drawer_addr_mode0_2 : integer range 0 to 16383; + signal VRAM_Drawer_addr_mode0_3 : integer range 0 to 16383; + signal VRAM_Drawer_addr_mode2_2 : integer range 0 to 16383; + signal VRAM_Drawer_addr_mode2_2_hd0 : integer range 0 to 16383; + signal VRAM_Drawer_addr_mode2_2_hd1 : integer range 0 to 16383; + signal VRAM_Drawer_addr_mode2_3 : integer range 0 to 16383; + signal VRAM_Drawer_addr_mode2_3_hd0 : integer range 0 to 16383; + signal VRAM_Drawer_addr_mode2_3_hd1 : integer range 0 to 16383; + signal VRAM_Drawer_addr_345_Lo : integer range 0 to 16383; + signal VRAM_Drawer_addr_345_Hi : integer range 0 to 8191; + signal VRAM_Drawer_addrobj : integer range 0 to 8191; + signal VRAM_Drawer_addrobj_hd0 : integer range 0 to 8191; + signal VRAM_Drawer_addrobj_hd1 : integer range 0 to 8191; - signal busy_mode0_0 : std_logic; - signal busy_mode0_1 : std_logic; - signal busy_mode0_2 : std_logic; - signal busy_mode0_3 : std_logic; - signal busy_mode2_2 : std_logic; - signal busy_mode2_3 : std_logic; - signal busy_mode345 : std_logic; - signal busy_modeobj : std_logic; + signal busy_mode0_0 : std_logic; + signal busy_mode0_1 : std_logic; + signal busy_mode0_2 : std_logic; + signal busy_mode0_3 : std_logic; + signal busy_mode2_2 : std_logic; + signal busy_mode2_2_hd0 : std_logic; + signal busy_mode2_2_hd1 : std_logic; + signal busy_mode2_3 : std_logic; + signal busy_mode2_3_hd0 : std_logic; + signal busy_mode2_3_hd1 : std_logic; + signal busy_mode345 : std_logic; + signal busy_modeobj : std_logic; + signal busy_modeobj_hd0 : std_logic; + signal busy_modeobj_hd1 : std_logic; signal draw_allmod : std_logic_vector(7 downto 0); signal busy_allmod : std_logic_vector(7 downto 0); -- linebuffers - signal clear_enable : std_logic := '0'; - signal clear_addr : integer range 0 to 239; - signal clear_trigger : std_logic := '0'; - signal clear_trigger_1 : std_logic := '0'; - - signal linecounter_int : integer range 0 to 159; - signal linebuffer_addr : integer range 0 to 239; - signal linebuffer_addr_1 : integer range 0 to 239; + signal clear_enable : std_logic := '0'; + signal clear_addr : integer range 0 to 479; + signal clear_trigger : std_logic := '0'; + signal clear_trigger_1 : std_logic := '0'; + + signal linecounter_int : integer range 0 to 159; + signal linebuffer_addr : integer range 0 to 239; + signal linebuffer_addr_1 : integer range 0 to 239; + signal pixelmult : std_logic := '0'; + signal linebuffer_addr_hd : integer range 0 to 479; + + signal linebuffer_bg0_data : std_logic_vector(15 downto 0); + signal linebuffer_bg1_data : std_logic_vector(15 downto 0); + signal linebuffer_bg2_data : std_logic_vector(15 downto 0); + signal linebuffer_bg3_data : std_logic_vector(15 downto 0); + signal linebuffer_obj_data : std_logic_vector(18 downto 0); + signal linebuffer_obj_color : std_logic_vector(15 downto 0); + signal linebuffer_obj_setting : std_logic_vector( 2 downto 0); + + signal linebuffer_objwindow : std_logic_vector(0 to 239) := (others => '0'); + signal linebuffer_objwindow_hd0 : std_logic_vector(0 to 479) := (others => '0'); + signal linebuffer_objwindow_hd1 : std_logic_vector(0 to 479) := (others => '0'); + + signal linebuffer_bg2_data_hd0 : std_logic_vector(15 downto 0); + signal linebuffer_bg2_data_hd1 : std_logic_vector(15 downto 0); + signal linebuffer_bg3_data_hd0 : std_logic_vector(15 downto 0); + signal linebuffer_bg3_data_hd1 : std_logic_vector(15 downto 0); - signal linebuffer_bg0_data : std_logic_vector(15 downto 0); - signal linebuffer_bg1_data : std_logic_vector(15 downto 0); - signal linebuffer_bg2_data : std_logic_vector(15 downto 0); - signal linebuffer_bg3_data : std_logic_vector(15 downto 0); - signal linebuffer_obj_data : std_logic_vector(18 downto 0); - signal linebuffer_obj_color : std_logic_vector(15 downto 0); - signal linebuffer_obj_setting : std_logic_vector( 2 downto 0); - - signal linebuffer_objwindow : std_logic_vector(0 to 239) := (others => '0'); - + signal linebuffer_obj_data_hd0 : std_logic_vector(18 downto 0); + signal linebuffer_obj_color_hd0 : std_logic_vector(15 downto 0); + signal linebuffer_obj_setting_hd0 : std_logic_vector( 2 downto 0); + signal linebuffer_obj_data_hd1 : std_logic_vector(18 downto 0); + signal linebuffer_obj_color_hd1 : std_logic_vector(15 downto 0); + signal linebuffer_obj_setting_hd1 : std_logic_vector( 2 downto 0); + + signal merge_in_bg2 : std_logic_vector(15 downto 0); + signal merge_in_bg3 : std_logic_vector(15 downto 0); + signal merge_in_obj : std_logic_vector(18 downto 0); + signal merge2_in_bg2 : std_logic_vector(15 downto 0); + signal merge2_in_bg3 : std_logic_vector(15 downto 0); + signal merge2_in_obj : std_logic_vector(18 downto 0); + -- merge_pixel signal pixeldata_back_next : std_logic_vector(15 downto 0) := (others => '0'); signal pixeldata_back : std_logic_vector(15 downto 0) := (others => '0'); @@ -369,7 +480,15 @@ architecture arch of gba_gpu_drawer is signal merge_pixel_x : integer range 0 to 239; signal merge_pixel_y : integer range 0 to 159; signal merge_pixel_we : std_logic := '0'; + signal objwindow_merge : std_logic := '0'; + signal objwindow_merge_hd0 : std_logic := '0'; + signal objwindow_merge_hd1 : std_logic := '0'; signal objwindow_merge_in : std_logic := '0'; + signal objwindow_merge2_in : std_logic := '0'; + + signal merge2_pixeldata_out : std_logic_vector(15 downto 0); + signal merge2_pixel_x : integer range 0 to 239; + signal merge2_pixel_we : std_logic := '0'; signal pixel_out_x_1 : integer range 0 to 239; signal pixel_out_y_1 : integer range 0 to 159; @@ -403,6 +522,38 @@ architecture arch of gba_gpu_drawer is signal ref3_x : signed(27 downto 0) := (others => '0'); signal ref3_y : signed(27 downto 0) := (others => '0'); + signal ref2_x_last : signed(27 downto 0) := (others => '0'); + signal ref2_y_last : signed(27 downto 0) := (others => '0'); + signal ref3_x_last : signed(27 downto 0) := (others => '0'); + signal ref3_y_last : signed(27 downto 0) := (others => '0'); + + signal ref2_x_hd0 : signed(28 downto 0) := (others => '0'); + signal ref2_y_hd0 : signed(28 downto 0) := (others => '0'); + signal ref2_x_hd1 : signed(28 downto 0) := (others => '0'); + signal ref2_y_hd1 : signed(28 downto 0) := (others => '0'); + signal ref3_x_hd0 : signed(28 downto 0) := (others => '0'); + signal ref3_y_hd0 : signed(28 downto 0) := (others => '0'); + signal ref3_x_hd1 : signed(28 downto 0) := (others => '0'); + signal ref3_y_hd1 : signed(28 downto 0) := (others => '0'); + + signal dx2_last : signed(15 downto 0) := (others => '0'); + signal dx2_hd0 : signed(16 downto 0) := (others => '0'); + signal dx2_hd1 : signed(16 downto 0) := (others => '0'); + signal dy2_last : signed(15 downto 0) := (others => '0'); + signal dy2_hd0 : signed(16 downto 0) := (others => '0'); + signal dy2_hd1 : signed(16 downto 0) := (others => '0'); + signal dx3_last : signed(15 downto 0) := (others => '0'); + signal dx3_hd0 : signed(16 downto 0) := (others => '0'); + signal dx3_hd1 : signed(16 downto 0) := (others => '0'); + signal dy3_last : signed(15 downto 0) := (others => '0'); + signal dy3_hd0 : signed(16 downto 0) := (others => '0'); + signal dy3_hd1 : signed(16 downto 0) := (others => '0'); + + signal new_dx2 : std_logic := '0'; + signal new_dy2 : std_logic := '0'; + signal new_dx3 : std_logic := '0'; + signal new_dy3 : std_logic := '0'; + signal mosaik_vcnt_bg : integer range 0 to 15 := 0; signal mosaik_vcnt_obj : integer range 0 to 15 := 0; @@ -414,12 +565,14 @@ architecture arch of gba_gpu_drawer is signal mosaic_ref3_x : signed(27 downto 0) := (others => '0'); signal mosaic_ref3_y : signed(27 downto 0) := (others => '0'); - -- framesmoothing buffer + -- interframe_blend options type tPixelArray is array(0 to (240 * 160) - 1) of std_logic_vector(14 downto 0); signal PixelArraySmooth : tPixelArray := (others => (others => '0')); signal pixel_smooth : std_logic_vector(14 downto 0); + signal frameselect : std_logic := '0'; + begin iREG_DISPCNT_BG_Mode : entity work.eProcReg_gba generic map (DISPCNT_BG_Mode ) port map (clk100, gb_bus, BG_Mode , BG_Mode ); @@ -655,6 +808,70 @@ begin OAMRAM_PROC_dataout(((i+1) * 8) - 1 downto (i * 8)) <= ram_dout_single1; OAMRAM_Drawer_data(((i+1) * 8) - 1 downto (i * 8)) <= ram_dout_single2; end generate; + goamram_hd0 : for i in 0 to 3 generate + signal ram_dout_single1 : std_logic_vector(7 downto 0); + signal ram_dout_single2 : std_logic_vector(7 downto 0); + signal ram_din_single : std_logic_vector(7 downto 0); + begin + + ibyteram: entity MEM.SyncRamDualNotPow2 + generic map + ( + DATA_WIDTH => 8, + DATA_COUNT => 256 + ) + port map + ( + clk => clk100, + + addr_a => OAMRAM_PROC_addr, + datain_a => ram_din_single, + dataout_a => open, + we_a => OAMRAM_PROC_we(i), + re_a => '1', + + addr_b => OAMRAM_Drawer_addr_hd0, + datain_b => x"00", + dataout_b => ram_dout_single2, + we_b => '0', + re_b => '1' + ); + + ram_din_single <= OAMRAM_PROC_datain(((i+1) * 8) - 1 downto (i * 8)); + OAMRAM_Drawer_data_hd0(((i+1) * 8) - 1 downto (i * 8)) <= ram_dout_single2; + end generate; + goamram_hd1 : for i in 0 to 3 generate + signal ram_dout_single1 : std_logic_vector(7 downto 0); + signal ram_dout_single2 : std_logic_vector(7 downto 0); + signal ram_din_single : std_logic_vector(7 downto 0); + begin + + ibyteram: entity MEM.SyncRamDualNotPow2 + generic map + ( + DATA_WIDTH => 8, + DATA_COUNT => 256 + ) + port map + ( + clk => clk100, + + addr_a => OAMRAM_PROC_addr, + datain_a => ram_din_single, + dataout_a => open, + we_a => OAMRAM_PROC_we(i), + re_a => '1', + + addr_b => OAMRAM_Drawer_addr_hd1, + datain_b => x"00", + dataout_b => ram_dout_single2, + we_b => '0', + re_b => '1' + ); + + ram_din_single <= OAMRAM_PROC_datain(((i+1) * 8) - 1 downto (i * 8)); + OAMRAM_Drawer_data_hd1(((i+1) * 8) - 1 downto (i * 8)) <= ram_dout_single2; + end generate; gpaletteram_bg : for i in 0 to 3 generate signal ram_dout_single1 : std_logic_vector(7 downto 0); @@ -723,6 +940,70 @@ begin PALETTE_OAM_dataout(((i+1) * 8) - 1 downto (i * 8)) <= ram_dout_single1; PALETTE_OAM_Drawer_data(((i+1) * 8) - 1 downto (i * 8)) <= ram_dout_single2; end generate; + gpaletteram_oam_hd0 : for i in 0 to 3 generate + signal ram_dout_single1 : std_logic_vector(7 downto 0); + signal ram_dout_single2 : std_logic_vector(7 downto 0); + signal ram_din_single : std_logic_vector(7 downto 0); + begin + + ibyteram: entity MEM.SyncRamDualNotPow2 + generic map + ( + DATA_WIDTH => 8, + DATA_COUNT => 128 + ) + port map + ( + clk => clk100, + + addr_a => PALETTE_OAM_addr, + datain_a => ram_din_single, + dataout_a => open, + we_a => PALETTE_OAM_we(i), + re_a => '1', + + addr_b => PALETTE_OAM_Drawer_addr_hd0, + datain_b => x"00", + dataout_b => ram_dout_single2, + we_b => '0', + re_b => '1' + ); + + ram_din_single <= PALETTE_OAM_datain(((i+1) * 8) - 1 downto (i * 8)); + PALETTE_OAM_Drawer_data_hd0(((i+1) * 8) - 1 downto (i * 8)) <= ram_dout_single2; + end generate; + gpaletteram_oam_hd1 : for i in 0 to 3 generate + signal ram_dout_single1 : std_logic_vector(7 downto 0); + signal ram_dout_single2 : std_logic_vector(7 downto 0); + signal ram_din_single : std_logic_vector(7 downto 0); + begin + + ibyteram: entity MEM.SyncRamDualNotPow2 + generic map + ( + DATA_WIDTH => 8, + DATA_COUNT => 128 + ) + port map + ( + clk => clk100, + + addr_a => PALETTE_OAM_addr, + datain_a => ram_din_single, + dataout_a => open, + we_a => PALETTE_OAM_we(i), + re_a => '1', + + addr_b => PALETTE_OAM_Drawer_addr_hd1, + datain_b => x"00", + dataout_b => ram_dout_single2, + we_b => '0', + re_b => '1' + ); + + ram_din_single <= PALETTE_OAM_datain(((i+1) * 8) - 1 downto (i * 8)); + PALETTE_OAM_Drawer_data_hd1(((i+1) * 8) - 1 downto (i * 8)) <= ram_dout_single2; + end generate; igba_drawer_mode0_0 : entity work.gba_drawer_mode0 port map @@ -857,8 +1138,8 @@ begin refY => ref2_y, refX_mosaic => mosaic_ref2_x, refY_mosaic => mosaic_ref2_y, - dx => signed(REG_BG2RotScaleParDX), - dy => signed(REG_BG2RotScaleParDY), + dx => signed(REG_BG2RotScaleParDX(15 downto 0)), + dy => signed(REG_BG2RotScaleParDY(15 downto 0)), pixel_we => pixel_we_mode2_2, pixeldata => pixeldata_mode2_2, pixel_x => pixel_x_mode2_2, @@ -869,6 +1150,76 @@ begin VRAM_Drawer_data => VRAM_Drawer_data_Lo, VRAM_Drawer_valid => VRAM_Drawer_valid_Lo(2) ); + igba_drawer_mode2_2_hd0 : entity work.gba_drawer_mode2 + generic map + ( + DXYBITS => 17, + ACCURACYBITS => 30, + PIXELCOUNT => 480 + ) + port map + ( + clk100 => clk100, + line_trigger => line_trigger_1, + drawline => drawline_mode2_2_hd0, + busy => busy_mode2_2_hd0, + mapbase => unsigned(REG_BG2CNT_Screen_Base_Block), + tilebase => unsigned(REG_BG2CNT_Character_Base_Block), + screensize => unsigned(REG_BG2CNT_Screen_Size), + wrapping => REG_BG2CNT_Display_Area_Overflow(REG_BG2CNT_Display_Area_Overflow'left), + mosaic => REG_BG2CNT_Mosaic(REG_BG2CNT_Mosaic'left), + Mosaic_H_Size => unsigned(REG_MOSAIC_BG_Mosaic_H_Size), + refX => ref2_x_hd0, + refY => ref2_y_hd0, + refX_mosaic => mosaic_ref2_x, + refY_mosaic => mosaic_ref2_y, + dx => dx2_hd0, + dy => dy2_hd0, + pixel_we => pixel_we_mode2_2_hd0, + pixeldata => pixeldata_mode2_2_hd0, + pixel_x => pixel_x_mode2_2_hd0, + PALETTE_Drawer_addr => PALETTE_Drawer_addr_mode2_2_hd0, + PALETTE_Drawer_data => PALETTE_BG_Drawer_data, + PALETTE_Drawer_valid => PALETTE_BG_Drawer_valid(2), + VRAM_Drawer_addr => VRAM_Drawer_addr_mode2_2_hd0, + VRAM_Drawer_data => VRAM_Drawer_data_Lo, + VRAM_Drawer_valid => VRAM_Drawer_valid_Lo(2) + ); + igba_drawer_mode2_2_hd1 : entity work.gba_drawer_mode2 + generic map + ( + DXYBITS => 17, + ACCURACYBITS => 30, + PIXELCOUNT => 480 + ) + port map + ( + clk100 => clk100, + line_trigger => line_trigger_1, + drawline => drawline_mode2_2_hd1, + busy => busy_mode2_2_hd1, + mapbase => unsigned(REG_BG2CNT_Screen_Base_Block), + tilebase => unsigned(REG_BG2CNT_Character_Base_Block), + screensize => unsigned(REG_BG2CNT_Screen_Size), + wrapping => REG_BG2CNT_Display_Area_Overflow(REG_BG2CNT_Display_Area_Overflow'left), + mosaic => REG_BG2CNT_Mosaic(REG_BG2CNT_Mosaic'left), + Mosaic_H_Size => unsigned(REG_MOSAIC_BG_Mosaic_H_Size), + refX => ref2_x_hd1, + refY => ref2_y_hd1, + refX_mosaic => mosaic_ref2_x, + refY_mosaic => mosaic_ref2_y, + dx => dx2_hd1, + dy => dy2_hd1, + pixel_we => pixel_we_mode2_2_hd1, + pixeldata => pixeldata_mode2_2_hd1, + pixel_x => pixel_x_mode2_2_hd1, + PALETTE_Drawer_addr => PALETTE_Drawer_addr_mode2_2_hd1, + PALETTE_Drawer_data => PALETTE_BG_Drawer_data, + PALETTE_Drawer_valid => PALETTE_BG_Drawer_valid(3), + VRAM_Drawer_addr => VRAM_Drawer_addr_mode2_2_hd1, + VRAM_Drawer_data => VRAM_Drawer_data_Lo, + VRAM_Drawer_valid => VRAM_Drawer_valid_Lo(3) + ); igba_drawer_mode2_3 : entity work.gba_drawer_mode2 port map @@ -899,6 +1250,76 @@ begin VRAM_Drawer_data => VRAM_Drawer_data_Lo, VRAM_Drawer_valid => VRAM_Drawer_valid_Lo(3) ); + igba_drawer_mode2_3_hd0 : entity work.gba_drawer_mode2 + generic map + ( + DXYBITS => 17, + ACCURACYBITS => 30, + PIXELCOUNT => 480 + ) + port map + ( + clk100 => clk100, + line_trigger => line_trigger_1, + drawline => drawline_mode2_3_hd0, + busy => busy_mode2_3_hd0, + mapbase => unsigned(REG_BG3CNT_Screen_Base_Block), + tilebase => unsigned(REG_BG3CNT_Character_Base_Block), + screensize => unsigned(REG_BG3CNT_Screen_Size), + wrapping => REG_BG3CNT_Display_Area_Overflow(REG_BG3CNT_Display_Area_Overflow'left), + mosaic => REG_BG3CNT_Mosaic(REG_BG3CNT_Mosaic'left), + Mosaic_H_Size => unsigned(REG_MOSAIC_BG_Mosaic_H_Size), + refX => ref3_x_hd0, + refY => ref3_y_hd0, + refX_mosaic => mosaic_ref3_x, + refY_mosaic => mosaic_ref3_y, + dx => dx3_hd0, + dy => dy3_hd0, + pixel_we => pixel_we_mode2_3_hd0, + pixeldata => pixeldata_mode2_3_hd0, + pixel_x => pixel_x_mode2_3_hd0, + PALETTE_Drawer_addr => PALETTE_Drawer_addr_mode2_3_hd0, + PALETTE_Drawer_data => PALETTE_BG_Drawer_data, + PALETTE_Drawer_valid => PALETTE_BG_Drawer_valid(0), + VRAM_Drawer_addr => VRAM_Drawer_addr_mode2_3_hd0, + VRAM_Drawer_data => VRAM_Drawer_data_Lo, + VRAM_Drawer_valid => VRAM_Drawer_valid_Lo(0) + ); + igba_drawer_mode2_3_hd1 : entity work.gba_drawer_mode2 + generic map + ( + DXYBITS => 17, + ACCURACYBITS => 30, + PIXELCOUNT => 480 + ) + port map + ( + clk100 => clk100, + line_trigger => line_trigger_1, + drawline => drawline_mode2_3_hd1, + busy => busy_mode2_3_hd1, + mapbase => unsigned(REG_BG3CNT_Screen_Base_Block), + tilebase => unsigned(REG_BG3CNT_Character_Base_Block), + screensize => unsigned(REG_BG3CNT_Screen_Size), + wrapping => REG_BG3CNT_Display_Area_Overflow(REG_BG3CNT_Display_Area_Overflow'left), + mosaic => REG_BG3CNT_Mosaic(REG_BG3CNT_Mosaic'left), + Mosaic_H_Size => unsigned(REG_MOSAIC_BG_Mosaic_H_Size), + refX => ref3_x_hd1, + refY => ref3_y_hd1, + refX_mosaic => mosaic_ref3_x, + refY_mosaic => mosaic_ref3_y, + dx => dx3_hd1, + dy => dy3_hd1, + pixel_we => pixel_we_mode2_3_hd1, + pixeldata => pixeldata_mode2_3_hd1, + pixel_x => pixel_x_mode2_3_hd1, + PALETTE_Drawer_addr => PALETTE_Drawer_addr_mode2_3_hd1, + PALETTE_Drawer_data => PALETTE_BG_Drawer_data, + PALETTE_Drawer_valid => PALETTE_BG_Drawer_valid(1), + VRAM_Drawer_addr => VRAM_Drawer_addr_mode2_3_hd1, + VRAM_Drawer_data => VRAM_Drawer_data_Lo, + VRAM_Drawer_valid => VRAM_Drawer_valid_Lo(1) + ); igba_drawer_mode345 : entity work.gba_drawer_mode345 port map @@ -968,25 +1389,116 @@ begin VRAM_Drawer_data => VRAM_Drawer_data_Hi, VRAM_Drawer_valid => VRAM_Drawer_valid_Hi(1) ); + igba_drawer_obj_hd0 : entity work.gba_drawer_obj + generic map + ( + RESMULT => 2, + PIXELCOUNT => 480 + ) + port map + ( + clk100 => clk100, + + hblank => hblank_trigger, + lockspeed => lockspeed, + busy => busy_modeobj_hd0, + + drawline => drawline_obj_hd0, + ypos => linecounter_int, + ypos_mosaic => linecounter_mosaic_obj, + + BG_Mode => BG_Mode, + one_dim_mapping => REG_DISPCNT_OBJ_Char_VRAM_Map(REG_DISPCNT_OBJ_Char_VRAM_Map'left), + Mosaic_H_Size => unsigned(REG_MOSAIC_OBJ_Mosaic_H_Size), + + hblankfree => REG_DISPCNT_H_Blank_IntervalFree(REG_DISPCNT_H_Blank_IntervalFree'left), + maxpixels => maxpixels, + + pixel_we_color => pixel_we_modeobj_color_hd0, + pixeldata_color => pixeldata_modeobj_color_hd0, + pixel_we_settings => pixel_we_modeobj_settings_hd0, + pixeldata_settings => pixeldata_modeobj_settings_hd0, + pixel_x => pixel_x_modeobj_hd0, + pixel_objwnd => pixel_objwnd_hd0, + + OAMRAM_Drawer_addr => OAMRAM_Drawer_addr_hd0, + OAMRAM_Drawer_data => OAMRAM_Drawer_data_hd0, + + PALETTE_Drawer_addr => PALETTE_OAM_Drawer_addr_hd0, + PALETTE_Drawer_data => PALETTE_OAM_Drawer_data_hd0, + + VRAM_Drawer_addr => VRAM_Drawer_addrobj_hd0, + VRAM_Drawer_data => VRAM_Drawer_data_Hi, + VRAM_Drawer_valid => VRAM_Drawer_valid_Hi(1) + ); + igba_drawer_obj_hd1 : entity work.gba_drawer_obj + generic map + ( + RESMULT => 2, + PIXELCOUNT => 480, + YMULTOFFSET => 1 + ) + port map + ( + clk100 => clk100, + + hblank => hblank_trigger, + lockspeed => lockspeed, + busy => busy_modeobj_hd1, + + drawline => drawline_obj_hd1, + ypos => linecounter_int, + ypos_mosaic => linecounter_mosaic_obj, + + BG_Mode => BG_Mode, + one_dim_mapping => REG_DISPCNT_OBJ_Char_VRAM_Map(REG_DISPCNT_OBJ_Char_VRAM_Map'left), + Mosaic_H_Size => unsigned(REG_MOSAIC_OBJ_Mosaic_H_Size), + + hblankfree => REG_DISPCNT_H_Blank_IntervalFree(REG_DISPCNT_H_Blank_IntervalFree'left), + maxpixels => maxpixels, + + pixel_we_color => pixel_we_modeobj_color_hd1, + pixeldata_color => pixeldata_modeobj_color_hd1, + pixel_we_settings => pixel_we_modeobj_settings_hd1, + pixeldata_settings => pixeldata_modeobj_settings_hd1, + pixel_x => pixel_x_modeobj_hd1, + pixel_objwnd => pixel_objwnd_hd1, + + OAMRAM_Drawer_addr => OAMRAM_Drawer_addr_hd1, + OAMRAM_Drawer_data => OAMRAM_Drawer_data_hd1, + + PALETTE_Drawer_addr => PALETTE_OAM_Drawer_addr_hd1, + PALETTE_Drawer_data => PALETTE_OAM_Drawer_data_hd1, + + VRAM_Drawer_addr => VRAM_Drawer_addrobj_hd1, + VRAM_Drawer_data => VRAM_Drawer_data_Hi, + VRAM_Drawer_valid => VRAM_Drawer_valid_Hi(0) + ); - drawline_mode0_0 <= on_delay_bg0(2) and start_draw when BG_Mode = "000" or BG_Mode = "001" else '0'; - drawline_mode0_1 <= on_delay_bg1(2) and start_draw when BG_Mode = "000" or BG_Mode = "001" else '0'; - drawline_mode0_2 <= on_delay_bg2(2) and start_draw when BG_Mode = "000" else '0'; - drawline_mode0_3 <= on_delay_bg3(2) and start_draw when BG_Mode = "000" else '0'; - drawline_mode2_2 <= on_delay_bg2(2) and start_draw when BG_Mode = "001" or BG_Mode = "010" else '0'; - drawline_mode2_3 <= on_delay_bg3(2) and start_draw when BG_Mode = "010" else '0'; - drawline_mode345 <= on_delay_bg2(2) and start_draw when BG_Mode = "011" or BG_Mode = "100" or BG_Mode = "101" else '0'; - drawline_obj <= Screen_Display_OBJ(Screen_Display_OBJ'left) and start_draw; + drawline_mode0_0 <= on_delay_bg0(2) and start_draw when BG_Mode = "000" or BG_Mode = "001" else '0'; + drawline_mode0_1 <= on_delay_bg1(2) and start_draw when BG_Mode = "000" or BG_Mode = "001" else '0'; + drawline_mode0_2 <= on_delay_bg2(2) and start_draw when BG_Mode = "000" else '0'; + drawline_mode0_3 <= on_delay_bg3(2) and start_draw when BG_Mode = "000" else '0'; + drawline_mode2_2 <= on_delay_bg2(2) and start_draw when (hdmode2x_bg = '0' and (BG_Mode = "001" or BG_Mode = "010")) else '0'; + drawline_mode2_2_hd0 <= on_delay_bg2(2) and start_draw when (hdmode2x_bg = '1' and (BG_Mode = "001" or BG_Mode = "010")) else '0'; + drawline_mode2_2_hd1 <= on_delay_bg2(2) and start_draw when (hdmode2x_bg = '1' and (BG_Mode = "001" or BG_Mode = "010")) else '0'; + drawline_mode2_3 <= on_delay_bg3(2) and start_draw when (hdmode2x_bg = '0' and BG_Mode = "010") else '0'; + drawline_mode2_3_hd0 <= on_delay_bg3(2) and start_draw when (hdmode2x_bg = '1' and BG_Mode = "010") else '0'; + drawline_mode2_3_hd1 <= on_delay_bg3(2) and start_draw when (hdmode2x_bg = '1' and BG_Mode = "010") else '0'; + drawline_mode345 <= on_delay_bg2(2) and start_draw when BG_Mode = "011" or BG_Mode = "100" or BG_Mode = "101" else '0'; + drawline_obj <= Screen_Display_OBJ(Screen_Display_OBJ'left) and start_draw when hdmode2x_obj = '0' else '0'; + drawline_obj_hd0 <= Screen_Display_OBJ(Screen_Display_OBJ'left) and start_draw when hdmode2x_obj = '1' else '0'; + drawline_obj_hd1 <= Screen_Display_OBJ(Screen_Display_OBJ'left) and start_draw when hdmode2x_obj = '1' and unsigned(BG_Mode) < 3 else '0'; - PALETTE_BG_Drawer_addr0 <= PALETTE_Drawer_addr_mode0_0; - PALETTE_BG_Drawer_addr1 <= PALETTE_Drawer_addr_mode0_1; - PALETTE_BG_Drawer_addr2 <= PALETTE_Drawer_addr_mode0_2 when BG_Mode = "000" else PALETTE_Drawer_addr_mode2_2 when BG_Mode = "001" or BG_Mode = "010" else PALETTE_Drawer_addr_mode345; - PALETTE_BG_Drawer_addr3 <= PALETTE_Drawer_addr_mode0_3 when BG_Mode = "000" else PALETTE_Drawer_addr_mode2_3; + PALETTE_BG_Drawer_addr0 <= PALETTE_Drawer_addr_mode2_3_hd0 when (hdmode2x_bg = '1' and BG_Mode = "010") else PALETTE_Drawer_addr_mode0_0; + PALETTE_BG_Drawer_addr1 <= PALETTE_Drawer_addr_mode2_3_hd1 when (hdmode2x_bg = '1' and BG_Mode = "010") else PALETTE_Drawer_addr_mode0_1; + PALETTE_BG_Drawer_addr2 <= PALETTE_Drawer_addr_mode0_2 when BG_Mode = "000" else PALETTE_Drawer_addr_mode2_2 when ((BG_Mode = "001" or BG_Mode = "010") and hdmode2x_bg = '0') else PALETTE_Drawer_addr_mode2_2_hd0 when BG_Mode = "001" or BG_Mode = "010" else PALETTE_Drawer_addr_mode345; + PALETTE_BG_Drawer_addr3 <= PALETTE_Drawer_addr_mode0_3 when BG_Mode = "000" else PALETTE_Drawer_addr_mode2_2_hd1 when hdmode2x_bg = '1' else PALETTE_Drawer_addr_mode2_3; - VRAM_Drawer_addr0 <= VRAM_Drawer_addr_mode0_0; - VRAM_Drawer_addr1 <= VRAM_Drawer_addr_mode0_1; - VRAM_Drawer_addr2 <= VRAM_Drawer_addr_mode0_2 when BG_Mode = "000" else VRAM_Drawer_addr_mode2_2 when BG_Mode = "001" or BG_Mode = "010" else VRAM_Drawer_addr_345_Lo; - VRAM_Drawer_addr3 <= VRAM_Drawer_addr_mode0_3 when BG_Mode = "000" else VRAM_Drawer_addr_mode2_3; + VRAM_Drawer_addr0 <= VRAM_Drawer_addr_mode2_3_hd0 when (hdmode2x_bg = '1' and BG_Mode = "010") else VRAM_Drawer_addr_mode0_0; + VRAM_Drawer_addr1 <= VRAM_Drawer_addr_mode2_3_hd1 when (hdmode2x_bg = '1' and BG_Mode = "010") else VRAM_Drawer_addr_mode0_1; + VRAM_Drawer_addr2 <= VRAM_Drawer_addr_mode0_2 when BG_Mode = "000" else VRAM_Drawer_addr_mode2_2 when ((BG_Mode = "001" or BG_Mode = "010") and hdmode2x_bg = '0') else VRAM_Drawer_addr_mode2_2_hd0 when BG_Mode = "001" or BG_Mode = "010" else VRAM_Drawer_addr_345_Lo; + VRAM_Drawer_addr3 <= VRAM_Drawer_addr_mode0_3 when BG_Mode = "000" else VRAM_Drawer_addr_mode2_2_hd1 when hdmode2x_bg = '1' else VRAM_Drawer_addr_mode2_3; draw_allmod(0) <= drawline_mode0_0; draw_allmod(1) <= drawline_mode0_1; @@ -1001,10 +1513,10 @@ begin busy_allmod(1) <= busy_mode0_1; busy_allmod(2) <= busy_mode0_2; busy_allmod(3) <= busy_mode0_3; - busy_allmod(4) <= busy_mode2_2; - busy_allmod(5) <= busy_mode2_3; + busy_allmod(4) <= busy_mode2_2 or busy_mode2_2_hd0 or busy_mode2_2_hd1; + busy_allmod(5) <= busy_mode2_3 or busy_mode2_3_hd0 or busy_mode2_3_hd1; busy_allmod(6) <= busy_mode345; - busy_allmod(7) <= busy_modeobj; + busy_allmod(7) <= busy_modeobj or busy_modeobj_hd0 or busy_modeobj_hd1; -- memory mapping process (clk100) @@ -1045,8 +1557,21 @@ begin VRAM_Drawer_cnt_Hi <= not VRAM_Drawer_cnt_Hi; case (VRAM_Drawer_cnt_Hi) is - when '0' => VRAM_Drawer_addr_Hi <= VRAM_Drawer_addr_345_Hi; VRAM_Drawer_valid_Hi <= "10"; - when '1' => VRAM_Drawer_addr_Hi <= VRAM_Drawer_addrobj; VRAM_Drawer_valid_Hi <= "01"; + when '0' => + VRAM_Drawer_valid_Hi <= "10"; + if (hdmode2x_obj = '1' and unsigned(BG_Mode) < 3) then + VRAM_Drawer_addr_Hi <= VRAM_Drawer_addrobj_hd1; + else + VRAM_Drawer_addr_Hi <= VRAM_Drawer_addr_345_Hi; + end if; + + when '1' => + VRAM_Drawer_valid_Hi <= "01"; + if (hdmode2x_obj = '1') then + VRAM_Drawer_addr_Hi <= VRAM_Drawer_addrobj_hd0; + else + VRAM_Drawer_addr_Hi <= VRAM_Drawer_addrobj; + end if; when others => null; end case; @@ -1058,56 +1583,97 @@ begin end if; if (clear_enable = '1') then - if (clear_addr < 239) then + if (((hdmode2x_bg = '1' or hdmode2x_obj = '1') and clear_addr < 479) or (hdmode2x_bg = '0' and hdmode2x_obj = '0' and clear_addr < 239)) then clear_addr <= clear_addr + 1; else clear_enable <= '0'; end if; - pixel_we_bg0 <= '1'; - pixel_we_bg1 <= '1'; - pixel_we_bg2 <= '1'; - pixel_we_bg3 <= '1'; - pixel_we_obj_color <= '1'; - pixel_we_obj_settings <= '1'; + pixel_we_bg0 <= '1'; + pixel_we_bg1 <= '1'; + pixel_we_bg2 <= '1'; + pixel_we_bg2_hd0 <= '1'; + pixel_we_bg2_hd1 <= '1'; + pixel_we_bg3 <= '1'; + pixel_we_bg3_hd0 <= '1'; + pixel_we_bg3_hd1 <= '1'; + pixel_we_obj_color <= '1'; + pixel_we_obj_color_hd0 <= '1'; + pixel_we_obj_color_hd1 <= '1'; + pixel_we_obj_settings <= '1'; + pixel_we_obj_settings_hd0 <= '1'; + pixel_we_obj_settings_hd1 <= '1'; + + pixeldata_bg0 <= x"8000"; + pixeldata_bg1 <= x"8000"; + pixeldata_bg2 <= x"8000"; + pixeldata_bg2_hd0 <= x"8000"; + pixeldata_bg2_hd1 <= x"8000"; + pixeldata_bg3 <= x"8000"; + pixeldata_bg3_hd0 <= x"8000"; + pixeldata_bg3_hd1 <= x"8000"; + pixeldata_obj_color <= x"8000"; + pixeldata_obj_color_hd0 <= x"8000"; + pixeldata_obj_color_hd1 <= x"8000"; + pixeldata_obj_settings <= "000"; + pixeldata_obj_settings_hd0 <= "000"; + pixeldata_obj_settings_hd1 <= "000"; - pixeldata_bg0 <= x"8000"; - pixeldata_bg1 <= x"8000"; - pixeldata_bg2 <= x"8000"; - pixeldata_bg3 <= x"8000"; - pixeldata_obj_color <= x"8000"; - pixeldata_obj_settings <= "000"; - - pixel_x_bg0 <= clear_addr; - pixel_x_bg1 <= clear_addr; - pixel_x_bg2 <= clear_addr; - pixel_x_bg3 <= clear_addr; - pixel_x_obj <= clear_addr; + if (clear_addr <= 239) then + pixel_x_bg0 <= clear_addr; + pixel_x_bg1 <= clear_addr; + pixel_x_bg2 <= clear_addr; + pixel_x_bg3 <= clear_addr; + pixel_x_obj <= clear_addr; + end if; + + pixel_x_bg2_hd0 <= clear_addr; + pixel_x_bg2_hd1 <= clear_addr; + pixel_x_bg3_hd0 <= clear_addr; + pixel_x_bg3_hd1 <= clear_addr; + pixel_x_obj_hd0 <= clear_addr; + pixel_x_obj_hd1 <= clear_addr; else - pixel_we_bg0 <= pixel_we_mode0_0; - pixel_we_bg1 <= pixel_we_mode0_1; - pixel_we_obj_color <= pixel_we_modeobj_color; - pixel_we_obj_settings <= pixel_we_modeobj_settings; + pixel_we_bg0 <= pixel_we_mode0_0; + pixel_we_bg1 <= pixel_we_mode0_1; + pixel_we_obj_color <= pixel_we_modeobj_color; + pixel_we_obj_color_hd0 <= pixel_we_modeobj_color_hd0; + pixel_we_obj_color_hd1 <= pixel_we_modeobj_color_hd1; + pixel_we_obj_settings <= pixel_we_modeobj_settings; + pixel_we_obj_settings_hd0 <= pixel_we_modeobj_settings_hd0; + pixel_we_obj_settings_hd1 <= pixel_we_modeobj_settings_hd1; - pixeldata_bg0 <= pixeldata_mode0_0; - pixeldata_bg1 <= pixeldata_mode0_1; - pixeldata_obj_color <= pixeldata_modeobj_color; - pixeldata_obj_settings <= pixeldata_modeobj_settings; + pixeldata_bg0 <= pixeldata_mode0_0; + pixeldata_bg1 <= pixeldata_mode0_1; + pixeldata_obj_color <= pixeldata_modeobj_color; + pixeldata_obj_color_hd0 <= pixeldata_modeobj_color_hd0; + pixeldata_obj_color_hd1 <= pixeldata_modeobj_color_hd1; + pixeldata_obj_settings <= pixeldata_modeobj_settings; + pixeldata_obj_settings_hd0 <= pixeldata_modeobj_settings_hd0; + pixeldata_obj_settings_hd1 <= pixeldata_modeobj_settings_hd1; - pixel_x_bg0 <= pixel_x_mode0_0; - pixel_x_bg1 <= pixel_x_mode0_1; - pixel_x_obj <= pixel_x_modeobj; + pixel_x_bg0 <= pixel_x_mode0_0; + pixel_x_bg1 <= pixel_x_mode0_1; + pixel_x_obj <= pixel_x_modeobj; + pixel_x_obj_hd0 <= pixel_x_modeobj_hd0; + pixel_x_obj_hd1 <= pixel_x_modeobj_hd1; if (BG_Mode = "000") then pixel_we_bg2 <= pixel_we_mode0_2; pixeldata_bg2 <= pixeldata_mode0_2; pixel_x_bg2 <= pixel_x_mode0_2; elsif (BG_Mode = "001" or BG_Mode = "010") then - pixel_we_bg2 <= pixel_we_mode2_2; - pixeldata_bg2 <= pixeldata_mode2_2; - pixel_x_bg2 <= pixel_x_mode2_2; + pixel_we_bg2 <= pixel_we_mode2_2; + pixel_we_bg2_hd0 <= pixel_we_mode2_2_hd0; + pixel_we_bg2_hd1 <= pixel_we_mode2_2_hd1; + pixeldata_bg2 <= pixeldata_mode2_2; + pixeldata_bg2_hd0 <= pixeldata_mode2_2_hd0; + pixeldata_bg2_hd1 <= pixeldata_mode2_2_hd1; + pixel_x_bg2 <= pixel_x_mode2_2; + pixel_x_bg2_hd0 <= pixel_x_mode2_2_hd0; + pixel_x_bg2_hd1 <= pixel_x_mode2_2_hd1; else pixel_we_bg2 <= pixel_we_mode345; pixeldata_bg2 <= pixeldata_mode345; @@ -1119,9 +1685,15 @@ begin pixeldata_bg3 <= pixeldata_mode0_3; pixel_x_bg3 <= pixel_x_mode0_3; else - pixel_we_bg3 <= pixel_we_mode2_3; - pixeldata_bg3 <= pixeldata_mode2_3; - pixel_x_bg3 <= pixel_x_mode2_3; + pixel_we_bg3 <= pixel_we_mode2_3; + pixel_we_bg3_hd0 <= pixel_we_mode2_3_hd0; + pixel_we_bg3_hd1 <= pixel_we_mode2_3_hd1; + pixeldata_bg3 <= pixeldata_mode2_3; + pixeldata_bg3_hd0 <= pixeldata_mode2_3_hd0; + pixeldata_bg3_hd1 <= pixeldata_mode2_3_hd1; + pixel_x_bg3 <= pixel_x_mode2_3; + pixel_x_bg3_hd0 <= pixel_x_mode2_3_hd0; + pixel_x_bg3_hd1 <= pixel_x_mode2_3_hd1; end if; end if; @@ -1196,6 +1768,50 @@ begin we_b => '0', re_b => '1' ); + ilinebuffer_bg2_hd0: entity MEM.SyncRamDual + generic map + ( + DATA_WIDTH => 16, + ADDR_WIDTH => 9 + ) + port map + ( + clk => clk100, + + addr_a => pixel_x_bg2_hd0, + datain_a => pixeldata_bg2_hd0, + dataout_a => open, + we_a => pixel_we_bg2_hd0, + re_a => '0', + + addr_b => linebuffer_addr_hd, + datain_b => x"0000", + dataout_b => linebuffer_bg2_data_hd0, + we_b => '0', + re_b => '1' + ); + ilinebuffer_bg2_hd1: entity MEM.SyncRamDual + generic map + ( + DATA_WIDTH => 16, + ADDR_WIDTH => 9 + ) + port map + ( + clk => clk100, + + addr_a => pixel_x_bg2_hd1, + datain_a => pixeldata_bg2_hd1, + dataout_a => open, + we_a => pixel_we_bg2_hd1, + re_a => '0', + + addr_b => linebuffer_addr_hd, + datain_b => x"0000", + dataout_b => linebuffer_bg2_data_hd1, + we_b => '0', + re_b => '1' + ); ilinebuffer_bg3: entity MEM.SyncRamDual generic map ( @@ -1218,6 +1834,50 @@ begin we_b => '0', re_b => '1' ); + ilinebuffer_bg3_hd0: entity MEM.SyncRamDual + generic map + ( + DATA_WIDTH => 16, + ADDR_WIDTH => 9 + ) + port map + ( + clk => clk100, + + addr_a => pixel_x_bg3_hd0, + datain_a => pixeldata_bg3_hd0, + dataout_a => open, + we_a => pixel_we_bg3_hd0, + re_a => '0', + + addr_b => linebuffer_addr_hd, + datain_b => x"0000", + dataout_b => linebuffer_bg3_data_hd0, + we_b => '0', + re_b => '1' + ); + ilinebuffer_bg3_hd1: entity MEM.SyncRamDual + generic map + ( + DATA_WIDTH => 16, + ADDR_WIDTH => 9 + ) + port map + ( + clk => clk100, + + addr_a => pixel_x_bg3_hd1, + datain_a => pixeldata_bg3_hd1, + dataout_a => open, + we_a => pixel_we_bg3_hd1, + re_a => '0', + + addr_b => linebuffer_addr_hd, + datain_b => x"0000", + dataout_b => linebuffer_bg3_data_hd1, + we_b => '0', + re_b => '1' + ); ilinebuffer_obj_color: entity MEM.SyncRamDual generic map ( @@ -1240,6 +1900,51 @@ begin we_b => '0', re_b => '1' ); + ilinebuffer_obj_color_hd0: entity MEM.SyncRamDual + generic map + ( + DATA_WIDTH => 16, + ADDR_WIDTH => 9 + ) + port map + ( + clk => clk100, + + addr_a => pixel_x_obj_hd0, + datain_a => pixeldata_obj_color_hd0, + dataout_a => open, + we_a => pixel_we_obj_color_hd0, + re_a => '0', + + addr_b => linebuffer_addr_hd, + datain_b => (15 downto 0 => '0'), + dataout_b => linebuffer_obj_color_hd0, + we_b => '0', + re_b => '1' + ); + ilinebuffer_obj_color_hd1: entity MEM.SyncRamDual + generic map + ( + DATA_WIDTH => 16, + ADDR_WIDTH => 9 + ) + port map + ( + clk => clk100, + + addr_a => pixel_x_obj_hd1, + datain_a => pixeldata_obj_color_hd1, + dataout_a => open, + we_a => pixel_we_obj_color_hd1, + re_a => '0', + + addr_b => linebuffer_addr_hd, + datain_b => (15 downto 0 => '0'), + dataout_b => linebuffer_obj_color_hd1, + we_b => '0', + re_b => '1' + ); + ilinebuffer_obj_settings: entity MEM.SyncRamDual generic map ( @@ -1262,17 +1967,63 @@ begin we_b => '0', re_b => '1' ); + ilinebuffer_obj_settings_hd0: entity MEM.SyncRamDual + generic map + ( + DATA_WIDTH => 3, + ADDR_WIDTH => 9 + ) + port map + ( + clk => clk100, + + addr_a => pixel_x_obj_hd0, + datain_a => pixeldata_obj_settings_hd0, + dataout_a => open, + we_a => pixel_we_obj_settings_hd0, + re_a => '0', + + addr_b => linebuffer_addr_hd, + datain_b => (2 downto 0 => '0'), + dataout_b => linebuffer_obj_setting_hd0, + we_b => '0', + re_b => '1' + ); + ilinebuffer_obj_settings_hd1: entity MEM.SyncRamDual + generic map + ( + DATA_WIDTH => 3, + ADDR_WIDTH => 9 + ) + port map + ( + clk => clk100, + + addr_a => pixel_x_obj_hd1, + datain_a => pixeldata_obj_settings_hd1, + dataout_a => open, + we_a => pixel_we_obj_settings_hd1, + re_a => '0', + + addr_b => linebuffer_addr_hd, + datain_b => (2 downto 0 => '0'), + dataout_b => linebuffer_obj_setting_hd1, + we_b => '0', + re_b => '1' + ); - linebuffer_obj_data <= linebuffer_obj_setting & linebuffer_obj_color; + linebuffer_obj_data <= linebuffer_obj_setting & linebuffer_obj_color; + linebuffer_obj_data_hd0 <= linebuffer_obj_setting_hd0 & linebuffer_obj_color_hd0; + linebuffer_obj_data_hd1 <= linebuffer_obj_setting_hd1 & linebuffer_obj_color_hd1; -- line buffer readout process (clk100) begin if rising_edge(clk100) then - if (pixel_objwnd = '1') then - linebuffer_objwindow(pixel_x_obj) <= '1'; - end if; + if (pixel_objwnd = '1') then linebuffer_objwindow(pixel_x_obj) <= '1'; end if; + if (pixel_objwnd_hd0 = '1') then linebuffer_objwindow_hd0(pixel_x_obj_hd0) <= '1'; end if; + if (pixel_objwnd_hd1 = '1') then linebuffer_objwindow_hd1(pixel_x_obj_hd1) <= '1'; end if; -- synthesis translate_off if (to_integer(linecounter) < 160) then @@ -1312,6 +2063,8 @@ begin end if; clear_trigger <= '0'; + + pixelmult <= not pixelmult; case (drawstate) is when IDLE => @@ -1321,7 +2074,9 @@ begin start_draw <= '1'; linecounter_int <= to_integer(linecounter); lineUpToDate(to_integer(linecounter)) <= '1'; - linebuffer_objwindow <= (others => '0'); + linebuffer_objwindow <= (others => '0'); + linebuffer_objwindow_hd0 <= (others => '0'); + linebuffer_objwindow_hd1 <= (others => '0'); end if; end if; @@ -1332,18 +2087,30 @@ begin when DRAWING => if (busy_allmod = x"00") then - drawstate <= MERGING; - linebuffer_addr <= 0; - merge_enable <= '1'; - clear_trigger <= '1'; + drawstate <= MERGING; + linebuffer_addr <= 0; + linebuffer_addr_hd <= 0; + pixelmult <= '0'; + merge_enable <= '1'; + if (hdmode2x_bg = '0' and hdmode2x_obj = '0') then + clear_trigger <= '1'; + end if; end if; when MERGING => - if (linebuffer_addr < 239) then - linebuffer_addr <= linebuffer_addr + 1; - else - merge_enable <= '0'; - drawstate <= IDLE; + if (linebuffer_addr_hd < 479) then + linebuffer_addr_hd <= linebuffer_addr_hd + 1; + end if; + if (pixelmult = '1' or (hdmode2x_bg = '0' and hdmode2x_obj = '0')) then + if (linebuffer_addr < 239) then + linebuffer_addr <= linebuffer_addr + 1; + if ((hdmode2x_bg = '1' or hdmode2x_obj = '1') and linebuffer_addr = 120) then + clear_trigger <= '1'; + end if; + else + merge_enable <= '0'; + drawstate <= IDLE; + end if; end if; end case; @@ -1351,13 +2118,18 @@ begin linebuffer_addr_1 <= linebuffer_addr; merge_enable_1 <= merge_enable; - objwindow_merge_in <= linebuffer_objwindow(linebuffer_addr); + objwindow_merge <= linebuffer_objwindow(linebuffer_addr); + objwindow_merge_hd0 <= linebuffer_objwindow_hd0(linebuffer_addr_hd); + objwindow_merge_hd1 <= linebuffer_objwindow_hd1(linebuffer_addr_hd); + --merger 1 -- cycle 1 pixel_out_x_1 <= merge_pixel_x; pixel_out_y_1 <= merge_pixel_y; pixelout_addr_1 <= merge_pixel_x + merge_pixel_y * 240; - merge_pixel_we_1 <= merge_pixel_we; + if (frameselect = '0' or interframe_blend /= "10") then + merge_pixel_we_1 <= merge_pixel_we; + end if; if (Forced_Blank = "1") then merge_pixeldata_out_1 <= x"7FFF"; else @@ -1383,13 +2155,31 @@ begin pixel_out_we <= merge_pixel_we_2; if (Forced_Blank = "1") then pixel_out_data <= "111" & x"FFF"; - elsif (interframe_blend = '1') then + elsif (interframe_blend = "01") then pixel_out_data(14 downto 10) <= std_logic_vector(to_unsigned((to_integer(unsigned(merge_pixeldata_out_2(14 downto 10))) + to_integer(unsigned(pixel_smooth(14 downto 10)))) / 2, 5)); pixel_out_data( 9 downto 5) <= std_logic_vector(to_unsigned((to_integer(unsigned(merge_pixeldata_out_2(9 downto 5))) + to_integer(unsigned(pixel_smooth(9 downto 5)))) / 2, 5)); pixel_out_data( 4 downto 0) <= std_logic_vector(to_unsigned((to_integer(unsigned(merge_pixeldata_out_2(4 downto 0))) + to_integer(unsigned(pixel_smooth(4 downto 0)))) / 2, 5)); else pixel_out_data <= merge_pixeldata_out_2(14 downto 0); end if; + + --merger 2 + if (pixelmult = '0') then + pixel_out_2x <= pixel_out_x_2 * 2; + pixel2_out_x <= merge2_pixel_x * 2; + else + pixel_out_2x <= pixel_out_x_2 * 2 + 1; + pixel2_out_x <= merge2_pixel_x * 2 + 1; + end if; + + if (frameselect = '0' or interframe_blend /= "10") then + pixel2_out_we <= merge2_pixel_we; + end if; + if (Forced_Blank = "1") then + pixel2_out_data <= "111" & x"FFF"; + else + pixel2_out_data <= merge2_pixeldata_out(4 downto 0) & merge2_pixeldata_out(9 downto 5) & merge2_pixeldata_out(14 downto 10); + end if; end if; end process; @@ -1399,6 +2189,12 @@ begin enables_wndobj <= REG_WINOUT_Objwnd_Special_Effect & REG_WINOUT_Objwnd_OBJ_Enable & REG_WINOUT_Objwnd_BG3_Enable & REG_WINOUT_Objwnd_BG2_Enable & REG_WINOUT_Objwnd_BG1_Enable & REG_WINOUT_Objwnd_BG0_Enable; enables_wndout <= REG_WINOUT_Outside_Special_Effect & REG_WINOUT_Outside_OBJ_Enable & REG_WINOUT_Outside_BG3_Enable & REG_WINOUT_Outside_BG2_Enable & REG_WINOUT_Outside_BG1_Enable & REG_WINOUT_Outside_BG0_Enable; + merge_in_bg2 <= linebuffer_bg2_data when (hdmode2x_bg = '0' or BG_Mode = "000" or unsigned(BG_Mode) > 2) else linebuffer_bg2_data_hd0; + merge_in_bg3 <= linebuffer_bg3_data when (hdmode2x_bg = '0' or BG_Mode /= "010") else linebuffer_bg3_data_hd0; + merge_in_obj <= linebuffer_obj_data when hdmode2x_obj = '0' else linebuffer_obj_data_hd0; + + objwindow_merge_in <= objwindow_merge when hdmode2x_obj = '0' else objwindow_merge_hd0; + igba_drawer_merge : entity work.gba_drawer_merge port map ( @@ -1458,9 +2254,9 @@ begin pixeldata_bg0 => linebuffer_bg0_data, pixeldata_bg1 => linebuffer_bg1_data, - pixeldata_bg2 => linebuffer_bg2_data, - pixeldata_bg3 => linebuffer_bg3_data, - pixeldata_obj => linebuffer_obj_data, + pixeldata_bg2 => merge_in_bg2, + pixeldata_bg3 => merge_in_bg3, + pixeldata_obj => merge_in_obj, pixeldata_back => pixeldata_back, objwindow_in => objwindow_merge_in, @@ -1470,16 +2266,193 @@ begin pixel_we => merge_pixel_we ); + merge2_in_bg2 <= linebuffer_bg2_data when (hdmode2x_bg = '0' or BG_Mode = "000" or unsigned(BG_Mode) > 2) else linebuffer_bg2_data_hd1; + merge2_in_bg3 <= linebuffer_bg3_data when (hdmode2x_bg = '0' or BG_Mode /= "010") else linebuffer_bg3_data_hd1; + merge2_in_obj <= linebuffer_obj_data when hdmode2x_obj = '0' else linebuffer_obj_data_hd1 when unsigned(BG_Mode) < 3 else linebuffer_obj_data_hd0; + + objwindow_merge2_in <= objwindow_merge when hdmode2x_obj = '0' else objwindow_merge_hd1 when unsigned(BG_Mode) < 3 else objwindow_merge_hd0; + + igba_drawer_merge2 : entity work.gba_drawer_merge + port map + ( + clk100 => clk100, + + enable => merge_enable_1, + hblank => hblank_trigger_1, -- delayed 1 cycle because background is switched off at hblank + xpos => linebuffer_addr_1, + ypos => linecounter_int, + + in_WND0_on => REG_DISPCNT_Window_0_Display_Flag(REG_DISPCNT_Window_0_Display_Flag'left), + in_WND1_on => REG_DISPCNT_Window_1_Display_Flag(REG_DISPCNT_Window_1_Display_Flag'left), + in_WNDOBJ_on => REG_DISPCNT_OBJ_Wnd_Display_Flag(REG_DISPCNT_OBJ_Wnd_Display_Flag'left), + + in_WND0_X1 => unsigned(REG_WIN0H_X1), + in_WND0_X2 => unsigned(REG_WIN0H_X2), + in_WND0_Y1 => unsigned(REG_WIN0V_Y1), + in_WND0_Y2 => unsigned(REG_WIN0V_Y2), + in_WND1_X1 => unsigned(REG_WIN1H_X1), + in_WND1_X2 => unsigned(REG_WIN1H_X2), + in_WND1_Y1 => unsigned(REG_WIN1V_Y1), + in_WND1_Y2 => unsigned(REG_WIN1V_Y2), + + in_enables_wnd0 => enables_wnd0, + in_enables_wnd1 => enables_wnd1, + in_enables_wndobj => enables_wndobj, + in_enables_wndout => enables_wndout, + + in_special_effect_in => unsigned(REG_BLDCNT_Color_Special_Effect), + in_effect_1st_bg0 => REG_BLDCNT_BG0_1st_Target_Pixel(REG_BLDCNT_BG0_1st_Target_Pixel'left), + in_effect_1st_bg1 => REG_BLDCNT_BG1_1st_Target_Pixel(REG_BLDCNT_BG1_1st_Target_Pixel'left), + in_effect_1st_bg2 => REG_BLDCNT_BG2_1st_Target_Pixel(REG_BLDCNT_BG2_1st_Target_Pixel'left), + in_effect_1st_bg3 => REG_BLDCNT_BG3_1st_Target_Pixel(REG_BLDCNT_BG3_1st_Target_Pixel'left), + in_effect_1st_obj => REG_BLDCNT_OBJ_1st_Target_Pixel(REG_BLDCNT_OBJ_1st_Target_Pixel'left), + in_effect_1st_BD => REG_BLDCNT_BD_1st_Target_Pixel(REG_BLDCNT_BD_1st_Target_Pixel'left), + in_effect_2nd_bg0 => REG_BLDCNT_BG0_2nd_Target_Pixel(REG_BLDCNT_BG0_2nd_Target_Pixel'left), + in_effect_2nd_bg1 => REG_BLDCNT_BG1_2nd_Target_Pixel(REG_BLDCNT_BG1_2nd_Target_Pixel'left), + in_effect_2nd_bg2 => REG_BLDCNT_BG2_2nd_Target_Pixel(REG_BLDCNT_BG2_2nd_Target_Pixel'left), + in_effect_2nd_bg3 => REG_BLDCNT_BG3_2nd_Target_Pixel(REG_BLDCNT_BG3_2nd_Target_Pixel'left), + in_effect_2nd_obj => REG_BLDCNT_OBJ_2nd_Target_Pixel(REG_BLDCNT_OBJ_2nd_Target_Pixel'left), + in_effect_2nd_BD => REG_BLDCNT_BD_2nd_Target_Pixel(REG_BLDCNT_BD_2nd_Target_Pixel'left), + + in_Prio_BG0 => unsigned(REG_BG0CNT_BG_Priority), + in_Prio_BG1 => unsigned(REG_BG1CNT_BG_Priority), + in_Prio_BG2 => unsigned(REG_BG2CNT_BG_Priority), + in_Prio_BG3 => unsigned(REG_BG3CNT_BG_Priority), + + in_EVA => unsigned(REG_BLDALPHA_EVA_Coefficient), + in_EVB => unsigned(REG_BLDALPHA_EVB_Coefficient), + in_BLDY => unsigned(REG_BLDY), + + in_ena_bg0 => on_delay_bg0(2), + in_ena_bg1 => on_delay_bg1(2), + in_ena_bg2 => on_delay_bg2(2), + in_ena_bg3 => on_delay_bg3(2), + in_ena_obj => Screen_Display_OBJ(Screen_Display_OBJ'left), + + pixeldata_bg0 => linebuffer_bg0_data, + pixeldata_bg1 => linebuffer_bg1_data, + pixeldata_bg2 => merge2_in_bg2, + pixeldata_bg3 => merge2_in_bg3, + pixeldata_obj => merge2_in_obj, + pixeldata_back => pixeldata_back, + objwindow_in => objwindow_merge2_in, + + pixeldata_out => merge2_pixeldata_out, + pixel_x => merge2_pixel_x, + pixel_y => open, + pixel_we => merge2_pixel_we + ); + -- affine + mosaik process (clk100) begin if rising_edge(clk100) then - if (refpoint_update = '1' or ref2_x_written = '1') then ref2_x <= signed(REG_BG2RefX); mosaic_ref2_x <= signed(REG_BG2RefX); end if; - if (refpoint_update = '1' or ref2_y_written = '1') then ref2_y <= signed(REG_BG2RefY); mosaic_ref2_y <= signed(REG_BG2RefY); end if; - if (refpoint_update = '1' or ref3_x_written = '1') then ref3_x <= signed(REG_BG3RefX); mosaic_ref3_x <= signed(REG_BG3RefX); end if; - if (refpoint_update = '1' or ref3_y_written = '1') then ref3_y <= signed(REG_BG3RefY); mosaic_ref3_y <= signed(REG_BG3RefY); end if; + -- ref point written + if (refpoint_update = '1' or ref2_x_written = '1') then + ref2_x <= signed(REG_BG2RefX); + mosaic_ref2_x <= signed(REG_BG2RefX); + end if; + if (refpoint_update = '1' or ref2_y_written = '1') then + ref2_y <= signed(REG_BG2RefY); + mosaic_ref2_y <= signed(REG_BG2RefY); + end if; + if (refpoint_update = '1' or ref3_x_written = '1') then + ref3_x <= signed(REG_BG3RefX); + mosaic_ref3_x <= signed(REG_BG3RefX); + end if; + if (refpoint_update = '1' or ref3_y_written = '1') then + ref3_y <= signed(REG_BG3RefY); + mosaic_ref3_y <= signed(REG_BG3RefY); + end if; + + -- hd d(m)x/y + if (drawline_mode2_2_hd0 = '1' and (unsigned(REG_BG2RotScaleParDX) > 0 or unsigned(REG_BG2RotScaleParDY) > 0)) then + new_dx2 <= '0'; + new_dy2 <= '0'; + if (new_dx2 = '1') then + dx2_last <= signed(REG_BG2RotScaleParDX); + dy2_last <= signed(REG_BG2RotScaleParDY); + end if; + end if; + if (drawline_mode2_3_hd0 = '1' and (unsigned(REG_BG3RotScaleParDX) > 0 or unsigned(REG_BG3RotScaleParDY) > 0)) then + new_dx3 <= '0'; + new_dy3 <= '0'; + if (new_dx3 = '1') then + dx3_last <= signed(REG_BG3RotScaleParDX); + dy3_last <= signed(REG_BG3RotScaleParDY); + end if; + end if; + + line_trigger_1 <= line_trigger; + if (line_trigger = '1') then + ref2_x_last <= ref2_x; + if (new_dx2 = '1') then + ref2_x_hd0 <= ref2_x & '0'; + else + ref2_x_hd0 <= resize(ref2_x_last, 29) + resize(ref2_x, 29); + end if; + ref2_x_hd1 <= ref2_x & '0'; + ref2_y_last <= ref2_y; + if (new_dy2 = '1') then + ref2_y_hd0 <= ref2_y & '0'; + else + ref2_y_hd0 <= resize(ref2_y_last, 29) + resize(ref2_y, 29); + end if; + ref2_y_hd1 <= ref2_y & '0'; + + ref3_x_last <= ref3_x; + if (new_dx3 = '1') then + ref3_x_hd0 <= ref3_x & '0'; + else + ref3_x_hd0 <= resize(ref3_x_last, 29) + resize(ref3_x, 29); + end if; + ref3_x_hd1 <= ref3_x & '0'; + + ref3_y_last <= ref3_y; + if (new_dy3 = '1') then + ref3_y_hd0 <= ref3_y & '0'; + else + ref3_y_hd0 <= resize(ref3_y_last, 29) + resize(ref3_y, 29); + end if; + ref3_y_hd1 <= ref3_y & '0'; + end if; + + if (drawline = '1') then + dx2_last <= signed(REG_BG2RotScaleParDX); + if (new_dx2 = '1') then + dx2_hd0 <= signed(REG_BG2RotScaleParDX) & '0'; + else + dx2_hd0 <= resize(dx2_last, 17) + resize(signed(REG_BG2RotScaleParDX), 17); + end if; + dx2_hd1 <= signed(REG_BG2RotScaleParDX) & '0'; + + dy2_last <= signed(REG_BG2RotScaleParDY); + if (new_dy2 = '1') then + dy2_hd0 <= signed(REG_BG2RotScaleParDY) & '0'; + else + dy2_hd0 <= resize(dy2_last, 17) + resize(signed(REG_BG2RotScaleParDY), 17); + end if; + dy2_hd1 <= signed(REG_BG2RotScaleParDY) & '0'; + + dx3_last <= signed(REG_BG3RotScaleParDX); + if (new_dx3 = '1') then + dx3_hd0 <= signed(REG_BG3RotScaleParDX) & '0'; + else + dx3_hd0 <= resize(dx3_last, 17) + resize(signed(REG_BG3RotScaleParDX), 17); + end if; + dx3_hd1 <= signed(REG_BG3RotScaleParDX) & '0'; + + dy3_last <= signed(REG_BG3RotScaleParDY); + if (new_dy3 = '1') then + dy3_hd0 <= signed(REG_BG3RotScaleParDY) & '0'; + else + dy3_hd0 <= resize(dy3_last, 17) + resize(signed(REG_BG3RotScaleParDY), 17); + end if; + dy3_hd1 <= signed(REG_BG3RotScaleParDY) & '0'; + end if; + if (hblank_trigger = '1') then pixeldata_back <= pixeldata_back_next; @@ -1499,6 +2472,13 @@ begin mosaik_vcnt_obj <= 0; linecounter_mosaic_bg <= 0; linecounter_mosaic_obj <= 0; + new_dx2 <= '1'; + new_dy2 <= '1'; + new_dx3 <= '1'; + new_dy3 <= '1'; + if (interframe_blend = "10") then -- by toggling only when option is on, even/odd picture can be selected with multiple switch on/off + frameselect <= not frameselect; + end if; elsif (drawline = '1') then -- background diff --git a/rtl/gba_top.vhd b/rtl/gba_top.vhd index a0edbf6..6e3c594 100644 --- a/rtl/gba_top.vhd +++ b/rtl/gba_top.vhd @@ -2,6 +2,8 @@ library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; +library MEM; + use work.pProc_bus_gba.all; use work.pReg_savestates.all; @@ -33,9 +35,11 @@ entity gba_top is memory_remap : in std_logic; save_state : in std_logic; load_state : in std_logic; - interframe_blend : in std_logic; + interframe_blend : in std_logic_vector(1 downto 0); -- 0 = off, 1 = blend, 2 = 30hz maxpixels : in std_logic; -- limit pixels per line shade_mode : in std_logic_vector(2 downto 0); -- 0 = off, 1..4 modes + hdmode2x_bg : in std_logic; + hdmode2x_obj : in std_logic; specialmodule : in std_logic; -- 0 = off, 1 = use gamepak GPIO Port at address 0x080000C4..0x080000C8 solar_in : in std_logic_vector(2 downto 0); tilt : in std_logic; -- 0 = off, 1 = use tilt at address 0x0E008200, 0x0E008300, 0x0E008400, 0x0E008500 @@ -108,20 +112,28 @@ entity gba_top is GBA_BusReadData : out std_logic_vector(31 downto 0); GBA_Bus_written : in std_logic; -- display data - pixel_out_x : out integer range 0 to 239; - pixel_out_y : out integer range 0 to 159; - pixel_out_addr : out integer range 0 to 38399; -- address for framebuffer - pixel_out_data : out std_logic_vector(17 downto 0); -- RGB data for framebuffer - pixel_out_we : out std_logic; -- new pixel for framebuffer - -- sound - sound_out_left : out std_logic_vector(15 downto 0) := (others => '0'); - sound_out_right : out std_logic_vector(15 downto 0) := (others => '0'); - -- debug - debug_cpu_pc : out std_logic_vector(31 downto 0); - debug_cpu_mixed : out std_logic_vector(31 downto 0); - debug_irq : out std_logic_vector(31 downto 0); - debug_dma : out std_logic_vector(31 downto 0); - debug_mem : out std_logic_vector(31 downto 0) + pixel_out_x : buffer integer range 0 to 239; + pixel_out_y : buffer integer range 0 to 159; + pixel_out_addr : buffer integer range 0 to 38399; -- address for framebuffer + pixel_out_data : buffer std_logic_vector(17 downto 0); -- RGB data for framebuffer + pixel_out_we : buffer std_logic; -- new pixel for framebuffer + + largeimg_out_base : out std_logic_vector(31 downto 0) := x"38000000"; + largeimg_out_addr : buffer std_logic_vector(25 downto 0) := (others => '0'); + largeimg_out_data : out std_logic_vector(63 downto 0); + largeimg_out_req : out std_logic := '0'; + largeimg_out_done : in std_logic; + largeimg_newframe : in std_logic; + largeimg_singlebuf : in std_logic; + -- sound + sound_out_left : out std_logic_vector(15 downto 0) := (others => '0'); + sound_out_right : out std_logic_vector(15 downto 0) := (others => '0'); + -- debug + debug_cpu_pc : out std_logic_vector(31 downto 0); + debug_cpu_mixed : out std_logic_vector(31 downto 0); + debug_irq : out std_logic_vector(31 downto 0); + debug_dma : out std_logic_vector(31 downto 0); + debug_mem : out std_logic_vector(31 downto 0) ); end entity; @@ -322,6 +334,43 @@ architecture arch of gba_top is signal CyclesVsync : unsigned(31 downto 0) := (others => '0'); signal bench_slow : integer range 0 to 1685375 := 0; + -- large image out + signal pixel_out_2x : integer range 0 to 479; + signal pixel_out_data2x : std_logic_vector(17 downto 0); + signal pixel_out_we2x : std_logic := '0'; + signal pixel2_out_x : integer range 0 to 479; + signal pixel2_out_data : std_logic_vector(17 downto 0); + signal pixel2_out_we : std_logic; + + signal pixel_write_addr : integer range 0 to 239; + signal pixel_write_data : std_logic_vector(35 downto 0); + signal pixel_write_ena : std_logic := '0'; + + signal pixel2_write_addr : integer range 0 to 239; + signal pixel2_write_data : std_logic_vector(35 downto 0); + signal pixel2_write_ena : std_logic := '0'; + + type tstate is + ( + IDLE, + READPIXEL, + WRITEPIXEL + ); + signal state : tstate := IDLE; + + signal pixel_out_y_1 : integer range 0 to 159 := 0; + signal pixelpos : integer range 0 to 240 := 0; + signal pixelpos2 : integer range 0 to 240 := 0; + signal pixelcnt : integer range 0 to 3 := 0; + signal firstpixel : std_logic := '0'; + signal linebuffer_data : std_logic_vector(35 downto 0); + signal linebuffer2_data : std_logic_vector(35 downto 0); + signal pixeladdress : integer range 0 to 262143; + + signal newframe_sreg : std_logic_vector(2 downto 0) := (others => '0'); + signal current_frame : integer range 0 to 2 := 0; + signal frameoffset : integer range 0 to 2 := 0; + begin -- dummy modules @@ -770,14 +819,21 @@ begin interframe_blend => interframe_blend, maxpixels => maxpixels, shade_mode => shade_mode, + hdmode2x_bg => hdmode2x_bg, + hdmode2x_obj => hdmode2x_obj, bitmapdrawmode => bitmapdrawmode, pixel_out_x => pixel_out_x, + pixel_out_2x => pixel_out_2x, pixel_out_y => pixel_out_y, pixel_out_addr => pixel_out_addr, pixel_out_data => pixel_out_data, pixel_out_we => pixel_out_we, + + pixel2_out_x => pixel2_out_x, + pixel2_out_data => pixel2_out_data, + pixel2_out_we => pixel2_out_we, new_cycles => new_cycles, new_cycles_valid => new_cycles_valid, @@ -1030,6 +1086,158 @@ begin end if; end process; + -- large pixel out + process (clk100) + begin + if rising_edge(clk100) then + + pixel_write_ena <= '0'; + if (pixel_out_we = '1') then + pixel_write_addr <= pixel_out_2x / 2; + if (pixel_out_2x mod 2 = 0) then + pixel_write_data(17 downto 0) <= pixel_out_data; + else + pixel_write_data(35 downto 18) <= pixel_out_data; + pixel_write_ena <= '1'; + end if; + end if; + + pixel2_write_ena <= '0'; + if (pixel2_out_we = '1') then + pixel2_write_addr <= pixel2_out_x / 2; + if (pixel2_out_x mod 2 = 0) then + pixel2_write_data(17 downto 0) <= pixel2_out_data; + else + pixel2_write_data(35 downto 18) <= pixel2_out_data; + pixel2_write_ena <= '1'; + end if; + end if; + + end if; + end process; + + + ilinebuffer_hd0: entity MEM.SyncRamDual + generic map + ( + DATA_WIDTH => 36, + ADDR_WIDTH => 8 + ) + port map + ( + clk => clk100, + + addr_a => pixel_write_addr, + datain_a => pixel_write_data, + dataout_a => open, + we_a => pixel_write_ena, + re_a => '0', + + addr_b => pixelpos, + datain_b => (35 downto 0 => '0'), + dataout_b => linebuffer_data, + we_b => '0', + re_b => '1' + ); + + ilinebuffer_hd1: entity MEM.SyncRamDual + generic map + ( + DATA_WIDTH => 36, + ADDR_WIDTH => 8 + ) + port map + ( + clk => clk100, + + addr_a => pixel2_write_addr, + datain_a => pixel2_write_data, + dataout_a => open, + we_a => pixel2_write_ena, + re_a => '0', + + addr_b => pixelpos2, + datain_b => (35 downto 0 => '0'), + dataout_b => linebuffer2_data, + we_b => '0', + re_b => '1' + ); + + process (clk100) + begin + if rising_edge(clk100) then + + largeimg_out_req <= '0'; + + newframe_sreg <= newframe_sreg(1 downto 0) & largeimg_newframe; + if (newframe_sreg(2 downto 1) = "01") then + largeimg_out_base <= (std_logic_vector(to_unsigned(16#38000000# + frameoffset * 16#400000#, 32))); + end if; + + case (state) is + + when IDLE => + if (pixel_out_y_1 /= pixel_out_y and pixel_write_ena = '1' and (hdmode2x_bg = '1' or hdmode2x_obj = '1')) then + pixel_out_y_1 <= pixel_out_y; + state <= READPIXEL; + pixelpos <= 0; + pixelpos2 <= 0; + pixeladdress <= pixel_out_y * 1024; + if (pixel_out_y = 0) then + frameoffset <= current_frame; + --if (largeimg_singlebuf = '0') then + if (current_frame < 2) then + current_frame <= current_frame + 1; + else + current_frame <= 0; + end if; + --end if; + end if; + end if; + + when READPIXEL => + state <= WRITEPIXEL; + firstpixel <= '1'; + + when WRITEPIXEL => + firstpixel <= '0'; + if (largeimg_out_done = '1' or firstpixel = '1') then + + if (pixelcnt = 0) then + pixelcnt <= 1; + pixelpos <= pixelpos + 1; + else + pixelcnt <= 0; + pixelpos2 <= pixelpos2 + 1; + if (pixelpos2 < 239) then + pixeladdress <= pixeladdress + 2; + else + state <= IDLE; + end if; + end if; + + largeimg_out_req <= '1'; + case (pixelcnt) is + when 0 => + largeimg_out_addr <= "1" & std_logic_vector(to_unsigned(pixeladdress + current_frame * 16#100000#, 25)); + largeimg_out_data(31 downto 0) <= x"00" & linebuffer_data( 5 downto 0) & "00" & linebuffer_data(11 downto 6) & "00" & linebuffer_data(17 downto 12) & "00"; + largeimg_out_data(63 downto 32) <= x"00" & linebuffer_data(23 downto 18) & "00" & linebuffer_data(29 downto 24) & "00" & linebuffer_data(35 downto 30) & "00"; + when 1 => + largeimg_out_addr <= "1" & std_logic_vector(to_unsigned(pixeladdress + 512 + current_frame * 16#100000#, 25)); + largeimg_out_data(31 downto 0) <= x"00" & linebuffer2_data( 5 downto 0) & "00" & linebuffer2_data(11 downto 6) & "00" & linebuffer2_data(17 downto 12) & "00"; + largeimg_out_data(63 downto 32) <= x"00" & linebuffer2_data(23 downto 18) & "00" & linebuffer2_data(29 downto 24) & "00" & linebuffer2_data(35 downto 30) & "00"; + when others => null; + end case; + + end if; + + end case; + + + + end if; + end process; + end architecture; diff --git a/sim/src/tb/ddrram_model.vhd b/sim/src/tb/ddrram_model.vhd index 26b6037..0eceb5b 100644 --- a/sim/src/tb/ddrram_model.vhd +++ b/sim/src/tb/ddrram_model.vhd @@ -96,7 +96,6 @@ begin cmd_burst_save := DDRAM_BURSTCNT; cmd_din_save := DDRAM_DIN; cmd_be_save := DDRAM_BE; - wait until rising_edge(DDRAM_CLK); for i in 0 to (to_integer(unsigned(cmd_burst_save)) - 1) loop if (cmd_be_save(7 downto 4) = x"F") then data(to_integer(unsigned(cmd_address_save)) * 2 + (i * 2) + 1) := to_integer(signed(cmd_din_save(63 downto 32))); diff --git a/sim/src/tb/tb.vhd b/sim/src/tb/tb.vhd index a632adf..653dd2b 100644 --- a/sim/src/tb/tb.vhd +++ b/sim/src/tb/tb.vhd @@ -117,6 +117,12 @@ architecture arch of etb is signal pixel_out_y : integer range 0 to 159; signal pixel_out_data : std_logic_vector(17 downto 0); signal pixel_out_we : std_logic; + + signal largeimg_out_addr : std_logic_vector(25 downto 0); + signal largeimg_out_data : std_logic_vector(63 downto 0); + signal largeimg_out_req : std_logic; + signal largeimg_out_done : std_logic; + signal largeimg_newframe : std_logic; signal sound_out_left : std_logic_vector(15 downto 0); signal sound_out_right : std_logic_vector(15 downto 0); @@ -250,9 +256,11 @@ begin memory_remap => GBA_MemoryRemap(GBA_MemoryRemap'left), save_state => GBA_SaveState(GBA_SaveState'left), load_state => GBA_LoadState(GBA_LoadState'left), - interframe_blend => '0', --GBA_FrameBlend(GBA_FrameBlend'left), + interframe_blend => "00", maxpixels => '0', - shade_mode => GBA_Pixelshade, + shade_mode => "000", + hdmode2x_bg => '1', + hdmode2x_obj => '1', specialmodule => '0', solar_in => "000", tilt => '0', @@ -333,7 +341,14 @@ begin pixel_out_y => pixel_out_y, pixel_out_addr => open, pixel_out_data => pixel_out_data, - pixel_out_we => pixel_out_we, + pixel_out_we => pixel_out_we, + + largeimg_out_addr => largeimg_out_addr, + largeimg_out_data => largeimg_out_data, + largeimg_out_req => largeimg_out_req, + largeimg_out_done => largeimg_out_done, + largeimg_newframe => largeimg_newframe, + largeimg_singlebuf => '0', -- sound sound_out_left => sound_out_left, sound_out_right => sound_out_right, @@ -345,6 +360,7 @@ begin debug_mem => open --GBA_DEBUG_MEM ); + largeimg_newframe <= '1' when unsigned(largeimg_out_addr(19 downto 0)) = 0 else '0'; ch1_addr <= '0' & sdram_read_addr & "0"; ch1_req <= sdram_read_ena; @@ -406,7 +422,12 @@ begin ch4_din => ch4_din, ch4_req => ch4_req, ch4_rnw => ch4_rnw, - ch4_ready => ch4_ready + ch4_ready => ch4_ready, + + ch5_addr => (27 downto 1 => '0'), + ch5_din => (63 downto 0 => '0'), + ch5_req => largeimg_out_req, + ch5_ready => largeimg_out_done ); iddrram_model : entity tb.ddrram_model @@ -440,6 +461,21 @@ begin pixel_in_we => pixel_out_we ); + iframebuffer_large : entity work.framebuffer_large + generic map + ( + FRAMESIZE_X => 480, + FRAMESIZE_Y => 320 + ) + port map + ( + clk100 => clk100, + + pixel_in_addr => largeimg_out_addr, + pixel_in_data => largeimg_out_data, + pixel_in_we => largeimg_out_req, + pixel_in_done => open + ); iTestprocessor : entity procbus.eTestprocessor generic map diff --git a/sim/vcom_all.bat b/sim/vcom_all.bat index 20d1808..86f6ca8 100644 --- a/sim/vcom_all.bat +++ b/sim/vcom_all.bat @@ -3,9 +3,9 @@ vcom -93 -quiet -work sim/tb ^ src/tb/globals.vhd vcom -93 -quiet -work sim/mem ^ -../src/SyncRam.vhd ^ -../src/SyncRamDual.vhd ^ -../src/SyncRamDualNotPow2.vhd ^ +../rtl/SyncRam.vhd ^ +../rtl/SyncRamDual.vhd ^ +../rtl/SyncRamDualNotPow2.vhd ^ src/mem/SyncRamDualByteEnable.vhd ^ src/mem/SyncFifo.vhd @@ -23,55 +23,57 @@ vcom -quiet -work sim/reg_map ^ src/reg_map/reg_gameboy.vhd vcom -quiet -work sim/gba ^ -../src/proc_bus_gba.vhd ^ -../src/cache.vhd ^ -../src/reggba_timer.vhd ^ -../src/reggba_keypad.vhd ^ -../src/reggba_serial.vhd ^ -../src/reggba_sound.vhd ^ -../src/reggba_display.vhd ^ -../src/reggba_dma.vhd ^ -../src/reggba_system.vhd ^ -../src/reg_savestates.vhd ^ -../src/gba_bios_fast.vhd ^ -../src/gba_reservedregs.vhd ^ -../src/gba_sound_ch1.vhd ^ -../src/gba_sound_ch3.vhd ^ -../src/gba_sound_ch4.vhd ^ -../src/gba_sound_dma.vhd ^ -../src/gba_sound.vhd ^ -../src/gba_joypad.vhd ^ -../src/gba_serial.vhd ^ -../src/gba_dma_module.vhd ^ -../src/gba_dma.vhd ^ -../src/gba_memorymux.vhd ^ -../src/gba_timer_module.vhd ^ -../src/gba_timer.vhd ^ -../src/gba_gpu_timing.vhd ^ -../src/gba_drawer_mode0.vhd ^ -../src/gba_drawer_mode2.vhd ^ -../src/gba_drawer_mode345.vhd ^ -../src/gba_drawer_obj.vhd ^ -../src/gba_drawer_merge.vhd ^ -../src/gba_gpu_drawer.vhd ^ -../src/gba_gpu_colorshade.vhd ^ -../src/gba_gpu.vhd ^ -../src/gba_savestates.vhd ^ -../src/gba_statemanager.vhd ^ -../src/gba_cheats.vhd ^ -../src/gba_gpioRTCSolarGyro.vhd +../rtl/proc_bus_gba.vhd ^ +../rtl/cache.vhd ^ +../rtl/reggba_timer.vhd ^ +../rtl/reggba_keypad.vhd ^ +../rtl/reggba_serial.vhd ^ +../rtl/reggba_sound.vhd ^ +../rtl/reggba_display.vhd ^ +../rtl/reggba_dma.vhd ^ +../rtl/reggba_system.vhd ^ +../rtl/reg_savestates.vhd ^ +../rtl/gba_bios_fast.vhd ^ +../rtl/gba_reservedregs.vhd ^ +../rtl/gba_sound_ch1.vhd ^ +../rtl/gba_sound_ch3.vhd ^ +../rtl/gba_sound_ch4.vhd ^ +../rtl/gba_sound_dma.vhd ^ +../rtl/gba_sound.vhd ^ +../rtl/gba_joypad.vhd ^ +../rtl/gba_serial.vhd ^ +../rtl/gba_dma_module.vhd ^ +../rtl/gba_dma.vhd ^ +../rtl/gba_memorymux.vhd ^ +../rtl/gba_timer_module.vhd ^ +../rtl/gba_timer.vhd ^ +../rtl/gba_gpu_timing.vhd ^ +../rtl/gba_drawer_mode0.vhd ^ +../rtl/gba_drawer_mode2.vhd ^ +../rtl/gba_drawer_mode2_2x.vhd ^ +../rtl/gba_drawer_mode345.vhd ^ +../rtl/gba_drawer_obj.vhd ^ +../rtl/gba_drawer_merge.vhd ^ +../rtl/gba_gpu_drawer.vhd ^ +../rtl/gba_gpu_colorshade.vhd ^ +../rtl/gba_gpu.vhd ^ +../rtl/gba_savestates.vhd ^ +../rtl/gba_statemanager.vhd ^ +../rtl/gba_cheats.vhd ^ +../rtl/gba_gpioRTCSolarGyro.vhd vcom -2008 -quiet -work sim/gba ^ -../src/gba_cpu.vhd ^ -../src/gba_top.vhd +../rtl/gba_cpu.vhd ^ +../rtl/gba_top.vhd vlog -sv -quiet -work sim/top ^ -../ddram.sv +../rtl/ddram.sv vcom -quiet -work sim/tb ^ src/tb/stringprocessor.vhd ^ src/tb/tb_interpreter.vhd ^ src/tb/ddrram_model.vhd ^ src/tb/framebuffer.vhd ^ +src/tb/framebuffer_large.vhd ^ src/tb/tb.vhd diff --git a/sys/alsa.sv b/sys/alsa.sv index 061a287..9034389 100644 --- a/sys/alsa.sv +++ b/sys/alsa.sv @@ -20,6 +20,9 @@ //============================================================================ module alsa +#( + parameter CLK_RATE = 24576000 +) ( input reset, input clk, @@ -139,17 +142,14 @@ always @(posedge clk) begin end end -localparam F48K = 48000; -localparam F50M = 50000000; - reg ce_sample; always @(posedge clk) begin reg [31:0] acc = 0; ce_sample <= 0; - acc <= acc + F48K + {hurryup,6'd0}; - if(acc >= F50M) begin - acc <= acc - F50M; + acc <= acc + 48000 + {hurryup,6'd0}; + if(acc >= CLK_RATE) begin + acc <= acc - CLK_RATE; ce_sample <= 1; end end diff --git a/sys/arcade_video.v b/sys/arcade_video.v index ba86c9b..5fba687 100644 --- a/sys/arcade_video.v +++ b/sys/arcade_video.v @@ -2,258 +2,6 @@ // // Copyright (C) 2017-2020 Sorgelig // -//============================================================================ - -////////////////////////////////////////////////////////// -// DW: -// 6 : 2R 2G 2B -// 8 : 3R 3G 2B -// 9 : 3R 3G 3B -// 12 : 4R 4G 4B -// 24 : 8R 8G 8B - -module arcade_video #(parameter WIDTH=320, HEIGHT=240, DW=8, GAMMA=1) -( - input clk_video, - input ce_pix, - - input[DW-1:0] RGB_in, - input HBlank, - input VBlank, - input HSync, - input VSync, - - output VGA_CLK, - output VGA_CE, - output [7:0] VGA_R, - output [7:0] VGA_G, - output [7:0] VGA_B, - output VGA_HS, - output VGA_VS, - output VGA_DE, - - output HDMI_CLK, - output HDMI_CE, - output [7:0] HDMI_R, - output [7:0] HDMI_G, - output [7:0] HDMI_B, - output HDMI_HS, - output HDMI_VS, - output HDMI_DE, - output [1:0] HDMI_SL, - - input [2:0] fx, - input forced_scandoubler, - input no_rotate, - input rotate_ccw, - inout [21:0] gamma_bus -); - -wire [7:0] R,G,B; -wire CE,HS,VS,HBL,VBL; - -wire [DW-1:0] RGB_fix; -wire VGA_HBL, VGA_VBL; -arcade_vga #(DW) vga -( - .clk_video(clk_video), - .ce_pix(ce_pix), - - .RGB_in(RGB_in), - .HBlank(HBlank), - .VBlank(VBlank), - .HSync(HSync), - .VSync(VSync), - - .RGB_out(RGB_fix), - .VGA_CLK(VGA_CLK), - .VGA_CE(CE), - .VGA_R(R), - .VGA_G(G), - .VGA_B(B), - .VGA_HS(HS), - .VGA_VS(VS), - .VGA_HBL(HBL), - .VGA_VBL(VBL) -); - -wire [DW-1:0] RGB_out; -wire rhs,rvs,rhblank,rvblank; - -screen_rotate #(WIDTH,HEIGHT,DW,4) rotator -( - .clk(VGA_CLK), - .ce(CE), - - .ccw(rotate_ccw), - - .video_in(RGB_fix), - .hblank(HBL), - .vblank(VBL), - - .ce_out(CE | (~scandoubler & ~gamma_bus[19])), - .video_out(RGB_out), - .hsync(rhs), - .vsync(rvs), - .hblank_out(rhblank), - .vblank_out(rvblank) -); - -generate - if(DW == 6) begin - wire [3:0] Rr = {RGB_out[5:4],RGB_out[5:4]}; - wire [3:0] Gr = {RGB_out[3:2],RGB_out[3:2]}; - wire [3:0] Br = {RGB_out[1:0],RGB_out[1:0]}; - end - else if(DW == 8) begin - wire [3:0] Rr = {RGB_out[7:5],RGB_out[7]}; - wire [3:0] Gr = {RGB_out[4:2],RGB_out[4]}; - wire [3:0] Br = {RGB_out[1:0],RGB_out[1:0]}; - end - else if(DW == 9) begin - wire [3:0] Rr = {RGB_out[8:6],RGB_out[8]}; - wire [3:0] Gr = {RGB_out[5:3],RGB_out[5]}; - wire [3:0] Br = {RGB_out[2:0],RGB_out[2]}; - end - else if(DW == 12) begin - wire [3:0] Rr = RGB_out[11:8]; - wire [3:0] Gr = RGB_out[7:4]; - wire [3:0] Br = RGB_out[3:0]; - end - else begin // 24 - wire [7:0] Rr = RGB_out[23:16]; - wire [7:0] Gr = RGB_out[15:8]; - wire [7:0] Br = RGB_out[7:0]; - end -endgenerate - -assign HDMI_CLK = VGA_CLK; -assign HDMI_SL = sl[1:0]; -wire [2:0] sl = fx ? fx - 1'd1 : 3'd0; -wire scandoubler = fx || forced_scandoubler; - -video_mixer #(.LINE_LENGTH(WIDTH+4), .HALF_DEPTH(DW!=24), .GAMMA(GAMMA)) video_mixer -( - .clk_vid(HDMI_CLK), - .ce_pix(CE | (~scandoubler & ~gamma_bus[19] & ~no_rotate)), - .ce_pix_out(HDMI_CE), - - .scandoubler(scandoubler), - .hq2x(fx==1), - .gamma_bus(gamma_bus), - - .R(no_rotate ? ((DW!=24) ? R[7:4] : R) : Rr), - .G(no_rotate ? ((DW!=24) ? G[7:4] : G) : Gr), - .B(no_rotate ? ((DW!=24) ? B[7:4] : B) : Br), - - .HSync (no_rotate ? HS : rhs), - .VSync (no_rotate ? VS : rvs), - .HBlank(no_rotate ? HBL : rhblank), - .VBlank(no_rotate ? VBL : rvblank), - - .VGA_R(HDMI_R), - .VGA_G(HDMI_G), - .VGA_B(HDMI_B), - .VGA_VS(HDMI_VS), - .VGA_HS(HDMI_HS), - .VGA_DE(HDMI_DE) -); - -assign VGA_CE = no_rotate ? HDMI_CE : CE; -assign VGA_R = no_rotate ? HDMI_R : R; -assign VGA_G = no_rotate ? HDMI_G : G; -assign VGA_B = no_rotate ? HDMI_B : B; -assign VGA_HS = no_rotate ? HDMI_HS : HS; -assign VGA_VS = no_rotate ? HDMI_VS : VS; -assign VGA_DE = no_rotate ? HDMI_DE : ~(HBL | VBL); - -endmodule - -////////////////////////////////////////////////////////// - -module arcade_vga #(parameter DW) -( - input clk_video, - input ce_pix, - - input [DW-1:0] RGB_in, - input HBlank, - input VBlank, - input HSync, - input VSync, - - output[DW-1:0] RGB_out, - output VGA_CLK, - output reg VGA_CE, - output [7:0] VGA_R, - output [7:0] VGA_G, - output [7:0] VGA_B, - output reg VGA_HS, - output reg VGA_VS, - output reg VGA_HBL, - output reg VGA_VBL -); - -assign VGA_CLK = clk_video; - -wire hs_fix,vs_fix; -sync_fix sync_v(VGA_CLK, HSync, hs_fix); -sync_fix sync_h(VGA_CLK, VSync, vs_fix); - -reg [DW-1:0] RGB_fix; - -always @(posedge VGA_CLK) begin - reg old_ce; - old_ce <= ce_pix; - VGA_CE <= 0; - if(~old_ce & ce_pix) begin - VGA_CE <= 1; - VGA_HS <= hs_fix; - if(~VGA_HS & hs_fix) VGA_VS <= vs_fix; - - RGB_fix <= RGB_in; - VGA_HBL <= HBlank; - if(VGA_HBL & ~HBlank) VGA_VBL <= VBlank; - end -end - -assign RGB_out = RGB_fix; - -generate - if(DW == 6) begin - assign VGA_R = {RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4]}; - assign VGA_G = {RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2]}; - assign VGA_B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]}; - end - else if(DW == 8) begin - assign VGA_R = {RGB_fix[7:5],RGB_fix[7:5],RGB_fix[7:6]}; - assign VGA_G = {RGB_fix[4:2],RGB_fix[4:2],RGB_fix[4:3]}; - assign VGA_B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]}; - end - else if(DW == 9) begin - assign VGA_R = {RGB_fix[8:6],RGB_fix[8:6],RGB_fix[8:7]}; - assign VGA_G = {RGB_fix[5:3],RGB_fix[5:3],RGB_fix[5:4]}; - assign VGA_B = {RGB_fix[2:0],RGB_fix[2:0],RGB_fix[2:1]}; - end - else if(DW == 12) begin - assign VGA_R = {RGB_fix[11:8],RGB_fix[11:8]}; - assign VGA_G = {RGB_fix[7:4],RGB_fix[7:4]}; - assign VGA_B = {RGB_fix[3:0],RGB_fix[3:0]}; - end - else begin // 24 - assign VGA_R = RGB_fix[23:16]; - assign VGA_G = RGB_fix[15:8]; - assign VGA_B = RGB_fix[7:0]; - end -endgenerate - -endmodule - -//============================================================================ -// -// Screen +90/-90 deg. rotation -// Copyright (C) 2017-2019 Sorgelig -// // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or (at your option) @@ -267,139 +15,278 @@ endmodule // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// //============================================================================ -// -// Output timings are incompatible with any TV/VGA mode. -// The output is supposed to be send to scaler input. -// -module screen_rotate #(parameter WIDTH=320, HEIGHT=240, DEPTH=8, MARGIN=4) +////////////////////////////////////////////////////////// +// DW: +// 6 : 2R 2G 2B +// 8 : 3R 3G 2B +// 9 : 3R 3G 3B +// 12 : 4R 4G 4B +// 24 : 8R 8G 8B + +module arcade_video #(parameter WIDTH=320, DW=8, GAMMA=1) ( - input clk, - input ce, + input clk_video, + input ce_pix, - input ccw, + input[DW-1:0] RGB_in, + input HBlank, + input VBlank, + input HSync, + input VSync, - input [DEPTH-1:0] video_in, - input hblank, - input vblank, + output CLK_VIDEO, + output CE_PIXEL, + output [7:0] VGA_R, + output [7:0] VGA_G, + output [7:0] VGA_B, + output VGA_HS, + output VGA_VS, + output VGA_DE, + output [1:0] VGA_SL, - input ce_out, - output [DEPTH-1:0] video_out, - output reg hsync, - output reg vsync, - output reg hblank_out, - output reg vblank_out + input [2:0] fx, + input forced_scandoubler, + inout [21:0] gamma_bus ); -localparam bufsize = WIDTH*HEIGHT; -localparam memsize = bufsize*2; -localparam aw = $clog2(memsize); // resolutions up to ~ 512x256 +assign CLK_VIDEO = clk_video; -reg [aw-1:0] addr_in, addr_out; -reg we_in; -reg buff = 0; +wire hs_fix,vs_fix; +sync_fix sync_v(CLK_VIDEO, HSync, hs_fix); +sync_fix sync_h(CLK_VIDEO, VSync, vs_fix); -(* ramstyle="no_rw_check" *) reg [DEPTH-1:0] ram[memsize]; -always @ (posedge clk) if (en_we) ram[addr_in] <= video_in; -always @ (posedge clk) out <= ram[addr_out]; +reg [DW-1:0] RGB_fix; -reg [DEPTH-1:0] out; -reg [DEPTH-1:0] vout; +reg CE,HS,VS,HBL,VBL; +always @(posedge CLK_VIDEO) begin + reg old_ce; + old_ce <= ce_pix; + CE <= 0; + if(~old_ce & ce_pix) begin + CE <= 1; + HS <= hs_fix; + if(~HS & hs_fix) VS <= vs_fix; -assign video_out = vout; - -wire en_we = ce & ~blank & en_x & en_y; -wire en_x = (xpos=MARGIN) && (yposo (HEIGHT + 16)) begin - xposo <= 0; - - if(yposo >= (WIDTH+MARGIN+MARGIN)) begin - vblank_out <= 1; - vbcnt <= vbcnt + 1; - if(vbcnt == 10 ) vsync <= 1; - if(vbcnt == 12) vsync <= 0; - end - else yposo <= yposo + 1; - - old_buff <= buff; - if(old_buff != buff) begin - addr_out <= buff ? {aw{1'b0}} : bufsize[aw-1:0]; - yposo <= 0; - vsync <= 0; - vbcnt <= 0; - vblank_out <= 0; - end - end +generate + if(DW == 6) begin + assign R = {RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4]}; + assign G = {RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2]}; + assign B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]}; end - - if(ced) begin - if((yposd=WIDTH+MARGIN)) begin - vout <= 0; - end else begin - vout <= out; + else if(DW == 8) begin + assign R = {RGB_fix[7:5],RGB_fix[7:5],RGB_fix[7:6]}; + assign G = {RGB_fix[4:2],RGB_fix[4:2],RGB_fix[4:3]}; + assign B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]}; + end + else if(DW == 9) begin + assign R = {RGB_fix[8:6],RGB_fix[8:6],RGB_fix[8:7]}; + assign G = {RGB_fix[5:3],RGB_fix[5:3],RGB_fix[5:4]}; + assign B = {RGB_fix[2:0],RGB_fix[2:0],RGB_fix[2:1]}; + end + else if(DW == 12) begin + assign R = {RGB_fix[11:8],RGB_fix[11:8]}; + assign G = {RGB_fix[7:4],RGB_fix[7:4]}; + assign B = {RGB_fix[3:0],RGB_fix[3:0]}; + end + else begin // 24 + assign R = RGB_fix[23:16]; + assign G = RGB_fix[15:8]; + assign B = RGB_fix[7:0]; + end +endgenerate + +assign VGA_SL = sl[1:0]; +wire [2:0] sl = fx ? fx - 1'd1 : 3'd0; +wire scandoubler = fx || forced_scandoubler; + +video_mixer #(.LINE_LENGTH(WIDTH+4), .HALF_DEPTH(DW!=24), .GAMMA(GAMMA)) video_mixer +( + .clk_vid(CLK_VIDEO), + .ce_pix(CE), + .ce_pix_out(CE_PIXEL), + + .scandoubler(scandoubler), + .hq2x(fx==1), + .gamma_bus(gamma_bus), + + .R((DW!=24) ? R[7:4] : R), + .G((DW!=24) ? G[7:4] : G), + .B((DW!=24) ? B[7:4] : B), + + .HSync (HS), + .VSync (VS), + .HBlank(HBL), + .VBlank(VBL), + + .VGA_R(VGA_R), + .VGA_G(VGA_G), + .VGA_B(VGA_B), + .VGA_VS(VGA_VS), + .VGA_HS(VGA_HS), + .VGA_DE(VGA_DE) +); + +endmodule + +//============================================================================ +// +// Screen +90/-90 deg. rotation +// Copyright (C) 2020 Sorgelig +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ + +module screen_rotate +( + input CLK_VIDEO, + input CE_PIXEL, + + input [7:0] VGA_R, + input [7:0] VGA_G, + input [7:0] VGA_B, + input VGA_HS, + input VGA_VS, + input VGA_DE, + + input rotate_ccw, + input no_rotate, + + output FB_EN, + output [4:0] FB_FORMAT, + output [11:0] FB_WIDTH, + output [11:0] FB_HEIGHT, + output [31:0] FB_BASE, + input FB_VBL, + input FB_LL, + + output DDRAM_CLK, + input DDRAM_BUSY, + output [7:0] DDRAM_BURSTCNT, + output [28:0] DDRAM_ADDR, + output [63:0] DDRAM_DIN, + output [7:0] DDRAM_BE, + output DDRAM_WE, + output DDRAM_RD +); + +assign DDRAM_CLK = CLK_VIDEO; +assign DDRAM_BURSTCNT = 1; +assign DDRAM_ADDR = {6'b001001, i_fb, ram_addr[23:3]}; // RAM at 0x24000000 +assign DDRAM_BE = ram_addr[2] ? 8'hF0 : 8'h0F; +assign DDRAM_DIN = {ram_data,ram_data}; +assign DDRAM_WE = ram_wr; +assign DDRAM_RD = 0; + +assign FB_EN = ~no_rotate; +assign FB_FORMAT = 5'b00110; +assign FB_BASE = {6'b001001,o_fb,24'd0}; +assign FB_WIDTH = vsz; +assign FB_HEIGHT = hsz; + +function [1:0] buf_next; + input [1:0] a,b; + begin + buf_next = 1; + if ((a==0 && b==1) || (a==1 && b==0)) buf_next = 2; + if ((a==1 && b==2) || (a==2 && b==1)) buf_next = 0; + end +endfunction + +reg [1:0] i_fb,o_fb; +always @(posedge CLK_VIDEO) begin + reg old_vbl,old_vs; + old_vbl <= FB_VBL; + old_vs <= VGA_VS; + + if(FB_LL) begin + if(~old_vbl & FB_VBL) o_fb<={1'b0,~i_fb[0]}; + if(~old_vs & VGA_VS) i_fb<={1'b0,~i_fb[0]}; + end + else begin + if(~old_vbl & FB_VBL) o_fb<=buf_next(o_fb,i_fb); + if(~old_vs & VGA_VS) i_fb<=buf_next(i_fb,o_fb); + end +end + +reg [11:0] hsz = 320, vsz = 240; +reg [13:0] bwidth; +reg [23:0] bufsize; +always @(posedge CLK_VIDEO) begin + reg [11:0] hcnt = 0, vcnt = 0; + reg old_vs, old_de; + + if(CE_PIXEL) begin + old_vs <= VGA_VS; + old_de <= VGA_DE; + + hcnt <= hcnt + 1'd1; + if(~old_de & VGA_DE) begin + hcnt <= 1; + vcnt <= vcnt + 1'd1; + end + if(old_de & ~VGA_DE) hsz <= hcnt; + if(~old_vs & VGA_VS) begin + vsz <= vcnt; + vcnt <= 0; + end + bwidth <= {vsz, 2'b00} + 14'd255; + + if(old_vs & ~VGA_VS) bufsize <= hsz * stride; + end +end + +wire [13:0] stride = {bwidth[13:8], 8'h00}; + +reg [23:0] ram_addr, next_addr; +reg [31:0] ram_data; +reg ram_wr; +always @(posedge CLK_VIDEO) begin + reg [13:0] hcnt = 0; + reg old_vs, old_de; + + ram_wr <= 0; + if(CE_PIXEL) begin + old_vs <= VGA_VS; + old_de <= VGA_DE; + + if(~old_vs & VGA_VS) begin + next_addr <= rotate_ccw ? (bufsize - stride) : {vsz-1'd1, 2'b00}; + hcnt <= rotate_ccw ? 3'd4 : {vsz-2'd2, 2'b00}; + end + if(VGA_DE) begin + ram_wr <= 1; + ram_data <= {VGA_B,VGA_G,VGA_R}; + ram_addr <= next_addr; + next_addr <= rotate_ccw ? (next_addr - stride) : (next_addr + stride); + end + if(old_de & ~VGA_DE) begin + next_addr <= rotate_ccw ? (bufsize - stride + hcnt) : hcnt; + hcnt <= rotate_ccw ? (hcnt + 3'd4) : (hcnt - 3'd4); end - if(xposd == 0) hblank_out <= 0; - if(xposd == HEIGHT) hblank_out <= 1; end end diff --git a/sys/ascal.vhd b/sys/ascal.vhd index 0f89a9e..d15bffa 100644 --- a/sys/ascal.vhd +++ b/sys/ascal.vhd @@ -148,8 +148,9 @@ ENTITY ascal IS o_hs : OUT std_logic; -- H sync o_vs : OUT std_logic; -- V sync o_de : OUT std_logic; -- Display Enable + o_vbl : OUT std_logic; -- V blank o_ce : IN std_logic; -- Clock Enable - o_clk : IN std_logic; -- Output clock + o_clk : IN std_logic; -- Output clock -- Border colour R G B o_border : IN unsigned(23 DOWNTO 0) := x"000000"; @@ -287,7 +288,7 @@ ARCHITECTURE rtl OF ascal IS TYPE arr_uv36 IS ARRAY (natural RANGE <>) OF unsigned(35 DOWNTO 0); TYPE arr_int9 IS ARRAY (natural RANGE <>) OF integer RANGE -256 TO 255; TYPE arr_uint12 IS ARRAY (natural RANGE <>) OF uint12; - + ---------------------------------------------------------- -- Input image SIGNAL i_pvs,i_pfl,i_pde,i_pce : std_logic; @@ -385,12 +386,12 @@ ARCHITECTURE rtl OF ascal IS SIGNAL o_run : std_logic; SIGNAL o_mode,o_hmode,o_vmode : unsigned(4 DOWNTO 0); SIGNAL o_format : unsigned(5 DOWNTO 0); - SIGNAL o_fb_pal_dr : unsigned(23 DOWNTO 0); - SIGNAL o_fb_pal_dr_x2 : unsigned(47 DOWNTO 0); - SIGNAL pal_idx: unsigned(7 DOWNTO 0); - SIGNAL pal_idx_lsb: std_logic; - SIGNAL pal_mem : arr_uv48(0 TO 127); - ATTRIBUTE ramstyle of pal_mem : signal is "no_rw_check"; + SIGNAL o_fb_pal_dr : unsigned(23 DOWNTO 0); + SIGNAL o_fb_pal_dr_x2 : unsigned(47 DOWNTO 0); + SIGNAL pal_idx: unsigned(7 DOWNTO 0); + SIGNAL pal_idx_lsb: std_logic; + SIGNAL pal_mem : arr_uv48(0 TO 127); + ATTRIBUTE ramstyle of pal_mem : signal is "no_rw_check"; SIGNAL o_htotal,o_hsstart,o_hsend : uint12; SIGNAL o_hmin,o_hmax,o_hdisp : uint12; SIGNAL o_hsize,o_vsize : uint12; @@ -430,7 +431,7 @@ ARCHITECTURE rtl OF ascal IS SIGNAL o_vfrac,o_hfrac,o_hfrac1,o_hfrac2,o_hfrac3,o_hfrac4 : unsigned(11 DOWNTO 0); SIGNAL o_hacc,o_hacc_ini,o_hacc_next,o_vacc,o_vacc_next,o_vacc_ini : natural RANGE 0 TO 4*OHRES-1; - SIGNAL o_hsv,o_vsv,o_dev,o_pev : unsigned(0 TO 5); + SIGNAL o_hsv,o_vsv,o_dev,o_pev,o_end : unsigned(0 TO 5); SIGNAL o_hsp,o_vss : std_logic; SIGNAL o_read,o_read_pre : std_logic; SIGNAL o_readlev,o_copylev : natural RANGE 0 TO 2; @@ -2049,10 +2050,10 @@ BEGIN pal_dr<=pal_mem(to_integer(pal_a)); END IF; END PROCESS; - - pal_idx <= shift_opack(o_acpt4,o_shift,o_dr,o_format)(0 TO 7); - pal_idx_lsb <= pal_idx(0) WHEN rising_edge(o_clk); - o_fb_pal_dr_x2 <= pal_mem(to_integer(pal_idx(7 DOWNTO 1))) WHEN rising_edge(o_clk); + + pal_idx <= shift_opack(o_acpt4,o_shift,o_dr,o_format)(0 TO 7); + pal_idx_lsb <= pal_idx(0) WHEN rising_edge(o_clk); + o_fb_pal_dr_x2 <= pal_mem(to_integer(pal_idx(7 DOWNTO 1))) WHEN rising_edge(o_clk); o_fb_pal_dr <= o_fb_pal_dr_x2(47 DOWNTO 24) WHEN pal_idx_lsb = '1' ELSE o_fb_pal_dr_x2(23 DOWNTO 0); END GENERATE GenPal; @@ -2152,7 +2153,7 @@ BEGIN o_copyv(1 TO 8)<=o_copyv(0 TO 7); o_dcptv(1)<=o_dcpt; - IF o_dcptv(1)>o_hsize THEN + IF o_dcptv(1)>=o_hsize THEN o_copyv(2)<='0'; END IF; o_dcptv(2)<=o_dcptv(1) MOD OHRES; @@ -2283,6 +2284,7 @@ BEGIN o_vcpt<=o_vcpt_pre; END IF; + o_end(0)<=to_std_logic(o_vcpt>=o_vdisp); o_dev(0)<=to_std_logic(o_hcpt=o_hmin AND o_hcpt<=o_hmax AND o_vcpt>=o_vmin AND o_vcpt<=o_vmax); @@ -2296,12 +2298,14 @@ BEGIN o_vsv(1 TO 5)<=o_vsv(0 TO 4); o_dev(1 TO 5)<=o_dev(0 TO 4); o_pev(1 TO 5)<=o_pev(0 TO 4); + o_end(1 TO 5)<=o_end(0 TO 4); IF o_run='0' THEN o_hsv(2)<='0'; o_vsv(2)<='0'; o_dev(2)<='0'; o_pev(2)<='0'; + o_end(2)<='0'; END IF; END IF; @@ -2401,6 +2405,7 @@ BEGIN o_hs<=o_hsv(5); o_vs<=o_vsv(5); o_de<=o_dev(5); + o_vbl<=o_end(5); o_r<=x"00"; o_g<=x"00"; o_b<=x"00"; diff --git a/sys/audio_out.v b/sys/audio_out.v index 545f3b9..3c24f25 100644 --- a/sys/audio_out.v +++ b/sys/audio_out.v @@ -1,7 +1,7 @@ module audio_out #( - parameter CLK_RATE = 50000000 + parameter CLK_RATE = 24576000 ) ( input reset, @@ -10,8 +10,24 @@ module audio_out //0 - 48KHz, 1 - 96KHz input sample_rate, - input [15:0] left_in, - input [15:0] right_in, + input [31:0] flt_rate, + input [39:0] cx, + input [7:0] cx0, + input [7:0] cx1, + input [7:0] cx2, + input [23:0] cy0, + input [23:0] cy1, + input [23:0] cy2, + + input [4:0] att, + input [1:0] mix, + + input is_signed, + input [15:0] core_l, + input [15:0] core_r, + + input [15:0] alsa_l, + input [15:0] alsa_r, // I2S output i2s_bclk, @@ -56,19 +72,6 @@ always @(posedge clk) begin end end -reg lpf_ce; -always @(posedge clk) begin - integer div; - lpf_ce <= 0; - if(mclk_ce) begin - div <= div + 1; - if(div == FILTER_DIV) begin - div <= 0; - lpf_ce <= 1; - end - end -end - i2s i2s ( .reset(reset), @@ -111,47 +114,183 @@ sigma_delta_dac #(15) sd_r .DACout(dac_r) ); -wire [15:0] al, ar; -lpf_aud lpf_l -( - .CLK(clk), - .CE(lpf_ce), - .IDATA(left_in), - .ODATA(al) -); +reg sample_ce; +always @(posedge clk) begin + reg [8:0] div = 0; + reg [1:0] add = 0; -lpf_aud lpf_r -( - .CLK(clk), - .CE(lpf_ce), - .IDATA(right_in), - .ODATA(ar) -); + div <= div + add; + if(!div) begin + div <= 2'd1 << sample_rate; + add <= 2'd1 << sample_rate; + end -endmodule - -module lpf_aud -( - input CLK, - input CE, - input [15:0] IDATA, - output reg [15:0] ODATA -); - -reg [511:0] acc; -reg [20:0] sum; - -always @(*) begin - integer i; - sum = 0; - for (i = 0; i < 32; i = i+1) sum = sum + {{5{acc[(i*16)+15]}}, acc[i*16 +:16]}; + sample_ce <= !div; end -always @(posedge CLK) begin - if(CE) begin - acc <= {acc[495:0], IDATA}; - ODATA <= sum[20:5]; +reg flt_ce; +always @(posedge clk) begin + reg [31:0] cnt = 0; + + flt_ce <= 0; + cnt = cnt + {flt_rate[30:0],1'b0}; + if(cnt >= CLK_RATE) begin + cnt = cnt - CLK_RATE; + flt_ce <= 1; end end +reg [15:0] cl,cr; +always @(posedge clk) begin + reg [15:0] cl1,cl2; + reg [15:0] cr1,cr2; + + cl1 <= core_l; cl2 <= cl1; + if(cl2 == cl1) cl <= cl2; + + cr1 <= core_r; cr2 <= cr1; + if(cr2 == cr1) cr <= cr2; +end + +reg a_en1 = 0, a_en2 = 0; +always @(posedge clk, posedge reset) begin + reg [1:0] dly1 = 0; + reg [14:0] dly2 = 0; + + if(reset) begin + dly1 <= 0; + dly2 <= 0; + a_en1 <= 0; + a_en2 <= 0; + end + else begin + if(flt_ce) begin + if(~&dly1) dly1 <= dly1 + 1'd1; + else a_en1 <= 1; + end + + if(sample_ce) begin + if(!dly2[13+sample_rate]) dly2 <= dly2 + 1'd1; + else a_en2 <= 1; + end + end +end + +wire [15:0] acl, acr; +IIR_filter #(.use_params(0)) IIR_filter +( + .clk(clk), + .reset(reset), + + .ce(flt_ce & a_en1), + .sample_ce(sample_ce), + + .cx(cx), + .cx0(cx0), + .cx1(cx1), + .cx2(cx2), + .cy0(cy0), + .cy1(cy1), + .cy2(cy2), + + .input_l({~is_signed ^ cl[15], cl[14:0]}), + .input_r({~is_signed ^ cr[15], cr[14:0]}), + .output_l(acl), + .output_r(acr) +); + +wire [15:0] adl; +DC_blocker dcb_l +( + .clk(clk), + .ce(sample_ce), + .sample_rate(sample_rate), + .mute(~a_en2), + .din(acl), + .dout(adl) +); + +wire [15:0] adr; +DC_blocker dcb_r +( + .clk(clk), + .ce(sample_ce), + .sample_rate(sample_rate), + .mute(~a_en2), + .din(acr), + .dout(adr) +); + +wire [15:0] al, audio_l_pre; +aud_mix_top audmix_l +( + .clk(clk), + .ce(sample_ce), + .att(att), + .mix(mix), + + .core_audio(adl), + .pre_in(audio_r_pre), + .linux_audio(alsa_l), + + .pre_out(audio_l_pre), + .out(al) +); + +wire [15:0] ar, audio_r_pre; +aud_mix_top audmix_r +( + .clk(clk), + .ce(sample_ce), + .att(att), + .mix(mix), + + .core_audio(adr), + .pre_in(audio_l_pre), + .linux_audio(alsa_r), + + .pre_out(audio_r_pre), + .out(ar) +); + +endmodule + +module aud_mix_top +( + input clk, + input ce, + + input [4:0] att, + input [1:0] mix, + + input [15:0] core_audio, + input [15:0] linux_audio, + input [15:0] pre_in, + + output reg [15:0] pre_out = 0, + output reg [15:0] out = 0 +); + +reg signed [16:0] a1, a2, a3, a4; +always @(posedge clk) if (ce) begin + + a1 <= {core_audio[15],core_audio}; + a2 <= a1 + {linux_audio[15],linux_audio}; + + pre_out <= a2[16:1]; + + case(mix) + 0: a3 <= a2; + 1: a3 <= $signed(a2) - $signed(a2[16:3]) + $signed(pre_in[15:2]); + 2: a3 <= $signed(a2) - $signed(a2[16:2]) + $signed(pre_in[15:1]); + 3: a3 <= {a2[16],a2[16:1]} + {pre_in[15],pre_in}; + endcase + + if(att[4]) a4 <= 0; + else a4 <= a3 >>> att[3:0]; + + //clamping + out <= ^a4[16:15] ? {a4[16],{15{a4[15]}}} : a4[15:0]; +end + endmodule diff --git a/sys/hps_io.v b/sys/hps_io.v index 1f37785..e79a84f 100644 --- a/sys/hps_io.v +++ b/sys/hps_io.v @@ -279,6 +279,7 @@ always@(posedge clk_sys) begin sd_ack_conf <= 0; io_dout <= 0; ps2skip <= 0; + img_mounted <= 0; end else if(io_strobe) begin @@ -297,10 +298,10 @@ always@(posedge clk_sys) begin 'h2F: io_dout <= 1; 'h32: io_dout <= gamma_bus[21]; 'h36: begin io_dout <= info_n; info_n <= 0; end + 'h39: io_dout <= 1; endcase sd_buff_addr <= 0; - img_mounted <= 0; if(io_din == 5) ps2_key_raw <= 0; end else begin diff --git a/sys/pll_q13.qip b/sys/pll_q13.qip index 7018c53..13a7ed4 100644 --- a/sys/pll_q13.qip +++ b/sys/pll_q13.qip @@ -1,5 +1,6 @@ set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll.13.qip ] set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.13.qip ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_audio.13.qip ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_cfg.v ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_cfg/altera_pll_reconfig_core.v ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_cfg/altera_pll_reconfig_top.v ] diff --git a/sys/pll_q17.qip b/sys/pll_q17.qip index 5bc92e0..85cc84b 100644 --- a/sys/pll_q17.qip +++ b/sys/pll_q17.qip @@ -1,3 +1,4 @@ set_global_assignment -name QIP_FILE rtl/pll.qip set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.qip ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_audio.qip ] set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_cfg.qip ] diff --git a/sys/sys.qip b/sys/sys.qip index 3a594df..9a28ae0 100644 --- a/sys/sys.qip +++ b/sys/sys.qip @@ -17,11 +17,12 @@ set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) a set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2s.v ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) spdif.v ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) audio_out.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) iir_filter.v ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ltc2308.sv ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sigma_delta_dac.v ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hdmi_config.sv ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mcp23009.sv ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ddr_svc.sv ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sysmem.sv ] -set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sd_card.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sd_card.sv ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) hps_io.v ] diff --git a/sys/sys_top.sdc b/sys/sys_top.sdc index 67619ac..90dc24d 100644 --- a/sys/sys_top.sdc +++ b/sys/sys_top.sdc @@ -12,6 +12,8 @@ derive_clock_uncertainty set_clock_groups -exclusive \ -group [get_clocks { *|pll|pll_inst|altera_pll_i|*[*].*|divclk}] \ -group [get_clocks { pll_hdmi|pll_hdmi_inst|altera_pll_i|*[0].*|divclk}] \ + -group [get_clocks { pll_audio|pll_audio_inst|altera_pll_i|*[0].*|divclk}] \ + -group [get_clocks { spi_sck}] \ -group [get_clocks { *|h2f_user0_clk}] \ -group [get_clocks { FPGA_CLK1_50 }] \ -group [get_clocks { FPGA_CLK2_50 }] \ @@ -45,7 +47,8 @@ set_false_path -to {*_osd|half} set_false_path -to {WIDTH[*] HFP[*] HS[*] HBP[*] HEIGHT[*] VFP[*] VS[*] VBP[*]} set_false_path -from {WIDTH[*] HFP[*] HS[*] HBP[*] HEIGHT[*] VFP[*] VS[*] VBP[*]} -set_false_path -to {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] FB_HMIN[*] FB_HMAX[*] FB_VMIN[*] FB_VMAX[*]} -set_false_path -from {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] FB_HMIN[*] FB_HMAX[*] FB_VMIN[*] FB_VMAX[*]} +set_false_path -to {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] LFB_HMAX[*] LFB_VMIN[*] LFB_VMAX[*]} +set_false_path -from {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] LFB_HMAX[*] LFB_VMIN[*] LFB_VMAX[*]} set_false_path -to {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} set_false_path -from {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} +set_false_path -from {aflt_* acx* acy* areset*} diff --git a/sys/sys_top.v b/sys/sys_top.v index c8ef6f7..ac4c6ae 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -24,6 +24,13 @@ `define USE_SDRAM `endif +`ifndef USE_DDRAM + `ifdef USE_FB + `define USE_DDRAM + `endif +`endif + + module sys_top ( /////////// CLOCK ////////// @@ -236,7 +243,10 @@ wire io_ss0 = gp_outr[18]; wire io_ss1 = gp_outr[19]; wire io_ss2 = gp_outr[20]; +`ifndef DEBUG_NOHDMI wire io_osd_hdmi = io_ss1 & ~io_ss0; +`endif + wire io_fpga = ~io_ss1 & io_ss0; wire io_uio = ~io_ss1 & io_ss2; @@ -276,11 +286,16 @@ cyclonev_hps_interface_mpu_general_purpose h2f_gp reg [15:0] cfg; -reg cfg_got = 0; reg cfg_set = 0; wire vga_fb = cfg[12]; wire [1:0] hdmi_limited = {cfg[11],cfg[8]}; + +`ifdef DEBUG_NOHDMI +wire direct_video = 1; +`else wire direct_video = cfg[10]; +`endif + wire dvi_mode = cfg[7]; wire audio_96k = cfg[6]; wire csync_en = cfg[3]; @@ -312,12 +327,24 @@ reg vs_wait = 0; reg [11:0] vs_line = 0; reg scaler_out = 0; + +reg [31:0] aflt_rate = 7056000; +reg [39:0] acx = 4258969; +reg [7:0] acx0 = 3; +reg [7:0] acx1 = 3; +reg [7:0] acx2 = 1; +reg [23:0] acy0 = -24'd6216759; +reg [23:0] acy1 = 24'd6143386; +reg [23:0] acy2 = -24'd2023767; +reg areset = 0; + always@(posedge clk_sys) begin reg [7:0] cmd; reg has_cmd; reg old_strobe; reg [7:0] cnt = 0; reg vs_d0,vs_d1,vs_d2; + reg [4:0] acx_att; old_strobe <= io_strobe; coef_wr <= 0; @@ -325,6 +352,9 @@ always@(posedge clk_sys) begin if(~io_uio) begin has_cmd <= 0; cmd <= 0; + areset <= 0; + acx_att <= 0; + acx <= acx >> acx_att; end else if(~old_strobe & io_strobe) begin @@ -333,6 +363,17 @@ always@(posedge clk_sys) begin cmd <= io_din[7:0]; cnt <= 0; if(io_din[7:0] == 'h30) vs_wait <= 1; + if(io_din[7:0] == 'h39) begin + aflt_rate <= 7056000; + acx <= 4258969; + acx0 <= 3; + acx1 <= 3; + acx2 <= 1; + acy0 <= -24'd6216759; + acy1 <= 24'd6143386; + acy2 <= -24'd2023767; + areset <= 1; + end end else begin if(cmd == 1) begin @@ -354,6 +395,7 @@ always@(posedge clk_sys) begin 6: if(VS != io_din[11:0]) VS <= io_din[11:0]; 7: if(VBP != io_din[11:0]) VBP <= io_din[11:0]; endcase +`ifndef DEBUG_NOHDMI if(cnt == 1) begin cfg_custom_p1 <= 0; cfg_custom_p2 <= 0; @@ -369,20 +411,21 @@ always@(posedge clk_sys) begin cnt[2:0] <= 3'b100; end if(cnt == 8) {lowlat,cfg_dis} <= io_din[15:14]; +`endif end end if(cmd == 'h2F) begin cnt <= cnt + 1'd1; case(cnt[3:0]) - 0: {FB_EN,FB_FLT,FB_FMT} <= {io_din[15], io_din[14], io_din[5:0]}; - 1: FB_BASE[15:0] <= io_din[15:0]; - 2: FB_BASE[31:16] <= io_din[15:0]; - 3: FB_WIDTH <= io_din[11:0]; - 4: FB_HEIGHT <= io_din[11:0]; - 5: FB_HMIN <= io_din[11:0]; - 6: FB_HMAX <= io_din[11:0]; - 7: FB_VMIN <= io_din[11:0]; - 8: FB_VMAX <= io_din[11:0]; + 0: {LFB_EN,LFB_FLT,LFB_FMT} <= {io_din[15], io_din[14], io_din[5:0]}; + 1: LFB_BASE[15:0] <= io_din[15:0]; + 2: LFB_BASE[31:16] <= io_din[15:0]; + 3: LFB_WIDTH <= io_din[11:0]; + 4: LFB_HEIGHT <= io_din[11:0]; + 5: LFB_HMIN <= io_din[11:0]; + 6: LFB_HMAX <= io_din[11:0]; + 7: LFB_VMIN <= io_din[11:0]; + 8: LFB_VMAX <= io_din[11:0]; endcase end if(cmd == 'h25) {led_overtake, led_state} <= io_din; @@ -392,6 +435,26 @@ always@(posedge clk_sys) begin if(cmd == 'h2B) scaler_flt <= io_din[2:0]; if(cmd == 'h37) {FREESCALE,HSET} <= {io_din[15],io_din[11:0]}; if(cmd == 'h38) vs_line <= io_din[11:0]; + if(cmd == 'h39) begin + cnt <= cnt + 1'd1; + case(cnt[3:0]) + 0: acx_att <= io_din[4:0]; + 1: aflt_rate[15:0] <= io_din; + 2: aflt_rate[31:16] <= io_din; + 3: acx[15:0] <= io_din; + 4: acx[31:16] <= io_din; + 5: acx[39:32] <= io_din[7:0]; + 6: acx0 <= io_din[7:0]; + 7: acx1 <= io_din[7:0]; + 8: acx2 <= io_din[7:0]; + 9: acy0[15:0] <= io_din; + 10: acy0[23:16] <= io_din[7:0]; + 11: acy1[15:0] <= io_din; + 12: acy1[23:16] <= io_din[7:0]; + 13: acy2[15:0] <= io_din; + 14: acy2[23:16] <= io_din[7:0]; + endcase + end end end @@ -402,16 +465,6 @@ always@(posedge clk_sys) begin if(~vs_d2 & vs_d1) vs_wait <= 0; end -always @(posedge clk_sys) begin - reg vsd, vsd2; - if(~cfg_ready || ~cfg_set) cfg_got <= cfg_set; - else begin - vsd <= HDMI_TX_VS; - vsd2 <= vsd; - if(~vsd2 & vsd) cfg_got <= cfg_set; - end -end - cyclonev_hps_interface_peripheral_uart uart ( .ri(0) @@ -466,8 +519,6 @@ always @(posedge FPGA_CLK2_50) begin end wire clk_100m; -wire clk_hdmi = hdmi_clk_out; -wire clk_audio = FPGA_CLK3_50; wire clk_pal = FPGA_CLK3_50; //////////////////// SYSTEM MEMORY & SCALER ///////////////////////// @@ -574,7 +625,10 @@ wire [15:0] vbuf_byteenable; wire vbuf_write; wire [23:0] hdmi_data; -wire hdmi_vs, hdmi_hs, hdmi_de; +wire hdmi_vs, hdmi_hs, hdmi_de, hdmi_vbl; + +`ifndef DEBUG_NOHDMI +wire clk_hdmi = hdmi_clk_out; ascal #( @@ -611,6 +665,7 @@ ascal .o_hs (hdmi_hs), .o_vs (hdmi_vs), .o_de (hdmi_de), + .o_vbl (hdmi_vbl), .o_lltune (lltune), .htotal (WIDTH + HFP + HBP + HS), .hsstart (WIDTH + HFP), @@ -625,7 +680,7 @@ ascal .vmin (vmin), .vmax (vmax), - .mode ({~lowlat,FB_EN ? FB_FLT : |scaler_flt,2'b00}), + .mode ({~lowlat,LFB_EN ? LFB_FLT : |scaler_flt,2'b00}), .poly_clk (clk_sys), .poly_a (coef_addr), .poly_dw (coef_data), @@ -653,18 +708,46 @@ ascal .avl_read (vbuf_read), .avl_byteenable (vbuf_byteenable) ); +`endif + +reg LFB_EN = 0; +reg LFB_FLT = 0; +reg [5:0] LFB_FMT = 0; +reg [11:0] LFB_WIDTH = 0; +reg [11:0] LFB_HEIGHT = 0; +reg [11:0] LFB_HMIN = 0; +reg [11:0] LFB_HMAX = 0; +reg [11:0] LFB_VMIN = 0; +reg [11:0] LFB_VMAX = 0; +reg [31:0] LFB_BASE = 0; reg FB_EN = 0; -reg FB_FLT = 0; reg [5:0] FB_FMT = 0; reg [11:0] FB_WIDTH = 0; reg [11:0] FB_HEIGHT = 0; -reg [11:0] FB_HMIN = 0; -reg [11:0] FB_HMAX = 0; -reg [11:0] FB_VMIN = 0; -reg [11:0] FB_VMAX = 0; reg [31:0] FB_BASE = 0; +always @(posedge clk_sys) begin + FB_EN <= LFB_EN | fb_en; + if(LFB_EN) begin + FB_FMT <= LFB_FMT; + FB_WIDTH <= LFB_WIDTH; + FB_HEIGHT <= LFB_HEIGHT; + FB_BASE <= LFB_BASE; + end + else begin + FB_FMT <= fb_fmt; + FB_WIDTH <= fb_width; + FB_HEIGHT <= fb_height; + FB_BASE <= fb_base; + end +end + +`ifdef USE_FB +reg fb_vbl; +always @(posedge clk_vid) fb_vbl <= hdmi_vbl; +`endif + reg [11:0] hmin; reg [11:0] hmax; reg [11:0] vmin; @@ -684,11 +767,11 @@ always @(posedge clk_vid) begin state <= state + 1'd1; case(state) - 0: if(FB_EN) begin - hmin <= FB_HMIN; - vmin <= FB_VMIN; - hmax <= FB_HMAX; - vmax <= FB_VMAX; + 0: if(LFB_EN) begin + hmin <= LFB_HMIN; + vmin <= LFB_VMIN; + hmax <= LFB_HMAX; + vmax <= LFB_VMAX; state<= 0; end else if(ARX && ARY && !FREESCALE) begin @@ -712,8 +795,8 @@ always @(posedge clk_vid) begin endcase end +`ifndef DEBUG_NOHDMI wire [15:0] lltune; - pll_hdmi_adj pll_hdmi_adj ( .clk(FPGA_CLK1_50), @@ -731,6 +814,9 @@ pll_hdmi_adj pll_hdmi_adj .o_address(cfg_address), .o_writedata(cfg_data) ); +`else + assign led_locked = 0; +`endif wire [63:0] pal_data; wire [47:0] pal_d = {pal_data[55:32], pal_data[23:0]}; @@ -750,7 +836,7 @@ end ///////////////////////// HDMI output ///////////////////////////////// - +`ifndef DEBUG_NOHDMI wire hdmi_clk_out; pll_hdmi pll_hdmi ( @@ -760,6 +846,7 @@ pll_hdmi pll_hdmi .reconfig_from_pll(reconfig_from_pll), .outclk_0(hdmi_clk_out) ); +`endif //1920x1080@60 PCLK=148.5MHz CEA reg [11:0] WIDTH = 1920; @@ -781,6 +868,7 @@ reg adj_write; reg [5:0] adj_address; reg [31:0] adj_data; +`ifndef DEBUG_NOHDMI pll_cfg pll_cfg ( .mgmt_clk(FPGA_CLK1_50), @@ -795,8 +883,18 @@ pll_cfg pll_cfg .reconfig_from_pll(reconfig_from_pll) ); -reg cfg_ready = 0; +reg cfg_got = 0; +always @(posedge clk_sys) begin + reg vsd, vsd2; + if(~cfg_ready || ~cfg_set) cfg_got <= cfg_set; + else begin + vsd <= HDMI_TX_VS; + vsd2 <= vsd; + if(~vsd2 & vsd) cfg_got <= cfg_set; + end +end +reg cfg_ready = 0; always @(posedge FPGA_CLK1_50) begin reg gotd = 0, gotd2 = 0; reg custd = 0, custd2 = 0; @@ -825,6 +923,12 @@ always @(posedge FPGA_CLK1_50) begin if(old_wait & ~adj_waitrequest & gotd) cfg_ready <= 1; end +`else + +wire cfg_ready = 1; + +`endif + wire hdmi_config_done; hdmi_config hdmi_config ( @@ -841,6 +945,7 @@ hdmi_config hdmi_config .ypbpr(ypbpr_en & direct_video) ); +`ifndef DEBUG_NOHDMI wire [23:0] hdmi_data_sl; wire hdmi_de_sl, hdmi_vs_sl, hdmi_hs_sl; scanlines #(1) HDMI_scanlines @@ -861,6 +966,7 @@ scanlines #(1) HDMI_scanlines wire [23:0] hdmi_data_osd; wire hdmi_de_osd, hdmi_vs_osd, hdmi_hs_osd; + osd hdmi_osd ( .clk_sys(clk_sys), @@ -884,6 +990,7 @@ osd hdmi_osd .osd_status(osd_status) `endif ); +`endif wire hdmi_cs_osd; csync csync_hdmi(clk_hdmi, hdmi_hs_osd, hdmi_vs_osd, hdmi_cs_osd); @@ -930,12 +1037,16 @@ always @(posedge clk_vid) begin end wire hdmi_tx_clk; +`ifndef DEBUG_NOHDMI cyclonev_clkselect hdmi_clk_sw ( .clkselect({1'b1, ~vga_fb & direct_video}), .inclk({clk_vid, hdmi_clk_out, 2'b00}), .outclk(hdmi_tx_clk) ); +`else +assign hdmi_tx_clk = clk_vid; +`endif altddio_out #( @@ -1082,65 +1193,60 @@ end assign SDCD_SPDIF =(SW[3] & ~spdif) ? 1'b0 : 1'bZ; `ifndef DUAL_SDRAM - wire anl,anr; + wire analog_l, analog_r; assign AUDIO_SPDIF = SW[3] ? 1'bZ : SW[0] ? HDMI_LRCLK : spdif; - assign AUDIO_R = SW[3] ? 1'bZ : SW[0] ? HDMI_I2S : anr; - assign AUDIO_L = SW[3] ? 1'bZ : SW[0] ? HDMI_SCLK : anl; + assign AUDIO_R = SW[3] ? 1'bZ : SW[0] ? HDMI_I2S : analog_r; + assign AUDIO_L = SW[3] ? 1'bZ : SW[0] ? HDMI_SCLK : analog_l; `endif -assign HDMI_MCLK = 0; +assign HDMI_MCLK = clk_audio; +wire clk_audio; -wire [15:0] audio_l, audio_l_pre; -aud_mix_top audmix_l +pll_audio pll_audio ( - .clk(clk_audio), - .att(vol_att), - .mix(audio_mix), - .is_signed(audio_s), - - .core_audio(audio_ls), - .pre_in(audio_r_pre), - .linux_audio(alsa_l), - - .pre_out(audio_l_pre), - .out(audio_l) -); - -wire [15:0] audio_r, audio_r_pre; -aud_mix_top audmix_r -( - .clk(clk_audio), - .att(vol_att), - .mix(audio_mix), - .is_signed(audio_s), - - .core_audio(audio_rs), - .pre_in(audio_l_pre), - .linux_audio(alsa_r), - - .pre_out(audio_r_pre), - .out(audio_r) + .refclk(FPGA_CLK3_50), + .rst(0), + .outclk_0(clk_audio) ); wire spdif; audio_out audio_out ( - .reset(reset), + .reset(reset | areset), .clk(clk_audio), + + .att(vol_att), + .mix(audio_mix), .sample_rate(audio_96k), - .left_in(audio_l), - .right_in(audio_r), + + .flt_rate(aflt_rate), + .cx(acx), + .cx0(acx0), + .cx1(acx1), + .cx2(acx2), + .cy0(acy0), + .cy1(acy1), + .cy2(acy2), + + .is_signed(audio_s), + .core_l(audio_l), + .core_r(audio_r), + + .alsa_l(alsa_l), + .alsa_r(alsa_r), + .i2s_bclk(HDMI_SCLK), .i2s_lrclk(HDMI_LRCLK), .i2s_data(HDMI_I2S), `ifndef DUAL_SDRAM - .dac_l(anl), - .dac_r(anr), + .dac_l(analog_l), + .dac_r(analog_r), `endif .spdif(spdif) ); + wire [28:0] alsa_address; wire [63:0] alsa_readdata; wire alsa_ready; @@ -1168,7 +1274,6 @@ alsa alsa .pcm_r(alsa_r) ); - //////////////// User I/O (USB 3.0 connector) ///////////////////////// assign USER_IO[0] = !user_out[0] ? 1'b0 : 1'bZ; @@ -1191,7 +1296,7 @@ assign user_in[6] = USER_IO[6]; /////////////////// User module connection //////////////////////////// wire clk_sys; -wire [15:0] audio_ls, audio_rs; +wire [15:0] audio_l, audio_r; wire audio_s; wire [1:0] audio_mix; wire [1:0] scanlines; @@ -1227,24 +1332,20 @@ wire [6:0] user_out, user_in; assign {SDRAM_DQ, SDRAM_A, SDRAM_BA, SDRAM_CLK, SDRAM_CKE, SDRAM_DQML, SDRAM_DQMH, SDRAM_nWE, SDRAM_nCAS, SDRAM_nRAS, SDRAM_nCS} = {39'bZ}; `endif -`ifdef ARCADE_SYS - wire hvs_emu, hhs_emu; - sync_fix hdmi_sync_v(clk_ihdmi, hvs_emu, hvs_fix); - sync_fix hdmi_sync_h(clk_ihdmi, hhs_emu, hhs_fix); +assign clk_ihdmi= clk_vid; +assign ce_hpix = ce_pix; +assign hr_out = r_out; +assign hg_out = g_out; +assign hb_out = b_out; +assign hhs_fix = hs_fix; +assign hvs_fix = vs_fix; +assign hde_emu = de_emu; +`ifdef ARCADE_SYS assign audio_mix = 0; assign {ADC_SCK, ADC_SDI, ADC_CONVST} = 0; assign btn = 0; `else - assign clk_ihdmi= clk_vid; - assign ce_hpix = ce_pix; - assign hr_out = r_out; - assign hg_out = g_out; - assign hb_out = b_out; - assign hhs_fix = hs_fix; - assign hvs_fix = vs_fix; - assign hde_emu = de_emu; - wire uart_dtr; wire uart_dsr; wire uart_cts; @@ -1254,6 +1355,19 @@ assign {SDRAM_DQ, SDRAM_A, SDRAM_BA, SDRAM_CLK, SDRAM_CKE, SDRAM_DQML, SDRAM_DQM wire osd_status; `endif +wire fb_en; +wire [4:0] fb_fmt; +wire [11:0] fb_width; +wire [11:0] fb_height; +wire [31:0] fb_base; + +`ifndef USE_FB + assign fb_en = 0; + assign fb_fmt = 0; + assign fb_width = 0; + assign fb_height = 0; + assign fb_base = 0; +`endif emu emu ( @@ -1269,39 +1383,36 @@ emu emu .VGA_DE(de_emu), .VGA_F1(f1), -`ifdef ARCADE_SYS - .VGA_CLK(clk_vid), - .VGA_CE(ce_pix), - .HDMI_CLK(clk_ihdmi), - .HDMI_CE(ce_hpix), - .HDMI_R(hr_out), - .HDMI_G(hg_out), - .HDMI_B(hb_out), - .HDMI_HS(hhs_emu), - .HDMI_VS(hvs_emu), - .HDMI_DE(hde_emu), - .HDMI_SL(scanlines), - .HDMI_ARX(ARX), - .HDMI_ARY(ARY), -`else .CLK_VIDEO(clk_vid), .CE_PIXEL(ce_pix), .VGA_SL(scanlines), .VIDEO_ARX(ARX), .VIDEO_ARY(ARY), - .AUDIO_MIX(audio_mix), - .ADC_BUS({ADC_SCK,ADC_SDO,ADC_SDI,ADC_CONVST}), +`ifdef USE_FB + .FB_EN(fb_en), + .FB_FORMAT(fb_fmt), + .FB_WIDTH(fb_width), + .FB_HEIGHT(fb_height), + .FB_BASE(fb_base), + .FB_VBL(fb_vbl), + .FB_LL(lowlat), `endif .LED_USER(led_user), .LED_POWER(led_power), .LED_DISK(led_disk), - .AUDIO_L(audio_ls), - .AUDIO_R(audio_rs), + .CLK_AUDIO(clk_audio), + .AUDIO_L(audio_l), + .AUDIO_R(audio_r), .AUDIO_S(audio_s), +`ifndef ARCADE_SYS + .AUDIO_MIX(audio_mix), + .ADC_BUS({ADC_SCK,ADC_SDO,ADC_SDI,ADC_CONVST}), +`endif + `ifdef USE_DDRAM .DDRAM_CLK(ram_clk), .DDRAM_ADDR(ram_address), @@ -1401,56 +1512,6 @@ endmodule ///////////////////////////////////////////////////////////////////// -module aud_mix_top -( - input clk, - - input [4:0] att, - input [1:0] mix, - input is_signed, - - input [15:0] core_audio, - input [15:0] linux_audio, - input [15:0] pre_in, - - output reg [15:0] pre_out, - output reg [15:0] out -); - -reg [15:0] ca; -always @(posedge clk) begin - reg [15:0] d1,d2,d3; - - d1 <= core_audio; d2<=d1; d3<=d2; - if(d2 == d3) ca <= d2; -end - -always @(posedge clk) begin - reg signed [16:0] a1, a2, a3, a4; - - a1 <= is_signed ? {ca[15],ca} : {2'b00,ca[15:1]}; - a2 <= a1 + {linux_audio[15],linux_audio}; - - pre_out <= a2[16:1]; - - case(mix) - 0: a3 <= a2; - 1: a3 <= $signed(a2) - $signed(a2[16:3]) + $signed(pre_in[15:2]); - 2: a3 <= $signed(a2) - $signed(a2[16:2]) + $signed(pre_in[15:1]); - 3: a3 <= {a2[16],a2[16:1]} + {pre_in[15],pre_in}; - endcase - - if(att[4]) a4 <= 0; - else a4 <= a3 >>> att[3:0]; - - //clamping - out <= ^a4[16:15] ? {a4[16],{15{a4[15]}}} : a4[15:0]; -end - -endmodule - -///////////////////////////////////////////////////////////////////// - // CSync generation // Shifts HSync left by 1 HSync period during VSync