⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iic_sfp.v

📁 pci pci转local bus总线的应用
💻 V
字号:
module  IIC_SFP(
CLK33M,
RESET_N,
IIC_DATA_IN,
IIC_DATA_OUT,
IIC_ACCESS_INIT,
IIC_W_R,
SLAVE_ADDR,
IIC_ACCESS_BUSY,
IIC_ACCESS_ERR,
IIC_SCL,
IIC_SDA,
TRI_IIC_SDA,
IIC_SFP_CLK
);

input CLK33M;
input RESET_N;
output IIC_SCL;
inout  IIC_SDA;

input[15:0] IIC_DATA_IN;
output[7:0] IIC_DATA_OUT;
reg[7:0] IIC_DATA_OUT;
input IIC_ACCESS_INIT;                 //Trigger IIC read or write  	 
input IIC_W_R;  
input [6:0] SLAVE_ADDR;                //SFP module phy iic address = 1010110
                                       //SFP module eeprom iic address = 1010000
output IIC_ACCESS_BUSY;
reg    IIC_ACCESS_BUSY;
output IIC_ACCESS_ERR;                 //ACK is ERROR!!!
reg    IIC_ACCESS_ERR;
reg    ERR_PULSE;

output IIC_SFP_CLK;
wire SCL_IN;
wire SCL_OUT;
wire SCL_DBL_IN;
wire SCL_DBL_OUT;

assign IIC_SCL = SCL_OUT;
assign IIC_SFP_CLK =SCL_IN;

GLOBAL GLOBALCLK1(.in(SCL_OUT),.out(SCL_IN));	
GLOBAL GLOBALCLK2(.in(SCL_DBL_OUT),.out(SCL_DBL_IN));	

wire  SDA_OUT;
wire  SDA_IN;

reg WR_FLAG;                      //Tristate control for SDA_OUT
output TRI_IIC_SDA;                 //Tristate control for IIC_SDA_OUT

assign IIC_SDA = (TRI_IIC_SDA)? 1'bz : SDA_OUT;

reg[42:0] W_DATA_BUF;
reg[8:0] CLK_COUNT;
reg[6:0] WR_COUNT;

reg WR_START;

reg [1:0] WR_START_STATE;
reg [1:0] IIC_WR_STATE; 

wire IIC_AC_ER;

//send control state machine
parameter   WAIT_START = 0,
            RW_READY = 1,
            WRITE_READ = 2;

assign TRI_IIC_SDA = WR_FLAG;

assign SCL_OUT = CLK_COUNT[8];	    //SCL_OUT=CLK33M/512
assign SCL_DBL_OUT = CLK_COUNT[7];       //SCL_DBL_OUT=2*SCL_OUT
assign SDA_OUT = W_DATA_BUF[42];   
assign SDA_IN = IIC_SDA;

assign IIC_AC_ER = ERR_PULSE||WR_START;

//************************WR_START generate********************//
always @ (posedge CLK33M) 
begin
if(!RESET_N)
	begin
		WR_START_STATE <= 2'b00;
		WR_START <= 1'b0;
	end
else
	begin
		case(WR_START_STATE)
 		2'b00:
		  begin
			if(IIC_ACCESS_INIT)
			  begin
			    WR_START <= 1'b1;
			    WR_START_STATE <= 2'b01;
			  end
			else
			  begin
			    WR_START <= 1'b0;     
			    WR_START_STATE <= 2'b00;
			  end
		  end
		2'b01:
		  begin
			WR_START <= 1'b1;
			if(CLK_COUNT[8] == 1'b0)
			   WR_START_STATE <= 2'b01;
			else
			   WR_START_STATE <= 2'b10;
		  end
		2'b10:
		  begin
			WR_START <= 1'b1;
			if(CLK_COUNT[8] == 1'b1)
			   WR_START_STATE <= 2'b10;
			else
			   WR_START_STATE <= 2'b11;
		  end
		2'b11:
		  begin
			WR_START <= 1'b1;
			if(CLK_COUNT[8] == 1'b0)
			   WR_START_STATE <= 2'b11;
			else
			   WR_START_STATE <= 2'b00;
		  end
		default:
				WR_START_STATE <= 2'b00;	 			
        endcase
	end
end

//*******************SDA_OUT TRISTATE CONTROL OUTPUT**********************//
always @ (negedge SCL_IN or negedge RESET_N)
begin
if(!RESET_N)
  begin
	WR_FLAG <= 1'b1;
  end
else
  begin
	if(IIC_W_R)  
	  WR_FLAG<=(WR_COUNT[6:1]==8||WR_COUNT[6:1]==17||WR_COUNT[6:1]==26||(WR_COUNT==0 && IIC_WR_STATE==0))?1'b1:1'b0;
	else
	  WR_FLAG<=(WR_COUNT[6:1]==8||WR_COUNT[6:1]==17||((WR_COUNT[6:1]>26)&&(WR_COUNT[6:1]<36))||(WR_COUNT==0 && IIC_WR_STATE==0))?1'b1:1'b0; 
  end
end

//***********************GENERATE IIC ACCESS ERROR************************//
always @ (posedge IIC_AC_ER or negedge RESET_N)
begin
if(!RESET_N)
	IIC_ACCESS_ERR <= 1'b0;
else
	IIC_ACCESS_ERR <= IIC_ACCESS_BUSY;
end 

//***************************EEPIIC READ/WRITE****************************//
always @ (posedge SCL_DBL_IN or negedge RESET_N)
begin
if(!RESET_N)
    begin
	  W_DATA_BUF<=43'h0;
	  WR_COUNT<=7'h0;
	  IIC_WR_STATE<=WAIT_START;
	  IIC_DATA_OUT<=8'h0;
	  IIC_ACCESS_BUSY<=1'b0;
	  ERR_PULSE<=1'b0;
    end
else
   begin

  	if(IIC_W_R)
	   ERR_PULSE <= ((WR_COUNT[6:1]==9 || WR_COUNT[6:1]==18 || WR_COUNT[6:1]==27)&&SCL_OUT)?SDA_IN:1'b0;			 
	else
	   ERR_PULSE <= ((WR_COUNT[6:1]==9 || WR_COUNT[6:1]==18 || WR_COUNT[6:1]==28)&&SCL_OUT)?SDA_IN:1'b0;

   	case(IIC_WR_STATE)
	WAIT_START:
	  begin
		IIC_ACCESS_BUSY <= 1'b0;
		WR_COUNT <= 7'h0;
		if(!SCL_OUT&&WR_START)
			IIC_WR_STATE <= RW_READY;
		else
			IIC_WR_STATE <= WAIT_START;
	  end
	RW_READY:
	  begin
        IIC_ACCESS_BUSY <= 1'b1;
        WR_COUNT <= 7'h0;
        if(!SCL_OUT && !WR_START)
           begin
             IIC_WR_STATE<=WRITE_READ;
             case(IIC_W_R)
             1'b1: W_DATA_BUF <= {2'b1_0,SLAVE_ADDR,2'b0_0,IIC_DATA_IN[15:8],1'b0,IIC_DATA_IN[7:0],4'b0_0_11,11'h0};
             1'b0: W_DATA_BUF <= {2'b1_0,SLAVE_ADDR,2'b0_0,IIC_DATA_IN[15:8],1'b0,2'b1_0,SLAVE_ADDR,2'b1_0,8'h0,4'b1_0_11};
             endcase
           end
        else
             IIC_WR_STATE <= RW_READY;
      end
    WRITE_READ:
      begin
        IIC_ACCESS_BUSY <= 1'b1;				
        WR_COUNT <= WR_COUNT+1;
		
        if((WR_COUNT[0]==1'b1)||(WR_COUNT==0)||(WR_COUNT==56&&IIC_W_R)||(!IIC_W_R&&WR_COUNT==38)||(!IIC_W_R&&WR_COUNT==76)) 
            W_DATA_BUF <= W_DATA_BUF<<1;
		
        if(!IIC_W_R&&SCL_OUT&&(WR_COUNT[6:1]>28)&&(WR_COUNT[6:1]<37))
          begin
             IIC_DATA_OUT <= IIC_DATA_OUT<<1;
             IIC_DATA_OUT[0]<=SDA_IN;   
          end

        if((!IIC_W_R&&(WR_COUNT[6:1]>38))||(IIC_W_R&&WR_COUNT[6:1]>28))
            IIC_WR_STATE<=WAIT_START;
        else
            IIC_WR_STATE<=WRITE_READ;
      end	    
    default:	     
            IIC_WR_STATE<=WAIT_START;		    
    endcase
   end
end


//////////////////////////////////////////////////////////////////////////
//*************************SCL CLOCK GENERATE*********************************//
always @ (posedge CLK33M)
begin
if(!RESET_N)
	begin
	  CLK_COUNT <= 9'h0;
	end
else
	begin
	  CLK_COUNT <= CLK_COUNT+1;
	end
end

////////////////////////////////////////////////////////////////////////

endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -