iic 控制源码

//     iic master module

module i2c_demo(

        input               sysClk          ,

        input               sysRst          ,

       

        input[7:0]          pid_slave_addr  ,

        input[7:0]          pid_op_len      ,

       

        input               pid_init        ,

        input[7:0]          pid_reg_addr    ,//addr

        input[7:0]          pid_data        ,//data

       

   

       

        inout               pio_sda         ,

        output reg          pod_scl         ,

       

        output reg[7:0]     pod_rxd         ,

        output reg          pod_rxv         ,

       

        output reg          pod_rdy    

       

                        );


 

reg         i2c_sda     = 1'b0  ;

reg         i2c_wren    = 1'b0  ;

reg[7:0]    reg_in      = 8'd0  ;

reg[7:0]    data_in     = 8'd0  ;

reg         init_in     = 4'd0  ;

reg[7:0]    op_len      = 8'd0  ;


 

reg[7:0]    slave_id    = 8'd0  ;

reg         op_type     = 1'b0  ;

   

assign                      pio_sda          = i2c_wren ? i2c_sda : 1'bz ;

always@(posedge sysClk)

    if(pid_init)            reg_in          <= pid_reg_addr                 ;

    else                    reg_in          <= reg_in                   ;

   

always@(posedge sysClk)

    if(pid_init)            data_in         <= pid_data                 ;

    else                    data_in         <= data_in                  ;

   

   

always@(posedge sysClk)     init_in         <= pid_init                 ;


 

always@(posedge sysClk)     op_type         <= slave_id[0]              ;//1-->READ   0-->WRITE        

       

always@(posedge sysClk)

    if(pid_init)            slave_id        <= pid_slave_addr           ;

    else                    slave_id        <= slave_id                 ;

   

always@(posedge sysClk)    

    if(pid_init)            op_len          <= pid_op_len               ;

    else                    op_len          <= op_len                   ;




 

reg[7:0]                    sclk_cnt         = 8'd0                     ;

reg[3:0]                    bit_cnt          = 8'd0                     ;

reg                         sclk_en          = 1'b0                     ;

reg                         scl_Fedge        = 1'b0                     ;

reg                         scl_high         = 1'b0                     ;

reg                         slave_ack        = 1'b0                     ;

reg                         scl_add          = 1'b0                     ;

reg[11:0]                   timer_out        = 12'd0                    ;

reg[7:0]                    dly              = 8'd0                     ;

reg[7:0]                    op_cnt           = 8'd0                     ;

reg[7:0]                    tx_cnt           = 8'd0                     ;//统计已经发送数据的个数


 

localparam  IDLE        = 4'd0      ;  

localparam  I2C_START   = 4'd1      ;  

localparam  I2C_TXD     = 4'd2      ;  

localparam  S_ACK       = 4'd3      ;  

localparam  I2C_DONE    = 4'd4      ;

localparam  M_ACK       = 4'd5      ;

localparam  I2C_STOP    = 4'd6      ;

localparam  I2C_ADD     = 4'd7      ;

localparam  I2C_RXD     = 4'd8      ;


 

reg         task_done   = 1'b0      ;

reg[3:0]    STATE       = IDLE      ;

reg[3:0]    NEXT_STATE  = IDLE      ;  


 

always@(posedge sysClk or posedge sysRst)

    if(sysRst)          STATE               <= IDLE                                     ;

    else if(init_in)    STATE               <= I2C_START                                ;

    else                STATE               <= NEXT_STATE                               ;

                   

                   

               

always@(*)              

    case(STATE)            

        IDLE : begin                

                        NEXT_STATE = IDLE                                               ;

        end

       

       

        I2C_START : begin

            if(scl_Fedge)

                        NEXT_STATE = I2C_TXD                                            ;

            else        NEXT_STATE = I2C_START                                          ;

        end            

                       

                       

        I2C_TXD : begin            

            if(bit_cnt[3] & bit_cnt[0])            

                        NEXT_STATE = S_ACK                                              ;

            else        NEXT_STATE = I2C_TXD                                            ;

        end            

                       

                       

        S_ACK : begin              

            if(~slave_ack)                          

                        NEXT_STATE = I2C_DONE                                           ;

            else if(timer_out[7])                      

                        NEXT_STATE = IDLE                                               ;

            else        NEXT_STATE = S_ACK                                              ;

        end

       

       

        I2C_DONE : begin    //判断是否完成一次操作

            if(~scl_Fedge)

                        NEXT_STATE = I2C_DONE                                           ;

            else if(task_done)

                        NEXT_STATE = I2C_STOP                                           ;

            else        NEXT_STATE = I2C_ADD                                            ;

        end


 

        I2C_RXD : begin

            if(bit_cnt[3] & bit_cnt[0])            

                        NEXT_STATE = M_ACK                                              ;

            else        NEXT_STATE = I2C_RXD                                            ;

        end

           

           

        M_ACK : begin

            if(scl_Fedge)      

                        NEXT_STATE = I2C_DONE                                           ;

            else        NEXT_STATE = M_ACK                                              ;

        end

           

                       

        I2C_ADD : begin            

            if(op_type) NEXT_STATE = I2C_RXD                                            ;

            else        NEXT_STATE = I2C_TXD                                            ;

        end            

                       

                       

        I2C_STOP : begin                

            if(&dly[7:4])   NEXT_STATE = IDLE                                               ;

            else        NEXT_STATE = I2C_STOP                                           ;

        end

    default : ;

    endcase

   

// 等待128个时钟,如果clk是25M,则已经等待了5us.    

always@(posedge sysClk)

    if(STATE==I2C_STOP)     dly                 <= dly + 1'b1                           ;

    else                    dly                 <= 8'd0                                 ;

               

always@(posedge sysClk)            

    if(STATE==IDLE)         sclk_en             <= 1'b0                                 ;

    else                    sclk_en             <= 1'b1                                 ;

               

               

always@(posedge sysClk)            

    if(sclk_en)             sclk_cnt            <= sclk_cnt + 1'b1                      ;

    else                    sclk_cnt            <= 8'h80                                ;

                   

//---------------                  

always@(posedge sysClk)     pod_scl             <= sclk_cnt[7]                          ;



 

reg                         tx_flg               = 1'b0                                 ;

reg                         sda                  = 1'b0                                 ;

reg                         get_ack              = 1'b0                                 ;

always@(posedge sysClk)                    

    case(STATE)            

        I2C_START :         sda                 <= 1'b0                                 ;

                       

        I2C_STOP  :         sda                 <= 1'b0                                 ;

                       

        IDLE      :         sda                 <= 1'b0                                 ;

    default : ;

    endcase

   

   

always@(posedge sysClk) begin

                            scl_Fedge           <= sclk_cnt>=8'hfe && sclk_cnt<=8'hff   ;

                            scl_add             <= sclk_cnt==8'h40                      ;

                            scl_high            <= sclk_cnt>=8'h80 && sclk_cnt<=8'h84   ;

                            get_ack             <= sclk_cnt>=8'h82 && sclk_cnt<=8'h88   ;

end


 

reg                         sda_in               = 1'b0                                 ;

always@(posedge sysClk)     sda_in              <= pio_sda                              ;

//-------- 只用记录ack即可,可以暂时不用管ack是否回复。

reg                         ack_in               = 1'b0                                 ;

always@(posedge sysClk)

    if(scl_high)            ack_in              <= sda_in                               ;

    else                    ack_in              <= ack_in                               ;

   

always@(posedge sysClk)    

    if(get_ack)             slave_ack           <= sda_in                               ;//sda_in

    else                    slave_ack           <= slave_ack                            ;


 

always@(posedge sysClk)

    if(STATE==S_ACK)        timer_out           <= timer_out + 1'b1                     ;

    else                    timer_out           <= 12'd0                                ;



 

always@(posedge sysClk)    

    if(~tx_flg)             bit_cnt             <= 4'd0                                 ;

    else if(scl_add)        bit_cnt             <= bit_cnt + 1'b1                       ;

    else                    bit_cnt             <= bit_cnt                              ;

   

   

   

always@(posedge sysClk)     task_done           <= op_cnt>=op_len                       ;



 

always@(posedge sysClk)

    case(STATE)

   

        I2C_START :         op_cnt              <= 4'd0                                 ;

                   

        I2C_ADD   :         op_cnt              <= op_cnt + 1'b1                        ;

                       

    default       : ;              

    endcase                

               

       

       

reg[7:0]    tx_data = 8'd0;            

always@(posedge sysClk)            

    case(op_cnt)                

        8'd0 :              tx_data             <= slave_id                             ;

        8'd1 :              tx_data             <= reg_in                               ;

        8'd2 :              tx_data             <= data_in                              ;

   

    default  : ;

    endcase

   

   

reg                         txd                  = 1'b0                                 ;  

always@(posedge sysClk)                    

    case(bit_cnt)              

        4'd1 :              txd                 <= tx_data[7]                           ;

        4'd2 :              txd                 <= tx_data[6]                           ;

        4'd3 :              txd                 <= tx_data[5]                           ;

        4'd4 :              txd                 <= tx_data[4]                           ;

        4'd5 :              txd                 <= tx_data[3]                           ;

        4'd6 :              txd                 <= tx_data[2]                           ;

        4'd7 :              txd                 <= tx_data[1]                           ;

        4'd8 :              txd                 <= tx_data[0]                           ;

    default  : ;

    endcase

   

   

   

always@(posedge sysClk)

    if(STATE==I2C_TXD || STATE==I2C_RXD)        

                            tx_flg              <= 1'b1                                 ;

    else                    tx_flg              <= 1'b0                                 ;

               

               

always@(posedge sysClk)            

    if(tx_flg)              i2c_sda             <= txd                                  ;

    else                    i2c_sda             <= 1'b0                                 ;//sda

               

               

               

always@(posedge sysClk)            

    if(STATE==IDLE || STATE==S_ACK || STATE==I2C_DONE || STATE==I2C_RXD)                

                            i2c_wren            <= 1'b0                                 ;

    else                    i2c_wren            <= 1'b1                                 ;

reg get_ack_dly;

always @ (posedge sysClk)

    get_ack_dly <= get_ack;

reg[7:0]                    rxd                  = 8'd0                                 ;

always@(posedge sysClk)

        case(bit_cnt)  

        4'd1 :                  rxd[7]              <= slave_ack                            ;

        4'd2 :                  rxd[6]              <= slave_ack                            ;

        4'd3 :                  rxd[5]              <= slave_ack                            ;

        4'd4 :                  rxd[4]              <= slave_ack                            ;

               

        4'd5 :                  rxd[3]              <= slave_ack                            ;

        4'd6 :                  rxd[2]              <= slave_ack                            ;

        4'd7 :                  rxd[1]              <= slave_ack                            ;

        4'd8 :                  rxd[0]              <= slave_ack                            ;

        default : ;

        endcase



 

always@(posedge sysClk)

    if(bit_cnt[3] & scl_Fedge)

                            pod_rxd             <= rxd                                  ;

    else                    pod_rxd             <= pod_rxd                              ;

   

   

always@(posedge sysClk)     pod_rxv             <= STATE==M_ACK                         ;


 

always@(posedge sysClk)

    if(STATE==IDLE)         pod_rdy             <= 1'b1                                 ;

    else                    pod_rdy             <= 1'b0                                 ;

   

endmodule

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值