diff --git a/SNES.sv b/SNES.sv index 153f78a..a9f211c 100644 --- a/SNES.sv +++ b/SNES.sv @@ -57,6 +57,7 @@ module emu input [11:0] HDMI_HEIGHT, output HDMI_FREEZE, output HDMI_BLACKOUT, + output HDMI_BOB_DEINT, `ifdef MISTER_FB // Use framebuffer in DDRAM @@ -187,6 +188,7 @@ assign VGA_SCALER= 0; assign VGA_DISABLE = 0; assign HDMI_FREEZE = 0; assign HDMI_BLACKOUT = 0; +assign HDMI_BOB_DEINT = 0; assign {SD_SCK, SD_MOSI, SD_CS} = 'Z; diff --git a/sys/ascal.vhd b/sys/ascal.vhd index a79f7ec..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 | @@ -319,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; @@ -334,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; @@ -411,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); @@ -1132,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'; @@ -1192,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; @@ -1206,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); @@ -1864,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; @@ -2096,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); diff --git a/sys/sys_top.v b/sys/sys_top.v index 5b20846..18f3969 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -679,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; @@ -710,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), @@ -1738,6 +1740,7 @@ emu emu .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),