A5E-FMC-Example¶
Overview¶
The A5E FMC example builds on the base A5E reference design and adds the fmc_subsys subsystem, which brings the carrier-side management signals of the FMC connector under software control.
The subsystem does not implement an FMC application. It provides the plumbing a carrier needs before a mezzanine card can be used: an I2C master on the FMC management bus, a switch for the mezzanine supplies, and the presence and power-good signals. All of it is exposed to Linux through a device tree overlay that ships with the release image, so the connector can be brought up from userspace with standard tools and no kernel work.
This example is provided for the MitySOM and MitySBC carriers. The MitySOM-Mini has no FMC connector and has no fmc project.
FMC Subsystem¶
The FMC subsystem contains five functional blocks plus three bridges:
- i2c_controller - Avalon-MM I2C master driving the FMC connector's SCL and SDA
- power_en_pio - single-bit output PIO driving the mezzanine power switch
- pg_m2c_pio - single-bit input PIO reading the mezzanine's power-good signal
- prsnt_n_pio - single-bit input PIO reading card presence (MitySBC only)
- pg_c2m_pio - single-bit output PIO reporting carrier power good to the mezzanine (MitySBC only)
- clock_bridge - provides the internal subsystem clock
- reset_bridge - provides the internal subsystem reset
- mm_bridge - bridges the HPS lightweight bridge to the subsystem's internal Avalon-MM fabric
At the top level of the design:
- The subsystem clock is driven from hps_subsys.intel_agilex_5_soc_0_h2f_user0_clk
- The subsystem reset is driven from fabric_reset_controller_0.reset_out
- mm_bridge.s0 is attached to the HPS lightweight bridge at offset 0x80
- i2c_controller raises FPGA-to-HPS interrupt 4
- The I2C, power enable, presence and power-good signals are exported to the FMC connector pins
hps_subsys.intel_agilex_5_soc_0_h2f_user0_clk (100 MHz)
│
▼
┌──────────────────────────┐
│ clock_bridge │
└────────────┬─────────────┘
│ clock to every block below
│
lwhps2fpga ┌────────────┴─────────────┐ ┌──────────────────┐
0x20000080 ────►│ mm_bridge │───────►│ i2c_controller │◄───► io_fmc_scl / io_fmc_sda
│ (subsystem entry point) │ 0x00 │ (Avalon I2C) │────► i2c_irq (F2H IRQ 4)
└────────────┬─────────────┘ └──────────────────┘
│ ┌──────────────────┐
├─────────────────────►│ prsnt_n_pio │◄──── i_fmc_prsnt_n (MitySBC)
│ 0x40 └──────────────────┘
│ ┌──────────────────┐
├─────────────────────►│ power_en_pio │────► o_fmc_power_en
│ 0x50 └──────────────────┘
│ ┌──────────────────┐
├─────────────────────►│ pg_c2m_pio │────► o_fmc_pg_c2m (MitySBC)
│ 0x60 └──────────────────┘
│ ┌──────────────────┐
└─────────────────────►│ pg_m2c_pio │◄──── i_fmc_pg_m2c
0x70 └──────────────────┘
┌──────────────────────────┐
│ reset_bridge │◄──── fabric_reset_controller_0.reset_out
└──────────────────────────┘
reset to every block
Two of these signals are not FPGA pins on the MitySOM development kit. Card presence is read from an I/O expander on the carrier rather than from the fabric, and carrier power good is tied high in hardware, so prsnt_n_pio and pg_c2m_pio are omitted from the subsystem on that platform. The offsets of the remaining blocks are unchanged, so the same addresses apply on both carriers.
What This Project Offers¶
This project provides:
- An I2C master on the FMC management bus, presented to Linux as a standard I2C adapter
- Software control of the mezzanine supplies through the Linux regulator framework
- Presence detection and the power-good handshake described by the VITA 57.1 FMC Standard
- A device tree overlay that ships in the release image, so no kernel rebuild is required
Memory Offsets¶
The subsystem occupies 0x20000080 through 0x200000FF on the HPS lightweight bridge.
| Block | Offset | Address | Span | Carriers |
|---|---|---|---|---|
| i2c_controller | 0x00 | 0x20000080 | 0x40 | MitySOM, MitySBC |
| prsnt_n_pio | 0x40 | 0x200000C0 | 0x10 | MitySBC |
| power_en_pio | 0x50 | 0x200000D0 | 0x10 | MitySOM, MitySBC |
| pg_c2m_pio | 0x60 | 0x200000E0 | 0x10 | MitySBC |
| pg_m2c_pio | 0x70 | 0x200000F0 | 0x10 | MitySOM, MitySBC |
Clocking and Reset¶
- clock_bridge fans out the subsystem clock to every block, fed from the HPS user0 clock, which is 100 MHz in this design
- reset_bridge fans out the subsystem reset to every block, fed from fabric_reset_controller_0.reset_out
- The I2C controller's serial clock is set to 100 kHz in the device tree, and its FIFOs are 32 entries deep
FMC User I/O¶
The FMC user I/O pairs carry no fabric logic in this design.
On the MitySBC they connect directly to FPGA banks. The HA and HB pairs sit in banks whose VCCIO is fixed at 1.3 V. The LA pairs sit in banks 6A through 6D, whose VCCIO is set to 1.8 V in the delivered project. Running them at 3.3 V instead means editing the bank VCCIO and the per-pin I/O standard assignments in the project's a5e.qsf, and the setting has to match the VADJ rail the carrier actually supplies.
On the MitySOM development kit each LA pair passes through an analog 2:1 mux on the carrier board that selects which of two FPGA pins the pair is wired to. The muxes are configured over I2C rather than from the fabric, and the overlay enables the I/O expanders that drive them. See "Configuring the FMC user I/O muxes" below.
Scope of This Example¶
This example brings the FMC connector up rather than using it. No fabric logic is attached to the FMC user I/O and no example application is supplied.
That makes it a good base for:
- adding user logic on the FMC LA, HA and HB pairs
- bringing up and characterising a third-party mezzanine card
- reading a mezzanine card's IPMI FRU information before configuring the rest of a design
Building the Example¶
Compile the FPGA design¶
Refer to Building the FPGA and Bootloader (MitySOM) or Building the FPGA and Bootloader (MitySBC) for building the FPGA design. Navigate into the mitysom-a5e-ref-fmc or mitysbc-a5e-ref-fmc example project before compiling the design.
- Ensure to flash the resulting a5e.hps.jic onto the hardware
- Ensure to replace the a5e.core.rbf on the SD card
- Ensure to replace the boot.scr on the SD card's FAT partition
boot.scr matters here: it is what applies this design's device tree overlay. An FPGA image loaded without the matching boot script comes up with none of the Linux devices described below.
Using the Example¶
What the overlay adds¶
The release image ships both overlays, and the generated boot script applies the one matching the carrier:
| Carrier | Overlay |
|---|---|
| MitySOM | /boot/socfpga_agilex5_mitysom_devkit_fmc.dtbo |
| MitySBC | /boot/socfpga_agilex5_mitysbc_devkit_fmc.dtbo |
The overlay adds an I2C adapter for the FMC management bus, a GPIO controller for each PIO in the subsystem, and a regulator representing the mezzanine supplies. The GPIO lines are named in the device tree, so libgpiod addresses them by name and nothing has to be looked up or calculated:
| Line name | Direction | Carriers |
|---|---|---|
| FMC_PRSNT_N | input | MitySBC |
| FMC_POWER_EN | output | MitySOM, MitySBC |
| FMC_PG_C2M | output | MitySBC |
| FMC_PG_M2C | input | MitySOM, MitySBC |
Checking for a mezzanine card¶
On the MitySBC, presence is a fabric input and is read by name:
gpioget FMC_PRSNT_N
The signal is active low and the device tree applies no inversion, so gpioget reports the electrical level directly: inactive means a card is installed and pulling the line low, active means the slot is empty.
On the MitySOM development kit the same signal comes from a carrier I/O expander instead of the fabric. It is still named FMC_PRSNT_N and is still read the same way, but it belongs to the expander's GPIO controller rather than to fmc_subsys.
Powering the mezzanine card¶
The mezzanine supplies are switched by FMC_POWER_EN, which the device tree models as a regulator rather than as a plain GPIO. The regulator driver claims the line at boot, so gpioset FMC_POWER_EN=1 will fail with "Device or resource busy". Drive it through the regulator's sysfs interface instead:
# turn the mezzanine supplies on echo enabled > /sys/bus/platform/devices/regulator-fmc-userspace/state # read the current state cat /sys/bus/platform/devices/regulator-fmc-userspace/state # turn them back off echo disabled > /sys/bus/platform/devices/regulator-fmc-userspace/state
This one control switches both the 12 V and the 3.3 V mezzanine supplies. VADJ is not switched, it is always on. The supplies are left off at boot on purpose, since a mezzanine card generally needs the user I/O muxes and the VADJ rail set up before it is powered.
Once the supplies are on, the mezzanine reports its own rails with FMC_PG_M2C:
gpioget FMC_PG_M2C
Note: the design enables a weak internal pull-up on this input, so it reads active whenever nothing is driving it, including with an empty connector. An active reading on its own does not prove that a card is present and supplying power, so check FMC_PRSNT_N alongside it.
On the MitySBC, the carrier reports its rails back to the mezzanine with FMC_PG_C2M. gpioset holds a line only while the process runs, so use --daemonize to leave it asserted:
gpioset --daemonize FMC_PG_C2M=1
The line stays driven until that background process is killed. gpioinfo FMC_PG_C2M shows a consumer= annotation while it is held, and kill $(pgrep gpioset) releases it.
Accessing the FMC I2C bus¶
The FMC management bus appears as an ordinary Linux I2C adapter. Its adapter name is derived from the controller's address, so the FMC bus is the one named 20000080.i2c:
i2cdetect -l
Use the bus number from that listing with the standard i2c-tools commands. The VITA 57.1 FMC Standard places the mezzanine card's IPMI FRU EEPROM on this bus, which is the usual first thing to read from a newly installed card.
The bus runs at 100 kHz. Early revisions of both carriers have no hardware pull-ups on the FMC I2C lines, so the design enables the FPGA's weak internal pull-ups. Those internal pull-ups are not strong enough on their own, and later board revisions add hardware pull-ups alongside them.
Configuring the FMC user I/O muxes¶
This section applies to the MitySOM development kit only. The MitySBC connects the FMC user I/O pairs directly to FPGA banks and has nothing to configure.
On the MitySOM development kit every FMC LA pair passes through an analog 2:1 mux, a TI TMUX121, on the carrier board, which selects which of two FPGA pins the pair is wired to:
| Mux position | FPGA destination | Electrical standard | Bank VCCIO |
|---|---|---|---|
| select low | HVIO bank pin | single ended LVCMOS | VADJ, 1.8 V by default, may be set to 3.3 V |
| select high | HSIO bank pin | true differential LVDS | 1.3 V, fixed |
Because the two destinations are different FPGA pins, the pin assignments in your Quartus project have to match the mux setting. Both pin numbers are listed for every pair in Table 17 of the MitySOM-A5E Standard Development Kit Datasheet. A pair cannot be split, because the mux switches both halves together: one half cannot go to an HVIO pin while the other goes to an HSIO pin.
Two controls matter:
- FMC_MUX_EN enables every mux on the board. It drives the mux enable input, which is active low, so drive it low to enable. While it is high, every mux is high impedance and no LA pin reaches the FPGA at all.
- FMC_SEL_LAnn selects the destination for one pair. Low selects the HVIO pin, high selects the HSIO pin.
The overlay enables the three I/O expanders that carry these controls, and names every line after the pair it controls, so libgpiod addresses them by name rather than by number:
gpioinfo | grep -E 'FMC_MUX_EN|FMC_SEL'
As with any other line, gpioset --daemonize is required for a setting that has to persist. Without it the line is released as soon as gpioset exits. To enable the muxes and route the LA06 pair to its HVIO (LVCMOS) pin:
gpioset --daemonize FMC_MUX_EN=0 gpioset --daemonize FMC_SEL_LA06=0
To route the same pair to its HSIO (LVDS) pin instead, set the select high:
gpioset --daemonize FMC_SEL_LA06=1
Several lines can be passed to one gpioset invocation, which leaves a single process holding all of them instead of one process per pair.
Note: these control nets have no pull resistors on the carrier. An undriven select or enable floats and holds whatever it was last driven to, so no particular state can be assumed after reset. Drive the enable and every select your design uses explicitly rather than relying on a power-on default.
Troubleshooting¶
No FMC I2C adapter and no FMC GPIO lines¶
The overlay was not applied. Check the U-Boot console for the line applying the carrier's fmc dtbo, and confirm the boot.scr on the FAT partition is the one generated alongside this FPGA image.
Writing to the regulator reports no error but the card stays unpowered¶
Read the state file back to confirm the write took effect, then check FMC_PRSNT_N to confirm the card is seated. FMC_PG_M2C is not a useful check on its own here, because its weak internal pull-up makes it read active even with an empty connector.
Nothing responds on the FMC I2C bus¶
Confirm the mezzanine supplies are enabled first, then check the I2C pull-ups noted above. The FMC management bus does not pass through the user I/O muxes, so the mux settings have no bearing on it.
No LA pin reaches the FPGA on the MitySOM development kit¶
FMC_MUX_EN is not being driven low. It drives an active low enable, so while it is high every mux on the carrier is high impedance and no LA pin reaches the FPGA. Check it with gpioinfo FMC_MUX_EN, and bear in mind the net floats when nothing is driving it. This does not apply to the MitySBC, which has no muxes in the FMC user I/O path.
An LA pair arrives on the wrong FPGA pin on the MitySOM development kit¶
That pair's mux is routing it to the other destination. Each pair reaches a different FPGA pin depending on whether its select is low (HVIO) or high (HSIO), and both pin numbers are listed in Table 17 of the MitySOM-A5E Standard Development Kit Datasheet. Confirm the select matches the pin your project assigns. This does not apply to the MitySBC, whose FMC user I/O pairs go straight to FPGA banks.
FMC_MUX_EN has no effect on the MitySOM development kit¶
The signal is left floating on the -1 and -2 revisions of the MitySOM development kit carrier board and needs a pull-up. See the rework notes on Development_Board_Schematics_and_Revision_Information.
None of these control nets carry pull resistors, so an undriven line holds its last driven level rather than settling to a defined state. Drive the enable and the selects explicitly.
References¶
- FPGA Mezzanine Card standards overview, VITA
- Development_Board_Schematics_and_Revision_Information - MitySOM development kit schematics and rework notes