diff --git a/sys/alsa.sv b/sys/alsa.sv new file mode 100644 index 0000000..9ed448e --- /dev/null +++ b/sys/alsa.sv @@ -0,0 +1,128 @@ +//============================================================================ +// +// ALSA sound support for MiSTer +// (c)2019 Sorgelig +// +// 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. +// +//============================================================================ + +module alsa +( + input reset, + + input ram_clk, + output reg [28:0] ram_address, + output reg [7:0] ram_burstcount, + input ram_waitrequest, + input [63:0] ram_readdata, + input ram_readdatavalid, + output reg ram_read, + + input spi_ss, + input spi_sck, + input spi_mosi, + + output reg [15:0] pcm_l, + output reg [15:0] pcm_r +); + +reg spi_new = 0; +reg [127:0] spi_data; +always @(posedge spi_sck, posedge spi_ss) begin + reg [7:0] mosi; + reg [6:0] spicnt = 0; + + if(spi_ss) spicnt <= 0; + else begin + mosi <= {mosi[6:0],spi_mosi}; + + spicnt <= spicnt + 1'd1; + if(&spicnt[2:0]) begin + spi_data[{spicnt[6:3],3'b000} +:8] <= {mosi[6:0],spi_mosi}; + spi_new <= &spicnt; + end + end +end + +reg [31:0] buf_addr; +reg [31:0] buf_len; +reg [31:0] buf_wptr = 0; + +always @(posedge ram_clk) begin + reg n1,n2,n3; + reg [127:0] data1,data2; + + n1 <= spi_new; + n2 <= n1; + n3 <= n2; + + data1 <= spi_data; + data2 <= data1; + + if(~n3 & n2) {buf_wptr,buf_len,buf_addr} <= data2[95:0]; +end + +reg [31:0] buf_rptr = 0; +always @(posedge ram_clk) begin + reg got_first = 0; + reg ready = 0; + reg ud; + reg [31:0] readdata; + + if(~ram_waitrequest) ram_read <= 0; + if(ram_readdatavalid && ram_burstcount) begin + ram_burstcount <= 0; + ready <= 1; + readdata <= ud ? ram_readdata[63:32] : ram_readdata[31:0]; + if(buf_rptr[31:2] >= buf_len[31:2]) buf_rptr <= 0; + end + + if(reset) {ready, got_first} <= 0; + else + if(buf_rptr[31:2] != buf_wptr[31:2]) begin + if(~got_first) begin + buf_rptr <= buf_wptr; + got_first <= 1; + end + else + if(!ram_burstcount && ~ram_waitrequest && ~ready) begin + ram_address <= buf_addr[31:3] + buf_rptr[31:3]; + ud <= buf_rptr[2]; + ram_burstcount <= 1; + ram_read <= 1; + buf_rptr <= buf_rptr + 4; + end + end + + if(ready & ce_48k) begin + {pcm_r,pcm_l} <= readdata; + ready <= 0; + end +end + +reg ce_48k; +always @(posedge ram_clk) begin + reg [15:0] acc = 0; + + ce_48k <= 0; + acc <= acc + 16'd48; + if(acc >= 50000) begin + acc <= acc - 16'd50000; + ce_48k <= 1; + end +end + +endmodule diff --git a/sys/ascal.vhd b/sys/ascal.vhd new file mode 100644 index 0000000..64b6b99 --- /dev/null +++ b/sys/ascal.vhd @@ -0,0 +1,2398 @@ +-------------------------------------------------------------------------------- +-- AVALON SCALER +-------------------------------------------------------------------------------- +-- TEMLIB 10/2018 +-------------------------------------------------------------------------------- +-- This code can be freely distributed and used for any purpose, but, if you +-- find any bug, or want to suggest an enhancement, you ought to send a mail +-- to info@temlib.org. +-------------------------------------------------------------------------------- + +-- Features : +-- - Arbitrary output video format +-- - Autodetect input image size or fixed window +-- - Progressive and interlaced input +-- - Interpolation +-- Upscaling : Nearest, Bilinear, Sharp Bilinear, Bicubic, Polyphase +-- Downscaling : Nearest, Bilinear +-- - Avalon bus interface with 128 or 64 bits DATA +-- - Optional triple buffering +-- - Support for external low lag syntonization + +-------------------------------------------- +-- Downscaling +-- - Horizontal and vertical up-/down-scaling are independant. +-- - Downscaling, H and/or V, supports only nearest-neighbour and bilinear +-- filtering. +-- - For interlaced video, when the vertical size is lower than a deinterlaced +-- frame size (2x half-frame), the scaler processes only half-frames +-- and upscales (when the output size is between 1x an 2x) or downscales (size +-- below 1x) them. + +-------------------------------------------- +-- 4 asynchronous clock domains : +-- i_xxx : Input video +-- o_xxx : Output video +-- avl_xxx : Avalon memory bus +-- poly_xxx : Polyphase filters memory + +-------------------------------------------- +-- Mode 24bits + +-------------------------------------------- +-- Image header. When HEADER = TRUE +-- Header Address = RAMBASE +-- Image Address = RAMBASE + HEADER_SIZE + +-- Header (Bytes. Big Endian.) +-- 0 : Type = 1 +-- 1 : Pixel format +-- 1 : 24 bits/pixel, packed RGB. Big Endian + +-- 3:2 : Header size : Offset to start of picture (= N_BURST). 12 bits +-- 5:4 : Attributes. TBD +-- b0 ; Interlaced +-- b1 : Field number +-- b2 : Horizontal downscaled +-- b3 : Vertical downscaled +-- b4 : Triple buffered +-- b7-5 : Frame counter +-- 7:6 : Image width. Pixels. 12 bits +-- 9:8 : Image height. Pixels. 12 bits +-- 11:10 : Line length. Bytes. +-- 13:12 : Output width. Pixels. 12 bits +-- 15:14 : Output height. Pixels. 12 bits +-------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE ieee.numeric_std.ALL; + +-- MODE[2:0] +-- 000 : Nearest +-- 001 : Bilinear +-- 010 : Sharp Bilinear +-- 011 : Bicubic +-- 100 : Polyphase +-- 101 : TBD +-- 110 : TBD +-- 111 : TEST + +-- MODE[3] +-- 0 : Direct. Single framebuffer. +-- 1 : Triple buffering + +-- MODE[4] : TBD + +-- MASK : Enable / Disable selected interpoler +-- 0:Nearest 1:Bilinear 2:SharpBilinear 3:Bicubic 4:Polyphase +-- RAMBASE : RAM base address for framebuffer +-- RAMSIZE : RAM allocated for one framebuffer (needs x3 if triple-buffering) +-- Must be a power of two +-- INTER : True=Autodetect interlaced video False=Force progressive scan +-- HEADER : True=Add image properties header +-- SYNCHRO : True=Support synchronized mode False=Force disabled +-- DOWNSCALE : True=Support downscaling False=Downscaling disabled +-- BYTESWAP : Little/Big endian byte swap +-- FRAC : Fractional bits, subpixel resolution +-- FORMAT : TBD +-- OHRES : Max. output horizontal resolution. Must be a power of two. +-- (Used for sizing line buffers) +-- IHRES : Max. input horizontal resolution. Must be a power of two. +-- (Used for sizing line buffers) +-- N_DW : Avalon data bus width. 64 or 128 bits +-- N_AW : Avalon address bus width +-- 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; + SYNCHRO : boolean := true; + DOWNSCALE : boolean := true; + BYTESWAP : boolean := true; + FRAC : natural RANGE 4 TO 6 :=4; + FORMAT : natural RANGE 1 TO 8 :=1; + OHRES : natural RANGE 1 TO 4096 :=2048; + 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_ce : IN std_logic; -- Clock Enable + o_clk : IN std_logic; -- Output clock + + ------------------------------------ + -- Low lag PLL tuning + o_lltune : OUT unsigned(15 DOWNTO 0); + + ------------------------------------ + -- Input video parameters + iauto : IN std_logic; -- 1=Autodetect image size 0=Choose window + himin : IN natural RANGE 0 TO 4095; -- MIN < MAX, MIN >=0, MAX < DISP + himax : IN natural RANGE 0 TO 4095; + vimin : IN natural RANGE 0 TO 4095; + vimax : IN natural RANGE 0 TO 4095; + + -- Output video parameters + run : IN std_logic; -- 1=Enable output image. 0=No image + freeze : IN std_logic; -- 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 + + ------------------------------------ + -- Polyphase filter coefficients + -- Order : + -- [Horizontal] [Vertical] + -- [0]...[2**FRAC-1] + -- [-1][0][1][2] + poly_clk : IN std_logic; + poly_dw : IN unsigned(8 DOWNTO 0); + poly_a : IN unsigned(FRAC+2 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; + +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 + CONSTANT NP : natural :=24; + + ---------------------------------------------------------- + TYPE arr_dw IS ARRAY (natural RANGE <>) OF unsigned(N_DW-1 DOWNTO 0); + + TYPE type_pix IS RECORD + r,g,b : unsigned(7 DOWNTO 0); -- 0.8 + END RECORD; + TYPE arr_pix IS ARRAY (natural RANGE <>) OF type_pix; + ATTRIBUTE ramstyle : string; + + SUBTYPE uint12 IS natural RANGE 0 TO 4095; + SUBTYPE uint13 IS natural RANGE 0 TO 8191; + + ---------------------------------------------------------- + -- Input image + SIGNAL i_phs,i_pvs,i_pfl,i_pde,i_pce : std_logic; + SIGNAL i_ppix : type_pix; + SIGNAL i_freeze : std_logic; + SIGNAL i_count : unsigned(2 DOWNTO 0); + SIGNAL i_hsize,i_hmin,i_hmax,i_hcpt : uint12; + SIGNAL i_hrsize,i_vrsize : uint12; + SIGNAL i_himax,i_vimax : uint12; + SIGNAL i_vsize,i_vmaxmin,i_vmin,i_vmax,i_vimaxc,i_vcpt : uint12; + SIGNAL i_iauto : std_logic; + SIGNAL i_mode : unsigned(4 DOWNTO 0); + SIGNAL i_ven,i_sof : std_logic; + SIGNAL i_wr : std_logic; + SIGNAL i_divstart,i_divrun : std_logic; + SIGNAL i_de_pre,i_hs_pre,i_vs_pre,i_fl_pre : std_logic; + SIGNAL i_hs_delay : natural RANGE 0 TO 15; + SIGNAL i_intercnt : natural RANGE 0 TO 3; + SIGNAL i_inter,i_half,i_flm : std_logic; + SIGNAL i_write,i_write_pre,i_walt,i_wline : std_logic; + SIGNAL i_push,i_pushend,i_pushend2,i_eol,i_eol2,i_eol3,i_eol4 : std_logic; + SIGNAL i_pushhead,i_pushhead2,i_hbfix : std_logic; + SIGNAL i_hburst,i_hbcpt : natural RANGE 0 TO 31; + SIGNAL i_shift : unsigned(0 TO 119) := (OTHERS =>'0'); + SIGNAL i_head : unsigned(127 DOWNTO 0); + SIGNAL i_acpt : natural RANGE 0 TO 15; + SIGNAL i_dpram : arr_dw(0 TO BLEN*2-1); + ATTRIBUTE ramstyle OF i_dpram : SIGNAL IS "no_rw_check"; + SIGNAL i_endframe0,i_endframe1,i_syncline : std_logic; + SIGNAL i_wad : natural RANGE 0 TO BLEN*2-1; + SIGNAL i_dw : unsigned(N_DW-1 DOWNTO 0); + SIGNAL i_adrs,i_adrsi : unsigned(31 DOWNTO 0); -- Avalon address + SIGNAL i_reset_na : std_logic; + SIGNAL i_hnp,i_vnp : std_logic; + SIGNAL i_line : arr_pix(0 TO IHRES-1); -- Downscale line buffer + ATTRIBUTE ramstyle OF i_line : SIGNAL IS "no_rw_check"; + SIGNAL i_ohsize,i_ovsize : 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 : std_logic; + SIGNAL i_lpush,i_bil : std_logic; + SIGNAL i_ldw,i_ldrm : type_pix; + SIGNAL i_hpixp,i_hpix0,i_hpix1,i_hpix2,i_hpix3,i_hpix4 : type_pix; + SIGNAL i_hpix,i_pix : type_pix; + SIGNAL i_hnp1,i_hnp2,i_hnp3,i_hnp4 : std_logic; + SIGNAL i_ven1,i_ven2,i_ven3,i_ven4,i_ven5,i_ven6,i_ven7 : std_logic; + + ---------------------------------------------------------- + -- 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_reading : std_logic; + SIGNAL avl_read_sr,avl_write_sr,avl_read_clr,avl_write_clr : std_logic; + SIGNAL avl_rad,avl_rad_c,avl_wad : natural RANGE 0 TO 2*BLEN-1; + SIGNAL avl_walt,avl_wline,avl_rline : std_logic; + SIGNAL avl_dw,avl_dr : unsigned(N_DW-1 DOWNTO 0); + SIGNAL avl_wr : std_logic; + SIGNAL avl_readack : std_logic; + SIGNAL avl_radrs,avl_wadrs : unsigned(31 DOWNTO 0); + SIGNAL avl_rbib : std_logic; + SIGNAL avl_i_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; + + FUNCTION buf_next(a,b : natural RANGE 0 TO 2) RETURN natural IS + BEGIN + IF (a=0 AND b=1) OR (a=1 AND b=0) THEN RETURN 2; END IF; + IF (a=1 AND b=2) OR (a=2 AND b=1) THEN RETURN 0; END IF; + RETURN 1; + END FUNCTION; + FUNCTION buf_offset(b : natural RANGE 0 TO 2) RETURN unsigned IS + BEGIN + IF b=1 THEN RETURN RAMSIZE; END IF; + IF b=2 THEN RETURN RAMSIZE(30 DOWNTO 0) & '0'; END IF; + RETURN x"00000000"; + END FUNCTION; + + ---------------------------------------------------------- + -- Output + SIGNAL o_run : std_logic; + SIGNAL o_mode,o_hmode,o_vmode : unsigned(4 DOWNTO 0); + SIGNAL o_htotal,o_hsstart,o_hsend : uint12; + SIGNAL o_hmin,o_hmax,o_hdisp : 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 type_o_state IS (sDISP,sHSYNC,sREAD,sWAITREAD); + SIGNAL o_state : type_o_state; + SIGNAL o_copy,o_readack,o_readack_sync,o_readack_sync2 : std_logic; + SIGNAL o_copyv : unsigned(0 TO 7); + SIGNAL o_adrs : unsigned(31 DOWNTO 0); -- Avalon address + SIGNAL o_adrs_pre : natural RANGE 0 TO 32*4096-1; + SIGNAL o_adrsa,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 : 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_radl : 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_ivsize : uint12; + + SIGNAL o_vfrac,o_hfrac,o_hfrac1,o_hfrac2,o_hfrac3 : unsigned(11 DOWNTO 0); + SIGNAL o_hacc,o_hacc_ini,o_hacc_next,o_vacc,o_vacc_next,o_vacc_ini : natural RANGE 0 TO 4*OHRES-1; + SIGNAL o_hsv,o_vsv,o_dev,o_pev : unsigned(0 TO 5); + SIGNAL o_hsp,o_vss,o_vss1,o_vstog : std_logic; + SIGNAL o_read,o_read_pre : std_logic; + SIGNAL o_readlev,o_copylev : natural RANGE 0 TO 2; + SIGNAL o_hburst,o_hbcpt : natural RANGE 0 TO 31; + SIGNAL o_fload : natural RANGE 0 TO 3; + SIGNAL o_acpt,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,o_last3 : std_logic; + SIGNAL o_lastt1,o_lastt2,o_lastt3 : std_logic; + SIGNAL o_alt : unsigned(3 DOWNTO 0); + SIGNAL o_hdown,o_vdown : std_logic; + SIGNAL o_primv,o_lastv,o_bibv : unsigned(0 TO 2); + SIGNAL o_bibu,o_bib : std_logic :='0'; + SIGNAL o_dcpt,o_dcpt1,o_dcpt2,o_dcpt3,o_dcpt4,o_dcpt5,o_dcpt6,o_dcpt7 : uint12; + SIGNAL o_hpix0,o_hpix1,o_hpix2,o_hpix3 : type_pix; + SIGNAL o_hpixq,o_vpixq,o_vpixq1 : arr_pix(0 TO 3); + + SIGNAL o_isyncline,o_isyncline2 : std_logic; + SIGNAL o_vpe : std_logic; + SIGNAL o_div,o_div2 : unsigned(18 DOWNTO 0); --uint12; + SIGNAL o_dir,o_dir2 : unsigned(11 DOWNTO 0); + SIGNAL o_vdivi : unsigned(12 DOWNTO 0); + SIGNAL o_vdivr : unsigned(24 DOWNTO 0); + SIGNAL o_divstart : std_logic; + SIGNAL o_divrun : std_logic; + SIGNAL o_hacpt,o_vacpt : unsigned(11 DOWNTO 0); + + SIGNAL o_llicpt,o_llisize,o_llipos : natural RANGE 0 TO 2**24-1; + SIGNAL o_llocpt,o_llosize : natural RANGE 0 TO 2**24-1; + SIGNAL o_lldiff : integer RANGE -2**23 TO 2**23-1 :=0; + SIGNAL o_llup,o_llos,o_llop,o_llfl : std_logic; + SIGNAL o_lltune_i : unsigned(15 DOWNTO 0); + SIGNAL o_llssh : natural RANGE 0 TO 2**24-1; + SIGNAL o_llcpt : natural RANGE 0 TO 31; + + ----------------------------------------------------------------------------- + -- ACPT 012345678901234--- 128bits DATA + -- 0 ...............RGB + -- 1 ............RGBrgb + -- 2 .........RGBrgbRGB + -- 3 ......RGBrgbRGBrgb + -- 4 ...RGBrgbRGBrgbRGB + -- 5 RGBrgbRGBrgbRGBrgb => PUSH RGBrgbRGBrgbRGBr + -- 6 .............gbRGB + -- 7 ..........gbRGBrgb + -- 8 .......gbRGBrgbRGB + -- 9 ....gbRGBrgbRGBrgb + -- 10 .gbRGBrgbRGBrgbRGB => PUSH gbRGBrgbRGBrgbRG + -- 11 ..............Brgb + -- 12 ...........BrgbRGB + -- 13 ........BrgbRGBrgb + -- 14 .....BrgbRGBrgbRGB + -- 15 ..BrgbRGBrgbRGBrgb => PUSH BrgbRGBrgbRGBrgb + + -- ACPT 012345678901234--- 64bits DATA + -- 0 ...............RGB + -- 1 ............RGBrgb + -- 2 .........RGBrgbRGB => PUSH RGBrgbRG + -- 3 ..............Brgb + -- 4 ...........BrgbRGB + -- 5 ........BrgbRGBrgb => PUSH BrgbRGBr + -- 6 .............gbRGB + --- 7 ..........gbRGBrgb => PUSH gbRGBrgb + + FUNCTION shift24_ipack(i_dw : unsigned(N_DW-1 DOWNTO 0); + acpt : natural RANGE 0 TO 15; + shift : unsigned(0 TO 119); + pix : type_pix) RETURN unsigned IS + VARIABLE dw : unsigned(N_DW-1 DOWNTO 0); + BEGIN + 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; + ELSE dw:=i_dw; + 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; + ELSE dw:=i_dw; + END IF; + END IF; + RETURN dw; + END FUNCTION; + + FUNCTION shift24_inext (acpt : natural RANGE 0 TO 15) RETURN boolean IS + BEGIN + IF N_DW=128 THEN + RETURN (acpt=5 OR acpt=10 OR acpt=15); + ELSE -- N_DW=64 + RETURN ((acpt MOD 8)=2 OR (acpt MOD 8)=5 OR (acpt MOD 8)=7); + END IF; + END FUNCTION; + + ---------------------- + -- ACPT 0123456789012345 128bits DATA + -- 0 >RGBrgbRGBrgbRGBr + -- 1 rgbRGBrgbRGBr + -- 2 RGBrgbRGBr + -- 3 rgbRGBr + -- 4 RGBr + -- 5 >r gbRGBrgbRGBrgbRG + -- 6 RGBrgbRGBrgbRG + -- 7 rgbRGBrgbRG + -- 8 RGBrgbRG + -- 9 rgbRG + -- 10 >RG BrgbRGBrgbRGBrgb + -- 11 rgbRGBrgbRGBrgb + -- 12 RGBrgbRGBrgb + -- 13 rgbRGBrgb + -- 14 RGBrgb + -- 15 rgb + + -- ACPT 01234567 64bits DATA + -- 0 >RGBrgbRG + -- 1 rgbRG + -- 2 >RG BrgbRGBr + -- 3 rgbRGBr + -- 4 RGBr + -- 5 >r gbRGBrgb + -- 6 RGBrgb + -- 7 rgb + + FUNCTION shift24_opack(acpt : natural RANGE 0 TO 15; + shift : unsigned(0 TO N_DW+15); + dr : unsigned(N_DW-1 DOWNTO 0)) RETURN unsigned IS + VARIABLE shift_v : unsigned(0 TO N_DW+15); + BEGIN + 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; + RETURN shift_v; + END FUNCTION; + + FUNCTION shift24_onext (acpt : natural RANGE 0 TO 15) RETURN boolean IS + BEGIN + IF N_DW=128 THEN + RETURN (acpt=0 OR acpt=5 OR acpt=10); + ELSE -- N_DW=64 + RETURN ((acpt MOD 8)=0 OR (acpt MOD 8)=2 OR (acpt MOD 8)=5); + END IF; + END FUNCTION; + + FUNCTION swap(d : unsigned(N_DW-1 DOWNTO 0)) RETURN unsigned IS + VARIABLE e : unsigned(N_DW-1 DOWNTO 0); + BEGIN + IF BYTESWAP THEN + FOR i IN 0 TO N_DW/8-1 LOOP + e(i*8+7 DOWNTO i*8):=d(N_DW-i*8-1 DOWNTO N_DW-i*8-8); + END LOOP; + RETURN e; + ELSE + RETURN d; + END IF; + END FUNCTION swap; + + ----------------------------------------------------------------------------- + FUNCTION altx (a : unsigned(1 DOWNTO 0)) RETURN unsigned IS + 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_frac2,o_v_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; + 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; + SIGNAL o_h_bil_t,o_v_bil_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 + + TYPE arr_uv36 IS ARRAY (natural RANGE <>) OF unsigned(35 DOWNTO 0); + TYPE arr_int9 IS ARRAY (natural RANGE <>) OF integer RANGE -256 TO 255; + --CONSTANT POLY16 : arr_int9 := ( + -- -24,-20,-16,-11,-6,-1,2,5,6,6,5,4,2,1,0,0, + -- 176,174,169,160,147,129,109,84,58,22,3,-12,-20,-25,-26,-25, + -- -24,-26,-26,-23,-16,-4,11,32,58,96,119,140,154,165,172,175, + -- 0,0,1,2,3,4,6,7,6,4,1,-4,-8,-13,-18,-22); + + CONSTANT POLY16 : arr_int9 := ( + -24,-21,-15,-9,-5,-1,4,8,6,8,5,4,3,1,0,0, + 176,174,169,160,150,131,115,85,58,27,4,-6,-20,-24,-26,-25, + -24,-25,-26,-24,-20,-6,4,27,58,85,115,131,150,160,169,174, + 0,0,0,1,3,4,5,8,6,8,4,-1,-5,-9,-15,-21); + + CONSTANT POLY32 : arr_int9 := ( + -24,-22,-20,-18,-16,-13,-11,-8,-6,-3,-1,0,2,3,5,5,6,6,6,5,5,4,4,3,2,1,1,0,0,0,0,0, + 176,175,174,172,169,164,160,153,147,138,129,119,109,96,84,71,58,40,22,12,3,-4,-12,-16,-20,-22,-25,-25,-26,-25,-25,-25, + -24,-25,-26,-26,-26,-24,-23,-19,-16,-10,-4,4,11,22,32,45,58,77,96,108,119,129,140,147,154,159,165,168,172,173,175,175, + 0,0,0,0,1,1,2,2,3,3,4,5,6,7,7,7,6,5,4,3,1,-1,-4,-6,-8,-10,-13,-15,-18,-20,-22,-22); + + FUNCTION init_poly RETURN arr_uv36 IS + VARIABLE m : arr_uv36(0 TO 2**FRAC-1) :=(OTHERS =>x"000000000"); + BEGIN + IF FRAC=4 THEN + FOR i IN 0 TO 15 LOOP + m(i):=unsigned(to_signed(POLY16(i),9) & to_signed(POLY16(i+16),9) & + to_signed(POLY16(i+32),9) & to_signed(POLY16(i+48),9)); + END LOOP; + ELSIF FRAC=5 THEN + FOR i IN 0 TO 31 LOOP + m(i):=unsigned(to_signed(POLY32(i),9) & to_signed(POLY32(i+32),9) & + to_signed(POLY32(i+64),9) & to_signed(POLY32(i+96),9)); + END LOOP; + END IF; + RETURN m; + END FUNCTION; + + SIGNAL o_h_poly : arr_uv36(0 TO 2**FRAC-1):=init_poly; + SIGNAL o_v_poly : arr_uv36(0 TO 2**FRAC-1):=init_poly; + ATTRIBUTE ramstyle OF o_h_poly : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_v_poly : SIGNAL IS "no_rw_check"; + SIGNAL o_h_poly_a,o_v_poly_a : integer RANGE 0 TO 2**FRAC-1; + SIGNAL o_h_poly_dr,o_h_poly_dr2,o_v_poly_dr,o_v_poly_dr2 : unsigned(35 DOWNTO 0); + SIGNAL o_h_poly_pix,o_v_poly_pix : type_pix; + SIGNAL poly_h_wr,poly_v_wr : std_logic; + SIGNAL poly_tdw : unsigned(35 DOWNTO 0); + SIGNAL poly_a2 : unsigned(FRAC-1 DOWNTO 0); + + TYPE type_poly_t IS RECORD + r0,r1,b0,b1,g0,g1 : signed(17 DOWNTO 0); + END RECORD; + + SIGNAL o_h_poly_t,o_v_poly_t : type_poly_t; + + FUNCTION poly_calc1(fi : unsigned(35 DOWNTO 0); + p : arr_pix(0 TO 3)) RETURN type_poly_t IS + VARIABLE t : type_poly_t; + BEGIN + -- 2.7 * 1.8 = 3.15 + t.r0:=(signed(fi(35 DOWNTO 27)) * signed('0' & p(0).r) + + signed(fi(26 DOWNTO 18)) * signed('0' & p(1).r)); + t.r1:=(signed(fi(17 DOWNTO 9)) * signed('0' & p(2).r) + + signed(fi( 8 DOWNTO 0)) * signed('0' & p(3).r)); + t.g0:=(signed(fi(35 DOWNTO 27)) * signed('0' & p(0).g) + + signed(fi(26 DOWNTO 18)) * signed('0' & p(1).g)); + t.g1:=(signed(fi(17 DOWNTO 9)) * signed('0' & p(2).g) + + signed(fi( 8 DOWNTO 0)) * signed('0' & p(3).g)); + t.b0:=(signed(fi(35 DOWNTO 27)) * signed('0' & p(0).b) + + signed(fi(26 DOWNTO 18)) * signed('0' & p(1).b)); + t.b1:=(signed(fi(17 DOWNTO 9)) * signed('0' & p(2).b) + + signed(fi( 8 DOWNTO 0)) * signed('0' & p(3).b)); + RETURN t; + END FUNCTION; + + FUNCTION poly_calc2(t : type_poly_t) RETURN type_pix IS + VARIABLE p : type_pix; + BEGIN + p.r:=bound(unsigned(t.r0+t.r1),15); + p.g:=bound(unsigned(t.g0+t.g1),15); + p.b:=bound(unsigned(t.b0+t.b1),15); + RETURN p; + 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_pre<='0'; + + ELSIF rising_edge(i_clk) THEN + i_push<='0'; + i_eol<='0'; -- End Of Line + i_freeze <=freeze; -- + i_iauto<=iauto; -- ? + + ------------------------------------------------------ + i_head(127 DOWNTO 120)<=x"01"; -- Header type + i_head(119 DOWNTO 112)<=x"01"; -- 24bits/pixels, packed RGB, big endian + i_head(111 DOWNTO 96)<="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_phs<=i_hs; + i_pvs<=i_vs; + i_pfl<=i_fl; + i_pde<=i_de; + i_pce<=i_ce; + + ------------------------------------------------------ + IF i_pce='1' THEN + ---------------------------------------------------- + i_hs_pre<=i_phs; + i_vs_pre<=i_pvs; + i_de_pre<=i_pde; + i_fl_pre<=i_pfl; + + ---------------------------------------------------- + -- 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_sof='1' THEN + i_sof<='0'; + i_vcpt<=0; + IF i_inter='1' AND i_flm='1' AND i_half='0' AND INTER THEN + i_wline<='1'; + i_adrsi<=to_unsigned(N_BURST * i_hburst,32) + + to_unsigned(N_BURST * to_integer( + unsigned'("00") & to_std_logic(HEADER)),32); + ELSE + i_wline<='0'; + i_adrsi<=to_unsigned(N_BURST * to_integer( + unsigned'("00") & to_std_logic(HEADER)),32); + END IF; + END IF; + + IF i_pde='1' THEN + i_flm<=NOT i_pfl; + END IF; + + i_ven<=to_std_logic(i_hcpt>=i_hmin AND i_hcpt<=i_hmax AND + i_vcpt>=i_vmin AND i_vcpt<=i_vmax); + + -- Detects end of frame for triple buffering. + -- Waits for second frame of interlaced video + i_endframe0<=to_std_logic(i_vcpt=i_vmax + 1 AND + (i_inter='0' OR i_pfl='0')); + i_endframe1<=to_std_logic(i_vcpt=i_vmax + 1 AND + (i_inter='0' OR i_pfl='1')); + -- Detects third line for low lag mode + i_syncline<=to_std_logic(i_vcpt=i_vmin + 3 + AND (i_inter='0' OR i_flm='1')); + + ---------------------------------------------------- + IF i_pde='1' AND i_de_pre='0' THEN + i_vimaxc<=i_vcpt; + i_hcpt<=0; + ELSE + i_hcpt<=(i_hcpt+1) MOD 4096; + END IF; + + IF i_pde='0' AND i_de_pre='1' THEN + i_himax<=i_hcpt; + END IF; + + IF i_pvs='1' THEN + i_vimax<=i_vimaxc; + END IF; + + IF i_iauto='1' THEN + -- Auto-size + i_hmin<=0; + i_hmax<=i_himax; + i_vmin<=0; + IF i_inter='0' OR i_pfl='0' THEN + i_vmax<=i_vimax; + END IF; + ELSE + -- Forced image + i_hmin<=himin; -- + i_hmax<=himax; -- + i_vmin<=vimin; -- + i_vmax<=vimax; -- + END IF; + + ---------------------------------------------------- + i_mode<=mode; -- + + -- Downscaling : Nearest or bilinear + i_bil<=to_std_logic(i_mode(2 DOWNTO 0)/="000" AND DOWNSCALE); + + 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_hs_delay=14 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 4096; + i_hnp<='0'; -- Skip. pix. + ELSE + i_hacc<=(i_hacc + 2*i_ohsize - 2*i_hsize + 4096) MOD 4096; + 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; i_ven7<=i_ven6; + + -- 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); + ELSE + frac_v:=bil_frac(i_h_frac); + END IF; + + i_h_bil_t<=bil_calc(frac_v,(i_hpix2,i_hpix2,i_hpix3,i_hpix3)); + i_hpix.r<=bound(i_h_bil_t.r,8+FRAC); + i_hpix.g<=bound(i_h_bil_t.g,8+FRAC); + i_hpix.b<=bound(i_h_bil_t.b,8+FRAC); + + 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)); + ELSE + frac_v:=bil_frac(i_v_frac(11 DOWNTO 0)); + END IF; + + bil_t_v:=bil_calc(frac_v,(i_hpix,i_hpix,i_ldrm,i_ldrm)); + i_pix.r<=bound(bil_t_v.r,8+FRAC); + i_pix.g<=bound(bil_t_v.g,8+FRAC); + i_pix.b<=bound(bil_t_v.b,8+FRAC); + + IF i_vdown='0' THEN + i_pix<=i_hpix; + 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<=i_shift(24 TO 119) & i_pix.r & i_pix.g & i_pix.b; + i_dw<=shift24_ipack(i_dw,i_acpt,i_shift,i_pix); + + IF shift24_inext(i_acpt) AND i_vnp='1' THEN + i_push<='1'; + i_pushend<='0'; + END IF; + i_acpt<=(i_acpt+1) MOD 16; + END IF; + + IF i_pushhead='1' THEN + i_dw<=i_head; + i_pushhead2<='1'; + i_pushhead<='0'; + i_count<=i_count+1; + END IF; + + IF i_ven6='1' AND i_ven5='0' AND i_vnp='1' THEN + i_pushend<='1'; + END IF; + i_pushend2<=i_pushend; + + IF ((i_ven6='0' AND i_ven7='1') OR i_pushend2='1')AND i_pushend='0' THEN + i_eol<='1'; + END IF; + + -- Delay I_HS raising for a few cycles, finish ongoing mem. access + IF i_phs='1' AND i_hs_pre='0' THEN + i_hs_delay<=0; + ELSIF i_hs_delay<15 THEN + i_hs_delay<=i_hs_delay+1; + END IF; + + IF i_hs_delay=14 THEN -- i_hs='1' AND i_hs_pre='0' THEN + i_acpt<=0; + i_hacc<=(i_hsize - i_ohsize + 8192) MOD 8192; + i_lwad<=0; + i_lrad<=0; + i_wad<=2*BLEN-1; + i_vcpt<=i_vcpt+1; + i_hbcpt<=0; -- Bursts per line counter + IF i_vnp='1' AND i_hbcpt>0 AND i_hbfix='0' THEN + i_hburst<=i_hbcpt; + i_hbfix<='1'; + END IF; + END IF; + + IF i_pvs='0' AND i_vs_pre='1' THEN + -- Push header + i_pushhead<=to_std_logic(HEADER); + i_hbfix<='0'; + 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; + + ------------------------------------------------------ + -- Push pixels to DPRAM + i_wr<='0'; + + IF i_push='1' AND i_freeze='0' THEN + i_wr<='1'; + i_wad<=(i_wad+1) MOD (BLEN*2); + IF ((i_wad+1) MOD BLEN=BLEN-1) THEN + i_hbcpt<=(i_hbcpt+1) MOD 32; + i_write_pre<=NOT i_write_pre; + IF (i_wad+1)/BLEN=0 THEN + i_walt<='0'; + ELSE + i_walt<='1'; + END IF; + i_adrs<=i_adrsi; + i_adrsi<=i_adrsi+N_BURST; + END IF; + END IF; + + IF i_pushhead2='1' AND i_freeze='0' THEN + i_wr<='1'; + i_wad<=0; + i_write_pre<=NOT i_write; + i_walt<='0'; + i_adrs<=(OTHERS =>'0'); + i_pushhead2<='0'; + END IF; + + -- Delay a bit EOL : Async. AVL/I clocks... + i_eol2<=i_eol; i_eol3<=i_eol2; i_eol4<=i_eol3; + + -- End of line + IF i_eol4='1' AND i_freeze='0' THEN + IF (i_wad MOD BLEN)/=BLEN-1 THEN + -- Some pixels are in the partially filled buffer + i_hbcpt<=(i_hbcpt+1) MOD 32; + i_write_pre<=NOT i_write_pre; + IF i_wad/BLEN=0 THEN + i_walt<='0'; + ELSE + i_walt<='1'; + END IF; + i_adrs<=i_adrsi; + IF i_inter='1' AND i_half='0' THEN + -- Skip every other line for interlaced video + i_adrsi<=i_adrsi + N_BURST * (i_hburst + 1); + ELSE + i_adrsi<=i_adrsi + N_BURST; + END IF; + ELSE + IF i_inter='1' AND i_half='0' THEN + -- Skip every other line for interlaced video + i_adrsi<=i_adrsi + N_BURST * i_hburst; + END IF; + END IF; + END IF; + i_write<=i_write_pre AND NOT i_freeze; + + END IF; + END PROCESS; + + -- If downscaling, export to the output part the downscaled size + i_hrsize<=i_hsize WHEN i_hdown='0' ELSE i_ohsize; + i_vrsize<=i_vsize WHEN i_vdown='0' ELSE i_ovsize; + + ----------------------------------------------------------------------------- + -- Input Divider. For downscaling. + + -- Vfrac = IVacc / IVsize 12 / 12 --> 12 + + -- Division + IDividers:PROCESS (i_clk,i_reset_na) IS + BEGIN + IF i_reset_na='0' THEN +--pragma synthesis_off + 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=12 THEN + i_divrun<='0'; + i_v_frac<=i_vdivr(10 DOWNTO 0) & NOT i_vdivr(24); + 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 + + PROCESS (i_clk) IS + BEGIN + IF rising_edge(i_clk) THEN + IF i_wr='1' THEN + i_dpram(i_wad)<=i_dw; + END IF; + END IF; + END PROCESS; + + avl_dr<=i_dpram(avl_rad_c) WHEN rising_edge(avl_clk); + + -- Line buffer for downscaling with interpolation + DownLine:IF DOWNSCALE GENERATE + ILBUF:PROCESS(i_clk) IS + BEGIN + IF rising_edge(i_clk) THEN + IF i_lwr='1' THEN + i_line(i_lwad)<=i_ldw; + END IF; + IF i_pce='1' THEN + i_ldrm<=i_line(i_lrad); + END IF; + END IF; + END PROCESS ILBUF; + END GENERATE DownLine; + + ----------------------------------------------------------------------------- + -- AVALON interface + Avaloir:PROCESS(avl_clk,avl_reset_na) IS + BEGIN + IF avl_reset_na='0' THEN + avl_reading<='0'; + avl_state<=sIDLE; + avl_write_sr<='0'; + avl_read_sr<='0'; + avl_readack<='0'; + + ELSIF rising_edge(avl_clk) THEN + ---------------------------------- + avl_write_sync<=i_write; -- + avl_write_sync2<=avl_write_sync; + avl_write_pulse<=avl_write_sync XOR avl_write_sync2; + avl_wadrs <=i_adrs AND (RAMSIZE - 1); -- + avl_wline <=i_wline; -- + avl_walt <=i_walt; -- + + ---------------------------------- + avl_read_sync<=o_read; -- + avl_read_sync2<=avl_read_sync; + avl_read_pulse<=avl_read_sync XOR avl_read_sync2; + avl_rbib <=o_bib; + avl_radrs <=o_adrs AND (RAMSIZE - 1); -- + avl_rline <=o_rline; -- + + -------------------------------------------- + avl_o_offset0<=buf_offset(o_obuf0); -- + avl_o_offset1<=buf_offset(o_obuf1); -- + avl_i_offset0<=buf_offset(o_ibuf0); -- + avl_i_offset1<=buf_offset(o_ibuf1); -- + + avl_o_vs_sync<=o_vsv(0); -- + avl_o_vs<=avl_o_vs_sync; + + -------------------------------------------- + avl_dw<=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_o_vs='0' AND avl_o_vs_sync='1' THEN + avl_wad<=0; + END IF; + IF avl_write_sr='1' THEN + avl_state<=sWRITE; + avl_write_clr<='1'; + IF avl_walt='0' THEN + avl_rad<=0; + ELSE + avl_rad<=BLEN; + END IF; + ELSIF avl_read_sr='1' AND avl_reading='0' THEN + IF avl_rbib='0' THEN + avl_wad<=2*BLEN-1; + ELSE + avl_wad<=BLEN-1; + END IF; + avl_state<=sREAD; + avl_read_clr<='1'; + END IF; + + WHEN sWRITE => + IF avl_wline='0' THEN + avl_address<=std_logic_vector(RAMBASE(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_wadrs(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_i_offset0(N_AW+NB_LA-1 DOWNTO NB_LA)); + ELSE + avl_address<=std_logic_vector(RAMBASE(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_wadrs(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_i_offset1(N_AW+NB_LA-1 DOWNTO NB_LA)); + END IF; + + avl_write_i<='1'; + IF avl_write_i='1' AND avl_waitrequest='0' THEN + IF (avl_rad MOD BLEN)=BLEN-1 THEN + avl_write_i<='0'; + avl_state<=sIDLE; + END IF; + END IF; + + WHEN sREAD => + IF avl_rline='0' THEN + avl_address<=std_logic_vector(RAMBASE(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_radrs(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_o_offset0(N_AW+NB_LA-1 DOWNTO NB_LA)); + ELSE + avl_address<=std_logic_vector(RAMBASE(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_radrs(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_o_offset1(N_AW+NB_LA-1 DOWNTO NB_LA)); + END IF; + avl_read_i<='1'; + avl_reading<='1'; + IF avl_read_i='1' AND avl_waitrequest='0' THEN + avl_state<=sIDLE; + avl_read_i<='0'; + 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_reading<='0'; + avl_readack<=NOT avl_readack; + END IF; + END IF; + + -------------------------------------------- + END IF; + END PROCESS Avaloir; + + avl_read<=avl_read_i; + avl_write<=avl_write_i; + avl_writedata<=std_logic_vector(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 + 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"; +--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 hcarry_v,vcarry_v : boolean; + VARIABLE dif_v : natural RANGE 0 TO 8*OHRES-1; + BEGIN + IF o_reset_na='0' THEN + o_copy<='0'; + o_state<=sDISP; + o_read_pre<='0'; + o_readlev<=0; + o_copylev<=0; + o_hsp<='0'; + + ELSIF rising_edge(o_clk) THEN + ------------------------------------------------------ + o_mode <=mode; -- ? + o_run <=run; -- ? + + o_htotal <=htotal; -- ? + o_hsstart<=hsstart; -- ? + o_hsend <=hsend; -- ? + o_hdisp <=hdisp; -- ? + o_hmin <=hmin; -- ? + o_hmax <=hmax; -- ? + + o_vtotal <=vtotal; -- ? + o_vsstart<=vsstart; -- ? + o_vsend <=vsend; -- ? + o_vdisp <=vdisp; -- ? + o_vmin <=vmin; -- ? + o_vmax <=vmax; -- ? + + o_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_inter <=i_inter; -- + + o_iendframe0<=i_endframe0; -- + o_iendframe02<=o_iendframe0; + IF o_iendframe0='1' AND o_iendframe02='0' THEN + o_ibuf0<=buf_next(o_ibuf0,o_obuf0); + o_bufup0<='1'; + END IF; + o_iendframe1<=i_endframe1; -- + o_iendframe12<=o_iendframe1; + IF o_iendframe1='1' AND o_iendframe12='0' THEN + o_ibuf1<=buf_next(o_ibuf1,o_obuf1); + o_bufup1<='1'; + END IF; + -- Output : Change framebuffer, and image properties, at VS falling edge + IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup1='1' THEN + o_obuf1<=buf_next(o_obuf1,o_ibuf1); + o_bufup1<='0'; + o_hburst <=i_hburst; -- Bursts per line + o_ihsize<=i_hrsize; -- + o_ivsize<=i_vrsize; -- + o_hdown<=i_hdown; -- + o_vdown<=i_vdown; -- + END IF; + IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN + o_obuf0<=buf_next(o_obuf0,o_ibuf0); + o_bufup0<='0'; + END IF; + + IF o_inter='0' THEN + o_ibuf1<=o_ibuf0; + o_obuf1<=o_obuf0; + END IF; + + -- Triple buffer disabled + IF o_mode(3)='0' THEN + o_obuf0<=0; + o_obuf1<=0; + o_ibuf0<=0; + o_ibuf1<=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; + + ------------------------------------------------------ + lev_inc_v:='0'; + lev_dec_v:='0'; + + -- acpt : Pixel position within current data word + -- dcpt : Destination image position + -- hpos : Source image position, fixed point 12.12 + + -- Force preload 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; + END IF; + o_hsp<='1'; + END IF; + + o_vpe<=to_std_logic(o_vcpt_pre=o_vmin); + o_divstart<='0'; + o_adrsa<='0'; + + o_vacc_ini<=(o_vsize - o_ivsize + 8192) MOD 8192; + o_hacc_ini<=(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; + + -------------------------------------------------- + WHEN sHSYNC => + dif_v:=(o_vacc_next - 2*o_vsize + 16384) MOD 16384; + IF dif_v>=8192 THEN + o_vacc <=o_vacc_next; + o_vacc_next<=(o_vacc_next + 2*o_ivsize) MOD 8192; + vcarry_v:=false; + ELSE + o_vacc <=dif_v; + o_vacc_next<=(dif_v + 2*o_ivsize + 8192) MOD 8192; + vcarry_v:=true; + END IF; + o_divstart<='1'; + IF o_vcpt_pre2=o_vmin THEN --pe='0' THEN + o_vacc <=o_vacc_ini; + o_vacc_next<=o_vacc_ini + 2*o_ivsize; + o_vacpt<=x"001"; + vcarry_v:=false; + END IF; + + IF vcarry_v THEN + o_vacpt<=o_vacpt+1; + END IF; + o_hbcpt<=0; -- Clear burst counter on line + IF (o_vpe='1' AND vcarry_v) OR o_fload>0 THEN + o_state<=sREAD; + ELSE + o_state<=sDISP; + END IF; + + WHEN sREAD => + -- Read a block + IF o_readlev<2 THEN + lev_inc_v:='1'; + o_read_pre<=NOT o_read_pre; + o_state <=sWAITREAD; + o_bibu<=NOT o_bibu; + END IF; + prim_v:=to_std_logic(o_hbcpt=0); + last_v:=to_std_logic(o_hbcpt=o_hburst-1); + bib_v :=o_bibu; + o_bib <=o_bibu; + 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_adrs_pre<=to_integer(o_vacpt) * o_hburst; + o_rline<=o_vacpt(0); -- Even/Odd line for interlaced video + IF o_adrsa='1' THEN + IF HEADER THEN + IF o_fload=2 THEN + o_adrs<=to_unsigned((o_hbcpt + 1) * N_BURST,32); + o_alt<="1111"; + ELSIF o_fload=1 THEN + o_adrs<=to_unsigned((o_hburst + o_hbcpt + 1) * N_BURST,32); + o_alt<="0100"; + ELSE + o_adrs<=to_unsigned((o_adrs_pre + o_hbcpt + 1) * N_BURST,32); + o_alt<=altx(o_vacpt(1 DOWNTO 0) + 1); + END IF; + ELSE + 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_hburst + o_hbcpt) * N_BURST,32); + o_alt<="0100"; + ELSE + o_adrs<=to_unsigned((o_adrs_pre + o_hbcpt) * N_BURST,32); + o_alt<=altx(o_vacpt(1 DOWNTO 0) + 1); + END IF; + END IF; + END IF; + + ------------------------------------------------------ + -- Copy from buffered memory to pixel lines + o_sh<='0'; + IF o_copy='0' THEN + o_copyv(0)<='0'; + IF o_copylev>0 AND o_copyv(0)='0' THEN + o_copy<='1'; + END IF; + o_adturn<='0'; + + IF o_primv(0)='1' THEN + -- First memcopy of a horizontal line, carriage return ! + -- HPOS starts at 1 for the first input image pix,to keep it positive + o_hacc <=o_hacc_ini; + o_hacc_next<=o_hacc_ini + 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; + ELSE + -- 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_ihsize-2); + 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 shift24_onext(o_acpt) THEN + o_ad<=(o_ad+1) MOD (2*BLEN); + END IF; + + IF o_adturn='1' AND (shift24_onext((o_acpt+1) MOD 16)) AND + (((o_ad MOD BLEN=0) AND o_lastv(0)='0') OR o_last2='1') THEN + o_copy<='0'; + lev_dec_v:='1'; + END IF; + + IF o_ad MOD BLEN=4 THEN + o_adturn<='1'; + END IF; + END IF; + END IF; + + 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_lastt1<=o_last; o_lastt2<=o_lastt1; o_lastt3<=o_lastt2; + + ------------------------------------------------------ + IF o_sh3='1' THEN + shift_v:=shift24_opack(o_acpt4,o_shift,o_dr); + o_shift<=shift_v; + + o_hpix0<=(r=>shift_v(0 TO 7),g=>shift_v(8 TO 15),b=>shift_v(16 TO 23)); + o_hpix1<=o_hpix0; + o_hpix2<=o_hpix1; + o_hpix3<=o_hpix2; + + IF o_first='1' THEN + -- Left edge. Duplicate first pixel + o_hpix1<=(r=>shift_v(0 TO 7),g=>shift_v(8 TO 15),b=>shift_v(16 TO 23)); + o_hpix2<=(r=>shift_v(0 TO 7),g=>shift_v(8 TO 15),b=>shift_v(16 TO 23)); + o_first<='0'; + END IF; + IF o_lastt3='1' THEN + -- Right edge. Keep last pixel. + o_hpix0<=o_hpix0; + END IF; + END IF; + + ------------------------------------------------------ + -- READLEV : Number of ongoing Avalon Reads + IF lev_dec_v='1' AND lev_inc_v='0' THEN + o_readlev<=o_readlev-1; + ELSIF lev_dec_v='0' AND lev_inc_v='1' THEN + o_readlev<=o_readlev+1; + END IF; + + -- COPYLEV : Number of ongoing copies to line buffers + IF lev_dec_v='1' AND o_readack='0' THEN + o_copylev<=o_copylev-1; + ELSIF lev_dec_v='0' AND o_readack='1' THEN + o_copylev<=o_copylev+1; + END IF; + + -- FIFOs + IF lev_dec_v='1' THEN + o_primv(0 TO 1)<=o_primv(1 TO 2); -- First buffer of line + o_lastv(0 TO 1)<=o_lastv(1 TO 2); -- Last buffer of line + o_bibv (0 TO 1)<=o_bibv (1 TO 2); -- Double buffer select + END IF; + + IF lev_inc_v='1' THEN + IF o_readlev=0 OR (o_readlev=1 AND lev_dec_v='1') THEN + o_primv(0)<=prim_v; + o_lastv(0)<=last_v; + o_bibv (0)<=bib_v; + ELSIF (o_readlev=1 AND lev_dec_v='0') OR + (o_readlev=2 AND lev_dec_v='1') THEN + o_primv(1)<=prim_v; + o_lastv(1)<=last_v; + o_bibv (1)<=bib_v; + END IF; + o_primv(2)<=prim_v; + o_lastv(2)<=last_v; + o_bibv (2)<=bib_v; + END IF; + + ------------------------------------------------------ + END IF; + END PROCESS Scalaire; + + o_h_poly_a<=to_integer(o_hfrac(11 DOWNTO 12-FRAC)); + o_v_poly_a<=to_integer(o_vfrac(11 DOWNTO 12-FRAC)); + + o_h_poly_dr<=o_h_poly(o_h_poly_a) WHEN rising_edge(o_clk); + o_v_poly_dr<=o_v_poly(o_v_poly_a) WHEN rising_edge(o_clk); + + ----------------------------------------------------------------------------- + -- Polyphase ROMs + Polikarpov:PROCESS(poly_clk) IS + BEGIN + IF rising_edge(poly_clk) THEN + IF poly_wr='1' THEN + poly_tdw(8+9*(3-to_integer(poly_a(1 DOWNTO 0))) DOWNTO + 9*(3-to_integer(poly_a(1 DOWNTO 0))))<=poly_dw; + END IF; + + poly_h_wr<=poly_wr AND NOT poly_a(FRAC+2); + poly_v_wr<=poly_wr AND poly_a(FRAC+2); + poly_a2<=poly_a(FRAC+1 DOWNTO 2); + + IF poly_h_wr='1' THEN + o_h_poly(to_integer(poly_a2))<=poly_tdw; + END IF; + IF poly_v_wr='1' THEN + o_v_poly(to_integer(poly_a2))<=poly_tdw; + END IF; + END IF; + END PROCESS Polikarpov; + + ----------------------------------------------------------------------------- + -- Horizontal Scaler + HSCAL:PROCESS(o_clk) IS + VARIABLE div_v : unsigned(18 DOWNTO 0); + VARIABLE dir_v : unsigned(11 DOWNTO 0); + BEGIN + IF rising_edge(o_clk) THEN + -- Pipeline signals + ----------------------------------- + -- Pipelined 6 bits non-restoring divider. Cycle 1 + dir_v:=x"000"; + div_v:=to_unsigned(o_hacc * 64,19); + + div_v:=div_v-to_unsigned(o_hsize*64,19); + dir_v(11):=NOT div_v(18); + IF div_v(18)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*32,19); + ELSE + div_v:=div_v+to_unsigned(o_hsize*32,19); + END IF; + dir_v(10):=NOT div_v(18); + o_div<=div_v; + o_dir<=dir_v; + + -- Cycle 2 + div_v:=o_div; + dir_v:=o_dir; + IF div_v(18)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*16,19); + ELSE + div_v:=div_v+to_unsigned(o_hsize*16,19); + END IF; + dir_v( 9):=NOT div_v(18); + + IF div_v(18)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*8,19); + ELSE + div_v:=div_v+to_unsigned(o_hsize*8,19); + END IF; + dir_v(8):=NOT div_v(18); + o_div2<=div_v; + o_dir2<=dir_v; + + -- Cycle 3 + div_v:=o_div2; + dir_v:=o_dir2; + IF div_v(18)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*4,19); + ELSE + div_v:=div_v+to_unsigned(o_hsize*4,19); + END IF; + dir_v(7):=NOT div_v(18); + IF FRAC>4 THEN + IF div_v(18)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*2,19); + ELSE + div_v:=div_v+to_unsigned(o_hsize*2,19); + END IF; + dir_v(6):=NOT div_v(18); + END IF; + + ----------------------------------- + o_hfrac<=dir_v; + o_hfrac1<=o_hfrac; o_hfrac2<=o_hfrac1; o_hfrac3<=o_hfrac2; + + o_copyv(1 TO 7)<=o_copyv(0 TO 6); + + o_dcpt1<=o_dcpt; + IF o_dcpt1>o_hsize THEN + o_copyv(2)<='0'; + END IF; + o_dcpt2<=o_dcpt1 MOD OHRES; + o_dcpt3<=o_dcpt2; o_dcpt4<=o_dcpt3; o_dcpt5<=o_dcpt4; + o_dcpt6<=o_dcpt5; o_dcpt7<=o_dcpt6; + + o_hpixq<=(o_hpix3,o_hpix2,o_hpix1,o_hpix0); + + -- NEAREST / BILINEAR / SHARP BILINEAR --------------- + -- C1 : Pre-calc Sharp Bilinear + o_h_sbil_t<=sbil_frac1(o_hfrac); + + -- C2 : Select + o_h_frac2<=(OTHERS =>'0'); + CASE o_hmode(1 DOWNTO 0) IS + WHEN "00" => -- Nearest + IF MASK(MASK_NEAREST)='1' THEN + o_h_frac2<=near_frac(o_hfrac1); + END IF; + WHEN "01" => -- Bilinear + IF MASK(MASK_BILINEAR)='1' THEN + o_h_frac2<=bil_frac(o_hfrac1); + END IF; + WHEN "10" => -- Sharp Bilinear + IF MASK(MASK_SHARP_BILINEAR)='1' THEN + o_h_frac2<=sbil_frac2(o_hfrac1,o_h_sbil_t); + END IF; + WHEN OTHERS => + NULL; + END CASE; + + -- C3 : Opposite frac + o_h_bil_t<=bil_calc(o_h_frac2,o_hpixq); + + -- C4 : Nearest / 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 ------------------------------------------- + -- C1 : Bicubic coefficients A,B,C,D + + -- C2 : Bicubic calc T1 = X.D + C + o_h_bic_abcd1<=bic_calc0(o_hfrac1,(o_hpix3,o_hpix2,o_hpix1,o_hpix0)); + o_h_bic_tt1<=bic_calc1(o_hfrac1, + bic_calc0(o_hfrac1,(o_hpix3,o_hpix2,o_hpix1,o_hpix0))); + + -- C3 : Bicubic calc T2 = X.T1 + B + o_h_bic_abcd2<=o_h_bic_abcd1; + o_h_bic_tt2<=bic_calc2(o_hfrac2,o_h_bic_tt1,o_h_bic_abcd1); + + -- C4 : Bicubic final Y = X.T2 + A + o_h_bic_pix<=bic_calc3(o_hfrac3,o_h_bic_tt2,o_h_bic_abcd2); + + -- POLYPHASE ----------------------------------------- + -- C1 : Read memory + + -- C2 : Filter calc + o_h_poly_dr2<=o_h_poly_dr; + + -- C3 : Add + o_h_poly_t<=poly_calc1(o_h_poly_dr2,o_hpixq); + + -- C4 : Bounding + o_h_poly_pix<=poly_calc2(o_h_poly_t); + + -- C5 : Select interpoler ---------------------------- + o_wadl<=o_dcpt7; + o_wr<=o_alt AND (o_copyv(7) & o_copyv(7) & o_copyv(7) & o_copyv(7)); + o_ldw<=(x"00",x"00",x"00"); + + CASE o_hmode(2 DOWNTO 0) IS + WHEN "000" | "001" | "010" => -- Nearest | Bilinear | Sharp Bilinear + IF MASK(MASK_NEAREST)='1' OR + 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_radl); + o_ldr1<=o_line1(o_radl); + o_ldr2<=o_line2(o_radl); + o_ldr3<=o_line3(o_radl); + 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_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_isyncline2<=o_isyncline; + + IF SYNCHRO THEN + -- Measure input image size + IF o_isyncline2='1' AND o_isyncline='0' THEN + o_llicpt<=0; + o_llipos<=o_llocpt; + o_llisize<=o_llicpt; + o_llfl<=i_pfl; -- + ELSE + o_llicpt<=o_llicpt+1; + END IF; + + -- Measure output image size + IF o_vss='1' AND o_vss1='0' THEN + o_vstog<=NOT o_vstog OR NOT o_inter; + END IF; + IF o_vss='1' AND o_vss1='0' AND o_vstog='1' THEN + o_llocpt<=0; + o_llup<='1'; + o_llosize<=o_llocpt; + ELSE + o_llocpt<=o_llocpt+1; + o_llup<='0'; + END IF; + + -- Period difference between input and output images + o_lldiff<=(integer(o_llosize) - integer(o_llisize)); + + o_lltune_i(14)<='0'; -- Interleaved video field + o_lltune_i(7 DOWNTO 6)<=o_inter & o_llfl; + IF o_llup='1' THEN + o_llcpt<=0; + o_llssh<=o_llosize; + o_llos<='0'; + o_llop<='0'; + + ELSIF o_llcpt<24 THEN + -- Frequency difference + IF o_lldiff>0 AND o_llssh=o_llosize/2 AND o_llssh<(o_llosize-o_llipos) + AND o_llop='0' THEN + o_lltune_i(13 DOWNTO 8)<='1' & to_unsigned(o_llcpt,5); + o_llop<='1'; + END IF; + o_llssh<=o_llssh/2; + o_llcpt<=o_llcpt+1; + + ELSIF o_llcpt=24 THEN + o_lltune_i(15)<=NOT o_lltune_i(15); + o_llssh<=o_llssh/2; + o_llcpt<=o_llcpt+1; + END IF; + END IF; + END IF; + END IF; + + END PROCESS OSWEEP; + + o_lltune<=o_lltune_i; + ----------------------------------------------------------------------------- + -- Vertical Scaler + VSCAL:PROCESS(o_clk) IS + VARIABLE pixq_v : arr_pix(0 TO 3); + BEGIN + IF rising_edge(o_clk) THEN + IF o_ce='1' THEN + -- CYCLE 1 ----------------------------------------- + -- Read mem + o_radl<=(o_hcpt-o_hmin+OHRES) MOD OHRES; + + -- CYCLE 2 ----------------------------------------- + -- Lines reordering + CASE o_vacpt(1 DOWNTO 0) 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; + + o_vpixq<=pixq_v; + + -- Bottom edge : replicate last line + IF to_integer(o_vacpt)=o_ivsize THEN + o_vpixq(2)<=pixq_v(2); + END IF; + IF to_integer(o_vacpt)>=o_ivsize+1 THEN + o_vpixq(2)<=pixq_v(1); + o_vpixq(1)<=pixq_v(1); + END IF; + + o_vpixq1<=o_vpixq; + + -- NEAREST / BILINEAR / SHARP BILINEAR ------------- + -- C3 : Pre-calc Sharp Bilinear + o_v_sbil_t<=sbil_frac1(o_vfrac); + + -- C4 : Select + o_v_frac<=(OTHERS =>'0'); + CASE o_vmode(1 DOWNTO 0) IS + WHEN "00" => -- Nearest + IF MASK(MASK_NEAREST)='1' THEN + o_v_frac<=near_frac(o_vfrac); + END IF; + WHEN "01" => -- Bilinear + IF MASK(MASK_BILINEAR)='1' THEN + o_v_frac<=bil_frac(o_vfrac); + END IF; + WHEN "10" => -- Sharp Bilinear + IF MASK(MASK_SHARP_BILINEAR)='1' THEN + o_v_frac<=sbil_frac2(o_vfrac,o_v_sbil_t); + END IF; + WHEN OTHERS => NULL; + END CASE; + + o_v_bil_t<=bil_calc(o_v_frac,o_vpixq1); + + -- C6 : 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 ----------------------------------------- + -- C3 : Bicubic coefficients A,B,C,D + + -- C4 : 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)); + + -- C5 : 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); + + -- C6 : Bicubic final Y = X.T2 + A + o_v_bic_pix<=bic_calc3(o_vfrac,o_v_bic_tt2,o_v_bic_abcd2); + + -- POLYPHASE --------------------------------------- + -- C3 : Read memory + + -- C4 : Filter calc + o_v_poly_dr2<=o_v_poly_dr; + + -- C5 : Add + o_v_poly_t<=poly_calc1(o_v_poly_dr2,o_vpixq1); + + -- C6 : Bounding + o_v_poly_pix<=poly_calc2(o_v_poly_t); + + -- CYCLE 6 ----------------------------------------- + o_hs<=o_hsv(5); + o_vs<=o_vsv(5); + o_de<=o_dev(5); + o_r<=x"00"; + o_g<=x"00"; + o_b<=x"00"; + + CASE o_vmode(2 DOWNTO 0) IS + WHEN "000" | "001" | "010" => -- Nearest | Bilinear | Sharp Bilinear + IF MASK(MASK_NEAREST)='1' OR + 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(5)='0' THEN + o_r<=x"00"; -- Border colour + o_g<=x"00"; + o_b<=x"00"; + END IF; + + ---------------------------------------------------- + END IF; + END IF; + + END PROCESS VSCAL; + + ---------------------------------------------------------------------------- +END ARCHITECTURE rtl; + diff --git a/sys/coeff.mif b/sys/coeff.mif new file mode 100644 index 0000000..fd0a47b --- /dev/null +++ b/sys/coeff.mif @@ -0,0 +1,71 @@ +DEPTH = 256; +WIDTH = 9; +ADDRESS_RADIX = HEX; +DATA_RADIX = HEX; +CONTENT BEGIN +000: 1E8 0B0 1E8 000; +004: 1EC 0AE 1E6 000; +008: 1F0 0A9 1E6 001; +00C: 1F5 0A0 1E9 002; +010: 1FA 093 1F0 003; +014: 1FF 081 1FC 004; +018: 002 06D 00B 006; +01C: 005 054 020 007; +020: 006 03A 03A 006; +024: 006 016 060 004; +028: 005 003 077 001; +02C: 004 1F4 08C 1FC; +030: 002 1EC 09A 1F8; +034: 001 1E7 0A5 1F3; +038: 000 1E6 0AC 1EE; +03C: 000 1E7 0AF 1EA; +040: 000 080 000 000; +044: 1FC 07E 006 000; +048: 1F8 07C 00D 1FF; +04C: 1F6 077 014 1FF; +050: 1F5 06F 01E 1FE; +054: 1F5 067 028 1FC; +058: 1F6 05D 032 1FB; +05C: 1F7 052 03D 1FA; +060: 1F8 048 048 1F8; +064: 1FA 038 058 1F6; +068: 1FC 02D 062 1F5; +06C: 1FD 023 06B 1F5; +070: 1FE 019 073 1F6; +074: 1FF 011 079 1F7; +078: 000 009 07D 1FA; +07C: 000 003 07F 1FE; + +080: 000 080 000 000; +084: 000 080 000 000; +088: 000 080 000 000; +08C: 000 080 000 000; +090: 000 080 000 000; +094: 000 080 000 000; +098: 000 080 000 000; +09C: 000 080 000 000; +0A0: 000 080 000 000; +0A4: 000 080 000 000; +0A8: 000 080 000 000; +0AC: 000 080 000 000; +0B0: 000 080 000 000; +0B4: 000 080 000 000; +0B8: 000 080 000 000; +0BC: 000 080 000 000; +0C0: 000 080 000 000; +0C4: 000 080 000 000; +0C8: 000 080 000 000; +0CC: 000 080 000 000; +0D0: 000 080 000 000; +0D4: 000 080 000 000; +0D8: 000 080 000 000; +0DC: 000 080 000 000; +0E0: 000 080 000 000; +0E4: 000 080 000 000; +0E8: 000 080 000 000; +0EC: 000 080 000 000; +0F0: 000 080 000 000; +0F4: 000 080 000 000; +0F8: 000 080 000 000; +0FC: 000 080 000 000; +END; diff --git a/sys/hdmi_config.sv b/sys/hdmi_config.sv index 0321792..476d72d 100644 --- a/sys/hdmi_config.sv +++ b/sys/hdmi_config.sv @@ -142,9 +142,9 @@ wire [15:0] init_data[58] = 16'hAA00, // ADI required Write. 16'hAB40, // ADI required Write. - {8'hAF, 6'b0001_01,~dvi_mode,1'b0}, // [7]=0 HDCP Disabled. + {8'hAF, 6'b0000_01,~dvi_mode,1'b0}, // [7]=0 HDCP Disabled. // [6:5] must be b00! - // [4]=1 Current frame IS HDCP encrypted!??? (HDCP disabled anyway?) + // [4]=0 Current frame is unencrypted // [3:2] must be b01! // [1]=1 HDMI Mode. // [0] must be b0! diff --git a/sys/hdmi_lite.sv b/sys/hdmi_lite.sv deleted file mode 100644 index 96eb441..0000000 --- a/sys/hdmi_lite.sv +++ /dev/null @@ -1,395 +0,0 @@ -//============================================================================ -// -// HDMI Lite output module -// Copyright (C) 2017 Sorgelig -// -// 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. -// -//============================================================================ - - -module hdmi_lite -( - input reset, - - input clk_video, - input ce_pixel, - input video_vs, - input video_de, - input [23:0] video_d, - - input clk_hdmi, - input hdmi_hde, - input hdmi_vde, - output reg hdmi_de, - output [23:0] hdmi_d, - - input [11:0] screen_w, - input [11:0] screen_h, - input quadbuf, - - // 0-3 => scale 1-4 - input [1:0] scale_x, - input [1:0] scale_y, - input scale_auto, - - input clk_vbuf, - output [27:0] vbuf_address, - input [127:0] vbuf_readdata, - output [127:0] vbuf_writedata, - output [7:0] vbuf_burstcount, - output [15:0] vbuf_byteenable, - input vbuf_waitrequest, - input vbuf_readdatavalid, - output reg vbuf_read, - output reg vbuf_write -); - -localparam [7:0] burstsz = 64; - -reg [1:0] nbuf = 0; -wire [27:0] read_buf = {4'd2, 3'b000, (quadbuf ? nbuf-2'd1 : 2'b00), 19'd0}; -wire [27:0] write_buf = {4'd2, 3'b000, (quadbuf ? nbuf+2'd1 : 2'b00), 19'd0}; - -assign vbuf_address = vbuf_write ? vbuf_waddress : vbuf_raddress; -assign vbuf_burstcount = vbuf_write ? vbuf_wburstcount : vbuf_rburstcount; - -wire [95:0] hf_out; -wire [7:0] hf_usedw; -reg hf_reset = 0; - -vbuf_fifo out_fifo -( - .aclr(hf_reset), - - .wrclk(clk_vbuf), - .wrreq(vbuf_readdatavalid), - .data({vbuf_readdata[96+:24],vbuf_readdata[64+:24],vbuf_readdata[32+:24],vbuf_readdata[0+:24]}), - .wrusedw(hf_usedw), - - .rdclk(~clk_hdmi), - .rdreq(hf_rdreq), - .q(hf_out) -); - -reg [11:0] rd_stride; -wire [7:0] rd_burst = (burstsz < rd_stride) ? burstsz : rd_stride[7:0]; - -reg [27:0] vbuf_raddress; -reg [7:0] vbuf_rburstcount; -always @(posedge clk_vbuf) begin - reg [18:0] rdcnt; - reg [7:0] bcnt; - reg vde1, vde2; - reg [1:0] mcnt; - reg [1:0] my; - reg [18:0] fsz; - reg [11:0] strd; - - vde1 <= hdmi_vde; - vde2 <= vde1; - - if(vbuf_readdatavalid) begin - rdcnt <= rdcnt + 1'd1; - if(bcnt) bcnt <= bcnt - 1'd1; - vbuf_raddress <= vbuf_raddress + 1'd1; - end - - if(!bcnt && reading) reading <= 0; - - vbuf_read <= 0; - if(~vbuf_waitrequest) begin - if(!hf_reset && rdcnt=off_x) && (x<(vh_width+off_x)) && (y>=off_y) && (y<(vh_height+off_y)) && !hload && !pcnt; -wire de_in = hdmi_hde & hdmi_vde; - -always @(posedge clk_hdmi) begin - reg [71:0] px_out; - reg [1:0] mx; - reg vde; - - vde <= hdmi_vde; - - if(vde & ~hdmi_vde) begin - off_x <= (screen_w>v_width) ? (screen_w - v_width)>>1 : 12'd0; - off_y <= (screen_h>v_height) ? (screen_h - v_height)>>1 : 12'd0; - vh_height <= v_height; - vh_width <= v_width; - mx <= mult_x; - end - - pcnt <= pcnt + 1'd1; - if(pcnt == mx) begin - pcnt <= 0; - hload <= hload + 1'd1; - end - - if(~de_in || x (screen_h/2)) ? 2'b00 : (video_y > (screen_h/3)) ? 2'b01 : (video_y > (screen_h/4)) ? 2'b10 : 2'b11; -wire [1:0] tm_x = (l1_width > (screen_w/2)) ? 2'b00 : (l1_width > (screen_w/3)) ? 2'b01 : (l1_width > (screen_w/4)) ? 2'b10 : 2'b11; -wire [1:0] tm_xy = (tm_x < tm_y) ? tm_x : tm_y; -wire [1:0] tmf_y = scale_auto ? tm_xy : scale_y; -wire [1:0] tmf_x = scale_auto ? tm_xy : scale_x; -wire [11:0] t_height = video_y + (tmf_y[0] ? video_y : 12'd0) + (tmf_y[1] ? video_y<<1 : 12'd0); -wire [11:0] t_width = l1_width + (tmf_x[0] ? l1_width : 12'd0) + (tmf_x[1] ? l1_width<<1 : 12'd0); -wire [23:0] t_fsz = l1_stride * t_height; - -reg [11:0] l1_width; -reg [11:0] l1_stride; -always @(posedge clk_video) begin - reg [7:0] loaded = 0; - reg [11:0] strd = 0; - reg old_de = 0; - reg old_vs = 0; - - old_vs <= video_vs; - if(~old_vs & video_vs) begin - cur_addr<= write_buf; - video_x <= 0; - video_y <= 0; - loaded <= 0; - strd <= 0; - nbuf <= nbuf + 1'd1; - - stride <= l1_stride; - framesz <= t_fsz[18:0]; - v_height<= t_height; - v_width <= t_width; - mult_x <= tmf_x; - mult_y <= tmf_y; - end - - if(pix_wr) begin - case(video_x[1:0]) - 0: pix_acc <= video_d; // zeroes upper bits too - 1: pix_acc[47:24] <= video_d; - 2: pix_acc[71:48] <= video_d; - 3: loaded <= loaded + 1'd1; - endcase - if(video_x= burstsz) || (old_de & ~video_de)) begin - if(loaded + infifo_tail) begin - flush_size <= loaded + infifo_tail; - flush_addr <= cur_addr; - flush_req <= ~flush_req; - loaded <= 0; - strd <= strd + loaded; - end - - cur_addr <= cur_addr + loaded + infifo_tail; - if(~video_de) begin - if(video_y -// Copyright (c) 2017 Sorgelig (port to DE10-nano) +// Copyright (c) 2017-2019 Sorgelig // // This source file is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published @@ -37,13 +37,26 @@ module hps_io #(parameter STRLEN=0, WIDE=0, VDNUM=1) output reg [15:0] joystick_0, output reg [15:0] joystick_1, + output reg [15:0] joystick_2, + output reg [15:0] joystick_3, + output reg [15:0] joystick_4, + output reg [15:0] joystick_5, output reg [15:0] joystick_analog_0, output reg [15:0] joystick_analog_1, + output reg [15:0] joystick_analog_2, + output reg [15:0] joystick_analog_3, + output reg [15:0] joystick_analog_4, + output reg [15:0] joystick_analog_5, output [1:0] buttons, output forced_scandoubler, output reg [31:0] status, + input [31:0] status_in, + input status_set, + + //toggle to force notify of video mode change + input new_vmode, // SD config output reg [VD:0] img_mounted, // signaling that new image has been mounted @@ -81,7 +94,13 @@ module hps_io #(parameter STRLEN=0, WIDE=0, VDNUM=1) output reg [7:0] fdc_data_in, // RTC MSM6242B layout - output reg [63:0] RTC, + output reg [64:0] RTC, + + // Seconds since 1970-01-01 00:00:00 + output reg [32:0] TIMESTAMP, + + // UART flags + input [15:0] uart_mode, input [7:0] kbd_out_data, input kbd_out_strobe, @@ -146,7 +165,7 @@ integer hcnt; always @(posedge clk_vid) begin integer vcnt; - reg old_vs= 0, old_de = 0; + reg old_vs= 0, old_de = 0, old_vmode = 0; reg calch = 0; if(ce_pix) begin @@ -159,7 +178,8 @@ always @(posedge clk_vid) begin if(old_vs & ~vs) begin if(hcnt && vcnt) begin - if(vid_hcnt != hcnt || vid_vcnt != vcnt) vid_nres <= vid_nres + 1'd1; + old_vmode <= new_vmode; + if(vid_hcnt != hcnt || vid_vcnt != vcnt || old_vmode != new_vmode) vid_nres <= vid_nres + 1'd1; vid_hcnt <= hcnt; vid_vcnt <= vcnt; end @@ -236,6 +256,15 @@ always@(posedge clk_sys) begin reg old_out_strobe = 0; reg kbd_out_data_available = 0; + reg [3:0] stflg = 0; + reg [31:0] status_req; + reg old_status_set = 0; + + old_status_set <= status_set; + if(~old_status_set & status_set) begin + stflg <= stflg + 1'd1; + status_req <= status_in; + end sd_buff_wr <= b_wr[0]; if(b_wr[2] && (~&sd_buff_addr)) sd_buff_addr <= sd_buff_addr + 1'b1; @@ -248,6 +277,7 @@ always@(posedge clk_sys) begin fdc_data_in_strobe <= 0; if(~io_enable) begin + if(cmd == 'h22) RTC[64] <= ~RTC[64]; cmd <= 0; byte_cnt <= 0; sd_ack <= 0; @@ -266,6 +296,8 @@ always@(posedge clk_sys) begin 'h19: sd_ack_conf <= 1; 'h17, 'h18: sd_ack <= 1; + 'h29: io_dout <= {4'hA, stflg}; + 'h2B: io_dout <= 1; endcase sd_buff_addr <= 0; @@ -277,6 +309,10 @@ always@(posedge clk_sys) begin 'h01: cfg <= io_din[7:0]; 'h02: joystick_0 <= io_din; 'h03: joystick_1 <= io_din; + 'h10: joystick_2 <= io_din; + 'h11: joystick_3 <= io_din; + 'h12: joystick_4 <= io_din; + 'h13: joystick_5 <= io_din; 'h04: begin if(byte_cnt == 1) begin @@ -292,20 +328,15 @@ always@(posedge clk_sys) begin kbd_in_data <= io_din[7:0]; end - // reading config string - 'h14: begin - // returning a byte from string - if(byte_cnt < STRLEN + 1) io_dout[7:0] <= conf_str[(STRLEN - byte_cnt)<<3 +:8]; - end + // reading config string, returning a byte from string + 'h14: if(byte_cnt < STRLEN + 1) io_dout[7:0] <= conf_str[(STRLEN - byte_cnt)<<3 +:8]; // reading sd card status - 'h16: begin - case(byte_cnt) + 'h16: case(byte_cnt) 1: io_dout <= sd_cmd; 2: io_dout <= sd_lba[15:0]; 3: io_dout <= sd_lba[31:16]; endcase - end // send SD config IO -> FPGA // flag that download begins @@ -326,14 +357,17 @@ always@(posedge clk_sys) begin end // joystick analog - 'h1a: begin - // first byte is joystick index - if(byte_cnt == 1) stick_idx <= io_din[2:0]; - if(byte_cnt == 2) begin - if(stick_idx == 0) joystick_analog_0 <= io_din; - if(stick_idx == 1) joystick_analog_1 <= io_din; - end - end + 'h1a: case(byte_cnt) + 1: stick_idx <= io_din[2:0]; // first byte is joystick index + 2: case(stick_idx) + 0: joystick_analog_0 <= io_din; + 1: joystick_analog_1 <= io_din; + 2: joystick_analog_2 <= io_din; + 3: joystick_analog_3 <= io_din; + 4: joystick_analog_4 <= io_din; + 5: joystick_analog_5 <= io_din; + endcase + endcase // notify image selection 'h1c: begin @@ -352,23 +386,33 @@ always@(posedge clk_sys) begin 'h22: RTC[(byte_cnt-6'd1)<<4 +:16] <= io_din; //Video res. - 'h23: begin - case(byte_cnt) - 1: io_dout <= vid_nres; - 2: io_dout <= vid_hcnt[15:0]; - 3: io_dout <= vid_hcnt[31:16]; - 4: io_dout <= vid_vcnt[15:0]; - 5: io_dout <= vid_vcnt[31:16]; - 6: io_dout <= vid_htime[15:0]; - 7: io_dout <= vid_htime[31:16]; - 8: io_dout <= vid_vtime[15:0]; - 9: io_dout <= vid_vtime[31:16]; - 10: io_dout <= vid_pix[15:0]; - 11: io_dout <= vid_pix[31:16]; - 12: io_dout <= vid_vtime_hdmi[15:0]; - 13: io_dout <= vid_vtime_hdmi[31:16]; - endcase - end + 'h23: case(byte_cnt) + 1: io_dout <= vid_nres; + 2: io_dout <= vid_hcnt[15:0]; + 3: io_dout <= vid_hcnt[31:16]; + 4: io_dout <= vid_vcnt[15:0]; + 5: io_dout <= vid_vcnt[31:16]; + 6: io_dout <= vid_htime[15:0]; + 7: io_dout <= vid_htime[31:16]; + 8: io_dout <= vid_vtime[15:0]; + 9: io_dout <= vid_vtime[31:16]; + 10: io_dout <= vid_pix[15:0]; + 11: io_dout <= vid_pix[31:16]; + 12: io_dout <= vid_vtime_hdmi[15:0]; + 13: io_dout <= vid_vtime_hdmi[31:16]; + endcase + + //RTC + 'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din; + + //UART flags + 'h28: io_dout <= uart_mode; + + //status set + 'h29: case(byte_cnt) + 1: io_dout <= status_req[15:0]; + 2: io_dout <= status_req[31:16]; + endcase 'h55: //ARCHIE_FDC_GET_STATUS: begin diff --git a/sys/hq2x.sv b/sys/hq2x.sv index 02b8543..ece54f9 100644 --- a/sys/hq2x.sv +++ b/sys/hq2x.sv @@ -1,7 +1,7 @@ // // // Copyright (c) 2012-2013 Ludvig Strigeus -// Copyright (c) 2017 Sorgelig +// Copyright (c) 2017,2018 Sorgelig // // This program is GPL Licensed. See COPYING for the full license. // @@ -12,36 +12,24 @@ `timescale 1 ps / 1 ps // synopsys translate_on -`define BITS_TO_FIT(N) ( \ - N <= 2 ? 0 : \ - N <= 4 ? 1 : \ - N <= 8 ? 2 : \ - N <= 16 ? 3 : \ - N <= 32 ? 4 : \ - N <= 64 ? 5 : \ - N <= 128 ? 6 : \ - N <= 256 ? 7 : \ - N <= 512 ? 8 : \ - N <= 1024 ? 9 : \ - N <= 2048 ?10 : 11 ) - module Hq2x #(parameter LENGTH, parameter HALF_DEPTH) ( - input clk, - input ce_x4, - input [DWIDTH:0] inputpixel, - input mono, - input disable_hq2x, - input reset_frame, - input reset_line, - input [1:0] read_y, - input [AWIDTH+1:0] read_x, - output [DWIDTH:0] outpixel + input clk, + input ce_x4, + input [DWIDTH:0] inputpixel, + input mono, + input disable_hq2x, + input reset_frame, + input reset_line, + input [1:0] read_y, + input hblank, + output [DWIDTH:0] outpixel ); -localparam AWIDTH = `BITS_TO_FIT(LENGTH); +localparam AWIDTH = $clog2(LENGTH)-1; localparam DWIDTH = HALF_DEPTH ? 11 : 23; +localparam DWIDTH1 = DWIDTH+1; wire [5:0] hqTable[256] = '{ 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, @@ -62,30 +50,29 @@ wire [5:0] hqTable[256] = '{ 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43 }; -reg [23:0] Prev0, Prev1, Prev2, Curr0, Curr1, Next0, Next1, Next2; +reg [23:0] Prev0, Prev1, Prev2, Curr0, Curr1, Curr2, Next0, Next1, Next2; reg [23:0] A, B, D, F, G, H; reg [7:0] pattern, nextpatt; -reg [1:0] i; -reg [7:0] y; +reg [1:0] cyc; -wire curbuf = y[0]; +reg curbuf; reg prevbuf = 0; wire iobuf = !curbuf; wire diff0, diff1; -DiffCheck diffcheck0(Curr1, (i == 0) ? Prev0 : (i == 1) ? Curr0 : (i == 2) ? Prev2 : Next1, diff0); -DiffCheck diffcheck1(Curr1, (i == 0) ? Prev1 : (i == 1) ? Next0 : (i == 2) ? Curr2 : Next2, diff1); +DiffCheck diffcheck0(Curr1, (cyc == 0) ? Prev0 : (cyc == 1) ? Curr0 : (cyc == 2) ? Prev2 : Next1, diff0); +DiffCheck diffcheck1(Curr1, (cyc == 0) ? Prev1 : (cyc == 1) ? Next0 : (cyc == 2) ? Curr2 : Next2, diff1); wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]}; -wire [23:0] X = (i == 0) ? A : (i == 1) ? Prev1 : (i == 2) ? Next1 : G; -wire [23:0] blend_result; -Blend blender(hqTable[nextpatt], disable_hq2x, Curr0, X, B, D, F, H, blend_result); +wire [23:0] X = (cyc == 0) ? A : (cyc == 1) ? Prev1 : (cyc == 2) ? Next1 : G; +wire [23:0] blend_result_pre; +Blend blender(hqTable[nextpatt], disable_hq2x, Curr0, X, B, D, F, H, blend_result_pre); -reg Curr2_addr1; -reg [AWIDTH:0] Curr2_addr2; -wire [23:0] Curr2 = HALF_DEPTH ? h2rgb(Curr2tmp) : Curr2tmp; -wire [DWIDTH:0] Curr2tmp; +wire [DWIDTH:0] Curr20tmp; +wire [23:0] Curr20 = HALF_DEPTH ? h2rgb(Curr20tmp) : Curr20tmp; +wire [DWIDTH:0] Curr21tmp; +wire [23:0] Curr21 = HALF_DEPTH ? h2rgb(Curr21tmp) : Curr21tmp; reg [AWIDTH:0] wrin_addr2; reg [DWIDTH:0] wrpix; @@ -109,9 +96,11 @@ hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in ( .clk(clk), - .rdaddr(Curr2_addr2), - .rdbuf(Curr2_addr1), - .q(Curr2tmp), + .rdaddr(offs), + .rdbuf0(prevbuf), + .rdbuf1(curbuf), + .q0(Curr20tmp), + .q1(Curr21tmp), .wraddr(wrin_addr2), .wrbuf(iobuf), @@ -119,27 +108,31 @@ hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in .wren(wrin_en) ); -reg [1:0] wrout_addr1; -reg [AWIDTH+1:0] wrout_addr2; -reg wrout_en; -reg [DWIDTH:0] wrdata; +reg [AWIDTH+1:0] read_x; +reg [AWIDTH+1:0] wrout_addr; +reg wrout_en; +reg [DWIDTH1*4-1:0] wrdata, wrdata_pre; +wire [DWIDTH1*4-1:0] outpixel_x4; +reg [DWIDTH1*2-1:0] outpixel_x2; -hq2x_out #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_out +assign outpixel = read_x[0] ? outpixel_x2[DWIDTH1*2-1:DWIDTH1] : outpixel_x2[DWIDTH:0]; + +hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH+1), .DWIDTH(DWIDTH1*4-1)) hq2x_out ( - .clk(clk), + .clock(clk), - .rdaddr(read_x), - .rdbuf(read_y), - .q(outpixel), + .rdaddress({read_x[AWIDTH+1:1],read_y[1]}), + .q(outpixel_x4), - .wraddr(wrout_addr2), - .wrbuf(wrout_addr1), .data(wrdata), + .wraddress(wrout_addr), .wren(wrout_en) ); +wire [DWIDTH:0] blend_result = HALF_DEPTH ? rgb2h(blend_result_pre) : blend_result_pre[DWIDTH:0]; + +reg [AWIDTH:0] offs; always @(posedge clk) begin - reg [AWIDTH:0] offs; reg old_reset_line; reg old_reset_frame; @@ -149,36 +142,33 @@ always @(posedge clk) begin if(ce_x4) begin pattern <= new_pattern; + if(read_x[0]) outpixel_x2 <= read_y[0] ? outpixel_x4[DWIDTH1*4-1:DWIDTH1*2] : outpixel_x4[DWIDTH1*2-1:0]; if(~&offs) begin - if (i == 0) begin - Curr2_addr1 <= prevbuf; - Curr2_addr2 <= offs; - end - if (i == 1) begin - Prev2 <= Curr2; - Curr2_addr1 <= curbuf; - Curr2_addr2 <= offs; - end - if (i == 2) begin + if (cyc == 1) begin + Prev2 <= Curr20; + Curr2 <= Curr21; Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel; wrpix <= inputpixel; wrin_addr2 <= offs; wrin_en <= 1; end - if (i == 3) begin + + case({cyc[1],^cyc}) + 0: wrdata[DWIDTH:0] <= blend_result; + 1: wrdata[DWIDTH1+DWIDTH:DWIDTH1] <= blend_result; + 2: wrdata[DWIDTH1*2+DWIDTH:DWIDTH1*2] <= blend_result; + 3: wrdata[DWIDTH1*3+DWIDTH:DWIDTH1*3] <= blend_result; + endcase + + if(cyc==3) begin offs <= offs + 1'd1; + wrout_addr <= {offs, curbuf}; + wrout_en <= 1; end - - if(HALF_DEPTH) wrdata <= rgb2h(blend_result); - else wrdata <= blend_result; - - wrout_addr1 <= {curbuf, i[1]}; - wrout_addr2 <= {offs, i[1]^i[0]}; - wrout_en <= 1; end - if(i==3) begin + if(cyc==3) begin nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]}; {A, G} <= {Prev0, Next0}; {B, F, H, D} <= {Prev1, Curr2, Next1, Curr0}; @@ -190,18 +180,22 @@ always @(posedge clk) begin {B, F, H, D} <= {F, H, D, B}; end - i <= i + 1'b1; + cyc <= cyc + 1'b1; if(old_reset_line && ~reset_line) begin old_reset_frame <= reset_frame; offs <= 0; - i <= 0; - y <= y + 1'd1; + cyc <= 0; + curbuf <= ~curbuf; prevbuf <= curbuf; + {Prev0, Prev1, Prev2, Curr0, Curr1, Curr2, Next0, Next1, Next2} <= '0; if(old_reset_frame & ~reset_frame) begin - y <= 0; + curbuf <= 0; prevbuf <= 0; end end + + if(~hblank & ~&read_x) read_x <= read_x + 1'd1; + if(hblank) read_x <= 0; old_reset_line <= reset_line; end @@ -216,8 +210,8 @@ module hq2x_in #(parameter LENGTH, parameter DWIDTH) input clk, input [AWIDTH:0] rdaddr, - input rdbuf, - output[DWIDTH:0] q, + input rdbuf0, rdbuf1, + output[DWIDTH:0] q0,q1, input [AWIDTH:0] wraddr, input wrbuf, @@ -225,40 +219,15 @@ module hq2x_in #(parameter LENGTH, parameter DWIDTH) input wren ); - localparam AWIDTH = `BITS_TO_FIT(LENGTH); - wire [DWIDTH:0] out[2]; - assign q = out[rdbuf]; + localparam AWIDTH = $clog2(LENGTH)-1; + wire [DWIDTH:0] out[2]; + assign q0 = out[rdbuf0]; + assign q1 = out[rdbuf1]; hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); endmodule - -module hq2x_out #(parameter LENGTH, parameter DWIDTH) -( - input clk, - - input [AWIDTH:0] rdaddr, - input [1:0] rdbuf, - output[DWIDTH:0] q, - - input [AWIDTH:0] wraddr, - input [1:0] wrbuf, - input [DWIDTH:0] data, - input wren -); - - localparam AWIDTH = `BITS_TO_FIT(LENGTH*2); - wire [DWIDTH:0] out[4]; - assign q = out[rdbuf]; - - hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); - hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); - hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf2(clk,data,rdaddr,wraddr,wren && (wrbuf == 2),out[2]); - hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf3(clk,data,rdaddr,wraddr,wren && (wrbuf == 3),out[3]); -endmodule - - module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH) ( input clock, diff --git a/sys/lpf48k.sv b/sys/lpf48k.sv index 2a32981..e6bab53 100644 --- a/sys/lpf48k.sv +++ b/sys/lpf48k.sv @@ -76,7 +76,7 @@ always @(posedge RESET or posedge CLK) begin end end -assign W_DATA = LPF_TAP_DATA[FF_ADDR] * IDATA; +assign W_DATA = LPF_TAP_DATA[FF_ADDR] * $signed(IDATA); always @(posedge RESET or posedge CLK) begin if (RESET) FF_INTEG <= 0; @@ -84,7 +84,7 @@ always @(posedge RESET or posedge CLK) begin begin if (CE) begin if (W_ADDR_END) FF_INTEG <= 0; - else FF_INTEG <= FF_INTEG + W_DATA; + else FF_INTEG <= $signed(FF_INTEG) + $signed(W_DATA); end end end diff --git a/sys/osd.v b/sys/osd.v index f6e8915..81939c6 100644 --- a/sys/osd.v +++ b/sys/osd.v @@ -13,7 +13,8 @@ module osd input [23:0] din, output [23:0] dout, input de_in, - output reg de_out + output reg de_out, + output reg osd_status ); parameter OSD_COLOR = 3'd4; @@ -23,21 +24,24 @@ parameter OSD_Y_OFFSET = 12'd0; localparam OSD_WIDTH = 12'd256; localparam OSD_HEIGHT = 12'd64; -reg osd_enable; -(* ramstyle = "no_rw_check" *) reg [7:0] osd_buffer[4096]; +reg osd_enable; +reg [7:0] osd_buffer[4096]; -reg highres = 0; reg info = 0; reg [8:0] infoh; reg [8:0] infow; reg [11:0] infox; reg [21:0] infoy; +reg [21:0] hrheight; always@(posedge clk_sys) begin reg [11:0] bcnt; reg [7:0] cmd; reg has_cmd; reg old_strobe; + reg highres = 0; + + hrheight <= info ? infoh : (OSD_HEIGHT<>1) + OSD_X_OFFSET - 2'd2); + if(h_cnt > {dsp_width, 2'b00}) begin v_cnt <= 0; - dsp_height <= v_cnt; - if(osd_enable) begin - if(v_cnt<320) begin - multiscan <= 0; - fheight <= hrheight; - finfoy <= infoy; - end - else if(v_cnt<640) begin - multiscan <= 1; - fheight <= hrheight << 1; - finfoy <= infoy << 1; - end - else if(v_cnt<960) begin - multiscan <= 2; - fheight <= hrheight + (hrheight<<1); - finfoy <= infoy + (infoy << 1); - end - else begin - multiscan <= 3; - fheight <= hrheight << 2; - finfoy <= infoy << 2; - end + osd_en <= (osd_en << 1) | osd_enable; + if(~osd_enable) osd_en <= 0; + + if(v_cnt<320) begin + multiscan <= 0; + v_osd_start <= info ? infoy : (((v_cnt-hrheight)>>1) + OSD_Y_OFFSET); + end + else if(v_cnt<640) begin + multiscan <= 1; + v_osd_start <= info ? (infoy<<1) : (((v_cnt-(hrheight<<1))>>1) + OSD_Y_OFFSET); + end + else if(v_cnt<960) begin + multiscan <= 2; + v_osd_start <= info ? (infoy + (infoy << 1)) : (((v_cnt-(hrheight + (hrheight<<1)))>>1) + OSD_Y_OFFSET); end else begin - fheight <= 0; + multiscan <= 3; + v_osd_start <= info ? (infoy<<2) : (((v_cnt-(hrheight<<2))>>1) + OSD_Y_OFFSET); end end - h_cnt <= 0; - + osd_div <= osd_div + 1'd1; if(osd_div == multiscan) begin osd_div <= 0; - osd_vcnt <= osd_vcnt + 1'd1; + if(~&osd_vcnt) osd_vcnt <= osd_vcnt + 1'd1; end if(v_osd_start == (v_cnt+1'b1)) {osd_div, osd_vcnt} <= 0; end - - osd_byte <= osd_buffer[{osd_vcnt[6:3], osd_hcnt[7:0]}]; + + osd_byte <= osd_buffer[{osd_vcnt[6:3], osd_hcnt[7:0]}]; + osd_pixel <= osd_byte[osd_vcnt[2:0]]; + osd_de[2:1] <= osd_de[1:0]; end end -// area in which OSD is being displayed -wire [21:0] h_osd_start = info ? infox : ((dsp_width - OSD_WIDTH)>>1) + OSD_X_OFFSET; -wire [21:0] h_osd_end = info ? (h_osd_start + infow) : (h_osd_start + OSD_WIDTH); -wire [21:0] v_osd_start = info ? finfoy : ((dsp_height- fheight)>>1) + OSD_Y_OFFSET; -wire [21:0] v_osd_end = v_osd_start + fheight; - -wire [21:0] osd_hcnt = h_cnt[21:0] - h_osd_start + 1'd1; - -wire osd_de = osd_enable && fheight && - (h_cnt >= h_osd_start) && (h_cnt < h_osd_end) && - (v_cnt >= v_osd_start) && (v_cnt < v_osd_end); - -wire osd_pixel = osd_byte[osd_vcnt[2:0]]; - reg [23:0] rdout; assign dout = rdout; - + always @(posedge clk_video) begin - rdout <= !osd_de ? din : {{osd_pixel, osd_pixel, OSD_COLOR[2], din[23:19]}, - {osd_pixel, osd_pixel, OSD_COLOR[1], din[15:11]}, - {osd_pixel, osd_pixel, OSD_COLOR[0], din[7:3]}}; + rdout <= ~osd_de[2] ? din : {{osd_pixel, osd_pixel, OSD_COLOR[2], din[23:19]}, + {osd_pixel, osd_pixel, OSD_COLOR[1], din[15:11]}, + {osd_pixel, osd_pixel, OSD_COLOR[0], din[7:3]}}; de_out <= de_in; end diff --git a/sys/pattern_vg.v b/sys/pattern_vg.v deleted file mode 100644 index 6379278..0000000 --- a/sys/pattern_vg.v +++ /dev/null @@ -1,120 +0,0 @@ -module pattern_vg -#( - parameter B=8, // number of bits per channel - X_BITS=13, - Y_BITS=13, - FRACTIONAL_BITS = 12 -) - -( - input reset, clk_in, - input wire [X_BITS-1:0] x, - input wire [Y_BITS-1:0] y, - input wire vn_in, hn_in, dn_in, - input wire [B-1:0] r_in, g_in, b_in, - output reg vn_out, hn_out, den_out, - output reg [B-1:0] r_out, g_out, b_out, - input wire [X_BITS-1:0] total_active_pix, - input wire [Y_BITS-1:0] total_active_lines, - input wire [7:0] pattern, - input wire [B+FRACTIONAL_BITS-1:0] ramp_step -); - -reg [B+FRACTIONAL_BITS-1:0] ramp_values; // 12-bit fractional end for ramp values - - -//wire bar_0 = y<90; -wire bar_1 = y>=90 & y<180; -wire bar_2 = y>=180 & y<270; -wire bar_3 = y>=270 & y<360; -wire bar_4 = y>=360 & y<450; -wire bar_5 = y>=450 & y<540; -wire bar_6 = y>=540 & y<630; -wire bar_7 = y>=630 & y<720; - - -wire red_enable = bar_1 | bar_3 | bar_5 | bar_7; -wire green_enable = bar_2 | bar_3 | bar_6 | bar_7; -wire blue_enable = bar_4 | bar_5 | bar_6 | bar_7; - -always @(posedge clk_in) - begin - vn_out <= vn_in; - hn_out <= hn_in; - den_out <= dn_in; - if (reset) - ramp_values <= 0; - else if (pattern == 8'b0) // no pattern - begin - r_out <= r_in; - g_out <= g_in; - b_out <= b_in; - end - else if (pattern == 8'b1) // border - begin - if (dn_in && ((y == 12'b0) || (x == 12'b0) || (x == total_active_pix - 1) || (y == total_active_lines - 1))) - begin - r_out <= 8'hFF; - g_out <= 8'hFF; - b_out <= 8'hFF; - end - else // Double-border (OzOnE)... - if (dn_in && ((y == 12'b0+20) || (x == 12'b0+20) || (x == total_active_pix - 1 - 20) || (y == total_active_lines - 1 - 20))) - begin - r_out <= 8'hD0; - g_out <= 8'hB0; - b_out <= 8'hB0; - end - else - begin - r_out <= r_in; - g_out <= g_in; - b_out <= b_in; - end - end - else if (pattern == 8'd2) // moireX - begin - if ((dn_in) && x[0] == 1'b1) - begin - r_out <= 8'hFF; - g_out <= 8'hFF; - b_out <= 8'hFF; - end - else - begin - r_out <= 8'b0; - g_out <= 8'b0; - b_out <= 8'b0; - end - end - else if (pattern == 8'd3) // moireY - begin - if ((dn_in) && y[0] == 1'b1) - begin - r_out <= 8'hFF; - g_out <= 8'hFF; - b_out <= 8'hFF; - end - else - begin - r_out <= 8'b0; - g_out <= 8'b0; - b_out <= 8'b0; - end - end - else if (pattern == 8'd4) // Simple RAMP - begin - r_out <= (red_enable) ? ramp_values[B+FRACTIONAL_BITS-1:FRACTIONAL_BITS] : 8'h00; - g_out <= (green_enable) ? ramp_values[B+FRACTIONAL_BITS-1:FRACTIONAL_BITS] : 8'h00; - b_out <= (blue_enable) ? ramp_values[B+FRACTIONAL_BITS-1:FRACTIONAL_BITS] : 8'h00; - - if ((x == total_active_pix - 1) && (dn_in)) - ramp_values <= 0; - else if ((x == 0) && (dn_in)) - ramp_values <= ramp_step; - else if (dn_in) - ramp_values <= ramp_values + ramp_step; - end -end - -endmodule diff --git a/sys/pll.qip b/sys/pll.qip index 133b0ae..411167f 100644 --- a/sys/pll.qip +++ b/sys/pll.qip @@ -23,8 +23,8 @@ set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_DESCR set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGVidWdfcHJpbnRfb3V0cHV0::ZmFsc2U=::ZGVidWdfcHJpbnRfb3V0cHV0" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k::ZmFsc2U=::ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGV2aWNl::NUNFQkEyRjE3QTc=::ZGV2aWNl" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9tb2Rl::SW50ZWdlci1OIFBMTA==::UExMIE1vZGU=" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::ZmFsc2U=::ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9tb2Rl::RnJhY3Rpb25hbC1OIFBMTA==::UExMIE1vZGU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::dHJ1ZQ==::ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmVyZW5jZV9jbG9ja19mcmVxdWVuY3k=::NTAuMA==::UmVmZXJlbmNlIENsb2NrIEZyZXF1ZW5jeQ==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==::NTAuMCBNSHo=::cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2NoYW5uZWxfc3BhY2luZw==::MC4w::Q2hhbm5lbCBTcGFjaW5n" @@ -35,17 +35,17 @@ set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAM set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3BlcmF0aW9uX21vZGU=::ZGlyZWN0::b3BlcmF0aW9uX21vZGU=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9sb2NrZWQ=::dHJ1ZQ==::RW5hYmxlIGxvY2tlZCBvdXRwdXQgcG9ydA==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Fkdl9wYXJhbXM=::ZmFsc2U=::RW5hYmxlIHBoeXNpY2FsIG91dHB1dCBjbG9jayBwYXJhbWV0ZXJz" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::Mg==::TnVtYmVyIE9mIENsb2Nrcw==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::Mg==::bnVtYmVyX29mX2Nsb2Nrcw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::NA==::TnVtYmVyIE9mIENsb2Nrcw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::NA==::bnVtYmVyX29mX2Nsb2Nrcw==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX211bHRpcGx5X2ZhY3Rvcg==::MQ==::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjA=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kw::MTI4LjA=::RGVzaXJlZCBGcmVxdWVuY3k=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzA=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::NjQ=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::MjU=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::MTc=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::Mzk1MTM2ODAyMw==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::Nw==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MA==::MA==::UGhhc2UgU2hpZnQ=" @@ -53,23 +53,23 @@ set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAM set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDA=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUw::NTA=::RHV0eSBDeWNsZQ==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kx::MzIuMA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kx::MTI4LjA=::RGVzaXJlZCBGcmVxdWVuY3k=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::NjQ=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::MTAw::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::MTc=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::Mzk1MTM2ODAyMw==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::Nw==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MQ==::LTQzNTA=::UGhhc2UgU2hpZnQ=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE=::MTgwLjA=::UGhhc2UgU2hpZnQ=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUx::NTA=::RHV0eSBDeWNsZQ==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjI=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3ky::NTAuMA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3ky::MzIuMA==::RGVzaXJlZCBGcmVxdWVuY3k=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzI=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iy::NjQ=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjI=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMg==::NjU=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iy::MTc=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjI=::Mzk1MTM2ODAyMw==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMg==::Mjg=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mg==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mg==::MA==::UGhhc2UgU2hpZnQ=" @@ -77,11 +77,11 @@ set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAM set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDI=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUy::NTA=::RHV0eSBDeWNsZQ==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjM=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kz::NTAuMTc1::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kz::NTAuMA==::RGVzaXJlZCBGcmVxdWVuY3k=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzM=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iz::MTI4::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjM=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMw==::MTMw::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iz::MTc=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjM=::Mzk1MTM2ODAyMw==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMw==::MTg=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mw==::MA==::UGhhc2UgU2hpZnQ=" @@ -91,9 +91,9 @@ set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAM set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjQ=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::NDguMA==::RGVzaXJlZCBGcmVxdWVuY3k=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzQ=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MTI4::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjQ=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MTM1::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NA==::MA==::UGhhc2UgU2hpZnQ=" @@ -256,16 +256,16 @@ set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAM set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE3::MC4w::UGhhc2UgU2hpZnQ=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE3::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNw==::NTA=::RHV0eSBDeWNsZQ==" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=::MTI4LjAwMDAwMCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=::MTI3Ljk5OTk5OSBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQw::MCBwcw==::cGhhc2Vfc2hpZnQw" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTA=::NTA=::ZHV0eV9jeWNsZTA=" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=::MzIuMDAwMDAwIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::MCBwcw==::cGhhc2Vfc2hpZnQx" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=::MTI3Ljk5OTk5OCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::LTQzMjQgcHM=::cGhhc2Vfc2hpZnQx" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE=::NTA=::ZHV0eV9jeWNsZTE=" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=::MzEuOTk5OTk5IE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQy::MCBwcw==::cGhhc2Vfc2hpZnQy" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTI=::NTA=::ZHV0eV9jeWNsZTI=" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::NDkuNzc3Nzc2IE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQz::MCBwcw==::cGhhc2Vfc2hpZnQz" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTM=::NTA=::ZHV0eV9jeWNsZTM=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=" @@ -317,8 +317,8 @@ set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAM set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3Bob3V0X3BvcnRz::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBQTEwgRFBBIG91dHB1dCBwb3J0" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGxsX3R5cGU=::R2VuZXJhbA==::UExMIFRZUEU=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGxsX3N1YnR5cGU=::R2VuZXJhbA==::UExMIFNVQlRZUEU=" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTEgSGkgRGl2aWRlLEMtQ291bnRlci0xIExvdyBEaXZpZGUsQy1Db3VudGVyLTEgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0xIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTEgSW5wdXQgU291cmNlLEMtQ291bnRlci0xIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTEgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz" -set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::MzIsMzIsMywyLGZhbHNlLGZhbHNlLGZhbHNlLHRydWUsMywyLDEsMCxwaF9tdXhfY2xrLGZhbHNlLHRydWUsMTAsMTAsMSwwLHBoX211eF9jbGssZmFsc2UsZmFsc2UsMSwyMCw2MDAwLDY0MC4wIE1IeiwxLG5vbmUsZ2xiLG1fY250LHBoX211eF9jbGssdHJ1ZQ==::UGFyYW1ldGVyIFZhbHVlcw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTEgSGkgRGl2aWRlLEMtQ291bnRlci0xIExvdyBEaXZpZGUsQy1Db3VudGVyLTEgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0xIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTEgSW5wdXQgU291cmNlLEMtQ291bnRlci0xIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTEgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTIgSGkgRGl2aWRlLEMtQ291bnRlci0yIExvdyBEaXZpZGUsQy1Db3VudGVyLTIgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0yIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTIgSW5wdXQgU291cmNlLEMtQ291bnRlci0yIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTMgSGkgRGl2aWRlLEMtQ291bnRlci0zIExvdyBEaXZpZGUsQy1Db3VudGVyLTMgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0zIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTMgSW5wdXQgU291cmNlLEMtQ291bnRlci0zIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTMgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::OSw4LDI1NiwyNTYsZmFsc2UsdHJ1ZSx0cnVlLGZhbHNlLDQsMywxLDAscGhfbXV4X2NsayxmYWxzZSx0cnVlLDQsMyw0LDEscGhfbXV4X2NsayxmYWxzZSx0cnVlLDE0LDE0LDEsMCxwaF9tdXhfY2xrLGZhbHNlLGZhbHNlLDksOSwxLDAscGhfbXV4X2NsayxmYWxzZSxmYWxzZSwxLDIwLDQwMDAsODk1Ljk5OTk3OCBNSHosMzk1MTM2ODAyMyxub25lLGdsYixtX2NudCxwaF9tdXhfY2xrLHRydWU=::UGFyYW1ldGVyIFZhbHVlcw==" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX21pZl9nZW5lcmF0ZQ==::ZmFsc2U=::R2VuZXJhdGUgTUlGIGZpbGU=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9taWZfZHBz::ZmFsc2U=::RW5hYmxlIER5bmFtaWMgUGhhc2UgU2hpZnQgZm9yIE1JRiBzdHJlYW1pbmc=" set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19jbnRy::QzA=::RFBTIENvdW50ZXIgU2VsZWN0aW9u" diff --git a/sys/pll.v b/sys/pll.v index 55b8f2e..63e648b 100644 --- a/sys/pll.v +++ b/sys/pll.v @@ -2,7 +2,7 @@ // GENERATION: XML // pll.v -// Generated using ACDS version 17.0 598 +// Generated using ACDS version 17.0 602 `timescale 1 ps / 1 ps module pll ( @@ -10,6 +10,8 @@ module pll ( input wire rst, // reset.reset output wire outclk_0, // outclk0.clk output wire outclk_1, // outclk1.clk + output wire outclk_2, // outclk2.clk + output wire outclk_3, // outclk3.clk output wire locked // locked.export ); @@ -18,6 +20,8 @@ module pll ( .rst (rst), // reset.reset .outclk_0 (outclk_0), // outclk0.clk .outclk_1 (outclk_1), // outclk1.clk + .outclk_2 (outclk_2), // outclk2.clk + .outclk_3 (outclk_3), // outclk3.clk .locked (locked) // locked.export ); @@ -28,7 +32,7 @@ endmodule // ************************************************************ // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! // ************************************************************ -// Copyright (C) 1991-2017 Altera Corporation +// Copyright (C) 1991-2019 Altera Corporation // Any megafunction design, and related net list (encrypted or decrypted), // support information, device programming or simulation file, and any other // associated documentation or information provided by Altera or a partner @@ -54,7 +58,7 @@ endmodule // Retrieval info: // Retrieval info: // Retrieval info: -// Retrieval info: +// Retrieval info: // Retrieval info: // Retrieval info: // Retrieval info: @@ -63,7 +67,7 @@ endmodule // Retrieval info: // Retrieval info: // Retrieval info: -// Retrieval info: +// Retrieval info: // Retrieval info: // Retrieval info: // Retrieval info: @@ -77,16 +81,16 @@ endmodule // Retrieval info: // Retrieval info: // Retrieval info: -// Retrieval info: +// Retrieval info: // Retrieval info: // Retrieval info: // Retrieval info: -// Retrieval info: +// Retrieval info: // Retrieval info: // Retrieval info: // Retrieval info: // Retrieval info: -// Retrieval info: +// Retrieval info: // Retrieval info: // Retrieval info: // Retrieval info: @@ -95,7 +99,7 @@ endmodule // Retrieval info: // Retrieval info: // Retrieval info: -// Retrieval info: +// Retrieval info: // Retrieval info: // Retrieval info: // Retrieval info: diff --git a/sys/pll/pll_0002.qip b/sys/pll/pll_0002.qip index aec45eb..9f8ded1 100644 --- a/sys/pll/pll_0002.qip +++ b/sys/pll/pll_0002.qip @@ -1,4 +1,4 @@ set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" - +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_0002*|altera_pll:altera_pll_i*|*" set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" diff --git a/sys/pll/pll_0002.v b/sys/pll/pll_0002.v index 64bc2aa..28b4167 100644 --- a/sys/pll/pll_0002.v +++ b/sys/pll/pll_0002.v @@ -13,25 +13,31 @@ module pll_0002( // interface 'outclk1' output wire outclk_1, + // interface 'outclk2' + output wire outclk_2, + + // interface 'outclk3' + output wire outclk_3, + // interface 'locked' output wire locked ); altera_pll #( - .fractional_vco_multiplier("false"), + .fractional_vco_multiplier("true"), .reference_clock_frequency("50.0 MHz"), .operation_mode("direct"), - .number_of_clocks(2), - .output_clock_frequency0("128.000000 MHz"), + .number_of_clocks(4), + .output_clock_frequency0("127.999999 MHz"), .phase_shift0("0 ps"), .duty_cycle0(50), - .output_clock_frequency1("32.000000 MHz"), - .phase_shift1("0 ps"), + .output_clock_frequency1("127.999998 MHz"), + .phase_shift1("-4324 ps"), .duty_cycle1(50), - .output_clock_frequency2("0 MHz"), + .output_clock_frequency2("31.999999 MHz"), .phase_shift2("0 ps"), .duty_cycle2(50), - .output_clock_frequency3("0 MHz"), + .output_clock_frequency3("49.777776 MHz"), .phase_shift3("0 ps"), .duty_cycle3(50), .output_clock_frequency4("0 MHz"), @@ -80,7 +86,7 @@ module pll_0002( .pll_subtype("General") ) altera_pll_i ( .rst (rst), - .outclk ({outclk_1, outclk_0}), + .outclk ({outclk_3, outclk_2, outclk_1, outclk_0}), .locked (locked), .fboutclk ( ), .fbclk (1'b0), diff --git a/sys/pll_hdmi/pll_hdmi_0002_q13.qip b/sys/pll_hdmi/pll_hdmi_0002_q13.qip new file mode 100644 index 0000000..fb8053d --- /dev/null +++ b/sys/pll_hdmi/pll_hdmi_0002_q13.qip @@ -0,0 +1,4 @@ +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" diff --git a/sys/pll_hdmi_adj.vhd b/sys/pll_hdmi_adj.vhd new file mode 100644 index 0000000..2065774 --- /dev/null +++ b/sys/pll_hdmi_adj.vhd @@ -0,0 +1,268 @@ +-------------------------------------------------------------------------------- +-- HDMI PLL Adjust +-------------------------------------------------------------------------------- + +-- Changes the HDMI PLL frequency according to the scaler suggestions. +-------------------------------------------- +-- LLTUNE : +-- 15 : Toggle +-- 14 : Unused +-- 13 : Sign phase difference +-- 12:8 : Phase difference. Log (0=Large 31=Small) +-- 7 : 1=Interlaced video 0=Progressive +-- 6 : Interlaced video field +-- 5 : Sign period difference. +-- 4:0 : Period difference. Log (0=Large 31=Small) + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE ieee.numeric_std.ALL; + +ENTITY pll_hdmi_adj IS + PORT ( + -- Scaler + llena : IN std_logic; -- 0=Disabled 1=Enabled + lltune : IN unsigned(15 DOWNTO 0); -- Outputs from scaler + + locked : OUT std_logic; + + -- Signals from reconfig commands + i_waitrequest : OUT std_logic; + i_write : IN std_logic; + i_address : IN unsigned(5 DOWNTO 0); + i_writedata : IN unsigned(31 DOWNTO 0); + + -- Outputs to PLL_HDMI_CFG + o_waitrequest : IN std_logic; + o_write : OUT std_logic; + o_address : OUT unsigned(5 DOWNTO 0); + o_writedata : OUT unsigned(31 DOWNTO 0); + + ------------------------------------ + clk : IN std_logic; + reset_na : IN std_logic + ); + +BEGIN + + +END ENTITY pll_hdmi_adj; + +--############################################################################## + +ARCHITECTURE rtl OF pll_hdmi_adj IS + SIGNAL pwrite : std_logic; + SIGNAL paddress : unsigned(5 DOWNTO 0); + SIGNAL pdata : unsigned(31 DOWNTO 0); + TYPE enum_state IS (sIDLE,sW1,sW2,sW3,sW4,sW5,sW6); + SIGNAL state : enum_state; + SIGNAL lltune_sync,lltune_sync2,lltune_sync3 : unsigned(15 DOWNTO 0); + SIGNAL mfrac,mfrac_mem,mfrac_ref,diff : unsigned(40 DOWNTO 0); + SIGNAL mul : unsigned(15 DOWNTO 0); + SIGNAL sign,sign_pre : std_logic; + SIGNAL up,modo,phm,dir : std_logic; + SIGNAL cpt : natural RANGE 0 TO 3; + SIGNAL col : natural RANGE 0 TO 15; +BEGIN + ---------------------------------------------------------------------------- + -- 000010 : Start reg "Write either 0 or 1 to start fractional PLL reconf. + -- 000100 : M counter + -- 000111 : M counter Fractional Value K + + Comb:PROCESS(i_write,i_address, + i_writedata,pwrite,paddress,pdata) IS + BEGIN + IF i_write='1' THEN + o_write <=i_write; + o_address <=i_address; + o_writedata <=i_writedata; + ELSE + o_write <=pwrite; + o_address <=paddress; + o_writedata<=pdata; + END IF; + END PROCESS Comb; + + i_waitrequest<=o_waitrequest WHEN state=sIDLE ELSE '0'; + + ---------------------------------------------------------------------------- + Schmurtz:PROCESS(clk,reset_na) IS + VARIABLE off_v,ofp_v : natural RANGE 0 TO 63; + VARIABLE diff_v : unsigned(40 DOWNTO 0); + VARIABLE mulco : unsigned(15 DOWNTO 0); + VARIABLE up_v,sign_v : std_logic; + BEGIN + IF reset_na='0' THEN + modo<='0'; + state<=sIDLE; + ELSIF rising_edge(clk) THEN + ------------------------------------------------------ + -- Snoop accesses to PLL reconfiguration + IF i_address="000100" AND i_write='1' THEN + mfrac (40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + + ('0' & i_writedata(7 DOWNTO 0)); + mfrac_ref(40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + + ('0' & i_writedata(7 DOWNTO 0)); + mfrac_mem(40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + + ('0' & i_writedata(7 DOWNTO 0)); + mul<=i_writedata(15 DOWNTO 0); + modo<='1'; + END IF; + + IF i_address="000111" AND i_write='1' THEN + mfrac (31 DOWNTO 0)<=i_writedata; + mfrac_ref(31 DOWNTO 0)<=i_writedata; + mfrac_mem(31 DOWNTO 0)<=i_writedata; + modo<='1'; + END IF; + + ------------------------------------------------------ + -- Tuning + lltune_sync<=lltune; -- + lltune_sync2<=lltune_sync; + lltune_sync3<=lltune_sync2; + + off_v:=to_integer('0' & lltune_sync(4 DOWNTO 0)); + IF off_v<4 THEN off_v:=4; END IF; + ofp_v:=to_integer('0' & lltune_sync(12 DOWNTO 8)); + IF ofp_v<3 THEN ofp_v:=3; END IF; + + IF off_v>=18 AND ofp_v>=18 THEN + locked<=llena; + ELSE + locked<='0'; + END IF; + + up_v:='0'; + IF lltune_sync3(15)/=lltune_sync2(15) THEN + cpt<=cpt+1; + IF cpt=3 THEN cpt<=0; END IF; + IF llena='0' THEN + -- Recover original freq when disabling low lag mode + cpt<=0; + col<=0; + IF modo='1' THEN + mfrac<=mfrac_mem; + mfrac_ref<=mfrac_mem; + up<='1'; + modo<='0'; + END IF; + + ELSIF phm='0' AND cpt=0 THEN + -- Frequency adjust + sign_v:=lltune_sync(5); + IF col<10 THEN col<=col+1; END IF; + IF off_v>=16 AND col>=10 THEN + phm<='1'; + col<=0; + ELSE + off_v:=off_v+1; + IF off_v>17 THEN + off_v:=off_v + 3; + END IF; + up_v:='1'; + up<='1'; + END IF; + + ELSIF cpt=0 THEN + -- Phase adjust + sign_v:=NOT lltune_sync(13); + col<=col+1; + IF col>=10 THEN + phm<='0'; + up_v:='1'; + off_v:=31; + col<=0; + ELSE + off_v:=ofp_v + 1; + IF ofp_v>7 THEN + off_v:=off_v + 1; + END IF; + IF ofp_v>14 THEN + off_v:=off_v + 2; + END IF; + IF ofp_v>17 THEN + off_v:=off_v + 3; + END IF; + up_v:='1'; + END IF; + up<='1'; + END IF; + END IF; + + diff_v:=shift_right(mfrac_ref,off_v); + IF sign_v='0' THEN + diff_v:=mfrac_ref + diff_v; + ELSE + diff_v:=mfrac_ref - diff_v; + END IF; + + IF up_v='1' THEN + mfrac<=diff_v; + END IF; + + IF up_v='1' AND phm='0' THEN + mfrac_ref<=diff_v; + END IF; + + ------------------------------------------------------ + -- Update PLL registers + mulco:=mfrac(40 DOWNTO 33) & (mfrac(40 DOWNTO 33) + ('0' & mfrac(32))); + + CASE state IS + WHEN sIDLE => + pwrite<='0'; + IF up='1' THEN + up<='0'; + IF mulco/=mul THEN + state<=sW1; + ELSE + state<=sW3; + END IF; + END IF; + + WHEN sW1 => -- Change M multiplier + mul<=mulco; + pdata<=x"0000" & mulco; + paddress<="000100"; + pwrite<='1'; + state<=sW2; + + WHEN sW2 => + IF pwrite='1' AND o_waitrequest='0' THEN + state<=sW3; + pwrite<='0'; + END IF; + + WHEN sW3 => -- Change M fractional value + pdata<=mfrac(31 DOWNTO 0); + paddress<="000111"; + pwrite<='1'; + state<=sW4; + + WHEN sW4 => + IF pwrite='1' AND o_waitrequest='0' THEN + state<=sW5; + pwrite<='0'; + END IF; + + WHEN sW5 => + pdata<=x"0000_0001"; + paddress<="000010"; + pwrite<='1'; + state<=sW6; + + WHEN sW6 => + IF pwrite='1' AND o_waitrequest='0' THEN + pwrite<='0'; + state<=sIDLE; + END IF; + END CASE; + + END IF; + END PROCESS Schmurtz; + + ---------------------------------------------------------------------------- + +END ARCHITECTURE rtl; + diff --git a/sys/pll_hdmi_q13.qip b/sys/pll_hdmi_q13.qip new file mode 100644 index 0000000..705d514 --- /dev/null +++ b/sys/pll_hdmi_q13.qip @@ -0,0 +1,13 @@ +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_VERSION "13.1" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll_hdmi" -name MISC_FILE [file join $::quartus(qip_path) "pll_hdmi.cmp"] +set_global_assignment -name SYNTHESIS_ONLY_QIP ON + +set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi.v"] +set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002.v"] +set_global_assignment -library "pll_hdmi" -name QIP_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002_q13.qip"] + +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_VERSION "13.1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" diff --git a/sys/scandoubler.v b/sys/scandoubler.v index e2b15c7..46274f5 100644 --- a/sys/scandoubler.v +++ b/sys/scandoubler.v @@ -31,8 +31,8 @@ module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) // shifter video interface input hs_in, input vs_in, - input hb_in, - input vb_in, + input hb_in, + input vb_in, input [DWIDTH:0] r_in, input [DWIDTH:0] g_in, @@ -42,8 +42,8 @@ module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) // output interface output reg hs_out, output vs_out, - output hb_out, - output vb_out, + output hb_out, + output vb_out, output [DWIDTH:0] r_out, output [DWIDTH:0] g_out, output [DWIDTH:0] b_out @@ -53,17 +53,16 @@ module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) localparam DWIDTH = HALF_DEPTH ? 3 : 7; assign vs_out = vso[3]; -assign ce_pix_out = ce_x4; +assign ce_pix_out = hq2x ? ce_x4 : ce_x2; //Compensate picture shift after HQ2x -assign vb_out = vbo[2]; -assign hb_out = &hbo[5:4]; +assign vb_out = vbo[2]; +assign hb_out = hbo[6]; reg [7:0] pix_len = 0; wire [7:0] pl = pix_len + 1'b1; -reg ce_x1, ce_x4; -reg req_line_reset; +reg ce_x1, ce_x4, ce_x2; always @(negedge clk_sys) begin reg old_ce; reg [2:0] ce_cnt; @@ -74,6 +73,7 @@ always @(negedge clk_sys) begin if(~&pix_len) pix_len <= pix_len + 1'd1; ce_x4 <= 0; + ce_x2 <= 0; ce_x1 <= 0; // use such odd comparison to place ce_x4 evenly if master clock isn't multiple 4. @@ -81,19 +81,20 @@ always @(negedge clk_sys) begin ce_x4 <= 1; end + if(pl == pixsz2) begin + ce_x2 <= 1; + end + if(~old_ce & ce_pix) begin pixsz2 <= {1'b0, pl[7:1]}; pixsz4 <= {2'b00, pl[7:2]}; ce_x1 <= 1; + ce_x2 <= 1; ce_x4 <= 1; pix_len <= 0; - req_line_reset <= 0; - - if(hb_in) req_line_reset <= 1; end end -localparam AWIDTH = `BITS_TO_FIT(LENGTH); Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x ( .clk(clk_sys), @@ -104,14 +105,13 @@ Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x .reset_frame(vs_in), .reset_line(req_line_reset), .read_y(sd_line), - .read_x(sd_h), + .hblank(hbo[0]&hbo[4]), .outpixel({b_out,g_out,r_out}) ); -reg [10:0] sd_h; reg [1:0] sd_line; reg [2:0] vbo; -reg [5:0] hbo; +reg [6:0] hbo; reg [DWIDTH:0] r_d; reg [DWIDTH:0] g_d; @@ -119,12 +119,13 @@ reg [DWIDTH:0] b_d; reg [3:0] vso; +reg req_line_reset; always @(posedge clk_sys) begin reg [11:0] hs_max,hs_rise; reg [10:0] hcnt; reg [11:0] sd_hcnt; - reg [11:0] hde_start, hde_end; + reg [11:0] hde_start, hde_end; reg hs, hs2, vs, hb; @@ -132,6 +133,8 @@ always @(posedge clk_sys) begin hs <= hs_in; hb <= hb_in; + req_line_reset <= hb_in; + r_d <= r_in; g_d <= g_in; b_d <= b_in; @@ -139,9 +142,9 @@ always @(posedge clk_sys) begin if(hb && !hb_in) begin hde_start <= {hcnt,1'b0}; vbo <= {vbo[1:0], vb_in}; - end - if(!hb && hb_in) hde_end <= {hcnt,1'b0}; - + end + if(!hb && hb_in) hde_end <= {hcnt,1'b0}; + // falling edge of hsync indicates start of line if(hs && !hs_in) begin vso <= (vso<<1) | vs_in; @@ -160,11 +163,10 @@ always @(posedge clk_sys) begin if(ce_x4) begin hs2 <= hs_in; - hbo[5:1] <= hbo[4:0]; + hbo[6:1] <= hbo[5:0]; // output counter synchronous to input and at twice the rate sd_hcnt <= sd_hcnt + 1'd1; - if(~&hbo) sd_h <= sd_h + 1'd1; if(hs2 && !hs_in) sd_hcnt <= hs_max; if(sd_hcnt == hs_max) sd_hcnt <= 0; @@ -172,13 +174,12 @@ always @(posedge clk_sys) begin //prepare to read in advance if(sd_hcnt == (hde_start-2)) begin - sd_h <= 0; sd_line <= sd_line + 1'd1; end - if(sd_hcnt == hde_start) hbo[0] <= 0; - if(sd_hcnt == hde_end) hbo[0] <= 1; - + if(sd_hcnt == hde_start) hbo[0] <= 0; + if(sd_hcnt == hde_end) hbo[0] <= 1; + // replicate horizontal sync at twice the speed if(sd_hcnt == hs_max) hs_out <= 0; if(sd_hcnt == hs_rise) hs_out <= 1; diff --git a/sys/scanlines.v b/sys/scanlines.v new file mode 100644 index 0000000..96aa6e3 --- /dev/null +++ b/sys/scanlines.v @@ -0,0 +1,52 @@ +module scanlines #(parameter v2=0) +( + input clk, + + input [1:0] scanlines, + input [23:0] din, + output reg [23:0] dout, + input hs,vs +); + +reg [1:0] scanline; +always @(posedge clk) begin + reg old_hs, old_vs; + + old_hs <= hs; + old_vs <= vs; + + if(old_hs && ~hs) begin + if(v2) begin + scanline <= scanline + 1'd1; + if (scanline == scanlines) scanline <= 0; + end + else scanline <= scanline ^ scanlines; + end + if(old_vs && ~vs) scanline <= 0; +end + +wire [7:0] r,g,b; +assign {r,g,b} = din; + +always @(*) begin + case(scanline) + 1: // reduce 25% = 1/2 + 1/4 + dout = {{1'b0, r[7:1]} + {2'b00, r[7:2]}, + {1'b0, g[7:1]} + {2'b00, g[7:2]}, + {1'b0, b[7:1]} + {2'b00, b[7:2]}}; + + 2: // reduce 50% = 1/2 + dout = {{1'b0, r[7:1]}, + {1'b0, g[7:1]}, + {1'b0, b[7:1]}}; + + 3: // reduce 75% = 1/4 + dout = {{2'b00, r[7:2]}, + {2'b00, g[7:2]}, + {2'b00, b[7:2]}}; + + default: dout = {r,g,b}; + endcase +end + +endmodule diff --git a/sys/sd_card.v b/sys/sd_card.v new file mode 100644 index 0000000..3761a7e --- /dev/null +++ b/sys/sd_card.v @@ -0,0 +1,538 @@ +// +// sd_card.v +// +// Copyright (c) 2014 Till Harbaum +// Copyright (c) 2015-2018 Sorgelig +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the Lesser GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file 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, see . +// +// http://elm-chan.org/docs/mmc/mmc_e.html +// +///////////////////////////////////////////////////////////////////////// + +// +// Made module syncrhronous. Total code refactoring. (Sorgelig) +// clk_spi must be at least 4 x sck for proper work. + +module sd_card +( + input clk_sys, + input reset, + + input sdhc, + + output [31:0] sd_lba, + output reg sd_rd, + output reg sd_wr, + input sd_ack, + input sd_ack_conf, + + input [8:0] sd_buff_addr, + input [7:0] sd_buff_dout, + output [7:0] sd_buff_din, + input sd_buff_wr, + + // SPI interface + input clk_spi, + + input ss, + input sck, + input mosi, + output reg miso +); + +assign sd_lba = sdhc ? lba : {9'd0, lba[31:9]}; + +wire[31:0] OCR = { 1'b1, sdhc, 30'd0 }; // bit30 = 1 -> high capaciry card (sdhc) // bit31 = 0 -> card power up finished +wire [7:0] READ_DATA_TOKEN = 8'hfe; +wire [7:0] WRITE_DATA_RESPONSE = 8'h05; + +// number of bytes to wait after a command before sending the reply +localparam NCR=3; + +localparam RD_STATE_IDLE = 0; +localparam RD_STATE_WAIT_IO = 1; +localparam RD_STATE_SEND_TOKEN = 2; +localparam RD_STATE_SEND_DATA = 3; +localparam RD_STATE_WAIT_M = 4; + +localparam WR_STATE_IDLE = 0; +localparam WR_STATE_EXP_DTOKEN = 1; +localparam WR_STATE_RECV_DATA = 2; +localparam WR_STATE_RECV_CRC0 = 3; +localparam WR_STATE_RECV_CRC1 = 4; +localparam WR_STATE_SEND_DRESP = 5; +localparam WR_STATE_BUSY = 6; + +sdbuf buffer +( + .clock_a(clk_sys), + .address_a(sd_buff_addr), + .data_a(sd_buff_dout), + .wren_a(sd_ack & sd_buff_wr), + .q_a(sd_buff_din), + + .clock_b(clk_spi), + .address_b(buffer_ptr), + .data_b(buffer_din), + .wren_b(buffer_wr), + .q_b(buffer_dout) +); + +sdbuf conf +( + .clock_a(clk_sys), + .address_a(sd_buff_addr), + .data_a(sd_buff_dout), + .wren_a(sd_ack_conf & sd_buff_wr), + + .clock_b(clk_spi), + .address_b(buffer_ptr), + .q_b(config_dout) +); + +reg [31:0] lba, new_lba; +reg [8:0] buffer_ptr; +reg [7:0] buffer_din; +wire [7:0] buffer_dout; +wire [7:0] config_dout; +reg buffer_wr; + +always @(posedge clk_spi) begin + reg [2:0] read_state; + reg [2:0] write_state; + reg [6:0] sbuf; + reg cmd55; + reg [7:0] cmd; + reg [2:0] bit_cnt; + reg [3:0] byte_cnt; + reg [7:0] reply; + reg [7:0] reply0, reply1, reply2, reply3; + reg [3:0] reply_len; + reg tx_finish; + reg rx_finish; + reg old_sck; + reg synced; + reg [5:0] ack; + reg io_ack; + reg [4:0] idle_cnt = 0; + reg [2:0] wait_m_cnt; + + if(buffer_wr & ~&buffer_ptr) buffer_ptr <= buffer_ptr + 1'd1; + buffer_wr <= 0; + + ack <= {ack[4:0], sd_ack}; + if(ack[5:4] == 2'b10) io_ack <= 1; + if(ack[5:4] == 2'b01) {sd_rd,sd_wr} <= 0; + + old_sck <= sck; + + if(~ss) idle_cnt <= 31; + else if(~old_sck && sck && idle_cnt) idle_cnt <= idle_cnt - 1'd1; + + if(reset || !idle_cnt) begin + bit_cnt <= 0; + byte_cnt <= 15; + synced <= 0; + miso <= 1; + sbuf <= 7'b1111111; + tx_finish <= 0; + rx_finish <= 0; + read_state <= RD_STATE_IDLE; + write_state <= WR_STATE_IDLE; + end + + if(old_sck & ~sck & ~ss) begin + tx_finish <= 0; + miso <= 1; // default: send 1's (busy/wait) + + if(byte_cnt == 5+NCR) begin + miso <= reply[~bit_cnt]; + + if(bit_cnt == 7) begin + // these three commands all have a reply_len of 0 and will thus + // not send more than a single reply byte + + // CMD9: SEND_CSD + // CMD10: SEND_CID + if((cmd == 'h49) | (cmd == 'h4a)) + read_state <= RD_STATE_SEND_TOKEN; // jump directly to data transmission + + // CMD17/CMD18 + if((cmd == 'h51) | (cmd == 'h52)) begin + io_ack <= 0; + read_state <= RD_STATE_WAIT_IO; // start waiting for data from io controller + lba <= new_lba; + sd_rd <= 1; // trigger request to io controller + end + end + end + else if((reply_len > 0) && (byte_cnt == 5+NCR+1)) miso <= reply0[~bit_cnt]; + else if((reply_len > 1) && (byte_cnt == 5+NCR+2)) miso <= reply1[~bit_cnt]; + else if((reply_len > 2) && (byte_cnt == 5+NCR+3)) miso <= reply2[~bit_cnt]; + else if((reply_len > 3) && (byte_cnt == 5+NCR+4)) miso <= reply3[~bit_cnt]; + else begin + if(byte_cnt > 5+NCR && read_state==RD_STATE_IDLE && write_state==WR_STATE_IDLE) tx_finish <= 1; + end + + // ---------- read state machine processing ------------- + + case(read_state) + RD_STATE_IDLE: ; // do nothing + + + // waiting for io controller to return data + RD_STATE_WAIT_IO: begin + if(io_ack & (bit_cnt == 7)) read_state <= RD_STATE_SEND_TOKEN; + end + + // send data token + RD_STATE_SEND_TOKEN: begin + miso <= READ_DATA_TOKEN[~bit_cnt]; + + if(bit_cnt == 7) begin + read_state <= RD_STATE_SEND_DATA; // next: send data + buffer_ptr <= 0; + if(cmd == 'h49) buffer_ptr <= 16; + end + end + + // send data + RD_STATE_SEND_DATA: begin + + miso <= ((cmd == 'h49) | (cmd == 'h4A)) ? config_dout[~bit_cnt] : buffer_dout[~bit_cnt]; + + if(bit_cnt == 7) begin + + // sent 512 sector data bytes? + if((cmd == 'h51) & &buffer_ptr) read_state <= RD_STATE_IDLE; + else if((cmd == 'h52) & &buffer_ptr) begin + read_state <= RD_STATE_WAIT_M; + wait_m_cnt <= 0; + end + + // sent 16 cid/csd data bytes? + else if(((cmd == 'h49) | (cmd == 'h4a)) & (&buffer_ptr[3:0])) read_state <= RD_STATE_IDLE; + + // not done yet -> trigger read of next data byte + else buffer_ptr <= buffer_ptr + 1'd1; + end + end + + RD_STATE_WAIT_M: begin + if(bit_cnt == 7) begin + wait_m_cnt <= wait_m_cnt + 1'd1; + if(&wait_m_cnt) begin + lba <= lba + 1; + io_ack <= 0; + sd_rd <= 1; + read_state <= RD_STATE_WAIT_IO; + end + end + end + endcase + + // ------------------ write support ---------------------- + // send write data response + if(write_state == WR_STATE_SEND_DRESP) miso <= WRITE_DATA_RESPONSE[~bit_cnt]; + + // busy after write until the io controller sends ack + if(write_state == WR_STATE_BUSY) miso <= 0; + end + + if(~old_sck & sck & ~ss) begin + + if(synced) bit_cnt <= bit_cnt + 1'd1; + + // assemble byte + if(bit_cnt != 7) begin + sbuf[6:0] <= { sbuf[5:0], mosi }; + + // resync while waiting for token + if(write_state==WR_STATE_EXP_DTOKEN) begin + if(cmd == 'h58) begin + if({sbuf,mosi} == 8'hfe) begin + write_state <= WR_STATE_RECV_DATA; + buffer_ptr <= 0; + bit_cnt <= 0; + end + end + else begin + if({sbuf,mosi} == 8'hfc) begin + write_state <= WR_STATE_RECV_DATA; + buffer_ptr <= 0; + bit_cnt <= 0; + end + if({sbuf,mosi} == 8'hfd) begin + write_state <= WR_STATE_IDLE; + rx_finish <= 1; + bit_cnt <= 0; + end + end + end + end + else begin + // finished reading one byte + // byte counter runs against 15 byte boundary + if(byte_cnt != 15) byte_cnt <= byte_cnt + 1'd1; + + // byte_cnt > 6 -> complete command received + // first byte of valid command is 01xxxxxx + // don't accept new commands once a write or read command has been accepted + if((byte_cnt > 5) & (write_state == WR_STATE_IDLE) & (read_state == RD_STATE_IDLE) && !rx_finish) begin + byte_cnt <= 0; + cmd <= { sbuf, mosi}; + + // set cmd55 flag if previous command was 55 + cmd55 <= (cmd == 'h77); + end + + if((byte_cnt > 5) & (read_state == RD_STATE_WAIT_M) && ({sbuf, mosi} == 8'h4c)) begin + byte_cnt <= 0; + rx_finish <= 0; + cmd <= {sbuf, mosi}; + read_state <= RD_STATE_IDLE; + end + + // parse additional command bytes + if(byte_cnt == 0) new_lba[31:24] <= { sbuf, mosi}; + if(byte_cnt == 1) new_lba[23:16] <= { sbuf, mosi}; + if(byte_cnt == 2) new_lba[15:8] <= { sbuf, mosi}; + if(byte_cnt == 3) new_lba[7:0] <= { sbuf, mosi}; + + // last byte (crc) received, evaluate + if(byte_cnt == 4) begin + + // default: + reply <= 4; // illegal command + reply_len <= 0; // no extra reply bytes + rx_finish <= 1; + + case(cmd) + // CMD0: GO_IDLE_STATE + 'h40: reply <= 1; // ok, busy + + // CMD1: SEND_OP_COND + 'h41: reply <= 0; // ok, not busy + + // CMD8: SEND_IF_COND (V2 only) + 'h48: begin + reply <= 1; // ok, busy + + reply0 <= 'h00; + reply1 <= 'h00; + reply2 <= 'h01; + reply3 <= 'hAA; + reply_len <= 4; + end + + // CMD9: SEND_CSD + 'h49: reply <= 0; // ok + + // CMD10: SEND_CID + 'h4a: reply <= 0; // ok + + // CMD12: STOP_TRANSMISSION + 'h4c: reply <= 0; // ok + + // CMD16: SET_BLOCKLEN + 'h50: begin + // we only support a block size of 512 + if(new_lba == 512) reply <= 0; // ok + else reply <= 'h40; // parmeter error + end + + // CMD17: READ_SINGLE_BLOCK + 'h51: reply <= 0; // ok + + // CMD18: READ_MULTIPLE + 'h52: reply <= 0; // ok + + // CMD24: WRITE_BLOCK + 'h58, + // CMD25: WRITE_MULTIPLE + 'h59: begin + reply <= 0; // ok + write_state <= WR_STATE_EXP_DTOKEN; // expect data token + rx_finish <=0; + lba <= new_lba; + end + + // ACMD41: APP_SEND_OP_COND + 'h69: if(cmd55) reply <= 0; // ok, not busy + + // CMD55: APP_COND + 'h77: reply <= 1; // ok, busy + + // CMD58: READ_OCR + 'h7a: begin + reply <= 0; // ok + + reply0 <= OCR[31:24]; // bit 30 = 1 -> high capacity card + reply1 <= OCR[23:16]; + reply2 <= OCR[15:8]; + reply3 <= OCR[7:0]; + reply_len <= 4; + end + + // CMD59: CRC_ON_OFF + 'h7b: reply <= 0; // ok + endcase + end + + // ---------- handle write ----------- + case(write_state) + // do nothing in idle state + WR_STATE_IDLE: ; + + // waiting for data token + WR_STATE_EXP_DTOKEN: begin + buffer_ptr <= 0; + if(cmd == 'h58) begin + if({sbuf,mosi} == 8'hfe) write_state <= WR_STATE_RECV_DATA; + end + else begin + if({sbuf,mosi} == 8'hfc) write_state <= WR_STATE_RECV_DATA; + if({sbuf,mosi} == 8'hfd) begin + write_state <= WR_STATE_IDLE; + rx_finish <= 1; + end + end + end + + // transfer 512 bytes + WR_STATE_RECV_DATA: begin + // push one byte into local buffer + buffer_wr <= 1; + buffer_din <= {sbuf, mosi}; + + // all bytes written? + if(&buffer_ptr) write_state <= WR_STATE_RECV_CRC0; + end + + // transfer 1st crc byte + WR_STATE_RECV_CRC0: + write_state <= WR_STATE_RECV_CRC1; + + // transfer 2nd crc byte + WR_STATE_RECV_CRC1: + write_state <= WR_STATE_SEND_DRESP; + + // send data response + WR_STATE_SEND_DRESP: begin + write_state <= WR_STATE_BUSY; + io_ack <= 0; + sd_wr <= 1; + end + + // wait for io controller to accept data + WR_STATE_BUSY: + if(io_ack) begin + if(cmd == 'h59) begin + write_state <= WR_STATE_EXP_DTOKEN; + lba <= lba + 1; + end + else begin + write_state <= WR_STATE_IDLE; + rx_finish <= 1; + end + end + endcase + end + + // wait for first 0 bit until start counting bits + if(!synced && !mosi) begin + synced <= 1; + bit_cnt <= 1; // byte assembly prepare for next time loop + sbuf <= 7'b1111110; // byte assembly prepare for next time loop + rx_finish<= 0; + end else if (synced && tx_finish && rx_finish ) begin + synced <= 0; + bit_cnt <= 0; + rx_finish<= 0; + end + end +end + +endmodule + +module sdbuf +( + input clock_a, + input clock_b, + input [8:0] address_a, + input [8:0] address_b, + input [7:0] data_a, + input [7:0] data_b, + input wren_a, + input wren_b, + output [7:0] q_a, + output [7:0] q_b +); + +altsyncram altsyncram_component +( + .address_a (address_a), + .address_b (address_b), + .clock0 (clock_a), + .clock1 (clock_b), + .data_a (data_a), + .data_b (data_b), + .wren_a (wren_a), + .wren_b (wren_b), + .q_a (q_a), + .q_b (q_b), + .aclr0 (1'b0), + .aclr1 (1'b0), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .eccstatus (), + .rden_a (1'b1), + .rden_b (1'b1) +); +defparam + altsyncram_component.address_reg_b = "CLOCK1", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_input_b = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.clock_enable_output_b = "BYPASS", + altsyncram_component.indata_reg_b = "CLOCK1", + altsyncram_component.intended_device_family = "Cyclone V", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 512, + altsyncram_component.numwords_b = 512, + altsyncram_component.operation_mode = "BIDIR_DUAL_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_a = "UNREGISTERED", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", + altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ", + altsyncram_component.widthad_a = 9, + altsyncram_component.widthad_b = 9, + altsyncram_component.width_a = 8, + altsyncram_component.width_b = 8, + altsyncram_component.width_byteena_a = 1, + altsyncram_component.width_byteena_b = 1, + altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1"; + +endmodule + diff --git a/sys/spdif.v b/sys/spdif.v index 671dcb2..add51d3 100644 --- a/sys/spdif.v +++ b/sys/spdif.v @@ -63,34 +63,27 @@ module spdif ); reg lpf_ce; -always @(negedge clk_i) begin - reg [3:0] div; - - div <= div + 1'd1; - if(div == 13) div <= 0; +always @(posedge clk_i) begin + reg [2:0] div; + if(bit_clk_q) div <= div + 1'd1; lpf_ce <= !div; end wire [15:0] al, ar; -lpf48k #(15) lpf_l +lpf_spdif lpf_l ( - .RESET(rst_i), .CLK(clk_i), .CE(lpf_ce), - .ENABLE(1), - .IDATA(audio_l), .ODATA(al) ); -lpf48k #(15) lpf_r +lpf_spdif lpf_r ( - .RESET(rst_i), .CLK(clk_i), .CE(lpf_ce), - .ENABLE(1), .IDATA(audio_r), .ODATA(ar) @@ -424,3 +417,29 @@ else assign spdif_o = spdif_out_q; endmodule + +module lpf_spdif +( + input CLK, + input CE, + input [15:0] IDATA, + output reg [15:0] ODATA +); + +reg [511:0] acc; +reg [20:0] sum; + +always @(*) begin + integer i; + sum = 0; + for (i = 0; i < 32; i = i+1) sum = sum + {{5{acc[(i*16)+15]}}, acc[i*16 +:16]}; +end + +always @(posedge CLK) begin + if(CE) begin + acc <= {acc[495:0], IDATA}; + ODATA <= sum[20:5]; + end +end + +endmodule diff --git a/sys/sync_vg.v b/sys/sync_vg.v deleted file mode 100644 index 54fc614..0000000 --- a/sys/sync_vg.v +++ /dev/null @@ -1,78 +0,0 @@ -module sync_vg -#( - parameter X_BITS=12, Y_BITS=12 -) -( - input wire clk, - input wire reset, - - input wire [Y_BITS-1:0] v_total, - input wire [Y_BITS-1:0] v_fp, - input wire [Y_BITS-1:0] v_bp, - input wire [Y_BITS-1:0] v_sync, - input wire [X_BITS-1:0] h_total, - input wire [X_BITS-1:0] h_fp, - input wire [X_BITS-1:0] h_bp, - input wire [X_BITS-1:0] h_sync, - input wire [X_BITS-1:0] hv_offset, - - output reg vs_out, - output reg hs_out, - output reg hde_out, - output reg vde_out, - output reg [Y_BITS-1:0] v_count_out, - output reg [X_BITS-1:0] h_count_out, - output reg [X_BITS-1:0] x_out, - output reg [Y_BITS-1:0] y_out -); - -reg [X_BITS-1:0] h_count; -reg [Y_BITS-1:0] v_count; - -/* horizontal counter */ -always @(posedge clk) - if (reset) - h_count <= 0; - else - if (h_count < h_total - 1) - h_count <= h_count + 1'd1; - else - h_count <= 0; - -/* vertical counter */ -always @(posedge clk) - if (reset) - v_count <= 0; - else - if (h_count == h_total - 1) - begin - if (v_count == v_total - 1) - v_count <= 0; - else - v_count <= v_count + 1'd1; - end - -always @(posedge clk) - if (reset) - { vs_out, hs_out, hde_out, vde_out } <= 0; - else begin - hs_out <= ((h_count < h_sync)); - - hde_out <= (h_count >= h_sync + h_bp) && (h_count <= h_total - h_fp - 1); - vde_out <= (v_count >= v_sync + v_bp) && (v_count <= v_total - v_fp - 1); - - if ((v_count == 0) && (h_count == hv_offset)) - vs_out <= 1'b1; - else if ((v_count == v_sync) && (h_count == hv_offset)) - vs_out <= 1'b0; - - /* H_COUNT_OUT and V_COUNT_OUT */ - h_count_out <= h_count; - v_count_out <= v_count; - - /* X and Y coords for a backend pattern generator */ - x_out <= h_count - (h_sync + h_bp); - y_out <= v_count - (v_sync + v_bp); - end - -endmodule diff --git a/sys/sys.qip b/sys/sys.qip index 5b397f4..104543a 100644 --- a/sys/sys.qip +++ b/sys/sys.qip @@ -1,23 +1,27 @@ -set_global_assignment -name VERILOG_FILE sys/sys_top.v -set_global_assignment -name SDC_FILE sys/sys_top.sdc -set_global_assignment -name QIP_FILE sys/pll.qip -set_global_assignment -name QIP_FILE sys/pll_hdmi.qip -set_global_assignment -name QIP_FILE sys/pll_hdmi_cfg.qip -set_global_assignment -name SYSTEMVERILOG_FILE sys/hdmi_lite.sv -set_global_assignment -name SYSTEMVERILOG_FILE sys/hq2x.sv -set_global_assignment -name VERILOG_FILE sys/scandoubler.v -set_global_assignment -name SYSTEMVERILOG_FILE sys/video_mixer.sv -set_global_assignment -name VERILOG_FILE sys/osd.v -set_global_assignment -name SYSTEMVERILOG_FILE sys/vga_out.sv -set_global_assignment -name VERILOG_FILE sys/sync_vg.v -set_global_assignment -name VERILOG_FILE sys/pattern_vg.v -set_global_assignment -name VERILOG_FILE sys/i2c.v -set_global_assignment -name VERILOG_FILE sys/i2s.v -set_global_assignment -name VERILOG_FILE sys/spdif.v -set_global_assignment -name VERILOG_FILE sys/sigma_delta_dac.v -set_global_assignment -name SYSTEMVERILOG_FILE sys/lpf48k.sv -set_global_assignment -name SYSTEMVERILOG_FILE sys/hdmi_config.sv -set_global_assignment -name SYSTEMVERILOG_FILE sys/sysmem.sv -set_global_assignment -name VERILOG_FILE sys/ip/reset_source.v -set_global_assignment -name SYSTEMVERILOG_FILE sys/vip_config.sv -set_global_assignment -name VERILOG_FILE sys/hps_io.v +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sys_top.v ] +set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) sys_top.sdc ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll.qip ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.qip ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi_cfg.qip ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ascal.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) pll_hdmi_adj.vhd ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hq2x.sv ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scandoubler.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scanlines.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_cleaner.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_mixer.sv ] +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 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 ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) spdif.v ] +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) lpf48k.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) sysmem.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) vip_config.sv ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sd_card.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) hps_io.v ] +set_instance_assignment -name HPS_LOCATION HPSINTERFACEPERIPHERALSPIMASTER_X52_Y72_N111 -entity sys_top -to spi +set_instance_assignment -name HPS_LOCATION HPSINTERFACEPERIPHERALUART_X52_Y67_N111 -entity sys_top -to uart diff --git a/sys/sys_q13.qip b/sys/sys_q13.qip new file mode 100644 index 0000000..59f687a --- /dev/null +++ b/sys/sys_q13.qip @@ -0,0 +1,31 @@ +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sys_top.v ] +set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) sys_top.sdc ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll/pll_0002.v ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll/pll_0002.qip ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi_q13.qip ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_hdmi_cfg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_hdmi_cfg/altera_pll_reconfig_core.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_hdmi_cfg/altera_pll_reconfig_top.v ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ascal.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) pll_hdmi_adj.vhd ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hq2x.sv ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scandoubler.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scanlines.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_cleaner.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_mixer.sv ] +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 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 ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) spdif.v ] +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) lpf48k.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) sysmem.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) vip_config.sv ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sd_card.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) hps_io.v ] +set_instance_assignment -name HPS_LOCATION HPSINTERFACEPERIPHERALSPIMASTER_X52_Y72_N111 -entity sys_top -to spi +set_instance_assignment -name HPS_LOCATION HPSINTERFACEPERIPHERALUART_X52_Y67_N111 -entity sys_top -to uart diff --git a/sys/sys_top.sdc b/sys/sys_top.sdc index cff810d..9a19e00 100644 --- a/sys/sys_top.sdc +++ b/sys/sys_top.sdc @@ -3,6 +3,7 @@ create_clock -period "50.0 MHz" [get_ports FPGA_CLK1_50] create_clock -period "50.0 MHz" [get_ports FPGA_CLK2_50] create_clock -period "50.0 MHz" [get_ports FPGA_CLK3_50] create_clock -period "100.0 MHz" [get_pins -compatibility_mode *|h2f_user0_clk] +create_clock -period 10.0 [get_pins -compatibility_mode spi|sclk_out] -name spi_sck derive_pll_clocks @@ -28,8 +29,11 @@ set_input_delay -min -clock SDRAM_CLK 3.7ns [get_ports SDRAM_DQ[*]] -to [get_clocks {*|pll|pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] \ -setup 2 -set_output_delay -max -clock SDRAM_CLK -0.9ns [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] -set_output_delay -min -clock SDRAM_CLK -1.6ns [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] +set_multicycle_path -from {*|vidc:VIDC|*} -to [get_clocks {*|pll|pll_inst|altera_pll_i|general[3].gpll~PLL_OUTPUT_COUNTER|divclk}] -setup 2 +set_multicycle_path -from {*|vidc:VIDC|*} -to [get_clocks {*|pll|pll_inst|altera_pll_i|general[3].gpll~PLL_OUTPUT_COUNTER|divclk}] -hold 2 + +set_output_delay -max -clock SDRAM_CLK 1.6ns [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] +set_output_delay -min -clock SDRAM_CLK -0.9ns [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] # Decouple different clock groups (to simplify routing) set_clock_groups -asynchronous \ @@ -41,6 +45,9 @@ set_clock_groups -asynchronous \ set_output_delay -max -clock HDMI_CLK 2.0ns [get_ports {HDMI_TX_D[*] HDMI_TX_DE HDMI_TX_HS HDMI_TX_VS}] set_output_delay -min -clock HDMI_CLK -1.5ns [get_ports {HDMI_TX_D[*] HDMI_TX_DE HDMI_TX_HS HDMI_TX_VS}] +set_false_path -from {*} -to [get_registers {wcalc[*] hcalc[*]}] + + # Put constraints on input ports set_false_path -from [get_ports {KEY*}] -to * set_false_path -from [get_ports {BTN_*}] -to * diff --git a/sys/sys_top.v b/sys/sys_top.v index 6281d97..e057e04 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -1,7 +1,7 @@ //============================================================================ // -// MiSTer hardware abstraction module (Archie) -// (c)2017,2018 Sorgelig +// MiSTer hardware abstraction module +// (c)2017-2019 Sorgelig // // 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 @@ -105,13 +105,14 @@ reg [7:0] led_state = 0; wire led_p = led_power[1] ? ~led_power[0] : 1'b0; wire led_d = led_disk[1] ? ~led_disk[0] : ~(led_disk[0] | gp_out[29]); wire led_u = ~led_user; +wire led_locked; assign LED_POWER = led_p ? 1'bZ : 1'b0; assign LED_HDD = led_d ? 1'bZ : 1'b0; assign LED_USER = led_u ? 1'bZ : 1'b0; //LEDs on main board -assign LED = (led_overtake & led_state) | (~led_overtake & {3'b000, ~led_p, 1'b0, ~led_d, 1'b0, ~led_u}); +assign LED = (led_overtake & led_state) | (~led_overtake & {1'b0,led_locked,1'b0, ~led_p, 1'b0, ~led_d, 1'b0, ~led_u}); ////////////////////////// Buttons /////////////////////////////////// @@ -189,16 +190,14 @@ cyclonev_hps_interface_mpu_general_purpose h2f_gp reg [15:0] cfg; -reg cfg_got = 0; -reg cfg_set = 0; +reg cfg_got = 0; +reg cfg_set = 0; //wire [2:0] hdmi_res = cfg[10:8]; -wire dvi_mode = cfg[7]; -wire audio_96k = cfg[6]; -wire ypbpr_en = cfg[5]; -wire csync = cfg[3]; -`ifndef LITE +wire dvi_mode = cfg[7]; +wire audio_96k = cfg[6]; +wire ypbpr_en = cfg[5]; +wire csync = cfg[3]; wire vga_scaler= cfg[2]; -`endif reg cfg_custom_t = 0; reg [5:0] cfg_custom_p1; @@ -206,7 +205,20 @@ reg [31:0] cfg_custom_p2; reg [4:0] vol_att = 0; -reg vip_newcfg = 0; +reg [6:0] coef_addr; +reg [8:0] coef_data; +reg coef_wr = 0; + +`ifndef LITE +reg vip_newcfg = 0; +reg coef_set = 0; +`endif + +wire [7:0] ARX, ARY; +reg [11:0] VSET = 0; +reg [2:0] scaler_flt; +reg lowlat = 0; + always@(posedge clk_sys) begin reg [7:0] cmd; reg has_cmd; @@ -214,8 +226,14 @@ always@(posedge clk_sys) begin reg [7:0] cnt = 0; old_strobe <= io_strobe; + coef_wr <= 0; - if(~io_uio) has_cmd <= 0; + if(~io_uio) begin + has_cmd <= 0; +`ifndef LITE + if(has_cmd && cmd == 'h2A) coef_set <= ~coef_set; +`endif + end else if(~old_strobe & io_strobe) begin if(!has_cmd) begin @@ -232,16 +250,18 @@ always@(posedge clk_sys) begin cfg_set <= 0; cnt <= cnt + 1'd1; if(cnt<8) begin +`ifndef LITE if(!cnt) vip_newcfg <= ~cfg_ready; +`endif case(cnt) - 0: if(WIDTH != io_din[11:0]) begin WIDTH <= io_din[11:0]; vip_newcfg <= 1; end - 1: if(HFP != io_din[11:0]) begin HFP <= io_din[11:0]; vip_newcfg <= 1; end - 2: if(HS != io_din[11:0]) begin HS <= io_din[11:0]; vip_newcfg <= 1; end - 3: if(HBP != io_din[11:0]) begin HBP <= io_din[11:0]; vip_newcfg <= 1; end - 4: if(HEIGHT != io_din[11:0]) begin HEIGHT <= io_din[11:0]; vip_newcfg <= 1; end - 5: if(VFP != io_din[11:0]) begin VFP <= io_din[11:0]; vip_newcfg <= 1; end - 6: if(VS != io_din[11:0]) begin VS <= io_din[11:0]; vip_newcfg <= 1; end - 7: if(VBP != io_din[11:0]) begin VBP <= io_din[11:0]; vip_newcfg <= 1; end + 0: if(WIDTH != io_din[11:0]) begin WIDTH <= io_din[11:0]; `ifndef LITE vip_newcfg <= 1; `endif end + 1: if(HFP != io_din[11:0]) begin HFP <= io_din[11:0]; `ifndef LITE vip_newcfg <= 1; `endif end + 2: if(HS != io_din[11:0]) begin HS <= io_din[11:0]; `ifndef LITE vip_newcfg <= 1; `endif end + 3: if(HBP != io_din[11:0]) begin HBP <= io_din[11:0]; `ifndef LITE vip_newcfg <= 1; `endif end + 4: if(HEIGHT != io_din[11:0]) begin HEIGHT <= io_din[11:0]; `ifndef LITE vip_newcfg <= 1; `endif end + 5: if(VFP != io_din[11:0]) begin VFP <= io_din[11:0]; `ifndef LITE vip_newcfg <= 1; `endif end + 6: if(VS != io_din[11:0]) begin VS <= io_din[11:0]; `ifndef LITE vip_newcfg <= 1; `endif end + 7: if(VBP != io_din[11:0]) begin VBP <= io_din[11:0]; `ifndef LITE vip_newcfg <= 1; `endif end endcase if(cnt == 1) begin cfg_custom_p1 <= 0; @@ -255,13 +275,16 @@ always@(posedge clk_sys) begin if(cnt[1:0]==2) begin cfg_custom_p2[31:16] <= io_din; cfg_custom_t <= ~cfg_custom_t; - cnt[1:0] <= 0; + cnt[2:0] <= 3'b100; end + if(cnt == 8) lowlat <= io_din[15]; end end if(cmd == 'h25) {led_overtake, led_state} <= io_din; if(cmd == 'h26) vol_att <= io_din[4:0]; if(cmd == 'h27) VSET <= io_din[11:0]; + if(cmd == 'h2A) {coef_wr,coef_addr,coef_data} <= {1'b1,io_din}; + if(cmd == 'h2B) scaler_flt <= io_din[2:0]; end end end @@ -276,6 +299,31 @@ always @(posedge clk_sys) begin end end +cyclonev_hps_interface_peripheral_uart uart +( + .ri(0), + .dsr(uart_dsr), + .dcd(uart_dsr), + .dtr(uart_dtr), + + .cts(uart_cts), + .rts(uart_rts), + .rxd(uart_rxd), + .txd(uart_txd) +); + +wire aspi_sck,aspi_mosi,aspi_ss; +cyclonev_hps_interface_peripheral_spi_master spi +( + .sclk_out(aspi_sck), + .txd(aspi_mosi), // mosi + .rxd(1), // miso + + .ss_0_n(aspi_ss), + .ss_in_n(1) +); + + /////////////////////////// RESET /////////////////////////////////// reg reset_req = 0; @@ -296,11 +344,11 @@ always @(posedge FPGA_CLK2_50) begin resetd2 <= resetd; end -wire clk_ctl; +wire clk_100m; +wire clk_hdmi = ~HDMI_TX_CLK; // Internal HDMI clock, inverted in relation to external clock +wire clk_audio = FPGA_CLK3_50; -///////////////////////// VIP version /////////////////////////////// - -wire iHdmiClk = ~HDMI_TX_CLK; // Internal HDMI clock, inverted in relation to external clock +//////////////////// SYSTEM MEMORY & SCALER ///////////////////////// `ifndef LITE @@ -321,7 +369,7 @@ vip vip .ctl_write(ctl_write), .ctl_writedata(ctl_writedata), .ctl_waitrequest(ctl_waitrequest), - .ctl_clock(clk_ctl), + .ctl_clock(clk_100m), .ctl_reset(ctl_reset), //64-bit DDR3 RAM access @@ -357,10 +405,10 @@ vip vip .in_v_sync(vs), .in_h_sync(hs), .in_ce(ce_pix), - .in_f(0), + .in_f(f1), //HDMI output - .hdmi_clk(iHdmiClk), + .hdmi_clk(clk_hdmi), .hdmi_data(hdmi_data), .hdmi_de(hdmi_de), .hdmi_v_sync(HDMI_TX_VS), @@ -372,11 +420,10 @@ wire ctl_write; wire [31:0] ctl_writedata; wire ctl_waitrequest; wire ctl_reset; -wire [7:0] ARX, ARY; vip_config vip_config ( - .clk(clk_ctl), + .clk(clk_100m), .reset(ctl_reset), .ARX(ARX), @@ -393,96 +440,43 @@ vip_config vip_config .VS(VS), .VSET(VSET), + .coef_set(coef_set), + .coef_clk(clk_sys), + .coef_addr(coef_addr), + .coef_data(coef_data), + .coef_wr(coef_wr), + .scaler_flt(scaler_flt), + .address(ctl_address), .write(ctl_write), .writedata(ctl_writedata), .waitrequest(ctl_waitrequest) ); + +assign cfg_write = adj_write; +assign cfg_address = adj_address; +assign cfg_data = adj_data; +assign adj_waitrequest = cfg_waitrequest; +assign led_locked = 0; + `endif -///////////////////////// Lite version //////////////////////////////// - `ifdef LITE -wire [11:0] x; -wire [11:0] y; - -sync_vg #(.X_BITS(12), .Y_BITS(12)) sync_vg -( - .clk(iHdmiClk), - .reset(reset), - .v_total(HEIGHT+VFP+VBP+VS), - .v_fp(VFP), - .v_bp(VBP), - .v_sync(VS), - .h_total(WIDTH+HFP+HBP+HS), - .h_fp(HFP), - .h_bp(HBP), - .h_sync(HS), - .hv_offset(0), - .vde_out(vde), - .hde_out(hde), - .vs_out(vs_hdmi), - .v_count_out(), - .h_count_out(), - .x_out(x), - .y_out(y), - .hs_out(hs_hdmi) -); - -wire vde, hde; -wire vs_hdmi; -wire hs_hdmi; - -/* - -pattern_vg -#( - .B(8), // Bits per channel - .X_BITS(12), - .Y_BITS(12), - .FRACTIONAL_BITS(12) // Number of fractional bits for ramp pattern -) -pattern_vg -( - .reset(reset), - .clk_in(iHdmiClk), - .x(x), - .y(y), - .vn_in(vs_hdmi), - .hn_in(hs_hdmi), - .dn_in(vde & hde), - .r_in(0), - .g_in(0), - .b_in(0), - .vn_out(HDMI_TX_VS), - .hn_out(HDMI_TX_HS), - .den_out(HDMI_TX_DE), - .r_out(hdmi_data[23:16]), - .g_out(hdmi_data[15:8]), - .b_out(hdmi_data[7:0]), - .total_active_pix(WIDTH), - .total_active_lines(HEIGHT), - .pattern(4), - .ramp_step(20'h0333) -); -*/ - wire reset; sysmem_lite sysmem ( //Reset/Clock - .reset_reset_req(reset_req), - .reset_reset(reset), - .ctl_clock(clk_ctl), + .reset_core_req(reset_req), + .reset_out(reset), + .clock(clk_100m), //DE10-nano has no reset signal on GPIO, so core has to emulate cold reset button. - .reset_cold_req(~btn_reset), - .reset_warm_req(0), + .reset_hps_cold_req(~btn_reset), //64-bit DDR3 RAM access - .ramclk1_clk(ram_clk), + .ram1_clk(ram_clk), .ram1_address(ram_address), .ram1_burstcount(ram_burstcount), .ram1_waitrequest(ram_waitrequest), @@ -493,22 +487,21 @@ sysmem_lite sysmem .ram1_byteenable(ram_byteenable), .ram1_write(ram_write), - //Spare 64-bit DDR3 RAM access - //currently unused - //can combine with ram1 to make a wider RAM bus (although will increase the latency) - .ramclk2_clk(0), - .ram2_address(0), - .ram2_burstcount(0), - .ram2_waitrequest(), - .ram2_readdata(), - .ram2_readdatavalid(), - .ram2_read(0), + //64-bit DDR3 RAM access + .ram2_clk(clk_audio), + .ram2_address(aram_address), + .ram2_burstcount(aram_burstcount), + .ram2_waitrequest(aram_waitrequest), + .ram2_readdata(aram_readdata), + .ram2_readdatavalid(aram_readdatavalid), + .ram2_read(aram_read), .ram2_writedata(0), - .ram2_byteenable(0), + .ram2_byteenable(8'hFF), .ram2_write(0), + //128-bit DDR3 RAM access // HDMI frame buffer - .vbuf_clk(clk_ctl), + .vbuf_clk(clk_100m), .vbuf_address(vbuf_address), .vbuf_burstcount(vbuf_burstcount), .vbuf_waitrequest(vbuf_waitrequest), @@ -530,42 +523,122 @@ wire [127:0] vbuf_writedata; wire [15:0] vbuf_byteenable; wire vbuf_write; -assign HDMI_TX_VS = vs_hdmi; -assign HDMI_TX_HS = hs_hdmi; - -hdmi_lite hdmi_lite +ascal +#( + .RAMBASE(32'h20000000), + .N_DW(128), + .N_AW(28) +) +ascal ( - .reset(reset), + .reset_na (~reset_req), + .run (1), + .freeze (0), - .clk_video(clk_vid), - .ce_pixel(ce_pix), - .video_vs(vs), - .video_de(de), - .video_d({r_out,g_out,b_out}), + .i_clk (clk_vid), + .i_ce (ce_pix), + .i_r (r_out), + .i_g (g_out), + .i_b (b_out), + .i_hs (hs), + .i_vs (vs), + .i_fl (f1), + .i_de (de), + .iauto (1), + .himin (0), + .himax (0), + .vimin (0), + .vimax (0), - .clk_hdmi(HDMI_TX_CLK), - .hdmi_hde(hde), - .hdmi_vde(vde), - .hdmi_d(hdmi_data), - .hdmi_de(hdmi_de), + .o_clk (clk_hdmi), + .o_ce (1), + .o_r (hdmi_data[23:16]), + .o_g (hdmi_data[15:8]), + .o_b (hdmi_data[7:0]), + .o_hs (HDMI_TX_HS), + .o_vs (HDMI_TX_VS), + .o_de (hdmi_de), + .o_lltune (lltune), + .htotal (WIDTH+HFP+HBP+HS), + .hsstart(WIDTH + HFP), + .hsend (WIDTH + HFP + HS), + .hdisp (WIDTH), + .hmin (hmin), + .hmax (hmax), + .vtotal (HEIGHT+VFP+VBP+VS), + .vsstart(HEIGHT + VFP), + .vsend (HEIGHT + VFP + VS), + .vdisp (HEIGHT), + .vmin (vmin), + .vmax (vmax), - .screen_w(WIDTH), - .screen_h(HEIGHT), - .quadbuf(1), - .scale_x(0), - .scale_y(0), - .scale_auto(1), + .mode ({~lowlat,|scaler_flt,2'b00}), + .poly_clk (clk_sys), + .poly_a (coef_addr), + .poly_dw (coef_data), + .poly_wr (coef_wr), - .clk_vbuf(clk_ctl), - .vbuf_address(vbuf_address), - .vbuf_burstcount(vbuf_burstcount), - .vbuf_waitrequest(vbuf_waitrequest), - .vbuf_writedata(vbuf_writedata), - .vbuf_byteenable(vbuf_byteenable), - .vbuf_write(vbuf_write), - .vbuf_readdata(vbuf_readdata), - .vbuf_readdatavalid(vbuf_readdatavalid), - .vbuf_read(vbuf_read) + .avl_clk (clk_100m), + .avl_waitrequest (vbuf_waitrequest), + .avl_readdata (vbuf_readdata), + .avl_readdatavalid(vbuf_readdatavalid), + .avl_burstcount (vbuf_burstcount), + .avl_writedata (vbuf_writedata), + .avl_address (vbuf_address), + .avl_write (vbuf_write), + .avl_read (vbuf_read), + .avl_byteenable (vbuf_byteenable) +); + +reg [11:0] hmin; +reg [11:0] hmax; +reg [11:0] vmin; +reg [11:0] vmax; + +always @(posedge clk_vid) begin + reg [31:0] wcalc; + reg [31:0] hcalc; + reg [2:0] state; + reg [11:0] videow; + reg [11:0] videoh; + + state <= state + 1'd1; + case(state) + 0: begin + wcalc <= VSET ? (VSET*ARX)/ARY : (HEIGHT*ARX)/ARY; + hcalc <= (WIDTH*ARY)/ARX; + end + 6: begin + videow <= (!VSET && (wcalc > WIDTH)) ? WIDTH : wcalc[11:0]; + videoh <= VSET ? VSET : (hcalc > HEIGHT) ? HEIGHT : hcalc[11:0]; + end + 7: begin + hmin <= ((WIDTH - videow)>>1); + hmax <= ((WIDTH - videow)>>1) + videow - 1'd1; + vmin <= ((HEIGHT - videoh)>>1); + vmax <= ((HEIGHT - videoh)>>1) + videoh - 1'd1; + end + endcase +end + +wire [15:0] lltune; + +pll_hdmi_adj pll_hdmi_adj +( + .clk(FPGA_CLK1_50), + .reset_na(~reset_req), + + .llena(lowlat), + .lltune(lltune), + .locked(led_locked), + .i_waitrequest(adj_waitrequest), + .i_write(adj_write), + .i_address(adj_address), + .i_writedata(adj_data), + .o_waitrequest(cfg_waitrequest), + .o_write(cfg_write), + .o_address(cfg_address), + .o_writedata(cfg_data) ); `endif @@ -591,14 +664,16 @@ reg [11:0] HEIGHT = 1080; reg [11:0] VFP = 4; reg [11:0] VS = 5; reg [11:0] VBP = 36; -reg [11:0] VSET = 0; wire [63:0] reconfig_to_pll; wire [63:0] reconfig_from_pll; -wire cfg_waitrequest; -reg cfg_write; -reg [5:0] cfg_address; -reg [31:0] cfg_data; +wire cfg_waitrequest,adj_waitrequest; +wire cfg_write; +wire [5:0] cfg_address; +wire [31:0] cfg_data; +reg adj_write; +reg [5:0] adj_address; +reg [31:0] adj_data; pll_hdmi_cfg pll_hdmi_cfg ( @@ -624,24 +699,24 @@ always @(posedge FPGA_CLK1_50) begin gotd <= cfg_got; gotd2 <= gotd; - cfg_write <= 0; + adj_write <= 0; custd <= cfg_custom_t; custd2 <= custd; if(custd2 != custd & ~gotd) begin - cfg_address <= cfg_custom_p1; - cfg_data <= cfg_custom_p2; - cfg_write <= 1; + adj_address <= cfg_custom_p1; + adj_data <= cfg_custom_p2; + adj_write <= 1; end if(~gotd2 & gotd) begin - cfg_address <= 2; - cfg_data <= 0; - cfg_write <= 1; + adj_address <= 2; + adj_data <= 0; + adj_write <= 1; end - old_wait <= cfg_waitrequest; - if(old_wait & ~cfg_waitrequest & gotd) cfg_ready <= 1; + old_wait <= adj_waitrequest; + if(old_wait & ~adj_waitrequest & gotd) cfg_ready <= 1; end hdmi_config hdmi_config @@ -657,8 +732,20 @@ hdmi_config hdmi_config ); wire [23:0] hdmi_data; +wire [23:0] hdmi_data_sl; wire hdmi_de; +scanlines #(1) HDMI_scanlines +( + .clk(clk_hdmi), + + .scanlines(scanlines), + .din(hdmi_data), + .dout(hdmi_data_sl), + .hs(HDMI_TX_HS), + .vs(HDMI_TX_VS) +); + osd hdmi_osd ( .clk_sys(clk_sys), @@ -667,33 +754,30 @@ osd hdmi_osd .io_strobe(io_strobe), .io_din(io_din), - .clk_video(iHdmiClk), - .din(hdmi_data), + .clk_video(clk_hdmi), + .din(hdmi_data_sl), .dout(HDMI_TX_D), .de_in(hdmi_de), - .de_out(HDMI_TX_DE) + .de_out(HDMI_TX_DE), + + .osd_status(osd_status) ); -assign HDMI_MCLK = 0; -i2s i2s -( - .reset(~cfg_ready), - .clk_sys(FPGA_CLK3_50), - .half_rate(~audio_96k), - - .sclk(HDMI_SCLK), - .lrclk(HDMI_LRCLK), - .sdata(HDMI_I2S), - - //Could inverse the MSB but it will shift 0 level to -MAX level - .left_chan (audio_l >> !audio_s), - .right_chan(audio_r >> !audio_s) -); - - ///////////////////////// VGA output ////////////////////////////////// -wire [23:0] vga_q; +wire [23:0] vga_data_sl; + +scanlines #(0) VGA_scanlines +( + .clk(clk_vid), + + .scanlines(scanlines), + .din(de ? {r_out, g_out, b_out} : 24'd0), + .dout(vga_data_sl), + .hs(hs1), + .vs(vs1) +); + osd vga_osd ( .clk_sys(clk_sys), @@ -703,11 +787,12 @@ osd vga_osd .io_din(io_din), .clk_video(clk_vid), - .din(de ? {r_out, g_out, b_out} : 24'd0), + .din(vga_data_sl), .dout(vga_q), .de_in(de) ); +wire [23:0] vga_q; wire [23:0] vga_o; vga_out vga_out @@ -715,20 +800,11 @@ vga_out vga_out .ypbpr_full(1), .ypbpr_en(ypbpr_en), .dout(vga_o), -`ifdef LITE - .din(vga_q) -`else .din(vga_scaler ? {24{HDMI_TX_DE}} & HDMI_TX_D : vga_q) -`endif ); -`ifdef LITE - wire vs1 = vs; - wire hs1 = hs; -`else - wire vs1 = vga_scaler ? HDMI_TX_VS : vs; - wire hs1 = vga_scaler ? HDMI_TX_HS : hs; -`endif +wire vs1 = vga_scaler ? HDMI_TX_VS : vs; +wire hs1 = vga_scaler ? HDMI_TX_HS : hs; assign VGA_VS = VGA_EN ? 1'bZ : csync ? 1'b1 : ~vs1; assign VGA_HS = VGA_EN ? 1'bZ : csync ? ~(vs1 ^ hs1) : ~hs1; @@ -739,93 +815,127 @@ assign VGA_B = VGA_EN ? 6'bZZZZZZ : vga_o[7:2]; ///////////////////////// Audio output //////////////////////////////// -wire al, ar, aspdif; +assign AUDIO_SPDIF = SW[0] ? HDMI_LRCLK : aspdif; +assign AUDIO_R = SW[0] ? HDMI_I2S : anr; +assign AUDIO_L = SW[0] ? HDMI_SCLK : anl; +assign HDMI_MCLK = 0; +i2s i2s +( + .clk_sys(clk_audio), + .reset(reset), + + .half_rate(~audio_96k), + + .sclk(HDMI_SCLK), + .lrclk(HDMI_LRCLK), + .sdata(HDMI_I2S), + + .left_chan (audio_l), + .right_chan(audio_r) +); + +wire anl; sigma_delta_dac #(15) dac_l ( - .CLK(FPGA_CLK3_50), + .CLK(clk_audio), .RESET(reset), - .DACin({audio_l[15] ^ audio_s, audio_l[14:0]}), - .DACout(al) + .DACin({~audio_l[15], audio_l[14:0]}), + .DACout(anl) ); +wire anr; sigma_delta_dac #(15) dac_r ( - .CLK(FPGA_CLK3_50), + .CLK(clk_audio), .RESET(reset), - .DACin({audio_r[15] ^ audio_s, audio_r[14:0]}), - .DACout(ar) + .DACin({~audio_r[15], audio_r[14:0]}), + .DACout(anr) ); +wire aspdif; spdif toslink ( - .clk_i(FPGA_CLK3_50), + .clk_i(clk_audio), .rst_i(reset), .half_rate(0), - .audio_l(audio_l >> !audio_s), - .audio_r(audio_r >> !audio_s), + .audio_l(audio_l), + .audio_r(audio_r), .spdif_o(aspdif) ); -assign AUDIO_SPDIF = SW[0] ? HDMI_LRCLK : aspdif; -assign AUDIO_R = SW[0] ? HDMI_I2S : ar; -assign AUDIO_L = SW[0] ? HDMI_SCLK : al; +wire [15:0] audio_l, audio_l_pre; +aud_mix_top audmix_l +( + .clk(clk_audio), + .att(vol_att), + .mix(audio_mix), + .is_signed(audio_s), -reg [15:0] audio_l; -reg [15:0] audio_r; + .core_audio(audio_ls), + .pre_in(audio_r_pre), + .linux_audio(alsa_l), -always @(posedge FPGA_CLK3_50) begin - reg signed [15:0] al; - reg signed [15:0] ar; + .pre_out(audio_l_pre), + .out(audio_l) +); - case({audio_s,audio_mix}) - 'b000: al <= audio_ls; - 'b001: al <= audio_ls - (audio_ls >> 3) + (audio_rs >> 3); - 'b010: al <= audio_ls - (audio_ls >> 2) + (audio_rs >> 2); - 'b011: al <= (audio_ls >> 1) + (audio_rs >> 1); - 'b100: al <= audio_ls; - 'b101: al <= audio_ls - (audio_ls >>> 3) + (audio_rs >>> 3); - 'b110: al <= audio_ls - (audio_ls >>> 2) + (audio_rs >>> 2); - 'b111: al <= (audio_ls >>> 1) + (audio_rs >>> 1); - endcase +wire [15:0] audio_r, audio_r_pre; +aud_mix_top audmix_r +( + .clk(clk_audio), + .att(vol_att), + .mix(audio_mix), + .is_signed(audio_s), - case({audio_s,audio_mix}) - 'b000: ar <= audio_rs; - 'b001: ar <= audio_rs - (audio_rs >> 3) + (audio_ls >> 3); - 'b010: ar <= audio_rs - (audio_rs >> 2) + (audio_ls >> 2); - 'b011: ar <= (audio_rs >> 1) + (audio_ls >> 1); - 'b100: ar <= audio_rs; - 'b101: ar <= audio_rs - (audio_rs >>> 3) + (audio_ls >>> 3); - 'b110: ar <= audio_rs - (audio_rs >>> 2) + (audio_ls >>> 2); - 'b111: ar <= (audio_rs >>> 1) + (audio_ls >>> 1); - endcase - - if(vol_att[4]) begin - audio_l <= 0; - audio_r <= 0; - end - else - if(audio_s) begin - audio_l <= al >>> vol_att[3:0]; - audio_r <= ar >>> vol_att[3:0]; - end - else - begin - audio_l <= al >> vol_att[3:0]; - audio_r <= ar >> vol_att[3:0]; - end -end + .core_audio(audio_rs), + .pre_in(audio_l_pre), + .linux_audio(alsa_r), + + .pre_out(audio_r_pre), + .out(audio_r) +); + +wire [28:0] aram_address; +wire [7:0] aram_burstcount; +wire aram_waitrequest; +wire [63:0] aram_readdata; +wire aram_readdatavalid; +wire aram_read; + +wire [15:0] alsa_l, alsa_r; + +alsa alsa +( + .reset(reset), + + .ram_clk(clk_audio), + .ram_address(aram_address), + .ram_burstcount(aram_burstcount), + .ram_waitrequest(aram_waitrequest), + .ram_readdata(aram_readdata), + .ram_readdatavalid(aram_readdatavalid), + .ram_read(aram_read), + + .spi_ss(aspi_ss), + .spi_sck(aspi_sck), + .spi_mosi(aspi_mosi), + + .pcm_l(alsa_l), + .pcm_r(alsa_r) +); /////////////////// User module connection //////////////////////////// -wire signed [15:0] audio_ls, audio_rs; +wire [15:0] audio_ls, audio_rs; wire audio_s; wire [1:0] audio_mix; wire [7:0] r_out, g_out, b_out; -wire vs, hs, de; +wire vs, hs, de, f1; +wire [1:0] scanlines; wire clk_sys, clk_vid, ce_pix; wire ram_clk; @@ -844,14 +954,22 @@ wire [1:0] led_power; wire [1:0] led_disk; wire vs_emu, hs_emu; -sync_fix sync_v(FPGA_CLK3_50, vs_emu, vs); -sync_fix sync_h(FPGA_CLK3_50, hs_emu, hs); +sync_fix sync_v(clk_vid, vs_emu, vs); +sync_fix sync_h(clk_vid, hs_emu, hs); + +wire uart_dtr; +wire uart_dsr; +wire uart_cts; +wire uart_rts; +wire uart_rxd; +wire uart_txd; +wire osd_status; emu emu ( .CLK_50M(FPGA_CLK3_50), .RESET(reset), - .HPS_BUS({HDMI_TX_VS, clk_ctl, clk_vid, ce_pix, de, hs, vs, io_wait, clk_sys, io_fpga, io_uio, io_strobe, io_wide, io_din, io_dout}), + .HPS_BUS({HDMI_TX_VS, clk_100m, clk_vid, ce_pix, de, hs, vs, io_wait, clk_sys, io_fpga, io_uio, io_strobe, io_wide, io_din, io_dout}), .CLK_VIDEO(clk_vid), .CE_PIXEL(ce_pix), @@ -862,15 +980,15 @@ emu emu .VGA_HS(hs_emu), .VGA_VS(vs_emu), .VGA_DE(de), + .VGA_F1(f1), + .VGA_SL(scanlines), .LED_USER(led_user), .LED_POWER(led_power), .LED_DISK(led_disk), -`ifndef LITE .VIDEO_ARX(ARX), .VIDEO_ARY(ARY), -`endif .AUDIO_L(audio_ls), .AUDIO_R(audio_rs), @@ -878,12 +996,6 @@ emu emu .AUDIO_MIX(audio_mix), .TAPE_IN(0), - // SCK -> CLK - // MOSI -> CMD - // MISO <- DAT0 - // Z -> DAT1 - // Z -> DAT2 - // CS -> DAT3 .SD_SCK(SDIO_CLK), .SD_MOSI(SDIO_CMD), .SD_MISO(SDIO_DAT[0]), @@ -911,11 +1023,22 @@ emu emu .SDRAM_nRAS(SDRAM_nRAS), .SDRAM_nCAS(SDRAM_nCAS), .SDRAM_CLK(SDRAM_CLK), - .SDRAM_CKE(SDRAM_CKE) + .SDRAM_CKE(SDRAM_CKE), + + .UART_CTS(uart_rts), + .UART_RTS(uart_cts), + .UART_RXD(uart_txd), + .UART_TXD(uart_rxd), + .UART_DTR(uart_dsr), + .UART_DSR(uart_dtr), + + .OSD_STATUS(osd_status) ); endmodule +///////////////////////////////////////////////////////////////////// + module sync_fix ( input clk, @@ -944,3 +1067,53 @@ always @(posedge clk) begin end endmodule + +///////////////////////////////////////////////////////////////////// + +module aud_mix_top +( + input clk, + + input [4:0] att, + input [1:0] mix, + input is_signed, + + input [15:0] core_audio, + input [15:0] linux_audio, + input [15:0] pre_in, + + output reg [15:0] pre_out, + output reg [15:0] out +); + +reg [15:0] ca; +always @(posedge clk) begin + reg [15:0] d1,d2,d3; + + d1 <= core_audio; d2<=d1; d3<=d2; + if(d2 == d3) ca <= d2; +end + +always @(posedge clk) begin + reg signed [16:0] a1, a2, a3, a4; + + a1 <= is_signed ? {ca[15],ca} : {2'b00,ca[15:1]}; + a2 <= a1 + {linux_audio[15],linux_audio}; + + pre_out <= a2[16:1]; + + case(mix) + 0: a3 <= a2; + 1: a3 <= $signed(a2) - $signed(a2[16:3]) + $signed(pre_in[15:2]); + 2: a3 <= $signed(a2) - $signed(a2[16:2]) + $signed(pre_in[15:1]); + 3: a3 <= {a2[16],a2[16:1]} + {pre_in[15],pre_in}; + endcase + + if(att[4]) a4 <= 0; + else a4 <= a3 >>> att[3:0]; + + //clamping + out <= ^a4[16:15] ? {a4[16],{15{a4[15]}}} : a4[15:0]; +end + +endmodule diff --git a/sys/sysmem.sv b/sys/sysmem.sv index 0f60f65..c90395e 100644 --- a/sys/sysmem.sv +++ b/sys/sysmem.sv @@ -1,531 +1,429 @@ -`timescale 1 ps / 1 ps -module sysmem_lite -( - input ramclk1_clk, // ramclk1.clk - input [28:0] ram1_address, // ram1.address - input [7:0] ram1_burstcount, // .burstcount - output ram1_waitrequest, // .waitrequest - output [63:0] ram1_readdata, // .readdata - output ram1_readdatavalid, // .readdatavalid - input ram1_read, // .read - input [63:0] ram1_writedata, // .writedata - input [7:0] ram1_byteenable, // .byteenable - input ram1_write, // .write - - input ramclk2_clk, // ramclk2.clk - input [28:0] ram2_address, // ram2.address - input [7:0] ram2_burstcount, // .burstcount - output ram2_waitrequest, // .waitrequest - output [63:0] ram2_readdata, // .readdata - output ram2_readdatavalid, // .readdatavalid - input ram2_read, // .read - input [63:0] ram2_writedata, // .writedata - input [7:0] ram2_byteenable, // .byteenable - input ram2_write, // .write - - output ctl_clock, - input reset_cold_req, // reset.cold_req - output reset_reset, // .reset - input reset_reset_req, // .reset_req - input reset_warm_req, // .warm_req - - input vbuf_clk, // vbuf.clk - input [27:0] vbuf_address, // vbuf.address - input [7:0] vbuf_burstcount, // .burstcount - output vbuf_waitrequest, // .waitrequest - output [127:0] vbuf_readdata, // .readdata - output vbuf_readdatavalid, // .readdatavalid - input vbuf_read, // .read - input [127:0] vbuf_writedata, // .writedata - input [15:0] vbuf_byteenable, // .byteenable - input vbuf_write // .write -); - -assign ctl_clock = clk_vip_clk; - -wire hps_h2f_reset_reset; // HPS:h2f_rst_n -> Reset_Source:reset_hps -wire reset_source_reset_cold_reset; // Reset_Source:reset_cold -> HPS:f2h_cold_rst_req_n -wire reset_source_reset_warm_reset; // Reset_Source:reset_warm -> HPS:f2h_warm_rst_req_n -wire clk_vip_clk; - -sysmem_HPS_fpga_interfaces fpga_interfaces ( - .f2h_cold_rst_req_n (~reset_source_reset_cold_reset), // f2h_cold_reset_req.reset_n - .f2h_warm_rst_req_n (~reset_source_reset_warm_reset), // f2h_warm_reset_req.reset_n - .h2f_user0_clk (clk_vip_clk), // h2f_user0_clock.clk - .h2f_rst_n (hps_h2f_reset_reset), // h2f_reset.reset_n - .f2h_sdram0_clk (vbuf_clk), // f2h_sdram0_clock.clk - .f2h_sdram0_ADDRESS (vbuf_address), // f2h_sdram0_data.address - .f2h_sdram0_BURSTCOUNT (vbuf_burstcount), // .burstcount - .f2h_sdram0_WAITREQUEST (vbuf_waitrequest), // .waitrequest - .f2h_sdram0_READDATA (vbuf_readdata), // .readdata - .f2h_sdram0_READDATAVALID (vbuf_readdatavalid), // .readdatavalid - .f2h_sdram0_READ (vbuf_read), // .read - .f2h_sdram0_WRITEDATA (vbuf_writedata), // .writedata - .f2h_sdram0_BYTEENABLE (vbuf_byteenable), // .byteenable - .f2h_sdram0_WRITE (vbuf_write), // .write - .f2h_sdram1_clk (ramclk1_clk), // f2h_sdram1_clock.clk - .f2h_sdram1_ADDRESS (ram1_address), // f2h_sdram1_data.address - .f2h_sdram1_BURSTCOUNT (ram1_burstcount), // .burstcount - .f2h_sdram1_WAITREQUEST (ram1_waitrequest), // .waitrequest - .f2h_sdram1_READDATA (ram1_readdata), // .readdata - .f2h_sdram1_READDATAVALID (ram1_readdatavalid), // .readdatavalid - .f2h_sdram1_READ (ram1_read), // .read - .f2h_sdram1_WRITEDATA (ram1_writedata), // .writedata - .f2h_sdram1_BYTEENABLE (ram1_byteenable), // .byteenable - .f2h_sdram1_WRITE (ram1_write), // .write - .f2h_sdram2_clk (ramclk2_clk), // f2h_sdram2_clock.clk - .f2h_sdram2_ADDRESS (ram2_address), // f2h_sdram2_data.address - .f2h_sdram2_BURSTCOUNT (ram2_burstcount), // .burstcount - .f2h_sdram2_WAITREQUEST (ram2_waitrequest), // .waitrequest - .f2h_sdram2_READDATA (ram2_readdata), // .readdata - .f2h_sdram2_READDATAVALID (ram2_readdatavalid), // .readdatavalid - .f2h_sdram2_READ (ram2_read), // .read - .f2h_sdram2_WRITEDATA (ram2_writedata), // .writedata - .f2h_sdram2_BYTEENABLE (ram2_byteenable), // .byteenable - .f2h_sdram2_WRITE (ram2_write) // .write -); - -reset_source reset_source ( - .clk (clk_vip_clk), // clock.clk - .reset_hps (~hps_h2f_reset_reset), // reset_hps.reset - .reset_sys (), // reset_sys.reset - .cold_req (reset_cold_req), // reset_ctl.cold_req - .reset (reset_reset), // .reset - .reset_req (reset_reset_req), // .reset_req - .reset_vip (0), // .reset_vip - .warm_req (reset_warm_req), // .warm_req - .reset_warm (reset_source_reset_warm_reset), // reset_warm.reset - .reset_cold (reset_source_reset_cold_reset) // reset_cold.reset -); - -endmodule - `timescale 1 ps / 1 ps -module sysmem -( - input ramclk1_clk, // ramclk1.clk - input [28:0] ram1_address, // ram1.address - input [7:0] ram1_burstcount, // .burstcount - output ram1_waitrequest, // .waitrequest - output [63:0] ram1_readdata, // .readdata - output ram1_readdatavalid, // .readdatavalid - input ram1_read, // .read - input [63:0] ram1_writedata, // .writedata - input [7:0] ram1_byteenable, // .byteenable - input ram1_write, // .write +module sysmem_lite +( + output clock, + output reset_out, - input ramclk2_clk, // ramclk2.clk - input [28:0] ram2_address, // ram2.address - input [7:0] ram2_burstcount, // .burstcount - output ram2_waitrequest, // .waitrequest - output [63:0] ram2_readdata, // .readdata - output ram2_readdatavalid, // .readdatavalid - input ram2_read, // .read - input [63:0] ram2_writedata, // .writedata - input [7:0] ram2_byteenable, // .byteenable - input ram2_write, // .write + input reset_hps_cold_req, + input reset_hps_warm_req, + input reset_core_req, - input reset_cold_req, // reset.cold_req - output reset_reset, // .reset - input reset_reset_req, // .reset_req - input reset_warm_req, // .warm_req + input ram1_clk, + input [28:0] ram1_address, + input [7:0] ram1_burstcount, + output ram1_waitrequest, + output [63:0] ram1_readdata, + output ram1_readdatavalid, + input ram1_read, + input [63:0] ram1_writedata, + input [7:0] ram1_byteenable, + input ram1_write, - input [27:0] ram_vip_address, // ram_vip.address - input [7:0] ram_vip_burstcount, // .burstcount - output ram_vip_waitrequest, // .waitrequest - output [127:0] ram_vip_readdata, // .readdata - output ram_vip_readdatavalid, // .readdatavalid - input ram_vip_read, // .read - input [127:0] ram_vip_writedata, // .writedata - input [15:0] ram_vip_byteenable, // .byteenable - input ram_vip_write, // .write + input ram2_clk, + input [28:0] ram2_address, + input [7:0] ram2_burstcount, + output ram2_waitrequest, + output [63:0] ram2_readdata, + output ram2_readdatavalid, + input ram2_read, + input [63:0] ram2_writedata, + input [7:0] ram2_byteenable, + input ram2_write, + + input vbuf_clk, + input [27:0] vbuf_address, + input [7:0] vbuf_burstcount, + output vbuf_waitrequest, + output [127:0] vbuf_readdata, + output vbuf_readdatavalid, + input vbuf_read, + input [127:0] vbuf_writedata, + input [15:0] vbuf_byteenable, + input vbuf_write +); + +assign reset_out = ~init_reset_n | ~hps_h2f_reset_n | reset_core_req; - output clk_vip_clk, // clk_vip.clk - output reset_vip_reset // reset_vip.reset -); - -wire hps_h2f_reset_reset; // HPS:h2f_rst_n -> Reset_Source:reset_hps -wire reset_source_reset_cold_reset; // Reset_Source:reset_cold -> HPS:f2h_cold_rst_req_n -wire reset_source_reset_warm_reset; // Reset_Source:reset_warm -> HPS:f2h_warm_rst_req_n - sysmem_HPS_fpga_interfaces fpga_interfaces ( - .f2h_cold_rst_req_n (~reset_source_reset_cold_reset), // f2h_cold_reset_req.reset_n - .f2h_warm_rst_req_n (~reset_source_reset_warm_reset), // f2h_warm_reset_req.reset_n - .h2f_user0_clk (clk_vip_clk), // h2f_user0_clock.clk - .h2f_rst_n (hps_h2f_reset_reset), // h2f_reset.reset_n - .f2h_sdram0_clk (clk_vip_clk), // f2h_sdram0_clock.clk - .f2h_sdram0_ADDRESS (ram_vip_address), // f2h_sdram0_data.address - .f2h_sdram0_BURSTCOUNT (ram_vip_burstcount), // .burstcount - .f2h_sdram0_WAITREQUEST (ram_vip_waitrequest), // .waitrequest - .f2h_sdram0_READDATA (ram_vip_readdata), // .readdata - .f2h_sdram0_READDATAVALID (ram_vip_readdatavalid), // .readdatavalid - .f2h_sdram0_READ (ram_vip_read), // .read - .f2h_sdram0_WRITEDATA (ram_vip_writedata), // .writedata - .f2h_sdram0_BYTEENABLE (ram_vip_byteenable), // .byteenable - .f2h_sdram0_WRITE (ram_vip_write), // .write - .f2h_sdram1_clk (ramclk1_clk), // f2h_sdram1_clock.clk - .f2h_sdram1_ADDRESS (ram1_address), // f2h_sdram1_data.address - .f2h_sdram1_BURSTCOUNT (ram1_burstcount), // .burstcount - .f2h_sdram1_WAITREQUEST (ram1_waitrequest), // .waitrequest - .f2h_sdram1_READDATA (ram1_readdata), // .readdata - .f2h_sdram1_READDATAVALID (ram1_readdatavalid), // .readdatavalid - .f2h_sdram1_READ (ram1_read), // .read - .f2h_sdram1_WRITEDATA (ram1_writedata), // .writedata - .f2h_sdram1_BYTEENABLE (ram1_byteenable), // .byteenable - .f2h_sdram1_WRITE (ram1_write), // .write - .f2h_sdram2_clk (ramclk2_clk), // f2h_sdram2_clock.clk - .f2h_sdram2_ADDRESS (ram2_address), // f2h_sdram2_data.address - .f2h_sdram2_BURSTCOUNT (ram2_burstcount), // .burstcount - .f2h_sdram2_WAITREQUEST (ram2_waitrequest), // .waitrequest - .f2h_sdram2_READDATA (ram2_readdata), // .readdata - .f2h_sdram2_READDATAVALID (ram2_readdatavalid), // .readdatavalid - .f2h_sdram2_READ (ram2_read), // .read - .f2h_sdram2_WRITEDATA (ram2_writedata), // .writedata - .f2h_sdram2_BYTEENABLE (ram2_byteenable), // .byteenable - .f2h_sdram2_WRITE (ram2_write) // .write -); - -reset_source reset_source ( - .clk (clk_vip_clk), // clock.clk - .reset_hps (~hps_h2f_reset_reset), // reset_hps.reset - .reset_sys (reset_vip_reset), // reset_sys.reset - .cold_req (reset_cold_req), // reset_ctl.cold_req - .reset (reset_reset), // .reset - .reset_req (reset_reset_req), // .reset_req - .warm_req (reset_warm_req), // .warm_req - .reset_warm (reset_source_reset_warm_reset), // reset_warm.reset - .reset_cold (reset_source_reset_cold_reset) // reset_cold.reset -); - -endmodule - -module sysmem_HPS_fpga_interfaces -( - // h2f_reset - output wire [1 - 1 : 0 ] h2f_rst_n - - // f2h_cold_reset_req - ,input wire [1 - 1 : 0 ] f2h_cold_rst_req_n - - // f2h_warm_reset_req - ,input wire [1 - 1 : 0 ] f2h_warm_rst_req_n - - // h2f_user0_clock - ,output wire [1 - 1 : 0 ] h2f_user0_clk - - // f2h_sdram0_data - ,input wire [28 - 1 : 0 ] f2h_sdram0_ADDRESS - ,input wire [8 - 1 : 0 ] f2h_sdram0_BURSTCOUNT - ,output wire [1 - 1 : 0 ] f2h_sdram0_WAITREQUEST - ,output wire [128 - 1 : 0 ] f2h_sdram0_READDATA - ,output wire [1 - 1 : 0 ] f2h_sdram0_READDATAVALID - ,input wire [1 - 1 : 0 ] f2h_sdram0_READ - ,input wire [128 - 1 : 0 ] f2h_sdram0_WRITEDATA - ,input wire [16 - 1 : 0 ] f2h_sdram0_BYTEENABLE - ,input wire [1 - 1 : 0 ] f2h_sdram0_WRITE - - // f2h_sdram0_clock - ,input wire [1 - 1 : 0 ] f2h_sdram0_clk - - // f2h_sdram1_data - ,input wire [29 - 1 : 0 ] f2h_sdram1_ADDRESS - ,input wire [8 - 1 : 0 ] f2h_sdram1_BURSTCOUNT - ,output wire [1 - 1 : 0 ] f2h_sdram1_WAITREQUEST - ,output wire [64 - 1 : 0 ] f2h_sdram1_READDATA - ,output wire [1 - 1 : 0 ] f2h_sdram1_READDATAVALID - ,input wire [1 - 1 : 0 ] f2h_sdram1_READ - ,input wire [64 - 1 : 0 ] f2h_sdram1_WRITEDATA - ,input wire [8 - 1 : 0 ] f2h_sdram1_BYTEENABLE - ,input wire [1 - 1 : 0 ] f2h_sdram1_WRITE - - // f2h_sdram1_clock - ,input wire [1 - 1 : 0 ] f2h_sdram1_clk - - // f2h_sdram2_data - ,input wire [29 - 1 : 0 ] f2h_sdram2_ADDRESS - ,input wire [8 - 1 : 0 ] f2h_sdram2_BURSTCOUNT - ,output wire [1 - 1 : 0 ] f2h_sdram2_WAITREQUEST - ,output wire [64 - 1 : 0 ] f2h_sdram2_READDATA - ,output wire [1 - 1 : 0 ] f2h_sdram2_READDATAVALID - ,input wire [1 - 1 : 0 ] f2h_sdram2_READ - ,input wire [64 - 1 : 0 ] f2h_sdram2_WRITEDATA - ,input wire [8 - 1 : 0 ] f2h_sdram2_BYTEENABLE - ,input wire [1 - 1 : 0 ] f2h_sdram2_WRITE - - // f2h_sdram2_clock - ,input wire [1 - 1 : 0 ] f2h_sdram2_clk -); - - -wire [29 - 1 : 0] intermediate; -assign intermediate[0:0] = ~intermediate[1:1]; -assign intermediate[8:8] = intermediate[4:4]|intermediate[7:7]; -assign intermediate[2:2] = intermediate[9:9]; -assign intermediate[3:3] = intermediate[9:9]; -assign intermediate[5:5] = intermediate[9:9]; -assign intermediate[6:6] = intermediate[9:9]; -assign intermediate[10:10] = intermediate[9:9]; -assign intermediate[11:11] = ~intermediate[12:12]; -assign intermediate[17:17] = intermediate[14:14]|intermediate[16:16]; -assign intermediate[13:13] = intermediate[18:18]; -assign intermediate[15:15] = intermediate[18:18]; -assign intermediate[19:19] = intermediate[18:18]; -assign intermediate[20:20] = ~intermediate[21:21]; -assign intermediate[26:26] = intermediate[23:23]|intermediate[25:25]; -assign intermediate[22:22] = intermediate[27:27]; -assign intermediate[24:24] = intermediate[27:27]; -assign intermediate[28:28] = intermediate[27:27]; -assign f2h_sdram0_WAITREQUEST[0:0] = intermediate[0:0]; -assign f2h_sdram1_WAITREQUEST[0:0] = intermediate[11:11]; -assign f2h_sdram2_WAITREQUEST[0:0] = intermediate[20:20]; -assign intermediate[4:4] = f2h_sdram0_READ[0:0]; -assign intermediate[7:7] = f2h_sdram0_WRITE[0:0]; -assign intermediate[9:9] = f2h_sdram0_clk[0:0]; -assign intermediate[14:14] = f2h_sdram1_READ[0:0]; -assign intermediate[16:16] = f2h_sdram1_WRITE[0:0]; -assign intermediate[18:18] = f2h_sdram1_clk[0:0]; -assign intermediate[23:23] = f2h_sdram2_READ[0:0]; -assign intermediate[25:25] = f2h_sdram2_WRITE[0:0]; -assign intermediate[27:27] = f2h_sdram2_clk[0:0]; - -cyclonev_hps_interface_clocks_resets clocks_resets( - .f2h_warm_rst_req_n({ - f2h_warm_rst_req_n[0:0] // 0:0 - }) -,.f2h_pending_rst_ack({ - 1'b1 // 0:0 - }) -,.f2h_dbg_rst_req_n({ - 1'b1 // 0:0 - }) -,.h2f_rst_n({ - h2f_rst_n[0:0] // 0:0 - }) -,.f2h_cold_rst_req_n({ - f2h_cold_rst_req_n[0:0] // 0:0 - }) -,.h2f_user0_clk({ - h2f_user0_clk[0:0] // 0:0 - }) -); - - -cyclonev_hps_interface_dbg_apb debug_apb( - .DBG_APB_DISABLE({ - 1'b0 // 0:0 - }) -,.P_CLK_EN({ - 1'b0 // 0:0 - }) -); - - -cyclonev_hps_interface_tpiu_trace tpiu( - .traceclk_ctl({ - 1'b1 // 0:0 - }) -); - - -cyclonev_hps_interface_boot_from_fpga boot_from_fpga( - .boot_from_fpga_ready({ - 1'b0 // 0:0 - }) -,.boot_from_fpga_on_failure({ - 1'b0 // 0:0 - }) -,.bsel_en({ - 1'b0 // 0:0 - }) -,.csel_en({ - 1'b0 // 0:0 - }) -,.csel({ - 2'b01 // 1:0 - }) -,.bsel({ - 3'b001 // 2:0 - }) -); - - -cyclonev_hps_interface_fpga2hps fpga2hps( - .port_size_config({ - 2'b11 // 1:0 - }) -); - - -cyclonev_hps_interface_hps2fpga hps2fpga( - .port_size_config({ - 2'b11 // 1:0 - }) -); - - -cyclonev_hps_interface_fpga2sdram f2sdram( - .cfg_rfifo_cport_map({ - 16'b0010000100000000 // 15:0 - }) -,.cfg_wfifo_cport_map({ - 16'b0010000100000000 // 15:0 - }) -,.rd_ready_3({ - 1'b1 // 0:0 - }) -,.cmd_port_clk_2({ - intermediate[28:28] // 0:0 - }) -,.rd_ready_2({ - 1'b1 // 0:0 - }) -,.cmd_port_clk_1({ - intermediate[19:19] // 0:0 - }) -,.rd_ready_1({ - 1'b1 // 0:0 - }) -,.cmd_port_clk_0({ - intermediate[10:10] // 0:0 - }) -,.rd_ready_0({ - 1'b1 // 0:0 - }) -,.wrack_ready_2({ - 1'b1 // 0:0 - }) -,.wrack_ready_1({ - 1'b1 // 0:0 - }) -,.wrack_ready_0({ - 1'b1 // 0:0 - }) -,.cmd_ready_2({ - intermediate[21:21] // 0:0 - }) -,.cmd_ready_1({ - intermediate[12:12] // 0:0 - }) -,.cmd_ready_0({ - intermediate[1:1] // 0:0 - }) -,.cfg_port_width({ - 12'b000000010110 // 11:0 - }) -,.rd_valid_3({ - f2h_sdram2_READDATAVALID[0:0] // 0:0 - }) -,.rd_valid_2({ - f2h_sdram1_READDATAVALID[0:0] // 0:0 - }) -,.rd_valid_1({ - f2h_sdram0_READDATAVALID[0:0] // 0:0 - }) -,.rd_clk_3({ - intermediate[22:22] // 0:0 - }) -,.rd_data_3({ - f2h_sdram2_READDATA[63:0] // 63:0 - }) -,.rd_clk_2({ - intermediate[13:13] // 0:0 - }) -,.rd_data_2({ - f2h_sdram1_READDATA[63:0] // 63:0 - }) -,.rd_clk_1({ - intermediate[3:3] // 0:0 - }) -,.rd_data_1({ - f2h_sdram0_READDATA[127:64] // 63:0 - }) -,.rd_clk_0({ - intermediate[2:2] // 0:0 - }) -,.rd_data_0({ - f2h_sdram0_READDATA[63:0] // 63:0 - }) -,.cfg_axi_mm_select({ - 6'b000000 // 5:0 - }) -,.cmd_valid_2({ - intermediate[26:26] // 0:0 - }) -,.cmd_valid_1({ - intermediate[17:17] // 0:0 - }) -,.cmd_valid_0({ - intermediate[8:8] // 0:0 - }) -,.cfg_cport_rfifo_map({ - 18'b000000000011010000 // 17:0 - }) -,.wr_data_3({ - 2'b00 // 89:88 - ,f2h_sdram2_BYTEENABLE[7:0] // 87:80 - ,16'b0000000000000000 // 79:64 - ,f2h_sdram2_WRITEDATA[63:0] // 63:0 - }) -,.wr_data_2({ - 2'b00 // 89:88 - ,f2h_sdram1_BYTEENABLE[7:0] // 87:80 - ,16'b0000000000000000 // 79:64 - ,f2h_sdram1_WRITEDATA[63:0] // 63:0 - }) -,.wr_data_1({ - 2'b00 // 89:88 - ,f2h_sdram0_BYTEENABLE[15:8] // 87:80 - ,16'b0000000000000000 // 79:64 - ,f2h_sdram0_WRITEDATA[127:64] // 63:0 - }) -,.cfg_cport_type({ - 12'b000000111111 // 11:0 - }) -,.wr_data_0({ - 2'b00 // 89:88 - ,f2h_sdram0_BYTEENABLE[7:0] // 87:80 - ,16'b0000000000000000 // 79:64 - ,f2h_sdram0_WRITEDATA[63:0] // 63:0 - }) -,.cfg_cport_wfifo_map({ - 18'b000000000011010000 // 17:0 - }) -,.wr_clk_3({ - intermediate[24:24] // 0:0 - }) -,.wr_clk_2({ - intermediate[15:15] // 0:0 - }) -,.wr_clk_1({ - intermediate[6:6] // 0:0 - }) -,.wr_clk_0({ - intermediate[5:5] // 0:0 - }) -,.cmd_data_2({ - 18'b000000000000000000 // 59:42 - ,f2h_sdram2_BURSTCOUNT[7:0] // 41:34 - ,3'b000 // 33:31 - ,f2h_sdram2_ADDRESS[28:0] // 30:2 - ,intermediate[25:25] // 1:1 - ,intermediate[23:23] // 0:0 - }) -,.cmd_data_1({ - 18'b000000000000000000 // 59:42 - ,f2h_sdram1_BURSTCOUNT[7:0] // 41:34 - ,3'b000 // 33:31 - ,f2h_sdram1_ADDRESS[28:0] // 30:2 - ,intermediate[16:16] // 1:1 - ,intermediate[14:14] // 0:0 - }) -,.cmd_data_0({ - 18'b000000000000000000 // 59:42 - ,f2h_sdram0_BURSTCOUNT[7:0] // 41:34 - ,4'b0000 // 33:30 - ,f2h_sdram0_ADDRESS[27:0] // 29:2 - ,intermediate[7:7] // 1:1 - ,intermediate[4:4] // 0:0 - }) -); - -endmodule + .f2h_cold_rst_req_n (~reset_hps_cold_req), + .f2h_warm_rst_req_n (~reset_hps_warm_req), + .h2f_user0_clk (clock), + .h2f_rst_n (hps_h2f_reset_n), + .f2h_sdram0_clk (vbuf_clk), + .f2h_sdram0_ADDRESS (vbuf_address), + .f2h_sdram0_BURSTCOUNT (vbuf_burstcount), + .f2h_sdram0_WAITREQUEST (vbuf_waitrequest), + .f2h_sdram0_READDATA (vbuf_readdata), + .f2h_sdram0_READDATAVALID (vbuf_readdatavalid), + .f2h_sdram0_READ (vbuf_read), + .f2h_sdram0_WRITEDATA (vbuf_writedata), + .f2h_sdram0_BYTEENABLE (vbuf_byteenable), + .f2h_sdram0_WRITE (vbuf_write), + .f2h_sdram1_clk (ram1_clk), + .f2h_sdram1_ADDRESS (ram1_address), + .f2h_sdram1_BURSTCOUNT (ram1_burstcount), + .f2h_sdram1_WAITREQUEST (ram1_waitrequest), + .f2h_sdram1_READDATA (ram1_readdata), + .f2h_sdram1_READDATAVALID (ram1_readdatavalid), + .f2h_sdram1_READ (ram1_read), + .f2h_sdram1_WRITEDATA (ram1_writedata), + .f2h_sdram1_BYTEENABLE (ram1_byteenable), + .f2h_sdram1_WRITE (ram1_write), + .f2h_sdram2_clk (ram2_clk), + .f2h_sdram2_ADDRESS (ram2_address), + .f2h_sdram2_BURSTCOUNT (ram2_burstcount), + .f2h_sdram2_WAITREQUEST (ram2_waitrequest), + .f2h_sdram2_READDATA (ram2_readdata), + .f2h_sdram2_READDATAVALID (ram2_readdatavalid), + .f2h_sdram2_READ (ram2_read), + .f2h_sdram2_WRITEDATA (ram2_writedata), + .f2h_sdram2_BYTEENABLE (ram2_byteenable), + .f2h_sdram2_WRITE (ram2_write) +); + +wire hps_h2f_reset_n; + +reg init_reset_n = 0; +always @(posedge clock) begin + integer timeout = 0; + + if(timeout < 2000000) begin + init_reset_n <= 0; + timeout <= timeout + 1; + end + else init_reset_n <= 1; +end + +endmodule + + +module sysmem_HPS_fpga_interfaces +( + // h2f_reset + output wire [1 - 1 : 0 ] h2f_rst_n + + // f2h_cold_reset_req + ,input wire [1 - 1 : 0 ] f2h_cold_rst_req_n + + // f2h_warm_reset_req + ,input wire [1 - 1 : 0 ] f2h_warm_rst_req_n + + // h2f_user0_clock + ,output wire [1 - 1 : 0 ] h2f_user0_clk + + // f2h_sdram0_data + ,input wire [28 - 1 : 0 ] f2h_sdram0_ADDRESS + ,input wire [8 - 1 : 0 ] f2h_sdram0_BURSTCOUNT + ,output wire [1 - 1 : 0 ] f2h_sdram0_WAITREQUEST + ,output wire [128 - 1 : 0 ] f2h_sdram0_READDATA + ,output wire [1 - 1 : 0 ] f2h_sdram0_READDATAVALID + ,input wire [1 - 1 : 0 ] f2h_sdram0_READ + ,input wire [128 - 1 : 0 ] f2h_sdram0_WRITEDATA + ,input wire [16 - 1 : 0 ] f2h_sdram0_BYTEENABLE + ,input wire [1 - 1 : 0 ] f2h_sdram0_WRITE + + // f2h_sdram0_clock + ,input wire [1 - 1 : 0 ] f2h_sdram0_clk + + // f2h_sdram1_data + ,input wire [29 - 1 : 0 ] f2h_sdram1_ADDRESS + ,input wire [8 - 1 : 0 ] f2h_sdram1_BURSTCOUNT + ,output wire [1 - 1 : 0 ] f2h_sdram1_WAITREQUEST + ,output wire [64 - 1 : 0 ] f2h_sdram1_READDATA + ,output wire [1 - 1 : 0 ] f2h_sdram1_READDATAVALID + ,input wire [1 - 1 : 0 ] f2h_sdram1_READ + ,input wire [64 - 1 : 0 ] f2h_sdram1_WRITEDATA + ,input wire [8 - 1 : 0 ] f2h_sdram1_BYTEENABLE + ,input wire [1 - 1 : 0 ] f2h_sdram1_WRITE + + // f2h_sdram1_clock + ,input wire [1 - 1 : 0 ] f2h_sdram1_clk + + // f2h_sdram2_data + ,input wire [29 - 1 : 0 ] f2h_sdram2_ADDRESS + ,input wire [8 - 1 : 0 ] f2h_sdram2_BURSTCOUNT + ,output wire [1 - 1 : 0 ] f2h_sdram2_WAITREQUEST + ,output wire [64 - 1 : 0 ] f2h_sdram2_READDATA + ,output wire [1 - 1 : 0 ] f2h_sdram2_READDATAVALID + ,input wire [1 - 1 : 0 ] f2h_sdram2_READ + ,input wire [64 - 1 : 0 ] f2h_sdram2_WRITEDATA + ,input wire [8 - 1 : 0 ] f2h_sdram2_BYTEENABLE + ,input wire [1 - 1 : 0 ] f2h_sdram2_WRITE + + // f2h_sdram2_clock + ,input wire [1 - 1 : 0 ] f2h_sdram2_clk +); + + +wire [29 - 1 : 0] intermediate; +assign intermediate[0:0] = ~intermediate[1:1]; +assign intermediate[8:8] = intermediate[4:4]|intermediate[7:7]; +assign intermediate[2:2] = intermediate[9:9]; +assign intermediate[3:3] = intermediate[9:9]; +assign intermediate[5:5] = intermediate[9:9]; +assign intermediate[6:6] = intermediate[9:9]; +assign intermediate[10:10] = intermediate[9:9]; +assign intermediate[11:11] = ~intermediate[12:12]; +assign intermediate[17:17] = intermediate[14:14]|intermediate[16:16]; +assign intermediate[13:13] = intermediate[18:18]; +assign intermediate[15:15] = intermediate[18:18]; +assign intermediate[19:19] = intermediate[18:18]; +assign intermediate[20:20] = ~intermediate[21:21]; +assign intermediate[26:26] = intermediate[23:23]|intermediate[25:25]; +assign intermediate[22:22] = intermediate[27:27]; +assign intermediate[24:24] = intermediate[27:27]; +assign intermediate[28:28] = intermediate[27:27]; +assign f2h_sdram0_WAITREQUEST[0:0] = intermediate[0:0]; +assign f2h_sdram1_WAITREQUEST[0:0] = intermediate[11:11]; +assign f2h_sdram2_WAITREQUEST[0:0] = intermediate[20:20]; +assign intermediate[4:4] = f2h_sdram0_READ[0:0]; +assign intermediate[7:7] = f2h_sdram0_WRITE[0:0]; +assign intermediate[9:9] = f2h_sdram0_clk[0:0]; +assign intermediate[14:14] = f2h_sdram1_READ[0:0]; +assign intermediate[16:16] = f2h_sdram1_WRITE[0:0]; +assign intermediate[18:18] = f2h_sdram1_clk[0:0]; +assign intermediate[23:23] = f2h_sdram2_READ[0:0]; +assign intermediate[25:25] = f2h_sdram2_WRITE[0:0]; +assign intermediate[27:27] = f2h_sdram2_clk[0:0]; + +cyclonev_hps_interface_clocks_resets clocks_resets( + .f2h_warm_rst_req_n({ + f2h_warm_rst_req_n[0:0] // 0:0 + }) +,.f2h_pending_rst_ack({ + 1'b1 // 0:0 + }) +,.f2h_dbg_rst_req_n({ + 1'b1 // 0:0 + }) +,.h2f_rst_n({ + h2f_rst_n[0:0] // 0:0 + }) +,.f2h_cold_rst_req_n({ + f2h_cold_rst_req_n[0:0] // 0:0 + }) +,.h2f_user0_clk({ + h2f_user0_clk[0:0] // 0:0 + }) +); + + +cyclonev_hps_interface_dbg_apb debug_apb( + .DBG_APB_DISABLE({ + 1'b0 // 0:0 + }) +,.P_CLK_EN({ + 1'b0 // 0:0 + }) +); + + +cyclonev_hps_interface_tpiu_trace tpiu( + .traceclk_ctl({ + 1'b1 // 0:0 + }) +); + + +cyclonev_hps_interface_boot_from_fpga boot_from_fpga( + .boot_from_fpga_ready({ + 1'b0 // 0:0 + }) +,.boot_from_fpga_on_failure({ + 1'b0 // 0:0 + }) +,.bsel_en({ + 1'b0 // 0:0 + }) +,.csel_en({ + 1'b0 // 0:0 + }) +,.csel({ + 2'b01 // 1:0 + }) +,.bsel({ + 3'b001 // 2:0 + }) +); + + +cyclonev_hps_interface_fpga2hps fpga2hps( + .port_size_config({ + 2'b11 // 1:0 + }) +); + + +cyclonev_hps_interface_hps2fpga hps2fpga( + .port_size_config({ + 2'b11 // 1:0 + }) +); + + +cyclonev_hps_interface_fpga2sdram f2sdram( + .cfg_rfifo_cport_map({ + 16'b0010000100000000 // 15:0 + }) +,.cfg_wfifo_cport_map({ + 16'b0010000100000000 // 15:0 + }) +,.rd_ready_3({ + 1'b1 // 0:0 + }) +,.cmd_port_clk_2({ + intermediate[28:28] // 0:0 + }) +,.rd_ready_2({ + 1'b1 // 0:0 + }) +,.cmd_port_clk_1({ + intermediate[19:19] // 0:0 + }) +,.rd_ready_1({ + 1'b1 // 0:0 + }) +,.cmd_port_clk_0({ + intermediate[10:10] // 0:0 + }) +,.rd_ready_0({ + 1'b1 // 0:0 + }) +,.wrack_ready_2({ + 1'b1 // 0:0 + }) +,.wrack_ready_1({ + 1'b1 // 0:0 + }) +,.wrack_ready_0({ + 1'b1 // 0:0 + }) +,.cmd_ready_2({ + intermediate[21:21] // 0:0 + }) +,.cmd_ready_1({ + intermediate[12:12] // 0:0 + }) +,.cmd_ready_0({ + intermediate[1:1] // 0:0 + }) +,.cfg_port_width({ + 12'b000000010110 // 11:0 + }) +,.rd_valid_3({ + f2h_sdram2_READDATAVALID[0:0] // 0:0 + }) +,.rd_valid_2({ + f2h_sdram1_READDATAVALID[0:0] // 0:0 + }) +,.rd_valid_1({ + f2h_sdram0_READDATAVALID[0:0] // 0:0 + }) +,.rd_clk_3({ + intermediate[22:22] // 0:0 + }) +,.rd_data_3({ + f2h_sdram2_READDATA[63:0] // 63:0 + }) +,.rd_clk_2({ + intermediate[13:13] // 0:0 + }) +,.rd_data_2({ + f2h_sdram1_READDATA[63:0] // 63:0 + }) +,.rd_clk_1({ + intermediate[3:3] // 0:0 + }) +,.rd_data_1({ + f2h_sdram0_READDATA[127:64] // 63:0 + }) +,.rd_clk_0({ + intermediate[2:2] // 0:0 + }) +,.rd_data_0({ + f2h_sdram0_READDATA[63:0] // 63:0 + }) +,.cfg_axi_mm_select({ + 6'b000000 // 5:0 + }) +,.cmd_valid_2({ + intermediate[26:26] // 0:0 + }) +,.cmd_valid_1({ + intermediate[17:17] // 0:0 + }) +,.cmd_valid_0({ + intermediate[8:8] // 0:0 + }) +,.cfg_cport_rfifo_map({ + 18'b000000000011010000 // 17:0 + }) +,.wr_data_3({ + 2'b00 // 89:88 + ,f2h_sdram2_BYTEENABLE[7:0] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram2_WRITEDATA[63:0] // 63:0 + }) +,.wr_data_2({ + 2'b00 // 89:88 + ,f2h_sdram1_BYTEENABLE[7:0] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram1_WRITEDATA[63:0] // 63:0 + }) +,.wr_data_1({ + 2'b00 // 89:88 + ,f2h_sdram0_BYTEENABLE[15:8] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram0_WRITEDATA[127:64] // 63:0 + }) +,.cfg_cport_type({ + 12'b000000111111 // 11:0 + }) +,.wr_data_0({ + 2'b00 // 89:88 + ,f2h_sdram0_BYTEENABLE[7:0] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram0_WRITEDATA[63:0] // 63:0 + }) +,.cfg_cport_wfifo_map({ + 18'b000000000011010000 // 17:0 + }) +,.wr_clk_3({ + intermediate[24:24] // 0:0 + }) +,.wr_clk_2({ + intermediate[15:15] // 0:0 + }) +,.wr_clk_1({ + intermediate[6:6] // 0:0 + }) +,.wr_clk_0({ + intermediate[5:5] // 0:0 + }) +,.cmd_data_2({ + 18'b000000000000000000 // 59:42 + ,f2h_sdram2_BURSTCOUNT[7:0] // 41:34 + ,3'b000 // 33:31 + ,f2h_sdram2_ADDRESS[28:0] // 30:2 + ,intermediate[25:25] // 1:1 + ,intermediate[23:23] // 0:0 + }) +,.cmd_data_1({ + 18'b000000000000000000 // 59:42 + ,f2h_sdram1_BURSTCOUNT[7:0] // 41:34 + ,3'b000 // 33:31 + ,f2h_sdram1_ADDRESS[28:0] // 30:2 + ,intermediate[16:16] // 1:1 + ,intermediate[14:14] // 0:0 + }) +,.cmd_data_0({ + 18'b000000000000000000 // 59:42 + ,f2h_sdram0_BURSTCOUNT[7:0] // 41:34 + ,4'b0000 // 33:30 + ,f2h_sdram0_ADDRESS[27:0] // 29:2 + ,intermediate[7:7] // 1:1 + ,intermediate[4:4] // 0:0 + }) +); + +endmodule diff --git a/sys/video_cleaner.sv b/sys/video_cleaner.sv new file mode 100644 index 0000000..f9f23d2 --- /dev/null +++ b/sys/video_cleaner.sv @@ -0,0 +1,91 @@ +// +// +// Copyright (c) 2018 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +module video_cleaner +( + input clk_vid, + input ce_pix, + + input [7:0] R, + input [7:0] G, + input [7:0] B, + + input HSync, + input VSync, + input HBlank, + input VBlank, + + // video output signals + output reg [7:0] VGA_R, + output reg [7:0] VGA_G, + output reg [7:0] VGA_B, + output reg VGA_VS, + output reg VGA_HS, + output VGA_DE, + + // optional aligned blank + output reg HBlank_out, + output reg VBlank_out +); + +wire hs, vs; +s_fix sync_v(clk_vid, HSync, hs); +s_fix sync_h(clk_vid, VSync, vs); + +wire hbl = hs | HBlank; +wire vbl = vs | VBlank; + +assign VGA_DE = ~(HBlank_out | VBlank_out); + +always @(posedge clk_vid) begin + if(ce_pix) begin + HBlank_out <= hbl; + + VGA_VS <= vs; + VGA_HS <= hs; + VGA_R <= R; + VGA_G <= G; + VGA_B <= B; + + if(HBlank_out & ~hbl) VBlank_out <= vbl; + end +end + +endmodule + +module s_fix +( + input clk, + + input sync_in, + output sync_out +); + +assign sync_out = sync_in ^ pol; + +reg pol; +always @(posedge clk) begin + integer pos = 0, neg = 0, cnt = 0; + reg s1,s2; + + s1 <= sync_in; + s2 <= s1; + + if(~s2 & s1) neg <= cnt; + if(s2 & ~s1) pos <= cnt; + + cnt <= cnt + 1; + if(s2 != s1) cnt <= 0; + + pol <= pos > neg; +end + +endmodule diff --git a/sys/vip.qsys b/sys/vip.qsys index 47306be..d49b11c 100644 --- a/sys/vip.qsys +++ b/sys/vip.qsys @@ -13,7 +13,15 @@ { datum _sortIndex { - value = "9"; + value = "10"; + type = "int"; + } + } + element Deinterlacer + { + datum _sortIndex + { + value = "4"; type = "int"; } } @@ -21,7 +29,7 @@ { datum _sortIndex { - value = "4"; + value = "5"; type = "int"; } } @@ -45,7 +53,7 @@ { datum _sortIndex { - value = "6"; + value = "7"; type = "int"; } } @@ -53,7 +61,7 @@ { datum _sortIndex { - value = "8"; + value = "9"; type = "int"; } } @@ -69,7 +77,7 @@ { datum _sortIndex { - value = "5"; + value = "6"; type = "int"; } } @@ -85,7 +93,7 @@ { datum _sortIndex { - value = "7"; + value = "8"; type = "int"; } } @@ -505,62 +513,6 @@ type = "String"; } } - element vip - { - datum _originalDeviceFamily - { - value = "Cyclone V"; - type = "String"; - } - } - element vip - { - datum _originalDeviceFamily - { - value = "Cyclone V"; - type = "String"; - } - } - element vip - { - datum _originalDeviceFamily - { - value = "Cyclone V"; - type = "String"; - } - } - element vip - { - datum _originalDeviceFamily - { - value = "Cyclone V"; - type = "String"; - } - } - element vip - { - datum _originalDeviceFamily - { - value = "Cyclone V"; - type = "String"; - } - } - element vip - { - datum _originalDeviceFamily - { - value = "Cyclone V"; - type = "String"; - } - } - element vip - { - datum _originalDeviceFamily - { - value = "Cyclone V"; - type = "String"; - } - } } ]]> @@ -586,8 +538,6 @@ - - @@ -598,12 +548,52 @@ type="conduit" dir="end" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -880,7 +870,7 @@ - + @@ -890,7 +880,7 @@ - + ]]> @@ -901,8 +891,8 @@ - - + + @@ -914,13 +904,13 @@ - - + + ]]> - + @@ -1027,6 +1017,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + end="Deinterlacer.din" /> + + - + + + + + >5) - 5: begin - w <= WIDTH; - hfp <= HFP; - hbp <= HBP; - hs <= HS; - h <= HEIGHT; - vfp <= VFP; - vbp <= VBP; - vs <= VS; - end - 4: begin - hb <= hfp+hbp+hs; - vb <= vfp+vbp+vs; - end - 3: begin - wcalc <= vset ? (vset*arx)/ary : (h*arx)/ary; - hcalc <= (w*ary)/arx; - end - 2: begin - videow <= (!vset && (wcalc > w)) ? w : wcalc[11:0]; - videoh <= vset ? vset : (hcalc > h) ? h : hcalc[11:0]; - end - 1: begin - posx <= (w - videow)>>1; - posy <= (h - videoh)>>1; - end - endcase - end - else - if(~waitrequest && state) - begin - state <= state + 1'd1; - write <= 0; - if((state&3)==3) begin - if(init[state>>2] == 22'h3FFFFF) begin - state <= 0; - newres <= 0; - end - else begin - writedata <= 0; - {write, address, writedata[11:0]} <= init[state>>2]; - end - end - end -end - -endmodule + +module vip_config +( + input clk, + input reset, + + input [7:0] ARX, + input [7:0] ARY, + input CFG_SET, + + input [11:0] WIDTH, + input [11:0] HFP, + input [11:0] HBP, + input [11:0] HS, + input [11:0] HEIGHT, + input [11:0] VFP, + input [11:0] VBP, + input [11:0] VS, + + input [11:0] VSET, + input coef_set, + input coef_clk, + input [6:0] coef_addr, + input [8:0] coef_data, + input coef_wr, + input [2:0] scaler_flt, + + output reg [8:0] address, + output reg write, + output reg [31:0] writedata, + input waitrequest +); + + +reg newres = 1; + +wire [21:0] init[23] = +'{ + //video mode + {newres, 2'd2, 7'd04, 12'd0 }, //Bank + {newres, 2'd2, 7'd30, 12'd0 }, //Valid + {newres, 2'd2, 7'd05, 12'd0 }, //Progressive/Interlaced + {newres, 2'd2, 7'd06, w }, //Active pixel count + {newres, 2'd2, 7'd07, h }, //Active line count + {newres, 2'd2, 7'd09, hfp }, //Horizontal Front Porch + {newres, 2'd2, 7'd10, hs }, //Horizontal Sync Length + {newres, 2'd2, 7'd11, hb }, //Horizontal Blanking (HFP+HBP+HSync) + {newres, 2'd2, 7'd12, vfp }, //Vertical Front Porch + {newres, 2'd2, 7'd13, vs }, //Vertical Sync Length + {newres, 2'd2, 7'd14, vb }, //Vertical blanking (VFP+VBP+VSync) + {newres, 2'd2, 7'd30, 12'd1 }, //Valid + {newres, 2'd2, 7'd00, 12'd1 }, //Go + + //mixer + { 1'd1, 2'd1, 7'd03, w }, //Bkg Width + { 1'd1, 2'd1, 7'd04, h }, //Bkg Height + { 1'd1, 2'd1, 7'd08, posx }, //Pos X + { 1'd1, 2'd1, 7'd09, posy }, //Pos Y + { 1'd1, 2'd1, 7'd10, 12'd1 }, //Enable Video 0 + { 1'd1, 2'd1, 7'd00, 12'd1 }, //Go + + //scaler + { 1'd1, 2'd0, 7'd03, videow }, //Output Width + { 1'd1, 2'd0, 7'd04, videoh }, //Output Height + { 1'd1, 2'd0, 7'd00, 12'd1 }, //Go + + 22'h3FFFFF +}; + +reg [6:0] coef_a; +wire [8:0] coef_q; + coeffbuf coeffbuf +( + .wrclock(coef_clk), + .wraddress({1'b1,coef_addr}), + .data(coef_data), + .wren(coef_wr), + .rdclock(clk), + .rdaddress({|scaler_flt,coef_a}), + .q(coef_q) +); +reg [11:0] w; +reg [11:0] hfp; +reg [11:0] hbp; +reg [11:0] hs; +reg [11:0] hb; +reg [11:0] h; +reg [11:0] vfp; +reg [11:0] vbp; +reg [11:0] vs; +reg [11:0] vb; + +reg [11:0] videow; +reg [11:0] videoh; + +reg [11:0] posx; +reg [11:0] posy; + +always @(posedge clk) begin + reg [7:0] state = 0; + reg [7:0] arx, ary; + reg [7:0] arxd, aryd; + reg [11:0] vset, vsetd; + reg cfg, cfgd; + reg [31:0] wcalc; + reg [31:0] hcalc; + reg [12:0] timeout = 0; + reg [4:0] coef_state = 0; + reg [6:0] coef_n; + reg coef_setd; + reg bank = 0; + + arxd <= ARX; + aryd <= ARY; + vsetd <= VSET; + coef_setd <= coef_set; + + cfg <= CFG_SET; + cfgd <= cfg; + + if(reset || (arx != arxd) || (ary != aryd) || (vset != vsetd) || (~cfgd && cfg) || (coef_setd ^ coef_set)) begin + arx <= arxd; + ary <= aryd; + vset <= vsetd; + timeout <= '1; + state <= 0; + if(reset || (~cfgd && cfg)) newres <= 1; + end + else + if(timeout > 0) + begin + timeout <= timeout - 1'd1; + state <= 1; + if(!(timeout & 'h1f)) case(timeout>>5) + 5: begin + w <= WIDTH; + hfp <= HFP; + hbp <= HBP; + hs <= HS; + h <= HEIGHT; + vfp <= VFP; + vbp <= VBP; + vs <= VS; + end + 4: begin + hb <= hfp+hbp+hs; + vb <= vfp+vbp+vs; + end + 3: begin + wcalc <= vset ? (vset*arx)/ary : (h*arx)/ary; + hcalc <= (w*ary)/arx; + end + 2: begin + videow <= (!vset && (wcalc > w)) ? w : wcalc[11:0]; + videoh <= vset ? vset : (hcalc > h) ? h : hcalc[11:0]; + end + 1: begin + posx <= (w - videow)>>1; + posy <= (h - videoh)>>1; + end + endcase + end + else +if(~waitrequest) + begin + + write <= 0; +if(state) begin + state <= state + 1'd1; + if((state&3)==3) begin + if(init[state>>2] == 22'h3FFFFF) begin + state <= 0; + newres <= 0; + coef_state <= 1; + coef_a <= 0; + end + else begin + writedata <= 0; + {write, address, writedata[11:0]} <= init[state>>2]; + end + end + end +else begin + case(coef_state) + 1,3: coef_state <= coef_state + 1'd1; + 2: begin + address <= 8; + writedata <= 0; + writedata[0] <= bank; + write <= 1; + coef_state <= coef_state + 1'd1; + end + 4: begin + address <= 10; + writedata <= 0; + writedata[0] <= bank; + write <= 1; + coef_state <= coef_state + 1'd1; + end + 5,7,9,11: coef_state <= coef_state + 1'd1; + 6,8,10,12: + begin + coef_state <= coef_state + 1'd1; + coef_a <= coef_a + 1'd1; + coef_n <= coef_a; + address <= 9'd14 + coef_a[1:0]; + writedata <= coef_q; + write <= 1; + end + 13: begin + coef_state <= (&coef_n) ? 5'd14 : 5'd5; + address <= 9'd12 + coef_n[6]; + writedata <= coef_n[5:2]; + write <= 1; + end + 14,16: coef_state <= coef_state + 1'd1; + 15: begin + address <= 9; + writedata <= 0; + writedata[0] <= bank; + write <= 1; + coef_state <= coef_state + 1'd1; + end + 17: begin + address <= 11; + writedata <= 0; + writedata[0] <= bank; + write <= 1; + bank <= ~bank; + coef_state <= coef_state + 1'd1; + end + 18: coef_state <= 0; + endcase; + end + end +end + +endmodule +module coeffbuf +( + input wrclock, + input [7:0] wraddress, + input [8:0] data, + input wren, + input rdclock, + input [7:0] rdaddress, + output[8:0] q +); + altsyncram altsyncram_component ( + .address_a (wraddress), + .address_b (rdaddress), + .clock0 (wrclock), + .clock1 (rdclock), + .data_a (data), + .wren_a (wren), + .q_b (q), + .aclr0 (1'b0), + .aclr1 (1'b0), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b ({9{1'b1}}), + .eccstatus (), + .q_a (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); +defparam + altsyncram_component.address_aclr_b = "NONE", + altsyncram_component.address_reg_b = "CLOCK1", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_input_b = "BYPASS", + altsyncram_component.clock_enable_output_b = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone V", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 256, + altsyncram_component.numwords_b = 256, + altsyncram_component.operation_mode = "DUAL_PORT", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.init_file = "coeff.mif", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.widthad_a = 8, + altsyncram_component.widthad_b = 8, + altsyncram_component.width_a = 9, + altsyncram_component.width_b = 9, + altsyncram_component.width_byteena_a = 1; + endmodule