Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .ci/Memora.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,21 @@ artifacts:
outputs:
- build/axi_cdc-%.tested

axi_cdc_isolatable-%:
inputs:
- Bender.yml
- include
- scripts/run_vsim.sh
- src/axi_pkg.sv
- src/axi_intf.sv
- src/axi_test.sv
- src/axi_cdc_dst_clearable.sv
- src/axi_cdc_src_clearable.sv
- src/axi_cdc_isolatable.sv
- test/tb_axi_cdc_isolatable.sv
outputs:
- build/axi_cdc_isolatable-%.tested

axi_delayer-%:
inputs:
- Bender.yml
Expand Down
5 changes: 5 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ axi_cdc:
variables:
TEST_MODULE: axi_cdc

axi_cdc_isolatable:
<<: *run_vsim
variables:
TEST_MODULE: axi_cdc_isolatable

axi_delayer:
<<: *run_vsim
variables:
Expand Down
4 changes: 4 additions & 0 deletions Bender.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ sources:
- src/axi_burst_unwrap.sv
- src/axi_bus_compare.sv
- src/axi_cdc_dst.sv
- src/axi_cdc_dst_clearable.sv
- src/axi_cdc_src.sv
- src/axi_cdc_src_clearable.sv
- src/axi_cut.sv
- src/axi_delayer.sv
- src/axi_demux_simple.sv
Expand Down Expand Up @@ -73,6 +75,7 @@ sources:
# Level 3
- src/axi_burst_splitter.sv
- src/axi_cdc.sv
- src/axi_cdc_isolatable.sv
- src/axi_demux.sv
- src/axi_err_slv.sv
- src/axi_dw_converter.sv
Expand Down Expand Up @@ -117,6 +120,7 @@ sources:
- test/tb_axi_atop_filter.sv
- test/tb_axi_bus_compare.sv
- test/tb_axi_cdc.sv
- test/tb_axi_cdc_isolatable.sv
- test/tb_axi_delayer.sv
- test/tb_axi_dw_downsizer.sv
- test/tb_axi_dw_upsizer.sv
Expand Down
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ endif

TBS ?= axi_addr_test \
axi_atop_filter \
axi_cdc axi_delayer \
axi_cdc \
axi_cdc_isolatable \
axi_delayer \
axi_dw_downsizer \
axi_dw_upsizer \
axi_fifo \
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ In addition to the documents linked in the following table, we are setting up [d
| [`axi_burst_splitter_gran`](src/axi_burst_splitter_gran.sv) | Split AXI4 burst transfers into transactions of runtime-configurable granularity. | |
| [`axi_burst_unwrap`](src/axi_burst_unwrap.sv) | Convert AXI4 wrapping burst transfers into up to two incremental bursts. | |
| [`axi_cdc`](src/axi_cdc.sv) | AXI clock domain crossing based on a Gray FIFO implementation. | |
| [`axi_cdc_isolatable`](src/axi_cdc_isolatable.sv) | Isolatable AXI clock domain crossing based on a Gray FIFO implementation allowing one-sided resets. | |
| [`axi_cut`](src/axi_cut.sv) | Breaks all combinatorial paths between its input and output. | |
| [`axi_delayer`](src/axi_delayer.sv) | Synthesizable module which can (randomly) delays AXI channels. | |
| [`axi_demux_simple`](src/axi_demux_simple.sv) | Demux without spill registers. | [Doc](doc/axi_demux.md) |
Expand Down
2 changes: 1 addition & 1 deletion scripts/run_vsim.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ exec_test() {
call_vsim tb_axi_atop_filter -gTB_N_TXNS=1000 -gTB_AXI_MAX_WRITE_TXNS=$MAX_TXNS
done
;;
axi_cdc|axi_delayer)
axi_cdc|axi_cdc_isolatable|axi_delayer)
call_vsim tb_$1
;;
axi_dw_downsizer)
Expand Down
307 changes: 307 additions & 0 deletions src/axi_cdc_dst_clearable.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,307 @@
// Copyright (c) 2019-2020 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:
// - Luca Valente <luca.valente@unibo.it>
// - Andreas Kurth <akurth@iis.ee.ethz.ch>

`include "axi/assign.svh"
`include "axi/typedef.svh"

/// Destination-clock-domain half of the clearable AXI CDC crossing.
///
/// For each of the five AXI channels, this module instantiates the source or destination half of
/// a clearable CDC FIFO. IMPORTANT: For each AXI channel, you MUST properly constrain three paths
/// through the FIFO; see the header of `cdc_fifo_gray_clearable` for instructions.
module axi_cdc_dst_clearable #(
/// Depth of the FIFO crossing the clock domain, given as 2**LOG_DEPTH.
parameter int unsigned LogDepth = 1,
/// Number of synchronization registers to insert on the async pointers
parameter int unsigned SyncStages = 2,
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,
parameter type axi_req_t = logic,
parameter type axi_resp_t = logic
) (
// asynchronous slave port
input aw_chan_t [2**LogDepth-1:0] async_data_slave_aw_data_i,
input logic [LogDepth:0] async_data_slave_aw_wptr_i,
output logic [LogDepth:0] async_data_slave_aw_rptr_o,
input w_chan_t [2**LogDepth-1:0] async_data_slave_w_data_i,
input logic [LogDepth:0] async_data_slave_w_wptr_i,
output logic [LogDepth:0] async_data_slave_w_rptr_o,
output b_chan_t [2**LogDepth-1:0] async_data_slave_b_data_o,
output logic [LogDepth:0] async_data_slave_b_wptr_o,
input logic [LogDepth:0] async_data_slave_b_rptr_i,
input ar_chan_t [2**LogDepth-1:0] async_data_slave_ar_data_i,
input logic [LogDepth:0] async_data_slave_ar_wptr_i,
output logic [LogDepth:0] async_data_slave_ar_rptr_o,
output r_chan_t [2**LogDepth-1:0] async_data_slave_r_data_o,
output logic [LogDepth:0] async_data_slave_r_wptr_o,
input logic [LogDepth:0] async_data_slave_r_rptr_i,
// synchronous master port - clocked by `dst_clk_i`
input logic dst_clk_i,
input logic dst_rst_ni,
input logic dst_clear_i,
output axi_req_t dst_req_o,
input axi_resp_t dst_resp_i
);

cdc_fifo_gray_dst_clearable #(
`ifdef QUESTA
// Workaround for a bug in Questa: Pass flat logic vector instead of struct to type parameter.
.T ( logic [$bits(aw_chan_t)-1:0] ),
`else
// Other tools, such as VCS, have problems with type parameters constructed through `$bits()`.
.T ( aw_chan_t ),
`endif
.LOG_DEPTH ( LogDepth ),
.SYNC_STAGES ( SyncStages )
) i_cdc_fifo_gray_dst_aw (
.async_data_i ( async_data_slave_aw_data_i ),
.async_wptr_i ( async_data_slave_aw_wptr_i ),
.async_rptr_o ( async_data_slave_aw_rptr_o ),
.dst_clk_i,
.dst_rst_ni,
.dst_clear_i,
.dst_data_o ( dst_req_o.aw ),
.dst_valid_o ( dst_req_o.aw_valid ),
.dst_ready_i ( dst_resp_i.aw_ready )
);

cdc_fifo_gray_dst_clearable #(
`ifdef QUESTA
.T ( logic [$bits(w_chan_t)-1:0] ),
`else
.T ( w_chan_t ),
`endif
.LOG_DEPTH ( LogDepth ),
.SYNC_STAGES ( SyncStages )
) i_cdc_fifo_gray_dst_w (
.async_data_i ( async_data_slave_w_data_i ),
.async_wptr_i ( async_data_slave_w_wptr_i ),
.async_rptr_o ( async_data_slave_w_rptr_o ),
.dst_clk_i,
.dst_rst_ni,
.dst_clear_i,
.dst_data_o ( dst_req_o.w ),
.dst_valid_o ( dst_req_o.w_valid ),
.dst_ready_i ( dst_resp_i.w_ready )
);

cdc_fifo_gray_src_clearable #(
`ifdef QUESTA
.T ( logic [$bits(b_chan_t)-1:0] ),
`else
.T ( b_chan_t ),
`endif
.LOG_DEPTH ( LogDepth ),
.SYNC_STAGES ( SyncStages )
) i_cdc_fifo_gray_src_b (
.src_clk_i ( dst_clk_i ),
.src_rst_ni ( dst_rst_ni ),
.src_clear_i ( dst_clear_i ),
.src_data_i ( dst_resp_i.b ),
.src_valid_i ( dst_resp_i.b_valid ),
.src_ready_o ( dst_req_o.b_ready ),
.async_data_o ( async_data_slave_b_data_o ),
.async_wptr_o ( async_data_slave_b_wptr_o ),
.async_rptr_i ( async_data_slave_b_rptr_i )
);

cdc_fifo_gray_dst_clearable #(
`ifdef QUESTA
.T ( logic [$bits(ar_chan_t)-1:0] ),
`else
.T ( ar_chan_t ),
`endif
.LOG_DEPTH ( LogDepth ),
.SYNC_STAGES ( SyncStages )
) i_cdc_fifo_gray_dst_ar (
.dst_clk_i,
.dst_rst_ni,
.dst_clear_i,
.dst_data_o ( dst_req_o.ar ),
.dst_valid_o ( dst_req_o.ar_valid ),
.dst_ready_i ( dst_resp_i.ar_ready ),
.async_data_i ( async_data_slave_ar_data_i ),
.async_wptr_i ( async_data_slave_ar_wptr_i ),
.async_rptr_o ( async_data_slave_ar_rptr_o )
);

cdc_fifo_gray_src_clearable #(
`ifdef QUESTA
.T ( logic [$bits(r_chan_t)-1:0] ),
`else
.T ( r_chan_t ),
`endif
.LOG_DEPTH ( LogDepth ),
.SYNC_STAGES ( SyncStages )
) i_cdc_fifo_gray_src_r (
.src_clk_i ( dst_clk_i ),
.src_rst_ni ( dst_rst_ni ),
.src_clear_i ( dst_clear_i ),
.src_data_i ( dst_resp_i.r ),
.src_valid_i ( dst_resp_i.r_valid ),
.src_ready_o ( dst_req_o.r_ready ),
.async_data_o ( async_data_slave_r_data_o ),
.async_wptr_o ( async_data_slave_r_wptr_o ),
.async_rptr_i ( async_data_slave_r_rptr_i )
);

endmodule


module axi_cdc_dst_clearable_intf #(
parameter int unsigned AXI_ID_WIDTH = 0,
parameter int unsigned AXI_ADDR_WIDTH = 0,
parameter int unsigned AXI_DATA_WIDTH = 0,
parameter int unsigned AXI_USER_WIDTH = 0,
/// Depth of the FIFO crossing the clock domain, given as 2**LOG_DEPTH.
parameter int unsigned LOG_DEPTH = 1,
/// Number of synchronization registers to insert on the async pointers
parameter int unsigned SYNC_STAGES = 2
) (
// asynchronous slave port
AXI_BUS_ASYNC_GRAY.Slave src,
// synchronous master port - clocked by `dst_clk_i`
input logic dst_clk_i,
input logic dst_rst_ni,
input logic dst_clear_i,
AXI_BUS.Master dst
);

typedef logic [AXI_ID_WIDTH-1:0] id_t;
typedef logic [AXI_ADDR_WIDTH-1:0] addr_t;
typedef logic [AXI_DATA_WIDTH-1:0] data_t;
typedef logic [AXI_DATA_WIDTH/8-1:0] strb_t;
typedef logic [AXI_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(req_t, aw_chan_t, w_chan_t, ar_chan_t)
`AXI_TYPEDEF_RESP_T(resp_t, b_chan_t, r_chan_t)

req_t dst_req;
resp_t dst_resp;

axi_cdc_dst_clearable #(
.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 ( req_t ),
.axi_resp_t ( resp_t ),
.LogDepth ( LOG_DEPTH ),
.SyncStages ( SYNC_STAGES )
) i_axi_cdc_dst (
.async_data_slave_aw_data_i ( src.aw_data ),
.async_data_slave_aw_wptr_i ( src.aw_wptr ),
.async_data_slave_aw_rptr_o ( src.aw_rptr ),
.async_data_slave_w_data_i ( src.w_data ),
.async_data_slave_w_wptr_i ( src.w_wptr ),
.async_data_slave_w_rptr_o ( src.w_rptr ),
.async_data_slave_b_data_o ( src.b_data ),
.async_data_slave_b_wptr_o ( src.b_wptr ),
.async_data_slave_b_rptr_i ( src.b_rptr ),
.async_data_slave_ar_data_i ( src.ar_data ),
.async_data_slave_ar_wptr_i ( src.ar_wptr ),
.async_data_slave_ar_rptr_o ( src.ar_rptr ),
.async_data_slave_r_data_o ( src.r_data ),
.async_data_slave_r_wptr_o ( src.r_wptr ),
.async_data_slave_r_rptr_i ( src.r_rptr ),
.dst_clk_i,
.dst_rst_ni,
.dst_clear_i,
.dst_req_o ( dst_req ),
.dst_resp_i ( dst_resp )
);

`AXI_ASSIGN_FROM_REQ(dst, dst_req)
`AXI_ASSIGN_TO_RESP(dst_resp, dst)

endmodule


module axi_lite_cdc_dst_clearable_intf #(
parameter int unsigned AXI_ADDR_WIDTH = 0,
parameter int unsigned AXI_DATA_WIDTH = 0,
/// Depth of the FIFO crossing the clock domain, given as 2**LOG_DEPTH.
parameter int unsigned LOG_DEPTH = 1,
/// Number of synchronization registers to insert on the async pointers
parameter int unsigned SYNC_STAGES = 2
) (
// asynchronous slave port
AXI_LITE_ASYNC_GRAY.Slave src,
// synchronous master port - clocked by `dst_clk_i`
input logic dst_clk_i,
input logic dst_rst_ni,
input logic dst_clear_i,
AXI_LITE.Master dst
);

typedef logic [AXI_ADDR_WIDTH-1:0] addr_t;
typedef logic [AXI_DATA_WIDTH-1:0] data_t;
typedef logic [AXI_DATA_WIDTH/8-1:0] strb_t;
`AXI_LITE_TYPEDEF_AW_CHAN_T(aw_chan_t, addr_t)
`AXI_LITE_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t)
`AXI_LITE_TYPEDEF_B_CHAN_T(b_chan_t)
`AXI_LITE_TYPEDEF_AR_CHAN_T(ar_chan_t, addr_t)
`AXI_LITE_TYPEDEF_R_CHAN_T(r_chan_t, data_t)
`AXI_LITE_TYPEDEF_REQ_T(req_t, aw_chan_t, w_chan_t, ar_chan_t)
`AXI_LITE_TYPEDEF_RESP_T(resp_t, b_chan_t, r_chan_t)

req_t dst_req;
resp_t dst_resp;

axi_cdc_dst_clearable #(
.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 ( req_t ),
.axi_resp_t ( resp_t ),
.LogDepth ( LOG_DEPTH ),
.SyncStages ( SYNC_STAGES )
) i_axi_cdc_dst (
.async_data_slave_aw_data_i ( src.aw_data ),
.async_data_slave_aw_wptr_i ( src.aw_wptr ),
.async_data_slave_aw_rptr_o ( src.aw_rptr ),
.async_data_slave_w_data_i ( src.w_data ),
.async_data_slave_w_wptr_i ( src.w_wptr ),
.async_data_slave_w_rptr_o ( src.w_rptr ),
.async_data_slave_b_data_o ( src.b_data ),
.async_data_slave_b_wptr_o ( src.b_wptr ),
.async_data_slave_b_rptr_i ( src.b_rptr ),
.async_data_slave_ar_data_i ( src.ar_data ),
.async_data_slave_ar_wptr_i ( src.ar_wptr ),
.async_data_slave_ar_rptr_o ( src.ar_rptr ),
.async_data_slave_r_data_o ( src.r_data ),
.async_data_slave_r_wptr_o ( src.r_wptr ),
.async_data_slave_r_rptr_i ( src.r_rptr ),
.dst_clk_i,
.dst_rst_ni,
.dst_clear_i,
.dst_req_o ( dst_req ),
.dst_resp_i ( dst_resp )
);

`AXI_LITE_ASSIGN_FROM_REQ(dst, dst_req)
`AXI_LITE_ASSIGN_TO_RESP(dst_resp, dst)

endmodule
Loading