diff --git a/sys/ascal.vhd b/sys/ascal.vhd index a41fa89..c26c1d2 100644 --- a/sys/ascal.vhd +++ b/sys/ascal.vhd @@ -255,6 +255,8 @@ ARCHITECTURE rtl OF ascal IS ---------------------------------------------------------- -- Input image + SIGNAL i_phs,i_pvs,i_pfl,i_pde,i_pce : std_logic; + SIGNAL i_pr,i_pg,i_pb : unsigned(7 DOWNTO 0); SIGNAL i_freeze : std_logic; SIGNAL i_hsize,i_hmin,i_hmax,i_hcpt : uint12; SIGNAL i_hrsize,i_vrsize : uint12; @@ -948,7 +950,6 @@ BEGIN ELSIF rising_edge(i_clk) THEN i_push<='0'; - i_pushhead<='0'; i_eol<='0'; -- End Of Line i_freeze <=freeze; -- i_iauto<=iauto; -- ? @@ -959,7 +960,7 @@ BEGIN i_head(111 DOWNTO 96)<=to_unsigned(N_BURST,16); -- Header size i_head(95 DOWNTO 80)<=x"0000"; -- Attributes. TBD i_head(80)<=i_inter; - i_head(81)<=i_fl; + i_head(81)<=i_pfl; i_head(82)<=i_hdown; i_head(83)<=i_vdown; i_head(79 DOWNTO 64)<=to_unsigned(i_hrsize,16); -- Image width @@ -967,32 +968,42 @@ BEGIN i_head(47 DOWNTO 32)<= to_unsigned(N_BURST * i_hburst,16); -- Line Length. Bytes i_head(31 DOWNTO 0)<=x"0000_0000"; -- TBD + + ------------------------------------------------------ + i_pr <=i_r; + i_pg <=i_g; + i_pb <=i_b; + i_phs<=i_hs; + i_pvs<=i_vs; + i_pfl<=i_fl; + i_pde<=i_de; + i_pce<=i_ce; ------------------------------------------------------ - IF i_ce='1' THEN + IF i_pce='1' THEN ---------------------------------------------------- - i_hs_pre<=i_hs; - i_vs_pre<=i_vs; - i_de_pre<=i_de; - i_fl_pre<=i_fl; + i_hs_pre<=i_phs; + i_vs_pre<=i_pvs; + i_de_pre<=i_pde; + i_fl_pre<=i_pfl; ---------------------------------------------------- -- Detect interlaced video IF NOT INTER THEN i_intercnt<=0; - ELSIF i_fl/=i_fl_pre THEN + ELSIF i_pfl/=i_fl_pre THEN i_intercnt<=3; - ELSIF i_vs='1' AND i_vs_pre='0' AND i_intercnt>0 THEN + ELSIF i_pvs='1' AND i_vs_pre='0' AND i_intercnt>0 THEN i_intercnt<=i_intercnt-1; END IF; i_inter<=to_std_logic(i_intercnt>0); ---------------------------------------------------- - IF i_vs='1' AND i_vs_pre='0' THEN + IF i_pvs='1' AND i_vs_pre='0' THEN i_sof<='1'; END IF; - IF i_de='1' AND i_sof='1' THEN + IF i_pde='1' AND i_sof='1' THEN i_sof<='0'; i_vcpt<=0; IF i_inter='1' AND i_flm='1' AND i_half='0' AND INTER THEN @@ -1005,33 +1016,33 @@ BEGIN END IF; END IF; - IF i_de='1' THEN - i_flm<=NOT i_fl; + IF i_pde='1' THEN + i_flm<=NOT i_pfl; END IF; i_ven<=to_std_logic(i_hcpt>=i_hmin AND i_hcpt<=i_hmax+1 AND - i_vcpt>=i_vmin AND i_vcpt<=i_vmax AND i_de='1'); + i_vcpt>=i_vmin AND i_vcpt<=i_vmax AND i_pde='1'); -- Detects end of frame for triple buffering. -- Waits for second frame of interlaced video i_endframe<=to_std_logic(i_vcpt=i_vmax + 1 AND - (i_inter='0' OR i_fl='1')); + (i_inter='0' OR i_pfl='1')); -- Detects third line for low lag mode i_syncline<=to_std_logic(i_vcpt=i_vmin + 3); ---------------------------------------------------- - IF i_de='1' AND i_de_pre='0' THEN + IF i_pde='1' AND i_de_pre='0' THEN i_vimaxc<=i_vcpt; i_hcpt<=0; ELSE i_hcpt<=(i_hcpt+1) MOD 4096; END IF; - IF i_de='0' AND i_de_pre='1' THEN + IF i_pde='0' AND i_de_pre='1' THEN i_himax<=i_hcpt; END IF; - IF i_vs='1' THEN + IF i_pvs='1' THEN i_vimax<=i_vimaxc; END IF; @@ -1040,7 +1051,7 @@ BEGIN i_hmin<=0; i_hmax<=i_himax; i_vmin<=0; - IF i_inter='0' OR i_fl='0' THEN + IF i_inter='0' OR i_pfl='0' THEN i_vmax<=i_vimax; END IF; ELSE @@ -1051,17 +1062,17 @@ BEGIN i_vmax<=vimax; -- END IF; ---pragma synthesis_off +--pragma synthesis_off ---------------------------------------------------- -- TEST : Scan image properties - IF i_hs='1' AND i_hs_pre='0' AND i_vcpt=1 THEN i_hsstart<=i_hcpt+1; END IF; - IF i_hs='0' AND i_hs_pre='1' AND i_vcpt=1 THEN i_hsend<=i_hcpt+1; END IF; - IF i_de='1' AND i_de_pre='0' AND i_vcpt=1 THEN i_htotal<=i_hcpt+1; END IF; + IF i_phs='1' AND i_hs_pre='0' AND i_vcpt=1 THEN i_hsstart<=i_hcpt+1; END IF; + IF i_phs='0' AND i_hs_pre='1' AND i_vcpt=1 THEN i_hsend<=i_hcpt+1; END IF; + IF i_pde='1' AND i_de_pre='0' AND i_vcpt=1 THEN i_htotal<=i_hcpt+1; END IF; - IF i_vs='1' AND i_vs_pre='0' THEN i_vsstart<=i_vcpt; END IF; - IF i_vs='0' AND i_vs_pre='1' THEN i_vsend<=i_vcpt; END IF; - IF i_de='1' AND i_sof='1' THEN i_vtotal<=i_vcpt; END IF; ---pragma synthesis_on + IF i_pvs='1' AND i_vs_pre='0' THEN i_vsstart<=i_vcpt; END IF; + IF i_pvs='0' AND i_vs_pre='1' THEN i_vsend<=i_vcpt; END IF; + IF i_pde='1' AND i_sof='1' THEN i_vtotal<=i_vcpt; END IF; +--pragma synthesis_on ---------------------------------------------------- i_mode<=mode; -- @@ -1132,7 +1143,7 @@ BEGIN ---------------------------------------------------- -- Downscaling interpolation - i_hpixp<=(i_r,i_g,i_b); + i_hpixp<=(i_pr,i_pg,i_pb); i_hpix0<=i_hpixp; i_hpix1<=i_hpix0; i_hpix2<=i_hpix1; @@ -1237,7 +1248,7 @@ BEGIN END IF; -- Delay I_HS raising for a few cycles, finish ongoing mem. access - IF i_hs='1' AND i_hs_pre='0' THEN + IF i_phs='1' AND i_hs_pre='0' THEN i_hs_delay<=0; ELSIF i_hs_delay<15 THEN i_hs_delay<=i_hs_delay+1; @@ -1257,24 +1268,24 @@ BEGIN END IF; END IF; - IF i_vs='0' AND i_vs_pre='1' THEN + IF i_pvs='0' AND i_vs_pre='1' THEN i_vacc<=i_ovsize/2 + i_vsize/2; -- Push header i_pushhead<=to_std_logic(HEADER); i_hbfix<='0'; END IF; - END IF; -- IF i_ce='1' + END IF; -- IF i_pce='1' ------------------------------------------------------ -- Push pixels to downscaling line buffer - i_lwr<=i_hnp4 AND i_ven5 AND i_ce; + i_lwr<=i_hnp4 AND i_ven5 AND i_pce; IF i_lwr='1' THEN i_lwad<=(i_lwad+1) MOD OHRES; END IF; i_ldw<=i_hpix; - IF i_hnp3='1' AND i_ven4='1' AND i_ce='1' THEN + IF i_hnp3='1' AND i_ven4='1' AND i_pce='1' THEN i_lrad<=(i_lrad+1) MOD OHRES; END IF; @@ -2206,7 +2217,7 @@ BEGIN o_llicpt<=0; o_llipos<=o_llocpt; o_llisize<=o_llicpt; - o_llfl<=i_fl; -- + o_llfl<=i_pfl; -- ELSE o_llicpt<=o_llicpt+1; END IF; @@ -2224,7 +2235,7 @@ BEGIN -- Period difference between input and output images o_lldiff<=(integer(o_llosize) - integer(o_llisize)); - o_lltune_i(14)<='0'; -- Unused + o_lltune_i(14)<='0'; -- Interleaved video field o_lltune_i(7 DOWNTO 6)<=i_inter & o_llfl; -- IF o_llup='1' THEN o_llcpt<=0; @@ -2389,13 +2400,13 @@ BEGIN o_b<=x"00"; END IF; ---pragma synthesis_off +--pragma synthesis_off IF o_mode(2 DOWNTO 0)="111" AND o_vcpt<2*8 THEN o_r<=(OTHERS => o_debug_set); o_g<=(OTHERS => o_debug_set); o_b<=(OTHERS => o_debug_set); END IF; ---pragma synthesis_on +--pragma synthesis_on ---------------------------------------------------- END IF; @@ -2403,7 +2414,7 @@ BEGIN END PROCESS VSCAL; ---pragma synthesis_off +--pragma synthesis_off ----------------------------------------------------------------------------- -- DEBUG Debug:PROCESS(o_clk) IS @@ -2507,8 +2518,8 @@ BEGIN '0' & o_lltune_i(7 DOWNTO 4) & -- 1 '0' & o_lltune_i(3 DOWNTO 0) & -- 1 CS(" "); - ---------------------------------------------------------------------------- ---pragma synthesis_on + ---------------------------------------------------------------------------- +--pragma synthesis_on END ARCHITECTURE rtl; diff --git a/sys/pll_hdmi_adj.vhd b/sys/pll_hdmi_adj.vhd new file mode 100644 index 0000000..feea1a0 --- /dev/null +++ b/sys/pll_hdmi_adj.vhd @@ -0,0 +1,239 @@ +-------------------------------------------------------------------------------- +-- HDMI PLL Adjust +-------------------------------------------------------------------------------- + +-- Changes the HDMI PLL frequency according to the scaler suggestions. +-------------------------------------------- +-- LLTUNE : +-- 15 : Toggle +-- 14 : Unused +-- 13 : Sign phase difference +-- 12:8 : Phase difference. Log (0=Large 31=Small) +-- 7:6 : Unused +-- 5 : Sign period difference. +-- 4:0 : Period difference. Log (0=Large 31=Small) + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE ieee.numeric_std.ALL; + +ENTITY pll_hdmi_adj IS + PORT ( + -- Scaler + llena : IN std_logic; -- 0=Disabled 1=Enabled + lltune : IN unsigned(15 DOWNTO 0); -- Outputs from scaler + + -- Signals from reconfig commands + i_waitrequest : OUT std_logic; + i_write : IN std_logic; + i_address : IN unsigned(5 DOWNTO 0); + i_writedata : IN unsigned(31 DOWNTO 0); + + -- Outputs to PLL_HDMI_CFG + o_waitrequest : IN std_logic; + o_write : OUT std_logic; + o_address : OUT unsigned(5 DOWNTO 0); + o_writedata : OUT unsigned(31 DOWNTO 0); + + ------------------------------------ + clk : IN std_logic; + reset_na : IN std_logic + ); + +BEGIN + + +END ENTITY pll_hdmi_adj; + +--############################################################################## + +ARCHITECTURE rtl OF pll_hdmi_adj IS + SIGNAL pwrite : std_logic; + SIGNAL paddress : unsigned(5 DOWNTO 0); + SIGNAL pdata : unsigned(31 DOWNTO 0); + TYPE enum_state IS (sIDLE,sW1,sW2,sW3); + SIGNAL state : enum_state; + SIGNAL lltune_sync,lltune_sync2,lltune_sync3 : unsigned(15 DOWNTO 0); + SIGNAL mfrac,mfrac_mem : unsigned(31 DOWNTO 0); + SIGNAL sign,sign_pre : std_logic; + SIGNAL up,modo,phm,dir : std_logic; + SIGNAL fcpt : natural RANGE 0 TO 3; + SIGNAL cptx : natural RANGE 0 TO 3; + SIGNAL cpt : natural RANGE 0 TO 4095; + SIGNAL phcor : natural RANGE 0 TO 3; + SIGNAL diff : unsigned(31 DOWNTO 0); + + TYPE enum_tstate IS (sWAIT,sADJ,sADJ2); + SIGNAL tstate : enum_tstate; +BEGIN + ---------------------------------------------------------------------------- + -- 000010 : Start reg "Write either 0 or 1 to start fractional PLL reconf. + -- 000111 : M counter Fractional Value + + Comb:PROCESS(i_write,i_address, + i_writedata,pwrite,paddress,pdata) IS + BEGIN + IF i_write='1' THEN + o_write <=i_write; + o_address <=i_address; + o_writedata <=i_writedata; + ELSE + o_write <=pwrite; + o_address <=paddress; + o_writedata<=pdata; + END IF; + END PROCESS Comb; + + i_waitrequest<=o_waitrequest WHEN state=sIDLE ELSE '0'; + + ---------------------------------------------------------------------------- + Schmurtz:PROCESS(clk,reset_na) IS + VARIABLE off,ofp : natural RANGE 0 TO 63; + VARIABLE dif : unsigned(31 DOWNTO 0); + BEGIN + IF reset_na='0' THEN + modo<='0'; + state<=sIDLE; + ELSIF rising_edge(clk) THEN + IF i_address="000111" AND i_write='1' THEN + mfrac<=i_writedata; + mfrac_mem<=i_writedata; + modo<='1'; + END IF; + + lltune_sync<=lltune; -- + lltune_sync2<=lltune_sync; + lltune_sync3<=lltune_sync2; + + off:=to_integer('0' & lltune_sync(4 DOWNTO 0)); + ofp:=to_integer('0' & lltune_sync(12 DOWNTO 8)); + + IF lltune_sync(15)/=lltune_sync2(15) THEN + fcpt<=fcpt+1; + IF fcpt=2 THEN fcpt<=0; END IF; + END IF; + + CASE tstate IS + WHEN sWAIT => + cpt<=0; + IF lltune_sync3(15)/=lltune_sync2(15) AND llena='1' THEN + + IF llena='0' THEN + -- Recover original freq when disabling low lag mode + phm<='0'; + IF modo='1' THEN + mfrac<=mfrac_mem; + up<='1'; + modo<='0'; + END IF; + + ELSIF phm='0' AND fcpt=2 THEN + -- Frequency adjust + IF off<10 THEN off:=10; END IF; + dif:=shift_right(mfrac,off + 1); + diff<=dif; + sign<=lltune_sync(5); + IF off>=18 THEN + phm<='1'; + ELSE + tstate<=sADJ; + END IF; + cptx<=0; + + ELSIF phm='1' THEN + -- Phase adjust + IF ofp<5 THEN ofp:=5; END IF; + dif:=shift_right(mfrac,ofp + 3 + 1); + IF (ofp>=18 OR off<16) AND fcpt=2 AND phcor=0 THEN + phm<='0'; + END IF; + IF phcor=0 THEN + IF cptx=0 THEN + sign<=NOT lltune_sync(13); + sign_pre<=sign; + diff<=dif; + IF sign_pre/=NOT lltune_sync(13) THEN + diff<='0' & dif(31 DOWNTO 1); + END IF; + END IF; + cptx<=cptx+1; + IF cptx=2 THEN + cptx<=0; + sign<=NOT sign; + phcor<=1; + END IF; + tstate<=sADJ; + ELSIF phcor=1 THEN + cptx<=cptx+1; + IF cptx=2 THEN + cptx<=0; + phcor<=2; + tstate<=sADJ; + END IF; + ELSIF fcpt=2 THEN + phcor<=0; + cptx<=0; + END IF; + END IF; + END IF; + + WHEN sADJ => + IF sign='0' THEN + mfrac<=mfrac + diff(31 DOWNTO 8); + ELSE + mfrac<=mfrac - diff(31 DOWNTO 8); + END IF; + IF up='0' THEN + up<='1'; + tstate<=sADJ2; + END IF; + + WHEN sADJ2 => + cpt<=cpt+1; + IF cpt=1023 THEN + tstate<=sWAIT; + ELSE + tstate<=sADJ; + END IF; + + END CASE; + + ------------------------------------------------------ + CASE state IS + WHEN sIDLE => + pwrite<='0'; + IF up='1' THEN + up<='0'; + state<=sW1; + pdata<=mfrac; + paddress<="000111"; + pwrite<='1'; + END IF; + + WHEN sW1 => + IF pwrite='1' AND o_waitrequest='0' THEN + state<=sW2; + pwrite<='0'; + END IF; + + WHEN sW2 => + pdata<=x"0000_0001"; + paddress<="000010"; + pwrite<='1'; + state<=sW3; + + WHEN sW3 => + IF pwrite='1' AND o_waitrequest='0' THEN + pwrite<='0'; + state<=sIDLE; + END IF; + END CASE; + + END IF; + END PROCESS Schmurtz; + + ---------------------------------------------------------------------------- + + +END ARCHITECTURE rtl; + diff --git a/sys/sys.qip b/sys/sys.qip index 3dd4831..9a2333d 100644 --- a/sys/sys.qip +++ b/sys/sys.qip @@ -4,6 +4,7 @@ set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) p set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.qip ] set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi_cfg.qip ] set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ascal.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) pll_hdmi_adj.vhd ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hq2x.sv ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scandoubler.v ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scanlines.v ] diff --git a/sys/sys_q13.qip b/sys/sys_q13.qip index c765279..01f9e29 100644 --- a/sys/sys_q13.qip +++ b/sys/sys_q13.qip @@ -8,6 +8,7 @@ set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) p set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_hdmi_cfg/altera_pll_reconfig_core.v ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_hdmi_cfg/altera_pll_reconfig_top.v ] set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ascal.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) pll_hdmi_adj.vhd ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hq2x.sv ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scandoubler.v ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scanlines.v ] diff --git a/sys/sys_top.v b/sys/sys_top.v index 215c71e..c28e2d4 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -216,6 +216,7 @@ reg coef_set = 0; wire [7:0] ARX, ARY; reg [11:0] VSET = 0; reg [2:0] scaler_flt; +reg lowlat = 0; always@(posedge clk_sys) begin reg [7:0] cmd; @@ -273,8 +274,9 @@ always@(posedge clk_sys) begin if(cnt[1:0]==2) begin cfg_custom_p2[31:16] <= io_din; cfg_custom_t <= ~cfg_custom_t; - cnt[1:0] <= 0; + cnt[2:0] <= 3'b100; end + if(cnt == 8) lowlat <= io_din[15]; end end if(cmd == 'h25) {led_overtake, led_state} <= io_din; @@ -434,6 +436,12 @@ vip_config vip_config .writedata(ctl_writedata), .waitrequest(ctl_waitrequest) ); + +assign cfg_write = adj_write; +assign cfg_address = adj_address; +assign cfg_data = adj_data; +assign adj_waitrequest = cfg_waitrequest; + `endif @@ -561,7 +569,7 @@ ascal .vmin (vmin), .vmax (vmax), - .mode ({1'b1,scaler_flt,2'b00}), + .mode ({~lowlat,|scaler_flt,2'b00}), .poly_clk (clk_sys), .poly_a (coef_addr), .poly_dw (coef_data), @@ -610,6 +618,23 @@ always @(posedge clk_vid) begin endcase end +pll_hdmi_adj pll_hdmi_adj +( + .clk(FPGA_CLK1_50), + .reset_na(~reset_req), + + .llena(lowlat), + .lltune(lltune), + .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) +); + `endif @@ -636,10 +661,10 @@ reg [11:0] VBP = 36; wire [63:0] reconfig_to_pll; wire [63:0] reconfig_from_pll; -wire cfg_waitrequest; -reg cfg_write; -reg [5:0] cfg_address; -reg [31:0] cfg_data; +wire cfg_waitrequest,adj_waitrequest; +reg cfg_write,adj_write; +reg [5:0] cfg_address,adj_address; +reg [31:0] cfg_data,adj_data; pll_hdmi_cfg pll_hdmi_cfg ( @@ -665,24 +690,24 @@ always @(posedge FPGA_CLK1_50) begin gotd <= cfg_got; gotd2 <= gotd; - cfg_write <= 0; + adj_write <= 0; custd <= cfg_custom_t; custd2 <= custd; if(custd2 != custd & ~gotd) begin - cfg_address <= cfg_custom_p1; - cfg_data <= cfg_custom_p2; - cfg_write <= 1; + adj_address <= cfg_custom_p1; + adj_data <= cfg_custom_p2; + adj_write <= 1; end if(~gotd2 & gotd) begin - cfg_address <= 2; - cfg_data <= 0; - cfg_write <= 1; + adj_address <= 2; + adj_data <= 0; + adj_write <= 1; end - old_wait <= cfg_waitrequest; - if(old_wait & ~cfg_waitrequest & gotd) cfg_ready <= 1; + old_wait <= adj_waitrequest; + if(old_wait & ~adj_waitrequest & gotd) cfg_ready <= 1; end hdmi_config hdmi_config @@ -884,6 +909,7 @@ wire [1:0] audio_mix; wire [7:0] r_out, g_out, b_out; wire vs, hs, de, f1; wire [1:0] scanlines; +wire [15:0] lltune; wire clk_sys, clk_vid, ce_pix; wire ram_clk;