| |
module i2cMstr (sdo,scl,sda);
input sdo;
output scl;
output tri sda;
integer i;
wire sdo;
reg drv_scl;
reg drv_sda;
reg [7:0] data;
pullup(sda);
pullup(scl);
assign sda = drv_sda? 1'bz : 0; //pull down
assign scl = drv_scl? 1'bz : 0; //pull down
reg clk;
always begin
#500 clk = 0;
#500 clk = 1;
end
initial begin
drv_scl=1'b1;
drv_sda=1'b1;
end
task start; //start condition
begin
@(posedge clk);
drv_sda = 1;
drv_scl = 1;
@(posedge clk);
drv_sda = 0;
@(posedge clk);
drv_scl = 0;
end
endtask
task stop; //stop condition
begin
drv_sda = 0;
@(posedge clk);
drv_scl = 1;
@(posedge clk);
drv_sda = 1;
@(posedge clk);
drv_scl = 1'b1;
@(posedge clk);
// @(posedge clk);
// drv_sda = 1'b1;
end
endtask
task rw_slave_addr;
input [6:0] slave_addr;
input rw;
begin
for(i=6; i>=0; i=i-1) begin
@(posedge clk);
drv_sda = slave_addr[i];
@(posedge clk);
drv_scl = 1;
@(posedge clk);
@(posedge clk);
drv_scl = 0;
end
@(posedge clk);
drv_sda = rw;
@(posedge clk);
drv_scl = 1;
@(posedge clk);
@(posedge clk);
drv_scl = 0;
@(posedge clk);
drv_sda = 1'b1;
@(posedge clk);
drv_scl = 1;
if(sdo != 0) $display("ACK error at time: %t", $time);
// if(sda != 0) $display("ACK error at time: %t", $time);
@(posedge clk);
@(posedge clk);
drv_scl = 0;
@(posedge clk);
end
endtask
task send_byte;
input [7:0] send_byte;
begin
for(i=7; i>=0; i=i-1) begin
drv_sda = send_byte[i];
@(posedge clk);
drv_scl = 1;
@(posedge clk);
@(posedge clk);
drv_scl = 0;
@(posedge clk);
end
drv_sda = 1'b1;
@(posedge clk);
drv_scl = 1'b1;
if(sdo != 0) $display("ACK error at time: %t", $time);
// if(sda != 0) $display("ACK error at time: %t", $time);
@(posedge clk);
@(posedge clk);
drv_scl = 0;
@(posedge clk);
end
endtask
task recv_byte;
output [7:0] recv_dat;
begin
drv_sda=1;
for(i=7; i>=0; i=i-1) begin
@(posedge clk);
drv_scl = 1;
recv_dat[i] = sdo;
// recv_dat[i] = sda;
@(posedge clk);
@(posedge clk);
drv_scl = 0;
@(posedge clk);
end
drv_sda = 1'b0; //send ACK
@(posedge clk);
drv_scl = 1;
@(posedge clk);
@(posedge clk);
drv_scl = 0;
@(posedge clk);
drv_sda = 1'b1;
end
endtask
task recv_byte_noack;
output [7:0] recv_dat;
begin
drv_sda=1;
for(i=7; i>=0; i=i-1) begin
@(posedge clk);
drv_scl = 1;
recv_dat[i] = sdo;
// recv_dat[i] = sda;
@(posedge clk);
@(posedge clk);
drv_scl = 0;
@(posedge clk);
end
drv_sda = 1'b1; //send NOACK
@(posedge clk);
drv_scl = 1;
@(posedge clk);
@(posedge clk);
drv_scl = 0;
@(posedge clk);
drv_sda = 1'b1;
end
endtask
task write_reg;
input [6:0] slave_addr_reg;
input [7:0] addr;
input [7:0] dat;
begin
start;
rw_slave_addr(slave_addr_reg, 0);
send_byte(addr);
send_byte(dat);
stop;
end
endtask
task read_reg;
input [6:0] slave_addr_reg;
input [7:0] addr;
output [7:0] recv_dat;
begin
start;
rw_slave_addr(slave_addr_reg, 0);
send_byte(addr);
start;
rw_slave_addr(slave_addr_reg, 1);
recv_byte_noack(recv_dat);
stop;
end
endtask
task write_reg_2byte;
input [6:0] slave_addr_reg;
input [7:0]addr;
input [15:0] dat;
begin
start;
rw_slave_addr(slave_addr_reg, 0);
send_byte(addr);
send_byte(dat[15:8]);
send_byte(dat[7:0]);
stop;
end
endtask
task read_reg_2byte;
input [6:0] slave_addr_reg;
input [7:0] addr;
output [15:0] recv_dat;
begin
start;
rw_slave_addr(slave_addr_reg, 0);
send_byte(addr);
start;
rw_slave_addr(slave_addr_reg, 1);
recv_byte_noack(recv_dat[15:8]);
recv_byte_noack(recv_dat[7:0]);
stop;
end
endtask
endmodule