CODE - Rutujakage1/I2C-Protocol-using-Verilog GitHub Wiki

How does the Code Work?

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;]

VERILOG CODE

Part 1 : Code for Slave

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

Part 2 : Code for Master

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

Part 3 :Test Fixture

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

⚠️ **GitHub.com Fallback** ⚠️