// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
//
|
//
|
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
|
|
`timescale 1ns/10ps
|
`timescale 1ns/10ps
|
|
|
|
|
module
|
module
|
i2c_master_model
|
i2c_master_model
|
#(
|
#(
|
parameter LOG_LEVEL = 3
|
parameter LOG_LEVEL = 3
|
)
|
)
|
(
|
(
|
inout i2c_data,
|
inout i2c_data,
|
inout i2c_clk
|
inout i2c_clk
|
);
|
);
|
|
|
localparam tBUF = 4700;
|
localparam tBUF = 4700;
|
localparam tSU_STA = 4700;
|
localparam tSU_STA = 4700;
|
localparam tSU_DAT = 250;
|
localparam tSU_DAT = 250;
|
localparam tHD_DAT = 0;
|
localparam tHD_DAT = 300;
|
localparam tHD_STA = 4000;
|
localparam tHD_STA = 4000;
|
localparam tLOW = 4700;
|
localparam tLOW = 4700;
|
localparam tHIGH = 4000;
|
localparam tHIGH = 4000;
|
|
|
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
// wires & regs
|
// wires & regs
|
wire i2c_data_in = i2c_data;
|
wire i2c_data_in = i2c_data;
|
wire i2c_clk_in = i2c_clk;
|
wire i2c_clk_in = i2c_clk;
|
|
|
reg i2c_data_oe;
|
reg i2c_data_oe;
|
reg i2c_clk_oe;
|
reg i2c_clk_oe;
|
reg i2c_data_out;
|
reg i2c_data_out;
|
reg i2c_clk_out;
|
reg i2c_clk_out;
|
|
|
reg i2c_ack_in;
|
reg i2c_ack_in;
|
|
|
|
|
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
// init
|
// init
|
initial
|
initial
|
begin
|
begin
|
i2c_data_oe = 1'b0;
|
i2c_data_oe = 1'b0;
|
i2c_clk_oe = 1'b0;
|
i2c_clk_oe = 1'b0;
|
i2c_data_out = 1'b1;
|
i2c_data_out = 1'b1;
|
i2c_clk_out = 1'b1;
|
i2c_clk_out = 1'b1;
|
end
|
end
|
|
|
|
|
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
// start
|
// start
|
task start;
|
task start;
|
begin
|
begin
|
|
|
if( LOG_LEVEL > 2 )
|
if( LOG_LEVEL > 2 )
|
$display( "###- %m: I2C start at time %t. ", $time );
|
$display( "###- %m: I2C start at time %t. ", $time );
|
|
|
i2c_data_out = 1'b1;
|
// i2c_data_out = 1'b1;
|
i2c_clk_out = 1'b1;
|
// i2c_clk_out = 1'b1;
|
|
|
#tBUF;
|
#tBUF;
|
|
|
i2c_data_oe = 1'b1;
|
i2c_data_oe = 1'b1;
|
i2c_clk_oe = 1'b1;
|
i2c_clk_oe = 1'b1;
|
|
|
if( i2c_data != 1'b1 )
|
if( i2c_data != 1'b1 )
|
begin
|
begin
|
#tHD_DAT;
|
#tHD_DAT;
|
i2c_data_out = 1'b1;
|
i2c_data_out = 1'b1;
|
end
|
end
|
|
|
if( i2c_clk != 1'b1 )
|
if( i2c_clk != 1'b1 )
|
begin
|
begin
|
i2c_clk_out = 1'b1;
|
i2c_clk_out = 1'b1;
|
#tSU_DAT;
|
#tLOW;
|
end
|
end
|
|
|
#tSU_STA;
|
#tSU_STA;
|
i2c_data_out = 1'b0;
|
i2c_data_out = 1'b0;
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
// stop
|
// stop
|
task stop;
|
task stop;
|
begin
|
begin
|
|
|
if( LOG_LEVEL > 2 )
|
if( LOG_LEVEL > 2 )
|
$display( "###- %m: I2C stop at time %t. ", $time );
|
$display( "###- %m: I2C stop at time %t. ", $time );
|
|
|
if( i2c_data != 1'b0 )
|
if( i2c_data != 1'b0 )
|
begin
|
begin
|
#tHD_DAT;
|
#tHD_DAT;
|
i2c_data_out = 1'b0;
|
i2c_data_out = 1'b0;
|
end
|
end
|
|
|
if( i2c_clk != 1'b1 )
|
if( i2c_clk != 1'b1 )
|
begin
|
begin
|
i2c_clk_out = 1'b1;
|
i2c_clk_out = 1'b1;
|
#tSU_DAT;
|
#tLOW;
|
end
|
end
|
|
|
i2c_data_out = 1'b1;
|
i2c_data_out = 1'b1;
|
i2c_clk_out = 1'b1;
|
i2c_clk_out = 1'b1;
|
|
|
i2c_data_oe = 1'b0;
|
i2c_data_oe = 1'b0;
|
i2c_clk_oe = 1'b0;
|
i2c_clk_oe = 1'b0;
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
// write_bit
|
// write_bit
|
task write_bit;
|
task write_bit;
|
input bit;
|
input bit;
|
begin
|
begin
|
|
|
#tHD_DAT;
|
#tHD_DAT;
|
i2c_data_oe = 1'b1;
|
i2c_data_oe = 1'b1;
|
i2c_data_out = bit;
|
i2c_data_out = bit;
|
#tLOW;
|
#tLOW;
|
|
|
i2c_clk_out = 1'b1;
|
i2c_clk_out = 1'b1;
|
#tHIGH;
|
#tHIGH;
|
i2c_clk_out = 1'b0;
|
i2c_clk_out = 1'b0;
|
|
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
// write_byte
|
// write_byte
|
|
reg write_byte_r = 1'b0;
|
|
|
task write_byte;
|
task write_byte;
|
input [7:0] data;
|
input [7:0] data;
|
begin
|
begin
|
|
|
|
write_byte_r = 1'b1;
|
|
|
if( LOG_LEVEL > 2 )
|
if( LOG_LEVEL > 2 )
|
$display( "###- %m: I2C write 0x%h at time %t. ", data, $time );
|
$display( "###- %m: I2C write 0x%h at time %t. ", data, $time );
|
|
|
#tHD_STA;
|
#tHD_STA;
|
|
|
i2c_clk_out = 1'b0;
|
i2c_clk_out = 1'b0;
|
|
|
write_bit( data[7] );
|
write_bit( data[7] );
|
write_bit( data[6] );
|
write_bit( data[6] );
|
write_bit( data[5] );
|
write_bit( data[5] );
|
write_bit( data[4] );
|
write_bit( data[4] );
|
write_bit( data[3] );
|
write_bit( data[3] );
|
write_bit( data[2] );
|
write_bit( data[2] );
|
write_bit( data[1] );
|
write_bit( data[1] );
|
write_bit( data[0] );
|
write_bit( data[0] );
|
|
|
#tHD_DAT;
|
#tHD_DAT;
|
i2c_data_oe = 1'b0;
|
i2c_data_oe = 1'b0;
|
#tLOW;
|
#tLOW;
|
|
|
i2c_clk_out = 1'b1;
|
i2c_clk_out = 1'b1;
|
|
|
i2c_ack_in = i2c_data;
|
i2c_ack_in = i2c_data;
|
|
|
if( LOG_LEVEL > 2 )
|
if( LOG_LEVEL > 2 )
|
if( i2c_data )
|
if( i2c_data )
|
$display( "###- %m: I2C NACK at time %t. ", $time );
|
$display( "###- %m: I2C NACK at time %t. ", $time );
|
else
|
else
|
$display( "###- %m: I2C ACK at time %t. ", $time );
|
$display( "###- %m: I2C ACK at time %t. ", $time );
|
|
|
#tHIGH;
|
#tHIGH;
|
|
i2c_clk_out = 1'b0;
|
|
|
|
write_byte_r = 1'b0;
|
|
#1;
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
// read_bit
|
// read_bit
|
reg [7:0] i2c_buffer_in;
|
reg [7:0] i2c_buffer_in;
|
|
|
task read_bit;
|
task read_bit;
|
input [3:0] bit;
|
input [3:0] bit;
|
begin
|
begin
|
|
|
i2c_data_oe = 1'b0;
|
i2c_data_oe = 1'b0;
|
|
|
#tHD_DAT;
|
#tHD_DAT;
|
i2c_buffer_in[bit] = i2c_data_in;
|
i2c_buffer_in[bit] = i2c_data_in;
|
#tLOW;
|
#tLOW;
|
|
|
i2c_clk_out = 1'b1;
|
i2c_clk_out = 1'b1;
|
#tHIGH;
|
#tHIGH;
|
i2c_clk_out = 1'b0;
|
i2c_clk_out = 1'b0;
|
|
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
// read_byte
|
// read_byte
|
task read_byte;
|
task read_byte;
|
begin
|
begin
|
|
|
#tHD_STA;
|
#tHD_STA;
|
|
|
i2c_clk_out = 1'b0;
|
i2c_clk_out = 1'b0;
|
i2c_data_oe = 1'b0;
|
i2c_data_oe = 1'b0;
|
|
|
read_bit( 7 );
|
read_bit( 7 );
|
read_bit( 6 );
|
read_bit( 6 );
|
read_bit( 5 );
|
read_bit( 5 );
|
read_bit( 4 );
|
read_bit( 4 );
|
read_bit( 3 );
|
read_bit( 3 );
|
read_bit( 2 );
|
read_bit( 2 );
|
read_bit( 1 );
|
read_bit( 1 );
|
read_bit( 0 );
|
read_bit( 0 );
|
|
|
i2c_data_oe = 1'b1;
|
i2c_data_oe = 1'b1;
|
#tHD_DAT;
|
#tHD_DAT;
|
i2c_data_out = 1'b0;
|
i2c_data_out = 1'b0;
|
#(tLOW - tHD_DAT);
|
#(tLOW - tHD_DAT);
|
i2c_clk_out = 1'b1;
|
i2c_clk_out = 1'b1;
|
|
|
if( LOG_LEVEL > 2 )
|
if( LOG_LEVEL > 2 )
|
$display( "###- %m: I2C read 0x%h at time %t. ", i2c_buffer_in, $time );
|
$display( "###- %m: I2C read 0x%h at time %t. ", i2c_buffer_in, $time );
|
|
|
|
#tHIGH;
|
|
i2c_clk_out = 1'b0;
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
// outputs
|
// outputs
|
assign i2c_data = i2c_data_oe ? i2c_data_out : 1'bz;
|
assign i2c_data = i2c_data_oe ? i2c_data_out : 1'bz;
|
assign i2c_clk = i2c_clk_oe ? i2c_clk_out : 1'bz;
|
assign i2c_clk = i2c_clk_oe ? i2c_clk_out : 1'bz;
|
|
|
|
|
endmodule
|
endmodule
|
|
|
|
|