diff --git a/sys/ascal.vhd b/sys/ascal.vhd index c26c1d2..651ee6d 100644 --- a/sys/ascal.vhd +++ b/sys/ascal.vhd @@ -49,17 +49,19 @@ -- 1 : Pixel format -- 1 : 24 bits/pixel, packed RGB. Big Endian --- 3:2 : Header size : Offset to start of picture (= N_BURST) +-- 3:2 : Header size : Offset to start of picture (= N_BURST). 12 bits -- 5:4 : Attributes. TBD -- b0 ; Interlaced -- b1 : Field number -- b2 : Horizontal downscaled -- b3 : Vertical downscaled --- 7:6 : Image width. Pixels. --- 9:8 : Image height. Pixels. +-- b4 : Triple buffered +-- b7-5 : Frame counter +-- 7:6 : Image width. Pixels. 12 bits +-- 9:8 : Image height. Pixels. 12 bits -- 11:10 : Line length. Bytes. --- 13:12 : TBD. --- 15:14 : TBD. +-- 13:12 : Output width. Pixels. 12 bits +-- 15:14 : Output height. Pixels. 12 bits -------------------------------------------- LIBRARY ieee; @@ -89,8 +91,8 @@ USE ieee.numeric_std.ALL; -- Must be a power of two -- INTER : True=Autodetect interlaced video False=Force progressive scan -- HEADER : True=Add image properties header --- SYNCHRO : True=Support synchronized mode False=Force disabled -- DOWNSCALE : True=Support downscaling False=Downscaling disabled +-- BYTESWAP : Little/Big endian byte swap -- FRAC : Fractional bits, subpixel resolution -- FORMAT : TBD -- OHRES : Max. output horizontal resolution. Must be a power of two. @@ -108,8 +110,8 @@ ENTITY ascal IS RAMSIZE : unsigned(31 DOWNTO 0) := x"0080_0000"; -- =8MB INTER : boolean := true; HEADER : boolean := true; - SYNCHRO : boolean := true; DOWNSCALE : boolean := true; + BYTESWAP : boolean := true; FRAC : natural RANGE 4 TO 6 :=4; FORMAT : natural RANGE 1 TO 8 :=1; OHRES : natural RANGE 1 TO 4096 :=2048; @@ -252,35 +254,37 @@ ARCHITECTURE rtl OF ascal IS ATTRIBUTE ramstyle : string; SUBTYPE uint12 IS natural RANGE 0 TO 4095; + SUBTYPE uint13 IS natural RANGE 0 TO 8191; ---------------------------------------------------------- -- 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_pvs,i_pfl,i_pde,i_pce : std_logic; + SIGNAL i_ppix : type_pix; SIGNAL i_freeze : 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; SIGNAL i_himax,i_vimax : uint12; - SIGNAL i_vsize,i_vmaxmin,i_vmin,i_vmax,i_vimaxc,i_vcpt : uint12; + SIGNAL i_vsize,i_vmaxmin,i_vmin,i_vmax,i_vcpt : uint12; SIGNAL i_iauto : std_logic; SIGNAL i_mode : unsigned(4 DOWNTO 0); SIGNAL i_ven,i_sof : std_logic; SIGNAL i_wr : std_logic; SIGNAL i_divstart,i_divrun : std_logic; - SIGNAL i_de_pre,i_hs_pre,i_vs_pre,i_fl_pre : std_logic; - SIGNAL i_hs_delay : natural RANGE 0 TO 15; + SIGNAL i_de_pre,i_vs_pre,i_fl_pre : std_logic; + SIGNAL i_hs_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_write,i_write_pre,i_walt : std_logic; - SIGNAL i_push,i_pushend,i_pushend2,i_eol,i_eol2,i_eol3,i_eol4 : std_logic; - SIGNAL i_pushhead,i_hbfix : std_logic; + SIGNAL i_write,i_walt,i_wline : std_logic; + SIGNAL i_push,i_pushend,i_pushend2,i_eol,i_eol2,i_eol3 : std_logic; + SIGNAL i_pushhead,i_pushhead2,i_pushhead3,i_hbfix : std_logic; SIGNAL i_hburst,i_hbcpt : natural RANGE 0 TO 31; SIGNAL i_shift : unsigned(0 TO 119) := (OTHERS =>'0'); SIGNAL i_head : unsigned(127 DOWNTO 0); SIGNAL i_acpt : natural RANGE 0 TO 15; SIGNAL i_dpram : arr_dw(0 TO BLEN*2-1); ATTRIBUTE ramstyle OF i_dpram : SIGNAL IS "no_rw_check"; - SIGNAL i_endframe,i_syncline : std_logic; + SIGNAL i_endframe0,i_endframe1,i_syncline : std_logic; SIGNAL i_wad : natural RANGE 0 TO BLEN*2-1; SIGNAL i_dw : unsigned(N_DW-1 DOWNTO 0); SIGNAL i_adrs,i_adrsi : unsigned(31 DOWNTO 0); -- Avalon address @@ -289,25 +293,21 @@ ARCHITECTURE rtl OF ascal IS SIGNAL i_line : arr_pix(0 TO IHRES-1); -- Downscale line buffer ATTRIBUTE ramstyle OF i_line : SIGNAL IS "no_rw_check"; SIGNAL i_ohsize,i_ovsize : uint12; - SIGNAL i_vdivi : unsigned(11 DOWNTO 0); - SIGNAL i_vdivr : unsigned(23 DOWNTO 0); - SIGNAL i_div : unsigned(15 DOWNTO 0); + SIGNAL i_vdivi : unsigned(12 DOWNTO 0); + SIGNAL i_vdivr : unsigned(24 DOWNTO 0); + SIGNAL i_div : unsigned(16 DOWNTO 0); SIGNAL i_dir : unsigned(11 DOWNTO 0); SIGNAL i_h_frac,i_v_frac : unsigned(11 DOWNTO 0); - SIGNAL i_hacc,i_vacc : uint12; + 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_lwr : std_logic; - SIGNAL i_lpush,i_bil : std_logic; + 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; SIGNAL i_hpix,i_pix : type_pix; SIGNAL i_hnp1,i_hnp2,i_hnp3,i_hnp4 : std_logic; SIGNAL i_ven1,i_ven2,i_ven3,i_ven4,i_ven5,i_ven6,i_ven7 : std_logic; - - SIGNAL i_htotal,i_hsstart,i_hsend : uint12; - SIGNAL i_vtotal,i_vsstart,i_vsend : uint12; ---------------------------------------------------------- -- Avalon @@ -319,13 +319,14 @@ ARCHITECTURE rtl OF ascal IS SIGNAL avl_reading : std_logic; SIGNAL avl_read_sr,avl_write_sr,avl_read_clr,avl_write_clr : std_logic; SIGNAL avl_rad,avl_rad_c,avl_wad : natural RANGE 0 TO 2*BLEN-1; - SIGNAL avl_walt : std_logic; + SIGNAL avl_walt,avl_wline,avl_rline : std_logic; SIGNAL avl_dw,avl_dr : unsigned(N_DW-1 DOWNTO 0); SIGNAL avl_wr : std_logic; SIGNAL avl_readack : std_logic; SIGNAL avl_radrs,avl_wadrs : unsigned(31 DOWNTO 0); SIGNAL avl_rbib : std_logic; - SIGNAL avl_i_offset,avl_o_offset : unsigned(31 DOWNTO 0); + SIGNAL avl_i_offset0,avl_o_offset0 : unsigned(31 DOWNTO 0); + SIGNAL avl_i_offset1,avl_o_offset1 : unsigned(31 DOWNTO 0); SIGNAL avl_reset_na : std_logic; SIGNAL avl_o_vs_sync,avl_o_vs : std_logic; @@ -352,15 +353,16 @@ ARCHITECTURE rtl OF ascal IS SIGNAL o_vtotal,o_vsstart,o_vsend : uint12; SIGNAL o_vmin,o_vmax,o_vdisp : uint12; SIGNAL o_divcpt : natural RANGE 0 TO 36; - SIGNAL o_iendframe,o_iendframe2,o_bufup : std_logic; - SIGNAL o_ibuf,o_obuf : natural RANGE 0 TO 2; + SIGNAL o_iendframe0,o_iendframe02,o_iendframe1,o_iendframe12 : std_logic; + SIGNAL o_bufup0,o_bufup1,o_inter : std_logic; + SIGNAL o_ibuf0,o_ibuf1,o_obuf0,o_obuf1 : natural RANGE 0 TO 2; TYPE type_o_state IS (sDISP,sHSYNC,sREAD,sWAITREAD); SIGNAL o_state : type_o_state; SIGNAL o_copy,o_readack,o_readack_sync,o_readack_sync2 : std_logic; SIGNAL o_copyv : unsigned(0 TO 7); SIGNAL o_adrs : unsigned(31 DOWNTO 0); -- Avalon address SIGNAL o_adrs_pre : natural RANGE 0 TO 32*4096-1; - SIGNAL o_adrsa : std_logic; + SIGNAL o_adrsa,o_rline : std_logic; SIGNAL o_ad,o_ad1,o_ad2,o_ad3 : natural RANGE 0 TO 2*BLEN-1; SIGNAL o_adturn : std_logic; SIGNAL o_dr : unsigned(N_DW-1 DOWNTO 0); @@ -381,9 +383,9 @@ ARCHITECTURE rtl OF ascal IS SIGNAL o_ihsize,o_ivsize : uint12; SIGNAL o_vfrac,o_hfrac,o_hfrac1,o_hfrac2,o_hfrac3 : unsigned(11 DOWNTO 0); - SIGNAL o_hacc,o_hacc_ini,o_hacc_next,o_vacc,o_vacc_next,o_vacc_ini : natural RANGE 0 TO 2*OHRES-1; + 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_hsv,o_vsv,o_dev,o_pev : unsigned(0 TO 5); - SIGNAL o_hsp,o_vss,o_vss1 : std_logic; + SIGNAL o_hsp,o_vss : std_logic; SIGNAL o_read,o_read_pre : std_logic; SIGNAL o_readlev,o_copylev : natural RANGE 0 TO 2; SIGNAL o_hburst,o_hbcpt : natural RANGE 0 TO 31; @@ -400,24 +402,15 @@ ARCHITECTURE rtl OF ascal IS SIGNAL o_hpix0,o_hpix1,o_hpix2,o_hpix3 : type_pix; SIGNAL o_hpixq,o_vpixq,o_vpixq1 : arr_pix(0 TO 3); - SIGNAL o_isyncline,o_isyncline2 : std_logic; SIGNAL o_vpe : std_logic; - SIGNAL o_div,o_div2 : unsigned(17 DOWNTO 0); --uint12; + SIGNAL o_div,o_div2 : unsigned(18 DOWNTO 0); --uint12; SIGNAL o_dir,o_dir2 : unsigned(11 DOWNTO 0); - SIGNAL o_vdivi : unsigned(11 DOWNTO 0); - SIGNAL o_vdivr : unsigned(23 DOWNTO 0); + SIGNAL o_vdivi : unsigned(12 DOWNTO 0); + SIGNAL o_vdivr : unsigned(24 DOWNTO 0); SIGNAL o_divstart : std_logic; SIGNAL o_divrun : std_logic; SIGNAL o_hacpt,o_vacpt : unsigned(11 DOWNTO 0); - SIGNAL o_llicpt,o_llisize,o_llipos : natural RANGE 0 TO 2**24-1; - SIGNAL o_llocpt,o_llosize : natural RANGE 0 TO 2**24-1; - SIGNAL o_lldiff : integer RANGE -2**23 TO 2**23-1 :=0; - SIGNAL o_llup,o_llos,o_llop,o_llfl : std_logic; - SIGNAL o_lltune_i : unsigned(15 DOWNTO 0); - SIGNAL o_llssh : natural RANGE 0 TO 2**24-1; - SIGNAL o_llcpt : natural RANGE 0 TO 31; - ----------------------------------------------------------------------------- -- ACPT 012345678901234--- 128bits DATA -- 0 ...............RGB @@ -544,6 +537,19 @@ ARCHITECTURE rtl OF ascal IS RETURN ((acpt MOD 8)=0 OR (acpt MOD 8)=2 OR (acpt MOD 8)=5); END IF; END FUNCTION; + + FUNCTION swap(d : unsigned(N_DW-1 DOWNTO 0)) RETURN unsigned IS + VARIABLE e : unsigned(N_DW-1 DOWNTO 0); + BEGIN + IF BYTESWAP THEN + FOR i IN 0 TO N_DW/8-1 LOOP + e(i*8+7 DOWNTO i*8):=d(N_DW-i*8-1 DOWNTO N_DW-i*8-8); + END LOOP; + RETURN e; + ELSE + RETURN d; + END IF; + END FUNCTION swap; ----------------------------------------------------------------------------- FUNCTION altx (a : unsigned(1 DOWNTO 0)) RETURN unsigned IS @@ -609,7 +615,7 @@ ARCHITECTURE rtl OF ascal IS RETURN x; END FUNCTION; SIGNAL o_h_bil_t,o_v_bil_t : type_bil_t; - SIGNAL i_h_bil_t,i_v_bil_t : type_bil_t; + SIGNAL i_h_bil_t : type_bil_t; ----------------------------------------------------------------------------- -- Sharp Bilinear @@ -781,13 +787,14 @@ ARCHITECTURE rtl OF ascal IS ----------------------------------------------------------------------------- -- Polyphase - TYPE arr_uv36 IS ARRAY (natural RANGE <>) OF unsigned(35 DOWNTO 0); -- 9/9/9/9 + TYPE arr_uv36 IS ARRAY (natural RANGE <>) OF unsigned(35 DOWNTO 0); TYPE arr_int9 IS ARRAY (natural RANGE <>) OF integer RANGE -256 TO 255; + CONSTANT POLY16 : arr_int9 := ( - -24,-20,-16,-11,-6,-1,2,5,6,6,5,4,2,1,0,0, - 176,174,169,160,147,129,109,84,58,22,3,-12,-20,-25,-26,-25, - -24,-26,-26,-23,-16,-4,11,32,58,96,119,140,154,165,172,175, - 0,0,1,2,3,4,6,7,6,4,1,-4,-8,-13,-18,-22); + -24,-21,-15,-9,-5,-1,4,8,6,8,5,4,3,1,0,0, + 176,174,169,160,150,131,115,85,58,27,4,-6,-20,-24,-26,-25, + -24,-25,-26,-24,-20,-6,4,27,58,85,115,131,150,160,169,174, + 0,0,0,1,3,4,5,8,6,8,4,-1,-5,-9,-15,-21); CONSTANT POLY32 : arr_int9 := ( -24,-22,-20,-18,-16,-13,-11,-8,-6,-3,-1,0,2,3,5,5,6,6,6,5,5,4,4,3,2,1,1,0,0,0,0,0, @@ -858,78 +865,6 @@ ARCHITECTURE rtl OF ascal IS RETURN p; END FUNCTION; - ----------------------------------------------------------------------------- - -- DEBUG - - SIGNAL o_debug_set : std_logic; - SIGNAL o_debug_col : unsigned(7 DOWNTO 0); - SIGNAL o_debug_vin0 : unsigned(0 TO 32*5-1) :=(OTHERS =>'0'); - SIGNAL o_debug_vin1 : unsigned(0 TO 32*5-1) :=(OTHERS =>'0'); - SIGNAL o_debug_hcpt2,o_debug_hcpt3,o_debug_hcpt4 : uint12; - SIGNAL o_debug_hcpt5,o_debug_hcpt6 : uint12; - - SIGNAL o_debug_char : unsigned(4 DOWNTO 0); - SIGNAL o_debug_hchar : natural RANGE 0 TO 255; - - FUNCTION CC(i : character) RETURN unsigned IS - BEGIN - CASE i IS - WHEN '0' => RETURN "00000"; - WHEN '1' => RETURN "00001"; - WHEN '2' => RETURN "00010"; - WHEN '3' => RETURN "00011"; - WHEN '4' => RETURN "00100"; - WHEN '5' => RETURN "00101"; - WHEN '6' => RETURN "00110"; - WHEN '7' => RETURN "00111"; - WHEN '8' => RETURN "01000"; - WHEN '9' => RETURN "01001"; - WHEN 'A' => RETURN "01010"; - WHEN 'B' => RETURN "01011"; - WHEN 'C' => RETURN "01100"; - WHEN 'D' => RETURN "01101"; - WHEN 'E' => RETURN "01110"; - WHEN 'F' => RETURN "01111"; - WHEN ' ' => RETURN "10000"; - WHEN '=' => RETURN "10001"; - WHEN '+' => RETURN "10010"; - WHEN '-' => RETURN "10011"; - WHEN '<' => RETURN "10100"; - WHEN '>' => RETURN "10101"; - WHEN '^' => RETURN "10110"; - WHEN 'v' => RETURN "10111"; - WHEN '(' => RETURN "11000"; - WHEN ')' => RETURN "11001"; - WHEN ':' => RETURN "11010"; - WHEN '.' => RETURN "11011"; - WHEN ',' => RETURN "11100"; - WHEN '?' => RETURN "11101"; - WHEN '|' => RETURN "11110"; - WHEN '#' => RETURN "11111"; - WHEN OTHERS => RETURN "10000"; - END CASE; - END FUNCTION CC; - FUNCTION CS(s : string) RETURN unsigned IS - VARIABLE r : unsigned(0 TO s'length*5-1); - VARIABLE j : natural :=0; - BEGIN - FOR i IN s'RANGE LOOP - r(j TO j+4) :=CC(s(i)); - j:=j+5; - END LOOP; - RETURN r; - END FUNCTION CS; - FUNCTION CN(v : unsigned) RETURN unsigned IS - VARIABLE t : unsigned(0 TO v'length-1); - VARIABLE o : unsigned(0 TO v'length/4*5-1); - BEGIN - t:=v; - FOR i IN 0 TO v'length/4-1 LOOP - o(i*5 TO i*5+4):='0' & t(i*4 TO i*4+3); - END LOOP; - RETURN o; - END FUNCTION CN; - BEGIN ----------------------------------------------------------------------------- @@ -942,38 +877,39 @@ BEGIN InAT:PROCESS(i_clk,i_reset_na) IS CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); VARIABLE frac_v : unsigned(FRAC-1 DOWNTO 0); - VARIABLE div_v : unsigned(15 DOWNTO 0); + VARIABLE div_v : unsigned(16 DOWNTO 0); VARIABLE dir_v : unsigned(11 DOWNTO 0); + VARIABLE bil_t_v : type_bil_t; BEGIN IF i_reset_na='0' THEN - i_write_pre<='0'; + i_write<='0'; ELSIF rising_edge(i_clk) THEN i_push<='0'; i_eol<='0'; -- End Of Line i_freeze <=freeze; -- - i_iauto<=iauto; -- ? + i_iauto<=iauto; -- ------------------------------------------------------ i_head(127 DOWNTO 120)<=x"01"; -- Header type i_head(119 DOWNTO 112)<=x"01"; -- 24bits/pixels, packed RGB, big endian - i_head(111 DOWNTO 96)<=to_unsigned(N_BURST,16); -- Header size + i_head(111 DOWNTO 96)<="0000" & to_unsigned(N_BURST,12); -- Header size i_head(95 DOWNTO 80)<=x"0000"; -- Attributes. TBD i_head(80)<=i_inter; - i_head(81)<=i_pfl; + i_head(81)<=i_flm; i_head(82)<=i_hdown; i_head(83)<=i_vdown; - i_head(79 DOWNTO 64)<=to_unsigned(i_hrsize,16); -- Image width - i_head(63 DOWNTO 48)<=to_unsigned(i_vrsize,16); -- Image height + i_head(84)<=i_mode(3); + i_head(87 DOWNTO 85)<=i_count; + i_head(79 DOWNTO 64)<="0000" & to_unsigned(i_hrsize,12); -- Image width + i_head(63 DOWNTO 48)<="0000" & to_unsigned(i_vrsize,12); -- Image height 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_head(31 DOWNTO 16)<="0000" & to_unsigned(i_ohsize,12); + i_head(15 DOWNTO 0) <="0000" & to_unsigned(i_ovsize,12); + ------------------------------------------------------ - i_pr <=i_r; - i_pg <=i_g; - i_pb <=i_b; - i_phs<=i_hs; + i_ppix<=(i_r,i_g,i_b); i_pvs<=i_vs; i_pfl<=i_fl; i_pde<=i_de; @@ -982,7 +918,6 @@ BEGIN ------------------------------------------------------ IF i_pce='1' THEN ---------------------------------------------------- - i_hs_pre<=i_phs; i_vs_pre<=i_pvs; i_de_pre<=i_pde; i_fl_pre<=i_pfl; @@ -1007,10 +942,12 @@ BEGIN i_sof<='0'; i_vcpt<=0; IF i_inter='1' AND i_flm='1' AND i_half='0' AND INTER THEN + i_wline<='1'; i_adrsi<=to_unsigned(N_BURST * i_hburst,32) + to_unsigned(N_BURST * to_integer( unsigned'("00") & to_std_logic(HEADER)),32); ELSE + i_wline<='0'; i_adrsi<=to_unsigned(N_BURST * to_integer( unsigned'("00") & to_std_logic(HEADER)),32); END IF; @@ -1020,19 +957,21 @@ BEGIN 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_pde='1'); + i_ven<=to_std_logic(i_hcpt>=i_hmin AND i_hcpt<=i_hmax AND + i_vcpt>=i_vmin AND i_vcpt<=i_vmax); -- 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_pfl='1')); + i_endframe0<=to_std_logic(i_vcpt=i_vmax + 1 AND + (i_inter='0' OR i_flm='0')); + i_endframe1<=to_std_logic(i_vcpt=i_vmax + 1 AND + (i_inter='0' OR i_flm='1')); + -- Detects third line for low lag mode - i_syncline<=to_std_logic(i_vcpt=i_vmin + 3); + i_syncline<=to_std_logic(i_vcpt=i_vmin + 4); ---------------------------------------------------- IF i_pde='1' AND i_de_pre='0' THEN - i_vimaxc<=i_vcpt; + i_vimax<=i_vcpt; i_hcpt<=0; ELSE i_hcpt<=(i_hcpt+1) MOD 4096; @@ -1042,16 +981,12 @@ BEGIN i_himax<=i_hcpt; END IF; - IF i_pvs='1' THEN - i_vimax<=i_vimaxc; - END IF; - IF i_iauto='1' THEN -- Auto-size i_hmin<=0; i_hmax<=i_himax; i_vmin<=0; - IF i_inter='0' OR i_pfl='0' THEN + IF i_pvs='1' AND i_vs_pre='0' AND (i_inter='0' OR i_pfl='0') THEN i_vmax<=i_vimax; END IF; ELSE @@ -1062,18 +997,6 @@ BEGIN i_vmax<=vimax; -- END IF; ---pragma synthesis_off - ---------------------------------------------------- - -- TEST : Scan image properties - 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_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; -- @@ -1107,33 +1030,33 @@ BEGIN ---------------------------------------------------- -- Downscaling vertical i_divstart<='0'; - IF i_hs_delay=14 THEN - IF i_vacc + i_ovsize < i_vsize THEN - i_vacc<=(i_vacc + i_ovsize) MOD 4096; + IF i_hs_delay=7 THEN + IF (i_vacc + 2*i_ovsize) < 2*i_vsize THEN + i_vacc<=(i_vacc + 2*i_ovsize) MOD 8192; i_vnp<='0'; ELSE - i_vacc<=(i_vacc + i_ovsize - i_vsize + 4096) MOD 4096; + i_vacc<=(i_vacc + 2*i_ovsize - 2*i_vsize + 8192) MOD 8192; i_vnp<='1'; END IF; i_divstart<='1'; IF i_vcpt=i_vmin THEN - i_vacc<=i_ovsize/2 + i_vsize/2; - i_vnp<='0'; -- + i_vacc<=(i_vsize - i_ovsize + 8192) MOD 8192; + i_vnp<='1'; -- END IF; END IF; - IF i_vdown='0' THEN - i_vnp<='1'; - END IF; + --IF i_vdown='0' THEN + -- i_vnp<='1'; + --END IF; -- Downscaling horizontal IF i_ven='1' THEN - IF i_hacc + i_ohsize < i_hsize THEN - i_hacc<=(i_hacc + i_ohsize) MOD 4096; - i_hnp<='0'; + IF i_hacc + 2*i_ohsize < 2*i_hsize THEN + i_hacc<=(i_hacc + 2*i_ohsize) MOD 8192; + i_hnp<='0'; -- Skip. pix. ELSE - i_hacc<=(i_hacc + i_ohsize - i_hsize + 4096) MOD 4096; + i_hacc<=(i_hacc + 2*i_ohsize - 2*i_hsize + 8192) MOD 8192; i_hnp<='1'; END IF; END IF; @@ -1143,7 +1066,7 @@ BEGIN ---------------------------------------------------- -- Downscaling interpolation - i_hpixp<=(i_pr,i_pg,i_pb); + i_hpixp<=i_ppix; i_hpix0<=i_hpixp; i_hpix1<=i_hpix0; i_hpix2<=i_hpix1; @@ -1156,37 +1079,37 @@ BEGIN -- C1 : DIV 1. Pipelined 4 bits non-restoring divider dir_v:=x"000"; - div_v:=to_unsigned(i_hacc * 16,16); + div_v:=to_unsigned(i_hacc * 16,17); - div_v:=div_v-to_unsigned(i_hsize*8,16); - dir_v(11):=NOT div_v(15); - IF div_v(15)='0' THEN - div_v:=div_v-to_unsigned(i_hsize*4,16); + div_v:=div_v-to_unsigned(i_hsize*16,17); + dir_v(11):=NOT div_v(16); + IF div_v(16)='0' THEN + div_v:=div_v-to_unsigned(i_hsize*8,17); ELSE - div_v:=div_v+to_unsigned(i_hsize*4,16); + div_v:=div_v+to_unsigned(i_hsize*8,17); END IF; - dir_v(10):=NOT div_v(15); + dir_v(10):=NOT div_v(16); i_div<=div_v; i_dir<=dir_v; -- C2 : DIV 2. div_v:=i_div; dir_v:=i_dir; - IF div_v(15)='0' THEN - div_v:=div_v-to_unsigned(i_hsize*2,16); + IF div_v(16)='0' THEN + div_v:=div_v-to_unsigned(i_hsize*4,17); ELSE - div_v:=div_v+to_unsigned(i_hsize*2,16); + div_v:=div_v+to_unsigned(i_hsize*4,17); END IF; - dir_v(9):=NOT div_v(15); + dir_v(9):=NOT div_v(16); - IF div_v(15)='0' THEN - div_v:=div_v-to_unsigned(i_hsize,16); + IF div_v(16)='0' THEN + div_v:=div_v-to_unsigned(i_hsize*2,17); ELSE - div_v:=div_v+to_unsigned(i_hsize,16); + div_v:=div_v+to_unsigned(i_hsize*2,17); END IF; - dir_v(8):=NOT div_v(15); + dir_v(8):=NOT div_v(16); i_h_frac<=dir_v; - + -- C4 : Horizontal Bilinear IF i_bil='0' THEN frac_v:=near_frac(i_h_frac); @@ -1194,7 +1117,7 @@ BEGIN frac_v:=bil_frac(i_h_frac); END IF; - i_h_bil_t<=bil_calc(frac_v,(i_hpix3,i_hpix3,i_hpix4,i_hpix4)); + i_h_bil_t<=bil_calc(frac_v,(i_hpix2,i_hpix2,i_hpix3,i_hpix3)); i_hpix.r<=bound(i_h_bil_t.r,8+FRAC); i_hpix.g<=bound(i_h_bil_t.g,8+FRAC); i_hpix.b<=bound(i_h_bil_t.b,8+FRAC); @@ -1210,10 +1133,10 @@ BEGIN frac_v:=bil_frac(i_v_frac(11 DOWNTO 0)); END IF; - i_v_bil_t<=bil_calc(frac_v,(i_hpix,i_hpix,i_ldrm,i_ldrm)); - i_pix.r<=bound(i_v_bil_t.r,8+FRAC); - i_pix.g<=bound(i_v_bil_t.g,8+FRAC); - i_pix.b<=bound(i_v_bil_t.b,8+FRAC); + bil_t_v:=bil_calc(frac_v,(i_hpix,i_hpix,i_ldrm,i_ldrm)); + i_pix.r<=bound(bil_t_v.r,8+FRAC); + i_pix.g<=bound(bil_t_v.g,8+FRAC); + i_pix.b<=bound(bil_t_v.b,8+FRAC); IF i_vdown='0' THEN i_pix<=i_hpix; @@ -1227,9 +1150,6 @@ BEGIN IF (i_hnp4='1' AND i_ven6='1') OR i_pushend='1' THEN i_shift<=i_shift(24 TO 119) & i_pix.r & i_pix.g & i_pix.b; i_dw<=shift24_ipack(i_dw,i_acpt,i_shift,i_pix); - IF i_pushhead='1' THEN - i_dw<=i_head; - END IF; IF shift24_inext(i_acpt) AND i_vnp='1' THEN i_push<='1'; @@ -1238,29 +1158,41 @@ BEGIN i_acpt<=(i_acpt+1) MOD 16; END IF; + IF i_pushhead='1' THEN + i_dw<=i_head; + i_pushhead2<='1'; + i_pushhead<='0'; + i_count<=i_count+1; + END IF; + IF i_ven6='1' AND i_ven5='0' AND i_vnp='1' THEN i_pushend<='1'; END IF; i_pushend2<=i_pushend; - IF ((i_ven6='0' AND i_ven7='1') OR i_pushend2='1')AND i_pushend='0' THEN + IF ((i_ven7='1' AND i_ven6='0') OR i_pushend2='1') + AND i_pushend='0' THEN + -- EOL après fin PUSHEND. + -- - Soit il n'y a pas eu de pushend (à cause de VNP) + -- - Soit front descendant pushend i_eol<='1'; END IF; - - -- Delay I_HS raising for a few cycles, finish ongoing mem. access - IF i_phs='1' AND i_hs_pre='0' THEN + + IF i_pde='0' AND i_de_pre='1' THEN i_hs_delay<=0; - ELSIF i_hs_delay<15 THEN + ELSIF i_hs_delay<18 THEN i_hs_delay<=i_hs_delay+1; END IF; - IF i_hs_delay=14 THEN -- i_hs='1' AND i_hs_pre='0' THEN - i_acpt<=0; - i_hacc<=i_ohsize/2 + i_hsize/2; + IF i_hs_delay=7 THEN i_lwad<=0; i_lrad<=0; - i_wad<=2*BLEN-1; i_vcpt<=i_vcpt+1; + i_hacc<=(i_hsize - i_ohsize + 8192) MOD 8192; + END IF; + IF i_hs_delay=17 THEN + i_acpt<=0; + i_wad<=2*BLEN-1; i_hbcpt<=0; -- Bursts per line counter IF i_vnp='1' AND i_hbcpt>0 AND i_hbfix='0' THEN i_hburst<=i_hbcpt; @@ -1269,7 +1201,6 @@ BEGIN END IF; 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'; @@ -1296,43 +1227,40 @@ BEGIN IF i_push='1' AND i_freeze='0' THEN i_wr<='1'; i_wad<=(i_wad+1) MOD (BLEN*2); - IF ((i_wad+1) MOD BLEN=BLEN-1) THEN + IF (i_wad+1) MOD BLEN=BLEN-1 THEN i_hbcpt<=(i_hbcpt+1) MOD 32; - i_write_pre<=NOT i_write_pre; - IF (i_wad+1)/BLEN=0 THEN - i_walt<='0'; - ELSE - i_walt<='1'; - END IF; + i_write<=i_write XOR NOT i_freeze; + i_walt<=to_std_logic((i_wad+1)/BLEN /= 0); i_adrs<=i_adrsi; i_adrsi<=i_adrsi+N_BURST; END IF; END IF; - IF i_pushhead='1' AND i_freeze='0' THEN + i_pushhead3<=i_pushhead2; + + IF i_pushhead2='1' AND i_freeze='0' THEN i_wr<='1'; i_wad<=0; - i_write_pre<=NOT i_write; + i_write<=i_write XOR NOT i_freeze; i_walt<='0'; i_adrs<=(OTHERS =>'0'); - i_pushhead<='0'; + i_pushhead2<='0'; + END IF; + IF i_pushhead3='1' THEN + i_wad<=BLEN-1; END IF; -- Delay a bit EOL : Async. AVL/I clocks... - i_eol2<=i_eol; i_eol3<=i_eol2; i_eol4<=i_eol3; + i_eol2<=i_eol; i_eol3<=i_eol2; -- End of line - IF i_eol4='1' AND i_freeze='0' THEN + IF i_eol3='1' AND i_freeze='0' THEN IF (i_wad MOD BLEN)/=BLEN-1 THEN -- Some pixels are in the partially filled buffer i_hbcpt<=(i_hbcpt+1) MOD 32; - i_write_pre<=NOT i_write_pre; - IF i_wad/BLEN=0 THEN - i_walt<='0'; - ELSE - i_walt<='1'; - END IF; - i_adrs<=i_adrsi; + i_write<=i_write XOR NOT i_freeze; + i_walt <=to_std_logic(i_wad/BLEN /= 0); + i_adrs <=i_adrsi; IF i_inter='1' AND i_half='0' THEN -- Skip every other line for interlaced video i_adrsi<=i_adrsi + N_BURST * (i_hburst + 1); @@ -1346,22 +1274,16 @@ BEGIN END IF; END IF; END IF; - i_write<=i_write_pre AND NOT i_freeze; - END IF; END PROCESS; - + -- If downscaling, export to the output part the downscaled size i_hrsize<=i_hsize WHEN i_hdown='0' ELSE i_ohsize; i_vrsize<=i_vsize WHEN i_vdown='0' ELSE i_ovsize; ----------------------------------------------------------------------------- - -- Input Dividers. For downscaling. - - -- Hdiv = 1 / IHsize 1.12 / 12 --> 0.12 + -- Input Divider. For downscaling. -- Vfrac = IVacc / IVsize 12 / 12 --> 12 - - -- Division IDividers:PROCESS (i_clk,i_reset_na) IS BEGIN IF i_reset_na='0' THEN @@ -1370,8 +1292,8 @@ BEGIN --pragma synthesis_on NULL; ELSIF rising_edge(i_clk) THEN - i_vdivi<=to_unsigned(i_vsize,12); - i_vdivr<=to_unsigned(i_vacc*4096,24); + i_vdivi<=to_unsigned(2*i_vsize,13); + i_vdivr<=to_unsigned(i_vacc*4096,25); ------------------------------------------------------ IF i_divstart='1' THEN @@ -1380,19 +1302,19 @@ BEGIN ELSIF i_divrun='1' THEN ---------------------------------------------------- - IF i_divcpt=12 THEN + IF i_divcpt=6 THEN i_divrun<='0'; - i_v_frac<=i_vdivr(10 DOWNTO 0) & NOT i_vdivr(23); + i_v_frac<=i_vdivr(4 DOWNTO 0) & NOT i_vdivr(24) & "000000"; ELSE i_divcpt<=i_divcpt+1; END IF; - IF i_vdivr(23)='0' THEN - i_vdivr(23 DOWNTO 12)<=i_vdivr(22 DOWNTO 11) - i_vdivi; + IF i_vdivr(24)='0' THEN + i_vdivr(24 DOWNTO 12)<=i_vdivr(23 DOWNTO 11) - i_vdivi; ELSE - i_vdivr(23 DOWNTO 12)<=i_vdivr(22 DOWNTO 11) + i_vdivi; + i_vdivr(24 DOWNTO 12)<=i_vdivr(23 DOWNTO 11) + i_vdivi; END IF; - i_vdivr(11 DOWNTO 0)<=i_vdivr(10 DOWNTO 0) & NOT i_vdivr(23); + i_vdivr(11 DOWNTO 0)<=i_vdivr(10 DOWNTO 0) & NOT i_vdivr(24); ---------------------------------------------------- END IF; @@ -1400,8 +1322,7 @@ BEGIN END PROCESS IDividers; ----------------------------------------------------------------------------- - -- DPRAM INPUT - + -- DPRAM Input. Double buffer for RAM bursts. PROCESS (i_clk) IS BEGIN IF rising_edge(i_clk) THEN @@ -1419,10 +1340,11 @@ BEGIN BEGIN IF rising_edge(i_clk) THEN IF i_lwr='1' THEN - i_line(i_lwad)<=i_ldw; + i_line(i_lwad MOD IHRES)<=i_ldw; + END IF; + IF i_pce='1' THEN + i_ldrm<=i_line(i_lrad MOD IHRES); END IF; - - i_ldrm<=i_line(i_lrad); END IF; END PROCESS ILBUF; END GENERATE DownLine; @@ -1444,6 +1366,7 @@ BEGIN avl_write_sync2<=avl_write_sync; avl_write_pulse<=avl_write_sync XOR avl_write_sync2; avl_wadrs <=i_adrs AND (RAMSIZE - 1); -- + avl_wline <=i_wline; -- avl_walt <=i_walt; -- ---------------------------------- @@ -1452,16 +1375,19 @@ BEGIN avl_read_pulse<=avl_read_sync XOR avl_read_sync2; avl_rbib <=o_bib; avl_radrs <=o_adrs AND (RAMSIZE - 1); -- + avl_rline <=o_rline; -- -------------------------------------------- - avl_o_offset<=buf_offset(o_obuf); -- - avl_i_offset<=buf_offset(o_ibuf); -- + avl_o_offset0<=buf_offset(o_obuf0); -- + avl_o_offset1<=buf_offset(o_obuf1); -- + avl_i_offset0<=buf_offset(o_ibuf0); -- + avl_i_offset1<=buf_offset(o_ibuf1); -- avl_o_vs_sync<=o_vsv(0); -- avl_o_vs<=avl_o_vs_sync; -------------------------------------------- - avl_dw<=unsigned(avl_readdata); + avl_dw<=swap(unsigned(avl_readdata)); avl_read_i<='0'; avl_write_i<='0'; @@ -1497,9 +1423,16 @@ BEGIN END IF; WHEN sWRITE => - avl_address<=std_logic_vector(RAMBASE(N_AW+NB_LA-1 DOWNTO NB_LA) + - avl_wadrs(N_AW+NB_LA-1 DOWNTO NB_LA) + - avl_i_offset(N_AW+NB_LA-1 DOWNTO NB_LA)); + IF avl_wline='0' THEN + avl_address<=std_logic_vector(RAMBASE(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_wadrs(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_i_offset0(N_AW+NB_LA-1 DOWNTO NB_LA)); + ELSE + avl_address<=std_logic_vector(RAMBASE(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_wadrs(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_i_offset1(N_AW+NB_LA-1 DOWNTO NB_LA)); + END IF; + avl_write_i<='1'; IF avl_write_i='1' AND avl_waitrequest='0' THEN IF (avl_rad MOD BLEN)=BLEN-1 THEN @@ -1509,9 +1442,15 @@ BEGIN END IF; WHEN sREAD => - avl_address<=std_logic_vector(RAMBASE(N_AW+NB_LA-1 DOWNTO NB_LA) + - avl_radrs(N_AW+NB_LA-1 DOWNTO NB_LA) + - avl_o_offset(N_AW+NB_LA-1 DOWNTO NB_LA)); + IF avl_rline='0' THEN + avl_address<=std_logic_vector(RAMBASE(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_radrs(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_o_offset0(N_AW+NB_LA-1 DOWNTO NB_LA)); + ELSE + avl_address<=std_logic_vector(RAMBASE(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_radrs(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_o_offset1(N_AW+NB_LA-1 DOWNTO NB_LA)); + END IF; avl_read_i<='1'; avl_reading<='1'; IF avl_read_i='1' AND avl_waitrequest='0' THEN @@ -1538,7 +1477,7 @@ BEGIN avl_read<=avl_read_i; avl_write<=avl_write_i; - avl_writedata<=std_logic_vector(avl_dr); + avl_writedata<=std_logic_vector(swap(avl_dr)); avl_burstcount<=std_logic_vector(to_unsigned(BLEN,8)); avl_byteenable<=(OTHERS =>'1'); @@ -1546,7 +1485,7 @@ BEGIN WHEN avl_write_i='1' AND avl_waitrequest='0' ELSE avl_rad; ----------------------------------------------------------------------------- - -- DPRAM OUTPUT + -- DPRAM Output. Double buffer for RAM bursts. PROCESS (avl_clk) IS BEGIN IF rising_edge(avl_clk) THEN @@ -1559,7 +1498,6 @@ BEGIN o_dr<=o_dpram(o_ad3) WHEN rising_edge(o_clk); ----------------------------------------------------------------------------- - -- Output Vertical Divider -- Vfrac = Vacc / Vsize ODivider:PROCESS (o_clk,o_reset_na) IS @@ -1569,8 +1507,8 @@ BEGIN o_vfrac<=x"000"; --pragma synthesis_on ELSIF rising_edge(o_clk) THEN - o_vdivi<=to_unsigned(o_vsize,12); - o_vdivr<=to_unsigned(o_vacc*4096,24); + o_vdivi<=to_unsigned(2*o_vsize,13); + o_vdivr<=to_unsigned(o_vacc*4096,25); ------------------------------------------------------ IF o_divstart='1' THEN o_divcpt<=0; @@ -1580,17 +1518,17 @@ BEGIN ---------------------------------------------------- IF o_divcpt=12 THEN o_divrun<='0'; - o_vfrac<=o_vdivr(10 DOWNTO 0) & NOT o_vdivr(23); + o_vfrac<=o_vdivr(10 DOWNTO 0) & NOT o_vdivr(24); ELSE o_divcpt<=o_divcpt+1; END IF; - IF o_vdivr(23)='0' THEN - o_vdivr(23 DOWNTO 12)<=o_vdivr(22 DOWNTO 11) - o_vdivi; + IF o_vdivr(24)='0' THEN + o_vdivr(24 DOWNTO 12)<=o_vdivr(23 DOWNTO 11) - o_vdivi; ELSE - o_vdivr(23 DOWNTO 12)<=o_vdivr(22 DOWNTO 11) + o_vdivi; + o_vdivr(24 DOWNTO 12)<=o_vdivr(23 DOWNTO 11) + o_vdivi; END IF; - o_vdivr(11 DOWNTO 0)<=o_vdivr(10 DOWNTO 0) & NOT o_vdivr(23); + o_vdivr(11 DOWNTO 0)<=o_vdivr(10 DOWNTO 0) & NOT o_vdivr(24); ---------------------------------------------------- END IF; END IF; @@ -1598,12 +1536,11 @@ BEGIN ----------------------------------------------------------------------------- Scalaire:PROCESS (o_clk,o_reset_na) IS - VARIABLE mul_v : unsigned(47 DOWNTO 0); VARIABLE lev_inc_v,lev_dec_v : std_logic; VARIABLE prim_v,last_v,bib_v : std_logic; VARIABLE shift_v : unsigned(0 TO N_DW+15); VARIABLE hcarry_v,vcarry_v : boolean; - VARIABLE dif_v : natural RANGE 0 TO 4*OHRES-1; + VARIABLE dif_v : natural RANGE 0 TO 8*OHRES-1; BEGIN IF o_reset_na='0' THEN o_copy<='0'; @@ -1637,29 +1574,47 @@ BEGIN -------------------------------------------- -- Triple buffering. + -- For intelaced video, half frames are updated independently -- Input : Toggle buffer at end of input frame - o_iendframe<=i_endframe; -- - o_iendframe2<=o_iendframe; - IF o_iendframe='1' AND o_iendframe2='0' THEN - o_ibuf<=buf_next(o_ibuf,o_obuf); - o_bufup<='1'; + o_inter <=i_inter; -- + o_iendframe0<=i_endframe0; -- + o_iendframe02<=o_iendframe0; + IF o_iendframe0='1' AND o_iendframe02='0' THEN + o_ibuf0<=buf_next(o_ibuf0,o_obuf0); + o_bufup0<='1'; + END IF; + o_iendframe1<=i_endframe1; -- + o_iendframe12<=o_iendframe1; + IF o_iendframe1='1' AND o_iendframe12='0' THEN + o_ibuf1<=buf_next(o_ibuf1,o_obuf1); + o_bufup1<='1'; END IF; - -- Output : Change framebuffer, and image properties, at VS falling edge - IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup='1' THEN - o_obuf<=buf_next(o_obuf,o_ibuf); - o_bufup<='0'; + IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup1='1' THEN + o_obuf1<=buf_next(o_obuf1,o_ibuf1); + o_bufup1<='0'; o_hburst <=i_hburst; -- Bursts per line o_ihsize<=i_hrsize; -- o_ivsize<=i_vrsize; -- o_hdown<=i_hdown; -- o_vdown<=i_vdown; -- END IF; + IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN + o_obuf0<=buf_next(o_obuf0,o_ibuf0); + o_bufup0<='0'; + END IF; + + IF o_inter='0' THEN + o_ibuf1<=o_ibuf0; + o_obuf1<=o_obuf0; + END IF; -- Triple buffer disabled IF o_mode(3)='0' THEN - o_obuf<=0; - o_ibuf<=0; + o_obuf0<=0; + o_obuf1<=0; + o_ibuf0<=0; + o_ibuf1<=0; END IF; ------------------------------------------------------ @@ -1701,8 +1656,8 @@ BEGIN o_divstart<='0'; o_adrsa<='0'; - o_vacc_ini<=(o_vsize/2 - o_ivsize/2 + 4096) MOD 4096; - o_hacc_ini<=o_hsize/2 + o_ihsize/2; + o_vacc_ini<=(o_vsize - o_ivsize + 8192) MOD 8192; + o_hacc_ini<=(o_hsize + o_ihsize + 8192) MOD 8192; CASE o_state IS -------------------------------------------------- @@ -1714,20 +1669,20 @@ BEGIN -------------------------------------------------- WHEN sHSYNC => - dif_v:=(o_vacc_next - o_vsize + 8192) MOD 8192; - IF dif_v>=4096 THEN + dif_v:=(o_vacc_next - 2*o_vsize + 16384) MOD 16384; + IF dif_v>=8192 THEN o_vacc <=o_vacc_next; - o_vacc_next<=(o_vacc_next + o_ivsize) MOD 4096; + o_vacc_next<=(o_vacc_next + 2*o_ivsize) MOD 8192; vcarry_v:=false; ELSE o_vacc <=dif_v; - o_vacc_next<=(dif_v + o_ivsize + 4096) MOD 4096; + o_vacc_next<=(dif_v + 2*o_ivsize + 8192) MOD 8192; vcarry_v:=true; END IF; o_divstart<='1'; IF o_vcpt_pre2=o_vmin THEN --pe='0' THEN o_vacc <=o_vacc_ini; - o_vacc_next<=o_vacc_ini + o_ivsize; + o_vacc_next<=o_vacc_ini + 2*o_ivsize; o_vacpt<=x"001"; vcarry_v:=false; END IF; @@ -1776,6 +1731,7 @@ BEGIN o_read<=o_read_pre AND o_run; o_adrs_pre<=to_integer(o_vacpt) * o_hburst; + o_rline<=o_vacpt(0); -- Even/Odd line for interlaced video IF o_adrsa='1' THEN IF HEADER THEN IF o_fload=2 THEN @@ -1816,14 +1772,10 @@ BEGIN -- First memcopy of a horizontal line, carriage return ! -- HPOS starts at 1 for the first input image pix,to keep it positive o_hacc <=o_hacc_ini; - o_hacc_next<=o_hacc_ini + o_ihsize; + o_hacc_next<=o_hacc_ini + 2*o_ihsize; o_hacpt <=x"000"; o_dcpt<=0; - IF o_hsize=o_ihsize THEN - o_dshi<=3; - ELSE - o_dshi<=2; - END IF; + o_dshi<=2; o_acpt<=0; o_first<='1'; o_last<='0'; @@ -1837,14 +1789,14 @@ BEGIN ELSE -- dshi : Force shift first two or three pixels of each line IF o_dshi=0 THEN - dif_v:=(o_hacc_next - o_hsize + (4*OHRES)) MOD (4*OHRES); - IF dif_v>=2*OHRES THEN + dif_v:=(o_hacc_next - 2*o_hsize + (8*OHRES)) MOD (8*OHRES); + IF dif_v>=4*OHRES THEN o_hacc<=o_hacc_next; - o_hacc_next<=o_hacc_next + o_ihsize; + o_hacc_next<=o_hacc_next + 2*o_ihsize; hcarry_v:=false; ELSE o_hacc<=dif_v; - o_hacc_next<=(dif_v + o_ihsize + (2*OHRES)) MOD (2*OHRES); + o_hacc_next<=(dif_v + 2*o_ihsize + (4*OHRES)) MOD (4*OHRES); hcarry_v:=true; END IF; o_dcpt<=(o_dcpt+1) MOD 4096; @@ -1956,11 +1908,11 @@ BEGIN o_h_poly_a<=to_integer(o_hfrac(11 DOWNTO 12-FRAC)); o_v_poly_a<=to_integer(o_vfrac(11 DOWNTO 12-FRAC)); - ----------------------------------------------------------------------------- - -- Polyphase ROMs o_h_poly_dr<=o_h_poly(o_h_poly_a) WHEN rising_edge(o_clk); o_v_poly_dr<=o_v_poly(o_v_poly_a) WHEN rising_edge(o_clk); + ----------------------------------------------------------------------------- + -- Polyphase ROMs Polikarpov:PROCESS(poly_clk) IS BEGIN IF rising_edge(poly_clk) THEN @@ -1985,7 +1937,7 @@ BEGIN ----------------------------------------------------------------------------- -- Horizontal Scaler HSCAL:PROCESS(o_clk) IS - VARIABLE div_v : unsigned(17 DOWNTO 0); + VARIABLE div_v : unsigned(18 DOWNTO 0); VARIABLE dir_v : unsigned(11 DOWNTO 0); BEGIN IF rising_edge(o_clk) THEN @@ -1993,35 +1945,35 @@ BEGIN ----------------------------------- -- Pipelined 6 bits non-restoring divider. Cycle 1 dir_v:=x"000"; - div_v:=to_unsigned(o_hacc * 64,18); + div_v:=to_unsigned(o_hacc * 64,19); - div_v:=div_v-to_unsigned(o_hsize*32,18); - dir_v(11):=NOT div_v(17); - IF div_v(17)='0' THEN - div_v:=div_v-to_unsigned(o_hsize*16,18); + div_v:=div_v-to_unsigned(o_hsize*64,19); + dir_v(11):=NOT div_v(18); + IF div_v(18)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*32,19); ELSE - div_v:=div_v+to_unsigned(o_hsize*16,18); + div_v:=div_v+to_unsigned(o_hsize*32,19); END IF; - dir_v(10):=NOT div_v(17); + dir_v(10):=NOT div_v(18); o_div<=div_v; o_dir<=dir_v; -- Cycle 2 div_v:=o_div; dir_v:=o_dir; - IF div_v(17)='0' THEN - div_v:=div_v-to_unsigned(o_hsize*8,18); + IF div_v(18)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*16,19); ELSE - div_v:=div_v+to_unsigned(o_hsize*8,18); + div_v:=div_v+to_unsigned(o_hsize*16,19); END IF; - dir_v( 9):=NOT div_v(17); + dir_v( 9):=NOT div_v(18); - IF div_v(17)='0' THEN - div_v:=div_v-to_unsigned(o_hsize*4,18); + IF div_v(18)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*8,19); ELSE - div_v:=div_v+to_unsigned(o_hsize*4,18); + div_v:=div_v+to_unsigned(o_hsize*8,19); END IF; - dir_v(8):=NOT div_v(17); + dir_v(8):=NOT div_v(18); o_div2<=div_v; o_dir2<=dir_v; @@ -2029,18 +1981,18 @@ BEGIN div_v:=o_div2; dir_v:=o_dir2; IF FRAC>4 THEN - IF div_v(17)='0' THEN - div_v:=div_v-to_unsigned(o_hsize*2,18); + IF div_v(18)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*4,19); ELSE - div_v:=div_v+to_unsigned(o_hsize*2,18); + div_v:=div_v+to_unsigned(o_hsize*4,19); END IF; - dir_v(7):=NOT div_v(17); - IF div_v(17)='0' THEN - div_v:=div_v-to_unsigned(o_hsize,18); + dir_v(7):=NOT div_v(18); + IF div_v(18)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*2,19); ELSE - div_v:=div_v+to_unsigned(o_hsize,18); + div_v:=div_v+to_unsigned(o_hsize*2,19); END IF; - dir_v(6):=NOT div_v(17); + dir_v(6):=NOT div_v(18); END IF; ----------------------------------- @@ -2191,7 +2143,6 @@ BEGIN (o_vcpt=o_vsend AND o_hcpt - o_isyncline2<=o_isyncline; - - IF SYNCHRO THEN - -- Measure input image size - IF o_isyncline2='1' AND o_isyncline='0' THEN - o_llicpt<=0; - o_llipos<=o_llocpt; - o_llisize<=o_llicpt; - o_llfl<=i_pfl; -- - ELSE - o_llicpt<=o_llicpt+1; - END IF; - - -- Measure output image size - IF o_vss='1' AND o_vss1='0' THEN - o_llocpt<=0; - o_llup<='1'; - o_llosize<=o_llocpt; - ELSE - o_llocpt<=o_llocpt+1; - o_llup<='0'; - END IF; - - -- Period difference between input and output images - o_lldiff<=(integer(o_llosize) - integer(o_llisize)); - - 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; - o_llssh<=o_llosize; - o_llos<='0'; - o_llop<='0'; - - ELSIF o_llcpt<24 THEN - -- Frequency difference - IF o_lldiff>0 AND o_llssh=o_llosize/2 AND o_llssh<(o_llosize-o_llipos) AND o_llop='0' THEN - o_lltune_i(13 DOWNTO 8)<='1' & to_unsigned(o_llcpt,5); - o_llop<='1'; - END IF; - o_llssh<=o_llssh/2; - o_llcpt<=o_llcpt+1; - - ELSIF o_llcpt=24 THEN - o_lltune_i(15)<=NOT o_lltune_i(15); - o_llcpt<=o_llcpt+1; - END IF; - END IF; END IF; END IF; END PROCESS OSWEEP; - - o_lltune<=o_lltune_i; + ----------------------------------------------------------------------------- -- Vertical Scaler VSCAL:PROCESS(o_clk) IS @@ -2400,126 +2287,26 @@ BEGIN o_b<=x"00"; END IF; ---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 - ---------------------------------------------------- END IF; END IF; END PROCESS VSCAL; ---pragma synthesis_off ----------------------------------------------------------------------------- - -- DEBUG - Debug:PROCESS(o_clk) IS - TYPE arr_uv8 IS ARRAY (natural RANGE <>) OF unsigned(7 DOWNTO 0); - CONSTANT CHARS : arr_uv8 :=( - x"3E", x"63", x"73", x"7B", x"6F", x"67", x"3E", x"00", -- 0 - x"0C", x"0E", x"0C", x"0C", x"0C", x"0C", x"3F", x"00", -- 1 - x"1E", x"33", x"30", x"1C", x"06", x"33", x"3F", x"00", -- 2 - x"1E", x"33", x"30", x"1C", x"30", x"33", x"1E", x"00", -- 3 - x"38", x"3C", x"36", x"33", x"7F", x"30", x"78", x"00", -- 4 - x"3F", x"03", x"1F", x"30", x"30", x"33", x"1E", x"00", -- 5 - x"1C", x"06", x"03", x"1F", x"33", x"33", x"1E", x"00", -- 6 - x"3F", x"33", x"30", x"18", x"0C", x"0C", x"0C", x"00", -- 7 - x"1E", x"33", x"33", x"1E", x"33", x"33", x"1E", x"00", -- 8 - x"1E", x"33", x"33", x"3E", x"30", x"18", x"0E", x"00", -- 9 - x"0C", x"1E", x"33", x"33", x"3F", x"33", x"33", x"00", -- A - x"3F", x"66", x"66", x"3E", x"66", x"66", x"3F", x"00", -- B - x"3C", x"66", x"03", x"03", x"03", x"66", x"3C", x"00", -- C - x"1F", x"36", x"66", x"66", x"66", x"36", x"1F", x"00", -- D - x"7F", x"46", x"16", x"1E", x"16", x"46", x"7F", x"00", -- E - x"7F", x"46", x"16", x"1E", x"16", x"06", x"0F", x"00", -- F - x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", --' ' 10 - x"00", x"00", x"3F", x"00", x"00", x"3F", x"00", x"00", -- = 11 - x"00", x"0C", x"0C", x"3F", x"0C", x"0C", x"00", x"00", -- + 12 - x"00", x"00", x"00", x"3F", x"00", x"00", x"00", x"00", -- - 13 - x"18", x"0C", x"06", x"03", x"06", x"0C", x"18", x"00", -- < 14 - x"06", x"0C", x"18", x"30", x"18", x"0C", x"06", x"00", -- > 15 - x"08", x"1C", x"36", x"63", x"41", x"00", x"00", x"00", -- ^ 16 - x"08", x"1C", x"36", x"63", x"41", x"00", x"00", x"00", -- v 17 - x"18", x"0C", x"06", x"06", x"06", x"0C", x"18", x"00", -- ( 18 - x"06", x"0C", x"18", x"18", x"18", x"0C", x"06", x"00", -- ) 19 - x"00", x"0C", x"0C", x"00", x"00", x"0C", x"0C", x"00", -- : 1A - x"00", x"00", x"00", x"00", x"00", x"0C", x"0C", x"00", -- . 1B - x"00", x"00", x"00", x"00", x"00", x"0C", x"0C", x"06", -- , 1C - x"1E", x"33", x"30", x"18", x"0C", x"00", x"0C", x"00", -- ? 1D - x"18", x"18", x"18", x"00", x"18", x"18", x"18", x"00", -- | 1E - x"36", x"36", x"7F", x"36", x"7F", x"36", x"36", x"00"); -- # 1F - - VARIABLE vin_v : unsigned(0 TO 32*5-1); - BEGIN - IF rising_edge(o_clk) THEN - IF o_ce='1' THEN - o_debug_hcpt2<=o_hcpt; - o_debug_hcpt3<=o_debug_hcpt2; - o_debug_hcpt4<=o_debug_hcpt3; - o_debug_hcpt5<=o_debug_hcpt4; - o_debug_hcpt6<=o_debug_hcpt5; - IF (o_vcpt/8) MOD 2=0 THEN - vin_v:=o_debug_vin0; - ELSE - vin_v:=o_debug_vin1; - END IF; - o_debug_hchar<=((o_debug_hcpt2/8)*5) MOD 256; - IF o_debug_hcpt3<32 * 8 AND o_vcpt<2 * 8 THEN - o_debug_char<=vin_v(o_debug_hchar TO o_debug_hchar+4); - ELSE - o_debug_char<="10000"; -- " " : Blank character - END IF; - - o_debug_col<=CHARS(to_integer(o_debug_char)*8+(o_vcpt MOD 8)); - - IF o_debug_col(o_debug_hcpt6 MOD 8)='1' THEN - o_debug_set<='1'; - ELSE - o_debug_set<='0'; - END IF; - END IF; - END IF; - END PROCESS Debug; - - ---------------------------------------------------------- - o_debug_vin0<= - CN(to_unsigned(i_himax ,12)) & -- 3 - CC(' ') & - CN(to_unsigned(i_hsstart,12)) & -- 3 - CC(' ') & - CN(to_unsigned(i_hsend ,12)) & -- 3 - CC(' ') & - CN(to_unsigned(i_htotal ,12)) & -- 3 - "1001" & NOT i_inter & - CN(to_unsigned(i_vimax ,12)) & -- 3 - CC(' ') & - CN(to_unsigned(i_vsstart,12)) & -- 3 - CC(' ') & - CN(to_unsigned(i_vsend ,12)) & -- 3 - CC(' ') & - CN(to_unsigned(i_vtotal ,12)) & -- 3 - CC(' '); - - o_debug_vin1<= - "0000" & i_inter & -- 1 - CC(' ') & -- 1 - CN(to_unsigned(o_lldiff,24)) & -- 6 - CC(' ') & -- 1 - CN(to_unsigned(o_llipos,24)) & -- 6 - CC(' ') & -- 1 - "0000" & o_lltune_i(15) & -- 1 - CC(' ') & -- 1 - "00" & o_lltune_i(14 DOWNTO 12) & -- 1 - '0' & o_lltune_i(11 DOWNTO 8) & -- 1 - '0' & o_lltune_i(7 DOWNTO 4) & -- 1 - '0' & o_lltune_i(3 DOWNTO 0) & -- 1 - CS(" "); + -- Low Lag syntoniser interface + -- i_syncline falling edge shall be aligned with o_vss raising edge. + + o_lltune<=(0 => NOT i_syncline, + 1 => '0', + 2 => i_inter, + 3 => i_flm, + 4 => o_vss, + 5 => '0', + 6 => i_clk, + 7 => o_clk, + OTHERS =>'0'); + ---------------------------------------------------------------------------- ---pragma synthesis_on - END ARCHITECTURE rtl; diff --git a/sys/pll_hdmi_adj.vhd b/sys/pll_hdmi_adj.vhd index feea1a0..01d6497 100644 --- a/sys/pll_hdmi_adj.vhd +++ b/sys/pll_hdmi_adj.vhd @@ -5,14 +5,15 @@ -- 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) - +-- 0 : Input Syncline +-- 1 : +-- 2 : Input Interlaced mode +-- 3 : Input Interlaced field +-- 4 : Output Syncline +-- 5 : +-- 6 : Input clock +-- 7 : Output clock + LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.numeric_std.ALL; @@ -23,6 +24,8 @@ ENTITY pll_hdmi_adj IS llena : IN std_logic; -- 0=Disabled 1=Enabled lltune : IN unsigned(15 DOWNTO 0); -- Outputs from scaler + locked : OUT std_logic; + -- Signals from reconfig commands i_waitrequest : OUT std_logic; i_write : IN std_logic; @@ -51,24 +54,115 @@ 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); + TYPE enum_state IS (sIDLE,sW1,sW2,sW3,sW4,sW5,sW6); SIGNAL state : enum_state; + SIGNAL tune_freq,tune_phase : unsigned(5 DOWNTO 0); SIGNAL lltune_sync,lltune_sync2,lltune_sync3 : unsigned(15 DOWNTO 0); - SIGNAL mfrac,mfrac_mem : unsigned(31 DOWNTO 0); + SIGNAL mfrac,mfrac_mem,mfrac_ref,diff : unsigned(40 DOWNTO 0); + SIGNAL mul : unsigned(15 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; + SIGNAL cpt : natural RANGE 0 TO 3; + SIGNAL col : natural RANGE 0 TO 15; + + SIGNAL icpt,ocpt,ssh : natural RANGE 0 TO 2**24-1; + SIGNAL isync,isync2,itog,ipulse : std_logic; + SIGNAL osync,osync2,otog,opulse : std_logic; + SIGNAL sync,pulse,los,lop : std_logic; + SIGNAL osize,isize,offset,osizep : signed(23 DOWNTO 0); + SIGNAL logcpt : natural RANGE 0 TO 31; + SIGNAL udiff : integer RANGE -2**23 TO 2**23-1 :=0; + BEGIN ---------------------------------------------------------------------------- + -- Sample image sizes + Sampler:PROCESS(clk,reset_na) IS + BEGIN + IF reset_na='0' THEN +--pragma synthesis_off + otog<='0'; + itog<='0'; + isync<='0'; + isync2<='0'; + osync<='0'; + osync2<='0'; +--pragma synthesis_on + + ELSIF rising_edge(clk) THEN + -- Clock domain crossing + isync<=lltune(0); -- + isync2<=isync; + osync<=lltune(4); -- + osync2<=osync; + + itog<=itog XOR (isync AND NOT isync2); + otog<=otog XOR (osync AND NOT osync2); + + ipulse<=isync AND NOT isync2 AND itog; + opulse<=osync AND NOT osync2 AND otog; + + -- Measure output image size + IF osync='1' AND osync2='0' AND otog='1' THEN + ocpt<=0; + osizep<=to_signed(ocpt,24); + ELSE + ocpt<=ocpt+1; + END IF; + + -- Measure input image size + IF isync='1' AND isync2='0' AND itog='1' THEN + icpt<=0; + isize<=to_signed(icpt,24); + osize<=osizep; + offset<=to_signed(ocpt,24); + udiff<=integer(to_integer(osizep)) - integer(icpt); + sync<='1'; + ELSE + icpt<=icpt+1; + sync<='0'; + END IF; + + -------------------------------------------- + pulse<='0'; + IF sync='1' THEN + logcpt<=0; + ssh<=to_integer(osize); + los<='0'; + lop<='0'; + + ELSIF logcpt<24 THEN + -- Frequency difference + IF udiff>0 AND ssh=osize/2 AND ssh<(osize-offset) AND lop='0' THEN + tune_phase<='1' & to_unsigned(logcpt,5); + lop<='1'; + END IF; + ssh<=ssh/2; + logcpt<=logcpt+1; + + ELSIF logcpt=24 THEN + pulse<='1'; + ssh<=ssh/2; + logcpt<=logcpt+1; + END IF; + + END IF; + END PROCESS Sampler; + + ---------------------------------------------------------------------------- -- 000010 : Start reg "Write either 0 or 1 to start fractional PLL reconf. - -- 000111 : M counter Fractional Value + -- 000100 : M counter + -- 000111 : M counter Fractional Value K Comb:PROCESS(i_write,i_address, i_writedata,pwrite,paddress,pdata) IS @@ -88,141 +182,169 @@ BEGIN ---------------------------------------------------------------------------- Schmurtz:PROCESS(clk,reset_na) IS - VARIABLE off,ofp : natural RANGE 0 TO 63; - VARIABLE dif : unsigned(31 DOWNTO 0); + VARIABLE off_v,ofp_v : natural RANGE 0 TO 63; + VARIABLE diff_v : unsigned(40 DOWNTO 0); + VARIABLE mulco : unsigned(15 DOWNTO 0); + VARIABLE up_v,sign_v : std_logic; 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; + ------------------------------------------------------ + -- Snoop accesses to PLL reconfiguration + IF i_address="000100" AND i_write='1' THEN + mfrac (40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + + ('0' & i_writedata(7 DOWNTO 0)); + mfrac_ref(40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + + ('0' & i_writedata(7 DOWNTO 0)); + mfrac_mem(40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + + ('0' & i_writedata(7 DOWNTO 0)); + mul<=i_writedata(15 DOWNTO 0); 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; + IF i_address="000111" AND i_write='1' THEN + mfrac (31 DOWNTO 0)<=i_writedata; + mfrac_ref(31 DOWNTO 0)<=i_writedata; + mfrac_mem(31 DOWNTO 0)<=i_writedata; + modo<='1'; 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; ------------------------------------------------------ + -- Tuning + off_v:=to_integer('0' & tune_freq(4 DOWNTO 0)); + ofp_v:=to_integer('0' & tune_phase(4 DOWNTO 0)); + --IF off_v<8 THEN off_v:=8; END IF; + --IF ofp_v<7 THEN ofp_v:=7; END IF; + IF off_v<4 THEN off_v:=4; END IF; + IF ofp_v<4 THEN ofp_v:=4; END IF; + + IF off_v>=18 AND ofp_v>=18 THEN + locked<=llena; + ELSE + locked<='0'; + END IF; + + up_v:='0'; + IF pulse='1' THEN + cpt<=(cpt+1) MOD 4; + IF llena='0' THEN + -- Recover original freq when disabling low lag mode + cpt<=0; + col<=0; + IF modo='1' THEN + mfrac<=mfrac_mem; + mfrac_ref<=mfrac_mem; + up<='1'; + modo<='0'; + END IF; + + ELSIF phm='0' AND cpt=0 THEN + -- Frequency adjust + sign_v:=tune_freq(5); + IF col<10 THEN col<=col+1; END IF; + IF off_v>=16 AND col>=10 THEN + phm<='1'; + col<=0; + ELSE + off_v:=off_v+1; + IF off_v>17 THEN + off_v:=off_v + 3; + END IF; + up_v:='1'; + up<='1'; + END IF; + + ELSIF cpt=0 THEN + -- Phase adjust + sign_v:=NOT tune_phase(5); + col<=col+1; + IF col>=10 THEN + phm<='0'; + up_v:='1'; + off_v:=31; + col<=0; + ELSE + off_v:=ofp_v + 1; + IF ofp_v>7 THEN + off_v:=off_v + 1; + END IF; + IF ofp_v>14 THEN + off_v:=off_v + 2; + END IF; + IF ofp_v>17 THEN + off_v:=off_v + 3; + END IF; + up_v:='1'; + END IF; + up<='1'; + END IF; + END IF; + + diff_v:=shift_right(mfrac_ref,off_v); + IF sign_v='0' THEN + diff_v:=mfrac_ref + diff_v; + ELSE + diff_v:=mfrac_ref - diff_v; + END IF; + + IF up_v='1' THEN + mfrac<=diff_v; + END IF; + + IF up_v='1' AND phm='0' THEN + mfrac_ref<=diff_v; + END IF; + + ------------------------------------------------------ + -- Update PLL registers + mulco:=mfrac(40 DOWNTO 33) & (mfrac(40 DOWNTO 33) + ('0' & mfrac(32))); + CASE state IS WHEN sIDLE => pwrite<='0'; IF up='1' THEN up<='0'; - state<=sW1; - pdata<=mfrac; - paddress<="000111"; - pwrite<='1'; + IF mulco/=mul THEN + state<=sW1; + ELSE + state<=sW3; + END IF; END IF; - WHEN sW1 => + WHEN sW1 => -- Change M multiplier + mul<=mulco; + pdata<=x"0000" & mulco; + paddress<="000100"; + pwrite<='1'; + state<=sW2; + + WHEN sW2 => IF pwrite='1' AND o_waitrequest='0' THEN - state<=sW2; + state<=sW3; pwrite<='0'; END IF; - WHEN sW2 => + WHEN sW3 => -- Change M fractional value + pdata<=mfrac(31 DOWNTO 0); + paddress<="000111"; + pwrite<='1'; + state<=sW4; + + WHEN sW4 => + IF pwrite='1' AND o_waitrequest='0' THEN + state<=sW5; + pwrite<='0'; + END IF; + + WHEN sW5 => pdata<=x"0000_0001"; paddress<="000010"; pwrite<='1'; - state<=sW3; + state<=sW6; - WHEN sW3 => + WHEN sW6 => IF pwrite='1' AND o_waitrequest='0' THEN pwrite<='0'; state<=sIDLE; @@ -233,7 +355,6 @@ BEGIN END PROCESS Schmurtz; ---------------------------------------------------------------------------- - END ARCHITECTURE rtl;