Now that we can issue read and write transactions on the bus, wouldn't it be fun to "see" how the transactions actually look like?
Here's a very simple transaction that was captured with Dragon.
During the address phase, CBE is 0x3, which means "IO Write".
It's an IO Write, data 0x00000000, at address 0x0200.
Looking at the signals usually requires expensive equipment, like bus extenders and logic analyzers. That can be tricky because the PCI specification doesn't allow more than one IO load on each PCI signal (per PCI card of course). That's because the bus is sensitive to capacitive loads or wire stubs that would distort the high-speed signals.
But couldn't the FPGA act like a logic analyzer?
The FPGA is already connected to the bus, and has internal memories that can be used to capture the bus operation in real time. Dragon has also a USB interface that can be used to dump out the PCI captures without disturbing the PCI interface implementation, even if the PCI bus "dies".
The FPGA can also easily create complex triggers conditions that would outsmart most logic analyzers... what if you want to capture the 17th write after the second read at address 0x1234?
wire [47:0] dsbr = { PCI_AD, PCI_CBE, PCI_IRDYn, PCI_TRDYn, PCI_FRAMEn, PCI_DEVSELn, PCI_IDSEL, PCI_PAR, PCI_GNTn, PCI_LOCKn, PCI_PERRn, PCI_REQn, PCI_SERRn, PCI_STOPn}; |
case(USB_readaddr[2:0]) 3'h0: USB_Data <= bro[ 7: 0]; 3'h1: USB_Data <= bro[15: 8]; 3'h2: USB_Data <= bro[23:16]; 3'h3: USB_Data <= bro[31:24]; 3'h4: USB_Data <= bro[39:32]; 3'h5: USB_Data <= bro[47:40]; 3'h6: USB_Data <= 8'h01; // padding, added for ease of implementation 3'h7: USB_Data <= 8'h02; // padding, added for ease of implementation endcase |
ReadIO_DWORD( 0x200 ); ReadIO_DWORD( 0x204 ); ReadIO_DWORD( 0x208 ); ReadIO_DWORD( 0x210 ); WriteIO_DWORD( 0x204, 0x12345678 ); WriteIO_DWORD( 0x208, 0x87654321 ); WriteIO_DWORD( 0x210, 0xDEADBEEF ); ReadIO_DWORD( 0x200 ); ReadIO_DWORD( 0x204 ); ReadIO_DWORD( 0x208 ); ReadIO_DWORD( 0x210 ); |