-- Timing Analyzer -- need 14 address Bits to read analyzer: lower 9 to address sample (0..511), -- 5 Bit (13 downto 9) to address memory block (0..17+1) (18 SM + 1 trigger sig -- etc.) -- top address (15 downto 14) fixed in adremux to "01" -> -- address range 0x4000 .. 0x7fff -- -- control TA: -- 32 Bit Trigger Mask only in extra block 18: -- 32 Bit Trigger pattern 32 Bit trigger mask (=select for trigger) -- Address TA_trig_pat (RW) (0x7002 = 28674) -- Address TA_trig_msk (RW) (0x7003 = 28675) -- -- Number of presamples(RW) (0x7004) = 28676) (0..511)= 9 Bit to store data before trigger -- -- Address TA_start (0x7000 = 28672) (WO) 1 Bit: start, -- TA_done_ack (0x7001 = 28673) Bit ack_done (to transit from done to ready) -- ctrl bits are not stored, only transitional used -- info from TA: -- Startsample (RO) (0x7005 = 28677) -- FSM-state (RO) (0x7006 = 28678) -- "00" when ready, -- "01" when wait_trigger, -- "10" when done, -- FSM state , startsample -- The TA works as ringbuffer. The trigger pattern is in startsample. The -- recording runs until samplecounter = startsample-presamples-1 -- For display the first sample is startsample-presamples (May be wrapped) -- FSM to sync to SCSN clock: -- ready, wait_prestore, wait_trigger, wait_ea, done -- -- -- from 0x4000 ... 0x63ff: Data from S inputs (18x512x32 Bit values SMxdepthxBitsperSM) -- 0x6400 = 25600: Extra Block with T-signals library IEEE; use IEEE.std_logic_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all; entity TA is port ( taclk : in std_logic; scsnclk : in std_logic; reset_n : in std_logic; address : in std_logic_vector(13 downto 0); we : in std_logic; TA_OBI : out std_logic_vector(31 downto 0); TA_IBO : in std_logic_vector(31 downto 0); S : in std_logic_vector(575 downto 0); T : in std_logic_vector(31 downto 0)); end TA; architecture behv of TA is component ta_acnt port ( clk : in std_logic; reset_n : in std_logic; acnt_clr : in std_logic; acnt_en : in std_logic; acnt_sa : out std_logic; stopadd : in std_logic_vector(8 downto 0); acnt_ps : out std_logic; presadd : in std_logic_vector(8 downto 0); address : out std_logic_vector (8 downto 0)); end component; component tamem port ( addra : IN std_logic_VECTOR(8 downto 0); addrb : IN std_logic_VECTOR(8 downto 0); clka : IN std_logic; clkb : IN std_logic; dina : IN std_logic_VECTOR(31 downto 0); doutb : OUT std_logic_VECTOR(31 downto 0); wea : IN std_logic); end component; -- Constant constant start_addr : std_logic_vector(13 downto 0) := "11000000000000"; constant done_ack_addr : std_logic_vector(13 downto 0) := "11000000000001"; constant TA_trig_pat_addr : std_logic_vector(13 downto 0) := "11000000000010"; constant TA_trig_msk_addr : std_logic_vector(13 downto 0) := "11000000000011"; constant presamples_addr : std_logic_vector(13 downto 0) := "11000000000100"; constant startsample_addr : std_logic_vector(13 downto 0) := "11000000000101"; constant state_addr : std_logic_vector(13 downto 0) := "11000000000110"; -- Register signal start_reg : std_logic; signal done_ack_reg : std_logic; signal TA_trig_pat_reg : std_logic_vector(31 downto 0); signal TA_trig_msk_reg : std_logic_vector(31 downto 0); signal presamples_reg : std_logic_vector(8 downto 0); -- Regiser from taclkbase synced to scsnclk signal startsample_reg : std_logic_vector(8 downto 0); signal state_ta : std_logic_vector(1 downto 0); signal state_reg : std_logic_vector(1 downto 0); -- Register sync to TA-clk signal start_sync : std_logic; signal done_ack_sync : std_logic; -- signal signal reg_OBI : std_logic_vector(31 downto 0); -- data read from registers signal mem_OBI : std_logic_vector(31 downto 0); -- data read from memory blocks -- signals from ta-address counter signal acnt_clr : std_logic; signal acnt_en : std_logic; signal acnt_sa : std_logic; signal stopadd : std_logic_vector(8 downto 0); signal acnt_ps : std_logic; signal presadd : std_logic_vector(8 downto 0); signal ta_address : std_logic_vector (8 downto 0); -- trigger signal signal trigger : std_logic; -- register for startaddress: signal sa_ld : std_logic; signal startsample_ta : std_logic_vector(8 downto 0); -- end address, computed by presamples signal ea : std_logic_vector(8 downto 0); -- Register T inputs to memoryclk signal T_reg : std_logic_vector(31 downto 0); -- data read from memory blocks -- FSM: type st_t is (ready, wait_prestore, wait_trigger, wait_ea, done); signal cst, nst : st_t; attribute state_vector : string; attribute state_vector of behv : architecture is "cst"; -- write enable to memory block signal we_mem : std_logic; -- arrays for memblosck -- signal wes : std_logic_vector(18 downto 0); type rd_data_array is array(0 to 31) of std_logic_vector(31 downto 0); signal dout : rd_data_array; begin -- behv TA_OBI <= reg_OBI when address(13 downto 12) = "11" else mem_OBI; with address select reg_OBI <= TA_trig_pat_reg when TA_trig_pat_addr, TA_trig_msk_reg when TA_trig_msk_addr, (31 downto 9 => '0') & presamples_reg when presamples_addr, (31 downto 9 => '0') & startsample_reg when startsample_addr, (31 downto 2 => '0') & state_reg when state_addr, x"00000000" when others; start_p : process (scsnclk, reset_n) begin -- process start_p if reset_n = '0' then -- asynchronous reset (active low) start_reg <= '0'; elsif scsnclk'event and scsnclk = '1' then -- rising clock edge if (address = start_addr) and (we = '1') then start_reg <= '1'; else start_reg <= '0'; end if; end if; end process start_p; done_ack_p : process (scsnclk, reset_n) begin -- process done_ack_p if reset_n = '0' then -- asynchronous reset (active low) done_ack_reg <= '0'; elsif scsnclk'event and scsnclk = '1' then -- rising clock edge if (address = done_ack_addr) and (we = '1') then done_ack_reg <= '1'; else done_ack_reg <= '0'; end if; end if; end process done_ack_p; TA_trig_pat_p : process (scsnclk, reset_n) begin -- process TA_trig_pat_p if reset_n = '0' then -- asynchronous reset (active low) TA_trig_pat_reg <= (others => '0'); elsif scsnclk'event and scsnclk = '1' then -- rising clock edge if (address = TA_trig_pat_addr) and (we = '1') then TA_trig_pat_reg <= TA_IBO; end if; end if; end process TA_trig_pat_p; TA_trig_msk_p : process (scsnclk, reset_n) begin -- process TA_trig_msk_p if reset_n = '0' then -- asynchronous reset (active low) TA_trig_msk_reg <= (others => '0'); elsif scsnclk'event and scsnclk = '1' then -- rising clock edge if (address = TA_trig_msk_addr) and (we = '1') then TA_trig_msk_reg <= TA_IBO; end if; end if; end process TA_trig_msk_p; presamples_p : process (scsnclk, reset_n) begin -- process presamples_p if reset_n = '0' then -- asynchronous reset (active low) presamples_reg <= (others => '0'); elsif scsnclk'event and scsnclk = '1' then -- rising clock edge if (address = presamples_addr) and (we = '1') then presamples_reg <= TA_IBO(8 downto 0); end if; end if; end process presamples_p; -- ***************************************************** -- sync bus signals to ta clk start_sync_p : process (taclk) begin if taclk'event and taclk = '1' then start_sync <= start_reg; end if; end process start_sync_p; done_ack_sync_p : process (taclk) begin if taclk'event and taclk = '1' then done_ack_sync <= done_ack_reg; end if; end process done_ack_sync_p; -- addresscounter ta_acnt_1 : ta_acnt port map ( clk => taclk, reset_n => reset_n, acnt_clr => acnt_clr, acnt_en => acnt_en, acnt_sa => acnt_sa, stopadd => stopadd, acnt_ps => acnt_ps, presadd => presamples_reg, address => ta_address); -- Startaddress register starta_p : process (taclk, reset_n) begin -- process sa_p if reset_n = '0' then -- asynchronous reset (active low) startsample_ta <= (others => '0'); elsif taclk'event and taclk = '1' then -- rising clock edge if sa_ld = '1' then startsample_ta <= ta_address; end if; end if; end process starta_p; sartsample_p : process (scsnclk) begin -- process sartsample_p if scsnclk'event and scsnclk = '1' then -- rising clock edge startsample_reg <= startsample_ta; end if; end process sartsample_p; -- calculate stopaddress based on presamples, wraps automatically stopadd <= startsample_ta + not(presamples_reg); -- Trigger input signal sync: T_reg_p : process (taclk) begin -- process T_reg_p if taclk'event and taclk = '1' then -- rising clock edge T_reg <= T; end if; end process T_reg_p; -- Trigger on pattern/mask trigger <= '1' when (T_reg and TA_trig_msk_reg) = (TA_trig_pat_reg and TA_trig_msk_reg) else '0'; -- FSM *************************************** fsm_seq : process (taclk, reset_n) begin -- process fsm_seq if reset_n = '0' then -- asynchronous reset (active low) cst <= ready; elsif taclk'event and taclk = '1' then -- rising clock edge cst <= nst; end if; end process fsm_seq; -- fsm_comb : process (start_sync,acnt_ps,trigger,acnt_sa,done_ack_sync) begin -- process fsm_comb case cst is -- redy: Wait for a start signal via SCSN when ready => if start_sync = '1' then nst <= wait_prestore; else nst <= ready; end if; -- wait_prestore: ignore trigger until prestore done when wait_prestore => if acnt_ps = '1' then nst <= wait_trigger; else nst <= wait_prestore; end if; -- wait_trigger: when wait_trigger => if trigger = '1' then nst <= wait_ea; else nst <= wait_trigger; end if; -- wait End Address: leaving wait_trigger state stores addresscounter in -- "startsamples_ta", based on presamples, counter raises acnt_sa when wait_ea => if acnt_sa = '1' then nst <= done; else nst <= wait_ea; end if; -- last address reached and stored, needs to be acked by CPU to go to ready, -- when done => if done_ack_sync = '1' then nst <= ready; else nst <= done; end if; when others => nst <= ready; end case; end process fsm_comb; -- fsm decode signals -- to counter: with cst select acnt_clr <= '1' when ready, '0' when others; with cst select acnt_en <= '0' when ready, '0' when done, '1' when others; -- to startaddress latch: with cst select sa_ld <= '1' when wait_trigger, '0' when others; -- write to block memories with cst select we_mem <= '0' when ready, '0' when done, '1' when others; -- inform CPU with cst select state_ta <= "00" when ready, "01" when wait_trigger, "10" when done, "11" when others; state_sync_p : process (scsnclk, reset_n) begin -- process state_sync_p if reset_n = '0' then -- asynchronous reset (active low) state_reg <= "11"; elsif scsnclk'event and scsnclk = '1' then -- rising clock edge state_reg <= state_ta; end if; end process state_sync_p; -- memory: Port A Logic in, Port B:SCSN in -- component tamem -- port ( -- addra : IN std_logic_VECTOR(8 downto 0); -- addrb : IN std_logic_VECTOR(8 downto 0); -- clka : IN std_logic; -- clkb : IN std_logic; -- dina : IN std_logic_VECTOR(31 downto 0); -- doutb : OUT std_logic_VECTOR(31 downto 0); -- wea : IN std_logic); -- end component; wes_gen: for i in 0 to 17 generate -- wes(i) <= '1' when conv_integer(address(13 downto 9)) = i else '0'; tamem_2: tamem port map ( addra => ta_address, addrb => address(8 downto 0), clka => taclk, clkb => scsnclk, dina => S( ( 32*i)+31 downto (32*i)), doutb => dout(i), wea => we_mem); end generate wes_gen; -- wes(18) <= '1' when conv_integer(address(13 downto 9)) = 18 else '0'; tamem_1: tamem port map ( addra => ta_address, addrb => address(8 downto 0), clka => taclk, clkb => scsnclk, dina => T_reg, doutb => dout(18), wea => we_mem); unused: for i in 19 to 31 generate dout(i) <= (others => '-'); end generate unused; mem_OBI <= dout(conv_integer(address(13 downto 9))); end behv;