Verilog Code for I2C Protocol



Hola Amigos
I2C devices have been around us for a long time. If you have done any Arduino projects with any peripherals such as Bluetooth (HC-05) or Gyroscope (MPU6050) or Barometer etc you might be surprised you have already used I2C devices. Yes

An I2C basically consists of a master microcontroller and a slave device which responds to the requests of the master. A slave cannot operate on its own. It can't even communicate with other slaves without having any permission from the master.

      You may have come across multi-master schematic but it becomes much more complex to handle such situation because of data leakage and also it requires more than 1 microcontrollers. So if you are using an I2C you cannot use any other non-I2C device on the same bus as both SDA and SCL lines are in conjunction with the I2C module. If you find this facility somewhere you are being fooled seriously !!!
 I2C works on 2 signals as SCL and SDA
                                           SCL - Serial Clock
                                           SDA- Serial Data
When SDA is having negedge and SCL is positive level triggered then we have start signal and with every SCL clock, a bit is transferred. Combining up to eight bit the slave receives an address. Then come the R/W signal means whether the slave has to read or write from/to address. AT the very moment after R/W bit the last bit known as acknowledgment bit is sent. Then the slave sends bit by bit data and finalizing by the acknowledge bit and the process comes to a STOP.

Do remember that when SDA changes the SCL lines must remain stable hence SDA doesn't change at posedge or nedge of SCL and only on the level of SCL i.e. either 1 or 0.

Here is a demonstration

Pic Credit- Google
 You can easily see the working as I have explained in comparison to the diagrams.
 Ok Coming down to the code

Starting with Master module and with its inputs

clk = Normal clock
sda = serial data
scl = serial clock
data_wr = data that has to be written if rw = 0;
address = address of slave
register = address of register which has to be read
rw = read or write pin

Next, we move to the declaration of internal variables

temp = to copy address incoming
register2 = to copy register value
scl2x = clock with which sda works to change sda while scl is 0
i = internal counter
n = single counter for start and stop conditions

One must note that initially, we have sda and scl = 1 
After 5ns we turn sda to 0 to introduce start bit condition

From Line 28 to 30 :- we use n as a flag to start scl and scl2x to start bit transmitting
At Line 33 :- Temp stores the concatenated value of the address of slave then rw bit and                                                acknowledge bit
At Line 34:- Incoming register address is stored in register2 internal variable because further we will be using shift operators which doesn't work on wires and always does on reg data type.
At Line 36 :- If n==1 means start condition and if rw=1 means we have to read register thus                        scl will run upto 50 times
                       Similarly, for rw=1 means, we have to write scl will run 64 times.
                       The value 50 and 64 can be obtained by self-coding 

This piece of code is for stop bit condition.

At Line 55 :- Till value of i reaches 9 we will grab bit by bit from temp
                       Here temp is having 6 bit slave address and 2 bits of rw and ack. Thus each bit                          is being read by shifting temp one by one and reading its MSB
                       Same is happening after Line 60 to get the address of the register
At Line 65 :- if rw ==0 we will receive data which has to be written hence the same process is followed too.

Get the full code with the following link
Kindly Disable your popups

Click Here to get the code

Here is the waveform for rw==0 means write a data to register
Better ZOOM it

Master Model
 Slave Model

So Long


  1. Replies
    1. Indeed just put sda=0 in test bench but after certain time

  2. Hello,
    J is used here as a counter to initiate operations at approprite timings.

  3. /* input data */ in the master program where it is used???

  4. why input data is declared in master code?

  5. Hello @Ajisha, @anonymous,
    Slave devices never have any third connection (out[7:0]) as I have used here. They transfer data back on the SDA line which is read by the master. This would make the code very complicated. Thus for simplicity, we used a separate out[7:0] register to output the data.

    The input[7:0] data in the master is a used line. It will receive data back from the slave if the rw bit is meant to read data. It won't work if data is meant to be written. It is connected with the out[7:0] from slave so that the data can be read back in the master. This is how real I2C devices work.The data that will be sent to the slave by the master is processed by data_wr wire which is incorporated into test bench.

    Have a nice day

  6. Awesome article. Worked perfectly with Xilinx. Had issues with ModelSim. Did you try on Model Sim ?

    1. Hi Tesla,
      Thanks for the compliment. Well yes, Shashi had many issues regarding ModelSim while he was working on I2C. Also the RTL viewer in Xilinx provided a bonus to work upon.

  7. If the transmission of the slave address is successful and recognized by the device, it should send the ACK as 0. But in the snippet of the simulation that you have given, the 9th bit, i.e the ACK bit is high. Does that mean it is a NACK? If so, why is it not re-transmitting the slave address and instead sending the register address? Also why do we have a stream of 0's after the 9th bit? And why is 'data' declared as an input in the master module and not used anywhere except in the port declaration of the slave?

    1. Q Why do we have a stream of 0's after the 9th bit?

      A: For a Naive Reason. To make it visually easy and understandable I used a stream of 0's. It can be modified.

      Q: Why is 'data' declared as an input in the master module and not used anywhere except in the port declaration of the slave?

      A: Because I have used a separate line as out from slave that connects to the input data in master. To avoid complexity and reading data back from slave on the same SDA line increased the complexity. It is just a wire connected between master and slave to read the data.

      Q: If the transmission of the slave address is successful and recognized by the device, it should send the ACK as 0. But in the snippet of the simulation that you have given, the 9th bit, i.e the ACK bit is high. Does that mean it is a NACK?

      A: No it is an ACK. Actually I hardcoded ack bit in the code because while my team was implementing this code on Basys2 FPGA, we had to face bit conflict issue i.e different bit at the same when Master tried to resend the address. That is why we used hard coded ACK in the code. Also its a mistake here. ACK = 0 and not 1. Thanks for pointing out.

      Have a nice day.

    2. You are welcome. Do follow us :)

  8. Thanks for the article!
    Can you tell me how to communicate with slave? How do we check the read operation? Since, the test bench is written for the master, how do we know if the value sent from the master is being written to the slave or not?
    Also, how do we read from the slave?
    Thank you.

    1. Hi There HiThere,
      Nice username by the way.

      You will have to select open the slave file on the left panel of simulator. Then right click on any of the wires and select "add to wave". This will instantaneously appear on the wave. Restart the simulation. You will certainly see the data stored inside the array of registers inside slave.

      To communicate with slave just pull the SDA line to zero in the test bench after a desired time.

      To read operation, firstly, you will have to send the RW bit as 1. Then mention the address of the register. The slave will send the data stored at that address on the out[7:0] line. However you will have to add that line to the wave by the same methid I described above.

    2. Thanks a lot for the quick reply.
      I meant, How do you include the slave instantiation inside the master's testbench and connect it to master and what are the connections that are to be made while doing that?

    3. Slave is not instantiated inside test bench. It is instantiated at line no.75
      It is a basic connection. Output from one module is input for another module. SDA and SCL are output in master. These are joined with slave as inputs. Similarly output from slave is output which is connected with master as input.

      Do check carefully while you are instantiating a module for correct order.
      Ex- Slave connections are Slave (output, input, input). The order inside is very important or else you may connect wrong wires.
      So instantiating slave in master at line no75 is Slave slv(data, sda, scl)

      data(input)<---------------------- out(output)
      SDA (output)-----------------------> SDA (input)
      SCL (output) -----------------------> SCL (input)

    4. Thanks a lot! That was really useful!!

  9. I am new to verilog. I have a few doubts in the code of slve module. Could you pleas help me

    1. What is the significance of bitin in the slave module. Why are we using it and what is it doing

    reg bitin;

    2. What does the following expression does. Could you give a few examples with the input and output
    temp = {temp,bitin};

    1. Hi,
      temp = {temp,bitin} This line will concatenate the bitin bit to the end of temp.
      Example if temp = 101011 and bitin = 0, then {temp,bitin} = 010110 and this will be stored in the temp itself.

      bitin helps to gather the data or address on SDA line which is to be stored for useful purposes.
      Example for(i<7) temp will store every bitin values repeatedly by concatenating it at the end of temp. This will be the address sent by the master. Similarly at i==8 SDA value is again stored in bitin which tells us whether rw is enabled or not.

      Actually I was having difficulties working with SDA wire hence I had to store the wire value locally to perform operations.


  10. subbu
    Hi I want to know the code for multi slave with single master

  11. How to communicate multiple slave with the same logic as you mentioned

    1. Hola,
      You will have to copy the code of slave and recreate a module named slave1 or anything different from previous one.
      Then you will have to change the line that says
      parameter address = **Unique Address**; in that particular slave code.
      Finally in the test bench set address = **Unique Address**.
      The if statement in each slave will first match the incoming address and only then it will start communication.
      Do remember to instantiate all slaves in master.

  12. Hello Thanks for the reply and if i want to communicate with one slave at a time and stop the operation of others how can i do it using the same logic even if the address does not match as you mentioned

    1. This code will work with only one slave at a time ONLY if you have assigned different address to each slave . If the address doesn't match then the variable in Slave module named "Register_address" will be equal to XXXXXX.

      Since the address won't match therefore, this if loop

      if(temp==address && (j>15 && j<24) && rw==1)begin

      will not execute.
      No need to worry. As long as Slave address is not matched, it will remain in a stop condition.
      Just remember to give different address to each slave and you are good to go.

  13. Hi i have a small error like
    ERROR:Xst:871 - "step 1.v" line 73: Invalid use of input signal as target.
    This is while instaniating slave code in master in Xilinx 9.2 version so say me how to fix that error.

  14. Hi the error is i m using data while instating slave as output in master code in the same way as you mentioned like Slave slv(data, sda, scl) but here the xilionx is saying that invalid use of data as target.

    1. You can't use data terminal for target. After contacting with slave, slave will send a data. Instead of keeping this data on SDA line, I have kept this information on *DATA* line for ease of use and visibility. So whenever communicated, the slave will send the data stored in it's arrays on the data line by *ITSELF*. If you want to see any particular data then store your data in the arrays inside the slave code.
      This is the line in slave that consists of an array to store data. -->
      reg [7:0]storage[0:38];
      storage[5] = "Your Data"

  15. Hi Shashi ,

    I wanted to read data from the slave .I updated rw and placed the register address after that. But I am unable to pull down SDA to low.Could you tell me how to do this ?

    1. Hi Jeffin,
      I have updated I2C here.
      You can visit the above link link for new working code.

  16. Can you tell me how to pull the sda line to low for sending next data.

    1. Hi.

      Follow this link

      Follow the note at the end of post where I have explained it.

    2. Hi Jishnu
      Follow this post where I have explained the working my code.


  17. Hi, 50 in line number 37, 64 in 42line,25 in 48th line ,32 in 51st line how do we get these values??

    1. These values were taken by trial and error because in real I2C there is no delay in clock cycles between Slave address, RW, ACK, Register Address. However, I preferred to use delay in order to increase the visibility and ease to find where is the Slave address, RW, ACK, Register Address.

      Follow this link for updated code....

    2. Hi, I have updated the post and the new link is this below


  18. Hi sir , we would like write the data into slave can you provide us logic
    thanking you sir.

  19. can you please explain clearly the code from line 31 to 64 in master.How you adjusted the clock and the use of scl2,alpha,direction,How that address and data shifting from slave to master

    1. This comment has been removed by the author.

    2. Hi Sindhu
      Follow this post where I have explained the working my code.


  20. sir we would like to interface fpga as master and lcd as a slave by using I2C communication protocol...could u please suggest us how to proceed further ....

  21. HELLO iam facing error in the 73 line in xilinx 14.5 version so please provide me the proper working code completly

    1. Check the link to new post at the top of this post

    2. Slave slv ( data ,SDA,scl) in this line we r getting error as unable to target the input signal ie data .please rectify error because I have project on this within 2days mail id is :

    3. Kindly post your code here.

      What error are you getting exactly?

  22. This comment has been removed by the author.

  23. do we need to include testbench? for viewing the RTL schematic diagram?becose for viewing the rtl schematic diagram we getting error in the 73 line as target input signal "data"is not found..

    1. As far as I have coded in Verliog RTL can be viewed without testbench. It selects the top module for RTL schematic

  24. Signal data_wr_dup[7] in unit master is connected to following multiple drivers:
    this is the error

  25. unable to get master RTL DIAGRAM

    1. kumar

      Try this link:

  26. As I said visit the new I2C code. I have made a new post. Search it in project above or you can find the link at the top of this post.
    Also simulation and implementation on FPGA (RTL) is different. Not every simulatio supports RTL because of some syntax like fork join etc. in the comment section of new post you can find *edited* code to view RTL schematic

    Here is the link

    So Long

  27. hi i am getting this error how to rectify it.
    ERROR:Xst:871 - "i2c_master1.v" line 98: Invalid use of input signal as target.

  28. This comment has been removed by a blog administrator.

  29. A newbie (Obviously), what I don't understand is how one actually reads data back from the slave device. I want to program a i2C EEPROM and later read the info back. All the variables in your top module are input only. Should the not be a "data_returned[7..0]. What am I missing?

    Thanks in advance

    John Monahan

  30. Error (10028): Can't resolve multiple constant drivers for net "data_wr_dup[7]" at TWI.v(54)

    1. Check This:

  31. Sir i wnt its explantion sir..mujhe y smj ni ara

  32. Delays are ignored in synthesis bro..,
    How is this going to work.
    I tried in xilinx ise but the waveform is not as intended in the code.

  33. sir i need slave code for the above master -code which i need to instantiate purpose


Post a Comment

Popular posts from this blog

SPI Working with Verilog Code

SR Flip Flop Verilog Code