-- -- LVDS receiver -- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.std_logic_unsigned.all; library UNISIM; use UNISIM.VCOMPONENTS.all; library dsat_lib; use dsat_lib.dsat.all; entity sldb_rx is port ( gclk, grst : in std_logic; -- Local bus signals lb_data_in : in std_logic_vector(7 downto 0); -- data in lb_data_out : out std_logic_vector(7 downto 0); -- data out lb_addr : in std_logic_vector(1 downto 0); -- latched address (low bits) lb_ena : in std_logic; -- address match lb_byte : in std_logic_vector(1 downto 0); -- byte counter for word access lb_read : in std_logic; -- local bus read enable lb_write : in std_logic; -- local bus write enable debug : out std_logic_vector(3 downto 0); g_trig : in std_logic; -- global trigger from SCL bp_start : in std_logic; fc : in std_logic; -- first crossing from SCL -- LVDS input signals sldb_refclk : out std_logic; -- sldb_rx_clk : in std_logic; -- sldb_dav_n : in std_logic; -- sldb_lock : inout std_logic; -- sldb_perr : in std_logic; -- sldb_d : in std_logic_vector(15 downto 0)); end sldb_rx; architecture sldbrx_a of sldb_rx is -- bit pattern for idle on LVDS inputs -- constant LVDS_idle_bits : std_logic_vector(27 downto 0) := (others => '0'); constant CSR_ena : integer := 0; -- CSR enable bit constant CSR_busy : integer := 1; -- CSR busy bit (read only) constant CSR_trig : integer := 2; -- CSR trigger bit (write only) constant CSR_glo : integer := 3; -- CSR global trigger enable bit constant CSR_fc : integer := 4; -- CSR FC trigger enable bit constant CSR_rst : integer := 5; -- CSR SLDB reset bit constant CSR_perr : integer := 6; -- CSR FC trigger enable bit constant CSR_lock : integer := 7; -- CSR FC trigger enable bit type lb_mux_t is array (3 downto 0) of std_logic_vector(7 downto 0); signal lb_mux : lb_mux_t; signal gclkn : std_logic; signal ram_ena : std_logic; -- DPRAM port B enable (receiver) signal port_a_ena : std_logic; -- DPRAM port A enable (lb access) signal pre_trig : std_logic; -- external trigger (fc or global) -- starts delay for receiver active signal en_delay_ctr : std_logic; signal ram_trig : std_logic; -- receiver trigger (CSR_trig, or pre_ -- trig plus delay) signal local_addr_l : std_logic_vector(8 downto 0); -- latch for adx(10:2) signal local_addr_s : std_logic_vector(10 downto 0); -- RAM port A adx signal csr : std_logic_vector(7 downto 0); signal rx_delay : std_logic_vector(6 downto 0); -- receiver delay register (R/W) signal delay_ctr : std_logic_vector(6 downto 0); -- receiver delay countdown signal ram_addr : std_logic_vector(8 downto 0); signal ram_data : std_logic_vector(31 downto 0); signal rxd_l : std_logic_vector(27 downto 0); signal en_rx : std_logic; signal mu_frame : std_logic_vector(2 downto 0); begin -- lvdsrx_a ------------------------------------------------------------------------------- -- Synchronous logic (receiver clock) ------------------------------------------------------------------------------- gclkn <= not gclk; i_refclk : OFDDRCPE port map ( Q => sldb_refclk, C0 => gclk, C1 => gclkn, CE => '1', CLR => '0', D0 => '1', D1 => '0', PRE => '0'); process (sldb_rx_clk) begin if sldb_rx_clk'event and sldb_rx_clk = '1' then ram_data(17 downto 0) <= not sldb_dav_n & sldb_perr & sldb_d; -- capture data with no delays if((ram_data(17) = '0' and sldb_dav_n = '0') or mu_frame = "110")then mu_frame <= "000"; else mu_frame <= mu_frame + 1; end if; end if; end process; process (sldb_rx_clk, grst) begin if grst = '0' then ram_addr <= (others => '0'); ram_ena <= '0'; csr(CSR_perr) <= '0'; elsif sldb_rx_clk'event and sldb_rx_clk = '1' then if en_rx = '1' and mu_frame = "110" then ram_ena <= '1'; ram_addr <= (others => '0'); end if; -- receive data if (enabled) and (not full) if ram_ena = '1' then ram_addr <= ram_addr + 1; if ram_addr = "111111111" then ram_ena <= '0'; -- disable when full end if; end if; if lb_ena = '1' and lb_write = '1' and lb_addr = "10" then -- write csr csr(CSR_perr) <= '0'; else csr(CSR_perr) <= csr(CSR_perr) or (sldb_perr and not sldb_dav_n); end if; end if; end process; ------------------------------------------------------------------------------- -- Synchronous logic (global RF clock) ------------------------------------------------------------------------------- process (gclk, grst) begin -- process if grst = '0' then -- asynchronous reset (active low) en_rx <= '0'; ram_trig <= '0'; local_addr_l <= (others => '0'); pre_trig <= '0'; delay_ctr <= (others => '0'); elsif gclk'event and gclk = '1' then -- rising clock edge if ((lb_ena = '1' and lb_write = '1' and lb_addr = "10" and lb_byte = "00" and lb_data_in( CSR_trig) = '1') or (csr(CSR_glo) = '1' and g_trig = '1') or (csr(CSR_fc) = '1' and fc = '1')) then -- if enabled, trigger bit sets ram_trig pre_trig <= csr( CSR_ena); csr(CSR_fc) <= csr(CSR_fc) and not (fc and csr(CSR_ena)); elsif bp_start = '1' then pre_trig <= '0'; end if; if bp_start = '1' then if pre_trig = '1' then delay_ctr <= rx_delay; en_delay_ctr <= '1'; elsif en_delay_ctr = '1' then if delay_ctr = 0 then en_delay_ctr <= '0'; else delay_ctr <= delay_ctr -1; end if; end if; if delay_ctr = 0 and en_delay_ctr = '1' then ram_trig <= '1'; else ram_trig <= '0'; end if; end if; en_rx <= ram_trig; -- local bus write if lb_ena = '1' and lb_write = '1' then if lb_addr = "00" then -- write to address register case lb_byte is when "00" => local_addr_l(7 downto 0) <= lb_data_in; when "01" => local_addr_l(8) <= lb_data_in(0); when others => null; end case; end if; end if; -- local bus write if lb_ena = '1' and lb_write = '1' then if lb_addr = "00" then -- write to address register case lb_byte is when "00" => local_addr_l(7 downto 0) <= lb_data_in; when "01" => local_addr_l(8) <= lb_data_in(0); when others => null; end case; end if; if lb_addr = "10" and lb_byte = "00" then -- write to CSR lsb csr(5 downto 0) <= lb_data_in(5 downto 0); end if; if lb_addr = "11" then -- write to delay case lb_byte is when "00" => rx_delay <= lb_data_in(6 downto 0); when others => null; end case; end if; end if; -- auto-increment ram address on R/W if port_a_ena = '1' then if lb_byte = "11" then local_addr_l <= local_addr_l + 1; end if; end if; end if; end process; ------------------------------------------------------------------------------- -- Asynchronous logic ------------------------------------------------------------------------------- sldb_lock <= '0' when csr(CSR_rst) = '1' else 'Z'; csr(CSR_lock) <= sldb_lock; debug(0) <= ram_trig; debug(1) <= en_rx; debug(2) <= ram_ena; local_addr_s <= local_addr_l & lb_byte; lb_data_out <= lb_mux( conv_integer( lb_addr)); -- address register read with lb_byte select lb_mux(0) <= local_addr_l(7 downto 0) when "00", ("0000000" & local_addr_l(8)) when "01", "00000000" when others; -- CSR read with receiver spy in upper bits with lb_byte select lb_mux(2) <= csr when "00", rxd_l(7 downto 0) when "10", rxd_l(15 downto 8) when "11", "00000000" when others; -- delay and word count read with lb_byte select lb_mux(3) <= '0' & rx_delay when "00", ram_addr(7 downto 0) when "10", "0000000" & ram_addr(8) when "11", "00000000" when others; port_a_ena <= '1' when (lb_ena = '1') and (lb_addr = "01") else '0'; -- RAM port A enable -- dual-port RAM entity -- debug option: save address and low 22 data bits -- ram_data <= '1' & ram_addr & rxd_l(21 downto 0); ram_data(31 downto 18) <= en_rx & "0000000000000"; r1 : RAMB16_S9_S36 port map ( ADDRA => local_addr_s, ADDRB => ram_addr, DIA => lb_data_in, DIB => ram_data, DIPA => (others => '0'), DIPB => (others => '0'), WEA => lb_write, WEB => '1', CLKA => gclk, CLKB => sldb_rx_clk, SSRA => '0', SSRB => '0', ENA => port_a_ena, ENB => ram_ena, DOA => lb_mux(1), DOB => open, DOPA => open, DOPB => open); end sldbrx_a;