📄 iic_sfp.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 + -