• xilinx axi_iic IP使用分享


    仿真环境:例化了两组axi_iic 的IP。一个slv一个mst。slv地址固定为0x33;7bit模式,iic总线速率为4000K。

    仿真发现每次只能发送3byte数据,和实际不符。仿真仅作参考。由于iic为双向端口,通过例化顶层将IO连接,且需要进行上拉。

    顶层文件:top_sim.sv

    `timescale 1ns/1ps

    module top_sim();
    wire iic_sda;
    wire iic_scl;


    top u_top(
    .scl_io_mst(iic_scl),
    .sda_io_mst(iic_sda),
    .scl_io_slv(iic_scl),
    .sda_io_slv(iic_sda)
    );

    endmodule

    仿真发送命令参考:top.sv

    `timescale 1ns/1ps
    module top(
    inout scl_io_mst,
    inout sda_io_mst,
    inout scl_io_slv,
    inout sda_io_slv
    );
    parameter PERIOD = 40;

    reg clk;
    reg rst;
    //write channel
    logic [8:0] s_axi_awaddr_slv;
    logic [8:0] s_axi_awaddr_mst;
    logic s_axi_awvalid;
    logic s_axi_awvalid_mst;
    logic s_axi_awready;
    logic s_axi_awready_mst;
    logic [3:0]s_axi_wstrb;
    logic s_axi_wvalid;
    logic s_axi_wvalid_mst;
    logic s_axi_wready;
    logic s_axi_wready_mst;
    logic [31:0] s_axi_wdata_slv;
    logic [31:0] s_axi_wdata_mst;
    logic s_axi_bvalid;
    logic s_axi_bvalid_mst;
    logic s_axi_bready;
    logic s_axi_bready_mst;
    logic [1:0] s_axi_bresp;
    logic [1:0] s_axi_bresp_mst;
    //read channel
    logic [8:0] s_axi_araddr_slv;
    logic [8:0] s_axi_araddr_mst;
    logic s_axi_arvalid;
    logic s_axi_arvalid_mst;
    logic s_axi_arready;
    logic s_axi_arready_mst;
    logic [31:0] s_axi_rdata_slv;
    logic [31:0] s_axi_rdata_mst;
    logic [1:0]  s_axi_rresp;
    logic [1:0]  s_axi_rresp_mst;
    logic s_axi_rvalid;
    logic s_axi_rvalid_mst;
    logic s_axi_rready;
    logic s_axi_rready_mst;


    logic iic_slv_done;
    logic rst_mst;

    initial begin
        clk = 0;
        forever #(PERIOD/2) clk = ~clk;
    end
    initial begin
        rst = 1'b0;
        #100
        rst = 1'b1;
    end

    //iic_slv device cfg
    `define iic_slv_w u_axi_iic_slv.axi_lite_mst_iic_w
    `define iic_slv_r u_axi_iic_slv.axi_lite_mst_iic_r
    `define iic_mst_w u_axi_iic_mst.axi_lite_mst_iic_w
    `define iic_mst_r u_axi_iic_mst.axi_lite_mst_iic_r

    initial begin
        rst_mst = 0;
        iic_slv_done = 0;
        `iic_slv_w(9'h120,32'hf);    //rx_fifo deapth
        `iic_slv_w(9'h110,32'h66);  //slv address bit[0] NC
        `iic_slv_w(9'h100,32'h1);   //CR as slv
    //    `iic_slv_r(9'h104,s_axi_rdata_slv); //read SR
        iic_slv_done = 1;
        rst_mst = 1;
        


    end


    axi_iic u_axi_iic_slv(
    .clk          (clk ),
    .rst          (rst ),
    .s_axi_awaddr (s_axi_awaddr_slv ),
    .s_axi_wdata  (s_axi_wdata_slv  ),
    .s_axi_awvalid(s_axi_awvalid),
    .s_axi_awready(s_axi_awready),
    .s_axi_wstrb  (s_axi_wstrb  ),
    .s_axi_wvalid (s_axi_wvalid ),
    .s_axi_wready (s_axi_wready ),

    .s_axi_bready (s_axi_bready),
    .s_axi_bvalid (s_axi_bvalid),
    .s_axi_bresp  (s_axi_bresp ),

    .s_axi_araddr (s_axi_araddr_slv ),
    .s_axi_arvalid(s_axi_arvalid),
    .s_axi_arready(s_axi_arready),
    .s_axi_rdata  (s_axi_rdata_slv  ),
    .s_axi_rresp  (s_axi_rresp  ),
    .s_axi_rvalid (s_axi_rvalid ),
    .s_axi_rready (s_axi_rready )

    );

    axi_iic_1 u_axi_slv_iic_0(
    .s_axi_aclk         (clk),
    .s_axi_aresetn        (rst),
    .iic2intc_irpt        (),//out
    .s_axi_awaddr        (s_axi_awaddr_slv),
    .s_axi_awvalid        (s_axi_awvalid),
    .s_axi_awready        (s_axi_awready),//out
    .s_axi_wdata        (s_axi_wdata_slv),
    .s_axi_wstrb        (s_axi_wstrb),
    .s_axi_wvalid        (s_axi_wvalid),
    .s_axi_wready        (s_axi_wready),    //out
    .s_axi_bvalid          (s_axi_bvalid),    //out
    .s_axi_bready          (s_axi_bready),
    .s_axi_araddr         (s_axi_araddr_slv),
    .s_axi_bresp         (s_axi_bresp),    //out
    .s_axi_arvalid         (s_axi_arvalid),
    .s_axi_arready         (s_axi_arready),    //out
    .s_axi_rdata         (s_axi_rdata_slv), //out
    .s_axi_rresp         (s_axi_rresp), //out
    .s_axi_rvalid         (s_axi_rvalid), //out
    .s_axi_rready         (s_axi_rready),
    .sda_i                 (sda_i_slv),
    .sda_o                 (sda_o_slv),//out
    .sda_t                 (sda_t_slv),//out
    .scl_i                 (scl_i_slv),
    .scl_o                 (scl_o_slv), //out
    .scl_t                 (scl_t_slv), //out
    .gpo                 ()  //out 


    );

    initial begin
        wait(rst_mst);
        `iic_mst_w(9'h120,32'hf);
        `iic_mst_w(9'h100,32'h2);
        `iic_mst_w(9'h100,32'h1);    
        @(posedge clk);
        `iic_mst_w(9'h108,32'h166);
        `iic_mst_w(9'h108,32'h01);
        `iic_mst_w(9'h100,32'hd);
        force s_axi_arvalid_mst = 1;
        `iic_mst_r(9'h020,s_axi_rdata_mst);
        wait (s_axi_rdata_mst == 32'hd4)
        begin
        force s_axi_arvalid_mst = 0;
        release s_axi_arvalid_mst;
        end
        ///w  byte
        @(posedge clk);
        `iic_mst_w(9'h108,32'h01);
        `iic_mst_w(9'h108,32'h205);
        `iic_mst_w(9'h100,32'hd);
        force s_axi_arvalid_mst = 1;
        `iic_mst_r(9'h104,s_axi_rdata_mst);
        wait (s_axi_rdata_mst == 32'hc4)
        begin
        force s_axi_arvalid_mst = 0;
        release s_axi_arvalid_mst;
        #25us;
        end
        `iic_mst_r(9'h020,s_axi_rdata_mst);
        `iic_mst_w(9'h100,32'h2);
        `iic_mst_w(9'h100,32'h0);
         repeat(10) begin
            `iic_mst_r(9'h020,s_axi_rdata_mst);
            $display("~~~~~~~~%h~~~~~~~",s_axi_rdata_mst);
            `iic_mst_w(9'h020,s_axi_rdata_mst);
        if (s_axi_rdata_mst == 32'hd0) begin
           $display("*******%h*******",s_axi_rdata_mst);
           break ;
        end
        end
        
    //write twice
        `iic_mst_w(9'h100,32'h1);    
        @(posedge clk);
        `iic_mst_w(9'h108,32'h166);
        `iic_mst_w(9'h108,32'h01);
        `iic_mst_w(9'h100,32'hd);
        force s_axi_arvalid_mst = 1;
        `iic_mst_r(9'h020,s_axi_rdata_mst);
        wait (s_axi_rdata_mst == 32'hd4)
        begin
        force s_axi_arvalid_mst = 0;
        release s_axi_arvalid_mst;
        end
        ///w  byte
        @(posedge clk);
        `iic_mst_w(9'h108,32'h01);
        `iic_mst_w(9'h108,32'h205);
        `iic_mst_w(9'h100,32'hd);
        force s_axi_arvalid_mst = 1;
        `iic_mst_r(9'h104,s_axi_rdata_mst);
        wait (s_axi_rdata_mst == 32'hc4)
        begin
        force s_axi_arvalid_mst = 0;
        release s_axi_arvalid_mst;
        #25us;
        end
        `iic_mst_r(9'h020,s_axi_rdata_mst);
        `iic_mst_w(9'h100,32'h2);
        `iic_mst_w(9'h100,32'h0);
         repeat(10) begin
            `iic_mst_r(9'h020,s_axi_rdata_mst);
            $display("~~~~~~~~%h~~~~~~~",s_axi_rdata_mst);
            `iic_mst_w(9'h020,s_axi_rdata_mst);
        if (s_axi_rdata_mst == 32'hd0) begin
           $display("*******%h*******",s_axi_rdata_mst);
           break ;
        end
        end

        

    end

    axi_iic u_axi_iic_mst(
    .clk          (clk ),
    .rst          (rst_mst ),
    .s_axi_awaddr (s_axi_awaddr_mst ),
    .s_axi_wdata  (s_axi_wdata_mst  ),
    .s_axi_awvalid(s_axi_awvalid),
    .s_axi_awready(s_axi_awready),
    .s_axi_wstrb  (s_axi_wstrb  ),
    .s_axi_wvalid (s_axi_wvalid ),
    .s_axi_wready (s_axi_wready ),

    .s_axi_bready (s_axi_bready),
    .s_axi_bvalid (s_axi_bvalid),
    .s_axi_bresp  (s_axi_bresp ),

    .s_axi_araddr (s_axi_araddr_mst ),
    .s_axi_arvalid(s_axi_arvalid_mst),
    .s_axi_arready(s_axi_arready_mst),
    .s_axi_rdata  (s_axi_rdata_mst  ),
    .s_axi_rresp  (s_axi_rresp_mst  ),
    .s_axi_rvalid (s_axi_rvalid_mst ),
    .s_axi_rready (s_axi_rready_mst )

    );


    axi_iic_0 u_axi_mst_iic_0(
    .s_axi_aclk         (clk),
    .s_axi_aresetn        (rst_mst),
    .iic2intc_irpt        (),//out
    .s_axi_awaddr        (s_axi_awaddr_mst),
    .s_axi_awvalid        (s_axi_awvalid),
    .s_axi_awready        (s_axi_awready),//out
    .s_axi_wdata        (s_axi_wdata_mst),
    .s_axi_wstrb        (s_axi_wstrb),
    .s_axi_wvalid        (s_axi_wvalid),
    .s_axi_wready        (s_axi_wready),    //out
    .s_axi_bvalid          (s_axi_bvalid),    //out
    .s_axi_bready          (s_axi_bready),
    .s_axi_araddr         (s_axi_araddr_mst),
    .s_axi_bresp         (s_axi_bresp),    //out
    .s_axi_arvalid         (s_axi_arvalid_mst),
    .s_axi_arready         (s_axi_arready_mst),    //out
    .s_axi_rdata         (s_axi_rdata_mst), //out
    .s_axi_rresp         (s_axi_rresp_mst), //out
    .s_axi_rvalid         (s_axi_rvalid_mst), //out
    .s_axi_rready         (s_axi_rready_mst),
    .sda_i                 (sda_i_mst),
    .sda_o                 (sda_o_mst),//out
    .sda_t                 (sda_t_mst),//out
    .scl_i                 (scl_i_mst),
    .scl_o                 (scl_o_mst), //out
    .scl_t                 (scl_t_mst), //out
    .gpo                 ()  //out 


    );


    //iic mst
    pullup(scl_io_mst);
    pullup(sda_io_mst);

    IOBUF iic_iobuf_mst(
        .I (scl_o_mst),
        .IO(scl_io_mst),
        .O (scl_i_mst),
        .T (scl_t_mst)
    );

    IOBUF iic_iobuf_sda_mst(
        .I (sda_o_mst),
        .IO(sda_io_mst),
        .O (sda_i_mst),
        .T (sda_t_mst)
    );

    //iic slv
    pullup(scl_io_slv);
    pullup(sda_io_slv);

    IOBUF iic_iobuf_slv(
        .I (scl_o_slv),
        .IO(scl_io_slv),
        .O (scl_i_slv),
        .T (scl_t_slv)
    );

    IOBUF iic_iobuf_sda_slv(
        .I (sda_o_slv),
        .IO(sda_io_slv),
        .O (sda_i_slv),
        .T (sda_t_slv)
    );

    initial begin
        #2ms
        $finish(1);
    end
    endmodule

    建立外部的axi_mst 任务去调用axi_iic:

    module axi_iic(
    input clk,
    input rst,

    //axi_mst_lite aw & w channel
    output logic [8:0]  s_axi_awaddr,
    output logic [31:0] s_axi_wdata,
    output logic           s_axi_awvalid,
    input  logic        s_axi_awready,
    output logic [3:0]  s_axi_wstrb,
    output logic           s_axi_wvalid,
    input  logic            s_axi_wready,
    //b channel
    output logic           s_axi_bready,
    input  logic          s_axi_bvalid,
    input  logic [1:0]  s_axi_bresp,
    //axi_mst_lite ar & r channel
    output logic[8:0]  s_axi_araddr,
    output logic          s_axi_arvalid,
    input     logic      s_axi_arready,
    input  logic [31:0]      s_axi_rdata,
    input     logic      s_axi_rresp,
    input     logic      s_axi_rvalid,
    output logic          s_axi_rready

    );

    task axi_lite_mst_iic_w(
    input [8:0]  ss_axi_awaddr,
    input [31:0] ss_axi_wdata

    );
    begin    
        wait(rst);
        s_axi_awvalid = 1'b1;
        force top.s_axi_awready = 1'b1;
        wait(s_axi_awready);
        release top.s_axi_awready;
        s_axi_awaddr = ss_axi_awaddr;
        s_axi_wstrb = 4'hf;
        //write
        s_axi_wvalid = 1'b1;
        wait(s_axi_wready);
        s_axi_wdata = ss_axi_wdata;
        repeat(2) @(posedge clk);
        s_axi_wvalid = 1'b0;
        wait(s_axi_bvalid);
        repeat(10) @(posedge clk);
        s_axi_bready = 1;
        @(posedge clk);
        s_axi_bready = 0;
        @(posedge clk);
        
    end
    endtask

    task axi_lite_mst_iic_r(
    input [8:0] ss_axi_araddr,
    output [31:0] ss_axi_rdata
    );
    begin
        s_axi_rready = 1;
        @(posedge clk);
        //read
        s_axi_arvalid = 1'b1;
    //    force top.s_axi_arready = 1'b1;
        s_axi_araddr  = ss_axi_araddr;
        repeat(7) @(posedge clk);
        s_axi_arvalid = 1'b0;
    //    repeat(3) @(posedge clk);
    //    wait (s_axi_rvalid);
    //    repeat(3) @(posedge clk);
        ss_axi_rdata = s_axi_rdata;

    end
    endtask

    task axi_lite_slv_iic_w();
    begin

    end
    endtask


    task axi_lite_slv_iic_r();
    begin

    end
    endtask

    endmodule

     

  • 相关阅读:
    机器学习基础
    Bean 作用域和生命周期
    Android Framework | 读懂异常调用栈
    机器学习笔记 - 感知器的数学表达
    信号量临界区保护
    高级运维学习(十四)Zabbix监控(一)
    HY57V561620FTP_SDRAM文档总结
    node.js知识系列(3)-每天了解一点
    map&set的封装
    Anaconda 踩过的一些坑
  • 原文地址:https://blog.csdn.net/u012780083/article/details/126874880