This is an I2C lab exercise to help a student or developer become acquainted with the FPGA architecture & tools for Private Island™. It is assumed that the developer has already built images for both the FPGA and K02 ARM micro controller (µC). Also, the developer should be familiar with the other related documentation on this site (see below).
This particular lab walks the developer through setting up the Reveal debug files and session so they can view the internal workings of the I2C slave circuit. The µC sends commands to the internal FPGA controller (controller.v) via the I2C bus. The command set is defined in the article Private Island External Register and Memory Interface. Example commands include reseting the PHYs, peeking and poking PHY registers, and polling the Ethernet line status.
Note that this article was created using Git commit bbe7e48e. A developer has the option to either re-create the Reveal files that are shown below or open the labs.rvl and labs.rva files included in the Diamond project under the boards folder.
If you're working with an oscilloscope, there is also an option to mirror the I2C bus on the Arduino-compatible COMMUNICATION connector pins: SCL and SDA. See the Darsena Hardware Specification for pin details. You'll also want to make sure DEBUG_I2C is defined under Debug Options in definitions.v
Some notes about the current I2C implementation:
- The code requires a clean up.
- The "dedicated memory interface" referred to in the code is not supported and may be removed. SPI is currently used to interface with the FPGA internal memories.
- SCL (I2C clock) is routed as a data signal and is sampled by the internal 10 MHz clock (clk_10). If you're familiar with I2C, you know that SCL really isn't a clock and data (SDA) is defined as stable when SCL is high. Sampling SCL by a faster clock allows for deglitching the line and eliminates the need to use a primary clock lane for SCL.
The figure below shows the Lattice Reveal Inserter for lab_1_i2c. We add signals to be traced by dragging them into the Trace Window from the Design Tree. If you're unfamiliar with Reveal, please review the Reveal User Guide. It's a quick read and is well written.
Not shown is the Trigger Signal Setup pane. We simply add the start signal as our TU (Trigger Unit). Also note that we are using the top level clk_10 clock as our sample clock.
The two traces below were generated in a live system while stepping through the µC ecp5_pcs_init() routine in ecp5_driver.c.
Figure 2 is generated when stepping over:
i2c_write(pXfer,I2C_ECP5_ADDR, (uint8_t*) &pcs_s, sizeof(pcs_s));
If you look for cont_we pulsing high, you'll see that the data being clocked is 0x70, 0xd, which is ASCII "P CR"
Figure 3 is generated when stepping over:
i2c_read(pXfer, I2C_ECP5_ADDR, (uint8_t*) pBuff, 8);
If you look for fifo_re pulsing high, you'll see that the data being read is 0x30, 0x30, 0x33, 0x30, which is ASCII "0030", and this is the current value of the internal PCS status register.
We'll keep adding to this I2C lab and also create new ones as the year progresses. If you're a student and interested in working on this project, please visit our Education link at the top of this page.