Im ursprünglichen PCI-Framework ("Konventionelle PCI") und auch in PCI-X entsprachen die Geräte den "Steckplätzen", die jeweils über einen eigenen parallelen Bus verfügen. Jeder Slot hatte einen eindeutigen ID-Pin, der während der Aufzählung aktiviert wurde. Die Aufzählung bestand im Wesentlichen (für jeden Slot): "Hey, gibt es etwas in diesem Slot?" Das Gerät reagierte, indem es auf dieses Signal Daten auf den Bus ansteuerte. Fehlende Reaktion bedeutete kein Gerät.
Ein Gerät könnte auch eine "Brücke" sein, was bedeutet, dass es einen untergeordneten Bus bildete. Dieser Bus hätte eine separate ID (vom Upstream zugewiesen) und hätte seinen eigenen Satz von Slots, die unabhängig voneinander aufgezählt wurden.
PCI-Express (PCIe) ist völlig anders. PCIe ist nicht wirklich ein Bus - wie in einer von Geräten gemeinsam genutzten Ressource. Stattdessen verfügt jedes Gerät über eine eigene serielle Punkt-zu-Punkt-Verbindung zu seinem Upstream-Gerät (und zu allen Downstream-Geräten - und wenn es über Downstream-Geräte verfügt, funktioniert es auch als Bridge). Stellen Sie sich PCIe wie ein LAN vor. Jede Bridge ist analog zu einem Switch, an dem mehrere Ports mit anderen Geräten verbunden sind. Bei den anderen Geräten kann es sich um Endgeräte oder um andere Switches (z. B. PCIe-Bridges) handeln.
PCIe wurde so konzipiert, dass sein konzeptioneller Rahmen und seine Adressierung (und damit das Verhalten der Software) mit PCI und PCI-X kompatibel ist. Die Implementierung ist jedoch völlig anders. Bei der Aufzählung von Geräten ist die einzige Frage, die an jedem Punkt der Aufzählung bestimmt werden muss, "Punkt da?". Da jedes Gerät über einen eigenen unabhängigen Kabelsatz verfügt, sind die Geräte-IDs im Wesentlichen alle hart codiert (daher teilt jede Brücke, einschließlich des "Root-Komplexes" der obersten Ebene, jedem Gerät mit, welche Geräte-ID es sein wird).
In allen Fällen wird der Teil "Funktion" von Bus / Gerät / Funktion streng innerhalb des Peripheriegeräts behandelt. Beispielsweise hat ein NIC-Controller mit zwei Ports oft zwei Funktionen, eine für jeden Port. Sie können unabhängig voneinander konfiguriert und betrieben werden, der Datenpfad von der CPU zur Funktion ist jedoch für beide gleich.