-------------------------------- -- P2084A.vhd ------------------ -- Firmware version 1 ---------- -------------------------------- -------------------------------- -- (c) 2016 Richard Studley ---- -- Brandeis University --------- -- Updated 29 June 2016 -------- -------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; -- library lattice; -- use lattice.components.all; entity main is port ( A, -- LVDS signal in LOGICZERO : in std_ulogic; WAKE5V, -- Power switches WAKE15V, B, LB, -- Loop back TP1, TP2, TP3, TP4 -- Test pads : out std_logic ); end; architecture behavior of main is ------------------------------------ -- LWDAQ Command Receiver signals:-- ------------------------------------ signal synchronized_A : std_logic; -- "A" synchronized to CLK signal synchronized_A_pipeline : -- pipeline register of SA to create DA & DDA std_logic_vector(31 downto 0); signal delayed_A : std_logic; -- "SA" positive edges delayed by 125 ns signal delayed_delayed_A : -- "SA" positive edges delayed by 250 ns std_logic; signal receiver_active : std_logic; -- shows that command receiver is active signal address_register : -- 16 bit LWDAQ address word std_logic_vector(15 downto 0); signal address_strobe : std_logic; -- loads data_bit_register into address_register -- Command Receiver Abbreviations: alias SA : std_logic is synchronized_A; alias SA_pipeline : std_logic_vector (31 downto 0) is synchronized_A_pipeline; alias DA : std_logic is delayed_A; alias DDA : std_logic is delayed_delayed_A; ------------------------------------------- --End LWDAQ Command Receiver Declarations-- ------------------------------------------- attribute syn_keep : boolean; attribute preserve_signal : boolean; --compiler attributes prevent optimization attribute nomerge : string; signal CLK : std_logic; signal delayone, delaytwo, delaythree : std_logic; signal downstream_off : std_logic; signal junk : std_logic; attribute syn_keep of delayone, delaytwo, delaythree, CLK : signal is true; attribute preserve_signal of delayone, delaytwo, delaythree, CLK : signal is true; attribute nomerge of delayone, delaytwo, delaythree, CLK : signal is ""; begin -------------------------------- --BEGIN LWDAQ Command Receiver-- -------------------------------- command_receiver: process(CLK) is type command_receiver_state is ( -- FSM state type defined inactive, address_receive ); variable current_state, next_state : -- FSM state variable instantiated command_receiver_state := inactive; variable driver_bit_register : -- Pipeline register records incoming bits; std_logic_vector(16 downto 0 ) := -- The command word is then clocked into "00000000000000000"; -- command register in its entirety begin -- Generation of synchronized and delayed versions of input signal "A": -- -- For more information, see: -- http://alignment.hep.brandeis.edu/Electronics/LWDAQ/LWDAQ.html#Transmit Signals if rising_edge(CLK) then SA <= A; -- synchronizes data stream; SA_pipeline <= SA_pipeline(30 downto 0) & SA; -- shifts data pipeline register DA <= SA_pipeline(11) and not SA_pipeline(12); -- creates DA from 125 ns delay DDA <= SA_pipeline(22) and not SA_pipeline(23); -- creates DDA from 250 ns delay -- creates loopback signal; -- Generation of "Receiver Active" signal: if (SA = '0' and DDA = '1') then receiver_active <= '1'; junk <= '1'; elsif (SA = '1' and DDA = '1') then receiver_active <= '0'; junk <= '1'; else receiver_active <= receiver_active; junk <= '0'; end if; -- Begin LWDAQ Command Receiver State Machine: case current_state is when inactive => if receiver_active = '1' then if driver_bit_register(0) = '1' then -- Looks at first bit of command word; next_state := inactive; -- if 1, word is LWDAQ command else next_state := address_receive; -- if 0, word is LWDAQ address end if; else next_state := inactive; -- Stays in inactive until receiver_active end if; address_strobe <= '0'; when address_receive => if receiver_active = '1' then next_state := address_receive; -- Stays in address_receive until LWDAQ address word is complete address_strobe <= '0'; else address_register <= -- Loads LWDAQ address word into register driver_bit_register(16 downto 1); address_strobe <= '1'; -- Activates address strobe pulse next_state := inactive; -- Returns to idle state end if; when others => next_state := inactive; address_register <= address_register; address_strobe <= '0'; end case; -- End LWDAQ Command Receiver State Machine -- Clocking of Command Word into "driver_bit_register": if DA = '1' then driver_bit_register := driver_bit_register(15 downto 0) & SA; else driver_bit_register := driver_bit_register; end if; -- Clocking of State Machine state register: -- TP2 <= driver_bit_register(0); current_state := next_state; end if; end process; ------------------------------ --END LWDAQ Command Receiver-- ------------------------------ WAKE5V <= NOT downstream_off; WAKE15V <= NOT downstream_off; LB <= '1'; delayone <= (delaythree NOR logiczero); delaytwo <= (delayone OR logiczero); delaythree <= (delaytwo OR logiczero); -- TP1 <= SA and DDA; -- TP2 <= (NOT SA) and DDA; TP1 <= receiver_active; TP2 <= address_strobe; -- TP1 <= address_register(0); -- TP2 <= address_strobe; CLK <= delayone; update_b : process (CLK) is begin if rising_edge(CLK) then B <= A; end if; end process; downstream_power : process (address_strobe) is begin if rising_edge(address_strobe) then if address_register(0) = '1' then -- TP1 <= not TP1; downstream_off <= '1'; else -- TP2 <= NOT TP2; downstream_off <= '0'; end if; end if; end process; end behavior;