diff --git a/Intv.qsf b/Intv.qsf index 0357976..9656ffd 100644 --- a/Intv.qsf +++ b/Intv.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.0 Lite 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 @@ -60,4 +60,5 @@ set_global_assignment -name SEED 1 source sys/sys.tcl source sys/sys_analog.tcl source files.qip -set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top + +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/intv.sv b/intv.sv index 8248fc6..e8e9c4b 100644 --- a/intv.sv +++ b/intv.sv @@ -54,6 +54,8 @@ module emu input [11:0] HDMI_WIDTH, input [11:0] HDMI_HEIGHT, output HDMI_FREEZE, + output HDMI_BLACKOUT, + output HDMI_BOB_DEINT, output LED_USER, // 1 - ON, 0 - OFF. output [1:0] LED_POWER, @@ -153,6 +155,8 @@ assign LED_USER = 0; assign LED_DISK = 0; assign LED_POWER = 0; assign HDMI_FREEZE = 0; +assign HDMI_BLACKOUT = 0; +assign HDMI_BOB_DEINT = 0; assign VGA_SCALER= 0; assign VGA_DISABLE = 0; diff --git a/releases/Intellivision_20250903.rbf b/releases/Intellivision_20250903.rbf new file mode 100644 index 0000000..43ccae3 Binary files /dev/null and b/releases/Intellivision_20250903.rbf differ diff --git a/sys/arcade_video.v b/sys/arcade_video.v index f53b136..f41d042 100644 --- a/sys/arcade_video.v +++ b/sys/arcade_video.v @@ -99,6 +99,11 @@ generate assign G = {RGB_fix[7:4],RGB_fix[7:4]}; assign B = {RGB_fix[3:0],RGB_fix[3:0]}; end + else if(DW == 18) begin + assign R = {RGB_fix[17:12],RGB_fix[17:16]}; + assign G = {RGB_fix[11: 6],RGB_fix[11:10]}; + assign B = {RGB_fix[ 5: 0],RGB_fix[ 5: 4]}; + end else begin // 24 assign R = RGB_fix[23:16]; assign G = RGB_fix[15:8]; 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 bf61f35..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, @@ -226,14 +226,13 @@ video_calc video_calc .new_vmode(new_vmode), .video_rotated(video_rotated), - .par_num(byte_cnt[3:0]), + .par_num(byte_cnt[4:0]), .dout(vc_dout) ); ///////////////////////////////////////////////////////// -localparam STRLEN = $size(CONF_STR)>>3; -localparam MAX_W = $clog2((32 > (STRLEN+2)) ? 32 : (STRLEN+2))-1; +localparam MAX_W = $clog2((64 > (STRLEN+2)) ? 64 : (STRLEN+2))-1; wire [7:0] conf_byte; generate @@ -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; @@ -502,7 +501,7 @@ always@(posedge clk_sys) begin : uio_block 'h22: RTC[(byte_cnt-6'd1)<<4 +:16] <= io_din; //Video res. - 'h23: if(!byte_cnt[MAX_W:4]) io_dout <= vc_dout; + 'h23: if(!byte_cnt[MAX_W:5]) io_dout <= vc_dout; //RTC 'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din; @@ -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; @@ -872,7 +871,7 @@ module video_calc input new_vmode, input video_rotated, - input [3:0] par_num, + input [4:0] par_num, output reg [15:0] dout ); @@ -893,6 +892,9 @@ always @(posedge clk_sys) begin 13: dout <= vid_vtime_hdmi[31:16]; 14: dout <= vid_ccnt[15:0]; 15: dout <= vid_ccnt[31:16]; + 16: dout <= vid_pixrep; + 17: dout <= vid_de_h; + 18: dout <= vid_de_v; default dout <= 0; endcase end @@ -902,24 +904,44 @@ reg [31:0] vid_vcnt = 0; reg [31:0] vid_ccnt = 0; reg [7:0] vid_nres = 0; reg [1:0] vid_int = 0; +reg [7:0] vid_pixrep; +reg [15:0] vid_de_h; +reg [7:0] vid_de_v; always @(posedge clk_vid) begin integer hcnt; integer vcnt; integer ccnt; - reg old_vs= 0, old_de = 0, old_vmode = 0; + reg [7:0] pcnt; + reg [7:0] de_v; + reg [15:0] de_h; + reg old_vs = 0, old_hs = 0, old_hs_vclk = 0, old_de = 0, old_de_vclk = 0, old_de1 = 0, old_vmode = 0; reg [3:0] resto = 0; reg calch = 0; if(calch & de) ccnt <= ccnt + 1; + pcnt <= pcnt + 1'd1; + + old_hs_vclk <= hs; + de_h <= de_h + 1'd1; + if(old_hs_vclk & ~hs) de_h <= 1; + + old_de_vclk <= de; + if(calch & ~old_de_vclk & de) vid_de_h <= de_h; if(ce_pix) begin old_vs <= vs; + old_hs <= hs; old_de <= de; + old_de1 <= old_de; + pcnt <= 1; if(~vs & ~old_de & de) vcnt <= vcnt + 1; if(calch & de) hcnt <= hcnt + 1; if(old_de & ~de) calch <= 0; + if(~old_de1 & old_de) vid_pixrep <= pcnt; + if(old_hs & ~hs) de_v <= de_v + 1'd1; + if(calch & ~old_de & de) vid_de_v <= de_v; if(old_vs & ~vs) begin vid_int <= {vid_int[0],f1}; @@ -939,6 +961,7 @@ always @(posedge clk_vid) begin hcnt <= 0; ccnt <= 0; calch <= 1; + de_v <= 0; end end end @@ -1008,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/mcp23009.sv b/sys/mcp23009.sv index 40cbf5e..82eaf37 100644 --- a/sys/mcp23009.sv +++ b/sys/mcp23009.sv @@ -8,10 +8,12 @@ module mcp23009 output reg [2:0] btn, input [2:0] led, - output reg sd_cd, + output reg flg_sd_cd, + output reg flg_present, + output reg flg_mode, - output scl, - inout sda + output scl, + inout sda ); @@ -50,7 +52,9 @@ always@(posedge clk) begin idx <= 0; btn <= 0; rw <= 0; - sd_cd <= 1; + flg_sd_cd <= 1; + flg_present <= 0; + flg_mode <= 1; end else begin if(~&init_data[idx]) begin @@ -84,7 +88,10 @@ always@(posedge clk) begin state <= 0; rw <= 0; if(!error) begin - if(rw) {sd_cd, btn} <= {dout[7], dout[5:3]}; + if(rw) begin + {flg_sd_cd, flg_mode, btn} <= {dout[7:3]}; + flg_present <= 1; + end rw <= ~rw; end end diff --git a/sys/pll_cfg.qip b/sys/pll_cfg.qip index c3394be..0b560f9 100644 --- a/sys/pll_cfg.qip +++ b/sys/pll_cfg.qip @@ -1,44 +1,5 @@ -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TOOL_NAME "altera_pll_reconfig" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TOOL_VERSION "17.0" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TOOL_ENV "mwpim" -set_global_assignment -library "pll_cfg" -name MISC_FILE [file join $::quartus(qip_path) "pll_cfg.cmp"] -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_QSYS_MODE "UNKNOWN" set_global_assignment -name SYNTHESIS_ONLY_QIP ON -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_NAME "cGxsX2hkbWlfY2Zn" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTCBSZWNvbmZpZw==" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_REPORT_HIERARCHY "Off" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_INTERNAL "Off" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_VERSION "MTcuMA==" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIFJlY29uZmlndXJhdGlvbiBCbG9jayhBTFRFUkFfUExMX1JFQ09ORklHKQ==" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0JZVEVFTkFCTEU=::ZmFsc2U=::QWRkIGJ5dGVlbmFibGUgcG9ydA==" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "QllURUVOQUJMRV9XSURUSA==::NA==::QllURUVOQUJMRV9XSURUSA==" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfQUREUl9XSURUSA==::Ng==::UkVDT05GSUdfQUREUl9XSURUSA==" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfREFUQV9XSURUSA==::MzI=::UkVDT05GSUdfREFUQV9XSURUSA==" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "cmVjb25mX3dpZHRo::NjQ=::cmVjb25mX3dpZHRo" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "V0FJVF9GT1JfTE9DSw==::dHJ1ZQ==::V0FJVF9GT1JfTE9DSw==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_NAME "YWx0ZXJhX3BsbF9yZWNvbmZpZ190b3A=" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTCBSZWNvbmZpZw==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_REPORT_HIERARCHY "Off" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_INTERNAL "Off" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_VERSION "MTcuMA==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIFJlY29uZmlndXJhdGlvbiBCbG9jayhBTFRFUkFfUExMX1JFQ09ORklHKQ==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "ZGV2aWNlX2ZhbWlseQ==::Q3ljbG9uZSBW::ZGV2aWNlX2ZhbWlseQ==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX01JRg==::ZmFsc2U=::RW5hYmxlIE1JRiBTdHJlYW1pbmc=" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0JZVEVFTkFCTEU=::ZmFsc2U=::QWRkIGJ5dGVlbmFibGUgcG9ydA==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "QllURUVOQUJMRV9XSURUSA==::NA==::QllURUVOQUJMRV9XSURUSA==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfQUREUl9XSURUSA==::Ng==::UkVDT05GSUdfQUREUl9XSURUSA==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfREFUQV9XSURUSA==::MzI=::UkVDT05GSUdfREFUQV9XSURUSA==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "cmVjb25mX3dpZHRo::NjQ=::cmVjb25mX3dpZHRo" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "V0FJVF9GT1JfTE9DSw==::dHJ1ZQ==::V0FJVF9GT1JfTE9DSw==" - -set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg.v"] +set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/pll_cfg.v"] +set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/pll_cfg_hdmi.v"] set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/altera_pll_reconfig_top.v"] set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/altera_pll_reconfig_core.v"] - -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_TOOL_NAME "altera_pll_reconfig" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_TOOL_VERSION "17.0" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll_cfg/altera_pll_reconfig_core.v b/sys/pll_cfg/altera_pll_reconfig_core.v index 4bc1fbb..a9e2b8c 100644 --- a/sys/pll_cfg/altera_pll_reconfig_core.v +++ b/sys/pll_cfg/altera_pll_reconfig_core.v @@ -16,7 +16,7 @@ module altera_pll_reconfig_core #( parameter reconf_width = 64, - parameter device_family = "Stratix V", + parameter device_family = "Cyclone V", // MIF Streaming parameters parameter RECONFIG_ADDR_WIDTH = 6, parameter RECONFIG_DATA_WIDTH = 32, @@ -1883,7 +1883,7 @@ module fpll_dprio_init ( endmodule module dyn_phase_shift #( - parameter device_family = "Stratix V" + parameter device_family = "Cyclone V" ) ( input wire clk, @@ -2112,7 +2112,7 @@ endmodule module generic_lcell_comb #( //parameter - parameter family = "Stratix V", + parameter family = "Cyclone V", parameter lut_mask = 64'hAAAAAAAAAAAAAAAA, parameter dont_touch = "on" ) ( diff --git a/sys/pll_cfg/altera_pll_reconfig_top.v b/sys/pll_cfg/altera_pll_reconfig_top.v index c1bfa8b..843c970 100644 --- a/sys/pll_cfg/altera_pll_reconfig_top.v +++ b/sys/pll_cfg/altera_pll_reconfig_top.v @@ -16,7 +16,7 @@ module altera_pll_reconfig_top #( parameter reconf_width = 64, - parameter device_family = "Stratix V", + parameter device_family = "Cyclone V", parameter RECONFIG_ADDR_WIDTH = 6, parameter RECONFIG_DATA_WIDTH = 32, diff --git a/sys/pll_cfg.v b/sys/pll_cfg/pll_cfg.v similarity index 98% rename from sys/pll_cfg.v rename to sys/pll_cfg/pll_cfg.v index 0adc36f..2a2f078 100644 --- a/sys/pll_cfg.v +++ b/sys/pll_cfg/pll_cfg.v @@ -1,86 +1,86 @@ -// megafunction wizard: %Altera PLL Reconfig v17.0% -// GENERATION: XML -// pll_cfg.v - -// Generated using ACDS version 17.0 598 - -`timescale 1 ps / 1 ps -module pll_cfg #( - parameter ENABLE_BYTEENABLE = 0, - parameter BYTEENABLE_WIDTH = 4, - parameter RECONFIG_ADDR_WIDTH = 6, - parameter RECONFIG_DATA_WIDTH = 32, - parameter reconf_width = 64, - parameter WAIT_FOR_LOCK = 1 - ) ( - input wire mgmt_clk, // mgmt_clk.clk - input wire mgmt_reset, // mgmt_reset.reset - output wire mgmt_waitrequest, // mgmt_avalon_slave.waitrequest - input wire mgmt_read, // .read - input wire mgmt_write, // .write - output wire [31:0] mgmt_readdata, // .readdata - input wire [5:0] mgmt_address, // .address - input wire [31:0] mgmt_writedata, // .writedata - output wire [63:0] reconfig_to_pll, // reconfig_to_pll.reconfig_to_pll - input wire [63:0] reconfig_from_pll // reconfig_from_pll.reconfig_from_pll - ); - - altera_pll_reconfig_top #( - .device_family ("Cyclone V"), - .ENABLE_MIF (0), - .MIF_FILE_NAME ("sys/pll_cfg.mif"), - .ENABLE_BYTEENABLE (ENABLE_BYTEENABLE), - .BYTEENABLE_WIDTH (BYTEENABLE_WIDTH), - .RECONFIG_ADDR_WIDTH (RECONFIG_ADDR_WIDTH), - .RECONFIG_DATA_WIDTH (RECONFIG_DATA_WIDTH), - .reconf_width (reconf_width), - .WAIT_FOR_LOCK (WAIT_FOR_LOCK) - ) pll_cfg_inst ( - .mgmt_clk (mgmt_clk), // mgmt_clk.clk - .mgmt_reset (mgmt_reset), // mgmt_reset.reset - .mgmt_waitrequest (mgmt_waitrequest), // mgmt_avalon_slave.waitrequest - .mgmt_read (mgmt_read), // .read - .mgmt_write (mgmt_write), // .write - .mgmt_readdata (mgmt_readdata), // .readdata - .mgmt_address (mgmt_address), // .address - .mgmt_writedata (mgmt_writedata), // .writedata - .reconfig_to_pll (reconfig_to_pll), // reconfig_to_pll.reconfig_to_pll - .reconfig_from_pll (reconfig_from_pll), // reconfig_from_pll.reconfig_from_pll - .mgmt_byteenable (4'b0000) // (terminated) - ); - -endmodule -// Retrieval info: -// -// Retrieval info: -// Retrieval info: -// Retrieval info: -// Retrieval info: -// Retrieval info: -// Retrieval info: -// IPFS_FILES : pll_cfg.vo -// RELATED_FILES: pll_cfg.v, altera_pll_reconfig_top.v, altera_pll_reconfig_core.v, altera_std_synchronizer.v +// megafunction wizard: %Altera PLL Reconfig v17.0% +// GENERATION: XML +// pll_cfg.v + +// Generated using ACDS version 17.0 598 + +`timescale 1 ps / 1 ps +module pll_cfg #( + parameter ENABLE_BYTEENABLE = 0, + parameter BYTEENABLE_WIDTH = 4, + parameter RECONFIG_ADDR_WIDTH = 6, + parameter RECONFIG_DATA_WIDTH = 32, + parameter reconf_width = 64, + parameter WAIT_FOR_LOCK = 1 + ) ( + input wire mgmt_clk, // mgmt_clk.clk + input wire mgmt_reset, // mgmt_reset.reset + output wire mgmt_waitrequest, // mgmt_avalon_slave.waitrequest + input wire mgmt_read, // .read + input wire mgmt_write, // .write + output wire [31:0] mgmt_readdata, // .readdata + input wire [5:0] mgmt_address, // .address + input wire [31:0] mgmt_writedata, // .writedata + output wire [63:0] reconfig_to_pll, // reconfig_to_pll.reconfig_to_pll + input wire [63:0] reconfig_from_pll // reconfig_from_pll.reconfig_from_pll + ); + + altera_pll_reconfig_top #( + .device_family ("Cyclone V"), + .ENABLE_MIF (0), + .MIF_FILE_NAME ("sys/pll_cfg.mif"), + .ENABLE_BYTEENABLE (ENABLE_BYTEENABLE), + .BYTEENABLE_WIDTH (BYTEENABLE_WIDTH), + .RECONFIG_ADDR_WIDTH (RECONFIG_ADDR_WIDTH), + .RECONFIG_DATA_WIDTH (RECONFIG_DATA_WIDTH), + .reconf_width (reconf_width), + .WAIT_FOR_LOCK (WAIT_FOR_LOCK) + ) pll_cfg_inst ( + .mgmt_clk (mgmt_clk), // mgmt_clk.clk + .mgmt_reset (mgmt_reset), // mgmt_reset.reset + .mgmt_waitrequest (mgmt_waitrequest), // mgmt_avalon_slave.waitrequest + .mgmt_read (mgmt_read), // .read + .mgmt_write (mgmt_write), // .write + .mgmt_readdata (mgmt_readdata), // .readdata + .mgmt_address (mgmt_address), // .address + .mgmt_writedata (mgmt_writedata), // .writedata + .reconfig_to_pll (reconfig_to_pll), // reconfig_to_pll.reconfig_to_pll + .reconfig_from_pll (reconfig_from_pll), // reconfig_from_pll.reconfig_from_pll + .mgmt_byteenable (4'b0000) // (terminated) + ); + +endmodule +// Retrieval info: +// +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// IPFS_FILES : pll_cfg.vo +// RELATED_FILES: pll_cfg.v, altera_pll_reconfig_top.v, altera_pll_reconfig_core.v, altera_std_synchronizer.v diff --git a/sys/pll_cfg/pll_cfg_hdmi.v b/sys/pll_cfg/pll_cfg_hdmi.v new file mode 100644 index 0000000..1912c2a --- /dev/null +++ b/sys/pll_cfg/pll_cfg_hdmi.v @@ -0,0 +1,1282 @@ +// (C) 2001-2017 Intel Corporation. All rights reserved. +// Your use of Intel Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Intel Program License Subscription +// Agreement, Intel MegaCore Function License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Intel and sold by +// Intel or its authorized distributors. Please refer to the applicable +// agreement for further details. + +// original file was altera_pll_reconfig_core.v +// not needed functionality was cut out to reduce ressource consumption + +module pll_cfg_hdmi +#( + parameter reconf_width = 64, + parameter device_family = "Cyclone V" +) ( + + //input + input wire mgmt_clk, + input wire mgmt_reset, + + + //conduits + output wire [reconf_width-1:0] reconfig_to_pll, + input wire [reconf_width-1:0] reconfig_from_pll, + + // user data (avalon-MM slave interface) + output wire mgmt_waitrequest, + input wire [5:0] mgmt_address, + input wire mgmt_write, + input wire [31:0] mgmt_writedata +); + localparam mode_WR = 1'b0; + localparam MODE_REG = 6'b000000; + localparam START_REG = 6'b000010; + localparam N_REG = 6'b000011; + localparam M_REG = 6'b000100; + localparam C_COUNTERS_REG = 6'b000101; + //localparam DPS_REG = 6'b000110; // unused + localparam DSM_REG = 6'b000111; + localparam BWCTRL_REG = 6'b001000; + localparam CP_CURRENT_REG = 6'b001001; + //localparam ANY_DPRIO = 6'b100000; // unused + //localparam CNT_BASE = 5'b001010; // unused + //localparam VCO_REG = 6'b011100; // unused + + //C Counters + localparam number_of_counters = 5'd6; + //C counter addresses + localparam C_CNT_0_DIV_ADDR = 5'h00; + localparam C_CNT_0_DIV_ADDR_DPRIO_1 = 5'h11; + localparam C_CNT_0_3_BYPASS_EN_ADDR = 5'h15; + localparam C_CNT_0_3_ODD_DIV_EN_ADDR = 5'h17; + localparam C_CNT_4_17_BYPASS_EN_ADDR = 5'h14; + localparam C_CNT_4_17_ODD_DIV_EN_ADDR = 5'h16; + //N counter addresses + localparam N_CNT_DIV_ADDR = 5'h13; + localparam N_CNT_BYPASS_EN_ADDR = 5'h15; + localparam N_CNT_ODD_DIV_EN_ADDR = 5'h17; + //M counter addresses + localparam M_CNT_DIV_ADDR = 5'h12; + localparam M_CNT_BYPASS_EN_ADDR = 5'h15; + localparam M_CNT_ODD_DIV_EN_ADDR = 5'h17; + + //DSM address + localparam DSM_K_FRACTIONAL_DIVISION_ADDR_0 = 5'h18; + localparam DSM_K_FRACTIONAL_DIVISION_ADDR_1 = 5'h19; + localparam DSM_K_READY_ADDR = 5'h17; + localparam DSM_K_DITHER_ADDR = 5'h17; + localparam DSM_OUT_SEL_ADDR = 6'h30; + + //Other DSM params + localparam DSM_K_READY_BIT_INDEX = 4'd11; + //BWCTRL address + //Bit 0-3 of addr + localparam BWCTRL_ADDR = 6'h30; + //CP_CURRENT address + //Bit 0-2 of addr + localparam CP_CURRENT_ADDR = 6'h31; + + // VCODIV address + localparam VCO_ADDR = 5'h17; + + localparam DPRIO_IDLE = 3'd0, ONE = 3'd1, TWO = 3'd2, THREE = 3'd3, FOUR = 3'd4, + FIVE = 3'd5, SIX = 3'd6, SEVEN = 3'd7, EIGHT = 4'd8, NINE = 4'd9, TEN = 4'd10, + ELEVEN = 4'd11, TWELVE = 4'd12, THIRTEEN = 4'd13, FOURTEEN = 4'd14, DPRIO_DONE = 4'd15; + localparam IDLE = 2'b00, WAIT_ON_LOCK = 2'b01, LOCKED = 2'b10; + + wire clk; + wire reset; + wire gnd; + + wire [5: 0] slave_address; + wire slave_write; + wire [31: 0] slave_writedata; + + wire slave_waitrequest; + reg slave_mode; + + assign clk = mgmt_clk; + + assign slave_address = mgmt_address; + assign slave_write = mgmt_write; + assign slave_writedata = mgmt_writedata; + + // Outputs + assign mgmt_waitrequest = slave_waitrequest; //Read waitrequest asserted in polling mode + + //internal signals + wire locked_orig; + wire locked; + + wire pll_start; + wire pll_start_valid; + + wire pll_start_asserted; + + reg [1:0] current_state; + reg [1:0] next_state; + + reg status;//0=busy, 1=ready + //user_mode_init user_mode_init_inst (clk, reset, dprio_mdio_dis, ser_shift_load); + //declaring the init wires. These will have 0 on them for 64 clk cycles + wire [ 5:0] init_dprio_address; + wire init_dprio_read; + wire [ 1:0] init_dprio_byteen; + wire init_dprio_write; + wire [15:0] init_dprio_writedata; + + wire init_atpgmode; + wire init_mdio_dis; + wire init_scanen; + wire init_ser_shift_load; + wire dprio_init_done; + + //DPRIO output signals after initialization is done + wire dprio_clk; + reg avmm_dprio_write; + reg avmm_dprio_read; + reg [5:0] avmm_dprio_address; + reg [15:0] avmm_dprio_writedata; + reg [1:0] avmm_dprio_byteen; + wire avmm_atpgmode; + wire avmm_mdio_dis; + wire avmm_scanen; + + //Final output wires that are muxed between the init and avmm wires. + wire dprio_init_reset; + wire [5:0] dprio_address /*synthesis keep*/; + wire dprio_read/*synthesis keep*/; + wire [1:0] dprio_byteen/*synthesis keep*/; + wire dprio_write/*synthesis keep*/; + wire [15:0] dprio_writedata/*synthesis keep*/; + wire dprio_mdio_dis/*synthesis keep*/; + wire dprio_ser_shift_load/*synthesis keep*/; + wire dprio_atpgmode/*synthesis keep*/; + wire dprio_scanen/*synthesis keep*/; + + + //other PLL signals for dyn ph shift + wire phase_done/*synthesis keep*/; + wire phase_en/*synthesis keep*/; + wire up_dn/*synthesis keep*/; + wire [4:0] cnt_sel; + + //DPRIO input signals + wire [15:0] dprio_readdata; + + //internal logic signals + //storage registers for user sent data + reg dprio_temp_read_1; + reg dprio_temp_read_2; + reg dprio_start; + wire usr_valid_changes; + reg [3:0] dprio_cur_state; + reg [3:0] dprio_next_state; + reg [15:0] dprio_temp_m_n_c_readdata_1_d; + reg [15:0] dprio_temp_m_n_c_readdata_2_d; + reg [15:0] dprio_temp_m_n_c_readdata_1_q; + reg [15:0] dprio_temp_m_n_c_readdata_2_q; + reg dprio_write_done; + //C counters signals + reg [7:0] usr_c_cnt_lo; + reg [7:0] usr_c_cnt_hi; + reg usr_c_cnt_bypass_en; + reg usr_c_cnt_odd_duty_div_en; + reg temp_c_cnt_bypass_en [0:17]; + reg temp_c_cnt_odd_duty_div_en [0:17]; + reg any_c_cnt_changed; + reg all_c_cnt_done_q; + reg all_c_cnt_done_d; + reg [17:0] c_cnt_changed; + reg [17:0] c_cnt_done_d; + reg [17:0] c_cnt_done_q; + //N counter signals + reg [7:0] usr_n_cnt_lo; + reg [7:0] usr_n_cnt_hi; + reg usr_n_cnt_bypass_en; + reg usr_n_cnt_odd_duty_div_en; + reg n_cnt_changed; + reg n_cnt_done_d; + reg n_cnt_done_q; + //M counter signals + reg [7:0] usr_m_cnt_lo; + reg [7:0] usr_m_cnt_hi; + reg usr_m_cnt_bypass_en; + reg usr_m_cnt_odd_duty_div_en; + reg m_cnt_changed; + reg m_cnt_done_d; + reg m_cnt_done_q; + //dyn phase regs + reg [15:0] usr_num_shifts; + reg [4:0] usr_cnt_sel /*synthesis preserve*/; + reg usr_up_dn; + reg dps_changed; + wire dps_changed_valid; + wire dps_done; + + //DSM Signals + reg [31:0] usr_k_value; + reg dsm_k_changed; + reg dsm_k_done_d; + reg dsm_k_done_q; + reg dsm_k_ready_false_done_d; + //BW signals + reg [3:0] usr_bwctrl_value; + reg bwctrl_changed; + reg bwctrl_done_d; + reg bwctrl_done_q; + //CP signals + reg [2:0] usr_cp_current_value; + reg cp_current_changed; + reg cp_current_done_d; + reg cp_current_done_q; + //VCO signals + reg usr_vco_value; + reg vco_changed; + reg vco_done_d; + reg vco_done_q; + //Manual DPRIO signals + reg manual_dprio_done_q; + reg manual_dprio_done_d; + reg manual_dprio_changed; + reg [5:0] usr_dprio_address; + reg [15:0] usr_dprio_writedata_0; + reg usr_r_w; + //keeping track of which operation happened last + reg [5:0] operation_address; + // Address wires for all C_counter DPRIO registers + // These are outputs of LUTS, changing depending + // on whether PLL_0 or PLL_1 being used + + + //Fitter will tell if FPLL1 is being used + wire fpll_1; + + // MAIN FSM + + // Synchronize locked signal + altera_std_synchronizer #( + .depth(3) + ) altera_std_synchronizer_inst ( + .clk(mgmt_clk), + .reset_n(~mgmt_reset), + .din(locked_orig), + .dout(locked) + ); + + always @(posedge clk) + begin + if (reset) + begin + dprio_cur_state <= DPRIO_IDLE; + current_state <= IDLE; + end + else + begin + current_state <= next_state; + dprio_cur_state <= dprio_next_state; + end + end + + always @(*) + begin + case(current_state) + IDLE: + begin + if (pll_start & !slave_waitrequest & usr_valid_changes) + next_state = WAIT_ON_LOCK; + else + next_state = IDLE; + end + WAIT_ON_LOCK: + begin + if (locked & dps_done & dprio_write_done) // received locked high from PLL + begin + if (slave_mode==mode_WR) //if the mode is waitrequest, then + // goto IDLE state directly + next_state = IDLE; + else + next_state = LOCKED; //otherwise go the locked state + end + else + next_state = WAIT_ON_LOCK; + end + + LOCKED: + begin + next_state = LOCKED; + end + + default: next_state = 2'bxx; + + endcase + end + + + // ask the pll to start reconfig + assign pll_start = (pll_start_asserted & (current_state==IDLE)) ; + assign pll_start_valid = (pll_start & (next_state==WAIT_ON_LOCK)) ; + + + + // WRITE OPERATIONS + assign pll_start_asserted = slave_write & (slave_address == START_REG); + + //reading the mode register to determine what mode the slave will operate + //in. + always @(posedge clk) + begin + if (reset) + slave_mode <= mode_WR; + else if (slave_write & (slave_address == MODE_REG) & !slave_waitrequest) + slave_mode <= slave_writedata[0]; + end + + //record which values user wants to change. + + //reading in the actual values that need to be reconfigged and sending + //them to the PLL + always @(posedge clk) + begin + if (reset) + begin + //reset all regs here + //BW signals reset + usr_bwctrl_value <= 0; + bwctrl_changed <= 0; + bwctrl_done_q <= 0; + //CP signals reset + usr_cp_current_value <= 0; + cp_current_changed <= 0; + cp_current_done_q <= 0; + //VCO signals reset + usr_vco_value <= 0; + vco_changed <= 0; + vco_done_q <= 0; + //DSM signals reset + usr_k_value <= 0; + dsm_k_changed <= 0; + dsm_k_done_q <= 0; + //N counter signals reset + usr_n_cnt_lo <= 0; + usr_n_cnt_hi <= 0; + usr_n_cnt_bypass_en <= 0; + usr_n_cnt_odd_duty_div_en <= 0; + n_cnt_changed <= 0; + n_cnt_done_q <= 0; + //M counter signals reset + usr_m_cnt_lo <= 0; + usr_m_cnt_hi <= 0; + usr_m_cnt_bypass_en <= 0; + usr_m_cnt_odd_duty_div_en <= 0; + m_cnt_changed <= 0; + m_cnt_done_q <= 0; + //C counter signals reset + usr_c_cnt_lo <= 0; + usr_c_cnt_hi <= 0; + usr_c_cnt_bypass_en <= 0; + usr_c_cnt_odd_duty_div_en <= 0; + any_c_cnt_changed <= 0; + all_c_cnt_done_q <= 0; + c_cnt_done_q <= 0; + //generic signals + dprio_start <= 0; + dprio_temp_m_n_c_readdata_1_q <= 0; + dprio_temp_m_n_c_readdata_2_q <= 0; + c_cnt_done_q <= 0; + //DPS signals + usr_up_dn <= 0; + usr_cnt_sel <= 0; + usr_num_shifts <= 0; + dps_changed <= 0; + //manual DPRIO signals + manual_dprio_changed <= 0; + usr_dprio_address <= 0; + usr_dprio_writedata_0 <= 0; + usr_r_w <= 0; + operation_address <= 0; + end + else + begin + if (dprio_temp_read_1) + begin + dprio_temp_m_n_c_readdata_1_q <= dprio_temp_m_n_c_readdata_1_d; + end + if (dprio_temp_read_2) + begin + dprio_temp_m_n_c_readdata_2_q <= dprio_temp_m_n_c_readdata_2_d; + end + if ((dps_done)) dps_changed <= 0; + if (dsm_k_done_d) dsm_k_done_q <= dsm_k_done_d; + if (n_cnt_done_d) n_cnt_done_q <= n_cnt_done_d; + if (m_cnt_done_d) m_cnt_done_q <= m_cnt_done_d; + if (all_c_cnt_done_d) all_c_cnt_done_q <= all_c_cnt_done_d; + if (c_cnt_done_d != 0) c_cnt_done_q <= c_cnt_done_q | c_cnt_done_d; + if (bwctrl_done_d) bwctrl_done_q <= bwctrl_done_d; + if (cp_current_done_d) cp_current_done_q <= cp_current_done_d; + if (vco_done_d) vco_done_q <= vco_done_d; + if (manual_dprio_done_d) manual_dprio_done_q <= manual_dprio_done_d; + + if (dprio_next_state == ONE) + dprio_start <= 0; + if (dprio_write_done) + begin + bwctrl_done_q <= 0; + cp_current_done_q <= 0; + vco_done_q <= 0; + dsm_k_done_q <= 0; + dsm_k_done_q <= 0; + n_cnt_done_q <= 0; + m_cnt_done_q <= 0; + all_c_cnt_done_q <= 0; + c_cnt_done_q <= 0; + dsm_k_changed <= 0; + n_cnt_changed <= 0; + m_cnt_changed <= 0; + any_c_cnt_changed <= 0; + bwctrl_changed <= 0; + cp_current_changed <= 0; + vco_changed <= 0; + manual_dprio_changed <= 0; + manual_dprio_done_q <= 0; + + end + else + begin + dsm_k_changed <= dsm_k_changed; + n_cnt_changed <= n_cnt_changed; + m_cnt_changed <= m_cnt_changed; + any_c_cnt_changed <= any_c_cnt_changed; + manual_dprio_changed <= manual_dprio_changed; + end + + + if(slave_write & !slave_waitrequest) + begin + case(slave_address) + //read in the values here from the user and act on them + DSM_REG: + begin + operation_address <= DSM_REG; + usr_k_value <= slave_writedata[31:0]; + dsm_k_changed <= 1'b1; + dsm_k_done_q <= 0; + dprio_start <= 1'b1; + end + N_REG: + begin + operation_address <= N_REG; + usr_n_cnt_lo <= slave_writedata[7:0]; + usr_n_cnt_hi <= slave_writedata[15:8]; + usr_n_cnt_bypass_en <= slave_writedata[16]; + usr_n_cnt_odd_duty_div_en <= slave_writedata[17]; + n_cnt_changed <= 1'b1; + n_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + M_REG: + begin + operation_address <= M_REG; + usr_m_cnt_lo <= slave_writedata[7:0]; + usr_m_cnt_hi <= slave_writedata[15:8]; + usr_m_cnt_bypass_en <= slave_writedata[16]; + usr_m_cnt_odd_duty_div_en <= slave_writedata[17]; + m_cnt_changed <= 1'b1; + m_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + //DPS_REG: + //begin + // operation_address <= DPS_REG; + // usr_num_shifts <= slave_writedata[15:0]; + // usr_up_dn <= slave_writedata[21]; + // dps_changed <= 1; + //end + C_COUNTERS_REG: + begin + operation_address <= C_COUNTERS_REG; + usr_c_cnt_lo <= slave_writedata[7:0]; + usr_c_cnt_hi <= slave_writedata[15:8]; + usr_c_cnt_bypass_en <= slave_writedata[16]; + usr_c_cnt_odd_duty_div_en <= slave_writedata[17]; + any_c_cnt_changed <= 1'b1; + all_c_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + BWCTRL_REG: + begin + usr_bwctrl_value <= slave_writedata[3:0]; + bwctrl_changed <= 1'b1; + bwctrl_done_q <= 0; + dprio_start <= 1'b1; + operation_address <= BWCTRL_REG; + end + CP_CURRENT_REG: + begin + usr_cp_current_value <= slave_writedata[2:0]; + cp_current_changed <= 1'b1; + cp_current_done_q <= 0; + dprio_start <= 1'b1; + operation_address <= CP_CURRENT_REG; + end + //VCO_REG: + //begin + // usr_vco_value <= slave_writedata[0]; + // vco_changed <= 1'b1; + // vco_done_q <= 0; + // dprio_start <= 1'b1; + // operation_address <= VCO_REG; + //end + //ANY_DPRIO: + //begin + // operation_address <= ANY_DPRIO; + // manual_dprio_changed <= 1'b1; + // usr_dprio_address <= slave_writedata[5:0]; + // usr_dprio_writedata_0 <= slave_writedata[21:6]; + // usr_r_w <= slave_writedata[22]; + // manual_dprio_done_q <= 0; + // dprio_start <= 1'b1; + //end + endcase + end + end + end + //C Counter assigning values to the 2-d array of values for each C counter + + reg [4:0] j; + always @(posedge clk) + begin + + if (reset) + begin + c_cnt_changed[17:0] <= 0; + for (j = 0; j < number_of_counters; j = j + 1'b1) + begin : c_cnt_reset + temp_c_cnt_bypass_en[j] <= 0; + temp_c_cnt_odd_duty_div_en[j] <= 0; + end + end + else + begin + if (dprio_write_done) + begin + c_cnt_changed <= 0; + end + if (any_c_cnt_changed && (operation_address == C_COUNTERS_REG)) + begin + temp_c_cnt_bypass_en [5] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [5] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [5] <= 1'b1; + end + end + end + + + //logic to handle which writes the user indicated and wants to start. + assign usr_valid_changes =dsm_k_changed| any_c_cnt_changed |n_cnt_changed | m_cnt_changed | dps_changed_valid |manual_dprio_changed |cp_current_changed|bwctrl_changed|vco_changed; + + + //start the reconfig operations by writing to the DPRIO + reg break_loop; + reg [4:0] i; + always @(*) + begin + dprio_temp_read_1 = 0; + dprio_temp_read_2 = 0; + dprio_temp_m_n_c_readdata_1_d = 0; + dprio_temp_m_n_c_readdata_2_d = 0; + break_loop = 0; + dprio_next_state = DPRIO_IDLE; + avmm_dprio_write = 0; + avmm_dprio_read = 0; + avmm_dprio_address = 0; + avmm_dprio_writedata = 0; + avmm_dprio_byteen = 0; + dprio_write_done = 1; + manual_dprio_done_d = 0; + n_cnt_done_d = 0; + dsm_k_done_d = 0; + dsm_k_ready_false_done_d = 0; + m_cnt_done_d = 0; + c_cnt_done_d[17:0] = 0; + all_c_cnt_done_d = 0; + bwctrl_done_d = 0; + cp_current_done_d = 0; + vco_done_d = 0; + i = 0; + + // Deassert dprio_write_done so it doesn't reset mif_reg_asserted (toggled writes) + if (dprio_start) + dprio_write_done = 0; + + if (current_state == WAIT_ON_LOCK) + begin + case (dprio_cur_state) + ONE: + begin + if (n_cnt_changed & !n_cnt_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_address = N_CNT_DIV_ADDR; + avmm_dprio_writedata[7:0] = usr_n_cnt_lo; + avmm_dprio_writedata[15:8] = usr_n_cnt_hi; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_address = M_CNT_DIV_ADDR; + avmm_dprio_writedata[7:0] = usr_m_cnt_lo; + avmm_dprio_writedata[15:8] = usr_m_cnt_hi; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + + for (i = 0; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_hilo + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + if (fpll_1) avmm_dprio_address = C_CNT_0_DIV_ADDR + C_CNT_0_DIV_ADDR_DPRIO_1 - i; + else avmm_dprio_address = C_CNT_0_DIV_ADDR + i; + avmm_dprio_writedata[7:0] = usr_c_cnt_lo; + avmm_dprio_writedata[15:8] = usr_c_cnt_hi; + //To break from the loop, since only one counter + //is addressed at a time + break_loop = 1'b1; + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (cp_current_changed & !cp_current_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (vco_changed & !vco_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (manual_dprio_changed & !manual_dprio_done_q) + begin + dprio_write_done = 0; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_write = usr_r_w; + avmm_dprio_address = usr_dprio_address; + avmm_dprio_writedata[15:0] = usr_dprio_writedata_0; + end + else dprio_next_state = DPRIO_IDLE; + end + + TWO: + begin + //handle reading the two setting bits on n_cnt, then + //writing them back while preserving other bits. + //Issue two consecutive reads then wait; readLatency=3 + dprio_write_done = 0; + dprio_next_state = THREE; + avmm_dprio_byteen = 2'b11; + avmm_dprio_read = 1'b1; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_BYPASS_EN_ADDR; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_BYPASS_EN_ADDR; + end + + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_read_bypass + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + end + end + end + //reading the K ready 16 bit word. Need to write 0 to it + //afterwards to indicate that K has not been done writing + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + dprio_next_state = FOUR; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_address = BWCTRL_ADDR; + dprio_next_state = FOUR; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_address = CP_CURRENT_ADDR; + dprio_next_state = FOUR; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_address = VCO_ADDR; + dprio_next_state = FOUR; + end + else if (manual_dprio_changed & !manual_dprio_done_q) + begin + avmm_dprio_read = ~usr_r_w; + avmm_dprio_address = usr_dprio_address; + dprio_next_state = DPRIO_DONE; + end + else dprio_next_state = DPRIO_IDLE; + end + THREE: + begin + dprio_write_done = 0; + avmm_dprio_byteen = 2'b11; + avmm_dprio_read = 1'b1; + dprio_next_state = FOUR; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_ODD_DIV_EN_ADDR; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_ODD_DIV_EN_ADDR; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_read_odd_div + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + end + end + end + else dprio_next_state = DPRIO_IDLE; + end + FOUR: + begin + dprio_temp_read_1 = 1'b1; + dprio_write_done = 0; + if (vco_changed|cp_current_changed|bwctrl_changed|dsm_k_changed|n_cnt_changed|m_cnt_changed|any_c_cnt_changed) + begin + dprio_temp_m_n_c_readdata_1_d = dprio_readdata; + dprio_next_state = FIVE; + end + else dprio_next_state = DPRIO_IDLE; + end + FIVE: + begin + dprio_write_done = 0; + dprio_temp_read_2 = 1'b1; + if (vco_changed|cp_current_changed|bwctrl_changed|dsm_k_changed|n_cnt_changed|m_cnt_changed|any_c_cnt_changed) + begin + //this is where DSM ready value comes. + //Need to store in a register to be used later + dprio_temp_m_n_c_readdata_2_d = dprio_readdata; + dprio_next_state = SIX; + end + else dprio_next_state = DPRIO_IDLE; + end + SIX: + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = SEVEN; + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_1_q; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_BYPASS_EN_ADDR; + avmm_dprio_writedata[5] = usr_n_cnt_bypass_en; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_BYPASS_EN_ADDR; + avmm_dprio_writedata[4] = usr_m_cnt_bypass_en; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_bypass + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + avmm_dprio_writedata[i-14] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + avmm_dprio_writedata[i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + avmm_dprio_writedata[3-i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + avmm_dprio_writedata[17-i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_write = 0; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_write = 0; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_write = 0; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_write = 0; + end + else dprio_next_state = DPRIO_IDLE; + end + SEVEN: + begin + dprio_write_done = 0; + dprio_next_state = EIGHT; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_2_q; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[5] = usr_n_cnt_odd_duty_div_en; + n_cnt_done_d = 1'b1; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[4] = usr_m_cnt_odd_duty_div_en; + m_cnt_done_d = 1'b1; + end + + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_odd_div + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[i-14] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + //have to OR the signals to prevent + //overwriting of previous dones + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[3-i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + //have to OR the signals to prevent + //overwriting of previous dones + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[17-i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + avmm_dprio_writedata[DSM_K_READY_BIT_INDEX] = 1'b0; + dsm_k_ready_false_done_d = 1'b1; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_address = BWCTRL_ADDR; + avmm_dprio_writedata[3:0] = usr_bwctrl_value; + bwctrl_done_d = 1'b1; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_address = CP_CURRENT_ADDR; + avmm_dprio_writedata[2:0] = usr_cp_current_value; + cp_current_done_d = 1'b1; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_address = VCO_ADDR; + avmm_dprio_writedata[8] = usr_vco_value; + vco_done_d = 1'b1; + end + + + //if all C_cnt that were changed are done, then assert all_c_cnt_done + if (c_cnt_done_d == c_cnt_changed) + all_c_cnt_done_d = 1'b1; + if (n_cnt_changed & n_cnt_done_d) + dprio_next_state = DPRIO_DONE; + if (any_c_cnt_changed & !all_c_cnt_done_d & !all_c_cnt_done_q) + dprio_next_state = ONE; + else if (m_cnt_changed & !m_cnt_done_d & !m_cnt_done_q) + dprio_next_state = ONE; + else if (dsm_k_changed & !dsm_k_ready_false_done_d) + dprio_next_state = TWO; + else if (dsm_k_changed & !dsm_k_done_q) + dprio_next_state = EIGHT; + else if (bwctrl_changed & !bwctrl_done_d) + dprio_next_state = TWO; + else if (cp_current_changed & !cp_current_done_d) + dprio_next_state = TWO; + else if (vco_changed & !vco_done_d) + dprio_next_state = TWO; + else + begin + dprio_next_state = DPRIO_DONE; + dprio_write_done = 1'b1; + end + end + //finish the rest of the DSM reads/writes + //writing k value, writing k_ready to 1. + EIGHT: + begin + dprio_write_done = 0; + dprio_next_state = NINE; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_FRACTIONAL_DIVISION_ADDR_0; + avmm_dprio_writedata[15:0] = usr_k_value[15:0]; + end + end + NINE: + begin + dprio_write_done = 0; + dprio_next_state = TEN; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_FRACTIONAL_DIVISION_ADDR_1; + avmm_dprio_writedata[15:0] = usr_k_value[31:16]; + end + end + TEN: + begin + dprio_write_done = 0; + dprio_next_state = ONE; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + //already have the readdata for DSM_K_READY_ADDR since we read it + //earlier. Just reuse here + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_2_q; + avmm_dprio_writedata[DSM_K_READY_BIT_INDEX] = 1'b1; + dsm_k_done_d = 1'b1; + end + end + DPRIO_DONE: + begin + dprio_write_done = 1'b1; + if (dprio_start) dprio_next_state = DPRIO_IDLE; + else dprio_next_state = DPRIO_DONE; + end + DPRIO_IDLE: + begin + if (dprio_start) dprio_next_state = ONE; + else dprio_next_state = DPRIO_IDLE; + end + default: dprio_next_state = 4'bxxxx; + endcase + end + + end + + + //assert the waitreq signal according to the state of the slave + assign slave_waitrequest = (slave_mode==mode_WR) ? ((locked === 1'b1) ? (((current_state==WAIT_ON_LOCK) & !dprio_write_done) | !dps_done |reset|!dprio_init_done) : 1'b1) : 1'b0; + + + dyn_phase_shift dyn_phase_shift_inst ( + .clk(clk), + .reset(reset), + .phase_done(phase_done), + .pll_start_valid(pll_start_valid), + .dps_changed(dps_changed), + .dps_changed_valid(dps_changed_valid), + .dprio_write_done(dprio_write_done), + .usr_num_shifts(usr_num_shifts), + .usr_cnt_sel(usr_cnt_sel), + .usr_up_dn(usr_up_dn), + .locked(locked), + .dps_done(dps_done), + .phase_en(phase_en), + .up_dn(up_dn), + .cnt_sel(cnt_sel)); + defparam dyn_phase_shift_inst.device_family = device_family; + + assign dprio_clk = clk; + self_reset self_reset_inst (mgmt_reset, clk, reset, dprio_init_reset); + + dprio_mux dprio_mux_inst ( + .init_dprio_address(init_dprio_address), + .init_dprio_read(init_dprio_read), + .init_dprio_byteen(init_dprio_byteen), + .init_dprio_write(init_dprio_write), + .init_dprio_writedata(init_dprio_writedata), + + + .init_atpgmode(init_atpgmode), + .init_mdio_dis(init_mdio_dis), + .init_scanen(init_scanen), + .init_ser_shift_load(init_ser_shift_load), + .dprio_init_done(dprio_init_done), + + // Inputs from avmm master + .avmm_dprio_address(avmm_dprio_address), + .avmm_dprio_read(avmm_dprio_read), + .avmm_dprio_byteen(avmm_dprio_byteen), + .avmm_dprio_write(avmm_dprio_write), + .avmm_dprio_writedata(avmm_dprio_writedata), + + .avmm_atpgmode(avmm_atpgmode), + .avmm_mdio_dis(avmm_mdio_dis), + .avmm_scanen(avmm_scanen), + + // Outputs to fpll + .dprio_address(dprio_address), + .dprio_read(dprio_read), + .dprio_byteen(dprio_byteen), + .dprio_write(dprio_write), + .dprio_writedata(dprio_writedata), + + .atpgmode(dprio_atpgmode), + .mdio_dis(dprio_mdio_dis), + .scanen(dprio_scanen), + .ser_shift_load(dprio_ser_shift_load) + ); + + + fpll_dprio_init fpll_dprio_init_inst ( + .clk(clk), + .reset_n(~reset), + .locked(locked), + + //outputs + .dprio_address(init_dprio_address), + .dprio_read(init_dprio_read), + .dprio_byteen(init_dprio_byteen), + .dprio_write(init_dprio_write), + .dprio_writedata(init_dprio_writedata), + + .atpgmode(init_atpgmode), + .mdio_dis(init_mdio_dis), + .scanen(init_scanen), + .ser_shift_load(init_ser_shift_load), + .dprio_init_done(dprio_init_done)); + + //address luts, to be reconfigged by the Fitter + //FPLL_1 or 0 address lut + generic_lcell_comb lcell_fpll_0_1 ( + .dataa(1'b0), + .combout (fpll_1)); + defparam lcell_fpll_0_1.lut_mask = 64'hAAAAAAAAAAAAAAAA; + defparam lcell_fpll_0_1.dont_touch = "on"; + defparam lcell_fpll_0_1.family = device_family; + + + wire dprio_read_combout; + generic_lcell_comb lcell_dprio_read ( + .dataa(fpll_1), + .datab(dprio_read), + .datac(1'b0), + .datad(1'b0), + .datae(1'b0), + .dataf(1'b0), + .combout (dprio_read_combout)); + defparam lcell_dprio_read.lut_mask = 64'hCCCCCCCCCCCCCCCC; + defparam lcell_dprio_read.dont_touch = "on"; + defparam lcell_dprio_read.family = device_family; + + + + + + //assign reconfig_to_pll signals + assign reconfig_to_pll[0] = dprio_clk; + assign reconfig_to_pll[1] = ~dprio_init_reset; + assign reconfig_to_pll[2] = dprio_write; + assign reconfig_to_pll[3] = dprio_read_combout; + assign reconfig_to_pll[9:4] = dprio_address; + assign reconfig_to_pll[25:10] = dprio_writedata; + assign reconfig_to_pll[27:26] = dprio_byteen; + assign reconfig_to_pll[28] = dprio_ser_shift_load; + assign reconfig_to_pll[29] = dprio_mdio_dis; + assign reconfig_to_pll[30] = phase_en; + assign reconfig_to_pll[31] = up_dn; + assign reconfig_to_pll[36:32] = cnt_sel; + assign reconfig_to_pll[37] = dprio_scanen; + assign reconfig_to_pll[38] = dprio_atpgmode; + //assign reconfig_to_pll[40:37] = clken; + assign reconfig_to_pll[63:39] = 0; + + //assign reconfig_from_pll signals + assign dprio_readdata = reconfig_from_pll [15:0]; + assign locked_orig = reconfig_from_pll [16]; + assign phase_done = reconfig_from_pll [17]; + +endmodule diff --git a/sys/pll_q13.qip b/sys/pll_q13.qip index 13a7ed4..78e7e40 100644 --- a/sys/pll_q13.qip +++ b/sys/pll_q13.qip @@ -1,6 +1,4 @@ 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 ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_cfg.qip ] 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 ce83683..93b6247 100644 --- a/sys/sys.tcl +++ b/sys/sys.tcl @@ -16,13 +16,6 @@ set_location_assignment PIN_V10 -to ADC_SCK set_location_assignment PIN_AC4 -to ADC_SDI set_location_assignment PIN_AD4 -to ADC_SDO -#============================================================ -# ARDUINO -#============================================================ -set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[*] -set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to ARDUINO_IO[*] -set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to ARDUINO_IO[*] - #============================================================ # I2C LEDS/BUTTONS #============================================================ diff --git a/sys/sys_top.sdc b/sys/sys_top.sdc index 0d8763f..c2b4118 100644 --- a/sys/sys_top.sdc +++ b/sys/sys_top.sdc @@ -25,6 +25,7 @@ set_false_path -from [get_ports {KEY*}] set_false_path -from [get_ports {BTN_*}] set_false_path -to [get_ports {LED_*}] set_false_path -to [get_ports {VGA_*}] +set_false_path -from [get_ports {VGA_EN}] set_false_path -to [get_ports {AUDIO_SPDIF}] set_false_path -to [get_ports {AUDIO_L}] set_false_path -to [get_ports {AUDIO_R}] @@ -34,6 +35,7 @@ set_false_path -from {cfg[*]} set_false_path -from {VSET[*]} set_false_path -to {wcalc[*] hcalc[*]} set_false_path -to {hdmi_width[*] hdmi_height[*]} +set_false_path -to {deb_* btn_en btn_up} set_multicycle_path -to {*_osd|osd_vcnt*} -setup 2 set_multicycle_path -to {*_osd|osd_vcnt*} -hold 1 @@ -58,6 +60,7 @@ set_false_path -from {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} set_false_path -from {aflt_* acx* acy* areset* arc*} set_false_path -from {arx* ary*} set_false_path -from {vs_line*} +set_false_path -from {ColorBurst_Range* PhaseInc* pal_en cvbs yc_en} set_false_path -from {ascal|o_ihsize*} set_false_path -from {ascal|o_ivsize*} @@ -70,4 +73,5 @@ set_false_path -from {ascal|o_htotal* ascal|o_vtotal*} set_false_path -from {ascal|o_hsstart* ascal|o_vsstart* ascal|o_hsend* ascal|o_vsend*} set_false_path -from {ascal|o_hsize* ascal|o_vsize*} -set_false_path -from {mcp23009|sd_cd} +set_false_path -from {mcp23009|flg_*} +set_false_path -to {sysmem|fpga_interfaces|clocks_resets|f2h*} diff --git a/sys/sys_top.v b/sys/sys_top.v index 55619db..f73bc10 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -72,7 +72,7 @@ module sys_top output [5:0] VGA_R, output [5:0] VGA_G, output [5:0] VGA_B, - inout VGA_HS, // VGA_HS is secondary SD card detect when VGA_EN = 1 (inactive) + inout VGA_HS, output VGA_VS, input VGA_EN, // active low @@ -125,27 +125,23 @@ module sys_top ); ////////////////////// Secondary SD /////////////////////////////////// -wire SD_CS, SD_CLK, SD_MOSI; +wire SD_CS, SD_CLK, SD_MOSI, SD_MISO, SD_CD; `ifndef MISTER_DUAL_SDRAM - wire sd_miso = SW[3] | SDIO_DAT[0]; + 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 | sd_cd) ? {vga_g,vga_r,vga_b} : {SD_CLK,SD_MOSI,SD_CS,3'bZZZ}; `else - wire sd_miso = 1; + assign SD_CD = mcp_sdcd; + assign SD_MISO = mcp_sdcd | SD_SPI_MISO; + assign SD_SPI_CS = mcp_sdcd ? 1'bZ : SD_CS; + assign SD_SPI_CLK = mcp_sdcd ? 1'bZ : SD_CLK; + assign SD_SPI_MOSI = mcp_sdcd ? 1'bZ : SD_MOSI; `endif -wire SD_MISO = mcp_sdcd ? sd_miso : SD_SPI_MISO; - -`ifndef MISTER_DUAL_SDRAM - assign SDIO_DAT[2:1]= 2'bZZ; - assign SDIO_DAT[3] = SW[3] ? 1'bZ : SD_CS; - assign SDIO_CLK = SW[3] ? 1'bZ : SD_CLK; - assign SDIO_CMD = SW[3] ? 1'bZ : SD_MOSI; - assign SD_SPI_CS = mcp_sdcd ? ((~VGA_EN & sog & ~cs1) ? 1'b1 : 1'bZ) : SD_CS; -`else - assign SD_SPI_CS = mcp_sdcd ? 1'bZ : SD_CS; -`endif - -assign SD_SPI_CLK = mcp_sdcd ? 1'bZ : SD_CLK; -assign SD_SPI_MOSI = mcp_sdcd ? 1'bZ : SD_MOSI; ////////////////////// LEDs/Buttons /////////////////////////////////// @@ -157,36 +153,59 @@ wire led_d = led_disk[1] ? ~led_disk[0] : ~(led_disk[0] | gp_out[29]); wire led_u = ~led_user; wire led_locked; -`ifndef MISTER_DUAL_SDRAM - assign LED_POWER = (SW[3] | led_p) ? 1'bZ : 1'b0; - assign LED_HDD = (SW[3] | led_d) ? 1'bZ : 1'b0; - assign LED_USER = (SW[3] | led_u) ? 1'bZ : 1'b0; -`endif - -//LEDs on main board +//LEDs on de10-nano board assign LED = (led_overtake & led_state) | (~led_overtake & {1'b0,led_locked,1'b0, ~led_p, 1'b0, ~led_d, 1'b0, ~led_u}); -wire btn_r, btn_o, btn_u; -`ifdef MISTER_DUAL_SDRAM - assign {btn_r,btn_o,btn_u} = SW[3] ? {mcp_btn[1],mcp_btn[2],mcp_btn[0]} : ~{SDRAM2_DQ[9],SDRAM2_DQ[13],SDRAM2_DQ[11]}; -`else - assign {btn_r,btn_o,btn_u} = ~{BTN_RESET,BTN_OSD,BTN_USER} | {mcp_btn[1],mcp_btn[2],mcp_btn[0]}; -`endif - wire [2:0] mcp_btn; wire mcp_sdcd; +wire mcp_en; +wire mcp_mode; mcp23009 mcp23009 ( .clk(FPGA_CLK2_50), .btn(mcp_btn), .led({led_p, led_d, led_u}), - .sd_cd(mcp_sdcd), + .flg_sd_cd(mcp_sdcd), + .flg_present(mcp_en), + .flg_mode(mcp_mode), .scl(IO_SCL), .sda(IO_SDA) ); +wire io_dig = mcp_en ? mcp_mode : SW[3]; + +`ifndef MISTER_DUAL_SDRAM + wire av_dis = io_dig | VGA_EN; + assign LED_POWER = av_dis ? 1'bZ : mcp_en ? de1 : led_p ? 1'bZ : 1'b0; + assign LED_HDD = av_dis ? 1'bZ : mcp_en ? (sog & ~cs1) : led_d ? 1'bZ : 1'b0; + //assign LED_USER = av_dis ? 1'bZ : mcp_en ? ~vga_tx_clk : led_u ? 1'bZ : 1'b0; + assign LED_USER = VGA_TX_CLK; + wire BTN_DIS = VGA_EN; +`else + 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; +reg [25:0] btn_timeout = 0; +initial btn_timeout = 0; +always @(posedge FPGA_CLK2_50) begin + reg btn_up = 0; + reg btn_en = 0; + + btn_up <= BTN_RESET & BTN_OSD & BTN_USER; + if(~reset & btn_up & ~&btn_timeout) btn_timeout <= btn_timeout + 1'd1; + btn_en <= ~BTN_DIS; + BTN_EN <= &btn_timeout & btn_en; +end + +wire btn_r = (mcp_en | SW[3]) ? mcp_btn[1] : (BTN_EN & ~BTN_RESET); +wire btn_o = (mcp_en | SW[3]) ? mcp_btn[2] : (BTN_EN & ~BTN_OSD ); +wire btn_u = (mcp_en | SW[3]) ? mcp_btn[0] : (BTN_EN & ~BTN_USER ); reg btn_user, btn_osd; always @(posedge FPGA_CLK2_50) begin @@ -212,7 +231,7 @@ end // gp_in[31] = 0 - quick flag that FPGA is initialized (HPS reads 1 when FPGA is not in user mode) // used to avoid lockups while JTAG loading -wire [31:0] gp_in = {1'b0, btn_user | btn[1], btn_osd | btn[0], SW[3], 8'd0, io_ver, io_ack, io_wide, io_dout | io_dout_sys}; +wire [31:0] gp_in = {1'b0, btn_user | btn[1], btn_osd | btn[0], io_dig, 8'd0, io_ver, io_ack, io_wide, io_dout | io_dout_sys}; wire [31:0] gp_out; wire [1:0] io_ver = 1; // 0 - obsolete. 1 - optimized HPS I/O. 2,3 - reserved for future. @@ -226,7 +245,7 @@ wire io_ss1 = gp_outr[19]; wire io_ss2 = gp_outr[20]; `ifndef MISTER_DEBUG_NOHDMI -wire io_osd_hdmi = io_ss1 & ~io_ss0; + wire io_osd_hdmi = io_ss1 & ~io_ss0; `endif wire io_fpga = ~io_ss1 & io_ss0; @@ -267,23 +286,28 @@ cyclonev_hps_interface_mpu_general_purpose h2f_gp reg [15:0] cfg; - reg cfg_set = 0; -wire vga_fb = cfg[12] | vga_force_scaler; `ifdef MISTER_DEBUG_NOHDMI -wire direct_video = 1; + wire vga_fb = 0; + wire direct_video = 1; `else -wire direct_video = cfg[10]; + wire vga_fb = cfg[12] | vga_force_scaler; + wire direct_video = cfg[10]; `endif 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 vga_scaler = cfg[2] | vga_force_scaler; + wire forced_scandoubler = cfg[4]; + wire ypbpr_en = cfg[5]; + wire sog = cfg[9]; + `ifdef MISTER_DEBUG_NOHDMI + wire vga_scaler = 0; + `else + wire vga_scaler = cfg[2] | vga_force_scaler; + `endif `endif reg cfg_custom_t = 0; @@ -309,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; @@ -476,18 +501,20 @@ 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]; + 6: subcarrier <= io_din[0]; endcase end -`endif end end @@ -519,17 +546,6 @@ cyclonev_hps_interface_peripheral_uart uart .txd(uart_txd) ); -wire aspi_sck,aspi_mosi,aspi_ss,aspi_miso; -cyclonev_hps_interface_peripheral_spi_master spi -( - .sclk_out(aspi_sck), - .txd(aspi_mosi), // mosi - .rxd(aspi_miso), // miso - - .ss_0_n(aspi_ss), - .ss_in_n(1) -); - wire [63:0] f2h_irq = {video_sync,HDMI_TX_VS}; cyclonev_hps_interface_interrupts interrupts ( @@ -635,11 +651,13 @@ ddr_svc ddr_svc .ram_write(ram2_write), .ram_bcnt(ram2_bcnt), +`ifndef MISTER_DISABLE_ALSA .ch0_addr(alsa_address), .ch0_burst(1), .ch0_data(alsa_readdata), .ch0_req(alsa_req), .ch0_ready(alsa_ready), +`endif .ch1_addr(pal_addr), .ch1_burst(128), @@ -664,122 +682,125 @@ 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; + wire clk_hdmi = hdmi_clk_out; -ascal -#( - .RAMBASE(32'h20000000), -`ifdef MISTER_SMALL_VBUF - .RAMSIZE(32'h00200000), -`else - .RAMSIZE(32'h00800000), -`endif -`ifndef MISTER_FB - .PALETTE2("false"), -`else - `ifndef MISTER_FB_PALETTE + ascal + #( + .RAMBASE(32'h20000000), + `ifdef MISTER_SMALL_VBUF + .RAMSIZE(32'h00200000), + `else + .RAMSIZE(32'h00800000), + `endif + `ifndef MISTER_FB .PALETTE2("false"), + `else + `ifndef MISTER_FB_PALETTE + .PALETTE2("false"), + `endif `endif -`endif -`ifdef MISTER_DISABLE_ADAPTIVE - .ADAPTIVE("false"), -`endif -`ifdef MISTER_DOWNSCALE_NN - .DOWNSCALE_NN("true"), -`endif - .FRAC(8), - .N_DW(128), - .N_AW(28) -) -ascal -( - .reset_na (~reset_req), - .run (1), - .freeze (freeze), - - .i_clk (clk_ihdmi), - .i_ce (ce_hpix), - .i_r (hr_out), - .i_g (hg_out), - .i_b (hb_out), - .i_hs (hhs_fix), - .i_vs (hvs_fix), - .i_fl (f1), - .i_de (hde_emu), - .iauto (1), - .himin (0), - .himax (0), - .vimin (0), - .vimax (0), - - .o_clk (clk_hdmi), - .o_ce (scaler_out), - .o_r (hdmi_data[23:16]), - .o_g (hdmi_data[15:8]), - .o_b (hdmi_data[7:0]), - .o_hs (hdmi_hs), - .o_vs (hdmi_vs), - .o_de (hdmi_de), - .o_vbl (hdmi_vbl), - .o_brd (hdmi_brd), - .o_lltune (lltune), - .htotal (WIDTH + HFP + HBP + HS[11:0]), - .hsstart (WIDTH + HFP), - .hsend (WIDTH + HFP + HS[11:0]), - .hdisp (WIDTH), - .hmin (hmin), - .hmax (hmax), - .vtotal (HEIGHT + VFP + VBP + VS[11:0]), - .vsstart (HEIGHT + VFP), - .vsend (HEIGHT + VFP + VS[11:0]), - .vdisp (HEIGHT), - .vmin (vmin), - .vmax (vmax), - .vrr (vrr_mode), - .vrrmax (HEIGHT + VBP + VS[11:0] + 12'd1), - - .mode ({~lowlat,LFB_EN ? LFB_FLT : |scaler_flt,2'b00}), - .poly_clk (clk_sys), - .poly_a (coef_addr), - .poly_dw (coef_data), - .poly_wr (coef_wr), - - .pal1_clk (clk_pal), - .pal1_dw (pal_d), - .pal1_a (pal_a), - .pal1_wr (pal_wr), - -`ifdef MISTER_FB - `ifdef MISTER_FB_PALETTE - .pal2_clk (fb_pal_clk), - .pal2_dw (fb_pal_d), - .pal2_dr (fb_pal_q), - .pal2_a (fb_pal_a), - .pal2_wr (fb_pal_wr), - .pal_n (fb_en), + `ifdef MISTER_DISABLE_ADAPTIVE + .ADAPTIVE("false"), `endif -`endif + `ifdef MISTER_DOWNSCALE_NN + .DOWNSCALE_NN("true"), + `endif + .FRAC(8), + .N_DW(128), + .N_AW(28) + ) + ascal + ( + .reset_na (~reset_req), + .run (1), + .freeze (freeze), + .bob_deint (bob_deint), - .o_fb_ena (FB_EN), - .o_fb_hsize (FB_WIDTH), - .o_fb_vsize (FB_HEIGHT), - .o_fb_format (FB_FMT), - .o_fb_base (FB_BASE), - .o_fb_stride (FB_STRIDE), + .i_clk (clk_ihdmi), + .i_ce (ce_hpix), + .i_r (hr_out), + .i_g (hg_out), + .i_b (hb_out), + .i_hs (hhs_fix), + .i_vs (hvs_fix), + .i_fl (f1), + .i_de (hde_emu), + .iauto (1), + .himin (0), + .himax (0), + .vimin (0), + .vimax (0), - .avl_clk (clk_100m), - .avl_waitrequest (vbuf_waitrequest), - .avl_readdata (vbuf_readdata), - .avl_readdatavalid(vbuf_readdatavalid), - .avl_burstcount (vbuf_burstcount), - .avl_writedata (vbuf_writedata), - .avl_address (vbuf_address), - .avl_write (vbuf_write), - .avl_read (vbuf_read), - .avl_byteenable (vbuf_byteenable) -); + .o_clk (clk_hdmi), + .o_ce (scaler_out), + .o_r (hdmi_data[23:16]), + .o_g (hdmi_data[15:8]), + .o_b (hdmi_data[7:0]), + .o_hs (hdmi_hs), + .o_vs (hdmi_vs), + .o_de (hdmi_de), + .o_vbl (hdmi_vbl), + .o_brd (hdmi_brd), + .o_lltune (lltune), + .htotal (WIDTH + HFP + HBP + HS[11:0]), + .hsstart (WIDTH + HFP), + .hsend (WIDTH + HFP + HS[11:0]), + .hdisp (WIDTH), + .hmin (hmin), + .hmax (hmax), + .vtotal (HEIGHT + VFP + VBP + VS[11:0]), + .vsstart (HEIGHT + VFP), + .vsend (HEIGHT + VFP + VS[11:0]), + .vdisp (HEIGHT), + .vmin (vmin), + .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), + .poly_a (coef_addr), + .poly_dw (coef_data), + .poly_wr (coef_wr), + + .pal1_clk (clk_pal), + .pal1_dw (pal_d), + .pal1_a (pal_a), + .pal1_wr (pal_wr), + + `ifdef MISTER_FB + `ifdef MISTER_FB_PALETTE + .pal2_clk (fb_pal_clk), + .pal2_dw (fb_pal_d), + .pal2_dr (fb_pal_q), + .pal2_a (fb_pal_a), + .pal2_wr (fb_pal_wr), + .pal_n (fb_en), + `endif + `endif + + .o_fb_ena (FB_EN), + .o_fb_hsize (FB_WIDTH), + .o_fb_vsize (FB_HEIGHT), + .o_fb_format (FB_FMT), + .o_fb_base (FB_BASE), + .o_fb_stride (FB_STRIDE), + + .avl_clk (clk_100m), + .avl_waitrequest (vbuf_waitrequest), + .avl_readdata (vbuf_readdata), + .avl_readdatavalid(vbuf_readdatavalid), + .avl_burstcount (vbuf_burstcount), + .avl_writedata (vbuf_writedata), + .avl_address (vbuf_address), + .avl_write (vbuf_write), + .avl_read (vbuf_read), + .avl_byteenable (vbuf_byteenable) + ); `endif reg LFB_EN = 0; @@ -820,8 +841,8 @@ always @(posedge clk_sys) begin end `ifdef MISTER_FB -reg fb_vbl; -always @(posedge clk_vid) fb_vbl <= hdmi_vbl; + reg fb_vbl; + always @(posedge clk_vid) fb_vbl <= hdmi_vbl; `endif reg ar_md_start; @@ -947,24 +968,24 @@ always @(posedge clk_vid) begin end `ifndef MISTER_DEBUG_NOHDMI -wire [15:0] lltune; -pll_hdmi_adj pll_hdmi_adj -( - .clk(FPGA_CLK1_50), - .reset_na(~reset_req), + wire [15:0] lltune; + pll_hdmi_adj pll_hdmi_adj + ( + .clk(FPGA_CLK1_50), + .reset_na(~reset_req), - .llena(lowlat), - .lltune({16{cfg_done}} & lltune), - .locked(led_locked), - .i_waitrequest(adj_waitrequest), - .i_write(adj_write), - .i_address(adj_address), - .i_writedata(adj_data), - .o_waitrequest(cfg_waitrequest), - .o_write(cfg_write), - .o_address(cfg_address), - .o_writedata(cfg_data) -); + .llena(lowlat), + .lltune({16{cfg_done}} & lltune), + .locked(led_locked), + .i_waitrequest(adj_waitrequest), + .i_write(adj_write), + .i_address(adj_address), + .i_writedata(adj_data), + .o_waitrequest(cfg_waitrequest), + .o_write(cfg_write), + .o_address(cfg_address), + .o_writedata(cfg_data) + ); `else assign led_locked = 0; `endif @@ -990,15 +1011,15 @@ end ///////////////////////// HDMI output ///////////////////////////////// `ifndef MISTER_DEBUG_NOHDMI -wire hdmi_clk_out; -pll_hdmi pll_hdmi -( - .refclk(FPGA_CLK1_50), - .rst(reset_req), - .reconfig_to_pll(reconfig_to_pll), - .reconfig_from_pll(reconfig_from_pll), - .outclk_0(hdmi_clk_out) -); + wire hdmi_clk_out; + pll_hdmi pll_hdmi + ( + .refclk(FPGA_CLK1_50), + .rst(reset_req), + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll), + .outclk_0(hdmi_clk_out) + ); `endif //1920x1080@60 PCLK=148.5MHz CEA @@ -1023,64 +1044,59 @@ reg [5:0] adj_address; reg [31:0] adj_data; `ifndef MISTER_DEBUG_NOHDMI -pll_cfg pll_cfg -( - .mgmt_clk(FPGA_CLK1_50), - .mgmt_reset(reset_req), - .mgmt_waitrequest(cfg_waitrequest), - .mgmt_read(0), - .mgmt_readdata(), - .mgmt_write(cfg_write), - .mgmt_address(cfg_address), - .mgmt_writedata(cfg_data), - .reconfig_to_pll(reconfig_to_pll), - .reconfig_from_pll(reconfig_from_pll) -); + pll_cfg_hdmi pll_cfg_hdmi + ( + .mgmt_clk(FPGA_CLK1_50), + .mgmt_reset(reset_req), + .mgmt_waitrequest(cfg_waitrequest), + .mgmt_write(cfg_write), + .mgmt_address(cfg_address), + .mgmt_writedata(cfg_data), + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll) + ); -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; - reg old_wait = 0; - - gotd <= cfg_got; - gotd2 <= gotd; - - adj_write <= 0; - - custd <= cfg_custom_t; - custd2 <= custd; - if(custd2 != custd & ~gotd) begin - adj_address <= cfg_custom_p1; - adj_data <= cfg_custom_p2; - adj_write <= 1; + 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 - if(~gotd2 & gotd) begin - adj_address <= 2; - adj_data <= 0; - adj_write <= 1; + reg cfg_ready = 0; + always @(posedge FPGA_CLK1_50) begin + reg gotd = 0, gotd2 = 0; + reg custd = 0, custd2 = 0; + reg old_wait = 0; + + gotd <= cfg_got; + gotd2 <= gotd; + + adj_write <= 0; + + custd <= cfg_custom_t; + custd2 <= custd; + if(custd2 != custd & ~gotd) begin + adj_address <= cfg_custom_p1; + adj_data <= cfg_custom_p2; + adj_write <= 1; + end + + if(~gotd2 & gotd) begin + adj_address <= 2; + adj_data <= 0; + adj_write <= 1; + end + + old_wait <= adj_waitrequest; + if(old_wait & ~adj_waitrequest & gotd) cfg_ready <= 1; end - - old_wait <= adj_waitrequest; - if(old_wait & ~adj_waitrequest & gotd) cfg_ready <= 1; -end - `else - -wire cfg_ready = 1; - + wire cfg_ready = 1; `endif assign HDMI_I2C_SCL = hdmi_scl_en ? 1'b0 : 1'bZ; @@ -1096,72 +1112,71 @@ cyclonev_hps_interface_peripheral_i2c hdmi_i2c ); `ifndef MISTER_DEBUG_NOHDMI + `ifdef MISTER_FB + reg dis_output; + always @(posedge clk_hdmi) begin + reg dis; + dis <= fb_force_blank & ~LFB_EN; + dis_output <= dis; + end + `else + wire dis_output = 0; + `endif -`ifdef MISTER_FB -reg dis_output; -always @(posedge clk_hdmi) begin - reg dis; - dis <= fb_force_blank & ~LFB_EN; - dis_output <= dis; -end -`else -wire dis_output = 0; + wire [23:0] hdmi_data_mask; + wire hdmi_de_mask, hdmi_vs_mask, hdmi_hs_mask; + + reg [15:0] shadowmask_data; + reg shadowmask_wr = 0; + + shadowmask HDMI_shadowmask + ( + .clk(clk_hdmi), + .clk_sys(clk_sys), + + .cmd_wr(shadowmask_wr), + .cmd_in(shadowmask_data), + + .din(dis_output ? 24'd0 : hdmi_data), + .hs_in(hdmi_hs), + .vs_in(hdmi_vs), + .de_in(hdmi_de), + .brd_in(hdmi_brd), + .enable(~LFB_EN), + + .dout(hdmi_data_mask), + .hs_out(hdmi_hs_mask), + .vs_out(hdmi_vs_mask), + .de_out(hdmi_de_mask) + ); + + wire [23:0] hdmi_data_osd; + wire hdmi_de_osd, hdmi_vs_osd, hdmi_hs_osd; + + osd hdmi_osd + ( + .clk_sys(clk_sys), + + .io_osd(io_osd_hdmi), + .io_strobe(io_strobe), + .io_din(io_din), + + .clk_video(clk_hdmi), + .din(hdmi_data_mask), + .hs_in(hdmi_hs_mask), + .vs_in(hdmi_vs_mask), + .de_in(hdmi_de_mask), + + .dout(hdmi_data_osd), + .hs_out(hdmi_hs_osd), + .vs_out(hdmi_vs_osd), + .de_out(hdmi_de_osd) + ); + + wire hdmi_cs_osd; + csync csync_hdmi(clk_hdmi, hdmi_hs_osd, hdmi_vs_osd, hdmi_cs_osd); `endif -wire [23:0] hdmi_data_mask; -wire hdmi_de_mask, hdmi_vs_mask, hdmi_hs_mask; - -reg [15:0] shadowmask_data; -reg shadowmask_wr = 0; - -shadowmask HDMI_shadowmask -( - .clk(clk_hdmi), - .clk_sys(clk_sys), - - .cmd_wr(shadowmask_wr), - .cmd_in(shadowmask_data), - - .din(dis_output ? 24'd0 : hdmi_data), - .hs_in(hdmi_hs), - .vs_in(hdmi_vs), - .de_in(hdmi_de), - .brd_in(hdmi_brd), - .enable(~LFB_EN), - - .dout(hdmi_data_mask), - .hs_out(hdmi_hs_mask), - .vs_out(hdmi_vs_mask), - .de_out(hdmi_de_mask) -); - -wire [23:0] hdmi_data_osd; -wire hdmi_de_osd, hdmi_vs_osd, hdmi_hs_osd; - -osd hdmi_osd -( - .clk_sys(clk_sys), - - .io_osd(io_osd_hdmi), - .io_strobe(io_strobe), - .io_din(io_din), - - .clk_video(clk_hdmi), - .din(hdmi_data_mask), - .hs_in(hdmi_hs_mask), - .vs_in(hdmi_vs_mask), - .de_in(hdmi_de_mask), - - .dout(hdmi_data_osd), - .hs_out(hdmi_hs_osd), - .vs_out(hdmi_vs_osd), - .de_out(hdmi_de_osd) -); -`endif - -wire hdmi_cs_osd; -csync csync_hdmi(clk_hdmi, hdmi_hs_osd, hdmi_vs_osd, hdmi_cs_osd); - reg [23:0] dv_data; reg dv_hs, dv_vs, dv_de; wire [23:0] dv_data_osd; @@ -1194,11 +1209,12 @@ always @(posedge clk_vid) begin end dv_de1 <= !{hss,dv_hs_osd} && vde; - dv_hs1 <= csync_en ? dv_cs_osd : dv_hs_osd; - dv_vs1 <= dv_vs_osd; end dv_d1 <= dv_data_osd; + dv_hs1 <= csync_en ? dv_cs_osd : dv_hs_osd; + dv_vs1 <= dv_vs_osd; + dv_d2 <= dv_d1; dv_de2 <= dv_de1; dv_hs2 <= dv_hs1; @@ -1211,21 +1227,21 @@ always @(posedge clk_vid) begin end `ifndef MISTER_DISABLE_YC -assign {dv_data_osd, dv_hs_osd, dv_vs_osd, dv_cs_osd } = ~yc_en ? {vga_data_osd, vga_hs_osd, vga_vs_osd, vga_cs_osd } : {yc_o, yc_hs, yc_vs, yc_cs }; + assign {dv_data_osd, dv_hs_osd, dv_vs_osd, dv_cs_osd } = ~yc_en ? {vga_data_osd, vga_hs_osd, vga_vs_osd, vga_cs_osd } : {yc_o, yc_hs, yc_vs, yc_cs }; `else -assign {dv_data_osd, dv_hs_osd, dv_vs_osd, dv_cs_osd } = {vga_data_osd, vga_hs_osd, vga_vs_osd, vga_cs_osd }; + assign {dv_data_osd, dv_hs_osd, dv_vs_osd, dv_cs_osd } = {vga_data_osd, vga_hs_osd, vga_vs_osd, vga_cs_osd }; `endif wire hdmi_tx_clk; `ifndef MISTER_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) -); + 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; + assign hdmi_tx_clk = clk_vid; `endif altddio_out @@ -1270,10 +1286,17 @@ always @(posedge hdmi_tx_clk) begin hdmi_dv_vs <= dv_vs; hdmi_dv_de <= dv_de; +`ifndef MISTER_DEBUG_NOHDMI hs <= (~vga_fb & direct_video) ? hdmi_dv_hs : (direct_video & csync_en) ? hdmi_cs_osd : hdmi_hs_osd; vs <= (~vga_fb & direct_video) ? hdmi_dv_vs : hdmi_vs_osd; de <= (~vga_fb & direct_video) ? hdmi_dv_de : hdmi_de_osd; d <= (~vga_fb & direct_video) ? hdmi_dv_data : hdmi_data_osd; +`else + hs <= hdmi_dv_hs; + vs <= hdmi_dv_vs; + de <= hdmi_dv_de; + d <= hdmi_dv_data; +`endif hdmi_out_hs <= hs; hdmi_out_vs <= vs; @@ -1288,6 +1311,46 @@ assign HDMI_TX_D = hdmi_out_d; ///////////////////////// VGA output ////////////////////////////////// +`ifndef MISTER_DUAL_SDRAM + wire vga_tx_clk; + `ifndef MISTER_DEBUG_NOHDMI + cyclonev_clkselect vga_clk_sw + ( + .clkselect({1'b1, ~vga_fb & ~vga_scaler}), + .inclk({clk_vid, hdmi_clk_out, 2'b00}), + .outclk(vga_tx_clk) + ); + `else + assign vga_tx_clk = clk_vid; + `endif + + wire VGA_TX_CLK; + altddio_out + #( + .extend_oe_disable("OFF"), + .intended_device_family("Cyclone V"), + .invert_output("OFF"), + .lpm_hint("UNUSED"), + .lpm_type("altddio_out"), + .oe_reg("UNREGISTERED"), + .power_up_high("OFF"), + .width(1) + ) + vgaclk_ddr + ( + .datain_h(1'b0), + .datain_l(1'b1), + .outclock(vga_tx_clk), + .dataout(VGA_TX_CLK), + .aclr(~mcp_en & ~av_dis), + .aset(1'b0), + .oe(~av_dis & (mcp_en | ~led_u)), + .outclocken(1'b1), + .sclr(1'b0), + .sset(1'b0) + ); +`endif + wire [23:0] vga_data_sl; wire vga_de_sl, vga_ce_sl, vga_vs_sl, vga_hs_sl; scanlines #(0) VGA_scanlines @@ -1309,7 +1372,7 @@ scanlines #(0) VGA_scanlines ); wire [23:0] vga_data_osd; -wire vga_vs_osd, vga_hs_osd; +wire vga_vs_osd, vga_hs_osd, vga_de_osd; osd vga_osd ( .clk_sys(clk_sys), @@ -1327,32 +1390,79 @@ osd vga_osd .dout(vga_data_osd), .hs_out(vga_hs_osd), - .vs_out(vga_vs_osd) + .vs_out(vga_vs_osd), + .de_out(vga_de_osd) ); wire vga_cs_osd; csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); `ifndef MISTER_DUAL_SDRAM + `ifndef MISTER_DISABLE_YC + reg pal_en; + reg yc_en; + reg cvbs; + reg [16:0] ColorBurst_Range; + wire [23:0] yc_o; + wire yc_hs, yc_vs, yc_cs, yc_de; + + yc_out yc_out + ( + .clk(clk_vid), + .PAL_EN(pal_en), + .CVBS(cvbs), + .PHASE_INC(PhaseInc), + .COLORBURST_RANGE(ColorBurst_Range), + .hsync(vga_hs_osd), + .vsync(vga_vs_osd), + .csync(vga_cs_osd), + .de(vga_de_osd), + .dout(yc_o), + .din(vga_data_osd), + .hsync_o(yc_hs), + .vsync_o(yc_vs), + .csync_o(yc_cs), + .de_o(yc_de) + ); + `endif + + // Subcarrier generation for external encoders (independent of YC module) + reg subcarrier; + reg [39:0] PhaseInc; + + 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; - vga_out vga_scaler_out - ( - .clk(clk_hdmi), - .ypbpr_en(ypbpr_en), - .hsync(hdmi_hs_osd), - .vsync(hdmi_vs_osd), - .csync(hdmi_cs_osd), - .dout(vgas_o), - .din({24{hdmi_de_osd}} & hdmi_data_osd), - .hsync_o(vgas_hs), - .vsync_o(vgas_vs), - .csync_o(vgas_cs) - ); + wire vgas_hs, vgas_vs, vgas_cs, vgas_de; + `ifndef MISTER_DEBUG_NOHDMI + vga_out vga_scaler_out + ( + .clk(clk_hdmi), + .ypbpr_en(ypbpr_en), + .hsync(hdmi_hs_osd), + .vsync(hdmi_vs_osd), + .csync(hdmi_cs_osd), + .de(hdmi_de_osd), + .dout(vgas_o), + .din({24{hdmi_de_osd}} & hdmi_data_osd), + .hsync_o(vgas_hs), + .vsync_o(vgas_vs), + .csync_o(vgas_cs), + .de_o(vgas_de) + ); + `else + assign {vgas_o, vgas_hs, vgas_vs, vgas_cs, vgas_de} = 0; + `endif wire [23:0] vga_o, vga_o_t; - wire vga_hs, vga_vs, vga_cs, vga_hs_t, vga_vs_t, vga_cs_t; + wire vga_hs, vga_vs, vga_cs, vga_de, vga_hs_t, vga_vs_t, vga_cs_t, vga_de_t; vga_out vga_out ( .clk(clk_vid), @@ -1360,51 +1470,35 @@ csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); .hsync(vga_hs_osd), .vsync(vga_vs_osd), .csync(vga_cs_osd), + .de(vga_de_osd), .dout(vga_o_t), .din(vga_data_osd), .hsync_o(vga_hs_t), .vsync_o(vga_vs_t), - .csync_o(vga_cs_t) + .csync_o(vga_cs_t), + .de_o(vga_de_t) ); -`ifndef MISTER_DISABLE_YC - reg pal_en; - 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; + `ifndef MISTER_DISABLE_YC + assign {vga_o, vga_hs, vga_vs, vga_cs, vga_de } = ~yc_en ? {vga_o_t, vga_hs_t, vga_vs_t, vga_cs_t, vga_de_t } : {yc_o, yc_hs, yc_vs, yc_cs, yc_de }; + `else + assign {vga_o, vga_hs, vga_vs, vga_cs, vga_de } = {vga_o_t, vga_hs_t, vga_vs_t, vga_cs_t, vga_de_t } ; + `endif - yc_out yc_out - ( - .clk(clk_vid), - .PAL_EN(pal_en), - .CVBS(cvbs), - .PHASE_INC(PhaseInc), - .COLORBURST_RANGE(ColorBurst_Range), - .hsync(vga_hs_osd), - .vsync(vga_vs_osd), - .csync(vga_cs_osd), - .dout(yc_o), - .din(vga_data_osd), - .hsync_o(yc_hs), - .vsync_o(yc_vs), - .csync_o(yc_cs) - ); - - assign {vga_o, vga_hs, vga_vs, vga_cs } = ~yc_en ? {vga_o_t, vga_hs_t, vga_vs_t, vga_cs_t } : {yc_o, yc_hs, yc_vs, yc_cs }; -`else - assign {vga_o, vga_hs, vga_vs, vga_cs } = {vga_o_t, vga_hs_t, vga_vs_t, vga_cs_t } ; -`endif + wire vgas_en = vga_fb | vga_scaler; - wire cs1 = (vga_fb | vga_scaler) ? vgas_cs : vga_cs; + wire cs1 = vgas_en ? vgas_cs : vga_cs; + wire de1 = vgas_en ? vgas_de : vga_de; - assign VGA_VS = (VGA_EN | SW[3]) ? 1'bZ : (((vga_fb | vga_scaler) ? (~vgas_vs ^ VS[12]) : VGA_DISABLE ? 1'd1 : ~vga_vs) | csync_en); - assign VGA_HS = (VGA_EN | SW[3]) ? 1'bZ : ((vga_fb | vga_scaler) ? ((csync_en ? ~vgas_cs : ~vgas_hs) ^ HS[12]) : VGA_DISABLE ? 1'd1 : (csync_en ? ~vga_cs : ~vga_hs)); - assign VGA_R = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[23:18] : VGA_DISABLE ? 6'd0 : vga_o[23:18]; - assign VGA_G = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[15:10] : VGA_DISABLE ? 6'd0 : vga_o[15:10]; - assign VGA_B = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[7:2] : VGA_DISABLE ? 6'd0 : vga_o[7:2] ; + 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]; + assign VGA_B = av_dis ? 6'bZZZZZZ : vgas_en ? vgas_o[7:2] : VGA_DISABLE ? 6'd0 : vga_o[7:2] ; + + wire [1:0] vga_r = vgas_en ? vgas_o[17:16] : VGA_DISABLE ? 2'd0 : vga_o[17:16]; + wire [1:0] vga_g = vgas_en ? vgas_o[9:8] : VGA_DISABLE ? 2'd0 : vga_o[9:8]; + wire [1:0] vga_b = vgas_en ? vgas_o[1:0] : VGA_DISABLE ? 2'd0 : vga_o[1:0]; `endif reg video_sync = 0; @@ -1434,14 +1528,14 @@ end ///////////////////////// Audio output //////////////////////////////// -assign SDCD_SPDIF =(SW[3] & ~spdif) ? 1'b0 : 1'bZ; +assign SDCD_SPDIF = (mcp_en & ~spdif) ? 1'b0 : 1'bZ; `ifndef MISTER_DUAL_SDRAM 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 : analog_r; - assign AUDIO_L = SW[3] ? 1'bZ : SW[0] ? HDMI_SCLK : analog_l; + assign AUDIO_SPDIF = av_dis ? 1'bZ : (SW[0] | mcp_en) ? HDMI_LRCLK : spdif; + assign AUDIO_R = av_dis ? 1'bZ : (SW[0] | mcp_en) ? HDMI_I2S : analog_r; + assign AUDIO_L = av_dis ? 1'bZ : (SW[0] | mcp_en) ? HDMI_SCLK : analog_l; `endif assign HDMI_MCLK = clk_audio; @@ -1477,8 +1571,10 @@ audio_out audio_out .core_l(audio_l), .core_r(audio_r), +`ifndef MISTER_DISABLE_ALSA .alsa_l(alsa_l), .alsa_r(alsa_r), +`endif .i2s_bclk(HDMI_SCLK), .i2s_lrclk(HDMI_LRCLK), @@ -1491,32 +1587,45 @@ audio_out audio_out ); -wire [28:0] alsa_address; -wire [63:0] alsa_readdata; -wire alsa_ready; -wire alsa_req; -wire alsa_late; +`ifndef MISTER_DISABLE_ALSA + wire aspi_sck,aspi_mosi,aspi_ss,aspi_miso; + cyclonev_hps_interface_peripheral_spi_master spi + ( + .sclk_out(aspi_sck), + .txd(aspi_mosi), // mosi + .rxd(aspi_miso), // miso -wire [15:0] alsa_l, alsa_r; + .ss_0_n(aspi_ss), + .ss_in_n(1) + ); -alsa alsa -( - .reset(reset), - .clk(clk_audio), + wire [28:0] alsa_address; + wire [63:0] alsa_readdata; + wire alsa_ready; + wire alsa_req; + wire alsa_late; - .ram_address(alsa_address), - .ram_data(alsa_readdata), - .ram_req(alsa_req), - .ram_ready(alsa_ready), + wire [15:0] alsa_l, alsa_r; - .spi_ss(aspi_ss), - .spi_sck(aspi_sck), - .spi_mosi(aspi_mosi), - .spi_miso(aspi_miso), + alsa alsa + ( + .reset(reset), + .clk(clk_audio), - .pcm_l(alsa_l), - .pcm_r(alsa_r) -); + .ram_address(alsa_address), + .ram_data(alsa_readdata), + .ram_req(alsa_req), + .ram_ready(alsa_ready), + + .spi_ss(aspi_ss), + .spi_sck(aspi_sck), + .spi_mosi(aspi_mosi), + .spi_miso(aspi_miso), + + .pcm_l(alsa_l), + .pcm_r(alsa_r) + ); +`endif //////////////// User I/O (USB 3.0 connector) ///////////////////////// @@ -1644,6 +1753,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), @@ -1716,7 +1827,7 @@ emu emu .SDRAM2_nRAS(SDRAM2_nRAS), .SDRAM2_nCAS(SDRAM2_nCAS), .SDRAM2_CLK(SDRAM2_CLK), - .SDRAM2_EN(SW[3]), + .SDRAM2_EN(io_dig), `endif .BUTTONS(btn), @@ -1726,11 +1837,7 @@ emu emu .SD_MOSI(SD_MOSI), .SD_MISO(SD_MISO), .SD_CS(SD_CS), -`ifdef MISTER_DUAL_SDRAM - .SD_CD(mcp_sdcd), -`else - .SD_CD(mcp_sdcd & (SW[0] ? VGA_HS : (SW[3] | SDCD_SPDIF))), -`endif + .SD_CD(SD_CD), .UART_CTS(uart_rts), .UART_RTS(uart_cts), @@ -1759,19 +1866,17 @@ assign sync_out = sync_in ^ pol; reg pol; always @(posedge clk) begin - integer pos = 0, neg = 0, cnt = 0; + reg [31:0] cnt; reg s1,s2; s1 <= sync_in; s2 <= s1; + cnt <= s2 ? (cnt - 1) : (cnt + 1); - if(~s2 & s1) neg <= cnt; - if(s2 & ~s1) pos <= cnt; - - cnt <= cnt + 1; - if(s2 != s1) cnt <= 0; - - pol <= pos > neg; + if(~s2 & s1) begin + cnt <= 0; + pol <= cnt[31]; + end end endmodule diff --git a/sys/vga_out.sv b/sys/vga_out.sv index fe8172b..4160635 100644 --- a/sys/vga_out.sv +++ b/sys/vga_out.sv @@ -7,23 +7,27 @@ module vga_out input hsync, input vsync, input csync, + input de, input [23:0] din, output [23:0] dout, output reg hsync_o, output reg vsync_o, - output reg csync_o + output reg csync_o, + output reg de_o ); -wire [5:0] red = din[23:18]; -wire [5:0] green = din[15:10]; -wire [5:0] blue = din[7:2]; +wire [7:0] red = din[23:16]; +wire [7:0] green = din[15:8]; +wire [7:0] blue = din[7:0]; // http://marsee101.blog19.fc2.com/blog-entry-2311.html -// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B) -// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B) -// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B) + + +// Y = 0.301*R + 0.586*G + 0.113*B (Y = 0.299*R + 0.587*G + 0.114*B) +// Pb = 128 - 0.168*R - 0.332*G + 0.500*B (Pb = -0.169*R - 0.331*G + 0.500*B) +// Pr = 128 + 0.500*R - 0.418*G - 0.082*B (Pr = 0.500*R - 0.419*G - 0.081*B) reg [7:0] y, pb, pr; reg [23:0] rgb; @@ -33,32 +37,33 @@ always @(posedge clk) begin reg [18:0] y_1b, pb_1b, pr_1b; reg [18:0] y_2, pb_2, pr_2; reg [23:0] din1, din2; - reg hsync2, vsync2, csync2; - reg hsync1, vsync1, csync1; + reg hsync2, vsync2, csync2, de2; + reg hsync1, vsync1, csync1, de1; - y_1r <= 19'd04096 + ({red, 8'd0} + {red, 3'd0}); - pb_1r <= 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}); - pr_1r <= 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}); + y_1r <= {red, 6'd0} + {red, 3'd0} + {red, 2'd0} + red; + pb_1r <= 19'd32768 - ({red, 5'd0} + {red, 3'd0} + {red, 1'd0}); + pr_1r <= 19'd32768 + {red, 7'd0}; - y_1g <= {green, 9'd0} + {green, 2'd0}; - pb_1g <= {green, 8'd0} + {green, 5'd0} + {green, 3'd0}; - pr_1g <= {green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}; + y_1g <= {green, 7'd0} + {green, 4'd0} + {green, 2'd0} + {green, 1'd0}; + pb_1g <= {green, 6'd0} + {green, 4'd0} + {green, 2'd0} + green; + pr_1g <= {green, 6'd0} + {green, 5'd0} + {green, 3'd0} + {green, 1'd0}; - y_1b <= {blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0}; - pb_1b <= {blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0}; - pr_1b <= {blue, 6'd0} + {blue, 3'd0}; + y_1b <= {blue, 4'd0} + {blue, 3'd0} + {blue, 2'd0} + blue; + pb_1b <= {blue, 7'd0}; + pr_1b <= {blue, 4'd0} + {blue, 2'd0} + blue; y_2 <= y_1r + y_1g + y_1b; pb_2 <= pb_1r - pb_1g + pb_1b; pr_2 <= pr_1r - pr_1g - pr_1b; - y <= ( y_2[18] || !y_2[17:12]) ? 8'd16 : (y_2[17:8] > 235) ? 8'd235 : y_2[15:8]; - pb <= (pb_2[18] || !pb_2[17:12]) ? 8'd16 : (&pb_2[17:12]) ? 8'd240 : pb_2[15:8]; - pr <= (pr_2[18] || !pr_2[17:12]) ? 8'd16 : (&pr_2[17:12]) ? 8'd240 : pr_2[15:8]; + y <= y_2[18] ? 8'd0 : y_2[16] ? 8'd255 : y_2[15:8]; + pb <= pb_2[18] ? 8'd0 : pb_2[16] ? 8'd255 : pb_2[15:8]; + pr <= pr_2[18] ? 8'd0 : pr_2[16] ? 8'd255 : pr_2[15:8]; hsync_o <= hsync2; hsync2 <= hsync1; hsync1 <= hsync; vsync_o <= vsync2; vsync2 <= vsync1; vsync1 <= vsync; csync_o <= csync2; csync2 <= csync1; csync1 <= csync; + de_o <= de2; de2 <= de1; de1 <= de; rgb <= din2; din2 <= din1; din1 <= din; end 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 diff --git a/sys/video_freak.sv b/sys/video_freak.sv index 18beb03..65375cd 100644 --- a/sys/video_freak.sv +++ b/sys/video_freak.sv @@ -170,10 +170,8 @@ reg [11:0] mul_arg1, mul_arg2; wire [23:0] mul_res; sys_umul #(12,12) mul(CLK_VIDEO,mul_start,mul_run, mul_arg1,mul_arg2,mul_res); -wire [11:0] wideres = mul_res[11:0] + hsize; - always @(posedge CLK_VIDEO) begin - reg [11:0] oheight,wres; + reg [11:0] oheight,htarget,wres,hinteger,wideres; reg [12:0] arxf,aryf; reg [3:0] cnt; reg narrow; @@ -188,11 +186,18 @@ always @(posedge CLK_VIDEO) begin else if(~div_start & ~div_run & ~mul_start & ~mul_run) begin cnt <= cnt + 1'd1; case(cnt) + // example ideal and non-ideal cases: + // [1] 720x400 4:3 VGA 80x25 text-mode (non-square pixels) + // [2] 640x480 4:3 VGA graphics mode (square pixels) + // [3] 512x512 4:3 X68000 graphics mode (non-square pixels) 0: begin div_num <= HDMI_HEIGHT; div_den <= vsize; div_start <= 1; end + // [1] 1080 / 400 -> 2 + // [2] 1080 / 480 -> 2 + // [3] 1080 / 512 -> 2 1: if(!div_res[11:0]) begin // screen resolution is lower than video resolution. @@ -206,6 +211,9 @@ always @(posedge CLK_VIDEO) begin mul_arg2 <= div_res[11:0]; mul_start <= 1; end + // [1] 1080 / 400 * 400 -> 800 + // [2] 1080 / 480 * 480 -> 960 + // [3] 1080 / 512 * 512 -> 1024 2: begin oheight <= mul_res[11:0]; @@ -219,27 +227,43 @@ always @(posedge CLK_VIDEO) begin mul_arg2 <= arx_i; mul_start <= 1; end + // [1] 1080 / 400 * 400 * 4 -> 3200 + // [2] 1080 / 480 * 480 * 4 -> 3840 + // [3] 1080 / 512 * 512 * 4 -> 4096 4: begin div_num <= mul_res; div_den <= ary_i; div_start <= 1; end + // [1] 1080 / 480 * 480 * 4 / 3 -> 1066 + // [2] 1080 / 480 * 480 * 4 / 3 -> 1280 + // [3] 1080 / 512 * 512 * 4 / 3 -> 1365 + // saved as htarget 5: begin + htarget <= div_res[11:0]; div_num <= div_res; div_den <= hsize; div_start <= 1; end + // computes wide scaling factor as a ceiling division + // [1] 1080 / 400 * 400 * 4 / 3 / 720 -> 1 + // [2] 1080 / 480 * 480 * 4 / 3 / 640 -> 2 + // [3] 1080 / 512 * 512 * 4 / 3 / 512 -> 2 6: begin mul_arg1 <= hsize; mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1; mul_start <= 1; end + // [1] 1080 / 400 * 400 * 4 / 3 / 720 * 720 -> 720 + // [2] 1080 / 480 * 480 * 4 / 3 / 640 * 640 -> 1280 + // [3] 1080 / 512 * 512 * 4 / 3 / 512 * 512 -> 1024 7: if(mul_res <= HDMI_WIDTH) begin - cnt <= 10; + hinteger = mul_res[11:0]; + cnt <= 12; end 8: begin @@ -247,23 +271,50 @@ always @(posedge CLK_VIDEO) begin div_den <= hsize; div_start <= 1; end + // [1] 1920 / 720 -> 2 + // [2] 1920 / 640 -> 3 + // [3] 1920 / 512 -> 3 9: begin mul_arg1 <= hsize; mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1; mul_start <= 1; end + // [1] 1920 / 720 * 720 -> 1440 + // [2] 1920 / 640 * 640 -> 1920 + // [3] 1920 / 512 * 512 -> 1536 - 10: begin - narrow <= ((div_num[11:0] - mul_res[11:0]) <= (wideres - div_num[11:0])) || (wideres > HDMI_WIDTH); - wres <= wideres; + 10: begin + hinteger <= mul_res[11:0]; + mul_arg1 <= vsize; + mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1; + mul_start <= 1; + end + + 11: begin + oheight <= mul_res[11:0]; + end + + 12: begin + wideres <= hinteger + hsize; + narrow <= ((htarget - hinteger) <= (wideres - htarget)) || (wideres > HDMI_WIDTH); + wres <= hinteger == htarget ? hinteger : wideres; end + // [1] 1066 - 720 = 346 <= 1440 - 1066 = 374 || 1440 > 1920 -> true + // [2] 1280 - 1280 = 0 <= 1920 - 1280 = 640 || 1920 > 1920 -> true + // [3] 1365 - 1024 = 341 <= 1536 - 1365 = 171 || 1536 > 1920 -> false + // 1. narrow flag is true when mul_res[11:0] narrow width is closer to + // htarget aspect ratio target width or when wideres wider width + // does not fit to the screen. + // 2. wres becomes wideres only when mul_res[11:0] narrow width not equal + // to target width, meaning it is not optimal for source aspect ratio. + // otherwise it is set to narrow width that is optimal. - 11: begin + 13: begin case(SCALE) - 2: arxf <= {1'b1, mul_res[11:0]}; - 3: arxf <= {1'b1, (wres > HDMI_WIDTH) ? mul_res[11:0] : wres}; - 4: arxf <= {1'b1, narrow ? mul_res[11:0] : wres}; + 2: arxf <= {1'b1, hinteger}; + 3: arxf <= {1'b1, (wres > HDMI_WIDTH) ? hinteger : wres}; + 4: arxf <= {1'b1, narrow ? hinteger : wres}; default: arxf <= {1'b1, div_num[11:0]}; endcase aryf <= {1'b1, oheight}; diff --git a/sys/yc_out.sv b/sys/yc_out.sv index 2e9a24e..984fc37 100644 --- a/sys/yc_out.sv +++ b/sys/yc_out.sv @@ -36,13 +36,15 @@ module yc_out input hsync, input vsync, input csync, + input de, input [23:0] din, output [23:0] dout, output reg hsync_o, output reg vsync_o, - output reg csync_o + output reg csync_o, + output reg de_o ); wire [7:0] red = din[23:16]; @@ -61,6 +63,7 @@ typedef struct { logic hsync; logic vsync; logic csync; + logic de; } phase_t; localparam MAX_PHASES = 7'd8; @@ -211,11 +214,11 @@ always_ff @(posedge clk) begin end // Adjust sync timing correctly - phase[1].hsync <= hsync; phase[1].vsync <= vsync; phase[1].csync <= csync; - phase[2].hsync <= phase[1].hsync; phase[2].vsync <= phase[1].vsync; phase[2].csync <= phase[1].csync; - phase[3].hsync <= phase[2].hsync; phase[3].vsync <= phase[2].vsync; phase[3].csync <= phase[2].csync; - phase[4].hsync <= phase[3].hsync; phase[4].vsync <= phase[3].vsync; phase[4].csync <= phase[3].csync; - hsync_o <= phase[4].hsync; vsync_o <= phase[4].vsync; csync_o <= phase[4].csync; + phase[1].hsync <= hsync; phase[1].vsync <= vsync; phase[1].csync <= csync; phase[1].de <= de; + phase[2].hsync <= phase[1].hsync; phase[2].vsync <= phase[1].vsync; phase[2].csync <= phase[1].csync; phase[2].de <= phase[1].de; + phase[3].hsync <= phase[2].hsync; phase[3].vsync <= phase[2].vsync; phase[3].csync <= phase[2].csync; phase[3].de <= phase[2].de; + phase[4].hsync <= phase[3].hsync; phase[4].vsync <= phase[3].vsync; phase[4].csync <= phase[3].csync; phase[4].de <= phase[3].de; + hsync_o <= phase[4].hsync; vsync_o <= phase[4].vsync; csync_o <= phase[4].csync; de_o <= phase[4].de; phase[1].y <= phase[0].y; phase[2].y <= phase[1].y; phase[3].y <= phase[2].y; phase[4].y <= phase[3].y; phase[5].y <= phase[4].y;