diff --git a/doc/fpga_firmware.md b/doc/fpga_firmware.md new file mode 100644 index 0000000..8353fe5 --- /dev/null +++ b/doc/fpga_firmware.md @@ -0,0 +1,680 @@ +# PuzzleFW FPGA firmware + +The PuzzleFW firmware provides the following functionality: + +* Collect ADC samples at 125 MSa/s with configurable decimation or averaging. +* Trigger on external digital input and collect a configurable number of samples. +* Detect transitions on digital input signals and assign time tags to these events. +* Transfer ADC data and timetagger data to the Zynq PS via DMA. + + +# Analog acquisition chain + +TODO ... + +When auto-trigger mode is active, the acquisition chain triggers continuously. +A new trigger occurs as soon as acquisition for the previous trigger has ended, after a dead time controlled by `TRIGGER_DELAY`. +In this mode, the decimation factor must be at least 2 (or at least 4 in 4-channel mode). +If `TRIGGER_DELAY` is zero, sampling continues accross at a fixed pace controlled by the decimation factor. +This makes it possible to set up continuous streaming data acquisition. + +When external triggering is active, sampling starts when the specified external trigger condition occurs, after a delay of `TRIGGER_DELAY` samples. +The external trigger event is subject to a jitter of 1 sample (8 ns). +Further trigger events are ignored until acquisition for the previous trigger has ended. + +TODO : DMA data format + +TODO : LEDs + + +# Timetagger + +TODO ... + +TODO : DMA data format + +TODO : LEDs + + +# Registers + +The behaviour of the PuzzleFW firmware is controlled via a set of registers. +These registers are accessible from the Zynq PS via memory mapped I/O. + +The registers are located in a 2 MB region with address 0x43000000 to 0x431fffff in the PS address map. + +Within the register address space, the first 1 MB area is intended for various types of control and status registers that are accessed by user space software. +The second 1 MB area is intended for privileged registers that are only accessed by system software such as the Linux kernel driver. +The difference is that writing incorrect values to privileged registers can corrupt or crash the PS system, while writing to user registers can not. + +The complete set of registers is listed below. +Access to undefined addresses within the register area must be avoided. +If such access occurs, the firmware may either ignore it or map it to an existing register in a way that may be unexpected. + +## Register list + +This list specifies register addresses as offsets within the register address space. +The base address 0x43000000 must be added to obtain the absolute address on the PS memory bus. + +**User registers** + +| Address | Name | Description | +|----------|-------------------|-------------| +| 0x000000 | INFO | Firmware version information | +| 0x000010 | IRQ_ENABLE | Enable PL-to-PS interrupts | +| 0x000014 | IRQ_PENDING | Mask of pending interrupt conditions | +| 0x000100 | DMA_EN | Enable DMA transfers | +| 0x000104 | DMA_STATUS | Status of DMA engine | +| 0x000108 | DMA_CLEAR | Clear DMA error flags | +| 0x000180 | TIMESTAMP_LO | Low 32 bits of global timestamp | +| 0x000184 | TIMESTAMP_HI | High 16 bits of global timestamp | +| 0x000188 | TIMESTAMP_CLEAR | Reset timestamp counter to zero | +| 0x000200 | ACQ_ADDR_START | Start address of DMA buffer for analog acquisition | +| 0x000204 | ACQ_ADDR_END | End address of DMA buffer for analog acquisition | +| 0x000208 | ACQ_ADDR_LIMIT | Pause DMA when write pointer reaches this point | +| 0x00020C | ACQ_ADDR_INTR | Raise interrupt when write pointer reaches thi point | +| 0x000210 | ACQ_ADDR_PTR | Current DMA write pointer | +| 0x000214 | ACQ_DMA_CTRL | Control DMA write stream for analog acquisition | +| 0x000218 | ACQ_INTR_CTRL | Control DMA interrupts for analog acquisition | +| 0x00021C | ACQ_DMA_STATUS | Status of DMA write stream for analog acquisition | +| 0x000220 | ACQUISITION_EN | Enable analog data acquisition | +| 0x000224 | RECORD_LENGTH | Number of samples per trigger minus 1. | +| 0x000228 | DECIMATION_FACTOR | Sample decimation factor minus 1. | +| 0x00022C | SHIFT_STEPS | Nr of bit steps to shift accumulated value right | +| 0x000230 | AVERAGING_EN | Select averaging or decimation | +| 0x000234 | CH4_MODE | Enable 4-channel sampling (4-channel device only) | +| 0x000238 | SIMULATE_ADC | Simulate ADC samples | +| 0x000240 | TRIGGER_MODE | Trigger configuration | +| 0x000244 | TRIGGER_DELAY | Trigger delay | +| 0x000248 | TRIGGER_STATUS | Trigger status | +| 0x000280 | ADC_SAMPLE | Most recent ADC samples from IN1 and IN2 | +| 0x000284 | ADC23_SAMPLE | Most recent ADC samples from IN3 and IN4 (4-channel device only) | +| 0x00028C | ADC_RANGE_CLEAR | Clear min/max ADC sample values | +| 0x000290 | ADC0_MINMAX | Min/max ADC sample values from IN1 | +| 0x000294 | ADC1_MINMAX | Min/max ADC sample values from IN2 | +| 0x000298 | ADC2_MINMAX | Min/max ADC sample values from IN3 (4-channel device only) | +| 0x00029C | ADC3_MINMAX | Min/max ADC sample values from IN4 (4-channel device only) | +| 0x000300 | TT_ADDR_START | Start address of DMA buffer for timetagger | +| 0x000304 | TT_ADDR_END | End address of DMA buffer for timetagger | +| 0x000308 | TT_ADDR_LIMIT | Pause DMA when write pointer reaches this point | +| 0x00030C | TT_ADDR_INTR | Raise interrupt when write pointer reaches thi point | +| 0x000310 | TT_ADDR_PTR | Current DMA write pointer | +| 0x000314 | TT_DMA_CTRL | Control DMA write stream for timetagger | +| 0x000318 | TT_INTR_CTRL | Control DMA interrupts for timetagger | +| 0x00031C | TT_DMA_STATUS | Status of DMA write stream for timetagger | +| 0x000320 | TIMETAGGER_EN | Mask of enabled timetagger channels | +| 0x000324 | TIMETAGGER_MARK | Emit marker record in timetagger data | +| 0x000404 | LED_STATE | Control LEDs | + +**Privileged registers** + +| Address | Name | Description | +|----------|-------------------|-------------| +| 0x100000 | DMA_BUF_ADDR | Base address of DMA buffer in RAM | +| 0x100004 | DMA_BUF_SIZE | Size of DMA buffer in RAM | + +## Register descriptions + +Registers are 32 bits wide, but many registers use only a subset of the bits. +A _field_ is a range of meaningful bits within a register. +Some registers contain multiple fields. + +Fields are marked as _RW_ or _RO_ or _WC_. + +* RW fields can be modified by writing to the register. + Reading from the register returns the most recent value written to the field. +* RO fields are read-only. Writes to these fields are ignored. + The value of these fields typically changes spontaneously to reflect the status of the firmware. +* WC fields are write-only and auto-clearing. + Writing a 1 bit to the field triggers an action in the firmware. + Writing a 0 bit has no effect. + WC fields are returned as 0 when reading from the register. + +Bits that are not part of a field are _reserved_. +Reserved bits must be ignored when reading. +Reserved bits should be written as zero or left unmodified when writing. + +### 0x000000: INFO + +Firmware version information. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 7 : 0 | version_minor | RO | Firmware minor version | +| 15 : 8 | version_major | RO | Firmware major version | +| 23 : 16 | api_version | RO | Firmware API version, currently 0x01 | +| 31 : 24 | | RO | Fixed value 0x4a | + +### 0x000010: IRQ_ENABLE + +Enable PL-to-PS interrupts. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | irq_enable | RW | '1' to enable interrupts, '0' to disable | + +This register acts as a master switch for interrupts from the firmware. +Specific interrupt conditions can be separately enabled or disabled via other registers. + +### 0x000014: IRQ_PENDING + +Mask of pending interrupt conditions. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | acq_intr | RO | '1' if an interrupt is pending for analog acquisition DMA | +| 1 | tt_intr | RO | '1' if an interrupt is pending for timetagger DMA | + +### 0x000100: DMA_EN + +Enable DMA transfers. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | dma_en | RW | '1' to enable DMA transfers, '0' to disable | + +This register acts as a master switch for the DMA engine in the PuzzleFW firmware. + +Disabling DMA will prevent new bursts from starting, but allows ongoing bursts to complete. +Under normal circumstances, the completion of ongoing bursts can take at most a few microseconds. + +### 0x000104: DMA_STATUS + +Status of DMA engine. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | dma_busy | RO | '1' if a DMA burst is in progres | +| 1 | err_read | RO | '1' if a DMA read access failed | +| 2 | err_write | RO | '1' if a DMA write access failed | +| 3 | err_address | RO | '1' if access outside the DMA buffer was attempted | +| 4 | err_any | RO | '1' if any DMA error occurred | + +If a DMA error occurs, no further DMA bursts will be started until the error is explicitly cleared. +The failed DMA burst will not be acknowledged to the subsystem that initiated it (analog or timetagger). +To recover from this situation, it will typically be necessary to stop and re-initialize all ongoing DMA data streams, clear the error, then restart DMA data streams. + +An address error typically occurs when the DMA address range for the analog subsystem or the timetagger exceeds the size of the DMA window specified via `DMA_BUF_SIZE`. + +### 0x000108: DMA_CLEAR + +Clear DMA error flags. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | dma_clear | WC | Write '1' to clear pending DMA errors | + +### 0x000180: TIMESTAMP_LO + +Low 32 bits of global timestamp. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 31 : 0 | | RO | Least significant 32 bits of the global 8 ns timestamp counter. | + +### 0x000184: TIMESTAMP_HI + +High 16 bits of global timestamp. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 15 : 0 | | RO | Most significant 16 bits of the global 8 ns timestamp counter. | + +When reading both `TIMESTAMP_LO` and `TIMESTAMP_HI`, note that the timestamp will change between the two reads, possibly resulting in an invalid combination of low and high part. +To avoid this, read `TIMESTAMP_HI`, then `TIMESTAMP_LO`, then `TIMESTAMP_HI` again. +Then check that the value of `TIMESTAMP_HI` has not changed during the sequence, otherwise retry. + +### 0x000188: TIMESTAMP_CLEAR + +Reset timestamp counter to zero. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | timestamp_clear | WC | Write '1' to reset the timestamp counter. | + +### 0x000200: ACQ_ADDR_START + +Start address of DMA buffer for analog acquisition. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 31 : 7 | | RW | Start address as multiple of 128 bytes. | + +The address must be aligned to a 128-byte boundary. +The address is interpreted as an offset relative to `DMA_BUF_ADDR`. + +### 0x000204: ACQ_ADDR_END + +End address of DMA buffer for analog acquisition. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 31 : 7 | | RW | End address as multiple of 128 bytes. | + +The end address points past the end of the DMA buffer. +When the DMA write pointer reaches `ACQ_ADDR_END`, it immediately wraps back to `ACQ_ADDR_START`. + +The address must be aligned to a 128-byte boundary. +The address is interpreted as an offset relative to `DMA_BUF_ADDR`. + +### 0x000208: ACQ_ADDR_LIMIT + +Pause DMA when write pointer reaches this point. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 31 : 7 | | RW | Address as multiple of 128 bytes. | + +When the address pointer reaches the limit address, the DMA engine pauses further transfers until software updates the limit. + +The address must be aligned to a 128-byte boundary. +The address is interpreted as an offset relative to `DMA_BUF_ADDR`. + +### 0x00020C: ACQ_ADDR_INTR + +Raise interrupt when write pointer reaches this point. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 31 : 3 | | RW | Address as multiple of 8 bytes. | + +When the address pointer reaches this address, an interrupt occurs if analog acquisition interrupts are enabled. + +The address must be aligned to an 8-byte boundary. +The address is interpreted as an offset relative to `DMA_BUF_ADDR`. + +### 0x000210: ACQ_ADDR_PTR + +Current DMA write pointer. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 31 : 3 | | RO | Address as multiple of 8 bytes. | + +This register indicates the address where the next write transfer will start. +Write transfers have completed for locations up to (but excluding) this address. +This indicates that software can read valid data up to (but excluding) the pointer address. + +The address will be aligned to an 8-byte boundary. +The address is interpreted as an offset relative to `DMA_BUF_ADDR`. + +### 0x000214: ACQ_DMA_CTRL + +Control DMA write stream for analog acquisition. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | acq_dma_en | RW | '1' to enable DMA transfers for analog acquisition. | +| 1 | acq_dma_init | WC | Write '1' to initialize the analog acquisition DMA stream | + +Initializing the DMA stream resets the write pointer to `ACQ_ADDR_START` and discards pending data from the internal buffer. +Initializing is necessary after setting up the buffer address, and to recover from DMA errors. + +### 0x000218: ACQ_INTR_CTRL + +Control DMA interrupts for analog acquisition. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | acq_intr_en | RW | '1' to enable interrupt for DMA write pointer. | +| 1 | acq_intr_clear | WC | Write '1' to clear a pending interrupt condition. | + +### 0x00021C: ACQ_DMA_STATUS + +Status of DMA write stream for analog acquisition. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | acq_dma_busy | RO | '1' if an uncompleted DMA burst is in progress. | + +### 0x000220: ACQUISITION_EN + +Enable analog data acquisition. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | acquisition_en | RW | '1' to enable analog data acquisition. | + +When analog acquisition is enabled, triggers are processed according to the configured trigger mode and samples are collected accordingly. +If analog acquisition is disabled, any ongoing sample collection stops immediately and further triggers are ignored. + +### 0x000224: RECORD_LENGTH + +Number of samples per trigger minus 1. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 15 : 0 | record_length | RW | Number of samples per trigger minus 1. | + +When a trigger condition occurs, the acquisition chain collects (`record_length` + 1) decimated samples. + +### 0x000228: DECIMATION_FACTOR + +Sample decimation factor minus 1. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 17 : 0 | decimation_factor | RW | Decimation factor minus 1. | + +The ADCs sample at a fixed sample rate of 125 MSa/s. +The resulting sample stream is decimated by a factor (`decimation_factor` + 1). + +If averaging is enabled, the sum of each group of (`decimation_factor` + 1) ADC samples is collected as a decimated sample. +If averaging is disabled, only the first sample of each group of (`decimation_factor` + 1) ADC samples is collected. + +### 0x00022C: SHIFT_STEPS + +Number of bit positions to shift accumulated value right. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 3 : 0 | shift_steps | RW | Number of bit positions. | + +The accumulated value of each decimated sample is right-shifted by the configured number of bit positions before the value is transferred to DMA. +This is necessary to prevent overflow when a high decimation factor (above 1024) is used in averaging mode. + +### 0x000230: AVERAGING_EN + +Select averaging or decimation. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | averaging_en | RW | '1' to average samples, '0' to decimate samples. | + +### 0x000234: CH4_MODE + +Enable 4-channel sampling (only supported on 4-channel devices). + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | ch4_mode | RW | '1' to enable 4-channel sampling. | + +When 4-channel sampling is disabled, only channels IN1 and IN2 are active. +One 64-bit word is emitted for each decimated sample, containing the data of these two channels. + +When 4-channel sampling is enabled, channels IN3 and IN4 are also active. +Two 64-bit words are emitted for each decimated sample. +The first word contains the data for channels IN1 and IN2. +The second word contains the data for channels IN3 and IN4. + +When 4-channel sampling is enabled, the decimation factor **must** be at least 2 (`DECIMATION_FACTOR` at least 1). + +### 0x000238: SIMULATE_ADC + +Simulate ADC samples. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | simulate_adc | RW | '1' to use simulated ADC samples, '0' to use real ADC samples. | + +### 0x000240: TRIGGER_MODE + +Trigger configuration. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | trig_auto_en | RW | '1' to enable auto-trigger mode. | +| 1 | trig_ext_en | RW | '1' to enable external triggering. | +| 5 : 4 | trig_ext_select | RW | Select digital input channel to use as external trigger. | +| 7 | trig_ext_falling | RW | '1' to trigger on falling edge, '0' to trigger on rising edge. | +| 8 | trig_force | WC | Write '1' to force a single trigger event. | + +Auto-trigger mode takes precedence over external triggering. +If auto-triggering and external triggering are both disabled, no data acquisition takes place unless a trigger is forced by writing to `trig_force`. + +### 0x000244: TRIGGER_DELAY + +Trigger delay. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 15 : 0 | trigger_delay | RW | Trigger delay in samples (8 ns). | + +### 0x000248: TRIGGER_STATUS + +Trigger delay. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | trig_waiting | RO | '1' if the acquisition chain is waiting for a trigger. | + +### 0x000280: ADC_SAMPLE + +Most recent ADC samples from IN1 and IN2. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 13 : 0 | adc0_sample | RO | ADC sample for channel IN1. | +| 29 : 16 | adc1_sample | RO | ADC sample for channel IN2. | + +### 0x000284: ADC_SAMPLE + +Most recent ADC samples from IN3 and IN4 (only supported on 4-channel devices). + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 13 : 0 | adc2_sample | RO | ADC sample for channel IN3. | +| 29 : 16 | adc3_sample | RO | ADC sample for channel IN4. | + +### 0x00028C: ADC_RANGE_CLEAR + +Most recent ADC samples from IN3 and IN4 (only supported on 4-channel devices). + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | adc_range_clear | WC | Write '1' to clear min/max ADC sample values. | + +### 0x000290: ADC0_MINMAX + +Minimum and maximum ADC sample from IN1. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 13 : 0 | adc0_min | RO | Minimum ADC sample from IN1 since range cleared. | +| 29 : 16 | adc0_max | RO | Maximum ADC sample from IN1 since range cleared. | + +### 0x000294: ADC1_MINMAX + +Minimum and maximum ADC sample from IN2. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 13 : 0 | adc1_min | RO | Minimum ADC sample from IN2 since range cleared. | +| 29 : 16 | adc1_max | RO | Maximum ADC sample from IN2 since range cleared. | + +### 0x000298: ADC2_MINMAX + +Minimum and maximum ADC sample from IN3 (only supported on 4-channel devices). + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 13 : 0 | adc2_min | RO | Minimum ADC sample from IN3 since range cleared. | +| 29 : 16 | adc2_max | RO | Maximum ADC sample from IN3 since range cleared. | + +### 0x00029C: ADC3_MINMAX + +Minimum and maximum ADC sample from IN4 (only supported on 4-channel devices). + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 13 : 0 | adc3_min | RO | Minimum ADC sample from IN4 since range cleared. | +| 29 : 16 | adc3_max | RO | Maximum ADC sample from IN4 since range cleared. | + +### 0x000300: TT_ADDR_START + +Start address of DMA buffer for timetagger. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 31 : 7 | | RW | Start address as multiple of 128 bytes. | + +The address must be aligned to a 128-byte boundary. +The address is interpreted as an offset relative to `DMA_BUF_ADDR`. + +### 0x000304: TT_ADDR_END + +End address of DMA buffer for timetagger. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 31 : 7 | | RW | End address as multiple of 128 bytes. | + +The end address points past the end of the DMA buffer. +When the DMA write pointer reaches `TT_ADDR_END`, it immediately wraps back to `TT_ADDR_START`. + +The address must be aligned to a 128-byte boundary. +The address is interpreted as an offset relative to `DMA_BUF_ADDR`. + +### 0x000308: TT_ADDR_LIMIT + +Pause DMA when write pointer reaches this point. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 31 : 7 | | RW | Address as multiple of 128 bytes. | + +When the address pointer reaches the limit address, the DMA engine pauses further transfers until software updates the limit. + +The address must be aligned to a 128-byte boundary. +The address is interpreted as an offset relative to `DMA_BUF_ADDR`. + +### 0x00030C: TT_ADDR_INTR + +Raise interrupt when write pointer reaches this point. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 31 : 3 | | RW | Address as multiple of 8 bytes. | + +When the address pointer reaches this address, an interrupt occurs if analog acquisition interrupts are enabled. + +The address must be aligned to an 8-byte boundary. +The address is interpreted as an offset relative to `DMA_BUF_ADDR`. + +### 0x000310: TT_ADDR_PTR + +Current DMA write pointer. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 31 : 3 | | RO | Address as multiple of 8 bytes. | + +This register indicates the address where the next write transfer will start. +Write transfers have completed for locations up to (but excluding) this address. +This indicates that software can read valid data up to (but excluding) the pointer address. + +The address will be aligned to an 8-byte boundary. +The address is interpreted as an offset relative to `DMA_BUF_ADDR`. + +### 0x000314: TT_DMA_CTRL + +Control DMA write stream for timetagger. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | tt_dma_en | RW | '1' to enable DMA transfers timetagger. | +| 1 | tt_dma_init | WC | Write '1' to initialize the timetagger DMA stream | + +Initializing the DMA stream resets the write pointer to `TT_ADDR_START` and discards pending data from the internal buffer. +Initializing is necessary after setting up the buffer address, and to recover from DMA errors. + +### 0x000318: TT_INTR_CTRL + +Control DMA interrupts for timetagger. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | tt_intr_en | RW | '1' to enable interrupt for DMA write pointer. | +| 1 | tt_intr_clear | WC | Write '1' to clear a pending interrupt condition. | + +### 0x00031C: TT_DMA_STATUS + +Status of DMA write stream for timetagger. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | tt_dma_busy | RO | '1' if an uncompleted DMA burst is in progress. | + +### 0x000320: TIMETAGGER_EN + +Mask of enabled timetagger channels. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | | RW | '1' to enable rising edge events on digital input 0. | +| 1 | | RW | '1' to enable falling edge events on digital input 0. | +| 2 | | RW | '1' to enable rising edge events on digital input 1. | +| 3 | | RW | '1' to enable falling edge events on digital input 1. | +| ... | | RW | ... | +| 7 | | RW | '1' to enable falling edge events on digital input 3. | + +### 0x000324: TIMETAGGER_MARK + +Emit marker record in timetagger data. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 0 | | WC | Write '1' to emit a marker record in the timetagger data stream. | + +### 0x000404: LED_STATE + +Control LEDs. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 7 : 4 | | RW | Mask controlling 4 yellow LEDs on the side of the Red Pitaya. | + +### 0x100000: DMA_BUF_ADDR + +Base address of DMA buffer in RAM. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 31 : 12 | | RW | Base address of the DMA buffer in physical RAM. | + +This register controls which region of PS RAM may be accessed via DMA. +Typically, the Linux kernel driver must allocate a suitable range of physical memory and initialize these registers accordingly. + +The base address must be aligned to a 4 kB boundary. + +### 0x100004: DMA_BUF_SIZE + +Size of DMA buffer in RAM. + +| Bits | Field name | Access | Description | +|---------|---------------|--------|-------------| +| 31 : 12 | | RW | DMA buffer size as number of 4 kB pages. | + + +# DMA + +TODO ... + + +# Interrupts + +The PuzzleFW firmware can send interrupts to the Zynq PS to notify the software of specific conditions. +Interrupts are routed via `IRQ_F2P[0]`, which corresponds to interrupt 61 in the Zynq Generic Interrupt Controller (GIC). + +There are two types of conditions that can trigger an interrupt: + +* DMA transfers for analog acquisition have progressed to a configurable point. +* DMA transfers for the timetagger have progressed to a configurable point. + +Each type of condition has a separate interrupt enable switch, configured via registers `ACQ_INTR_CTRL` and `TT_INTR_CTRL`. +Furthermore, there is a master interrupt enable switch, configured via register `IRQ_ENABLE`. + +For example, interrupts may be used to wait for a certain amount of data from the analog acquisition system as follows: + +* Write register `ACQ_ADDR_INTR` to specify the amount of progress after which it wants to be notified. +* Write register `ACQ_INTR_CTRL` to clear any pending interrupt and enable interrupts on DMA progress. +* Read register `ACQ_ADDR_PTR` to check whether DMA progress has already passed the configured threshold. + This is necessary to avoid a race condition where software keeps waiting for a condition thas has already happened. +* Write register `IRQ_ENABLE` to enable firmware interrupts. +* Wait for the interrupt or do other stuff in the mean time. +* When the interrupt occurs, the interrupt handler may write register `IRQ_ENABLE` to disable firmware interrupts until the software has time to handle the cause of the interrupt. +* Optionally read register `IRQ_PENDING` to confirm that the interrupt was caused by analog data acquisition. +* Write register `ACQ_INTR_CTRL` to clear the interrupt and disable further interrupts of this type. +* Process the data that arrived in the DMA buffer. + +Interrupts can be used to wait for timetagger data in a similar way.