summaryrefslogtreecommitdiffstats
path: root/cpld/laser.vhd
diff options
context:
space:
mode:
Diffstat (limited to 'cpld/laser.vhd')
-rw-r--r--cpld/laser.vhd213
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;
+