diff --git a/.ci/Memora.yml b/.ci/Memora.yml index 72cd5ad1e..176afb4ff 100644 --- a/.ci/Memora.yml +++ b/.ci/Memora.yml @@ -103,6 +103,20 @@ artifacts: outputs: - build/axi_dw_upsizer-%.tested + axi_fifo-%: + inputs: + - Bender.yml + - include + - scripts/run_vsim.sh + - src/axi_pkg.sv + - src/axi_intf.sv + - src/axi_test.sv + - src/axi_fifo.sv + - test/tb_axi_fifo.sv + outputs: + - build/axi_fifo-%.tested + + axi_isolate-%: inputs: - Bender.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6d450fc0f..979eef5f2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -93,6 +93,11 @@ axi_dw_upsizer: variables: TEST_MODULE: axi_dw_upsizer +axi_fifo: + <<: *run_vsim + variables: + TEST_MODULE: axi_fifo + axi_isolate: <<: *run_vsim variables: diff --git a/Bender.yml b/Bender.yml index ccc855ee3..ede8af01f 100644 --- a/Bender.yml +++ b/Bender.yml @@ -33,6 +33,7 @@ sources: - src/axi_demux.sv - src/axi_dw_downsizer.sv - src/axi_dw_upsizer.sv + - src/axi_fifo.sv - src/axi_id_remap.sv - src/axi_id_prepend.sv - src/axi_isolate.sv @@ -85,6 +86,7 @@ sources: - test/tb_axi_delayer.sv - test/tb_axi_dw_downsizer.sv - test/tb_axi_dw_upsizer.sv + - test/tb_axi_fifo.sv - test/tb_axi_isolate.sv - test/tb_axi_lite_mailbox.sv - test/tb_axi_lite_regs.sv diff --git a/README.md b/README.md index 47a5458bc..b26d3ae6c 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ In addition to the documents linked in the following table, we are setting up [d | [`axi_dw_downsizer`](src/axi_dw_downsizer.sv) | A data width converter between a wide AXI master and a narrower AXI slave. | | | [`axi_dw_upsizer`](src/axi_dw_upsizer.sv) | A data width converter between a narrow AXI master and a wider AXI slave. | | | [`axi_err_slv`](src/axi_err_slv.sv) | Always responds with an AXI decode/slave error for transactions which are sent to it. | | +| [`axi_fifo`](src/axi_fifo.sv) | A Fifo for each AXI4 channel to buffer requests. | | | [`axi_id_prepend`](src/axi_id_prepend.sv) | This module prepends/strips the MSB from the AXI IDs. | | | [`axi_id_remap`](src/axi_id_remap.sv) | Remap AXI IDs from wide IDs at the slave port to narrower IDs at the master port. | [Doc][doc.axi_id_remap] | | [`axi_id_serialize`](src/axi_id_serialize.sv) | Reduce AXI IDs by serializing transactions when necessary. | [Doc][doc.axi_id_serialize] | diff --git a/axi.core b/axi.core index 9df067ba0..711a08e9c 100644 --- a/axi.core +++ b/axi.core @@ -24,6 +24,7 @@ filesets: - src/axi_demux.sv - src/axi_dw_downsizer.sv - src/axi_dw_upsizer.sv + - src/axi_fifo.sv - src/axi_id_remap.sv - src/axi_id_prepend.sv - src/axi_isolate.sv diff --git a/scripts/run_vsim.sh b/scripts/run_vsim.sh index b83862bcd..a6b2678b2 100755 --- a/scripts/run_vsim.sh +++ b/scripts/run_vsim.sh @@ -72,6 +72,14 @@ exec_test() { done done ;; + axi_fifo) + for DEPTH in 0 1 16; do + for FALL_THROUGH in 0 1; do + call_vsim tb_axi_fifo -gDepth=$DEPTH \ + -gFallThrough=$FALL_THROUGH + done + done + ;; axi_iw_converter) for SLV_PORT_IW in 1 2 3 4 8; do MAX_SLV_PORT_IDS=$((2**SLV_PORT_IW)) diff --git a/src/axi_fifo.sv b/src/axi_fifo.sv new file mode 100644 index 000000000..89d43ef6a --- /dev/null +++ b/src/axi_fifo.sv @@ -0,0 +1,254 @@ +// Copyright (c) 2014-2022 ETH Zurich, University of Bologna +// +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +// +// Authors: +// - Noah Huetter + +// AXI4 Fifo +// +// Can be used to buffer transactions + +module axi_fifo #( + parameter int unsigned Depth = 32'd1, // Number of FiFo slots. + parameter bit FallThrough = 1'b0, // fifos are in fall-through mode + // AXI channel structs + parameter type aw_chan_t = logic, + parameter type w_chan_t = logic, + parameter type b_chan_t = logic, + parameter type ar_chan_t = logic, + parameter type r_chan_t = logic, + // AXI request & response structs + parameter type axi_req_t = logic, + parameter type axi_resp_t = logic +) ( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low + input logic test_i, + // slave port + input axi_req_t slv_req_i, + output axi_resp_t slv_resp_o, + // master port + output axi_req_t mst_req_o, + input axi_resp_t mst_resp_i +); + + if (Depth == '0) begin : gen_no_fifo + // degenerate case, connect input to output + assign mst_req_o = slv_req_i; + assign slv_resp_o = mst_resp_i; + end else begin : gen_axi_fifo + logic aw_fifo_empty, ar_fifo_empty, w_fifo_empty, r_fifo_empty, b_fifo_empty; + logic aw_fifo_full, ar_fifo_full, w_fifo_full, r_fifo_full, b_fifo_full; + + assign mst_req_o.aw_valid = ~aw_fifo_empty; + assign mst_req_o.ar_valid = ~ar_fifo_empty; + assign mst_req_o.w_valid = ~w_fifo_empty; + assign slv_resp_o.r_valid = ~r_fifo_empty; + assign slv_resp_o.b_valid = ~b_fifo_empty; + + assign slv_resp_o.aw_ready = ~aw_fifo_full; + assign slv_resp_o.ar_ready = ~ar_fifo_full; + assign slv_resp_o.w_ready = ~w_fifo_full; + assign mst_req_o.r_ready = ~r_fifo_full; + assign mst_req_o.b_ready = ~b_fifo_full; + + // A FiFo for each channel + fifo_v3 #( + .dtype(aw_chan_t), + .DEPTH(Depth), + .FALL_THROUGH(FallThrough) + ) i_aw_fifo ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i(test_i), + .full_o (aw_fifo_full), + .empty_o (aw_fifo_empty), + .usage_o (), + .data_i (slv_req_i.aw), + .push_i (slv_req_i.aw_valid && slv_resp_o.aw_ready), + .data_o (mst_req_o.aw), + .pop_i (mst_req_o.aw_valid && mst_resp_i.aw_ready) + ); + fifo_v3 #( + .dtype(ar_chan_t), + .DEPTH(Depth), + .FALL_THROUGH(FallThrough) + ) i_ar_fifo ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i(test_i), + .full_o (ar_fifo_full), + .empty_o (ar_fifo_empty), + .usage_o (), + .data_i (slv_req_i.ar), + .push_i (slv_req_i.ar_valid && slv_resp_o.ar_ready), + .data_o (mst_req_o.ar), + .pop_i (mst_req_o.ar_valid && mst_resp_i.ar_ready) + ); + fifo_v3 #( + .dtype(w_chan_t), + .DEPTH(Depth), + .FALL_THROUGH(FallThrough) + ) i_w_fifo ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i(test_i), + .full_o (w_fifo_full), + .empty_o (w_fifo_empty), + .usage_o (), + .data_i (slv_req_i.w), + .push_i (slv_req_i.w_valid && slv_resp_o.w_ready), + .data_o (mst_req_o.w), + .pop_i (mst_req_o.w_valid && mst_resp_i.w_ready) + ); + fifo_v3 #( + .dtype(r_chan_t), + .DEPTH(Depth), + .FALL_THROUGH(FallThrough) + ) i_r_fifo ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i(test_i), + .full_o (r_fifo_full), + .empty_o (r_fifo_empty), + .usage_o (), + .data_i (mst_resp_i.r), + .push_i (mst_resp_i.r_valid && mst_req_o.r_ready), + .data_o (slv_resp_o.r), + .pop_i (slv_resp_o.r_valid && slv_req_i.r_ready) + ); + fifo_v3 #( + .dtype(b_chan_t), + .DEPTH(Depth), + .FALL_THROUGH(FallThrough) + ) i_b_fifo ( + .clk_i, + .rst_ni, + .flush_i (1'b0), + .testmode_i(test_i), + .full_o (b_fifo_full), + .empty_o (b_fifo_empty), + .usage_o (), + .data_i (mst_resp_i.b), + .push_i (mst_resp_i.b_valid && mst_req_o.b_ready), + .data_o (slv_resp_o.b), + .pop_i (slv_resp_o.b_valid && slv_req_i.b_ready) + ); + end + + // Check the invariants + // pragma translate_off +`ifndef VERILATOR + initial begin + assert (Depth >= 0); + end +`endif + // pragma translate_on +endmodule + +`include "axi/assign.svh" +`include "axi/typedef.svh" + +// interface wrapper +module axi_fifo_intf #( + parameter int unsigned ADDR_WIDTH = 0, // The address width. + parameter int unsigned DATA_WIDTH = 0, // The data width. + parameter int unsigned ID_WIDTH = 0, // The ID width. + parameter int unsigned USER_WIDTH = 0, // The user data width. + parameter int unsigned DEPTH = 0, // The number of FiFo slots. + parameter int unsigned FALL_THROUGH = 0 // FiFo in fall-through mode +) ( + input logic clk_i, + input logic rst_ni, + input logic test_i, + AXI_BUS.Slave slv, + AXI_BUS.Master mst +); + + typedef logic [ID_WIDTH-1:0] id_t; + typedef logic [ADDR_WIDTH-1:0] addr_t; + typedef logic [DATA_WIDTH-1:0] data_t; + typedef logic [DATA_WIDTH/8-1:0] strb_t; + typedef logic [USER_WIDTH-1:0] user_t; + + `AXI_TYPEDEF_AW_CHAN_T(aw_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(b_chan_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(ar_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(r_chan_t, data_t, id_t, user_t) + `AXI_TYPEDEF_REQ_T(axi_req_t, aw_chan_t, w_chan_t, ar_chan_t) + `AXI_TYPEDEF_RESP_T(axi_resp_t, b_chan_t, r_chan_t) + + axi_req_t slv_req, mst_req; + axi_resp_t slv_resp, mst_resp; + + `AXI_ASSIGN_TO_REQ(slv_req, slv) + `AXI_ASSIGN_FROM_RESP(slv, slv_resp) + + `AXI_ASSIGN_FROM_REQ(mst, mst_req) + `AXI_ASSIGN_TO_RESP(mst_resp, mst) + + axi_fifo #( + .Depth (DEPTH), + .FallThrough(FALL_THROUGH), + .aw_chan_t (aw_chan_t), + .w_chan_t (w_chan_t), + .b_chan_t (b_chan_t), + .ar_chan_t (ar_chan_t), + .r_chan_t (r_chan_t), + .axi_req_t (axi_req_t), + .axi_resp_t (axi_resp_t) + ) i_axi_fifo ( + .clk_i, + .rst_ni, + .test_i, + .slv_req_i (slv_req), + .slv_resp_o(slv_resp), + .mst_req_o (mst_req), + .mst_resp_i(mst_resp) + ); + + // Check the invariants. + // pragma translate_off +`ifndef VERILATOR + initial begin + assert (ADDR_WIDTH > 0) + else $fatal(1, "Wrong addr width parameter"); + assert (DATA_WIDTH > 0) + else $fatal(1, "Wrong data width parameter"); + assert (ID_WIDTH > 0) + else $fatal(1, "Wrong id width parameter"); + assert (USER_WIDTH > 0) + else $fatal(1, "Wrong user width parameter"); + assert (slv.AXI_ADDR_WIDTH == ADDR_WIDTH) + else $fatal(1, "Wrong interface definition"); + assert (slv.AXI_DATA_WIDTH == DATA_WIDTH) + else $fatal(1, "Wrong interface definition"); + assert (slv.AXI_ID_WIDTH == ID_WIDTH) + else $fatal(1, "Wrong interface definition"); + assert (slv.AXI_USER_WIDTH == USER_WIDTH) + else $fatal(1, "Wrong interface definition"); + assert (mst.AXI_ADDR_WIDTH == ADDR_WIDTH) + else $fatal(1, "Wrong interface definition"); + assert (mst.AXI_DATA_WIDTH == DATA_WIDTH) + else $fatal(1, "Wrong interface definition"); + assert (mst.AXI_ID_WIDTH == ID_WIDTH) + else $fatal(1, "Wrong interface definition"); + assert (mst.AXI_USER_WIDTH == USER_WIDTH) + else $fatal(1, "Wrong interface definition"); + end +`endif + // pragma translate_on +endmodule diff --git a/src_files.yml b/src_files.yml index fe4fdc67e..a5bb04f88 100644 --- a/src_files.yml +++ b/src_files.yml @@ -23,6 +23,7 @@ axi: - src/axi_demux.sv - src/axi_dw_downsizer.sv - src/axi_dw_upsizer.sv + - src/axi_fifo.sv - src/axi_id_remap.sv - src/axi_id_prepend.sv - src/axi_isolate.sv diff --git a/test/tb_axi_fifo.sv b/test/tb_axi_fifo.sv new file mode 100644 index 000000000..da88a4c81 --- /dev/null +++ b/test/tb_axi_fifo.sv @@ -0,0 +1,201 @@ +// Copyright (c) 2019 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +// +// Authors: +// - Wolfgang Roenninger +// - Andreas Kurth +// - Noah Huetter + +`include "axi/typedef.svh" +`include "axi/assign.svh" + +module tb_axi_fifo #( + parameter int unsigned Depth = 16, + parameter int unsigned FallThrough = 0, + parameter int unsigned NoWrites = 200, // How many writes per master + parameter int unsigned NoReads = 200 // How many reads per master +); + // Random Master Atomics + localparam int unsigned MaxAW = 30; + localparam int unsigned MaxAR = 30; + localparam bit EnAtop = 1'b1; + // timing parameters + localparam time CyclTime = 10ns; + localparam time ApplTime = 2ns; + localparam time TestTime = 8ns; + // AXI configuration + localparam int unsigned AxiIdWidth = 4; + localparam int unsigned AxiAddrWidth = 32; // Axi Address Width + localparam int unsigned AxiDataWidth = 64; // Axi Data Width + localparam int unsigned AxiUserWidth = 5; + // Sim print config, how many transactions + localparam int unsigned PrintTnx = 100; + + typedef axi_test::axi_rand_master#( + // AXI interface parameters + .AW (AxiAddrWidth), + .DW (AxiDataWidth), + .IW (AxiIdWidth), + .UW (AxiUserWidth), + // Stimuli application and test time + .TA (ApplTime), + .TT (TestTime), + // Maximum number of read and write transactions in flight + .MAX_READ_TXNS (MaxAR), + .MAX_WRITE_TXNS(MaxAW), + .AXI_ATOPS (EnAtop) + ) axi_rand_master_t; + typedef axi_test::axi_rand_slave#( + // AXI interface parameters + .AW(AxiAddrWidth), + .DW(AxiDataWidth), + .IW(AxiIdWidth), + .UW(AxiUserWidth), + // Stimuli application and test time + .TA(ApplTime), + .TT(TestTime) + ) axi_rand_slave_t; + + // ------------- + // DUT signals + // ------------- + logic clk; + logic rst_n; + logic end_of_sim; + + // interfaces + AXI_BUS #( + .AXI_ADDR_WIDTH(AxiAddrWidth), + .AXI_DATA_WIDTH(AxiDataWidth), + .AXI_ID_WIDTH (AxiIdWidth), + .AXI_USER_WIDTH(AxiUserWidth) + ) + master (), slave (); + AXI_BUS_DV #( + .AXI_ADDR_WIDTH(AxiAddrWidth), + .AXI_DATA_WIDTH(AxiDataWidth), + .AXI_ID_WIDTH (AxiIdWidth), + .AXI_USER_WIDTH(AxiUserWidth) + ) + master_dv (clk), slave_dv (clk); + + `AXI_ASSIGN(master, master_dv) + `AXI_ASSIGN(slave_dv, slave) + + //----------------------------------- + // Clock generator + //----------------------------------- + clk_rst_gen #( + .ClkPeriod (CyclTime), + .RstClkCycles(5) + ) i_clk_gen ( + .clk_o (clk), + .rst_no(rst_n) + ); + + //----------------------------------- + // DUT + //----------------------------------- + axi_fifo_intf #( + .DEPTH (Depth), // number of FiFo slots + .FALL_THROUGH(FallThrough), // FiFos in fall through mode + .ID_WIDTH (AxiIdWidth), // AXI ID width + .ADDR_WIDTH (AxiAddrWidth), // AXI address width + .DATA_WIDTH (AxiDataWidth), // AXI data width + .USER_WIDTH (AxiUserWidth) // AXI user width + ) i_dut ( + .clk_i (clk), // clock + .rst_ni(rst_n), // asynchronous reset active low + .test_i(1'b0), + .slv (master), // slave port + .mst (slave) // master port + ); + + initial begin : proc_axi_master + automatic axi_rand_master_t axi_rand_master = new(master_dv); + end_of_sim <= 1'b0; + axi_rand_master.add_memory_region(32'h0000_0000, 32'h1000_0000, axi_pkg::DEVICE_NONBUFFERABLE); + axi_rand_master.add_memory_region(32'h2000_0000, 32'h3000_0000, axi_pkg::WTHRU_NOALLOCATE); + axi_rand_master.add_memory_region(32'h4000_0000, 32'h5000_0000, axi_pkg::WBACK_RWALLOCATE); + axi_rand_master.reset(); + @(posedge rst_n); + axi_rand_master.run(NoReads, NoWrites); + end_of_sim <= 1'b1; + repeat (10000) @(posedge clk); + $stop(); + end + + initial begin : proc_axi_slave + automatic axi_rand_slave_t axi_rand_slave = new(slave_dv); + axi_rand_slave.reset(); + @(posedge rst_n); + axi_rand_slave.run(); + end + + initial begin : proc_sim_progress + automatic int unsigned aw = 0; + automatic int unsigned ar = 0; + automatic bit aw_printed = 1'b0; + automatic bit ar_printed = 1'b0; + + @(posedge rst_n); + + forever begin + @(posedge clk); + #TestTime; + if (master.aw_valid && master.aw_ready) begin + aw++; + end + if (master.ar_valid && master.ar_ready) begin + ar++; + end + + if ((aw % PrintTnx == 0) && !aw_printed) begin + $display("%t> Transmit AW %d of %d.", $time(), aw, NoWrites); + aw_printed = 1'b1; + end + if ((ar % PrintTnx == 0) && !ar_printed) begin + $display("%t> Transmit AR %d of %d.", $time(), ar, NoReads); + ar_printed = 1'b1; + end + + if (aw % PrintTnx == 1) begin + aw_printed = 1'b0; + end + if (ar % PrintTnx == 1) begin + ar_printed = 1'b0; + end + + if (end_of_sim) begin + $info("All transactions completed."); + break; + end + end + end + + + default disable iff (!rst_n); aw_unstable : + assert property (@(posedge clk) (slave.aw_valid && !slave.aw_ready) |=> $stable(slave.aw_addr)) + else $fatal(1, "AW is unstable."); + w_unstable : + assert property (@(posedge clk) (slave.w_valid && !slave.w_ready) |=> $stable(slave.w_data)) + else $fatal(1, "W is unstable."); + b_unstable : + assert property (@(posedge clk) (master.b_valid && !master.b_ready) |=> $stable(master.b_resp)) + else $fatal(1, "B is unstable."); + ar_unstable : + assert property (@(posedge clk) (slave.ar_valid && !slave.ar_ready) |=> $stable(slave.ar_addr)) + else $fatal(1, "AR is unstable."); + r_unstable : + assert property (@(posedge clk) (master.r_valid && !master.r_ready) |=> $stable(master.r_data)) + else $fatal(1, "R is unstable."); + + +endmodule diff --git a/test/tb_axi_fifo.wave.do b/test/tb_axi_fifo.wave.do new file mode 100644 index 000000000..bdf1d9e20 --- /dev/null +++ b/test/tb_axi_fifo.wave.do @@ -0,0 +1,201 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate -label Clock /tb_axi_fifo/i_dut/clk_i +add wave -noupdate -label Reset /tb_axi_fifo/i_dut/rst_ni +add wave -noupdate -divider {Slave Ports} +add wave -noupdate -expand -group {Master AW} /tb_axi_fifo/master/aw_id +add wave -noupdate -expand -group {Master AW} /tb_axi_fifo/master/aw_addr +add wave -noupdate -expand -group {Master AW} /tb_axi_fifo/master/aw_len +add wave -noupdate -expand -group {Master AW} /tb_axi_fifo/master/aw_size +add wave -noupdate -expand -group {Master AW} /tb_axi_fifo/master/aw_burst +add wave -noupdate -expand -group {Master AW} /tb_axi_fifo/master/aw_lock +add wave -noupdate -expand -group {Master AW} /tb_axi_fifo/master/aw_cache +add wave -noupdate -expand -group {Master AW} /tb_axi_fifo/master/aw_prot +add wave -noupdate -expand -group {Master AW} /tb_axi_fifo/master/aw_qos +add wave -noupdate -expand -group {Master AW} /tb_axi_fifo/master/aw_region +add wave -noupdate -expand -group {Master AW} /tb_axi_fifo/master/aw_atop +add wave -noupdate -expand -group {Master AW} /tb_axi_fifo/master/aw_user +add wave -noupdate -expand -group {Master AW} /tb_axi_fifo/master/aw_valid +add wave -noupdate -expand -group {Master AW} /tb_axi_fifo/master/aw_ready +add wave -noupdate -group {Master W} /tb_axi_fifo/master/w_data +add wave -noupdate -group {Master W} /tb_axi_fifo/master/w_strb +add wave -noupdate -group {Master W} /tb_axi_fifo/master/w_last +add wave -noupdate -group {Master W} /tb_axi_fifo/master/w_user +add wave -noupdate -group {Master W} /tb_axi_fifo/master/w_valid +add wave -noupdate -group {Master W} /tb_axi_fifo/master/w_ready +add wave -noupdate -group {Master B} /tb_axi_fifo/master/b_id +add wave -noupdate -group {Master B} /tb_axi_fifo/master/b_resp +add wave -noupdate -group {Master B} /tb_axi_fifo/master/b_user +add wave -noupdate -group {Master B} /tb_axi_fifo/master/b_valid +add wave -noupdate -group {Master B} /tb_axi_fifo/master/b_ready +add wave -noupdate -expand -group {Master AR} /tb_axi_fifo/master/ar_id +add wave -noupdate -expand -group {Master AR} /tb_axi_fifo/master/ar_addr +add wave -noupdate -expand -group {Master AR} /tb_axi_fifo/master/ar_len +add wave -noupdate -expand -group {Master AR} /tb_axi_fifo/master/ar_size +add wave -noupdate -expand -group {Master AR} /tb_axi_fifo/master/ar_burst +add wave -noupdate -expand -group {Master AR} /tb_axi_fifo/master/ar_lock +add wave -noupdate -expand -group {Master AR} /tb_axi_fifo/master/ar_cache +add wave -noupdate -expand -group {Master AR} /tb_axi_fifo/master/ar_prot +add wave -noupdate -expand -group {Master AR} /tb_axi_fifo/master/ar_qos +add wave -noupdate -expand -group {Master AR} /tb_axi_fifo/master/ar_region +add wave -noupdate -expand -group {Master AR} /tb_axi_fifo/master/ar_user +add wave -noupdate -expand -group {Master AR} /tb_axi_fifo/master/ar_valid +add wave -noupdate -expand -group {Master AR} /tb_axi_fifo/master/ar_ready +add wave -noupdate -group {Master R} /tb_axi_fifo/master/r_id +add wave -noupdate -group {Master R} /tb_axi_fifo/master/r_data +add wave -noupdate -group {Master R} /tb_axi_fifo/master/r_resp +add wave -noupdate -group {Master R} /tb_axi_fifo/master/r_last +add wave -noupdate -group {Master R} /tb_axi_fifo/master/r_user +add wave -noupdate -group {Master R} /tb_axi_fifo/master/r_valid +add wave -noupdate -group {Master R} /tb_axi_fifo/master/r_ready +add wave -noupdate -divider {Master Ports} +add wave -noupdate -expand -group {Slave AW} /tb_axi_fifo/slave/aw_id +add wave -noupdate -expand -group {Slave AW} /tb_axi_fifo/slave/aw_addr +add wave -noupdate -expand -group {Slave AW} /tb_axi_fifo/slave/aw_len +add wave -noupdate -expand -group {Slave AW} /tb_axi_fifo/slave/aw_size +add wave -noupdate -expand -group {Slave AW} /tb_axi_fifo/slave/aw_burst +add wave -noupdate -expand -group {Slave AW} /tb_axi_fifo/slave/aw_lock +add wave -noupdate -expand -group {Slave AW} /tb_axi_fifo/slave/aw_cache +add wave -noupdate -expand -group {Slave AW} /tb_axi_fifo/slave/aw_prot +add wave -noupdate -expand -group {Slave AW} /tb_axi_fifo/slave/aw_qos +add wave -noupdate -expand -group {Slave AW} /tb_axi_fifo/slave/aw_region +add wave -noupdate -expand -group {Slave AW} /tb_axi_fifo/slave/aw_atop +add wave -noupdate -expand -group {Slave AW} /tb_axi_fifo/slave/aw_user +add wave -noupdate -expand -group {Slave AW} /tb_axi_fifo/slave/aw_valid +add wave -noupdate -expand -group {Slave AW} /tb_axi_fifo/slave/aw_ready +add wave -noupdate -group {Slave W} /tb_axi_fifo/slave/w_data +add wave -noupdate -group {Slave W} /tb_axi_fifo/slave/w_strb +add wave -noupdate -group {Slave W} /tb_axi_fifo/slave/w_last +add wave -noupdate -group {Slave W} /tb_axi_fifo/slave/w_user +add wave -noupdate -group {Slave W} /tb_axi_fifo/slave/w_valid +add wave -noupdate -group {Slave W} /tb_axi_fifo/slave/w_ready +add wave -noupdate -group {Slave B} /tb_axi_fifo/slave/b_id +add wave -noupdate -group {Slave B} /tb_axi_fifo/slave/b_resp +add wave -noupdate -group {Slave B} /tb_axi_fifo/slave/b_user +add wave -noupdate -group {Slave B} /tb_axi_fifo/slave/b_valid +add wave -noupdate -group {Slave B} /tb_axi_fifo/slave/b_ready +add wave -noupdate -expand -group {Slave AR} /tb_axi_fifo/slave/ar_id +add wave -noupdate -expand -group {Slave AR} /tb_axi_fifo/slave/ar_addr +add wave -noupdate -expand -group {Slave AR} /tb_axi_fifo/slave/ar_len +add wave -noupdate -expand -group {Slave AR} /tb_axi_fifo/slave/ar_size +add wave -noupdate -expand -group {Slave AR} /tb_axi_fifo/slave/ar_burst +add wave -noupdate -expand -group {Slave AR} /tb_axi_fifo/slave/ar_lock +add wave -noupdate -expand -group {Slave AR} /tb_axi_fifo/slave/ar_cache +add wave -noupdate -expand -group {Slave AR} /tb_axi_fifo/slave/ar_prot +add wave -noupdate -expand -group {Slave AR} /tb_axi_fifo/slave/ar_qos +add wave -noupdate -expand -group {Slave AR} /tb_axi_fifo/slave/ar_region +add wave -noupdate -expand -group {Slave AR} /tb_axi_fifo/slave/ar_user +add wave -noupdate -expand -group {Slave AR} /tb_axi_fifo/slave/ar_valid +add wave -noupdate -expand -group {Slave AR} /tb_axi_fifo/slave/ar_ready +add wave -noupdate -group {Slave R} /tb_axi_fifo/slave/r_id +add wave -noupdate -group {Slave R} /tb_axi_fifo/slave/r_data +add wave -noupdate -group {Slave R} /tb_axi_fifo/slave/r_resp +add wave -noupdate -group {Slave R} /tb_axi_fifo/slave/r_last +add wave -noupdate -group {Slave R} /tb_axi_fifo/slave/r_user +add wave -noupdate -group {Slave R} /tb_axi_fifo/slave/r_valid +add wave -noupdate -group {Slave R} /tb_axi_fifo/slave/r_ready +add wave -noupdate -divider Custom +add wave -noupdate -expand -group {AW FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_aw_fifo/clk_i +add wave -noupdate -expand -group {AW FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_aw_fifo/rst_ni +add wave -noupdate -expand -group {AW FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_aw_fifo/flush_i +add wave -noupdate -expand -group {AW FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_aw_fifo/testmode_i +add wave -noupdate -expand -group {AW FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_aw_fifo/full_o +add wave -noupdate -expand -group {AW FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_aw_fifo/empty_o +add wave -noupdate -expand -group {AW FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_aw_fifo/usage_o +add wave -noupdate -expand -group {AW FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_aw_fifo/data_i +add wave -noupdate -expand -group {AW FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_aw_fifo/push_i +add wave -noupdate -expand -group {AW FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_aw_fifo/data_o +add wave -noupdate -expand -group {AW FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_aw_fifo/pop_i +add wave -noupdate -expand -group {W FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_w_fifo/clk_i +add wave -noupdate -expand -group {W FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_w_fifo/rst_ni +add wave -noupdate -expand -group {W FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_w_fifo/flush_i +add wave -noupdate -expand -group {W FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_w_fifo/testmode_i +add wave -noupdate -expand -group {W FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_w_fifo/full_o +add wave -noupdate -expand -group {W FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_w_fifo/empty_o +add wave -noupdate -expand -group {W FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_w_fifo/usage_o +add wave -noupdate -expand -group {W FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_w_fifo/data_i +add wave -noupdate -expand -group {W FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_w_fifo/push_i +add wave -noupdate -expand -group {W FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_w_fifo/data_o +add wave -noupdate -expand -group {W FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_w_fifo/pop_i +add wave -noupdate -expand -group {B FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_b_fifo/clk_i +add wave -noupdate -expand -group {B FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_b_fifo/rst_ni +add wave -noupdate -expand -group {B FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_b_fifo/flush_i +add wave -noupdate -expand -group {B FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_b_fifo/testmode_i +add wave -noupdate -expand -group {B FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_b_fifo/full_o +add wave -noupdate -expand -group {B FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_b_fifo/empty_o +add wave -noupdate -expand -group {B FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_b_fifo/usage_o +add wave -noupdate -expand -group {B FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_b_fifo/data_i +add wave -noupdate -expand -group {B FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_b_fifo/push_i +add wave -noupdate -expand -group {B FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_b_fifo/data_o +add wave -noupdate -expand -group {B FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_b_fifo/pop_i +add wave -noupdate -expand -group {Ar FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_ar_fifo/clk_i +add wave -noupdate -expand -group {Ar FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_ar_fifo/rst_ni +add wave -noupdate -expand -group {Ar FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_ar_fifo/flush_i +add wave -noupdate -expand -group {Ar FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_ar_fifo/testmode_i +add wave -noupdate -expand -group {Ar FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_ar_fifo/full_o +add wave -noupdate -expand -group {Ar FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_ar_fifo/empty_o +add wave -noupdate -expand -group {Ar FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_ar_fifo/usage_o +add wave -noupdate -expand -group {Ar FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_ar_fifo/data_i +add wave -noupdate -expand -group {Ar FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_ar_fifo/push_i +add wave -noupdate -expand -group {Ar FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_ar_fifo/data_o +add wave -noupdate -expand -group {Ar FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_ar_fifo/pop_i +add wave -noupdate -expand -group {R FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_r_fifo/clk_i +add wave -noupdate -expand -group {R FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_r_fifo/rst_ni +add wave -noupdate -expand -group {R FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_r_fifo/flush_i +add wave -noupdate -expand -group {R FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_r_fifo/testmode_i +add wave -noupdate -expand -group {R FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_r_fifo/full_o +add wave -noupdate -expand -group {R FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_r_fifo/empty_o +add wave -noupdate -expand -group {R FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_r_fifo/usage_o +add wave -noupdate -expand -group {R FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_r_fifo/data_i +add wave -noupdate -expand -group {R FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_r_fifo/push_i +add wave -noupdate -expand -group {R FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_r_fifo/data_o +add wave -noupdate -expand -group {R FiFo} /tb_axi_fifo/i_dut/i_axi_fifo/gen_axi_fifo/i_r_fifo/pop_i +add wave -noupdate -divider {DUT Ports} +add wave -noupdate -expand -group {DUT slv AW} /tb_axi_fifo/i_dut/i_axi_fifo/slv_req_i.aw_valid +add wave -noupdate -expand -group {DUT slv AW} /tb_axi_fifo/i_dut/i_axi_fifo/slv_resp_o.aw_ready +add wave -noupdate -expand -group {DUT slv AW} /tb_axi_fifo/i_dut/i_axi_fifo/slv_req_i.aw +add wave -noupdate -expand -group {DUT slv W} /tb_axi_fifo/i_dut/i_axi_fifo/slv_req_i.w +add wave -noupdate -expand -group {DUT slv W} /tb_axi_fifo/i_dut/i_axi_fifo/slv_req_i.w_valid +add wave -noupdate -expand -group {DUT slv W} /tb_axi_fifo/i_dut/i_axi_fifo/slv_resp_o.w_ready +add wave -noupdate -expand -group {DUT slv B} /tb_axi_fifo/i_dut/i_axi_fifo/slv_resp_o.b_valid +add wave -noupdate -expand -group {DUT slv B} /tb_axi_fifo/i_dut/i_axi_fifo/slv_req_i.b_ready +add wave -noupdate -expand -group {DUT slv B} /tb_axi_fifo/i_dut/i_axi_fifo/slv_resp_o.b +add wave -noupdate -expand -group {DUT slv AR} /tb_axi_fifo/i_dut/i_axi_fifo/slv_req_i.ar_valid +add wave -noupdate -expand -group {DUT slv AR} /tb_axi_fifo/i_dut/i_axi_fifo/slv_resp_o.ar_ready +add wave -noupdate -expand -group {DUT slv AR} /tb_axi_fifo/i_dut/i_axi_fifo/slv_req_i.ar +add wave -noupdate -expand -group {DUT slv R} /tb_axi_fifo/i_dut/i_axi_fifo/slv_resp_o.r_valid +add wave -noupdate -expand -group {DUT slv R} /tb_axi_fifo/i_dut/i_axi_fifo/slv_req_i.r_ready +add wave -noupdate -expand -group {DUT slv R} /tb_axi_fifo/i_dut/i_axi_fifo/slv_resp_o.r +add wave -noupdate -expand -group {DUT mst AW} /tb_axi_fifo/i_dut/i_axi_fifo/mst_req_o.aw_valid +add wave -noupdate -expand -group {DUT mst AW} /tb_axi_fifo/i_dut/i_axi_fifo/mst_resp_i.aw_ready +add wave -noupdate -expand -group {DUT mst AW} /tb_axi_fifo/i_dut/i_axi_fifo/mst_req_o.aw +add wave -noupdate -expand -group {DUT mst W} /tb_axi_fifo/i_dut/i_axi_fifo/mst_req_o.w +add wave -noupdate -expand -group {DUT mst W} /tb_axi_fifo/i_dut/i_axi_fifo/mst_req_o.w_valid +add wave -noupdate -expand -group {DUT mst W} /tb_axi_fifo/i_dut/i_axi_fifo/mst_resp_i.w_ready +add wave -noupdate -expand -group {DUT mst B} /tb_axi_fifo/i_dut/i_axi_fifo/mst_resp_i.b_valid +add wave -noupdate -expand -group {DUT mst B} /tb_axi_fifo/i_dut/i_axi_fifo/mst_req_o.b_ready +add wave -noupdate -expand -group {DUT mst B} /tb_axi_fifo/i_dut/i_axi_fifo/mst_resp_i.b +add wave -noupdate -expand -group {DUT mst AR} /tb_axi_fifo/i_dut/i_axi_fifo/mst_req_o.ar_valid +add wave -noupdate -expand -group {DUT mst AR} /tb_axi_fifo/i_dut/i_axi_fifo/mst_resp_i.ar_ready +add wave -noupdate -expand -group {DUT mst AR} /tb_axi_fifo/i_dut/i_axi_fifo/mst_req_o.ar +add wave -noupdate -expand -group {DUT mst R} /tb_axi_fifo/i_dut/i_axi_fifo/mst_resp_i.r_valid +add wave -noupdate -expand -group {DUT mst R} /tb_axi_fifo/i_dut/i_axi_fifo/mst_req_o.r_ready +add wave -noupdate -expand -group {DUT mst R} /tb_axi_fifo/i_dut/i_axi_fifo/mst_resp_i.r +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {{Cursor 1} {70 ns} 0} +quietly wave cursor active 1 +configure wave -namecolwidth 197 +configure wave -valuecolwidth 100 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ns +update +WaveRestoreZoom {0 ns} {841 ns}