From ea33f47e0dd322231cc9c770ecf8624ec00a46e9 Mon Sep 17 00:00:00 2001 From: jackyangantelope Date: Tue, 9 Dec 2025 22:58:45 +0800 Subject: [PATCH] Update sys --- Arcade-Pacman.qsf | 2 +- Arcade-Pacman.sv | 5 + sys/ascal.vhd | 221 +++++++++++++++++++++++++++++++++---------- sys/hps_io.sv | 24 +++-- sys/i2c.v | 2 +- sys/sd_card.sv | 8 +- sys/sys.tcl | 4 +- sys/sys_top.sdc | 2 +- sys/sys_top.v | 76 +++++++++++---- sys/video_cleaner.sv | 13 ++- 10 files changed, 265 insertions(+), 92 deletions(-) diff --git a/Arcade-Pacman.qsf b/Arcade-Pacman.qsf index f717bd5..d2701c6 100644 --- a/Arcade-Pacman.qsf +++ b/Arcade-Pacman.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.2 Lite Edition" set_global_assignment -name GENERATE_RBF_FILE ON set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files diff --git a/Arcade-Pacman.sv b/Arcade-Pacman.sv index bc29c2f..67e5f04 100644 --- a/Arcade-Pacman.sv +++ b/Arcade-Pacman.sv @@ -57,6 +57,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 (USE_FB=1 in qsf) @@ -188,6 +190,9 @@ assign BUTTONS = 0; assign AUDIO_MIX = 0; assign FB_FORCE_BLANK = 0; assign HDMI_FREEZE = 0; +assign HDMI_BLACKOUT = 0; +assign HDMI_BOB_DEINT = 0; + assign VGA_DISABLE = 0; wire [1:0] ar = status[15:14]; diff --git a/sys/ascal.vhd b/sys/ascal.vhd index f3e5370..a735e6b 100644 --- a/sys/ascal.vhd +++ b/sys/ascal.vhd @@ -103,7 +103,7 @@ USE ieee.numeric_std.ALL; -- DOWNSCALE : True=Support downscaling False=Downscaling disabled -- BYTESWAP : Little/Big endian byte swap -- FRAC : Fractional bits, subpixel resolution --- OHRES : Max. output horizontal resolution. Must be a power of two. +-- OHRES : Max. output horizontal resolution. 1024, 2048, 2304, 2560, 4096 -- (Used for sizing line buffers) -- IHRES : Max. input horizontal resolution. Must be a power of two. -- (Used for sizing line buffers) @@ -125,7 +125,7 @@ ENTITY ascal IS ADAPTIVE : boolean := true; DOWNSCALE_NN : boolean := false; FRAC : natural RANGE 4 TO 8 :=4; - OHRES : natural RANGE 1 TO 4096 :=2048; + OHRES : natural RANGE 1 TO 4096 :=2304; IHRES : natural RANGE 1 TO 2048 :=2048; N_DW : natural RANGE 64 TO 128 := 128; N_AW : natural RANGE 8 TO 32 := 32; @@ -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"; @@ -256,6 +258,9 @@ ENTITY ascal IS BEGIN ASSERT N_DW=64 OR N_DW=128 REPORT "DW" SEVERITY failure; + + ASSERT OHRES = 1024 OR OHRES = 2048 OR OHRES = 2304 OR + OHRES = 2560 OR OHRES = 4096 REPORT "OHRES" SEVERITY failure; END ENTITY ascal; @@ -287,10 +292,39 @@ ARCHITECTURE rtl OF ascal IS END IF; END FUNCTION to_std_logic; + ---------------------------------------------------------- + FUNCTION ohres_h(CONSTANT r : natural) RETURN natural IS + BEGIN + CASE r IS + WHEN 1024 => RETURN 1024; + WHEN 2048 => RETURN 2048; + WHEN OTHERS => RETURN 4096; + END CASE; + END FUNCTION; + FUNCTION ohres_l(CONSTANT r : natural) RETURN natural IS + BEGIN + CASE r IS + WHEN 1024 => RETURN 1024; + WHEN 2048 | 2304 | 2560 => RETURN 2048; + WHEN OTHERS => RETURN 4096; + END CASE; + END FUNCTION; + FUNCTION ohres_m(CONSTANT r : natural) RETURN natural IS + BEGIN + CASE r IS + WHEN 1024 | 2048 | 2304 => RETURN 256; + WHEN OTHERS => RETURN 512; + END CASE; + END FUNCTION; + + CONSTANT OHRESH : natural := ohres_h(OHRES); + CONSTANT OHRESL : natural := ohres_l(OHRES); + CONSTANT OHRESM : natural := ohres_m(OHRES); + ---------------------------------------------------------- CONSTANT NB_BURST : natural :=ilog2(N_BURST); - CONSTANT NB_LA : natural :=ilog2(N_DW/8); -- Low address bits - CONSTANT BLEN : natural :=N_BURST / N_DW * 8; -- Burst length + CONSTANT NB_LA : natural :=ilog2(N_DW/8); -- Low address bits + CONSTANT BLEN : natural :=N_BURST / N_DW * 8; -- Burst length ---------------------------------------------------------- TYPE arr_dw IS ARRAY (natural RANGE <>) OF unsigned(N_DW-1 DOWNTO 0); @@ -318,6 +352,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 +368,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; @@ -362,7 +398,7 @@ ARCHITECTURE rtl OF ascal IS SIGNAL i_hacc,i_vacc : uint13; SIGNAL i_hdown,i_vdown : std_logic; SIGNAL i_divcpt : natural RANGE 0 TO 36; - SIGNAL i_lwad,i_lrad : natural RANGE 0 TO OHRES-1; + SIGNAL i_lwad,i_lrad : natural RANGE 0 TO OHRESH-1; SIGNAL i_lwr,i_bil : std_logic; SIGNAL i_ldw,i_ldrm : type_pix; SIGNAL i_hpixp,i_hpix0,i_hpix1,i_hpix2,i_hpix3,i_hpix4 : type_pix; @@ -410,6 +446,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); @@ -456,13 +494,21 @@ ARCHITECTURE rtl OF ascal IS SIGNAL o_reset_na : std_logic; SIGNAL o_dpram : arr_dw(0 TO BLEN*2-1); ATTRIBUTE ramstyle OF o_dpram : SIGNAL IS "no_rw_check"; - SIGNAL o_line0,o_line1,o_line2,o_line3 : arr_pix(0 TO OHRES-1); + SIGNAL o_line0,o_line1,o_line2,o_line3 : arr_pix(0 TO OHRESL-1); + SIGNAL o_linf0,o_linf1,o_linf2,o_linf3 : arr_pix(0 TO OHRESM-1); + ATTRIBUTE ramstyle OF o_line0 : SIGNAL IS "no_rw_check"; ATTRIBUTE ramstyle OF o_line1 : SIGNAL IS "no_rw_check"; ATTRIBUTE ramstyle OF o_line2 : SIGNAL IS "no_rw_check"; ATTRIBUTE ramstyle OF o_line3 : SIGNAL IS "no_rw_check"; - SIGNAL o_wadl,o_radl0,o_radl1,o_radl2,o_radl3 : natural RANGE 0 TO OHRES-1; - SIGNAL o_ldw,o_ldr0,o_ldr1,o_ldr2,o_ldr3 : type_pix; + ATTRIBUTE ramstyle OF o_linf0 : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_linf1 : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_linf2 : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_linf3 : SIGNAL IS "no_rw_check"; + SIGNAL o_wadl,o_radl0,o_radl1,o_radl2,o_radl3 : natural RANGE 0 TO OHRESH-1; + SIGNAL o_ldr0,o_ldr1,o_ldr2,o_ldr3,o_ldw : type_pix; + SIGNAL o_ler0,o_ler1,o_ler2,o_ler3 : type_pix; + SIGNAL o_lex0,o_lex1,o_lex2,o_lex3 : std_logic; SIGNAL o_wr : unsigned(3 DOWNTO 0); SIGNAL o_hcpt,o_vcpt,o_vcpt_pre,o_vcpt_pre2,o_vcpt_pre3,o_vcpt2 : uint12; SIGNAL o_ihsize,o_ihsizem,o_ivsize : uint12; @@ -472,7 +518,7 @@ ARCHITECTURE rtl OF ascal IS SIGNAL o_hfrac : arr_frac(0 TO 9); ATTRIBUTE ramstyle OF o_hfrac : SIGNAL IS "logic"; -- avoid blockram shift register - 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_hacc,o_hacc_ini,o_hacc_next,o_vacc,o_vacc_next,o_vacc_ini : natural RANGE 0 TO 4*OHRESH-1; SIGNAL o_hsv,o_vsv,o_dev,o_pev,o_end : unsigned(0 TO 11); SIGNAL o_hsp,o_vss : std_logic; SIGNAL o_vcarrym,o_prim : boolean; @@ -490,8 +536,9 @@ ARCHITECTURE rtl OF ascal IS TYPE arr_uint4 IS ARRAY (natural RANGE <>) OF natural RANGE 0 TO 15; SIGNAL o_off : arr_uint4(0 TO 2); SIGNAL o_bibu : std_logic :='0'; - SIGNAL o_dcptv : arr_uint12(1 TO 14); - SIGNAL o_dcpt : uint12; + SIGNAL o_dcptv : arr_uint12(13 TO 14); + SIGNAL o_dcpt_clr, o_dcpt_inc : std_logic; + SIGNAL o_dcptv_clr, o_dcptv_inc : std_logic_vector(1 TO 12); SIGNAL o_hpixs,o_hpix0,o_hpix1,o_hpix2,o_hpix3 : type_pix; SIGNAL o_hpixq : arr_pixq(2 TO 8); ATTRIBUTE ramstyle OF o_hpixq : SIGNAL IS "logic"; -- avoid blockram shift register @@ -499,7 +546,6 @@ ARCHITECTURE rtl OF ascal IS SIGNAL o_vpix_outer : arr_pix(0 TO 2); SIGNAL o_vpix_inner : arr_pix(0 TO 6); - SIGNAL o_vpe : std_logic; SIGNAL o_div : arr_div(0 TO 2); --uint12; SIGNAL o_dir : arr_frac(0 TO 2); @@ -510,6 +556,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); @@ -528,11 +575,11 @@ ARCHITECTURE rtl OF ascal IS END CASE; END FUNCTION; - FUNCTION shift_ipack( i_dw : unsigned(N_DW-1 DOWNTO 0); - acpt : natural RANGE 0 TO 15; - shift : unsigned(0 TO 119); - pix : type_pix; - format : unsigned(1 DOWNTO 0)) RETURN unsigned IS + FUNCTION shift_ipack(i_dw : unsigned(N_DW-1 DOWNTO 0); + acpt : natural RANGE 0 TO 15; + shift : unsigned(0 TO 119); + pix : type_pix; + format : unsigned(1 DOWNTO 0)) RETURN unsigned IS VARIABLE dw : unsigned(N_DW-1 DOWNTO 0); BEGIN dw:=i_dw; @@ -1130,6 +1177,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 +1238,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 +1254,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); @@ -1453,12 +1503,12 @@ BEGIN -- Push pixels to downscaling line buffer i_lwr<=i_hnp4 AND i_ven5 AND i_pce; IF i_lwr='1' THEN - i_lwad<=(i_lwad+1) MOD OHRES; + i_lwad<=(i_lwad+1) MOD OHRESH; END IF; i_ldw<=i_hpix; IF i_hnp3='1' AND i_ven4='1' AND i_pce='1' THEN - i_lrad<=(i_lrad+1) MOD OHRES; + i_lrad<=(i_lrad+1) MOD OHRESH; END IF; ------------------------------------------------------ @@ -1817,7 +1867,7 @@ BEGIN VARIABLE shift_v : unsigned(0 TO N_DW+15); VARIABLE hpix_v : type_pix; VARIABLE hcarry_v,vcarry_v : boolean; - VARIABLE dif_v : natural RANGE 0 TO 8*OHRES-1; + VARIABLE dif_v : natural RANGE 0 TO 8*OHRESH-1; VARIABLE off_v : natural RANGE 0 TO 15; BEGIN IF o_reset_na='0' THEN @@ -1862,6 +1912,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 +1942,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 +2146,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); @@ -2103,6 +2182,9 @@ BEGIN ------------------------------------------------------ -- Copy from buffered memory to pixel lines o_sh<='0'; + o_dcpt_clr <= '0'; + o_dcpt_inc <= '0'; + CASE o_copy IS WHEN sWAIT => o_copyv(0)<='0'; @@ -2121,7 +2203,7 @@ BEGIN o_hacc <=o_hacc_ini; o_hacc_next<=o_hacc_ini + 2*o_ihsize; o_hacpt <=x"000"; - o_dcpt<=0; + o_dcpt_clr <= '1'; o_dshi<=2; o_acpt<=0; o_first<='1'; @@ -2149,17 +2231,17 @@ BEGIN WHEN sCOPY => -- dshi : Force shift first two or three pixels of each line IF o_dshi=0 THEN - dif_v:=(o_hacc_next - 2*o_hsize + (8*OHRES)) MOD (8*OHRES); - IF dif_v>=4*OHRES THEN + dif_v:=(o_hacc_next - 2*o_hsize + (8*OHRESH)) MOD (8*OHRESH); + IF dif_v>=4*OHRESH THEN o_hacc<=o_hacc_next; o_hacc_next<=o_hacc_next + 2*o_ihsize; hcarry_v:=false; ELSE o_hacc<=dif_v; - o_hacc_next<=(dif_v + 2*o_ihsize + (4*OHRES)) MOD (4*OHRES); + o_hacc_next<=(dif_v + 2*o_ihsize + (4*OHRESH)) MOD (4*OHRESH); hcarry_v:=true; END IF; - o_dcpt<=(o_dcpt+1) MOD 4096; + o_dcpt_inc <= '1'; ELSE o_dshi<=o_dshi-1; hcarry_v:=false; @@ -2219,6 +2301,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; @@ -2526,13 +2611,19 @@ BEGIN o_hfrac(2 TO 9) <= o_hfrac(1 TO 8); o_copyv(1 TO 14)<=o_copyv(0 TO 13); + o_dcptv_clr(1 TO 12)<=o_dcpt_clr & o_dcptv_clr(1 TO 11); + o_dcptv_inc(1 TO 12)<=o_dcpt_inc & o_dcptv_inc(1 TO 11); - o_dcptv(1)<=o_dcpt; - IF o_dcptv(1)>=o_hsize THEN - o_copyv(2)<='0'; + IF o_dcptv_clr(12)='1' THEN + o_dcptv(13) <= 0; + ELSIF o_dcptv_inc(12)='1' THEN + o_dcptv(13) <= (o_dcptv(13) + 1) MOD OHRESH; + END IF; + o_dcptv(14)<=o_dcptv(13); + + IF o_dcptv(13)>=o_hsize THEN + o_copyv(14)<='0'; END IF; - o_dcptv(2)<=o_dcptv(1) MOD OHRES; - o_dcptv(3 TO 14)<=o_dcptv(2 TO 13); -- C2 o_hpixq(2)<=(o_hpix3,o_hpix2,o_hpix1,o_hpix0); @@ -2625,17 +2716,39 @@ BEGIN OLBUF:PROCESS(o_clk) IS BEGIN IF rising_edge(o_clk) THEN + ----------------------------------------------- -- WRITES - IF o_wr(0)='1' THEN o_line0(o_wadl)<=o_ldw; END IF; - IF o_wr(1)='1' THEN o_line1(o_wadl)<=o_ldw; END IF; - IF o_wr(2)='1' THEN o_line2(o_wadl)<=o_ldw; END IF; - IF o_wr(3)='1' THEN o_line3(o_wadl)<=o_ldw; END IF; + IF o_wr(0)='1' AND o_wadl < OHRESL THEN o_line0(o_wadl MOD OHRESL)<=o_ldw; END IF; + IF o_wr(1)='1' AND o_wadl < OHRESL THEN o_line1(o_wadl MOD OHRESL)<=o_ldw; END IF; + IF o_wr(2)='1' AND o_wadl < OHRESL THEN o_line2(o_wadl MOD OHRESL)<=o_ldw; END IF; + IF o_wr(3)='1' AND o_wadl < OHRESL THEN o_line3(o_wadl MOD OHRESL)<=o_ldw; END IF; + IF OHRES = 2304 OR OHRES = 2560 THEN + IF o_wr(0)='1' AND o_wadl >= OHRESL THEN o_linf0(o_wadl MOD OHRESM)<=o_ldw; END IF; + IF o_wr(1)='1' AND o_wadl >= OHRESL THEN o_linf1(o_wadl MOD OHRESM)<=o_ldw; END IF; + IF o_wr(2)='1' AND o_wadl >= OHRESL THEN o_linf2(o_wadl MOD OHRESM)<=o_ldw; END IF; + IF o_wr(3)='1' AND o_wadl >= OHRESL THEN o_linf3(o_wadl MOD OHRESM)<=o_ldw; END IF; + END IF; + ----------------------------------------------- -- READS - o_ldr0<=o_line0(o_radl0); - o_ldr1<=o_line1(o_radl1); - o_ldr2<=o_line2(o_radl2); - o_ldr3<=o_line3(o_radl3); + o_ldr0<=o_line0(o_radl0 MOD OHRESL); + o_ldr1<=o_line1(o_radl1 MOD OHRESL); + o_ldr2<=o_line2(o_radl2 MOD OHRESL); + o_ldr3<=o_line3(o_radl3 MOD OHRESL); + + IF OHRES = 2304 OR OHRES = 2560 THEN + o_ler0<=o_linf0(o_radl0 MOD OHRESM); + o_ler1<=o_linf1(o_radl1 MOD OHRESM); + o_ler2<=o_linf2(o_radl2 MOD OHRESM); + o_ler3<=o_linf3(o_radl3 MOD OHRESM); + END IF; + + o_lex0 <= to_std_logic(o_radl0 >= OHRESL); + o_lex1 <= to_std_logic(o_radl1 >= OHRESL); + o_lex2 <= to_std_logic(o_radl2 >= OHRESL); + o_lex3 <= to_std_logic(o_radl3 >= OHRESL); + ----------------------------------------------- + END IF; END PROCESS OLBUF; @@ -2721,16 +2834,17 @@ BEGIN VSCAL:PROCESS(o_clk) IS VARIABLE pixq_v : arr_pix(0 TO 3); VARIABLE vlumpix_v : type_pix; - VARIABLE r1_v, r2_v : natural RANGE 0 TO OHRES-1; + VARIABLE r1_v, r2_v : natural RANGE 0 TO OHRESH-1; VARIABLE fracnn_v : std_logic; + VARIABLE o_l0_v, o_l1_v, o_l2_v, o_l3_v : type_pix; BEGIN IF rising_edge(o_clk) THEN IF o_ce='1' THEN o_v_hmin_adj<=o_hmin + 5; fracnn_v := o_vfrac(o_vfrac'left); - r1_v := (o_hcpt - o_v_hmin_adj + OHRES) MOD OHRES; - r2_v := (o_hcpt - o_hmin + OHRES) MOD OHRES; + r1_v := (o_hcpt - o_v_hmin_adj + OHRESH) MOD OHRESH; + r2_v := (o_hcpt - o_hmin + OHRESH) MOD OHRESH; -- CYCLE 1 ----------------------------------------- -- Read mem @@ -2757,11 +2871,16 @@ BEGIN -- CYCLE 2 ----------------------------------------- -- Lines reordering + IF o_lex0='0' THEN o_l0_v := o_ldr0; ELSE o_l0_v := o_ler0; END IF; + IF o_lex1='0' THEN o_l1_v := o_ldr1; ELSE o_l1_v := o_ler1; END IF; + IF o_lex2='0' THEN o_l2_v := o_ldr2; ELSE o_l2_v := o_ler2; END IF; + IF o_lex3='0' THEN o_l3_v := o_ldr3; ELSE o_l3_v := o_ler3; END IF; + CASE o_vacptl IS - WHEN "10" => pixq_v:=(o_ldr0,o_ldr1,o_ldr2,o_ldr3); - WHEN "11" => pixq_v:=(o_ldr1,o_ldr2,o_ldr3,o_ldr0); - WHEN "00" => pixq_v:=(o_ldr2,o_ldr3,o_ldr0,o_ldr1); - WHEN OTHERS => pixq_v:=(o_ldr3,o_ldr0,o_ldr1,o_ldr2); + WHEN "10" => pixq_v:=(o_l0_v,o_l1_v,o_l2_v,o_l3_v); + WHEN "11" => pixq_v:=(o_l1_v,o_l2_v,o_l3_v,o_l0_v); + WHEN "00" => pixq_v:=(o_l2_v,o_l3_v,o_l0_v,o_l1_v); + WHEN OTHERS => pixq_v:=(o_l3_v,o_l0_v,o_l1_v,o_l2_v); END CASE; IF fracnn_v = '0' THEN 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.tcl b/sys/sys.tcl index 93b6247..9f3de3e 100644 --- a/sys/sys.tcl +++ b/sys/sys.tcl @@ -65,8 +65,8 @@ set_location_assignment PIN_AD17 -to SDRAM_A[11] set_location_assignment PIN_D12 -to SDRAM_A[12] set_location_assignment PIN_Y17 -to SDRAM_BA[0] set_location_assignment PIN_AB25 -to SDRAM_BA[1] -set_location_assignment PIN_E8 -to SDRAM_DQ[0] -set_location_assignment PIN_V12 -to SDRAM_DQ[1] +set_location_assignment PIN_V12 -to SDRAM_DQ[0] +set_location_assignment PIN_E8 -to SDRAM_DQ[1] set_location_assignment PIN_D11 -to SDRAM_DQ[2] set_location_assignment PIN_W12 -to SDRAM_DQ[3] set_location_assignment PIN_AH13 -to SDRAM_DQ[4] diff --git a/sys/sys_top.sdc b/sys/sys_top.sdc index ac21334..c2b4118 100644 --- a/sys/sys_top.sdc +++ b/sys/sys_top.sdc @@ -74,4 +74,4 @@ set_false_path -from {ascal|o_hsstart* ascal|o_vsstart* ascal|o_hsend* ascal|o_v set_false_path -from {ascal|o_hsize* ascal|o_vsize*} set_false_path -from {mcp23009|flg_*} -set_false_path -to {sysmem|fpga_interfaces|clocks_resets*} +set_false_path -to {sysmem|fpga_interfaces|clocks_resets|f2h*} diff --git a/sys/sys_top.v b/sys/sys_top.v index 65129eb..a646213 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; @@ -299,8 +300,9 @@ wire audio_96k = cfg[6]; wire csync_en = cfg[3]; wire io_osd_vga = io_ss1 & ~io_ss2; `ifndef MISTER_DUAL_SDRAM - wire ypbpr_en = cfg[5]; - wire sog = cfg[9]; + wire forced_scandoubler = cfg[4]; + wire ypbpr_en = cfg[5]; + wire sog = cfg[9]; `ifdef MISTER_DEBUG_NOHDMI wire vga_scaler = 0; `else @@ -331,6 +333,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; @@ -392,6 +395,7 @@ always@(posedge clk_sys) begin `ifndef MISTER_DEBUG_NOHDMI if(io_din[7:0] == 'h40) io_dout_sys <= fb_crc; `endif + if(io_din[7:0] == 'h42) io_dout_sys <= {1'b1, frame_cnt}; end else begin cnt <= cnt + 1'd1; @@ -498,18 +502,22 @@ always@(posedge clk_sys) begin endcase end `endif -`ifndef MISTER_DISABLE_YC if(cmd == 'h41) begin case(cnt[3:0]) - 0: {pal_en,cvbs,yc_en} <= io_din[2:0]; - 1: PhaseInc[15:0] <= io_din; - 2: PhaseInc[31:16] <= io_din; - 3: PhaseInc[39:32] <= io_din[7:0]; - 4: ColorBurst_Range[15:0] <= io_din; - 5: ColorBurst_Range[16] <= io_din[0]; +`ifndef MISTER_DISABLE_YC + 0: {pal_en,cvbs,yc_en} <= io_din[2:0]; + 4: ColorBurst_Range[15:0] <= io_din; + 5: ColorBurst_Range[16] <= io_din[0]; +`endif + // Subcarrier commands (independent of YC module) + 1: PhaseInc[15:0] <= io_din; + 2: PhaseInc[31:16] <= io_din; + 3: PhaseInc[39:32] <= io_din[7:0]; +`ifndef MISTER_DUAL_SDRAM + 6: subcarrier <= io_din[0]; +`endif endcase end -`endif end end @@ -528,6 +536,15 @@ always@(posedge clk_sys) begin if(~vs_d2 & vs_d1) vs_wait <= 0; end +reg [7:0] frame_cnt; +always @(posedge clk_sys) begin + reg vs_r, vs_old; + + vs_r <= vs_fix; + if(vs_r == vs_fix) vs_old <= vs_r; + if(~vs_old & vs_r) frame_cnt <= frame_cnt + 1'd1; +end + cyclonev_hps_interface_peripheral_uart uart ( .ri(0), @@ -677,6 +694,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 +726,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 +771,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), @@ -1394,7 +1414,6 @@ csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); reg yc_en; reg cvbs; reg [16:0] ColorBurst_Range; - reg [39:0] PhaseInc; wire [23:0] yc_o; wire yc_hs, yc_vs, yc_cs, yc_de; @@ -1418,7 +1437,20 @@ csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); ); `endif +reg [39:0] PhaseInc; + `ifndef MISTER_DUAL_SDRAM + // Subcarrier generation for external encoders (independent of YC module) + reg subcarrier; + + reg [39:0] sub_accum; + always @(posedge clk_vid) sub_accum <= sub_accum + PhaseInc; + + // 1-bit output for positive/negative of wave, no LUT required. Output 1 if disabled for further logic + reg subcarrier_out; + always @(posedge clk_vid) subcarrier_out <= ~(subcarrier & csync_en & ~ypbpr_en & ~forced_scandoubler & ~vgas_en) | sub_accum[39]; + + wire VGA_DISABLE; wire [23:0] vgas_o; wire vgas_hs, vgas_vs, vgas_cs, vgas_de; @@ -1471,7 +1503,7 @@ csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); wire cs1 = vgas_en ? vgas_cs : vga_cs; wire de1 = vgas_en ? vgas_de : vga_de; - assign VGA_VS = av_dis ? 1'bZ : ((vgas_en ? (~vgas_vs ^ VS[12]) : VGA_DISABLE ? 1'd1 : ~vga_vs) | csync_en); + assign VGA_VS = av_dis ? 1'bZ :(((vgas_en ? (~vgas_vs ^ VS[12]) : VGA_DISABLE ? 1'd1 : ~vga_vs) | csync_en) & subcarrier_out); assign VGA_HS = av_dis ? 1'bZ : (vgas_en ? ((csync_en ? ~vgas_cs : ~vgas_hs) ^ HS[12]) : VGA_DISABLE ? 1'd1 : (csync_en ? ~vga_cs : ~vga_hs)); assign VGA_R = av_dis ? 6'bZZZZZZ : vgas_en ? vgas_o[23:18] : VGA_DISABLE ? 6'd0 : vga_o[23:18]; assign VGA_G = av_dis ? 6'bZZZZZZ : vgas_en ? vgas_o[15:10] : VGA_DISABLE ? 6'd0 : vga_o[15:10]; @@ -1734,6 +1766,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