-------------------------------------------------------------------------------- -- AVALON SCALER -------------------------------------------------------------------------------- -- TEMLIB 10/2018 -------------------------------------------------------------------------------- -- This code can be used for any purpose, but, if you find any bug, or want to -- suggest an enhancement, you ought to send a mail to info@temlib.org -------------------------------------------------------------------------------- -- Features : -- - Arbitrary output video format -- - Autodetect input image size or fixed window -- - Progressive and interleaved frames -- - Interpolation -- Upscaling : Nearest, Bilinear, Bicubic, Polyphase, Sharp Bilinear -- Downscaling : Nearest, Bilinear -- - Avalon bus interface with 128 or 64 bits DATA -- - Optional triple buffering -- - -- AFAIRE: -- - Configurable colour depth -- - 64bits/32 bits Avalon -- - Sync. pol. detect -- - Border colour -- - run/stop -- - better rounding (linear) -- - Downscaling -- - -------------------------------------------- -- 4 clock domains -- i_xxx : Input video -- o_xxx : Output video -- avl_xxx : Avalon memory bus -- poly_xxx : Polyphase filters memory -------------------------------------------- -- Mode 24bits -------------------------------------------- -- Image header. When HEADER = TRUE -- Header Address = RAMBASE -- Image Address = RAMBASE + HEADER_SIZE -- Header (Bytes. Big Endian.) -- 0 : Type = 1 -- 1 : Pixel format -- 1 : 24 bits/pixel, packed RGB. Big Endian -- 3:2 : Header size : Offset to start of picture -- = N_BURST -- 5:4 : Attributes. TBD -- 7:6 : Image width. Pixels. -- 9:8 : Image heigth. Pixels. -- 11:10 : Line length. Bytes. -- 13:12 : TBD. -- 15:14 : TBD. -------------------------------------------- LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.numeric_std.ALL; -- MODE[2:0] -- 000 : Nearest -- 001 : Bilinear -- 010 : Sharp Bilinear -- 011 : Bicubic -- 100 : Polyphase 1 -- 101 : Polyphase 2 -- 110 : Polyphase 3 -- 111 : TEST -- MODE[3] -- 0 : Direct. Single framebuffer. -- 1 : Triple buffering -- MODE[4] -- 0 : Normal -- 1 : Low Latency mode. Output vertical frequency locked on input signal. -- MASK : Enable / Disable selected interpoler (0)=Nearest (1)=Bilinear -- RAMBASE : RAM base address for framebuffer -- RAMSIZE : RAM allocated for one framebuffer (needs x3 if triple-buffering) -- Must be a power of two -- RO : True = Read Only. Another block updates the framebuffer -- INTER : True=Autodetect interleaved 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 -- FRAC : Fractional bits, subpixel resolution -- NPOLY : Number of polyphase filters stored -- FORMAT : TBD -- N_DW : Avalon data bus width -- N_AW : Avalon address bus width -- N_BURST : Burst size in bytes. Power of two. -- OHRES : Max. output resolution. Must be a power of two -- IHRES : Max. input resolution. Must be a power of two ENTITY ascal IS GENERIC ( MASK : unsigned(0 TO 7) :=x"FF"; RAMBASE : unsigned(31 DOWNTO 0); RAMSIZE : unsigned(31 DOWNTO 0) := x"0080_0000"; -- =8MB RO : boolean := false; INTER : boolean := true; HEADER : boolean := true; --false; SYNCHRO : boolean := true; DOWNSCALE : boolean := true; FRAC : natural RANGE 4 TO 6 :=4; NPOLY : natural RANGE 0 TO 2 :=2; FORMAT : natural RANGE 1 TO 8 :=8; OHRES : natural RANGE 1 TO 2048 :=2048; IHRES : natural RANGE 1 TO 2048 :=2048; N_DW : natural RANGE 32 TO 128 := 128; N_AW : natural RANGE 8 TO 32 := 32; N_BURST : natural := 256 -- 256 bytes per burst ); PORT ( ------------------------------------ -- Input video i_r : IN unsigned(7 DOWNTO 0); i_g : IN unsigned(7 DOWNTO 0); i_b : IN unsigned(7 DOWNTO 0); i_hs : IN std_logic; -- Horizontal sync i_vs : IN std_logic; -- Vertical sync i_fl : IN std_logic; -- Interlaced field i_de : IN std_logic; -- Display Enable i_ce : IN std_logic; -- Clock Enable i_clk : IN std_logic; -- Input clock ------------------------------------ -- Output video o_r : OUT unsigned(7 DOWNTO 0); o_g : OUT unsigned(7 DOWNTO 0); o_b : OUT unsigned(7 DOWNTO 0); o_hs : OUT std_logic; -- H sychro o_vs : OUT std_logic; -- V sychro o_de : OUT std_logic; -- Display Enable o_ce : IN std_logic; -- Clock Enable o_clk : IN std_logic; -- Output clock ------------------------------------ -- Input video parameters iauto : IN std_logic; -- 1=Autodetect image size 0=Choose window himin : IN natural RANGE 0 TO 4095; himax : IN natural RANGE 0 TO 4095; vimin : IN natural RANGE 0 TO 4095; vimax : IN natural RANGE 0 TO 4095; -- Output video parameters run : IN std_logic; mode : IN unsigned(4 DOWNTO 0); -- SYNC |________________________/"""""""""\______| -- DE |""""""""""""""""""\______________________| -- RGB | <#IMAGE#> ^HDISP | -- ^HMIN ^HMAX ^HSSTART ^HSEND ^HTOTAL htotal : IN natural RANGE 0 TO 4095; hsstart : IN natural RANGE 0 TO 4095; hsend : IN natural RANGE 0 TO 4095; hdisp : IN natural RANGE 0 TO 4095; hmin : IN natural RANGE 0 TO 4095; hmax : IN natural RANGE 0 TO 4095; vtotal : IN natural RANGE 0 TO 4095; vsstart : IN natural RANGE 0 TO 4095; vsend : IN natural RANGE 0 TO 4095; vdisp : IN natural RANGE 0 TO 4095; vmin : IN natural RANGE 0 TO 4095; vmax : IN natural RANGE 0 TO 4095; ------------------------------------ -- Polyphase filter coefficients poly_clk : IN std_logic; poly_dw : IN unsigned(8 DOWNTO 0); poly_a : IN unsigned(NPOLY+FRAC+2 DOWNTO 0); poly_wr : IN std_logic; -- Order : -- [Filter 0] [Filter 1] -- [Horizontal] [Vertical] -- [0]...[2**FRAC-1] -- [-1][0][1][2] ------------------------------------ -- Avalon avl_clk : IN std_logic; -- Avalon clock avl_waitrequest : IN std_logic; avl_readdata : IN std_logic_vector(N_DW-1 DOWNTO 0); avl_readdatavalid : IN std_logic; avl_burstcount : OUT std_logic_vector(7 DOWNTO 0); avl_writedata : OUT std_logic_vector(N_DW-1 DOWNTO 0); avl_address : OUT std_logic_vector(N_AW-1 DOWNTO 0); avl_write : OUT std_logic; avl_read : OUT std_logic; avl_byteenable : OUT std_logic_vector(N_DW/8-1 DOWNTO 0); ------------------------------------ reset_na : IN std_logic ); BEGIN ASSERT N_DW=32 OR N_DW=64 OR N_DW=128 REPORT "DW" SEVERITY failure; END ENTITY ascal; --############################################################################## ARCHITECTURE rtl OF ascal IS ---------------------------------------------------------- FUNCTION ilog2 (CONSTANT v : natural) RETURN natural IS VARIABLE r : natural := 1; VARIABLE n : natural := 0; BEGIN WHILE v>r LOOP n:=n+1; r:=r*2; END LOOP; RETURN n; END FUNCTION ilog2; FUNCTION to_std_logic (a : boolean) RETURN std_logic IS BEGIN IF a THEN RETURN '1'; ELSE RETURN '0'; END IF; END FUNCTION to_std_logic; ---------------------------------------------------------- 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 NP : natural :=24; ---------------------------------------------------------- TYPE arr_dw IS ARRAY (natural RANGE <>) OF unsigned(N_DW-1 DOWNTO 0); TYPE type_pix IS RECORD r,g,b : unsigned(7 DOWNTO 0); -- 0.8 END RECORD; TYPE arr_pix IS ARRAY (natural RANGE <>) OF type_pix; ATTRIBUTE ramstyle : string; ---------------------------------------------------------- -- Input image -- IHSIZE=IHMAX-IHMIN SIGNAL i_run : std_logic; SIGNAL i_hsize,i_hmin,i_hmax,i_hcpt : natural RANGE 0 TO 4095; SIGNAL i_hrsize,i_vrsize : natural RANGE 0 TO 4095; SIGNAL i_chmin,i_chmax,i_cvmin,i_cvmax : natural RANGE 0 TO 4095; SIGNAL i_vsize,i_vmin,i_vmax,i_vmaxc,i_vcpt : natural RANGE 0 TO 4095; SIGNAL i_vminset : std_logic; SIGNAL i_iauto : std_logic; SIGNAL i_ven : std_logic; SIGNAL i_wr : std_logic; SIGNAL i_de_pre,i_hs_pre,i_vs_pre,i_fl_pre : std_logic; SIGNAL i_vs_pred : std_logic; SIGNAL i_intercnt : natural RANGE 0 TO 7; SIGNAL i_inter : std_logic; SIGNAL i_write,i_walt : std_logic; SIGNAL i_push : std_logic; SIGNAL i_pushhead,i_pushhead2,i_pushhead3 : 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_syncline : std_logic; SIGNAL i_wad,i_wad_pre : 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 SIGNAL i_reset_na : std_logic; SIGNAL i_hnp,i_vnp : std_logic; 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 : natural RANGE 0 TO 4095; SIGNAL i_hdivi,i_vdivi : unsigned(11 DOWNTO 0); SIGNAL i_hdivr,i_vdivr : unsigned(23 DOWNTO 0); SIGNAL i_hdiv,i_v_frac : unsigned(11 DOWNTO 0); SIGNAL i_hacc,i_vacc : natural RANGE 0 TO 4095; SIGNAL i_hdown,i_vdown : std_logic; SIGNAL i_divcpt : natural RANGE 0 TO 36; SIGNAL i_divstart : std_logic; SIGNAL i_divrun : std_logic; SIGNAL i_count,i_ctotal : unsigned(31 DOWNTO 0); 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_ldw,i_ldrm : type_pix; SIGNAL i_h_frac2,i_h_fracn2 : unsigned(FRAC DOWNTO 0); SIGNAL i_v_frac2,i_v_fracn2 : unsigned(FRAC DOWNTO 0); SIGNAL i_hpix0,i_hpix1,i_hpix2,i_hpix3 : 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 : std_logic; ---------------------------------------------------------- -- Avalon TYPE type_avl_state IS (sIDLE,sWRITE,sREAD); SIGNAL avl_state : type_avl_state; SIGNAL avl_mode : unsigned(4 DOWNTO 0); SIGNAL avl_write_i,avl_write_sync,avl_write_sync2 : std_logic; SIGNAL avl_read_i,avl_read_sync,avl_read_sync2 : std_logic; SIGNAL avl_read_pulse,avl_write_pulse : std_logic; SIGNAL avl_i_vs,avl_i_vs_sync : std_logic; SIGNAL avl_o_vs,avl_o_vs_sync : std_logic; 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_fl,avl_inter : 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_buf,avl_o_buf : natural RANGE 0 TO 2; SIGNAL avl_i_offset,avl_o_offset : unsigned(31 DOWNTO 0); SIGNAL avl_bufup : std_logic; SIGNAL avl_reset_na : std_logic; FUNCTION buf_next(a,b : natural RANGE 0 TO 2) RETURN natural IS BEGIN IF (a=0 AND b=1) OR (a=1 AND b=0) THEN RETURN 2; END IF; IF (a=1 AND b=2) OR (a=2 AND b=1) THEN RETURN 0; END IF; RETURN 1; END FUNCTION; FUNCTION buf_offset(b : natural RANGE 0 TO 2) RETURN unsigned IS BEGIN IF b=1 THEN RETURN RAMSIZE; END IF; IF b=2 THEN RETURN RAMSIZE(30 DOWNTO 0) & '0'; END IF; RETURN x"00000000"; END FUNCTION; SIGNAL avl_debug_write : natural RANGE 0 TO 255; ---------------------------------------------------------- -- Output SIGNAL o_run : std_logic; SIGNAL o_mode,o_modex : unsigned(4 DOWNTO 0); SIGNAL o_htotal,o_hsstart,o_hsend : natural RANGE 0 TO 4095; SIGNAL o_hmin,o_hmax,o_hdisp : natural RANGE 0 TO 4095; SIGNAL o_vtotal,o_vsstart,o_vsend : natural RANGE 0 TO 4095; SIGNAL o_vmin,o_vmax,o_vdisp : natural RANGE 0 TO 4095; SIGNAL o_divcpt : natural RANGE 0 TO 36; SIGNAL o_divstart : std_logic; SIGNAL o_divrun : std_logic; 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_copy1,o_copy2,o_copy3,o_copy4 : std_logic; SIGNAL o_adrs : unsigned(31 DOWNTO 0); -- Avalon address SIGNAL o_adrs_pre : natural RANGE 0 TO 32*4096-1; SIGNAL o_ad : natural RANGE 0 TO 2*BLEN-1; SIGNAL o_adturn : std_logic; SIGNAL o_dr : unsigned(N_DW-1 DOWNTO 0); SIGNAL o_shift : unsigned(0 TO 143); 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_linem,o_line0,o_line1,o_line2 : arr_pix(0 TO OHRES-1); ATTRIBUTE ramstyle OF o_linem : SIGNAL IS "no_rw_check"; 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"; SIGNAL o_wadl,o_radl : natural RANGE 0 TO OHRES-1; SIGNAL o_ldw,o_ldrm,o_ldr0,o_ldr1,o_ldr2 : type_pix; SIGNAL o_wr : unsigned(3 DOWNTO 0); SIGNAL o_hcpt,o_vcpt : natural RANGE 0 TO 4095; SIGNAL o_hdelta,o_vdelta : unsigned(23 DOWNTO 0); SIGNAL o_ihsize,o_ivsize : natural RANGE 0 TO 4095; SIGNAL o_hdivi,o_vdivi : unsigned(11 DOWNTO 0); SIGNAL o_hdivr,o_vdivr : unsigned(35 DOWNTO 0); SIGNAL o_hpos,o_hpos_next : unsigned(23 DOWNTO 0); SIGNAL o_vpos,o_vpos2,o_vpos_next : unsigned(23 DOWNTO 0); -- [23:12].[11.0] SIGNAL o_hpos1,o_hpos2,o_hpos3 : unsigned(23 DOWNTO 0); SIGNAL xxx_vposi : natural RANGE 0 TO 4095; SIGNAL o_hsp,o_hs0,o_hs1,o_hs2,o_hs3,o_hs4 : std_logic; SIGNAL o_vs0,o_vs1,o_vs2,o_vs3,o_vs4,o_vs5,o_vs6 : std_logic; SIGNAL o_de0,o_de1,o_de2,o_de3,o_de4,o_de5,o_de6 : std_logic; SIGNAL o_pe0,o_pe1,o_pe2,o_pe3,o_pe4,o_pe5,o_pe6 : 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; SIGNAL o_fload : natural RANGE 0 TO 3; SIGNAL o_acpt : natural RANGE 0 TO 15; -- Alternance pixels FIFO SIGNAL o_dshi : natural RANGE 0 TO 3; SIGNAL o_alt,o_altp : unsigned(3 DOWNTO 0); SIGNAL o_altv : unsigned(0 TO 11); SIGNAL o_primv,o_lastv ,o_bibv : unsigned(0 TO 2); SIGNAL o_bibu,o_bib : std_logic :='0'; SIGNAL o_dcpt,o_dcpt1,o_dcpt2,o_dcpt3,o_dcpt4,o_dcpt5 : natural RANGE 0 TO 4095; SIGNAL o_hpix0,o_hpix1,o_hpix2,o_hpix3 : type_pix; SIGNAL o_hpix01,o_hpix11,o_hpix21,o_hpix31 : type_pix; SIGNAL o_hpix02,o_hpix12,o_hpix22,o_hpix32 : type_pix; SIGNAL o_hpix03,o_hpix13,o_hpix23,o_hpix33 : type_pix; SIGNAL o_vpixm2,o_vpix02,o_vpix12,o_vpix22 : type_pix; SIGNAL o_vpixm3,o_vpix03,o_vpix13,o_vpix23 : type_pix; SIGNAL o_vpix04,o_vpix14 : type_pix; SIGNAL o_ivs,o_ivs2,o_ivs3,o_isyncline,o_isyncline2,o_ouda,o_oudb : std_logic; SIGNAL o_icnt,o_ocnt : natural RANGE 0 TO 4096*4096-1; SIGNAL o_osdelay,o_idelay,o_isdelay,o_dsync : natural RANGE 0 TO 4096*4096-1; SIGNAL o_dosync : std_logic; SIGNAL o_vpe : std_logic; ----------------------------------------------------------------------------- FUNCTION altx (a : unsigned(1 DOWNTO 0)) RETURN unsigned IS BEGIN CASE a IS WHEN "00" => RETURN "0001"; WHEN "01" => RETURN "0010"; WHEN "10" => RETURN "0100"; WHEN OTHERS => RETURN "1000"; END CASE; END FUNCTION; ----------------------------------------------------------------------------- FUNCTION change(pos_pre : unsigned(23 DOWNTO 0); pos : unsigned(23 DOWNTO 0)) RETURN boolean IS BEGIN RETURN (pos_pre(12 DOWNTO 11)="00" AND pos(12 DOWNTO 11)="01") OR (pos_pre(12 DOWNTO 11)="10" AND pos(12 DOWNTO 11)="11") OR (pos_pre(12 DOWNTO 11)="00" AND pos(12 DOWNTO 11)="10") OR (pos_pre(12 DOWNTO 11)="01" AND pos(12 DOWNTO 11)="11") OR (pos_pre(12 DOWNTO 11)="10" AND pos(12 DOWNTO 11)="00") OR (pos_pre(12 DOWNTO 11)="11" AND pos(12 DOWNTO 11)="01"); END FUNCTION; ----------------------------------------------------------------------------- FUNCTION bound(a : unsigned; s : natural) RETURN unsigned IS BEGIN IF a(a'left)='1' THEN RETURN x"00"; ELSIF a(a'left DOWNTO s)/=0 THEN RETURN x"FF"; ELSE RETURN a(s-1 DOWNTO s-8); END IF; END FUNCTION bound; ----------------------------------------------------------------------------- -- Nearest FUNCTION near_frac(f : unsigned(11 DOWNTO 0)) RETURN unsigned IS VARIABLE x : unsigned(FRAC-1 DOWNTO 0); BEGIN x:=(OTHERS =>NOT f(11)); RETURN x; END FUNCTION; SIGNAL o_h_frac,o_v_frac : unsigned(FRAC-1 DOWNTO 0); SIGNAL o_h_frac2,o_h_fracn2,o_v_frac2,o_v_fracn2 : unsigned(FRAC DOWNTO 0); SIGNAL o_h_bil_pix,o_v_bil_pix : type_pix; ----------------------------------------------------------------------------- -- Nearest + Bilinear + Sharp Bilinear FUNCTION bil_frac(f : unsigned(11 DOWNTO 0)) RETURN unsigned IS VARIABLE x : unsigned(FRAC-1 DOWNTO 0); BEGIN x:=f(11 DOWNTO 12-FRAC); x(FRAC-1):=NOT f(11); RETURN x; END FUNCTION; FUNCTION bil_calc(f :unsigned(FRAC DOWNTO 0); g :unsigned(FRAC DOWNTO 0); p0,p1 : type_pix) RETURN type_pix IS VARIABLE u : unsigned(8+FRAC DOWNTO 0); VARIABLE x : type_pix; CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); BEGIN u:=p1.r * f + p0.r * g; x.r:=bound(u,8+FRAC); u:=p1.g * f + p0.g * g; x.g:=bound(u,8+FRAC); u:=p1.b * f + p0.b * g; x.b:=bound(u,8+FRAC); RETURN x; END FUNCTION; ----------------------------------------------------------------------------- -- Sharp Bilinear -- <0.5 : x*x*x*4 -- >0.5 : 1 - (1-x)*(1-x)*(1-x)*4 TYPE type_sbil_tt IS RECORD f : unsigned(FRAC-1 DOWNTO 0); s : unsigned(FRAC-1 DOWNTO 0); END RECORD; SIGNAL o_h_sbil_t,o_v_sbil_t : type_sbil_tt; FUNCTION sbil_frac1(f : unsigned(11 DOWNTO 0)) RETURN type_sbil_tt IS VARIABLE u : unsigned(FRAC-1 DOWNTO 0); VARIABLE v : unsigned(2*FRAC-1 DOWNTO 0); VARIABLE x : type_sbil_tt; VARIABLE ff : unsigned(11 DOWNTO 0); BEGIN ff:=f; ff(11):=NOT f(11); IF ff(11)='0' THEN u:=ff(11 DOWNTO 12-FRAC); ELSE u:=NOT ff(11 DOWNTO 12-FRAC); END IF; v:=u*u; x.f:=u; x.s:=v(2*FRAC-2 DOWNTO FRAC-1); RETURN x; END FUNCTION; FUNCTION sbil_frac2(f : unsigned(11 DOWNTO 0); t : type_sbil_tt) RETURN unsigned IS VARIABLE v : unsigned(2*FRAC-1 DOWNTO 0); VARIABLE ff : unsigned(11 DOWNTO 0); BEGIN ff:=f; ff(11):=NOT f(11); v:=t.f*t.s; IF ff(11)='0' THEN RETURN v(2*FRAC-2 DOWNTO FRAC-1); ELSE RETURN NOT v(2*FRAC-2 DOWNTO FRAC-1); END IF; END FUNCTION; ----------------------------------------------------------------------------- -- Bicubic TYPE type_bic_abcd IS RECORD a : unsigned(7 DOWNTO 0); -- 0.8 b : signed(8 DOWNTO 0); -- 0.9 c : signed(11 DOWNTO 0); -- 3.9 d : signed(10 DOWNTO 0); -- 2.9 xx : signed(8 DOWNTO 0); -- X.X 1.8 END RECORD; TYPE type_bic_pix_abcd IS RECORD r,g,b : type_bic_abcd; END RECORD; TYPE type_bic_tt1 IS RECORD -- Intermediate result r_bx,g_bx,b_bx : signed(8 DOWNTO 0); -- B.X 1.8 r_cxx,g_cxx,b_cxx : signed(11 DOWNTO 0); -- C.XX 3.9 r_dxx,g_dxx,b_dxx : signed(10 DOWNTO 0); -- D.XX 2.9 END RECORD; TYPE type_bic_tt2 IS RECORD -- Intermediate result r_abxcxx,g_abxcxx,b_abxcxx : signed(9 DOWNTO 0); -- A + B.X + C.XX 2.8 r_dxxx,g_dxxx,b_dxxx : signed(9 DOWNTO 0); -- D.X.X.X 2.8 END RECORD; ---------------------------------------------------------- -- Y = A + B.X + C.X.X + D.X.X.X = A + X.(B + X.(C + X.D)) -- A = Y(0) 0 .. 1 unsigned -- B = Y(1)/2 - Y(-1)/2 -1/2 .. +1/2 signed -- C = Y(-1) - 5*Y(0)/2 + 2*Y(1) - Y(2)/2 -3 .. +3 signed -- D = -Y(-1)/2 + 3*Y(0)/2 - 3*Y(1)/2 + Y(2)/2 -2 .. +2 signed FUNCTION bic_calc0(f : unsigned(11 DOWNTO 0); pm,p0,p1,p2 : unsigned(7 DOWNTO 0)) RETURN type_bic_abcd IS VARIABLE xx : signed(2*FRAC+1 DOWNTO 0); -- 2.(2*FRAC) VARIABLE ff : unsigned(11 DOWNTO 0); BEGIN ff:=f; ff(11):=NOT f(11); xx := signed('0' & ff(11 DOWNTO 12-FRAC)) * signed('0' & ff(11 DOWNTO 12-FRAC)); -- 2.(2*FRAC) RETURN type_bic_abcd'( a=>p0,-- 0.8 b=>signed(('0' & p1) - ('0' & pm)), -- 0.9 c=>signed(("000" & pm & '0') - ("00" & p0 & "00") - ("0000" & p0) + ("00" & p1 & "00") - ("0000" & p2)), -- 3.9 d=>signed(("00" & p0 & '0') - ("00" & p1 & '0') - ("000" & p1) + ("000" & p0) + ("000" & p2) - ("000" & pm)), -- 2.9 xx=>xx(2*FRAC DOWNTO 2*FRAC-8)); -- 1.8 END FUNCTION; FUNCTION bic_calc0(f : unsigned(11 DOWNTO 0); pm,p0,p1,p2 : type_pix) RETURN type_bic_pix_abcd IS BEGIN RETURN type_bic_pix_abcd'(r=>bic_calc0(f,pm.r,p0.r,p1.r,p2.r), g=>bic_calc0(f,pm.g,p0.g,p1.g,p2.g), b=>bic_calc0(f,pm.b,p0.b,p1.b,p2.b)); END FUNCTION; ---------------------------------------------------------- -- Calc : B.X, C.XX, D.XX FUNCTION bic_calc1(f : unsigned(11 DOWNTO 0); abcd : type_bic_pix_abcd) RETURN type_bic_tt1 IS VARIABLE t : type_bic_tt1; VARIABLE bx : signed(9+FRAC DOWNTO 0); -- 1.(FRAC+9) VARIABLE cxx : signed(20 DOWNTO 0); -- 4.17 VARIABLE dxx : signed(19 DOWNTO 0); -- 3.17 VARIABLE ff : unsigned(11 DOWNTO 0); BEGIN ff:=f; ff(11):=NOT f(11); bx := abcd.r.b * signed('0' & ff(11 DOWNTO 12-FRAC)); -- 1.(FRAC+9) t.r_bx:=bx(9+FRAC DOWNTO 9+FRAC-8); -- 1.8 cxx:= abcd.r.c * abcd.r.xx; -- 3.9 * 1.8 = 4.17 t.r_cxx:=cxx(19 DOWNTO 8); -- 3.9 dxx:= abcd.r.d * abcd.r.xx; -- 2.9 * 1.8 = 3.17 t.r_dxx:=dxx(18 DOWNTO 8); -- 2.9 bx := abcd.g.b * signed('0' & ff(11 DOWNTO 12-FRAC)); -- 1.(FRAC+9) t.g_bx:=bx(9+FRAC DOWNTO 9+FRAC-8); -- 1.8 cxx:= abcd.g.c * abcd.g.xx; -- 3.9 * 1.8 = 4.17 t.g_cxx:=cxx(19 DOWNTO 8); -- 3.9 dxx:= abcd.g.d * abcd.g.xx; -- 2.9 * 1.8 = 3.17 t.g_dxx:=dxx(18 DOWNTO 8); -- 2.9 bx := abcd.b.b * signed('0' & ff(11 DOWNTO 12-FRAC)); -- 1.(FRAC+9) t.b_bx:=bx(9+FRAC DOWNTO 9+FRAC-8); -- 1.8 cxx:= abcd.b.c * abcd.b.xx; -- 3.9 * 1.8 = 4.17 t.b_cxx:=cxx(19 DOWNTO 8); -- 3.9 dxx:= abcd.b.d * abcd.b.xx; -- 2.9 * 1.8 = 3.17 t.b_dxx:=dxx(18 DOWNTO 8); -- 2.9 RETURN t; END FUNCTION; ---------------------------------------------------------- -- Calc A + BX + CXX , X.DXX FUNCTION bic_calc2(f : unsigned(11 DOWNTO 0); t : type_bic_tt1; abcd : type_bic_pix_abcd) RETURN type_bic_tt2 IS VARIABLE u : type_bic_tt2; VARIABLE x : signed(11+FRAC DOWNTO 0); -- 3.(9+FRAC) VARIABLE ff : unsigned(11 DOWNTO 0); BEGIN ff:=f; ff(11):=NOT f(11); u.r_abxcxx:=(t.r_bx(8) & t.r_bx) + ("00" & signed(abcd.r.a)) + t.r_cxx(10 DOWNTO 1); -- 2.8 u.g_abxcxx:=(t.g_bx(8) & t.g_bx) + ("00" & signed(abcd.g.a)) + t.g_cxx(10 DOWNTO 1); -- 2.8 u.b_abxcxx:=(t.b_bx(8) & t.b_bx) + ("00" & signed(abcd.b.a)) + t.b_cxx(10 DOWNTO 1); -- 2.8 x:=t.r_dxx * signed('0' & ff(11 DOWNTO 12-FRAC)); --2.9 * 1.FRAC =3.(9+FRAC) u.r_dxxx:=x(10+FRAC DOWNTO 9+FRAC-8); -- 2.8 x:=t.g_dxx * signed('0' & ff(11 DOWNTO 12-FRAC)); --2.9 * 1.FRAC =3.(9+FRAC) u.g_dxxx:=x(10+FRAC DOWNTO 9+FRAC-8); -- 2.8 x:=t.b_dxx * signed('0' & ff(11 DOWNTO 12-FRAC)); --2.9 * 1.FRAC =3.(9+FRAC) u.b_dxxx:=x(10+FRAC DOWNTO 9+FRAC-8); -- 2.8 RETURN u; END FUNCTION; ---------------------------------------------------------- -- Calc (A + BX + CXX) + (DXXX) FUNCTION bic_calc3(f : unsigned(11 DOWNTO 0); t : type_bic_tt2; abcd : type_bic_pix_abcd) RETURN type_pix IS VARIABLE x : type_pix; VARIABLE v : signed(9 DOWNTO 0); -- 2.8 BEGIN v:=t.r_abxcxx + t.r_dxxx; x.r:=bound(unsigned(v),8); v:=t.g_abxcxx + t.g_dxxx; x.g:=bound(unsigned(v),8); v:=t.b_abxcxx + t.b_dxxx; x.b:=bound(unsigned(v),8); RETURN x; END FUNCTION; ----------------------------------------------------------------------------- SIGNAL o_h_bic_pix,o_v_bic_pix : type_pix; SIGNAL o_h_bic_abcd,o_h_bic_abcd1,o_h_bic_abcd2 : type_bic_pix_abcd; SIGNAL o_v_bic_abcd,o_v_bic_abcd1,o_v_bic_abcd2 : type_bic_pix_abcd; SIGNAL o_h_bic_tt1,o_v_bic_tt1 : type_bic_tt1; SIGNAL o_h_bic_tt2,o_v_bic_tt2 : type_bic_tt2; ----------------------------------------------------------------------------- -- Polyphase TYPE arr_uv36 IS ARRAY (natural RANGE <>) OF unsigned(35 DOWNTO 0); -- 9/9/9/9 TYPE arr_integer IS ARRAY (natural RANGE <>) OF integer; CONSTANT POLY16_A : arr_integer := ( -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); CONSTANT POLY16_B : arr_integer := ( 0,-4,-8,-10,-11,-11,-10,-9,-8,-6,-4,-3,-2,-1,0,0, 127,126,124,119,111,103,93,82,72,56,45,35,25,17,9,3, 0,6,13,20,30,40,50,61,72,88,98,107,115,121,125,127, 0,0,-1,-1,-2,-4,-5,-6,-8,-10,-11,-11,-10,-9,-6,-2); CONSTANT POLY32_A : arr_integer := ( -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, 176,175,174,172,169,164,160,153,147,138,129,119,109,96,84,71,58,40,22,12,3,-4,-12,-16,-20,-22,-25,-25,-26,-25,-25,-25, -24,-25,-26,-26,-26,-24,-23,-19,-16,-10,-4,4,11,22,32,45,58,77,96,108,119,129,140,147,154,159,165,168,172,173,175,175, 0,0,0,0,1,1,2,2,3,3,4,5,6,7,7,7,6,5,4,3,1,-1,-4,-6,-8,-10,-13,-15,-18,-20,-22,-22); CONSTANT POLY32_B : arr_integer := ( 0,-2,-4,-6,-8,-9,-10,-10,-11,-11,-11,-10,-10,-9,-9,-8,-8,-7,-6,-5,-4,-3,-3,-2,-2,-1,-1,0,0,0,0,0, 128,127,126,125,124,121,119,115,111,107,103,98,93,87,82,77,72,64,56,50,45,40,35,30,25,21,17,13,9,6,3,3, 0,3,6,9,13,17,20,25,30,35,40,45,50,55,61,66,72,80,88,93,98,102,107,111,115,118,121,123,125,126,127,127, 0,0,0,0,-1,-1,-1,-2,-2,-3,-4,-5,-5,-5,-6,-7,-8,-9,-10,-10,-11,-11,-11,-11,-10,-10,-9,-8,-6,-4,-2,-2); FUNCTION gen_poly(n : natural) RETURN arr_uv36 IS VARIABLE p16 : arr_integer(0 TO 4*16-1); VARIABLE p32 : arr_integer(0 TO 4*32-1); VARIABLE m : arr_uv36(0 TO 2**FRAC-1) :=(OTHERS =>x"000000000"); BEGIN IF FRAC=4 THEN IF n=0 THEN p16:=POLY16_A; ELSE p16:=POLY16_B; END IF; FOR i IN 0 TO 15 LOOP m(i):=unsigned(to_signed(p16(i),9) & to_signed(p16(i+16),9) & to_signed(p16(i+32),9) & to_signed(p16(i+48),9)); END LOOP; ELSIF FRAC=5 THEN IF n=0 THEN p32:=POLY32_A; ELSE p32:=POLY32_B; END IF; FOR i IN 0 TO 31 LOOP m(i):=unsigned(to_signed(p32(i),9) & to_signed(p32(i+32),9) & to_signed(p32(i+64),9) & to_signed(p32(i+96),9)); END LOOP; END IF; RETURN m; END FUNCTION; FUNCTION init_poly RETURN arr_uv36 IS VARIABLE p : arr_uv36(0 TO 2**(FRAC+NPOLY)-1); BEGIN FOR i IN 0 TO 2**NPOLY-1 LOOP p(i*2**FRAC TO (i+1)*2**FRAC-1):=gen_poly(i MOD 2); END LOOP; RETURN p; END; SIGNAL o_h_poly : arr_uv36(0 TO 2**(FRAC+NPOLY)-1):=init_poly; SIGNAL o_v_poly : arr_uv36(0 TO 2**(FRAC+NPOLY)-1):=init_poly; ATTRIBUTE ramstyle OF o_h_poly : SIGNAL IS "no_rw_check"; ATTRIBUTE ramstyle OF o_v_poly : SIGNAL IS "no_rw_check"; SIGNAL o_h_poly_a,o_v_poly_a : integer RANGE 0 TO 2**(FRAC+NPOLY)-1; SIGNAL o_h_poly_dr,o_v_poly_dr : unsigned(35 DOWNTO 0); SIGNAL o_h_poly_pix,o_v_poly_pix : type_pix; SIGNAL poly_h_wr,poly_v_wr : std_logic; SIGNAL poly_tdw : unsigned(35 DOWNTO 0); SIGNAL poly_a2 : unsigned(FRAC+NPOLY-1 DOWNTO 0); TYPE type_poly_t IS RECORD r0,r1,b0,b1,g0,g1 : signed(17 DOWNTO 0); END RECORD; TYPE type_poly_t2 IS RECORD r,g,b : unsigned(17 DOWNTO 0); END RECORD; SIGNAL o_h_poly_t,o_v_poly_t : type_poly_t; SIGNAL o_h_poly_t2,o_v_poly_t2 : type_poly_t2; FUNCTION poly_calc1(fi : unsigned(35 DOWNTO 0); pm,p0,p1,p2 : type_pix) RETURN type_poly_t IS VARIABLE t : type_poly_t; BEGIN -- 2.7 * 1.8 = 3.15 t.r0:=(signed(fi(35 DOWNTO 27)) * signed('0' & pm.r) + signed(fi(26 DOWNTO 18)) * signed('0' & p0.r)); t.r1:=(signed(fi(17 DOWNTO 9)) * signed('0' & p1.r) + signed(fi( 8 DOWNTO 0)) * signed('0' & p2.r)); t.g0:=(signed(fi(35 DOWNTO 27)) * signed('0' & pm.g) + signed(fi(26 DOWNTO 18)) * signed('0' & p0.g)); t.g1:=(signed(fi(17 DOWNTO 9)) * signed('0' & p1.g) + signed(fi( 8 DOWNTO 0)) * signed('0' & p2.g)); t.b0:=(signed(fi(35 DOWNTO 27)) * signed('0' & pm.b) + signed(fi(26 DOWNTO 18)) * signed('0' & p0.b)); t.b1:=(signed(fi(17 DOWNTO 9)) * signed('0' & p1.b) + signed(fi( 8 DOWNTO 0)) * signed('0' & p2.b)); RETURN t; END FUNCTION; FUNCTION poly_calc2(pt : type_poly_t) RETURN type_poly_t2 IS VARIABLE p : type_poly_t2; VARIABLE t : signed(17 DOWNTO 0); -- 3.15 BEGIN p.r:=unsigned(pt.r0+pt.r1); p.g:=unsigned(pt.g0+pt.g1); p.b:=unsigned(pt.b0+pt.b1); RETURN p; END FUNCTION; FUNCTION poly_calc3(t : type_poly_t2) RETURN type_pix IS VARIABLE p : type_pix; BEGIN p.r:=bound(unsigned(t.r),15); p.g:=bound(unsigned(t.g),15); p.b:=bound(unsigned(t.b),15); RETURN p; END FUNCTION; ----------------------------------------------------------------------------- -- DEBUG SIGNAL o_debug_read : integer RANGE 0 TO 255; 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_hcpt2,o_hcpt3,o_hcpt4 : natural RANGE 0 TO 4095; 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 ----------------------------------------------------------------------------- i_reset_na<='0' WHEN reset_na='0' ELSE '1' WHEN rising_edge(i_clk); o_reset_na<='0' WHEN reset_na='0' ELSE '1' WHEN rising_edge(o_clk); avl_reset_na<='0' WHEN reset_na='0' ELSE '1' WHEN rising_edge(avl_clk); ----------------------------------------------------------------------------- -- Input pixels FIFO and shreg InAT:PROCESS(i_clk,i_reset_na) IS CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); VARIABLE hfrac_v : unsigned(23 DOWNTO 0); BEGIN IF i_reset_na='0' THEN i_write<='0'; ELSIF rising_edge(i_clk) THEN i_push<='0'; i_run <= run; -- 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(95 DOWNTO 80)<=x"0000"; -- Attributes. TBD i_head(79 DOWNTO 64)<=to_unsigned(i_hrsize+1,16); -- Image width i_head(63 DOWNTO 48)<=to_unsigned(i_vrsize+1,16); -- 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 ------------------------------------------------------ IF i_ce='1' THEN ---------------------------------------------------- i_hs_pre<=i_hs; i_vs_pre<=i_vs; i_de_pre<=i_de; i_fl_pre<=i_fl; ---------------------------------------------------- -- Detect interleaved video IF NOT INTER THEN i_intercnt<=0; ELSIF i_fl/=i_fl_pre AND i_intercnt<4 THEN i_intercnt<=i_intercnt+2; ELSIF i_vs='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_hs='1' THEN i_hcpt<=0; ELSE i_hcpt<=i_hcpt+1; END IF; IF i_vs='1' THEN i_vcpt<=0; IF i_inter='1' AND i_fl='1' AND INTER THEN i_adrsi<=to_unsigned(N_BURST * i_hburst,32); ELSE i_adrsi<=(OTHERS =>'0'); END IF; i_vminset<='0'; i_wad_pre<=0; END IF; IF i_hs='1' AND i_hs_pre='0' THEN i_vcpt<=i_vcpt+1; END IF; i_ven<=to_std_logic(i_hcpt+1>=i_hmin AND i_hcpt+1<=i_hmax AND i_vcpt>=i_vmin AND i_vcpt<=i_vmax AND i_hs='0' AND i_vs='0'); i_syncline<=to_std_logic(i_vcpt=i_vmin + 3); ---------------------------------------------------- -- Auto-sizing of the input image IF i_de='1' AND i_de_pre='0' THEN i_chmin<=i_hcpt+1; END IF; IF i_de='0' AND i_de_pre='1' THEN i_chmax<=i_hcpt; END IF; IF i_de='1' AND i_de_pre='0' AND i_vminset='0' THEN i_cvmin<=i_vcpt; i_vminset<='1'; END if; IF i_de='1' AND i_de_pre='0' THEN i_vmaxc<=i_vcpt; END IF; IF i_vs='1' THEN i_cvmax<=i_vmaxc; END IF; IF i_iauto='1' THEN i_hmin<=i_chmin; i_hmax<=i_chmax; i_vmin<=i_cvmin; i_vmax<=i_cvmax; ELSE -- Forced image i_hmin<=himin+i_chmin; i_hmax<=himax+i_chmin; i_vmin<=vimin+i_cvmin; i_vmax<=vimax+i_cvmin; END IF; ---------------------------------------------------- IF o_modex(2 DOWNTO 0)="000" OR NOT DOWNSCALE THEN -- Nearest downscaling i_bil<='0'; ELSE -- Bilinear downscaling i_bil<='1'; END IF; ---------------------------------------------------- i_hdown<=to_std_logic(i_hsize>i_ohsize AND DOWNSCALE); -- Horiz. donwscale i_vdown<=to_std_logic(i_vsize>i_ovsize AND DOWNSCALE); -- Vert. downscale -- If downscaling, export to the output part the downscaled size IF i_hdown='0' THEN i_hrsize<=i_hsize; ELSE i_hrsize<=(i_ohsize-1+4096) MOD 4096; END IF; IF i_vdown='0' THEN i_vrsize<=i_vsize; ELSE i_vrsize<=(i_ovsize-1+4096) MOD 4096; END IF; ---------------------------------------------------- -- VS __/""""\_______________________ -- DE _________________/"""""""\_____ -- VCPT 0 0 0 1 2 3 4 5 6 7 8 9 10 -- VMIN = 6 VMAX=9 -- HS __/""""\_______________________ -- DE _________________/"""""""\_____ -- HCPT 0 0 0 1 2 3 4 5 6 7 8 9 10 -- HMIN = 6 HMAX=9 i_hsize<=(4096+i_hmax-i_hmin) MOD 4096; IF i_inter='0' THEN i_vsize<=(4096+i_vmax-i_vmin) MOD 4096; ELSE -- Interlaced : Double image height i_vsize<=2*((4096+i_vmax-i_vmin) MOD 4096) +1; END IF; i_ohsize<=to_integer(o_hdivi); -- i_ovsize<=to_integer(o_vdivi); -- ---------------------------------------------------- -- Downscaling vertical i_divstart<='0'; IF i_hs='1' AND i_hs_pre='0' THEN IF i_hcpt>=i_hmin THEN IF i_vacc>=i_ovsize THEN i_vacc<=(i_vacc - i_ovsize + 4096) MOD 4096; i_vnp<=NOT i_vdown; ELSE i_vacc<=(i_vacc - i_ovsize + i_vsize + 4096) MOD 4096; i_vnp<='1'; END IF; i_divstart<='1'; END IF; END IF; -- Downscaling horizontal IF i_hdown='1' AND i_ven='1' THEN IF i_hacc>=i_ohsize THEN i_hacc<=(i_hacc - i_ohsize + 4096) MOD 4096; i_hnp<='0'; ELSE i_hacc<=(i_hacc - i_ohsize + i_hsize + 4096) MOD 4096; i_hnp<='1'; END IF; ELSE i_hnp<='1'; END IF; ---------------------------------------------------- -- Downscaling interpolation i_hpix0<=(i_r,i_g,i_b); i_hpix1<=i_hpix0; i_hpix2<=i_hpix1; i_hnp1<=i_hnp; i_hnp2<=i_hnp1; i_hnp3<=i_hnp2; i_hnp4<=i_hnp3; i_ven1<=i_ven; i_ven2<=i_ven1; i_ven3<=i_ven2; i_ven4<=i_ven3; i_ven5<=i_ven4; -- C1 : Frac hfrac_v:=i_hacc * i_hdiv; -- 12 * 0.12 i_h_frac2 <='0' & hfrac_v(11 DOWNTO 12-FRAC); i_h_fracn2<=('1' & Z) - ('0' & hfrac_v(11 DOWNTO 12-FRAC)); i_v_frac2 <='0' & i_v_frac(11 DOWNTO 12-FRAC); i_v_fracn2<=('1' & Z) - ('0' & i_v_frac(11 DOWNTO 12-FRAC)); -- C2 : Horizontal Bilinear i_hpix<=bil_calc(i_h_frac2,i_h_fracn2,i_hpix2,i_hpix1); IF i_hdown='0' OR i_bil='0' THEN i_hpix<=i_hpix2; END IF; -- C3 : Vertical Bilinear i_pix<=bil_calc(i_v_frac2,i_v_fracn2,i_ldrm,i_hpix); IF i_vdown='0' OR i_bil='0' THEN i_pix<=i_hpix; END IF; ---------------------------------------------------- -- Assemble pixels -- ACPT -- 0 ...............RGB -- 1 ............RGBrgb -- 2 .........RGBrgbRGB -- 3 ......RGBrgbRGBrgb -- 4 ...RGBrgbRGBrgbRGB -- 5 RGBrgbRGBrgbRGBrgb => PUSH RGBrgbRGBrgbRGBr -- 6 .............gbRGB -- 7 ..........gbRGBrgb -- 8 .......gbRGBrgbRGB -- 9 ....gbRGBrgbRGBrgb -- 10 .gbRGBrgbRGBrgbRGB => PUSH gbRGBrgbRGBrgbRG -- 11 ..............Brgb -- 12 ...........BrgbRGB -- 13 ........BrgbRGBrgb -- 14 .....BrgbRGBrgbRGB -- 15 ..BrgbRGBrgbRGBrgb => PUSH BrgbRGBrgbRGBrgb IF i_hnp3='1' THEN i_shift<=i_shift(24 TO 119) & i_pix.r & i_pix.g & i_pix.b; IF i_acpt=5 THEN i_dw<=i_shift(0 TO 119) & i_pix.r; ELSIF i_acpt=10 THEN i_dw<=i_shift(8 TO 119) & i_pix.r & i_pix.g; ELSIF i_acpt=15 THEN i_dw<=i_shift(16 TO 119) & i_pix.r & i_pix.g & i_pix.b; ELSIF i_pushhead='1' THEN i_dw<=i_head; END IF; END IF; IF i_vnp='1' AND i_hnp3='1' AND (i_ven4='1' OR i_acpt/=0) THEN IF i_acpt=5 OR i_acpt=10 OR i_acpt=15 OR i_pushhead='1' THEN i_push<='1'; END IF; i_pushhead<='0'; i_acpt<=(i_acpt+1) MOD 16; END IF; IF i_hs='1' AND i_hs_pre='0' THEN i_acpt<=0; i_hacc<=0; i_lwad<=0; i_lrad<=0; END IF; IF i_vs='0' AND i_vs_pre='1' THEN i_vacc<=0; -- Push header : -- 1) Trigger write to dual port memory -- 2) Trigger AVALON write burst -- 3) Skip "number of bursts per line" for this line. i_pushhead<=to_std_logic(HEADER); i_pushhead2<=to_std_logic(HEADER); i_pushhead3<=to_std_logic(HEADER); END IF; IF i_hs='0' AND i_hs_pre='1' AND i_vs='0' THEN i_hbcpt<=0; -- Bursts per line counter IF i_hbcpt>0 AND i_pushhead3='0' THEN i_hburst<=i_hbcpt; END IF; IF i_hbcpt>0 THEN i_pushhead3<='0'; END IF; IF i_wad_pre MOD BLEN/=0 THEN i_wad_pre<=((i_wad_pre/BLEN+1) MOD 2)*BLEN; END IF; END IF; END IF; -- IF i_ce='1' i_vs_pred<=i_vs; -- Test. Total clocks per frame IF i_vs='1' AND i_vs_pred='0' THEN i_count<=x"0000_0000"; i_ctotal<=i_count; ELSE i_count<=i_count+1; END IF; ------------------------------------------------------ -- Push pixels to downscaling line buffer IF i_lwr='1' THEN i_lwad<=(i_lwad+1) MOD OHRES; END IF; i_lwr<=i_hnp2 AND i_ven3; i_ldw<=i_hpix; IF i_hnp1='1' AND i_ven2='1' THEN i_lrad<=(i_lrad+1) MOD OHRES; END IF; ------------------------------------------------------ -- Push pixels to DPRAM i_wr<='0'; IF i_push='1' AND i_run='1' THEN i_wr<='1'; i_wad_pre<=(i_wad_pre+1) MOD (BLEN*2); IF (i_wad MOD BLEN=BLEN-1) OR i_ven4='0' OR i_pushhead2='1' THEN IF i_pushhead2='1' THEN i_wad_pre<=0; END IF; i_pushhead2<='0'; i_hbcpt<=(i_hbcpt+1) MOD 32; i_write<=NOT i_write; IF i_wad/BLEN=0 THEN i_walt<='0'; ELSE i_walt<='1'; END IF; i_adrs<=i_adrsi; i_adrsi<=i_adrsi+N_BURST; IF i_inter='1' AND i_ven5='0' THEN -- Skip every other line for interlaced video i_adrsi<=i_adrsi + N_BURST * (i_hburst + 1); END IF; END IF; END IF; i_wad<=i_wad_pre; END IF; END PROCESS; ----------------------------------------------------------------------------- -- Input Dividers. For downscaling. -- Hdiv = 1 / IHsize 1.12 / 12 --> 0.12 -- Vfrac = IVacc / IVsize 12 / 12 --> 12 -- Division IDividers:PROCESS (i_clk,i_reset_na) IS BEGIN IF i_reset_na='0' THEN i_hdiv<=x"000"; -- Simu ! i_v_frac<=x"000"; ELSIF rising_edge(i_clk) THEN i_hdivi<=to_unsigned(i_hrsize,12); i_vdivi<=to_unsigned(i_vrsize,12); i_hdivr<=to_unsigned(4096,24); i_vdivr<=to_unsigned(i_vacc*4096,24); ------------------------------------------------------ IF i_divstart='1' THEN i_divcpt<=0; i_divrun<='1'; ELSIF i_divrun='1' THEN ---------------------------------------------------- IF i_divcpt=12 THEN i_divrun<='0'; i_hdiv<=i_hdivr(10 DOWNTO 0) & NOT i_hdivr(23); i_v_frac<=i_vdivr(10 DOWNTO 0) & NOT i_vdivr(23); ELSE i_divcpt<=i_divcpt+1; END IF; ---------------------------------------------------- IF i_hdivr(23)='0' THEN i_hdivr(23 DOWNTO 12)<=i_hdivr(22 DOWNTO 11) - i_hdivi; ELSE i_hdivr(23 DOWNTO 12)<=i_hdivr(22 DOWNTO 11) + i_hdivi; END IF; i_hdivr(11 DOWNTO 0)<=i_hdivr(10 DOWNTO 0) & NOT i_hdivr(23); IF i_vdivr(23)='0' THEN i_vdivr(23 DOWNTO 12)<=i_vdivr(22 DOWNTO 11) - i_vdivi; ELSE i_vdivr(23 DOWNTO 12)<=i_vdivr(22 DOWNTO 11) + i_vdivi; END IF; i_vdivr(11 DOWNTO 0)<=i_vdivr(10 DOWNTO 0) & NOT i_vdivr(23); ---------------------------------------------------- END IF; END IF; END PROCESS IDividers; ----------------------------------------------------------------------------- -- DPRAM INPUT PROCESS (i_clk) IS BEGIN IF rising_edge(i_clk) THEN IF i_wr='1' THEN i_dpram(i_wad)<=i_dw; END IF; END IF; END PROCESS; avl_dr<=i_dpram(avl_rad_c) WHEN rising_edge(avl_clk); -- Line buffer for downscaling with interpolation DownLine:IF DOWNSCALE GENERATE ILBUF:PROCESS(i_clk) IS BEGIN IF rising_edge(i_clk) THEN IF i_lwr='1' THEN i_line(i_lwad)<=i_ldw; END IF; i_ldrm<=i_line(i_lrad); END IF; END PROCESS ILBUF; END GENERATE DownLine; ----------------------------------------------------------------------------- -- AVALON interface Avaloir:PROCESS(avl_clk,avl_reset_na) IS VARIABLE debug_write_inc,debug_write_dec : std_logic; BEGIN IF avl_reset_na='0' THEN avl_reading<='0'; avl_state<=sIDLE; avl_write_sr<='0'; avl_read_sr<='0'; avl_readack<='0'; ELSIF rising_edge(avl_clk) THEN ---------------------------------- avl_mode<=mode; -- ? avl_write_sync<=i_write; -- avl_write_sync2<=avl_write_sync; avl_write_pulse<=avl_write_sync XOR avl_write_sync2; debug_write_inc:=avl_write_pulse; debug_write_dec:='0'; avl_wadrs <=i_adrs AND (RAMSIZE - 1); -- avl_walt <=i_walt; -- ---------------------------------- avl_read_sync<=o_read; -- avl_read_sync2<=avl_read_sync; avl_read_pulse<=avl_read_sync XOR avl_read_sync2; avl_rbib <=o_bib; avl_radrs <=o_adrs AND (RAMSIZE - 1); -- -------------------------------------------- avl_i_vs_sync<=i_vs; -- avl_i_vs<=avl_i_vs_sync; avl_o_vs_sync<=o_vs0; -- avl_o_vs<=avl_o_vs_sync; avl_inter<=i_inter; -- avl_fl <=i_fl; -- -------------------------------------------- -- Triple buffering. IF avl_i_vs_sync='1' AND avl_i_vs='0' AND (avl_inter='0' OR avl_fl='1') THEN -- Input : Frees framebuffer at begin of VSYNC pulse -- Waits for second frame of interleaved video avl_i_buf<=buf_next(avl_i_buf,avl_o_buf); avl_bufup<='1'; END IF; IF avl_o_vs_sync='0' AND avl_o_vs='1' THEN -- Output : Pick new framebuffer at end of VSYNC pulse IF avl_bufup='1' THEN avl_o_buf<=buf_next(avl_o_buf,avl_i_buf); avl_bufup<='0'; END IF; END IF; IF avl_mode(3)='0' THEN -- Triple buffer disabled avl_o_buf<=0; avl_i_buf<=0; END IF; avl_o_offset<=buf_offset(avl_o_buf); avl_i_offset<=buf_offset(avl_i_buf); -------------------------------------------- avl_dw<=unsigned(avl_readdata); avl_read_i<='0'; avl_write_i<='0'; avl_write_sr<=(avl_write_sr OR avl_write_pulse) AND NOT avl_write_clr; avl_read_sr <=(avl_read_sr OR avl_read_pulse) AND NOT avl_read_clr; avl_write_clr<='0'; avl_read_clr <='0'; avl_rad<=avl_rad_c; -------------------------------------------- CASE avl_state IS WHEN sIDLE => IF avl_o_vs='0' AND avl_o_vs_sync='1' THEN avl_wad<=0; END IF; IF avl_write_sr='1' THEN avl_state<=sWRITE; avl_write_clr<='1'; debug_write_dec:='1'; IF avl_walt='0' THEN avl_rad<=0; ELSE avl_rad<=BLEN; END IF; ELSIF avl_read_sr='1' AND avl_reading='0' THEN IF avl_rbib='0' THEN avl_wad<=2*BLEN-1; ELSE avl_wad<=BLEN-1; END IF; avl_state<=sREAD; avl_read_clr<='1'; 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)); avl_write_i<='1'; IF avl_write_i='1' AND avl_waitrequest='0' THEN IF (avl_rad MOD BLEN)=BLEN-1 THEN avl_write_i<='0'; avl_state<=sIDLE; END IF; 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)); avl_read_i<='1'; avl_reading<='1'; IF avl_read_i='1' AND avl_waitrequest='0' THEN avl_state<=sIDLE; avl_read_i<='0'; END IF; END CASE; -------------------------------------------- IF debug_write_inc='1' AND debug_write_dec='0' THEN avl_debug_write<=avl_debug_write+1; ELSIF debug_write_dec='1' AND debug_write_inc='0' THEN avl_debug_write<=avl_debug_write-1; END IF; -------------------------------------------- -- Pipelined data read avl_wr<='0'; IF avl_readdatavalid='1' THEN avl_wr<='1'; avl_wad<=(avl_wad+1) MOD (2*BLEN); IF (avl_wad MOD BLEN)=BLEN-2 THEN avl_reading<='0'; avl_readack<=NOT avl_readack; END IF; END IF; -------------------------------------------- END IF; END PROCESS Avaloir; avl_read<=avl_read_i; avl_write<=avl_write_i; avl_writedata<=std_logic_vector(avl_dr); avl_burstcount<=std_logic_vector(to_unsigned(BLEN,8)); avl_byteenable<=(OTHERS =>'1'); avl_rad_c<=(avl_rad+1) MOD (2*BLEN) WHEN avl_write_i='1' AND avl_waitrequest='0' ELSE avl_rad; ----------------------------------------------------------------------------- -- DPRAM OUTPUT PROCESS (avl_clk) IS BEGIN IF rising_edge(avl_clk) THEN IF avl_wr='1' THEN o_dpram(avl_wad)<=avl_dw; END IF; END IF; END PROCESS; o_dr<=o_dpram(o_ad) WHEN rising_edge(o_clk); ----------------------------------------------------------------------------- -- Dividers o_ihsize<=i_hrsize WHEN rising_edge(o_clk); -- o_ivsize<=i_vrsize WHEN rising_edge(o_clk); -- -------------------------------------- -- Hdelta = IHsize / (OHmax-OHmin) -- Vdelta = IVsize / (OVmax-OVmin) -- Division : 12 / 12 --> 12.12 ODividers:PROCESS (o_clk,o_reset_na) IS BEGIN IF o_reset_na='0' THEN o_hdelta<=x"001000"; -- Simu ! o_vdelta<=x"001000"; ELSIF rising_edge(o_clk) THEN o_hdivi<=to_unsigned(o_hmax - o_hmin+1,12); o_vdivi<=to_unsigned(o_vmax - o_vmin+1,12); o_hdivr<=to_unsigned((o_ihsize+1) * 4096,36); o_vdivr<=to_unsigned((o_ivsize+1) * 4096,36); ------------------------------------------------------ IF o_divstart='1' THEN o_divcpt<=0; o_divrun<='1'; ELSIF o_divrun='1' THEN ---------------------------------------------------- IF o_divcpt=24 THEN o_divrun<='0'; o_hdelta<=o_hdivr(22 DOWNTO 0) & NOT o_hdivr(35); o_vdelta<=o_vdivr(22 DOWNTO 0) & NOT o_vdivr(35); ELSE o_divcpt<=o_divcpt+1; END IF; ---------------------------------------------------- IF o_hdivr(35)='0' THEN o_hdivr(35 DOWNTO 24)<=o_hdivr(34 DOWNTO 23) - o_hdivi; ELSE o_hdivr(35 DOWNTO 24)<=o_hdivr(34 DOWNTO 23) + o_hdivi; END IF; o_hdivr(23 DOWNTO 0)<=o_hdivr(22 DOWNTO 0) & NOT o_hdivr(35); IF o_vdivr(35)='0' THEN o_vdivr(35 DOWNTO 24)<=o_vdivr(34 DOWNTO 23) - o_vdivi; ELSE o_vdivr(35 DOWNTO 24)<=o_vdivr(34 DOWNTO 23) + o_vdivi; END IF; o_vdivr(23 DOWNTO 0)<=o_vdivr(22 DOWNTO 0) & NOT o_vdivr(35); ---------------------------------------------------- END IF; END IF; END PROCESS ODividers; ----------------------------------------------------------------------------- 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 debug_read_dec,debug_read_inc : std_logic; VARIABLE prim_v,last_v,bib_v : std_logic; VARIABLE vpos_v : unsigned(23 DOWNTO 0); BEGIN IF o_reset_na='0' THEN o_copy<='0'; o_state<=sDISP; o_read_pre<='0'; o_readlev<=0; o_copylev<=0; o_hsp<='0'; ELSIF rising_edge(o_clk) THEN ------------------------------------------------------ o_mode <=mode; -- ? o_run <=run; -- ? o_htotal <=htotal; -- ? o_hsstart<=hsstart; -- ? o_hsend <=hsend; -- ? o_hdisp <=hdisp; -- ? o_hmin <=hmin; -- ? o_hmax <=hmax; -- ? o_vtotal <=vtotal; -- ? o_vsstart<=vsstart; -- ? o_vsend <=vsend; -- ? o_vdisp <=vdisp; -- ? o_vmin <=vmin; -- ? o_vmax <=vmax; -- ? o_hburst<=i_hburst; -- Bursts per line ------------------------------------------------------ -- Test mode o_modex<=o_mode; IF o_mode(2 DOWNTO 0)="111" THEN o_modex(2 DOWNTO 0)<=to_unsigned((o_hcpt/128 + o_vcpt/128) MOD 8,3); END IF; ------------------------------------------------------ -- End DRAM READ o_readack_sync<=avl_readack; -- o_readack_sync2<=o_readack_sync; o_readack<=o_readack_sync XOR o_readack_sync2; debug_read_dec:=o_readack; debug_read_inc:='0'; o_divstart<=o_vs1 AND NOT o_vs0; ------------------------------------------------------ lev_inc_v:='0'; lev_dec_v:='0'; -- acpt : Pixel position within current data word -- dcpt : Destination image position -- hpos : Source image position, fixed point 12.12 -- Force preload 3 lines at top of screen IF o_hs0='1' AND o_hs1='0' THEN IF (o_vmin=0 AND o_vcpt=o_vtotal-3) OR (o_vmin=1 AND o_vcpt=o_vtotal-2) OR (o_vmin=2 AND o_vcpt=o_vtotal-1) OR (o_vmin>2 AND o_vcpt=o_vmin-3) THEN o_fload<=3; END IF; END IF; IF o_hs0='1' AND o_hs1='0' THEN o_hsp<='1'; END IF; CASE o_state IS -------------------------------------------------- WHEN sDISP => IF o_hsp='1' THEN o_state<=sHSYNC; o_hsp<='0'; END IF; -------------------------------------------------- WHEN sHSYNC => o_vpos<=o_vpos_next; o_hbcpt<=0; -- Clear burst counter on line IF (o_vpe='1' AND change(o_vpos,o_vpos_next)) OR o_fload>0 THEN o_state<=sREAD; ELSE o_state<=sDISP; END IF; WHEN sREAD => -- Read a block IF o_readlev<2 THEN lev_inc_v:='1'; o_read_pre<=NOT o_read_pre; debug_read_inc:='1'; o_state <=sWAITREAD; o_bibu<=NOT o_bibu; END IF; prim_v:=to_std_logic(o_hbcpt=0); last_v:=to_std_logic(o_hbcpt=o_hburst-1); bib_v :=o_bibu; o_bib <=o_bibu; IF o_fload=3 THEN o_adrs_pre<=0; o_altp<="1111"; ELSIF o_fload=2 THEN o_adrs_pre<=o_hburst; o_altp<="0100"; ELSIF o_fload=1 THEN o_adrs_pre<=o_hburst*2; o_altp<="1000"; ELSE vpos_v:=o_vpos+x"000800"; o_adrs_pre<=to_integer(vpos_v(23 DOWNTO 12)) * o_hburst + o_hburst; o_altp<=altx(vpos_v(13 DOWNTO 12) + 2); END IF; WHEN sWAITREAD => IF o_readack='1' THEN o_hbcpt<=o_hbcpt+1; IF o_hbcpt=1 THEN o_fload<=o_fload-1; END IF; END IF; END IF; -------------------------------------------------- END CASE; IF HEADER THEN o_adrs<=to_unsigned((o_adrs_pre + o_hbcpt + 1) * N_BURST,32); ELSE o_adrs<=to_unsigned((o_adrs_pre + o_hbcpt) * N_BURST,32); END IF; o_read<=o_read_pre; IF debug_read_inc='1' AND debug_read_dec='0' THEN o_debug_read<=o_debug_read+1; ELSIF debug_read_dec='1' AND debug_read_inc='0' THEN o_debug_read<=o_debug_read-1; END IF; ------------------------------------------------------ -- Copy from buffered memory to pixel lines IF o_copy='0' THEN o_copy1<='0'; IF o_copylev>0 AND o_copy1='0' THEN o_copy<='1'; END IF; o_adturn<='0'; IF o_acpt=0 THEN o_shift(0 TO 127)<=o_dr; ELSIF o_acpt=5 THEN o_shift(8 TO 135)<=o_dr; ELSIF o_acpt=10 THEN o_shift(16 TO 143)<=o_dr; END IF; IF o_primv(0)='1' THEN -- First memcopy of a horizontal line, carriage return ! o_hpos<='0' & o_hdelta(23 DOWNTO 1); --x"000000"; o_hpos_next<=o_hdelta + ('0' & o_hdelta(23 DOWNTO 1)); o_dcpt<=0; o_dshi<=3; o_acpt<=0; END IF; IF o_bibv(0)='0' THEN o_ad<=0; ELSE o_ad<=BLEN; END IF; ELSE IF o_dshi=0 THEN o_dcpt<=(o_dcpt+1) MOD 4096; o_copy1<='1'; END IF; IF o_dshi=0 THEN o_hpos_next<=o_hpos_next+o_hdelta; o_hpos<=o_hpos_next; o_dshi<=0; ELSE -- dshi : Force shift first two pixels of each line o_dshi<=o_dshi-1; END IF; -- Pixels -1 / 0 / 1 / 2 IF change(o_hpos,o_hpos_next) OR o_dshi>0 THEN -- 0 >RGBrgbRGBrgbRGBr -- 1 rgbRGBrgbRGBr -- 2 RGBrgbRGBr -- 3 rgbRGBr -- 4 RGBr -- 5 >r gbRGBrgbRGBrgbRG -- 6 RGBrgbRGBrgbRG -- 7 rgbRGBrgbRG -- 8 RGBrgbRG -- 9 rgbRG -- 10 >RG BrgbRGBrgbRGBrgb -- 11 rgbRGBrgbRGBrgb -- 12 RGBrgbRGBrgb -- 13 rgbRGBrgb -- 14 RGBrgb -- 15 rgb IF o_acpt=15 THEN o_shift(0 TO 127)<=o_dr; ELSIF o_acpt=4 THEN o_shift(0 TO 135)<=o_shift(24 TO 31) & o_dr; ELSIF o_acpt=9 THEN o_shift<=o_shift(24 TO 39) & o_dr; ELSE o_shift(0 TO 119)<=o_shift(24 TO 143); END IF; o_acpt<=(o_acpt+1) MOD 16; o_hpix0<=(r=>o_shift(0 TO 7),g=>o_shift(8 TO 15),b=>o_shift(16 TO 23)); o_hpix1<=o_hpix0; o_hpix2<=o_hpix1; o_hpix3<=o_hpix2; IF o_adturn='1' AND (o_acpt=15 OR o_acpt=9 OR o_acpt=4) AND (((o_ad MOD BLEN=0) AND o_lastv(0)='0') OR ((o_ad MOD BLEN=1) AND o_lastv(0)='1')) THEN o_copy<='0'; lev_dec_v:='1'; o_ad<=(o_ad/BLEN)*BLEN; END IF; IF o_acpt=2 OR o_acpt=7 OR o_acpt=12 THEN o_ad<=(o_ad+1) MOD (2*BLEN); END IF; IF o_ad MOD BLEN=4 THEN o_adturn<='1'; END IF; END IF; END IF; ------------------------------------------------------ -- READLEV : Number of ongoing Avalon Reads IF lev_dec_v='1' AND lev_inc_v='0' THEN o_readlev<=o_readlev-1; ELSIF lev_dec_v='0' AND lev_inc_v='1' THEN o_readlev<=o_readlev+1; END IF; -- COPYLEV : Number of ongoing copies to line buffers IF lev_dec_v='1' AND o_readack='0' THEN o_copylev<=o_copylev-1; ELSIF lev_dec_v='0' AND o_readack='1' THEN o_copylev<=o_copylev+1; END IF; -- FIFOs IF lev_dec_v='1' THEN o_primv(0 TO 1)<=o_primv(1 TO 2); -- First buffer of line o_lastv(0 TO 1)<=o_lastv(1 TO 2); -- Last buffer of line o_bibv (0 TO 1)<=o_bibv (1 TO 2); -- Double buffer select END IF; IF lev_inc_v='1' THEN IF o_readlev=0 OR (o_readlev=1 AND lev_dec_v='1') THEN o_primv(0)<=prim_v; o_lastv(0)<=last_v; o_bibv (0)<=bib_v; ELSIF (o_readlev=1 AND lev_dec_v='0') OR (o_readlev=2 AND lev_dec_v='1') THEN o_primv(1)<=prim_v; o_lastv(1)<=last_v; o_bibv (1)<=bib_v; END IF; o_primv(2)<=prim_v; o_lastv(2)<=last_v; o_bibv (2)<=bib_v; END IF; ------------------------------------------------------ -- FIFO that stores which line buffer should be updated IF lev_dec_v='1' THEN o_altv(0 TO 7)<=o_altv(4 TO 11); END IF; IF o_readack='1' THEN -- push IF o_copylev=0 OR (o_copylev=1 AND lev_dec_v='1') THEN o_altv(0 TO 3)<=o_altp; ELSIF (o_copylev=1 AND lev_dec_v='0') OR (o_copylev=2 AND lev_dec_v='1') THEN o_altv(4 TO 7)<=o_altp; END IF; o_altv(8 TO 11)<=o_altp; END IF; ------------------------------------------------------ END IF; END PROCESS Scalaire; o_alt<=o_altv(0 TO 3); o_h_poly_a<=to_integer(o_modex(0) & NOT o_hpos(11) & o_hpos(10 DOWNTO 12-FRAC)); o_v_poly_a<=to_integer(o_modex(0) & NOT o_vpos2(11) & o_vpos2(10 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); Polikarpov:PROCESS(poly_clk) IS BEGIN IF rising_edge(poly_clk) THEN IF poly_wr='1' THEN poly_tdw(8+9*(3-to_integer(poly_a(1 DOWNTO 0))) DOWNTO 9*(3-to_integer(poly_a(1 DOWNTO 0))))<=poly_dw; END IF; poly_h_wr<=poly_wr AND NOT poly_a(FRAC+2); poly_v_wr<=poly_wr AND poly_a(FRAC+2); poly_a2<=poly_a(NPOLY+FRAC+2 DOWNTO FRAC+3) & poly_a(FRAC+1 DOWNTO 2); IF poly_h_wr='1' THEN o_h_poly(to_integer(poly_a2))<=poly_tdw; END IF; IF poly_v_wr='1' THEN o_v_poly(to_integer(poly_a2))<=poly_tdw; END IF; END IF; END PROCESS Polikarpov; ----------------------------------------------------------------------------- -- Horizontal Scaler HSCAL:PROCESS(o_clk) IS CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); BEGIN IF rising_edge(o_clk) THEN -- Pipeline signals o_hpos1<=o_hpos; o_hpos2<=o_hpos1; o_hpos3<=o_hpos2; o_copy2<=o_copy1; o_copy3<=o_copy2; o_copy4<=o_copy3; IF o_dcpt1>=OHRES THEN o_copy2<='0'; END IF; o_hpix01<=o_hpix3; o_hpix11<=o_hpix2; o_hpix21<=o_hpix1; o_hpix31<=o_hpix0; o_hpix02<=o_hpix01; o_hpix12<=o_hpix11; o_hpix22<=o_hpix21; o_hpix32<=o_hpix31; o_hpix03<=o_hpix02; o_hpix13<=o_hpix12; o_hpix23<=o_hpix22; o_hpix33<=o_hpix32; o_dcpt1<=o_dcpt MOD OHRES; o_dcpt2<=o_dcpt1; o_dcpt3<=o_dcpt2; o_dcpt4<=o_dcpt3; o_dcpt5<=o_dcpt4; -- NEAREST / BILINEAR / SHARP BILINEAR --------------- -- C1 : Pre-calc Sharp Bilinear o_h_sbil_t<=sbil_frac1(o_hpos(11 DOWNTO 0)); -- C2 : Select CASE o_modex(1 DOWNTO 0) IS WHEN "00" => -- Nearest o_h_frac<=near_frac(o_hpos1(11 DOWNTO 0)); WHEN "01" => -- Bilinear o_h_frac<=bil_frac(o_hpos1(11 DOWNTO 0)); WHEN "10" => -- Sharp Bilinear o_h_frac<=sbil_frac2(o_hpos1(11 DOWNTO 0),o_h_sbil_t); WHEN OTHERS => o_h_frac<=near_frac(o_hpos1(11 DOWNTO 0)); END CASE; -- C3 : Opposite frac o_h_frac2 <='0' & o_h_frac; o_h_fracn2<=('1' & Z) - ('0' & o_h_frac); -- C4 : Nearest / Bilinear / Sharp Bilinear o_h_bil_pix<=bil_calc(o_h_frac2,o_h_fracn2,o_hpix13,o_hpix23); -- BICUBIC ------------------------------------------- -- C1 : Bicubic coefficients A,B,C,D o_h_bic_abcd<=bic_calc0(o_hpos(11 DOWNTO 0),o_hpix3,o_hpix2,o_hpix1,o_hpix0); -- C2 : Bicubic calc T1 = X.D + C o_h_bic_abcd1<=o_h_bic_abcd; o_h_bic_tt1<=bic_calc1(o_hpos1(11 DOWNTO 0),o_h_bic_abcd); -- C3 : Bicubic calc T2 = X.T1 + B o_h_bic_abcd2<=o_h_bic_abcd1; o_h_bic_tt2<=bic_calc2(o_hpos2(11 DOWNTO 0),o_h_bic_tt1,o_h_bic_abcd1); -- C4 : Bicubic final Y = X.T2 + A o_h_bic_pix<=bic_calc3(o_hpos3(11 DOWNTO 0),o_h_bic_tt2,o_h_bic_abcd2); -- POLYPHASE ----------------------------------------- -- C1 : Read memory -- C2 : Filter calc o_h_poly_t<=poly_calc1(o_h_poly_dr,o_hpix01,o_hpix11,o_hpix21,o_hpix31); -- C3 : Add o_h_poly_t2<=poly_calc2(o_h_poly_t); -- C4 : Bounding o_h_poly_pix<=poly_calc3(o_h_poly_t2); -- C4 : Select interpoler ---------------------------- o_wadl<=o_dcpt2; o_wr(0)<=o_alt(0) AND o_copy2; o_wr(1)<=o_alt(1) AND o_copy2; o_wr(2)<=o_alt(2) AND o_copy2; o_wr(3)<=o_alt(3) AND o_copy2; CASE o_modex(2 DOWNTO 0) IS WHEN "000" | "001" | "010" => -- Nearest | Bilinear | Sharp Bilinear o_ldw<=o_h_bil_pix; WHEN "011" => -- BiCubic o_ldw<=o_h_bic_pix; WHEN OTHERS => -- PolyPhase o_ldw<=o_h_poly_pix; END CASE; ------------------------------------------------------ END IF; END PROCESS HSCAL; ----------------------------------------------------------------------------- -- Line buffers 4 x OHSIZE x (R+G+B) OLBUF:PROCESS(o_clk) IS BEGIN IF rising_edge(o_clk) THEN -- WRITES IF o_wr(0)='1' THEN o_linem(o_wadl)<=o_ldw; -- -1 END IF; IF o_wr(1)='1' THEN o_line0(o_wadl)<=o_ldw; -- 0 END IF; IF o_wr(2)='1' THEN o_line1(o_wadl)<=o_ldw; -- 1 END IF; IF o_wr(3)='1' THEN o_line2(o_wadl)<=o_ldw; -- 2 END IF; -- READS o_ldrm<=o_linem(o_radl); o_ldr0<=o_line0(o_radl); o_ldr1<=o_line1(o_radl); o_ldr2<=o_line2(o_radl); END IF; END PROCESS OLBUF; o_radl<=(o_hcpt-o_hmin+OHRES) MOD OHRES; xxx_vposi<=to_integer(o_vpos(23 DOWNTO 12)); -- Simu! ----------------------------------------------------------------------------- -- Output video sweep OSWEEP:PROCESS(o_clk) IS BEGIN IF rising_edge(o_clk) THEN IF o_ce='1' THEN -- Output pixels count IF o_hcpt=o_vtotal-1 AND (NOT SYNCHRO OR mode(4)='0')) OR (o_dosync='1' AND SYNCHRO AND mode(4)='1') THEN o_vcpt<=0; o_dosync<='0'; ELSE o_vcpt<=(o_vcpt+1) MOD 4096; END IF; END IF; IF o_icnt=o_dsync THEN o_dosync<='1'; END IF; -- Input pixels position IF o_hs0='1' AND o_hs1='0' THEN o_vpos_next<=o_vpos_next+o_vdelta; IF (o_vcpt=o_vtotal-1 AND o_vmin=0) OR (o_vcpt=o_vmin-1 AND o_vmin>0) THEN o_vpos_next<='0' & o_vdelta(23 DOWNTO 1); END IF; END IF; IF o_vcpt=vmin-2 AND vmin>2) OR ((o_vcpt>=o_vtotal-1 AND vmin=1) OR o_vcpt>0) OR ((o_vcpt>=o_vtotal-2 AND vmin=0) OR o_vcpt>0)) THEN o_vpe<='1'; ELSE o_vpe<='0'; END IF; o_de0<=to_std_logic(o_hcpt=o_hmin AND o_hcpt<=o_hmax AND o_vcpt>=o_vmin AND o_vcpt<=o_vmax); o_hs0<=to_std_logic(o_hcpt>=o_hsstart AND o_hcpt=o_vsstart AND o_vcpt=o_osdelay THEN o_dsync<=o_isdelay-o_osdelay; ELSE o_dsync<=(o_isdelay+o_idelay-o_osdelay) MOD (4096*4096); END IF; -- Measure total input image size o_ivs<=i_vs; -- o_ivs2<=o_ivs; o_ivs3<=o_ivs2; IF o_ivs2='1' AND o_ivs3='0' THEN o_icnt<=0; o_idelay<=o_icnt; o_oudb<='1'; ELSE o_icnt<=(o_icnt+1) MOD (4096*4096); END IF; -- Measure delay between input Vsync and third displayed line o_isyncline<=i_syncline; -- o_isyncline2<=o_isyncline; IF o_isyncline2='1' AND o_oudb='1' THEN o_oudb<='0'; o_isdelay<=o_icnt; END IF; -- Measure delay between output Vsync and first displayed line IF o_vs0='1' AND o_vs1='0' THEN o_ocnt<=0; o_ouda<='1'; ELSE o_ocnt<=(o_ocnt+1) MOD (4096*4096); END IF; IF o_pe0='1' AND o_ouda='1' THEN o_osdelay<=o_ocnt; o_ouda<='0'; END IF; END IF; END IF; END PROCESS OSWEEP; ----------------------------------------------------------------------------- -- Vertical Scaler VSCAL:PROCESS(o_clk) IS CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); BEGIN IF rising_edge(o_clk) THEN IF o_ce='1' THEN -- Pipeline signals o_hs1<=o_hs0; o_hs2<=o_hs1; o_hs3<=o_hs2; o_hs4<=o_hs3; o_vs1<=o_vs0; o_vs2<=o_vs1; o_vs3<=o_vs2; o_vs4<=o_vs3; o_de1<=o_de0; o_de2<=o_de1; o_de3<=o_de2; o_de4<=o_de3; o_pe1<=o_pe0; o_pe2<=o_pe1; o_pe3<=o_pe2; o_pe4<=o_pe3; -- CYCLE 1 ----------------------------------------- -- Read mem -- CYCLE 2 ----------------------------------------- -- Lines reordering -- TOP IF o_vpos(23)='1' THEN o_vpos2<=(OTHERS =>'0'); o_vpos2<=(OTHERS =>'0'); ELSE o_vpos2<=o_vpos; o_vpos2<=o_vpos+x"000800"; END IF; -- BOTTOM -> TODO CASE o_vpos2(13 DOWNTO 11) IS -- 00 01 10 11 WHEN "010" | "001" => -- L3 is bottom o_vpixm2<=o_ldrm; o_vpix02<=o_ldr0; o_vpix12<=o_ldr1; o_vpix22<=o_ldr2; WHEN "100" | "011" => -- L0 is bottom o_vpixm2<=o_ldr0; o_vpix02<=o_ldr1; o_vpix12<=o_ldr2; o_vpix22<=o_ldrm; WHEN "110" | "101" => -- L1 is bottom o_vpixm2<=o_ldr1; o_vpix02<=o_ldr2; o_vpix12<=o_ldrm; o_vpix22<=o_ldr0; WHEN OTHERS => -- L2 is bottom o_vpixm2<=o_ldr2; o_vpix02<=o_ldrm; o_vpix12<=o_ldr0; o_vpix22<=o_ldr1; END CASE; -- CYCLE 3 ----------------------------------------- o_vpixm3<=o_vpixm2; o_vpix03<=o_vpix02; o_vpix04<=o_vpix03; o_vpix13<=o_vpix12; o_vpix14<=o_vpix13; o_vpix23<=o_vpix22; -- NEAREST / BILINEAR / SHARP BILINEAR ------------- -- C3 : Pre-calc Sharp Bilinear o_v_sbil_t<=sbil_frac1(o_vpos2(11 DOWNTO 0)); -- C4 : Select CASE o_modex(1 DOWNTO 0) IS WHEN "00" => -- Nearest o_v_frac<=near_frac(o_vpos2(11 DOWNTO 0)); WHEN "01" => -- Bilinear o_v_frac<=bil_frac(o_vpos2(11 DOWNTO 0)); WHEN "10" => -- Sharp Bilinear o_v_frac<=sbil_frac2(o_vpos2(11 DOWNTO 0),o_v_sbil_t); WHEN OTHERS => o_v_frac<=near_frac(o_vpos2(11 DOWNTO 0)); END CASE; o_v_frac2 <='0' & o_v_frac; o_v_fracn2<=('1' & Z) - ('0' & o_v_frac); -- C5 : Nearest / Bilinear / Sharp Bilinear o_v_bil_pix<=bil_calc(o_v_frac2,o_v_fracn2,o_vpix04,o_vpix14); -- BICUBIC ----------------------------------------- -- C3 : Bicubic coefficients A,B,C,D o_v_bic_abcd<=bic_calc0(o_vpos2(11 DOWNTO 0),o_vpixm2,o_vpix02,o_vpix12,o_vpix22); -- C4 : Bicubic calc T1 = X.D + C o_v_bic_abcd1<=o_v_bic_abcd; o_v_bic_tt1<=bic_calc1(o_vpos2(11 DOWNTO 0),o_v_bic_abcd); -- C5 : Bicubic calc T2 = X.T1 + B o_v_bic_abcd2<=o_v_bic_abcd1; o_v_bic_tt2<=bic_calc2(o_vpos2(11 DOWNTO 0),o_v_bic_tt1,o_v_bic_abcd1); -- C6 : Bicubic final Y = X.T2 + A o_v_bic_pix<=bic_calc3(o_vpos2(11 DOWNTO 0),o_v_bic_tt2,o_v_bic_abcd2); -- POLYPHASE --------------------------------------- -- C3 : Read memory -- C4 : Filter calc o_v_poly_t<=poly_calc1(o_v_poly_dr,o_vpixm3,o_vpix03,o_vpix13,o_vpix23); -- C5 : Add o_v_poly_t2<=poly_calc2(o_v_poly_t); -- C6 : Bounding o_v_poly_pix<=poly_calc3(o_v_poly_t2); -- CYCLE 6 ----------------------------------------- o_hs<=o_hs4; o_vs<=o_vs4; o_de<=o_de4; CASE o_modex(2 DOWNTO 0) IS WHEN "000" | "001" | "010" => -- Nearest | Bilinear | Sharp Bilinear o_r<=o_v_bil_pix.r; o_g<=o_v_bil_pix.g; o_b<=o_v_bil_pix.b; WHEN "011" => -- BiCubic o_r<=o_v_bic_pix.r; o_g<=o_v_bic_pix.g; o_b<=o_v_bic_pix.b; WHEN OTHERS => -- Polyphase o_r<=o_v_poly_pix.r; o_g<=o_v_poly_pix.g; o_b<=o_v_poly_pix.b; END CASE; IF o_pe4='0' THEN o_r<=x"00"; -- Border colour o_g<=x"00"; o_b<=x"00"; END IF; 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; ---------------------------------------------------- END IF; END IF; END PROCESS VSCAL; ----------------------------------------------------------------------------- -- 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_hcpt2<=o_hcpt; o_hcpt3<=o_hcpt2; o_hcpt4<=o_hcpt3; 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_hcpt/8)*5) MOD 256; IF o_hcpt2<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_hcpt4 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(o_hburst,8)) & -- 2 CC(' ') & -- 1 CN(to_unsigned(o_ihsize,12)) & -- 3 CC(' ') & -- 1 CN(to_unsigned(o_ivsize,12)) & -- 3 CC(' ') & -- 1 CN(to_unsigned(o_hmin,12)) & -- 3 CC(' ') & -- 1 CN(to_unsigned(o_hmax,12)) & -- 3 CC(' ') & -- 1 CN(to_unsigned(o_vmin,12)) & -- 3 CC(' ') & -- 1 CN(to_unsigned(o_vmax,12)) & -- 3 CC(' ') & -- 1 CN(to_unsigned(i_intercnt,4)) & -- 1 CC(' ') & -- 1 CN(to_unsigned(avl_i_buf,4)) & -- 1 CC(' ') & -- 1 CN(to_unsigned(avl_o_buf,4)) ; -- 1 o_debug_vin1<= CN(to_unsigned(o_debug_read,4)) & -- 1 CN(to_unsigned(avl_debug_write,4)) & -- 1 CC(' ') & -- 1 CN(o_hdelta(11 DOWNTO 0)) & -- 3 CC(' ') & -- 1 CN(o_vdelta(11 DOWNTO 0)) & -- 3 CC(' ') & -- 1 CN(i_ctotal) & -- 8 CC(' ') & -- 1 CN(to_unsigned(o_isdelay,20)) & -- 5 CC(' ') & -- 1 CN(to_unsigned(o_idelay,24)); -- 6 ----------------------------------------------------------------------------- END ARCHITECTURE rtl;