diff --git a/address_table/ETROC2_example.yaml b/address_table/ETROC2_example.yaml index fa8077f3204cb6e295db67c73820fff49a083039..094f795c0b0cffec2d96032bef1c4f3c65ab98db 100644 --- a/address_table/ETROC2_example.yaml +++ b/address_table/ETROC2_example.yaml @@ -1,10 +1,15 @@ +############################################ +##### In-Pixel Configuration Registers ##### +############################################ + CLSel: - doc: "Select of load capacitance of the preamp first stage. - 2‘b00: 0 fC; - 2‘b01–> 80 fC; - 2‘b10–> 80 fC; - 2‘b01–> 160 fC. - Debugging use only." + doc: |- + Select of load capacitance of the preamp first stage. + 2‘b00: 0 fC; + 2‘b01: 80 fC; + 2‘b10: 80 fC; + 2‘b01: 160 fC. + Debugging use only. address: - 0 mask: @@ -13,8 +18,158 @@ CLSel: stat: 0 default: 0x0 +IBSel: + doc: |- + Bias current selection of the input transistor in the preamp. + 3'b000: I1; + 3'b001, 3'b010, 3'b100: I2; + 3'b011, 3'b110, 3'b101: I3; + 3'b111: I4 + I1 > I2 > I3 > I4. + address: + - 0 + mask: + - 0x1C + pixel: 1 + stat: 0 + default: 0x7 + +RfSel: + doc: |- + Feedback resistance selection. + 2'b00: 20 kOHm + 2'b01: 10 kOHm + 2'b10: 5.7 kOHm + 2'b11: 4.4 kOHm + address: + - 0 + mask: + - 0x60 + pixel: 1 + stat: 0 + default: 0x2 + +HysSel: + doc: |- + Hysteresis voltage selection. + 4'b0000: Vhys1 + 4'b0001: Vhys2 + 4'b0011: Vhys3 + 4'b0111: Vhys4 + 4'b1111: Vhys5 + Vhys1 > Vhys2 > Vhys3 > Vhys4 = Vhys5 = 0 + address: + - 2 + mask: + - 0xF + pixel: 1 + stat: 0 + default: 0xF + +PD_DACDiscri: + doc: |- + Power down the DAC and the discriminator in pixels. + When PD_DACDiscri is 1, the DAC and the discriminator are powered down. + address: + - 2 + mask: + - 0x10 + pixel: 1 + stat: 0 + default: 0x0 + +QSel: + doc: "Select injected charge, from 1 fC (5'b00000) to 32 fC (5'b11111)." + address: + - 1 + mask: + - 0x1F + pixel: 1 + stat: 0 + default: 0x6 + +QInjEn: + doc: "Enable the charge injection of the specified pixel. Active high." + address: + - 1 + mask: + - 0x20 + pixel: 1 + stat: 0 + default: 0x0 + +autoReset_TDC: + doc: "TDC automatically reset controller for every clock period." + address: + - 6 + mask: + - 0x20 + pixel: 1 + stat: 0 + default: 0x0 + +enable_TDC: + doc: |- + TDC enable. + 1'b1: enable TDC conversion + 1'b0: disable TDC conversion + address: + - 6 + mask: + - 0x80 + pixel: 1 + stat: 0 + default: 0x1 + +level_TDC: + doc: "The bit width of bubble tolerant in TDC encode. It is up to 3'b011" + address: + - 6 + mask: + - 0xE + pixel: 1 + stat: 0 + default: 0x1 + +resetn_TDC: + doc: "Reset TDC encoder, active low." + address: + - 6 + mask: + - 0x40 + pixel: 1 + stat: 0 + default: 0x1 + +testMode_TDC: + doc: |- + Test mode enable of TDC, active high. In test mode, TDC generates + a fixed test pulse as input signal for test for every 25 ns. + address: + - 6 + mask: + - 0x10 + pixel: 1 + stat: 0 + default: 0x0 + +Bypass_THCal: + doc: |- + Bypass control of the in-pixel threshold calibration block. + 1: Bypassing the in-pixel threshold calibration block. DAC is applied to TH. + Users can control the threshold voltage through DAC. + 0: Calibrated threshold is applied to TH. + TH = BL + TH_offset. + address: + - 3 + mask: + - 0x4 + pixel: 1 + stat: 0 + default: 0x1 + DAC: - doc: "threshold" + doc: "When THCal_Bypass==1'b1, TH = DAC." address: - 4 - 5 @@ -26,7 +181,7 @@ DAC: default: 0x0 TH_offset: - doc: "Threshold offset for the calibrated baseline. + doc: "Threshold offset for the calibrated baseline. TH = BL + TH_offset" address: - 5 @@ -36,8 +191,203 @@ TH_offset: stat: 0 default: 0xa +RSTn_THCal: + doc: "Reset of threshold calibration block, active low." + address: + - 3 + mask: + - 0x1 + pixel: 1 + stat: 0 + default: 0x1 + +ScanStart_THCal: + doc: "A rising edge of ScanStart_THCal initializes the threshold calibration." + address: + - 3 + mask: + - 0x10 + pixel: 1 + stat: 0 + default: 0x0 + +BufEn_THCal: + doc: |- + Threshold calibration buffer enable. + 1: enabling the buffer between discriminator output and the TH_Ctrl. + 0: disabling the buffer between discriminator output and the TH_Ctrl. + address: + - 3 + mask: + - 0x2 + pixel: 1 + stat: 0 + default: 0x0 + +CLKEn_THCal: + doc: |- + This register is only used when the threshold calibration clock is bypassed. + 1: enabling the clock for measuring average discriminator output. + 0: disabling the clock. Measurement of the average discriminator output is not available. + address: + - 3 + mask: + - 0x8 + pixel: 1 + stat: 0 + default: 0x0 + +workMode: + doc: |- + Readout work mode selection. + 2'b00: normal, + 2'b01: self test, periodic trigger fixed TDC data, + 2'b10: self test, random TDC data, + 2'b11: reservered. + address: + - 7 + mask: + - 0x18 + pixel: 1 + stat: 0 + default: 0x0 + +L1Adelay: + doc: "L1A latency" + address: + - 8 + - 9 + mask: + - 0x80 + - 0xFF + pixel: 1 + stat: 0 + default: 0x1F5 + +disDataReadout: + doc: |- + Disable signal of the TDC data readout. + 1: disabling the TDC data readout of the current pixel. + 0: enabling the TDC data readout fo the current pixel. + address: + - 7 + mask: + - 0x2 + pixel: 1 + stat: 0 + default: 0x0 + +disTrigPath: + doc: |- + Disable signal of the trigger readout. + 1: disabling the trigger readout of the current pixel. + 0: enabling the trigger readout of the current pixel. + address: + - 7 + mask: + - 0x4 + pixel: 1 + stat: 0 + default: 0x0 + +upperTOATrig: + doc: "TOA upper threshold for the trigger readout" + address: + - 21 + - 22 + mask: + - 0xFF + - 0x3 + pixel: 1 + stat: 0 + default: 0x200 + +lowerTOATrig: + doc: "TOA lower threshold for the trigger readout" + address: + - 19 + - 20 + mask: + - 0xC0 + - 0xFF + pixel: 1 + stat: 0 + default: 0x20 + +upperTOTTrig: + doc: "TOT upper threshold for the trigger readout" # Potential mismatch between register table default (p.62) and address register table default (p. 63) in Users Manual. + address: + - 23 + - 24 + mask: + - 0xF8 + - 0xF + pixel: 1 + stat: 0 + default: 0x40 + +lowerTOTTrig: + doc: "TOT lower threshold for the trigger readout" + address: + - 22 + - 23 + mask: + - 0xFC + - 0x7 + pixel: 1 + stat: 0 + default: 0x10 + +upperCalTrig: + doc: "Cal upper threshold for the trigger readout" + address: + - 18 + - 19 + mask: + - 0xF0 + - 0x3F + pixel: 1 + stat: 0 + default: 0x200 + +lowerCalTrig: + doc: "Cal lower threshold for the trigger readout" + address: + - 17 + - 18 + mask: + - 0xFC + - 0xF + pixel: 1 + stat: 0 + default: 0x10 + +upperTOA: + doc: "TOA upper threshold for the TDC data readout" + address: + - 13 + - 14 + mask: + - 0xC0 + - 0xFF + pixel: 1 + stat: 0 + default: 0x200 + +lowerTOA: + doc: "TOA lower threshold for the TDC data readout" + address: + - 12 + - 13 + mask: + - 0xF0 + - 0x3F + pixel: 1 + stat: 0 + default: 0x20 + upperTOT: - doc: "please add doc" + doc: "TOT upper threshold for the TDC data readout" address: - 16 - 17 @@ -46,40 +396,1274 @@ upperTOT: - 0x3 pixel: 1 stat: 0 - default: 0x0 + default: 0x100 -disScrambler: - doc: "Disable scrambler. - 0: enable scrambler - 1: disable scrambler" +lowerTOT: + doc: "TOT lower threshold for the TDC data readout" address: - - 19 + - 15 + - 16 mask: + - 0xFF - 0x1 - pixel: 0 + pixel: 1 + stat: 0 + default: 0x10 + +upperCal: + doc: "Cal upper threshold for the TDC data readout" + address: + - 11 + - 12 + mask: + - 0xFC + - 0xF + pixel: 1 + stat: 0 + default: 0x200 + +lowerCal: + doc: "Cal lower threshold for the TDC data readout" # Potential mismatch between register table default (p.62) and address register table default (p. 63) in Users Manual. + address: + - 10 + - 11 + mask: + - 0xFF + - 0x3 + pixel: 1 + stat: 0 + default: 0x10 + +addrOffset: + doc: |- + Enabling of the circular buffer (CB) write address offset + by the pixel ID, active high. + 1: enabling of the CB write address offset. + 0: disabling of the CB write address offset. + address: + - 7 + mask: + - 0x1 + pixel: 1 stat: 0 default: 0x1 -singlePort: - doc: "enable single port or both ports. - 0: use both left and right serial ports. - 1: use right serial port only" +selfTestOccupancy: + doc: |- + Self-test data occupancy is selfTestOccupancy[6:0]/128. + For example: + 1: 1/1.28% + 2: 2/1.28% + 5: 5/1.28% + 10: 10/1.28% address: - - 19 + - 8 mask: - - 0x40 - pixel: 0 + - 0x7F + pixel: 1 stat: 0 default: 0x1 -mergeTriggerData: - doc: "merge trigger and data in a port - 0: trigger and data in separate port, only valid when single port is false. - 1: trigger and data are merged in serial port" +############################################ +######### In-Pixel Status Registers ######## +############################################ + +ACC: + doc: "Accumulator of the threshold calibration." address: - - 20 + - 5 + - 6 + mask: + - 0xFF + - 0xFF + pixel: 1 + stat: 1 + +ScanDone: + doc: "Scan done signal of the threshold calibration." + address: + - 1 mask: - 0x1 + pixel: 1 + stat: 1 + +BL: + doc: "Baseline obtained from threshold calibration." + address: + - 2 + - 3 + mask: + - 0xFF + - 0x3 + pixel: 1 + stat: 1 + +NW: + doc: "Noise width from threshold calibration. Expect less than 10." + address: + - 1 + mask: + - 0x1E + pixel: 1 + stat: 1 + +TH: + doc: "10-bit threshold applied to the DAC input." + address: + - 3 + - 4 + mask: + - 0xC0 + - 0xFF + pixel: 1 + stat: 1 + +THState: + doc: "Threshold calibration state machine output." + address: + - 1 + mask: + - 0xE0 + pixel: 1 + stat: 1 + +PixelID: + doc: "Col[3:0], Row[3:0]" + address: + - 0 + mask: + - 0xFF + pixel: 1 + stat: 1 + +############################################ +#### Peripheral Configuration Registers #### +############################################ + +readoutClockDelayPixel: + doc: "Phase delay of pixel readout clock, 780 ps a step." + address: + - 13 + mask: + - 0x1F + pixel: 0 + stat: 0 + default: 0x0 + +readoutClockWidthPixel: + doc: "Positive pulse width of pixel clock, 780 ps a step." + address: + - 14 + mask: + - 0x1F + pixel: 0 + stat: 0 + default: 0x20 + +readoutClockDelayGlobal: + doc: "Phase delay of global readout clock, 780 ps a step." + address: + - 15 + mask: + - 0x1F pixel: 0 stat: 0 default: 0x0 + +readoutClockWidthGlobal: + doc: "Positive pulse width of global readout clock, 780 ps a step." + address: + - 16 + mask: + - 0x1F + pixel: 0 + stat: 0 + default: 0x20 + +serRateRight: + doc: |- + Data rate selection of the right data port. + 2'b00: 320 Mbps; + 2'b01: 640 Mbps; + 2'b10: 1280 Mbps. + address: + - 19 + mask: + - 0x30 + pixel: 0 + stat: 0 + default: 0x1 + +serRateLeft: + doc: |- + Data rate selection of the left data port. + 2'b00: 320 Mbps; + 2'b01: 640 Mbps; + 2'b10: 1280 Mbps. + address: + - 19 + mask: + - 0xC + pixel: 0 + stat: 0 + default: 0x1 + +linkResetTestPattern: + doc: |- + Link reset test pattern selection. + 1'b0: PRBS; + 1'b1: Fixed pattern. + address: + - 19 + mask: + - 0x2 + pixel: 0 + stat: 0 + default: 0x1 + +linkResetFixedPattern: + doc: "User-specified pattern to be sent during link reset, LSB first." + address: + - 26 + - 27 + - 28 + - 29 + mask: + - 0xFF + - 0xFF + - 0xFF + - 0xFF + pixel: 0 + stat: 0 + default: 0xACC78CC5 + +emptySlotBCID: + doc: "Empty BCID slot for synchronization." + address: + - 11 + - 12 + mask: + - 0xF0 + - 0xFF + pixel: 0 + stat: 0 + default: 0x7 + +triggerGranularity: + doc: |- + The trigger data size varies from 0, 1, 2, 4, 8, 16. + 0/6/7: trigger data size is 0. + 1: trigger data size is 1. + 2: trigger data size is 2. + 3: trigger data size is 4. + 4: trigger data size is 8. + 5: trigger data size is 16. + address: + - 20 + mask: + - 0xE + pixel: 0 + stat: 0 + default: 0x0 + +disScrambler: + doc: |- + Disable scrambler. + 0: enable scrambler + 1: disable scrambler + address: + - 19 + mask: + - 0x1 + pixel: 0 + stat: 0 + default: 0x1 + +mergeTriggerData: + doc: |- + Merge trigger and data in a port + 0: trigger and data in separate port, only valid when single port is false. + 1: trigger and data are merged in serial port + address: + - 20 + mask: + - 0x1 + pixel: 0 + stat: 0 + default: 0x0 + +singlePort: + doc: |- + Enable single port or both ports. + 0: use both left and right serial ports. + 1: use right serial port only + address: + - 19 + mask: + - 0x40 + pixel: 0 + stat: 0 + default: 0x1 + +onChipL1AConf: + doc: |- + On-chip L1A mode + 2'b0x: on-chip L1A disable; + 2'b10: periodic L1A; + 2'b11: random L1A. + address: + - 18 + mask: + - 0x60 + pixel: 0 + stat: 0 + default: 0x0 + +BCIDoffset: + doc: "BCID when BCID is reset" + address: + - 10 + - 11 + mask: + - 0xFF + - 0xF + pixel: 0 + stat: 0 + default: 0x0 + +fcSelfAlignEn: + doc: |- + Fast command decoder self-alignment mode enable. + 1: self-alignment mode enabled; + 0: manual alignment mode enabled. + address: + - 18 + mask: + - 0x4 + pixel: 0 + stat: 0 + default: 0x0 + +fcClkDelayEn: + doc: "Enable clock delay in fast command manual alignment mode" + address: + - 18 + mask: + - 0x8 + pixel: 0 + stat: 0 + default: 0x0 + +fcDataDelayEn: + doc: "Enable data delay in fast command manual alignment mode, active high." + address: + - 18 + mask: + - 0x10 + pixel: 0 + stat: 0 + default: 0x0 + +chargeInjectionDelay: + doc: |- + The charge injection delay to the 40 MHz clock rising + edge. Start from the rising edge of 40 MHz clock, + each step 781 ps. The pulse width is fixed of 50 ns. + address: + - 17 + mask: + - 0x1F + pixel: 0 + stat: 0 + default: 0x18 + +RefStrSel: + doc: "TDC reference strobe selection." + address: + - 6 + mask: + - 0xFF + pixel: 0 + stat: 0 + default: 0x3 + +PLL_BIASGEN_CONFIG: + doc: "Charge pump bias current selection, [0:8:120] uA. Debugging use only." # Potential name mismatch of registers between page 55 and page 60 of Users manual + address: + - 1 + mask: + - 0xF + pixel: 0 + stat: 0 + default: 0x8 + +PLL_CONFIG_I_PLL: + doc: "Bias current selection of the I-filter unit cell in PLL mode [0:1.1:8] uA. Debugging use only." + address: + - 1 + mask: + - 0xF0 + pixel: 0 + stat: 0 + default: 0x9 + +PLL_CONFIG_P_PLL: + doc: "Bias current selection of the P-filter unit cell in PLL mode [0:5.46:82] uA. Debugging use only." + address: + - 2 + mask: + - 0xF + pixel: 0 + stat: 0 + default: 0x9 + +PLL_R_CONFIG: + doc: "Resistor selection of the P-path in PLL mode [R=1/2*79.8k/CONFIG] Ohm. Debugging use only." # Potential name mismatch of registers between page 55 and page 60 of Users manual + address: + - 2 + mask: + - 0xF0 + pixel: 0 + stat: 0 + default: 0x2 + +PLL_vcoDAC: + doc: "Bias current selection of the VCO core [0:0.470:7.1] mA. Debugging use only." + address: + - 3 + mask: + - 0xF + pixel: 0 + stat: 0 + default: 0x8 + +PLL_vcoRailMode: + doc: |- + Output rail-to-rail mode selection of the VCO, active low. + 1'b0: rail-to-rail output. + 1'b1: CML output. + Debugging use only. + address: + - 3 + mask: + - 0x10 + pixel: 0 + stat: 0 + default: 0x1 + +PLL_ENABLEPLL: + doc: "Enable PLL mode, active high. Debugging use only." + address: + - 3 + mask: + - 0x20 + pixel: 0 + stat: 0 + default: 0x0 + +PLL_FBDiv_skip: + doc: |- + Adjusting the phase of the output clk1G28 of freqPrescaler + in the feedback divider (N=64) by one skip from low to high. + Debugging use only. + address: + - 0 + mask: + - 0x80 + pixel: 0 + stat: 0 + default: 0x0 + +PLL_FBDiv_clkTreeDisable: + doc: |- + Disable the feedback divider, active high. + 1'b0: all output clocks with different frequencies (40MHz - 2.56GHz) are enabled. + 1'b1: The input clk2G56 from the prescaler and all output clocks are disabled. + Debugging use only. + address: + - 0 + mask: + - 0x40 + pixel: 0 + stat: 0 + default: 0x0 + +PLLclkgen_disSER: + doc: |- # Potential name mismatch of registers between page 56 and page 60 of Users manual + Disable output clocks for serializer, active high. + When PLLclkgen_disSER is high, the following clocks are disabled: + clk2g56S, clk2g56SN, clk5g12S, clk5g12SN. + Debuggin use only. + address: + - 0 + mask: + - 0x8 + pixel: 0 + stat: 0 + default: 0x1 + +PLLclkgen_disVCO: + doc: |- # Potential name mismatch of registers between page 56 and page 60 of Users manual + Disable VCO output buffer (associated with clk5g12lshp, clk5g12lshn), active high. + clk5g12lsh is the output clock of the first input buffer in prescaler, and the source + clock for all output clocks. Once disabled, all output clocks are disabled. + Debugging use only. + address: + - 0 + mask: + - 0x10 + pixel: 0 + stat: 0 + default: 0x0 + +PLLclkgen_disEOM: + doc: |- # Potential name mismatch of registers between page 56 and page 60 of Users manual + Disable output clocks for EOM, active high. When PLLclkgen_disEOM is high, the following + clocks are disabled: clk5g12EOMp, clk5g12EOMn. + Debugging use only. + address: + - 0 + mask: + - 0x4 + pixel: 0 + stat: 0 + default: 0x1 + +PLLclkgen_disCLK: + doc: |- # Potential name mismatch of registers between page 56 and page 60 of Users manual + Disable the internal clock buffers and 1/2 clock divider in prescaler, active high. When + PLLclkgen_disCLK is high, all output clocks are disabled. + Debugging use only. + address: + - 0 + mask: + - 0x1 + pixel: 0 + stat: 0 + default: 0x0 + +PLLclkgen_disDES: + doc: |- # Potential name mismatch of registers between page 56 and page 60 of Users manual + Disable output clocks for deserializer, active high. When PLLclkgen_disDES is high, the + following clocks are disabled: clk2g56Qp, clk2g56Qn, clk2g56lp, clk2g56ln. clk2g56Q is + the 2.56 GHz clock for test in ETROC_PLL. clk2g56Q is used as WS clock in ETROC2. + Debugging use only. + address: + - 0 + mask: + - 0x2 + pixel: 0 + stat: 0 + default: 0x0 + +CLKSel: + doc: |- + Selecting PLL clock or off-chip clock for TDC and readout. + 1'b0: using off-chip clocks for TDC and readout; + 1'b1: using PLL clocks for TDC and readout. + Debugging use only. + address: + - 0 + mask: + - 0x20 + pixel: 0 + stat: 0 + default: 0x1 + +PS_CPCurrent: + doc: "Charge pump current control bits, range from 0 to 15uA for charge and discharge. Debugging use only." + address: + - 4 + mask: + - 0xF + pixel: 0 + stat: 0 + default: 0x1 + +PS_CapRst: + doc: "Reset the control voltage of DLL to power supply, active high. Debugging use only." + address: + - 4 + mask: + - 0x10 + pixel: 0 + stat: 0 + default: 0x0 + +PS_Enable: + doc: "Enabling DLL, active high. Debugging use only." + address: + - 4 + mask: + - 0x20 + pixel: 0 + stat: 0 + default: 0x1 + +PS_ForceDown: + doc: "Force to pull down the output of the phase detector, active high. Debugging use only." + address: + - 4 + mask: + - 0x40 + pixel: 0 + stat: 0 + default: 0x0 + +PS_PhaseAdj: + doc: "Phase selecting control bits, PS_PhaseAdj[7:3] for coarse, PS_PhaseAdj[2:0] for fine." + address: + - 5 + mask: + - 0xFF + pixel: 0 + stat: 0 + default: 0x0 + +CLK40_EnRx: + doc: "Enable the Rx for the 40 MHz reference clock, active high. Debugging use only." + address: + - 7 + mask: + - 0x1 + pixel: 0 + stat: 0 + default: 0x1 + +CLK40_EnTer: + doc: "Enable internal termination of the Rx for the 40 MHz reference clock, active high. Debugging use only." + address: + - 7 + mask: + - 0x2 + pixel: 0 + stat: 0 + default: 0x1 + +CLK40_Equ: + doc: |- + Equalization strength of the Rx for the 40 MHz reference clock. + 2'b00: equalization is turned off; + 2'b11: maximal equalization. + Debugging use only. + address: + - 7 + mask: + - 0xC + pixel: 0 + stat: 0 + default: 0x0 + +CLK40_InvData: + doc: "Inverting data of the Rx for the 40 MHz reference clock, active high. Debugging use only." + address: + - 7 + mask: + - 0x10 + pixel: 0 + stat: 0 + default: 0x0 + +CLK40_SetCM: + doc: "Set common voltage of the Rx for the 40 MHz reference clock to 1/2 vdd, active high. Debugging use only." + address: + - 7 + mask: + - 0x20 + pixel: 0 + stat: 0 + default: 0x1 + +CLK1280_EnRx: + doc: "Enable the Rx for the 1.28 GHz clock, active high. Debugging use only." + address: + - 8 + mask: + - 0x1 + pixel: 0 + stat: 0 + default: 0x1 + +CLK1280_EnTer: + doc: "Enable the internal termination of the Rx for the 1.28 GHz clock, active high. Debugging use only." + address: + - 8 + mask: + - 0x2 + pixel: 0 + stat: 0 + default: 0x1 + +CLK1280_Equ: + doc: |- + Equalization strength of the Rx for the 1.28 GHz clock. + 2'b00: equalization is turned off; + 2'b11: maximal equalization. + Debugging use only. + address: + - 8 + mask: + - 0xC + pixel: 0 + stat: 0 + default: 0x0 + +CLK1280_InvData: + doc: "Inverting data of the Rx for the 1.28 GHz clock, active high. Debugging use only." + address: + - 8 + mask: + - 0x10 + pixel: 0 + stat: 0 + default: 0x0 + +CLK1280_SetCM: + doc: "Set common voltage of the Rx for the 1.28 GHz clock to 1/2 vdd, active high. Debugging use only." + address: + - 8 + mask: + - 0x20 + pixel: 0 + stat: 0 + default: 0x1 + +FC_EnRx: + doc: "Enable the Rx for the fast command, active high. Debugging use only." + address: + - 9 + mask: + - 0x1 + pixel: 0 + stat: 0 + default: 0x1 + +FC_EnTer: + doc: "Enable internal termination of the Rx for the fast command, active high. Debugging use only." + address: + - 9 + mask: + - 0x2 + pixel: 0 + stat: 0 + default: 0x1 + +FC_Equ: + doc: |- + Equalization strength of the Rx for the fast command. + 2'b00: equalization is turned off; + 2'b11: maximal equalization. + Debugging use only. + address: + - 9 + mask: + - 0xC + pixel: 0 + stat: 0 + default: 0x0 + +FC_InvData: + doc: "Inverting data of the Rx for the fast command, active high. Debugging use only." + address: + - 9 + mask: + - 0x10 + pixel: 0 + stat: 0 + default: 0x0 + +FC_SetCM: + doc: "Set common voltage of the Rx for the fast command to 1/2 vdd, active high. Debugging use only." + address: + - 9 + mask: + - 0x20 + pixel: 0 + stat: 0 + default: 0x1 + +disPowerSequence: + doc: "Disabling the power up sequence, active high." + address: + - 18 + mask: + - 0x1 + pixel: 0 + stat: 0 + default: 0x1 + +softBoot: + doc: "Reset power sequencer controller, active high." + address: + - 18 + mask: + - 0x2 + pixel: 0 + stat: 0 + default: 0x0 + +EFuse_TCKHP: + doc: |- + The register controlling the SCLK pulse width, ranging ranges from 3 us to 10 us with step of 0.5 us. + The default value is 4 corresponding to 5 us pulse width. + Debugging use only. + address: + - 20 + mask: + - 0xF0 + pixel: 0 + stat: 0 + default: 0x4 + +EFuse_EnClk: + doc: |- + EFuse clock enable. + 1'b1: enabling the clock of the EFuse controller; + 1'b0: disabling the clock of the EFuse controller. + address: + - 21 + mask: + - 0x1 + pixel: 0 + stat: 0 + default: 0x0 + +EFuse_Mode: + doc: |- + Operation mode of EFuse. + 2'b01: programming mode; + 2'b10: reading mode. + address: + - 21 + mask: + - 0x6 + pixel: 0 + stat: 0 + default: 0x2 + +EFuse_Rstn: + doc: "Reset signal of the EFuse controller, active low." + address: + - 21 + mask: + - 0x8 + pixel: 0 + stat: 0 + default: 0x0 + +EFuse_Start: + doc: "Start signal of the EFuse programming. A positive pulse will start the programming." + address: + - 21 + mask: + - 0x10 + pixel: 0 + stat: 0 + default: 0x0 + +EFuse_Prog: + doc: "Data to be written into EFuse." + address: + - 22 + - 23 + - 24 + - 25 + mask: + - 0xFF + - 0xFF + - 0xFF + - 0xFF + pixel: 0 + stat: 0 + default: 0x0 + +EFuse_Bypass: + doc: |- + Bypass EFuse. + 1'b0: EFuse output Q[31:0] is output; + 1'b1: EFuse raw data from I2C (EFuse_Prog[31:0]) is output. + address: + - 21 + mask: + - 0x20 + pixel: 0 + stat: 0 + default: 0x1 + +IfLockThrCounter: + doc: "If the number of instantLock is true for 2^IfLockThrCounter in a row, the PLL is locked in the initial status." + address: + - 30 + mask: + - 0xF + pixel: 0 + stat: 0 + default: 0xB + +IfReLockThrCounter: + doc: "If the number of instantLock is true for 2^IfReLockThrCounter in a row, the PLL is relocked before the unlock status is confirmed." + address: + - 30 + mask: + - 0xF0 + pixel: 0 + stat: 0 + default: 0xB + +IfUnLockThrCounter: + doc: "If the number of instantLock is false for 2^IfUnLockThrCounter in a row, the PLL is unlocked." + address: + - 31 + mask: + - 0xF + pixel: 0 + stat: 0 + default: 0xB + +asyAlignFastcommand: + doc: |- + The fast command bit clock alignment command is issued by I2C. + Used in self-alignment only. + Initializing the clock phase alignment process at its rising edge (synchronized by the 40 MHz PLL clock) + address: + - 13 + mask: + - 0x20 + pixel: 0 + stat: 0 + default: 0x0 + +asyLinkReset: + doc: "Link reset signal from I2C, active high. If it is high, ETROC2 sends test pattern via link." + address: + - 13 + mask: + - 0x40 + pixel: 0 + stat: 0 + default: 0x0 + +asyPLLReset: + doc: "Reset PLL AFC from I2C, active low." + address: + - 13 + mask: + - 0x80 + pixel: 0 + stat: 0 + default: 0x1 + +asyResetChargeInj: + doc: "Reset charge injection module, active low." + address: + - 14 + mask: + - 0x20 + pixel: 0 + stat: 0 + default: 0x1 + +asyResetFastcommand: + doc: "Reset fastcommand from I2C, active low." + address: + - 14 + mask: + - 0x40 + pixel: 0 + stat: 0 + default: 0x1 + +asyResetGlobalReadout: + doc: "Reset globalReadout module, active low." + address: + - 14 + mask: + - 0x80 + pixel: 0 + stat: 0 + default: 0x1 + +asyResetLockDetect: + doc: "Reset lock detect, active low (original lockDetect reset is active high, polarity changed)" + address: + - 15 + mask: + - 0x20 + pixel: 0 + stat: 0 + default: 0x1 + +asyStartCalibration: + doc: "Start PLL calibration process, active high." + address: + - 15 + mask: + - 0x40 + pixel: 0 + stat: 0 + default: 0x1 + +VRefGen_PD: + doc: |- + Power down voltage reference generator, active high. + 1'b1: the voltage reference generator is down. + 1'b0: the voltage reference generator is up. + address: + - 3 + mask: + - 0x80 + pixel: 0 + stat: 0 + default: 0x0 + +TS_PD: + doc: |- + Power down the temperature sensor, active high. + 1'b1: the temperature sensor is down; + 1'b0: the temperature sensor is up. + address: + - 4 + mask: + - 0x80 + pixel: 0 + stat: 0 + default: 0x0 + +TDCClockTest: + doc: |- + The TDC clock testing enable. + 1'b1: sending TDC clock at the left serial port; + 1'b0: sending left serializer data at the left port. + address: + - 31 + mask: + - 0x10 + pixel: 0 + stat: 0 + default: 0x0 + +TDCStrobeTest: + doc: |- + The TDC reference strobe testing enable. + 1'b1: sending TDC reference strobe at the right serial port; + 1'b0: sending right serializer data at the right port. + address: + - 31 + mask: + - 0x20 + pixel: 0 + stat: 0 + default: 0x0 + +LTx_AmplSel: + doc: |- + Left Tx amplitude selection. + 3'b000: min amplitude (50 mV) + 3'b111: max amplitude (320 mV) + Step size is about 40 mV. + address: + - 16 + mask: + - 0xE0 + pixel: 0 + stat: 0 + default: 0x4 + +RTx_AmplSel: + doc: |- + Right Tx amplitude selection. + 3'b000: min amplitude (50 mV) + 3'b111: max amplitude (320 mV) + Step size is about 40 mV. + address: + - 17 + mask: + - 0xE0 + pixel: 0 + stat: 0 + default: 0x4 + +disLTx: + doc: "Left Tx disable, active high." + address: + - 18 + mask: + - 0x80 + pixel: 0 + stat: 0 + default: 0x0 + +disRTx: + doc: "Right Tx disable, active high." + address: + - 19 + mask: + - 0x80 + pixel: 0 + stat: 0 + default: 0x0 + +GRO_TOARST_N: + doc: "GRO TOA reset, active low." + address: + - 7 + mask: + - 0x80 + pixel: 0 + stat: 0 + default: 0x1 + +GRO_Start: + doc: "GRO Start, active high." + address: + - 7 + mask: + - 0x40 + pixel: 0 + stat: 0 + default: 0x0 + +GRO_TOA_Latch: + doc: "GRO TOA latch clock." + address: + - 8 + mask: + - 0x80 + pixel: 0 + stat: 0 + default: 0x1 + +GRO_TOA_CK: + doc: "GRO TOA clock." + address: + - 8 + mask: + - 0x40 + pixel: 0 + stat: 0 + default: 0x1 + +GRO_TOT_CK: + doc: "GRO TOT clock." # Potential name mismatch of registers between page 58 and page 60 of Users manual + address: + - 9 + mask: + - 0x80 + pixel: 0 + stat: 0 + default: 0x1 + +GRO_TOTRST_N: + doc: "GRO TOT reset, active low." + address: + - 9 + mask: + - 0x40 + pixel: 0 + stat: 0 + default: 0x1 + +############################################ +######## Peripheral Status Registers ####### +############################################ + +fcBitAlignError: + doc: "Bit alignment error" + address: + - 2 + mask: + - 0x1 + pixel: 0 + stat: 1 + +PS_Late: + doc: "Phase shifter late" + address: + - 0 + mask: + - 0x80 + pixel: 0 + stat: 1 + +AFCcalCap: + doc: "AFC capacitance" + address: + - 0 + mask: + - 0x7E + pixel: 0 + stat: 1 + +AFCBusy: + doc: "AFC busy, 1: AFC is ongoing, 0: AFC is done" + address: + - 0 + mask: + - 0x1 + pixel: 0 + stat: 1 + +fcAlignFinalState: + doc: "Fast command alignment FSM state" + address: + - 1 + mask: + - 0xF0 + pixel: 0 + stat: 1 + +controllerState: + doc: "Global control FSM state" + address: + - 1 + mask: + - 0xF + pixel: 0 + stat: 1 + +fcAlignStatus: + doc: "Fast command self-alignment error indicator, ed[3:0] in figure 53" + address: + - 2 + mask: + - 0xF0 + pixel: 0 + stat: 1 + +invalidFCCount: + doc: "Count of invalid fast command received" + address: + - 3 + - 4 + mask: + - 0xFF + - 0xF + pixel: 0 + stat: 1 + +pllUnlockCount: + doc: "Count of PLL unlock detected" + address: + - 4 + - 5 + mask: + - 0xF0 + - 0xFF + pixel: 0 + stat: 1 + +EFuseQ: + doc: "32-bit EFuse output" + address: + - 6 + - 7 + - 8 + - 9 + mask: + - 0xFF + - 0xFF + - 0xFF + - 0xFF + pixel: 0 + stat: 1 diff --git a/tamalero/ETROC.py b/tamalero/ETROC.py index 7495c88da44284d3ad0d80fa2dd92dee97cfa2a3..784e888517a52be86d847d98603821671b7ebe51 100644 --- a/tamalero/ETROC.py +++ b/tamalero/ETROC.py @@ -218,7 +218,9 @@ class ETROC(): self.wr_reg('mergeTriggerData', 0) self.wr_reg('disScrambler', 1) + # *********************** # *** IN-PIXEL CONFIG *** + # *********************** # (FOR ALL PIXELS) set/get load capacitance of preamp first stage # 0, 80, 80, or 160 fC FIXME typo? 80 appears twice in doc @@ -280,59 +282,68 @@ class ETROC(): self.wr_reg('PD_DACDiscri', 1, row=row, col=col) # (FOR ALL PIXELS) set/get injected charge - # 1 ~ 36 fC, typical charge is 7fC - def set_Qinj(self, C): + # 1 ~ 32 fC, typical charge is 7fC + def set_Qinj(self, C, row=0, col=0, broadcast=True): if C > 32: raise Exception('Injected charge should be < 32 fC.') - self.wr_reg('QSel', 0, C-1) + self.wr_reg('QSel', C-1, row=row, col=col, broadcast=broadcast) - def get_Qinj(self): - return self.rd_reg('QSel', 0)+1 + def get_Qinj(self, row=0, col=0): + return self.rd_reg('QSel', row=row, col=col) - # enable/disable charge injection - def enable_Qinj(self, pix): - self.wr_reg('QInjEn', pix, 1) + # (FOR ALL PIXELS) enable/disable charge injection + def enable_Qinj(self, row=0, col=0, broadcast=True): + self.wr_reg('QInjEn', 1, row=row, col=col, broadcast=broadcast) - def disable_Qinj(self, pix): - self.wr_reg('QInjEn', pix, 0) + def disable_Qinj(self, row=0, col=0, broadcast=True): + self.wr_reg('QInjEn', 0, row=row, col=col, broadcast=broadcast) - # TDC control - def autoReset_TDC(self, pix): - self.wr_reg('autoReset_TDC', pix, 1) + # (FOR ALL PIXELS) TDC control + # TDC automatically reset controller for every clock period + def autoReset_TDC(self, row=0, col=0, broadcast=True): + self.wr_reg('autoReset_TDC', 1, row=row, col=col, broadcast=broadcast) - def enable_TDC(self, pix): - self.wr_reg('enable_TDC', pix, 1) + # enable/disable TDC conversion + def enable_TDC(self, row=0, col=0, broadcast=True): + self.wr_reg('enable_TDC', 1, row=row, col=col, broadcast=broadcast) - def disable_TDC(self, pix): - self.wr_reg('enable_TDC', pix, 0) + def disable_TDC(self, row=0, col=0, broadcast=True): + self.wr_reg('enable_TDC', 0, row=row, col=col, broadcast=broadcast) - def set_level_TDC(self, pix, w): + # Bit width of bubble tolerant in TDC encode + def set_level_TDC(self, w, row=0, col=0, broadcast=True): if w > 0b011: raise Exception('bit width can be up to 0b011.') - self.wr_reg('level_TDC', pix, w) + self.wr_reg('level_TDC', w, row=row, col=col, broadcast=broadcast) - def get_level_TDC(self, pix): - return self.rd_reg('level_TDC', pix) + def get_level_TDC(self, row=0, col=0): + return self.rd_reg('level_TDC', row=row, col=col) - def reset_TDC(self, pix): - self.wr_reg('resetn_TDC', pix, 1) #FIXME reg name has typo in doc? + # Reset TDC encoder, active low + def reset_TDC(self, row=0, col=0, broadcast=True): + self.wr_reg('resetn_TDC', 0, row=row, col=col, broadcast=broadcast) #FIXME reg name has typo in doc? - def enable_TDC_testMode(self, pix): - self.wr_reg('testMode_TDC', pix, 1) + # enable/disable test mode where TDC generates a fixed test pulse as input signal for test for every 25 ns + def enable_TDC_testMode(self, row=0, col=0, broadcast=True): + self.wr_reg('testMode_TDC', 1, row=row, col=col, broadcast=broadcast) - def disable_TDC_testMode(self, pix): - self.wr_reg('testMode_TDC', pix, 0) + def disable_TDC_testMode(self, row=0, col=0, broadcast=True): + self.wr_reg('testMode_TDC', 0, row=row, col=col, broadcast=broadcast) - # threshold callibration - def bypass_THCal(self, pix): - self.wr_reg('Bypass_THCal', pix, 1) + # (FOR ALL PIXELS) THCal control + # Bypass/apply in-pixel threshold calibration block + def bypass_THCal(self, row=0, col=0, broadcast=True): + self.wr_reg('Bypass_THCal', 1, row=row, col=col, broadcast=broadcast) - def apply_THCal(self, pix): - self.wr_reg('Bypass_THCal', pix, 0) - - def set_Vth_pix(self, pix, vth): - self.wr_reg('DAC', vth, pix) + def apply_THCal(self, row=0, col=0, broadcast=True): + self.wr_reg('Bypass_THCal', 0, row=row, col=col, broadcast=broadcast) + # When Bypass_THCal = 1, TH = DAC +# def set_Vth_pix(self, vth, row=0, col=0, broadcast=True): +# self.wr_reg('DAC', vth, row=row, col=col, broadcast=broadcast) +# +# def get_Vth_pix(self, row=0, col=0): +# return self.rd_reg('DAC', row=row, col=col) def set_Vth_mV(self, vth, row=0, col=0, broadcast=True): # FIXME this needs to be understood # Pretend that we set the threshold and then the "DAC" register @@ -358,122 +369,897 @@ class ETROC(): th = self.rd_reg('DAC', row=row, col=col) return offset*offset_step + th*th_step - def set_THoffset(self, pix, V): - self.wr_reg('TH_offset', pix, V) + # Threshold offset for calibrated baseline. TH = BL + TH_offset +# def set_THoffset(self, V, row=0, col=0, broadcast=True): +# self.wr_reg('TH_offset', V, row=row, col=col, broadcast=broadcast) +# +# def get_THoffset(self, row=0, col=0): +# return self.rd_reg('TH_offset', row=row, col=col) - def reset_THCal(self, pix): - self.wr_reg('RSTn_THCal', pix, 1) + # Reset of threshold calibration block, active low + def reset_THCal(self, row=0, col=0, broadcast=True): + self.wr_reg('RSTn_THCal', 0, row=row, col=col, broadcast=broadcast) - def init_THCal(self, pix): #FIXME better name? - self.wr_reg('ScanStart_THCal', pix, 1) + # Initialize threshold calibration + def init_THCal(self, row=0, col=0, broadcast=True): #FIXME better name? + self.wr_reg('ScanStart_THCal', 1, row=row, col=col, broadcast=broadcast) - def enable_THCal_buffer(self, pix): - self.wr_reg('BufEn_THCal', pix, 1) + # Enable/disable threshold calibration buffer + def enable_THCal_buffer(self, row=0, col=0, broadcast=True): + self.wr_reg('BufEn_THCal', 1, row=row, col=col, broadcast=broadcast) - def disable_THCal_buffer(self, pix): - self.wr_reg('BufEn_THCal', pix, 0) + def disable_THCal_buffer(self, row=0, col=0, broadcast=True): + self.wr_reg('BufEn_THCal', 0, row=row, col=col, broadcast=broadcast) - def enable_THCal_clock(self, pix): - self.wr_reg('CLKEn_THCal', pix, 1) + # Enable/disable threshold calibration clock. Only used when threshold calibration clock is bypassed. + def enable_THCal_clock(self, row=0, col=0, broadcast=True): + self.wr_reg('CLKEn_THCal', 1, row=row, col=col, broadcast=broadcast) - def disable_THCal_clock(self, pix): - self.wr_reg('CLKEn_THCal', pix, 0) + def disable_THCal_clock(self, row=0, col=0, broadcast=True): + self.wr_reg('CLKEn_THCal', 0, row=row, col=col, broadcast=broadcast) - def set_workMode(self, pix, mode): + # (FOR ALL PIXELS) Readout control + # Readout work mode selection + def set_workMode(self, mode, row=0, col=0, broadcast=True): val = {'normal': 0b00, 'self test fixed': 0b01, 'self test random': 0b10} try: - self.wr_reg('workMode', pix, val(mode)) + self.wr_reg('workMode', val(mode), row=row, col=col, broadcast=broadcast) except KeyError: print('Choose between \'normal\', \'self test fixed\', \'self test random\'.') - def get_workMode(self, pix): + def get_workMode(self, row=0, col=0): val = {0b00:'normal', 0b01:'self test fixed', 0b10:'self test random'} - return val[self.wr_reg('workMod', pix)] + return val[self.wr_reg('workMode', row=row, col=col)] - def set_L1Adelay(self, pix, delay): - self.wr_reg('L1Adelay', pix, delay) + # L1A latency + def set_L1Adelay(self, delay, row=0, col=0, broadcast=True): + self.wr_reg('L1Adelay', delay, row=row, col=col, broadcast=broadcast) - def get_L1Adelay(self, pix): - return self.rd_reg('L1Adelay', pix) + def get_L1Adelay(self, row=0, col=0): + return self.rd_reg('L1Adelay', row=row, col=col) - def enable_data_readout(self, pix): - self.wr_reg('disDataReadout', pix, 0) + # Enable/disable TDC data readout of current pixel + def enable_data_readout(self, row=0, col=0, broadcast=True): + self.wr_reg('disDataReadout', 0, row=row, col=col, broadcast=broadcast) - def disable_data_readout(self, pix): - self.wr_reg('disDataReadout', pix, 1) + def disable_data_readout(self, row=0, col=0, broadcast=True): + self.wr_reg('disDataReadout', 1, row=row, col=col, broadcast=broadcast) - def enable_trigger_readout(self, pix): - self.wr_reg('disTrigPath', pix, 0) + # Enable/disable trigger readout of current pixel + def enable_trigger_readout(self, row=0, col=0, broadcast=True): + self.wr_reg('disTrigPath', 0, row=row, col=col, broadcast=broadcast) - def disable_trigger_readout(self, pix): - self.wr_reg('disTrigPath', pix, 1) + def disable_trigger_readout(self, row=0, col=0, broadcast=True): + self.wr_reg('disTrigPath', 1, row=row, col=col, broadcast=broadcast) - def set_trigger_TH(self, pix, datatype, upper=None, lower=None): + # Set upper/lower thresholds for trigger readout of TOA, TOT, Cal + def set_trigger_TH(self, datatype, upper=None, lower=None, row=0, col=0, broadcast=True): if datatype not in ['TOA', 'TOT', 'Cal']: raise Exception('type of data should be TOA, TOT or CAL.') if upper is not None: - self.wr_reg('upper'+data+'Trig', pix, upper) + self.wr_reg('upper'+data+'Trig', upper, row=row, col=col, broadcast=broadcast) if lower is not None: - self.wr_reg('lower'+data+'Trig', pix, lower) + self.wr_reg('lower'+data+'Trig', lower, row=row, col=col, broadcast=broadcast) - def get_trigger_TH(self, pix, datatype): + def get_trigger_TH(self, datatype, row=0, col=0): if datatype not in ['TOA', 'TOT', 'Cal']: raise Exception('type of data should be TOA, TOT or CAL.') upper = 'upper'+data+'Trig' lower = 'lower'+data+'Trig' - return self.rd_reg(upper, pix), self.rd_reg(lower, pix) + return self.rd_reg(upper, row=row, col=col), self.rd_reg(lower, row=row, col=col) - def set_data_TH(self, pix, datatype, upper=None, lower=None): + # Set upper/lower thresholds for TDC data readout of TOA, TOT, Cal + def set_data_TH(self, datatype, upper=None, lower=None, row=0, col=0, broadcast=True): if datatype not in ['TOA', 'TOT', 'Cal']: raise Exception('type of data should be TOA, TOT or CAL.') if upper is not None: - self.wr_reg('upper'+data, pix, upper) + self.wr_reg('upper'+data, upper, row=row, col=col, broadcast=broadcast) if lower is not None: - self.wr_reg('lower'+data, pix, lower) + self.wr_reg('lower'+data, lower, row=row, col=col, broadcast=broadcast) - def get_data_TH(self, pix, datatype): + def get_data_TH(self, datatype, row=0, col=0): if datatype not in ['TOA', 'TOT', 'Cal']: raise Exception('type of data should be TOA, TOT or CAL.') upper = 'upper'+data lower = 'lower'+data - return self.rd_reg(upper, pix), self.rd_reg(lower, pix) + return self.rd_reg(upper, row=row, col=col), self.rd_reg(lower, row=row, col=col) - def enable_adr_offset(self, pix): - self.wr_reg('addrOffset', pix, 1) + # Enable/disable circular buffer write address offset + def enable_adr_offset(self, row=0, col=0, broadcast=True): + self.wr_reg('addrOffset', 1, row=row, col=col, broadcast=broadcast) - def disable_adr_offset(self, pix): - self.wr_reg('addrOffset', pix, 0) + def disable_adr_offset(self, row=0, col=0, broadcast=True): + self.wr_reg('addrOffset', 0, row=row, col=col, broadcast=broadcast) - def set_selftest_occupancy(self, pix, occ): - self.wr_reg('selfTestOccupancy', pix, occ) + # Self-test data occupancy is selfTestOccupancy[6:0]/128 + def set_selftest_occupancy(self, occ, row=0, col=0, broadcast=True): + self.wr_reg('selfTestOccupancy', occ, row=row, col=col, broadcast=broadcast) - def get_selftest_occupancy(self, pix): - return self.rd_reg('selfTestOccupancy', pix) + def get_selftest_occupancy(self, row=0, col=0): + return self.rd_reg('selfTestOccupancy', row=row, col=col) + # *********************** # *** IN-PIXEL STATUS *** + # *********************** - def get_ACC(self, pix): - return self.rd_reg('ACC', pix) + # (FOR ALL PIXELS) Accumulator of the threshold calibration + def get_ACC(self, row=0, col=0): + return self.rd_reg('ACC', row=row, col=col) - def is_scanDone(self, pix): - result = self.rd_reg('ScanDone', pix) + # (FOR ALL PIXELS) Scan done signal of the threshold calibration + def is_scanDone(self, row=0, col=0): + result = self.rd_reg('ScanDone', row=row, col=col) if result == 1: return True else: return False - def get_baseline(self, pix): - return self.rd_reg('BL', pix) + # (FOR ALL PIXELS) Baseline obtained from threshold calibration + def get_baseline(self, row=0, col=0): + return self.rd_reg('BL', row=row, col=col) + + # (FOR ALL PIXELS) Noise width from threshold calibration. Expect less than 10. + def get_noisewidth(self, row=0, col=0): + return self.rd_reg('NW', row=row, col=col) + + # (FOR ALL PIXELS) 10-bit threshold applied to the DAC input + def get_threshold(self, row=0, col=0): + return self.rd_reg('TH', row=row, col=col) + + # (FOR ALL PIXELS) Threshold calibration state machine output + def get_THstate(self, row=0, col=0): + return self.rd_reg('THstate', row=row, col=col) + + # (FOR ALL PIXELS) Col[3:0], Row[3:0] + def get_pixelID(self, row=0, col=0): + return self.rd_reg('PixelID', row=row, col=col) + + # *********************** + # **** PERIPH CONFIG **** + # *********************** + + # Phase delay of readout clock, 780 ps a step (Pixel or Global) + def set_readoutClkDelay(self, clk, delay): + if clk not in ['Pixel', 'Global']: + raise Exception('Clock should be either Pixel or Global') + self.wr_reg('readoutClockDelay'+clk, delay) + + def get_readoutClkDelay(self, clk): + if clk not in ['Pixel', 'Global']: + raise Exception('Clock should be either Pixel or Global') + return self.rd_reg('readoutClockDelay'+clk) + + # Positive pulse width of readout clock, 780 ps a step (Pixel or Global) + def set_readoutClkWidth(self, clk, width): + if clk not in ['Pixel', 'Global']: + raise Exception('Clock should be either Pixel or Global') + self.wr_reg('readoutClockWidth'+clk, width) + + def get_readoutClkWidth(self, clk): + if clk not in ['Pixel', 'Global']: + raise Exception('Clock should be either Pixel or Global') + return self.rd_reg('readoutClockWidth'+clk) + + # Data rate selection of Right or Left serial port + def set_dataRate(self, port, rate): + if port not in ['Left', 'Right']: + raise Exception('Choose between Left or Right serial port') + val = {320:0b00, 640:0b01, 1280:0b10} + try: + self.wr_reg('serRate'+port, val[rate]) + except KeyError: + print('Choose between rates of 320 Mbps, 640 Mbps and 1280 Mbps') + + def get_dataRate(self, port): + if port not in ['Left', 'Right']: + raise Exception('Choose between Left or Right serial port') + val = {0b00:320, 0b01:640, 0b10:1280} + return val[self.rd_reg('serRate'+port)] + + # Link reset test pattern selection + def set_linkResetTestPattern(self, mode): + val = {'PRBS':0b0, 'Fixed pattern':0b1} + try: + self.wr_reg('linkResetTestPattern', val[mode]) + except KeyError: + print('Choose between \'PRBS\' and \'Fixed pattern\' selections') + + def get_linkResetTestPattern(self): + val = {0b0:'PRBS', 0b1:'Fixed pattern'} + return val[self.rd_reg('linkResetTestPattern')] + + # User-specified pattern to be sent during link reset, LSB first + def set_linkResetFixedPattern(self, pattern): + self.wr_reg('linkResetFixedPattern', pattern) + + def get_linkResetFixedPattern(self): + return self.rd_reg('linkResetFixedPattern') + + # Empty BCID slot for synchronization + def set_BCID(self, bcid): + self.wr_reg('emptySlotBCID', bcid) + + def get_BCID(self): + return self.rd_reg('emptySlotBCID') + + # Trigger data size, can be 0, 1, 2, 4, 8, 16 + def set_triggerGranularity(self, size): + val = {0:0, 1:1, 2:2, 4:3, 8:4, 16:5} + try: + self.wr_reg('triggerGranularity', val[size]) + except KeyError: + print('Trigger data size can only be 0, 1, 2, 4, 8 or 16') + + def get_triggerGranularity(self): + val = {0:0, 1:1, 2:2, 3:4, 4:8, 5:16, 6:0, 7:0} + return val[self.rd_reg('triggerGranularity')] + + # Enable/disable scrambler + def enable_Scrambler(self): + self.wr_reg('disScrambler', 0) + + def disable_Scrambler(self): + self.wr_reg('disScrambler', 1) + + # Merge trigger and data in a port + def set_mergeTriggerData(self, mode): + val = {'separate':0, 'merge':1} + if (self.get_singlePort == 'right') and (mode == 'separate'): + raise Exception('Trigger and data in separate ports is only allowed when singlePort is set to \'both\'') + try: + self.wr_reg('mergeTriggerData', val[mode]) + except KeyError: + print('Choose between \'merge\' and \'separate\' options') + + def get_mergeTriggerData(self): + val = {0: 'separate', 1:'merge'} + return val[self.rd_reg('mergeTriggerData')] + + # Enable single port (right) or both ports + def set_singlePort(self, mode): + val = {'both':0, 'right':1} + try: + self.wr_reg('singlePort', val[mode]) + except KeyError: + print('Choose between \'both\' and \'right\' options') + + def get_singlePort(self): + val = {0:'both', 1:'right'} + return val[self.rd_reg('singlePort')] + + # On-chip L1A mode + def set_l1aMode(self, mode): + val = {'disable':0b00, 'periodic':0b10, 'random':0b11} + try: + self.wr_reg('onChipL1AConf', val[mode]) + except KeyError: + print('Choose between \'disable\', \'periodic\' and \'random\' options') + + def get_l1aMode(self): + val = {0b00:'disable', 0b10:'periodic', 0b11:'random', 0b01:'disable'} + return val[self.rd_reg('onChipL1AConf')] + + # BCID when BCID is reset + def set_BCIDoffset(self, offset): + self.wr_reg('BCIDoffset', offset) + + def get_BCIDoffset(self, offset): + self.rd_reg('BCIDoffset') + + # Fast command decoder self-alignment or manual alignment + def set_fcAlign(self, mode): + val = {'manual':0, 'self':1} + try: + self.wr_reg('fcSelfAlignEn', val[mode]) + except KeyError: + print('Choose between \'manual\' and \'self\' options') + + def get_fcAlign(self): + val = {0:'manual', 1:'self'} + return val[self.rd_reg('fcSelfAlignEn')] + + # Enable/disable clock delay in fast command manual alignment mode + def enable_fcClkDelay(self): + assert self.get_fcAlign() == 'manual' + self.wr_reg('fcClkDelayEn', 1) + + def disable_fcClkDelay(self): + assert self.get_fcAlign() == 'manual' + self.wr_reg('fcClkDelayEn', 0) + + # Enable/disable data delay in fast command manual alignment mode, active high + def enable_fcDataDelay(self): + assert self.get_fcAlign() == 'manual' + self.wr_reg('fcDataDelayEn', 1) + + def disable_fcDataDelay(self): + assert self.get_fcAlign() == 'manual' + self.wr_reg('fcDataDelayEn', 0) + + # The charge injection delay to the 40 MHz clock rising edge. Start from rising edge + # of 40 MHz clock, each step 781 ps. The pulse width is fixed of 50 ns. + def set_chargeInjDelay(self, delay): + self.wr_reg('chargeInjectionDelay', delay) + + def get_chargeInjDelay(self): + return self.rd_reg('chargeInjectionDelay') + + # TDC Reference strobe selection + def set_refStr(self, refStr): + self.wr_reg('RefStrSel', refStr) + + def get_refStr(self): + return self.rd_reg('RefStrSel') + + # Charge pump bias current selection, [0:8:120] uA. Debugging use only. + def set_PLLBiasGen(self, bias): + self.wr_reg('PLL_BIASGEN_CONFIG', bias) + + def get_PLLBiasGen(self): + return self.rd_reg('PLL_BIASGEN_CONFIG') + + # Bias current selection of the I-filter (0:1.1:8 uA) or P-filter (0:5.46:82 uA) unit cell in PLL mod. Debugging use only. + def set_PLLConfig(self, filt, bias): + if filt not in ['I', 'P']: + raise Exception('Choose between \'I\' or \'P\' filter') + self.wr_reg('PLL_CONFIG_'+filt+'_PLL', bias) + + def get_PLLConfig(self, filt): + if filt not in ['I', 'P']: + raise Exception('Choose between \'I\' or \'P\' filter') + return self.rd_reg('PLL_CONFIG_'+filt+'_PLL') + + # Resistor selection of the P-path in PLL mode [R=1/2*79.8k/CONFIG] Ohm. Debugging use only. + def set_PLLRes(self, R): + config = 1 / (2 * 79.8e3) / R + self.wr_reg('PLL_R_CONFIG', config) + + def get_PLLRes(self): + config = self.rd_reg('PLL_R_CONFIG') + R = 1 / (2 * 79.8e3) / config + return R + + # Bias current selection of the VCO core [0:0.470:7.1] mA. Debugging use only. + def set_PLLvco(self, bias): + self.wr_reg('PLL_vcoDAC', bias) + + def get_PLLvco(self): + return self.rd_reg('PLL_vcoDAC') + + # Output rail-to-rail mode selection of the VCO, active low. Debugging use only. + def set_PLLvcoRail(self, mode): + if mode not in ['rail', 'CML']: + raise Exception('Chose between \'rail\' and \'CML\' options') + val = {'rail':0, 'CML':1} + self.wr_reg('PLL_vcoRailMode', val[mode]) + + def get_PLLvcoRail(self): + val = {0:'rail', 'CML':1} + return val[self.rd_reg('PLL_vcoRailMode')] + + # Enable/disable PLL mode, active high. Debugging use only. + def enable_PLL(self): + self.wr_reg('PLL_ENABLEPLL', 1) + + def disable_PLL(self): + self.wr_reg('PLL_ENABLEPLL', 0) + + # Adjusting the phase of the output clk1G28 of freqPrescaler in the feedback + # divider (N=64) by one skip from low to high. Debugging use only. + def set_PLLFBDiv(self, skip): + self.wr_reg('PLL_FBDiv_skip', skip) + + def get_PLLFBDiv(self): + return self.rd_reg('PLL_FBDiv_skip') + + # Enable/disable feedback divider + def enable_PLLFB(self): + self.wr_reg('PLL_FBDiv_clkTreeDisable', 0) + + def disable_PLLFB(self): + self.wr_reg('PLL_FBDiv_clkTreeDisable', 1) + + # Enable/disable output clocks for serializer + def enable_PLLclkSer(self): + self.wr_reg('PLLclkgen_disSER', 0) + + def disable_PLLclkSer(self): + self.wr_reg('PLLclkgen_disSER', 1) + + # Enable/disable VCO output buffer (associated with clk5g12lshp, clk5g12lshn), active high. + # clk5g12lsh is the output clock of the first input buffer in prescaler, and the source + # clock for all output clocks. Once disabled, all output clocks are disabled. Debugging use only. + def enable_PLLvcoBuff(self): + self.wr_reg('PLLclkgen_disVCO', 0) + + def disable_PLLvcoBuff(self): + self.wr_reg('PLLclkgen_disVCO', 1) + + # Enable/disable output clocks for EOM, active high. When PLLclkgen_disEOM is high, the following + # clocks are disabled: clk5g12EOMp, clk5g12EOMn. Debugging use only. + def enable_PLLEOM(self): + self.wr_reg('PLLclkgen_disEOM', 0) + + def disable_PLLEOM(self): + self.wr_reg('PLLclkgen_disEOM', 1) + + # Enable/disable the internal clock buffers and 1/2 clock divider in prescaler, active high. When + # PLLclkgen_disCLK is high, all output clocks are disabled. Debugging use only. + def enable_PLLclk(self): + self.wr_reg('PLLclkgen_disCLK', 0) + + def disable_PLLclk(self): + self.wr_reg('PLLclkgen_disCLK', 1) + + # Enable/disable output clocks for deserializer, active high. When PLLclkgen_disDES is high, the + # following clocks are disabled: clk2g56Qp, clk2g56Qn, clk2g56lp, clk2g56ln. clk2g56Q is + # the 2.56 GHz clock for test in ETROC_PLL. clk2g56Q is used as WS clock in ETROC2. Debugging use only. + def enable_PLLDes(self): + self.wr_reg('PLLclkgen_disDES', 0) + + def disable_PLLDes(self): + self.wr_reg('PLLclkgen_disDES', 1) + + # Selecting PLL clock or off-chip clock for TDC and readout. Debugging use only. + def set_CLKSel(self, clk): + if clk not in ['off-chip', 'PLL']: + raise Exception('Choose between \'off-chip\' and \'PLL\' options') + val = {'off-chip':0, 'PLL':1} + self.wr_reg('CLKSel', val[clk]) + + def get_CLKSel(self): + val = {0:'off-chip', 1:'PLL'} + return val[self.rd_reg('CLKSel')] + + # Charge pump current control bits, range from 0 to 15uA for charge and discharge. Debugging use only. + def set_CPCurrent(self, current): + self.wr_reg('PS_CPCurrent', current) + + def get_CPCurrent(self): + return self.rd_reg('PS_CPCurrent') + + # Reset the control voltage of DLL to power supply, active high. Debugging use only. + def toggle_CapRst(self): + val = ~self.get_CapRst() + self.wr_reg('PS_CapRst', val) + + def get_CapRst(self): + return self.rd_reg('PS_CapRst') + + # Enable/disable DLL, active high. Debugging use only. + def enable_DLL(self): + self.wr_reg('PS_Enable', 1) + + def disable_DLL(self): + self.wr_reg('PS_Enable', 0) + + # Force to pull down the output of the phase detector, active high. Debugging use only. + def set_PSForceDown(self, boolean): + if not isinstance(boolean, bool): + raise TypeError('Argument must be a boolean') + val = 1 if boolean else 0 + self.wr_reg('PS_ForceDown', val) + + def get_PSForceDown(self): + val = self.rd_reg('PS_ForceDown') + return True if val == 1 else False + + # Phase selecting control bits, PS_PhaseAdj[7:3] for coarse, PS_PhaseAdj[2:0] for fine. + def set_PhaseAdj(self, phase): + self.wr_reg('PS_PhaseAdj', phase) + + def get_PhaseAdj(self): + return self.rd_reg('PS_PhaseAdj') + + # Enable/disable the Rx for the 40 MHz, 1.28 GHz reference clock or the fast command, active high. Debugging use only + def set_Rx(self, mode, boolean): + if not isinstance(boolean, bool): + raise TypeError('Argument must be True (enable) or False (disable)') + val = 1 if boolean else 0 + regs = {40:'CLK40_EnRx', 1280:'CLK1280_EnRx', 'FC':'FC_EnRx'} + try: + self.wr_reg(regs[mode], val) + except KeyError: + print('Choose between 40 (40 MHz ref. clock), 1280 (1.28 GHz ref. clock) and \'FC\' (fast command) options') + + def get_Rx(self, mode): + regs = {40:'CLK40_EnRx', 1280:'CLK1280_EnRx', 'FC':'FC_EnRx'} + try: + return self.rd_reg(regs[mode]) + except KeyError: + print('Choose between 40 (40 MHz ref. clock), 1280 (1.28 GHz ref. clock) and \'FC\' (fast command) options') + + # Enable/disable internal termination of the Rx for the 40 MHz, 1.28 GHz reference clock or the fast command, active high. Debugging use only. + def set_Ter(self, mode, boolean): + if not isinstance(boolean, bool): + raise TypeError('Argument must be True (enable) or False (disable)') + val = 1 if boolean else 0 + regs = {40:'CLK40_EnTer', 1280:'CLK1280_EnTer', 'FC':'FC_EnTer'} + try: + self.wr_reg(regs[mode], val) + except KeyError: + print('Choose between 40 (40 MHz ref. clock), 1280 (1.28 GHz ref. clock) and \'FC\' (fast command) options') + + def get_Ter(self, mode): + regs = {40:'CLK40_EnTer', 1280:'CLK1280_EnTer', 'FC':'FC_EnTer'} + try: + return self.rd_reg(regs[mode]) + except KeyError: + print('Choose between 40 (40 MHz ref. clock), 1280 (1.28 GHz ref. clock) and \'FC\' (fast command) options') + + # Equalization strength of the Rx for the 40 MHz, 1.28 GHz reference clock or the fast command. Debugging use only. + # 2'b00: equalization is turned off; 2'b11: maximal equalization. + def set_Equ(self, mode, equalization): + regs = {40:'CLK40_Equ', 1280:'CLK1280_Equ', 'FC':'FC_Equ'} + try: + self.wr_reg(regs[mode], equalization) + except KeyError: + print('Choose between 40 (40 MHz ref. clock), 1280 (1.28 GHz ref. clock) and \'FC\' (fast command) options for \'mode\' arg.') + + def get_Equ(self, mode): + regs = {40:'CLK40_Equ', 1280:'CLK1280_Equ', 'FC':'FC_Equ'} + try: + return self.rd_reg(regs[mode]) + except KeyError: + print('Choose between 40 (40 MHz ref. clock), 1280 (1.28 GHz ref. clock) and \'FC\' (fast command) options') + + # Inverting data of the Rx for the 40 MHz, 1.28 GHz reference clock or the fast command, active high. Debugging use only. + def set_Inv(self, mode, boolean): + if not isinstance(boolean, bool): + raise TypeError('Argument must be True (invert) or False (don\'t invert)') + val = 1 if boolean else 0 + regs = {40:'CLK40_InvData', 1280:'CLK1280_InvData', 'FC':'FC_InvData'} + try: + self.wr_reg(regs[mode], val) + except KeyError: + print('Choose between 40 (40 MHz ref. clock), 1280 (1.28 GHz ref. clock) and \'FC\' (fast command) options') + + def get_Inv(self, mode): + regs = {40:'CLK40_InvData', 1280:'CLK1280_InvData', 'FC':'FC_InvData'} + try: + return self.rd_reg(regs[mode]) + except KeyError: + print('Choose between 40 (40 MHz ref. clock), 1280 (1.28 GHz ref. clock) and \'FC\' (fast command) options') + + # Set common voltage of the Rx for the 40 MHz, 1.28 GHz reference clock or the fast command to 1/2 vdd, active high. Debugging use only. + def set_commonV(self, mode, boolean): + if not isinstance(boolean, bool): + raise TypeError('Argument must be True (set) or False (don\'t set)') + val = 1 if boolean else 0 + regs = {40:'CLK40_SetCM', 1280:'CLK1280_SetCM', 'FC':'FC_SetCM'} + try: + self.wr_reg(regs[mode], val) + except KeyError: + print('Choose between 40 (40 MHz ref. clock), 1280 (1.28 GHz ref. clock) and \'FC\' (fast command) options') + + def get_commonV(self, mode): + regs = {40:'CLK40_SetCM', 1280:'CLK1280_SetCM', 'FC':'FC_SetCM'} + try: + return self.rd_reg(regs[mode]) + except KeyError: + print('Choose between 40 (40 MHz ref. clock), 1280 (1.28 GHz ref. clock) and \'FC\' (fast command) options') + + # Enable/disable the power up sequence, active high + def enable_PowerUp(self): + self.wr_reg('disPowerSequence', 0) + + def disable_PowerUp(self): + self.wr_reg('disPowerSequence', 1) + + # Reset power sequencer controller, active high + def reset_Power(self): + self.wr_reg('softBoot', 1) + + # The register controlling the SCLK pulse width, ranging ranges from 3 us to 10 us with step of 0.5 us. + # The default value is 4 corresponding to 5 us pulse width. Debugging use only. + def set_SCLKWidth(self, width): + self.wr_reg('EFuse_TCKHP', width) + + def get_SCLKWidth(self): + return self.rd_reg('EFuse_TCKHP') + + # Enable/disable EFuse clock + def enable_EFuseClk(self): + self.wr_reg('EFuse_EnClk', 1) + + def disable_EFuseClk(self): + self.wr_reg('EFuse_EnClk', 0) + + # Operation mode of EFuse. + # 2'b01: programming mode; + # 2'b10: reading mode. + def set_EFuseMode(self, mode): + val = {'programming':0b01, 'reading':0b10} + try: + self.wr_reg('EFuse_Mode', val[mode]) + except KeyError: + print('Choose between \'programming\' and \'reading\' options') + + def get_EFuseMode(self): + val = {0b01:'programming', 0b10:'reading'} + return val[self.rd_reg('EFuse_Mode')] + + # Reset signal of the EFuse controller, active low + def reset_EFuse(self): + self.wr_reg('EFuse_Rstn', 0) + + # Start signal of the EFuse programming. A positive pulse will start the programming + def start_EFuse(self): + self.wr_reg('EFuse_Start', 1) + + # Data to be written into EFuse + def set_EFuseDat(self, data): + self.wr_reg('EFuse_Prog', data) + + def get_EFuseDat(self): + return self.rd_reg('EFuse_Prog') + + # Bypass EFuse. + # 1'b0: EFuse output Q[31:0] is output; + # 1'b1: EFuse raw data from I2C (EFuse_Prog[31:0]) is output + def bypass_EFuse(self, bypass): + if not isinstance(bypass, bool): + raise TypeError('Argument must be True (bypass) or False (don\'t bypass)') + val = 1 if bypass else 0 + self.wr_reg('EFuse_Bypass', val) + + # If the number of instantLock is true for 2^IfLockThrCounter in a row, the PLL is locked in the initial status + def set_IfLockThrCounter(self, counter): + self.wr_reg('IfLockThrCounter', counter) + + def get_IfLockThrCounter(self): + return self.rd_reg('IfLockThrCounter') + + # If the number of instantLock is true for 2^IfReLockThrCounter in a row, the PLL is relocked before the unlock status is confirmed + def set_IfReLockThrCounter(self, counter): + self.wr_reg('IfReLockThrCounter', counter) + + def get_IfReLockThrCounter(self): + return self.rd_reg('IfReLockThrCounter') + + # If the number of instantLock is false for 2^IfUnLockThrCounter in a row, the PLL is unlocked + def set_IfUnLockThrCounter(self, counter): + self.wr_reg('IfUnLockThrCounter', counter) + + def get_IfUnLockThrCounter(self): + return self.rd_reg('IfUnLockThrCounter') + + # The fast command bit clock alignment command is issued by I2C. + # Used in self-alignment only. + # Initializing the clock phase alignment process at its rising edge (synchronized by the 40 MHz PLL clock) + def enable_FCClkPhaseAlign(self): + assert self.get_fcAlign() == 'self' + self.wr_reg('asyAlignFastcommand', 1) + + def disable_FCClkPhaseAlign(self): + assert self.get_fcAlign() == 'self' + self.wr_reg('asyAlignFastcommand', 0) + + # Link reset signal from I2C, active high. If it is high, ETROC2 sends test pattern via link + def set_LinkReset(self, reset): + if not isinstance(reset, bool): + raise TypeError('Argument must be True (reset) or False (don\'t reset)') + val = 1 if reset else 0 + self.wr_reg('asyLinkReset', val) + + def get_LinkReset(self): + return self.rd_reg('asyLinkReset') + + # Reset PLL AFC from I2C, active low + def set_PLLReset(self, reset): + if not isinstance(reset, bool): + raise TypeError('Argument must be True (reset) or False (don\'t reset)') + val = 0 if reset else 1 + self.wr_reg('asyPLLReset', val) + + def get_PLLReset(self): + return self.rd_reg('asyPLLReset') + + # Reset charge injection module, active low + def set_ChargeInjReset(self, reset): + if not isinstance(reset, bool): + raise TypeError('Argument must be True (reset) or False (don\'t reset)') + val = 0 if reset else 1 + self.wr_reg('asyResetChargeInj', val) + + def get_ChargeInjReset(self): + return self.rd_reg('asyResetChargeInj') + + # Reset fastcommand from I2C, active low + def set_FCReset(self, reset): + if not isinstance(reset, bool): + raise TypeError('Argument must be True (reset) or False (don\'t reset)') + val = 0 if reset else 1 + self.wr_reg('asyResetFastcommand', val) + + def get_FCReset(self): + return self.rd_reg('asyResetFastcommand') + + # Reset globalReadout module, active low + def set_GlobalReadoutReset(self, reset): + if not isinstance(reset, bool): + raise TypeError('Argument must be True (reset) or False (don\'t reset)') + val = 0 if reset else 1 + self.wr_reg('asyResetGlobalReadout', val) + + def get_GlobalReadoutReset(self): + return self.rd_reg('asyResetGlobalReadout') + + # Reset lock detect, active low (original lockDetect reset is active high, polarity changed) + def set_LockDetectReset(self, reset): + if not isinstance(reset, bool): + raise TypeError('Argument must be True (reset) or False (don\'t reset)') + val = 0 if reset else 1 + self.wr_reg('asyResetLockDetect', val) + + def get_LockDetectReset(self): + return self.rd_reg('asyResetLockDetect') + + # Start PLL calibration process, active high + def start_PLLCal(self): + self.wr_reg('asyStartCalibration', 1) + + def stop_PLLCal(self): + self.wr_reg('asyStartCalibration', 0) + + # Power down voltage reference generator, active high. + # 1'b1: the voltage reference generator is down. + # 1'b0: the voltage reference generator is up. + def power_up_VRef(self): + self.wr_reg('VRefGen_PD', 0) + + def power_down_VRef(self): + self.wr_reg('VRefGen_PD', 1) + + # Power down the temperature sensor, active high. + # 1'b1: the temperature sensor is down; + # 1'b0: the temperature sensor is up. + def power_up_TempSen(self): + self.wr_reg('TS_PD', 0) + + def power_down_TempSen(self): + self.wr_reg('TS_PD', 1) + + # The TDC clock testing enable. + # 1'b1: sending TDC clock at the left serial port; + # 1'b0: sending left serializer data at the left port. + def enable_TDCClkTest(self): + self.wr_reg('TDCClockTest', 1) + + def disable_TDCClkTest(self): + self.wr_reg('TDCClockTest', 0) + + # The TDC reference strobe testing enable. + # 1'b1: sending TDC reference strobe at the right serial port; + # 1'b0: sending right serializer data at the right port. + def enable_TDCRefStrTest(self): + self.wr_reg('TDCStrobeTest', 1) + + def disable_TDCRefStrTest(self): + self.wr_reg('TDCStrobeTest', 0) + + # Left/Right Tx amplitude selection. + # 3'b000: min amplitude (50 mV) + # 3'b111: max amplitude (320 mV) + # Step size is about 40 mV. + def set_TxAmplSel(self, side, amp): + regs = {'left':'LTx_AmplSel', 'right':'RTx_AmplSel'} + try: + self.wr_reg(regs[side], amp) + except KeyError: + print('Choose between \'left\' or \'right\' side options') + + def get_TxAmplSel(self, side): + regs = {'left':'LTx_AmplSel', 'right':'RTx_AmplSel'} + try: + return self.rd_reg(regs[side]) + except KeyError: + print('Choose between \'left\' or \'right\' side options') + + # Left/Right Tx disable, active high. + def enable_Tx(self, side): + regs = {'left':'disLTx', 'right':'disRTx'} + try: + self.wr_reg(regs[side], 0) + except KeyError: + print('Choose between \'left\' or \'right\' side options') + + def disable_Tx(self, side): + regs = {'left':'disLTx', 'right':'disRTx'} + try: + self.wr_reg(regs[side], 1) + except KeyError: + print('Choose between \'left\' or \'right\' side options') + + # GRO TOA reset, active low + def set_GROTOAReset(self, reset): + if not isinstance(reset, bool): + raise TypeError('Argument must be True (reset) or False (don\'t reset)') + val = 0 if reset else 1 + self.wr_reg('GRO_TOARST_N', val) + + def get_GROTOAReset(self): + return self.rd_reg('GRO_TOARST_N') + + # GRO Start, active high. + def start_GRO(self): + self.wr_reg('GRO_Start', 1) + + def stop_GRO(self): + self.wr_reg('GRO_Start', 0) + + # GRO TOA latch clock. (Guessing this means enable/disable) + def enable_GROTOALatch(self): + self.wr_reg('GRO_TOA_Latch', 1) + + def disable_GROTOALatch(self): + self.wr_reg('GRO_TOA_Latch', 0) + + # GRO TOA clock. + def enable_GROTOAClk(self): + self.wr_reg('GRO_TOA_CK', 1) + + def disable_GROTOAClk(self): + self.wr_reg('GRO_TOA_CK', 0) + + # GRO TOT clock. + def enable_GROTOTClk(self): + self.wr_reg('GRO_TOT_CK', 1) + + def disable_GROTOTClk(self): + self.wr_reg('GRO_TOT_CK', 0) + + # GRO TOT reset, active low. + def set_GROTOTReset(self, reset): + if not isinstance(reset, bool): + raise TypeError('Argument must be True (reset) or False (don\'t reset)') + val = 0 if reset else 1 + self.wr_reg('GRO_TOTRST_N', val) + + def get_GROTOTReset(self): + return self.rd_reg('GRO_TOTRST_N') + + # *********************** + # **** PERIPH STATUS **** + # *********************** + + # Bit alignment error + def get_BitAlignErr(self): + return self.rd_reg('fcBitAlignError') + + # Phase shifter late + def get_PhaseShiftLate(self): + return self.rd_reg('PS_Late') + + # AFC capacitance + def get_AFCCap(self): + return self.rd_reg('AFCcalCap') + + # AFC busy, 1: AFC is ongoing, 0: AFC is done + def get_AFCBusy(self): + return self.rd_reg('AFCBusy') + + # Fast command alignment FSM state + def get_FSM_FCAlign(self): + return self.rd_reg('fcAlignFinalState') + + # Global control FSM state + def get_FSM_GlobCtrl(self): + return self.rd_reg('controllerState') - def get_noisewidth(self, pix): - return self.rd_reg('NW', pix) + # Fast command self-alignment error indicator, ed[3:0] in figure 53 + def get_SelfAlignErr(self): + return self.rd_reg('fcAlignStatus') - def get_threshold(self, pix): - return self.rd_reg('TH', pix) + # Count of invalid fast command received + def get_invalidFCCount(self): + return self.rd_reg('invalidFCCount') - def get_THstate(self, pix): - return self.rd_reg('THstate', pix) + # Count of PLL unlock detected + def get_PLLUnlockCount(self): + return self.rd_reg('pllUnlockCount') - def get_pixelID(self, pix): - return self.rd_reg('PixelID', pix) + # 32-bit EFuse output + def get_EFuseOut(self): + return self.rd_reg('EFuseQ')