library IEEE; use IEEE.std_logic_1164.all; use ieee.std_logic_arith.all; USE ieee.std_logic_unsigned.all; -- PASA DACs -- -- Offset -- 0 ..31 w/r time(23..15) & channel(14) & DAC(13..0) -- 32..63 w/r configuration reg -- Bit 3 write only, when 1 start -- Bit 2 enable pretrigger start -- Bit 1 not used now -- Bit 0 when 1 run cont -- -- The time is measured using the TRAP fast clock / 2 -- In idle state the DACs are in low power mode. -- After start the DACs are in full power mode and the timer -- runs. The state machine waits until the time matches the -- first programmed time (at address 0). Then it -- fires the corresponding DAC clock output. -- Then the state machine reads the next time and waits -- and so on. If the programmed time is 0 or the address -- wraps to 0 the state machine stops (if not in cont mode) -- or starts again. -- -- DAC channel 0 is for the odd PASA channels (1,3,...17) -- DAC channel 1 is for the even PASA channels (2,4,...18) -- -- On the MCM PASA channel 1 is connected to ADC channel 2 -- PASA channel 2 is connected to ADC channel 3 -- ... -- PASA channel 18 is connected to ADC channel 19 entity pasadac is PORT ( CLK120 : in std_logic; -- Clock, 120 MHz CLK : in std_logic; -- Clock, 30 or 40 MHz RESET_n : in std_logic; -- reset start : in std_logic; -- to the internal bus CE : in std_logic; WE : in std_logic; ADDR : in std_logic_vector( 5 downto 0); WDATA : in std_logic_vector(28 downto 0); RDATA : out std_logic_vector(31 downto 0); -- to the ADC PasaDAC1_CLK : out std_logic; PasaDAC2_CLK : out std_logic; PasaDAC_Sleep : out std_logic; PasaDAC_D : out std_logic_vector(13 downto 0) ); end pasadac; architecture a of pasadac is component pasadac_ram PORT ( data_a : IN STD_LOGIC_VECTOR (23 DOWNTO 0); wren_a : IN STD_LOGIC := '1'; address_a : IN STD_LOGIC_VECTOR (4 DOWNTO 0); data_b : IN STD_LOGIC_VECTOR (23 DOWNTO 0); address_b : IN STD_LOGIC_VECTOR (4 DOWNTO 0); wren_b : IN STD_LOGIC := '1'; clock_a : IN STD_LOGIC ; clock_b : IN STD_LOGIC ; q_a : OUT STD_LOGIC_VECTOR (23 DOWNTO 0); q_b : OUT STD_LOGIC_VECTOR (23 DOWNTO 0) ); end component; type sm_type is (idle, checktime, dac, stop); signal sm : sm_type; signal timer_en : std_logic; signal timer : std_logic_vector( 8 downto 0); signal time_dac : std_logic_vector( 8 downto 0); signal ch_dac : std_logic; signal ampl_dac : std_logic_vector(13 downto 0); signal ampl_rev : std_logic_vector(13 downto 0); signal rdat_rev : std_logic_vector(13 downto 0); signal rdata_dac : std_logic_vector(23 downto 0); signal rdata_io : std_logic_vector(23 downto 0); signal wdata_dac : std_logic_vector(23 downto 0); signal wdata_cor : std_logic_vector(wdata_dac'range); signal cfr : std_logic_vector(2 downto 0); signal addr_sm : std_logic_vector( 4 downto 0); signal wren_io : std_logic; signal wren_cfr : std_logic; signal start_s : std_logic; signal io_start : std_logic; signal timematch : std_logic; begin wren_io <= CE and WE and ADDR(ADDR'high); wren_cfr <= CE and WE and not ADDR(ADDR'high); wdata_dac <= (others =>'0'); process(clk, reset_n) begin if reset_n = '0' then cfr <= (cfr'high => '1', others =>'0'); io_start <= '0'; elsif clk'event and clk= '1' then io_start <= '0'; if wren_cfr = '1' then cfr <= WDATA(cfr'range); io_start <= WDATA(cfr'high+1); end if; end if; end process; inv: for i in 0 to ampl_rev'high generate ampl_rev(i) <= WDATA(ampl_rev'high-i); rdat_rev(i) <= rdata_io(ampl_rev'high-i); end generate; -- process(WDATA) -- begin -- wdata_cor <= (others -- end process; wdata_cor(23 downto 15) <= WDATA(28 downto 20); wdata_cor(14 ) <= WDATA(16 ); wdata_cor(13 downto 0) <= not (WDATA(13 downto 0)) when WDATA(16)='1' -- channel 2 else not ampl_rev; -- channel 1, bit 0 <-> bit 13 ... dacram: pasadac_ram PORT map ( -- IO port clock_a => clk, data_a => wdata_cor, wren_a => wren_io, address_a => ADDR(4 downto 0), q_a => rdata_io, -- internal port for DAC clock_b => clk120, data_b => wdata_dac, wren_b => '0', address_b => addr_sm, q_b => rdata_dac ); time_dac <= rdata_dac(23 downto 15); ch_dac <= rdata_dac(14); ampl_dac <= rdata_dac(13 downto 0); timematch <= '1' when time_dac = timer else '0'; process(clk120, reset_n) begin if reset_n = '0' then sm <= idle; elsif clk120'event and clk120='1' then -- state machine case sm is when idle => if start_s = '1' then sm <= checktime; end if; when checktime => if time_dac = 0 then sm <= stop; elsif timematch='1' then sm <= dac; end if; when dac => if addr_sm = 0 then sm <= idle; else sm <= checktime; end if; when stop => if addr_sm = 0 then sm <= idle; end if; when others => sm <= idle; end case; end if; end process; process(clk120) begin if clk120'event and clk120='1' then PasaDAC_D <= ampl_dac; start_s <= (start and cfr(2)) or io_start or cfr(0); -- timer if sm = idle then timer <= (others => '0'); timer_en <= '0'; else timer_en <= not timer_en; if timer_en = '1' then timer <= timer + 1; end if; end if; -- read address if sm = idle or sm = stop then addr_sm <= (others => '0'); elsif sm = checktime and timematch='1' then addr_sm <= addr_sm + 1; end if; -- DAC clock outputs PasaDAC1_CLK <= '0'; PasaDAC2_CLK <= '0'; if sm=dac then if ch_dac = '0' then PasaDAC1_CLK <= '1'; else PasaDAC2_CLK <= '1'; end if; end if; if sm = idle then PasaDAC_Sleep <= cfr(1); else PasaDAC_Sleep <= '0'; end if; end if; end process; -- read mux omx: process(addr, cfr, rdata_io, rdat_rev) begin RDATA <= (others => '0'); if ADDR(ADDR'high)='1' then -- RAM RDATA(16 ) <= rdata_io(14 ); -- channel RDATA(28 downto 20) <= rdata_io(23 downto 15); -- channel if rdata_io(14)='1' then RDATA(13 downto 0) <= not rdata_io(13 downto 0 ); -- DAC else RDATA(13 downto 0) <= not rdat_rev; end if; else RDATA(cfr'range) <= cfr; end if; end process; end;