Design Overview

The FPGA PCIe interface is built using Altera's SOPC tool under Quartus. A Conduit module runs on the SOPC provided clock at 50MHz. It provides an Avalon slave, Avalon master, and interrupt connections into the SOPC builder system. It also provides conduits to the top level for an external block bus and a streaming data input interface. The Avalon Master and Slave ports are standard SOPC master and slave ports.

The block bus is synchronous with the SOPC builder clock. It provides a decoded 32-bit wide data bus to allow for reading and writing external registers. It does a single read/write per clock cycle. This bus also bursts out data at one read or write per clock. The returned data can have any number of pipeline delays but the order of data must be returned in the order that it was asked for.

The streaming input is synchronous with the 50MHz SOPC clock and is 64 bits wide. This is the data that is DMAed into DDR memory. The st_valid signal indicates the data is valid and is written into the FIFO. The st_irq_in can be used to generate an interrupt to the CPU. A st_half_full signal gives feedback so the data can be throttled to not overflow the FIFO. The FIFO is 256 entries deep and when the half-full flag is not set 128 entries can be pushed into the FIFO.

The conduit block bursts out the blocks to the CPU according to the DMA Descriptor Table. It also keeps a Start Pointer and a Current Pointer into the Descriptor Table. The DMA Descriptor Table is located inside the conduit block (in dual port RAM) and is accessed by the slave port.

The FPGA firmware defines 3 interrupt types:

  1. FIFO Overflow Interrupt (this happens when the FIFO overflows)
  2. Descriptor Table Interrupt (this happens when a descriptor has been processed AND the Interrupt when done flag in the descriptor has been set)
  3. External Interrupt (this is tied to st_irq_in on the conduit, and is currently controlled by the Temp.vhd code)

The Linux SDK for the NAS7825 requires that we use Legacy interrupts. Legacy interrupts are signaled on the PCI Express link using message TLPs that are generated internally by the IP Compiler for PCI Express.

To differentiate among the 3 interrupt types from Linux, with only one Interrupt Service Routine, we look at the bits in the Control/Status register. To clear the interrupt write a zero to that register.