Skip to content

Instantly share code, notes, and snippets.

@rigred
Last active June 15, 2023 13:10
Show Gist options
  • Save rigred/850ea8929c1faa35ea3a067852b04400 to your computer and use it in GitHub Desktop.
Save rigred/850ea8929c1faa35ea3a067852b04400 to your computer and use it in GitHub Desktop.
PCI-e bus bandwidth calculation

How PCI-e bandwidth and actual true data bandwidth can be calculated.

PCI-e 1.x uses an 8/10b encoding scheme, so to send 8 bits of data, 10 bits of encoded data must be transfered. 2 of those bits are there as error checking and correction bits to account for interference which is very common on fast buses. SATA btw also uses 8b/10b encoding, you loose 20% of bandwidth (1-8/10) to get the data across.

PCI-e 1.0 is clocked at 2.5Ghz, it sends 1 bit per clock cycle and each lane corresponds to a 1 bit bi-directional serial channel. Which is kind of neat since here 'Gigatransfers' indicate 1 bit transfered for every clock cycle. This should immediately tell us that unlike FSB which transfers multiple bts per cycle in a parallel fashion, PCI-e is serial, since we are sequentially throwing 1 bit of data per cycle onto the bus and it takes multiple cycles to send a full byte. While on a parallel bus multiple bytes can be sent per cycle.

So to calculate the overall unidirectional bandwidth of a single lane of a PCI-e 1.0 bus we take the clock rate of the bus and divide it by the encoding rate (10). So we get 2500Megacycles/second divide by 10bits = 250Megaytes per second. But this is a weird number, because we are using 10bit wide bytes. And this is also not the real usable data rate. Rathere there are 2 additionaly ECC (Error Checking and Correcting) bits part of the 10bit encoding rate. We can remove these from the overall usable data rate. The real data rate then is the number of lanes (1x) multiplier by the clock rate (2500Mhz) multiplied by the fraction of the data rate(8bits) over the encoding rate(10bits) multiplied by the number of directions (1 for unidirectional) divided by the number of bits in a byte.

Finally to get our answer in GB/s we divide by 1000.

For a single PCI-e 1.0 link this can be written as follows:

1x Link PCI-e 1.0 uni-directional

1x (lanes) 2500 (clock rate in Mhz) * (8/10) (data over encoding) * 1 (directions) / 8 (bits per byte) = 200MB/s

1x Link PCI-e 1.0 bi-directional

1x (lanes) 2500 (clock rate in Mhz) * (8/10) (data over encoding) * 2 (directions) / 8 (bits per byte) = 400MB/s

And if we want to do multiple lanes?

16x Link PCI-e 1.0 bi-directional

16x (lanes) 2500 (clock rate in Mhz) * (8/10) (data over encoding) * 2 (directions) / 8 (bits per byte) = 8000MB/s

But what if we want to calculate for PCI-e Gen 3.0?

Ignoring all else, PCI-e gen 3 uses a 8GHz clock rate (Yip it's the fastest bus in your system by far) and uses a 128b/130b encoding scheme. So first thing that changes is we no longer have a nice 8bits in 1 byte unit alignment. There are now 16bytes (16x8bits) (128bits) plus 2 error checking bits.

So for a single lane of uni-directional traffic our math changes to the following:

1x (lanes) 8000 (clock rate in Mhz) * (128/130) (data over encoding) * 1 (uni-directional) / 8 (bits per byte) = ~969.47MB/s

And for 16 lanes of uni-directional, we simply multiply by 16 again.

16x (lanes) 8000 (clock rate in Mhz) * (128/130) (data over encoding) * 1 (uni-directional) / 8 (bits per byte) = 15511.48MB/s or 15.51GB/s

And for 16 lanes of bi-directional, we simply multiply by 16 again.

16x (lanes) 8000 (clock rate in Mhz) * (128/130) (data over encoding) * 2 (bi-directional) / 8 (bits per byte) = 31507.69MB/s or 31.508GB/s

PCI-e Gen 4 uses the same encoding scheme but runs at 16Ghz, and PCI-e Gen 5 at an insane 32GHz. You do the math.

@ahogen
Copy link

ahogen commented May 22, 2023

1 × 8000 × (128÷130) × 1 ÷ 8 = 984.6154

I'm confused. 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment