仿真环境:例化了两组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
?
|