-- -- dummy SCL block with test registers -- 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 scl is port ( g_clk : in std_logic; debug : out std_logic_vector(3 downto 0); -- debug outputs lb_data_in : in std_logic_vector(7 downto 0); lb_data_out : out std_logic_vector(7 downto 0); lb_addr : in std_logic_vector(1 downto 0); lb_ena : in std_logic; lb_byte : in std_logic_vector(1 downto 0); lb_read : in std_logic; lb_write : in std_logic; bp_start : in std_logic; -- NRZC start bit from backplane logic nrzc : out std_logic; -- encoded NRZC output iso_out : out std_logic_vector(1 downto 0); fc : out std_logic; -- first crossing signal out ctrl_bit : out std_logic_vector(3 downto 0); -- SCL clear global_trig : out std_logic; -- global trigger to rest of system g_pattern : out std_logic; -- send link pattern g_rst : out std_logic; -- send system reset g_pass : out std_logic); end scl; architecture scl_arch of scl is constant CSR_ena : integer := 0; -- CSR enable bit constant CSR_busy : integer := 1; -- CSR busy bit (read)/scl clear when write constant CSR_trig : integer := 2; -- CSR trigger bit (write only) -- constant CSR_rep : integer := 3; -- CSR repeat enable bit constant CSR_tick : integer := 3; -- trigger on specified tick constant CSR_pass : integer := 4; -- directly passing rx to tx constant CSR_pattern : integer := 5; -- link pattern sending constant CSR_reset : integer := 7; -- system reset type lb_mux_t is array (3 downto 0) of std_logic_vector(7 downto 0); signal lb_mux : lb_mux_t; signal nrzc_s : std_logic; signal ena_s : std_logic; -- ram port A ram enables signal csr : std_logic_vector(7 downto 0); 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 scl_ena : std_logic; -- transmitter enabled signal scl_ena_n : std_logic; signal scl_trig : std_logic; -- transmit trigger (delayed) signal scl_trig_dl : std_logic; -- transmit trigger (delayed) signal scl_busy : std_logic; -- timing cycle running signal scl_addr : std_logic_vector(8 downto 0); signal scl_wcount : std_logic_vector(7 downto 0); signal scl_data_s : std_logic_vector(31 downto 0); signal frame: std_logic_vector( 2 downto 0); -- counts the frames signal tick: std_logic_vector( 7 downto 0); signal turn: std_logic_vector( 15 downto 0); signal nrzc_dl : std_logic; signal fc_bit : std_logic; signal sg_bit : std_logic; signal l1_bit : std_logic; signal clr_bit : std_logic; signal par_bit : std_logic; signal ctrl_bitp : std_logic_vector( 3 downto 0); signal tick_eq : std_logic; signal pre_trig : std_logic; signal pre_trig_dl : std_logic; signal pre_trig_l : std_logic; signal rep_trig : std_logic; signal wait4fx : std_logic; signal tick_l : std_logic_vector( 7 downto 0); signal tick_reg : std_logic_vector( 7 downto 0); signal rep_reg : std_logic_vector( 15 downto 0); signal rep_cntr : std_logic_vector( 15 downto 0); signal turn_l : std_logic_vector( 15 downto 0); signal scl_clearp : std_logic; signal scl_clear : std_logic; signal iso_out_dl : std_logic_vector( 1 downto 0); signal iso_out_dl2 : std_logic_vector( 1 downto 0); signal sample : std_logic; signal sample_dl : std_logic; signal reset : std_logic; attribute INIT : string; attribute INIT of rep_cntr: signal is "S"; begin -- scl_arch ----------------------------------------------------------------------------- -- Synchronous logic (global RF clock) ----------------------------------------------------------------------------- process(g_clk) begin if g_clk'event and g_clk = '1' then iso_out <= iso_out_dl2; if(tick = tick_reg or csr(CSR_tick) = '0')then tick_eq <= '1'; else tick_eq <= '0'; end if; if(bp_start = '1')then pre_trig_dl <= pre_trig; if(rep_cntr = rep_reg)then rep_trig <= '1'; else rep_trig <= '0'; end if; if(rep_reg = x"0000" or rep_cntr = rep_reg)then rep_cntr <= x"0001"; else rep_cntr <= rep_cntr + 1; end if; end if; if lb_ena = '1' and lb_write = '1' and lb_addr = "10" and lb_byte = "00" then reset <= not lb_data_in(CSR_reset); else reset <= '1'; end if; end if; end process; g_iso : for i in iso_out'range generate i_isoout_dl1: srlc16e port map( d => scl_data_s(2+i), clk => g_clk, ce => bp_start, a0 => '1', a1 => '1', a2 => '1', a3 => '1', q => iso_out_dl(i)); i_isoout_dl2: srlc16e port map( d => iso_out_dl(i), clk => g_clk, ce => '1', a0 => '1', a1 => '1', a2 => '1', a3 => '1', q => iso_out_dl2(i)); end generate; i_scl_trig_dl: srlc16e port map( d => scl_trig, clk => g_clk, ce => bp_start, a0 => '1', a1 => '0', a2 => '1', a3 => '1', q => scl_trig_dl); process (g_clk, reset) begin -- process if reset = '0' then -- asynchronous reset (active low) scl_addr <= (others => '0'); scl_ena <= '0'; global_trig <= '0'; local_addr_l <= (others => '0'); csr <= (others => '0'); scl_trig <= '0'; pre_trig <= '0'; pre_trig_l <= '0'; scl_wcount <= (others => '0'); elsif g_clk'event and g_clk = '1' then -- rising clock edge -- miscellaneous clocked signals if bp_start = '1' then if scl_ena = '0' and scl_trig = '1' then scl_addr <= (others => '0'); scl_ena <= '1'; elsif scl_ena = '1' then -- when address counts up to word count, disable transmitter if scl_addr(7 downto 0) = scl_wcount - 1 then scl_addr <= (others => '0'); scl_ena <= '0'; else scl_addr <= scl_addr + 1; end if; end if; end if; -- leading edge of scl_trig, zero address and enable transmitter if scl_trig_dl = '1' and bp_start = '1' then global_trig <= '1'; -- send global trigger to system else global_trig <= '0'; end if; if bp_start = '1' then pre_trig_l <= pre_trig_dl or (pre_trig_l and not tick_eq); scl_trig <= (pre_trig_l or rep_trig) and tick_eq; end if; -- local bus write -- write trigger if lb_ena = '1' and lb_write = '1' and lb_addr = "10" and lb_byte = "11" then -- enabled in CSR and trigger pre_trig <= csr(CSR_ena) and csr(CSR_trig); elsif bp_start = '1' then pre_trig <= '0'; end if; if lb_ena = '1' and lb_write = '1' and lb_addr = "10" and lb_byte = "00" then scl_clearp <= lb_data_in(CSR_busy); elsif bp_start = '1' then scl_clearp <= '0'; end if; if lb_ena = '1' and lb_write = '1' then -- write to CSR if lb_addr = "10" then case lb_byte is -- write to CSR lsb when "00" => csr(CSR_ena) <= lb_data_in(CSR_ena); -- csr(CSR_rep) <= lb_data_in(CSR_rep); csr(CSR_pattern) <= lb_data_in(CSR_pattern); csr(CSR_pass) <= lb_data_in(CSR_pass); csr(CSR_trig) <= lb_data_in(CSR_trig); csr(CSR_tick) <= lb_data_in(CSR_tick); when "01" => tick_reg <= lb_data_in; when "10" => rep_reg(7 downto 0) <= lb_data_in; when others => rep_reg(15 downto 8) <= lb_data_in; end case; end if; if lb_addr = "11" then -- write to word count case lb_byte is when "00" => scl_wcount(7 downto 0) <= lb_data_in; when others => null; end case; end if; end if; csr(CSR_busy) <= scl_busy; -- overwrite CSR busy bit every clock if lb_ena = '1' then if lb_addr = "00" and lb_write = '1' 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; -- auto-increment ram address on R/W when crossing a word boundary elsif lb_addr = "01" and lb_byte = "11" then local_addr_l <= local_addr_l + 1; end if; end if; end if; end process; ------------------------------------------------------------------------------- -- Asynchronous logic ------------------------------------------------------------------------------- debug(0) <= scl_trig; debug(1) <= scl_busy; debug(2) <= scl_busy and fc_bit; debug(3) <= '0'; g_rst <= reset; g_pass <= csr(CSR_pass); g_pattern <= csr(CSR_pattern); scl_busy <= scl_ena or scl_trig; 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 & ID read with lb_byte select lb_mux(2) <= csr when "00", REV when "01", -- firmware revision X"a1" when "10", X"d5" when others; -- word count read with lb_byte select lb_mux(3) <= scl_wcount(7 downto 0) when "00", tick_l when "01", turn_l(7 downto 0) when "10", turn_l(15 downto 8) when others; ena_s <= '1' when (lb_ena = '1') and (lb_addr = "01") else '0'; -- RAM port B enable -- dual-port RAM entity r1 : RAMB16_S9_S36 port map ( ADDRB => scl_addr, ADDRA => local_addr_s, DIB => (others => '0'), DIA => lb_data_in, DIPA => (others => '0'), DIPB => (others => '0'), WEB => '0', WEA => lb_write, CLKA => g_clk, CLKB => g_clk, SSRB => scl_ena_n, SSRA => '0', ENB => '1', ENA => ena_s, DOB => scl_data_s, DOA => lb_mux(1)); scl_ena_n <= not scl_ena; sample <= scl_trig and not scl_ena; i_sample: srlc16e port map( d => sample, clk => g_clk, ce => bp_start, a0 => '0', a1 => '1', a2 => '0', a3 => '0', q => sample_dl); process(g_clk) begin if g_clk'event and g_clk = '1' then if bp_start = '1' and sample_dl = '1' then turn_l <= turn; tick_l <= tick; end if; end if; end process; -- sg and fc generations process(g_clk) begin if g_clk'event and g_clk = '1' then if(bp_start = '1')then frame <= "000"; else frame <= frame + 1; end if; if(bp_start = '1')then scl_clear <= scl_clearp; if(tick = x"5")then fc_bit <= '1'; else fc_bit <= '0'; end if; if(tick = x"5")then sg_bit <= '0'; elsif(tick = x"93")then sg_bit <= '1'; end if; if(clr_bit = '1')then wait4fx <= '1'; elsif(fc_bit = '1')then wait4fx <= '0'; end if; if(wait4fx = '1' and fc_bit = '1')then tick <= x"07"; turn <= x"0001"; elsif(tick = x"9E")then tick <= x"00"; else tick <= tick + 1; end if; if(tick = x"9E")then turn <= turn + 1; end if; clr_bit <= scl_data_s(1) or scl_clear; end if; par_bit <= fc_bit xor sg_bit xor l1_bit xor clr_bit; nrzc <= nrzc_dl; -- fc <= fc_bit; case frame is when "000" => nrzc_s <= fc_bit; when "001" => nrzc_s <= sg_bit; when "010" => nrzc_s <= l1_bit; when "011" => nrzc_s <= clr_bit; when "101" => nrzc_s <= par_bit; when "110" => nrzc_s <= '1'; when others => nrzc_s <= '0'; end case; end if; end process; i_srlc_dl: srlc16e port map( d => nrzc_s, clk => g_clk, ce => '1', a0 => '0', a1 => '0', a2 => '1', a3 => '0', q => nrzc_dl); i_ctrl_bit0: srlc16e port map( d => fc_bit, clk => g_clk, ce => bp_start, a0 => '1', a1 => '0', a2 => '1', a3 => '1', q => ctrl_bitp(0)); i_ctrl_bit1: srlc16e port map( d => sg_bit, clk => g_clk, ce => bp_start, a0 => '1', a1 => '0', a2 => '1', a3 => '1', q => ctrl_bitp(1)); i_ctrl_bit2: srlc16e port map( d => l1_bit, clk => g_clk, ce => bp_start, a0 => '1', a1 => '0', a2 => '1', a3 => '1', q => ctrl_bitp(2)); i_ctrl_bit3: srlc16e port map( d => clr_bit, clk => g_clk, ce => bp_start, a0 => '1', a1 => '0', a2 => '1', a3 => '1', q => ctrl_bitp(3)); fc <= ctrl_bitp(0); ctrl_bit <= ctrl_bitp; i_l1_bit: srlc16e port map( d => scl_data_s(0), clk => g_clk, ce => bp_start, a0 => '1', a1 => '1', a2 => '1', a3 => '1', q => l1_bit); end scl_arch;