--------------------------------------------------------------------------- -- (c) 2017 mark watson -- I am happy for anyone to use this for non-commercial use. -- If my vhdl files are used commercially or otherwise sold, -- please contact me for explicit permission at scrameta (gmail). -- This applies for source and binary form and derived works. --------------------------------------------------------------------------- LIBRARY ieee; USE ieee.std_logic_1164.all; use ieee.numeric_std.all; USE ieee.math_real.ceil; USE ieee.math_real.log2; use IEEE.STD_LOGIC_MISC.all; ENTITY hue IS PORT ( clk : in std_logic; reset_n : in std_logic; hue : in std_logic_vector(3 downto 0); burst : in std_logic; blank : in std_logic; vpos_lsb : in std_logic; pal : in std_logic; colour_osc : in std_logic_vector(1 downto 0); colour_osc_phased : out std_logic_vector(1 downto 0) ); END hue; ARCHITECTURE vhdl OF hue IS signal sin_phase : std_logic_vector(7 downto 0); --signal sin_phase_real :real; signal sin_on : std_logic; signal hue_adj : std_logic_vector(3 downto 0); signal hue_delay : std_logic_vector(3 downto 0); signal colour_shift : std_logic_vector(7 downto 0); signal base_shift : std_logic_vector(7 downto 0); signal colour_osc_delay_next : std_logic_vector(511 downto 0); signal colour_osc_delay_reg : std_logic_vector(511 downto 0); signal colour_osc_phased_next : std_logic_vector(1 downto 0); signal colour_osc_phased_reg : std_logic_vector(1 downto 0); BEGIN process(clk,reset_n) begin if (reset_n='0') then colour_osc_delay_reg <= (others=>'0'); colour_osc_phased_reg <= "00"; elsif (clk'event and clk='1') then colour_osc_delay_reg <= colour_osc_delay_next; colour_osc_phased_reg <= colour_osc_phased_next; end if; end process; -- next state process(colour_osc_delay_reg,colour_osc) begin colour_osc_delay_next(511 downto 0) <= colour_osc_delay_reg(509 downto 0)&colour_osc; end process; process(colour_osc_delay_reg,sin_phase,sin_on) variable idx : integer; begin idx := to_integer(unsigned(sin_phase))/2; colour_osc_phased_next <= colour_osc_delay_reg(idx+1 downto idx); end process; -- 4.43361875MHz - PAL carrier - i.e. 12.8 clock cycles per sin wave! so if we have 256 sine entries,+5*16/4 per cycle, +20 per cycle -- 3.579545MHz - NTSC carrier - i.e. 16 clock cycles per sin wave. so if we have 256 sine entries,+16 per cycle -- NTSC:hue1=same phase as colour carrier, each next has 24 degree shift (adjustable) ... 17.066/256? Will 17 do? -- PAL:hue1=same phase as colour burst, each next has 22.5 degree shift (adjustable). adjust phase each line. 135/225 degrees for burst/hue1... 16/256, nice! process(hue,hue_adj,vpos_lsb,burst,pal) variable hue_use : std_logic_vector(3 downto 0); begin hue_adj <= "0000"; hue_use := hue; if (burst = '1') then hue_use := x"1"; end if; if pal='1' then -- pal has some gaps... if (unsigned(hue_use)>6) then hue_adj <= "000"&pal; end if; if (unsigned(hue_use)>10) then hue_adj <= "00"&pal&"0"; end if; if vpos_lsb='1' then hue_delay <= std_logic_vector(to_unsigned(0,4)-unsigned(hue_use)-unsigned(hue_adj)); else hue_delay <= std_logic_vector(to_unsigned(2,4)+unsigned(hue_use)+unsigned(hue_adj)); end if; else hue_delay <= std_logic_vector(to_unsigned(0,4)-unsigned(hue_use)); end if; end process; process(hue_delay,pal) begin colour_shift <= hue_delay&"0000"; if pal='0' then colour_shift <= std_logic_vector(unsigned(hue_delay&"0000") + unsigned("000"&hue_delay&"0")); end if; end process; process(pal) begin if (pal = '1') then base_shift <= std_logic_vector(to_unsigned(112,8)); -- 157.5 degrees (256*157.5/360) else base_shift <= std_logic_vector(to_unsigned(248,8)); -- -12 degrees (256*348/360) end if; end process; process(blank,burst,colour_shift,hue,sin_phase,base_shift) begin sin_on <= '0'; sin_phase <=std_logic_vector(unsigned(base_shift)+unsigned(colour_shift)); --sin_phase_real <= real(to_integer(unsigned(sin_phase)))*real(360)/real(256); if (blank='1') then sin_on <= burst; else sin_on <= or_reduce(hue); end if; end process; colour_osc_phased <= colour_osc_phased_reg when sin_on='1' else "00"; END vhdl;