0,直接在ISE里面编译过逻辑不正常,在SYNPLIFY,不勾选FSM_EXPORLER可以得到正确结果,否则也是错误结果。
1,状态机实现。
2,不检测ACK,但满足ACK的时序。
3,使用24C02测试通过。
4,继续补充。
5,怎么能在这里面输入代码格式?
module wr_a_byte_to_24c02(
input clk,rst,
input [6:0] dev_addr,
input [7:0] dat,
input [7:0] byte_addr,
input do_wr,
output reg fsm_done ,
output scl,sda
);
wire done ;
parameter IDLE = 0;
parameter DEV_CHK = 1;
parameter DEV_CHK_ACK =2 ;
parameter SEND_BYTE_ADDR =3 ;
parameter SEND_BYTE_ADDR_ACK=4 ;
parameter SEND_DAT =5 ;
parameter SEND_DAT_ACK =6 ;
parameter DONE =7 ;
parameter DEV_CHK_ACK_DONE=8;
reg [31:0] st ;
reg [7:0] dat_to_i2c;
reg sta,wr,sto;
always @ (posedge clk)
if (rst) begin
st <=IDLE;
end
else
begin
if (done){sta,wr,sto}<=0;
case (st)
IDLE :begin if (do_wr) st<=DEV_CHK ;end
DEV_CHK : begin st<= DEV_CHK_ACK; dat_to_i2c[7:0]<= {dev_addr[6:0],1'b0}; sta<=1;wr<=1;sto<=0;end
DEV_CHK_ACK: if (done ) st<=DEV_CHK_ACK_DONE ;
DEV_CHK_ACK_DONE: st <= SEND_BYTE_ADDR ;
SEND_BYTE_ADDR : begin st <=SEND_BYTE_ADDR_ACK ; sta<=0;wr<=1;sto<=0; dat_to_i2c[7:0]<=byte_addr ; end
SEND_BYTE_ADDR_ACK : if (done) st <= SEND_DAT;
SEND_DAT : begin st <= SEND_DAT_ACK ; sta<=0;wr<=1;sto<=1;dat_to_i2c[7:0] <= dat; end
SEND_DAT_ACK: if (done) st <= DONE ;
DONE :begin st<=IDLE; end
default st<= IDLE;
endcase
end
eeprom_fsm u1(
.clk(clk),
// .sta(1'b1),
//.sto(1'b1),
//.wr(1'b1),
.sta(sta),
.sto(sto),
.wr(wr),
.dat(dat_to_i2c),
.done(done ),
.scl(scl),
.sda(sda)
);
always @ (posedge clk)fsm_done<=st == DONE ;
endmodule
module eeprom_fsm(
input clk,rst,input sta,sto,wr,
input [7:0]dat,
output reg done,
output scl,sda
);
reg sclr,sdar;
assign scl = (sclr)?1'bz:0 ;
assign sda = (sdar)?1'bz:0 ;
reg [31:0] st ;
parameter DIV_CNTR = 1000;
reg [31:0] c ;
always @ (posedge clk)
if ((c==DIV_CNTR)||(st==10)) c<=0;
else c <= c+1 ;
wire i2c_clk = (c==DIV_CNTR) ;
reg [7:0] idx =0;
reg outbit ;
always @ (posedge clk)
case (idx[2:0])
0:outbit <= dat[7 ] ;
1:outbit <= dat[6 ] ;
2:outbit <= dat[5 ] ;
3:outbit <= dat[4 ] ;
4:outbit <= dat[3 ] ;
5:outbit <= dat[2 ] ;
6:outbit <= dat[1 ] ;
7:outbit <= dat[0 ] ;
endcase
wire go = sta|sto|wr;
reg [4:0]cc;always @ (posedge clk)cc<=cc+1;
always @ (posedge clk)
if (rst)
begin
st <=0 ;
sdar<=1;
sclr<=1;
end else
case(st )
0:begin sclr<=1;sdar<=1;if (i2c_clk) st<=10 ;end
10: begin idx<=0;if (go) st <= 1;end
1: if (sta) st<=2 ; else st <= 100;
2: begin sclr<=1 ;sdar <= 1 ; if (i2c_clk) st<=3 ;end
3: begin sclr<=1 ;sdar <= 0 ; if (i2c_clk) st<=4 ;end
4: begin sclr<=0 ;sdar <= 0 ; if (i2c_clk) st<=5 ;end
5: begin st <= 100 ;end
100:st<=101;
101:st<=102;
102:begin sclr<=0;sdar<=outbit ; if (i2c_clk) st<=103;end
103:begin sclr<=1;sdar<=outbit ; if (i2c_clk) st<=104;end
104:begin sclr<=1;sdar<=outbit ; if (i2c_clk) st<=105;end
105:begin sclr<=0;sdar<=outbit ; if (i2c_clk) st<=106;end
106: if(idx==7)st<=110;else begin idx<=idx+1; st<=100;end
110:begin sclr<=0;sdar<=1 ; if (i2c_clk) st<=111;end
111:begin sclr<=1;sdar<=1 ; if (i2c_clk) st<=112;end
112:begin sclr<=1;sdar<=1 ; if (i2c_clk) st<=115;end
115:begin sclr<=0;sdar<=1 ; if (i2c_clk) st<=116;end
116:begin sclr<=0;sdar<=1 ; if (i2c_clk) st<=200;end
200: if(sto) st<=201 ; else st<=300;
201: begin sclr<=1;sdar<=0 ; if (i2c_clk) st<=202;end
202: begin sclr<=1;sdar<=1 ; if (i2c_clk) st<=203;end
203: begin sclr<=1;sdar<=1 ; if (i2c_clk) st<=300;end
300: st<=301;
301: st<=10;
default st<=0;
endcase
always @ (posedge clk)
if (st==300)done<=1;else done<=0;
endmodule
波形测试正确