📄 i2ctop.v
字号:
module i2ctop(ResetN, CLKM,
I2C_D_IN, I2C_D_O, IDO_EN,
I2C_C_IN, I2C_C_O, ICO_EN,
//input
I2cAddr, MEM_FAIL,PROG_END,
//output
K, Pause, PIDT_Addr, PIDT_WR, PIDT_DATA,
//debug
cur_st,datai,datao,cnt1
);
input ResetN;
input CLKM;
input I2C_D_IN;
input I2C_C_IN;
output I2C_D_O;
output IDO_EN;
output I2C_C_O;
output ICO_EN;
//input
input [2:0] I2cAddr;
input MEM_FAIL;
input PROG_END;
//output
output K;
output Pause;
output [5:0] PIDT_Addr;
output PIDT_WR;
output [7:0] PIDT_DATA;
//debug
output [4:0] cur_st;
output [7:0] datai;
output [7:0] datao ;
output [3:0] cnt1;
wire in1;
wire out1 ;
wire i2cc_pe ;
wire i2cc_ne ;
wire ack_in ;
wire ack_out;
wire stop;
wire start;
wire [3:0] cnt2;
wire [3:0] cnt1;
wire [7:0] datai;
wire [7:0] datao ;
wire cnt_en;
wire i2cen_in;
wire i2cen_o ;
wire i2c_c_i;
wire cen;
wire [5:0] ADDR;
wire WR_REG;
wire [7:0] DO;
assign PIDT_DATA = DO;
assign ICO_EN=~i2cen_o;
assign I2C_C_O = 0;
movereg U1( .clk(CLKM),
.reset(ResetN) ,
.in(in1),
.out(out1),
.cnt1(cnt1),
.i2c_clk(i2c_c_i),
.i2c_clk_posedge(i2cc_pe),
.i2c_clk_negedge(i2cc_ne),
.data_in(datao),
.data_out(datai),
.ack_in(ack_out),
.ack_out(ack_in),
.i2c_d_out_en(IDO_EN),
.i2c_d_in(I2C_D_IN),
.i2c_d_out(I2C_D_O),
.i2c_en_in(i2cen_in),
.i2c_en_out(i2cen_o)
);
I2Csm U2( .clk(CLKM) ,
.reset(ResetN) ,
.cnt1(cnt1),
.cnt_en(cnt_en),
.reg_in(in1),
.reg_out(out1),
.i2c_data_in(datai),
.i2c_data_out(datao),
.start(start),
.stop(stop),
.ack_in(ack_in),
.ack_out(ack_out),
.i2c_en(i2cen_in),
.data_out(DO),
.data_in(8'h00),
.addr(ADDR),
.wr_reg(WR_REG),
.I2cAddr(I2cAddr),
.cur_state(cur_st));
EdgeDetect U3( .clk(CLKM),
.i2c_clk(i2c_c_i),
.i2c_data(I2C_D_IN),
.i2c_clk_posedge(i2cc_pe),
.i2c_clk_negedge(i2cc_ne),
.start(start),
.stop(stop));
counter U4( .clk(CLKM) ,
.en(cnt_en) ,
.i2c_clk_posedge(i2cc_pe) ,
.cnt1(cnt1) ,
.cnt2(cnt2));
m1 U5( .in(I2C_C_IN),
.out(i2c_c_i),
.ctl(~i2cen_o));
CtrlReg U6( .ResetN(ResetN),
.CLKM(CLKM),
.I2CDB(DO),
.CEN(cen),
.WR(WR_REG),
.MEM_FAIL(MEM_FAIL),
.PROG_END(PROG_END),
.K(K),
.Pause(Pause)
);
RegAddr U7( .ResetN(ResetN),
.CLKM(CLKM),
.abus(ADDR),
.CEN(cen),
.PIDT_Addr(PIDT_Addr),
.WR(WR_REG),
.PIDT_WR(PIDT_WR)
);
endmodule
/*******************************************************************/
module CtrlReg(ResetN, CLKM,
//input
I2CDB, CEN, WR, MEM_FAIL, PROG_END,
//output
K, Pause);
input ResetN;
input CLKM;
input CEN;
input WR;
input MEM_FAIL;
input PROG_END;
input [7:0] I2CDB;
output K;
output Pause;
reg [7:0] CtrReg;
assign K = CtrReg[3];
assign Pause = CtrReg[4];
always @(posedge CLKM or negedge ResetN)
if(!ResetN)
CtrReg <= 8'h08;
else if(MEM_FAIL || PROG_END)
CtrReg <= 8'h08;
else if(CEN & WR)
CtrReg <= I2CDB;
else
CtrReg <= CtrReg;
endmodule
/*******************************************************************/
module RegAddr(ResetN, CLKM, abus, CEN, PIDT_Addr, WR, PIDT_WR);
input ResetN;
input CLKM;
input [5:0] abus;
input WR;
output CEN;
output [5:0] PIDT_Addr;
output PIDT_WR;
reg CEN;
reg [5:0] PIDT_Addr;
reg PIDT_WR;
always @(posedge CLKM or negedge ResetN)
if(!ResetN) begin
CEN <= 0;
PIDT_Addr <= 0;
PIDT_WR <= 0;
end else if(abus == 6'h00) begin
CEN <= 1;
PIDT_Addr <= 0;
PIDT_WR <= 0;
end else if(abus > 6'h01 && abus<6'h32) begin
CEN <= 0;
PIDT_Addr <= abus - 6'h02;
PIDT_WR <= WR;
end else begin
CEN <= 0;
PIDT_Addr <= 0;
PIDT_WR <= 0;
end
endmodule
/*******************************************************************/
module counter ( clk ,
en ,
i2c_clk_posedge ,
cnt1 , cnt2 );
input clk ;
input en ;
input i2c_clk_posedge ;
output [3:0] cnt1 ;
output [3:0] cnt2 ;
reg [3:0] cnt1;
reg [3:0] cnt2;
always @(posedge clk or negedge en)
if(~en) begin
cnt1 <= 0 ;
cnt2 <= 0 ;
end
else begin
if(i2c_clk_posedge) begin
if(cnt1==8) begin
cnt1 <= 0 ;
if (cnt2==15)
cnt2 <= cnt2 ;
else
cnt2 <= cnt2 + 1 ;
end
else begin
cnt1 <= cnt1 + 1 ;
cnt2 <= cnt2 ;
end
end
end
endmodule
/**************************************************************/
module EdgeDetect ( clk , i2c_clk , i2c_data ,
i2c_clk_posedge,i2c_clk_negedge,start,stop);
input clk;
input i2c_clk ;
input i2c_data ;
output i2c_clk_posedge;
output i2c_clk_negedge;
output start;
output stop;
reg start ;
reg stop ;
reg i2c_clk_buf1;
reg i2c_data_buf1;
reg i2c_clk_buf2;
reg i2c_data_buf2;
wire i2c_data_posedge;
wire i2c_data_negedge;
assign i2c_clk_posedge = i2c_clk_buf1 & (~i2c_clk_buf2) ;
assign i2c_clk_negedge = (~i2c_clk_buf1) & i2c_clk_buf2 ;
assign i2c_data_posedge = i2c_data_buf1 & (~i2c_data_buf2) ;
assign i2c_data_negedge = (~i2c_data_buf1) & i2c_data_buf2 ;
always @(posedge clk)
begin
i2c_clk_buf1 <= i2c_clk ;
i2c_clk_buf2 <= i2c_clk_buf1 ;
i2c_data_buf1 <= i2c_data ;
i2c_data_buf2 <= i2c_data_buf1 ;
if(i2c_clk) begin
if (i2c_data_negedge) begin
start <= 1;
stop <= 0;
end
else if (i2c_data_posedge) begin
start <= 0 ;
stop <= 1 ;
end
else begin
start <= 0 ;
stop <= 0 ;
end
end
else begin
start <= 0 ;
stop <= 0 ;
end
end
endmodule
/******************************************************************/
module I2Csm(clk , reset , cnt1,cnt_en,reg_in,reg_out,
i2c_data_in ,i2c_data_out , start,stop,
ack_in,ack_out,i2c_en,
data_out,data_in,
addr,wr_reg, I2cAddr,
cur_state);
input clk ;
input reset ;
input [3:0] cnt1;
input [7:0] i2c_data_in ;
input start,stop;
input ack_in;
input [7:0] data_in;
input [2:0] I2cAddr;
output cnt_en;
output reg_in,reg_out;
output ack_out;
output [7:0] i2c_data_out;
output [7:0] data_out;
output [5:0] addr ;
output wr_reg;
output i2c_en;
output [4:0] cur_state ;
reg cnt_en;
reg reg_in,reg_out;
reg ack_out;
reg [7:0] i2c_data_out;
reg [7:0] data_out;
reg [5:0] addr ;
reg wr_reg;
reg i2c_en;
reg [4:0] cur_state ;
reg [4:0] next_state ;
//wire Device_addr_wr = {4'b1011 , I2cAddr, 1'b0};
//wire Device_addr_rd = {4'b1011 , I2cAddr, 1'b1};
parameter IDLE = 5'd0, START = 5'd1,
COMP_ADDR_WR=5'd2 , ADDRESS=5'd3 , COMP_INS=5'd4 ,
WRITE_REG1=5'd5 , WRITE_REG2=5'd6 , WRITE_REG3=5'd7 , WRITE_REG4=5'd8 ,
WRITE_REG5=5'd9 , SEND_ACK=5'd10 , SEND_NAK=5'd11 ,
WAIT_RESTART2=5'd12, RESTART=5'd13 , COMP_ADDR_RD=5'd14 , START_READ=5'd15 ,
READ_REG1=5'd16 , READ_REG2=5'd17 , READ_REG3=5'd18 , READ_REG4=5'd19 ,
READ_REG5=5'd20 , WAIT_STOP1=5'd21 , WAIT_STOP2=5'd22 ,WAIT_RESTART1=5'd23
;
always @(posedge clk or negedge reset)
if(!reset)
cur_state <= IDLE ;
else
cur_state <= next_state ;
always @(cur_state or ack_in or cnt1 or start or stop or i2c_data_in or I2cAddr or data_out)
begin
case (cur_state)
IDLE : begin
if(start)
next_state <= START ;
else
next_state <= IDLE ;
end
START : begin//has received START signal , read 1st Byte
if(cnt1==8)
next_state <= COMP_ADDR_WR ;
else
next_state <= START ;
end
COMP_ADDR_WR : begin //compare addr,send ack/nak
if(data_out=={4'b1011 , I2cAddr, 1'b0})
if(cnt1==0)
next_state <= ADDRESS ;
else
next_state <= COMP_ADDR_WR ;
else
next_state <= IDLE ;
end
ADDRESS : begin//read 2nd Byte
if(cnt1==8)
next_state <= COMP_INS ;
else
next_state <= ADDRESS ;
end
COMP_INS : begin
if(data_out[5:0]<6'h32)
next_state <= SEND_ACK ;
else
next_state <= SEND_NAK;
end
//-----------------------------------------------------------------------------
//stop
/* WAIT_STOP1 : begin
if(cnt1==1)
next_state <= WAIT_STOP2 ;
else
next_state <= WAIT_STOP1 ;
end
WAIT_STOP2 : begin
// if(stop)
next_state <= IDLE ;
// else
// next_state <= WAIT_STOP2 ;
end
*/
//-----------------------------------------------------------------------------
//return ACK
SEND_ACK : begin
if(cnt1==0) begin
// if(data_out[7]==1)
// next_state <= WAIT_RESTART1 ;//read operation
// else
next_state <= WRITE_REG1 ; //write addr
end
else
next_state <= SEND_ACK ;
end
//-----------------------------------------------------------------------------
//return NAK
SEND_NAK : begin
if(cnt1==0)
next_state <= WAIT_STOP1 ;
else
next_state <= SEND_NAK ;
end
//--------------------------------------------------------------------------
//write reg
WRITE_REG1 : begin
if(stop)
next_state <= IDLE ;
else if(cnt1==8)
next_state <= WRITE_REG2 ;
else
next_state <= WRITE_REG1 ;
end
WRITE_REG2 : begin
next_state <= WRITE_REG3 ;
end
WRITE_REG3 : begin
next_state <= WRITE_REG4 ;
end
WRITE_REG4 : begin
next_state <= WRITE_REG5 ;
end
WRITE_REG5 : begin//reset mcu_wr_reg , and return ack
if(cnt1==0)
next_state <= WRITE_REG1 ;
else
next_state <= WRITE_REG5 ;
end
//-------------------------------------------------------------------------------
//read device , wait re_start
/* WAIT_RESTART1 : begin
if(cnt1==1)
next_state <= WAIT_RESTART2;
else
next_state <= WAIT_RESTART1;
end
WAIT_RESTART2 : begin
if(start)
next_state <= RESTART ;
else
next_state <= WAIT_RESTART2 ;
end
RESTART : begin
if(cnt1==8)
next_state <= COMP_ADDR_RD ;
else
next_state <= RESTART ;
end
COMP_ADDR_RD : begin//compare addr ( read device ), and return ack or nak
if(data_out=={4'b1011 , I2cAddr, 1'b1})
if(cnt1 == 0 )
next_state <= START_READ ;
else
next_state <= COMP_ADDR_RD ;
else
next_state <= IDLE ;
end
START_READ : begin
next_state <= READ_REG1 ;
end
*/
//------------------------------------------------------------------------
//read status
/* READ_REG1 : begin//wait a clock cycle
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -