How to enjoy I2C by EFB inside Lattice FPGA?

A project log for HDL training board by FPGA for real beginner

Previously I've made CPLD board, but eventually new FPGA version!

kodera2tkodera2t 08/15/2017 at 02:060 Comments


Now this board is available at tindie store!

Lattice MachO2 has a wonderful embedded block enables handy I2C device creation. Here I would like to show you how to enable it. Starting from scratch is far beyond my level and let's start from Lattice's reference design.

(1) Get files from Lattice site

By googling "RD1124 Lattice" will guide you the download site. Just click zip file and download it.

(2) Extract zip and place it on your folder

Inside zip file, it contains "rd1124" and let's put it in, for example document folder

(3) Open project file

Inside rd1124 folder, it contains files both for MachXO3 and MachXO2. Let's confirm the file inside project/xo2/verilog. Now execute Lattice Diamond and select the project file...

(4) Change program device

The default device is 132pins version but my board is TQFP100 version of LCMXO2-1200HC. Let's change the device by right click on the device name.

The appropriate selection is shown above. Please don't forget to change package type to TQFP100.

(5) Source file modification

The original sample file assume 132pins version and it cannot be fit inside TQFP100 version (lack pins). Let's change values of i2c_gpio.v as above and save file...

(6) Rerun synthesize by modified verilog file

On the process tab, right click on "Lattice Synthesis Engine" will create new file along the modification. Just parameter change will not make any error...

(7) Pin layout definition

Currently pin layout is not still defined. Click "Spreadsheet View" will show you the layout window..

First of all, let's change logic level from 2.5V to 3.3V. Multiple selection by shift-click and right click and select "LVCMOS33" will change all of pin logic at once.

Now input pins can be written as above (along my board connection). Clock is injected to pin 63 in my board but we need to adjust it design by design. Five GPIO input are connected to tactile switch in my board. Just to be noted is pull mode of RST_N. It should be "UP", otherwise it will remain reset.

And let's define output pins.  In my board, Pins of GPIO_0 (1, 2, 4, 7, 8, 13, 16, 17) are connected to LED bus and 21, 24, 25 are device selection (active low). It will not hurt but let's set them all "NONE" for pull mode.

(8) Device programming setting

Let's check "JEDEC file" in Export File and right click to "Rerun". This will not show any error if pinout can be fit inside FPGA.

Now let's connect board to computer!

Now let's add "Programming File" by right click and Add->New file and

Select "Other Files" in categories and name it. The name does not matter, and click "New"

It will show you device scan selection and just click "OK"

After certain period, you will see the device scan result. It is yellow but don't need to care about it. Just confirm "File Name" column is not empty but filled as above picture.

(9) Finally Program!

Just click "Programmer" and

"Program" will make your board to be I2C controlled GPIO board!!

How to configure I2C of EFB??

The above sample is just using preconfigured I2C block in sample, but of course we can configure them by very quick way.

From Tools menu, click "IPexpress"

We can see vast number of wonderful possibility (these functions, not limited to EFB, can be tailored and utilize!) but just click "EFB" and set up Project Path by Browse button.

The default folder to be set for IPexpress is source/verilog/ipexpress/xo2. Just select Folder and

name file "efb" and Module Output as "Verilog" and click "Customize"

You will see confirmation of overwrite. Yes, it means the modification will reflect on the current project. Click "OK"

We have SPI, Timer/Counter and PLL and Flash memory in addition to I2C!!. Current interest is I2C and it has three types, Primary Configuration, Primary User, and Secondary User. MachXO2 has two I2C block and Primary user is connected to pre-defined pins (86 and 85 for SDA, SCL) but Secondary User can take arbitral pins for SDA/SCL. Let's check only "Primary user" and click "I2C" tab.

Here we can define I2C device address. Two bit of LSB are preserved for Primary/Secondary/Configuration blocks and let's modify it to "0001001"=0x09 for slave. In addition we can select high speed mode (400kHz). Just modify parameters as you wish and click will generate the corresponding sources.

After generation, just re-synthesize and re-program FPGA will make it.

How to drive I2C ?

The implemented I2C device is slave and we need master controller. Indeed any Arduino can work for it. (3.3V version of Arduino is recommended but 5V is also work because I2C bus is pull-up by 3.3V inside FPGA board.). Just connect GND and A4(SDA) and A5(SCL) and write the sketch will full blink all of LEDs.

#include <Wire.h>
int disp=1;
void setup() {
///activate 0x09 device
  Wire.beginTransmission(0x09);//select 0x09
  Wire.write(0x06);//"activate" command
void loop() {
byte regis_num=1,tmp;
////select LEDs(0x00) or 7seg-LEDs(0x01 or 0x02)
////by the valuve of GPIO_1
  for(int j=0;j<3;j++){
    Wire.beginTransmission(0x09);//select 0x09
    Wire.write(0x01);//"write GPIO" command
    Wire.write(0x01);//select GPIO_1
    Wire.write(~regis_num);//write ~regis_num(negative logic)
//////write value of GPIO_0
  for(int i=0;i<8;i++){
    Wire.beginTransmission(0x09);//select 0x09
    Wire.write(0x01);//"write GPIO" command
    Wire.write(0x00);//select GPIO_0
    Wire.write(~disp);//write ~disp value
  for(int i=0;i<8;i++){
    Wire.write(0x01);//"write GPIO" command
    Wire.write(0x00);//select GPIO_0
    Wire.write(~disp);//write ~disp value
      regis_num=regis_num<<1;//one bit shift

After activation by command "0x06", we can switch GPIO pins in FPGA as we wish....