How to Add Support for a New ASIC
Pix2PGP is designed to be adapted to a new detection ASIC through
parameterization only — no changes to the shared RTL core
(gateware/shared/rtl) or the FPGA receiver
(firmware/fpga/rtl) are required.
Throughout this guide, NewAsic refers to the ASIC being added. Rename
it accordingly in every step.
Pick a Template
Two event-closure families are supported:
Self-Closure — the ASIC User Logic determines when to issue
EoFinternally (no external ERO signal). Template: SparkPixSExternal-Trigger-Closure (ERO) — an external End-Of-Readout trigger closes the event. Template: SparkPixT
Copy the closest template as the starting point for NewAsic:
$ cd pix2pgp/gateware/asics
$ cp -r SparkPixT NewAsic # or SparkPixS
Edit the RTL Package
Inside NewAsic/rtl/Pix2PgpAsicPkg.vhd, adjust the following constants:
NUM_OF_COL_MANAGERS_C— how many columns each Pix2PGP instance servesNUM_OF_SERIALIZERS_C— how many serializers / Pix2PGP instances / lanes exist on the whole ASICASIC_DATABUS_DWIDTH_C— the width of the data bus driven into Pix2PGP (see the widths supported below)HEADER_WIDTH_MULT_C— if the doubled internal bus width (PIX2PGP_DATABUS_DWIDTH_C = 2 * ASIC_DATABUS_DWIDTH_C) is not large enough to fit the header bitfield, scale it up here. See Data Frame FormatThe header bitfield and column metadata bitfield definitions — the layout of Pause / OverOcc / Pause-Error / Timeout / Column Hitmask / Trigger Counter fields inside the frame header
Supported ASIC_DATABUS_DWIDTH_C values: 4, 8, 12, 16, 20, 24, 28,
32 bits. Using widths below 16 bits requires padding — bandwidth is
wasted. Widths above 32 bits should be split across multiple cycles.
Edit the RTL Top
Rename and edit NewAsic/rtl/Pix2PgpNewAsicTop.vhd:
$ cd NewAsic/rtl
$ mv Pix2PgpSparkPixTTop.vhd Pix2PgpNewAsicTop.vhd
Update:
Change the VHDL entity name to
Pix2PgpNewAsicTopSet the width of the
sof,eof,overOcc(etc.) signals toNUM_OF_COL_MANAGERS_CSet the number of
dinXXports to matchNUM_OF_COL_MANAGERS_CSet the width of each
dinXXport toASIC_DATABUS_DWIDTH_C
Note
The top-level intentionally uses simple std_logic / std_logic_vector ports rather than complex VHDL types. This is because the top-level is often instantiated within a SystemVerilog / Verilog context (many ASIC-integration flows still cannot handle VHDL records across language boundaries).
Edit the Testbench Files
$ cd ../tb
$ mv DummySparkPixTPixel.vhd DummyNewAsicPixel.vhd
$ mv Pix2PgpSparkPixTFpgaRxTop.vhd Pix2PgpNewAsicFpgaRxTop.vhd
$ mv Pix2PgpSparkPixTTopTb.vhd Pix2PgpNewAsicTopTb.vhd
DummyNewAsicPixel.vhd— behavioral model of a single pixel of the new ASIC. Adjust the pixel model’s timing (delay betweenwrEnstrobes, delay betweenSROassertion and the firstwrEn) to match the intended in-silicon behavior. ThehitLenport is set from the top-level testbench and controls how many hits each pixel injects per eventPix2PgpNewAsicFpgaRxTop.vhd— wrapper for the FPGA receiver logic. Expand or collapse the number of input data ports to matchNUM_OF_SERIALIZERS_CPix2PgpNewAsicTopTb.vhd— full behavioral testbench. Update all entity and instance names; adjust bus widths as needed. The testbench instantiates every lane of the ASIC and routes them intoPix2PgpNewAsicFpgaRxTopPer-column hit patterns are set via lines like
hitLen(0)(3) <= toSlv(3, hitLen(0)(0)'length);— three hits for a pixel in column 3 of lane 0For random stimuli, use the helper script:
$ python software/scripts/hitsToVhd.py \ --numOfLanes=4 --numOfCols=40 \ --minRange=0 --maxRange=4 \ --laneEnable=1,1,1,1
Quick Syntax Check
From firmware/ghdl:
$ make build ASIC=NewAsic
If the command exits without errors, the VHDL is well-formed.
Create a VCS Simulation Target
$ cd pix2pgp/firmware/targets
$ cp -r Pix2PgpSparkPixTEmu Pix2PgpNewAsicEmu
Update:
hdl/— renamePix2PgpEmuSparkPixT.vhd/Pix2PgpEmuSparkPixT.xdctoPix2PgpEmuNewAsic.*and edit entity names inside. These are dummy files not actually used by the testbenchtb/— renamePix2PgpSparkPixTEmuTb.vhdtoPix2PgpNewAsicEmuTb.vhd; update entity names inside. In particular, changeU_Uut : entity pix2pgp.Pix2PgpSparkPixTTopTbtoU_Uut : entity pix2pgp.Pix2PgpNewAsicTopTbruckus.tcl— change:loadRuckusTcl $::DIR_PATH/../../../gateware/asics/SparkPixT
to:
loadRuckusTcl $::DIR_PATH/../../../gateware/asics/NewAsic
and
set_property top {Pix2PgpSparkPixTEmuTb} [get_filesets sim_1]
to:
set_property top {Pix2PgpNewAsicEmuTb} [get_filesets sim_1]
Run the VCS testbench following How to Simulate Using VCS, substituting
NewAsic for SparkPixS.
Extend the Python Decoder
Once the VCS run produces a data dump, extend the Python decoder to parse
it. Four files must be edited under firmware/python/pix2pgp/:
_AsicParameters.py
Add NewAsic to asicTypeDict and asicParams, then add a
parameter class:
asicTypeDict = {
1: "SparkPixS",
2: "SparkPixT",
3: "NewAsic",
}
asicParams = {
'SparkPixS': SparkPixSParameters,
'SparkPixT': SparkPixTParameters,
'NewAsic' : NewAsicParameters,
}
class NewAsicParameters(AsicParameterBase):
@property
def asicTypeId(self):
for key, value in AsicParameterBase.asicTypeDict.items():
if value == "NewAsic":
return key
raise ValueError("ASIC type not found in asicTypeDict!")
def asicParamExtract(self):
param_dict = {
'asicTypeId' : self.asicTypeId,
'asicType' : AsicParameterBase.asicTypeDict[self.asicTypeId],
'numOfLanes' : 4, # NUM_OF_SERIALIZERS_C
'numOfCols' : 40, # NUM_OF_COL_MANAGERS_C
'wordLen' : 10, # PIX2PGP_DATABUS_DWIDTH_C in bytes
}
return param_dict
Note
The asicTypeId value must equal the ASIC_TYPE_C constant
set in NewAsicPkg.vhd. wordLen is expressed in bytes (the VHDL
constant is in bits).
_Pix2PgpHeaderFormat.py
Register a NewAsicHeaderFormat class and decode the header bit-mapping
in accordance with the header bitfield in Pix2PgpAsicPkg.vhd. The
upper bit of the header must be at position (wordLen * 8) - 1; the
Column Hitmask width must be NUM_OF_COL_MANAGERS_C bits.
_Pix2PgpColMetadataFormat.py
Register a NewAsicColMetadataFormat class and decode the column
metadata bit-mapping according to the corresponding fields in
Pix2PgpAsicPkg.vhd.
_Pix2PgpSparseDataFormat.py
Register a NewAsicDataFormat class and decode the individual hit data
words according to the ASIC’s sparse-data layout (ADC + row, ToA + ToT +
row, etc.). Update both dataDecoder and dataPrinter.
Housekeeping
Update the top-level
README.mdand the Supported ASICs list in this documentation (docs/src/introduction.rst)Run benchmarking for
NewAsic(see How to Benchmark Throughput and Latency)Update the Pix2PGP Confluence page