attribute HGROUP: string;
attribute HGROUP of arch : architecture is "coinc_proc";
attribute BBOX: string;
-attribute BBOX of arch: architecture is "7,7";
+attribute BBOX of arch: architecture is "8,8";
signal reg_inp : std_logic_vector(INP'range);
signal sel1,sel2,sel3 : std_logic;
+signal reg_out : std_logic;
attribute syn_preserve : boolean;
attribute syn_preserve of reg_inp : signal is true;
+ attribute syn_preserve of reg_out : signal is true;
attribute syn_keep : boolean;
attribute syn_keep of reg_inp : signal is true;
+ attribute syn_keep of reg_out : signal is true;
-- (1 or 2) and 3
begin
sel2 <= reg_inp(CONF.mux_input2);
sel3 <= reg_inp(CONF.mux_input3);
-OUTP <= (((sel1 xor CONF.invert(0)) and CONF.enable(0))
+reg_out <= (((sel1 xor CONF.invert(0)) and CONF.enable(0))
or ((sel2 xor CONF.invert(1)) and CONF.enable(1)))
and ((sel3 xor CONF.invert(2)) or not CONF.enable(2))
and CONF.module_enable
when rising_edge(CLK);
+OUTP <= reg_out;
+
end architecture;
architecture arch of input_processor is
attribute syn_hier : string;
-attribute syn_hier of arch : architecture is "fixed";
+--attribute syn_hier of arch : architecture is "fixed";
attribute HGROUP: string;
attribute BBOX: string;
signal reg_tick_us, reg_tick_ms : std_logic;
signal timer : unsigned(11 downto 0);
signal counter : unsigned(15 downto 0);
-
+signal reg_outp : std_logic;
attribute syn_preserve : boolean;
attribute syn_preserve of reg_tick_us : signal is true;
attribute syn_preserve of reg_tick_ms : signal is true;
+ attribute syn_preserve of reg_inp : signal is true;
attribute syn_keep : boolean;
attribute syn_keep of reg_tick_us : signal is true;
attribute syn_keep of reg_tick_ms : signal is true;
+ attribute syn_keep of reg_inp : signal is true;
attribute syn_maxfan : integer;
- attribute syn_maxfan of OUTP : signal is 5;
+-- attribute syn_maxfan of reg_outp : signal is 10;
begin
-- Output
--------------------------------
- OUTP <= delayed_inp when rising_edge(CLK);
+ reg_outp <= delayed_inp when rising_edge(CLK);
+ OUTP <= reg_outp;
end architecture;
attribute syn_hier : string;
attribute syn_hier of arch : architecture is "fixed";
--- attribute HGROUP: string;
--- attribute HGROUP of arch : architecture is "mult_proc";
+attribute HGROUP: string;
+attribute HGROUP of arch : architecture is "mult_proc";
attribute BBOX: string;
-attribute BBOX of arch: architecture is "8,7";
+attribute BBOX of arch: architecture is "10,10";
signal reg_inp : std_logic_vector(INP'range);
signal mult_gated : std_logic_vector(95 downto 0) := (others => '0');
signal out_reg : std_logic;
signal result : unsigned(4 downto 0);
attribute syn_preserve : boolean;
- attribute syn_preserve of reg_inp : signal is true;
+ attribute syn_preserve of mult_gated : signal is true;
attribute syn_preserve of out_reg : signal is true;
attribute syn_keep : boolean;
- attribute syn_keep of reg_inp : signal is true;
+ attribute syn_keep of mult_gated : signal is true;
attribute syn_keep of out_reg : signal is true;
attribute syn_keep of OUTP : signal is true;
attribute syn_maxfan : integer;
- attribute syn_maxfan of out_reg : signal is 1;
-
+-- attribute syn_maxfan of out_reg : signal is 1;
+ attribute syn_maxfan of mult_gated : signal is 1;
+ attribute syn_maxfan of current_multiplicity : signal is 1;
begin
reg_inp <= INP;
mult_gated(INP'range) <= reg_INP and CONF.enable(INP'range) when rising_edge(CLK);
+
PROC_MULT : process
- variable m,n : integer range 0 to 20;
+ variable m,n : integer range 0 to 8;
begin
wait until rising_edge(CLK);
-
- for j in 0 to 3 loop
+ for j in 0 to 4 loop
m := 0; n := 0;
- for i in 20*j+0 to 20*j+9 loop
+ for i in 16*j+0 to 16*j+7 loop
if mult_gated(i) = '1' then
m := m + 1;
end if;
end loop;
- for i in 20*j+10 to 20*j+19 loop
+ for i in 16*j+8 to 16*j+15 loop
if mult_gated(i) = '1' then
n := n + 1;
end if;
current_multiplicity(j) <= to_unsigned(m+n,5);
end loop;
-- + (current_multiplicity(4) + current_multiplicity(5))
- result <= (current_multiplicity(0) + current_multiplicity(1)) + (current_multiplicity(2) + current_multiplicity(3));
- if result >= CONF.multiplicity and CONF.multiplicity > 0 then
+ result <= (current_multiplicity(0) + current_multiplicity(1)) + (current_multiplicity(2) + current_multiplicity(3)) ;
+ if result + current_multiplicity(4) >= CONF.multiplicity and CONF.multiplicity > 0 then
out_reg <= '1';
else
out_reg <= '0';
end if;
end process;
+
+-- PROC_MULT : process
+-- variable m,n : integer range 0 to 20;
+-- begin
+-- wait until rising_edge(CLK);
+--
+-- for j in 0 to 3 loop
+-- m := 0; n := 0;
+-- for i in 20*j+0 to 20*j+9 loop
+-- if mult_gated(i) = '1' then
+-- m := m + 1;
+-- end if;
+-- end loop;
+-- for i in 20*j+10 to 20*j+19 loop
+-- if mult_gated(i) = '1' then
+-- n := n + 1;
+-- end if;
+-- end loop;
+-- current_multiplicity(j) <= to_unsigned(m+n,5);
+-- end loop;
+-- -- + (current_multiplicity(4) + current_multiplicity(5))
+-- result <= (current_multiplicity(0) + current_multiplicity(1)) + (current_multiplicity(2) + current_multiplicity(3));
+-- if result >= CONF.multiplicity and CONF.multiplicity > 0 then
+-- out_reg <= '1';
+-- else
+-- out_reg <= '0';
+-- end if;
+-- end process;
+
OUTP <= out_reg; --'1' when result >= CONF.multiplicity and CONF.multiplicity > 0 else '0' ;
end architecture;
INP : in std_logic_vector(NUM_INPUTS-1 downto 0);
BUS_RX : in CTRLBUS_RX;
- BUS_TX : out CTRLBUS_TX
+ BUS_TX : out CTRLBUS_TX;
+ TIMER : in TIMERS;
+ RDO_RX : in READOUT_RX;
+ RDO_TX : out READOUT_TX
);
end entity;
attribute HGROUP: string;
attribute HGROUP of arch : architecture is "scalers";
+attribute BBOX: string;
+attribute HGROUP of arch : architecture is "input_proc";
+attribute BBOX of arch: architecture is "60,40";
-signal reg_inp, reg2_inp, reg3_inp : std_logic_vector(INP'range);
+
+signal reg_inp, reg2_inp, reg3_inp, reg4_inp, cnt_en : std_logic_vector(INP'range);
attribute syn_preserve : boolean;
attribute syn_preserve of reg_inp : signal is true;
signal reset_cnt : std_logic := '0';
signal send_ack, reg_send_ack, reg2_send_ack, reg3_send_ack : std_logic := '0';
-signal muxreg : std_logic_vector(31 downto 0);
+signal muxreg, rdo_muxreg : std_logic_vector(31 downto 0);
+
+ type rdo_state_t is (IDLE, ADDTIME, WRITEFIRST, WRITE, WAIT1, WAIT2, WAIT3, CALC, FINISH, BUSYEND);
+ signal state : rdo_state_t;
+ signal addr,ram_addr : integer range 0 to 255;
+
+ type ram_arr is array (0 to 255) of std_logic_vector(31 downto 0);
+ signal ram : ram_arr;
+
+ signal ram_din, ram_dout, ram_dout_i : std_logic_vector(31 downto 0);
+ signal result : std_logic_vector(31 downto 0);
+ signal ram_write: std_logic;
+
+
+
begin
reg_inp <= INP when rising_edge(CLK_FULL);
reg2_inp <= reg_inp when rising_edge(CLK_FULL);
reg3_inp <= reg2_inp when rising_edge(CLK_FULL);
+reg4_inp <= reg3_inp when rising_edge(CLK_SYS);
+--------------------------------
+-- Scaler
+--------------------------------
gen_scalers : for i in 0 to NUM_INPUTS-1 generate
process begin
wait until rising_edge(CLK_FULL);
- if reg2_inp(i) = '1' and reg3_inp(i) = '0' then
+ cnt_en(i) <= reg2_inp(i) and not reg3_inp(i);
+ if cnt_en(i) = '1' then
cnt(i) <= cnt(i) + 1;
end if;
if RESET = '1' then
end process;
end generate;
+
+--------------------------------
+-- CTRL readout
+--------------------------------
muxreg(27 downto 0) <= cnt(to_integer(unsigned(BUS_RX.addr(8 downto 0)))) when rising_edge(CLK_SYS);
+muxreg(31) <= reg4_inp(to_integer(unsigned(BUS_RX.addr(8 downto 0))));
THE_REGS : process
variable slice : integer range 0 to 511;
end if;
end process;
+--------------------------------
+-- Scaler memory
+--------------------------------
+
+ THE_MEM : process
+ begin
+ wait until rising_edge(CLK_SYS);
+ if ram_write = '1' then
+ ram(ram_addr) <= ram_din;
+ end if;
+ ram_dout_i <= ram(ram_addr);
+ end process;
+
+ram_din <= rdo_muxreg;
+ram_dout <= ram_dout_i when rising_edge(CLK_SYS);
+ram_addr <= addr;
+
+
+
+
+--------------------------------
+-- Trigger Handling
+--------------------------------
+THE_RDO : process begin
+ wait until rising_edge(CLK_SYS);
+ RDO_TX.busy_release <= '0';
+ RDO_TX.data_write <= '0';
+ RDO_TX.data_finished <= '0';
+ ram_write <= '0';
+
+
+
+ case state is
+ when IDLE =>
+ addr <= 0;
+ if RDO_RX.valid_notiming_trg = '1' and RDO_RX.trg_type = x"E" then
+ state <= WRITEFIRST;
+ elsif RDO_RX.valid_notiming_trg = '1' or RDO_RX.valid_timing_trg = '1' or RDO_RX.invalid_trg = '1' then
+ state <= ADDTIME;
+ end if;
+
+ when ADDTIME =>
+ RDO_TX.data <= TIMER.microsecond;
+ RDO_TX.data_write <= '1';
+ state <= FINISH;
+
+ when WRITEFIRST =>
+ RDO_TX.data <= TIMER.microsecond;
+ RDO_TX.data_write <= '1';
+ state <= WAIT1;
+
+ when WAIT1 =>
+ state <= WAIT2;
+
+ when WAIT2 =>
+ state <= WAIT3;
+
+ when WAIT3 =>
+ state <= CALC;
+ rdo_muxreg(27 downto 0) <= cnt(addr);
+
+ when CALC =>
+ state <= WRITE;
+ ram_write <= '1';
+ result(27 downto 0) <= std_logic_vector(unsigned(rdo_muxreg(27 downto 0)) - unsigned(ram_dout(27 downto 0)));
+ result(31) <= reg4_inp(to_integer(unsigned(BUS_RX.addr(8 downto 0))));
+
+ when WRITE =>
+
+ RDO_TX.data_write <= '1';
+ RDO_TX.data <= result;
+ addr <= addr + 1;
+
+ if addr = NUM_INPUTS - 1 then
+ state <= FINISH;
+ else
+ state <= WAIT1;
+
+ end if;
+
+ when FINISH =>
+ state <= BUSYEND;
+ RDO_TX.data_finished <= '1';
+
+ when BUSYEND =>
+ state <= IDLE;
+ RDO_TX.busy_release <= '1';
+ end case;
+end process;
+
end architecture;
BUS_TX : out CTRLBUS_TX;
BUSSCALER_RX : in CTRLBUS_RX;
BUSSCALER_TX : out CTRLBUS_TX;
-
+ TIMER : in TIMERS;
BUSRDO_RX : in READOUT_RX;
BUSRDO_TX : out READOUT_TX
signal groups, reg_groups : std_logic_vector(NUM_GROUPS-1 downto 0);
signal coincs, reg_coincs : std_logic_vector(NUM_COINC-1 downto 0);
signal multis, reg_multis : std_logic_vector(NUM_MULT-1 downto 0);
-signal out1_i, out2_i, reg_out : std_logic_vector(OUTP'range);
+signal reg_out, out1_i, out2_i, out_i, long_reg_out_1, long_reg_out_2 : std_logic_vector(OUTP'range);
+
signal list_of_scaler : std_logic_vector(NUM_SCALER-1 downto 0);
type CONF_input_processor_arr is array(0 to NUM_INPUTS+NUM_VIRTUALIN-1) of CONF_input_processor_t;
type config_mem_t is array(0 to 1023) of std_logic_vector(31 downto 0);
signal config_mem : config_mem_t;
+signal CONF_output_strecher : std_logic_vector(NUM_OUTPUTS-1 downto 0);
+
signal config_mem_out : std_logic_vector(31 downto 0);
signal read_mem : std_logic;
signal coinc_inputs : std_logic_vector(255 downto 0) := (others => '0');
-- attribute syn_maxfan of list_of_inp : signal is 16;
attribute syn_maxfan of reg_processed_inp : signal is 1;
- attribute syn_maxfan of temp_processed_inp : signal is 2;
+ attribute syn_maxfan of temp_processed_inp : signal is 1;
+ attribute syn_maxfan of processed_inp : signal is 1;
attribute syn_maxfan of reg_groups : signal is 1;
attribute syn_maxfan of reg_multis : signal is 1;
attribute syn_maxfan of reg_coincs : signal is 1;
attribute syn_maxfan of list_of_monitor : signal is 1;
attribute syn_maxfan of temp_list_of_monitor : signal is 1;
- attribute HGROUP : string;
- attribute HGROUP of gen_input_muxes : label is "muxes_group";
begin
gen_coincs : for i in 0 to NUM_COINC-1 generate
THE_COINC : entity work.coincidence
generic map (
- NUM_INPUTS => NUM_COINC + NUM_GROUPS + NUM_INPUTS + NUM_VIRTUALIN
+ NUM_INPUTS => NUM_MULT + NUM_GROUPS + NUM_INPUTS + NUM_VIRTUALIN
)
port map(
CLK => CLK_FULL,
- INP => coinc_inputs(NUM_COINC + NUM_GROUPS + NUM_INPUTS + NUM_VIRTUALIN-1 downto 0),
+ INP => coinc_inputs(NUM_MULT + NUM_GROUPS + NUM_INPUTS + NUM_VIRTUALIN-1 downto 0),
OUTP => coincs(i),
CONF => CONF_coincidence(i)
);
--------------------------------
-- Outputs
--------------------------------
---TODO: add a bit of stretching to the OUTPUT
+
list_of_outp(NUM_MULT + NUM_COINC + NUM_VIRTUALIN + NUM_INPUTS-1 downto 0) <= reg_multis & reg_coincs & reg_processed_inp ;--when rising_edge(CLK_FULL);
gen_outputs : for i in 0 to NUM_OUTPUTS-1 generate
out1_i(i) <= or (list_of_outp and CONF_outputs(i)(0)) when rising_edge(CLK_FULL);
out2_i(i) <= or (list_of_outp and CONF_outputs(i)(1)) when rising_edge(CLK_FULL);
end generate;
+
+reg_out <= out_i or ((long_reg_out_1 or long_reg_out_2) and CONF_output_strecher) when rising_edge(CLK_FULL);
+out_i <= out1_i and out2_i;
+long_reg_out_1 <= out_i when rising_edge(CLK_FULL);
+long_reg_out_2 <= long_reg_out_1 when rising_edge(CLK_FULL);
OUTP <= reg_out;
-reg_out <= out1_i and out2_i when rising_edge(CLK_FULL);
--------------------------------
-- Registers
BUS_TX.ack <= '1';
slice := to_integer(unsigned(BUS_RX.addr(3 downto 0)));
CONF_monitor(slice) <= to_integer(unsigned(BUS_RX.data(8 downto 0)));
--- end if;
elsif BUS_RX.addr(11 downto 7) = "00011" then
slice := to_integer(unsigned(BUS_RX.addr(6 downto 2)));
else
BUS_TX.unknown <= '1';
end if;
-
+
+ elsif BUS_RX.addr(11 downto 0) = "000111000000" then
+ BUS_TX.ack <= '1';
+ CONF_output_strecher <= BUS_RX.data(NUM_OUTPUTS-1 downto 0);
+
elsif BUS_RX.addr(11 downto 7) = "00100" then
slice := to_integer(unsigned(BUS_RX.addr(6 downto 3)));
if slice < NUM_OUTPUTS then
or (BUS_RX.addr(11 downto 7) = "00011" and to_integer(unsigned(BUS_RX.addr(6 downto 2))) < NUM_MULT)
or (BUS_RX.addr(11 downto 7) = "00100" and to_integer(unsigned(BUS_RX.addr(6 downto 3))) < NUM_OUTPUTS)
or (BUS_RX.addr(11 downto 7) = "00110" and to_integer(unsigned(BUS_RX.addr(6 downto 3))) < NUM_OUTPUTS)
+ or (BUS_RX.addr(11 downto 0) = "000111000000")
then
read_mem <= '1';
RESET => RESET,
INP => list_of_scaler,
BUS_RX => BUSSCALER_RX,
- BUS_TX => BUSSCALER_TX
+ BUS_TX => BUSSCALER_TX,
+ TIMER => TIMER,
+
+ RDO_RX => BUSRDO_RX,
+ RDO_TX => BUSRDO_TX
);
-- Monitor
--------------------------------
list_of_monitor(NUM_SCALER-1 downto 0) <= reg_out & reg_multis & reg_coincs & reg_groups & reg_processed_inp & reg_inp when rising_edge(CLK_FULL);
---list_of_monitor <= temp_list_of_monitor when rising_edge(CLK_FULL);
+-- list_of_monitor <= temp_list_of_monitor when rising_edge(CLK_FULL);
gen_monitors : for i in MONITOR_OUT'range generate
THE_MONITOR : entity work.monitor_output
generic map(
--------------------------------
-- Readout
--------------------------------
-BUSRDO_TX.data_finished <= '1';
-BUSRDO_TX.data_write <= '0';
-BUSRDO_TX.busy_release <= '1';
+
end architecture;
lm_license_file_for_synplify => "27020\@jspc29", #"27000\@lxcad01.gsi.de";
lm_license_file_for_par => "1702\@hadeb05.gsi.de",
lattice_path => '/d/jspc29/lattice/diamond/3.11_x64',
-synplify_path => '/d/jspc29/lattice/synplify/P-2019.09-SP1/',
+synplify_path => '/d/jspc29/lattice/synplify/R-2020.09-SP1/',
#synplify_command => "/d/jspc29/lattice/diamond/3.6_x64/bin/lin64/synpwrap -fg -options",
# synplify_command => "/d/jspc29/lattice/synplify/J-2014.09-SP2/bin/synplify_premier_dp",
#Report settings
firefox_open => 0,
twr_number_of_errors => 50,
-mapper_options => ' -hier -tdm -td_pack',
+mapper_options => ' -hier -tdm -retime EFFORT=1', #-td_pack
-w
--i 15
+-i 25
-l 5
--n 1
+#-n 1
-y
-s 12
-t 26
-c 1
--e 4
+-e 5
#-g guidefile.ncd
#-m nodelist.txt
# -w
# MULTICYCLE TO CELL "X_c*" 20 ns;
BLOCK PATH TO CELL "THE_BOX/THE_SCALER/reg_in*";
-MULTICYCLE FROM CELL "THE_BOX/THE_SCALER/gen_scalers.*.cnt*" TO CELL "THE_BOX/THE_SCALER/muxre*" 20 ns;
+MULTICYCLE FROM CELL "THE_BOX/THE_SCALER/gen_scalers.*.cnt*" TO CELL "THE_BOX/THE_SCALER/muxre*" 15 ns;
+MULTICYCLE FROM CELL "THE_BOX/THE_SCALER/gen_scalers.*.cnt*" TO CELL "THE_BOX/THE_SCALER/THE_RDO.rdo_muxre*" 15 ns;
BLOCK PATH TO CELL "THE_BOX/list_of_scale*";
+PRIORITIZE NET "THE_BOX/temp_processed_inp*" 20;
+PRIORITIZE NET "THE_BOX/processed_inp*" 20;
+# PRIORITIZE NET "THE_BOX/reg_processed_inp*" 20;
+
# MULTICYCLE TO CELL "THE_BOX/gen_coincs.*.THE_COINC/reg_in*" 2x ;
REGION "COINMULT_region" "R35C70" 34 65;
LOCATE UGROUP "THE_BOX/gen_coincs.14.THE_COINC/coinc_proc" REGION "COINMULT_region";
LOCATE UGROUP "THE_BOX/gen_coincs.15.THE_COINC/coinc_proc" REGION "COINMULT_region";
-UGROUP "multis"
-BLKNAME "THE_BOX/gen_multis.0.THE_MULTIPLICITY"
-BLKNAME "THE_BOX/gen_multis.1.THE_MULTIPLICITY"
-BLKNAME "THE_BOX/gen_multis.2.THE_MULTIPLICITY"
-BLKNAME "THE_BOX/gen_multis.3.THE_MULTIPLICITY"
-BLKNAME "THE_BOX/gen_multis.4.THE_MULTIPLICITY"
-BLKNAME "THE_BOX/gen_multis.5.THE_MULTIPLICITY"
-BLKNAME "THE_BOX/gen_multis.6.THE_MULTIPLICITY"
-BLKNAME "THE_BOX/gen_multis.7.THE_MULTIPLICITY";
-LOCATE UGROUP "multis" REGION "COINMULT_region";
-#LOCATE UGROUP "THE_BOX/gen_multis.0.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
-#LOCATE UGROUP "THE_BOX/gen_multis.1.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
-#LOCATE UGROUP "THE_BOX/gen_multis.2.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
-#LOCATE UGROUP "THE_BOX/gen_multis.3.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
-#LOCATE UGROUP "THE_BOX/gen_multis.4.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
-#LOCATE UGROUP "THE_BOX/gen_multis.5.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
-#LOCATE UGROUP "THE_BOX/gen_multis.6.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
-#LOCATE UGROUP "THE_BOX/gen_multis.7.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
+
+LOCATE UGROUP "THE_BOX/gen_multis.0.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
+LOCATE UGROUP "THE_BOX/gen_multis.1.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
+LOCATE UGROUP "THE_BOX/gen_multis.2.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
+LOCATE UGROUP "THE_BOX/gen_multis.3.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
+LOCATE UGROUP "THE_BOX/gen_multis.4.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
+LOCATE UGROUP "THE_BOX/gen_multis.5.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
+LOCATE UGROUP "THE_BOX/gen_multis.6.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
+LOCATE UGROUP "THE_BOX/gen_multis.7.THE_MULTIPLICITY/mult_proc" REGION "COINMULT_region";
LOCATE UGROUP "THE_BOX/gen_groups.0.THE_GROUPS/groups" REGION "COINMULT_region";
LOCATE UGROUP "THE_BOX/gen_groups.1.THE_GROUPS/groups" REGION "COINMULT_region";
BUS_TX => busrdo_tx,
BUSSCALER_RX => busscaler_rx,
BUSSCALER_TX => busscaler_tx,
+ TIMER => timer,
BUSRDO_RX => readout_rx,
BUSRDO_TX => readout_tx(0)