CODE - Rutujakage1/I2C-Protocol-using-Verilog GitHub Wiki
In this code we consider master and a single slave .The Master will send 7-bit address along with RW bit on the SDA line and the corresponding slave will respond back with an ACK bit. After that Master will send the register address which will be acknowledged by the slave with an ACK bit. Then the slave will send the 8-bit data from the received register to the Master.
After receiving the data, Master will respond back with ACK bit and after a Clock Cycle the I2C operation will end with the STOP bit.
The SCL line changes only when SDA is stable. The testbench acts as a supervisor which provides a clock signal to Master. The Master is connected to the slave only with SDA and SCL line.
The SDA has to be an inout line or else it won't be a proper I2C model, despite serving the same functionality.Inout command should only be used using a tri-state buffer.
[coded as: x <= direction?data:1'bZ;]
module SLAVE(
inout sda,
//*The SDA has to be an inout line *//
input scl
);
parameter [6:0] address = 7'b1101001;
reg [7:0] temp = 8'bx;
reg [6:0] s_add;
parameter [6:0] register = 7'b1001010;
reg[7:0] array[0:75];
reg[7:0] array2[0:75];
reg ack;
reg scl2;
reg [7:0]x;
initial begin
scl2 <= 0;
x = 0;
array[74] = 8'b00011101;
end
always @(negedge scl)
begin
ack <= sda;
#1 forever #2 scl2 = !scl2;
end
reg alpha = 0;
reg direction = 0;
integer n = 1;
assign sda = direction?alpha:1'bz;
always @(negedge sda)
begin
if(scl == 1 && n==30)
n = 1;
end
/always @(negedge scl)begin
ack <= 0;
temp <= {temp,ack};
end/
always @(negedge scl2)
begin
if(n<=8)
begin
temp <= {temp,sda};
n <= n + 1;
end
else if(n==9)
begin
temp = {temp,sda};
if(temp[7:1]===address)
begin
direction <= 1;
alpha <= 1;
end
else
begin
direction <= 1;
alpha <= 0;
end
//temp <= {temp,sda};
n <= n + 1;
end
else if(n==10)
begin
if (temp[7:1] !== address)
begin
direction <= 0;
n <= 1;
end
else
begin
direction <= 0;
n <= n + 1;
end
end
else if(n>=11 && n<=17)
begin
s_add <= {s_add,sda};
n <= n+1;
end
else if(n==18)
begin
s_add = {s_add,sda};
direction <= 1;
if(s_add==register)
alpha <= 1;
else
alpha <= 0;
n <= n + 1;
end
else if (n==19)
begin
alpha <= 0;
x <= array[s_add];
n <= n + 1;
end
else if(n>=20 && n<=28)
begin
//alpha <= array[s_add][7];
//array[s_add] <= array[s_add]<<1;
alpha <= x[7];
x <= x<<1;
n <= n + 1;
end
else if(n==29)
begin
direction <= 0;
n <= n + 1;
//array[74] <= array2[74];
end
else
ack = sda;
//n <= n + 1;
end
endmodule
module Master(sda,scl,clk);
inout sda;
input clk;
output reg scl;
reg scl2;
reg ack;
reg direction;
reg alpha;
reg [6:0] address;
reg [7:0] temp;
reg [7:0] temp_reserved;
reg rw;
reg[6:0] register;
reg[6:0] reg_temp;
reg a;
initial begin
a = 0;
rw = 1;
scl = 1'b1;
scl2 = 1'b1;
direction = 1;
address = 7'b1101001;
register = 7'b1001010;
temp = {address,rw};
temp_reserved = {address,rw};
reg_temp = register;
alpha = 1;
#5 alpha = 0;
fork
#160 alpha <= 0;
#160 direction <= 1;
#162 left_bits <= 1;
join
end
always @(posedge clk)
begin
if(a==0)
scl <= 1;
else if(a==1)
scl <= !scl;
end
always @(negedge sda)
a <= 1;
always @(negedge clk)
begin
if(sda == 0 && scl == 1)
forever #2 scl2 <= !scl2;
end
always @(sda)
begin
if(scl==1'b1)
begin
scl <= 1'b1;
end
end
integer left_bits = 1;
always @(negedge scl2)
begin
if(left_bits <= 8)
begin //Sending Slave Address//
alpha <= temp[7];
temp <= temp<<1;
left_bits <= left_bits + 1;
end
else if(left_bits == 9)
begin //Receive ACK bit from Slave//
direction <= 0;
ack <= sda;
left_bits <= left_bits + 1;
end
else if(left_bits == 10)
begin
if(sda == 0)
begin //ACK = 1 Resend the Slave Address//
left_bits <= 1;
direction <= 1;
temp <= temp_reserved;
end
else
begin //ACK = 0 Get Ready to send Register Address//
direction <= 1;
alpha <= 0;
left_bits <= left_bits + 1;
end
end
else if(left_bits >=11 && left_bits <=17)
begin //Sending 7-bit Register Address//
//if(left_bits <=17)begin
alpha <= reg_temp[6];
reg_temp <= reg_temp<<1;
//end
left_bits <= left_bits + 1;
end
else if (left_bits >= 18 && left_bits <= 28)
begin //ACK from Slave and 8 bit Data from Slave//
direction <=0;
left_bits <= left_bits + 1;
end
else if(left_bits == 29)
begin //*ACK from Master *//
direction <= 1;
alpha <= 1;
left_bits <= left_bits + 1;
end
else if(left_bits == 30)
begin
alpha <= 0;
left_bits <= left_bits + 1;
end
else if(left_bits == 31)
begin //** STOP Condition **//
#2 alpha <= 1;
//a <= 0;
left_bits <= left_bits + 1;
end
else if(left_bits == 32)
begin //** STOP Condition **//
a <= 0;
temp <= temp_reserved;
reg_temp <= register;
left_bits <= left_bits + 1;
end
//left_bits <= left_bits + 1;
end
assign sda = direction?alpha:1'bZ;
SLAVE Sl1(sda,scl);
Endmodule
module test12c;
// Inputs
reg clk;
// Outputs
wire scl;
// Bidirs
wire sda;
// Instantiate the Unit Under Test (UUT)
Master uut (
.sda(sda),
.scl(scl),
.clk(clk)
);
initial
begin
// Initialize Inputs
clk = 0;
end
always #1 clk =( ~clk);
endmodule