
axilite_slave_axilite_bridge.v// // 模块名称 : axilite_slave_axilite_bridge // 功能说明 : 1 路 AXI-Lite Slave 输入按地址范围路由到 2 路 AXI-Lite Master 输出 // // 设计说明 : // 1. 上游只有一组 s_axi_* 接口下游有 m0_axi_* / m1_axi_* 两组接口。 // 2. AW/AR 地址落在 slot0 地址范围时访问转发到 m0_axi_*。 // 3. AW/AR 地址落在 slot1 地址范围时访问转发到 m1_axi_*。 // 4. 地址范围通过 P_SLOTx_BASE_ADDR / P_SLOTx_ADDR_SIZE 参数配置单位为 byte。 // 5. 地址不命中任何 slot 时不访问下游 master直接给上游返回 DECERR。 // 6. AXI-Lite 写地址 AW 和写数据 W 允许不同拍到达本模块会分别锁存 // 等 AW/W 都到齐后再向选中的 master 发起写事务。 // 7. 本模块支持读写通道独立工作最多同时存在 1 个写事务和 1 个读事务。 // // 注意 : // 下游 m0/m1 收到的是上游原始 AXI-Lite byte address本模块只做地址译码 // 不做 base 地址减法。如果下游需要局部地址可在下游模块中自行处理。 // module axilite_slave_axilite_bridge #( parameter P_S_AXI_ADDR_WIDTH 32, parameter P_S_AXI_DATA_WIDTH 32, // slot0 - m0_axi_* 地址范围单位 byte parameter [P_S_AXI_ADDR_WIDTH-1:0] P_SLOT0_BASE_ADDR 32h0000_0000, parameter [P_S_AXI_ADDR_WIDTH-1:0] P_SLOT0_ADDR_SIZE 32h0000_1000, // slot1 - m1_axi_* 地址范围单位 byte parameter [P_S_AXI_ADDR_WIDTH-1:0] P_SLOT1_BASE_ADDR 32h0000_1000, parameter [P_S_AXI_ADDR_WIDTH-1:0] P_SLOT1_ADDR_SIZE 32h0000_1000 )( // // AXI-Lite Slave interface // input wire s_axi_aclk, input wire s_axi_aresetn, input wire [P_S_AXI_ADDR_WIDTH-1:0] s_axi_awaddr, input wire s_axi_awvalid, output reg s_axi_awready, input wire [P_S_AXI_DATA_WIDTH-1:0] s_axi_wdata, input wire [(P_S_AXI_DATA_WIDTH/8)-1:0] s_axi_wstrb, input wire s_axi_wvalid, output reg s_axi_wready, output reg [1:0] s_axi_bresp, output reg s_axi_bvalid, input wire s_axi_bready, input wire [P_S_AXI_ADDR_WIDTH-1:0] s_axi_araddr, input wire s_axi_arvalid, output reg s_axi_arready, output reg [P_S_AXI_DATA_WIDTH-1:0] s_axi_rdata, output reg [1:0] s_axi_rresp, output reg s_axi_rvalid, input wire s_axi_rready, // // AXI-Lite Master 0 interface // output reg [P_S_AXI_ADDR_WIDTH-1:0] m0_axi_awaddr, output reg m0_axi_awvalid, input wire m0_axi_awready, output reg [P_S_AXI_DATA_WIDTH-1:0] m0_axi_wdata, output reg [(P_S_AXI_DATA_WIDTH/8)-1:0] m0_axi_wstrb, output reg m0_axi_wvalid, input wire m0_axi_wready, input wire [1:0] m0_axi_bresp, input wire m0_axi_bvalid, output reg m0_axi_bready, output reg [P_S_AXI_ADDR_WIDTH-1:0] m0_axi_araddr, output reg m0_axi_arvalid, input wire m0_axi_arready, input wire [P_S_AXI_DATA_WIDTH-1:0] m0_axi_rdata, input wire [1:0] m0_axi_rresp, input wire m0_axi_rvalid, output reg m0_axi_rready, // // AXI-Lite Master 1 interface // output reg [P_S_AXI_ADDR_WIDTH-1:0] m1_axi_awaddr, output reg m1_axi_awvalid, input wire m1_axi_awready, output reg [P_S_AXI_DATA_WIDTH-1:0] m1_axi_wdata, output reg [(P_S_AXI_DATA_WIDTH/8)-1:0] m1_axi_wstrb, output reg m1_axi_wvalid, input wire m1_axi_wready, input wire [1:0] m1_axi_bresp, input wire m1_axi_bvalid, output reg m1_axi_bready, output reg [P_S_AXI_ADDR_WIDTH-1:0] m1_axi_araddr, output reg m1_axi_arvalid, input wire m1_axi_arready, input wire [P_S_AXI_DATA_WIDTH-1:0] m1_axi_rdata, input wire [1:0] m1_axi_rresp, input wire m1_axi_rvalid, output reg m1_axi_rready ); localparam [1:0] C_RESP_OKAY 2b00; localparam [1:0] C_RESP_DECERR 2b11; localparam [1:0] C_SEL_NONE 2d0; localparam [1:0] C_SEL_SLOT0 2d1; localparam [1:0] C_SEL_SLOT1 2d2; reg [P_S_AXI_ADDR_WIDTH-1:0] r_write_addr; // 上游 AWADDR 锁存 reg [P_S_AXI_DATA_WIDTH-1:0] r_write_data; // 上游 WDATA 锁存 reg [(P_S_AXI_DATA_WIDTH/8)-1:0] r_write_strb; // 上游 WSTRB 锁存 reg r_aw_valid; // AWADDR 已锁存 reg r_w_valid; // WDATA/WSTRB 已锁存 reg r_write_active; // 正在向下游 master 发送 AW/W reg r_write_resp_wait;// 等待下游 B 响应 reg [1:0] r_write_sel; // 当前写事务选择的下游 master reg r_m_aw_done; // 下游 AW 通道已握手 reg r_m_w_done; // 下游 W 通道已握手 reg [P_S_AXI_ADDR_WIDTH-1:0] r_read_addr; // 上游 ARADDR 锁存 reg r_read_active; // 正在向下游 master 发送 AR reg r_read_resp_wait; // 等待下游 R 响应 reg [1:0] r_read_sel; // 当前读事务选择的下游 master function [1:0] f_decode_addr; input [P_S_AXI_ADDR_WIDTH-1:0] addr; begin if ((addr P_SLOT0_BASE_ADDR) (addr (P_SLOT0_BASE_ADDR P_SLOT0_ADDR_SIZE))) begin f_decode_addr C_SEL_SLOT0; end else if ((addr P_SLOT1_BASE_ADDR) (addr (P_SLOT1_BASE_ADDR P_SLOT1_ADDR_SIZE))) begin f_decode_addr C_SEL_SLOT1; end else begin f_decode_addr C_SEL_NONE; end end endfunction wire w_aw_fire s_axi_awvalid s_axi_awready; wire w_w_fire s_axi_wvalid s_axi_wready; wire w_ar_fire s_axi_arvalid s_axi_arready; wire w_write_addr_ready r_aw_valid || w_aw_fire; wire w_write_data_ready r_w_valid || w_w_fire; wire w_write_ready !r_write_active !r_write_resp_wait !s_axi_bvalid w_write_addr_ready w_write_data_ready; wire [P_S_AXI_ADDR_WIDTH-1:0] w_write_addr w_aw_fire ? s_axi_awaddr : r_write_addr; wire [P_S_AXI_DATA_WIDTH-1:0] w_write_data w_w_fire ? s_axi_wdata : r_write_data; wire [(P_S_AXI_DATA_WIDTH/8)-1:0] w_write_strb w_w_fire ? s_axi_wstrb : r_write_strb; wire [1:0] w_write_sel f_decode_addr(w_write_addr); wire w_m0_aw_fire r_write_active (r_write_sel C_SEL_SLOT0) !r_m_aw_done m0_axi_awvalid m0_axi_awready; wire w_m0_w_fire r_write_active (r_write_sel C_SEL_SLOT0) !r_m_w_done m0_axi_wvalid m0_axi_wready; wire w_m1_aw_fire r_write_active (r_write_sel C_SEL_SLOT1) !r_m_aw_done m1_axi_awvalid m1_axi_awready; wire w_m1_w_fire r_write_active (r_write_sel C_SEL_SLOT1) !r_m_w_done m1_axi_wvalid m1_axi_wready; wire w_m_aw_done_next r_m_aw_done || w_m0_aw_fire || w_m1_aw_fire; wire w_m_w_done_next r_m_w_done || w_m0_w_fire || w_m1_w_fire; wire w_m0_b_fire r_write_resp_wait (r_write_sel C_SEL_SLOT0) m0_axi_bvalid m0_axi_bready; wire w_m1_b_fire r_write_resp_wait (r_write_sel C_SEL_SLOT1) m1_axi_bvalid m1_axi_bready; wire w_m0_ar_fire r_read_active (r_read_sel C_SEL_SLOT0) m0_axi_arvalid m0_axi_arready; wire w_m1_ar_fire r_read_active (r_read_sel C_SEL_SLOT1) m1_axi_arvalid m1_axi_arready; wire w_m0_r_fire r_read_resp_wait (r_read_sel C_SEL_SLOT0) m0_axi_rvalid m0_axi_rready; wire w_m1_r_fire r_read_resp_wait (r_read_sel C_SEL_SLOT1) m1_axi_rvalid m1_axi_rready; // 上游 ready 控制 // 写通道一次只接收一个 AW/W 配对等待下游 B 响应返回后再接收下一笔写。 // 读通道一次只接收一个 AR等待下游 R 响应返回后再接收下一笔读。 always (*) begin s_axi_awready s_axi_aresetn !r_aw_valid !r_write_active !r_write_resp_wait !s_axi_bvalid; s_axi_wready s_axi_aresetn !r_w_valid !r_write_active !r_write_resp_wait !s_axi_bvalid; s_axi_arready s_axi_aresetn !r_read_active !r_read_resp_wait !s_axi_rvalid; end // 下游 master 输出组合逻辑。 // 未选中的 master 保持 valid/bready/rready 为 0避免误访问。 always (*) begin m0_axi_awaddr r_write_addr; m0_axi_awvalid r_write_active (r_write_sel C_SEL_SLOT0) !r_m_aw_done; m0_axi_wdata r_write_data; m0_axi_wstrb r_write_strb; m0_axi_wvalid r_write_active (r_write_sel C_SEL_SLOT0) !r_m_w_done; m0_axi_bready r_write_resp_wait (r_write_sel C_SEL_SLOT0) !s_axi_bvalid; m0_axi_araddr r_read_addr; m0_axi_arvalid r_read_active (r_read_sel C_SEL_SLOT0); m0_axi_rready r_read_resp_wait (r_read_sel C_SEL_SLOT0) !s_axi_rvalid; m1_axi_awaddr r_write_addr; m1_axi_awvalid r_write_active (r_write_sel C_SEL_SLOT1) !r_m_aw_done; m1_axi_wdata r_write_data; m1_axi_wstrb r_write_strb; m1_axi_wvalid r_write_active (r_write_sel C_SEL_SLOT1) !r_m_w_done; m1_axi_bready r_write_resp_wait (r_write_sel C_SEL_SLOT1) !s_axi_bvalid; m1_axi_araddr r_read_addr; m1_axi_arvalid r_read_active (r_read_sel C_SEL_SLOT1); m1_axi_rready r_read_resp_wait (r_read_sel C_SEL_SLOT1) !s_axi_rvalid; end always (posedge s_axi_aclk or negedge s_axi_aresetn) begin if (!s_axi_aresetn) begin s_axi_bresp C_RESP_OKAY; s_axi_bvalid 1b0; s_axi_rdata {P_S_AXI_DATA_WIDTH{1b0}}; s_axi_rresp C_RESP_OKAY; s_axi_rvalid 1b0; r_write_addr {P_S_AXI_ADDR_WIDTH{1b0}}; r_write_data {P_S_AXI_DATA_WIDTH{1b0}}; r_write_strb {(P_S_AXI_DATA_WIDTH/8){1b0}}; r_aw_valid 1b0; r_w_valid 1b0; r_write_active 1b0; r_write_resp_wait 1b0; r_write_sel C_SEL_NONE; r_m_aw_done 1b0; r_m_w_done 1b0; r_read_addr {P_S_AXI_ADDR_WIDTH{1b0}}; r_read_active 1b0; r_read_resp_wait 1b0; r_read_sel C_SEL_NONE; end else begin // // 上游写地址/写数据锁存 // if (w_aw_fire) begin r_aw_valid 1b1; r_write_addr s_axi_awaddr; end if (w_w_fire) begin r_w_valid 1b1; r_write_data s_axi_wdata; r_write_strb s_axi_wstrb; end // AW/W 到齐后根据 AWADDR 选择下游 master。 // 未命中任何地址范围时直接给上游返回 DECERR。 if (w_write_ready) begin r_aw_valid 1b0; r_w_valid 1b0; r_write_addr w_write_addr; r_write_data w_write_data; r_write_strb w_write_strb; r_write_sel w_write_sel; r_m_aw_done 1b0; r_m_w_done 1b0; if (w_write_sel C_SEL_NONE) begin s_axi_bresp C_RESP_DECERR; s_axi_bvalid 1b1; end else begin r_write_active 1b1; end end // 下游 AW/W 握手完成后进入 B 响应等待阶段。 if (r_write_active) begin r_m_aw_done w_m_aw_done_next; r_m_w_done w_m_w_done_next; if (w_m_aw_done_next w_m_w_done_next) begin r_write_active 1b0; r_write_resp_wait 1b1; r_m_aw_done 1b0; r_m_w_done 1b0; end end // 把选中 master 的 B 响应转发给上游 slave 接口。 if (w_m0_b_fire) begin r_write_resp_wait 1b0; s_axi_bresp m0_axi_bresp; s_axi_bvalid 1b1; end else if (w_m1_b_fire) begin r_write_resp_wait 1b0; s_axi_bresp m1_axi_bresp; s_axi_bvalid 1b1; end else if (s_axi_bvalid s_axi_bready) begin s_axi_bvalid 1b0; end // // 读地址接收与路由 // if (w_ar_fire) begin r_read_addr s_axi_araddr; r_read_sel f_decode_addr(s_axi_araddr); if (f_decode_addr(s_axi_araddr) C_SEL_NONE) begin s_axi_rdata {P_S_AXI_DATA_WIDTH{1b0}}; s_axi_rresp C_RESP_DECERR; s_axi_rvalid 1b1; end else begin r_read_active 1b1; end end // 下游 AR 握手完成后进入 R 响应等待阶段。 if (w_m0_ar_fire || w_m1_ar_fire) begin r_read_active 1b0; r_read_resp_wait 1b1; end // 把选中 master 的 R 数据/响应转发给上游 slave 接口。 if (w_m0_r_fire) begin r_read_resp_wait 1b0; s_axi_rdata m0_axi_rdata; s_axi_rresp m0_axi_rresp; s_axi_rvalid 1b1; end else if (w_m1_r_fire) begin r_read_resp_wait 1b0; s_axi_rdata m1_axi_rdata; s_axi_rresp m1_axi_rresp; s_axi_rvalid 1b1; end else if (s_axi_rvalid s_axi_rready) begin s_axi_rvalid 1b0; end end end endmoduleaxi_lite_test_slave.vtimescale 1ns/1ps // // 模块名称 : axi_lite_test_slave // 功能说明 : AXI-Lite 测试用从设备模型 // // 用途 : // 1. 给 axilite_slave_axilite_bridge 的 m0_axi_* / m1_axi_* 接口做仿真目标 // 2. 内部带一个简单 32-bit RAM支持 AXI-Lite 单拍写、单拍读 // 3. AW/W 支持同拍到达也支持 AW 先到或 W 先到。 // module axi_lite_test_slave #( parameter P_ADDR_WIDTH 32, parameter P_DATA_WIDTH 32, parameter P_MEM_WORDS 16 )( input wire s_axi_aclk, input wire s_axi_aresetn, input wire [P_ADDR_WIDTH-1:0] s_axi_awaddr, input wire s_axi_awvalid, output wire s_axi_awready, input wire [P_DATA_WIDTH-1:0] s_axi_wdata, input wire [(P_DATA_WIDTH/8)-1:0] s_axi_wstrb, input wire s_axi_wvalid, output wire s_axi_wready, output reg [1:0] s_axi_bresp, output reg s_axi_bvalid, input wire s_axi_bready, input wire [P_ADDR_WIDTH-1:0] s_axi_araddr, input wire s_axi_arvalid, output wire s_axi_arready, output reg [P_DATA_WIDTH-1:0] s_axi_rdata, output reg [1:0] s_axi_rresp, output reg s_axi_rvalid, input wire s_axi_rready ); localparam C_ADDR_LSB 2; reg [P_DATA_WIDTH-1:0] r_mem [0:P_MEM_WORDS-1]; reg [P_ADDR_WIDTH-1:0] r_awaddr; reg [P_DATA_WIDTH-1:0] r_wdata; reg [(P_DATA_WIDTH/8)-1:0] r_wstrb; reg r_aw_valid; reg r_w_valid; integer i; integer byte_idx; wire w_aw_fire s_axi_awvalid s_axi_awready; wire w_w_fire s_axi_wvalid s_axi_wready; wire w_ar_fire s_axi_arvalid s_axi_arready; wire w_write_ready (r_aw_valid || w_aw_fire) (r_w_valid || w_w_fire) !s_axi_bvalid; wire [P_ADDR_WIDTH-1:0] w_write_addr w_aw_fire ? s_axi_awaddr : r_awaddr; wire [P_DATA_WIDTH-1:0] w_write_data w_w_fire ? s_axi_wdata : r_wdata; wire [(P_DATA_WIDTH/8)-1:0] w_write_strb w_w_fire ? s_axi_wstrb : r_wstrb; wire [3:0] w_write_idx w_write_addr[C_ADDR_LSB3:C_ADDR_LSB]; wire [3:0] w_read_idx s_axi_araddr[C_ADDR_LSB3:C_ADDR_LSB]; assign s_axi_awready s_axi_aresetn !r_aw_valid !s_axi_bvalid; assign s_axi_wready s_axi_aresetn !r_w_valid !s_axi_bvalid; assign s_axi_arready s_axi_aresetn !s_axi_rvalid; always (posedge s_axi_aclk or negedge s_axi_aresetn) begin if (!s_axi_aresetn) begin r_awaddr {P_ADDR_WIDTH{1b0}}; r_wdata {P_DATA_WIDTH{1b0}}; r_wstrb {(P_DATA_WIDTH/8){1b0}}; r_aw_valid 1b0; r_w_valid 1b0; s_axi_bresp 2b00; s_axi_bvalid 1b0; s_axi_rdata {P_DATA_WIDTH{1b0}}; s_axi_rresp 2b00; s_axi_rvalid 1b0; for (i 0; i P_MEM_WORDS; i i 1) begin r_mem[i] {P_DATA_WIDTH{1b0}}; end end else begin if (w_aw_fire) begin r_awaddr s_axi_awaddr; r_aw_valid 1b1; end if (w_w_fire) begin r_wdata s_axi_wdata; r_wstrb s_axi_wstrb; r_w_valid 1b1; end if (w_write_ready) begin for (byte_idx 0; byte_idx (P_DATA_WIDTH/8); byte_idx byte_idx 1) begin if (w_write_strb[byte_idx]) begin r_mem[w_write_idx][byte_idx*8 : 8] w_write_data[byte_idx*8 : 8]; end end r_aw_valid 1b0; r_w_valid 1b0; s_axi_bresp 2b00; s_axi_bvalid 1b1; end else if (s_axi_bvalid s_axi_bready) begin s_axi_bvalid 1b0; end if (w_ar_fire) begin s_axi_rdata r_mem[w_read_idx]; s_axi_rresp 2b00; s_axi_rvalid 1b1; end else if (s_axi_rvalid s_axi_rready) begin s_axi_rvalid 1b0; end end end endmoduletb_axilite_slave_axilite_bridge.vtimescale 1ns/1ps // // 文件名称 : tb_axilite_slave_axilite_bridge.v // 功能说明 : axilite_slave_axilite_bridge 的行为仿真测试平台 // // 测试拓扑 : // TB 产生 1 路上游 AXI-Lite 访问送入 axilite_slave_axilite_bridge // bridge 根据地址范围把访问分别转发到 2 路下游 AXI-Lite test slave。 // // 上游 AXI-Lite 激励 // | // v // axilite_slave_axilite_bridge // / \ // v v // axi_lite_test_slave0 axi_lite_test_slave1 // // 地址配置 : // slot0/m0 地址范围 : 0x0000_0000 ~ 0x0000_0fff // slot1/m1 地址范围 : 0x0000_1000 ~ 0x0000_1fff // 其它地址 : 未命中bridge 返回 DECERR // // 测试内容 : // 1. slot0 命中访问写 0x0000_0004再从同地址读回校验 // 2. slot1 命中访问AW 先到、W 后到写 0x0000_1008再读回校验 // 3. W 先到、AW 后到写 0x0000_000c再读回校验 // 4. 未命中地址写访问 0x0000_3000期望 B 通道返回 DECERR // 5. 未命中地址读访问 0x0000_3000期望 R 通道返回 DECERR读数据为 0。 // // 通过条件 : // 所有写响应、读响应和读回数据均符合预期打印 // PASS axilite_slave_axilite_bridge tb // module tb_axilite_slave_axilite_bridge; localparam C_RESP_OKAY 2b00; localparam C_RESP_DECERR 2b11; reg clk; reg rst_n; reg [31:0] s_axi_awaddr; reg s_axi_awvalid; wire s_axi_awready; reg [31:0] s_axi_wdata; reg [3:0] s_axi_wstrb; reg s_axi_wvalid; wire s_axi_wready; wire [1:0] s_axi_bresp; wire s_axi_bvalid; reg s_axi_bready; reg [31:0] s_axi_araddr; reg s_axi_arvalid; wire s_axi_arready; wire [31:0] s_axi_rdata; wire [1:0] s_axi_rresp; wire s_axi_rvalid; reg s_axi_rready; wire [31:0] m0_axi_awaddr; wire m0_axi_awvalid; wire m0_axi_awready; wire [31:0] m0_axi_wdata; wire [3:0] m0_axi_wstrb; wire m0_axi_wvalid; wire m0_axi_wready; wire [1:0] m0_axi_bresp; wire m0_axi_bvalid; wire m0_axi_bready; wire [31:0] m0_axi_araddr; wire m0_axi_arvalid; wire m0_axi_arready; wire [31:0] m0_axi_rdata; wire [1:0] m0_axi_rresp; wire m0_axi_rvalid; wire m0_axi_rready; wire [31:0] m1_axi_awaddr; wire m1_axi_awvalid; wire m1_axi_awready; wire [31:0] m1_axi_wdata; wire [3:0] m1_axi_wstrb; wire m1_axi_wvalid; wire m1_axi_wready; wire [1:0] m1_axi_bresp; wire m1_axi_bvalid; wire m1_axi_bready; wire [31:0] m1_axi_araddr; wire m1_axi_arvalid; wire m1_axi_arready; wire [31:0] m1_axi_rdata; wire [1:0] m1_axi_rresp; wire m1_axi_rvalid; wire m1_axi_rready; axilite_slave_axilite_bridge #( .P_S_AXI_ADDR_WIDTH(32), .P_S_AXI_DATA_WIDTH(32), .P_SLOT0_BASE_ADDR(32h0000_0000), .P_SLOT0_ADDR_SIZE(32h0000_1000), .P_SLOT1_BASE_ADDR(32h0000_1000), .P_SLOT1_ADDR_SIZE(32h0000_1000) ) u_bridge ( .s_axi_aclk (clk), .s_axi_aresetn (rst_n), .s_axi_awaddr (s_axi_awaddr), .s_axi_awvalid (s_axi_awvalid), .s_axi_awready (s_axi_awready), .s_axi_wdata (s_axi_wdata), .s_axi_wstrb (s_axi_wstrb), .s_axi_wvalid (s_axi_wvalid), .s_axi_wready (s_axi_wready), .s_axi_bresp (s_axi_bresp), .s_axi_bvalid (s_axi_bvalid), .s_axi_bready (s_axi_bready), .s_axi_araddr (s_axi_araddr), .s_axi_arvalid (s_axi_arvalid), .s_axi_arready (s_axi_arready), .s_axi_rdata (s_axi_rdata), .s_axi_rresp (s_axi_rresp), .s_axi_rvalid (s_axi_rvalid), .s_axi_rready (s_axi_rready), .m0_axi_awaddr (m0_axi_awaddr), .m0_axi_awvalid (m0_axi_awvalid), .m0_axi_awready (m0_axi_awready), .m0_axi_wdata (m0_axi_wdata), .m0_axi_wstrb (m0_axi_wstrb), .m0_axi_wvalid (m0_axi_wvalid), .m0_axi_wready (m0_axi_wready), .m0_axi_bresp (m0_axi_bresp), .m0_axi_bvalid (m0_axi_bvalid), .m0_axi_bready (m0_axi_bready), .m0_axi_araddr (m0_axi_araddr), .m0_axi_arvalid (m0_axi_arvalid), .m0_axi_arready (m0_axi_arready), .m0_axi_rdata (m0_axi_rdata), .m0_axi_rresp (m0_axi_rresp), .m0_axi_rvalid (m0_axi_rvalid), .m0_axi_rready (m0_axi_rready), .m1_axi_awaddr (m1_axi_awaddr), .m1_axi_awvalid (m1_axi_awvalid), .m1_axi_awready (m1_axi_awready), .m1_axi_wdata (m1_axi_wdata), .m1_axi_wstrb (m1_axi_wstrb), .m1_axi_wvalid (m1_axi_wvalid), .m1_axi_wready (m1_axi_wready), .m1_axi_bresp (m1_axi_bresp), .m1_axi_bvalid (m1_axi_bvalid), .m1_axi_bready (m1_axi_bready), .m1_axi_araddr (m1_axi_araddr), .m1_axi_arvalid (m1_axi_arvalid), .m1_axi_arready (m1_axi_arready), .m1_axi_rdata (m1_axi_rdata), .m1_axi_rresp (m1_axi_rresp), .m1_axi_rvalid (m1_axi_rvalid), .m1_axi_rready (m1_axi_rready) ); axi_lite_test_slave u_mem0 ( .s_axi_aclk (clk), .s_axi_aresetn(rst_n), .s_axi_awaddr (m0_axi_awaddr), .s_axi_awvalid(m0_axi_awvalid), .s_axi_awready(m0_axi_awready), .s_axi_wdata (m0_axi_wdata), .s_axi_wstrb (m0_axi_wstrb), .s_axi_wvalid (m0_axi_wvalid), .s_axi_wready (m0_axi_wready), .s_axi_bresp (m0_axi_bresp), .s_axi_bvalid (m0_axi_bvalid), .s_axi_bready (m0_axi_bready), .s_axi_araddr (m0_axi_araddr), .s_axi_arvalid(m0_axi_arvalid), .s_axi_arready(m0_axi_arready), .s_axi_rdata (m0_axi_rdata), .s_axi_rresp (m0_axi_rresp), .s_axi_rvalid (m0_axi_rvalid), .s_axi_rready (m0_axi_rready) ); axi_lite_test_slave u_mem1 ( .s_axi_aclk (clk), .s_axi_aresetn(rst_n), .s_axi_awaddr (m1_axi_awaddr), .s_axi_awvalid(m1_axi_awvalid), .s_axi_awready(m1_axi_awready), .s_axi_wdata (m1_axi_wdata), .s_axi_wstrb (m1_axi_wstrb), .s_axi_wvalid (m1_axi_wvalid), .s_axi_wready (m1_axi_wready), .s_axi_bresp (m1_axi_bresp), .s_axi_bvalid (m1_axi_bvalid), .s_axi_bready (m1_axi_bready), .s_axi_araddr (m1_axi_araddr), .s_axi_arvalid(m1_axi_arvalid), .s_axi_arready(m1_axi_arready), .s_axi_rdata (m1_axi_rdata), .s_axi_rresp (m1_axi_rresp), .s_axi_rvalid (m1_axi_rvalid), .s_axi_rready (m1_axi_rready) ); always #5 clk ~clk; task axi_write_same_cycle; input [31:0] addr; input [31:0] data; input [1:0] exp_resp; begin (negedge clk); s_axi_awaddr addr; s_axi_awvalid 1b1; s_axi_wdata data; s_axi_wstrb 4hf; s_axi_wvalid 1b1; s_axi_bready 1b1; while (!(s_axi_awvalid s_axi_awready s_axi_wvalid s_axi_wready)) begin (posedge clk); end (negedge clk); s_axi_awvalid 1b0; s_axi_wvalid 1b0; while (!s_axi_bvalid) begin (posedge clk); end if (s_axi_bresp ! exp_resp) begin $display(FAIL write same-cycle addr%08x bresp%b exp%b, addr, s_axi_bresp, exp_resp); $finish; end (negedge clk); s_axi_bready 1b0; end endtask task axi_write_aw_first; input [31:0] addr; input [31:0] data; input [1:0] exp_resp; begin (negedge clk); s_axi_awaddr addr; s_axi_awvalid 1b1; s_axi_bready 1b1; while (!(s_axi_awvalid s_axi_awready)) begin (posedge clk); end (negedge clk); s_axi_awvalid 1b0; repeat (2) (negedge clk); s_axi_wdata data; s_axi_wstrb 4hf; s_axi_wvalid 1b1; while (!(s_axi_wvalid s_axi_wready)) begin (posedge clk); end (negedge clk); s_axi_wvalid 1b0; while (!s_axi_bvalid) begin (posedge clk); end if (s_axi_bresp ! exp_resp) begin $display(FAIL write aw-first addr%08x bresp%b exp%b, addr, s_axi_bresp, exp_resp); $finish; end (negedge clk); s_axi_bready 1b0; end endtask task axi_write_w_first; input [31:0] addr; input [31:0] data; input [1:0] exp_resp; begin (negedge clk); s_axi_wdata data; s_axi_wstrb 4hf; s_axi_wvalid 1b1; s_axi_bready 1b1; while (!(s_axi_wvalid s_axi_wready)) begin (posedge clk); end (negedge clk); s_axi_wvalid 1b0; repeat (2) (negedge clk); s_axi_awaddr addr; s_axi_awvalid 1b1; while (!(s_axi_awvalid s_axi_awready)) begin (posedge clk); end (negedge clk); s_axi_awvalid 1b0; while (!s_axi_bvalid) begin (posedge clk); end if (s_axi_bresp ! exp_resp) begin $display(FAIL write w-first addr%08x bresp%b exp%b, addr, s_axi_bresp, exp_resp); $finish; end (negedge clk); s_axi_bready 1b0; end endtask task axi_read_check; input [31:0] addr; input [31:0] exp_data; input [1:0] exp_resp; begin (negedge clk); s_axi_araddr addr; s_axi_arvalid 1b1; s_axi_rready 1b1; while (!(s_axi_arvalid s_axi_arready)) begin (posedge clk); end (negedge clk); s_axi_arvalid 1b0; while (!s_axi_rvalid) begin (posedge clk); end if ((s_axi_rdata ! exp_data) || (s_axi_rresp ! exp_resp)) begin $display(FAIL read addr%08x rdata%08x exp%08x rresp%b exp%b, addr, s_axi_rdata, exp_data, s_axi_rresp, exp_resp); $finish; end (negedge clk); s_axi_rready 1b0; end endtask initial begin clk 1b0; rst_n 1b0; s_axi_awaddr 32h0; s_axi_awvalid 1b0; s_axi_wdata 32h0; s_axi_wstrb 4h0; s_axi_wvalid 1b0; s_axi_bready 1b0; s_axi_araddr 32h0; s_axi_arvalid 1b0; s_axi_rready 1b0; repeat (5) (negedge clk); rst_n 1b1; axi_write_same_cycle(32h0000_0004, 32h1111_2222, C_RESP_OKAY); axi_read_check (32h0000_0004, 32h1111_2222, C_RESP_OKAY); axi_write_aw_first (32h0000_1008, 32h3333_4444, C_RESP_OKAY); axi_read_check (32h0000_1008, 32h3333_4444, C_RESP_OKAY); axi_write_w_first (32h0000_000c, 32h5555_6666, C_RESP_OKAY); axi_read_check (32h0000_000c, 32h5555_6666, C_RESP_OKAY); axi_write_same_cycle(32h0000_3000, 32h7777_8888, C_RESP_DECERR); axi_read_check (32h0000_3000, 32h0000_0000, C_RESP_DECERR); $display(PASS axilite_slave_axilite_bridge tb); $finish; end endmodule测试PASS axilite_slave_axilite_bridge tb