Update sys.

This commit is contained in:
Sorgelig 2023-03-02 01:08:42 +08:00
parent 8dd279eef3
commit 98b7a395ce
11 changed files with 3222 additions and 3067 deletions

View File

@ -52,13 +52,14 @@ module emu
output VGA_F1,
output [1:0] VGA_SL,
output VGA_SCALER, // Force VGA scaler
output VGA_DISABLE, // analog out is off
input [11:0] HDMI_WIDTH,
input [11:0] HDMI_HEIGHT,
output HDMI_FREEZE,
`ifdef MISTER_FB
// Use framebuffer in DDRAM (USE_FB=1 in qsf)
// Use framebuffer in DDRAM
// FB_FORMAT:
// [2:0] : 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp
// [3] : 0=16bits 565 1=16bits 1555
@ -185,6 +186,7 @@ assign LED_POWER = 0;
assign BUTTONS = 0;
assign VGA_SCALER= 0;
assign HDMI_FREEZE = 0;
assign VGA_DISABLE = 0;
wire [1:0] ar = status[8:7];
video_freak video_freak

View File

@ -220,6 +220,8 @@ ENTITY ascal IS
vdisp : IN natural RANGE 0 TO 4095;
vmin : IN natural RANGE 0 TO 4095;
vmax : IN natural RANGE 0 TO 4095; -- 0 <= vmin < vmax < vdisp
vrr : IN std_logic := '0';
vrrmax : IN natural RANGE 0 TO 4095 := 0;
-- Scaler format. 00=16bpp 565, 01=24bpp 10=32bpp
format : IN unsigned(1 DOWNTO 0) :="01";
@ -423,6 +425,12 @@ ARCHITECTURE rtl OF ascal IS
SIGNAL o_hmin,o_hmax,o_hdisp,o_v_hmin_adj : uint12;
SIGNAL o_hsize,o_vsize : uint12;
SIGNAL o_vtotal,o_vsstart,o_vsend : uint12;
SIGNAL o_vrr,o_isync,o_isync2 : std_logic;
SIGNAL o_vrr_sync,o_vrr_sync2 : boolean;
SIGNAL o_vrr_min,o_vrr_min2 : boolean;
SIGNAL o_vrr_max,o_vrr_max2 : boolean;
SIGNAL o_vcpt_sync,o_vcpt_sync2, o_vrrmax : uint12;
SIGNAL o_sync, o_sync_max : boolean;
SIGNAL o_vmin,o_vmax,o_vdisp : uint12;
SIGNAL o_divcpt : natural RANGE 0 TO 36;
SIGNAL o_iendframe0,o_iendframe02,o_iendframe1,o_iendframe12 : std_logic;
@ -435,7 +443,7 @@ ARCHITECTURE rtl OF ascal IS
SIGNAL o_pshift : natural RANGE 0 TO 15;
SIGNAL o_readack,o_readack_sync,o_readack_sync2 : std_logic;
SIGNAL o_readdataack,o_readdataack_sync,o_readdataack_sync2 : std_logic;
SIGNAL o_copyv : unsigned(0 TO 12);
SIGNAL o_copyv : unsigned(0 TO 14);
SIGNAL o_adrs : unsigned(31 DOWNTO 0); -- Avalon address
SIGNAL o_adrs_pre : natural RANGE 0 TO 2**24-1;
SIGNAL o_stride : unsigned(13 DOWNTO 0);
@ -456,16 +464,16 @@ ARCHITECTURE rtl OF ascal IS
SIGNAL o_wadl,o_radl0,o_radl1,o_radl2,o_radl3 : natural RANGE 0 TO OHRES-1;
SIGNAL o_ldw,o_ldr0,o_ldr1,o_ldr2,o_ldr3 : type_pix;
SIGNAL o_wr : unsigned(3 DOWNTO 0);
SIGNAL o_hcpt,o_vcpt,o_vcpt_pre,o_vcpt_pre2,o_vcpt_pre3 : uint12;
SIGNAL o_hcpt,o_vcpt,o_vcpt_pre,o_vcpt_pre2,o_vcpt_pre3,o_vcpt2 : uint12;
SIGNAL o_ihsize,o_ihsizem,o_ivsize : uint12;
SIGNAL o_ihsize_temp, o_ihsize_temp2 : natural RANGE 0 TO 32767;
SIGNAL o_vfrac : unsigned(11 DOWNTO 0);
SIGNAL o_hfrac : arr_frac(0 TO 8);
SIGNAL o_hfrac : arr_frac(0 TO 9);
ATTRIBUTE ramstyle OF o_hfrac : SIGNAL IS "logic"; -- avoid blockram shift register
SIGNAL o_hacc,o_hacc_ini,o_hacc_next,o_vacc,o_vacc_next,o_vacc_ini : natural RANGE 0 TO 4*OHRES-1;
SIGNAL o_hsv,o_vsv,o_dev,o_pev,o_end : unsigned(0 TO 9);
SIGNAL o_hsv,o_vsv,o_dev,o_pev,o_end : unsigned(0 TO 11);
SIGNAL o_hsp,o_vss : std_logic;
SIGNAL o_vcarrym,o_prim : boolean;
SIGNAL o_read,o_read_pre : std_logic;
@ -482,16 +490,14 @@ ARCHITECTURE rtl OF ascal IS
TYPE arr_uint4 IS ARRAY (natural RANGE <>) OF natural RANGE 0 TO 15;
SIGNAL o_off : arr_uint4(0 TO 2);
SIGNAL o_bibu : std_logic :='0';
SIGNAL o_dcptv : arr_uint12(1 TO 12);
SIGNAL o_dcptv : arr_uint12(1 TO 14);
SIGNAL o_dcpt : uint12;
SIGNAL o_hpixs,o_hpix0,o_hpix1,o_hpix2,o_hpix3 : type_pix;
SIGNAL o_hpixq : arr_pixq(2 TO 6);
SIGNAL o_hpixq : arr_pixq(2 TO 8);
ATTRIBUTE ramstyle OF o_hpixq : SIGNAL IS "logic"; -- avoid blockram shift register
SIGNAL o_vpixq : arr_pix(0 TO 3);
SIGNAL o_vpixq, o_vpixq_pre : arr_pix(0 TO 3);
SIGNAL o_vpix_outer : arr_pix(0 TO 2);
SIGNAL o_vpix_inner : arr_pix(0 TO 5);
-- ATTRIBUTE ramstyle OF o_hpixq : SIGNAL IS "logic";
SIGNAL o_vpix_inner : arr_pix(0 TO 6);
SIGNAL o_vpe : std_logic;
@ -522,7 +528,7 @@ ARCHITECTURE rtl OF ascal IS
END CASE;
END FUNCTION;
FUNCTION shift_ipack(i_dw : unsigned(N_DW-1 DOWNTO 0);
FUNCTION shift_ipack( i_dw : unsigned(N_DW-1 DOWNTO 0);
acpt : natural RANGE 0 TO 15;
shift : unsigned(0 TO 119);
pix : type_pix;
@ -867,7 +873,7 @@ ARCHITECTURE rtl OF ascal IS
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),
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;
@ -964,22 +970,21 @@ ARCHITECTURE rtl OF ascal IS
r0,r1,b0,b1,g0,g1 : signed(26 DOWNTO 0);
END RECORD;
SIGNAL o_h_poly_mem : arr_uv40(0 TO 2**FRAC-1);
SIGNAL o_v_poly_mem : arr_uv40(0 TO 2**FRAC-1);
SIGNAL o_a_poly_mem : arr_uv40(0 TO 2**FRAC-1);
ATTRIBUTE ramstyle OF o_h_poly_mem : SIGNAL IS "no_rw_check";
ATTRIBUTE ramstyle OF o_v_poly_mem : SIGNAL IS "no_rw_check";
ATTRIBUTE ramstyle OF o_a_poly_mem : SIGNAL IS "no_rw_check";
SIGNAL o_a_poly_addr, o_v_poly_addr, o_h_poly_addr : integer RANGE 0 TO 2**FRAC-1;
SIGNAL o_h_poly_phase_a,o_h_poly_phase_a2,o_h_poly_phase_a3 : poly_phase_t;
SIGNAL o_v_poly_phase_a,o_v_poly_phase_a2,o_v_poly_phase_a3 : poly_phase_t;
SIGNAL o_a_poly_addr, o_v_poly_addr : integer RANGE 0 TO 2**FRAC-1;
SIGNAL o_h_poly_phase_a,o_h_poly_phase_a2,o_h_poly_phase_a3, o_h_poly_phase_a4, o_h_poly_phase_a5 : poly_phase_t;
SIGNAL o_v_poly_phase_a,o_v_poly_phase_a2,o_v_poly_phase_a3, o_v_poly_phase_a4, o_v_poly_phase_a5 : poly_phase_t;
SIGNAL o_poly_phase_a, o_poly_phase_a2, o_poly_phase_a3 : poly_phase_t;
SIGNAL o_poly_phase_b,o_poly_phase_b2,o_poly_phase_b3 : poly_phase_t;
SIGNAL o_v_poly_phase, o_v_poly_phase2, o_h_poly_phase, o_poly_phase : poly_phase_interp_t;
SIGNAL o_v_poly_pix, o_h_poly_pix : type_pix;
SIGNAL o_v_poly_lum, o_h_poly_lum, o_poly_lum : unsigned(7 DOWNTO 0);
SIGNAL o_poly_lerp_ta, o_poly_lerp_tb, o_poly_lerp_tb3 : signed(9 DOWNTO 0);
SIGNAL o_v_poly_phase, o_v_poly_phase2, o_h_poly_phase, o_poly_phase, o_poly_phase1 : poly_phase_interp_t;
SIGNAL o_v_poly_pix, o_h_poly_pix, o_h_lum_pix, o_v_lum_pix : type_pix;
SIGNAL o_poly_lum, o_poly_lum1 : unsigned(7 DOWNTO 0);
SIGNAL o_poly_lerp_ta, o_poly_lerp_tb : signed(9 DOWNTO 0);
SIGNAL o_h_poly_t,o_h_poly_t2,o_v_poly_t : type_poly_t;
SIGNAL o_v_poly_adaptive, o_h_poly_adaptive, o_v_poly_use_adaptive, o_h_poly_use_adaptive : std_logic;
@ -987,7 +992,6 @@ ARCHITECTURE rtl OF ascal IS
SIGNAL poly_tdw : unsigned(39 DOWNTO 0);
SIGNAL poly_a2 : unsigned(FRAC-1 DOWNTO 0);
FUNCTION poly_unpack(a : unsigned(39 DOWNTO 0)) RETURN poly_phase_t IS
VARIABLE v : poly_phase_t;
BEGIN
@ -995,7 +999,6 @@ ARCHITECTURE rtl OF ascal IS
v.t1 := signed(a(29 DOWNTO 20));
v.t2 := signed(a(19 DOWNTO 10));
v.t3 := signed(a( 9 DOWNTO 0));
RETURN v;
END FUNCTION;
@ -1144,8 +1147,7 @@ BEGIN
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(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);
@ -1850,10 +1852,15 @@ BEGIN
o_hsize <=o_hmax - o_hmin + 1;
o_vsize <=o_vmax - o_vmin + 1;
o_vrr <=vrr;
o_vrrmax <= vrrmax;
--------------------------------------------
-- Triple buffering.
-- For intelaced video, half frames are updated independently
-- Input : Toggle buffer at end of input frame
o_isync <= '0';
o_isync2 <= o_isync;
o_freeze <= freeze;
o_inter <=i_inter; -- <ASYNC>
o_iendframe0<=i_endframe0; -- <ASYNC>
@ -1861,12 +1868,14 @@ BEGIN
IF o_iendframe0='1' AND o_iendframe02='0' THEN
o_ibuf0<=buf_next(o_ibuf0,o_obuf0,o_freeze);
o_bufup0<='1';
o_isync <= '1';
END IF;
o_iendframe1<=i_endframe1; -- <ASYNC>
o_iendframe12<=o_iendframe1;
IF o_iendframe1='1' AND o_iendframe12='0' THEN
o_ibuf1<=buf_next(o_ibuf1,o_obuf1,o_freeze);
o_bufup1<='1';
o_isync <= '1';
END IF;
-- Output : Change framebuffer, and image properties, at VS falling edge
@ -2277,25 +2286,15 @@ BEGIN
-- Fetch polyphase coefficients
PolyFetch:PROCESS (o_clk) IS
VARIABLE hfrac2_v, hfrac3_v, vfrac_v : unsigned(FRAC-1 DOWNTO 0);
VARIABLE o_poly_phase_v : poly_phase_interp_t;
VARIABLE hfrac3_v, vfrac_v : unsigned(FRAC-1 DOWNTO 0);
BEGIN
IF rising_edge(o_clk) THEN
hfrac2_v:=o_hfrac(2)(11 DOWNTO 12-FRAC);
hfrac3_v:=o_hfrac(3)(11 DOWNTO 12-FRAC);
vfrac_v:=o_vfrac(11 DOWNTO 12-FRAC);
o_v_poly_use_adaptive <= to_std_logic((o_vmode(2 DOWNTO 0)/="000") AND (o_v_poly_adaptive = '1'));
o_h_poly_use_adaptive <= to_std_logic((o_hmode(2 DOWNTO 0)/="000") AND (o_h_poly_adaptive = '1'));
-- C2 / HC2 / VC3
o_v_poly_addr<=to_integer(vfrac_v);
o_h_poly_addr<=to_integer(hfrac2_v);
IF o_v_poly_use_adaptive = '1' THEN
o_a_poly_addr<=to_integer(vfrac_v);
ELSIF o_h_poly_use_adaptive = '1' THEN
o_a_poly_addr<=to_integer(hfrac2_v);
END IF;
o_v_poly_addr<=to_integer(o_vfrac(11 DOWNTO 12-FRAC));
-- C3 / HC3 / VC4
IF o_vmode(2 DOWNTO 0)/="000" THEN
@ -2305,22 +2304,21 @@ BEGIN
END IF;
IF o_hmode(2 DOWNTO 0)/="000" THEN
o_h_poly_phase_a<=poly_unpack(o_h_poly_mem(o_h_poly_addr));
o_h_poly_phase_a<=poly_unpack(o_h_poly_mem(to_integer(hfrac3_v)));
ELSE
o_h_poly_phase_a<=poly_nn(hfrac3_v);
END IF;
IF o_v_poly_use_adaptive='1' THEN
o_poly_lum<=o_v_poly_lum;
o_poly_lum<=poly_lum(o_v_lum_pix);
o_a_poly_addr<=o_v_poly_addr;
ELSIF o_h_poly_use_adaptive='1' THEN
o_poly_lum<=o_h_poly_lum;
o_poly_lum<=poly_lum(o_h_lum_pix);
o_a_poly_addr<=to_integer(hfrac3_v);
END IF;
o_poly_phase_b<=poly_unpack(o_a_poly_mem(o_a_poly_addr));
-- C4 / HC4 / VC5
o_poly_lerp_ta<=signed(to_unsigned(256,10) - resize(o_poly_lum,10));
o_poly_lerp_tb<=signed(resize(o_poly_lum,10));
o_poly_phase_b<=poly_unpack(o_a_poly_mem(o_a_poly_addr));
IF o_v_poly_use_adaptive='1' THEN
o_poly_phase_a<=o_v_poly_phase_a;
@ -2330,21 +2328,36 @@ BEGIN
o_h_poly_phase_a2<=o_h_poly_phase_a;
o_v_poly_phase_a2<=o_v_poly_phase_a;
o_poly_phase_b2<=o_poly_phase_b;
o_poly_lum1<=o_poly_lum;
-- C5 / HC5 / VC6
o_poly_phase<=poly_lerp(o_poly_phase_a, o_poly_phase_b2, o_poly_lerp_ta, o_poly_lerp_tb);
o_poly_lerp_ta<=signed(to_unsigned(256,10) - resize(o_poly_lum1,10));
o_poly_lerp_tb<=signed(resize(o_poly_lum1,10));
o_poly_phase_b2<=o_poly_phase_b;
o_poly_phase_a2<=o_poly_phase_a;
o_h_poly_phase_a3<=o_h_poly_phase_a2;
o_v_poly_phase_a3<=o_v_poly_phase_a2;
-- C6 / HC6 / VC7
o_v_poly_phase<=poly_cvt(o_v_poly_phase_a3);
o_h_poly_phase<=poly_cvt(o_h_poly_phase_a3);
o_poly_phase<=poly_lerp(o_poly_phase_a2, o_poly_phase_b2, o_poly_lerp_ta, o_poly_lerp_tb);
o_h_poly_phase_a4<=o_h_poly_phase_a3;
o_v_poly_phase_a4<=o_v_poly_phase_a3;
-- C7 / HC7 / VC8
o_h_poly_phase_a5<=o_h_poly_phase_a4;
o_v_poly_phase_a5<=o_v_poly_phase_a4;
o_poly_phase1<=o_poly_phase;
-- C8 / HC8 / VC9
o_v_poly_phase<=poly_cvt(o_v_poly_phase_a5);
o_h_poly_phase<=poly_cvt(o_h_poly_phase_a5);
IF o_v_poly_use_adaptive = '1' THEN
o_v_poly_phase<=o_poly_phase;
o_v_poly_phase<=o_poly_phase1;
ELSIF o_h_poly_use_adaptive = '1' THEN
o_h_poly_phase<=o_poly_phase;
o_h_poly_phase<=o_poly_phase1;
END IF;
END IF;
@ -2510,77 +2523,78 @@ BEGIN
-----------------------------------
o_hfrac(1)<=dir_v;
o_hfrac(2 TO 6) <= o_hfrac(1 TO 5);
o_hfrac(2 TO 9) <= o_hfrac(1 TO 8);
o_copyv(1 TO 12)<=o_copyv(0 TO 11);
o_copyv(1 TO 14)<=o_copyv(0 TO 13);
o_dcptv(1)<=o_dcpt;
IF o_dcptv(1)>=o_hsize THEN
o_copyv(2)<='0';
END IF;
o_dcptv(2)<=o_dcptv(1) MOD OHRES;
o_dcptv(3 TO 12)<=o_dcptv(2 TO 11);
o_dcptv(3 TO 14)<=o_dcptv(2 TO 13);
-- C2
o_hpixq(2)<=(o_hpix3,o_hpix2,o_hpix1,o_hpix0);
o_hpixq(3 TO 6)<=o_hpixq(2 TO 5);
o_hpixq(3 TO 8)<=o_hpixq(2 TO 7);
-- BILINEAR / SHARP BILINEAR ---------------
-- C4 : Pre-calc Sharp Bilinear
o_h_sbil_t<=sbil_frac1(o_hfrac(3));
-- C7 : Pre-calc Sharp Bilinear
o_h_sbil_t<=sbil_frac1(o_hfrac(6));
-- C5 : Select
-- C8 : Select
o_h_bil_frac<=(OTHERS =>'0');
IF o_hmode(0)='1' THEN -- Bilinear
IF MASK(MASK_BILINEAR)='1' THEN
o_h_bil_frac<=bil_frac(o_hfrac(4));
o_h_bil_frac<=bil_frac(o_hfrac(7));
END IF;
ELSE -- Sharp Bilinear
IF MASK(MASK_SHARP_BILINEAR)='1' THEN
o_h_bil_frac<=sbil_frac2(o_hfrac(4),o_h_sbil_t);
o_h_bil_frac<=sbil_frac2(o_hfrac(7),o_h_sbil_t);
END IF;
END IF;
-- C6 : Opposite frac
o_h_bil_t<=bil_calc(o_h_bil_frac,o_hpixq(5));
-- C9 : Opposite frac
o_h_bil_t<=bil_calc(o_h_bil_frac,o_hpixq(8));
-- C7 : Bilinear / Sharp Bilinear
-- C10 : Bilinear / Sharp Bilinear
o_h_bil_pix.r<=bound(o_h_bil_t.r,8+FRAC);
o_h_bil_pix.g<=bound(o_h_bil_t.g,8+FRAC);
o_h_bil_pix.b<=bound(o_h_bil_t.b,8+FRAC);
-- BICUBIC -------------------------------------------
-- C5 : Bicubic coefficients A,B,C,D
-- C5 : Bicubic calc T1 = X.D + C
o_h_bic_abcd1<=bic_calc0(o_hfrac(4),o_hpixq(4));
o_h_bic_tt1<=bic_calc1(o_hfrac(4),
bic_calc0(o_hfrac(4),o_hpixq(4)));
-- C8 : Bicubic coefficients A,B,C,D
-- C8 : Bicubic calc T1 = X.D + C
o_h_bic_abcd1<=bic_calc0(o_hfrac(7),o_hpixq(6));
o_h_bic_tt1<=bic_calc1(o_hfrac(7),
bic_calc0(o_hfrac(7),o_hpixq(6)));
-- C6 : Bicubic calc T2 = X.T1 + B
-- C9 : Bicubic calc T2 = X.T1 + B
o_h_bic_abcd2<=o_h_bic_abcd1;
o_h_bic_tt2<=bic_calc2(o_hfrac(5),o_h_bic_tt1,o_h_bic_abcd1);
o_h_bic_tt2<=bic_calc2(o_hfrac(8),o_h_bic_tt1,o_h_bic_abcd1);
-- C7 : Bicubic final Y = X.T2 + A
o_h_bic_pix<=bic_calc3(o_hfrac(6),o_h_bic_tt2,o_h_bic_abcd2);
-- C10 : Bicubic final Y = X.T2 + A
o_h_bic_pix<=bic_calc3(o_hfrac(9),o_h_bic_tt2,o_h_bic_abcd2);
-- POLYPHASE -----------------------------------------
-- C2
IF o_hfrac(2)(o_hfrac(2)'left)='0' THEN
o_h_poly_lum<=poly_lum(o_hpix2);
o_h_lum_pix<=o_hpix2;
ELSE
o_h_poly_lum<=poly_lum(o_hpix1);
o_h_lum_pix<=o_hpix1;
END IF;
-- C3-C6 in PolyFetch
-- C7 : Apply Polyphase
o_h_poly_t<=poly_calc(o_h_poly_phase,o_hpixq(6));
-- C3-C8 in PolyFetch
-- C8 : Sum and bound
-- C9 : Apply Polyphase
o_h_poly_t<=poly_calc(o_h_poly_phase,o_hpixq(8));
-- C10 : Sum and bound
o_h_poly_pix<=poly_final(o_h_poly_t);
-- C9 : Select interpoler ----------------------------
o_wadl<=o_dcptv(12);
o_wr<=o_altx AND (o_copyv(12) & o_copyv(12) & o_copyv(12) & o_copyv(12));
-- C11 : Select interpoler ----------------------------
o_wadl<=o_dcptv(14);
o_wr<=o_altx AND (o_copyv(14) & o_copyv(14) & o_copyv(14) & o_copyv(14));
o_ldw<=(x"00",x"00",x"00");
CASE o_hmode(2 DOWNTO 0) IS
@ -2630,17 +2644,27 @@ BEGIN
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_htotal THEN
o_hcpt<=(o_hcpt+1) MOD 4096;
ELSE
o_hcpt<=0;
IF o_vcpt_sync /= 4095 THEN
o_vcpt_sync <= o_vcpt_sync+1;
END IF;
IF o_vcpt_pre3+1>=o_vtotal THEN
o_vcpt_pre3<=0;
ELSIF o_vrr_sync2 THEN
o_vcpt_pre3<=o_vsstart;
o_sync<=false;
ELSE
o_vcpt_pre3<=(o_vcpt_pre3+1) MOD 4096;
END IF;
o_vcpt_pre2<=o_vcpt_pre3;
o_vcpt_pre<=o_vcpt_pre2;
o_vcpt<=o_vcpt_pre;
@ -2656,11 +2680,11 @@ BEGIN
(o_vcpt=o_vsend AND o_hcpt<o_hsstart));
o_vss<=to_std_logic(o_vcpt_pre2>=o_vmin AND o_vcpt_pre2<=o_vmax);
o_hsv(1 TO 9)<=o_hsv(0 TO 8);
o_vsv(1 TO 9)<=o_vsv(0 TO 8);
o_dev(1 TO 9)<=o_dev(0 TO 8);
o_pev(1 TO 9)<=o_pev(0 TO 8);
o_end(1 TO 9)<=o_end(0 TO 8);
o_hsv(1 TO 11)<=o_hsv(0 TO 10);
o_vsv(1 TO 11)<=o_vsv(0 TO 10);
o_dev(1 TO 11)<=o_dev(0 TO 10);
o_pev(1 TO 11)<=o_pev(0 TO 10);
o_end(1 TO 11)<=o_end(0 TO 10);
IF o_run='0' THEN
o_hsv(2)<='0';
@ -2669,10 +2693,27 @@ BEGIN
o_pev(2)<='0';
o_end(2)<='0';
END IF;
END IF;
END IF;
o_vcpt_sync2<=o_vcpt_sync;
o_vrr_min<=(o_vcpt_sync2<o_vtotal);
o_vrr_min2<=o_vrr_min;
o_vrr_max<=(o_vcpt_sync2<o_vrrmax);
o_vrr_max2<=o_vrr_max;
IF o_isync2='1' THEN
o_vcpt_sync<=0;
o_sync_max<=o_vrr_max2;
IF o_vrr_min2 THEN
o_sync<=true;
END iF;
END IF;
o_vcpt2<=o_vcpt_pre3;
o_vrr_sync<=(o_vrr='1' AND (o_sync OR o_sync_max) AND o_vcpt2>=o_vdisp AND o_vcpt2<o_vsstart);
o_vrr_sync2<=o_vrr_sync;
END IF;
END PROCESS OSWEEP;
-----------------------------------------------------------------------------
@ -2685,7 +2726,7 @@ BEGIN
BEGIN
IF rising_edge(o_clk) THEN
IF o_ce='1' THEN
o_v_hmin_adj<=o_hmin + 4;
o_v_hmin_adj<=o_hmin + 5;
fracnn_v := o_vfrac(o_vfrac'left);
r1_v := (o_hcpt - o_v_hmin_adj + OHRES) MOD OHRES;
@ -2731,35 +2772,38 @@ BEGIN
o_vpix_inner(0)<=pixq_v(2);
END IF;
-- CYCLE 3-6
o_vpix_inner(1 TO 4)<=o_vpix_inner(0 TO 3);
-- CYCLE 3-7
o_vpix_inner(1 TO 5)<=o_vpix_inner(0 TO 4);
-- CYCLE 7
-- CYCLE 8
IF to_integer(o_vacpt)>o_ivsize THEN
IF fracnn_v = '0' THEN
o_vpixq<=(o_vpix_outer(0), o_vpix_inner(4), o_vpix_inner(4), o_vpix_inner(4));
o_vpixq_pre<=(o_vpix_outer(0), o_vpix_inner(5), o_vpix_inner(5), o_vpix_inner(5));
ELSE
o_vpixq<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_outer(1), o_vpix_outer(1));
o_vpixq_pre<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_outer(1), o_vpix_outer(1));
END IF;
ELSIF to_integer(o_vacpt)=o_ivsize THEN
IF fracnn_v = '0' THEN
o_vpixq<=(o_vpix_outer(0), o_vpix_inner(4), o_vpix_outer(1), o_vpix_outer(1));
o_vpixq_pre<=(o_vpix_outer(0), o_vpix_inner(5), o_vpix_outer(1), o_vpix_outer(1));
ELSE
o_vpixq<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_inner(4), o_vpix_inner(4));
o_vpixq_pre<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_inner(5), o_vpix_inner(5));
END IF;
ELSE
IF fracnn_v = '0' THEN
o_vpixq<=(o_vpix_outer(0), o_vpix_inner(4), o_vpix_outer(1), o_vpix_outer(2));
o_vpixq_pre<=(o_vpix_outer(0), o_vpix_inner(5), o_vpix_outer(1), o_vpix_outer(2));
ELSE
o_vpixq<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_inner(4), o_vpix_outer(2));
o_vpixq_pre<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_inner(5), o_vpix_outer(2));
END IF;
END IF;
-- CYCLE 9
o_vpixq<=o_vpixq_pre;
-- BILINEAR / SHARP BILINEAR -----------------------
-- C6 : Pre-calc Sharp Bilinear
-- C8 : Pre-calc Sharp Bilinear
o_v_sbil_t<=sbil_frac1(o_vfrac);
-- C7 : Select
-- C9 : Select
o_v_bil_frac<=(OTHERS =>'0');
IF o_vmode(0)='1' THEN -- Bilinear
IF MASK(MASK_BILINEAR)='1' THEN
@ -2771,48 +2815,48 @@ BEGIN
END IF;
END IF;
-- C8 :
-- C10 :
o_v_bil_t<=bil_calc(o_v_bil_frac,o_vpixq);
-- C9 : Nearest / Bilinear / Sharp Bilinear
-- C11 : Nearest / Bilinear / Sharp Bilinear
o_v_bil_pix.r<=bound(o_v_bil_t.r,8+FRAC);
o_v_bil_pix.g<=bound(o_v_bil_t.g,8+FRAC);
o_v_bil_pix.b<=bound(o_v_bil_t.b,8+FRAC);
-- BICUBIC -----------------------------------------
-- C7 : Bicubic coefficients A,B,C,D
-- C7 : Bicubic calc T1 = X.D + C
-- C9 : Bicubic coefficients A,B,C,D
-- C9 : Bicubic calc T1 = X.D + C
o_v_bic_abcd1<=bic_calc0(o_vfrac,o_vpixq);
o_v_bic_tt1<=bic_calc1(o_vfrac,bic_calc0(o_vfrac,o_vpixq));
-- C8 : Bicubic calc T2 = X.T1 + B
-- C10 : Bicubic calc T2 = X.T1 + B
o_v_bic_abcd2<=o_v_bic_abcd1;
o_v_bic_tt2<=bic_calc2(o_vfrac,o_v_bic_tt1,o_v_bic_abcd1);
-- C9 : Bicubic final Y = X.T2 + A
-- C11 : Bicubic final Y = X.T2 + A
o_v_bic_pix<=bic_calc3(o_vfrac,o_v_bic_tt2,o_v_bic_abcd2);
-- POLYPHASE ---------------------------------------
-- C3 : Calculate Luminance
o_v_poly_lum<=poly_lum(o_vpix_inner(0));
-- C3 : Setup luminance
o_v_lum_pix<=o_vpix_inner(0);
-- C4-C7 in PolyFetch
-- C4-C9 in PolyFetch
-- C8 : Apply polyphase
-- C10 : Apply polyphase
o_v_poly_t<=poly_calc(o_v_poly_phase,o_vpixq);
-- C9 : Bound
-- C11 : Bound
o_v_poly_pix<=poly_final(o_v_poly_t);
-- CYCLE 10 -----------------------------------------
o_hs<=o_hsv(9);
o_vs<=o_vsv(9);
o_de<=o_dev(9);
o_vbl<=o_end(9);
-- CYCLE 12 -----------------------------------------
o_hs<=o_hsv(11);
o_vs<=o_vsv(11);
o_de<=o_dev(11);
o_vbl<=o_end(11);
o_r<=x"00";
o_g<=x"00";
o_b<=x"00";
o_brd<= not o_pev(9);
o_brd<= not o_pev(11);
CASE o_vmode(2 DOWNTO 0) IS
WHEN "000" => -- Nearest
@ -2843,7 +2887,7 @@ BEGIN
END IF;
END CASE;
IF o_pev(9)='0' THEN
IF o_pev(11)='0' THEN
o_r<=o_border(23 DOWNTO 16); -- Copy border colour
o_g<=o_border(15 DOWNTO 8);
o_b<=o_border(7 DOWNTO 0);
@ -2852,7 +2896,6 @@ BEGIN
----------------------------------------------------
END IF;
END IF;
END PROCESS VSCAL;
-----------------------------------------------------------------------------

View File

@ -1,239 +0,0 @@
module hdmi_config
(
// Host Side
input iCLK,
input iRST_N,
input dvi_mode,
input audio_96k,
input [1:0] limited,
input ypbpr,
output reg done,
// I2C Side
output I2C_SCL,
inout I2C_SDA
);
// Internal Registers/Wires
reg mI2C_GO = 0;
wire mI2C_END;
wire mI2C_ACK;
reg [15:0] LUT_DATA;
reg [7:0] LUT_INDEX = 0;
i2c #(50_000_000, 20_000) i2c_av
(
.CLK(iCLK),
.I2C_SCL(I2C_SCL), // I2C CLOCK
.I2C_SDA(I2C_SDA), // I2C DATA
.I2C_ADDR('h39), // 0x39 is the Slave Address of the ADV7513 chip!
.I2C_WLEN(1),
.I2C_WDATA1(init_data[LUT_INDEX][15:8]), // SUB_ADDR
.I2C_WDATA2(init_data[LUT_INDEX][7:0]), // DATA
.START(mI2C_GO), // START transfer
.READ(0),
.END(mI2C_END), // END transfer
.ACK(mI2C_ACK) // ACK
);
////////////////////// Config Control ////////////////////////////
always@(posedge iCLK or negedge iRST_N) begin
reg [1:0] mSetup_ST = 0;
if(!iRST_N) begin
LUT_INDEX <= 0;
mSetup_ST <= 0;
mI2C_GO <= 0;
done <= 0;
end else begin
if(init_data[LUT_INDEX] != 16'hFFFF) begin
case(mSetup_ST)
0: begin
mI2C_GO <= 1;
mSetup_ST <= 1;
end
1: if(~mI2C_END) mSetup_ST <= 2;
2: begin
mI2C_GO <= 0;
if(mI2C_END) begin
mSetup_ST <= 0;
if(!mI2C_ACK) LUT_INDEX <= LUT_INDEX + 8'd1;
end
end
endcase
end
else done <= 1;
end
end
////////////////////////////////////////////////////////////////////
///////////////////// Config Data LUT //////////////////////////
wire [15:0] init_data[82] =
'{
16'h9803, // ADI required Write.
{8'hD6, 8'b1100_0000}, // [7:6] HPD Control...
// 00 = HPD is from both HPD pin or CDC HPD
// 01 = HPD is from CDC HPD
// 10 = HPD is from HPD pin
// 11 = HPD is always high
16'h4110, // Power Down control
16'h9A70, // ADI required Write.
16'h9C30, // ADI required Write.
{8'h9D, 8'b0110_0001}, // [7:4] must be b0110!.
// [3:2] b00 = Input clock not divided. b01 = Clk divided by 2. b10 = Clk divided by 4. b11 = invalid!
// [1:0] must be b01!
16'hA2A4, // ADI required Write.
16'hA3A4, // ADI required Write.
16'hE0D0, // ADI required Write.
16'h35_40,
16'h36_D9,
16'h37_0A,
16'h38_00,
16'h39_2D,
16'h3A_00,
{8'h16, 8'b0011_1000}, // Output Format 444 [7]=0.
// [6] must be 0!
// Colour Depth for Input Video data [5:4] b11 = 8-bit.
// Input Style [3:2] b10 = Style 1 (ignored when using 444 input).
// DDR Input Edge falling [1]=0 (not using DDR atm).
// Output Colour Space RGB [0]=0.
{8'h17, 8'b01100010}, // Aspect ratio 16:9 [1]=1, 4:3 [1]=0
{8'h18, ypbpr ? 8'h86 : limited[0] ? 8'h8D : limited[1] ? 8'h8E : 8'h00}, // CSC Scaling Factors and Coefficients for RGB Full->Limited.
{8'h19, ypbpr ? 8'hDF : limited[0] ? 8'hBC : 8'hFE}, // Taken from table in ADV7513 Programming Guide.
{8'h1A, ypbpr ? 8'h1A : 8'h00}, // CSC Channel A.
{8'h1B, ypbpr ? 8'h3F : 8'h00},
{8'h1C, ypbpr ? 8'h1E : 8'h00},
{8'h1D, ypbpr ? 8'hE2 : 8'h00},
{8'h1E, ypbpr ? 8'h07 : 8'h01},
{8'h1F, ypbpr ? 8'hE7 : 8'h00},
{8'h20, ypbpr ? 8'h04 : 8'h00}, // CSC Channel B.
{8'h21, ypbpr ? 8'h1C : 8'h00},
{8'h22, ypbpr ? 8'h08 : limited[0] ? 8'h0D : 8'h0E},
{8'h23, ypbpr ? 8'h11 : limited[0] ? 8'hBC : 8'hFE},
{8'h24, ypbpr ? 8'h01 : 8'h00},
{8'h25, ypbpr ? 8'h91 : 8'h00},
{8'h26, ypbpr ? 8'h01 : 8'h01},
{8'h27, 8'h00},
{8'h28, ypbpr ? 8'h1D : 8'h00}, // CSC Channel C.
{8'h29, ypbpr ? 8'hAE : 8'h00},
{8'h2A, ypbpr ? 8'h1B : 8'h00},
{8'h2B, ypbpr ? 8'h73 : 8'h00},
{8'h2C, ypbpr ? 8'h06 : limited[0] ? 8'h0D : 8'h0E},
{8'h2D, ypbpr ? 8'hDF : limited[0] ? 8'hBC : 8'hFE},
{8'h2E, ypbpr ? 8'h07 : 8'h01},
{8'h2F, ypbpr ? 8'hE7 : 8'h00},
{8'h3B, 8'b0000_0000}, // Pixel repetition [6:5] b00 AUTO. [4:3] b00 x1 mult of input clock. [2:1] b00 x1 pixel rep to send to HDMI Rx.
16'h4000, // General Control Packet Enable
{8'h48, 8'b0000_1000}, // [6]=0 Normal bus order!
// [5] DDR Alignment.
// [4:3] b01 Data right justified (for YCbCr 422 input modes).
16'h49A8, // ADI required Write.
16'h4C00, // ADI required Write.
{8'h55, 8'b0001_0000}, // [7] must be 0!. Set RGB444 in AVinfo Frame [6:5], Set active format [4].
// AVI InfoFrame Valid [4].
// Bar Info [3:2] b00 Bars invalid. b01 Bars vertical. b10 Bars horizontal. b11 Bars both.
// Scan Info [1:0] b00 (No data). b01 TV. b10 PC. b11 None.
{8'h57, 1'b0, // [7] IT Content. 0 - No. 1 - Yes (type set in register h59).
3'b000, // [6:4] Color space (ignored for RGB)
(ypbpr | limited) ? 2'b01 : 2'b10, // [3:2] RGB Quantization range
2'b00}, // [1:0] Non-Uniform Scaled: 00 - None. 01 - Horiz. 10 - Vert. 11 - Both.
16'h7301,
{8'h94, 8'b1000_0000}, // [7]=1 HPD Interrupt ENabled.
16'h9902, // ADI required Write.
16'h9B18, // ADI required Write.
16'h9F00, // ADI required Write.
{8'hA1, 8'b0000_0000}, // [6]=1 Monitor Sense Power Down DISabled.
16'hA408, // ADI required Write.
16'hA504, // ADI required Write.
16'hA600, // ADI required Write.
16'hA700, // ADI required Write.
16'hA800, // ADI required Write.
16'hA900, // ADI required Write.
16'hAA00, // ADI required Write.
16'hAB40, // ADI required Write.
{8'hAF, 6'b0000_01,~dvi_mode,1'b0}, // [7]=0 HDCP Disabled.
// [6:5] must be b00!
// [4]=0 Current frame is unencrypted
// [3:2] must be b01!
// [1]=1 HDMI Mode.
// [0] must be b0!
16'hB900, // ADI required Write.
{8'hBA, 8'b0110_0000}, // [7:5] Input Clock delay...
// b000 = -1.2ns.
// b001 = -0.8ns.
// b010 = -0.4ns.
// b011 = No delay.
// b100 = 0.4ns.
// b101 = 0.8ns.
// b110 = 1.2ns.
// b111 = 1.6ns.
16'hBB00, // ADI required Write.
16'hDE9C, // ADI required Write.
16'hE460, // ADI required Write.
16'hFA7D, // Nbr of times to search for good phase
// (Audio stuff on Programming Guide, Page 66)...
{8'h0A, 8'b0000_0000}, // [6:4] Audio Select. b000 = I2S.
// [3:2] Audio Mode. (HBR stuff, leave at 00!).
{8'h0B, 8'b0000_1110}, //
{8'h0C, 8'b0000_0100}, // [7] 0 = Use sampling rate from I2S stream. 1 = Use samp rate from I2C Register.
// [6] 0 = Use Channel Status bits from stream. 1 = Use Channel Status bits from I2C register.
// [2] 1 = I2S0 Enable.
// [1:0] I2S Format: 00 = Standard. 01 = Right Justified. 10 = Left Justified. 11 = AES.
{8'h0D, 8'b0001_0000}, // [4:0] I2S Bit (Word) Width for Right-Justified.
{8'h14, 8'b0000_0010}, // [3:0] Audio Word Length. b0010 = 16 bits.
{8'h15, audio_96k, 7'b010_0000}, // I2S Sampling Rate [7:4]. b0000 = (44.1KHz). b0010 = 48KHz.
// Input ID [3:1] b000 (0) = 24-bit RGB 444 or YCrCb 444 with Separate Syncs.
// Audio Clock Config
16'h0100, //
audio_96k ? 16'h0230 : 16'h0218, // Set N Value 12288/6144
16'h0300, //
16'h0701, //
16'h0822, // Set CTS Value 74250
16'h090A, //
16'hFFFF // END
};
////////////////////////////////////////////////////////////////////
endmodule

View File

@ -55,6 +55,13 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1,
output reg [15:0] joystick_r_analog_4,
output reg [15:0] joystick_r_analog_5,
input [15:0] joystick_0_rumble, // 15:8 - 'large' rumble motor magnitude, 7:0 'small' rumble motor magnitude
input [15:0] joystick_1_rumble,
input [15:0] joystick_2_rumble,
input [15:0] joystick_3_rumble,
input [15:0] joystick_4_rumble,
input [15:0] joystick_5_rumble,
// paddle 0..255
output reg [7:0] paddle_0,
output reg [7:0] paddle_1,
@ -71,6 +78,29 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1,
output reg [8:0] spinner_4,
output reg [8:0] spinner_5,
// ps2 keyboard emulation
output ps2_kbd_clk_out,
output ps2_kbd_data_out,
input ps2_kbd_clk_in,
input ps2_kbd_data_in,
input [2:0] ps2_kbd_led_status,
input [2:0] ps2_kbd_led_use,
output ps2_mouse_clk_out,
output ps2_mouse_data_out,
input ps2_mouse_clk_in,
input ps2_mouse_data_in,
// ps2 alternative interface.
// [8] - extended, [9] - pressed, [10] - toggles with every press/release
output reg [10:0] ps2_key = 0,
// [24] - toggles with every event
output reg [24:0] ps2_mouse = 0,
output reg [15:0] ps2_mouse_ext = 0, // 15:8 - reserved(additional buttons), 7:0 - wheel movements
output [1:0] buttons,
output forced_scandoubler,
output direct_video,
@ -79,8 +109,10 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1,
//toggle to force notify of video mode change
input new_vmode,
output reg [63:0] status,
input [63:0] status_in,
inout [21:0] gamma_bus,
output reg [127:0] status,
input [127:0] status_in,
input status_set,
input [15:0] status_menumask,
@ -133,31 +165,6 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1,
output reg [7:0] uart_mode,
output reg [31:0] uart_speed,
// ps2 keyboard emulation
output ps2_kbd_clk_out,
output ps2_kbd_data_out,
input ps2_kbd_clk_in,
input ps2_kbd_data_in,
input [2:0] ps2_kbd_led_status,
input [2:0] ps2_kbd_led_use,
output ps2_mouse_clk_out,
output ps2_mouse_data_out,
input ps2_mouse_clk_in,
input ps2_mouse_data_in,
// ps2 alternative interface.
// [8] - extended, [9] - pressed, [10] - toggles with every press/release
output reg [10:0] ps2_key = 0,
// [24] - toggles with every event
output reg [24:0] ps2_mouse = 0,
output reg [15:0] ps2_mouse_ext = 0, // 15:8 - reserved(additional buttons), 7:0 - wheel movements
inout [21:0] gamma_bus,
// for core-specific extensions
inout [35:0] EXT_BUS
);
@ -259,7 +266,7 @@ always@(posedge clk_sys) begin : uio_block
reg [3:0] pdsp_idx;
reg ps2skip = 0;
reg [3:0] stflg = 0;
reg [63:0] status_req;
reg[127:0] status_req;
reg old_status_set = 0;
reg old_upload_req = 0;
reg upload_req = 0;
@ -330,6 +337,12 @@ always@(posedge clk_sys) begin : uio_block
'h39: io_dout <= 1;
'h3C: if(upload_req) begin io_dout <= {ioctl_upload_index, 8'd1}; upload_req <= 0; end
'h3E: io_dout <= 1; // shadow mask
'h003F: io_dout <= joystick_0_rumble;
'h013F: io_dout <= joystick_1_rumble;
'h023F: io_dout <= joystick_2_rumble;
'h033F: io_dout <= joystick_3_rumble;
'h043F: io_dout <= joystick_4_rumble;
'h053F: io_dout <= joystick_5_rumble;
endcase
sd_buff_addr <= 0;
@ -455,13 +468,17 @@ always@(posedge clk_sys) begin : uio_block
// send image info
'h1d: if(byte_cnt<5) img_size[{byte_cnt-1'b1, 4'b0000} +:16] <= io_din;
// status, 64bit version
'h1e: if(!byte_cnt[MAX_W:3]) begin
case(byte_cnt[2:0])
// status, 128bit version
'h1e: if(!byte_cnt[MAX_W:4]) begin
case(byte_cnt[3:0])
1: status[15:00] <= io_din;
2: status[31:16] <= io_din;
3: status[47:32] <= io_din;
4: status[63:48] <= io_din;
5: status[79:64] <= io_din;
6: status[95:80] <= io_din;
7: status[111:96] <= io_din;
8: status[127:112] <= io_din;
endcase
end
@ -491,12 +508,16 @@ always@(posedge clk_sys) begin : uio_block
'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din;
//status set
'h29: if(!byte_cnt[MAX_W:3]) begin
case(byte_cnt[2:0])
'h29: if(!byte_cnt[MAX_W:4]) begin
case(byte_cnt[3:0])
1: io_dout <= status_req[15:00];
2: io_dout <= status_req[31:16];
3: io_dout <= status_req[47:32];
4: io_dout <= status_req[63:48];
5: io_dout <= status_req[79:64];
6: io_dout <= status_req[95:80];
7: io_dout <= status_req[111:96];
8: io_dout <= status_req[127:112];
endcase
end
@ -870,22 +891,28 @@ always @(posedge clk_sys) begin
11: dout <= vid_pix[31:16];
12: dout <= vid_vtime_hdmi[15:0];
13: dout <= vid_vtime_hdmi[31:16];
14: dout <= vid_ccnt[15:0];
15: dout <= vid_ccnt[31:16];
default dout <= 0;
endcase
end
reg [31:0] vid_hcnt = 0;
reg [31:0] vid_vcnt = 0;
reg [31:0] vid_ccnt = 0;
reg [7:0] vid_nres = 0;
reg [1:0] vid_int = 0;
always @(posedge clk_vid) begin
integer hcnt;
integer vcnt;
integer ccnt;
reg old_vs= 0, old_de = 0, old_vmode = 0;
reg [3:0] resto = 0;
reg calch = 0;
if(calch & de) ccnt <= ccnt + 1;
if(ce_pix) begin
old_vs <= vs;
old_de <= de;
@ -906,9 +933,11 @@ always @(posedge clk_vid) begin
if(&resto) vid_nres <= vid_nres + 1'd1;
vid_hcnt <= hcnt;
vid_vcnt <= vcnt;
vid_ccnt <= ccnt;
end
vcnt <= 0;
hcnt <= 0;
ccnt <= 0;
calch <= 1;
end
end

View File

@ -102,19 +102,19 @@ end
endmodule
module ltc2308_tape #(parameter HIST_LOW = 16, HIST_HIGH = 64, ADC_RATE = 48000, CLK_RATE = 50000000)
module ltc2308_tape #(parameter HIST_LOW = 16, HIST_HIGH = 64, ADC_RATE = 48000, CLK_RATE = 50000000, NUM_CH = 1)
(
input reset,
input clk,
inout [3:0] ADC_BUS,
output reg dout,
output active
output active,
output adc_sync,
output [(NUM_CH*12)-1:0] adc_data
);
wire [11:0] adc_data;
wire adc_sync;
ltc2308 #(1, ADC_RATE, CLK_RATE) adc
ltc2308 #(NUM_CH, ADC_RATE, CLK_RATE) adc
(
.reset(reset),
.clk(clk),
@ -133,7 +133,7 @@ always @(posedge clk) begin
data1 <= data2;
data2 <= data3;
data3 <= data4;
data4 <= adc_data;
data4 <= adc_data[11:0];
sum <= data1+data2+data3+data4;

View File

@ -131,7 +131,7 @@ wire [21:0] osd_h_hdr = (info || rot) ? osd_h : (osd_h + OSD_HDR);
// pipeline the comparisons a bit
always @(posedge clk_video) if(ce_pix) begin
v_cnt_h <= v_cnt < osd_t;
v_cnt_h <= v_cnt <= osd_t;
v_cnt_1 <= v_cnt < 320;
v_cnt_2 <= v_cnt < 640;
v_cnt_3 <= v_cnt < 960;

View File

@ -16,6 +16,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) v
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) arcade_video.v ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) osd.v ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) vga_out.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) yc_out.sv ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2c.v ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) alsa.sv ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2s.v ]
@ -25,7 +26,6 @@ set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ltc2308.sv ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sigma_delta_dac.v ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mt32pi.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hdmi_config.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mcp23009.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) f2sdram_safe_terminator.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ddr_svc.sv ]

View File

@ -45,6 +45,7 @@ set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM2_
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM2_*
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM2_DQ[*]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM2_DQ[*]
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDRAM2_DQ[*]
set_instance_assignment -name ALLOW_SYNCH_CTRL_USAGE OFF -to *|SDRAM2_*
set_global_assignment -name VERILOG_MACRO "MISTER_DUAL_SDRAM=1"

View File

@ -28,6 +28,7 @@ set_false_path -to [get_ports {VGA_*}]
set_false_path -to [get_ports {AUDIO_SPDIF}]
set_false_path -to [get_ports {AUDIO_L}]
set_false_path -to [get_ports {AUDIO_R}]
set_false_path -from {get_ports {SW[*]}}
set_false_path -to {cfg[*]}
set_false_path -from {cfg[*]}
set_false_path -from {VSET[*]}
@ -55,6 +56,7 @@ set_false_path -from {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*]
set_false_path -to {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]}
set_false_path -from {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]}
set_false_path -from {aflt_* acx* acy* areset* arc*}
set_false_path -from {arx* ary*}
set_false_path -from {vs_line*}
set_false_path -from {ascal|o_ihsize*}
@ -62,7 +64,7 @@ set_false_path -from {ascal|o_ivsize*}
set_false_path -from {ascal|o_format*}
set_false_path -from {ascal|o_hdown}
set_false_path -from {ascal|o_vdown}
set_false_path -from {ascal|o_hmin* ascal|o_hmax* ascal|o_vmin* ascal|o_vmax*}
set_false_path -from {ascal|o_hmin* ascal|o_hmax* ascal|o_vmin* ascal|o_vmax* ascal|o_vrrmax* ascal|o_vrr}
set_false_path -from {ascal|o_hdisp* ascal|o_vdisp*}
set_false_path -from {ascal|o_htotal* ascal|o_vtotal*}
set_false_path -from {ascal|o_hsstart* ascal|o_vsstart* ascal|o_hsend* ascal|o_vsend*}

View File

@ -168,7 +168,7 @@ assign LED = (led_overtake & led_state) | (~led_overtake & {1'b0,led_locked,1'b0
wire btn_r, btn_o, btn_u;
`ifdef MISTER_DUAL_SDRAM
assign {btn_r,btn_o,btn_u} = {mcp_btn[1],mcp_btn[2],mcp_btn[0]};
assign {btn_r,btn_o,btn_u} = SW[3] ? {mcp_btn[1],mcp_btn[2],mcp_btn[0]} : ~{SDRAM2_DQ[9],SDRAM2_DQ[13],SDRAM2_DQ[11]};
`else
assign {btn_r,btn_o,btn_u} = ~{BTN_RESET,BTN_OSD,BTN_USER} | {mcp_btn[1],mcp_btn[2],mcp_btn[0]};
`endif
@ -212,7 +212,7 @@ end
// gp_in[31] = 0 - quick flag that FPGA is initialized (HPS reads 1 when FPGA is not in user mode)
// used to avoid lockups while JTAG loading
wire [31:0] gp_in = {1'b0, btn_user | btn[1], btn_osd | btn[0], SW[3], 8'd0, io_ver, io_ack, io_wide, io_dout};
wire [31:0] gp_in = {1'b0, btn_user | btn[1], btn_osd | btn[0], SW[3], 8'd0, io_ver, io_ack, io_wide, io_dout | io_dout_sys};
wire [31:0] gp_out;
wire [1:0] io_ver = 1; // 0 - obsolete. 1 - optimized HPS I/O. 2,3 - reserved for future.
@ -270,7 +270,6 @@ reg [15:0] cfg;
reg cfg_set = 0;
wire vga_fb = cfg[12] | vga_force_scaler;
wire [1:0] hdmi_limited = {cfg[11],cfg[8]};
`ifdef MISTER_DEBUG_NOHDMI
wire direct_video = 1;
@ -278,12 +277,11 @@ wire direct_video = 1;
wire direct_video = cfg[10];
`endif
wire dvi_mode = cfg[7];
wire audio_96k = cfg[6];
wire csync_en = cfg[3];
wire ypbpr_en = cfg[5];
wire io_osd_vga = io_ss1 & ~io_ss2;
`ifndef MISTER_DUAL_SDRAM
wire ypbpr_en = cfg[5];
wire sog = cfg[9];
wire vga_scaler = cfg[2] | vga_force_scaler;
`endif
@ -304,12 +302,13 @@ reg [11:0] VSET = 0, HSET = 0;
reg FREESCALE = 0;
reg [2:0] scaler_flt;
reg lowlat = 0;
reg cfg_dis = 0;
reg cfg_done = 0;
reg vs_wait = 0;
reg [11:0] vs_line = 0;
reg scaler_out = 0;
reg vrr_mode = 0;
reg [31:0] aflt_rate = 7056000;
reg [39:0] acx = 4258969;
@ -324,16 +323,16 @@ reg [12:0] arc1x = 0;
reg [12:0] arc1y = 0;
reg [12:0] arc2x = 0;
reg [12:0] arc2y = 0;
reg [15:0] io_dout_sys;
always@(posedge clk_sys) begin
reg [7:0] cmd;
reg has_cmd;
reg old_strobe;
reg [7:0] cnt = 0;
reg vs_d0,vs_d1,vs_d2;
reg [4:0] acx_att;
reg [7:0] fb_crc;
old_strobe <= io_strobe;
coef_wr <= 0;
`ifndef MISTER_DEBUG_NOHDMI
@ -346,9 +345,11 @@ always@(posedge clk_sys) begin
areset <= 0;
acx_att <= 0;
acx <= acx >> acx_att;
io_dout_sys <= 0;
end
else
if(~old_strobe & io_strobe) begin
if(io_strobe) begin
io_dout_sys <= 0;
if(!has_cmd) begin
has_cmd <= 1;
cmd <= io_din[7:0];
@ -365,6 +366,10 @@ always@(posedge clk_sys) begin
acy2 <= -24'd2023767;
areset <= 1;
end
if(io_din[7:0] == 'h20) io_dout_sys <= 'b11;
`ifndef MISTER_DEBUG_NOHDMI
if(io_din[7:0] == 'h40) io_dout_sys <= fb_crc;
`endif
end
else begin
cnt <= cnt + 1'd1;
@ -377,7 +382,7 @@ always@(posedge clk_sys) begin
cfg_set <= 0;
if(cnt<8) begin
case(cnt[2:0])
0: WIDTH <= io_din[11:0];
0: {HDMI_PR,vrr_mode,WIDTH} <= {io_din[15:14], io_din[11:0]};
1: HFP <= io_din[11:0];
2: HS <= {io_din[15], io_din[11:0]};
3: HBP <= io_din[11:0];
@ -401,7 +406,7 @@ always@(posedge clk_sys) begin
cfg_custom_t <= ~cfg_custom_t;
cnt[2:0] <= 3'b100;
end
if(cnt == 8) {lowlat,cfg_dis} <= io_din[15:14];
if(cnt == 8) {lowlat,cfg_done} <= {io_din[15],1'b1};
`endif
end
end
@ -458,10 +463,42 @@ always@(posedge clk_sys) begin
end
`ifndef MISTER_DEBUG_NOHDMI
if(cmd == 'h3E) {shadowmask_wr,shadowmask_data} <= {1'b1, io_din};
if(cmd == 'h40) begin
case(cnt[3:0])
0: io_dout_sys <= {arxy, arx};
1: io_dout_sys <= {arxy, ary};
2: io_dout_sys <= {LFB_EN, FB_EN, FB_FMT};
3: io_dout_sys <= FB_WIDTH;
4: io_dout_sys <= FB_HEIGHT;
5: io_dout_sys <= FB_BASE[15:0];
6: io_dout_sys <= FB_BASE[31:16];
7: io_dout_sys <= FB_STRIDE;
endcase
end
`endif
`ifndef MISTER_DISABLE_YC
if(cmd == 'h41) begin
case(cnt[3:0])
0: {pal_en,cvbs,yc_en} <= io_din[2:0];
1: PhaseInc[15:0] <= io_din;
2: PhaseInc[31:16] <= io_din;
3: PhaseInc[39:32] <= io_din[7:0];
4: ColorBurst_Range[15:0] <= io_din;
5: ColorBurst_Range[16] <= io_din[0];
endcase
end
`endif
end
end
`ifndef MISTER_DEBUG_NOHDMI
fb_crc <= {LFB_EN, FB_EN, FB_FMT}
^ FB_WIDTH[7:0] ^ FB_WIDTH[11:8]
^ FB_HEIGHT[7:0] ^ FB_HEIGHT[11:8]
^ arx[7:0] ^ arx[11:8] ^ arxy
^ ary[7:0] ^ ary[11:8];
`endif
vs_d0 <= HDMI_TX_VS;
if(vs_d0 == HDMI_TX_VS) vs_d1 <= vs_d0;
@ -482,17 +519,6 @@ cyclonev_hps_interface_peripheral_uart uart
.txd(uart_txd)
);
wire aspi_sck,aspi_mosi,aspi_ss,aspi_miso;
cyclonev_hps_interface_peripheral_spi_master spi
(
.sclk_out(aspi_sck),
.txd(aspi_mosi), // mosi
.rxd(aspi_miso), // miso
.ss_0_n(aspi_ss),
.ss_in_n(1)
);
wire [63:0] f2h_irq = {video_sync,HDMI_TX_VS};
cyclonev_hps_interface_interrupts interrupts
(
@ -598,11 +624,13 @@ ddr_svc ddr_svc
.ram_write(ram2_write),
.ram_bcnt(ram2_bcnt),
`ifndef MISTER_DISABLE_ALSA
.ch0_addr(alsa_address),
.ch0_burst(1),
.ch0_data(alsa_readdata),
.ch0_req(alsa_req),
.ch0_ready(alsa_ready),
`endif
.ch1_addr(pal_addr),
.ch1_burst(128),
@ -634,6 +662,11 @@ wire clk_hdmi = hdmi_clk_out;
ascal
#(
.RAMBASE(32'h20000000),
`ifdef MISTER_SMALL_VBUF
.RAMSIZE(32'h00200000),
`else
.RAMSIZE(32'h00800000),
`endif
`ifndef MISTER_FB
.PALETTE2("false"),
`else
@ -695,6 +728,8 @@ ascal
.vdisp (HEIGHT),
.vmin (vmin),
.vmax (vmax),
.vrr (vrr_mode),
.vrrmax (HEIGHT + VBP + VS[11:0] + 12'd1),
.mode ({~lowlat,LFB_EN ? LFB_FLT : |scaler_flt,2'b00}),
.poly_clk (clk_sys),
@ -804,37 +839,40 @@ reg [11:0] vmax;
reg [11:0] hdmi_height;
reg [11:0] hdmi_width;
reg [11:0] arx;
reg [11:0] ary;
reg arxy;
always @(posedge clk_vid) begin
reg [11:0] hmini,hmaxi,vmini,vmaxi;
reg [11:0] wcalc,videow,arx;
reg [11:0] hcalc,videoh,ary;
reg [11:0] wcalc,videow;
reg [11:0] hcalc,videoh;
reg [2:0] state;
reg xy;
hdmi_height <= (VSET && (VSET < HEIGHT)) ? VSET : HEIGHT;
hdmi_width <= (HSET && (HSET < WIDTH)) ? HSET : WIDTH;
hdmi_width <= (HSET && (HSET < WIDTH)) ? HSET << HDMI_PR : WIDTH << HDMI_PR;
if(!ARY) begin
if(ARX == 1) begin
arx <= arc1x[11:0];
ary <= arc1y[11:0];
xy <= arc1x[12] | arc1y[12];
arxy <= arc1x[12] | arc1y[12];
end
else if(ARX == 2) begin
arx <= arc2x[11:0];
ary <= arc2y[11:0];
xy <= arc2x[12] | arc2y[12];
arxy <= arc2x[12] | arc2y[12];
end
else begin
arx <= 0;
ary <= 0;
xy <= 0;
arxy <= 0;
end
end
else begin
arx <= ARX[11:0];
ary <= ARY[11:0];
xy <= ARX[12] | ARY[12];
arxy <= ARX[12] | ARY[12];
end
ar_md_start <= 0;
@ -852,7 +890,7 @@ always @(posedge clk_vid) begin
hcalc <= hdmi_height;
state <= 6;
end
else if(xy) begin
else if(arxy) begin
wcalc <= arx;
hcalc <= ary;
state <= 6;
@ -881,7 +919,7 @@ always @(posedge clk_vid) begin
end
6: begin
videow <= (wcalc > hdmi_width) ? hdmi_width : wcalc[11:0];
videow <= (wcalc > hdmi_width) ? (hdmi_width >> HDMI_PR) : (wcalc[11:0] >> HDMI_PR);
videoh <= (hcalc > hdmi_height) ? hdmi_height : hcalc[11:0];
end
@ -907,7 +945,7 @@ pll_hdmi_adj pll_hdmi_adj
.reset_na(~reset_req),
.llena(lowlat),
.lltune({16{hdmi_config_done | cfg_dis}} & lltune),
.lltune({16{cfg_done}} & lltune),
.locked(led_locked),
.i_waitrequest(adj_waitrequest),
.i_write(adj_write),
@ -963,6 +1001,7 @@ reg [11:0] HEIGHT = 1080;
reg [11:0] VFP = 4;
reg [12:0] VS = 5;
reg [11:0] VBP = 36;
reg HDMI_PR = 0;
wire [63:0] reconfig_to_pll;
wire [63:0] reconfig_from_pll;
@ -1035,22 +1074,6 @@ wire cfg_ready = 1;
`endif
wire hdmi_config_done;
hdmi_config hdmi_config
(
.iCLK(FPGA_CLK1_50),
.iRST_N(cfg_ready & ~HDMI_TX_INT & ~cfg_dis),
.done(hdmi_config_done),
.I2C_SCL(HDMI_I2C_SCL),
.I2C_SDA(HDMI_I2C_SDA),
.dvi_mode(dvi_mode),
.audio_96k(audio_96k),
.limited(hdmi_limited),
.ypbpr(ypbpr_en & direct_video)
);
assign HDMI_I2C_SCL = hdmi_scl_en ? 1'b0 : 1'bZ;
assign HDMI_I2C_SDA = hdmi_sda_en ? 1'b0 : 1'bZ;
@ -1132,34 +1155,41 @@ csync csync_hdmi(clk_hdmi, hdmi_hs_osd, hdmi_vs_osd, hdmi_cs_osd);
reg [23:0] dv_data;
reg dv_hs, dv_vs, dv_de;
wire [23:0] dv_data_osd;
wire dv_hs_osd, dv_vs_osd, dv_cs_osd;
always @(posedge clk_vid) begin
reg [23:0] dv_d1, dv_d2;
reg dv_de1, dv_de2, dv_hs1, dv_hs2, dv_vs1, dv_vs2;
reg [12:0] vsz, vcnt;
reg [12:0] vsz, vcnt, vcnt_l, vcnt_ll;
reg old_hs, old_vs;
reg vde;
reg [3:0] hss;
if(ce_pix) begin
hss <= (hss << 1) | vga_hs_osd;
hss <= (hss << 1) | dv_hs_osd;
old_hs <= vga_hs_osd;
if(~old_hs && vga_hs_osd) begin
old_vs <= vga_vs_osd;
old_hs <= dv_hs_osd;
if(~old_hs && dv_hs_osd) begin
old_vs <= dv_vs_osd;
if(~&vcnt) vcnt <= vcnt + 1'd1;
if(~old_vs & vga_vs_osd & ~f1) vsz <= vcnt;
if(old_vs & ~vga_vs_osd) vcnt <= 0;
if(~old_vs & dv_vs_osd) begin
if (vcnt != vcnt_ll || vcnt < vcnt_l) vsz <= vcnt;
vcnt_l <= vcnt;
vcnt_ll <= vcnt_l;
end
if(old_vs & ~dv_vs_osd) vcnt <= 0;
if(vcnt == 1) vde <= 1;
if(vcnt == vsz - 3) vde <= 0;
end
dv_de1 <= !{hss,vga_hs_osd} && vde;
dv_hs1 <= csync_en ? vga_cs_osd : vga_hs_osd;
dv_vs1 <= vga_vs_osd;
dv_de1 <= !{hss,dv_hs_osd} && vde;
dv_hs1 <= csync_en ? dv_cs_osd : dv_hs_osd;
dv_vs1 <= dv_vs_osd;
end
dv_d1 <= vga_data_osd;
dv_d1 <= dv_data_osd;
dv_d2 <= dv_d1;
dv_de2 <= dv_de1;
dv_hs2 <= dv_hs1;
@ -1171,6 +1201,12 @@ always @(posedge clk_vid) begin
dv_vs <= dv_vs2;
end
`ifndef MISTER_DISABLE_YC
assign {dv_data_osd, dv_hs_osd, dv_vs_osd, dv_cs_osd } = ~yc_en ? {vga_data_osd, vga_hs_osd, vga_vs_osd, vga_cs_osd } : {yc_o, yc_hs, yc_vs, yc_cs };
`else
assign {dv_data_osd, dv_hs_osd, dv_vs_osd, dv_cs_osd } = {vga_data_osd, vga_hs_osd, vga_vs_osd, vga_cs_osd };
`endif
wire hdmi_tx_clk;
`ifndef MISTER_DEBUG_NOHDMI
cyclonev_clkselect hdmi_clk_sw
@ -1289,6 +1325,7 @@ wire vga_cs_osd;
csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd);
`ifndef MISTER_DUAL_SDRAM
wire VGA_DISABLE;
wire [23:0] vgas_o;
wire vgas_hs, vgas_vs, vgas_cs;
vga_out vga_scaler_out
@ -1305,8 +1342,8 @@ csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd);
.csync_o(vgas_cs)
);
wire [23:0] vga_o;
wire vga_hs, vga_vs, vga_cs;
wire [23:0] vga_o, vga_o_t;
wire vga_hs, vga_vs, vga_cs, vga_hs_t, vga_vs_t, vga_cs_t;
vga_out vga_out
(
.clk(clk_vid),
@ -1314,20 +1351,51 @@ csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd);
.hsync(vga_hs_osd),
.vsync(vga_vs_osd),
.csync(vga_cs_osd),
.dout(vga_o),
.dout(vga_o_t),
.din(vga_data_osd),
.hsync_o(vga_hs),
.vsync_o(vga_vs),
.csync_o(vga_cs)
.hsync_o(vga_hs_t),
.vsync_o(vga_vs_t),
.csync_o(vga_cs_t)
);
`ifndef MISTER_DISABLE_YC
reg pal_en;
reg yc_en;
reg cvbs;
reg [16:0] ColorBurst_Range;
reg [39:0] PhaseInc;
wire [23:0] yc_o;
wire yc_hs, yc_vs, yc_cs;
yc_out yc_out
(
.clk(clk_vid),
.PAL_EN(pal_en),
.CVBS(cvbs),
.PHASE_INC(PhaseInc),
.COLORBURST_RANGE(ColorBurst_Range),
.hsync(vga_hs_osd),
.vsync(vga_vs_osd),
.csync(vga_cs_osd),
.dout(yc_o),
.din(vga_data_osd),
.hsync_o(yc_hs),
.vsync_o(yc_vs),
.csync_o(yc_cs)
);
assign {vga_o, vga_hs, vga_vs, vga_cs } = ~yc_en ? {vga_o_t, vga_hs_t, vga_vs_t, vga_cs_t } : {yc_o, yc_hs, yc_vs, yc_cs };
`else
assign {vga_o, vga_hs, vga_vs, vga_cs } = {vga_o_t, vga_hs_t, vga_vs_t, vga_cs_t } ;
`endif
wire cs1 = (vga_fb | vga_scaler) ? vgas_cs : vga_cs;
assign VGA_VS = (VGA_EN | SW[3]) ? 1'bZ :((((vga_fb | vga_scaler) ? ~vgas_vs : ~vga_vs) | csync_en) ^ VS[12]);
assign VGA_HS = (VGA_EN | SW[3]) ? 1'bZ : (((vga_fb | vga_scaler) ? (csync_en ? ~vgas_cs : ~vgas_hs) : (csync_en ? ~vga_cs : ~vga_hs)) ^ HS[12]);
assign VGA_R = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[23:18] : vga_o[23:18];
assign VGA_G = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[15:10] : vga_o[15:10];
assign VGA_B = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[7:2] : vga_o[7:2] ;
assign VGA_VS = (VGA_EN | SW[3]) ? 1'bZ : (((vga_fb | vga_scaler) ? (~vgas_vs ^ VS[12]) : VGA_DISABLE ? 1'd1 : ~vga_vs) | csync_en);
assign VGA_HS = (VGA_EN | SW[3]) ? 1'bZ : ((vga_fb | vga_scaler) ? ((csync_en ? ~vgas_cs : ~vgas_hs) ^ HS[12]) : VGA_DISABLE ? 1'd1 : (csync_en ? ~vga_cs : ~vga_hs));
assign VGA_R = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[23:18] : VGA_DISABLE ? 6'd0 : vga_o[23:18];
assign VGA_G = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[15:10] : VGA_DISABLE ? 6'd0 : vga_o[15:10];
assign VGA_B = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[7:2] : VGA_DISABLE ? 6'd0 : vga_o[7:2] ;
`endif
reg video_sync = 0;
@ -1400,8 +1468,10 @@ audio_out audio_out
.core_l(audio_l),
.core_r(audio_r),
`ifndef MISTER_DISABLE_ALSA
.alsa_l(alsa_l),
.alsa_r(alsa_r),
`endif
.i2s_bclk(HDMI_SCLK),
.i2s_lrclk(HDMI_LRCLK),
@ -1414,6 +1484,18 @@ audio_out audio_out
);
`ifndef MISTER_DISABLE_ALSA
wire aspi_sck,aspi_mosi,aspi_ss,aspi_miso;
cyclonev_hps_interface_peripheral_spi_master spi
(
.sclk_out(aspi_sck),
.txd(aspi_mosi), // mosi
.rxd(aspi_miso), // miso
.ss_0_n(aspi_ss),
.ss_in_n(1)
);
wire [28:0] alsa_address;
wire [63:0] alsa_readdata;
wire alsa_ready;
@ -1440,6 +1522,7 @@ alsa alsa
.pcm_l(alsa_l),
.pcm_r(alsa_r)
);
`endif
//////////////// User I/O (USB 3.0 connector) /////////////////////////
@ -1560,6 +1643,10 @@ emu emu
.VGA_F1(f1),
.VGA_SCALER(vga_force_scaler),
`ifndef MISTER_DUAL_SDRAM
.VGA_DISABLE(VGA_DISABLE),
`endif
.HDMI_WIDTH(direct_video ? 12'd0 : hdmi_width),
.HDMI_HEIGHT(direct_video ? 12'd0 : hdmi_height),
.HDMI_FREEZE(freeze),

230
sys/yc_out.sv Normal file
View File

@ -0,0 +1,230 @@
//============================================================================
// YC - Luma / Chroma Generation
// Copyright (C) 2022 Mike Simone
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
//============================================================================
/*
Colorspace
Y 0.299R' + 0.587G' + 0.114B'
U 0.492(B' - Y) = 504 (X 1024)
V 0.877(R' - Y) = 898 (X 1024)
*/
//////////////////////////////////////////////////////////
module yc_out
(
input clk,
input [39:0] PHASE_INC,
input PAL_EN,
input CVBS,
input [16:0] COLORBURST_RANGE,
input hsync,
input vsync,
input csync,
input [23:0] din,
output [23:0] dout,
output reg hsync_o,
output reg vsync_o,
output reg csync_o
);
wire [7:0] red = din[23:16];
wire [7:0] green = din[15:8];
wire [7:0] blue = din[7:0];
logic [9:0] red_1, blue_1, green_1, red_2, blue_2, green_2;
logic signed [20:0] yr = 0, yb = 0, yg = 0;
typedef struct {
logic signed [20:0] y;
logic signed [20:0] c;
logic signed [20:0] u;
logic signed [20:0] v;
logic hsync;
logic vsync;
logic csync;
} phase_t;
localparam MAX_PHASES = 7'd8;
phase_t phase[MAX_PHASES];
reg unsigned [7:0] Y, C, c, U, V;
reg [10:0] cburst_phase; // colorburst counter
reg unsigned [7:0] vref = 'd128; // Voltage reference point (Used for Chroma)
logic [7:0] chroma_LUT_COS; // Chroma cos LUT reference
logic [7:0] chroma_LUT_SIN; // Chroma sin LUT reference
logic [7:0] chroma_LUT_BURST; // Chroma colorburst LUT reference
logic [7:0] chroma_LUT = 8'd0;
/*
THe following LUT table was calculated by Sin(2*pi*t/2^8) where t: 0 - 255
*/
/*************************************
8 bit Sine look up Table
**************************************/
wire signed [10:0] chroma_SIN_LUT[256] = '{
11'h000, 11'h006, 11'h00C, 11'h012, 11'h018, 11'h01F, 11'h025, 11'h02B, 11'h031, 11'h037, 11'h03D, 11'h044, 11'h04A, 11'h04F,
11'h055, 11'h05B, 11'h061, 11'h067, 11'h06D, 11'h072, 11'h078, 11'h07D, 11'h083, 11'h088, 11'h08D, 11'h092, 11'h097, 11'h09C,
11'h0A1, 11'h0A6, 11'h0AB, 11'h0AF, 11'h0B4, 11'h0B8, 11'h0BC, 11'h0C1, 11'h0C5, 11'h0C9, 11'h0CC, 11'h0D0, 11'h0D4, 11'h0D7,
11'h0DA, 11'h0DD, 11'h0E0, 11'h0E3, 11'h0E6, 11'h0E9, 11'h0EB, 11'h0ED, 11'h0F0, 11'h0F2, 11'h0F4, 11'h0F5, 11'h0F7, 11'h0F8,
11'h0FA, 11'h0FB, 11'h0FC, 11'h0FD, 11'h0FD, 11'h0FE, 11'h0FE, 11'h0FE, 11'h0FF, 11'h0FE, 11'h0FE, 11'h0FE, 11'h0FD, 11'h0FD,
11'h0FC, 11'h0FB, 11'h0FA, 11'h0F8, 11'h0F7, 11'h0F5, 11'h0F4, 11'h0F2, 11'h0F0, 11'h0ED, 11'h0EB, 11'h0E9, 11'h0E6, 11'h0E3,
11'h0E0, 11'h0DD, 11'h0DA, 11'h0D7, 11'h0D4, 11'h0D0, 11'h0CC, 11'h0C9, 11'h0C5, 11'h0C1, 11'h0BC, 11'h0B8, 11'h0B4, 11'h0AF,
11'h0AB, 11'h0A6, 11'h0A1, 11'h09C, 11'h097, 11'h092, 11'h08D, 11'h088, 11'h083, 11'h07D, 11'h078, 11'h072, 11'h06D, 11'h067,
11'h061, 11'h05B, 11'h055, 11'h04F, 11'h04A, 11'h044, 11'h03D, 11'h037, 11'h031, 11'h02B, 11'h025, 11'h01F, 11'h018, 11'h012,
11'h00C, 11'h006, 11'h000, 11'h7F9, 11'h7F3, 11'h7ED, 11'h7E7, 11'h7E0, 11'h7DA, 11'h7D4, 11'h7CE, 11'h7C8, 11'h7C2, 11'h7BB,
11'h7B5, 11'h7B0, 11'h7AA, 11'h7A4, 11'h79E, 11'h798, 11'h792, 11'h78D, 11'h787, 11'h782, 11'h77C, 11'h777, 11'h772, 11'h76D,
11'h768, 11'h763, 11'h75E, 11'h759, 11'h754, 11'h750, 11'h74B, 11'h747, 11'h743, 11'h73E, 11'h73A, 11'h736, 11'h733, 11'h72F,
11'h72B, 11'h728, 11'h725, 11'h722, 11'h71F, 11'h71C, 11'h719, 11'h716, 11'h714, 11'h712, 11'h70F, 11'h70D, 11'h70B, 11'h70A,
11'h708, 11'h707, 11'h705, 11'h704, 11'h703, 11'h702, 11'h702, 11'h701, 11'h701, 11'h701, 11'h701, 11'h701, 11'h701, 11'h701,
11'h702, 11'h702, 11'h703, 11'h704, 11'h705, 11'h707, 11'h708, 11'h70A, 11'h70B, 11'h70D, 11'h70F, 11'h712, 11'h714, 11'h716,
11'h719, 11'h71C, 11'h71F, 11'h722, 11'h725, 11'h728, 11'h72B, 11'h72F, 11'h733, 11'h736, 11'h73A, 11'h73E, 11'h743, 11'h747,
11'h74B, 11'h750, 11'h754, 11'h759, 11'h75E, 11'h763, 11'h768, 11'h76D, 11'h772, 11'h777, 11'h77C, 11'h782, 11'h787, 11'h78D,
11'h792, 11'h798, 11'h79E, 11'h7A4, 11'h7AA, 11'h7B0, 11'h7B5, 11'h7BB, 11'h7C2, 11'h7C8, 11'h7CE, 11'h7D4, 11'h7DA, 11'h7E0,
11'h7E7, 11'h7ED, 11'h7F3, 11'h7F9
};
logic [39:0] phase_accum;
logic PAL_FLIP = 1'd0;
logic PAL_line_count = 1'd0;
/**************************************
Generate Luma and Chroma Signals
***************************************/
always_ff @(posedge clk) begin
for (logic [3:0] x = 0; x < (MAX_PHASES - 1'd1); x = x + 1'd1) begin
phase[x + 1] <= phase[x];
end
// delay red / blue signals to align luma with U/V calculation (Fixes colorbleeding)
red_1 <= red;
blue_1 <= blue;
red_2 <= red_1;
blue_2 <= blue_1;
// Calculate Luma signal
yr <= {red, 8'd0} + {red, 5'd0}+ {red, 4'd0} + {red, 1'd0};
yg <= {green, 9'd0} + {green, 6'd0} + {green, 4'd0} + {green, 3'd0} + green;
yb <= {blue, 6'd0} + {blue, 5'd0} + {blue, 4'd0} + {blue, 2'd0} + blue;
phase[0].y <= yr + yg + yb;
// Generate the LUT values using the phase accumulator reference.
phase_accum <= phase_accum + PHASE_INC;
chroma_LUT <= phase_accum[39:32];
// Adjust SINE carrier reference for PAL (Also adjust for PAL Switch)
if (PAL_EN) begin
if (PAL_FLIP)
chroma_LUT_BURST <= chroma_LUT + 8'd160;
else
chroma_LUT_BURST <= chroma_LUT + 8'd96;
end else // Adjust SINE carrier reference for NTSC
chroma_LUT_BURST <= chroma_LUT + 8'd128;
// Prepare LUT values for sin / cos (+90 degress)
chroma_LUT_SIN <= chroma_LUT;
chroma_LUT_COS <= chroma_LUT + 8'd64;
// Calculate for U, V - Bit Shift Multiple by u = by * 1024 x 0.492 = 504, v = ry * 1024 x 0.877 = 898
phase[0].u <= $signed({2'b0 ,(blue_2)}) - $signed({2'b0 ,phase[0].y[17:10]});
phase[0].v <= $signed({2'b0 , (red_2)}) - $signed({2'b0 ,phase[0].y[17:10]});
phase[1].u <= 21'($signed({phase[0].u, 8'd0}) + $signed({phase[0].u, 7'd0}) + $signed({phase[0].u, 6'd0}) + $signed({phase[0].u, 5'd0}) + $signed({phase[0].u, 4'd0}) + $signed({phase[0].u, 3'd0}));
phase[1].v <= 21'($signed({phase[0].v, 9'd0}) + $signed({phase[0].v, 8'd0}) + $signed({phase[0].v, 7'd0}) + $signed({phase[0].v, 1'd0}));
phase[0].c <= vref;
phase[1].c <= phase[0].c;
phase[2].c <= phase[1].c;
phase[3].c <= phase[2].c;
if (hsync) begin // Reset colorburst counter, as well as the calculated cos / sin values.
cburst_phase <= 'd0;
phase[2].u <= 21'b0;
phase[2].v <= 21'b0;
phase[4].c <= phase[3].c;
if (PAL_line_count) begin
PAL_FLIP <= ~PAL_FLIP;
PAL_line_count <= ~PAL_line_count;
end
end
else begin // Generate Colorburst for 9 cycles
if (cburst_phase >= COLORBURST_RANGE[16:10] && cburst_phase <= COLORBURST_RANGE[9:0]) begin // Start the color burst signal at 40 samples or 0.9 us
// COLORBURST SIGNAL GENERATION (9 CYCLES ONLY or between count 40 - 240)
phase[2].u <= $signed({chroma_SIN_LUT[chroma_LUT_BURST],5'd0});
phase[2].v <= 21'b0;
// Division to scale down the results to fit 8 bit.
if (PAL_EN)
phase[3].u <= $signed(phase[2].u[20:8]) + $signed(phase[2].u[20:10]) + $signed(phase[2].u[20:14]);
else
phase[3].u <= $signed(phase[2].u[20:8]) + $signed(phase[2].u[20:11]) + $signed(phase[2].u[20:12]) + $signed(phase[2].u[20:13]);
phase[3].v <= phase[2].v;
end else begin // MODULATE U, V for chroma
/*
U,V are both multiplied by 1024 earlier to scale for the decimals in the YUV colorspace conversion.
U and V are both divided by 2^10 which introduce chroma subsampling of 4:1:1 (25% or from 8 bit to 6 bit)
*/
phase[2].u <= $signed((phase[1].u)>>>10) * $signed(chroma_SIN_LUT[chroma_LUT_SIN]);
phase[2].v <= $signed((phase[1].v)>>>10) * $signed(chroma_SIN_LUT[chroma_LUT_COS]);
// Divide U*sin(wt) and V*cos(wt) to fit results to 8 bit
phase[3].u <= $signed(phase[2].u[20:9]) + $signed(phase[2].u[20:10]) + $signed(phase[2].u[20:14]);
phase[3].v <= $signed(phase[2].v[20:9]) + $signed(phase[2].v[20:10]) + $signed(phase[2].u[20:14]);
end
// Stop the colorburst timer as its only needed for the initial pulse
if (cburst_phase <= COLORBURST_RANGE[9:0])
cburst_phase <= cburst_phase + 9'd1;
// Calculate for chroma (Note: "PAL SWITCH" routine flips V * COS(Wt) every other line)
if (PAL_EN) begin
if (PAL_FLIP)
phase[4].c <= vref + phase[3].u - phase[3].v;
else
phase[4].c <= vref + phase[3].u + phase[3].v;
PAL_line_count <= 1'd1;
end else
phase[4].c <= vref + phase[3].u + phase[3].v;
end
// Adjust sync timing correctly
phase[1].hsync <= hsync; phase[1].vsync <= vsync; phase[1].csync <= csync;
phase[2].hsync <= phase[1].hsync; phase[2].vsync <= phase[1].vsync; phase[2].csync <= phase[1].csync;
phase[3].hsync <= phase[2].hsync; phase[3].vsync <= phase[2].vsync; phase[3].csync <= phase[2].csync;
phase[4].hsync <= phase[3].hsync; phase[4].vsync <= phase[3].vsync; phase[4].csync <= phase[3].csync;
hsync_o <= phase[4].hsync; vsync_o <= phase[4].vsync; csync_o <= phase[4].csync;
phase[1].y <= phase[0].y; phase[2].y <= phase[1].y; phase[3].y <= phase[2].y; phase[4].y <= phase[3].y; phase[5].y <= phase[4].y;
// Set Chroma / Luma output
C <= CVBS ? 8'd0 : phase[4].c[7:0];
Y <= CVBS ? ({1'b0, phase[5].y[17:11]} + {1'b0, phase[4].c[7:1]}) : phase[5].y[17:10];
end
assign dout = {C, Y, 8'd0};
endmodule