module SMBus(clk,sda,scl,en,count //,data,clksynth,count,hold
);
input clk;
inout sda;
input en;
output scl;
//=====simulation outputs
output count;
//output [15:0] clksynth;
//output hold;
//output [9:0] data;
//output [5:0] count;
//======================
reg sdareg;
initial sdareg = 1'b0;
reg [15:0] clksynth;
initial clksynth = 16'b0;
reg init;
initial init = 1'b0;
reg scl_;
initial scl_ = 1'bz;
wire _scl_ = scl_;
wire scl = init ? _scl_ : 1'bz;
reg [17:0] data;
initial data = 18'b011101100000001001;//data[17] = start, data[16:10] = SlaveAddress, data[9] = Write
reg [5:0] count;
initial count = 6'b0;
reg ss;
initial ss = 1'b0;
wire sda = ss ? 1'b0 : 1'bz;
//============generate SCL======================
always @(posedge clk)begin
clksynth <= clksynth + 1'b1;
if(en)begin
scl_ <= clksynth[12] ? 1'b0 : 1'bz;
end
if(~en)begin
scl_ <= 1'bz;
end
if(count == 6'd20)begin
scl_ <= 1'bz;
end
end
//==============================================
reg [3:0] state;
initial state = 4'b0;
reg hold;
initial hold = 1'b0;
always @(negedge _scl_)begin
if(en)begin
if(count > 6'b0)begin
init <= 1'b1;//set SCL to high impedance before start condition
end
if(hold == 1'b1)
ss <= 1'b0;//set SDA to high impedance while waiting for ACK
else if(hold == 1'b0)begin
if(data[17] == 1'b0)//pull low (data = 0)
ss <= 1'b1;
else if(data[17] == 1'b1)//high impedance (data = 1)
ss <= 1'b0;
end
//=========state machine to shift data bits==========
case(count)
6'd0:begin
count <= count + 1'b1;
data <= data<<1;
end
6'd1:begin
count <= count + 1'b1;
data <= data<<1;
end
6'd2:begin
count <= count + 1'b1;
data <= data<<1;
end
6'd3:begin
count <= count + 1'b1;
data <= data<<1;
end
6'd4:begin
count <= count + 1'b1;
data <= data<<1;
end
6'd5:begin
count <= count + 1'b1;
data <= data<<1;
end
6'd6:begin
count <= count + 1'b1;
data <= data<<1;
end
6'd7:begin
count <= count + 1'b1;
data <= data<<1;
end
6'd8:begin
hold <= 1'b1;//wait for ACK
count <= count + 1'b1;
end
6'd9:count <= count + 1'b1;
6'd10:begin
if(sda == 1'b0)begin//continue on ACK
count <= count + 1'b1;
hold <= 1'b0;
data <= data<<1;end
end
6'd11:begin
count <= count + 1'b1;
data <= data<<1;end
6'd12:begin
count <= count + 1'b1;
data <= data<<1;end
6'd13:begin
count <= count + 1'b1;
data <= data<<1;end
6'd14:begin
count <= count + 1'b1;
data <= data<<1;end
6'd15:begin
count <= count + 1'b1;
data <= data<<1;end
6'd16:begin
count <= count + 1'b1;
data <= data<<1;end
6'd17:begin
count <= count + 1'b1;
data <= data<<1;end
6'd18:begin
hold <= 1'b1;//wait for ACK
count <= count + 1'b1;end
6'd19:count <= count + 1'b1;
6'd20:begin
if(sda == 1'b0)begin
hold <= 1'b0;
data <= data<<1;end
end
endcase
//=====================================================================
end
end
endmodule