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