Friday, May 20, 2011

Furlough Friday

Although FAMU's summer furlough does not officially apply to research staff (the lights are still on in the research building on Fridays), I am voluntarily restricting my work days to Monday-Thursday this summer, with the goal of saving gas money by only driving into Tallahassee four days a week instead of 5. I am only working half-time anyway, and it is easy enough to just work 5 hours a day on M-Th afternoons.

However, I may still work from home some Fridays, when I feel like it. I'm spending a little time from now working on the design of the input capture pathway.

Just now, I investigated the FIFO device for Avalon ("On Chip FIFO Memory") in SOPC Builder. It assumes that both the producer and consumer of the data are on the bus fabric, so is not suitable for our application, in which the data producer is custom gelware outside of the SOPC-Builder-generated system. Instead, we will put a FIFO in our custom gelware, and just use PIOs for the communication to the processor.

Let's go ahead and start outlining the design in more detail. The following input capture path will be need to be replicated in parallel for each input channel (that is up to 5 times, including one channel for the 409.6us timing sync input pulse, and one for each of the four PMTs at a site). However, all of the input capture paths will reference the same DECS (dual-edged carry-save) time counter (for consistency between their reported time values).

Current plan: For each input capture channel, have four 32-bit data input PIOs, as follows:
  • leading-low: Least significant 32 bits of the time value of the pulse leading edge.
  • leading-high: Most significant 32 bits of the time value of pulse leading edge.
  • trailing-low: Least significant 32 bits of the time value of the pulse trailing edge.
  • trailing-high: Most significant 32 bits of the time value of pulse trailing edge.
In addition, have one 8-bit bidirectional control/handshaking PIO called icpath_control, with the following bits:
  • Bit 0: nRESET (used as output only) - CPU sets this to 0 to reset the IC (input capture) path, 1 to let it operate normally.

  • Bit 1: nPAUSE_RUN (used as output only) - CPU sets this to 0 to freeze this input-capture channel, 1 to let it run freely. When paused, input pulses will be ignored entirely.

  • Bit 2: HANDSHAKE (used bidirectionally) - The FSM at the FIFO head sets this bit to 1 when data for a new pulse is in the PIOs and is ready for the CPU to consume. This causes an interrupt. The CPU then sets this bit to 0 when it has consumed the data; after this gelware is allowed to write new values to the PIO data input registers.

  • Bit 3: BUF_FULL (used as input only) - If an input pulse is captured but the FIFO is full because the CPU has not consumed previous pulses quickly enough, so that there is nowhere to put the pulse data, and the input capture circuit is stuck in dead time, the gelware asserts this signal to indicate to the CPU that any new input pulses will be inadvertently lost. This causes an interrupt, so that the firmware may report a warning about this condition. Later, when the CPU has consumed some pulse data, so that the input FIFO is no longer full, the gelware will deassert this signal.

  • Bits 4-7: Reserved for future expansion.
In addition to the above for each IC channel, we can have one more 8-bit output PIO called cntr_ctrl (counter control), which can be similar to the one I already am using in the GPS time application.

The overall architecture of the input capture system is as follows:
One thing that is a bit odd about this architecture at the moment is that each threshold level has its own input capture path, which is strange because actually we expect the different thresholds to be crossed at around the same time.

What we could do, then, is modify the input capture FSM for the PMT inputs so that, after the first threshold is crossed, it collects level-crossing times for all of the thresholds, until we reach the trailing edge for the first threshold. Then, that packet of data (leading and trailing edge times for all 5 thresholds) is stuffed all at once into the FIFO. The width of the input capture data path is then 5x64 = 320 bits.

The only problem is, this makes the structure of the input capture FSM more complex, which means the state-update logic might have trouble executing within one PLL clock cycle. So we may need to hand-optimize the state-update logic to some extent.

OK, so here is the new architecture:
All that is different here is that the input capture path for the PMTs is 5x wider, but there are 5x fewer paths.

We need to come up with a representation for threshold levels that are not crossed in a given pulse. For each level above the lowest one, we can include a bit that indicates whether that level was crossed at all in the current pulse. This indicates whether the next 128 bits (denoting the 64-bit leading/trailing edge times) are valid, or should be ignored.

Bad things will happen if there is glitching on any of the LVDS inputs during the leading edge - specifically, we might capture the glitch instead of the actual pulse. However, these bad data points can always be identified and thrown away in later data analysis.

One thing that will help our performance is to have a separate high-speed state machine for each threshold that just stuffs the pulse data in a register; and a slower state machine that gathers the data for all thresholds from the registers and stuffs them into the FIFO when everything is ready.

Just drafted the following needed modules:
  • pde_dff_en.vhd - Pseudo dual-edged D flip-flop with enable.
  • pde_reg_en.vhd - Pseudo dual-edged register with enable.
  • pde_shift_reg.vhd - Pseudo dual-edged shift register (for synchronizers & edge detectors).
  • pulse_cap.vhd - Module to capture rise/fall times for a single digital pulse signal (i.e., level-crossing times for a single analog signal to cross a single threshold level).
NOTE: Currently, pulse_cap.vhd uses a bidirectional single-wire handshaking signal to hand off data to its consumer. This could lead to problems since this signal may be left floating for extended periods unless we add a pulldown. But that may cause problems too, since we need it to stay high by itself for at least 20 ns until the next consumer clock edge. If we can't get this working, we should back off and go to a 2-wire handshaking protocol.

Next up, need to write the following modules:
  • pulseform_cap - A 50 MHz FSM (in behavioral VHDL) that (in parallel) gathers up the rise/fall data for all 5 thresholds for a given analog input signal, and writes that data to a bank of output registers which are then handed off to a consumer process.

  • FIFO_writer - Another 50 MHz FSM which takes the data packet from pulseform_cap and appends it to the tail of a FIFO queue. If/when the FIFO becomes full, it complains by asserting a BUF_FULL signal that alerts the CPU of the problem.

  • pulse_FIFO - This can be a standard LPM/ALT megafunction.

  • FIFO_reader (PIO feeder) - Pulls data items out of the FIFO and presents them to the PIO so that the CPU can consume them.
One more note: Actually, we can greatly simplify the architecture for the input capture datapath for the timing sync pulses. Since we only get one of those every 409.6 us, we can safely assume that the CPU can service the interrupt for each one before the next one occurs. So the FIFO and associated feeder modules are not necessary.

Here's the new design for the input capture datapath for just 1 of the 4 PMT inputs:

No comments:

Post a Comment