library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; entity laser is port ( n_por : in std_logic; clk_50mhz : in std_logic; iis_sdin : in std_logic; iis_sclk : in std_logic; iis_lrclk : in std_logic; iis_mclk : in std_logic; laser_out : out std_logic; dbg : out std_logic_vector(7 downto 0) ); end laser; architecture rtl of laser is signal sdin_sr: std_logic_vector(32 downto 0); signal lrclk_sr: std_logic_vector(32 downto 0); signal l: std_logic_vector(15 downto 0); signal r: std_logic_vector(15 downto 0); signal sample_clock: std_logic; signal last_lrclk : std_logic; signal sample_clk : std_logic; signal laser: std_logic; signal laser_sr: std_logic_vector(31 downto 0); signal sr: std_logic_vector(3 downto 0); signal sl: std_logic_vector(3 downto 0); signal se: std_logic; signal safety: std_logic; signal safety_counter: std_logic_vector(31 downto 0); signal n_reset: std_logic; -- signal ticks: -- std_logic_vector(31 downto 0); -- signal toggle: std_logic; begin dbg(0) <= iis_sdin; dbg(1) <= iis_sclk; dbg(2) <= iis_lrclk; dbg(3) <= iis_mclk; dbg(4) <= se; dbg(5) <= '0'; dbg(6) <= '0'; dbg(7) <= '0'; n_reset <= n_por; -- iis shift register, latch bits on rising edge of sample_clk -- detect edges in lrclk and copy to l and r registers on falling edge -- generate a sample clock whose rising edge is 1 sclk after data is latched -- and therefor 1.5sclk after data arrives process(iis_sclk,iis_sdin,iis_lrclk,sdin_sr,lrclk_sr,n_reset) begin if n_reset ='0' then sdin_sr <= (others => '0'); lrclk_sr <= (others => '0'); sample_clk <='1'; l<=(others => '0'); r<=(others => '0'); else if rising_edge(iis_sclk) then sdin_sr <= sdin_sr(31 downto 0) & iis_sdin; lrclk_sr <= lrclk_sr(31 downto 0) & iis_lrclk; end if; if falling_edge(iis_sclk) then -- new data for left channel if (lrclk_sr(1) = '0') and (lrclk_sr(0) ='1') then l <=sdin_sr(31 downto 16); end if; -- new data for right channel if (lrclk_sr(1) = '1') and (lrclk_sr(0) ='0') then r <=sdin_sr(31 downto 16); sample_clk <='0'; else sample_clk <='1'; end if; end if; end if; end process; -- drive the laser from the xor of the LSBs laser <= not(l(0) xor r(0)); -- make sample clock based shift register of -- laser because DAC has latency process(sample_clk,laser,laser_sr,n_reset) begin if n_reset ='0' then laser_sr <= (others => '0'); elsif rising_edge(sample_clk) then laser_sr <= laser_sr(30 downto 0) & laser; end if; end process; -- safety system -- see if there are changes in a bit of either the -- left or right channels in 0.5s -- run this from a different clock domain incase sample_clk stops -- resample the l and r bits into new clock domain -- with shift register process(clk_50mhz,sl,sr,l,r,safety_counter,n_reset) begin if n_reset ='0' then sl <= (others => '0'); sr <= (others => '0'); elsif rising_edge(clk_50mhz) then sl <= sl(2 downto 0) & l(12); sr <= sr(2 downto 0) & r(12); end if; end process; -- detect changes in either bit se<=(sl(3) xor sl(2)) or (sr(3) xor sr(2)); process(clk_50mhz,se,safety_counter,n_reset) begin -- count how long since a bit changed if n_reset ='0' then safety_counter <= (others => '0'); elsif falling_edge(clk_50mhz) then if se='1' then safety_counter <= (others => '0'); else safety_counter <= safety_counter + 1; end if; end if; -- if it's too long blank the beam if n_reset ='0' then safety <= '0'; elsif rising_edge(clk_50mhz) then if (safety_counter>1000000) then safety <= '0'; else safety <= '1'; end if; end if; end process; laser_out <= laser_sr(10) and safety; -- laser_out <= laser; -- process(test_clk,ticks,n_reset) -- begin -- if n_reset ='0' then -- ticks <= (others => '0'); -- toggle <= '0'; -- elsif rising_edge(test_clk) then -- if ticks < (22050 * 32) then -- ticks <= ticks + 1; -- else -- toggle <= not toggle; -- ticks <= (others => '0'); -- end if; -- end if; -- end process; -- -- -- laser_out <= toggle; end rtl;