TestBench 程序
`timescale 1ns / 1ps
module test(
sda
);
reg scl;
inout sda;
reg sda_out;
wire sda_in;
reg [7:0] data;
reg start_flag, stop_flag;
assign sda = sda_out ? 1'bz : 1'b0;
assign sda_in = sda;
pullup( sda );
I2CTEST testmine(.SDA(sda), .SCL(scl));
initial
begin
scl = 0;
sda_out = 0;
data = 8'h27;
start_flag = 0;
#160000;
start ( );
end
always
begin
#50000 scl = ~scl;
end
always @ (posedge start_flag)
begin
repeat (8)
begin
wait ( scl == 0 );
#20000;
sda_out = data[7];
#40000;
data = data << 1;
end
wait (~ scl);
#20000;
sda_out = 1;
#160000;
stop ( );
end
always @ ( posedge stop_flag)
begin
// sda_out = 0;
// #50000;
sda_out = 1;
end
task start;
begin
wait (scl == 0);
#20000;
sda_out = 1;
wait ( scl == 1 );
#20000;
sda_out = 0;
start_flag = 1;
end
endtask
task stop;
begin
wait ( scl == 0 );
#20000;
sda_out = 0;
wait ( scl ==1 );
#20000;
sda_out = 1;
stop_flag = 1;
end
endtask
endmodule
I2C程序
`timescale 1ns / 1ps
module I2CTEST(
SDA, SCL
);
input SCL;
inout SDA;
// The 7-bits address that we want for our I2C slave
parameter I2C_ADR = 7'h13;
//---------------------------------------------
//start,stop condition judgement
//---------------------------------------------
wire start, stop;
reg sda1, sda2;
reg sda11;
always @ ( posedge SCL )
sda1 <= SDA;
always @ ( negedge SCL )
sda2 <= SDA;
always @ ( negedge SCL )
sda11 <= sda1;
assign start = sda11 & (!sda2);
assign stop = sda2 & ( !sda11 );
//----------------------------------------------
//count setting
//----------------------------------------------
reg [3:0] bitcont;
wire bit_ack = bitcont[3];
always @ ( posedge SCL or posedge start)
begin
if ( start )
bitcont <= 4'h6;
else
begin
if (bit_ack)
bitcont <= 4'h6;
else
bitcont <= bitcont -4'h1;
end
end
//-------------------------------------
//get sda using posedge scl
//-------------------------------------
reg sdar;
always @ ( posedge SCL ) sdar <= SDA;
//----------------------------------------
//address match
//----------------------------------------
reg addr_match, op_read;
always @ ( negedge SCL or posedge start )
begin
if ( start )
begin
addr_match <= 1'h1;
op_read <= 1'h0;
end
else
begin
if( (bitcont == 6) & (sdar != I2C_ADR[6])) addr_match <= 1'h0;
if( (bitcont == 5) & (sdar != I2C_ADR[5])) addr_match <= 1'h0;
if( (bitcont == 4) & (sdar != I2C_ADR[4])) addr_match <= 1'h0;
if( (bitcont == 3) & (sdar != I2C_ADR[3])) addr_match <= 1'h0;
if( (bitcont == 2) & (sdar != I2C_ADR[2])) addr_match <= 1'h0;
if( (bitcont == 1) & (sdar != I2C_ADR[1])) addr_match <= 1'h0;
if( (bitcont == 0) & (sdar != I2C_ADR[0])) addr_match <= 1'h0;
if( bitcont == 0 ) op_read <= sdar;
end
end
//-----------------------------------------------------------------------
//send ack
//-----------------------------------------------------------------------
reg ack_assert;
always @ ( negedge SCL )
begin
if ( bit_ack & addr_match & op_read )
ack_assert <= 1'h1;
else
ack_assert <= 1'h0;
end
//-------------------------------------------------------------------------
//control SDA line
//-------------------------------------------------------------------------
assign SDA = ack_assert ? 1'h0 : 1'hz;
pullup ( SDA );
endmodule