|
本人在测试读写I2C,但是搞了很久都没行,我是从单片机程序利用状态机方式改写的verilog程序,大体功能就是能够在固定地址读写1字节的数据就可以。clk频率为0.2M(分频过) inout sda; output scl; reg io; //定义略写 assign sda=(io==1)?1'bz:sdat; //when io="1",sda is input state ,or sda is output state
always@(posedge clk or negedge rst) if(!rst) begin (略) end else begin /*-------------------------------读I2C----------------------------------------*/ begin case (state_h) //--------------Start()------------// h0:begin io<=0;sdat<=1; scl<=1; state_h<=h1; end h1:begin sdat<=0; state_h<=h2; end//发送起始信 h2:begin scl<=0; state_h<=h3; end//钳住I2C总线准备发送或接收数据 //-----------发送器件地址Send(a0)写------------// h3:begin if(bitcnt==8)begin bitcnt<=0; state_h<=h7; end else begin state_h<=h4 ;end end h4:begin if((8'ha0< h5:begin scl<=1; state_h<=h6; end//置时14us h6:begin scl<=0; bitcnt<=bitcnt+1; state_h<=h3; end //------------应答Ack()-----------------// h7:begin sdat<=0; state_h<=h8; end h8:begin scl<=1; state_h<=h9; end h9:begin scl<=0; state_h<=h10; end //----------发送存储单元地址Send(0)----------// h10:begin if(bitcnt==8)begin bitcnt<=0; state_h<=h14;end else begin state_h<=h11 ;end end h11:begin if((8'h0f< h12:begin scl<=1; state_h<=h13;end h13:begin scl<=0; bitcnt<=bitcnt+1; state_h<=h10;end //------------应答Ack()-----------------// h14:begin sdat<=0; state_h<=h15;end h15:begin scl<=1; state_h<=h16;end h16:begin scl<=0; state_h<=h17;end //--------------Start()------------// h17:begin sdat<=1; scl<=1; state_h<=h18;end h18:begin sdat<=0; state_h<=h19;end h19:begin scl<=0; state_h<=h20;end //-----------发送器件地址Send(a1)读------------// h20:begin if(bitcnt==8)begin bitcnt<=0; state_h<=h24;end else begin state_h<=h21 ;end end h21:begin if((8'ha1< h22:begin scl<=1; state_h<=h23;end h23:begin scl<=0; bitcnt<=bitcnt+1; state_h<=h20;end //------------应答位Ack()-----------------// h24:begin sdat<=0; state_h<=h25;end h25:begin scl<=1; state_h<=h26;end h26:begin scl<=0; state_h<=h27;end //------------读一字节数据Read()-----------------// h27:begin rcv<=0; io<=1; state_h<=h28;end//置数据to input state h28:begin if(bitcnt==8)begin bitcnt<=0; ini_decay<=rcv; io<=0; state_h<=h32;end //read to ini_decay else begin scl<=0; state_h<=h29 ;end //置时钟线为低,准备接收数据位,>4.7us end h29:begin scl<=1; state_h<=h30;end//置时钟线为高,使数据线数据有效 h30:begin rcv<=rcv<<1; state_h<=h31;end h31:begin if(sda==1)rcv<=rcv+1; bitcnt<=bitcnt+1; state_h<=h28;end//读数据位,接收的数据位放入rcv sdat or sda?? h32:begin scl<=0; state_h<=h33;end //---------------NoAck()-----------------------// h33:begin sdat<=1; state_h<=h34;end h34:begin scl<=1; state_h<=h35;end h35:begin scl<=0; state_h<=h36;end //---------------Stop()-----------------------// h36:begin sdat<=0;scl<=1; state_h<=h37;end h37:begin sdat<=1; state_h<=h38;end h38:begin ini_iic_ok<=1; state_h<=h38;end //read e2prom over default: begin state_h<=h0; end endcase end ///////////////////////////写I2C/////////////////////////////////////////////// begin case(state_k) //--------------Start()------------// k0:begin io<=0;sdat<=1; scl<=1; wc<=0; state_k<=k1; end //write control k1:begin sdat<=0; state_k<=k2;end k2:begin scl<=0; state_k<=k3;end //-----------发送器件地址Send(a0)------------// k3:begin if(bitcnt==8)begin bitcnt<=0; state_k<=k7; end else begin state_k<=k4; end end k4:begin if((8'ha0< k5:begin scl<=1; state_k<=k6;end k6:begin scl<=0; bitcnt<=bitcnt+1;state_k<=k3;end //------------应答位Ack()-----------------// k7:begin sdat<=0; state_k<=k8;end k8:begin scl<=1; state_k<=k9;end k9:begin scl<=0; state_k<=k10;end //----------发Send(0)----------// k10:begin if(bitcnt==8)begin bitcnt<=0; state_k<=k14;end else begin state_k<=k11 ;end end k11:begin if((8'h0f< k12:begin scl<=1; state_k<=k13;end k13:begin scl<=0; bitcnt<=bitcnt+1; state_k<=k10;end //------------应答位Ack()-----------------// k14:begin sdat<=0; state_k<=k15;end k15:begin scl<=1; state_k<=k16;end k16:begin scl<=0; state_k<=k17;end //------------写Send(decay)-----------------// k17:begin if(bitcnt==8)begin bitcnt<=0; state_k<=k21; end else begin state_k<=k18 ;end end k18:begin if((8'haa< k19:begin scl<=1; state_k<=k20;end k20:begin scl<=0; bitcnt<=bitcnt+1; state_k<=k17;end //------------应答位Ack()-----------------// k21:begin sdat<=0; state_k<=k22;end k22:begin scl<=1; state_k<=k23;end k23:begin scl<=0; state_k<=k24;end //---------------Stop()-----------------------// k24:begin sdat<=0;scl<=1; state_k<=k25;end k25:begin sdat<=1;state_k<=k26;end k26:begin state_k<=k26;end //jump local default: begin state_k<=k0; end endcase end end |
|