状态机实现对I2C器件的写操作

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








波形测试正确




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值