I2C PROTOCOL
Hola Amigos
I2C devices have been around us from a long time. If you have done any arduino projects with any peripherals such as Bluetooh (HC-05) or Gyroscope (MPU6050) or Barometer etc you might be surprised you have already used I2C devices. Yes
I2C devices have been around us from a long time. If you have done any arduino projects with any peripherals such as Bluetooh (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 micro controller 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 slave without having nay permission from the master.
You may have come across multi master schematic but it become much more complex to handle such situation because of data leakage and also it requires more than 1 micro controllers. So if you are using an I2C you cannot use any other non-I2C device on the same bus as bothe 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 acknowledgement 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.
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 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 concated value of 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 address of register
At Line 65 :- if rw ==0 we will recieve data which has to be written hence same process is followed too.
Here is the full code -:
Master Code-:
module master(data,address,clk,rw,sda,scl,register,data_wr);
output reg sda;
input [7:0] data;
input [7:0] data_wr;
reg [7:0]data_wr_dup;
input clk;
input rw;
output reg scl;
input [6:0] address;
input [7:0] register;
reg [8:0] temp;
reg [7:0] register2;
reg pstate;
reg scl2x;
reg ack;
reg a;
integer i;
integer n;
initial begin
i = 0;
n = 0;
scl2x = 0;
ack = 1'b1;
sda = 1;
scl = 1;
#5 sda = 0; //START BIT condition starts here
end
always @(negedge sda)
if(scl==1)
n=1;
always @(posedge clk)begin
ack = 1;
temp = {address,rw,ack};
register2 = register;
data_wr_dup = data_wr;
if(n==1 && rw==1)
repeat(50)begin
#2 scl <= !scl;n=0;
#1 scl2x <= !scl2x;n=0;
end
else if(n==1 && rw==0)
repeat(64) begin
#2 scl = !scl;
#1 scl2x = !scl2x;n=0;
end
end
always @(posedge clk)begin
if(i==25 && rw==1)
repeat(2)
#1 scl2x = !scl2x;
else if(i==32 && rw==0)
repeat(2)
#1 scl2x = !scl2x;end
always @(posedge scl2x)begin
if(i<=9)begin
sda = temp[8];
temp = temp<<1;
end
else if(i==12 || i==13)
sda = 1'b0;
else if(i>=14)begin
sda = register2[7];
register2 = register2<<1;
end
if(rw==0 && i>=23)begin
sda = data_wr_dup[7];
data_wr_dup = data_wr_dup<<1;
end
i = i + 1;
if(i>32 && rw ==0)
sda= 1;
else if(i>25 && rw==1)
sda = 1;
end
slave slv(data,sda,scl);
endmodule
And here is the code for Slave-:
module slave(out,sda,scl);
input sda;
input scl;
output reg [7:0]out;
integer j = 0;
reg [6:0]temp;
reg [7:0]add;
reg rw;
reg [7:0]register_address;
reg bitin;
reg [7:0]storage[0:38];
initial
storage[37]=16;
parameter address = 7'b1101001;
always @(posedge scl)begin
//if({sda,scl}==2'b01)begin
bitin = sda;
if(j<8)
temp = {temp,bitin};
if(j==8)
if(bitin==0)
rw = 0;
else
rw = 1;
j = j +1 ;
if(temp==address && (j>15 && j<24) && rw==1)begin
add = {add,bitin};
end
if(temp==address && rw == 0 && j>15 && j!=24 && j<33)begin
add = {add,bitin};
end
else if(j==24)
register_address = add;
if(j==33 && rw==0)
storage[register_address]=add;
out = storage[add];
end
endmodule
And here is the testbench _-:
module tbmast;
// Inputs
reg [6:0] address;
reg [7:0] register;
reg [7:0] data;
reg [7:0] data_wr;
reg clk;
reg rw;
// Outputs
wire sda;
wire scl;
// Instantiate the Unit Under Test (UUT)
master uut (
.address(address),
.register(register),
.clk(clk),
.rw(rw),
.sda(sda),
.scl(scl),
.data(data),
.data_wr(data_wr)
);
initial begin
// Initialize Inputs
address = 105;
register = 7'b0100101;
clk = 0;
rw = 0;
data_wr = 20;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
end
always
#1 clk = !clk;
endmodule
Here is the waveform for rw==0 means write a data to register
Better ZOOM it
Master Model
Slave ModelSo Long
Can it be restarted ?
ReplyDeleteIndeed just put sda=0 in test bench but after certain time
Delete