diff options
Diffstat (limited to 'cpld/laser.vhd')
-rw-r--r-- | cpld/laser.vhd | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/cpld/laser.vhd b/cpld/laser.vhd new file mode 100644 index 0000000..cfa1c87 --- /dev/null +++ b/cpld/laser.vhd @@ -0,0 +1,213 @@ + + +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; + |