I2C Verilog 의 실현 (1)

3882 단어 cinput
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

좋은 웹페이지 즐겨찾기