== Code and Notes * https://gitlab.cern.ch/ehazen/l0mdt-daq-felix (submodule) * https://github.com/eshazen/picoblaze-ebus (top level test with picoblaze on basys3) == Work Log '''2022-06-07''' Next step is to build a simulation tb for {{{daq_unit}}} which contains the random generators and get it working. That way the sim can be compared with the basys3 hardware version. '''2022-03-10''' Working on {{{picoblaze-ebus}}} top-level with {{{l0mdt-daq-felix}}} submodule. Address table: {{{ 00000000 - GPIO/control 10000000 - rate meter for test \ these are connected together 0 - rate generator (at 20000000) 1 - MDT trigger rate 2 - MDT hit rate 3 - N/A 20000000 - rate generator for test / for basic checking, unrelated to L0MDT 30000000 - FELIX readout GPIO: Control regs 0 - trigger rate random threshold [1] 1 - hit rate random threshold [2] 2 - n/a 3 - n/a Status regs 4 - switches 5 - n/a Action regs 100 - bit 1: OcR bit 2: EcR Soft reset: output to 10, so command "O 10 0" FELIX: Address Read Write Notes 0..7 Data N/A 32-bit chunks, low-endian 8 "beef" + wr_addr wr_addr 10 bits 9 "cafe" + rd_addr rd_addr 10 bits A wr_ena wr_ena bit 0 only [1] - /2**32 is probability of trigger in one BX [2] - /2**32 is probability of tube hit in one clock Clock period is 100MHz for testing, BX period is 1/8 of that or 1/12.5MHz }}} '''2022-02-13''' Andrew says to ignore {{{ttc-core}}} submodule. Need to figure out where to put in the TTC generator. Currently there is a {{{ttc_commands}}} record originating in {{{top_hal.vhd}}} originating in {{{felix_decoder}}}. So for now we should make a {{{ttc_commands}}} record which is of type {{{l0mdt_ttc_rt}}}. {{{ subtype bcid_t is unsigned(12-1 downto 0); subtype evid_t is unsigned(32-1 downto 0); subtype orid_t is unsigned(32-1 downto 0); type l0mdt_ttc_rt is record bcr : std_logic; ocr : std_logic; ecr : std_logic; l0a : std_logic; l1a : std_logic; bcid : bcid_t; evid : evid_t; orid : orid_t; end record l0mdt_ttc_rt; }}} Looking at the clocking. In {{{top_clocking}}} there is {{{framework_mmcm}}} which outputs {{{clk320}}} and {{{clk40}}}. There's a record {{{l0mdt_control_rt}}} as: {{{ type l0mdt_control_rt is record clk : std_logic; rst : std_logic; bx : std_logic; end record l0mdt_control_rt; }}} The strobe {{{bx}}} is generated by an instance of {{{clock_strobe}}} in {{{top_hal.vhd}}}. '''2022-02-07''' Working on random hit/trig generator. VHDL entity '''trig_gen.vhd''' generates random triggers at specified rate. Currently it generates one urand per clock at 100MHz, which requires two DSP48 in an Artix-7. Basys3 test project created and tested. Also working on synthesizable '''ttc_eric.vhd''' which generates global TTC signals, including a map of LHC bunch structure. Thinking about generating some semi-legit looking random MDT data. Here's the data format as of now: {{{ - tdcpolmux2tar: - data_valid: [type : logic] - tdc: [type : tdc] # 1 - chanid: [type : unsigned , length : TDC_CHANID_LEN] # 5 - edgemode: [type : logic , length : TDC_EDGEMODE_LEN] # 2 - coarsetime: [type : unsigned , length : TDC_COARSETIME_LEN] # 12 - finetime: [type : unsigned , length : TDC_FINETIME_LEN] # 5 - pulsewidth: [type : unsigned , length : TDC_PULSEWIDTH_LEN] # 8 - csmid: [type : unsigned , length : TDCPOLMUX2TAR_CSMID_LEN] # 4 - tdcid: [type : unsigned , length : TDCPOLMUX2TAR_TDCID_LEN] # 5 }}} '''2022-01-21''' Thoughts on HW testing: Create a programmable random trigger/hit generator and simple control interface (picoblaze?) Build for some eval board or even a CM and test. '''2022-01-17''' Seems to be working, with a few caveats. For an 80MHz hit rate, 1MHz trigger rate, 32 WM. Compare against output of simulation check_daq.pl. There are a few errors; all seem to be off-by-one at the extreme end of the matching window. Not sure this is that important. '''2022-01-11''' First version synthesized. No constraints. 32 WM. Utilization: [[Image("https://ohm.bu.edu/~hazen/ATLAS/Phase2MDT/daq-synth1.jpg",width=300)]] This compares favorably with blackboard estimate! I've created a constraint file and trying to build with 320MHz clock now. '''2022-01-07''' Working on "toy" DAQ for resource comparison. Here's a detailed specification :) [[Image("https://ohm.bu.edu/~hazen/ATLAS/Phase2MDT/daq-blackboard.jpg",width=300)]] Assumptions: * One pipeline hit stream stream (aka PTSD) at ~320MHz feeds one FELIX fiber. * Each "DAQ block" handles one such stream/fiber and operates independently of all others * Inputs: * TTC: clock, trigger, BX strobe, BcN[11:0], OrN[11:0], EvN[11:0] * HITS: 41 bits data (with BcN at known bit offset) and data valid * Outputs: * 230 bit FELIX data at pipeline clock, data valid * Monitoring * Various random error signals come out and could be connected somewhere Given the first assumption the DAQ is conceptually very simple. Here are the VHDL entities: {{{wm}}}:: single window match with FIFO {{{dispatch}}}:: group of window matchers. Dispatcher for triggers, mux for output {{{format}}}:: output formatter. Currently includes trigger FIFO. Outputs header, data, trailer words to FELIX with a few hits packed in each data word. {{{daq}}}:: top level, includes one {{{dispatch}}} and one {{{format}}}. ''''2021-12-15''' Investigating PicoBlaze speed... if one would run at 320MHz it could be a useful tool for DAQ work. Creating a simple test design in a {{{xcvu3p-ffvc1517-1-i}}} device. Just the picoblaze, very short program, and 4 each input and output ports decoded with 1 address bit per port. Configured with 100MHz clock input, MMCM synthesizing 320MHz. Seems to have worked. Trying 400MHz. Nope. For 320MHz the reported WNS is 0.095ns. Ouch! '''2021-12-01''' Looking at the DAQ. The submodule with the code is here: https://gitlab.cern.ch/tcpaiva/atlas-daq-core It is included here: https://gitlab.cern.ch/atlas-tdaq-phase2-l0mdt-electronics/l0mdt-hdl-design/-/tree/devel/UserLogic/daq Here is the hierarchy resulting from loading all the VHDL files into Vivado: [[Image("https://ohm.bu.edu/~hazen/ATLAS/Phase2MDT/DAQ_h.png")]] Top level is at {{{UserLogic/ult/src/ult_daq.vhd}}}. Entity {{{daq}}} takes as input arrays for each station (I, M, O, X) an {{{mdt_polmux_bus_avt}}} which consists of {{{tdcpolmux2tar_rt}}} which have {{{csmid}}}, {{{tdcid}}} and {{{tdc_rt}}}. {{{ - tdcpolmux2tar: - data_valid: [type : logic] - tdc: [type : tdc] # 1 - chanid: [type : unsigned , length : TDC_CHANID_LEN] # 5 - edgemode: [type : logic , length : TDC_EDGEMODE_LEN] # 2 - coarsetime: [type : unsigned , length : TDC_COARSETIME_LEN] # 12 - finetime: [type : unsigned , length : TDC_FINETIME_LEN] # 5 - pulsewidth: [type : unsigned , length : TDC_PULSEWIDTH_LEN] # 8 - csmid: [type : unsigned , length : TDCPOLMUX2TAR_CSMID_LEN] # 4 - tdcid: [type : unsigned , length : TDCPOLMUX2TAR_TDCID_LEN] # 5 # Total 42 }}} Here we see loops over {{{inner_tdc_hits}}} which is an array of 6 "streams" of input data (6x POLMUX presumably). Output is {{{felix_stream_bus_avt}}}, defined in {{{{shared/types/common_types_pkg.vhd}}} as an array of {{{felix_data_t}}} plus {{{valid}}}. For some reason the {{{felix_data_t}}} is 65 bits wide. All the mess is in {{{daq_branch.vhd}}} in {{{UserLogic/daq/daq-core/src}}}. This is very confusing code which Thiago is going to explain to us :) Here it goes: {{{ in UserLogic/ult/src/ult_daq.vhd: daq_streams(j) <= outputify( inner_er.o.f2e_bus(j)) (inner_er is daq_branch_ert) daq_branch_t is array of daq_stream_rt daq_stream_rt is (valid, bcid, daq_stream_data_t) }}} I give up!