diff --git a/MacPlus.sv b/MacPlus.sv index 48282c4..8b6e9ac 100644 --- a/MacPlus.sv +++ b/MacPlus.sv @@ -52,13 +52,14 @@ module emu output VGA_F1, output [1:0] VGA_SL, output VGA_SCALER, // Force VGA scaler + output VGA_DISABLE, // analog out is off input [11:0] HDMI_WIDTH, input [11:0] HDMI_HEIGHT, output HDMI_FREEZE, `ifdef MISTER_FB - // Use framebuffer in DDRAM (USE_FB=1 in qsf) + // Use framebuffer in DDRAM // FB_FORMAT: // [2:0] : 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp // [3] : 0=16bits 565 1=16bits 1555 @@ -185,6 +186,7 @@ assign LED_POWER = 0; assign BUTTONS = 0; assign VGA_SCALER= 0; assign HDMI_FREEZE = 0; +assign VGA_DISABLE = 0; wire [1:0] ar = status[8:7]; video_freak video_freak diff --git a/sys/ascal.vhd b/sys/ascal.vhd index aa2af61..6f085e0 100644 --- a/sys/ascal.vhd +++ b/sys/ascal.vhd @@ -112,2760 +112,2803 @@ USE ieee.numeric_std.ALL; -- N_BURST : Burst size in bytes. Power of two. ENTITY ascal IS - GENERIC ( - MASK : unsigned(7 DOWNTO 0) :=x"FF"; - RAMBASE : unsigned(31 DOWNTO 0); - RAMSIZE : unsigned(31 DOWNTO 0) := x"0080_0000"; -- =8MB - INTER : boolean := true; - HEADER : boolean := true; - DOWNSCALE : boolean := true; - BYTESWAP : boolean := true; - PALETTE : boolean := true; - PALETTE2 : boolean := true; - ADAPTIVE : boolean := true; - DOWNSCALE_NN : boolean := false; - FRAC : natural RANGE 4 TO 8 :=4; - OHRES : natural RANGE 1 TO 4096 :=2048; - IHRES : natural RANGE 1 TO 2048 :=2048; - N_DW : natural RANGE 64 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; -- H sync - i_vs : IN std_logic; -- V 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 sync - o_vs : OUT std_logic; -- V sync - o_de : OUT std_logic; -- Display Enable - o_vbl : OUT std_logic; -- V blank - o_brd : OUT std_logic; -- border enable - o_ce : IN std_logic; -- Clock Enable - o_clk : IN std_logic; -- Output clock - - -- Border colour R G B - o_border : IN unsigned(23 DOWNTO 0) := x"000000"; - - ------------------------------------ - -- Framebuffer mode - o_fb_ena : IN std_logic :='0'; -- Enable Framebuffer Mode - o_fb_hsize : IN natural RANGE 0 TO 4095 :=0; - o_fb_vsize : IN natural RANGE 0 TO 4095 :=0; - o_fb_format : IN unsigned(5 DOWNTO 0) :="000100"; - o_fb_base : IN unsigned(31 DOWNTO 0) :=x"0000_0000"; - o_fb_stride : IN unsigned(13 DOWNTO 0) :=(OTHERS =>'0'); - - -- Framebuffer palette in 8bpp mode - pal1_clk : IN std_logic :='0'; - pal1_dw : IN unsigned(47 DOWNTO 0) :=x"000000000000"; -- R1 G1 B1 R0 G0 B0 - pal1_dr : OUT unsigned(47 DOWNTO 0) :=x"000000000000"; - pal1_a : IN unsigned(6 DOWNTO 0) :="0000000"; -- Colour index/2 - pal1_wr : IN std_logic :='0'; + GENERIC ( + MASK : unsigned(7 DOWNTO 0) :=x"FF"; + RAMBASE : unsigned(31 DOWNTO 0); + RAMSIZE : unsigned(31 DOWNTO 0) := x"0080_0000"; -- =8MB + INTER : boolean := true; + HEADER : boolean := true; + DOWNSCALE : boolean := true; + BYTESWAP : boolean := true; + PALETTE : boolean := true; + PALETTE2 : boolean := true; + ADAPTIVE : boolean := true; + DOWNSCALE_NN : boolean := false; + FRAC : natural RANGE 4 TO 8 :=4; + OHRES : natural RANGE 1 TO 4096 :=2048; + IHRES : natural RANGE 1 TO 2048 :=2048; + N_DW : natural RANGE 64 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; -- H sync + i_vs : IN std_logic; -- V 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 - pal_n : IN std_logic :='0'; + ------------------------------------ + -- 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 sync + o_vs : OUT std_logic; -- V sync + o_de : OUT std_logic; -- Display Enable + o_vbl : OUT std_logic; -- V blank + o_brd : OUT std_logic; -- border enable + o_ce : IN std_logic; -- Clock Enable + o_clk : IN std_logic; -- Output clock - pal2_clk : IN std_logic :='0'; - pal2_dw : IN unsigned(23 DOWNTO 0) :=x"000000"; -- R G B - pal2_dr : OUT unsigned(23 DOWNTO 0) :=x"000000"; - pal2_a : IN unsigned(7 DOWNTO 0) :="00000000"; -- Colour index - pal2_wr : IN std_logic :='0'; - - ------------------------------------ - -- Low lag PLL tuning - o_lltune : OUT unsigned(15 DOWNTO 0); - - ------------------------------------ - -- Input video parameters - iauto : IN std_logic :='1'; -- 1=Autodetect image size 0=Choose window - himin : IN natural RANGE 0 TO 4095 :=0; -- MIN < MAX, MIN >=0, MAX < DISP - himax : IN natural RANGE 0 TO 4095 :=0; - vimin : IN natural RANGE 0 TO 4095 :=0; - vimax : IN natural RANGE 0 TO 4095 :=0; + -- Border colour R G B + o_border : IN unsigned(23 DOWNTO 0) := x"000000"; - -- Detected input image size - i_hdmax : OUT natural RANGE 0 TO 4095; - i_vdmax : OUT natural RANGE 0 TO 4095; - - -- Output video parameters - run : IN std_logic :='1'; -- 1=Enable output image. 0=No image - freeze : IN std_logic :='0'; -- 1=Disable framebuffer writes - mode : IN unsigned(4 DOWNTO 0); - -- 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; -- 0 <= hmin < hmax < hdisp - 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; -- 0 <= vmin < vmax < vdisp - - -- Scaler format. 00=16bpp 565, 01=24bpp 10=32bpp - format : IN unsigned(1 DOWNTO 0) :="01"; - - ------------------------------------ - -- Polyphase filter coefficients - -- Order : - -- [Horizontal] [Vertical] [Horizontal2] [Vertical2] - -- [0]...[2**FRAC-1] - -- [-1][0][1][2] - poly_clk : IN std_logic; - poly_dw : IN unsigned(9 DOWNTO 0); - poly_a : IN unsigned(FRAC+3 DOWNTO 0); - poly_wr : IN std_logic; - - ------------------------------------ - -- 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 - ); + ------------------------------------ + -- Framebuffer mode + o_fb_ena : IN std_logic :='0'; -- Enable Framebuffer Mode + o_fb_hsize : IN natural RANGE 0 TO 4095 :=0; + o_fb_vsize : IN natural RANGE 0 TO 4095 :=0; + o_fb_format : IN unsigned(5 DOWNTO 0) :="000100"; + o_fb_base : IN unsigned(31 DOWNTO 0) :=x"0000_0000"; + o_fb_stride : IN unsigned(13 DOWNTO 0) :=(OTHERS =>'0'); + + -- Framebuffer palette in 8bpp mode + pal1_clk : IN std_logic :='0'; + pal1_dw : IN unsigned(47 DOWNTO 0) :=x"000000000000"; -- R1 G1 B1 R0 G0 B0 + pal1_dr : OUT unsigned(47 DOWNTO 0) :=x"000000000000"; + pal1_a : IN unsigned(6 DOWNTO 0) :="0000000"; -- Colour index/2 + pal1_wr : IN std_logic :='0'; + + pal_n : IN std_logic :='0'; + + pal2_clk : IN std_logic :='0'; + pal2_dw : IN unsigned(23 DOWNTO 0) :=x"000000"; -- R G B + pal2_dr : OUT unsigned(23 DOWNTO 0) :=x"000000"; + pal2_a : IN unsigned(7 DOWNTO 0) :="00000000"; -- Colour index + pal2_wr : IN std_logic :='0'; + + ------------------------------------ + -- Low lag PLL tuning + o_lltune : OUT unsigned(15 DOWNTO 0); + + ------------------------------------ + -- Input video parameters + iauto : IN std_logic :='1'; -- 1=Autodetect image size 0=Choose window + himin : IN natural RANGE 0 TO 4095 :=0; -- MIN < MAX, MIN >=0, MAX < DISP + himax : IN natural RANGE 0 TO 4095 :=0; + vimin : IN natural RANGE 0 TO 4095 :=0; + vimax : IN natural RANGE 0 TO 4095 :=0; + + -- Detected input image size + i_hdmax : OUT natural RANGE 0 TO 4095; + i_vdmax : OUT natural RANGE 0 TO 4095; + + -- Output video parameters + run : IN std_logic :='1'; -- 1=Enable output image. 0=No image + freeze : IN std_logic :='0'; -- 1=Disable framebuffer writes + mode : IN unsigned(4 DOWNTO 0); + -- 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; -- 0 <= hmin < hmax < hdisp + 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; -- 0 <= vmin < vmax < vdisp + vrr : IN std_logic := '0'; + vrrmax : IN natural RANGE 0 TO 4095 := 0; + + -- Scaler format. 00=16bpp 565, 01=24bpp 10=32bpp + format : IN unsigned(1 DOWNTO 0) :="01"; + + ------------------------------------ + -- Polyphase filter coefficients + -- Order : + -- [Horizontal] [Vertical] [Horizontal2] [Vertical2] + -- [0]...[2**FRAC-1] + -- [-1][0][1][2] + poly_clk : IN std_logic; + poly_dw : IN unsigned(9 DOWNTO 0); + poly_a : IN unsigned(FRAC+3 DOWNTO 0); + poly_wr : IN std_logic; + + ------------------------------------ + -- 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=64 OR N_DW=128 REPORT "DW" SEVERITY failure; - + ASSERT N_DW=64 OR N_DW=128 REPORT "DW" SEVERITY failure; + END ENTITY ascal; --############################################################################## ARCHITECTURE rtl OF ascal IS - - CONSTANT MASK_NEAREST : natural :=0; - CONSTANT MASK_BILINEAR : natural :=1; - CONSTANT MASK_SHARP_BILINEAR : natural :=2; - CONSTANT MASK_BICUBIC : natural :=3; - CONSTANT MASK_POLY : natural :=4; - - ---------------------------------------------------------- - 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 - - ---------------------------------------------------------- - 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; - TYPE arr_pixq IS ARRAY(natural RANGE <>) OF arr_pix(0 TO 3); - ATTRIBUTE ramstyle : string; - - SUBTYPE uint12 IS natural RANGE 0 TO 4095; - SUBTYPE uint13 IS natural RANGE 0 TO 8191; - - TYPE arr_uv48 IS ARRAY (natural RANGE <>) OF unsigned(47 DOWNTO 0); - TYPE arr_uv24 IS ARRAY (natural RANGE <>) OF unsigned(23 DOWNTO 0); - TYPE arr_uv40 IS ARRAY (natural RANGE <>) OF unsigned(39 DOWNTO 0); - TYPE arr_int9 IS ARRAY (natural RANGE <>) OF integer RANGE -256 TO 255; - TYPE arr_uint12 IS ARRAY (natural RANGE <>) OF uint12; - TYPE arr_frac IS ARRAY (natural RANGE <>) OF unsigned(11 DOWNTO 0); - TYPE arr_div IS ARRAY (natural RANGE <>) OF unsigned(20 DOWNTO 0); - ---------------------------------------------------------- - -- Input image - 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_vcpt : uint12; - SIGNAL i_iauto : std_logic; - SIGNAL i_mode : unsigned(4 DOWNTO 0); - SIGNAL i_format : unsigned(1 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_vs_pre,i_fl_pre : std_logic; - SIGNAL i_de_delay : natural RANGE 0 TO 31; - SIGNAL i_intercnt : natural RANGE 0 TO 3; - SIGNAL i_inter,i_half,i_flm : std_logic; - SIGNAL i_write,i_wreq,i_alt,i_line,i_wline,i_wline_mem : std_logic; - SIGNAL i_walt,i_walt_mem,i_wreq_mem : std_logic; - SIGNAL i_wdelay : natural RANGE 0 TO 7; - SIGNAL i_push,i_pushend,i_pushend2 : std_logic; - SIGNAL i_eol : 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_endframe0,i_endframe1,i_vss : 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,i_wadrs,i_wadrs_mem : unsigned(31 DOWNTO 0); - SIGNAL i_reset_na : std_logic; - SIGNAL i_hnp,i_vnp : std_logic; - SIGNAL i_mem : arr_pix(0 TO IHRES-1); -- Downscale line buffer - ATTRIBUTE ramstyle OF i_mem : SIGNAL IS "no_rw_check"; - SIGNAL i_ohsize,i_ovsize : uint12; - 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 : 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,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 : std_logic; - - ---------------------------------------------------------- - -- Avalon - TYPE type_avl_state IS (sIDLE,sWRITE,sREAD); - SIGNAL avl_state : type_avl_state; - 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_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,avl_wline,avl_rline : std_logic; - SIGNAL avl_dw,avl_dr : unsigned(N_DW-1 DOWNTO 0); - SIGNAL avl_wr : std_logic; - SIGNAL avl_readdataack,avl_readack : std_logic; - SIGNAL avl_radrs,avl_wadrs : 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; - SIGNAL avl_fb_ena : std_logic; - - FUNCTION buf_next(a,b : natural RANGE 0 TO 2; freeze : std_logic := '0') RETURN natural IS - BEGIN - IF (freeze='1') THEN RETURN a; END IF; - 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; - base : unsigned(31 DOWNTO 0); - size : unsigned(31 DOWNTO 0)) RETURN unsigned IS - BEGIN - IF b=1 THEN RETURN base+size; END IF; - IF b=2 THEN RETURN base+(size(30 DOWNTO 0) & '0'); END IF; - RETURN base; - END FUNCTION; - - ---------------------------------------------------------- - -- Output - SIGNAL o_run : std_logic; - SIGNAL o_freeze : std_logic; - SIGNAL o_mode,o_hmode,o_vmode : unsigned(4 DOWNTO 0); - SIGNAL o_format : unsigned(5 DOWNTO 0); - SIGNAL o_fb_pal_dr : unsigned(23 DOWNTO 0); - SIGNAL o_fb_pal_dr2 : unsigned(23 DOWNTO 0); - SIGNAL o_fb_pal_dr_x2 : unsigned(47 DOWNTO 0); - SIGNAL pal_idx: unsigned(7 DOWNTO 0); - SIGNAL pal_idx_lsb: std_logic; - SIGNAL pal1_mem : arr_uv48(0 TO 127); - SIGNAL pal2_mem : arr_uv24(0 TO 255); - ATTRIBUTE ramstyle of pal1_mem : signal is "no_rw_check"; - ATTRIBUTE ramstyle of pal2_mem : signal is "no_rw_check"; - SIGNAL o_htotal,o_hsstart,o_hsend : uint12; - SIGNAL o_hmin,o_hmax,o_hdisp,o_v_hmin_adj : uint12; - SIGNAL o_hsize,o_vsize : uint12; - 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_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 enum_o_state IS (sDISP,sHSYNC,sREAD,sWAITREAD); - SIGNAL o_state : enum_o_state; - TYPE enum_o_copy IS (sWAIT,sSHIFT,sCOPY); - SIGNAL o_copy : enum_o_copy; - SIGNAL o_pshift : natural RANGE 0 TO 15; - SIGNAL o_readack,o_readack_sync,o_readack_sync2 : std_logic; - SIGNAL o_readdataack,o_readdataack_sync,o_readdataack_sync2 : std_logic; - SIGNAL o_copyv : unsigned(0 TO 12); - SIGNAL o_adrs : unsigned(31 DOWNTO 0); -- Avalon address - SIGNAL o_adrs_pre : natural RANGE 0 TO 2**24-1; - SIGNAL o_stride : unsigned(13 DOWNTO 0); - SIGNAL o_adrsa,o_adrsb,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); - SIGNAL o_shift : unsigned(0 TO N_DW+15); - SIGNAL o_sh,o_sh1,o_sh2,o_sh3,o_sh4 : std_logic; - SIGNAL o_reset_na : std_logic; - SIGNAL o_dpram : arr_dw(0 TO BLEN*2-1); - ATTRIBUTE ramstyle OF o_dpram : SIGNAL IS "no_rw_check"; - SIGNAL o_line0,o_line1,o_line2,o_line3 : arr_pix(0 TO OHRES-1); - ATTRIBUTE ramstyle OF o_line0 : SIGNAL IS "no_rw_check"; - ATTRIBUTE ramstyle OF o_line1 : SIGNAL IS "no_rw_check"; - ATTRIBUTE ramstyle OF o_line2 : SIGNAL IS "no_rw_check"; - ATTRIBUTE ramstyle OF o_line3 : SIGNAL IS "no_rw_check"; - SIGNAL o_wadl,o_radl0,o_radl1,o_radl2,o_radl3 : natural RANGE 0 TO OHRES-1; - SIGNAL o_ldw,o_ldr0,o_ldr1,o_ldr2,o_ldr3 : type_pix; - SIGNAL o_wr : unsigned(3 DOWNTO 0); - SIGNAL o_hcpt,o_vcpt,o_vcpt_pre,o_vcpt_pre2,o_vcpt_pre3 : uint12; - SIGNAL o_ihsize,o_ihsizem,o_ivsize : uint12; - SIGNAL o_ihsize_temp, o_ihsize_temp2 : natural RANGE 0 TO 32767; + CONSTANT MASK_NEAREST : natural :=0; + CONSTANT MASK_BILINEAR : natural :=1; + CONSTANT MASK_SHARP_BILINEAR : natural :=2; + CONSTANT MASK_BICUBIC : natural :=3; + CONSTANT MASK_POLY : natural :=4; - SIGNAL o_vfrac : unsigned(11 DOWNTO 0); - SIGNAL o_hfrac : arr_frac(0 TO 8); - ATTRIBUTE ramstyle OF o_hfrac : SIGNAL IS "logic"; -- avoid blockram shift register + ---------------------------------------------------------- + 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; - 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,o_end : unsigned(0 TO 9); - SIGNAL o_hsp,o_vss : std_logic; - SIGNAL o_vcarrym,o_prim : boolean; - 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,o_acpt1,o_acpt2,o_acpt3,o_acpt4 : natural RANGE 0 TO 15; -- Alternance pixels FIFO - SIGNAL o_dshi : natural RANGE 0 TO 3; - SIGNAL o_first,o_last,o_last1,o_last2 : std_logic; - SIGNAL o_lastt1,o_lastt2,o_lastt3,o_lastt4 : std_logic; - SIGNAL o_alt,o_altx : unsigned(3 DOWNTO 0); - SIGNAL o_hdown,o_vdown : std_logic; - SIGNAL o_primv,o_lastv,o_bibv : unsigned(0 TO 2); - TYPE arr_uint4 IS ARRAY (natural RANGE <>) OF natural RANGE 0 TO 15; - SIGNAL o_off : arr_uint4(0 TO 2); - SIGNAL o_bibu : std_logic :='0'; - SIGNAL o_dcptv : arr_uint12(1 TO 12); - SIGNAL o_dcpt : uint12; - SIGNAL o_hpixs,o_hpix0,o_hpix1,o_hpix2,o_hpix3 : type_pix; - SIGNAL o_hpixq : arr_pixq(2 TO 6); - ATTRIBUTE ramstyle OF o_hpixq : SIGNAL IS "logic"; -- avoid blockram shift register - SIGNAL o_vpixq : arr_pix(0 TO 3); - SIGNAL o_vpix_outer : arr_pix(0 TO 2); - SIGNAL o_vpix_inner : arr_pix(0 TO 5); + ---------------------------------------------------------- + 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 - -- ATTRIBUTE ramstyle OF o_hpixq : SIGNAL IS "logic"; - - - SIGNAL o_vpe : std_logic; - SIGNAL o_div : arr_div(0 TO 2); --uint12; - SIGNAL o_dir : arr_frac(0 TO 2); - ATTRIBUTE ramstyle OF o_div, o_dir : SIGNAL IS "logic"; -- avoid blockram shift register - 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_vacptl : unsigned(1 DOWNTO 0); - - ----------------------------------------------------------------------------- - FUNCTION shift_ishift(shift : unsigned(0 TO 119); - pix : type_pix; - format : unsigned(1 DOWNTO 0)) RETURN unsigned IS - BEGIN - CASE format IS - WHEN "01" => -- 24bpp - RETURN shift(24 TO 119) & pix.r & pix.g & pix.b; - WHEN "10" => -- 32bpp - RETURN shift(32 TO 119) & pix.r & pix.g & pix.b & x"00"; - WHEN OTHERS => -- 16bpp 565 - RETURN shift(16 TO 119) & - pix.g(4 DOWNTO 2) & pix.r(7 DOWNTO 3) & - pix.b(7 DOWNTO 3) & pix.g(7 DOWNTO 5); - END CASE; - END FUNCTION; - - FUNCTION shift_ipack(i_dw : unsigned(N_DW-1 DOWNTO 0); - acpt : natural RANGE 0 TO 15; - shift : unsigned(0 TO 119); - pix : type_pix; - format : unsigned(1 DOWNTO 0)) RETURN unsigned IS - VARIABLE dw : unsigned(N_DW-1 DOWNTO 0); - BEGIN - dw:=i_dw; - CASE format IS - WHEN "01" => -- 24bpp - IF N_DW=128 THEN - IF acpt=5 THEN dw:=shift(0 TO 119) & pix.r; - ELSIF acpt=10 THEN dw:=shift(8 TO 119) & pix.r & pix.g; - ELSIF acpt=15 THEN dw:=shift(16 TO 119) & pix.r & pix.g & pix.b; - END IF; - ELSE -- N_DW=64 - IF (acpt MOD 8)=2 THEN dw:=shift(72 TO 119) & pix.r & pix.g; - ELSIF (acpt MOD 8)=5 THEN dw:=shift(64 TO 119) & pix.r; - ELSIF (acpt MOD 8)=7 THEN dw:=shift(80 TO 119) & pix.r & pix.g & pix.b; - END IF; - END IF; - WHEN "10" => -- 32bpp - IF (N_DW=128 AND (acpt MOD 4)=3) OR (N_DW=64 AND (acpt MOD 8)=7) THEN - dw:=shift(128-N_DW+24 TO 119) & pix.r & pix.g & pix.b & x"00"; - END IF; - WHEN OTHERS => -- 16bpp 565 - IF (N_DW=128 AND (acpt MOD 8)=7) OR (N_DW=64 AND (acpt MOD 4)=3) THEN - dw:=shift(128-N_DW+8 TO 119) & pix.g(4 DOWNTO 2) & pix.r(7 DOWNTO 3) & - pix.b(7 DOWNTO 3) & pix.g(7 DOWNTO 5); - END IF; - END CASE; - RETURN dw; - END FUNCTION; - - FUNCTION shift_inext (acpt : natural RANGE 0 TO 15; - format : unsigned(1 DOWNTO 0)) RETURN boolean IS - BEGIN - CASE format IS - WHEN "01" => -- 24bpp - RETURN (N_DW=128 AND (acpt=5 OR acpt=10 OR acpt=15)) OR - (N_DW=64 AND ((acpt MOD 8)=2 OR (acpt MOD 8)=5 OR (acpt MOD 8)=7)); - WHEN "10" => -- 32bpp - RETURN (N_DW=128 AND ((acpt MOD 4)=3)) OR - (N_DW=64 AND ((acpt MOD 2)=1)); - WHEN OTHERS => -- 16bpp - RETURN (N_DW=128 AND ((acpt MOD 8)=7)) OR - (N_DW=64 AND ((acpt MOD 4)=3)); - END CASE; - END FUNCTION; - - FUNCTION shift_opack(acpt : natural RANGE 0 TO 15; - shift : unsigned(0 TO N_DW+15); - dr : unsigned(N_DW-1 DOWNTO 0); - format : unsigned(5 DOWNTO 0)) RETURN unsigned IS - VARIABLE shift_v : unsigned(0 TO N_DW+15); - BEGIN - CASE format(2 DOWNTO 0) IS - WHEN "011" => -- 8bpp - IF (N_DW=128 AND acpt=0) OR (N_DW=64 AND (acpt MOD 8)=0) THEN - shift_v:=dr & dr(15 DOWNTO 0); - ELSE - shift_v:=shift(8 TO N_DW+15) & dr(7 DOWNTO 0); - END IF; - - WHEN "100" => -- 16bpp - IF (N_DW=128 AND (acpt MOD 8)=0) OR (N_DW=64 AND (acpt MOD 4)=0) THEN - shift_v:=dr & dr(15 DOWNTO 0); - ELSE - shift_v:=shift(16 TO N_DW+15) & dr(15 DOWNTO 0); - END IF; - - WHEN "101" => -- 24bpp - IF N_DW=128 THEN - IF acpt=0 THEN - shift_v:=dr & dr(15 DOWNTO 0); - ELSIF acpt=5 THEN - shift_v:=shift(24 TO 31) & dr & dr(7 DOWNTO 0); - ELSIF acpt=10 THEN - shift_v:=shift(24 TO 39) & dr; - ELSE - shift_v:=shift(24 TO N_DW+15) & dr(23 DOWNTO 0); - END IF; - ELSE -- N_DW=64 - IF (acpt MOD 8)=0 THEN - shift_v:=dr & dr(15 DOWNTO 0); - ELSIF (acpt MOD 8)=2 THEN - shift_v:=shift(24 TO 39) & dr; - ELSIF (acpt MOD 8)=5 THEN - shift_v:=shift(24 TO 31) & dr & dr(7 DOWNTO 0); - ELSE - shift_v:=shift(24 TO N_DW+15) & dr(23 DOWNTO 0); - END IF; - END IF; - WHEN OTHERS => -- 32bpp - IF (N_DW=128 AND (acpt MOD 4)=0) OR (N_DW=64 AND (acpt MOD 2)=0) THEN - shift_v:=dr & dr(15 DOWNTO 0); - ELSE - shift_v:=shift(32 TO N_DW+15) & dr(31 DOWNTO 0); - END IF; - END CASE; - RETURN shift_v; - END FUNCTION; - - FUNCTION shift_onext (acpt : natural RANGE 0 TO 15; - format : unsigned(5 DOWNTO 0)) RETURN boolean IS - BEGIN - CASE format(2 DOWNTO 0) IS - WHEN "011" => -- 8bpp - RETURN (N_DW=128 AND acpt=0) OR - (N_DW=64 AND ((acpt MOD 8)=0)); - WHEN "100" => -- 16bpp - RETURN (N_DW=128 AND ((acpt MOD 8)=0)) OR - (N_DW=64 AND ((acpt MOD 4)=0)); - WHEN "101" => -- 24bpp - RETURN (N_DW=128 AND (acpt=0 OR acpt=5 OR acpt=10)) OR - (N_DW=64 AND ((acpt MOD 8)=0 OR (acpt MOD 8)=2 OR (acpt MOD 8)=5)); - WHEN OTHERS => -- 32bpp - RETURN (N_DW=128 AND ((acpt MOD 4)=0)) OR - (N_DW=64 AND ((acpt MOD 2)=0)); - END CASE; - END FUNCTION; - - FUNCTION shift_opix (shift : unsigned(0 TO N_DW+15); - format : unsigned(5 DOWNTO 0)) RETURN type_pix IS - BEGIN - CASE format(3 DOWNTO 0) IS - WHEN "0100" => -- 16bpp 565 - RETURN (b=>shift(8 TO 12) & shift(8 TO 10), - g=>shift(13 TO 15) & shift(0 TO 2) & shift(13 TO 14), - r=>shift(3 TO 7) & shift(3 TO 5)); - WHEN "1100" => -- 16bpp 1555 - RETURN (b=>shift(9 TO 13) & shift(9 TO 11), - g=>shift(14 TO 15) & shift(0 TO 2) & shift(14 TO 15) & shift(0), - r=>shift(3 TO 7) & shift(3 TO 5)); - WHEN "0101" | "0110" => -- 24bpp / 32bpp - RETURN (r=>shift(0 TO 7),g=>shift(8 TO 15),b=>shift(16 TO 23)); - - WHEN OTHERS => - RETURN (r=>shift(0 TO 7),g=>shift(8 TO 15),b=>shift(16 TO 23)); - - END CASE; - END FUNCTION; - - FUNCTION pixoffset(adrs : unsigned(31 DOWNTO 0); - format : unsigned (5 DOWNTO 0)) RETURN natural IS - BEGIN - CASE format(2 DOWNTO 0) IS - WHEN "011" => -- 8bbp - RETURN to_integer(adrs(NB_LA-1 DOWNTO 0)); - WHEN "100" => -- 16bpp 565 - RETURN to_integer(adrs(NB_LA-1 DOWNTO 1)); - WHEN OTHERS => -- 32bpp - RETURN to_integer(adrs(NB_LA-1 DOWNTO 2)); - END CASE; - 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 - 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 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) RETURN unsigned IS - VARIABLE x : unsigned(FRAC-1 DOWNTO 0); - BEGIN - x:=(OTHERS =>f(f'left)); - RETURN x; - END FUNCTION; - - SIGNAL o_h_near_frac,o_v_near_frac : unsigned(FRAC-1 DOWNTO 0); - SIGNAL o_h_bil_frac,o_v_bil_frac : unsigned(FRAC-1 DOWNTO 0); - SIGNAL o_h_bil_pix,o_v_bil_pix : type_pix; + ---------------------------------------------------------- + TYPE arr_dw IS ARRAY (natural RANGE <>) OF unsigned(N_DW-1 DOWNTO 0); - ----------------------------------------------------------------------------- - -- Nearest + Bilinear + Sharp Bilinear - FUNCTION bil_frac(f : unsigned) RETURN unsigned IS - BEGIN - RETURN f(f'left DOWNTO f'left+1-FRAC); - END FUNCTION; - - TYPE type_bil_t IS RECORD - r,g,b : unsigned(8+FRAC DOWNTO 0); - END RECORD; - - FUNCTION bil_calc(f : unsigned(FRAC-1 DOWNTO 0); - p : arr_pix(0 TO 3)) RETURN type_bil_t IS - VARIABLE fp,fn : unsigned(FRAC DOWNTO 0); - VARIABLE u : unsigned(8+FRAC DOWNTO 0); - VARIABLE x : type_bil_t; - CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); - BEGIN - fp:=('0' & f) + (Z & f(FRAC-1)); - fn:=('1' & Z) - fp; - u:=p(2).r * fp + p(1).r * fn; - x.r:=u; - u:=p(2).g * fp + p(1).g * fn; - x.g:=u; - u:=p(2).b * fp + p(1).b * fn; - x.b:=u; - RETURN x; - END FUNCTION; - - FUNCTION near_calc(f : unsigned(FRAC-1 DOWNTO 0); - p : arr_pix(0 TO 3)) RETURN type_bil_t IS - VARIABLE fp,fn : unsigned(FRAC DOWNTO 0); - VARIABLE u : unsigned(8+FRAC DOWNTO 0); - VARIABLE x : type_bil_t; - CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); - BEGIN - IF f(FRAC-1)='0' THEN - x.r := '0' & p(1).r & Z; - x.g := '0' & p(1).g & Z; - x.b := '0' & p(1).b & Z; - ELSE - x.r := '0' & p(2).r & Z; - x.g := '0' & p(2).g & Z; - x.b := '0' & p(2).b & Z; - END IF; - RETURN x; - END FUNCTION; - - SIGNAL o_h_bil_t,o_v_bil_t : type_bil_t; - SIGNAL o_h_near_t,o_v_near_t : type_bil_t; - SIGNAL i_h_bil_t : type_bil_t; - - ----------------------------------------------------------------------------- - -- 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; - BEGIN - IF f(11)='0' THEN - u:=f(11 DOWNTO 12-FRAC); - ELSE - u:=NOT f(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); - BEGIN - v:=t.f*t.s; - IF f(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) - BEGIN - xx := signed('0' & f(11 DOWNTO 12-FRAC)) * - signed('0' & f(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); - p : arr_pix(0 TO 3)) RETURN type_bic_pix_abcd IS - BEGIN - RETURN type_bic_pix_abcd'(r=>bic_calc0(f,p(0).r,p(1).r,p(2).r,p(3).r), - g=>bic_calc0(f,p(0).g,p(1).g,p(2).g,p(3).g), - b=>bic_calc0(f,p(0).b,p(1).b,p(2).b,p(3).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 - BEGIN - bx := abcd.r.b * signed('0' & f(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' & f(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' & f(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) - BEGIN - 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 + 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; + TYPE arr_pixq IS ARRAY(natural RANGE <>) OF arr_pix(0 TO 3); + ATTRIBUTE ramstyle : string; - x:=t.r_dxx * signed('0' & f(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' & f(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' & f(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_abcd1,o_h_bic_abcd2 : type_bic_pix_abcd; - SIGNAL 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 - -- 2.7 - TYPE poly_phase_t IS RECORD - t0, t1, t2, t3 : signed(9 DOWNTO 0); - END RECORD; + SUBTYPE uint12 IS natural RANGE 0 TO 4095; + SUBTYPE uint13 IS natural RANGE 0 TO 8191; - -- 4.14 - TYPE poly_phase_interp_t IS RECORD - t0, t1, t2, t3 : signed(17 DOWNTO 0); - END RECORD; - - -- 5.22 - TYPE type_poly_t IS RECORD - r0,r1,b0,b1,g0,g1 : signed(26 DOWNTO 0); - END RECORD; - + TYPE arr_uv48 IS ARRAY (natural RANGE <>) OF unsigned(47 DOWNTO 0); + TYPE arr_uv24 IS ARRAY (natural RANGE <>) OF unsigned(23 DOWNTO 0); + TYPE arr_uv40 IS ARRAY (natural RANGE <>) OF unsigned(39 DOWNTO 0); + TYPE arr_int9 IS ARRAY (natural RANGE <>) OF integer RANGE -256 TO 255; + TYPE arr_uint12 IS ARRAY (natural RANGE <>) OF uint12; + TYPE arr_frac IS ARRAY (natural RANGE <>) OF unsigned(11 DOWNTO 0); + TYPE arr_div IS ARRAY (natural RANGE <>) OF unsigned(20 DOWNTO 0); - SIGNAL o_h_poly_mem : arr_uv40(0 TO 2**FRAC-1); - SIGNAL o_v_poly_mem : arr_uv40(0 TO 2**FRAC-1); - SIGNAL o_a_poly_mem : arr_uv40(0 TO 2**FRAC-1); - ATTRIBUTE ramstyle OF o_h_poly_mem : SIGNAL IS "no_rw_check"; - ATTRIBUTE ramstyle OF o_v_poly_mem : SIGNAL IS "no_rw_check"; - ATTRIBUTE ramstyle OF o_a_poly_mem : SIGNAL IS "no_rw_check"; - SIGNAL o_a_poly_addr, o_v_poly_addr, o_h_poly_addr : integer RANGE 0 TO 2**FRAC-1; - SIGNAL o_h_poly_phase_a,o_h_poly_phase_a2,o_h_poly_phase_a3 : poly_phase_t; - SIGNAL o_v_poly_phase_a,o_v_poly_phase_a2,o_v_poly_phase_a3 : poly_phase_t; - SIGNAL o_poly_phase_a, o_poly_phase_a2, o_poly_phase_a3 : poly_phase_t; - SIGNAL o_poly_phase_b,o_poly_phase_b2,o_poly_phase_b3 : poly_phase_t; - SIGNAL o_v_poly_phase, o_v_poly_phase2, o_h_poly_phase, o_poly_phase : poly_phase_interp_t; - SIGNAL o_v_poly_pix, o_h_poly_pix : type_pix; - SIGNAL o_v_poly_lum, o_h_poly_lum, o_poly_lum : unsigned(7 DOWNTO 0); - SIGNAL o_poly_lerp_ta, o_poly_lerp_tb, o_poly_lerp_tb3 : signed(9 DOWNTO 0); - SIGNAL o_h_poly_t,o_h_poly_t2,o_v_poly_t : type_poly_t; - - SIGNAL o_v_poly_adaptive, o_h_poly_adaptive, o_v_poly_use_adaptive, o_h_poly_use_adaptive : std_logic; - SIGNAL poly_wr_mode : std_logic_vector(2 DOWNTO 0); - SIGNAL poly_tdw : unsigned(39 DOWNTO 0); - SIGNAL poly_a2 : unsigned(FRAC-1 DOWNTO 0); + ---------------------------------------------------------- + -- Input image + 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_vcpt : uint12; + SIGNAL i_iauto : std_logic; + SIGNAL i_mode : unsigned(4 DOWNTO 0); + SIGNAL i_format : unsigned(1 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_vs_pre,i_fl_pre : std_logic; + SIGNAL i_de_delay : natural RANGE 0 TO 31; + SIGNAL i_intercnt : natural RANGE 0 TO 3; + SIGNAL i_inter,i_half,i_flm : std_logic; + SIGNAL i_write,i_wreq,i_alt,i_line,i_wline,i_wline_mem : std_logic; + SIGNAL i_walt,i_walt_mem,i_wreq_mem : std_logic; + SIGNAL i_wdelay : natural RANGE 0 TO 7; + SIGNAL i_push,i_pushend,i_pushend2 : std_logic; + SIGNAL i_eol : 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_endframe0,i_endframe1,i_vss : 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,i_wadrs,i_wadrs_mem : unsigned(31 DOWNTO 0); + SIGNAL i_reset_na : std_logic; + SIGNAL i_hnp,i_vnp : std_logic; + SIGNAL i_mem : arr_pix(0 TO IHRES-1); -- Downscale line buffer + ATTRIBUTE ramstyle OF i_mem : SIGNAL IS "no_rw_check"; + SIGNAL i_ohsize,i_ovsize : uint12; + 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 : 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,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 : std_logic; - - FUNCTION poly_unpack(a : unsigned(39 DOWNTO 0)) RETURN poly_phase_t IS - VARIABLE v : poly_phase_t; - BEGIN - v.t0 := signed(a(39 DOWNTO 30)); - v.t1 := signed(a(29 DOWNTO 20)); - v.t2 := signed(a(19 DOWNTO 10)); - v.t3 := signed(a( 9 DOWNTO 0)); + ---------------------------------------------------------- + -- Avalon + TYPE type_avl_state IS (sIDLE,sWRITE,sREAD); + SIGNAL avl_state : type_avl_state; + 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_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,avl_wline,avl_rline : std_logic; + SIGNAL avl_dw,avl_dr : unsigned(N_DW-1 DOWNTO 0); + SIGNAL avl_wr : std_logic; + SIGNAL avl_readdataack,avl_readack : std_logic; + SIGNAL avl_radrs,avl_wadrs : 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; + SIGNAL avl_fb_ena : std_logic; - RETURN v; - END FUNCTION; + FUNCTION buf_next(a,b : natural RANGE 0 TO 2; freeze : std_logic := '0') RETURN natural IS + BEGIN + IF (freeze='1') THEN RETURN a; END IF; + 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; + base : unsigned(31 DOWNTO 0); + size : unsigned(31 DOWNTO 0)) RETURN unsigned IS + BEGIN + IF b=1 THEN RETURN base+size; END IF; + IF b=2 THEN RETURN base+(size(30 DOWNTO 0) & '0'); END IF; + RETURN base; + END FUNCTION; - -- 6 DSP 18*18 + 18*18 - FUNCTION poly_calc(fi : poly_phase_interp_t; - p : arr_pix(0 TO 3)) RETURN type_poly_t IS - VARIABLE t : type_poly_t; - BEGIN - -- 3.15 * 1.8 = 4.23 - t.r0:=(fi.t0 * signed('0' & p(0).r) + - fi.t1 * signed('0' & p(1).r)); - t.r1:=(fi.t2 * signed('0' & p(2).r) + - fi.t3 * signed('0' & p(3).r)); - t.g0:=(fi.t0 * signed('0' & p(0).g) + - fi.t1 * signed('0' & p(1).g)); - t.g1:=(fi.t2 * signed('0' & p(2).g) + - fi.t3 * signed('0' & p(3).g)); - t.b0:=(fi.t0 * signed('0' & p(0).b) + - fi.t1 * signed('0' & p(1).b)); - t.b1:=(fi.t2 * signed('0' & p(2).b) + - fi.t3 * signed('0' & p(3).b)); - RETURN t; - END FUNCTION; - - FUNCTION poly_final(t : type_poly_t) RETURN type_pix IS - VARIABLE p : type_pix; - BEGIN - p.r:=bound(unsigned(t.r0(26 DOWNTO 8)+t.r1(26 DOWNTO 8)),15); - p.g:=bound(unsigned(t.g0(26 DOWNTO 8)+t.g1(26 DOWNTO 8)),15); - p.b:=bound(unsigned(t.b0(26 DOWNTO 8)+t.b1(26 DOWNTO 8)),15); - RETURN p; - END FUNCTION; + ---------------------------------------------------------- + -- Output + SIGNAL o_run : std_logic; + SIGNAL o_freeze : std_logic; + SIGNAL o_mode,o_hmode,o_vmode : unsigned(4 DOWNTO 0); + SIGNAL o_format : unsigned(5 DOWNTO 0); + SIGNAL o_fb_pal_dr : unsigned(23 DOWNTO 0); + SIGNAL o_fb_pal_dr2 : unsigned(23 DOWNTO 0); + SIGNAL o_fb_pal_dr_x2 : unsigned(47 DOWNTO 0); + SIGNAL pal_idx: unsigned(7 DOWNTO 0); + SIGNAL pal_idx_lsb: std_logic; + SIGNAL pal1_mem : arr_uv48(0 TO 127); + SIGNAL pal2_mem : arr_uv24(0 TO 255); + ATTRIBUTE ramstyle of pal1_mem : signal is "no_rw_check"; + ATTRIBUTE ramstyle of pal2_mem : signal is "no_rw_check"; + SIGNAL o_htotal,o_hsstart,o_hsend : uint12; + SIGNAL o_hmin,o_hmax,o_hdisp,o_v_hmin_adj : uint12; + SIGNAL o_hsize,o_vsize : uint12; + SIGNAL o_vtotal,o_vsstart,o_vsend : uint12; + SIGNAL o_vrr,o_isync,o_isync2 : std_logic; + SIGNAL o_vrr_sync,o_vrr_sync2 : boolean; + SIGNAL o_vrr_min,o_vrr_min2 : boolean; + SIGNAL o_vrr_max,o_vrr_max2 : boolean; + SIGNAL o_vcpt_sync,o_vcpt_sync2, o_vrrmax : uint12; + SIGNAL o_sync, o_sync_max : boolean; + SIGNAL o_vmin,o_vmax,o_vdisp : uint12; + SIGNAL o_divcpt : natural RANGE 0 TO 36; + 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 enum_o_state IS (sDISP,sHSYNC,sREAD,sWAITREAD); + SIGNAL o_state : enum_o_state; + TYPE enum_o_copy IS (sWAIT,sSHIFT,sCOPY); + SIGNAL o_copy : enum_o_copy; + SIGNAL o_pshift : natural RANGE 0 TO 15; + SIGNAL o_readack,o_readack_sync,o_readack_sync2 : std_logic; + SIGNAL o_readdataack,o_readdataack_sync,o_readdataack_sync2 : std_logic; + SIGNAL o_copyv : unsigned(0 TO 14); + SIGNAL o_adrs : unsigned(31 DOWNTO 0); -- Avalon address + SIGNAL o_adrs_pre : natural RANGE 0 TO 2**24-1; + SIGNAL o_stride : unsigned(13 DOWNTO 0); + SIGNAL o_adrsa,o_adrsb,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); + SIGNAL o_shift : unsigned(0 TO N_DW+15); + SIGNAL o_sh,o_sh1,o_sh2,o_sh3,o_sh4 : std_logic; + SIGNAL o_reset_na : std_logic; + SIGNAL o_dpram : arr_dw(0 TO BLEN*2-1); + ATTRIBUTE ramstyle OF o_dpram : SIGNAL IS "no_rw_check"; + SIGNAL o_line0,o_line1,o_line2,o_line3 : arr_pix(0 TO OHRES-1); + ATTRIBUTE ramstyle OF o_line0 : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_line1 : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_line2 : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_line3 : SIGNAL IS "no_rw_check"; + SIGNAL o_wadl,o_radl0,o_radl1,o_radl2,o_radl3 : natural RANGE 0 TO OHRES-1; + SIGNAL o_ldw,o_ldr0,o_ldr1,o_ldr2,o_ldr3 : type_pix; + SIGNAL o_wr : unsigned(3 DOWNTO 0); + SIGNAL o_hcpt,o_vcpt,o_vcpt_pre,o_vcpt_pre2,o_vcpt_pre3,o_vcpt2 : uint12; + SIGNAL o_ihsize,o_ihsizem,o_ivsize : uint12; + SIGNAL o_ihsize_temp, o_ihsize_temp2 : natural RANGE 0 TO 32767; - -- 4 DSP 18*18 + 18*18 - FUNCTION poly_lerp(a : poly_phase_t; - b : poly_phase_t; - ta : SIGNED(9 DOWNTO 0); - tb : SIGNED(9 DOWNTO 0)) RETURN poly_phase_interp_t IS - VARIABLE v : poly_phase_interp_t; - VARIABLE t0,t1,t2,t3 : signed(19 DOWNTO 0); - BEGIN - -- 2.8 * 2.8 = 4.16 - t0 := (a.t0 * ta) + (b.t0 * tb); - t1 := (a.t1 * ta) + (b.t1 * tb); - t2 := (a.t2 * ta) + (b.t2 * tb); - t3 := (a.t3 * ta) + (b.t3 * tb); - - -- 4.16 -> 3.15 - v.t0 := t0(18 DOWNTO 1); - v.t1 := t1(18 DOWNTO 1); - v.t2 := t2(18 DOWNTO 1); - v.t3 := t3(18 DOWNTO 1); - - RETURN v; - END FUNCTION; + SIGNAL o_vfrac : unsigned(11 DOWNTO 0); + SIGNAL o_hfrac : arr_frac(0 TO 9); + ATTRIBUTE ramstyle OF o_hfrac : SIGNAL IS "logic"; -- avoid blockram shift register - FUNCTION poly_cvt(a : poly_phase_t) RETURN poly_phase_interp_t IS - VARIABLE v : poly_phase_interp_t; - BEGIN - v.t0 := resize(signed( a.t0 & "0000000" ), v.t0'length); - v.t1 := resize(signed( a.t1 & "0000000" ), v.t1'length); - v.t2 := resize(signed( a.t2 & "0000000" ), v.t2'length); - v.t3 := resize(signed( a.t3 & "0000000" ), v.t3'length); - RETURN v; - END FUNCTION; - - -- Nearest neighbor polyphase ceoffs - FUNCTION poly_nn(frac : unsigned(FRAC-1 DOWNTO 0)) RETURN poly_phase_t IS - VARIABLE v : poly_phase_t; - BEGIN - IF frac(frac'left)='0' THEN - v := (t1=>to_signed(256, 10), OTHERS=>to_signed(0, 10)); - ELSE - v := (t2=>to_signed(256, 10), OTHERS=>to_signed(0, 10)); - END IF; - RETURN v; - END FUNCTION; + 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,o_end : unsigned(0 TO 11); + SIGNAL o_hsp,o_vss : std_logic; + SIGNAL o_vcarrym,o_prim : boolean; + 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,o_acpt1,o_acpt2,o_acpt3,o_acpt4 : natural RANGE 0 TO 15; -- Alternance pixels FIFO + SIGNAL o_dshi : natural RANGE 0 TO 3; + SIGNAL o_first,o_last,o_last1,o_last2 : std_logic; + SIGNAL o_lastt1,o_lastt2,o_lastt3,o_lastt4 : std_logic; + SIGNAL o_alt,o_altx : unsigned(3 DOWNTO 0); + SIGNAL o_hdown,o_vdown : std_logic; + SIGNAL o_primv,o_lastv,o_bibv : unsigned(0 TO 2); + TYPE arr_uint4 IS ARRAY (natural RANGE <>) OF natural RANGE 0 TO 15; + SIGNAL o_off : arr_uint4(0 TO 2); + SIGNAL o_bibu : std_logic :='0'; + SIGNAL o_dcptv : arr_uint12(1 TO 14); + SIGNAL o_dcpt : uint12; + SIGNAL o_hpixs,o_hpix0,o_hpix1,o_hpix2,o_hpix3 : type_pix; + SIGNAL o_hpixq : arr_pixq(2 TO 8); + ATTRIBUTE ramstyle OF o_hpixq : SIGNAL IS "logic"; -- avoid blockram shift register + SIGNAL o_vpixq, o_vpixq_pre : arr_pix(0 TO 3); + SIGNAL o_vpix_outer : arr_pix(0 TO 2); + SIGNAL o_vpix_inner : arr_pix(0 TO 6); - FUNCTION poly_lum(p : type_pix) RETURN unsigned IS - VARIABLE v : UNSIGNED(7 DOWNTO 0); - BEGIN - -- 0.375 R + 0.5 G + 0.125 B - --v := ("00" & p.r(7 DOWNTO 2)) + ("000" & p.r(7 DOWNTO 3)) + ("0" & p.g(7 DOWNTO 1)) + ("000" & p.b(7 DOWNTO 3)); + SIGNAL o_vpe : std_logic; + SIGNAL o_div : arr_div(0 TO 2); --uint12; + SIGNAL o_dir : arr_frac(0 TO 2); + ATTRIBUTE ramstyle OF o_div, o_dir : SIGNAL IS "logic"; -- avoid blockram shift register + 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_vacptl : unsigned(1 DOWNTO 0); - -- 0.25 R + 0.5 G + 0.25 B - -- v := ( ("00" & p.r(7 DOWNTO 2)) + ("0" & p.g(7 DOWNTO 1)) + ("00" & p.b(7 DOWNTO 2)) ); + ----------------------------------------------------------------------------- + FUNCTION shift_ishift(shift : unsigned(0 TO 119); + pix : type_pix; + format : unsigned(1 DOWNTO 0)) RETURN unsigned IS + BEGIN + CASE format IS + WHEN "01" => -- 24bpp + RETURN shift(24 TO 119) & pix.r & pix.g & pix.b; + WHEN "10" => -- 32bpp + RETURN shift(32 TO 119) & pix.r & pix.g & pix.b & x"00"; + WHEN OTHERS => -- 16bpp 565 + RETURN shift(16 TO 119) & + pix.g(4 DOWNTO 2) & pix.r(7 DOWNTO 3) & + pix.b(7 DOWNTO 3) & pix.g(7 DOWNTO 5); + END CASE; + END FUNCTION; - -- Just OR them all together - --v := (p.r OR p.g OR p.b); + FUNCTION shift_ipack( i_dw : unsigned(N_DW-1 DOWNTO 0); + acpt : natural RANGE 0 TO 15; + shift : unsigned(0 TO 119); + pix : type_pix; + format : unsigned(1 DOWNTO 0)) RETURN unsigned IS + VARIABLE dw : unsigned(N_DW-1 DOWNTO 0); + BEGIN + dw:=i_dw; + CASE format IS + WHEN "01" => -- 24bpp + IF N_DW=128 THEN + IF acpt=5 THEN dw:=shift(0 TO 119) & pix.r; + ELSIF acpt=10 THEN dw:=shift(8 TO 119) & pix.r & pix.g; + ELSIF acpt=15 THEN dw:=shift(16 TO 119) & pix.r & pix.g & pix.b; + END IF; + ELSE -- N_DW=64 + IF (acpt MOD 8)=2 THEN dw:=shift(72 TO 119) & pix.r & pix.g; + ELSIF (acpt MOD 8)=5 THEN dw:=shift(64 TO 119) & pix.r; + ELSIF (acpt MOD 8)=7 THEN dw:=shift(80 TO 119) & pix.r & pix.g & pix.b; + END IF; + END IF; + WHEN "10" => -- 32bpp + IF (N_DW=128 AND (acpt MOD 4)=3) OR (N_DW=64 AND (acpt MOD 8)=7) THEN + dw:=shift(128-N_DW+24 TO 119) & pix.r & pix.g & pix.b & x"00"; + END IF; + WHEN OTHERS => -- 16bpp 565 + IF (N_DW=128 AND (acpt MOD 8)=7) OR (N_DW=64 AND (acpt MOD 4)=3) THEN + dw:=shift(128-N_DW+8 TO 119) & pix.g(4 DOWNTO 2) & pix.r(7 DOWNTO 3) & + pix.b(7 DOWNTO 3) & pix.g(7 DOWNTO 5); + END IF; + END CASE; + RETURN dw; + END FUNCTION; - -- Maximum - IF p.r > p.g THEN - v := p.r; - ELSE - v := p.g; - END IF; + FUNCTION shift_inext (acpt : natural RANGE 0 TO 15; + format : unsigned(1 DOWNTO 0)) RETURN boolean IS + BEGIN + CASE format IS + WHEN "01" => -- 24bpp + RETURN (N_DW=128 AND (acpt=5 OR acpt=10 OR acpt=15)) OR + (N_DW=64 AND ((acpt MOD 8)=2 OR (acpt MOD 8)=5 OR (acpt MOD 8)=7)); + WHEN "10" => -- 32bpp + RETURN (N_DW=128 AND ((acpt MOD 4)=3)) OR + (N_DW=64 AND ((acpt MOD 2)=1)); + WHEN OTHERS => -- 16bpp + RETURN (N_DW=128 AND ((acpt MOD 8)=7)) OR + (N_DW=64 AND ((acpt MOD 4)=3)); + END CASE; + END FUNCTION; - IF p.b > v THEN - v := p.b; - END IF; - - -- 100% - -- v := "1111111"; - - RETURN v; - END FUNCTION; + FUNCTION shift_opack(acpt : natural RANGE 0 TO 15; + shift : unsigned(0 TO N_DW+15); + dr : unsigned(N_DW-1 DOWNTO 0); + format : unsigned(5 DOWNTO 0)) RETURN unsigned IS + VARIABLE shift_v : unsigned(0 TO N_DW+15); + BEGIN + CASE format(2 DOWNTO 0) IS + WHEN "011" => -- 8bpp + IF (N_DW=128 AND acpt=0) OR (N_DW=64 AND (acpt MOD 8)=0) THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSE + shift_v:=shift(8 TO N_DW+15) & dr(7 DOWNTO 0); + END IF; + + WHEN "100" => -- 16bpp + IF (N_DW=128 AND (acpt MOD 8)=0) OR (N_DW=64 AND (acpt MOD 4)=0) THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSE + shift_v:=shift(16 TO N_DW+15) & dr(15 DOWNTO 0); + END IF; + + WHEN "101" => -- 24bpp + IF N_DW=128 THEN + IF acpt=0 THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSIF acpt=5 THEN + shift_v:=shift(24 TO 31) & dr & dr(7 DOWNTO 0); + ELSIF acpt=10 THEN + shift_v:=shift(24 TO 39) & dr; + ELSE + shift_v:=shift(24 TO N_DW+15) & dr(23 DOWNTO 0); + END IF; + ELSE -- N_DW=64 + IF (acpt MOD 8)=0 THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSIF (acpt MOD 8)=2 THEN + shift_v:=shift(24 TO 39) & dr; + ELSIF (acpt MOD 8)=5 THEN + shift_v:=shift(24 TO 31) & dr & dr(7 DOWNTO 0); + ELSE + shift_v:=shift(24 TO N_DW+15) & dr(23 DOWNTO 0); + END IF; + END IF; + WHEN OTHERS => -- 32bpp + IF (N_DW=128 AND (acpt MOD 4)=0) OR (N_DW=64 AND (acpt MOD 2)=0) THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSE + shift_v:=shift(32 TO N_DW+15) & dr(31 DOWNTO 0); + END IF; + END CASE; + RETURN shift_v; + END FUNCTION; + + FUNCTION shift_onext (acpt : natural RANGE 0 TO 15; + format : unsigned(5 DOWNTO 0)) RETURN boolean IS + BEGIN + CASE format(2 DOWNTO 0) IS + WHEN "011" => -- 8bpp + RETURN (N_DW=128 AND acpt=0) OR + (N_DW=64 AND ((acpt MOD 8)=0)); + WHEN "100" => -- 16bpp + RETURN (N_DW=128 AND ((acpt MOD 8)=0)) OR + (N_DW=64 AND ((acpt MOD 4)=0)); + WHEN "101" => -- 24bpp + RETURN (N_DW=128 AND (acpt=0 OR acpt=5 OR acpt=10)) OR + (N_DW=64 AND ((acpt MOD 8)=0 OR (acpt MOD 8)=2 OR (acpt MOD 8)=5)); + WHEN OTHERS => -- 32bpp + RETURN (N_DW=128 AND ((acpt MOD 4)=0)) OR + (N_DW=64 AND ((acpt MOD 2)=0)); + END CASE; + END FUNCTION; + + FUNCTION shift_opix (shift : unsigned(0 TO N_DW+15); + format : unsigned(5 DOWNTO 0)) RETURN type_pix IS + BEGIN + CASE format(3 DOWNTO 0) IS + WHEN "0100" => -- 16bpp 565 + RETURN (b=>shift(8 TO 12) & shift(8 TO 10), + g=>shift(13 TO 15) & shift(0 TO 2) & shift(13 TO 14), + r=>shift(3 TO 7) & shift(3 TO 5)); + WHEN "1100" => -- 16bpp 1555 + RETURN (b=>shift(9 TO 13) & shift(9 TO 11), + g=>shift(14 TO 15) & shift(0 TO 2) & shift(14 TO 15) & shift(0), + r=>shift(3 TO 7) & shift(3 TO 5)); + WHEN "0101" | "0110" => -- 24bpp / 32bpp + RETURN (r=>shift(0 TO 7),g=>shift(8 TO 15),b=>shift(16 TO 23)); + + WHEN OTHERS => + RETURN (r=>shift(0 TO 7),g=>shift(8 TO 15),b=>shift(16 TO 23)); + + END CASE; + END FUNCTION; + + FUNCTION pixoffset(adrs : unsigned(31 DOWNTO 0); + format : unsigned (5 DOWNTO 0)) RETURN natural IS + BEGIN + CASE format(2 DOWNTO 0) IS + WHEN "011" => -- 8bbp + RETURN to_integer(adrs(NB_LA-1 DOWNTO 0)); + WHEN "100" => -- 16bpp 565 + RETURN to_integer(adrs(NB_LA-1 DOWNTO 1)); + WHEN OTHERS => -- 32bpp + RETURN to_integer(adrs(NB_LA-1 DOWNTO 2)); + END CASE; + 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 + 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 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) RETURN unsigned IS + VARIABLE x : unsigned(FRAC-1 DOWNTO 0); + BEGIN + x:=(OTHERS =>f(f'left)); + RETURN x; + END FUNCTION; + + SIGNAL o_h_near_frac,o_v_near_frac : unsigned(FRAC-1 DOWNTO 0); + SIGNAL o_h_bil_frac,o_v_bil_frac : unsigned(FRAC-1 DOWNTO 0); + SIGNAL o_h_bil_pix,o_v_bil_pix : type_pix; + + ----------------------------------------------------------------------------- + -- Nearest + Bilinear + Sharp Bilinear + FUNCTION bil_frac(f : unsigned) RETURN unsigned IS + BEGIN + RETURN f(f'left DOWNTO f'left+1-FRAC); + END FUNCTION; + + TYPE type_bil_t IS RECORD + r,g,b : unsigned(8+FRAC DOWNTO 0); + END RECORD; + + FUNCTION bil_calc(f : unsigned(FRAC-1 DOWNTO 0); + p : arr_pix(0 TO 3)) RETURN type_bil_t IS + VARIABLE fp,fn : unsigned(FRAC DOWNTO 0); + VARIABLE u : unsigned(8+FRAC DOWNTO 0); + VARIABLE x : type_bil_t; + CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); + BEGIN + fp:=('0' & f) + (Z & f(FRAC-1)); + fn:=('1' & Z) - fp; + u:=p(2).r * fp + p(1).r * fn; + x.r:=u; + u:=p(2).g * fp + p(1).g * fn; + x.g:=u; + u:=p(2).b * fp + p(1).b * fn; + x.b:=u; + RETURN x; + END FUNCTION; + + FUNCTION near_calc(f : unsigned(FRAC-1 DOWNTO 0); + p : arr_pix(0 TO 3)) RETURN type_bil_t IS + VARIABLE fp,fn : unsigned(FRAC DOWNTO 0); + VARIABLE u : unsigned(8+FRAC DOWNTO 0); + VARIABLE x : type_bil_t; + CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); + BEGIN + IF f(FRAC-1)='0' THEN + x.r := '0' & p(1).r & Z; + x.g := '0' & p(1).g & Z; + x.b := '0' & p(1).b & Z; + ELSE + x.r := '0' & p(2).r & Z; + x.g := '0' & p(2).g & Z; + x.b := '0' & p(2).b & Z; + END IF; + RETURN x; + END FUNCTION; + + SIGNAL o_h_bil_t,o_v_bil_t : type_bil_t; + SIGNAL o_h_near_t,o_v_near_t : type_bil_t; + SIGNAL i_h_bil_t : type_bil_t; + + ----------------------------------------------------------------------------- + -- 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; + BEGIN + IF f(11)='0' THEN + u:=f(11 DOWNTO 12-FRAC); + ELSE + u:=NOT f(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); + BEGIN + v:=t.f*t.s; + IF f(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) + BEGIN + xx := signed('0' & f(11 DOWNTO 12-FRAC)) * + signed('0' & f(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); + p : arr_pix(0 TO 3)) RETURN type_bic_pix_abcd IS + BEGIN + RETURN type_bic_pix_abcd'( r=>bic_calc0(f,p(0).r,p(1).r,p(2).r,p(3).r), + g=>bic_calc0(f,p(0).g,p(1).g,p(2).g,p(3).g), + b=>bic_calc0(f,p(0).b,p(1).b,p(2).b,p(3).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 + BEGIN + bx := abcd.r.b * signed('0' & f(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' & f(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' & f(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) + BEGIN + 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' & f(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' & f(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' & f(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_abcd1,o_h_bic_abcd2 : type_bic_pix_abcd; + SIGNAL 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 + -- 2.7 + TYPE poly_phase_t IS RECORD + t0, t1, t2, t3 : signed(9 DOWNTO 0); + END RECORD; + + -- 4.14 + TYPE poly_phase_interp_t IS RECORD + t0, t1, t2, t3 : signed(17 DOWNTO 0); + END RECORD; + + -- 5.22 + TYPE type_poly_t IS RECORD + r0,r1,b0,b1,g0,g1 : signed(26 DOWNTO 0); + END RECORD; + + SIGNAL o_h_poly_mem : arr_uv40(0 TO 2**FRAC-1); + SIGNAL o_v_poly_mem : arr_uv40(0 TO 2**FRAC-1); + SIGNAL o_a_poly_mem : arr_uv40(0 TO 2**FRAC-1); + ATTRIBUTE ramstyle OF o_h_poly_mem : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_v_poly_mem : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_a_poly_mem : SIGNAL IS "no_rw_check"; + SIGNAL o_a_poly_addr, o_v_poly_addr : integer RANGE 0 TO 2**FRAC-1; + SIGNAL o_h_poly_phase_a,o_h_poly_phase_a2,o_h_poly_phase_a3, o_h_poly_phase_a4, o_h_poly_phase_a5 : poly_phase_t; + SIGNAL o_v_poly_phase_a,o_v_poly_phase_a2,o_v_poly_phase_a3, o_v_poly_phase_a4, o_v_poly_phase_a5 : poly_phase_t; + SIGNAL o_poly_phase_a, o_poly_phase_a2, o_poly_phase_a3 : poly_phase_t; + SIGNAL o_poly_phase_b,o_poly_phase_b2,o_poly_phase_b3 : poly_phase_t; + SIGNAL o_v_poly_phase, o_v_poly_phase2, o_h_poly_phase, o_poly_phase, o_poly_phase1 : poly_phase_interp_t; + SIGNAL o_v_poly_pix, o_h_poly_pix, o_h_lum_pix, o_v_lum_pix : type_pix; + SIGNAL o_poly_lum, o_poly_lum1 : unsigned(7 DOWNTO 0); + SIGNAL o_poly_lerp_ta, o_poly_lerp_tb : signed(9 DOWNTO 0); + SIGNAL o_h_poly_t,o_h_poly_t2,o_v_poly_t : type_poly_t; + + SIGNAL o_v_poly_adaptive, o_h_poly_adaptive, o_v_poly_use_adaptive, o_h_poly_use_adaptive : std_logic; + SIGNAL poly_wr_mode : std_logic_vector(2 DOWNTO 0); + SIGNAL poly_tdw : unsigned(39 DOWNTO 0); + SIGNAL poly_a2 : unsigned(FRAC-1 DOWNTO 0); + + FUNCTION poly_unpack(a : unsigned(39 DOWNTO 0)) RETURN poly_phase_t IS + VARIABLE v : poly_phase_t; + BEGIN + v.t0 := signed(a(39 DOWNTO 30)); + v.t1 := signed(a(29 DOWNTO 20)); + v.t2 := signed(a(19 DOWNTO 10)); + v.t3 := signed(a( 9 DOWNTO 0)); + RETURN v; + END FUNCTION; + + -- 6 DSP 18*18 + 18*18 + FUNCTION poly_calc(fi : poly_phase_interp_t; + p : arr_pix(0 TO 3)) RETURN type_poly_t IS + VARIABLE t : type_poly_t; + BEGIN + -- 3.15 * 1.8 = 4.23 + t.r0:=(fi.t0 * signed('0' & p(0).r) + + fi.t1 * signed('0' & p(1).r)); + t.r1:=(fi.t2 * signed('0' & p(2).r) + + fi.t3 * signed('0' & p(3).r)); + t.g0:=(fi.t0 * signed('0' & p(0).g) + + fi.t1 * signed('0' & p(1).g)); + t.g1:=(fi.t2 * signed('0' & p(2).g) + + fi.t3 * signed('0' & p(3).g)); + t.b0:=(fi.t0 * signed('0' & p(0).b) + + fi.t1 * signed('0' & p(1).b)); + t.b1:=(fi.t2 * signed('0' & p(2).b) + + fi.t3 * signed('0' & p(3).b)); + RETURN t; + END FUNCTION; + + FUNCTION poly_final(t : type_poly_t) RETURN type_pix IS + VARIABLE p : type_pix; + BEGIN + p.r:=bound(unsigned(t.r0(26 DOWNTO 8)+t.r1(26 DOWNTO 8)),15); + p.g:=bound(unsigned(t.g0(26 DOWNTO 8)+t.g1(26 DOWNTO 8)),15); + p.b:=bound(unsigned(t.b0(26 DOWNTO 8)+t.b1(26 DOWNTO 8)),15); + RETURN p; + END FUNCTION; + + -- 4 DSP 18*18 + 18*18 + FUNCTION poly_lerp(a : poly_phase_t; + b : poly_phase_t; + ta : SIGNED(9 DOWNTO 0); + tb : SIGNED(9 DOWNTO 0)) RETURN poly_phase_interp_t IS + VARIABLE v : poly_phase_interp_t; + VARIABLE t0,t1,t2,t3 : signed(19 DOWNTO 0); + BEGIN + -- 2.8 * 2.8 = 4.16 + t0 := (a.t0 * ta) + (b.t0 * tb); + t1 := (a.t1 * ta) + (b.t1 * tb); + t2 := (a.t2 * ta) + (b.t2 * tb); + t3 := (a.t3 * ta) + (b.t3 * tb); + + -- 4.16 -> 3.15 + v.t0 := t0(18 DOWNTO 1); + v.t1 := t1(18 DOWNTO 1); + v.t2 := t2(18 DOWNTO 1); + v.t3 := t3(18 DOWNTO 1); + + RETURN v; + END FUNCTION; + + FUNCTION poly_cvt(a : poly_phase_t) RETURN poly_phase_interp_t IS + VARIABLE v : poly_phase_interp_t; + BEGIN + v.t0 := resize(signed( a.t0 & "0000000" ), v.t0'length); + v.t1 := resize(signed( a.t1 & "0000000" ), v.t1'length); + v.t2 := resize(signed( a.t2 & "0000000" ), v.t2'length); + v.t3 := resize(signed( a.t3 & "0000000" ), v.t3'length); + RETURN v; + END FUNCTION; + + -- Nearest neighbor polyphase ceoffs + FUNCTION poly_nn(frac : unsigned(FRAC-1 DOWNTO 0)) RETURN poly_phase_t IS + VARIABLE v : poly_phase_t; + BEGIN + IF frac(frac'left)='0' THEN + v := (t1=>to_signed(256, 10), OTHERS=>to_signed(0, 10)); + ELSE + v := (t2=>to_signed(256, 10), OTHERS=>to_signed(0, 10)); + END IF; + RETURN v; + END FUNCTION; + + + FUNCTION poly_lum(p : type_pix) RETURN unsigned IS + VARIABLE v : UNSIGNED(7 DOWNTO 0); + BEGIN + -- 0.375 R + 0.5 G + 0.125 B + --v := ("00" & p.r(7 DOWNTO 2)) + ("000" & p.r(7 DOWNTO 3)) + ("0" & p.g(7 DOWNTO 1)) + ("000" & p.b(7 DOWNTO 3)); + + -- 0.25 R + 0.5 G + 0.25 B + -- v := ( ("00" & p.r(7 DOWNTO 2)) + ("0" & p.g(7 DOWNTO 1)) + ("00" & p.b(7 DOWNTO 2)) ); + + -- Just OR them all together + --v := (p.r OR p.g OR p.b); + + -- Maximum + IF p.r > p.g THEN + v := p.r; + ELSE + v := p.g; + END IF; + + IF p.b > v THEN + v := p.b; + END IF; + + -- 100% + -- v := "1111111"; + + RETURN v; + END FUNCTION; 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 frac_v : unsigned(FRAC-1 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<='0'; - - ELSIF rising_edge(i_clk) THEN - i_push<='0'; - i_pushhead<='0'; - i_eol<='0'; -- End Of Line - i_freeze <=freeze; -- - i_iauto<=iauto; -- - i_wreq<='0'; - i_wr<='0'; - - ------------------------------------------------------ - i_head(127 DOWNTO 120)<=x"01"; -- Header type - i_head(119 DOWNTO 112)<="000000" & i_format; -- Header format - 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_flm; - i_head(82)<=i_hdown; - i_head(83)<=i_vdown; - 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 16)<="0000" & to_unsigned(i_ohsize,12); - i_head(15 DOWNTO 0) <="0000" & to_unsigned(i_ovsize,12); - - ------------------------------------------------------ - i_ppix<=(i_r,i_g,i_b); - i_pvs<=i_vs; - i_pfl<=i_fl; - i_pde<=i_de; - i_pce<=i_ce; - - ------------------------------------------------------ - IF i_pce='1' THEN - ---------------------------------------------------- - i_vs_pre<=i_pvs; - i_de_pre<=i_pde; - i_fl_pre<=i_pfl; - - ---------------------------------------------------- - -- Detect interlaced video - IF NOT INTER THEN - i_intercnt<=0; - ELSIF i_pfl/=i_fl_pre THEN - i_intercnt<=3; - ELSIF i_pvs='1' AND i_vs_pre='0' AND i_intercnt>0 THEN - i_intercnt<=i_intercnt-1; - END IF; - i_inter<=to_std_logic(i_intercnt>0); - - ---------------------------------------------------- - IF i_pvs='1' AND i_vs_pre='0' THEN - i_sof<='1'; - END IF; - - IF i_pde='1' AND i_de_pre='0' THEN - i_flm<=i_pfl; - END IF; - - IF i_pde='1' AND i_sof='1' THEN - i_sof<='0'; - i_vcpt<=0; - IF i_inter='1' AND i_flm='0' AND i_half='0' AND INTER THEN - i_line<='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_line<='0'; - i_adrsi<=to_unsigned(N_BURST * to_integer( - unsigned'("00") & to_std_logic(HEADER)),32); - END IF; - END IF; - - 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. - i_endframe0<=i_vs AND (NOT i_inter OR i_flm); - i_endframe1<=i_vs AND (NOT i_inter OR NOT i_flm); - - i_vss<=to_std_logic(i_vcpt>=i_vmin AND i_vcpt<=i_vmax); - - ---------------------------------------------------- - IF i_pde='1' AND i_de_pre='0' THEN - i_vimax<=i_vcpt; - i_hcpt<=0; - ELSE - i_hcpt<=(i_hcpt+1) MOD 4096; - END IF; - - IF i_pde='0' AND i_de_pre='1' THEN - i_himax<=i_hcpt; - END IF; - - IF i_iauto='1' THEN - -- Auto-size - i_hmin<=0; - i_hmax<=i_himax; - i_vmin<=0; - 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 - -- Forced image - i_hmin<=himin; -- - i_hmax<=himax; -- - i_vmin<=vimin; -- - IF i_pvs='1' AND i_vs_pre='0' AND (i_inter='0' OR i_pfl='0') THEN - i_vmax<=vimax; -- - END IF; - END IF; - - IF i_pvs='1' AND i_vs_pre='0' AND (i_inter='0' OR i_pfl='0') THEN - i_vdmax<=i_vimax; - END IF; - i_hdmax<=i_himax; - - IF i_format="00" OR i_format="11" THEN -- 16bpp - i_hburst<=(i_hrsize*2 + N_BURST - 1) / N_BURST; - ELSIF i_format="01" THEN -- 24bpp - i_hburst<=(i_hrsize*3 + N_BURST - 1) / N_BURST; - ELSE -- 32bpp - i_hburst<=(i_hrsize*4 + N_BURST - 1) / N_BURST; - END IF; - ---------------------------------------------------- - i_mode<=mode; -- - i_format<=format; -- - - -- Downscaling : Nearest or bilinear - i_bil<=to_std_logic(i_mode(2 DOWNTO 0)/="000" AND NOT DOWNSCALE_NN); - - i_hdown<=to_std_logic(i_hsize>i_ohsize AND DOWNSCALE); --H downscale - i_vdown<=to_std_logic(i_vsize>i_ovsize AND DOWNSCALE); --V downscale - - ---------------------------------------------------- - i_hsize <=(4096+i_hmax-i_hmin+1) MOD 4096; - i_vmaxmin<=(4096+i_vmax-i_vmin+1) MOD 4096; - - IF i_inter='0' THEN - -- Non interlaced - i_vsize<=i_vmaxmin; - i_half <='0'; - ELSIF i_ovsize<2*i_vmaxmin THEN - -- Interlaced, but downscaling, use only half frames - i_vsize<=i_vmaxmin; - i_half <='1'; - ELSE - -- Interlaced : Double image height - i_vsize<=2*i_vmaxmin; - i_half <='0'; - END IF; - - i_ohsize<=o_hsize; -- - i_ovsize<=o_vsize; -- - - ---------------------------------------------------- - -- Downscaling vertical - i_divstart<='0'; - IF i_de_delay=16 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 + 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_vsize - i_ovsize + 8192) MOD 8192; - i_vnp<='1'; -- - END IF; - END IF; - - IF i_vdown='0' THEN - i_vnp<='1'; - END IF; - - -- Downscaling horizontal - IF i_ven='1' THEN - 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 + 2*i_ohsize - 2*i_hsize + 8192) MOD 8192; - i_hnp<='1'; - END IF; - END IF; - IF i_hdown='0' THEN - i_hnp<='1'; - END IF; - - ---------------------------------------------------- - -- Downscaling interpolation - i_hpixp<=i_ppix; - i_hpix0<=i_hpixp; - i_hpix1<=i_hpix0; - i_hpix2<=i_hpix1; - i_hpix3<=i_hpix2; - i_hpix4<=i_hpix3; - - 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; i_ven6<=i_ven5; - - -- C1 : DIV 1. Pipelined 4 bits non-restoring divider - dir_v:=x"000"; - div_v:=to_unsigned(i_hacc * 16,17); - - 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*8,17); - END IF; - 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(16)='0' THEN - div_v:=div_v-to_unsigned(i_hsize*4,17); - ELSE - div_v:=div_v+to_unsigned(i_hsize*4,17); - END IF; - dir_v(9):=NOT div_v(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*2,17); - END IF; - 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); - i_h_bil_t<=near_calc(frac_v,(i_hpix2,i_hpix2,i_hpix3,i_hpix3)); - ELSE - frac_v:=bil_frac(i_h_frac); - i_h_bil_t<=bil_calc(frac_v,(i_hpix2,i_hpix2,i_hpix3,i_hpix3)); - END IF; - - 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); - - IF i_hdown='0' THEN - i_hpix<=i_hpix4; - END IF; - - -- C5 : Vertical Bilinear - IF i_bil='0' THEN - frac_v:=near_frac(i_v_frac(11 DOWNTO 0)); - bil_t_v:=near_calc(frac_v,(i_hpix,i_hpix,i_ldrm,i_ldrm)); - ELSE - frac_v:=bil_frac(i_v_frac(11 DOWNTO 0)); - bil_t_v:=bil_calc(frac_v,(i_hpix,i_hpix,i_ldrm,i_ldrm)); - END IF; - - 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; - END IF; - - ---------------------------------------------------- - -- VNP : Vert. downscaling line enable - -- HNP : Horiz. downscaling pix. enable - -- VEN : Enable pixel within displayed window - - IF (i_hnp4='1' AND i_ven6='1') OR i_pushend='1' THEN - i_shift<=shift_ishift(i_shift,i_pix,i_format); - i_dw<=shift_ipack(i_dw,i_acpt,i_shift,i_pix,i_format); - - IF shift_inext(i_acpt,i_format) AND i_vnp='1' THEN - i_push<='1'; - i_pushend<='0'; - END IF; - i_acpt<=(i_acpt+1) MOD 16; - 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_pushend2='1' AND i_pushend='0' THEN - i_eol<='1'; - END IF; - - IF i_pde='0' AND i_de_pre='1' THEN - i_de_delay<=0; - ELSIF i_de_delay<18 THEN - i_de_delay<=i_de_delay+1; - END IF; - - IF i_de_delay=16 THEN - i_lwad<=0; - i_lrad<=0; - i_vcpt<=i_vcpt+1; - i_hacc<=(i_hsize - i_ohsize + 8192) MOD 8192; - i_hbcpt<=0; - END IF; - IF i_de_delay=17 THEN - i_acpt<=0; - i_wad<=2*BLEN-1; - END IF; - - IF i_pvs='0' AND i_vs_pre='1' THEN - -- Push header - i_pushhead<=to_std_logic(HEADER); - END IF; - - END IF; -- IF i_pce='1' - - ------------------------------------------------------ - -- Push pixels to downscaling line buffer - i_lwr<=i_hnp4 AND i_ven5 AND i_pce; - IF i_lwr='1' THEN - i_lwad<=(i_lwad+1) MOD OHRES; - END IF; - i_ldw<=i_hpix; - - IF i_hnp3='1' AND i_ven4='1' AND i_pce='1' THEN - i_lrad<=(i_lrad+1) MOD OHRES; - END IF; - - ------------------------------------------------------ - -- Write image properties header - i_pushhead2<=i_pushhead; i_pushhead3<=i_pushhead2; - - IF i_pushhead='1' AND i_freeze='0' THEN - i_dw<=i_head(127 DOWNTO 128-N_DW); - i_count<=i_count+1; - i_wr<='1'; - i_wad<=0; - IF N_DW=128 THEN - i_alt<='0'; - i_wreq<=NOT i_freeze; - i_adrs<=(OTHERS =>'0'); - END IF; - END IF; - - IF i_pushhead2='1' AND i_freeze='0' AND N_DW=64 THEN - i_dw<=i_head(N_DW-1 DOWNTO 0); - i_wr<='1'; - i_wad<=1; - i_wreq<=NOT i_freeze; - i_alt<='0'; - i_adrs<=(OTHERS =>'0'); - END IF; - IF i_pushhead3='1' THEN - i_wad<=BLEN-1; - END IF; - - ------------------------------------------------------ - -- Push pixels to DPRAM - 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 AND i_hbcpt 12 - IDividers:PROCESS (i_clk,i_reset_na) IS - BEGIN - IF i_reset_na='0' THEN + ----------------------------------------------------------------------------- + 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 frac_v : unsigned(FRAC-1 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<='0'; + + ELSIF rising_edge(i_clk) THEN + i_push<='0'; + i_pushhead<='0'; + i_eol<='0'; -- End Of Line + i_freeze <=freeze; -- + i_iauto<=iauto; -- + i_wreq<='0'; + i_wr<='0'; + + ------------------------------------------------------ + i_head(127 DOWNTO 120)<=x"01"; -- Header type + i_head(119 DOWNTO 112)<="000000" & i_format; -- Header format + 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_flm; + i_head(82)<=i_hdown; + i_head(83)<=i_vdown; + 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 16)<="0000" & to_unsigned(i_ohsize,12); + i_head(15 DOWNTO 0) <="0000" & to_unsigned(i_ovsize,12); + + ------------------------------------------------------ + i_ppix<=(i_r,i_g,i_b); + i_pvs<=i_vs; + i_pfl<=i_fl; + i_pde<=i_de; + i_pce<=i_ce; + + ------------------------------------------------------ + IF i_pce='1' THEN + ---------------------------------------------------- + i_vs_pre<=i_pvs; + i_de_pre<=i_pde; + i_fl_pre<=i_pfl; + + ---------------------------------------------------- + -- Detect interlaced video + IF NOT INTER THEN + i_intercnt<=0; + ELSIF i_pfl/=i_fl_pre THEN + i_intercnt<=3; + ELSIF i_pvs='1' AND i_vs_pre='0' AND i_intercnt>0 THEN + i_intercnt<=i_intercnt-1; + END IF; + i_inter<=to_std_logic(i_intercnt>0); + + ---------------------------------------------------- + IF i_pvs='1' AND i_vs_pre='0' THEN + i_sof<='1'; + END IF; + + IF i_pde='1' AND i_de_pre='0' THEN + i_flm<=i_pfl; + END IF; + + IF i_pde='1' AND i_sof='1' THEN + i_sof<='0'; + i_vcpt<=0; + IF i_inter='1' AND i_flm='0' AND i_half='0' AND INTER THEN + i_line<='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_line<='0'; + i_adrsi<=to_unsigned(N_BURST * to_integer( + unsigned'("00") & to_std_logic(HEADER)),32); + END IF; + END IF; + + 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. + i_endframe0<=i_vs AND (NOT i_inter OR i_flm); + i_endframe1<=i_vs AND (NOT i_inter OR NOT i_flm); + + i_vss<=to_std_logic(i_vcpt>=i_vmin AND i_vcpt<=i_vmax); + + ---------------------------------------------------- + IF i_pde='1' AND i_de_pre='0' THEN + i_vimax<=i_vcpt; + i_hcpt<=0; + ELSE + i_hcpt<=(i_hcpt+1) MOD 4096; + END IF; + + IF i_pde='0' AND i_de_pre='1' THEN + i_himax<=i_hcpt; + END IF; + + IF i_iauto='1' THEN + -- Auto-size + i_hmin<=0; + i_hmax<=i_himax; + i_vmin<=0; + 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 + -- Forced image + i_hmin<=himin; -- + i_hmax<=himax; -- + i_vmin<=vimin; -- + IF i_pvs='1' AND i_vs_pre='0' AND (i_inter='0' OR i_pfl='0') THEN + i_vmax<=vimax; -- + END IF; + END IF; + + IF i_pvs='1' AND i_vs_pre='0' AND (i_inter='0' OR i_pfl='0') THEN + i_vdmax<=i_vimax; + END IF; + i_hdmax<=i_himax; + + IF i_format="00" OR i_format="11" THEN -- 16bpp + i_hburst<=(i_hrsize*2 + N_BURST - 1) / N_BURST; + ELSIF i_format="01" THEN -- 24bpp + i_hburst<=(i_hrsize*3 + N_BURST - 1) / N_BURST; + ELSE -- 32bpp + i_hburst<=(i_hrsize*4 + N_BURST - 1) / N_BURST; + END IF; + ---------------------------------------------------- + i_mode<=mode; -- + i_format<=format; -- + + -- Downscaling : Nearest or bilinear + i_bil<=to_std_logic(i_mode(2 DOWNTO 0)/="000" AND NOT DOWNSCALE_NN); + + i_hdown<=to_std_logic(i_hsize>i_ohsize AND DOWNSCALE); --H downscale + i_vdown<=to_std_logic(i_vsize>i_ovsize AND DOWNSCALE); --V downscale + + ---------------------------------------------------- + i_hsize <=(4096+i_hmax-i_hmin+1) MOD 4096; + i_vmaxmin<=(4096+i_vmax-i_vmin+1) MOD 4096; + + IF i_inter='0' THEN + -- Non interlaced + i_vsize<=i_vmaxmin; + i_half <='0'; + ELSIF i_ovsize<2*i_vmaxmin THEN + -- Interlaced, but downscaling, use only half frames + i_vsize<=i_vmaxmin; + i_half <='1'; + ELSE + -- Interlaced : Double image height + i_vsize<=2*i_vmaxmin; + i_half <='0'; + END IF; + + i_ohsize<=o_hsize; -- + i_ovsize<=o_vsize; -- + + ---------------------------------------------------- + -- Downscaling vertical + i_divstart<='0'; + IF i_de_delay=16 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 + 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_vsize - i_ovsize + 8192) MOD 8192; + i_vnp<='1'; -- + END IF; + END IF; + + IF i_vdown='0' THEN + i_vnp<='1'; + END IF; + + -- Downscaling horizontal + IF i_ven='1' THEN + 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 + 2*i_ohsize - 2*i_hsize + 8192) MOD 8192; + i_hnp<='1'; + END IF; + END IF; + IF i_hdown='0' THEN + i_hnp<='1'; + END IF; + + ---------------------------------------------------- + -- Downscaling interpolation + i_hpixp<=i_ppix; + i_hpix0<=i_hpixp; + i_hpix1<=i_hpix0; + i_hpix2<=i_hpix1; + i_hpix3<=i_hpix2; + i_hpix4<=i_hpix3; + + 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; i_ven6<=i_ven5; + + -- C1 : DIV 1. Pipelined 4 bits non-restoring divider + dir_v:=x"000"; + div_v:=to_unsigned(i_hacc * 16,17); + + 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*8,17); + END IF; + 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(16)='0' THEN + div_v:=div_v-to_unsigned(i_hsize*4,17); + ELSE + div_v:=div_v+to_unsigned(i_hsize*4,17); + END IF; + dir_v(9):=NOT div_v(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*2,17); + END IF; + 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); + i_h_bil_t<=near_calc(frac_v,(i_hpix2,i_hpix2,i_hpix3,i_hpix3)); + ELSE + frac_v:=bil_frac(i_h_frac); + i_h_bil_t<=bil_calc(frac_v,(i_hpix2,i_hpix2,i_hpix3,i_hpix3)); + END IF; + + 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); + + IF i_hdown='0' THEN + i_hpix<=i_hpix4; + END IF; + + -- C5 : Vertical Bilinear + IF i_bil='0' THEN + frac_v:=near_frac(i_v_frac(11 DOWNTO 0)); + bil_t_v:=near_calc(frac_v,(i_hpix,i_hpix,i_ldrm,i_ldrm)); + ELSE + frac_v:=bil_frac(i_v_frac(11 DOWNTO 0)); + bil_t_v:=bil_calc(frac_v,(i_hpix,i_hpix,i_ldrm,i_ldrm)); + END IF; + + 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; + END IF; + + ---------------------------------------------------- + -- VNP : Vert. downscaling line enable + -- HNP : Horiz. downscaling pix. enable + -- VEN : Enable pixel within displayed window + + IF (i_hnp4='1' AND i_ven6='1') OR i_pushend='1' THEN + i_shift<=shift_ishift(i_shift,i_pix,i_format); + i_dw<=shift_ipack(i_dw,i_acpt,i_shift,i_pix,i_format); + + IF shift_inext(i_acpt,i_format) AND i_vnp='1' THEN + i_push<='1'; + i_pushend<='0'; + END IF; + i_acpt<=(i_acpt+1) MOD 16; + 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_pushend2='1' AND i_pushend='0' THEN + i_eol<='1'; + END IF; + + IF i_pde='0' AND i_de_pre='1' THEN + i_de_delay<=0; + ELSIF i_de_delay<18 THEN + i_de_delay<=i_de_delay+1; + END IF; + + IF i_de_delay=16 THEN + i_lwad<=0; + i_lrad<=0; + i_vcpt<=i_vcpt+1; + i_hacc<=(i_hsize - i_ohsize + 8192) MOD 8192; + i_hbcpt<=0; + END IF; + IF i_de_delay=17 THEN + i_acpt<=0; + i_wad<=2*BLEN-1; + END IF; + + IF i_pvs='0' AND i_vs_pre='1' THEN + -- Push header + i_pushhead<=to_std_logic(HEADER); + END IF; + + END IF; -- IF i_pce='1' + + ------------------------------------------------------ + -- Push pixels to downscaling line buffer + i_lwr<=i_hnp4 AND i_ven5 AND i_pce; + IF i_lwr='1' THEN + i_lwad<=(i_lwad+1) MOD OHRES; + END IF; + i_ldw<=i_hpix; + + IF i_hnp3='1' AND i_ven4='1' AND i_pce='1' THEN + i_lrad<=(i_lrad+1) MOD OHRES; + END IF; + + ------------------------------------------------------ + -- Write image properties header + i_pushhead2<=i_pushhead; i_pushhead3<=i_pushhead2; + + IF i_pushhead='1' AND i_freeze='0' THEN + i_dw<=i_head(127 DOWNTO 128-N_DW); + i_count<=i_count+1; + i_wr<='1'; + i_wad<=0; + IF N_DW=128 THEN + i_alt<='0'; + i_wreq<=NOT i_freeze; + i_adrs<=(OTHERS =>'0'); + END IF; + END IF; + + IF i_pushhead2='1' AND i_freeze='0' AND N_DW=64 THEN + i_dw<=i_head(N_DW-1 DOWNTO 0); + i_wr<='1'; + i_wad<=1; + i_wreq<=NOT i_freeze; + i_alt<='0'; + i_adrs<=(OTHERS =>'0'); + END IF; + IF i_pushhead3='1' THEN + i_wad<=BLEN-1; + END IF; + + ------------------------------------------------------ + -- Push pixels to DPRAM + 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 AND i_hbcpt 12 + IDividers:PROCESS (i_clk,i_reset_na) IS + BEGIN + IF i_reset_na='0' THEN --pragma synthesis_off - i_v_frac<=x"000"; + i_v_frac<=x"000"; --pragma synthesis_on - NULL; - ELSIF rising_edge(i_clk) THEN - i_vdivi<=to_unsigned(2*i_vsize,13); - i_vdivr<=to_unsigned(i_vacc*4096,25); - - ------------------------------------------------------ - IF i_divstart='1' THEN - i_divcpt<=0; - i_divrun<='1'; - - ELSIF i_divrun='1' THEN - ---------------------------------------------------- - IF i_divcpt=6 THEN - i_divrun<='0'; - i_v_frac<=i_vdivr(4 DOWNTO 0) & NOT i_vdivr(24) & "000000"; - ELSE - i_divcpt<=i_divcpt+1; - END IF; - - IF i_vdivr(24)='0' THEN - i_vdivr(24 DOWNTO 12)<=i_vdivr(23 DOWNTO 11) - i_vdivi; - ELSE - 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(24); - - ---------------------------------------------------- - END IF; - END IF; - END PROCESS IDividers; + NULL; + ELSIF rising_edge(i_clk) THEN + i_vdivi<=to_unsigned(2*i_vsize,13); + i_vdivr<=to_unsigned(i_vacc*4096,25); - ----------------------------------------------------------------------------- - -- DPRAM Input. Double buffer for RAM bursts. - 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_mem(i_lwad MOD IHRES)<=i_ldw; - END IF; - IF i_pce='1' THEN - i_ldrm<=i_mem(i_lrad MOD IHRES); - END IF; - END IF; - END PROCESS ILBUF; - END GENERATE DownLine; - - ----------------------------------------------------------------------------- - -- AVALON interface - Avaloir:PROCESS(avl_clk,avl_reset_na) IS - VARIABLE adr_v : unsigned(31 DOWNTO 0); - BEGIN - IF avl_reset_na='0' THEN - avl_state<=sIDLE; - avl_write_sr<='0'; - avl_read_sr<='0'; - avl_readdataack<='0'; - avl_readack<='0'; - - ELSIF rising_edge(avl_clk) THEN - ---------------------------------- - avl_write_sync<=i_write; -- - avl_write_sync2<=avl_write_sync; - avl_write_pulse<=avl_write_sync XOR avl_write_sync2; - IF avl_write_pulse='1' THEN - avl_wadrs <=i_wadrs AND (RAMSIZE - 1); -- - avl_wline <=i_wline; -- - avl_walt <=i_walt; -- - END IF; - - ---------------------------------- - avl_read_sync<=o_read; -- - avl_read_sync2<=avl_read_sync; - avl_read_pulse<=avl_read_sync XOR avl_read_sync2; - avl_radrs <=o_adrs; -- - avl_rline <=o_rline; -- - - -------------------------------------------- - avl_o_vs_sync<=o_vsv(0); -- - avl_o_vs<=avl_o_vs_sync; - - avl_fb_ena<=o_fb_ena; -- - IF avl_fb_ena='0' THEN - IF HEADER THEN - avl_o_offset0<=buf_offset(o_obuf0,RAMBASE,RAMSIZE) + N_BURST; -- - avl_o_offset1<=buf_offset(o_obuf1,RAMBASE,RAMSIZE) + N_BURST; -- - ELSE - avl_o_offset0<=buf_offset(o_obuf0,RAMBASE,RAMSIZE); -- - avl_o_offset1<=buf_offset(o_obuf1,RAMBASE,RAMSIZE); -- - END IF; - ELSIF avl_o_vs_sync='0' AND avl_o_vs='1' THEN - -- Copy framebuffer base address at VS falling edge - avl_o_offset0<=o_fb_base; -- - avl_o_offset1<=o_fb_base; -- - END IF; - - avl_i_offset0<=buf_offset(o_ibuf0,RAMBASE,RAMSIZE); -- - avl_i_offset1<=buf_offset(o_ibuf1,RAMBASE,RAMSIZE); -- - - -------------------------------------------- - avl_dw<=swap(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_write_sr='1' THEN - avl_state<=sWRITE; - avl_write_clr<='1'; - IF avl_walt='0' THEN - avl_rad<=0; - ELSE - avl_rad<=BLEN; - END IF; - IF avl_wline='0' THEN - avl_address<=std_logic_vector( - 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( - avl_wadrs(N_AW+NB_LA-1 DOWNTO NB_LA) + - avl_i_offset1(N_AW+NB_LA-1 DOWNTO NB_LA)); - END IF; - ELSIF avl_read_sr='1' THEN - avl_state<=sREAD; - avl_read_clr<='1'; - END IF; - - WHEN sWRITE => - 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 => - IF avl_rline='0' THEN - adr_v:=avl_radrs + avl_o_offset0; - ELSE - adr_v:=avl_radrs + avl_o_offset1; - END IF; - avl_address<=std_logic_vector(adr_v(N_AW+NB_LA-1 DOWNTO NB_LA)); - - avl_read_i<='1'; - IF avl_read_i='1' AND avl_waitrequest='0' THEN - avl_state<=sIDLE; - avl_read_i<='0'; - avl_readack<=NOT avl_readack; - END IF; - END CASE; - - -------------------------------------------- - -- 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_readdataack<=NOT avl_readdataack; - END IF; - END IF; + ------------------------------------------------------ + IF i_divstart='1' THEN + i_divcpt<=0; + i_divrun<='1'; - IF avl_o_vs_sync='0' AND avl_o_vs='1' THEN - avl_wad<=2*BLEN-1; - END IF; - - -------------------------------------------- - END IF; - END PROCESS Avaloir; - - avl_read<=avl_read_i; - avl_write<=avl_write_i; - avl_writedata<=std_logic_vector(swap(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. Double buffer for RAM bursts. - 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_ad3) WHEN rising_edge(o_clk); - - ----------------------------------------------------------------------------- - -- Output Vertical Divider - -- Vfrac = Vacc / Vsize - ODivider:PROCESS (o_clk,o_reset_na) IS - BEGIN - IF o_reset_na='0' THEN + ELSIF i_divrun='1' THEN + ---------------------------------------------------- + IF i_divcpt=6 THEN + i_divrun<='0'; + i_v_frac<=i_vdivr(4 DOWNTO 0) & NOT i_vdivr(24) & "000000"; + ELSE + i_divcpt<=i_divcpt+1; + END IF; + + IF i_vdivr(24)='0' THEN + i_vdivr(24 DOWNTO 12)<=i_vdivr(23 DOWNTO 11) - i_vdivi; + ELSE + 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(24); + + ---------------------------------------------------- + END IF; + END IF; + END PROCESS IDividers; + + ----------------------------------------------------------------------------- + -- DPRAM Input. Double buffer for RAM bursts. + 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_mem(i_lwad MOD IHRES)<=i_ldw; + END IF; + IF i_pce='1' THEN + i_ldrm<=i_mem(i_lrad MOD IHRES); + END IF; + END IF; + END PROCESS ILBUF; + END GENERATE DownLine; + + ----------------------------------------------------------------------------- + -- AVALON interface + Avaloir:PROCESS(avl_clk,avl_reset_na) IS + VARIABLE adr_v : unsigned(31 DOWNTO 0); + BEGIN + IF avl_reset_na='0' THEN + avl_state<=sIDLE; + avl_write_sr<='0'; + avl_read_sr<='0'; + avl_readdataack<='0'; + avl_readack<='0'; + + ELSIF rising_edge(avl_clk) THEN + ---------------------------------- + avl_write_sync<=i_write; -- + avl_write_sync2<=avl_write_sync; + avl_write_pulse<=avl_write_sync XOR avl_write_sync2; + IF avl_write_pulse='1' THEN + avl_wadrs <=i_wadrs AND (RAMSIZE - 1); -- + avl_wline <=i_wline; -- + avl_walt <=i_walt; -- + END IF; + + ---------------------------------- + avl_read_sync<=o_read; -- + avl_read_sync2<=avl_read_sync; + avl_read_pulse<=avl_read_sync XOR avl_read_sync2; + avl_radrs <=o_adrs; -- + avl_rline <=o_rline; -- + + -------------------------------------------- + avl_o_vs_sync<=o_vsv(0); -- + avl_o_vs<=avl_o_vs_sync; + + avl_fb_ena<=o_fb_ena; -- + IF avl_fb_ena='0' THEN + IF HEADER THEN + avl_o_offset0<=buf_offset(o_obuf0,RAMBASE,RAMSIZE) + N_BURST; -- + avl_o_offset1<=buf_offset(o_obuf1,RAMBASE,RAMSIZE) + N_BURST; -- + ELSE + avl_o_offset0<=buf_offset(o_obuf0,RAMBASE,RAMSIZE); -- + avl_o_offset1<=buf_offset(o_obuf1,RAMBASE,RAMSIZE); -- + END IF; + ELSIF avl_o_vs_sync='0' AND avl_o_vs='1' THEN + -- Copy framebuffer base address at VS falling edge + avl_o_offset0<=o_fb_base; -- + avl_o_offset1<=o_fb_base; -- + END IF; + + avl_i_offset0<=buf_offset(o_ibuf0,RAMBASE,RAMSIZE); -- + avl_i_offset1<=buf_offset(o_ibuf1,RAMBASE,RAMSIZE); -- + + -------------------------------------------- + avl_dw<=swap(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_write_sr='1' THEN + avl_state<=sWRITE; + avl_write_clr<='1'; + IF avl_walt='0' THEN + avl_rad<=0; + ELSE + avl_rad<=BLEN; + END IF; + IF avl_wline='0' THEN + avl_address<=std_logic_vector( + 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( + avl_wadrs(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_i_offset1(N_AW+NB_LA-1 DOWNTO NB_LA)); + END IF; + ELSIF avl_read_sr='1' THEN + avl_state<=sREAD; + avl_read_clr<='1'; + END IF; + + WHEN sWRITE => + 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 => + IF avl_rline='0' THEN + adr_v:=avl_radrs + avl_o_offset0; + ELSE + adr_v:=avl_radrs + avl_o_offset1; + END IF; + avl_address<=std_logic_vector(adr_v(N_AW+NB_LA-1 DOWNTO NB_LA)); + + avl_read_i<='1'; + IF avl_read_i='1' AND avl_waitrequest='0' THEN + avl_state<=sIDLE; + avl_read_i<='0'; + avl_readack<=NOT avl_readack; + END IF; + END CASE; + + -------------------------------------------- + -- 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_readdataack<=NOT avl_readdataack; + END IF; + END IF; + + IF avl_o_vs_sync='0' AND avl_o_vs='1' THEN + avl_wad<=2*BLEN-1; + END IF; + + -------------------------------------------- + END IF; + END PROCESS Avaloir; + + avl_read<=avl_read_i; + avl_write<=avl_write_i; + avl_writedata<=std_logic_vector(swap(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. Double buffer for RAM bursts. + 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_ad3) WHEN rising_edge(o_clk); + + ----------------------------------------------------------------------------- + -- Output Vertical Divider + -- Vfrac = Vacc / Vsize + ODivider:PROCESS (o_clk,o_reset_na) IS + BEGIN + IF o_reset_na='0' THEN --pragma synthesis_off - o_vfrac<=x"000"; + o_vfrac<=x"000"; --pragma synthesis_on - ELSIF rising_edge(o_clk) THEN - o_vdivi<=to_unsigned(2*o_vsize,13); - o_vdivr<=to_unsigned(o_vacc*4096,25); - ------------------------------------------------------ - IF o_divstart='1' THEN - o_divcpt<=0; - o_divrun<='1'; - - ELSIF o_divrun='1' THEN - ---------------------------------------------------- - IF o_divcpt=12 THEN - o_divrun<='0'; - o_vfrac<=o_vdivr(10 DOWNTO 0) & NOT o_vdivr(24); - ELSE - o_divcpt<=o_divcpt+1; - END IF; - - IF o_vdivr(24)='0' THEN - o_vdivr(24 DOWNTO 12)<=o_vdivr(23 DOWNTO 11) - o_vdivi; - ELSE - 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(24); - ---------------------------------------------------- - END IF; - END IF; - END PROCESS ODivider; - - ----------------------------------------------------------------------------- - Scalaire:PROCESS (o_clk,o_reset_na) IS - 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 hpix_v : type_pix; - VARIABLE hcarry_v,vcarry_v : boolean; - VARIABLE dif_v : natural RANGE 0 TO 8*OHRES-1; - VARIABLE off_v : natural RANGE 0 TO 15; - BEGIN - IF o_reset_na='0' THEN - o_copy<=sWAIT; - 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_format <="0001" & format; -- ? - - 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_hsize <=o_hmax - o_hmin + 1; - o_vsize <=o_vmax - o_vmin + 1; - - -------------------------------------------- - -- Triple buffering. - -- For intelaced video, half frames are updated independently - -- Input : Toggle buffer at end of input frame - o_freeze <= freeze; - 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_freeze); - 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_freeze); - 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_bufup0='1' THEN - o_obuf0<=buf_next(o_obuf0,o_ibuf0,o_freeze); - o_bufup0<='0'; - END IF; - IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup1='1' THEN - o_obuf1<=buf_next(o_obuf1,o_ibuf1,o_freeze); - o_bufup1<='0'; - o_ihsize<=i_hrsize; -- - o_ivsize<=i_vrsize; -- - o_hdown<=i_hdown; -- - o_vdown<=i_vdown; -- - END IF; - - -- Simultaneous change of input and output framebuffers - IF o_vsv(1)='1' AND o_vsv(0)='0' AND - o_iendframe0='1' AND o_iendframe02='0' THEN - o_bufup0<='0'; - o_obuf0<=o_ibuf0; - END IF; - IF o_vsv(1)='1' AND o_vsv(0)='0' AND - o_iendframe1='1' AND o_iendframe12='0' THEN - o_bufup1<='0'; - o_obuf1<=o_ibuf1; - END IF; - - -- Non-interlaced, use same buffer for even and odd lines - 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_obuf0<=0; - o_obuf1<=0; - o_ibuf0<=0; - o_ibuf1<=0; - END IF; - - -- Framebuffer mode. - IF o_fb_ena='1' THEN - o_ihsize<=o_fb_hsize; - o_ivsize<=o_fb_vsize; - o_format<=o_fb_format; - o_hdown<='0'; - o_vdown<='0'; - END IF; - - -- 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp - CASE o_format(2 DOWNTO 0) IS - WHEN "011" => o_ihsize_temp <= o_ihsize; - WHEN "100" => o_ihsize_temp <= o_ihsize * 2; - WHEN "110" => o_ihsize_temp <= o_ihsize * 4; - WHEN OTHERS => o_ihsize_temp <= o_ihsize * 3; - END CASE; + ELSIF rising_edge(o_clk) THEN + o_vdivi<=to_unsigned(2*o_vsize,13); + o_vdivr<=to_unsigned(o_vacc*4096,25); + ------------------------------------------------------ + IF o_divstart='1' THEN + o_divcpt<=0; + o_divrun<='1'; - o_ihsize_temp2 <= (o_ihsize_temp + N_BURST - 1); - o_hburst <= o_ihsize_temp2 / N_BURST; - - IF o_fb_ena='1' AND o_fb_stride /= 0 THEN - o_stride<=o_fb_stride; - ELSE - o_stride<=to_unsigned(o_ihsize_temp2,14); - o_stride(NB_BURST-1 DOWNTO 0)<=(OTHERS =>'0'); - END IF; - ------------------------------------------------------ - o_hmode<=o_mode; - IF o_hdown='1' AND DOWNSCALE THEN - -- Force nearest if downscaling : Downscaled framebuffer - o_hmode(2 DOWNTO 0)<="000"; - END IF; - - o_vmode<=o_mode; - IF o_vdown='1' AND DOWNSCALE THEN - -- Force nearest if downscaling : Downscaled framebuffer - o_vmode(2 DOWNTO 0)<="000"; - 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; - - o_readdataack_sync<=avl_readdataack; -- - o_readdataack_sync2<=o_readdataack_sync; - o_readdataack<=o_readdataack_sync XOR o_readdataack_sync2; - - ------------------------------------------------------ - lev_inc_v:='0'; - lev_dec_v:='0'; - - -- acpt : Pixel position within current data word - -- dcpt : Destination image position - - -- Force preload 2 lines at top of screen - IF o_hsv(0)='1' AND o_hsv(1)='0' THEN - IF o_vcpt_pre3=o_vmin THEN - o_fload<=2; - o_bibu<='0'; - END IF; - o_hsp<='1'; - END IF; - - o_vpe<=to_std_logic(o_vcpt_pre=o_vmin); - o_divstart<='0'; - o_adrsa<='0'; - o_adrsb<=o_adrsa; - - o_vacc_ini<=(o_vsize - o_ivsize + 8192) MOD 8192; - o_hacc_ini<=(o_hsize + o_ihsize + 8192) MOD 8192; - - --Alternate phase - --o_vacc_ini<=o_ivsize; - --o_hacc_ini<=(2*o_hsize - o_ihsize + 8192) MOD 8192; - - CASE o_state IS - -------------------------------------------------- - WHEN sDISP => - IF o_hsp='1' THEN - o_state<=sHSYNC; - o_hsp<='0'; - END IF; - o_prim<=true; - o_vcarrym<=false; - - -------------------------------------------------- - WHEN sHSYNC => - dif_v :=(o_vacc_next - 2*o_vsize + 16384) MOD 16384; - IF o_prim THEN - IF dif_v>=8192 THEN - o_vacc <=o_vacc_next; - ELSE - o_vacc <=dif_v; - END IF; - END IF; - IF dif_v>=8192 THEN - o_vacc_next<=(o_vacc_next + 2*o_ivsize) MOD 8192; - vcarry_v:=false; - ELSE - o_vacc_next<=dif_v; - vcarry_v:=true; - END IF; - - IF o_vcpt_pre2=o_vmin THEN - o_vacc <=o_vacc_ini; - o_vacc_next<=o_vacc_ini + 2*o_ivsize; - o_vacpt <=x"001"; - o_vacptl<="01"; - vcarry_v:=false; - END IF; - - IF vcarry_v THEN - o_vacpt<=o_vacpt+1; - END IF; - IF vcarry_v AND o_prim THEN - o_vacptl<=o_vacptl+1; - END IF; - o_vcarrym <= o_vcarrym OR vcarry_v; - o_prim <= false; - o_hbcpt<=0; -- Clear burst counter on line - o_divstart<=to_std_logic(NOT vcarry_v); - IF NOT vcarry_v OR o_fload>0 THEN - IF (o_vpe='1' AND o_vcarrym) OR o_fload>0 THEN - o_state<=sREAD; - ELSE - o_state<=sDISP; - END IF; - END IF; - - WHEN sREAD => - -- Read a block - IF o_readlev<2 AND o_adrsb='1' THEN - lev_inc_v:='1'; - o_read_pre<=NOT o_read_pre; - 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; - off_v :=pixoffset(o_adrs + o_fb_base(NB_LA-1 DOWNTO 0),o_fb_format); - IF o_fb_ena='0' THEN - off_v:=0; - END IF; - o_adrsa<='1'; - - 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; - - o_read<=o_read_pre AND o_run; - o_rline<=o_vacpt(0); -- Even/Odd line for interlaced video - - o_adrs_pre<=to_integer(o_vacpt) * to_integer(o_stride); - IF o_adrsa='1' THEN - IF o_fload=2 THEN - o_adrs<=to_unsigned(o_hbcpt * N_BURST,32); - o_alt<="1111"; - ELSIF o_fload=1 THEN - o_adrs<=to_unsigned(o_hbcpt * N_BURST,32) + o_stride; - o_alt<="0100"; - ELSE - o_adrs<=to_unsigned(o_adrs_pre + (o_hbcpt * N_BURST),32); - o_alt<=altx(o_vacptl + 1); - END IF; - END IF; - - ------------------------------------------------------ - -- Copy from buffered memory to pixel lines - o_sh<='0'; - CASE o_copy IS - WHEN sWAIT => - o_copyv(0)<='0'; - IF o_copylev>0 AND o_copyv(0)='0' THEN - o_copy<=sCOPY; - IF o_off(0)>0 AND o_primv(0)='1' THEN - o_copy<=sSHIFT; - END IF; - o_altx<=o_alt; - END IF; - o_adturn<='0'; - o_pshift<=o_off(0) -1; - IF o_primv(0)='1' THEN - -- First memcopy of a horizontal line, carriage return ! - o_ihsizem<=o_ihsize + o_off(0) - 2; - o_hacc <=o_hacc_ini; - o_hacc_next<=o_hacc_ini + 2*o_ihsize; - o_hacpt <=x"000"; - o_dcpt<=0; - o_dshi<=2; - o_acpt<=0; - o_first<='1'; - o_last<='0'; - END IF; - - IF o_bibv(0)='0' THEN - o_ad<=0; - ELSE - o_ad<=BLEN; - END IF; - - WHEN sSHIFT => - o_hacpt<=o_hacpt+1; - o_sh<='1'; - o_acpt<=(o_acpt+1) MOD 16; - IF shift_onext(o_acpt,o_format) THEN - o_ad<=(o_ad+1) MOD (2*BLEN); - END IF; - o_pshift<=o_pshift-1; - IF o_pshift=0 THEN - o_copy<=sCOPY; - END IF; - - WHEN sCOPY => - -- dshi : Force shift first two or three pixels of each line - IF o_dshi=0 THEN - dif_v:=(o_hacc_next - 2*o_hsize + (8*OHRES)) MOD (8*OHRES); - IF dif_v>=4*OHRES THEN - o_hacc<=o_hacc_next; - o_hacc_next<=o_hacc_next + 2*o_ihsize; - hcarry_v:=false; - ELSE - o_hacc<=dif_v; - o_hacc_next<=(dif_v + 2*o_ihsize + (4*OHRES)) MOD (4*OHRES); - hcarry_v:=true; - END IF; - o_dcpt<=(o_dcpt+1) MOD 4096; - ELSE - o_dshi<=o_dshi-1; - hcarry_v:=false; - END IF; - IF o_dshi<=1 THEN - o_copyv(0)<='1'; - END IF; - IF hcarry_v THEN - o_hacpt<=o_hacpt+1; - o_last <=to_std_logic(o_hacpt>=o_ihsizem); - END IF; - - IF hcarry_v OR o_dshi>0 THEN - o_sh<='1'; - o_acpt<=(o_acpt+1) MOD 16; - - -- Shift two more pixels to the right before ending line. - o_last1<=o_last; - o_last2<=o_last1; - - IF shift_onext(o_acpt,o_format) THEN - o_ad<=(o_ad+1) MOD (2*BLEN); - END IF; - - IF o_adturn='1' AND (shift_onext((o_acpt+1) MOD 16,o_format)) AND - (((o_ad MOD BLEN=0) AND o_lastv(0)='0') OR o_last2='1') THEN - o_copy<=sWAIT; - lev_dec_v:='1'; - END IF; - - IF o_ad MOD BLEN=4 THEN - o_adturn<='1'; - END IF; - END IF; - END CASE; - - o_acpt1<=o_acpt; o_acpt2<=o_acpt1; o_acpt3<=o_acpt2; o_acpt4<=o_acpt3; - o_ad1<=o_ad; o_ad2<=o_ad1; o_ad3<=o_ad2; - o_sh1<=o_sh; o_sh2<=o_sh1; o_sh3<=o_sh2; o_sh4<=o_sh3; - o_lastt1<=o_last; o_lastt2<=o_lastt1; - o_lastt3<=o_lastt2; o_lastt4<=o_lastt3; - - ------------------------------------------------------ - IF o_sh3='1' THEN - shift_v:=shift_opack(o_acpt4,o_shift,o_dr,o_format); - o_shift<=shift_v; - o_hpixs<=shift_opix(shift_v,o_format); - END IF; - - IF o_sh4='1' THEN - hpix_v:=o_hpixs; - IF o_format(4)='1' THEN -- Swap B <-> R - hpix_v:=(r=>o_hpixs.b,g=>o_hpixs.g,b=>o_hpixs.r); - END IF; - IF o_format(2 DOWNTO 0)="011" THEN - -- 8bpp indexed colour mode - hpix_v:=(r=>o_fb_pal_dr(23 DOWNTO 16),g=>o_fb_pal_dr(15 DOWNTO 8), - b=>o_fb_pal_dr(7 DOWNTO 0)); - END IF; - o_hpix0<=hpix_v; - o_hpix1<=o_hpix0; - o_hpix2<=o_hpix1; - o_hpix3<=o_hpix2; + ELSIF o_divrun='1' THEN + ---------------------------------------------------- + IF o_divcpt=12 THEN + o_divrun<='0'; + o_vfrac<=o_vdivr(10 DOWNTO 0) & NOT o_vdivr(24); + ELSE + o_divcpt<=o_divcpt+1; + END IF; - IF o_first='1' THEN - -- Left edge. Duplicate first pixel - o_hpix1<=hpix_v; - o_hpix2<=hpix_v; - o_first<='0'; - END IF; - IF o_lastt4='1' THEN - -- Right edge. Keep last pixel. - o_hpix0<=o_hpix0; - END IF; - END IF; - - ------------------------------------------------------ - -- lev_inc : read start - -- lev_dec : end of copy - -- READLEV : Number of ongoing Avalon Reads - IF lev_dec_v='0' AND lev_inc_v='1' THEN - o_readlev<=o_readlev+1; - ELSIF lev_dec_v='1' AND lev_inc_v='0' THEN - o_readlev<=o_readlev-1; - END IF; - - -- COPYLEV : Number of ongoing copies to line buffers - IF lev_dec_v='1' AND o_readdataack='0' THEN - o_copylev<=o_copylev-1; - ELSIF lev_dec_v='0' AND o_readdataack='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 - o_off (0 TO 1)<=o_off (1 TO 2); -- Start offset - 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; - o_off (0)<=off_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; - o_off (1)<=off_v; - END IF; - o_primv(2)<=prim_v; - o_lastv(2)<=last_v; - o_bibv (2)<=bib_v; - o_off (2)<=off_v; - END IF; - - ------------------------------------------------------ - END IF; - END PROCESS Scalaire; + IF o_vdivr(24)='0' THEN + o_vdivr(24 DOWNTO 12)<=o_vdivr(23 DOWNTO 11) - o_vdivi; + ELSE + 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(24); + ---------------------------------------------------- + END IF; + END IF; + END PROCESS ODivider; - -- Fetch polyphase coefficients - PolyFetch:PROCESS (o_clk) IS - VARIABLE hfrac2_v, hfrac3_v, vfrac_v : unsigned(FRAC-1 DOWNTO 0); - VARIABLE o_poly_phase_v : poly_phase_interp_t; - BEGIN - IF rising_edge(o_clk) THEN - hfrac2_v:=o_hfrac(2)(11 DOWNTO 12-FRAC); - hfrac3_v:=o_hfrac(3)(11 DOWNTO 12-FRAC); - vfrac_v:=o_vfrac(11 DOWNTO 12-FRAC); + ----------------------------------------------------------------------------- + Scalaire:PROCESS (o_clk,o_reset_na) IS + 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 hpix_v : type_pix; + VARIABLE hcarry_v,vcarry_v : boolean; + VARIABLE dif_v : natural RANGE 0 TO 8*OHRES-1; + VARIABLE off_v : natural RANGE 0 TO 15; + BEGIN + IF o_reset_na='0' THEN + o_copy<=sWAIT; + o_state<=sDISP; + o_read_pre<='0'; + o_readlev<=0; + o_copylev<=0; + o_hsp<='0'; - o_v_poly_use_adaptive <= to_std_logic((o_vmode(2 DOWNTO 0)/="000") AND (o_v_poly_adaptive = '1')); - o_h_poly_use_adaptive <= to_std_logic((o_hmode(2 DOWNTO 0)/="000") AND (o_h_poly_adaptive = '1')); + ELSIF rising_edge(o_clk) THEN + ------------------------------------------------------ + o_mode <=mode; -- ? + o_format <="0001" & format; -- ? - -- C2 / HC2 / VC3 - o_v_poly_addr<=to_integer(vfrac_v); - o_h_poly_addr<=to_integer(hfrac2_v); - IF o_v_poly_use_adaptive = '1' THEN - o_a_poly_addr<=to_integer(vfrac_v); - ELSIF o_h_poly_use_adaptive = '1' THEN - o_a_poly_addr<=to_integer(hfrac2_v); - END IF; + o_run <=run; -- ? - -- C3 / HC3 / VC4 - IF o_vmode(2 DOWNTO 0)/="000" THEN - o_v_poly_phase_a<=poly_unpack(o_v_poly_mem(o_v_poly_addr)); - ELSE - o_v_poly_phase_a<=poly_nn(vfrac_v); - END IF; + o_htotal <=htotal; -- ? + o_hsstart<=hsstart; -- ? + o_hsend <=hsend; -- ? + o_hdisp <=hdisp; -- ? + o_hmin <=hmin; -- ? + o_hmax <=hmax; -- ? - IF o_hmode(2 DOWNTO 0)/="000" THEN - o_h_poly_phase_a<=poly_unpack(o_h_poly_mem(o_h_poly_addr)); - ELSE - o_h_poly_phase_a<=poly_nn(hfrac3_v); - END IF; + o_vtotal <=vtotal; -- ? + o_vsstart<=vsstart; -- ? + o_vsend <=vsend; -- ? + o_vdisp <=vdisp; -- ? + o_vmin <=vmin; -- ? + o_vmax <=vmax; -- ? - IF o_v_poly_use_adaptive='1' THEN - o_poly_lum<=o_v_poly_lum; - ELSIF o_h_poly_use_adaptive='1' THEN - o_poly_lum<=o_h_poly_lum; - END IF; + o_hsize <=o_hmax - o_hmin + 1; + o_vsize <=o_vmax - o_vmin + 1; - o_poly_phase_b<=poly_unpack(o_a_poly_mem(o_a_poly_addr)); + o_vrr <=vrr; + o_vrrmax <= vrrmax; - -- C4 / HC4 / VC5 - o_poly_lerp_ta<=signed(to_unsigned(256,10) - resize(o_poly_lum,10)); - o_poly_lerp_tb<=signed(resize(o_poly_lum,10)); + -------------------------------------------- + -- Triple buffering. + -- For intelaced video, half frames are updated independently + -- Input : Toggle buffer at end of input frame + o_isync <= '0'; + o_isync2 <= o_isync; + o_freeze <= freeze; + 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_freeze); + o_bufup0<='1'; + o_isync <= '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_freeze); + o_bufup1<='1'; + o_isync <= '1'; + END IF; - IF o_v_poly_use_adaptive='1' THEN - o_poly_phase_a<=o_v_poly_phase_a; - ELSIF o_h_poly_use_adaptive = '1' THEN - o_poly_phase_a<=o_h_poly_phase_a; - END IF; + -- Output : Change framebuffer, and image properties, at VS falling edge + IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN + o_obuf0<=buf_next(o_obuf0,o_ibuf0,o_freeze); + o_bufup0<='0'; + END IF; + IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup1='1' THEN + o_obuf1<=buf_next(o_obuf1,o_ibuf1,o_freeze); + o_bufup1<='0'; + o_ihsize<=i_hrsize; -- + o_ivsize<=i_vrsize; -- + o_hdown<=i_hdown; -- + o_vdown<=i_vdown; -- + END IF; - o_h_poly_phase_a2<=o_h_poly_phase_a; - o_v_poly_phase_a2<=o_v_poly_phase_a; - o_poly_phase_b2<=o_poly_phase_b; + -- Simultaneous change of input and output framebuffers + IF o_vsv(1)='1' AND o_vsv(0)='0' AND + o_iendframe0='1' AND o_iendframe02='0' THEN + o_bufup0<='0'; + o_obuf0<=o_ibuf0; + END IF; + IF o_vsv(1)='1' AND o_vsv(0)='0' AND + o_iendframe1='1' AND o_iendframe12='0' THEN + o_bufup1<='0'; + o_obuf1<=o_ibuf1; + END IF; - -- C5 / HC5 / VC6 - o_poly_phase<=poly_lerp(o_poly_phase_a, o_poly_phase_b2, o_poly_lerp_ta, o_poly_lerp_tb); - o_h_poly_phase_a3<=o_h_poly_phase_a2; - o_v_poly_phase_a3<=o_v_poly_phase_a2; + -- Non-interlaced, use same buffer for even and odd lines + IF o_inter='0' THEN + o_ibuf1<=o_ibuf0; + o_obuf1<=o_obuf0; + END IF; - -- C6 / HC6 / VC7 - o_v_poly_phase<=poly_cvt(o_v_poly_phase_a3); - o_h_poly_phase<=poly_cvt(o_h_poly_phase_a3); + -- Triple buffer disabled + IF o_mode(3)='0' THEN + o_obuf0<=0; + o_obuf1<=0; + o_ibuf0<=0; + o_ibuf1<=0; + END IF; - IF o_v_poly_use_adaptive = '1' THEN - o_v_poly_phase<=o_poly_phase; - ELSIF o_h_poly_use_adaptive = '1' THEN - o_h_poly_phase<=o_poly_phase; - END IF; + -- Framebuffer mode. + IF o_fb_ena='1' THEN + o_ihsize<=o_fb_hsize; + o_ivsize<=o_fb_vsize; + o_format<=o_fb_format; + o_hdown<='0'; + o_vdown<='0'; + END IF; - END IF; - END PROCESS PolyFetch; + -- 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp + CASE o_format(2 DOWNTO 0) IS + WHEN "011" => o_ihsize_temp <= o_ihsize; + WHEN "100" => o_ihsize_temp <= o_ihsize * 2; + WHEN "110" => o_ihsize_temp <= o_ihsize * 4; + WHEN OTHERS => o_ihsize_temp <= o_ihsize * 3; + END CASE; + + o_ihsize_temp2 <= (o_ihsize_temp + N_BURST - 1); + o_hburst <= o_ihsize_temp2 / N_BURST; + + IF o_fb_ena='1' AND o_fb_stride /= 0 THEN + o_stride<=o_fb_stride; + ELSE + o_stride<=to_unsigned(o_ihsize_temp2,14); + o_stride(NB_BURST-1 DOWNTO 0)<=(OTHERS =>'0'); + END IF; + ------------------------------------------------------ + o_hmode<=o_mode; + IF o_hdown='1' AND DOWNSCALE THEN + -- Force nearest if downscaling : Downscaled framebuffer + o_hmode(2 DOWNTO 0)<="000"; + END IF; + + o_vmode<=o_mode; + IF o_vdown='1' AND DOWNSCALE THEN + -- Force nearest if downscaling : Downscaled framebuffer + o_vmode(2 DOWNTO 0)<="000"; + 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; + + o_readdataack_sync<=avl_readdataack; -- + o_readdataack_sync2<=o_readdataack_sync; + o_readdataack<=o_readdataack_sync XOR o_readdataack_sync2; + + ------------------------------------------------------ + lev_inc_v:='0'; + lev_dec_v:='0'; + + -- acpt : Pixel position within current data word + -- dcpt : Destination image position + + -- Force preload 2 lines at top of screen + IF o_hsv(0)='1' AND o_hsv(1)='0' THEN + IF o_vcpt_pre3=o_vmin THEN + o_fload<=2; + o_bibu<='0'; + END IF; + o_hsp<='1'; + END IF; + + o_vpe<=to_std_logic(o_vcpt_pre=o_vmin); + o_divstart<='0'; + o_adrsa<='0'; + o_adrsb<=o_adrsa; + + o_vacc_ini<=(o_vsize - o_ivsize + 8192) MOD 8192; + o_hacc_ini<=(o_hsize + o_ihsize + 8192) MOD 8192; + + --Alternate phase + --o_vacc_ini<=o_ivsize; + --o_hacc_ini<=(2*o_hsize - o_ihsize + 8192) MOD 8192; + + CASE o_state IS + -------------------------------------------------- + WHEN sDISP => + IF o_hsp='1' THEN + o_state<=sHSYNC; + o_hsp<='0'; + END IF; + o_prim<=true; + o_vcarrym<=false; + + -------------------------------------------------- + WHEN sHSYNC => + dif_v :=(o_vacc_next - 2*o_vsize + 16384) MOD 16384; + IF o_prim THEN + IF dif_v>=8192 THEN + o_vacc <=o_vacc_next; + ELSE + o_vacc <=dif_v; + END IF; + END IF; + IF dif_v>=8192 THEN + o_vacc_next<=(o_vacc_next + 2*o_ivsize) MOD 8192; + vcarry_v:=false; + ELSE + o_vacc_next<=dif_v; + vcarry_v:=true; + END IF; + + IF o_vcpt_pre2=o_vmin THEN + o_vacc <=o_vacc_ini; + o_vacc_next<=o_vacc_ini + 2*o_ivsize; + o_vacpt <=x"001"; + o_vacptl<="01"; + vcarry_v:=false; + END IF; + + IF vcarry_v THEN + o_vacpt<=o_vacpt+1; + END IF; + IF vcarry_v AND o_prim THEN + o_vacptl<=o_vacptl+1; + END IF; + o_vcarrym <= o_vcarrym OR vcarry_v; + o_prim <= false; + o_hbcpt<=0; -- Clear burst counter on line + o_divstart<=to_std_logic(NOT vcarry_v); + IF NOT vcarry_v OR o_fload>0 THEN + IF (o_vpe='1' AND o_vcarrym) OR o_fload>0 THEN + o_state<=sREAD; + ELSE + o_state<=sDISP; + END IF; + END IF; + + WHEN sREAD => + -- Read a block + IF o_readlev<2 AND o_adrsb='1' THEN + lev_inc_v:='1'; + o_read_pre<=NOT o_read_pre; + 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; + off_v :=pixoffset(o_adrs + o_fb_base(NB_LA-1 DOWNTO 0),o_fb_format); + IF o_fb_ena='0' THEN + off_v:=0; + END IF; + o_adrsa<='1'; + + 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; + + o_read<=o_read_pre AND o_run; + o_rline<=o_vacpt(0); -- Even/Odd line for interlaced video + + o_adrs_pre<=to_integer(o_vacpt) * to_integer(o_stride); + IF o_adrsa='1' THEN + IF o_fload=2 THEN + o_adrs<=to_unsigned(o_hbcpt * N_BURST,32); + o_alt<="1111"; + ELSIF o_fload=1 THEN + o_adrs<=to_unsigned(o_hbcpt * N_BURST,32) + o_stride; + o_alt<="0100"; + ELSE + o_adrs<=to_unsigned(o_adrs_pre + (o_hbcpt * N_BURST),32); + o_alt<=altx(o_vacptl + 1); + END IF; + END IF; + + ------------------------------------------------------ + -- Copy from buffered memory to pixel lines + o_sh<='0'; + CASE o_copy IS + WHEN sWAIT => + o_copyv(0)<='0'; + IF o_copylev>0 AND o_copyv(0)='0' THEN + o_copy<=sCOPY; + IF o_off(0)>0 AND o_primv(0)='1' THEN + o_copy<=sSHIFT; + END IF; + o_altx<=o_alt; + END IF; + o_adturn<='0'; + o_pshift<=o_off(0) -1; + IF o_primv(0)='1' THEN + -- First memcopy of a horizontal line, carriage return ! + o_ihsizem<=o_ihsize + o_off(0) - 2; + o_hacc <=o_hacc_ini; + o_hacc_next<=o_hacc_ini + 2*o_ihsize; + o_hacpt <=x"000"; + o_dcpt<=0; + o_dshi<=2; + o_acpt<=0; + o_first<='1'; + o_last<='0'; + END IF; + + IF o_bibv(0)='0' THEN + o_ad<=0; + ELSE + o_ad<=BLEN; + END IF; + + WHEN sSHIFT => + o_hacpt<=o_hacpt+1; + o_sh<='1'; + o_acpt<=(o_acpt+1) MOD 16; + IF shift_onext(o_acpt,o_format) THEN + o_ad<=(o_ad+1) MOD (2*BLEN); + END IF; + o_pshift<=o_pshift-1; + IF o_pshift=0 THEN + o_copy<=sCOPY; + END IF; + + WHEN sCOPY => + -- dshi : Force shift first two or three pixels of each line + IF o_dshi=0 THEN + dif_v:=(o_hacc_next - 2*o_hsize + (8*OHRES)) MOD (8*OHRES); + IF dif_v>=4*OHRES THEN + o_hacc<=o_hacc_next; + o_hacc_next<=o_hacc_next + 2*o_ihsize; + hcarry_v:=false; + ELSE + o_hacc<=dif_v; + o_hacc_next<=(dif_v + 2*o_ihsize + (4*OHRES)) MOD (4*OHRES); + hcarry_v:=true; + END IF; + o_dcpt<=(o_dcpt+1) MOD 4096; + ELSE + o_dshi<=o_dshi-1; + hcarry_v:=false; + END IF; + IF o_dshi<=1 THEN + o_copyv(0)<='1'; + END IF; + IF hcarry_v THEN + o_hacpt<=o_hacpt+1; + o_last <=to_std_logic(o_hacpt>=o_ihsizem); + END IF; + + IF hcarry_v OR o_dshi>0 THEN + o_sh<='1'; + o_acpt<=(o_acpt+1) MOD 16; + + -- Shift two more pixels to the right before ending line. + o_last1<=o_last; + o_last2<=o_last1; + + IF shift_onext(o_acpt,o_format) THEN + o_ad<=(o_ad+1) MOD (2*BLEN); + END IF; + + IF o_adturn='1' AND (shift_onext((o_acpt+1) MOD 16,o_format)) AND + (((o_ad MOD BLEN=0) AND o_lastv(0)='0') OR o_last2='1') THEN + o_copy<=sWAIT; + lev_dec_v:='1'; + END IF; + + IF o_ad MOD BLEN=4 THEN + o_adturn<='1'; + END IF; + END IF; + END CASE; + + o_acpt1<=o_acpt; o_acpt2<=o_acpt1; o_acpt3<=o_acpt2; o_acpt4<=o_acpt3; + o_ad1<=o_ad; o_ad2<=o_ad1; o_ad3<=o_ad2; + o_sh1<=o_sh; o_sh2<=o_sh1; o_sh3<=o_sh2; o_sh4<=o_sh3; + o_lastt1<=o_last; o_lastt2<=o_lastt1; + o_lastt3<=o_lastt2; o_lastt4<=o_lastt3; + + ------------------------------------------------------ + IF o_sh3='1' THEN + shift_v:=shift_opack(o_acpt4,o_shift,o_dr,o_format); + o_shift<=shift_v; + o_hpixs<=shift_opix(shift_v,o_format); + END IF; + + IF o_sh4='1' THEN + hpix_v:=o_hpixs; + IF o_format(4)='1' THEN -- Swap B <-> R + hpix_v:=(r=>o_hpixs.b,g=>o_hpixs.g,b=>o_hpixs.r); + END IF; + IF o_format(2 DOWNTO 0)="011" THEN + -- 8bpp indexed colour mode + hpix_v:=(r=>o_fb_pal_dr(23 DOWNTO 16),g=>o_fb_pal_dr(15 DOWNTO 8), + b=>o_fb_pal_dr(7 DOWNTO 0)); + END IF; + o_hpix0<=hpix_v; + o_hpix1<=o_hpix0; + o_hpix2<=o_hpix1; + o_hpix3<=o_hpix2; + + IF o_first='1' THEN + -- Left edge. Duplicate first pixel + o_hpix1<=hpix_v; + o_hpix2<=hpix_v; + o_first<='0'; + END IF; + IF o_lastt4='1' THEN + -- Right edge. Keep last pixel. + o_hpix0<=o_hpix0; + END IF; + END IF; + + ------------------------------------------------------ + -- lev_inc : read start + -- lev_dec : end of copy + -- READLEV : Number of ongoing Avalon Reads + IF lev_dec_v='0' AND lev_inc_v='1' THEN + o_readlev<=o_readlev+1; + ELSIF lev_dec_v='1' AND lev_inc_v='0' THEN + o_readlev<=o_readlev-1; + END IF; + + -- COPYLEV : Number of ongoing copies to line buffers + IF lev_dec_v='1' AND o_readdataack='0' THEN + o_copylev<=o_copylev-1; + ELSIF lev_dec_v='0' AND o_readdataack='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 + o_off (0 TO 1)<=o_off (1 TO 2); -- Start offset + 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; + o_off (0)<=off_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; + o_off (1)<=off_v; + END IF; + o_primv(2)<=prim_v; + o_lastv(2)<=last_v; + o_bibv (2)<=bib_v; + o_off (2)<=off_v; + END IF; + + ------------------------------------------------------ + END IF; + END PROCESS Scalaire; + + -- Fetch polyphase coefficients + PolyFetch:PROCESS (o_clk) IS + VARIABLE hfrac3_v, vfrac_v : unsigned(FRAC-1 DOWNTO 0); + BEGIN + IF rising_edge(o_clk) THEN + hfrac3_v:=o_hfrac(3)(11 DOWNTO 12-FRAC); + vfrac_v:=o_vfrac(11 DOWNTO 12-FRAC); + + o_v_poly_use_adaptive <= to_std_logic((o_vmode(2 DOWNTO 0)/="000") AND (o_v_poly_adaptive = '1')); + o_h_poly_use_adaptive <= to_std_logic((o_hmode(2 DOWNTO 0)/="000") AND (o_h_poly_adaptive = '1')); + o_v_poly_addr<=to_integer(o_vfrac(11 DOWNTO 12-FRAC)); + + -- C3 / HC3 / VC4 + IF o_vmode(2 DOWNTO 0)/="000" THEN + o_v_poly_phase_a<=poly_unpack(o_v_poly_mem(o_v_poly_addr)); + ELSE + o_v_poly_phase_a<=poly_nn(vfrac_v); + END IF; + + IF o_hmode(2 DOWNTO 0)/="000" THEN + o_h_poly_phase_a<=poly_unpack(o_h_poly_mem(to_integer(hfrac3_v))); + ELSE + o_h_poly_phase_a<=poly_nn(hfrac3_v); + END IF; + + IF o_v_poly_use_adaptive='1' THEN + o_poly_lum<=poly_lum(o_v_lum_pix); + o_a_poly_addr<=o_v_poly_addr; + ELSIF o_h_poly_use_adaptive='1' THEN + o_poly_lum<=poly_lum(o_h_lum_pix); + o_a_poly_addr<=to_integer(hfrac3_v); + END IF; + + -- C4 / HC4 / VC5 + o_poly_phase_b<=poly_unpack(o_a_poly_mem(o_a_poly_addr)); + + IF o_v_poly_use_adaptive='1' THEN + o_poly_phase_a<=o_v_poly_phase_a; + ELSIF o_h_poly_use_adaptive = '1' THEN + o_poly_phase_a<=o_h_poly_phase_a; + END IF; + + o_h_poly_phase_a2<=o_h_poly_phase_a; + o_v_poly_phase_a2<=o_v_poly_phase_a; + o_poly_lum1<=o_poly_lum; + + -- C5 / HC5 / VC6 + o_poly_lerp_ta<=signed(to_unsigned(256,10) - resize(o_poly_lum1,10)); + o_poly_lerp_tb<=signed(resize(o_poly_lum1,10)); + + o_poly_phase_b2<=o_poly_phase_b; + o_poly_phase_a2<=o_poly_phase_a; + + o_h_poly_phase_a3<=o_h_poly_phase_a2; + o_v_poly_phase_a3<=o_v_poly_phase_a2; + + -- C6 / HC6 / VC7 + o_poly_phase<=poly_lerp(o_poly_phase_a2, o_poly_phase_b2, o_poly_lerp_ta, o_poly_lerp_tb); + o_h_poly_phase_a4<=o_h_poly_phase_a3; + o_v_poly_phase_a4<=o_v_poly_phase_a3; + + -- C7 / HC7 / VC8 + o_h_poly_phase_a5<=o_h_poly_phase_a4; + o_v_poly_phase_a5<=o_v_poly_phase_a4; + o_poly_phase1<=o_poly_phase; + + -- C8 / HC8 / VC9 + o_v_poly_phase<=poly_cvt(o_v_poly_phase_a5); + o_h_poly_phase<=poly_cvt(o_h_poly_phase_a5); + + IF o_v_poly_use_adaptive = '1' THEN + o_v_poly_phase<=o_poly_phase1; + ELSIF o_h_poly_use_adaptive = '1' THEN + o_h_poly_phase<=o_poly_phase1; + END IF; + + END IF; + END PROCESS PolyFetch; - -- Framebuffer palette - GenPal1:IF PALETTE GENERATE - Tempera1:PROCESS(pal1_clk) IS - BEGIN - IF rising_edge(pal1_clk) THEN - IF pal1_wr='1' THEN - pal1_mem(to_integer(pal1_a))<=pal1_dw; - END IF; - pal1_dr<=pal1_mem(to_integer(pal1_a)); - END IF; - END PROCESS; + -- Framebuffer palette + GenPal1:IF PALETTE GENERATE + Tempera1:PROCESS(pal1_clk) IS + BEGIN + IF rising_edge(pal1_clk) THEN + IF pal1_wr='1' THEN + pal1_mem(to_integer(pal1_a))<=pal1_dw; + END IF; + pal1_dr<=pal1_mem(to_integer(pal1_a)); + END IF; + END PROCESS; - pal_idx <= shift_opack(o_acpt4,o_shift,o_dr,o_format)(0 TO 7); - pal_idx_lsb <= pal_idx(0) WHEN rising_edge(o_clk); - o_fb_pal_dr_x2 <= pal1_mem(to_integer(pal_idx(7 DOWNTO 1))) WHEN rising_edge(o_clk); - END GENERATE GenPal1; - - GenPal2:IF PALETTE and PALETTE2 GENERATE - Tempera2:PROCESS(pal2_clk) IS - BEGIN - IF rising_edge(pal2_clk) THEN - IF pal2_wr='1' THEN - pal2_mem(to_integer(pal2_a))<=pal2_dw; - END IF; - pal2_dr<=pal2_mem(to_integer(pal2_a)); - END IF; - END PROCESS; + pal_idx <= shift_opack(o_acpt4,o_shift,o_dr,o_format)(0 TO 7); + pal_idx_lsb <= pal_idx(0) WHEN rising_edge(o_clk); + o_fb_pal_dr_x2 <= pal1_mem(to_integer(pal_idx(7 DOWNTO 1))) WHEN rising_edge(o_clk); + END GENERATE GenPal1; - o_fb_pal_dr2 <= pal2_mem(to_integer(pal_idx(7 DOWNTO 0))) WHEN rising_edge(o_clk); - o_fb_pal_dr <= o_fb_pal_dr2 when pal_n = '1' else o_fb_pal_dr_x2(47 DOWNTO 24) WHEN pal_idx_lsb = '1' ELSE o_fb_pal_dr_x2(23 DOWNTO 0); - END GENERATE GenPal2; + GenPal2:IF PALETTE and PALETTE2 GENERATE + Tempera2:PROCESS(pal2_clk) IS + BEGIN + IF rising_edge(pal2_clk) THEN + IF pal2_wr='1' THEN + pal2_mem(to_integer(pal2_a))<=pal2_dw; + END IF; + pal2_dr<=pal2_mem(to_integer(pal2_a)); + END IF; + END PROCESS; - GenPal1not2:IF PALETTE and not PALETTE2 GENERATE - o_fb_pal_dr <= o_fb_pal_dr_x2(47 DOWNTO 24) WHEN pal_idx_lsb = '1' ELSE o_fb_pal_dr_x2(23 DOWNTO 0); - END GENERATE GenPal1not2; - - GenNoPal:IF NOT PALETTE GENERATE - o_fb_pal_dr<=x"000000"; - END GENERATE GenNoPal; - - ----------------------------------------------------------------------------- - -- Polyphase ROMs - Polikarpov:PROCESS(poly_clk) IS - BEGIN - IF rising_edge(poly_clk) THEN - IF poly_wr='1' THEN - poly_tdw(9+10*(3-to_integer(poly_a(1 DOWNTO 0))) DOWNTO - 10*(3-to_integer(poly_a(1 DOWNTO 0))))<=poly_dw; - END IF; - - poly_wr_mode(0)<=poly_wr AND NOT poly_a(FRAC+2); - poly_wr_mode(1)<=poly_wr AND poly_a(FRAC+2); - poly_wr_mode(2)<=poly_wr AND poly_a(FRAC+3) AND to_std_logic(ADAPTIVE); - poly_a2<=poly_a(FRAC+1 DOWNTO 2); - - CASE poly_wr_mode IS - WHEN "001" => -- horiz - o_h_poly_mem(to_integer(poly_a2))<=poly_tdw; - o_h_poly_adaptive<='0'; - WHEN "010" => -- vert - o_v_poly_mem(to_integer(poly_a2))<=poly_tdw; - o_v_poly_adaptive<='0'; - WHEN "101" => -- horiz adaptive - o_a_poly_mem(to_integer(poly_a2))<=poly_tdw; - o_h_poly_adaptive<='1'; - WHEN "110" => -- vert adaptive - o_a_poly_mem(to_integer(poly_a2))<=poly_tdw; - o_v_poly_adaptive<='1'; - WHEN OTHERS => NULL; - END CASE; - END IF; - END PROCESS Polikarpov; - - ----------------------------------------------------------------------------- - -- Horizontal Scaler - HSCAL:PROCESS(o_clk) IS - VARIABLE div_v : unsigned(20 DOWNTO 0); - VARIABLE dir_v : unsigned(11 DOWNTO 0); - BEGIN - IF rising_edge(o_clk) THEN - -- Pipeline signals - ----------------------------------- - -- Pipelined 8 bits non-restoring divider. Cycle 1 - dir_v:=x"000"; - div_v:=to_unsigned(o_hacc * 256,21); - - div_v:=div_v-to_unsigned(o_hsize*256,21); - dir_v(11):=NOT div_v(20); - IF div_v(20)='0' THEN - div_v:=div_v-to_unsigned(o_hsize*128,21); - ELSE - div_v:=div_v+to_unsigned(o_hsize*128,21); - END IF; - dir_v(10):=NOT div_v(20); + o_fb_pal_dr2 <= pal2_mem(to_integer(pal_idx(7 DOWNTO 0))) WHEN rising_edge(o_clk); + o_fb_pal_dr <= o_fb_pal_dr2 when pal_n = '1' else o_fb_pal_dr_x2(47 DOWNTO 24) WHEN pal_idx_lsb = '1' ELSE o_fb_pal_dr_x2(23 DOWNTO 0); + END GENERATE GenPal2; - o_div(0)<=div_v; - o_dir(0)<=dir_v; - - -- Cycle 2 - div_v:=o_div(0); - dir_v:=o_dir(0); - IF div_v(20)='0' THEN - div_v:=div_v-to_unsigned(o_hsize*64,21); - ELSE - div_v:=div_v+to_unsigned(o_hsize*64,21); - END IF; - dir_v( 9):=NOT div_v(20); + GenPal1not2:IF PALETTE and not PALETTE2 GENERATE + o_fb_pal_dr <= o_fb_pal_dr_x2(47 DOWNTO 24) WHEN pal_idx_lsb = '1' ELSE o_fb_pal_dr_x2(23 DOWNTO 0); + END GENERATE GenPal1not2; - IF div_v(20)='0' THEN - div_v:=div_v-to_unsigned(o_hsize*32,21); - ELSE - div_v:=div_v+to_unsigned(o_hsize*32,21); - END IF; - dir_v( 8):=NOT div_v(20); + GenNoPal:IF NOT PALETTE GENERATE + o_fb_pal_dr<=x"000000"; + END GENERATE GenNoPal; - o_div(1)<=div_v; - o_dir(1)<=dir_v; + ----------------------------------------------------------------------------- + -- Polyphase ROMs + Polikarpov:PROCESS(poly_clk) IS + BEGIN + IF rising_edge(poly_clk) THEN + IF poly_wr='1' THEN + poly_tdw(9+10*(3-to_integer(poly_a(1 DOWNTO 0))) DOWNTO + 10*(3-to_integer(poly_a(1 DOWNTO 0))))<=poly_dw; + END IF; - -- Cycle 3 - div_v:=o_div(1); - dir_v:=o_dir(1); - IF FRAC>4 THEN - IF div_v(20)='0' THEN - div_v:=div_v-to_unsigned(o_hsize*16,21); - ELSE - div_v:=div_v+to_unsigned(o_hsize*16,21); - END IF; - dir_v(7):=NOT div_v(20); + poly_wr_mode(0)<=poly_wr AND NOT poly_a(FRAC+2); + poly_wr_mode(1)<=poly_wr AND poly_a(FRAC+2); + poly_wr_mode(2)<=poly_wr AND poly_a(FRAC+3) AND to_std_logic(ADAPTIVE); + poly_a2<=poly_a(FRAC+1 DOWNTO 2); - IF div_v(20)='0' THEN - div_v:=div_v-to_unsigned(o_hsize*8,21); - ELSE - div_v:=div_v+to_unsigned(o_hsize*8,21); - END IF; - dir_v(6):=NOT div_v(20); - END IF; - o_div(2)<=div_v; - o_dir(2)<=dir_v; + CASE poly_wr_mode IS + WHEN "001" => -- horiz + o_h_poly_mem(to_integer(poly_a2))<=poly_tdw; + o_h_poly_adaptive<='0'; + WHEN "010" => -- vert + o_v_poly_mem(to_integer(poly_a2))<=poly_tdw; + o_v_poly_adaptive<='0'; + WHEN "101" => -- horiz adaptive + o_a_poly_mem(to_integer(poly_a2))<=poly_tdw; + o_h_poly_adaptive<='1'; + WHEN "110" => -- vert adaptive + o_a_poly_mem(to_integer(poly_a2))<=poly_tdw; + o_v_poly_adaptive<='1'; + WHEN OTHERS => NULL; + END CASE; + END IF; + END PROCESS Polikarpov; - div_v:=o_div(2); - dir_v:=o_dir(2); - IF FRAC>6 THEN - IF div_v(20)='0' THEN - div_v:=div_v-to_unsigned(o_hsize*4,21); - ELSE - div_v:=div_v+to_unsigned(o_hsize*4,21); - END IF; - dir_v(5):=NOT div_v(20); - - IF div_v(20)='0' THEN - div_v:=div_v-to_unsigned(o_hsize*2,21); - ELSE - div_v:=div_v+to_unsigned(o_hsize*2,21); - END IF; - dir_v(4):=NOT div_v(20); - END IF; - - ----------------------------------- - o_hfrac(1)<=dir_v; - o_hfrac(2 TO 6) <= o_hfrac(1 TO 5); - - o_copyv(1 TO 12)<=o_copyv(0 TO 11); - - o_dcptv(1)<=o_dcpt; - IF o_dcptv(1)>=o_hsize THEN - o_copyv(2)<='0'; - END IF; - o_dcptv(2)<=o_dcptv(1) MOD OHRES; - o_dcptv(3 TO 12)<=o_dcptv(2 TO 11); - - -- C2 - o_hpixq(2)<=(o_hpix3,o_hpix2,o_hpix1,o_hpix0); - o_hpixq(3 TO 6)<=o_hpixq(2 TO 5); - - -- BILINEAR / SHARP BILINEAR --------------- - -- C4 : Pre-calc Sharp Bilinear - o_h_sbil_t<=sbil_frac1(o_hfrac(3)); - - -- C5 : Select - o_h_bil_frac<=(OTHERS =>'0'); - IF o_hmode(0)='1' THEN -- Bilinear - IF MASK(MASK_BILINEAR)='1' THEN - o_h_bil_frac<=bil_frac(o_hfrac(4)); - END IF; - ELSE -- Sharp Bilinear - IF MASK(MASK_SHARP_BILINEAR)='1' THEN - o_h_bil_frac<=sbil_frac2(o_hfrac(4),o_h_sbil_t); - END IF; - END IF; - - -- C6 : Opposite frac - o_h_bil_t<=bil_calc(o_h_bil_frac,o_hpixq(5)); - - -- C7 : Bilinear / Sharp Bilinear - o_h_bil_pix.r<=bound(o_h_bil_t.r,8+FRAC); - o_h_bil_pix.g<=bound(o_h_bil_t.g,8+FRAC); - o_h_bil_pix.b<=bound(o_h_bil_t.b,8+FRAC); - - -- BICUBIC ------------------------------------------- - -- C5 : Bicubic coefficients A,B,C,D - -- C5 : Bicubic calc T1 = X.D + C - o_h_bic_abcd1<=bic_calc0(o_hfrac(4),o_hpixq(4)); - o_h_bic_tt1<=bic_calc1(o_hfrac(4), - bic_calc0(o_hfrac(4),o_hpixq(4))); - - -- C6 : Bicubic calc T2 = X.T1 + B - o_h_bic_abcd2<=o_h_bic_abcd1; - o_h_bic_tt2<=bic_calc2(o_hfrac(5),o_h_bic_tt1,o_h_bic_abcd1); - - -- C7 : Bicubic final Y = X.T2 + A - o_h_bic_pix<=bic_calc3(o_hfrac(6),o_h_bic_tt2,o_h_bic_abcd2); - - -- POLYPHASE ----------------------------------------- - -- C2 - IF o_hfrac(2)(o_hfrac(2)'left)='0' THEN - o_h_poly_lum<=poly_lum(o_hpix2); - ELSE - o_h_poly_lum<=poly_lum(o_hpix1); - END IF; - -- C3-C6 in PolyFetch + ----------------------------------------------------------------------------- + -- Horizontal Scaler + HSCAL:PROCESS(o_clk) IS + VARIABLE div_v : unsigned(20 DOWNTO 0); + VARIABLE dir_v : unsigned(11 DOWNTO 0); + BEGIN + IF rising_edge(o_clk) THEN + -- Pipeline signals + ----------------------------------- + -- Pipelined 8 bits non-restoring divider. Cycle 1 + dir_v:=x"000"; + div_v:=to_unsigned(o_hacc * 256,21); - -- C7 : Apply Polyphase - o_h_poly_t<=poly_calc(o_h_poly_phase,o_hpixq(6)); + div_v:=div_v-to_unsigned(o_hsize*256,21); + dir_v(11):=NOT div_v(20); + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*128,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*128,21); + END IF; + dir_v(10):=NOT div_v(20); - -- C8 : Sum and bound - o_h_poly_pix<=poly_final(o_h_poly_t); - - -- C9 : Select interpoler ---------------------------- - o_wadl<=o_dcptv(12); - o_wr<=o_altx AND (o_copyv(12) & o_copyv(12) & o_copyv(12) & o_copyv(12)); - o_ldw<=(x"00",x"00",x"00"); - - CASE o_hmode(2 DOWNTO 0) IS - WHEN "000" => -- Nearest - IF MASK(MASK_NEAREST)='1' THEN - o_ldw<=o_h_poly_pix; - END IF; - WHEN "001" | "010" => -- Bilinear | Sharp Bilinear - IF MASK(MASK_BILINEAR)='1' OR - MASK(MASK_SHARP_BILINEAR)='1' THEN - o_ldw<=o_h_bil_pix; - END IF; - WHEN "011" => -- BiCubic - IF MASK(MASK_BICUBIC)='1' THEN - o_ldw<=o_h_bic_pix; - END IF; - WHEN OTHERS => -- PolyPhase - IF MASK(MASK_POLY)='1' THEN - o_ldw<=o_h_poly_pix; - END IF; - END CASE; - ------------------------------------------------------ - END IF; - END PROCESS HSCAL; - - ----------------------------------------------------------------------------- - -- Line buffers 4 x OHRES x (R+G+B) - OLBUF:PROCESS(o_clk) IS - BEGIN - IF rising_edge(o_clk) THEN - -- WRITES - IF o_wr(0)='1' THEN o_line0(o_wadl)<=o_ldw; END IF; - IF o_wr(1)='1' THEN o_line1(o_wadl)<=o_ldw; END IF; - IF o_wr(2)='1' THEN o_line2(o_wadl)<=o_ldw; END IF; - IF o_wr(3)='1' THEN o_line3(o_wadl)<=o_ldw; END IF; - - -- READS - o_ldr0<=o_line0(o_radl0); - o_ldr1<=o_line1(o_radl1); - o_ldr2<=o_line2(o_radl2); - o_ldr3<=o_line3(o_radl3); - END IF; - END PROCESS OLBUF; - - ----------------------------------------------------------------------------- - -- 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+1=o_vtotal THEN - o_vcpt_pre3<=0; - ELSE - o_vcpt_pre3<=(o_vcpt_pre3+1) MOD 4096; - END IF; - o_vcpt_pre2<=o_vcpt_pre3; - o_vcpt_pre<=o_vcpt_pre2; - o_vcpt<=o_vcpt_pre; - END IF; - - o_end(0)<=to_std_logic(o_vcpt>=o_vdisp); - o_dev(0)<=to_std_logic(o_hcpt=o_hmin AND o_hcpt<=o_hmax AND - o_vcpt>=o_vmin AND o_vcpt<=o_vmax); - o_hsv(0)<=to_std_logic(o_hcpt>=o_hsstart AND o_hcpt=o_hsstart) OR - (o_vcpt>o_vsstart AND o_vcpt=o_vmin AND o_vcpt_pre2<=o_vmax); - o_hsv(1 TO 9)<=o_hsv(0 TO 8); - o_vsv(1 TO 9)<=o_vsv(0 TO 8); - o_dev(1 TO 9)<=o_dev(0 TO 8); - o_pev(1 TO 9)<=o_pev(0 TO 8); - o_end(1 TO 9)<=o_end(0 TO 8); - - IF o_run='0' THEN - o_hsv(2)<='0'; - o_vsv(2)<='0'; - o_dev(2)<='0'; - o_pev(2)<='0'; - o_end(2)<='0'; - END IF; - - END IF; - END IF; - - END PROCESS OSWEEP; - - ----------------------------------------------------------------------------- - -- Vertical Scaler - VSCAL:PROCESS(o_clk) IS - VARIABLE pixq_v : arr_pix(0 TO 3); - VARIABLE vlumpix_v : type_pix; - VARIABLE r1_v, r2_v : natural RANGE 0 TO OHRES-1; - VARIABLE fracnn_v : std_logic; - BEGIN - IF rising_edge(o_clk) THEN - IF o_ce='1' THEN - o_v_hmin_adj<=o_hmin + 4; + o_div(0)<=div_v; + o_dir(0)<=dir_v; - fracnn_v := o_vfrac(o_vfrac'left); - r1_v := (o_hcpt - o_v_hmin_adj + OHRES) MOD OHRES; - r2_v := (o_hcpt - o_hmin + OHRES) MOD OHRES; + -- Cycle 2 + div_v:=o_div(0); + dir_v:=o_dir(0); + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*64,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*64,21); + END IF; + dir_v( 9):=NOT div_v(20); - -- CYCLE 1 ----------------------------------------- - -- Read mem - o_radl0<=r1_v; - o_radl1<=r1_v; - o_radl2<=r1_v; - o_radl3<=r1_v; + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*32,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*32,21); + END IF; + dir_v( 8):=NOT div_v(20); - IF fracnn_v = '0' THEN - CASE o_vacptl IS - WHEN "10" => o_radl1<=r2_v; - WHEN "11" => o_radl2<=r2_v; - WHEN "00" => o_radl3<=r2_v; - WHEN OTHERS => o_radl0<=r2_v; - END CASE; - ELSE - CASE o_vacptl IS - WHEN "10" => o_radl2<=r2_v; - WHEN "11" => o_radl3<=r2_v; - WHEN "00" => o_radl0<=r2_v; - WHEN OTHERS => o_radl1<=r2_v; - END CASE; - END IF; + o_div(1)<=div_v; + o_dir(1)<=dir_v; - -- CYCLE 2 ----------------------------------------- - -- Lines reordering - CASE o_vacptl IS - WHEN "10" => pixq_v:=(o_ldr0,o_ldr1,o_ldr2,o_ldr3); - WHEN "11" => pixq_v:=(o_ldr1,o_ldr2,o_ldr3,o_ldr0); - WHEN "00" => pixq_v:=(o_ldr2,o_ldr3,o_ldr0,o_ldr1); - WHEN OTHERS => pixq_v:=(o_ldr3,o_ldr0,o_ldr1,o_ldr2); - END CASE; + -- Cycle 3 + div_v:=o_div(1); + dir_v:=o_dir(1); + IF FRAC>4 THEN + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*16,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*16,21); + END IF; + dir_v(7):=NOT div_v(20); - IF fracnn_v = '0' THEN - o_vpix_outer<=(pixq_v(0), pixq_v(2), pixq_v(3)); - o_vpix_inner(0)<=pixq_v(1); - ELSE - o_vpix_outer<=(pixq_v(0), pixq_v(1), pixq_v(3)); - o_vpix_inner(0)<=pixq_v(2); - END IF; + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*8,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*8,21); + END IF; + dir_v(6):=NOT div_v(20); + END IF; + o_div(2)<=div_v; + o_dir(2)<=dir_v; - -- CYCLE 3-6 - o_vpix_inner(1 TO 4)<=o_vpix_inner(0 TO 3); + div_v:=o_div(2); + dir_v:=o_dir(2); + IF FRAC>6 THEN + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*4,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*4,21); + END IF; + dir_v(5):=NOT div_v(20); - -- CYCLE 7 - IF to_integer(o_vacpt)>o_ivsize THEN - IF fracnn_v = '0' THEN - o_vpixq<=(o_vpix_outer(0), o_vpix_inner(4), o_vpix_inner(4), o_vpix_inner(4)); - ELSE - o_vpixq<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_outer(1), o_vpix_outer(1)); - END IF; - ELSIF to_integer(o_vacpt)=o_ivsize THEN - IF fracnn_v = '0' THEN - o_vpixq<=(o_vpix_outer(0), o_vpix_inner(4), o_vpix_outer(1), o_vpix_outer(1)); - ELSE - o_vpixq<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_inner(4), o_vpix_inner(4)); - END IF; - ELSE - IF fracnn_v = '0' THEN - o_vpixq<=(o_vpix_outer(0), o_vpix_inner(4), o_vpix_outer(1), o_vpix_outer(2)); - ELSE - o_vpixq<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_inner(4), o_vpix_outer(2)); - END IF; - END IF; - - -- BILINEAR / SHARP BILINEAR ----------------------- - -- C6 : Pre-calc Sharp Bilinear - o_v_sbil_t<=sbil_frac1(o_vfrac); - - -- C7 : Select - o_v_bil_frac<=(OTHERS =>'0'); - IF o_vmode(0)='1' THEN -- Bilinear - IF MASK(MASK_BILINEAR)='1' THEN - o_v_bil_frac<=bil_frac(o_vfrac); - END IF; - ELSE -- Sharp Bilinear - IF MASK(MASK_SHARP_BILINEAR)='1' THEN - o_v_bil_frac<=sbil_frac2(o_vfrac,o_v_sbil_t); - END IF; - END IF; + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*2,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*2,21); + END IF; + dir_v(4):=NOT div_v(20); + END IF; - -- C8 : - o_v_bil_t<=bil_calc(o_v_bil_frac,o_vpixq); - - -- C9 : Nearest / Bilinear / Sharp Bilinear - o_v_bil_pix.r<=bound(o_v_bil_t.r,8+FRAC); - o_v_bil_pix.g<=bound(o_v_bil_t.g,8+FRAC); - o_v_bil_pix.b<=bound(o_v_bil_t.b,8+FRAC); - - -- BICUBIC ----------------------------------------- - -- C7 : Bicubic coefficients A,B,C,D - -- C7 : Bicubic calc T1 = X.D + C - o_v_bic_abcd1<=bic_calc0(o_vfrac,o_vpixq); - o_v_bic_tt1<=bic_calc1(o_vfrac,bic_calc0(o_vfrac,o_vpixq)); - - -- C8 : Bicubic calc T2 = X.T1 + B - o_v_bic_abcd2<=o_v_bic_abcd1; - o_v_bic_tt2<=bic_calc2(o_vfrac,o_v_bic_tt1,o_v_bic_abcd1); - - -- C9 : Bicubic final Y = X.T2 + A - o_v_bic_pix<=bic_calc3(o_vfrac,o_v_bic_tt2,o_v_bic_abcd2); - - -- POLYPHASE --------------------------------------- - -- C3 : Calculate Luminance - o_v_poly_lum<=poly_lum(o_vpix_inner(0)); + ----------------------------------- + o_hfrac(1)<=dir_v; + o_hfrac(2 TO 9) <= o_hfrac(1 TO 8); - -- C4-C7 in PolyFetch + o_copyv(1 TO 14)<=o_copyv(0 TO 13); - -- C8 : Apply polyphase - o_v_poly_t<=poly_calc(o_v_poly_phase,o_vpixq); + o_dcptv(1)<=o_dcpt; + IF o_dcptv(1)>=o_hsize THEN + o_copyv(2)<='0'; + END IF; + o_dcptv(2)<=o_dcptv(1) MOD OHRES; + o_dcptv(3 TO 14)<=o_dcptv(2 TO 13); - -- C9 : Bound - o_v_poly_pix<=poly_final(o_v_poly_t); + -- C2 + o_hpixq(2)<=(o_hpix3,o_hpix2,o_hpix1,o_hpix0); + o_hpixq(3 TO 8)<=o_hpixq(2 TO 7); - -- CYCLE 10 ----------------------------------------- - o_hs<=o_hsv(9); - o_vs<=o_vsv(9); - o_de<=o_dev(9); - o_vbl<=o_end(9); - o_r<=x"00"; - o_g<=x"00"; - o_b<=x"00"; - o_brd<= not o_pev(9); - - CASE o_vmode(2 DOWNTO 0) IS - WHEN "000" => -- Nearest - IF MASK(MASK_NEAREST)='1' THEN - o_r<=o_v_poly_pix.r; - o_g<=o_v_poly_pix.g; - o_b<=o_v_poly_pix.b; - END IF; - WHEN "001" | "010" => -- Bilinear | Sharp Bilinear - IF MASK(MASK_BILINEAR)='1' OR - MASK(MASK_SHARP_BILINEAR)='1' THEN - o_r<=o_v_bil_pix.r; - o_g<=o_v_bil_pix.g; - o_b<=o_v_bil_pix.b; - END IF; - WHEN "011" => -- BiCubic - IF MASK(MASK_BICUBIC)='1' THEN - o_r<=o_v_bic_pix.r; - o_g<=o_v_bic_pix.g; - o_b<=o_v_bic_pix.b; - END IF; - - WHEN OTHERS => -- Polyphase - IF MASK(MASK_POLY)='1' THEN - o_r<=o_v_poly_pix.r; - o_g<=o_v_poly_pix.g; - o_b<=o_v_poly_pix.b; - END IF; - END CASE; - - IF o_pev(9)='0' THEN - o_r<=o_border(23 DOWNTO 16); -- Copy border colour - o_g<=o_border(15 DOWNTO 8); - o_b<=o_border(7 DOWNTO 0); - END IF; - - ---------------------------------------------------- - END IF; - END IF; + -- BILINEAR / SHARP BILINEAR --------------- + -- C7 : Pre-calc Sharp Bilinear + o_h_sbil_t<=sbil_frac1(o_hfrac(6)); - END PROCESS VSCAL; - - ----------------------------------------------------------------------------- - -- Low Lag syntoniser interface - o_lltune<=(0 => i_vss, - 1 => i_pde, - 2 => i_inter, - 3 => i_flm, - 4 => o_vss, - 5 => i_pce, - 6 => i_clk, - 7 => o_clk, - OTHERS =>'0'); - - ---------------------------------------------------------------------------- + -- C8 : Select + o_h_bil_frac<=(OTHERS =>'0'); + IF o_hmode(0)='1' THEN -- Bilinear + IF MASK(MASK_BILINEAR)='1' THEN + o_h_bil_frac<=bil_frac(o_hfrac(7)); + END IF; + ELSE -- Sharp Bilinear + IF MASK(MASK_SHARP_BILINEAR)='1' THEN + o_h_bil_frac<=sbil_frac2(o_hfrac(7),o_h_sbil_t); + END IF; + END IF; + + -- C9 : Opposite frac + o_h_bil_t<=bil_calc(o_h_bil_frac,o_hpixq(8)); + + -- C10 : Bilinear / Sharp Bilinear + o_h_bil_pix.r<=bound(o_h_bil_t.r,8+FRAC); + o_h_bil_pix.g<=bound(o_h_bil_t.g,8+FRAC); + o_h_bil_pix.b<=bound(o_h_bil_t.b,8+FRAC); + + -- BICUBIC ------------------------------------------- + -- C8 : Bicubic coefficients A,B,C,D + -- C8 : Bicubic calc T1 = X.D + C + o_h_bic_abcd1<=bic_calc0(o_hfrac(7),o_hpixq(6)); + o_h_bic_tt1<=bic_calc1(o_hfrac(7), + bic_calc0(o_hfrac(7),o_hpixq(6))); + + -- C9 : Bicubic calc T2 = X.T1 + B + o_h_bic_abcd2<=o_h_bic_abcd1; + o_h_bic_tt2<=bic_calc2(o_hfrac(8),o_h_bic_tt1,o_h_bic_abcd1); + + -- C10 : Bicubic final Y = X.T2 + A + o_h_bic_pix<=bic_calc3(o_hfrac(9),o_h_bic_tt2,o_h_bic_abcd2); + + -- POLYPHASE ----------------------------------------- + -- C2 + IF o_hfrac(2)(o_hfrac(2)'left)='0' THEN + o_h_lum_pix<=o_hpix2; + ELSE + o_h_lum_pix<=o_hpix1; + END IF; + + -- C3-C8 in PolyFetch + + -- C9 : Apply Polyphase + o_h_poly_t<=poly_calc(o_h_poly_phase,o_hpixq(8)); + + -- C10 : Sum and bound + o_h_poly_pix<=poly_final(o_h_poly_t); + + -- C11 : Select interpoler ---------------------------- + o_wadl<=o_dcptv(14); + o_wr<=o_altx AND (o_copyv(14) & o_copyv(14) & o_copyv(14) & o_copyv(14)); + o_ldw<=(x"00",x"00",x"00"); + + CASE o_hmode(2 DOWNTO 0) IS + WHEN "000" => -- Nearest + IF MASK(MASK_NEAREST)='1' THEN + o_ldw<=o_h_poly_pix; + END IF; + WHEN "001" | "010" => -- Bilinear | Sharp Bilinear + IF MASK(MASK_BILINEAR)='1' OR + MASK(MASK_SHARP_BILINEAR)='1' THEN + o_ldw<=o_h_bil_pix; + END IF; + WHEN "011" => -- BiCubic + IF MASK(MASK_BICUBIC)='1' THEN + o_ldw<=o_h_bic_pix; + END IF; + WHEN OTHERS => -- PolyPhase + IF MASK(MASK_POLY)='1' THEN + o_ldw<=o_h_poly_pix; + END IF; + END CASE; + ------------------------------------------------------ + END IF; + END PROCESS HSCAL; + + ----------------------------------------------------------------------------- + -- Line buffers 4 x OHRES x (R+G+B) + OLBUF:PROCESS(o_clk) IS + BEGIN + IF rising_edge(o_clk) THEN + -- WRITES + IF o_wr(0)='1' THEN o_line0(o_wadl)<=o_ldw; END IF; + IF o_wr(1)='1' THEN o_line1(o_wadl)<=o_ldw; END IF; + IF o_wr(2)='1' THEN o_line2(o_wadl)<=o_ldw; END IF; + IF o_wr(3)='1' THEN o_line3(o_wadl)<=o_ldw; END IF; + + -- READS + o_ldr0<=o_line0(o_radl0); + o_ldr1<=o_line1(o_radl1); + o_ldr2<=o_line2(o_radl2); + o_ldr3<=o_line3(o_radl3); + END IF; + END PROCESS OLBUF; + + ----------------------------------------------------------------------------- + -- 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+1=o_vtotal THEN + o_vcpt_pre3<=0; + ELSIF o_vrr_sync2 THEN + o_vcpt_pre3<=o_vsstart; + o_sync<=false; + ELSE + o_vcpt_pre3<=(o_vcpt_pre3+1) MOD 4096; + END IF; + + o_vcpt_pre2<=o_vcpt_pre3; + o_vcpt_pre<=o_vcpt_pre2; + o_vcpt<=o_vcpt_pre; + END IF; + + o_end(0)<=to_std_logic(o_vcpt>=o_vdisp); + o_dev(0)<=to_std_logic(o_hcpt=o_hmin AND o_hcpt<=o_hmax AND + o_vcpt>=o_vmin AND o_vcpt<=o_vmax); + o_hsv(0)<=to_std_logic(o_hcpt>=o_hsstart AND o_hcpt=o_hsstart) OR + (o_vcpt>o_vsstart AND o_vcpt=o_vmin AND o_vcpt_pre2<=o_vmax); + o_hsv(1 TO 11)<=o_hsv(0 TO 10); + o_vsv(1 TO 11)<=o_vsv(0 TO 10); + o_dev(1 TO 11)<=o_dev(0 TO 10); + o_pev(1 TO 11)<=o_pev(0 TO 10); + o_end(1 TO 11)<=o_end(0 TO 10); + + IF o_run='0' THEN + o_hsv(2)<='0'; + o_vsv(2)<='0'; + o_dev(2)<='0'; + o_pev(2)<='0'; + o_end(2)<='0'; + END IF; + END IF; + + o_vcpt_sync2<=o_vcpt_sync; + o_vrr_min<=(o_vcpt_sync2=o_vdisp AND o_vcpt2 o_radl1<=r2_v; + WHEN "11" => o_radl2<=r2_v; + WHEN "00" => o_radl3<=r2_v; + WHEN OTHERS => o_radl0<=r2_v; + END CASE; + ELSE + CASE o_vacptl IS + WHEN "10" => o_radl2<=r2_v; + WHEN "11" => o_radl3<=r2_v; + WHEN "00" => o_radl0<=r2_v; + WHEN OTHERS => o_radl1<=r2_v; + END CASE; + END IF; + + -- CYCLE 2 ----------------------------------------- + -- Lines reordering + CASE o_vacptl IS + WHEN "10" => pixq_v:=(o_ldr0,o_ldr1,o_ldr2,o_ldr3); + WHEN "11" => pixq_v:=(o_ldr1,o_ldr2,o_ldr3,o_ldr0); + WHEN "00" => pixq_v:=(o_ldr2,o_ldr3,o_ldr0,o_ldr1); + WHEN OTHERS => pixq_v:=(o_ldr3,o_ldr0,o_ldr1,o_ldr2); + END CASE; + + IF fracnn_v = '0' THEN + o_vpix_outer<=(pixq_v(0), pixq_v(2), pixq_v(3)); + o_vpix_inner(0)<=pixq_v(1); + ELSE + o_vpix_outer<=(pixq_v(0), pixq_v(1), pixq_v(3)); + o_vpix_inner(0)<=pixq_v(2); + END IF; + + -- CYCLE 3-7 + o_vpix_inner(1 TO 5)<=o_vpix_inner(0 TO 4); + + -- CYCLE 8 + IF to_integer(o_vacpt)>o_ivsize THEN + IF fracnn_v = '0' THEN + o_vpixq_pre<=(o_vpix_outer(0), o_vpix_inner(5), o_vpix_inner(5), o_vpix_inner(5)); + ELSE + o_vpixq_pre<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_outer(1), o_vpix_outer(1)); + END IF; + ELSIF to_integer(o_vacpt)=o_ivsize THEN + IF fracnn_v = '0' THEN + o_vpixq_pre<=(o_vpix_outer(0), o_vpix_inner(5), o_vpix_outer(1), o_vpix_outer(1)); + ELSE + o_vpixq_pre<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_inner(5), o_vpix_inner(5)); + END IF; + ELSE + IF fracnn_v = '0' THEN + o_vpixq_pre<=(o_vpix_outer(0), o_vpix_inner(5), o_vpix_outer(1), o_vpix_outer(2)); + ELSE + o_vpixq_pre<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_inner(5), o_vpix_outer(2)); + END IF; + END IF; + + -- CYCLE 9 + o_vpixq<=o_vpixq_pre; + + -- BILINEAR / SHARP BILINEAR ----------------------- + -- C8 : Pre-calc Sharp Bilinear + o_v_sbil_t<=sbil_frac1(o_vfrac); + + -- C9 : Select + o_v_bil_frac<=(OTHERS =>'0'); + IF o_vmode(0)='1' THEN -- Bilinear + IF MASK(MASK_BILINEAR)='1' THEN + o_v_bil_frac<=bil_frac(o_vfrac); + END IF; + ELSE -- Sharp Bilinear + IF MASK(MASK_SHARP_BILINEAR)='1' THEN + o_v_bil_frac<=sbil_frac2(o_vfrac,o_v_sbil_t); + END IF; + END IF; + + -- C10 : + o_v_bil_t<=bil_calc(o_v_bil_frac,o_vpixq); + + -- C11 : Nearest / Bilinear / Sharp Bilinear + o_v_bil_pix.r<=bound(o_v_bil_t.r,8+FRAC); + o_v_bil_pix.g<=bound(o_v_bil_t.g,8+FRAC); + o_v_bil_pix.b<=bound(o_v_bil_t.b,8+FRAC); + + -- BICUBIC ----------------------------------------- + -- C9 : Bicubic coefficients A,B,C,D + -- C9 : Bicubic calc T1 = X.D + C + o_v_bic_abcd1<=bic_calc0(o_vfrac,o_vpixq); + o_v_bic_tt1<=bic_calc1(o_vfrac,bic_calc0(o_vfrac,o_vpixq)); + + -- C10 : Bicubic calc T2 = X.T1 + B + o_v_bic_abcd2<=o_v_bic_abcd1; + o_v_bic_tt2<=bic_calc2(o_vfrac,o_v_bic_tt1,o_v_bic_abcd1); + + -- C11 : Bicubic final Y = X.T2 + A + o_v_bic_pix<=bic_calc3(o_vfrac,o_v_bic_tt2,o_v_bic_abcd2); + + -- POLYPHASE --------------------------------------- + -- C3 : Setup luminance + o_v_lum_pix<=o_vpix_inner(0); + + -- C4-C9 in PolyFetch + + -- C10 : Apply polyphase + o_v_poly_t<=poly_calc(o_v_poly_phase,o_vpixq); + + -- C11 : Bound + o_v_poly_pix<=poly_final(o_v_poly_t); + + -- CYCLE 12 ----------------------------------------- + o_hs<=o_hsv(11); + o_vs<=o_vsv(11); + o_de<=o_dev(11); + o_vbl<=o_end(11); + o_r<=x"00"; + o_g<=x"00"; + o_b<=x"00"; + o_brd<= not o_pev(11); + + CASE o_vmode(2 DOWNTO 0) IS + WHEN "000" => -- Nearest + IF MASK(MASK_NEAREST)='1' THEN + o_r<=o_v_poly_pix.r; + o_g<=o_v_poly_pix.g; + o_b<=o_v_poly_pix.b; + END IF; + WHEN "001" | "010" => -- Bilinear | Sharp Bilinear + IF MASK(MASK_BILINEAR)='1' OR + MASK(MASK_SHARP_BILINEAR)='1' THEN + o_r<=o_v_bil_pix.r; + o_g<=o_v_bil_pix.g; + o_b<=o_v_bil_pix.b; + END IF; + WHEN "011" => -- BiCubic + IF MASK(MASK_BICUBIC)='1' THEN + o_r<=o_v_bic_pix.r; + o_g<=o_v_bic_pix.g; + o_b<=o_v_bic_pix.b; + END IF; + + WHEN OTHERS => -- Polyphase + IF MASK(MASK_POLY)='1' THEN + o_r<=o_v_poly_pix.r; + o_g<=o_v_poly_pix.g; + o_b<=o_v_poly_pix.b; + END IF; + END CASE; + + IF o_pev(11)='0' THEN + o_r<=o_border(23 DOWNTO 16); -- Copy border colour + o_g<=o_border(15 DOWNTO 8); + o_b<=o_border(7 DOWNTO 0); + END IF; + + ---------------------------------------------------- + END IF; + END IF; + END PROCESS VSCAL; + + ----------------------------------------------------------------------------- + -- Low Lag syntoniser interface + o_lltune<=(0 => i_vss, + 1 => i_pde, + 2 => i_inter, + 3 => i_flm, + 4 => o_vss, + 5 => i_pce, + 6 => i_clk, + 7 => o_clk, + OTHERS =>'0'); + + ---------------------------------------------------------------------------- END ARCHITECTURE rtl; diff --git a/sys/hdmi_config.sv b/sys/hdmi_config.sv deleted file mode 100644 index 4a0a13d..0000000 --- a/sys/hdmi_config.sv +++ /dev/null @@ -1,239 +0,0 @@ - -module hdmi_config -( - // Host Side - input iCLK, - input iRST_N, - - input dvi_mode, - input audio_96k, - input [1:0] limited, - input ypbpr, - - output reg done, - - // I2C Side - output I2C_SCL, - inout I2C_SDA -); - -// Internal Registers/Wires -reg mI2C_GO = 0; -wire mI2C_END; -wire mI2C_ACK; -reg [15:0] LUT_DATA; -reg [7:0] LUT_INDEX = 0; - -i2c #(50_000_000, 20_000) i2c_av -( - .CLK(iCLK), - - .I2C_SCL(I2C_SCL), // I2C CLOCK - .I2C_SDA(I2C_SDA), // I2C DATA - - .I2C_ADDR('h39), // 0x39 is the Slave Address of the ADV7513 chip! - .I2C_WLEN(1), - .I2C_WDATA1(init_data[LUT_INDEX][15:8]), // SUB_ADDR - .I2C_WDATA2(init_data[LUT_INDEX][7:0]), // DATA - .START(mI2C_GO), // START transfer - .READ(0), - .END(mI2C_END), // END transfer - .ACK(mI2C_ACK) // ACK -); - -////////////////////// Config Control //////////////////////////// -always@(posedge iCLK or negedge iRST_N) begin - reg [1:0] mSetup_ST = 0; - - if(!iRST_N) begin - LUT_INDEX <= 0; - mSetup_ST <= 0; - mI2C_GO <= 0; - done <= 0; - end else begin - if(init_data[LUT_INDEX] != 16'hFFFF) begin - case(mSetup_ST) - 0: begin - mI2C_GO <= 1; - mSetup_ST <= 1; - end - 1: if(~mI2C_END) mSetup_ST <= 2; - 2: begin - mI2C_GO <= 0; - if(mI2C_END) begin - mSetup_ST <= 0; - if(!mI2C_ACK) LUT_INDEX <= LUT_INDEX + 8'd1; - end - end - endcase - end - else done <= 1; - end -end - -//////////////////////////////////////////////////////////////////// -///////////////////// Config Data LUT ////////////////////////// - -wire [15:0] init_data[82] = -'{ - 16'h9803, // ADI required Write. - - {8'hD6, 8'b1100_0000}, // [7:6] HPD Control... - // 00 = HPD is from both HPD pin or CDC HPD - // 01 = HPD is from CDC HPD - // 10 = HPD is from HPD pin - // 11 = HPD is always high - - 16'h4110, // Power Down control - 16'h9A70, // ADI required Write. - 16'h9C30, // ADI required Write. - {8'h9D, 8'b0110_0001}, // [7:4] must be b0110!. - // [3:2] b00 = Input clock not divided. b01 = Clk divided by 2. b10 = Clk divided by 4. b11 = invalid! - // [1:0] must be b01! - 16'hA2A4, // ADI required Write. - 16'hA3A4, // ADI required Write. - 16'hE0D0, // ADI required Write. - - - 16'h35_40, - 16'h36_D9, - 16'h37_0A, - 16'h38_00, - 16'h39_2D, - 16'h3A_00, - - {8'h16, 8'b0011_1000}, // Output Format 444 [7]=0. - // [6] must be 0! - // Colour Depth for Input Video data [5:4] b11 = 8-bit. - // Input Style [3:2] b10 = Style 1 (ignored when using 444 input). - // DDR Input Edge falling [1]=0 (not using DDR atm). - // Output Colour Space RGB [0]=0. - - {8'h17, 8'b01100010}, // Aspect ratio 16:9 [1]=1, 4:3 [1]=0 - - {8'h18, ypbpr ? 8'h86 : limited[0] ? 8'h8D : limited[1] ? 8'h8E : 8'h00}, // CSC Scaling Factors and Coefficients for RGB Full->Limited. - {8'h19, ypbpr ? 8'hDF : limited[0] ? 8'hBC : 8'hFE}, // Taken from table in ADV7513 Programming Guide. - {8'h1A, ypbpr ? 8'h1A : 8'h00}, // CSC Channel A. - {8'h1B, ypbpr ? 8'h3F : 8'h00}, - {8'h1C, ypbpr ? 8'h1E : 8'h00}, - {8'h1D, ypbpr ? 8'hE2 : 8'h00}, - {8'h1E, ypbpr ? 8'h07 : 8'h01}, - {8'h1F, ypbpr ? 8'hE7 : 8'h00}, - - {8'h20, ypbpr ? 8'h04 : 8'h00}, // CSC Channel B. - {8'h21, ypbpr ? 8'h1C : 8'h00}, - {8'h22, ypbpr ? 8'h08 : limited[0] ? 8'h0D : 8'h0E}, - {8'h23, ypbpr ? 8'h11 : limited[0] ? 8'hBC : 8'hFE}, - {8'h24, ypbpr ? 8'h01 : 8'h00}, - {8'h25, ypbpr ? 8'h91 : 8'h00}, - {8'h26, ypbpr ? 8'h01 : 8'h01}, - {8'h27, 8'h00}, - - {8'h28, ypbpr ? 8'h1D : 8'h00}, // CSC Channel C. - {8'h29, ypbpr ? 8'hAE : 8'h00}, - {8'h2A, ypbpr ? 8'h1B : 8'h00}, - {8'h2B, ypbpr ? 8'h73 : 8'h00}, - {8'h2C, ypbpr ? 8'h06 : limited[0] ? 8'h0D : 8'h0E}, - {8'h2D, ypbpr ? 8'hDF : limited[0] ? 8'hBC : 8'hFE}, - {8'h2E, ypbpr ? 8'h07 : 8'h01}, - {8'h2F, ypbpr ? 8'hE7 : 8'h00}, - - {8'h3B, 8'b0000_0000}, // Pixel repetition [6:5] b00 AUTO. [4:3] b00 x1 mult of input clock. [2:1] b00 x1 pixel rep to send to HDMI Rx. - - 16'h4000, // General Control Packet Enable - - {8'h48, 8'b0000_1000}, // [6]=0 Normal bus order! - // [5] DDR Alignment. - // [4:3] b01 Data right justified (for YCbCr 422 input modes). - - 16'h49A8, // ADI required Write. - 16'h4C00, // ADI required Write. - - {8'h55, 8'b0001_0000}, // [7] must be 0!. Set RGB444 in AVinfo Frame [6:5], Set active format [4]. - // AVI InfoFrame Valid [4]. - // Bar Info [3:2] b00 Bars invalid. b01 Bars vertical. b10 Bars horizontal. b11 Bars both. - // Scan Info [1:0] b00 (No data). b01 TV. b10 PC. b11 None. - - {8'h57, 1'b0, // [7] IT Content. 0 - No. 1 - Yes (type set in register h59). - 3'b000, // [6:4] Color space (ignored for RGB) - (ypbpr | limited) ? 2'b01 : 2'b10, // [3:2] RGB Quantization range - 2'b00}, // [1:0] Non-Uniform Scaled: 00 - None. 01 - Horiz. 10 - Vert. 11 - Both. - - 16'h7301, - - {8'h94, 8'b1000_0000}, // [7]=1 HPD Interrupt ENabled. - - 16'h9902, // ADI required Write. - 16'h9B18, // ADI required Write. - - 16'h9F00, // ADI required Write. - - {8'hA1, 8'b0000_0000}, // [6]=1 Monitor Sense Power Down DISabled. - - 16'hA408, // ADI required Write. - 16'hA504, // ADI required Write. - 16'hA600, // ADI required Write. - 16'hA700, // ADI required Write. - 16'hA800, // ADI required Write. - 16'hA900, // ADI required Write. - 16'hAA00, // ADI required Write. - 16'hAB40, // ADI required Write. - - {8'hAF, 6'b0000_01,~dvi_mode,1'b0}, // [7]=0 HDCP Disabled. - // [6:5] must be b00! - // [4]=0 Current frame is unencrypted - // [3:2] must be b01! - // [1]=1 HDMI Mode. - // [0] must be b0! - - 16'hB900, // ADI required Write. - - {8'hBA, 8'b0110_0000}, // [7:5] Input Clock delay... - // b000 = -1.2ns. - // b001 = -0.8ns. - // b010 = -0.4ns. - // b011 = No delay. - // b100 = 0.4ns. - // b101 = 0.8ns. - // b110 = 1.2ns. - // b111 = 1.6ns. - - 16'hBB00, // ADI required Write. - - 16'hDE9C, // ADI required Write. - 16'hE460, // ADI required Write. - 16'hFA7D, // Nbr of times to search for good phase - - - // (Audio stuff on Programming Guide, Page 66)... - - {8'h0A, 8'b0000_0000}, // [6:4] Audio Select. b000 = I2S. - // [3:2] Audio Mode. (HBR stuff, leave at 00!). - - {8'h0B, 8'b0000_1110}, // - - {8'h0C, 8'b0000_0100}, // [7] 0 = Use sampling rate from I2S stream. 1 = Use samp rate from I2C Register. - // [6] 0 = Use Channel Status bits from stream. 1 = Use Channel Status bits from I2C register. - // [2] 1 = I2S0 Enable. - // [1:0] I2S Format: 00 = Standard. 01 = Right Justified. 10 = Left Justified. 11 = AES. - - {8'h0D, 8'b0001_0000}, // [4:0] I2S Bit (Word) Width for Right-Justified. - {8'h14, 8'b0000_0010}, // [3:0] Audio Word Length. b0010 = 16 bits. - {8'h15, audio_96k, 7'b010_0000}, // I2S Sampling Rate [7:4]. b0000 = (44.1KHz). b0010 = 48KHz. - // Input ID [3:1] b000 (0) = 24-bit RGB 444 or YCrCb 444 with Separate Syncs. - - // Audio Clock Config - 16'h0100, // - audio_96k ? 16'h0230 : 16'h0218, // Set N Value 12288/6144 - 16'h0300, // - - 16'h0701, // - 16'h0822, // Set CTS Value 74250 - 16'h090A, // - - 16'hFFFF // END -}; - -//////////////////////////////////////////////////////////////////// - -endmodule \ No newline at end of file diff --git a/sys/hps_io.sv b/sys/hps_io.sv index d6616c5..bf61f35 100644 --- a/sys/hps_io.sv +++ b/sys/hps_io.sv @@ -55,6 +55,13 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1, output reg [15:0] joystick_r_analog_4, output reg [15:0] joystick_r_analog_5, + input [15:0] joystick_0_rumble, // 15:8 - 'large' rumble motor magnitude, 7:0 'small' rumble motor magnitude + input [15:0] joystick_1_rumble, + input [15:0] joystick_2_rumble, + input [15:0] joystick_3_rumble, + input [15:0] joystick_4_rumble, + input [15:0] joystick_5_rumble, + // paddle 0..255 output reg [7:0] paddle_0, output reg [7:0] paddle_1, @@ -71,6 +78,29 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1, output reg [8:0] spinner_4, output reg [8:0] spinner_5, + // ps2 keyboard emulation + output ps2_kbd_clk_out, + output ps2_kbd_data_out, + input ps2_kbd_clk_in, + input ps2_kbd_data_in, + + input [2:0] ps2_kbd_led_status, + input [2:0] ps2_kbd_led_use, + + output ps2_mouse_clk_out, + output ps2_mouse_data_out, + input ps2_mouse_clk_in, + input ps2_mouse_data_in, + + // ps2 alternative interface. + + // [8] - extended, [9] - pressed, [10] - toggles with every press/release + output reg [10:0] ps2_key = 0, + + // [24] - toggles with every event + output reg [24:0] ps2_mouse = 0, + output reg [15:0] ps2_mouse_ext = 0, // 15:8 - reserved(additional buttons), 7:0 - wheel movements + output [1:0] buttons, output forced_scandoubler, output direct_video, @@ -79,10 +109,12 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1, //toggle to force notify of video mode change input new_vmode, - output reg [63:0] status, - input [63:0] status_in, - input status_set, - input [15:0] status_menumask, + inout [21:0] gamma_bus, + + output reg [127:0] status, + input [127:0] status_in, + input status_set, + input [15:0] status_menumask, input info_req, input [7:0] info, @@ -133,31 +165,6 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1, output reg [7:0] uart_mode, output reg [31:0] uart_speed, - // ps2 keyboard emulation - output ps2_kbd_clk_out, - output ps2_kbd_data_out, - input ps2_kbd_clk_in, - input ps2_kbd_data_in, - - input [2:0] ps2_kbd_led_status, - input [2:0] ps2_kbd_led_use, - - output ps2_mouse_clk_out, - output ps2_mouse_data_out, - input ps2_mouse_clk_in, - input ps2_mouse_data_in, - - // ps2 alternative interface. - - // [8] - extended, [9] - pressed, [10] - toggles with every press/release - output reg [10:0] ps2_key = 0, - - // [24] - toggles with every event - output reg [24:0] ps2_mouse = 0, - output reg [15:0] ps2_mouse_ext = 0, // 15:8 - reserved(additional buttons), 7:0 - wheel movements - - inout [21:0] gamma_bus, - // for core-specific extensions inout [35:0] EXT_BUS ); @@ -259,7 +266,7 @@ always@(posedge clk_sys) begin : uio_block reg [3:0] pdsp_idx; reg ps2skip = 0; reg [3:0] stflg = 0; - reg [63:0] status_req; + reg[127:0] status_req; reg old_status_set = 0; reg old_upload_req = 0; reg upload_req = 0; @@ -330,6 +337,12 @@ always@(posedge clk_sys) begin : uio_block 'h39: io_dout <= 1; 'h3C: if(upload_req) begin io_dout <= {ioctl_upload_index, 8'd1}; upload_req <= 0; end 'h3E: io_dout <= 1; // shadow mask + 'h003F: io_dout <= joystick_0_rumble; + 'h013F: io_dout <= joystick_1_rumble; + 'h023F: io_dout <= joystick_2_rumble; + 'h033F: io_dout <= joystick_3_rumble; + 'h043F: io_dout <= joystick_4_rumble; + 'h053F: io_dout <= joystick_5_rumble; endcase sd_buff_addr <= 0; @@ -455,13 +468,17 @@ always@(posedge clk_sys) begin : uio_block // send image info 'h1d: if(byte_cnt<5) img_size[{byte_cnt-1'b1, 4'b0000} +:16] <= io_din; - // status, 64bit version - 'h1e: if(!byte_cnt[MAX_W:3]) begin - case(byte_cnt[2:0]) - 1: status[15:00] <= io_din; - 2: status[31:16] <= io_din; - 3: status[47:32] <= io_din; - 4: status[63:48] <= io_din; + // status, 128bit version + 'h1e: if(!byte_cnt[MAX_W:4]) begin + case(byte_cnt[3:0]) + 1: status[15:00] <= io_din; + 2: status[31:16] <= io_din; + 3: status[47:32] <= io_din; + 4: status[63:48] <= io_din; + 5: status[79:64] <= io_din; + 6: status[95:80] <= io_din; + 7: status[111:96] <= io_din; + 8: status[127:112] <= io_din; endcase end @@ -491,12 +508,16 @@ always@(posedge clk_sys) begin : uio_block 'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din; //status set - 'h29: if(!byte_cnt[MAX_W:3]) begin - case(byte_cnt[2:0]) + 'h29: if(!byte_cnt[MAX_W:4]) begin + case(byte_cnt[3:0]) 1: io_dout <= status_req[15:00]; 2: io_dout <= status_req[31:16]; 3: io_dout <= status_req[47:32]; 4: io_dout <= status_req[63:48]; + 5: io_dout <= status_req[79:64]; + 6: io_dout <= status_req[95:80]; + 7: io_dout <= status_req[111:96]; + 8: io_dout <= status_req[127:112]; endcase end @@ -870,22 +891,28 @@ always @(posedge clk_sys) begin 11: dout <= vid_pix[31:16]; 12: dout <= vid_vtime_hdmi[15:0]; 13: dout <= vid_vtime_hdmi[31:16]; + 14: dout <= vid_ccnt[15:0]; + 15: dout <= vid_ccnt[31:16]; default dout <= 0; endcase end reg [31:0] vid_hcnt = 0; reg [31:0] vid_vcnt = 0; +reg [31:0] vid_ccnt = 0; reg [7:0] vid_nres = 0; reg [1:0] vid_int = 0; always @(posedge clk_vid) begin integer hcnt; integer vcnt; + integer ccnt; reg old_vs= 0, old_de = 0, old_vmode = 0; reg [3:0] resto = 0; reg calch = 0; + if(calch & de) ccnt <= ccnt + 1; + if(ce_pix) begin old_vs <= vs; old_de <= de; @@ -906,9 +933,11 @@ always @(posedge clk_vid) begin if(&resto) vid_nres <= vid_nres + 1'd1; vid_hcnt <= hcnt; vid_vcnt <= vcnt; + vid_ccnt <= ccnt; end vcnt <= 0; hcnt <= 0; + ccnt <= 0; calch <= 1; end end diff --git a/sys/ltc2308.sv b/sys/ltc2308.sv index 33134fd..4d3ccc1 100644 --- a/sys/ltc2308.sv +++ b/sys/ltc2308.sv @@ -102,19 +102,19 @@ end endmodule -module ltc2308_tape #(parameter HIST_LOW = 16, HIST_HIGH = 64, ADC_RATE = 48000, CLK_RATE = 50000000) +module ltc2308_tape #(parameter HIST_LOW = 16, HIST_HIGH = 64, ADC_RATE = 48000, CLK_RATE = 50000000, NUM_CH = 1) ( - input reset, - input clk, + input reset, + input clk, - inout [3:0] ADC_BUS, - output reg dout, - output active + inout [3:0] ADC_BUS, + output reg dout, + output active, + output adc_sync, + output [(NUM_CH*12)-1:0] adc_data ); -wire [11:0] adc_data; -wire adc_sync; -ltc2308 #(1, ADC_RATE, CLK_RATE) adc +ltc2308 #(NUM_CH, ADC_RATE, CLK_RATE) adc ( .reset(reset), .clk(clk), @@ -133,8 +133,8 @@ always @(posedge clk) begin data1 <= data2; data2 <= data3; data3 <= data4; - data4 <= adc_data; - + data4 <= adc_data[11:0]; + sum <= data1+data2+data3+data4; if(sum[13:2]CLK_RATE) begin onesec <= 0; diff --git a/sys/osd.v b/sys/osd.v index 782fc81..c354f6f 100644 --- a/sys/osd.v +++ b/sys/osd.v @@ -131,7 +131,7 @@ wire [21:0] osd_h_hdr = (info || rot) ? osd_h : (osd_h + OSD_HDR); // pipeline the comparisons a bit always @(posedge clk_video) if(ce_pix) begin - v_cnt_h <= v_cnt < osd_t; + v_cnt_h <= v_cnt <= osd_t; v_cnt_1 <= v_cnt < 320; v_cnt_2 <= v_cnt < 640; v_cnt_3 <= v_cnt < 960; diff --git a/sys/sys.qip b/sys/sys.qip index 094dab7..ced8e8b 100644 --- a/sys/sys.qip +++ b/sys/sys.qip @@ -16,6 +16,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) v set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) arcade_video.v ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) osd.v ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) vga_out.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) yc_out.sv ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2c.v ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) alsa.sv ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2s.v ] @@ -25,7 +26,6 @@ set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ltc2308.sv ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sigma_delta_dac.v ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mt32pi.sv ] -set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hdmi_config.sv ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mcp23009.sv ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) f2sdram_safe_terminator.sv ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ddr_svc.sv ] diff --git a/sys/sys_dual_sdram.tcl b/sys/sys_dual_sdram.tcl index 9da6c8e..cf90eab 100644 --- a/sys/sys_dual_sdram.tcl +++ b/sys/sys_dual_sdram.tcl @@ -45,6 +45,7 @@ set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM2_ set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM2_* set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM2_DQ[*] set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM2_DQ[*] +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDRAM2_DQ[*] set_instance_assignment -name ALLOW_SYNCH_CTRL_USAGE OFF -to *|SDRAM2_* set_global_assignment -name VERILOG_MACRO "MISTER_DUAL_SDRAM=1" diff --git a/sys/sys_top.sdc b/sys/sys_top.sdc index cf2d492..0d8763f 100644 --- a/sys/sys_top.sdc +++ b/sys/sys_top.sdc @@ -28,11 +28,12 @@ set_false_path -to [get_ports {VGA_*}] set_false_path -to [get_ports {AUDIO_SPDIF}] set_false_path -to [get_ports {AUDIO_L}] set_false_path -to [get_ports {AUDIO_R}] +set_false_path -from {get_ports {SW[*]}} set_false_path -to {cfg[*]} set_false_path -from {cfg[*]} set_false_path -from {VSET[*]} set_false_path -to {wcalc[*] hcalc[*]} -set_false_path -to {hdmi_width[*] hdmi_height[*]} +set_false_path -to {hdmi_width[*] hdmi_height[*]} set_multicycle_path -to {*_osd|osd_vcnt*} -setup 2 set_multicycle_path -to {*_osd|osd_vcnt*} -hold 1 @@ -55,6 +56,7 @@ set_false_path -from {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] set_false_path -to {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} set_false_path -from {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} set_false_path -from {aflt_* acx* acy* areset* arc*} +set_false_path -from {arx* ary*} set_false_path -from {vs_line*} set_false_path -from {ascal|o_ihsize*} @@ -62,7 +64,7 @@ set_false_path -from {ascal|o_ivsize*} set_false_path -from {ascal|o_format*} set_false_path -from {ascal|o_hdown} set_false_path -from {ascal|o_vdown} -set_false_path -from {ascal|o_hmin* ascal|o_hmax* ascal|o_vmin* ascal|o_vmax*} +set_false_path -from {ascal|o_hmin* ascal|o_hmax* ascal|o_vmin* ascal|o_vmax* ascal|o_vrrmax* ascal|o_vrr} set_false_path -from {ascal|o_hdisp* ascal|o_vdisp*} set_false_path -from {ascal|o_htotal* ascal|o_vtotal*} set_false_path -from {ascal|o_hsstart* ascal|o_vsstart* ascal|o_hsend* ascal|o_vsend*} diff --git a/sys/sys_top.v b/sys/sys_top.v index 635ae56..6de0011 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -168,7 +168,7 @@ assign LED = (led_overtake & led_state) | (~led_overtake & {1'b0,led_locked,1'b0 wire btn_r, btn_o, btn_u; `ifdef MISTER_DUAL_SDRAM - assign {btn_r,btn_o,btn_u} = {mcp_btn[1],mcp_btn[2],mcp_btn[0]}; + assign {btn_r,btn_o,btn_u} = SW[3] ? {mcp_btn[1],mcp_btn[2],mcp_btn[0]} : ~{SDRAM2_DQ[9],SDRAM2_DQ[13],SDRAM2_DQ[11]}; `else assign {btn_r,btn_o,btn_u} = ~{BTN_RESET,BTN_OSD,BTN_USER} | {mcp_btn[1],mcp_btn[2],mcp_btn[0]}; `endif @@ -212,13 +212,13 @@ end // gp_in[31] = 0 - quick flag that FPGA is initialized (HPS reads 1 when FPGA is not in user mode) // used to avoid lockups while JTAG loading -wire [31:0] gp_in = {1'b0, btn_user | btn[1], btn_osd | btn[0], SW[3], 8'd0, io_ver, io_ack, io_wide, io_dout}; +wire [31:0] gp_in = {1'b0, btn_user | btn[1], btn_osd | btn[0], SW[3], 8'd0, io_ver, io_ack, io_wide, io_dout | io_dout_sys}; wire [31:0] gp_out; wire [1:0] io_ver = 1; // 0 - obsolete. 1 - optimized HPS I/O. 2,3 - reserved for future. wire io_wait; wire io_wide; -wire [15:0] io_dout; +wire [15:0] io_dout; wire [15:0] io_din = gp_outr[15:0]; wire io_clk = gp_outr[17]; wire io_ss0 = gp_outr[18]; @@ -270,7 +270,6 @@ reg [15:0] cfg; reg cfg_set = 0; wire vga_fb = cfg[12] | vga_force_scaler; -wire [1:0] hdmi_limited = {cfg[11],cfg[8]}; `ifdef MISTER_DEBUG_NOHDMI wire direct_video = 1; @@ -278,12 +277,11 @@ wire direct_video = 1; wire direct_video = cfg[10]; `endif -wire dvi_mode = cfg[7]; wire audio_96k = cfg[6]; wire csync_en = cfg[3]; -wire ypbpr_en = cfg[5]; wire io_osd_vga = io_ss1 & ~io_ss2; `ifndef MISTER_DUAL_SDRAM + wire ypbpr_en = cfg[5]; wire sog = cfg[9]; wire vga_scaler = cfg[2] | vga_force_scaler; `endif @@ -304,12 +302,13 @@ reg [11:0] VSET = 0, HSET = 0; reg FREESCALE = 0; reg [2:0] scaler_flt; reg lowlat = 0; -reg cfg_dis = 0; +reg cfg_done = 0; reg vs_wait = 0; reg [11:0] vs_line = 0; reg scaler_out = 0; +reg vrr_mode = 0; reg [31:0] aflt_rate = 7056000; reg [39:0] acx = 4258969; @@ -324,16 +323,16 @@ reg [12:0] arc1x = 0; reg [12:0] arc1y = 0; reg [12:0] arc2x = 0; reg [12:0] arc2y = 0; +reg [15:0] io_dout_sys; always@(posedge clk_sys) begin reg [7:0] cmd; reg has_cmd; - reg old_strobe; reg [7:0] cnt = 0; reg vs_d0,vs_d1,vs_d2; reg [4:0] acx_att; + reg [7:0] fb_crc; - old_strobe <= io_strobe; coef_wr <= 0; `ifndef MISTER_DEBUG_NOHDMI @@ -346,9 +345,11 @@ always@(posedge clk_sys) begin areset <= 0; acx_att <= 0; acx <= acx >> acx_att; + io_dout_sys <= 0; end else - if(~old_strobe & io_strobe) begin + if(io_strobe) begin + io_dout_sys <= 0; if(!has_cmd) begin has_cmd <= 1; cmd <= io_din[7:0]; @@ -365,6 +366,10 @@ always@(posedge clk_sys) begin acy2 <= -24'd2023767; areset <= 1; end + if(io_din[7:0] == 'h20) io_dout_sys <= 'b11; +`ifndef MISTER_DEBUG_NOHDMI + if(io_din[7:0] == 'h40) io_dout_sys <= fb_crc; +`endif end else begin cnt <= cnt + 1'd1; @@ -377,14 +382,14 @@ always@(posedge clk_sys) begin cfg_set <= 0; if(cnt<8) begin case(cnt[2:0]) - 0: WIDTH <= io_din[11:0]; - 1: HFP <= io_din[11:0]; - 2: HS <= {io_din[15], io_din[11:0]}; - 3: HBP <= io_din[11:0]; - 4: HEIGHT <= io_din[11:0]; - 5: VFP <= io_din[11:0]; - 6: VS <= {io_din[15],io_din[11:0]}; - 7: VBP <= io_din[11:0]; + 0: {HDMI_PR,vrr_mode,WIDTH} <= {io_din[15:14], io_din[11:0]}; + 1: HFP <= io_din[11:0]; + 2: HS <= {io_din[15], io_din[11:0]}; + 3: HBP <= io_din[11:0]; + 4: HEIGHT <= io_din[11:0]; + 5: VFP <= io_din[11:0]; + 6: VS <= {io_din[15],io_din[11:0]}; + 7: VBP <= io_din[11:0]; endcase `ifndef MISTER_DEBUG_NOHDMI if(cnt == 1) begin @@ -401,7 +406,7 @@ always@(posedge clk_sys) begin cfg_custom_t <= ~cfg_custom_t; cnt[2:0] <= 3'b100; end - if(cnt == 8) {lowlat,cfg_dis} <= io_din[15:14]; + if(cnt == 8) {lowlat,cfg_done} <= {io_din[15],1'b1}; `endif end end @@ -458,10 +463,42 @@ always@(posedge clk_sys) begin end `ifndef MISTER_DEBUG_NOHDMI if(cmd == 'h3E) {shadowmask_wr,shadowmask_data} <= {1'b1, io_din}; + if(cmd == 'h40) begin + case(cnt[3:0]) + 0: io_dout_sys <= {arxy, arx}; + 1: io_dout_sys <= {arxy, ary}; + 2: io_dout_sys <= {LFB_EN, FB_EN, FB_FMT}; + 3: io_dout_sys <= FB_WIDTH; + 4: io_dout_sys <= FB_HEIGHT; + 5: io_dout_sys <= FB_BASE[15:0]; + 6: io_dout_sys <= FB_BASE[31:16]; + 7: io_dout_sys <= FB_STRIDE; + endcase + end +`endif +`ifndef MISTER_DISABLE_YC + if(cmd == 'h41) begin + case(cnt[3:0]) + 0: {pal_en,cvbs,yc_en} <= io_din[2:0]; + 1: PhaseInc[15:0] <= io_din; + 2: PhaseInc[31:16] <= io_din; + 3: PhaseInc[39:32] <= io_din[7:0]; + 4: ColorBurst_Range[15:0] <= io_din; + 5: ColorBurst_Range[16] <= io_din[0]; + endcase + end `endif end end +`ifndef MISTER_DEBUG_NOHDMI + fb_crc <= {LFB_EN, FB_EN, FB_FMT} + ^ FB_WIDTH[7:0] ^ FB_WIDTH[11:8] + ^ FB_HEIGHT[7:0] ^ FB_HEIGHT[11:8] + ^ arx[7:0] ^ arx[11:8] ^ arxy + ^ ary[7:0] ^ ary[11:8]; +`endif + vs_d0 <= HDMI_TX_VS; if(vs_d0 == HDMI_TX_VS) vs_d1 <= vs_d0; @@ -482,17 +519,6 @@ cyclonev_hps_interface_peripheral_uart uart .txd(uart_txd) ); -wire aspi_sck,aspi_mosi,aspi_ss,aspi_miso; -cyclonev_hps_interface_peripheral_spi_master spi -( - .sclk_out(aspi_sck), - .txd(aspi_mosi), // mosi - .rxd(aspi_miso), // miso - - .ss_0_n(aspi_ss), - .ss_in_n(1) -); - wire [63:0] f2h_irq = {video_sync,HDMI_TX_VS}; cyclonev_hps_interface_interrupts interrupts ( @@ -598,11 +624,13 @@ ddr_svc ddr_svc .ram_write(ram2_write), .ram_bcnt(ram2_bcnt), +`ifndef MISTER_DISABLE_ALSA .ch0_addr(alsa_address), .ch0_burst(1), .ch0_data(alsa_readdata), .ch0_req(alsa_req), .ch0_ready(alsa_ready), +`endif .ch1_addr(pal_addr), .ch1_burst(128), @@ -634,6 +662,11 @@ wire clk_hdmi = hdmi_clk_out; ascal #( .RAMBASE(32'h20000000), +`ifdef MISTER_SMALL_VBUF + .RAMSIZE(32'h00200000), +`else + .RAMSIZE(32'h00800000), +`endif `ifndef MISTER_FB .PALETTE2("false"), `else @@ -695,6 +728,8 @@ ascal .vdisp (HEIGHT), .vmin (vmin), .vmax (vmax), + .vrr (vrr_mode), + .vrrmax (HEIGHT + VBP + VS[11:0] + 12'd1), .mode ({~lowlat,LFB_EN ? LFB_FLT : |scaler_flt,2'b00}), .poly_clk (clk_sys), @@ -804,37 +839,40 @@ reg [11:0] vmax; reg [11:0] hdmi_height; reg [11:0] hdmi_width; +reg [11:0] arx; +reg [11:0] ary; +reg arxy; + always @(posedge clk_vid) begin reg [11:0] hmini,hmaxi,vmini,vmaxi; - reg [11:0] wcalc,videow,arx; - reg [11:0] hcalc,videoh,ary; + reg [11:0] wcalc,videow; + reg [11:0] hcalc,videoh; reg [2:0] state; - reg xy; hdmi_height <= (VSET && (VSET < HEIGHT)) ? VSET : HEIGHT; - hdmi_width <= (HSET && (HSET < WIDTH)) ? HSET : WIDTH; + hdmi_width <= (HSET && (HSET < WIDTH)) ? HSET << HDMI_PR : WIDTH << HDMI_PR; if(!ARY) begin if(ARX == 1) begin - arx <= arc1x[11:0]; - ary <= arc1y[11:0]; - xy <= arc1x[12] | arc1y[12]; + arx <= arc1x[11:0]; + ary <= arc1y[11:0]; + arxy <= arc1x[12] | arc1y[12]; end else if(ARX == 2) begin - arx <= arc2x[11:0]; - ary <= arc2y[11:0]; - xy <= arc2x[12] | arc2y[12]; + arx <= arc2x[11:0]; + ary <= arc2y[11:0]; + arxy <= arc2x[12] | arc2y[12]; end else begin - arx <= 0; - ary <= 0; - xy <= 0; + arx <= 0; + ary <= 0; + arxy <= 0; end end else begin - arx <= ARX[11:0]; - ary <= ARY[11:0]; - xy <= ARX[12] | ARY[12]; + arx <= ARX[11:0]; + ary <= ARY[11:0]; + arxy <= ARX[12] | ARY[12]; end ar_md_start <= 0; @@ -852,7 +890,7 @@ always @(posedge clk_vid) begin hcalc <= hdmi_height; state <= 6; end - else if(xy) begin + else if(arxy) begin wcalc <= arx; hcalc <= ary; state <= 6; @@ -881,7 +919,7 @@ always @(posedge clk_vid) begin end 6: begin - videow <= (wcalc > hdmi_width) ? hdmi_width : wcalc[11:0]; + videow <= (wcalc > hdmi_width) ? (hdmi_width >> HDMI_PR) : (wcalc[11:0] >> HDMI_PR); videoh <= (hcalc > hdmi_height) ? hdmi_height : hcalc[11:0]; end @@ -907,7 +945,7 @@ pll_hdmi_adj pll_hdmi_adj .reset_na(~reset_req), .llena(lowlat), - .lltune({16{hdmi_config_done | cfg_dis}} & lltune), + .lltune({16{cfg_done}} & lltune), .locked(led_locked), .i_waitrequest(adj_waitrequest), .i_write(adj_write), @@ -955,14 +993,15 @@ pll_hdmi pll_hdmi `endif //1920x1080@60 PCLK=148.5MHz CEA -reg [11:0] WIDTH = 1920; -reg [11:0] HFP = 88; -reg [12:0] HS = 48; -reg [11:0] HBP = 148; -reg [11:0] HEIGHT = 1080; -reg [11:0] VFP = 4; -reg [12:0] VS = 5; -reg [11:0] VBP = 36; +reg [11:0] WIDTH = 1920; +reg [11:0] HFP = 88; +reg [12:0] HS = 48; +reg [11:0] HBP = 148; +reg [11:0] HEIGHT = 1080; +reg [11:0] VFP = 4; +reg [12:0] VS = 5; +reg [11:0] VBP = 36; +reg HDMI_PR = 0; wire [63:0] reconfig_to_pll; wire [63:0] reconfig_from_pll; @@ -1035,22 +1074,6 @@ wire cfg_ready = 1; `endif -wire hdmi_config_done; -hdmi_config hdmi_config -( - .iCLK(FPGA_CLK1_50), - .iRST_N(cfg_ready & ~HDMI_TX_INT & ~cfg_dis), - .done(hdmi_config_done), - - .I2C_SCL(HDMI_I2C_SCL), - .I2C_SDA(HDMI_I2C_SDA), - - .dvi_mode(dvi_mode), - .audio_96k(audio_96k), - .limited(hdmi_limited), - .ypbpr(ypbpr_en & direct_video) -); - assign HDMI_I2C_SCL = hdmi_scl_en ? 1'b0 : 1'bZ; assign HDMI_I2C_SDA = hdmi_sda_en ? 1'b0 : 1'bZ; @@ -1132,34 +1155,41 @@ csync csync_hdmi(clk_hdmi, hdmi_hs_osd, hdmi_vs_osd, hdmi_cs_osd); reg [23:0] dv_data; reg dv_hs, dv_vs, dv_de; +wire [23:0] dv_data_osd; +wire dv_hs_osd, dv_vs_osd, dv_cs_osd; + always @(posedge clk_vid) begin reg [23:0] dv_d1, dv_d2; reg dv_de1, dv_de2, dv_hs1, dv_hs2, dv_vs1, dv_vs2; - reg [12:0] vsz, vcnt; + reg [12:0] vsz, vcnt, vcnt_l, vcnt_ll; reg old_hs, old_vs; reg vde; reg [3:0] hss; if(ce_pix) begin - hss <= (hss << 1) | vga_hs_osd; + hss <= (hss << 1) | dv_hs_osd; - old_hs <= vga_hs_osd; - if(~old_hs && vga_hs_osd) begin - old_vs <= vga_vs_osd; + old_hs <= dv_hs_osd; + if(~old_hs && dv_hs_osd) begin + old_vs <= dv_vs_osd; if(~&vcnt) vcnt <= vcnt + 1'd1; - if(~old_vs & vga_vs_osd & ~f1) vsz <= vcnt; - if(old_vs & ~vga_vs_osd) vcnt <= 0; + if(~old_vs & dv_vs_osd) begin + if (vcnt != vcnt_ll || vcnt < vcnt_l) vsz <= vcnt; + vcnt_l <= vcnt; + vcnt_ll <= vcnt_l; + end + if(old_vs & ~dv_vs_osd) vcnt <= 0; if(vcnt == 1) vde <= 1; if(vcnt == vsz - 3) vde <= 0; end - dv_de1 <= !{hss,vga_hs_osd} && vde; - dv_hs1 <= csync_en ? vga_cs_osd : vga_hs_osd; - dv_vs1 <= vga_vs_osd; + dv_de1 <= !{hss,dv_hs_osd} && vde; + dv_hs1 <= csync_en ? dv_cs_osd : dv_hs_osd; + dv_vs1 <= dv_vs_osd; end - dv_d1 <= vga_data_osd; + dv_d1 <= dv_data_osd; dv_d2 <= dv_d1; dv_de2 <= dv_de1; dv_hs2 <= dv_hs1; @@ -1171,6 +1201,12 @@ always @(posedge clk_vid) begin dv_vs <= dv_vs2; end +`ifndef MISTER_DISABLE_YC +assign {dv_data_osd, dv_hs_osd, dv_vs_osd, dv_cs_osd } = ~yc_en ? {vga_data_osd, vga_hs_osd, vga_vs_osd, vga_cs_osd } : {yc_o, yc_hs, yc_vs, yc_cs }; +`else +assign {dv_data_osd, dv_hs_osd, dv_vs_osd, dv_cs_osd } = {vga_data_osd, vga_hs_osd, vga_vs_osd, vga_cs_osd }; +`endif + wire hdmi_tx_clk; `ifndef MISTER_DEBUG_NOHDMI cyclonev_clkselect hdmi_clk_sw @@ -1289,6 +1325,7 @@ wire vga_cs_osd; csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); `ifndef MISTER_DUAL_SDRAM + wire VGA_DISABLE; wire [23:0] vgas_o; wire vgas_hs, vgas_vs, vgas_cs; vga_out vga_scaler_out @@ -1305,8 +1342,8 @@ csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); .csync_o(vgas_cs) ); - wire [23:0] vga_o; - wire vga_hs, vga_vs, vga_cs; + wire [23:0] vga_o, vga_o_t; + wire vga_hs, vga_vs, vga_cs, vga_hs_t, vga_vs_t, vga_cs_t; vga_out vga_out ( .clk(clk_vid), @@ -1314,20 +1351,51 @@ csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); .hsync(vga_hs_osd), .vsync(vga_vs_osd), .csync(vga_cs_osd), - .dout(vga_o), + .dout(vga_o_t), .din(vga_data_osd), - .hsync_o(vga_hs), - .vsync_o(vga_vs), - .csync_o(vga_cs) + .hsync_o(vga_hs_t), + .vsync_o(vga_vs_t), + .csync_o(vga_cs_t) ); +`ifndef MISTER_DISABLE_YC + reg pal_en; + reg yc_en; + reg cvbs; + reg [16:0] ColorBurst_Range; + reg [39:0] PhaseInc; + wire [23:0] yc_o; + wire yc_hs, yc_vs, yc_cs; + + yc_out yc_out + ( + .clk(clk_vid), + .PAL_EN(pal_en), + .CVBS(cvbs), + .PHASE_INC(PhaseInc), + .COLORBURST_RANGE(ColorBurst_Range), + .hsync(vga_hs_osd), + .vsync(vga_vs_osd), + .csync(vga_cs_osd), + .dout(yc_o), + .din(vga_data_osd), + .hsync_o(yc_hs), + .vsync_o(yc_vs), + .csync_o(yc_cs) + ); + + assign {vga_o, vga_hs, vga_vs, vga_cs } = ~yc_en ? {vga_o_t, vga_hs_t, vga_vs_t, vga_cs_t } : {yc_o, yc_hs, yc_vs, yc_cs }; +`else + assign {vga_o, vga_hs, vga_vs, vga_cs } = {vga_o_t, vga_hs_t, vga_vs_t, vga_cs_t } ; +`endif + wire cs1 = (vga_fb | vga_scaler) ? vgas_cs : vga_cs; - assign VGA_VS = (VGA_EN | SW[3]) ? 1'bZ :((((vga_fb | vga_scaler) ? ~vgas_vs : ~vga_vs) | csync_en) ^ VS[12]); - assign VGA_HS = (VGA_EN | SW[3]) ? 1'bZ : (((vga_fb | vga_scaler) ? (csync_en ? ~vgas_cs : ~vgas_hs) : (csync_en ? ~vga_cs : ~vga_hs)) ^ HS[12]); - assign VGA_R = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[23:18] : vga_o[23:18]; - assign VGA_G = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[15:10] : vga_o[15:10]; - assign VGA_B = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[7:2] : vga_o[7:2] ; + assign VGA_VS = (VGA_EN | SW[3]) ? 1'bZ : (((vga_fb | vga_scaler) ? (~vgas_vs ^ VS[12]) : VGA_DISABLE ? 1'd1 : ~vga_vs) | csync_en); + assign VGA_HS = (VGA_EN | SW[3]) ? 1'bZ : ((vga_fb | vga_scaler) ? ((csync_en ? ~vgas_cs : ~vgas_hs) ^ HS[12]) : VGA_DISABLE ? 1'd1 : (csync_en ? ~vga_cs : ~vga_hs)); + assign VGA_R = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[23:18] : VGA_DISABLE ? 6'd0 : vga_o[23:18]; + assign VGA_G = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[15:10] : VGA_DISABLE ? 6'd0 : vga_o[15:10]; + assign VGA_B = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[7:2] : VGA_DISABLE ? 6'd0 : vga_o[7:2] ; `endif reg video_sync = 0; @@ -1400,8 +1468,10 @@ audio_out audio_out .core_l(audio_l), .core_r(audio_r), +`ifndef MISTER_DISABLE_ALSA .alsa_l(alsa_l), .alsa_r(alsa_r), +`endif .i2s_bclk(HDMI_SCLK), .i2s_lrclk(HDMI_LRCLK), @@ -1414,6 +1484,18 @@ audio_out audio_out ); +`ifndef MISTER_DISABLE_ALSA +wire aspi_sck,aspi_mosi,aspi_ss,aspi_miso; +cyclonev_hps_interface_peripheral_spi_master spi +( + .sclk_out(aspi_sck), + .txd(aspi_mosi), // mosi + .rxd(aspi_miso), // miso + + .ss_0_n(aspi_ss), + .ss_in_n(1) +); + wire [28:0] alsa_address; wire [63:0] alsa_readdata; wire alsa_ready; @@ -1440,6 +1522,7 @@ alsa alsa .pcm_l(alsa_l), .pcm_r(alsa_r) ); +`endif //////////////// User I/O (USB 3.0 connector) ///////////////////////// @@ -1560,6 +1643,10 @@ emu emu .VGA_F1(f1), .VGA_SCALER(vga_force_scaler), +`ifndef MISTER_DUAL_SDRAM + .VGA_DISABLE(VGA_DISABLE), +`endif + .HDMI_WIDTH(direct_video ? 12'd0 : hdmi_width), .HDMI_HEIGHT(direct_video ? 12'd0 : hdmi_height), .HDMI_FREEZE(freeze), diff --git a/sys/yc_out.sv b/sys/yc_out.sv new file mode 100644 index 0000000..2e9a24e --- /dev/null +++ b/sys/yc_out.sv @@ -0,0 +1,230 @@ +//============================================================================ +// YC - Luma / Chroma Generation +// Copyright (C) 2022 Mike Simone +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ +/* +Colorspace +Y 0.299R' + 0.587G' + 0.114B' +U 0.492(B' - Y) = 504 (X 1024) +V 0.877(R' - Y) = 898 (X 1024) +*/ +////////////////////////////////////////////////////////// + +module yc_out +( + input clk, + input [39:0] PHASE_INC, + input PAL_EN, + input CVBS, + input [16:0] COLORBURST_RANGE, + + input hsync, + input vsync, + input csync, + + input [23:0] din, + output [23:0] dout, + + output reg hsync_o, + output reg vsync_o, + output reg csync_o +); + +wire [7:0] red = din[23:16]; +wire [7:0] green = din[15:8]; +wire [7:0] blue = din[7:0]; + +logic [9:0] red_1, blue_1, green_1, red_2, blue_2, green_2; + +logic signed [20:0] yr = 0, yb = 0, yg = 0; + +typedef struct { + logic signed [20:0] y; + logic signed [20:0] c; + logic signed [20:0] u; + logic signed [20:0] v; + logic hsync; + logic vsync; + logic csync; +} phase_t; + +localparam MAX_PHASES = 7'd8; + +phase_t phase[MAX_PHASES]; +reg unsigned [7:0] Y, C, c, U, V; + + +reg [10:0] cburst_phase; // colorburst counter +reg unsigned [7:0] vref = 'd128; // Voltage reference point (Used for Chroma) +logic [7:0] chroma_LUT_COS; // Chroma cos LUT reference +logic [7:0] chroma_LUT_SIN; // Chroma sin LUT reference +logic [7:0] chroma_LUT_BURST; // Chroma colorburst LUT reference +logic [7:0] chroma_LUT = 8'd0; + +/* +THe following LUT table was calculated by Sin(2*pi*t/2^8) where t: 0 - 255 +*/ + +/************************************* + 8 bit Sine look up Table +**************************************/ +wire signed [10:0] chroma_SIN_LUT[256] = '{ + 11'h000, 11'h006, 11'h00C, 11'h012, 11'h018, 11'h01F, 11'h025, 11'h02B, 11'h031, 11'h037, 11'h03D, 11'h044, 11'h04A, 11'h04F, + 11'h055, 11'h05B, 11'h061, 11'h067, 11'h06D, 11'h072, 11'h078, 11'h07D, 11'h083, 11'h088, 11'h08D, 11'h092, 11'h097, 11'h09C, + 11'h0A1, 11'h0A6, 11'h0AB, 11'h0AF, 11'h0B4, 11'h0B8, 11'h0BC, 11'h0C1, 11'h0C5, 11'h0C9, 11'h0CC, 11'h0D0, 11'h0D4, 11'h0D7, + 11'h0DA, 11'h0DD, 11'h0E0, 11'h0E3, 11'h0E6, 11'h0E9, 11'h0EB, 11'h0ED, 11'h0F0, 11'h0F2, 11'h0F4, 11'h0F5, 11'h0F7, 11'h0F8, + 11'h0FA, 11'h0FB, 11'h0FC, 11'h0FD, 11'h0FD, 11'h0FE, 11'h0FE, 11'h0FE, 11'h0FF, 11'h0FE, 11'h0FE, 11'h0FE, 11'h0FD, 11'h0FD, + 11'h0FC, 11'h0FB, 11'h0FA, 11'h0F8, 11'h0F7, 11'h0F5, 11'h0F4, 11'h0F2, 11'h0F0, 11'h0ED, 11'h0EB, 11'h0E9, 11'h0E6, 11'h0E3, + 11'h0E0, 11'h0DD, 11'h0DA, 11'h0D7, 11'h0D4, 11'h0D0, 11'h0CC, 11'h0C9, 11'h0C5, 11'h0C1, 11'h0BC, 11'h0B8, 11'h0B4, 11'h0AF, + 11'h0AB, 11'h0A6, 11'h0A1, 11'h09C, 11'h097, 11'h092, 11'h08D, 11'h088, 11'h083, 11'h07D, 11'h078, 11'h072, 11'h06D, 11'h067, + 11'h061, 11'h05B, 11'h055, 11'h04F, 11'h04A, 11'h044, 11'h03D, 11'h037, 11'h031, 11'h02B, 11'h025, 11'h01F, 11'h018, 11'h012, + 11'h00C, 11'h006, 11'h000, 11'h7F9, 11'h7F3, 11'h7ED, 11'h7E7, 11'h7E0, 11'h7DA, 11'h7D4, 11'h7CE, 11'h7C8, 11'h7C2, 11'h7BB, + 11'h7B5, 11'h7B0, 11'h7AA, 11'h7A4, 11'h79E, 11'h798, 11'h792, 11'h78D, 11'h787, 11'h782, 11'h77C, 11'h777, 11'h772, 11'h76D, + 11'h768, 11'h763, 11'h75E, 11'h759, 11'h754, 11'h750, 11'h74B, 11'h747, 11'h743, 11'h73E, 11'h73A, 11'h736, 11'h733, 11'h72F, + 11'h72B, 11'h728, 11'h725, 11'h722, 11'h71F, 11'h71C, 11'h719, 11'h716, 11'h714, 11'h712, 11'h70F, 11'h70D, 11'h70B, 11'h70A, + 11'h708, 11'h707, 11'h705, 11'h704, 11'h703, 11'h702, 11'h702, 11'h701, 11'h701, 11'h701, 11'h701, 11'h701, 11'h701, 11'h701, + 11'h702, 11'h702, 11'h703, 11'h704, 11'h705, 11'h707, 11'h708, 11'h70A, 11'h70B, 11'h70D, 11'h70F, 11'h712, 11'h714, 11'h716, + 11'h719, 11'h71C, 11'h71F, 11'h722, 11'h725, 11'h728, 11'h72B, 11'h72F, 11'h733, 11'h736, 11'h73A, 11'h73E, 11'h743, 11'h747, + 11'h74B, 11'h750, 11'h754, 11'h759, 11'h75E, 11'h763, 11'h768, 11'h76D, 11'h772, 11'h777, 11'h77C, 11'h782, 11'h787, 11'h78D, + 11'h792, 11'h798, 11'h79E, 11'h7A4, 11'h7AA, 11'h7B0, 11'h7B5, 11'h7BB, 11'h7C2, 11'h7C8, 11'h7CE, 11'h7D4, 11'h7DA, 11'h7E0, + 11'h7E7, 11'h7ED, 11'h7F3, 11'h7F9 +}; + +logic [39:0] phase_accum; +logic PAL_FLIP = 1'd0; +logic PAL_line_count = 1'd0; + +/************************************** + Generate Luma and Chroma Signals +***************************************/ + +always_ff @(posedge clk) begin + for (logic [3:0] x = 0; x < (MAX_PHASES - 1'd1); x = x + 1'd1) begin + phase[x + 1] <= phase[x]; + end + + // delay red / blue signals to align luma with U/V calculation (Fixes colorbleeding) + red_1 <= red; + blue_1 <= blue; + red_2 <= red_1; + blue_2 <= blue_1; + + // Calculate Luma signal + yr <= {red, 8'd0} + {red, 5'd0}+ {red, 4'd0} + {red, 1'd0}; + yg <= {green, 9'd0} + {green, 6'd0} + {green, 4'd0} + {green, 3'd0} + green; + yb <= {blue, 6'd0} + {blue, 5'd0} + {blue, 4'd0} + {blue, 2'd0} + blue; + phase[0].y <= yr + yg + yb; + + // Generate the LUT values using the phase accumulator reference. + phase_accum <= phase_accum + PHASE_INC; + chroma_LUT <= phase_accum[39:32]; + + // Adjust SINE carrier reference for PAL (Also adjust for PAL Switch) + if (PAL_EN) begin + if (PAL_FLIP) + chroma_LUT_BURST <= chroma_LUT + 8'd160; + else + chroma_LUT_BURST <= chroma_LUT + 8'd96; + end else // Adjust SINE carrier reference for NTSC + chroma_LUT_BURST <= chroma_LUT + 8'd128; + + // Prepare LUT values for sin / cos (+90 degress) + chroma_LUT_SIN <= chroma_LUT; + chroma_LUT_COS <= chroma_LUT + 8'd64; + + // Calculate for U, V - Bit Shift Multiple by u = by * 1024 x 0.492 = 504, v = ry * 1024 x 0.877 = 898 + phase[0].u <= $signed({2'b0 ,(blue_2)}) - $signed({2'b0 ,phase[0].y[17:10]}); + phase[0].v <= $signed({2'b0 , (red_2)}) - $signed({2'b0 ,phase[0].y[17:10]}); + phase[1].u <= 21'($signed({phase[0].u, 8'd0}) + $signed({phase[0].u, 7'd0}) + $signed({phase[0].u, 6'd0}) + $signed({phase[0].u, 5'd0}) + $signed({phase[0].u, 4'd0}) + $signed({phase[0].u, 3'd0})); + phase[1].v <= 21'($signed({phase[0].v, 9'd0}) + $signed({phase[0].v, 8'd0}) + $signed({phase[0].v, 7'd0}) + $signed({phase[0].v, 1'd0})); + + phase[0].c <= vref; + phase[1].c <= phase[0].c; + phase[2].c <= phase[1].c; + phase[3].c <= phase[2].c; + + if (hsync) begin // Reset colorburst counter, as well as the calculated cos / sin values. + cburst_phase <= 'd0; + phase[2].u <= 21'b0; + phase[2].v <= 21'b0; + phase[4].c <= phase[3].c; + + if (PAL_line_count) begin + PAL_FLIP <= ~PAL_FLIP; + PAL_line_count <= ~PAL_line_count; + end + end + else begin // Generate Colorburst for 9 cycles + if (cburst_phase >= COLORBURST_RANGE[16:10] && cburst_phase <= COLORBURST_RANGE[9:0]) begin // Start the color burst signal at 40 samples or 0.9 us + // COLORBURST SIGNAL GENERATION (9 CYCLES ONLY or between count 40 - 240) + phase[2].u <= $signed({chroma_SIN_LUT[chroma_LUT_BURST],5'd0}); + phase[2].v <= 21'b0; + + // Division to scale down the results to fit 8 bit. + if (PAL_EN) + phase[3].u <= $signed(phase[2].u[20:8]) + $signed(phase[2].u[20:10]) + $signed(phase[2].u[20:14]); + else + phase[3].u <= $signed(phase[2].u[20:8]) + $signed(phase[2].u[20:11]) + $signed(phase[2].u[20:12]) + $signed(phase[2].u[20:13]); + + phase[3].v <= phase[2].v; + end else begin // MODULATE U, V for chroma + /* + U,V are both multiplied by 1024 earlier to scale for the decimals in the YUV colorspace conversion. + U and V are both divided by 2^10 which introduce chroma subsampling of 4:1:1 (25% or from 8 bit to 6 bit) + */ + phase[2].u <= $signed((phase[1].u)>>>10) * $signed(chroma_SIN_LUT[chroma_LUT_SIN]); + phase[2].v <= $signed((phase[1].v)>>>10) * $signed(chroma_SIN_LUT[chroma_LUT_COS]); + + // Divide U*sin(wt) and V*cos(wt) to fit results to 8 bit + phase[3].u <= $signed(phase[2].u[20:9]) + $signed(phase[2].u[20:10]) + $signed(phase[2].u[20:14]); + phase[3].v <= $signed(phase[2].v[20:9]) + $signed(phase[2].v[20:10]) + $signed(phase[2].u[20:14]); + end + + // Stop the colorburst timer as its only needed for the initial pulse + if (cburst_phase <= COLORBURST_RANGE[9:0]) + cburst_phase <= cburst_phase + 9'd1; + + // Calculate for chroma (Note: "PAL SWITCH" routine flips V * COS(Wt) every other line) + if (PAL_EN) begin + if (PAL_FLIP) + phase[4].c <= vref + phase[3].u - phase[3].v; + else + phase[4].c <= vref + phase[3].u + phase[3].v; + PAL_line_count <= 1'd1; + end else + phase[4].c <= vref + phase[3].u + phase[3].v; + end + + // Adjust sync timing correctly + phase[1].hsync <= hsync; phase[1].vsync <= vsync; phase[1].csync <= csync; + phase[2].hsync <= phase[1].hsync; phase[2].vsync <= phase[1].vsync; phase[2].csync <= phase[1].csync; + phase[3].hsync <= phase[2].hsync; phase[3].vsync <= phase[2].vsync; phase[3].csync <= phase[2].csync; + phase[4].hsync <= phase[3].hsync; phase[4].vsync <= phase[3].vsync; phase[4].csync <= phase[3].csync; + hsync_o <= phase[4].hsync; vsync_o <= phase[4].vsync; csync_o <= phase[4].csync; + + phase[1].y <= phase[0].y; phase[2].y <= phase[1].y; phase[3].y <= phase[2].y; phase[4].y <= phase[3].y; phase[5].y <= phase[4].y; + + // Set Chroma / Luma output + C <= CVBS ? 8'd0 : phase[4].c[7:0]; + Y <= CVBS ? ({1'b0, phase[5].y[17:11]} + {1'b0, phase[4].c[7:1]}) : phase[5].y[17:10]; +end + +assign dout = {C, Y, 8'd0}; + +endmodule +