--
-- data_logger.vhd
--
-- Timing Signal Edge detection and multiplexing
--
--
-- Version 1.0 4/1/06 A.McCormick (Alpha Data)
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_signed.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_misc.all;
entity data_logger is
port (
clk : in std_logic;
rst : in std_logic;
ten_mhz_clk : in std_logic;
-- Inputs from PLL
ms_pulse : in std_logic;
acq : in std_logic;
cycle : in std_logic_vector(31 downto 0);
ctime : in std_logic_vector(31 downto 0);
sigma_avg : in std_logic_vector(15 downto 0);
deltax_avg : in std_logic_vector(15 downto 0);
deltay_avg : in std_logic_vector(15 downto 0);
avg_valid : in std_logic;
init : in std_logic;
bunchmean_acc : in std_logic_vector(1 downto 0);
phase_table_sync : in std_Logic;
hchange_sync : in std_logic;
injection_sync : in std_logic;
cal_start_sync : in std_logic;
-- Timing Inputs (already edge detected)
cycle_start_edge : in std_logic;
cycle_stop_edge : in std_logic;
cal_start_edge : in std_logic;
cal_stop_edge : in std_logic;
injection_edge : in std_logic;
hchange_edge : in std_logic;
-- Timing Inputs
cycle_start : in std_logic;
cycle_start_ten_mhz : in std_logic;
cycle_stop : in std_logic;
cal_start : in std_logic;
cal_stop : in std_logic;
injection : in std_logic;
hchange : in std_logic;
fref : in std_logic;
-- Diagnostics from PLL
diagnostics : in std_logic_vector(255 downto 0);
-- Host Control Registers
diag_control : in std_logic_vector(31 downto 0);
diag_control_set : in std_logic;
diag_delay : in std_logic_vector(31 downto 0);
diag_delay_set : in std_logic;
diag_trigger : in std_logic_vector(31 downto 0);
diag_status : out std_logic_vector(31 downto 0);
diag_irq : out std_logic;
-- Write Signals to Memory
sdram_addr : out std_logic_vector(24 downto 0);
sdram_data : out std_logic_vector(63 downto 0);
sdram_write : out std_logic;
timing_addr : out std_logic_vector(11 downto 0);
timing_data : out std_logic_vector(63 downto 0);
timing_write : out std_logic;
info_addr : out std_logic_vector(5 downto 0);
info_data : out std_logic_vector(63 downto 0);
info_write : out std_logic;
diagnostics_data : out std_logic_vector(63 downto 0);
diagnostics_addr : out std_logic_vector(11 downto 0);
diagnostics_write : out std_logic;
bunchmean0_data : out std_logic_vector(63 downto 0);
bunchmean0_addr : out std_logic_vector(11 downto 0);
bunchmean0_write : out std_logic;
bunchmean1_data : out std_logic_vector(63 downto 0);
bunchmean1_addr : out std_logic_vector(11 downto 0);
bunchmean1_write : out std_logic);
end data_logger;
architecture rtl of data_logger is
constant bunch_mean_base_addr : integer := 254*1024*1024/8;
constant number_of_bunches : integer := 24;
signal sdram_addr_i : std_logic_vector(24 downto 0);
signal sdram_addr_sync : std_logic_vector(24 downto 0);
signal timing_addr_i : std_logic_vector(11 downto 0);
signal event_counter : std_logic_vector(3 downto 0);
signal trigger,trigger1 : std_logic_vector(7 downto 0);
signal analyser_data,analyser_data1,analyser_data2: std_logic_vector(63 downto 0);
signal analyser_src : std_logic_vector(1 downto 0);
signal store_trigger : std_logic;
signal arm : std_logic;
signal capturing : std_logic;
signal clk_counter : std_logic_vector(16 downto 0);
signal clk_count_limit : std_logic_vector(16 downto 0);
signal clk_count_strb : std_logic;
signal clk_select : std_logic_vector(4 downto 0);
signal trig_and,trig_or,data_and,data_or : std_logic;
signal wait_clk : std_logic;
signal capture_count : std_logic_vector(11 downto 0);
signal sample_clk : std_logic;
signal diagnostics_r1 : std_logic_vector(255 downto 0);
signal fref_reg : std_logic;
signal trig_delay : std_logic_vector(31 downto 0);
signal trig_delayed : std_logic;
signal info_clear_count : std_logic_vector(3 downto 0);
-- BRAM based bunch mean average system
signal bma_s0,bma_dx0,bma_dy0,bma_s1,bma_dx1,bma_dy1 : std_logic_vector(15 downto 0);
signal bma_counter2,bma_counter3 : std_logic_vector(15 downto 0);
signal bma_s2,bma_dx2,bma_dy2,bma_s3,bma_dx3,bma_dy3 : std_logic_vector(27 downto 0);
-- SDRAM based bunch mean average system
type bunch_mean_array is array (natural range <>) of std_logic_vector(31 downto 0);
signal sigma_averages,deltax_averages,deltay_averages,counts : bunch_mean_array(0 to number_of_bunches);
signal bunch_one_hot : std_logic_vector(number_of_bunches-1 downto 0);
signal bunch_mean_acc_valid : std_logic_vector(number_of_bunches downto 0);
component bunch_mean_acc
port (
clk : in std_logic;
acc : in std_logic;
clr : in std_logic;
sigma : in std_logic_vector(15 downto 0);
deltax : in std_logic_vector(15 downto 0);
deltay : in std_logic_vector(15 downto 0);
sum_sigma : out std_logic_vector(31 downto 0);
sum_deltax : out std_logic_vector(31 downto 0);
sum_deltay : out std_logic_vector(31 downto 0);
count : out std_logic_vector(31 downto 0));
end component;
signal bunch_writing : std_logic;
signal ms_pulse_reg : std_logic;
signal bunch_write_state,next_bunch_write_state : std_logic_vector(5 downto 0);
signal bunch_sdram_data : std_logic_vector(63 downto 0);
signal timing_addr_bunch : std_logic_vector(11 downto 0);
signal bunch_sdram_addr : std_logic_vector(24 downto 0);
begin -- rtl
--
-- Data logging for normal operation
--
log_data: process (clk, rst)
begin -- process log_data
if rst = '1' then -- asynchronous reset
sdram_addr_i <= (others => '0');
timing_addr_i <= (others => '0');
event_counter <= (others => '0');
sdram_addr_sync <= (others => '0');
fref_reg <= '0';
elsif clk'event and clk = '1' then -- rising clock edge
fref_reg <= fref;
if init = '1' then
sdram_addr_i <= (others => '0');
timing_addr_i <= (others => '0');
event_counter <= (others => '0');
else
if avg_valid = '1' and acq = '1' then
if sdram_addr_i = CONV_STD_LOGIC_VECTOR(bunch_mean_base_addr-1,25) then
sdram_addr_i <= (others => '0');
else
sdram_addr_i <= sdram_addr_i+1;
end if;
end if;
if ms_pulse = '1' and acq = '1' then
timing_addr_i <= timing_addr_i +1;
end if;
if (hchange_sync or injection_sync or cal_stop_edge or cal_start_sync) = '1' then
event_counter <= event_counter +1;
elsif cycle_stop_edge = '1' then
event_counter <= (others => '0');
elsif cycle_start_edge = '1' then
event_counter <= "0001";
end if;
end if;
if phase_table_sync = '1' then
sdram_addr_sync <= sdram_addr_i;
end if;
if avg_valid = '1' then
sdram_addr <= sdram_addr_i;
sdram_data <= ctime(15 downto 0) & deltay_avg & deltax_avg & sigma_avg;
else
sdram_addr <= bunch_sdram_addr;
sdram_data <= bunch_sdram_data;
end if;
sdram_write <= (avg_valid or bunch_writing) and acq;
timing_addr <= timing_addr_i;
timing_data <= EXT(sdram_addr_sync,32) & ctime;
timing_write <= ms_pulse and acq;
if cycle_start_edge = '0' then
if info_clear_count = "0000" then
info_write <= (hchange_sync or injection_sync or cal_stop_edge or cal_start_sync or cycle_stop_edge or cycle_start_edge);
info_data <= EXT(sdram_addr_i,32) & EXT(hchange_sync & injection_sync & cal_stop_edge & cal_start_sync & cycle_stop_edge & cycle_start_edge,8) & EXT(timing_addr_i,24);
info_addr <= cycle(1 downto 0) & event_counter;
else
info_data <= (others => '0');
info_write <= '1';
info_clear_count <= info_clear_count+1;
info_addr <= cycle(1 downto 0) & info_clear_count;
end if;
else
info_write <= '1';
info_data <= EXT(sdram_addr_i,32) & EXT(hchange_sync & injection_sync & cal_stop_edge & cal_start_edge & cycle_stop_edge & cycle_start_edge,8) & EXT(timing_addr_i,24);
info_addr <= cycle(1 downto 0) & "0000";
info_clear_count <= "0001";
end if;
end if;
end process log_data;
--
-- Built in Logic Analyser
--
analyser0: process (clk, rst)
variable trig_valid : std_logic;
begin -- process analyser0
if rst = '1' then -- asynchronous reset
arm <= '0';
capturing <= '0';
analyser_src <= "00";
store_trigger <= '0';
clk_counter <= (others => '0');
clk_count_limit <= (others => '0');
clk_count_strb <= '0';
capture_count <= (others => '0');
diagnostics_data <= (others => '0');
diagnostics_addr <= (others => '0');
diagnostics_write <= '0';
diag_status <= (others => '0');
sample_clk <= '0';
diag_irq <= '0';
diagnostics_r1 <= (others => '0');
trigger1 <= (others => '0');
trig_delay <= (others => '0');
trig_delayed <= '0';
elsif clk'event and clk = '1' then -- rising clock edge
diagnostics_r1 <= diagnostics;
-- Select Trigger source and AND/OR mask operation
case diag_control(6 downto 5) is
when "00" => trig_valid := trig_or;
when "01" => trig_valid := trig_and;
when "10" => trig_valid := data_or;
when "11" => trig_valid := data_and;
when others => trig_valid := '0';
end case;
if diag_control_set = '1' then
arm <= diag_control(0);
wait_clk <= diag_control(7);
capturing <= '0';
analyser_src <= diag_control(3 downto 2);
store_trigger <= diag_control(4);
clk_counter <= (others => '0');
clk_count_strb <= '0';
clk_select <= diag_control(12 downto 8);
capture_count <= (others => '0');
case diag_control(12 downto 8) is
when "00000" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(0,17);
when "00001" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(1,17);
when "00010" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(4,17);
when "00011" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(9,17);
when "00100" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(19,17);
when "00101" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(49,17);
when "00110" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(99,17);
when "00111" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(199,17);
when "01000" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(499,17);
when "01001" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(999,17);
when "01010" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(1999,17);
when "01011" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(4999,17);
when "01100" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(9999,17);
when "01101" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(19999,17);
when "01110" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(49999,17);
when "01111" => clk_count_limit <= CONV_STD_LOGIC_VECTOR(99999,17);
when others => clk_count_limit <= CONV_STD_LOGIC_VECTOR(0,17);
end case;
sample_clk <= '0';
diag_irq <= '0';
if diag_control(7) = '0' then
trig_delay <= diag_delay;
else
trig_delay <= (others => '0');
end if;
else
if clk_counter = clk_count_limit then
clk_counter <= (others => '0');
clk_count_strb <= '1';
else
clk_count_strb <= '0';
clk_counter <= clk_counter+1;
end if;
if clk_select(4) = '1' then
if clk_select(0) = '0' then
sample_clk <= ms_pulse;
else
sample_clk <= fref and not fref_reg;
end if;
else
sample_clk <= clk_count_strb;
end if;
if ctime(15 downto 0) = diag_control(31 downto 16) then
wait_clk <= '0';
end if;
if capturing = '0' then
if wait_clk = '0' and arm = '1' and (trig_valid = '1' or trig_delayed = '1') then
if OR_reduce(trig_delay) = '1' then
trig_delay <= trig_delay -1;
trig_delayed <= '1';
else
trig_delayed <= '0';
capturing <= '1';
arm <= '0';
end if;
capture_count <= (others => '0');
end if;
diag_irq <= '0';
else
if sample_clk = '1' then
if AND_reduce(capture_count) = '1' then
capturing <= '0';
diag_irq <= '1';
else
diag_irq <= '0';
end if;
capture_count <= capture_count+1;
else
diag_irq <= '0';
end if;
end if;
end if;
case analyser_src is
when "00" =>
analyser_data <= diagnostics_r1(63 downto 0);
when "01" =>
analyser_data <= diagnostics_r1(127 downto 64);
when "10" =>
analyser_data <= diagnostics_r1(191 downto 128);
when "11" =>
analyser_data <= diagnostics_r1(255 downto 192);
when others =>
analyser_data <= (others => '0');
end case;
trigger1 <= fref & hchange & injection & cal_stop & cal_start & cycle_stop & cycle_start & ten_mhz_clk;
trigger <= trigger1;
if store_trigger = '1' then
analyser_data1 <= analyser_data(63 downto 8) & trigger;
else
analyser_data1 <= analyser_data;
end if;
trig_and <= not AND_reduce(trigger or diag_trigger(7 downto 0));
trig_or <= OR_reduce(trigger and diag_trigger(7 downto 0));
data_and <= not AND_reduce(analyser_data(31 downto 0) or diag_trigger);
data_or <= OR_reduce(analyser_data(31 downto 0) and diag_trigger);
analyser_data2 <= analyser_data1;
diagnostics_data <= analyser_data2;
diagnostics_addr <= capture_count;
diagnostics_write <= sample_clk and capturing;
diag_status <= diag_control(31 downto 2) & capturing & arm;
end if;
end process analyser0;
--
-- Bunch Mean Averaging
--
-- Use IIR filter y[n] = x[n] + 0.75 y[n-1]
-- bunchmean_avg0: process (clk, rst)
-- begin -- process bunchmean_avg0
-- if rst = '1' then -- asynchronous reset
-- bma_s0 <= (others => '0');
-- bma_dx0 <= (others => '0');
-- bma_dy0 <= (others => '0');
-- bma_s1 <= (others => '0');
-- bma_dx1 <= (others => '0');
-- bma_dy1 <= (others => '0');
-- elsif clk'event and clk = '1' then -- rising clock edge
-- if bunchmean_acc(0) = '1' then
-- bma_s0 <= sigma_avg + SXT(bma_s0(15 downto 1),16) + SXT(bma_s0(15 downto 2),16);
-- bma_dx0 <= deltax_avg + SXT(bma_dx0(15 downto 1),16) + SXT(bma_dx0(15 downto 2),16);
-- bma_dy0 <= deltay_avg + SXT(bma_dy0(15 downto 1),16) + SXT(bma_dy0(15 downto 2),16);
-- end if;
-- bunchmean0_data <= EXT(bma_dy0 & bma_dx0 & bma_s0,64);
-- bunchmean0_addr <= timing_addr_i;
-- bunchmean0_write <= ms_pulse and acq;
-- if bunchmean_acc(1) = '1' then
-- bma_s1 <= sigma_avg + SXT(bma_s1(15 downto 1),16) + SXT(bma_s1(15 downto 2),16);
-- bma_dx1 <= deltax_avg + SXT(bma_dx1(15 downto 1),16) + SXT(bma_dx1(15 downto 2),16);
-- bma_dy1 <= deltay_avg + SXT(bma_dy1(15 downto 1),16) + SXT(bma_dy1(15 downto 2),16);
-- end if;
-- bunchmean1_data <= EXT(bma_dy1 & bma_dx1 & bma_s1,64);
-- bunchmean1_addr <= timing_addr_i;
-- bunchmean1_write <= ms_pulse and acq;
-- end if;
-- end process bunchmean_avg0;
-- Bunch mean averaging
-- Old system using block RAM
bunchmean_avg0: process (clk, rst)
begin -- process bunchmean_avg0
if rst = '1' then -- asynchronous reset
bma_s2 <= (others => '0');
bma_dx2 <= (others => '0');
bma_dy2 <= (others => '0');
bma_s3 <= (others => '0');
bma_dx3 <= (others => '0');
bma_dy3 <= (others => '0');
bma_counter2 <= (others => '0');
bma_counter3 <= (others => '0');
elsif clk'event and clk = '1' then -- rising clock edge
if ms_pulse = '1' then
bma_s2 <= (others => '0');
bma_dx2 <= (others => '0');
bma_dy2 <= (others => '0');
bma_s3 <= (others => '0');
bma_dx3 <= (others => '0');
bma_dy3 <= (others => '0');
bma_counter2 <= (others => '0');
bma_counter3 <= (others => '0');
else
if bunchmean_acc(0) = '1' then
bma_s2 <= SXT(sigma_avg,28) + bma_s2;
bma_dx2 <= SXT(deltax_avg,28) + bma_dx2;
bma_dy2 <= SXT(deltay_avg,28) + bma_dy2;
bma_counter2 <= bma_counter2+1;
end if;
if bunchmean_acc(1) = '1' then
bma_s3 <= SXT(sigma_avg,28) + bma_s3;
bma_dx3 <= SXT(deltax_avg,28) + bma_dx3;
bma_dy3 <= SXT(deltay_avg,28) + bma_dy3;
bma_counter3 <= bma_counter3+1;
end if;
end if;
if OR_reduce(bma_counter2(15 downto 11)) = '1' then
bunchmean0_data <= bma_counter2 & bma_dy2(27 downto 12) & bma_dx2(27 downto 12) & bma_s2(27 downto 12);
elsif bma_counter2(10) = '1' then
bunchmean0_data <= bma_counter2 & bma_dy2(26 downto 11) & bma_dx2(26 downto 11) & bma_s2(26 downto 11);
elsif bma_counter2(9) = '1' then
bunchmean0_data <= bma_counter2 & bma_dy2(25 downto 10) & bma_dx2(25 downto 10) & bma_s2(25 downto 10);
elsif bma_counter2(8) = '1' then
bunchmean0_data <= bma_counter2 & bma_dy2(24 downto 9) & bma_dx2(24 downto 9) & bma_s2(24 downto 9);
else
bunchmean0_data <= bma_counter2 & bma_dy2(23 downto 8) & bma_dx2(23 downto 8) & bma_s2(23 downto 8);
end if;
--bunchmean0_data <= bma_counter2 & bma_dy2(23 downto 8) & bma_dx2(23 downto 8) & bma_s2(23 downto 8);
bunchmean0_addr <= timing_addr_i;
bunchmean0_write <= ms_pulse and acq;
if OR_reduce(bma_counter3(15 downto 11)) = '1' then
bunchmean1_data <= bma_counter3 & bma_dy3(27 downto 12) & bma_dx3(27 downto 12) & bma_s3(27 downto 12);
elsif bma_counter3(10) = '1' then
bunchmean1_data <= bma_counter3 & bma_dy3(26 downto 11) & bma_dx3(26 downto 11) & bma_s3(26 downto 11);
elsif bma_counter3(9) = '1' then
bunchmean1_data <= bma_counter3 & bma_dy3(25 downto 10) & bma_dx3(25 downto 10) & bma_s3(25 downto 10);
elsif bma_counter3(8) = '1' then
bunchmean1_data <= bma_counter3 & bma_dy3(24 downto 9) & bma_dx3(24 downto 9) & bma_s3(24 downto 9);
else
bunchmean1_data <= bma_counter3 & bma_dy3(23 downto 8) & bma_dx3(23 downto 8) & bma_s3(23 downto 8);
end if;
--bunchmean1_data <= bma_counter3 & bma_dy3(23 downto 8) & bma_dx3(23 downto 8) & bma_s3(23 downto 8);
bunchmean1_addr <= timing_addr_i;
bunchmean1_write <= ms_pulse and acq;
end if;
end process bunchmean_avg0;
-- Bunch Mean averaging
-- New system using upper 2MB of SDRAM
gen_bma_accs: for i in 0 to number_of_bunches generate
bma0: bunch_mean_acc
port map (
clk => clk,
acc => bunch_mean_acc_valid(i),
clr => ms_pulse,
sigma => sigma_avg,
deltax => deltax_avg,
deltay => deltay_avg,
sum_sigma => sigma_averages(i),
sum_deltax => deltax_averages(i),
sum_deltay => deltay_averages(i),
count => counts(i));
end generate gen_bma_accs;
bunch_mean_acc_valid(0) <= bunchmean_acc(0);
gen_bma_accs_v: for i in 1 to number_of_bunches-1 generate
bunch_mean_acc_valid(i) <= bunchmean_acc(0) and bunch_one_hot(i-1);
end generate gen_bma_accs_v;
bunch_mean_logic0: process (clk, rst)
begin -- process bunch_mean_logic0
if rst = '1' then -- asynchronous reset (active low)
bunch_one_hot <= (others => '0');
bunch_writing <= '0';
bunch_write_state <= (others => '0');
next_bunch_write_state <= (others => '0');
ms_pulse_reg <= '0';
bunch_sdram_data <= (others => '0');
timing_addr_bunch <= (others => '0');
elsif clk'event and clk = '1' then -- rising clock edge
-- Write bunches 1 to 30 into averages 1 to 30
if phase_table_sync = '1' then
bunch_one_hot(0) <= '1';
bunch_one_hot(number_of_bunches-1 downto 1) <= (others => '0');
elsif bunchmean_acc(0) = '1' then
bunch_one_hot <= bunch_one_hot(number_of_bunches-2 downto 0) & '0';
end if;
-- Write out data after ms_pulse
ms_pulse_reg <= ms_pulse;
if ms_pulse = '1' then
timing_addr_bunch <= timing_addr_i;
end if;
if ms_pulse_reg = '1' then
bunch_writing <= '1';
bunch_write_state <= (others => '0');
next_bunch_write_state <= CONV_STD_LOGIC_VECTOR(1,6);
bunch_sdram_data <=deltax_averages(0) & sigma_averages(0);
else
if bunch_writing = '1' and avg_valid = '0' then
bunch_write_state <= next_bunch_write_state;
next_bunch_write_state <= next_bunch_write_state+1;
if bunch_write_state = CONV_STD_LOGIC_VECTOR(number_of_bunches*2-1,6) then
bunch_writing <= '0';
end if;
if next_bunch_write_state(0) = '0' then
bunch_sdram_data <= deltax_averages(CONV_INTEGER(next_bunch_write_state(5 downto 1))) & sigma_averages(CONV_INTEGER(next_bunch_write_state(5 downto 1)));
else
bunch_sdram_data <= counts(CONV_INTEGER(next_bunch_write_state(5 downto 1))) & deltay_averages(CONV_INTEGER(next_bunch_write_state(5 downto 1)));
end if;
end if;
end if;
end if;
end process bunch_mean_logic0;
bunch_sdram_addr <= "1111111" & bunch_write_state(5 downto 1) & timing_addr_bunch & bunch_write_state(0);
end rtl;