From f7464db6c14cfcad6dc87f0e7bd20194bca0bb00 Mon Sep 17 00:00:00 2001 From: Sorgelig Date: Wed, 18 Jun 2025 21:22:03 +0800 Subject: [PATCH] Update sys. --- Gameboy.sv | 4 ++++ sys/ascal.vhd | 54 +++++++++++++++++++++++++++++++++++++++----- sys/hps_io.sv | 24 ++++++++++++-------- sys/i2c.v | 2 +- sys/sd_card.sv | 8 +++---- sys/sys_top.v | 25 ++++++++++++-------- sys/video_cleaner.sv | 13 +++++++++-- 7 files changed, 99 insertions(+), 31 deletions(-) diff --git a/Gameboy.sv b/Gameboy.sv index 8b7b7f7..ef5dfd4 100644 --- a/Gameboy.sv +++ b/Gameboy.sv @@ -62,6 +62,8 @@ module emu input [11:0] HDMI_WIDTH, input [11:0] HDMI_HEIGHT, output HDMI_FREEZE, + output HDMI_BLACKOUT, + output HDMI_BOB_DEINT, `ifdef MISTER_FB // Use framebuffer in DDRAM @@ -193,6 +195,8 @@ assign BUTTONS = 0; assign HDMI_FREEZE = 0; assign VGA_SCALER= 0; assign VGA_DISABLE = 0; +assign HDMI_BLACKOUT = 0; +assign HDMI_BOB_DEINT = 0; assign AUDIO_MIX = status[8:7]; diff --git a/sys/ascal.vhd b/sys/ascal.vhd index 6f085e0..5607e64 100644 --- a/sys/ascal.vhd +++ b/sys/ascal.vhd @@ -201,9 +201,10 @@ ENTITY ascal IS i_vdmax : OUT natural RANGE 0 TO 4095; -- Output video parameters - run : IN std_logic :='1'; -- 1=Enable output image. 0=No image - freeze : IN std_logic :='0'; -- 1=Disable framebuffer writes - mode : IN unsigned(4 DOWNTO 0); + run : IN std_logic :='1'; -- 1=Enable output image. 0=No image + freeze : IN std_logic :='0'; -- 1=Disable framebuffer writes + mode : IN unsigned(4 DOWNTO 0); + bob_deint : IN std_logic := '0'; -- SYNC |_________________________/"""""""""\_______| -- DE |""""""""""""""""""\________________________| -- RGB | <#IMAGE#> ^HDISP | @@ -222,6 +223,7 @@ ENTITY ascal IS vmax : IN natural RANGE 0 TO 4095; -- 0 <= vmin < vmax < vdisp vrr : IN std_logic := '0'; vrrmax : IN natural RANGE 0 TO 4095 := 0; + swblack : IN std_logic := '0'; -- will output 3 black frame on every resolution switch -- Scaler format. 00=16bpp 565, 01=24bpp 10=32bpp format : IN unsigned(1 DOWNTO 0) :="01"; @@ -318,6 +320,7 @@ ARCHITECTURE rtl OF ascal IS SIGNAL i_pvs,i_pfl,i_pde,i_pce : std_logic; SIGNAL i_ppix : type_pix; SIGNAL i_freeze : std_logic; + SIGNAL i_bob_deint : std_logic; SIGNAL i_count : unsigned(2 DOWNTO 0); SIGNAL i_hsize,i_hmin,i_hmax,i_hcpt : uint12; SIGNAL i_hrsize,i_vrsize : uint12; @@ -333,6 +336,7 @@ ARCHITECTURE rtl OF ascal IS SIGNAL i_de_delay : natural RANGE 0 TO 31; SIGNAL i_intercnt : natural RANGE 0 TO 3; SIGNAL i_inter,i_half,i_flm : std_logic; + SIGNAL i_wfl : std_logic_vector(2 DOWNTO 0); SIGNAL i_write,i_wreq,i_alt,i_line,i_wline,i_wline_mem : std_logic; SIGNAL i_walt,i_walt_mem,i_wreq_mem : std_logic; SIGNAL i_wdelay : natural RANGE 0 TO 7; @@ -410,6 +414,8 @@ ARCHITECTURE rtl OF ascal IS -- Output SIGNAL o_run : std_logic; SIGNAL o_freeze : std_logic; + SIGNAL o_bob_deint : std_logic; + SIGNAL o_iwfl : std_logic_vector(2 DOWNTO 0); 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); @@ -510,6 +516,7 @@ ARCHITECTURE rtl OF ascal IS SIGNAL o_divrun : std_logic; SIGNAL o_hacpt,o_vacpt : unsigned(11 DOWNTO 0); SIGNAL o_vacptl : unsigned(1 DOWNTO 0); + signal o_newres : integer range 0 to 3; ----------------------------------------------------------------------------- FUNCTION shift_ishift(shift : unsigned(0 TO 119); @@ -1130,6 +1137,7 @@ BEGIN i_pushhead<='0'; i_eol<='0'; -- End Of Line i_freeze <=freeze; -- + i_bob_deint <= bob_deint; i_iauto<=iauto; -- i_wreq<='0'; i_wr<='0'; @@ -1190,11 +1198,13 @@ BEGIN i_vcpt<=0; IF i_inter='1' AND i_flm='0' AND i_half='0' AND INTER THEN i_line<='1'; + i_wfl(o_ibuf1) <= '0'; i_adrsi<=to_unsigned(N_BURST * i_hburst,32) + to_unsigned(N_BURST * to_integer( unsigned'("00") & to_std_logic(HEADER)),32); ELSE i_line<='0'; + i_wfl(o_ibuf0) <= '1'; i_adrsi<=to_unsigned(N_BURST * to_integer( unsigned'("00") & to_std_logic(HEADER)),32); END IF; @@ -1204,8 +1214,8 @@ BEGIN i_vcpt>=i_vmin AND i_vcpt<=i_vmax); -- Detects end of frame for triple buffering. - i_endframe0<=i_vs AND (NOT i_inter OR i_flm); - i_endframe1<=i_vs AND (NOT i_inter OR NOT i_flm); + i_endframe0<=i_vs AND (NOT i_inter OR i_flm OR i_bob_deint); + i_endframe1<=i_vs AND (NOT i_inter OR NOT i_flm OR i_bob_deint); i_vss<=to_std_logic(i_vcpt>=i_vmin AND i_vcpt<=i_vmax); @@ -1862,6 +1872,8 @@ BEGIN o_isync <= '0'; o_isync2 <= o_isync; o_freeze <= freeze; + o_bob_deint <= bob_deint; + o_iwfl <= i_wfl; o_inter <=i_inter; -- o_iendframe0<=i_endframe0; -- o_iendframe02<=o_iendframe0; @@ -1890,6 +1902,14 @@ BEGIN o_ivsize<=i_vrsize; -- o_hdown<=i_hdown; -- o_vdown<=i_vdown; -- + + IF (o_newres > 0) then + o_newres <= o_newres- 1; + END IF; + END IF; + + IF (swblack = '1' and o_fb_ena = '0' and (o_ihsize /= i_hrsize or o_ivsize /= i_vrsize)) then + o_newres <= 3; END IF; -- Simultaneous change of input and output framebuffers @@ -2086,7 +2106,26 @@ BEGIN o_read<=o_read_pre AND o_run; o_rline<=o_vacpt(0); -- Even/Odd line for interlaced video - o_adrs_pre<=to_integer(o_vacpt) * to_integer(o_stride); + ---- + -- When bob deinterlacing we read lines from one buffer (the most current) but we read them twice + -- (in contrast to weave deinterlacing where we read each 480p line from alternating buffers) + -- To counteract the severe vibrating/motion with bob deinterlacing, we need to offset one field + -- by a half-line. This is done by only reading the first line of the 'even' frame once + + IF o_inter='1' AND o_bob_deint='1' THEN + IF o_iwfl(o_obuf0)='0' THEN + IF o_vacpt=0 OR o_rline='1' THEN + o_adrs_pre <= to_integer(o_vacpt) * to_integer(o_stride); + ELSE + o_adrs_pre <= (to_integer(o_vacpt)-1) * to_integer(o_stride); + END IF; + ELSE + o_adrs_pre <= to_integer(o_vacpt(11 DOWNTO 1) & "0") * to_integer(o_stride); + END IF; + ELSE + o_adrs_pre<=to_integer(o_vacpt) * to_integer(o_stride); + END IF; + IF o_adrsa='1' THEN IF o_fload=2 THEN o_adrs<=to_unsigned(o_hbcpt * N_BURST,32); @@ -2219,6 +2258,9 @@ BEGIN hpix_v:=(r=>o_fb_pal_dr(23 DOWNTO 16),g=>o_fb_pal_dr(15 DOWNTO 8), b=>o_fb_pal_dr(7 DOWNTO 0)); END IF; + IF (o_newres > 0) then + hpix_v := (others => (others => '0')); + END IF; o_hpix0<=hpix_v; o_hpix1<=o_hpix0; o_hpix2<=o_hpix1; diff --git a/sys/hps_io.sv b/sys/hps_io.sv index 4fac671..92cdf77 100644 --- a/sys/hps_io.sv +++ b/sys/hps_io.sv @@ -27,7 +27,7 @@ // VDNUM 1..10 // BLKSZ 0..7: 0 = 128, 1 = 256, 2 = 512(default), .. 7 = 16384 // -module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1, BLKSZ=2, PS2WE=0) +module hps_io #(parameter CONF_STR, CONF_STR_BRAM=0, PS2DIV=0, WIDE=0, VDNUM=1, BLKSZ=2, PS2WE=0, STRLEN=$size(CONF_STR)>>3) ( input clk_sys, inout [48:0] HPS_BUS, @@ -39,7 +39,7 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1, output reg [31:0] joystick_3, output reg [31:0] joystick_4, output reg [31:0] joystick_5, - + // analog -127..+127, Y: [15:8], X: [7:0] output reg [15:0] joystick_l_analog_0, output reg [15:0] joystick_l_analog_1, @@ -232,7 +232,6 @@ video_calc video_calc ///////////////////////////////////////////////////////// -localparam STRLEN = $size(CONF_STR)>>3; localparam MAX_W = $clog2((64 > (STRLEN+2)) ? 64 : (STRLEN+2))-1; wire [7:0] conf_byte; @@ -281,7 +280,7 @@ always@(posedge clk_sys) begin : uio_block stflg <= stflg + 1'd1; status_req <= status_in; end - + old_upload_req <= ioctl_upload_req; if(~old_upload_req & ioctl_upload_req) upload_req <= 1; @@ -523,7 +522,7 @@ always@(posedge clk_sys) begin : uio_block //menu mask 'h2E: if(byte_cnt == 1) io_dout <= status_menumask; - + //sdram size set 'h31: if(byte_cnt == 1) sdram_sz <= io_din; @@ -630,7 +629,7 @@ always@(posedge clk_sys) begin : fio_block reg has_cmd; reg [26:0] addr; reg wr; - + ioctl_rd <= 0; ioctl_wr <= wr; wr <= 0; @@ -663,7 +662,7 @@ always@(posedge clk_sys) begin : fio_block FIO_FILE_TX: begin cnt <= cnt + 1'd1; - case(cnt) + case(cnt) 0: if(io_din[7:0] == 8'hAA) begin ioctl_addr <= 0; ioctl_upload <= 1; @@ -1032,8 +1031,15 @@ module confstr_rom #(parameter CONF_STR, STRLEN) output reg [7:0] conf_byte ); -wire [7:0] rom[STRLEN]; -initial for(int i = 0; i < STRLEN; i++) rom[i] = CONF_STR[((STRLEN-i)*8)-1 -:8]; +reg [7:0] rom[STRLEN]; + +initial begin + if( CONF_STR=="" ) + $readmemh("cfgstr.hex",rom); + else + for(int i = 0; i < STRLEN; i++) rom[i] = CONF_STR[((STRLEN-i)*8)-1 -:8]; +end + always @ (posedge clk_sys) conf_byte <= rom[conf_addr]; endmodule diff --git a/sys/i2c.v b/sys/i2c.v index 9ccba93..6da6a14 100644 --- a/sys/i2c.v +++ b/sys/i2c.v @@ -75,7 +75,7 @@ always @(posedge CLK) begin END <= 0; rd <= READ; len <= I2C_WLEN; - if(READ) SD <= {2'b10, I2C_ADDR, 1'b1, 1'b1, 8'b11111111, 1'b0, 3'b011, 9'b111111111}; + if(READ) SD <= {2'b10, I2C_ADDR, 1'b1, 1'b1, 8'b11111111, 1'b1, 3'b011, 9'b111111111}; else SD <= {2'b10, I2C_ADDR, 1'b0, 1'b1, I2C_WDATA1, 1'b1, I2C_WDATA2, 4'b1011}; SD_COUNTER <= 0; end else begin diff --git a/sys/sd_card.sv b/sys/sd_card.sv index 610c271..417d8d4 100644 --- a/sys/sd_card.sv +++ b/sys/sd_card.sv @@ -58,10 +58,10 @@ localparam DW = WIDE ? 15 : 7; localparam SZ = OCTAL ? 8 : 1; localparam SW = SZ-1; -wire [7:0] DATA_TOKEN_CMD25 = 8'hfc; -wire [7:0] STOP_TRAN = 8'hfd; -wire [7:0] DATA_TOKEN = 8'hfe; -wire [7:0] WRITE_DATA_RESPONSE = 8'h05; +localparam DATA_TOKEN_CMD25 = 8'hfc; +localparam STOP_TRAN = 8'hfd; +localparam DATA_TOKEN = 8'hfe; +localparam WRITE_DATA_RESPONSE = 8'he5; // number of bytes to wait after a command before sending the reply localparam NCR = 5+3; // 5 bytes are required (command length) diff --git a/sys/sys_top.v b/sys/sys_top.v index 65129eb..18f3969 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -128,12 +128,13 @@ module sys_top wire SD_CS, SD_CLK, SD_MOSI, SD_MISO, SD_CD; `ifndef MISTER_DUAL_SDRAM - assign SD_CD = mcp_en ? mcp_sdcd : SDCD_SPDIF; + wire sd_cd = SDCD_SPDIF & ~SW[2]; // SW[2]=ON workaround for faulty boards without SD card detect pin. + assign SD_CD = mcp_en ? mcp_sdcd : sd_cd; assign SD_MISO = SD_CD | (mcp_en ? SD_SPI_MISO : (VGA_EN | SDIO_DAT[0])); assign SD_SPI_CS = mcp_en ? (mcp_sdcd ? 1'bZ : SD_CS) : (sog & ~cs1 & ~VGA_EN) ? 1'b1 : 1'bZ; assign SD_SPI_CLK = (~mcp_en | mcp_sdcd) ? 1'bZ : SD_CLK; assign SD_SPI_MOSI = (~mcp_en | mcp_sdcd) ? 1'bZ : SD_MOSI; - assign {SDIO_CLK,SDIO_CMD,SDIO_DAT} = av_dis ? 6'bZZZZZZ : (mcp_en | (SDCD_SPDIF & ~SW[2])) ? {vga_g,vga_r,vga_b} : {SD_CLK,SD_MOSI,SD_CS,3'bZZZ}; + assign {SDIO_CLK,SDIO_CMD,SDIO_DAT} = av_dis ? 6'bZZZZZZ : (mcp_en | sd_cd) ? {vga_g,vga_r,vga_b} : {SD_CLK,SD_MOSI,SD_CS,3'bZZZ}; `else assign SD_CD = mcp_sdcd; assign SD_MISO = mcp_sdcd | SD_SPI_MISO; @@ -183,10 +184,10 @@ wire io_dig = mcp_en ? mcp_mode : SW[3]; assign LED_USER = VGA_TX_CLK; wire BTN_DIS = VGA_EN; `else - wire BTN_RESET = SDRAM2_DQ[9]; - wire BTN_OSD = SDRAM2_DQ[13]; - wire BTN_USER = SDRAM2_DQ[11]; - wire BTN_DIS = SDRAM2_DQ[15]; + wire BTN_RESET = 1'b1; + wire BTN_OSD = 1'b1; + wire BTN_USER = 1'b1; + wire BTN_DIS = 1'b1; `endif reg BTN_EN = 0; @@ -331,6 +332,7 @@ reg [11:0] vs_line = 0; reg scaler_out = 0; reg vrr_mode = 0; +wire hdmi_blackout; reg [31:0] aflt_rate = 7056000; reg [39:0] acx = 4258969; @@ -677,6 +679,7 @@ wire vbuf_write; wire [23:0] hdmi_data; wire hdmi_vs, hdmi_hs, hdmi_de, hdmi_vbl, hdmi_brd; wire freeze; +wire bob_deint; `ifndef MISTER_DEBUG_NOHDMI wire clk_hdmi = hdmi_clk_out; @@ -708,9 +711,10 @@ wire freeze; ) ascal ( - .reset_na (~reset_req), - .run (1), - .freeze (freeze), + .reset_na (~reset_req), + .run (1), + .freeze (freeze), + .bob_deint (bob_deint), .i_clk (clk_ihdmi), .i_ce (ce_hpix), @@ -752,6 +756,7 @@ wire freeze; .vmax (vmax), .vrr (vrr_mode), .vrrmax (HEIGHT + VBP + VS[11:0] + 12'd1), + .swblack (hdmi_blackout), .mode ({~lowlat,LFB_EN ? LFB_FLT : |scaler_flt,2'b00}), .poly_clk (clk_sys), @@ -1734,6 +1739,8 @@ emu emu .HDMI_WIDTH(direct_video ? 12'd0 : hdmi_width), .HDMI_HEIGHT(direct_video ? 12'd0 : hdmi_height), .HDMI_FREEZE(freeze), + .HDMI_BLACKOUT(hdmi_blackout), + .HDMI_BOB_DEINT(bob_deint), .CLK_VIDEO(clk_vid), .CE_PIXEL(ce_pix), diff --git a/sys/video_cleaner.sv b/sys/video_cleaner.sv index b0acbc3..4c057a8 100644 --- a/sys/video_cleaner.sv +++ b/sys/video_cleaner.sv @@ -26,6 +26,10 @@ module video_cleaner //optional de input DE_in, + //optional interlace support + input interlace, + input f1, + // video output signals output reg [7:0] VGA_R, output reg [7:0] VGA_G, @@ -56,14 +60,19 @@ always @(posedge clk_vid) begin HBlank_out <= hbl; VGA_HS <= hs; - if(~VGA_HS & hs) VGA_VS <= vs; VGA_R <= R; VGA_G <= G; VGA_B <= B; DE_out <= DE_in; - if(HBlank_out & ~hbl) VBlank_out <= vbl; + if (interlace & f1) begin + VGA_VS <= vs; + VBlank_out <= vbl; + end else begin + if(~VGA_HS & hs) VGA_VS <= vs; + if(HBlank_out & ~hbl) VBlank_out <= vbl; + end end end