Skip to content

Instantly share code, notes, and snippets.

@mlyoung101
Created May 4, 2026 08:07
Show Gist options
  • Select an option

  • Save mlyoung101/1756c6f4361b8e87316d235354b03eff to your computer and use it in GitHub Desktop.

Select an option

Save mlyoung101/1756c6f4361b8e87316d235354b03eff to your computer and use it in GitHub Desktop.
This file has been truncated, but you can view the full file.
// Dump of all post-preprocessor input
// Blank lines and `line directives have been removed
//
// Information:
// Version: Verilator 5.048 2026-04-26 rev v5.048
// Arguments: --lint-only --top-module tb_axi_xbar --timing -j 10 +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR /home/mel/build/axi/.bender/git/checkouts/common_verification-5b9bacfe2f79eb87/src/clk_rst_gen.sv /home/mel/build/axi/.bender/git/checkouts/common_verification-5b9bacfe2f79eb87/src/sim_timeout.sv /home/mel/build/axi/.bender/git/checkouts/common_verification-5b9bacfe2f79eb87/src/stream_watchdog.sv /home/mel/build/axi/.bender/git/checkouts/common_verification-5b9bacfe2f79eb87/src/signal_highlighter.sv +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR /home/mel/build/axi/.bender/git/checkouts/common_verification-5b9bacfe2f79eb87/src/rand_id_queue.sv /home/mel/build/axi/.bender/git/checkouts/common_verification-5b9bacfe2f79eb87/src/rand_stream_mst.sv /home/mel/build/axi/.bender/git/checkouts/common_verification-5b9bacfe2f79eb87/src/rand_synch_holdable_driver.sv /home/mel/build/axi/.bender/git/checkouts/common_verification-5b9bacfe2f79eb87/src/rand_verif_pkg.sv /home/mel/build/axi/.bender/git/checkouts/common_verification-5b9bacfe2f79eb87/src/rand_synch_driver.sv /home/mel/build/axi/.bender/git/checkouts/common_verification-5b9bacfe2f79eb87/src/rand_stream_slv.sv +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR /home/mel/build/axi/.bender/git/checkouts/common_verification-5b9bacfe2f79eb87/test/tb_clk_rst_gen.sv +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR /home/mel/build/axi/.bender/git/checkouts/tech_cells_generic-6e6736c6cf5dbb6b/src/rtl/tc_sram.sv /home/mel/build/axi/.bender/git/checkouts/tech_cells_generic-6e6736c6cf5dbb6b/src/rtl/tc_sram_impl.sv +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR /home/mel/build/axi/.bender/git/checkouts/tech_cells_generic-6e6736c6cf5dbb6b/src/rtl/tc_clk.sv +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR /home/mel/build/axi/.bender/git/checkouts/tech_cells_generic-6e6736c6cf5dbb6b/test/tb_tc_sram.sv +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR /home/mel/build/axi/.bender/git/checkouts/tech_cells_generic-6e6736c6cf5dbb6b/src/deprecated/pulp_clock_gating_async.sv /home/mel/build/axi/.bender/git/checkouts/tech_cells_generic-6e6736c6cf5dbb6b/src/deprecated/cluster_clk_cells.sv /home/mel/build/axi/.bender/git/checkouts/tech_cells_generic-6e6736c6cf5dbb6b/src/deprecated/pulp_clk_cells.sv +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR +incdir+/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/include /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/binary_to_gray.sv +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR +incdir+/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/include /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cb_filter_pkg.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cc_onehot.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_reset_ctrlr_pkg.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cf_math_pkg.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/clk_int_div.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/credit_counter.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/delta_counter.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/ecc_pkg.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/edge_propagator_tx.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/exp_backoff.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/fifo_v3.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/gray_to_binary.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/heaviside.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/isochronous_4phase_handshake.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/isochronous_spill_register.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/lfsr.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/lfsr_16bit.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/lfsr_8bit.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/lossy_valid_to_stream.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/mv_filter.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/onehot_to_bin.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/plru_tree.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/passthrough_stream_fifo.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/popcount.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/ring_buffer.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/rr_arb_tree.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/rstgen_bypass.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/serial_deglitch.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/shift_reg.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/shift_reg_gated.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/spill_register_flushable.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_demux.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_filter.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_fork.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_intf.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_join_dynamic.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_mux.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_throttle.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/sub_per_hash.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/sync.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/sync_wedge.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/unread.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/read.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/addr_decode_dync.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/boxcar.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_2phase.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_4phase.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/clk_int_div_static.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/trip_counter.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/addr_decode.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/addr_decode_napot.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/multiaddr_decode.sv +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR +incdir+/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/include /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cb_filter.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_fifo_2phase.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/clk_mux_glitch_free.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/counter.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/ecc_decode.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/ecc_encode.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/edge_detect.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/lzc.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/max_counter.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/rstgen.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/spill_register.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_delay.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_fifo.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_fork_dynamic.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_join.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_reset_ctrlr.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_fifo_gray.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/fall_through_register.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/id_queue.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_to_mem.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_arbiter_flushable.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_fifo_optimal_wrap.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_register.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_xbar.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_fifo_gray_clearable.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_2phase_clearable.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/mem_to_banks_detailed.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_arbiter.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_omega_net.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/mem_to_banks.sv +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR +incdir+/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/include /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/addr_decode_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/cb_filter_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/cdc_2phase_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/cdc_2phase_clearable_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/cdc_fifo_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/cdc_fifo_clearable_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/fifo_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/graycode_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/id_queue_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/passthrough_stream_fifo_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/popcount_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/rr_arb_tree_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/stream_test.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/stream_register_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/stream_to_mem_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/sub_per_hash_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/isochronous_crossing_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/stream_omega_net_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/stream_xbar_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/clk_int_div_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/clk_int_div_static_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/clk_mux_glitch_free_tb.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/lossy_valid_to_stream_tb.sv +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR +incdir+/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/include /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/deprecated/clock_divider_counter.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/deprecated/clk_div.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/deprecated/find_first_one.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/deprecated/generic_LFSR_8bit.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/deprecated/generic_fifo.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/deprecated/prioarbiter.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/deprecated/pulp_sync.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/deprecated/pulp_sync_wedge.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/deprecated/rrarbiter.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/deprecated/clock_divider.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/deprecated/fifo_v2.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/deprecated/fifo_v1.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/edge_propagator_ack.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/edge_propagator.sv /home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/edge_propagator_rx.sv +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR +incdir+/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/include +incdir+/home/mel/build/axi/include /home/mel/build/axi/src/axi_pkg.sv /home/mel/build/axi/src/axi_demux_id_counters.sv /home/mel/build/axi/src/axi_intf.sv /home/mel/build/axi/src/axi_atop_filter.sv /home/mel/build/axi/src/axi_burst_splitter_gran.sv /home/mel/build/axi/src/axi_burst_unwrap.sv /home/mel/build/axi/src/axi_bus_compare.sv /home/mel/build/axi/src/axi_cdc_dst.sv /home/mel/build/axi/src/axi_cdc_src.sv /home/mel/build/axi/src/axi_cut.sv /home/mel/build/axi/src/axi_delayer.sv /home/mel/build/axi/src/axi_demux_simple.sv /home/mel/build/axi/src/axi_dw_downsizer.sv /home/mel/build/axi/src/axi_dw_upsizer.sv /home/mel/build/axi/src/axi_fifo.sv /home/mel/build/axi/src/axi_fifo_delay_dyn.sv /home/mel/build/axi/src/axi_id_remap.sv /home/mel/build/axi/src/axi_id_prepend.sv /home/mel/build/axi/src/axi_inval_filter.sv /home/mel/build/axi/src/axi_isolate.sv /home/mel/build/axi/src/axi_join.sv /home/mel/build/axi/src/axi_lite_demux.sv /home/mel/build/axi/src/axi_lite_dw_converter.sv /home/mel/build/axi/src/axi_lite_from_mem.sv /home/mel/build/axi/src/axi_lite_join.sv /home/mel/build/axi/src/axi_lite_lfsr.sv /home/mel/build/axi/src/axi_lite_mailbox.sv /home/mel/build/axi/src/axi_lite_mux.sv /home/mel/build/axi/src/axi_lite_regs.sv /home/mel/build/axi/src/axi_lite_to_apb.sv /home/mel/build/axi/src/axi_lite_to_axi.sv /home/mel/build/axi/src/axi_modify_address.sv /home/mel/build/axi/src/axi_mux.sv /home/mel/build/axi/src/axi_rw_join.sv /home/mel/build/axi/src/axi_rw_split.sv /home/mel/build/axi/src/axi_serializer.sv /home/mel/build/axi/src/axi_slave_compare.sv /home/mel/build/axi/src/axi_throttle.sv /home/mel/build/axi/src/axi_to_detailed_mem.sv /home/mel/build/axi/src/axi_burst_splitter.sv /home/mel/build/axi/src/axi_cdc.sv /home/mel/build/axi/src/axi_demux.sv /home/mel/build/axi/src/axi_err_slv.sv /home/mel/build/axi/src/axi_dw_converter.sv /home/mel/build/axi/src/axi_from_mem.sv /home/mel/build/axi/src/axi_id_serialize.sv /home/mel/build/axi/src/axi_lfsr.sv /home/mel/build/axi/src/axi_multicut.sv /home/mel/build/axi/src/axi_to_axi_lite.sv /home/mel/build/axi/src/axi_to_mem.sv /home/mel/build/axi/src/axi_zero_mem.sv /home/mel/build/axi/src/axi_interleaved_xbar.sv /home/mel/build/axi/src/axi_iw_converter.sv /home/mel/build/axi/src/axi_lite_xbar.sv /home/mel/build/axi/src/axi_xbar_unmuxed.sv /home/mel/build/axi/src/axi_to_mem_banked.sv /home/mel/build/axi/src/axi_to_mem_interleaved.sv /home/mel/build/axi/src/axi_to_mem_split.sv /home/mel/build/axi/src/axi_xbar.sv /home/mel/build/axi/src/axi_xp.sv +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR +incdir+/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/include +incdir+/home/mel/build/axi/include /home/mel/build/axi/src/axi_chan_compare.sv /home/mel/build/axi/src/axi_dumper.sv /home/mel/build/axi/src/axi_sim_mem.sv /home/mel/build/axi/src/axi_test.sv +define+TARGET_SIMULATION +define+TARGET_SYNTHESIS +define+TARGET_TEST +define+TARGET_VERILATOR +incdir+/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/include +incdir+/home/mel/build/axi/include /home/mel/build/axi/test/tb_axi_dw_pkg.sv /home/mel/build/axi/test/tb_axi_xbar_pkg.sv /home/mel/build/axi/test/tb_axi_addr_test.sv /home/mel/build/axi/test/tb_axi_atop_filter.sv /home/mel/build/axi/test/tb_axi_bus_compare.sv /home/mel/build/axi/test/tb_axi_cdc.sv /home/mel/build/axi/test/tb_axi_delayer.sv /home/mel/build/axi/test/tb_axi_dw_downsizer.sv /home/mel/build/axi/test/tb_axi_dw_upsizer.sv /home/mel/build/axi/test/tb_axi_fifo.sv /home/mel/build/axi/test/tb_axi_isolate.sv /home/mel/build/axi/test/tb_axi_lite_dw_converter.sv /home/mel/build/axi/test/tb_axi_lite_mailbox.sv /home/mel/build/axi/test/tb_axi_lite_regs.sv /home/mel/build/axi/test/tb_axi_iw_converter.sv /home/mel/build/axi/test/tb_axi_lite_to_apb.sv /home/mel/build/axi/test/tb_axi_lite_to_axi.sv /home/mel/build/axi/test/tb_axi_lite_xbar.sv /home/mel/build/axi/test/tb_axi_modify_address.sv /home/mel/build/axi/test/tb_axi_serializer.sv /home/mel/build/axi/test/tb_axi_sim_mem.sv /home/mel/build/axi/test/tb_axi_slave_compare.sv /home/mel/build/axi/test/tb_axi_to_axi_lite.sv /home/mel/build/axi/test/tb_axi_to_mem_banked.sv /home/mel/build/axi/test/tb_axi_xbar.sv --debug
// Build jobs: 10
// Verilate jobs: 10
// verilator fargs --lint-only
// verilator fargs --top-module tb_axi_xbar
// verilator fargs --timing
// verilator fargs -j 10
`begin_keywords "1800-2023"
module clk_rst_gen #(
parameter time ClkPeriod = 0ps,
parameter int unsigned RstClkCycles = 0
) (
output logic clk_o,
output logic rst_no
);
logic clk;
initial begin
clk = 1'b0;
end
always begin
clk = 1'b1;
#(ClkPeriod / 2);
clk = 1'b0;
#((ClkPeriod + 1) / 2);
end
assign clk_o = clk;
initial begin
static int unsigned rst_cnt = 0;
rst_no = 1'b0;
#(ClkPeriod / 2);
while (rst_cnt < RstClkCycles) begin
@(posedge clk);
rst_cnt++;
end
rst_no = 1'b1;
end
endmodule
`begin_keywords "1800-2023"
module sim_timeout #(
parameter longint unsigned Cycles = 0,
parameter bit ResetRestartsTimeout = 1'b0
) (
input logic clk_i,
input logic rst_ni
);
longint unsigned cycles = 0;
always_ff @(posedge clk_i, negedge rst_ni) begin
if (ResetRestartsTimeout && !rst_ni) begin
cycles <= 0;
end else begin
cycles <= cycles + 1;
end
if (cycles > Cycles) begin
$fatal(1, "Timeout exceeded!");
end
end
endmodule
`begin_keywords "1800-2023"
module stream_watchdog #(
parameter int unsigned NumCycles
)(
input logic clk_i,
input logic rst_ni,
input logic valid_i,
input logic ready_i
);
int unsigned cnt;
initial begin : wd
cnt = NumCycles;
while (cnt > 0) begin
if (valid_i && ready_i || !rst_ni) begin
cnt = NumCycles;
end else begin
cnt--;
end
@(posedge clk_i);
end
$fatal(1, "Tripped Watchdog (%m) at %dns, Inactivity for %d cycles", $time(), NumCycles);
end
endmodule
`begin_keywords "1800-2023"
module signal_highlighter #(
parameter type T = logic
)(
input logic ready_i,
input logic valid_i,
input T data_i
);
T in_wave;
always_comb begin
in_wave = 'Z;
if (ready_i & valid_i) begin
in_wave = data_i;
end
end
endmodule
`begin_keywords "1800-2023"
package rand_id_queue_pkg;
class rand_id_queue #(
type data_t = logic,
int unsigned ID_WIDTH = 0
);
localparam int unsigned N_IDS = 2**ID_WIDTH;
localparam type id_t = logic[ID_WIDTH-1:0];
data_t queues[N_IDS-1:0][$];
int unsigned size;
function new();
size = 0;
endfunction
function void push(id_t id, data_t data);
queues[id].push_back(data);
size++;
endfunction
function bit empty();
return (size == 0);
endfunction
function bit is_empty();
return (size == 0);
endfunction
function data_t peek();
return queues[rand_id()][0];
endfunction
function data_t pop();
return pop_id(rand_id());
endfunction
function data_t pop_id(id_t id);
size--;
return queues[id].pop_front();
endfunction
function id_t rand_id();
if (!is_empty()) begin
id_t id;
do begin
void'(std::randomize(id));
end while (queues[id].size() == 0);
return id;
end else begin
return 'x;
end
endfunction
function void set(id_t id, data_t data);
queues[id][0] = data;
endfunction
function data_t get(id_t id);
return queues[id][0];
endfunction
endclass
endpackage
`begin_keywords "1800-2023"
module rand_stream_mst #(
parameter type data_t = logic,
parameter int MinWaitCycles = -1,
parameter int MaxWaitCycles = -1,
parameter time ApplDelay = 0ps,
parameter time AcqDelay = 0ps
) (
input logic clk_i,
input logic rst_ni,
output data_t data_o,
output logic valid_o,
input logic ready_i
);
int unsigned rand_wait_cycles;
function static void randomize_wait_cycles();
int unsigned rand_success;
rand_success = std::randomize(rand_wait_cycles) with {
rand_wait_cycles >= MinWaitCycles;
rand_wait_cycles <= MaxWaitCycles;
};
assert (rand_success) else $error("Failed to randomize wait cycles!");
endfunction
initial begin
data_o = '0;
valid_o = 1'b0;
wait (rst_ni);
randomize_wait_cycles();
@(posedge clk_i);
forever begin
repeat(rand_wait_cycles) begin
@(posedge clk_i);
end
#(ApplDelay);
void'(std::randomize(data_o));
valid_o = 1'b1;
#(AcqDelay-ApplDelay);
while (!ready_i) begin
@(posedge clk_i);
#(AcqDelay);
end
randomize_wait_cycles();
if (rand_wait_cycles == 0) begin
@(posedge clk_i);
end else begin
@(posedge clk_i);
#(ApplDelay);
valid_o = 1'b0;
void'(std::randomize(data_o));
end
end
end
endmodule
`begin_keywords "1800-2023"
module rand_synch_holdable_driver #(
parameter type data_t = logic,
parameter int MinWaitCycles = -1,
parameter int MaxWaitCycles = -1,
parameter time ApplDelay = 0ps
) (
input logic clk_i,
input logic rst_ni,
input logic hold_i,
output data_t data_o
);
initial begin
int unsigned rand_delay, rand_success;
data_o = '0;
wait (rst_ni);
@(posedge clk_i);
forever begin
rand_success = std::randomize(rand_delay) with {
rand_delay >= MinWaitCycles;
rand_delay <= MaxWaitCycles;
};
assert (rand_success) else $error("Failed to randomize wait cycles!");
repeat(rand_delay) begin
@(posedge clk_i);
end
#(ApplDelay);
if (!hold_i) begin
void'(std::randomize(data_o));
end
end
end
endmodule
`begin_keywords "1800-2023"
package rand_verif_pkg;
task automatic rand_wait(input int unsigned min, max, ref logic clk);
int unsigned rand_success, cycles;
rand_success = std::randomize(cycles) with {
cycles >= min;
cycles <= max;
};
assert (rand_success) else $error("Failed to randomize wait cycles!");
repeat (cycles) @(posedge clk);
endtask
endpackage
`begin_keywords "1800-2023"
module rand_synch_driver #(
parameter type data_t = logic,
parameter int MinWaitCycles = -1,
parameter int MaxWaitCycles = -1,
parameter time ApplDelay = 0ps
) (
input logic clk_i,
input logic rst_ni,
output data_t data_o
);
rand_synch_holdable_driver #(
.data_t (data_t),
.MinWaitCycles (MinWaitCycles),
.MaxWaitCycles (MaxWaitCycles),
.ApplDelay (ApplDelay)
) i_ready_driver (
.clk_i (clk_i),
.rst_ni (rst_ni),
.hold_i (1'b0),
.data_o (data_o)
);
endmodule
`begin_keywords "1800-2023"
module rand_stream_slv #(
parameter type data_t = logic,
parameter int MinWaitCycles = -1,
parameter int MaxWaitCycles = -1,
parameter time ApplDelay = 0ps,
parameter time AcqDelay = 0ps,
parameter bit Enqueue = 1'b0
) (
input logic clk_i,
input logic rst_ni,
input data_t data_i,
input logic valid_i,
output logic ready_o
);
if (Enqueue) begin: gen_queue
data_t queue[$];
always @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
queue = {};
end else begin
#(AcqDelay);
if (valid_i && ready_o) begin
queue.push_back(data_i);
end
end
end
end
rand_synch_driver #(
.data_t (logic),
.MinWaitCycles (MinWaitCycles),
.MaxWaitCycles (MaxWaitCycles),
.ApplDelay (ApplDelay)
) i_ready_driver (
.clk_i (clk_i),
.rst_ni (rst_ni),
.data_o (ready_o)
);
endmodule
`begin_keywords "1800-2023"
module tb_clk_rst_gen #(
parameter time TbClkPeriod = 10ns,
parameter int unsigned TbClkCycles = 12,
parameter int unsigned TbRstClkCycles = 7,
parameter bit TbDebugPrint = 1'b0
) ();
logic clk,
rst_n;
clk_rst_gen #(
.ClkPeriod (TbClkPeriod),
.RstClkCycles (TbRstClkCycles)
) i_dut (
.clk_o (clk),
.rst_no (rst_n)
);
int unsigned clk_cnt,
rst_cnt;
initial begin
clk_cnt = 0;
rst_cnt = 0;
while (1) begin
#(TbClkPeriod - 1);
if (rst_n == 1'b0) begin
rst_cnt++;
if (TbDebugPrint) $info("Reset clock cycle complete");
end
@(posedge clk);
clk_cnt++;
if (TbDebugPrint) $info("Clock cycle complete");
end
end
initial begin
static time TB_RUN_TIME = TbClkCycles * TbClkPeriod + (TbClkPeriod / 2);
assert (TbRstClkCycles < TbClkCycles)
else $fatal(1, "The number of clock cycles must be larger than the number of reset cycles!");
#TB_RUN_TIME;
assert (clk_cnt == TbClkCycles)
else $error("Counted %0d instead of %0d clock cycles!", clk_cnt, TbClkCycles);
assert (rst_cnt == TbRstClkCycles)
else $error("Counted %0d instead of %0d reset clock cycles!", rst_cnt, TbRstClkCycles);
$finish();
end
endmodule
`begin_keywords "1800-2023"
module tc_sram #(
parameter int unsigned NumWords = 32'd1024,
parameter int unsigned DataWidth = 32'd128,
parameter int unsigned ByteWidth = 32'd8,
parameter int unsigned NumPorts = 32'd2,
parameter int unsigned Latency = 32'd1,
parameter SimInit = "none",
parameter bit PrintSimCfg = 1'b0,
parameter ImplKey = "none",
parameter int unsigned AddrWidth = (NumWords > 32'd1) ? $clog2(NumWords) : 32'd1,
parameter int unsigned BeWidth = (DataWidth + ByteWidth - 32'd1) / ByteWidth,
parameter type addr_t = logic [AddrWidth-1:0],
parameter type data_t = logic [DataWidth-1:0],
parameter type be_t = logic [BeWidth-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic [NumPorts-1:0] req_i,
input logic [NumPorts-1:0] we_i,
input addr_t [NumPorts-1:0] addr_i,
input data_t [NumPorts-1:0] wdata_i,
input be_t [NumPorts-1:0] be_i,
output data_t [NumPorts-1:0] rdata_o
);
data_t sram [NumWords-1:0];
addr_t [NumPorts-1:0] r_addr_q;
data_t init_val[NumWords-1:0];
initial begin : proc_sram_init
for (int unsigned i = 0; i < NumWords; i++) begin
case (SimInit)
"zeros": init_val[i] = {DataWidth{1'b0}};
"ones": init_val[i] = {DataWidth{1'b1}};
"random": init_val[i] = {DataWidth{$urandom()}};
default: init_val[i] = {DataWidth{1'bx}};
endcase
end
end
data_t [NumPorts-1:0][Latency-1:0] rdata_q, rdata_d;
if (Latency == 32'd0) begin : gen_no_read_lat
for (genvar i = 0; i < NumPorts; i++) begin : gen_port
assign rdata_o[i] = (req_i[i] && !we_i[i]) ? sram[addr_i[i]] : sram[r_addr_q[i]];
end
end else begin : gen_read_lat
always_comb begin
for (int unsigned i = 0; i < NumPorts; i++) begin
rdata_o[i] = rdata_q[i][0];
for (int unsigned j = 0; j < (Latency-1); j++) begin
rdata_d[i][j] = rdata_q[i][j+1];
end
rdata_d[i][Latency-1] = (req_i[i] && !we_i[i]) ? sram[addr_i[i]] : sram[r_addr_q[i]];
end
end
end
if (SimInit == "none") begin
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
for (int i = 0; i < NumPorts; i++) begin
r_addr_q[i] <= {AddrWidth{1'b0}};
end
end else begin
for (int unsigned i = 0; i < NumPorts; i++) begin
if (Latency != 0) begin
for (int unsigned j = 0; j < Latency; j++) begin
rdata_q[i][j] <= rdata_d[i][j];
end
end
end
for (int unsigned i = 0; i < NumPorts; i++) begin
if (req_i[i]) begin
if (we_i[i]) begin
for (int unsigned j = 0; j < BeWidth; j++) begin
if (be_i[i][j]) begin
sram[addr_i[i]][j*ByteWidth+:ByteWidth] <= wdata_i[i][j*ByteWidth+:ByteWidth];
end
end
end else begin
r_addr_q[i] <= addr_i[i];
end
end
end
end
end
end else begin
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
sram <= init_val;
for (int i = 0; i < NumPorts; i++) begin
r_addr_q[i] <= {AddrWidth{1'b0}};
if (Latency != 32'd0) begin
for (int unsigned j = 0; j < Latency; j++) begin
rdata_q[i][j] <= init_val[{AddrWidth{1'b0}}];
end
end
end
end else begin
for (int unsigned i = 0; i < NumPorts; i++) begin
if (Latency != 0) begin
for (int unsigned j = 0; j < Latency; j++) begin
rdata_q[i][j] <= rdata_d[i][j];
end
end
end
for (int unsigned i = 0; i < NumPorts; i++) begin
if (req_i[i]) begin
if (we_i[i]) begin
for (int unsigned j = 0; j < BeWidth; j++) begin
if (be_i[i][j]) begin
sram[addr_i[i]][j*ByteWidth+:ByteWidth] <= wdata_i[i][j*ByteWidth+:ByteWidth];
end
end
end else begin
r_addr_q[i] <= addr_i[i];
end
end
end
end
end
end
endmodule
`begin_keywords "1800-2023"
module tc_sram_impl #(
parameter int unsigned NumWords = 32'd1024,
parameter int unsigned DataWidth = 32'd128,
parameter int unsigned ByteWidth = 32'd8,
parameter int unsigned NumPorts = 32'd2,
parameter int unsigned Latency = 32'd1,
parameter SimInit = "none",
parameter bit PrintSimCfg = 1'b0,
parameter ImplKey = "none",
parameter type impl_in_t = logic,
parameter type impl_out_t = logic,
parameter impl_out_t ImplOutSim = 'X,
parameter int unsigned AddrWidth = (NumWords > 32'd1) ? $clog2(NumWords) : 32'd1,
parameter int unsigned BeWidth = (DataWidth + ByteWidth - 32'd1) / ByteWidth,
parameter type addr_t = logic [AddrWidth-1:0],
parameter type data_t = logic [DataWidth-1:0],
parameter type be_t = logic [BeWidth-1:0]
) (
input logic clk_i,
input logic rst_ni,
input impl_in_t impl_i,
output impl_out_t impl_o,
input logic [NumPorts-1:0] req_i,
input logic [NumPorts-1:0] we_i,
input addr_t [NumPorts-1:0] addr_i,
input data_t [NumPorts-1:0] wdata_i,
input be_t [NumPorts-1:0] be_i,
output data_t [NumPorts-1:0] rdata_o
);
assign impl_o = ImplOutSim;
tc_sram #(
.NumWords ( NumWords ),
.DataWidth ( DataWidth ),
.ByteWidth ( ByteWidth ),
.NumPorts ( NumPorts ),
.Latency ( Latency ),
.SimInit ( SimInit ),
.PrintSimCfg ( PrintSimCfg ),
.ImplKey ( ImplKey )
) i_tc_sram (
.clk_i,
.rst_ni,
.req_i,
.we_i,
.addr_i,
.wdata_i,
.be_i,
.rdata_o
);
endmodule
`begin_keywords "1800-2023"
module tc_clk_and2 (
input logic clk0_i,
input logic clk1_i,
output logic clk_o
);
assign clk_o = clk0_i & clk1_i;
endmodule
module tc_clk_buffer (
input logic clk_i,
output logic clk_o
);
assign clk_o = clk_i;
endmodule
module tc_clk_gating #(
parameter bit IS_FUNCTIONAL = 1'b1
)(
input logic clk_i,
input logic en_i,
input logic test_en_i,
output logic clk_o
);
logic clk_en;
always_latch begin
if (clk_i == 1'b0) clk_en <= en_i | test_en_i;
end
assign clk_o = clk_i & clk_en;
endmodule
module tc_clk_inverter (
input logic clk_i,
output logic clk_o
);
assign clk_o = ~clk_i;
endmodule
module tc_clk_mux2 (
input logic clk0_i,
input logic clk1_i,
input logic clk_sel_i,
output logic clk_o
);
assign clk_o = (clk_sel_i) ? clk1_i : clk0_i;
endmodule
module tc_clk_xor2 (
input logic clk0_i,
input logic clk1_i,
output logic clk_o
);
assign clk_o = clk0_i ^ clk1_i;
endmodule
module tc_clk_or2 (
input logic clk0_i,
input logic clk1_i,
output logic clk_o
);
assign clk_o = clk0_i | clk1_i;
endmodule
module tc_clk_delay #(
parameter int unsigned Delay = 300ps
) (
input logic in_i,
output logic out_o
);
endmodule
`begin_keywords "1800-2023"
module tb_tc_sram #(
parameter int unsigned NumPorts = 32'd2,
parameter int unsigned Latency = 32'd1,
parameter int unsigned NumWords = 32'd1024,
parameter int unsigned DataWidth = 32'd64,
parameter int unsigned ByteWidth = 32'd8,
parameter int unsigned NoReq = 32'd200000,
parameter string SimInit = "zeros",
parameter time CyclTime = 10ns,
parameter time ApplTime = 2ns,
parameter time TestTime = 8ns
);
logic clk, rst_n;
clk_rst_gen #(
.ClkPeriod ( CyclTime ),
.RstClkCycles( 5 )
) i_clk_gen (
.clk_o ( clk ),
.rst_no ( rst_n )
);
logic [NumPorts-1:0] done;
localparam int unsigned AddrWidth = (NumWords > 32'd1) ? $clog2(NumWords) : 32'd1;
localparam int unsigned BeWidth = (DataWidth + ByteWidth - 32'd1) / ByteWidth;
typedef logic [AddrWidth-1:0] addr_t;
typedef logic [DataWidth-1:0] data_t;
typedef logic [BeWidth-1:0] be_t;
logic [NumPorts-1:0] req, we;
addr_t [NumPorts-1:0] addr;
data_t [NumPorts-1:0] wdata, rdata;
be_t [NumPorts-1:0] be;
data_t memory [NumWords-1:0];
longint unsigned failed_test;
for (genvar i = 0; i < NumPorts; i++) begin : gen_stimuli
initial begin : proc_drive_port
automatic logic stim_write;
automatic addr_t stim_addr;
automatic data_t stim_data;
automatic be_t stim_be;
done[i] <= 1'b0;
req[i] <= 1'b0;
we[i] <= 1'b0;
addr[i] <= addr_t'(0);
wdata[i] <= data_t'(0);
be[i] <= be_t'(0);
@(posedge rst_n);
repeat (10) @(posedge clk);
for (int unsigned j = 0; j < NoReq; j++) begin
stim_write = bit'($urandom());
for (int unsigned k = 0; k < AddrWidth; k++) begin
stim_addr[k] = bit'($urandom());
end
while (stim_addr >= NumWords) begin
for (int unsigned k = 0; k < AddrWidth; k++) begin
stim_addr[k] = bit'($urandom());
end
end
for (int unsigned k = 0; k < DataWidth; k++) begin
stim_data[k] = bit'($urandom());
end
for (int unsigned k = 0; k < BeWidth; k++) begin
stim_be[k] = bit'($urandom());
end
req[i] <= #ApplTime 1'b1;
we[i] <= #ApplTime stim_write;
addr[i] <= #ApplTime stim_addr;
wdata[i] <= #ApplTime stim_data;
be[i] <= #ApplTime stim_be;
@(posedge clk);
req[i] <= #ApplTime 1'b0;
we[i] <= #ApplTime 1'b0;
addr[i] <= #ApplTime addr_t'(0);
wdata[i] <= #ApplTime data_t'(0);
be[i] <= #ApplTime be_t'(0);
repeat ($urandom_range(0,5)) @(posedge clk);
end
done[i] <= 1'b1;
end
end
initial begin: proc_golden_model
failed_test = 0;
for (int unsigned i = 0; i < NumWords; i++) begin
for (int unsigned j = 0; j < DataWidth; j++) begin
case (SimInit)
"zeros": memory[i][j] = 1'b0;
"ones": memory[i][j] = 1'b1;
default: memory[i][j] = 1'bx;
endcase
end
end
@(posedge rst_n);
forever begin
@(posedge clk);
for (int unsigned i = 0; i < NumPorts; i++) begin
if (req[i] && we[i]) begin
for (int unsigned j = 0; j < DataWidth; j++) begin
if (be[i][j/ByteWidth]) begin
memory[addr[i]][j] = wdata[i][j];
end
end
end
end
#TestTime;
fork
for (int unsigned i = 0; i < NumPorts; i++) begin
check_read(i, addr[i]);
end
join_none
end
end
task automatic check_read(input int unsigned port, input addr_t read_addr);
if (req[port] && !we[port]) begin
data_t exp_data = memory[read_addr];
if (Latency > 0) begin
repeat (Latency) @(posedge clk);
#TestTime;
end
for (int unsigned i = 0; i < DataWidth; i++) begin
if (!$isunknown(exp_data[i])) begin
assert(exp_data[i] === rdata[port][i]) else begin
$warning("Port: %0d unexpected bit[%0h], Addr: %0h expected: %0h, measured: %0h",
port, i, read_addr, exp_data[i], rdata[port][i]);
failed_test++;
end
end
end
end
endtask : check_read
initial begin : proc_stop
@(posedge rst_n);
wait (&done);
repeat (10) @(posedge clk);
$info("Simulation done, errors: %0d", failed_test);
$stop();
end
tc_sram #(
.NumWords ( NumWords ),
.DataWidth ( DataWidth ),
.ByteWidth ( ByteWidth ),
.NumPorts ( NumPorts ),
.Latency ( Latency ),
.SimInit ( SimInit ),
.PrintSimCfg ( 1'b1 )
) i_tc_sram_dut (
.clk_i ( clk ),
.rst_ni ( rst_n ),
.req_i ( req ),
.we_i ( we ),
.addr_i ( addr ),
.wdata_i ( wdata ),
.be_i ( be ),
.rdata_o ( rdata )
);
endmodule
`begin_keywords "1800-2023"
module pulp_clock_gating_async #(
parameter int unsigned STAGES = 2
) (
input logic clk_i,
input logic rstn_i,
input logic en_async_i,
output logic en_ack_o,
input logic test_en_i,
output logic clk_o
);
logic [STAGES-1:0] r_reg;
assign en_ack_o = r_reg[STAGES-1];
always_ff @ (posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
r_reg <= '0;
end else begin
r_reg <= {r_reg[STAGES-2:0], en_async_i};
end
end
pulp_clock_gating i_clk_gate (
.clk_i,
.en_i ( r_reg[STAGES-1] ),
.test_en_i,
.clk_o
);
endmodule
`begin_keywords "1800-2023"
module cluster_clock_and2 (
input logic clk0_i,
input logic clk1_i,
output logic clk_o
);
tc_clk_and2 i_tc_clk_and2 (
.clk0_i,
.clk1_i,
.clk_o
);
endmodule
module cluster_clock_buffer (
input logic clk_i,
output logic clk_o
);
tc_clk_buffer i_tc_clk_buffer (
.clk_i,
.clk_o
);
endmodule
module cluster_clock_gating (
input logic clk_i,
input logic en_i,
input logic test_en_i,
output logic clk_o
);
tc_clk_gating i_tc_clk_gating (
.clk_i,
.en_i,
.test_en_i,
.clk_o
);
endmodule
module cluster_clock_inverter (
input logic clk_i,
output logic clk_o
);
tc_clk_inverter i_tc_clk_inverter (
.clk_i,
.clk_o
);
endmodule
module cluster_clock_mux2 (
input logic clk0_i,
input logic clk1_i,
input logic clk_sel_i,
output logic clk_o
);
tc_clk_mux2 i_tc_clk_mux2 (
.clk0_i,
.clk1_i,
.clk_sel_i,
.clk_o
);
endmodule
module cluster_clock_xor2 (
input logic clk0_i,
input logic clk1_i,
output logic clk_o
);
tc_clk_xor2 i_tc_clk_xor2 (
.clk0_i,
.clk1_i,
.clk_o
);
endmodule
`begin_keywords "1800-2023"
module pulp_clock_and2 (
input logic clk0_i,
input logic clk1_i,
output logic clk_o
);
tc_clk_and2 i_tc_clk_and2 (
.clk0_i,
.clk1_i,
.clk_o
);
endmodule
module pulp_clock_buffer (
input logic clk_i,
output logic clk_o
);
tc_clk_buffer i_tc_clk_buffer (
.clk_i,
.clk_o
);
endmodule
module pulp_clock_gating (
input logic clk_i,
input logic en_i,
input logic test_en_i,
output logic clk_o
);
tc_clk_gating i_tc_clk_gating (
.clk_i,
.en_i,
.test_en_i,
.clk_o
);
endmodule
module pulp_clock_inverter (
input logic clk_i,
output logic clk_o
);
tc_clk_inverter i_tc_clk_inverter (
.clk_i,
.clk_o
);
endmodule
module pulp_clock_mux2 (
input logic clk0_i,
input logic clk1_i,
input logic clk_sel_i,
output logic clk_o
);
tc_clk_mux2 i_tc_clk_mux2 (
.clk0_i,
.clk1_i,
.clk_sel_i,
.clk_o
);
endmodule
module pulp_clock_xor2 (
input logic clk0_i,
input logic clk1_i,
output logic clk_o
);
tc_clk_xor2 i_tc_clk_xor2 (
.clk0_i,
.clk1_i,
.clk_o
);
endmodule
module pulp_clock_delay(
input logic in_i,
output logic out_o
);
assign #(300ps) out_o = in_i;
endmodule
`begin_keywords "1800-2023"
module binary_to_gray #(
parameter int N = -1
)(
input logic [N-1:0] A,
output logic [N-1:0] Z
);
assign Z = A ^ (A >> 1);
endmodule
`begin_keywords "1800-2023"
package cb_filter_pkg;
typedef struct packed {
int unsigned PermuteSeed;
int unsigned XorSeed;
} cb_seed_t;
localparam cb_seed_t [2:0] EgSeeds = '{
'{PermuteSeed: 32'd299034753, XorSeed: 32'd4094834 },
'{PermuteSeed: 32'd19921030, XorSeed: 32'd995713 },
'{PermuteSeed: 32'd294388, XorSeed: 32'd65146511 }
};
endpackage
`begin_keywords "1800-2023"
module cc_onehot #(
parameter int unsigned Width = 4
) (
input logic [Width-1:0] d_i,
output logic is_onehot_o
);
if (Width == 1) begin : gen_degenerated_onehot
assign is_onehot_o = d_i;
end else begin : gen_onehot
localparam int LVLS = $clog2(Width) + 1;
logic [LVLS-1:0][2**(LVLS-1)-1:0] sum, carry;
logic [LVLS-2:0] carry_array;
assign sum[0] = $unsigned(d_i);
for (genvar i = 1; i < LVLS; i++) begin : gen_lvl
localparam int unsigned LVLWidth = 2**LVLS / 2**i;
for (genvar j = 0; j < LVLWidth; j+=2) begin : gen_width
assign sum[i][j/2] = sum[i-1][j] ^ sum[i-1][j+1];
assign carry[i][j/2] = sum[i-1][j] & sum[i-1][j+1];
end
assign carry_array[i-1] = |carry[i][LVLWidth/2-1:0];
end
assign is_onehot_o = sum[LVLS-1][0] & ~|carry_array;
end
endmodule
`begin_keywords "1800-2023"
package cdc_reset_ctrlr_pkg;
typedef enum logic[1:0] {
CLEAR_PHASE_IDLE,
CLEAR_PHASE_ISOLATE,
CLEAR_PHASE_CLEAR,
CLEAR_PHASE_POST_CLEAR
} clear_seq_phase_e;
endpackage : cdc_reset_ctrlr_pkg
`begin_keywords "1800-2023"
package cf_math_pkg;
function automatic integer ceil_div (input longint dividend, input longint divisor);
automatic longint remainder;
if (dividend < 0) begin
$fatal(1, "Dividend %0d is not a natural number!", dividend);
end
if (divisor < 0) begin
$fatal(1, "Divisor %0d is not a natural number!", divisor);
end
if (divisor == 0) begin
$fatal(1, "Division by zero!");
end
remainder = dividend;
for (ceil_div = 0; remainder > 0; ceil_div++) begin
remainder = remainder - divisor;
end
endfunction
function automatic integer unsigned idx_width (input integer unsigned num_idx);
return (num_idx > 32'd1) ? unsigned'($clog2(num_idx)) : 32'd1;
endfunction
function automatic bit is_power_of_2 (input integer unsigned value);
return (value != 0) && (value & (value - 1)) == 0;
endfunction
endpackage
`begin_keywords "1800-2023"
module clk_int_div #(
parameter int unsigned DIV_VALUE_WIDTH = 4,
parameter int unsigned DEFAULT_DIV_VALUE = 0,
parameter bit ENABLE_CLOCK_IN_RESET = 1'b0
) (
input logic clk_i,
input logic rst_ni,
input logic en_i,
input logic test_mode_en_i,
input logic [DIV_VALUE_WIDTH-1:0] div_i,
input logic div_valid_i,
output logic div_ready_o,
output logic clk_o,
output logic [DIV_VALUE_WIDTH-1:0] cycl_count_o
);
if ($clog2(DEFAULT_DIV_VALUE+1) > DIV_VALUE_WIDTH) begin : gen_elab_error
$error("Default divider value %0d is not representable with the configured",
"div value width of %0d bits.",
DEFAULT_DIV_VALUE, DIV_VALUE_WIDTH);
end
localparam int unsigned DivResetValue = (DEFAULT_DIV_VALUE != 0)? DEFAULT_DIV_VALUE: 1;
logic [DIV_VALUE_WIDTH-1:0] div_i_normalized;
logic [DIV_VALUE_WIDTH-1:0] div_d, div_q;
logic toggle_ffs_en;
logic t_ff1_d, t_ff1_q;
logic t_ff1_en;
logic t_ff2_d, t_ff2_q;
logic t_ff2_en;
logic [DIV_VALUE_WIDTH-1:0] cycle_cntr_d, cycle_cntr_q;
logic cycle_counter_en;
logic clk_div_bypass_en_d, clk_div_bypass_en_q;
logic odd_clk;
logic even_clk;
logic generated_clock;
logic ungated_output_clock;
logic use_odd_division_d, use_odd_division_q;
logic gate_en_d, gate_en_q;
logic gate_is_open_q;
logic clear_cycle_counter;
logic clear_toggle_flops;
typedef enum logic[1:0] {IDLE, LOAD_DIV, WAIT_END_PERIOD} clk_gate_state_e;
clk_gate_state_e clk_gate_state_d, clk_gate_state_q;
assign div_i_normalized = (div_i != 0)? div_i : 1;
always_comb begin
div_d = div_q;
div_ready_o = 1'b0;
clk_div_bypass_en_d = clk_div_bypass_en_q;
use_odd_division_d = use_odd_division_q;
clk_gate_state_d = clk_gate_state_q;
cycle_counter_en = 1'b1;
clear_cycle_counter = 1'b0;
clear_toggle_flops = 1'b0;
toggle_ffs_en = 1'b1;
gate_en_d = 1'b0;
clk_gate_state_d = clk_gate_state_q;
case (clk_gate_state_q)
IDLE: begin
gate_en_d = 1'b1;
toggle_ffs_en = 1'b1;
if (div_valid_i) begin
if (div_i_normalized == div_q) begin
div_ready_o = 1'b1;
end else begin
clk_gate_state_d = LOAD_DIV;
gate_en_d = 1'b0;
end
end else if (!en_i && gate_is_open_q == 1'b0) begin
cycle_counter_en = 1'b0;
toggle_ffs_en = 1'b0;
end
end
LOAD_DIV: begin
gate_en_d = 1'b0;
toggle_ffs_en = 1'b1;
if ((gate_is_open_q == 1'b0) || clk_div_bypass_en_q) begin
toggle_ffs_en = 1'b0;
div_d = div_i_normalized;
div_ready_o = 1'b1;
clear_cycle_counter = 1'b1;
clear_toggle_flops = 1'b1;
use_odd_division_d = div_i_normalized[0];
clk_div_bypass_en_d = div_i_normalized == 1;
clk_gate_state_d = WAIT_END_PERIOD;
end
end
WAIT_END_PERIOD: begin
gate_en_d = 1'b0;
toggle_ffs_en = 1'b0;
if (cycle_cntr_q == div_q - 1) begin
clk_gate_state_d = IDLE;
end
end
default: begin
clk_gate_state_d = IDLE;
end
endcase
end
localparam logic UseOddDivisionResetValue = DEFAULT_DIV_VALUE[0];
localparam logic ClkDivBypassEnResetValue = (DEFAULT_DIV_VALUE < 2)? 1'b1: 1'b0;
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
use_odd_division_q <= UseOddDivisionResetValue;
clk_div_bypass_en_q <= ClkDivBypassEnResetValue;
div_q <= DivResetValue;
clk_gate_state_q <= IDLE;
gate_en_q <= ENABLE_CLOCK_IN_RESET;
end else begin
use_odd_division_q <= use_odd_division_d;
clk_div_bypass_en_q <= clk_div_bypass_en_d;
div_q <= div_d;
clk_gate_state_q <= clk_gate_state_d;
gate_en_q <= gate_en_d;
end
end
always_comb begin
cycle_cntr_d = cycle_cntr_q;
if (clear_cycle_counter) begin
cycle_cntr_d = '0;
end else begin
if (cycle_counter_en) begin
if (clk_div_bypass_en_q || (cycle_cntr_q == div_q-1)) begin
cycle_cntr_d = '0;
end else begin
cycle_cntr_d = cycle_cntr_q + 1;
end
end
end
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
cycle_cntr_q <= '0;
end else begin
cycle_cntr_q <= cycle_cntr_d;
end
end
assign cycl_count_o = cycle_cntr_q;
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
t_ff1_q = '0;
end else begin
if (t_ff1_en) begin
t_ff1_q = t_ff1_d;
end
end
end
always_ff @(negedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
t_ff2_q = '0;
end else begin
if (t_ff2_en) begin
t_ff2_q = t_ff2_d;
end
end
end
always_comb begin
if (clear_toggle_flops) begin
t_ff1_d = '0;
t_ff2_d = '0;
end else begin
t_ff1_d = t_ff1_en? !t_ff1_q: t_ff1_q;
t_ff2_d = t_ff2_en? !t_ff2_q: t_ff2_q;
end
end
always_comb begin
t_ff1_en = 1'b0;
t_ff2_en = 1'b0;
if (!clk_div_bypass_en_q && toggle_ffs_en) begin
if (use_odd_division_q) begin
t_ff1_en = (cycle_cntr_q == 0)? 1'b1: 1'b0;
t_ff2_en = (cycle_cntr_q == (div_q+1)/2)? 1'b1: 1'b0;
end else begin
t_ff1_en = (cycle_cntr_q == 0 || cycle_cntr_q == div_q/2)? 1'b1: 1'b0;
end
end
end
assign even_clk = t_ff1_q;
tc_clk_xor2 i_odd_clk_xor (
.clk0_i ( t_ff1_q ),
.clk1_i ( t_ff2_q ),
.clk_o ( odd_clk )
);
tc_clk_mux2 i_clk_mux (
.clk0_i ( even_clk ),
.clk1_i ( odd_clk ),
.clk_sel_i ( use_odd_division_q ),
.clk_o ( generated_clock )
);
tc_clk_mux2 i_clk_bypass_mux (
.clk0_i ( generated_clock ),
.clk1_i ( clk_i ),
.clk_sel_i ( clk_div_bypass_en_q || test_mode_en_i ),
.clk_o ( ungated_output_clock )
);
always_ff @(posedge ungated_output_clock, negedge rst_ni) begin
if (!rst_ni) begin
gate_is_open_q <= 1'b0;
end else begin
gate_is_open_q <= gate_en_q & en_i;
end
end
tc_clk_gating #(
.IS_FUNCTIONAL(1)
) i_clk_gate (
.clk_i ( ungated_output_clock ),
.en_i ( gate_en_q & en_i ),
.test_en_i ( test_mode_en_i ),
.clk_o
);
endmodule
`begin_keywords "1800-2023"
module credit_counter #(
parameter int unsigned NumCredits = 0,
parameter bit InitCreditEmpty = 1'b0,
parameter int unsigned InitNumCredits = InitCreditEmpty ? '0 : NumCredits,
parameter type credit_cnt_t = logic [$clog2(NumCredits):0]
) (
input logic clk_i,
input logic rst_ni,
output credit_cnt_t credit_o,
input logic credit_give_i,
input logic credit_take_i,
input logic credit_init_i,
output logic credit_left_o,
output logic credit_crit_o,
output logic credit_full_o
);
credit_cnt_t credit_d, credit_q;
logic increment, decrement;
assign decrement = credit_take_i & ~credit_give_i;
assign increment = ~credit_take_i & credit_give_i;
always_comb begin
credit_d = credit_q;
if (decrement) credit_d = credit_q - 1;
else if (increment) credit_d = credit_q + 1;
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
credit_q <= (InitNumCredits);
end else begin
if (credit_init_i) begin
credit_q <= (InitNumCredits);
end else begin
credit_q <= (credit_d);
end
end
end
assign credit_o = credit_q;
assign credit_left_o = (credit_q != '0);
assign credit_crit_o = (credit_q == NumCredits-1);
assign credit_full_o = (credit_q == NumCredits);
CreditUnderflow: assert property (@(posedge clk_i) disable iff (( !rst_ni) !== '0) not (credit_o == '0 && decrement))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "CreditUnderflow", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/credit_counter.sv", 52);
end
CreditOverflow: assert property (@(posedge clk_i) disable iff (( !rst_ni) !== '0) not (credit_o == NumCredits && increment))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "CreditOverflow", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/credit_counter.sv", 53);
end
endmodule
`begin_keywords "1800-2023"
module delta_counter #(
parameter int unsigned WIDTH = 4,
parameter bit STICKY_OVERFLOW = 1'b0
)(
input logic clk_i,
input logic rst_ni,
input logic clear_i,
input logic en_i,
input logic load_i,
input logic down_i,
input logic [WIDTH-1:0] delta_i,
input logic [WIDTH-1:0] d_i,
output logic [WIDTH-1:0] q_o,
output logic overflow_o
);
logic [WIDTH:0] counter_q, counter_d;
if (STICKY_OVERFLOW) begin : gen_sticky_overflow
logic overflow_d, overflow_q;
always_ff @(posedge clk_i or negedge rst_ni)
begin
if(!rst_ni) begin
overflow_q <= 1'b0;
end else begin
overflow_q <= overflow_d;
end
end
always_comb begin
overflow_d = overflow_q;
if (clear_i || load_i) begin
overflow_d = 1'b0;
end else if (!overflow_q && en_i) begin
if (down_i) begin
overflow_d = delta_i > counter_q[WIDTH-1:0];
end else begin
overflow_d = counter_q[WIDTH-1:0] > ({WIDTH{1'b1}} - delta_i);
end
end
end
assign overflow_o = overflow_q;
end else begin : gen_transient_overflow
assign overflow_o = counter_q[WIDTH];
end
assign q_o = counter_q[WIDTH-1:0];
always_comb begin
counter_d = counter_q;
if (clear_i) begin
counter_d = '0;
end else if (load_i) begin
counter_d = {1'b0, d_i};
end else if (en_i) begin
if (down_i) begin
counter_d = counter_q - delta_i;
end else begin
counter_d = counter_q + delta_i;
end
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
counter_q <= '0;
end else begin
counter_q <= counter_d;
end
end
endmodule
`begin_keywords "1800-2023"
package ecc_pkg;
function automatic int unsigned get_parity_width (input int unsigned data_width);
int unsigned cw_width = 2;
while (unsigned'(2**cw_width) < cw_width + data_width + 1) cw_width++;
return cw_width;
endfunction
function automatic int unsigned get_cw_width (input int unsigned data_width);
return data_width + get_parity_width(data_width);
endfunction
endpackage
`begin_keywords "1800-2023"
module edge_propagator_tx (
input logic clk_i,
input logic rstn_i,
input logic valid_i,
input logic ack_i,
output logic valid_o
);
logic [1:0] sync_a;
logic r_input_reg;
logic s_input_reg_next;
assign s_input_reg_next = valid_i | (r_input_reg & ~sync_a[0]);
always @(negedge rstn_i or posedge clk_i) begin
if (~rstn_i) begin
r_input_reg <= 1'b0;
sync_a <= 2'b00;
end else begin
r_input_reg <= s_input_reg_next;
sync_a <= {ack_i,sync_a[1]};
end
end
assign valid_o = r_input_reg;
endmodule
`begin_keywords "1800-2023"
module exp_backoff #(
parameter int unsigned Seed = 'hffff,
parameter int unsigned MaxExp = 16
) (
input logic clk_i,
input logic rst_ni,
input logic set_i,
input logic clr_i,
output logic is_zero_o
);
localparam int unsigned WIDTH = 16;
logic [WIDTH-1:0] lfsr_d, lfsr_q, cnt_d, cnt_q, mask_d, mask_q;
logic lfsr;
assign lfsr = lfsr_q[15-15] ^
lfsr_q[15-13] ^
lfsr_q[15-12] ^
lfsr_q[15-10];
assign lfsr_d = (set_i) ? {lfsr, lfsr_q[$high(lfsr_q):1]} :
lfsr_q;
assign mask_d = (clr_i) ? '0 :
(set_i) ? {{(WIDTH-MaxExp){1'b0}},mask_q[MaxExp-2:0], 1'b1} :
mask_q;
assign cnt_d = (clr_i) ? '0 :
(set_i) ? (mask_q & lfsr_q) :
(!is_zero_o) ? cnt_q - 1'b1 : '0;
assign is_zero_o = (cnt_q=='0);
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
if (!rst_ni) begin
lfsr_q <= WIDTH'(Seed);
mask_q <= '0;
cnt_q <= '0;
end else begin
lfsr_q <= lfsr_d;
mask_q <= mask_d;
cnt_q <= cnt_d;
end
end
initial begin
max_exp_0: assert (MaxExp>0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "max_exp_0", "MaxExp must be greater than 0", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/exp_backoff.sv", 88);
end
end
initial begin
max_exp_gt_16: assert (MaxExp<=16)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "max_exp_gt_16", "MaxExp cannot be greater than 16", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/exp_backoff.sv", 89);
end
end
initial begin
seed_0: assert (Seed>0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "seed_0", "Zero seed is not allowed for LFSR", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/exp_backoff.sv", 90);
end
end
endmodule
`begin_keywords "1800-2023"
module fifo_v3 #(
parameter bit FALL_THROUGH = 1'b0,
parameter int unsigned DATA_WIDTH = 32,
parameter int unsigned DEPTH = 8,
parameter type dtype = logic [DATA_WIDTH-1:0],
parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1
)(
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input logic testmode_i,
output logic full_o,
output logic empty_o,
output logic [ADDR_DEPTH-1:0] usage_o,
input dtype data_i,
input logic push_i,
output dtype data_o,
input logic pop_i
);
localparam int unsigned FifoDepth = (DEPTH > 0) ? DEPTH : 1;
logic gate_clock;
logic [ADDR_DEPTH - 1:0] read_pointer_n, read_pointer_q, write_pointer_n, write_pointer_q;
logic [ADDR_DEPTH:0] status_cnt_n, status_cnt_q;
dtype [FifoDepth - 1:0] mem_n, mem_q;
assign usage_o = status_cnt_q[ADDR_DEPTH-1:0];
if (DEPTH == 0) begin : gen_pass_through
assign empty_o = ~push_i;
assign full_o = ~pop_i;
end else begin : gen_fifo
assign full_o = (status_cnt_q == FifoDepth[ADDR_DEPTH:0]);
assign empty_o = (status_cnt_q == 0) & ~(FALL_THROUGH & push_i);
end
always_comb begin : read_write_comb
read_pointer_n = read_pointer_q;
write_pointer_n = write_pointer_q;
status_cnt_n = status_cnt_q;
data_o = (DEPTH == 0) ? data_i : mem_q[read_pointer_q];
mem_n = mem_q;
gate_clock = 1'b1;
if (push_i && ~full_o) begin
mem_n[write_pointer_q] = data_i;
gate_clock = 1'b0;
if (write_pointer_q == FifoDepth[ADDR_DEPTH-1:0] - 1)
write_pointer_n = '0;
else
write_pointer_n = write_pointer_q + 1;
status_cnt_n = status_cnt_q + 1;
end
if (pop_i && ~empty_o) begin
if (read_pointer_n == FifoDepth[ADDR_DEPTH-1:0] - 1)
read_pointer_n = '0;
else
read_pointer_n = read_pointer_q + 1;
status_cnt_n = status_cnt_q - 1;
end
if (push_i && pop_i && ~full_o && ~empty_o)
status_cnt_n = status_cnt_q;
if (FALL_THROUGH && (status_cnt_q == 0) && push_i) begin
data_o = data_i;
if (pop_i) begin
status_cnt_n = status_cnt_q;
read_pointer_n = read_pointer_q;
write_pointer_n = write_pointer_q;
end
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if(~rst_ni) begin
read_pointer_q <= '0;
write_pointer_q <= '0;
status_cnt_q <= '0;
end else begin
if (flush_i) begin
read_pointer_q <= '0;
write_pointer_q <= '0;
status_cnt_q <= '0;
end else begin
read_pointer_q <= read_pointer_n;
write_pointer_q <= write_pointer_n;
status_cnt_q <= status_cnt_n;
end
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if(~rst_ni) begin
mem_q <= {FifoDepth{dtype'('0)}};
end else if (!gate_clock) begin
mem_q <= mem_n;
end
end
initial begin
depth_0: assert (DEPTH > 0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "depth_0", "DEPTH must be greater than 0.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/fifo_v3.sv", 143);
end
end
full_write: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (full_o |-> ~push_i))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "full_write", "Trying to push new data although the FIFO is full.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/fifo_v3.sv", 146);
end
empty_read: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (empty_o |-> ~pop_i))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "empty_read", "Trying to pop data although the FIFO is empty.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/fifo_v3.sv", 149);
end
endmodule
`begin_keywords "1800-2023"
module gray_to_binary #(
parameter int N = -1
)(
input logic [N-1:0] A,
output logic [N-1:0] Z
);
for (genvar i = 0; i < N; i++)
assign Z[i] = ^A[N-1:i];
endmodule
`begin_keywords "1800-2023"
module heaviside #(
parameter int unsigned Width = 32,
localparam int unsigned IdxWidth = cf_math_pkg::idx_width(Width),
localparam type idx_t = logic [IdxWidth-1:0],
localparam type mask_t = logic [Width-1:0]
) (
input idx_t x_i,
output mask_t mask_o
);
assign mask_o = (1 << (x_i + 1)) - 1;
endmodule
`begin_keywords "1800-2023"
module isochronous_4phase_handshake (
input logic src_clk_i,
input logic src_rst_ni,
input logic src_valid_i,
output logic src_ready_o,
input logic dst_clk_i,
input logic dst_rst_ni,
output logic dst_valid_o,
input logic dst_ready_i
);
logic src_req_q, src_ack_q;
logic dst_req_q, dst_ack_q;
always_ff @(posedge (src_clk_i) or negedge (src_rst_ni)) begin
if (!src_rst_ni) begin
src_req_q <= (1'b0);
end else begin
if ((src_valid_i && src_ready_o)) begin
src_req_q <= (~src_req_q);
end
end
end
always_ff @(posedge (src_clk_i) or negedge (src_rst_ni)) begin
if (!src_rst_ni) begin
src_ack_q <= (1'b0);
end else begin
src_ack_q <= (dst_ack_q);
end
end
assign src_ready_o = (src_req_q == src_ack_q);
always_ff @(posedge (dst_clk_i) or negedge (dst_rst_ni)) begin
if (!dst_rst_ni) begin
dst_ack_q <= (1'b0);
end else begin
if ((dst_valid_o && dst_ready_i)) begin
dst_ack_q <= (~dst_ack_q);
end
end
end
always_ff @(posedge (dst_clk_i) or negedge (dst_rst_ni)) begin
if (!dst_rst_ni) begin
dst_req_q <= (1'b0);
end else begin
dst_req_q <= (src_req_q);
end
end
assign dst_valid_o = (dst_req_q != dst_ack_q);
src_valid_unstable: assert property (@(posedge src_clk_i) disable iff ((!src_rst_ni) !== '0) (src_valid_i && !src_ready_o |=> $stable(src_valid_i)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "src_valid_unstable", "src_valid_i is unstable", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/isochronous_4phase_handshake.sv", 75);
end
dst_valid_unstable: assert property (@(posedge dst_clk_i) disable iff ((!dst_rst_ni) !== '0) (dst_valid_o && !dst_ready_i |=> $stable(dst_valid_o)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "dst_valid_unstable", "dst_valid_o is unstable", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/isochronous_4phase_handshake.sv", 77);
end
endmodule
`begin_keywords "1800-2023"
module isochronous_spill_register #(
parameter type T = logic,
parameter bit Bypass = 1'b0
) (
input logic src_clk_i,
input logic src_rst_ni,
input logic src_valid_i,
output logic src_ready_o,
input T src_data_i,
input logic dst_clk_i,
input logic dst_rst_ni,
output logic dst_valid_o,
input logic dst_ready_i,
output T dst_data_o
);
if (Bypass) begin : gen_bypass
assign dst_valid_o = src_valid_i;
assign src_ready_o = dst_ready_i;
assign dst_data_o = src_data_i;
end else begin : gen_isochronous_spill_register
logic [1:0] rd_pointer_q, wr_pointer_q;
always_ff @(posedge (src_clk_i) or negedge (src_rst_ni)) begin
if (!src_rst_ni) begin
wr_pointer_q <= ('0);
end else begin
if ((src_valid_i && src_ready_o)) begin
wr_pointer_q <= (wr_pointer_q+1);
end
end
end
always_ff @(posedge (dst_clk_i) or negedge (dst_rst_ni)) begin
if (!dst_rst_ni) begin
rd_pointer_q <= ('0);
end else begin
if ((dst_valid_o && dst_ready_i)) begin
rd_pointer_q <= (rd_pointer_q+1);
end
end
end
T [1:0] mem_d, mem_q;
always_ff @(posedge (src_clk_i) or negedge (src_rst_ni)) begin
if (!src_rst_ni) begin
mem_q <= ('0);
end else begin
if ((src_valid_i && src_ready_o)) begin
mem_q <= (mem_d);
end
end
end
always_comb begin
mem_d = mem_q;
mem_d[wr_pointer_q[0]] = src_data_i;
end
assign src_ready_o = (rd_pointer_q ^ wr_pointer_q) != 2'b10;
assign dst_valid_o = (rd_pointer_q ^ wr_pointer_q) != '0;
assign dst_data_o = mem_q[rd_pointer_q[0]];
end
src_valid_unstable: assert property (@(posedge src_clk_i) disable iff ((!src_rst_ni) !== '0) (src_valid_i && !src_ready_o |=> $stable(src_valid_i)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "src_valid_unstable", "src_valid_i is unstable", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/isochronous_spill_register.sv", 102);
end
dst_valid_unstable: assert property (@(posedge dst_clk_i) disable iff ((!dst_rst_ni) !== '0) (dst_valid_o && !dst_ready_i |=> $stable(dst_valid_o)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "dst_valid_unstable", "dst_valid_o is unstable", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/isochronous_spill_register.sv", 104);
end
endmodule
`begin_keywords "1800-2023"
module lfsr #(
parameter int unsigned LfsrWidth = 64,
parameter int unsigned OutWidth = 8,
parameter logic [LfsrWidth-1:0] RstVal = '1,
parameter int unsigned CipherLayers = 0,
parameter bit CipherReg = 1'b1
) (
input logic clk_i,
input logic rst_ni,
input logic en_i,
output logic [OutWidth-1:0] out_o
);
localparam logic [63:0] Masks [4:64] = '{64'hC,
64'h1E,
64'h39,
64'h7E,
64'hFA,
64'h1FD,
64'h3FC,
64'h64B,
64'hD8F,
64'h1296,
64'h2496,
64'h4357,
64'h8679,
64'h1030E,
64'h206CD,
64'h403FE,
64'h807B8,
64'h1004B2,
64'h2006A8,
64'h4004B2,
64'h800B87,
64'h10004F3,
64'h200072D,
64'h40006AE,
64'h80009E3,
64'h10000583,
64'h20000C92,
64'h400005B6,
64'h80000EA6,
64'h1000007A3,
64'h200000ABF,
64'h400000842,
64'h80000123E,
64'h100000074E,
64'h2000000AE9,
64'h400000086A,
64'h8000001213,
64'h1000000077E,
64'h2000000123B,
64'h40000000877,
64'h8000000108D,
64'h100000000AE9,
64'h200000000E9F,
64'h4000000008A6,
64'h80000000191E,
64'h100000000090E,
64'h2000000000FB3,
64'h4000000000D7D,
64'h80000000016A5,
64'h10000000000B4B,
64'h200000000010AF,
64'h40000000000DDE,
64'h8000000000181A,
64'h100000000000B65,
64'h20000000000102D,
64'h400000000000CD5,
64'h8000000000024C1,
64'h1000000000000EF6,
64'h2000000000001363,
64'h4000000000000FCD,
64'h80000000000019E2};
localparam logic[15:0][3:0] Sbox4 = {4'h2, 4'h1, 4'h7, 4'h4,
4'h8, 4'hF, 4'hE, 4'h3,
4'hD, 4'hA, 4'h0, 4'h9,
4'hB, 4'h6, 4'h5, 4'hC };
localparam logic[63:0][5:0] Perm = {6'd63, 6'd47, 6'd31, 6'd15, 6'd62, 6'd46, 6'd30, 6'd14,
6'd61, 6'd45, 6'd29, 6'd13, 6'd60, 6'd44, 6'd28, 6'd12,
6'd59, 6'd43, 6'd27, 6'd11, 6'd58, 6'd42, 6'd26, 6'd10,
6'd57, 6'd41, 6'd25, 6'd09, 6'd56, 6'd40, 6'd24, 6'd08,
6'd55, 6'd39, 6'd23, 6'd07, 6'd54, 6'd38, 6'd22, 6'd06,
6'd53, 6'd37, 6'd21, 6'd05, 6'd52, 6'd36, 6'd20, 6'd04,
6'd51, 6'd35, 6'd19, 6'd03, 6'd50, 6'd34, 6'd18, 6'd02,
6'd49, 6'd33, 6'd17, 6'd01, 6'd48, 6'd32, 6'd16, 6'd00};
function automatic logic [63:0] sbox4_layer(logic [63:0] in);
logic [63:0] out;
out[0*4 +: 4] = Sbox4[in[0*4 +: 4]];
out[1*4 +: 4] = Sbox4[in[1*4 +: 4]];
out[2*4 +: 4] = Sbox4[in[2*4 +: 4]];
out[3*4 +: 4] = Sbox4[in[3*4 +: 4]];
out[4*4 +: 4] = Sbox4[in[4*4 +: 4]];
out[5*4 +: 4] = Sbox4[in[5*4 +: 4]];
out[6*4 +: 4] = Sbox4[in[6*4 +: 4]];
out[7*4 +: 4] = Sbox4[in[7*4 +: 4]];
out[8*4 +: 4] = Sbox4[in[8*4 +: 4]];
out[9*4 +: 4] = Sbox4[in[9*4 +: 4]];
out[10*4 +: 4] = Sbox4[in[10*4 +: 4]];
out[11*4 +: 4] = Sbox4[in[11*4 +: 4]];
out[12*4 +: 4] = Sbox4[in[12*4 +: 4]];
out[13*4 +: 4] = Sbox4[in[13*4 +: 4]];
out[14*4 +: 4] = Sbox4[in[14*4 +: 4]];
out[15*4 +: 4] = Sbox4[in[15*4 +: 4]];
return out;
endfunction : sbox4_layer
function automatic logic [63:0] perm_layer(logic [63:0] in);
logic [63:0] out;
out[Perm[0]] = in[0];
out[Perm[1]] = in[1];
out[Perm[2]] = in[2];
out[Perm[3]] = in[3];
out[Perm[4]] = in[4];
out[Perm[5]] = in[5];
out[Perm[6]] = in[6];
out[Perm[7]] = in[7];
out[Perm[8]] = in[8];
out[Perm[9]] = in[9];
out[Perm[10]] = in[10];
out[Perm[11]] = in[11];
out[Perm[12]] = in[12];
out[Perm[13]] = in[13];
out[Perm[14]] = in[14];
out[Perm[15]] = in[15];
out[Perm[16]] = in[16];
out[Perm[17]] = in[17];
out[Perm[18]] = in[18];
out[Perm[19]] = in[19];
out[Perm[20]] = in[20];
out[Perm[21]] = in[21];
out[Perm[22]] = in[22];
out[Perm[23]] = in[23];
out[Perm[24]] = in[24];
out[Perm[25]] = in[25];
out[Perm[26]] = in[26];
out[Perm[27]] = in[27];
out[Perm[28]] = in[28];
out[Perm[29]] = in[29];
out[Perm[30]] = in[30];
out[Perm[31]] = in[31];
out[Perm[32]] = in[32];
out[Perm[33]] = in[33];
out[Perm[34]] = in[34];
out[Perm[35]] = in[35];
out[Perm[36]] = in[36];
out[Perm[37]] = in[37];
out[Perm[38]] = in[38];
out[Perm[39]] = in[39];
out[Perm[40]] = in[40];
out[Perm[41]] = in[41];
out[Perm[42]] = in[42];
out[Perm[43]] = in[43];
out[Perm[44]] = in[44];
out[Perm[45]] = in[45];
out[Perm[46]] = in[46];
out[Perm[47]] = in[47];
out[Perm[48]] = in[48];
out[Perm[49]] = in[49];
out[Perm[50]] = in[50];
out[Perm[51]] = in[51];
out[Perm[52]] = in[52];
out[Perm[53]] = in[53];
out[Perm[54]] = in[54];
out[Perm[55]] = in[55];
out[Perm[56]] = in[56];
out[Perm[57]] = in[57];
out[Perm[58]] = in[58];
out[Perm[59]] = in[59];
out[Perm[60]] = in[60];
out[Perm[61]] = in[61];
out[Perm[62]] = in[62];
out[Perm[63]] = in[63];
return out;
endfunction : perm_layer
logic [LfsrWidth-1:0] lfsr_d, lfsr_q;
assign lfsr_d =
(en_i) ? (lfsr_q>>1) ^ ({LfsrWidth{lfsr_q[0]}} & Masks[LfsrWidth][LfsrWidth-1:0]) : lfsr_q;
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
if (!rst_ni) begin
lfsr_q <= LfsrWidth'(RstVal);
end else begin
lfsr_q <= lfsr_d;
end
end
if (CipherLayers > unsigned'(0)) begin : g_cipher_layers
logic [63:0] ciph_layer;
localparam int unsigned NumRepl = ((64+LfsrWidth)/LfsrWidth);
always_comb begin : p_ciph_layer
automatic logic [63:0] tmp;
tmp = 64'({NumRepl{lfsr_q}});
for(int unsigned k = 0; k < CipherLayers; k++) begin
tmp = perm_layer(sbox4_layer(tmp));
end
ciph_layer = tmp;
end
if (CipherReg) begin : g_cipher_reg
logic [OutWidth-1:0] out_d, out_q;
assign out_d = (en_i) ? ciph_layer[OutWidth-1:0] : out_q;
assign out_o = out_q[OutWidth-1:0];
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
if (!rst_ni) begin
out_q <= '0;
end else begin
out_q <= out_d;
end
end
end else begin : g_no_out_reg
assign out_o = ciph_layer[OutWidth-1:0];
end
end else begin : g_no_cipher_layers
assign out_o = lfsr_q[OutWidth-1:0];
end
initial begin
outwidth_gt_lfsrwidth: assert (OutWidth <= LfsrWidth)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "outwidth_gt_lfsrwidth", "OutWidth must be smaller equal the LfsrWidth.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/lfsr.sv", 297);
end
end
initial begin
rstval_0: assert (RstVal > unsigned'(0))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "rstval_0", "RstVal must be nonzero.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/lfsr.sv", 298);
end
end
initial begin
lfsrwidth_invalid: assert ((LfsrWidth >= $low(Masks)) && (LfsrWidth <= $high(Masks)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "lfsrwidth_invalid", "Unsupported LfsrWidth.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/lfsr.sv", 300);
end
end
initial begin
mask_invalid: assert (Masks[LfsrWidth][LfsrWidth-1])
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "mask_invalid", "LFSR mask is not correct. The MSB must be 1.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/lfsr.sv", 302);
end
end
initial begin
cipherlayers_invalid: assert ((CipherLayers > 0) && (LfsrWidth == 64) || (CipherLayers == 0))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "cipherlayers_invalid", "Use additional cipher layers only in conjunction with an LFSR width of 64 bit.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/lfsr.sv", 304);
end
end
all_zero: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (en_i |-> lfsr_d))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "all_zero", "Lfsr must not be all-zero.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/lfsr.sv", 306);
end
endmodule
`begin_keywords "1800-2023"
module lfsr_16bit #(
parameter logic [15:0] SEED = 8'b0,
parameter int unsigned WIDTH = 16
)(
input logic clk_i,
input logic rst_ni,
input logic en_i,
output logic [WIDTH-1:0] refill_way_oh,
output logic [$clog2(WIDTH)-1:0] refill_way_bin
);
localparam int unsigned LogWidth = $clog2(WIDTH);
logic [15:0] shift_d, shift_q;
always_comb begin
automatic logic shift_in;
shift_in = !(shift_q[15] ^ shift_q[12] ^ shift_q[5] ^ shift_q[1]);
shift_d = shift_q;
if (en_i)
shift_d = {shift_q[14:0], shift_in};
refill_way_oh = 'b0;
refill_way_oh[shift_q[LogWidth-1:0]] = 1'b1;
refill_way_bin = shift_q;
end
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_
if(~rst_ni) begin
shift_q <= SEED;
end else begin
shift_q <= shift_d;
end
end
initial begin
width_gt_16: assert (WIDTH <= 16)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "width_gt_16", "WIDTH needs to be less than 16 because of the 16-bit LFSR", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/lfsr_16bit.sv", 65);
end
end
endmodule
`begin_keywords "1800-2023"
module lfsr_8bit #(
parameter logic [7:0] SEED = 8'b0,
parameter int unsigned WIDTH = 8
) (
input logic clk_i,
input logic rst_ni,
input logic en_i,
output logic [ WIDTH-1:0] refill_way_oh,
output logic [$clog2(WIDTH)-1:0] refill_way_bin
);
localparam int unsigned LogWidth = $clog2(WIDTH);
logic [7:0] shift_d, shift_q;
always_comb begin
automatic logic shift_in;
shift_in = !(shift_q[7] ^ shift_q[3] ^ shift_q[2] ^ shift_q[1]);
shift_d = shift_q;
if (en_i) shift_d = {shift_q[6:0], shift_in};
refill_way_oh = 'b0;
refill_way_oh[shift_q[LogWidth - 1:0]] = 1'b1;
refill_way_bin = shift_q;
end
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_
if (~rst_ni) begin
shift_q <= SEED;
end else begin
shift_q <= shift_d;
end
end
initial begin
width_gt_8: assert (WIDTH <= 8)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "width_gt_8", "WIDTH needs to be less than 8 because of the 8-bit LFSR", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/lfsr_8bit.sv", 58);
end
end
endmodule
`begin_keywords "1800-2023"
module lossy_valid_to_stream #(
parameter int unsigned DATA_WIDTH = 32,
parameter type T = logic [DATA_WIDTH-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic valid_i,
input T data_i,
output logic valid_o,
input logic ready_i,
output T data_o,
output busy_o
);
logic read_ptr_d, read_ptr_q;
logic write_ptr_d, write_ptr_q;
logic [1:0] pending_tx_counter_d, pending_tx_counter_q;
T[1:0] mem_d, mem_q;
assign valid_o = pending_tx_counter_q != 0 || valid_i;
always_comb begin : write_logic
write_ptr_d = write_ptr_q;
mem_d = mem_q;
if (valid_i) begin
if (pending_tx_counter_q != 0 || !ready_i) begin
if (pending_tx_counter_q == 2 && !ready_i) begin
mem_d[write_ptr_q - 1'b1] = data_i;
end else begin
mem_d[write_ptr_q] = data_i;
write_ptr_d = write_ptr_q + 1'b1;
end
end
end
end
always_comb begin : read_logic
read_ptr_d = read_ptr_q;
data_o = mem_q[read_ptr_q];
if (pending_tx_counter_q == 0 && valid_i) begin
data_o = data_i;
end else if (valid_o && ready_i) begin
read_ptr_d = read_ptr_q + 1'b1;
end
end
always_comb begin: count_transactions
pending_tx_counter_d = pending_tx_counter_q;
if (valid_i && valid_o && ready_i) begin
pending_tx_counter_d = pending_tx_counter_q;
end else if (valid_i && !(valid_o && ready_i)) begin
if (pending_tx_counter_q != 2) begin
pending_tx_counter_d = pending_tx_counter_q + 1'b1;
end
end else if (!valid_i && (valid_o && ready_i)) begin
pending_tx_counter_d = pending_tx_counter_q - 1'b1;
end
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
read_ptr_q <= '0;
write_ptr_q <= '0;
pending_tx_counter_q <= '0;
mem_q <= {2{T'('0)}};
end else begin
read_ptr_q <= read_ptr_d;
write_ptr_q <= write_ptr_d;
pending_tx_counter_q <= pending_tx_counter_d;
mem_q <= mem_d;
end
end
assign busy_o = pending_tx_counter_q != 0;
endmodule
`begin_keywords "1800-2023"
module mv_filter #(
parameter int unsigned WIDTH = 4,
parameter int unsigned THRESHOLD = 10
)(
input logic clk_i,
input logic rst_ni,
input logic sample_i,
input logic clear_i,
input logic d_i,
output logic q_o
);
logic [WIDTH-1:0] counter_q, counter_d;
logic d, q;
assign q_o = q;
always_comb begin
counter_d = counter_q;
d = q;
if (counter_q >= THRESHOLD[WIDTH-1:0]) begin
d = 1'b1;
end else if (sample_i && d_i) begin
counter_d = counter_q + 1;
end
if (clear_i) begin
counter_d = '0;
d = 1'b0;
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
counter_q <= '0;
q <= 1'b0;
end else begin
counter_q <= counter_d;
q <= d;
end
end
endmodule
`begin_keywords "1800-2023"
module onehot_to_bin #(
parameter int unsigned ONEHOT_WIDTH = 16,
parameter int unsigned BIN_WIDTH = ONEHOT_WIDTH == 1 ? 1 : $clog2(ONEHOT_WIDTH)
) (
input logic [ONEHOT_WIDTH-1:0] onehot,
output logic [BIN_WIDTH-1:0] bin
);
for (genvar j = 0; j < BIN_WIDTH; j++) begin : gen_jl
logic [ONEHOT_WIDTH-1:0] tmp_mask;
for (genvar i = 0; i < ONEHOT_WIDTH; i++) begin : gen_il
logic [BIN_WIDTH-1:0] tmp_i;
assign tmp_i = BIN_WIDTH'(i);
assign tmp_mask[i] = tmp_i[j];
end
assign bin[j] = |(tmp_mask & onehot);
end
final begin
more_than_2_bits: assert ($onehot0(onehot) || $test$plusargs("disable_assert_final_checks"))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "more_than_2_bits", "More than two bit set in the one-hot signal", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/onehot_to_bin.sv", 35);
end
end
endmodule
`begin_keywords "1800-2023"
module plru_tree #(
parameter int unsigned ENTRIES = 16
) (
input logic clk_i,
input logic rst_ni,
input logic [ENTRIES-1:0] used_i,
output logic [ENTRIES-1:0] plru_o
);
localparam int unsigned LogEntries = $clog2(ENTRIES);
logic [2*(ENTRIES-1)-1:0] plru_tree_q, plru_tree_d;
always_comb begin : plru_replacement
automatic int unsigned idx_base, shift;
automatic logic new_index;
idx_base = 0;
shift = 0;
new_index = 1'b0;
plru_tree_d = plru_tree_q;
for (int unsigned i = 0; i < ENTRIES; i++) begin
if (used_i[i]) begin
for (int unsigned lvl = 0; lvl < LogEntries; lvl++) begin
idx_base = $unsigned((2**lvl)-1);
shift = LogEntries - lvl;
new_index = 1'(~(i >> (shift-1)));
plru_tree_d[idx_base + (i >> shift)] = new_index;
end
end
end
end
always_comb begin : plru_output
automatic int unsigned idx_base, shift;
automatic logic new_index;
idx_base = 0;
shift = 0;
new_index = 1'b0;
plru_o = '1;
for (int unsigned i = 0; i < ENTRIES; i += 1) begin
for (int unsigned lvl = 0; lvl < LogEntries; lvl++) begin
idx_base = $unsigned((2**lvl)-1);
shift = LogEntries - lvl;
new_index = 1'(i >> (shift-1));
if (new_index) begin
plru_o[i] &= plru_tree_q[idx_base + (i>>shift)];
end else begin
plru_o[i] &= ~plru_tree_q[idx_base + (i>>shift)];
end
end
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
plru_tree_q <= '0;
end else begin
plru_tree_q <= plru_tree_d;
end
end
initial begin
entries_not_power_of_2: assert (ENTRIES == 2**LogEntries)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "entries_not_power_of_2", "Entries must be a power of two", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/plru_tree.sv", 124);
end
end
output_onehot: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) ($onehot0(plru_o)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "output_onehot", "More than one bit set in PLRU output.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/plru_tree.sv", 127);
end
endmodule
`begin_keywords "1800-2023"
module passthrough_stream_fifo #(
parameter int unsigned Depth = 32'd8,
parameter bit PrintInfo = 1'b0,
parameter bit SameCycleRW = 1'b1,
parameter type type_t = logic
) (
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input logic testmode_i,
input type_t data_i,
input logic valid_i,
output logic ready_o,
output type_t data_o,
output logic valid_o,
input logic ready_i
);
localparam int unsigned PointerWidth = $clog2(Depth) + 1;
logic [PointerWidth-1:0] read_ptr_d, read_ptr_q;
logic [PointerWidth-1:0] write_ptr_d, write_ptr_q;
type_t [Depth-1 :0] data_d, data_q;
logic load_data;
assign data_o = data_q[read_ptr_q[PointerWidth-2:0]];
always_comb begin
load_data = 1'b0;
read_ptr_d = read_ptr_q;
write_ptr_d = write_ptr_q;
data_d = data_q;
if (flush_i) begin
read_ptr_d = '0;
write_ptr_d = '0;
valid_o = 1'b0;
ready_o = 1'b0;
end else begin
valid_o = read_ptr_q[PointerWidth-1] == write_ptr_q[PointerWidth-1]
? read_ptr_q[PointerWidth-2:0] != write_ptr_q[PointerWidth-2:0] : 1'b1;
if (ready_i) begin
if (read_ptr_q[PointerWidth-2:0] == (Depth-1)) begin
read_ptr_d[PointerWidth-2:0] = '0;
read_ptr_d[PointerWidth-1] = !read_ptr_q[PointerWidth-1];
end else begin
read_ptr_d = read_ptr_q + 'd1;
end
end
ready_o = (read_ptr_q[PointerWidth-1] == write_ptr_q[PointerWidth-1]
? 1'b1 : write_ptr_q[PointerWidth-2:0] != read_ptr_q[PointerWidth-2:0])
|| (SameCycleRW && ready_i && valid_o);
if (valid_i) begin
load_data = 1'b1;
data_d[write_ptr_q[PointerWidth-2:0]] = data_i;
if (write_ptr_q[PointerWidth-2:0] == (Depth-1)) begin
write_ptr_d[PointerWidth-2:0] = '0;
write_ptr_d[PointerWidth-1] = !write_ptr_q[PointerWidth-1];
end else begin
write_ptr_d = write_ptr_q + 'd1;
end
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
read_ptr_q <= ('0);
end else begin
read_ptr_q <= (read_ptr_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
write_ptr_q <= ('0);
end else begin
write_ptr_q <= (write_ptr_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
data_q <= ('0);
end else begin
if (load_data) begin
data_q <= (data_d);
end
end
end
CheckFullPush: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) not ((!ready_o & valid_i)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "CheckFullPush", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/passthrough_stream_fifo.sv", 118);
end
CheckEmptyPop: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) not ((!valid_o & ready_i)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "CheckEmptyPop", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/passthrough_stream_fifo.sv", 120);
end
endmodule
`begin_keywords "1800-2023"
module popcount #(
parameter int unsigned INPUT_WIDTH = 256,
localparam int unsigned PopcountWidth = $clog2(INPUT_WIDTH) + 1
) (
input logic [ INPUT_WIDTH-1:0] data_i,
output logic [PopcountWidth-1:0] popcount_o
);
if (INPUT_WIDTH < 1)
$error("INPUT_WIDTH must be larger or equal to 1.");
always_comb begin
popcount_o = 0;
for (int i = 0; i < INPUT_WIDTH; i++) begin
popcount_o += data_i[i];
end
end
endmodule : popcount
`begin_keywords "1800-2023"
module ring_buffer #(
parameter int unsigned Depth = 32,
parameter type data_t = logic,
localparam int unsigned AddrWidth = cf_math_pkg::idx_width(Depth),
localparam int unsigned StepWidth = cf_math_pkg::idx_width(Depth+1),
localparam type addr_t = logic [AddrWidth-1:0],
localparam type step_t = logic [StepWidth-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic wvalid_i,
output logic wready_o,
input data_t wdata_i,
input logic rvalid_i,
output logic rready_o,
input addr_t raddr_i,
output data_t rdata_o,
input logic advance_i,
input step_t step_i,
output addr_t wptr_o,
output addr_t rptr_o,
output logic full_o,
output logic empty_o
);
data_t [Depth-1:0] mem_d, mem_q;
logic [AddrWidth:0] rptr_d, rptr_q;
logic [AddrWidth:0] wptr_d, wptr_q;
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
mem_q <= ('0);
end else begin
mem_q <= (mem_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
rptr_q <= ('0);
end else begin
rptr_q <= (rptr_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
wptr_q <= ('0);
end else begin
wptr_q <= (wptr_d);
end
end
always_comb begin
mem_d = mem_q;
rptr_d = rptr_q;
wptr_d = wptr_q;
if (wvalid_i && wready_o) begin
mem_d[wptr_q[AddrWidth-1:0]] = wdata_i;
wptr_d = wptr_q + 1;
end
if (advance_i) begin
rptr_d = rptr_q + step_i;
end
end
assign wptr_o = wptr_q[AddrWidth-1:0];
assign rptr_o = rptr_q[AddrWidth-1:0];
assign empty_o = wptr_q == rptr_q;
assign full_o = (wptr_q[AddrWidth-1:0] == rptr_q[AddrWidth-1:0]) && !empty_o;
assign rready_o = ((rptr_o < wptr_o) && ((raddr_i >= rptr_o) && (raddr_i < wptr_o))) ||
((rptr_o > wptr_o) && ((raddr_i >= rptr_o) || (raddr_i < wptr_o))) ||
((rptr_o == wptr_o) && !empty_o);
assign wready_o = !full_o;
assign rdata_o = mem_q[raddr_i];
step_t max_step;
always_comb begin
if (rptr_q[AddrWidth] == wptr_d[AddrWidth])
max_step = wptr_d[AddrWidth-1:0] - rptr_q[AddrWidth-1:0];
else
max_step = Depth - rptr_q[AddrWidth-1:0] + wptr_d[AddrWidth-1:0];
end
ReadPtrOvertakesWritePtr: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (advance_i |-> step_i <= max_step))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "ReadPtrOvertakesWritePtr", "Attempting to increment rptr beyond wptr", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/ring_buffer.sv", 140);
end
;
WritePtrOvertakesReadPtr: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (wvalid_i && wready_o |-> !((wptr_q[AddrWidth-1:0] == rptr_d[AddrWidth-1:0]) && !(wptr_q == rptr_d))))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "WritePtrOvertakesReadPtr", "Attempting to increment wptr beyond rptr", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/ring_buffer.sv", 149);
end
;
ReadAddrOutOfBounds: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (rvalid_i && rready_o |-> ( ((rptr_o < wptr_o) && ((raddr_i >= rptr_o) && (raddr_i < wptr_o))) || ((rptr_o > wptr_o) && ((raddr_i >= rptr_o) || (raddr_i < wptr_o))) || ((rptr_o == wptr_o) && !empty_o) )))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "ReadAddrOutOfBounds", "raddr_i is not within the valid range defined by rptr_o and wptr_o", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/ring_buffer.sv", 164);
end
;
WriteStable: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) ((wvalid_i) && !(wready_o) |=> $stable((wdata_i) & ~( '0))))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "WriteStable", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/ring_buffer.sv", 167);
end
ReadStable: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) ((rvalid_i) && !(rready_o) |=> $stable((raddr_i) & ~( '0))))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "ReadStable", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/ring_buffer.sv", 168);
end
initial begin
CheckDepthPow2: assert (cf_math_pkg::is_power_of_2(Depth))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "CheckDepthPow2", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/ring_buffer.sv", 171);
end
end
endmodule
`begin_keywords "1800-2023"
module rr_arb_tree #(
parameter int unsigned NumIn = 64,
parameter int unsigned DataWidth = 32,
parameter type DataType = logic [DataWidth-1:0],
parameter bit ExtPrio = 1'b0,
parameter bit AxiVldRdy = 1'b0,
parameter bit LockIn = 1'b0,
parameter bit FairArb = 1'b1,
parameter int unsigned IdxWidth = (NumIn > 32'd1) ? unsigned'($clog2(NumIn)) : 32'd1,
parameter type idx_t = logic [IdxWidth-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input idx_t rr_i,
input logic [NumIn-1:0] req_i,
/*verilator lint_off UNOPTFLAT*/
output logic [NumIn-1:0] gnt_o,
/*verilator lint_on UNOPTFLAT*/
input DataType [NumIn-1:0] data_i,
output logic req_o,
input logic gnt_i,
output DataType data_o,
output idx_t idx_o
);
if (NumIn == unsigned'(1)) begin : gen_pass_through
assign req_o = req_i[0];
assign gnt_o[0] = gnt_i;
assign data_o = data_i[0];
assign idx_o = '0;
end else begin : gen_arbiter
localparam int unsigned NumLevels = unsigned'($clog2(NumIn));
/*verilator lint_off SPLITVAR*/
idx_t [2**NumLevels-2:0] index_nodes /*verilator split_var*/;
DataType [2**NumLevels-2:0] data_nodes /*verilator split_var*/;
logic [2**NumLevels-2:0] gnt_nodes /*verilator split_var*/;
logic [2**NumLevels-2:0] req_nodes /*verilator split_var*/;
/*verilator lint_on SPLITVAR*/
idx_t rr_q;
logic [NumIn-1:0] req_d;
assign req_o = req_nodes[0];
assign data_o = data_nodes[0];
assign idx_o = index_nodes[0];
if (ExtPrio) begin : gen_ext_rr
assign rr_q = rr_i;
assign req_d = req_i;
end else begin : gen_int_rr
idx_t rr_d;
if (LockIn) begin : gen_lock
logic lock_d, lock_q;
logic [NumIn-1:0] req_q;
assign lock_d = req_o & ~gnt_i;
assign req_d = (lock_q) ? req_q : req_i;
always_ff @(posedge clk_i or negedge rst_ni) begin : p_lock_reg
if (!rst_ni) begin
lock_q <= '0;
end else begin
if (flush_i) begin
lock_q <= '0;
end else begin
lock_q <= lock_d;
end
end
end
lock: assert property (@(posedge clk_i) disable iff ((!rst_ni || flush_i) !== '0) (req_o && (!gnt_i && !flush_i) |=> idx_o == $past(idx_o)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "lock", "Lock implies same arbiter decision in next cycle if output is not ready.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/rr_arb_tree.sv", 169);
end
logic [NumIn-1:0] req_tmp;
assign req_tmp = req_q & req_i;
lock_req: assume property (@(posedge clk_i) disable iff ((!rst_ni || flush_i) !== '0) (lock_d |=> req_tmp == req_q))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "lock_req", "It is disallowed to deassert unserved request signals when LockIn is enabled.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/rr_arb_tree.sv", 174);
end
always_ff @(posedge clk_i or negedge rst_ni) begin : p_req_regs
if (!rst_ni) begin
req_q <= '0;
end else begin
if (flush_i) begin
req_q <= '0;
end else begin
req_q <= req_d;
end
end
end
end else begin : gen_no_lock
assign req_d = req_i;
end
if (FairArb) begin : gen_fair_arb
logic [NumIn-1:0] upper_mask, lower_mask;
idx_t upper_idx, lower_idx, next_idx;
logic upper_empty, lower_empty;
for (genvar i = 0; i < NumIn; i++) begin : gen_mask
assign upper_mask[i] = (i > rr_q) ? req_d[i] : 1'b0;
assign lower_mask[i] = (i <= rr_q) ? req_d[i] : 1'b0;
end
lzc #(
.WIDTH ( NumIn ),
.MODE ( 1'b0 )
) i_lzc_upper (
.in_i ( upper_mask ),
.cnt_o ( upper_idx ),
.empty_o ( upper_empty )
);
lzc #(
.WIDTH ( NumIn ),
.MODE ( 1'b0 )
) i_lzc_lower (
.in_i ( lower_mask ),
.cnt_o ( lower_idx ),
.empty_o ( )
);
assign next_idx = upper_empty ? lower_idx : upper_idx;
assign rr_d = (gnt_i && req_o) ? next_idx : rr_q;
end else begin : gen_unfair_arb
assign rr_d = (gnt_i && req_o) ? ((rr_q == idx_t'(NumIn-1)) ? '0 : rr_q + 1'b1) : rr_q;
end
always_ff @(posedge clk_i or negedge rst_ni) begin : p_rr_regs
if (!rst_ni) begin
rr_q <= '0;
end else begin
if (flush_i) begin
rr_q <= '0;
end else begin
rr_q <= rr_d;
end
end
end
end
assign gnt_nodes[0] = gnt_i;
for (genvar level = 0; unsigned'(level) < NumLevels; level++) begin : gen_levels
for (genvar l = 0; l < 2**level; l++) begin : gen_level
logic sel;
localparam int unsigned Idx0 = 2**level-1+l;
localparam int unsigned Idx1 = 2**(level+1)-1+l*2;
if (unsigned'(level) == NumLevels-1) begin : gen_first_level
if (unsigned'(l) * 2 < NumIn-1) begin : gen_reduce
assign req_nodes[Idx0] = req_d[l*2] | req_d[l*2+1];
assign sel = ~req_d[l*2] | req_d[l*2+1] & rr_q[NumLevels-1-level];
assign index_nodes[Idx0] = idx_t'(sel);
assign data_nodes[Idx0] = (sel) ? data_i[l*2+1] : data_i[l*2];
assign gnt_o[l*2] = gnt_nodes[Idx0] & (AxiVldRdy | req_d[l*2]) & ~sel;
assign gnt_o[l*2+1] = gnt_nodes[Idx0] & (AxiVldRdy | req_d[l*2+1]) & sel;
end
if (unsigned'(l) * 2 == NumIn-1) begin : gen_first
assign req_nodes[Idx0] = req_d[l*2];
assign index_nodes[Idx0] = '0;
assign data_nodes[Idx0] = data_i[l*2];
assign gnt_o[l*2] = gnt_nodes[Idx0] & (AxiVldRdy | req_d[l*2]);
end
if (unsigned'(l) * 2 > NumIn-1) begin : gen_out_of_range
assign req_nodes[Idx0] = 1'b0;
assign index_nodes[Idx0] = idx_t'('0);
assign data_nodes[Idx0] = DataType'('0);
end
end else begin : gen_other_levels
assign req_nodes[Idx0] = req_nodes[Idx1] | req_nodes[Idx1+1];
assign sel = ~req_nodes[Idx1] | req_nodes[Idx1+1] & rr_q[NumLevels-1-level];
assign index_nodes[Idx0] = (sel) ?
idx_t'({1'b1, index_nodes[Idx1+1][NumLevels-unsigned'(level)-2:0]}) :
idx_t'({1'b0, index_nodes[Idx1][NumLevels-unsigned'(level)-2:0]});
assign data_nodes[Idx0] = (sel) ? data_nodes[Idx1+1] : data_nodes[Idx1];
assign gnt_nodes[Idx1] = gnt_nodes[Idx0] & ~sel;
assign gnt_nodes[Idx1+1] = gnt_nodes[Idx0] & sel;
end
end
end
initial begin
numin_0: assert (NumIn)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "numin_0", "Input must be at least one element wide.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/rr_arb_tree.sv", 300);
end
end
initial begin
lockin_and_extprio: assert (!(LockIn && ExtPrio))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "lockin_and_extprio", "Cannot use LockIn feature together with external ExtPrio.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/rr_arb_tree.sv", 302);
end
end
hot_one: assert property (@(posedge clk_i) disable iff ((!rst_ni || flush_i) !== '0) ($onehot0(gnt_o)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "hot_one", "Grant signal must be hot1 or zero.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/rr_arb_tree.sv", 305);
end
gnt0: assert property (@(posedge clk_i) disable iff ((!rst_ni || flush_i) !== '0) (|gnt_o |-> gnt_i))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "gnt0", "Grant out implies grant in.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/rr_arb_tree.sv", 307);
end
gnt1: assert property (@(posedge clk_i) disable iff ((!rst_ni || flush_i) !== '0) (req_o |-> gnt_i |-> |gnt_o))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "gnt1", "Req out and grant in implies grant out.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/rr_arb_tree.sv", 310);
end
gnt_idx: assert property (@(posedge clk_i) disable iff ((!rst_ni || flush_i) !== '0) (req_o |-> gnt_i |-> gnt_o[idx_o]))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "gnt_idx", "Idx_o / gnt_o do not match.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/rr_arb_tree.sv", 313);
end
req0: assert property (@(posedge clk_i) disable iff ((!rst_ni || flush_i) !== '0) (|req_i |-> req_o))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "req0", "Req in implies req out.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/rr_arb_tree.sv", 315);
end
req1: assert property (@(posedge clk_i) disable iff ((!rst_ni || flush_i) !== '0) (req_o |-> |req_i))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "req1", "Req out implies req in.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/rr_arb_tree.sv", 317);
end
end
endmodule : rr_arb_tree
`begin_keywords "1800-2023"
module rstgen_bypass #(
parameter int unsigned NumRegs = 4
) (
input logic clk_i,
input logic rst_ni,
input logic rst_test_mode_ni,
input logic test_mode_i,
output logic rst_no,
output logic init_no
);
logic rst_n;
logic [NumRegs-1:0] synch_regs_q;
tc_clk_mux2 i_tc_clk_mux2_rst_n (
.clk0_i ( rst_ni ),
.clk1_i ( rst_test_mode_ni ),
.clk_sel_i ( test_mode_i ),
.clk_o ( rst_n )
);
tc_clk_mux2 i_tc_clk_mux2_rst_no (
.clk0_i ( synch_regs_q[NumRegs-1] ),
.clk1_i ( rst_test_mode_ni ),
.clk_sel_i ( test_mode_i ),
.clk_o ( rst_no )
);
tc_clk_mux2 i_tc_clk_mux2_init_no (
.clk0_i ( synch_regs_q[NumRegs-1] ),
.clk1_i ( 1'b1 ),
.clk_sel_i ( test_mode_i ),
.clk_o ( init_no )
);
always @(posedge clk_i or negedge rst_n) begin
if (~rst_n) begin
synch_regs_q <= 0;
end else begin
synch_regs_q <= {synch_regs_q[NumRegs-2:0], 1'b1};
end
end
initial begin : p_assertions
if (NumRegs < 1) $fatal(1, "At least one register is required.");
end
endmodule
`begin_keywords "1800-2023"
module serial_deglitch #(
parameter int unsigned SIZE = 4
)(
input logic clk_i,
input logic rst_ni,
input logic en_i,
input logic d_i,
output logic q_o
);
logic [SIZE-1:0] count_q;
logic q;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
count_q <= '0;
q <= 1'b0;
end else begin
if (en_i) begin
if (d_i == 1'b1 && count_q != SIZE[SIZE-1:0]) begin
count_q <= count_q + 1;
end else if (d_i == 1'b0 && count_q != SIZE[SIZE-1:0]) begin
count_q <= count_q - 1;
end
end
end
end
always_comb begin
if (count_q == SIZE[SIZE-1:0]) begin
q_o = 1'b1;
end else if (count_q == 0) begin
q_o = 1'b0;
end
end
endmodule
`begin_keywords "1800-2023"
module shift_reg #(
parameter type dtype = logic,
parameter int unsigned Depth = 1
)(
input logic clk_i,
input logic rst_ni,
input dtype d_i,
output dtype d_o
);
shift_reg_gated #(
.Depth(Depth),
.dtype(dtype)
) i_shift_reg_gated (
.clk_i (clk_i),
.rst_ni (rst_ni),
.valid_i(1'b1),
.data_i (d_i),
.valid_o(),
.data_o (d_o)
);
endmodule
`begin_keywords "1800-2023"
module shift_reg_gated #(
parameter int unsigned Depth = 32'd8,
parameter type dtype = logic
) (
input logic clk_i,
input logic rst_ni,
input logic valid_i,
input dtype data_i,
output logic valid_o,
output dtype data_o
);
if (Depth == 0) begin : gen_pass_through
assign valid_o = valid_i;
assign data_o = data_i;
end else begin : gen_shift_reg
logic [Depth-1 : 0] valid_d, valid_q;
dtype [Depth-1 : 0] data_d, data_q;
for (genvar i = 0; i < Depth; i++) begin : gen_regs
if (i == 0) begin : gen_shift_in
assign valid_d[i] = valid_i;
assign data_d[i] = data_i;
end else begin : gen_shift
assign valid_d[i] = valid_q[i-1];
assign data_d[i] = data_q[i-1];
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
valid_q[i] <= ('0);
end else begin
valid_q[i] <= (valid_d[i]);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
data_q[i] <= (dtype'('0));
end else begin
if (valid_d[i]) begin
data_q[i] <= (data_d[i]);
end
end
end
end
assign valid_o = valid_q[Depth-1];
assign data_o = data_q[Depth-1];
end
endmodule
`begin_keywords "1800-2023"
module spill_register_flushable #(
parameter type T = logic,
parameter bit Bypass = 1'b0
) (
input logic clk_i ,
input logic rst_ni ,
input logic valid_i ,
input logic flush_i ,
output logic ready_o ,
input T data_i ,
output logic valid_o ,
input logic ready_i ,
output T data_o
);
if (Bypass) begin : gen_bypass
assign valid_o = valid_i;
assign ready_o = ready_i;
assign data_o = data_i;
end else begin : gen_spill_reg
T a_data_q;
logic a_full_q;
logic a_fill, a_drain;
always_ff @(posedge clk_i or negedge rst_ni) begin : ps_a_data
if (!rst_ni)
a_data_q <= T'('0);
else if (a_fill)
a_data_q <= data_i;
end
always_ff @(posedge clk_i or negedge rst_ni) begin : ps_a_full
if (!rst_ni)
a_full_q <= 0;
else if (a_fill || a_drain)
a_full_q <= a_fill;
end
T b_data_q;
logic b_full_q;
logic b_fill, b_drain;
always_ff @(posedge clk_i or negedge rst_ni) begin : ps_b_data
if (!rst_ni)
b_data_q <= T'('0);
else if (b_fill)
b_data_q <= a_data_q;
end
always_ff @(posedge clk_i or negedge rst_ni) begin : ps_b_full
if (!rst_ni)
b_full_q <= 0;
else if (b_fill || b_drain)
b_full_q <= b_fill;
end
assign a_fill = valid_i && ready_o && (!flush_i);
assign a_drain = (a_full_q && !b_full_q) || flush_i;
assign b_fill = a_drain && (!ready_i) && (!flush_i);
assign b_drain = (b_full_q && ready_i) || flush_i;
assign ready_o = !a_full_q || !b_full_q;
assign valid_o = a_full_q | b_full_q;
assign data_o = b_full_q ? b_data_q : a_data_q;
flush_valid: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (flush_i |-> ~valid_i))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "flush_valid", "Trying to flush and feed the spill register simultaneously. You will lose data!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/spill_register_flushable.sv", 100);
end
end
endmodule
`begin_keywords "1800-2023"
module stream_demux #(
parameter int unsigned N_OUP = 32'd1,
parameter int unsigned LOG_N_OUP = (N_OUP > 32'd1) ? unsigned'($clog2(N_OUP)) : 1'b1
) (
input logic inp_valid_i,
output logic inp_ready_o,
input logic [LOG_N_OUP-1:0] oup_sel_i,
output logic [N_OUP-1:0] oup_valid_o,
input logic [N_OUP-1:0] oup_ready_i
);
always_comb begin
oup_valid_o = '0;
oup_valid_o[oup_sel_i] = inp_valid_i;
end
assign inp_ready_o = oup_ready_i[oup_sel_i];
endmodule
`begin_keywords "1800-2023"
module stream_filter (
input logic valid_i,
output logic ready_o,
input logic drop_i,
output logic valid_o,
input logic ready_i
);
assign valid_o = drop_i ? 1'b0 : valid_i;
assign ready_o = drop_i ? 1'b1 : ready_i;
endmodule
`begin_keywords "1800-2023"
module stream_fork #(
parameter int unsigned N_OUP = 0
) (
input logic clk_i,
input logic rst_ni,
input logic valid_i,
output logic ready_o,
output logic [N_OUP-1:0] valid_o,
input logic [N_OUP-1:0] ready_i
);
typedef enum logic {READY, WAIT} state_t;
logic [N_OUP-1:0] oup_ready,
all_ones;
state_t inp_state_d, inp_state_q;
always_comb begin
inp_state_d = inp_state_q;
unique case (inp_state_q)
READY: begin
if (valid_i) begin
if (valid_o == all_ones && ready_i == all_ones) begin
ready_o = 1'b1;
end else begin
ready_o = 1'b0;
inp_state_d = WAIT;
end
end else begin
ready_o = 1'b0;
end
end
WAIT: begin
if (valid_i && oup_ready == all_ones) begin
ready_o = 1'b1;
inp_state_d = READY;
end else begin
ready_o = 1'b0;
end
end
default: begin
inp_state_d = READY;
ready_o = 1'b0;
end
endcase
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
inp_state_q <= READY;
end else begin
inp_state_q <= inp_state_d;
end
end
for (genvar i = 0; i < N_OUP; i++) begin: gen_oup_state
state_t oup_state_d, oup_state_q;
always_comb begin
oup_ready[i] = 1'b1;
valid_o[i] = 1'b0;
oup_state_d = oup_state_q;
unique case (oup_state_q)
READY: begin
if (valid_i) begin
valid_o[i] = 1'b1;
if (ready_i[i]) begin
if (!ready_o) begin
oup_state_d = WAIT;
end
end else begin
oup_ready[i] = 1'b0;
end
end
end
WAIT: begin
if (valid_i && ready_o) begin
oup_state_d = READY;
end
end
default: begin
oup_state_d = READY;
end
endcase
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
oup_state_q <= READY;
end else begin
oup_state_q <= oup_state_d;
end
end
end
assign all_ones = '1;
initial begin
n_oup_0: assert (N_OUP >= 1)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "n_oup_0", "Number of outputs must be at least 1!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_fork.sv", 128);
end
end
endmodule
`begin_keywords "1800-2023"
interface STREAM_DV #(
parameter type payload_t = logic
)(
input logic clk_i
);
payload_t data;
logic valid;
logic ready;
modport In (
output ready,
input valid, data
);
modport Out (
output valid, data,
input ready
);
modport Passive (
input valid, ready, data
);
data_unstable: assert property (@(posedge clk_i) disable iff ((1'b0) !== '0) ((valid && !ready |=> $stable(data))))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "data_unstable", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_intf.sv", 46);
end
valid_unstable: assert property (@(posedge clk_i) disable iff ((1'b0) !== '0) ((valid && !ready |=> valid)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "valid_unstable", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_intf.sv", 47);
end
endinterface
`begin_keywords "1800-2023"
module stream_join_dynamic #(
parameter int unsigned N_INP = 32'd0
) (
input logic [N_INP-1:0] inp_valid_i,
output logic [N_INP-1:0] inp_ready_o,
input logic [N_INP-1:0] sel_i,
output logic oup_valid_o,
input logic oup_ready_i
);
assign oup_valid_o = &(inp_valid_i | ~sel_i) && |sel_i;
for (genvar i = 0; i < N_INP; i++) begin : gen_inp_ready
assign inp_ready_o[i] = oup_valid_o & oup_ready_i & sel_i[i];
end
initial begin
n_inp_0: assert (N_INP >= 1)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "n_inp_0", "N_INP must be at least 1!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_join_dynamic.sv", 43);
end
end
endmodule
`begin_keywords "1800-2023"
module stream_mux #(
parameter type DATA_T = logic,
parameter integer N_INP = 0,
parameter integer LOG_N_INP = $clog2(N_INP)
) (
input DATA_T [N_INP-1:0] inp_data_i,
input logic [N_INP-1:0] inp_valid_i,
output logic [N_INP-1:0] inp_ready_o,
input logic [LOG_N_INP-1:0] inp_sel_i,
output DATA_T oup_data_o,
output logic oup_valid_o,
input logic oup_ready_i
);
always_comb begin
inp_ready_o = '0;
inp_ready_o[inp_sel_i] = oup_ready_i;
end
assign oup_data_o = inp_data_i[inp_sel_i];
assign oup_valid_o = inp_valid_i[inp_sel_i];
initial begin
n_inp_0: assert (N_INP >= 1)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "n_inp_0", "The number of inputs must be at least 1!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_mux.sv", 41);
end
end
endmodule
`begin_keywords "1800-2023"
module stream_throttle #(
parameter int unsigned MaxNumPending = 1,
parameter int unsigned CntWidth = cf_math_pkg::idx_width(MaxNumPending),
parameter type credit_t = logic [CntWidth-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic req_valid_i,
output logic req_valid_o,
input logic req_ready_i,
output logic req_ready_o,
input logic rsp_valid_i,
input logic rsp_ready_i,
input credit_t credit_i
);
credit_t credit_d, credit_q;
logic credit_available;
always_comb begin : proc_credit_counter
credit_d = credit_q;
if (req_ready_o & req_valid_o) begin
credit_d = credit_d + 'd1;
end
if (rsp_valid_i & rsp_ready_i) begin
credit_d = credit_d - 'd1;
end
end
assign credit_available = credit_q <= (credit_i - 'd1);
assign req_valid_o = req_valid_i & credit_available;
assign req_ready_o = req_ready_i & credit_available;
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
credit_q <= ('0);
end else begin
credit_q <= (credit_d);
end
end
endmodule : stream_throttle
`begin_keywords "1800-2023"
module sub_per_hash #(
parameter int unsigned InpWidth = 32'd11,
parameter int unsigned HashWidth = 32'd5,
parameter int unsigned NoRounds = 32'd1,
parameter int unsigned PermuteKey = 32'd299034753,
parameter int unsigned XorKey = 32'd4094834
) (
input logic [InpWidth-1:0] data_i,
output logic [HashWidth-1:0] hash_o,
output logic [2**HashWidth-1:0] hash_onehot_o
);
typedef int unsigned perm_lists_t [NoRounds][InpWidth];
perm_lists_t Permutations;
assign Permutations = get_permutations(PermuteKey);
typedef int unsigned xor_stages_t [NoRounds][InpWidth][3];
xor_stages_t XorStages;
assign XorStages = get_xor_stages(XorKey);
logic [NoRounds-1:0][InpWidth-1:0] permuted, xored;
for (genvar r = 0; r < NoRounds; r++) begin : gen_round
for (genvar i = 0; i < InpWidth ; i++) begin : gen_sub_per
if (r == 0) begin : gen_input
assign permuted[r][i] = data_i[Permutations[r][i]];
end else begin : gen_permutation
assign permuted[r][i] = permuted[r-1][Permutations[r][i]];
end
assign xored[r][i] = permuted[r][XorStages[r][i][0]] ^
permuted[r][XorStages[r][i][1]] ^
permuted[r][XorStages[r][i][2]];
end
end
assign hash_o = xored[NoRounds-1][HashWidth-1:0];
assign hash_onehot_o = 1 << hash_o;
function automatic perm_lists_t get_permutations(input int unsigned seed);
perm_lists_t indices;
perm_lists_t perm_array;
longint unsigned A = 2147483629;
longint unsigned C = 2147483587;
longint unsigned M = 2**31 - 1;
longint unsigned index = 0;
longint unsigned advance = 0;
longint unsigned rand_number = (A * seed + C) % M;
for (int unsigned r = 0; r < NoRounds; r++) begin
for (int unsigned i = 0; i < InpWidth; i++) begin
indices[r][i] = i;
end
for (int unsigned i = 0; i < InpWidth; i++) begin
if (i > 0) begin
rand_number = (A * rand_number + C) % M;
index = rand_number % i;
end
if (i != index) begin
perm_array[r][i] = perm_array[r][index];
perm_array[r][index] = indices[r][i];
end
end
rand_number = (A * rand_number + C) % M;
advance = rand_number % NoRounds;
for (int unsigned i = 0; i < advance; i++) begin
rand_number = (A * rand_number + C) % M;
end
end
return perm_array;
endfunction : get_permutations
function automatic xor_stages_t get_xor_stages(input int unsigned seed);
xor_stages_t xor_array;
longint unsigned A = 1664525;
longint unsigned C = 1013904223;
longint unsigned M = 2**32;
longint unsigned index = 0;
longint unsigned advance = 0;
longint unsigned rand_number = (A * seed + C) % M;
for (int unsigned r = 0; r < NoRounds; r++) begin
for (int unsigned i = 0; i < InpWidth; i++) begin
rand_number = (A * rand_number + C) % M;
for (int unsigned j = 0; j < 3; j++) begin
rand_number = (A * rand_number + C) % M;
index = rand_number % InpWidth;
xor_array[r][i][j] = index;
end
end
rand_number = (A * rand_number + C) % M;
advance = rand_number % NoRounds;
for (int unsigned i = 0; i < advance; i++) begin
rand_number = (A * rand_number + C) % M;
end
end
return xor_array;
endfunction : get_xor_stages
endmodule
`begin_keywords "1800-2023"
module sync #(
parameter int unsigned STAGES = 2,
parameter bit ResetValue = 1'b0
) (
input logic clk_i,
input logic rst_ni,
input logic serial_i,
output logic serial_o
);
(* dont_touch = "true" *)
(* async_reg = "true" *)
logic [STAGES-1:0] reg_q;
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
reg_q <= {STAGES{ResetValue}};
end else begin
reg_q <= {reg_q[STAGES-2:0], serial_i};
end
end
assign serial_o = reg_q[STAGES-1];
endmodule
`begin_keywords "1800-2023"
module sync_wedge #(
parameter int unsigned STAGES = 2
) (
input logic clk_i,
input logic rst_ni,
input logic en_i,
input logic serial_i,
output logic r_edge_o,
output logic f_edge_o,
output logic serial_o
);
logic clk;
logic serial, serial_q;
assign serial_o = serial_q;
assign f_edge_o = (~serial) & serial_q;
assign r_edge_o = serial & (~serial_q);
sync #(
.STAGES (STAGES)
) i_sync (
.clk_i,
.rst_ni,
.serial_i,
.serial_o ( serial )
);
pulp_clock_gating i_pulp_clock_gating (
.clk_i,
.en_i,
.test_en_i ( 1'b0 ),
.clk_o ( clk )
);
always_ff @(posedge clk, negedge rst_ni) begin
if (!rst_ni) begin
serial_q <= 1'b0;
end else begin
if (en_i) begin
serial_q <= serial;
end
end
end
endmodule
`begin_keywords "1800-2023"
/*verilator lint_off UNUSED*/
module unread (
input logic d_i
);
endmodule
/*verilator lint_on UNUSED*/
`begin_keywords "1800-2023"
(* no_ungroup *)
module read #(
parameter int unsigned Width = 1,
parameter type T = logic [Width-1:0]
) (
input T d_i,
output T d_o
);
assign d_o = d_i;
endmodule
`begin_keywords "1800-2023"
module addr_decode_dync #(
parameter int unsigned NoIndices = 32'd0,
parameter int unsigned NoRules = 32'd0,
parameter type addr_t = logic,
parameter type rule_t = logic,
parameter bit Napot = 0,
parameter int unsigned IdxWidth = cf_math_pkg::idx_width(NoIndices),
parameter type idx_t = logic [IdxWidth-1:0]
) (
input addr_t addr_i,
input rule_t [NoRules-1:0] addr_map_i,
output idx_t idx_o,
output logic dec_valid_o,
output logic dec_error_o,
input logic en_default_idx_i,
input idx_t default_idx_i,
input logic config_ongoing_i
);
logic [NoRules-1:0] matched_rules;
always_comb begin
matched_rules = '0;
dec_valid_o = 1'b0;
dec_error_o = (en_default_idx_i) ? 1'b0 : 1'b1;
idx_o = (en_default_idx_i) ? default_idx_i : '0;
for (int unsigned i = 0; i < NoRules; i++) begin
if (
!Napot && (addr_i >= addr_map_i[i].start_addr) &&
((addr_i < addr_map_i[i].end_addr) || (addr_map_i[i].end_addr == '0)) ||
Napot && (addr_map_i[i].start_addr & addr_map_i[i].end_addr) ==
(addr_i & addr_map_i[i].end_addr)
) begin
matched_rules[i] = ~config_ongoing_i;
dec_valid_o = ~config_ongoing_i;
dec_error_o = 1'b0;
idx_o = config_ongoing_i ? default_idx_i : idx_t'(addr_map_i[i].idx);
end
end
end
initial begin : proc_check_parameters
addr_width_mismatch: assume ($bits(addr_i) == $bits(addr_map_i[0].start_addr))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "addr_width_mismatch", $sformatf("Input address has %d bits and address map has %d bits.", $bits(addr_i), $bits(addr_map_i[0].start_addr)), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/addr_decode_dync.sv", 129);
end
norules_0: assume (NoRules > 0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "norules_0", $sformatf("At least one rule needed"), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/addr_decode_dync.sv", 130);
end
end
final begin
more_than_1_bit_set: assert ($onehot0(matched_rules) || config_ongoing_i || $test$plusargs("disable_assert_final_checks"))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "more_than_1_bit_set", "More than one bit set in the one-hot signal, matched_rules", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/addr_decode_dync.sv", 134);
end
end
always_comb begin : proc_check_addr_map
if (!$isunknown(addr_map_i) && ~config_ongoing_i) begin
for (int unsigned i = 0; i < NoRules; i++) begin
check_start: assume (Napot || addr_map_i[i].start_addr < addr_map_i[i].end_addr || addr_map_i[i].end_addr == '0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "check_start", $sformatf("This rule has a higher start than end address!!!\n\
Violating rule %d.\n\
Rule> IDX: %h START: %h END: %h\n\
#####################################################", i ,addr_map_i[i].idx, addr_map_i[i].start_addr, addr_map_i[i].end_addr), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/addr_decode_dync.sv", 154);
end
for (int unsigned j = i + 1; j < NoRules; j++) begin
check_overlap: assume (Napot || !((addr_map_i[j].start_addr < addr_map_i[i].end_addr) && (addr_map_i[j].end_addr > addr_map_i[i].start_addr)) || !((addr_map_i[i].end_addr == '0) && (addr_map_i[j].end_addr > addr_map_i[i].start_addr)) || !((addr_map_i[j].start_addr < addr_map_i[i].end_addr) && (addr_map_i[j].end_addr == '0)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "check_overlap", $sformatf("Overlapping address region found!!!\n\
Rule %d: IDX: %h START: %h END: %h\n\
Rule %d: IDX: %h START: %h END: %h\n\
#####################################################", i, addr_map_i[i].idx, addr_map_i[i].start_addr, addr_map_i[i].end_addr, j, addr_map_i[j].idx, addr_map_i[j].start_addr, addr_map_i[j].end_addr), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/addr_decode_dync.sv", 169);
end
end
end
end
end
endmodule
`begin_keywords "1800-2023"
module boxcar #(
parameter int unsigned Width = 32,
localparam int unsigned IdxWidth = cf_math_pkg::idx_width(Width),
localparam type idx_t = logic [IdxWidth-1:0],
localparam type mask_t = logic [Width-1:0]
) (
input idx_t lsb_i,
input idx_t msb_i,
output mask_t mask_o
);
mask_t low_mask, high_mask_n;
heaviside #(.Width(Width)) i_lo (.x_i(lsb_i), .mask_o(low_mask));
heaviside #(.Width(Width)) i_hi (.x_i(msb_i), .mask_o(high_mask_n));
assign mask_o = ~low_mask & high_mask_n;
endmodule
`begin_keywords "1800-2023"
/*verilator lint_off DECLFILENAME*/
module cdc_2phase #(
parameter type T = logic
)(
input logic src_rst_ni,
input logic src_clk_i,
input T src_data_i,
input logic src_valid_i,
output logic src_ready_o,
input logic dst_rst_ni,
input logic dst_clk_i,
output T dst_data_o,
output logic dst_valid_o,
input logic dst_ready_i
);
(* dont_touch = "true" *) logic async_req;
(* dont_touch = "true" *) logic async_ack;
(* dont_touch = "true" *) T async_data;
cdc_2phase_src #(.T(T)) i_src (
.rst_ni ( src_rst_ni ),
.clk_i ( src_clk_i ),
.data_i ( src_data_i ),
.valid_i ( src_valid_i ),
.ready_o ( src_ready_o ),
.async_req_o ( async_req ),
.async_ack_i ( async_ack ),
.async_data_o ( async_data )
);
cdc_2phase_dst #(.T(T)) i_dst (
.rst_ni ( dst_rst_ni ),
.clk_i ( dst_clk_i ),
.data_o ( dst_data_o ),
.valid_o ( dst_valid_o ),
.ready_i ( dst_ready_i ),
.async_req_i ( async_req ),
.async_ack_o ( async_ack ),
.async_data_i ( async_data )
);
endmodule
module cdc_2phase_src #(
parameter type T = logic
)(
input logic rst_ni,
input logic clk_i,
input T data_i,
input logic valid_i,
output logic ready_o,
output logic async_req_o,
input logic async_ack_i,
output T async_data_o
);
(* dont_touch = "true" *)
logic req_src_q, ack_src_q, ack_q;
(* dont_touch = "true" *)
T data_src_q;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
req_src_q <= 0;
data_src_q <= T'('0);
end else if (valid_i && ready_o) begin
req_src_q <= ~req_src_q;
data_src_q <= data_i;
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
ack_src_q <= 0;
ack_q <= 0;
end else begin
ack_src_q <= async_ack_i;
ack_q <= ack_src_q;
end
end
assign ready_o = (req_src_q == ack_q);
assign async_req_o = req_src_q;
assign async_data_o = data_src_q;
endmodule
module cdc_2phase_dst #(
parameter type T = logic
)(
input logic rst_ni,
input logic clk_i,
output T data_o,
output logic valid_o,
input logic ready_i,
input logic async_req_i,
output logic async_ack_o,
input T async_data_i
);
(* dont_touch = "true" *)
(* async_reg = "true" *)
logic req_dst_q, req_q0, req_q1, ack_dst_q;
(* dont_touch = "true" *)
T data_dst_q;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
ack_dst_q <= 0;
end else if (valid_o && ready_i) begin
ack_dst_q <= ~ack_dst_q;
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
data_dst_q <= T'('0);
end else if (req_q0 != req_q1 && !valid_o) begin
data_dst_q <= async_data_i;
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
req_dst_q <= 0;
req_q0 <= 0;
req_q1 <= 0;
end else begin
req_dst_q <= async_req_i;
req_q0 <= req_dst_q;
req_q1 <= req_q0;
end
end
assign valid_o = (ack_dst_q != req_q1);
assign data_o = data_dst_q;
assign async_ack_o = ack_dst_q;
endmodule
/*verilator lint_on DECLFILENAME*/
`begin_keywords "1800-2023"
/*verilator lint_off DECLFILENAME*/
module cdc_4phase #(
parameter type T = logic,
parameter bit DECOUPLED = 1'b1,
parameter bit SEND_RESET_MSG = 1'b0,
parameter T RESET_MSG = T'('0)
)(
input logic src_rst_ni,
input logic src_clk_i,
input T src_data_i,
input logic src_valid_i,
output logic src_ready_o,
input logic dst_rst_ni,
input logic dst_clk_i,
output T dst_data_o,
output logic dst_valid_o,
input logic dst_ready_i
);
(* dont_touch = "true" *) logic async_req;
(* dont_touch = "true" *) logic async_ack;
(* dont_touch = "true" *) T async_data;
cdc_4phase_src #(
.T(T),
.DECOUPLED(DECOUPLED),
.SEND_RESET_MSG(SEND_RESET_MSG),
.RESET_MSG(RESET_MSG)
) i_src (
.rst_ni ( src_rst_ni ),
.clk_i ( src_clk_i ),
.data_i ( src_data_i ),
.valid_i ( src_valid_i ),
.ready_o ( src_ready_o ),
.async_req_o ( async_req ),
.async_ack_i ( async_ack ),
.async_data_o ( async_data )
);
cdc_4phase_dst #(.T(T), .DECOUPLED(DECOUPLED)) i_dst (
.rst_ni ( dst_rst_ni ),
.clk_i ( dst_clk_i ),
.data_o ( dst_data_o ),
.valid_o ( dst_valid_o ),
.ready_i ( dst_ready_i ),
.async_req_i ( async_req ),
.async_ack_o ( async_ack ),
.async_data_i ( async_data )
);
endmodule
module cdc_4phase_src #(
parameter type T = logic,
parameter int unsigned SYNC_STAGES = 2,
parameter bit DECOUPLED = 1'b1,
parameter bit SEND_RESET_MSG = 1'b0,
parameter T RESET_MSG = T'('0)
)(
input logic rst_ni,
input logic clk_i,
input T data_i,
input logic valid_i,
output logic ready_o,
output logic async_req_o,
input logic async_ack_i,
output T async_data_o
);
(* dont_touch = "true" *)
logic req_src_d, req_src_q;
(* dont_touch = "true" *)
T data_src_d, data_src_q;
(* dont_touch = "true" *)
logic ack_synced;
typedef enum logic[1:0] {IDLE, WAIT_ACK_ASSERT, WAIT_ACK_DEASSERT} state_e;
state_e state_d, state_q;
sync #(
.STAGES(SYNC_STAGES)
) i_sync(
.clk_i,
.rst_ni,
.serial_i( async_ack_i ),
.serial_o( ack_synced )
);
always_comb begin
state_d = state_q;
req_src_d = 1'b0;
data_src_d = data_src_q;
ready_o = 1'b0;
case (state_q)
IDLE: begin
if (DECOUPLED) begin
ready_o = 1'b1;
end else begin
ready_o = 1'b0;
end
if (valid_i) begin
data_src_d = data_i;
req_src_d = 1'b1;
state_d = WAIT_ACK_ASSERT;
end
end
WAIT_ACK_ASSERT: begin
req_src_d = 1'b1;
if (ack_synced == 1'b1) begin
req_src_d = 1'b0;
state_d = WAIT_ACK_DEASSERT;
end
end
WAIT_ACK_DEASSERT: begin
if (ack_synced == 1'b0) begin
state_d = IDLE;
if (!DECOUPLED) begin
ready_o = 1'b1;
end
end
end
default: begin
state_d = IDLE;
end
endcase
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
state_q <= IDLE;
end else begin
state_q <= state_d;
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
if (SEND_RESET_MSG) begin
req_src_q <= 1'b1;
data_src_q <= RESET_MSG;
end else begin
req_src_q <= 1'b0;
data_src_q <= T'('0);
end
end else begin
req_src_q <= req_src_d;
data_src_q <= data_src_d;
end
end
assign async_req_o = req_src_q;
assign async_data_o = data_src_q;
endmodule
module cdc_4phase_dst #(
parameter type T = logic,
parameter int unsigned SYNC_STAGES = 2,
parameter bit DECOUPLED = 1
)(
input logic rst_ni,
input logic clk_i,
output T data_o,
output logic valid_o,
input logic ready_i,
input logic async_req_i,
output logic async_ack_o,
input T async_data_i
);
(* dont_touch = "true" *)
logic ack_dst_d, ack_dst_q;
(* dont_touch = "true" *)
logic req_synced;
logic data_valid;
logic output_ready;
typedef enum logic[1:0] {IDLE, WAIT_DOWNSTREAM_ACK, WAIT_REQ_DEASSERT} state_e;
state_e state_d, state_q;
sync #(
.STAGES(SYNC_STAGES)
) i_sync(
.clk_i,
.rst_ni,
.serial_i( async_req_i ),
.serial_o( req_synced )
);
always_comb begin
state_d = state_q;
data_valid = 1'b0;
ack_dst_d = 1'b0;
case (state_q)
IDLE: begin
if (req_synced == 1'b1) begin
data_valid = 1'b1;
if (output_ready == 1'b1) begin
state_d = WAIT_REQ_DEASSERT;
end else begin
state_d = WAIT_DOWNSTREAM_ACK;
end
end
end
WAIT_DOWNSTREAM_ACK: begin
data_valid = 1'b1;
if (output_ready == 1'b1) begin
state_d = WAIT_REQ_DEASSERT;
ack_dst_d = 1'b1;
end
end
WAIT_REQ_DEASSERT: begin
ack_dst_d = 1'b1;
if (req_synced == 1'b0) begin
ack_dst_d = 1'b0;
state_d = IDLE;
end
end
default: begin
state_d = IDLE;
end
endcase
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
state_q <= IDLE;
end else begin
state_q <= state_d;
end
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
ack_dst_q <= 1'b0;
end else begin
ack_dst_q <= ack_dst_d;
end
end
if (DECOUPLED) begin : gen_decoupled
spill_register #(
.T(T),
.Bypass(1'b0)
) i_spill_register (
.clk_i,
.rst_ni,
.valid_i(data_valid),
.ready_o(output_ready),
.data_i(async_data_i),
.valid_o,
.ready_i,
.data_o
);
end else begin : gen_not_decoupled
assign valid_o = data_valid;
assign output_ready = ready_i;
assign data_o = async_data_i;
end
assign async_ack_o = ack_dst_q;
endmodule
/*verilator lint_on DECLFILENAME*/
`begin_keywords "1800-2023"
module clk_int_div_static #(
parameter int unsigned DIV_VALUE = 1,
parameter bit ENABLE_CLOCK_IN_RESET = 1'b1
) (
input logic clk_i,
input logic rst_ni,
input logic en_i,
input logic test_mode_en_i,
output logic clk_o
);
if (DIV_VALUE == 0) begin : gen_elab_error
$error("DIV_VALUE must be strictly larger than 0.");
end
localparam int unsigned DivValueWidth = $clog2(DIV_VALUE+1);
logic [DivValueWidth-1:0] div_value;
assign div_value = DIV_VALUE;
clk_int_div #(
.DIV_VALUE_WIDTH ( DivValueWidth ),
.DEFAULT_DIV_VALUE ( DIV_VALUE ),
.ENABLE_CLOCK_IN_RESET ( ENABLE_CLOCK_IN_RESET )
) i_clk_int_div (
.clk_i,
.rst_ni,
.en_i,
.test_mode_en_i,
.div_i ( div_value ),
.div_valid_i ( 1'b0 ),
.div_ready_o ( ),
.clk_o,
.cycl_count_o ( )
);
endmodule
`begin_keywords "1800-2023"
module trip_counter #(
parameter int unsigned WIDTH = 4
)(
input logic clk_i,
input logic rst_ni,
input logic en_i,
input logic [WIDTH-1:0] delta_i,
input logic [WIDTH-1:0] bound_i,
output logic [WIDTH-1:0] q_o,
output logic last_o,
output logic trip_o
);
delta_counter #(
.WIDTH(WIDTH)
) i_delta_counter (
.clk_i(clk_i),
.rst_ni(rst_ni),
.clear_i(trip_o),
.en_i(en_i),
.load_i(1'b0),
.down_i(1'b0),
.delta_i(delta_i),
.d_i('0),
.q_o(q_o),
.overflow_o()
);
assign last_o = (q_o == bound_i);
assign trip_o = last_o && en_i;
CounterExceedsBound: assert property (@(posedge clk_i) disable iff (( !rst_ni) !== '0) (!(en_i && (q_o + delta_i) > bound_i)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "CounterExceedsBound", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/trip_counter.sv", 49);
end
endmodule
`begin_keywords "1800-2023"
module addr_decode #(
parameter int unsigned NoIndices = 32'd0,
parameter int unsigned NoRules = 32'd0,
parameter type addr_t = logic,
parameter type rule_t = logic,
parameter bit Napot = 0,
parameter int unsigned IdxWidth = cf_math_pkg::idx_width(NoIndices),
parameter type idx_t = logic [IdxWidth-1:0]
) (
input addr_t addr_i,
input rule_t [NoRules-1:0] addr_map_i,
output idx_t idx_o,
output logic dec_valid_o,
output logic dec_error_o,
input logic en_default_idx_i,
input idx_t default_idx_i
);
addr_decode_dync #(
.NoRules ( NoRules ),
.addr_t ( addr_t ),
.rule_t ( rule_t ),
.Napot ( Napot ),
.idx_t ( idx_t )
) i_addr_decode_dync (
.addr_i,
.addr_map_i,
.idx_o,
.dec_valid_o,
.dec_error_o,
.en_default_idx_i,
.default_idx_i,
.config_ongoing_i ( 1'b0 )
);
endmodule
`begin_keywords "1800-2023"
module addr_decode_napot #(
parameter int unsigned NoIndices = 32'd0,
parameter int unsigned NoRules = 32'd0,
parameter type addr_t = logic,
parameter type rule_t = logic,
parameter int unsigned IdxWidth = cf_math_pkg::idx_width(NoIndices),
parameter type idx_t = logic [IdxWidth-1:0]
) (
input addr_t addr_i,
input rule_t [NoRules-1:0] addr_map_i,
output idx_t idx_o,
output logic dec_valid_o,
output logic dec_error_o,
input logic en_default_idx_i,
input idx_t default_idx_i
);
typedef struct packed {
int unsigned idx;
addr_t start_addr;
addr_t end_addr;
} rule_range_t;
addr_decode_dync #(
.NoIndices ( NoIndices ) ,
.NoRules ( NoRules ),
.addr_t ( addr_t ),
.rule_t ( rule_range_t ),
.Napot ( 1 )
) i_addr_decode_dync (
.addr_i,
.addr_map_i,
.idx_o,
.dec_valid_o,
.dec_error_o,
.en_default_idx_i,
.default_idx_i,
.config_ongoing_i ( 1'b0 )
);
endmodule
`begin_keywords "1800-2023"
module multiaddr_decode #(
parameter int unsigned NoIndices = 32'd0,
parameter int unsigned NoRules = 32'd0,
parameter type addr_t = logic,
parameter type rule_t = logic
) (
input addr_t addr_i,
input addr_t mask_i,
input rule_t [NoRules-1:0] addr_map_i,
output logic [NoIndices-1:0] select_o,
output addr_t [NoIndices-1:0] addr_o,
output addr_t [NoIndices-1:0] mask_o,
output logic dec_valid_o,
output logic dec_error_o
);
logic [NoRules-1:0] matched_rules;
always_comb begin
matched_rules = '0;
dec_valid_o = 1'b0;
dec_error_o = 1'b1;
select_o = '0;
addr_o = '0;
mask_o = '0;
for (int unsigned i = 0; i < NoRules; i++) begin
automatic int unsigned idx = addr_map_i[i].idx;
automatic addr_t dont_care = mask_i | addr_map_i[i].mask;
automatic addr_t matching_bits = ~(addr_i ^ addr_map_i[i].addr);
automatic logic match = &(dont_care | matching_bits);
if (match) begin
matched_rules[i] = 1'b1;
dec_valid_o = 1'b1;
dec_error_o = 1'b0;
select_o[idx] |= 1'b1;
mask_o[idx] = mask_i & addr_map_i[i].mask;
addr_o[idx] = (~mask_i & addr_i) | (mask_i & addr_map_i[i].addr);
end
end
end
initial begin : proc_check_parameters
norules_0: assume (NoRules > 0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "norules_0", $sformatf("At least one rule needed"), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/multiaddr_decode.sv", 127);
end
addr_width_not_equal: assume ($bits(addr_i) == $bits(addr_map_i[0].addr))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "addr_width_not_equal", $sformatf("Input address has %d bits and address map has %d bits.", $bits(addr_i), $bits(addr_map_i[0].addr)), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/multiaddr_decode.sv", 130);
end
end
always_comb begin : proc_check_addr_map
if (!$isunknown(addr_map_i)) begin
for (int unsigned i = 0; i < NoRules; i++) begin
check_idx: assume (addr_map_i[i].idx < NoIndices)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "check_idx", $sformatf("This rule has a IDX that is not allowed!!!\n\
Violating rule %d.\n\
Rule> IDX: %h\n\
Rule> MAX_IDX: %h\n\
#####################################################", i, addr_map_i[i].idx, (NoIndices-1)), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/multiaddr_decode.sv", 146);
end
end
end
end
endmodule
`begin_keywords "1800-2023"
module cb_filter #(
parameter int unsigned KHashes = 32'd3,
parameter int unsigned HashWidth = 32'd4,
parameter int unsigned HashRounds = 32'd1,
parameter int unsigned InpWidth = 32'd32,
parameter int unsigned BucketWidth = 32'd4,
parameter cb_filter_pkg::cb_seed_t [KHashes-1:0] Seeds = cb_filter_pkg::EgSeeds
) (
input logic clk_i,
input logic rst_ni,
input logic [InpWidth-1:0] look_data_i,
output logic look_valid_o,
input logic [InpWidth-1:0] incr_data_i,
input logic incr_valid_i,
input logic [InpWidth-1:0] decr_data_i,
input logic decr_valid_i,
input logic filter_clear_i,
output logic [HashWidth-1:0] filter_usage_o,
output logic filter_full_o,
output logic filter_empty_o,
output logic filter_error_o
);
localparam int unsigned NoCounters = 2**HashWidth;
logic [NoCounters-1:0] look_ind;
logic [NoCounters-1:0] incr_ind;
logic [NoCounters-1:0] decr_ind;
logic [NoCounters-1:0] bucket_en;
logic [NoCounters-1:0] bucket_down;
logic [NoCounters-1:0] bucket_occupied;
logic [NoCounters-1:0] bucket_overflow;
logic [NoCounters-1:0] bucket_full;
logic [NoCounters-1:0] bucket_empty;
logic [NoCounters-1:0] data_in_bucket;
logic cnt_en;
logic cnt_down;
logic cnt_overflow;
hash_block #(
.NoHashes ( KHashes ),
.InpWidth ( InpWidth ),
.HashWidth ( HashWidth ),
.NoRounds ( HashRounds ),
.Seeds ( Seeds )
) i_look_hashes (
.data_i ( look_data_i ),
.indicator_o ( look_ind )
);
assign data_in_bucket = look_ind & bucket_occupied;
assign look_valid_o = (data_in_bucket == look_ind) ? 1'b1 : 1'b0;
hash_block #(
.NoHashes ( KHashes ),
.InpWidth ( InpWidth ),
.HashWidth ( HashWidth ),
.NoRounds ( HashRounds ),
.Seeds ( Seeds )
) i_incr_hashes (
.data_i ( incr_data_i ),
.indicator_o ( incr_ind )
);
hash_block #(
.NoHashes ( KHashes ),
.InpWidth ( InpWidth ),
.HashWidth ( HashWidth ),
.NoRounds ( HashRounds ),
.Seeds ( Seeds )
) i_decr_hashes (
.data_i ( decr_data_i ),
.indicator_o ( decr_ind )
);
assign bucket_down = decr_valid_i ? decr_ind : '0;
always_comb begin : proc_bucket_control
case ({incr_valid_i, decr_valid_i})
2'b00 : bucket_en = '0;
2'b10 : bucket_en = incr_ind;
2'b01 : bucket_en = decr_ind;
2'b11 : bucket_en = incr_ind ^ decr_ind;
default: bucket_en = '0;
endcase
end
for (genvar i = 0; i < NoCounters; i++) begin : gen_buckets
logic [BucketWidth-1:0] bucket_content;
counter #(
.WIDTH( BucketWidth )
) i_bucket (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.clear_i ( filter_clear_i ),
.en_i ( bucket_en[i] ),
.load_i ( '0 ),
.down_i ( bucket_down[i] ),
.d_i ( '0 ),
.q_o ( bucket_content ),
.overflow_o ( bucket_overflow[i])
);
assign bucket_full[i] = bucket_overflow[i] | (&bucket_content);
assign bucket_occupied[i] = |bucket_content;
assign bucket_empty[i] = ~bucket_occupied[i];
end
assign cnt_en = incr_valid_i ^ decr_valid_i;
assign cnt_down = decr_valid_i;
counter #(
.WIDTH ( HashWidth )
) i_tot_count (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.clear_i ( filter_clear_i ),
.en_i ( cnt_en ),
.load_i ( '0 ),
.down_i ( cnt_down ),
.d_i ( '0 ),
.q_o ( filter_usage_o ),
.overflow_o( cnt_overflow )
);
assign filter_full_o = |bucket_full;
assign filter_empty_o = &bucket_empty;
assign filter_error_o = |bucket_overflow | cnt_overflow;
endmodule
module hash_block #(
parameter int unsigned NoHashes = 32'd3,
parameter int unsigned InpWidth = 32'd11,
parameter int unsigned HashWidth = 32'd5,
parameter int unsigned NoRounds = 32'd1,
parameter cb_filter_pkg::cb_seed_t [NoHashes-1:0] Seeds = cb_filter_pkg::EgSeeds
) (
input logic [InpWidth-1:0] data_i,
output logic [2**HashWidth-1:0] indicator_o
);
logic [NoHashes-1:0][2**HashWidth-1:0] hashes;
for (genvar i = 0; i < NoHashes; i++) begin : gen_hashes
sub_per_hash #(
.InpWidth ( InpWidth ),
.HashWidth ( HashWidth ),
.NoRounds ( NoRounds ),
.PermuteKey ( Seeds[i].PermuteSeed ),
.XorKey ( Seeds[i].XorSeed )
) i_hash (
.data_i ( data_i ),
.hash_o ( ),
.hash_onehot_o ( hashes[i] )
);
end
always_comb begin : proc_hash_or
indicator_o = '0;
for (int unsigned j = 0; j < NoHashes; j++) begin
indicator_o = indicator_o | hashes[j];
end
end
initial begin
hash_conf: assume (InpWidth > HashWidth)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "hash_conf", $sformatf("%m:\nA Hash Function reduces the width of the input>\nInpWidth: %s\nOUT_WIDTH: %s", InpWidth, HashWidth), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cb_filter.sv", 243);
end
end
endmodule
`begin_keywords "1800-2023"
module cdc_fifo_2phase #(
parameter type T = logic,
parameter int LOG_DEPTH = 3
)(
input logic src_rst_ni,
input logic src_clk_i,
input T src_data_i,
input logic src_valid_i,
output logic src_ready_o,
input logic dst_rst_ni,
input logic dst_clk_i,
output T dst_data_o,
output logic dst_valid_o,
input logic dst_ready_i
);
initial begin
log_depth_0: assert (LOG_DEPTH > 0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "log_depth_0", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_fifo_2phase.sv", 68);
end
end
localparam int PtrWidth = LOG_DEPTH+1;
typedef logic [PtrWidth-1:0] pointer_t;
typedef logic [LOG_DEPTH-1:0] index_t;
localparam pointer_t PtrFull = (1 << LOG_DEPTH);
localparam pointer_t PtrEmpty = '0;
index_t fifo_widx, fifo_ridx;
logic fifo_write;
T fifo_wdata, fifo_rdata;
T fifo_data_q [2**LOG_DEPTH];
assign fifo_rdata = fifo_data_q[fifo_ridx];
for (genvar i = 0; i < 2**LOG_DEPTH; i++) begin : g_word
always_ff @(posedge src_clk_i, negedge src_rst_ni) begin
if (!src_rst_ni)
fifo_data_q[i] <= T'('0);
else if (fifo_write && fifo_widx == i)
fifo_data_q[i] <= fifo_wdata;
end
end
pointer_t src_wptr_q, dst_wptr, src_rptr, dst_rptr_q;
always_ff @(posedge src_clk_i, negedge src_rst_ni) begin
if (!src_rst_ni)
src_wptr_q <= 0;
else if (src_valid_i && src_ready_o)
src_wptr_q <= src_wptr_q + 1;
end
always_ff @(posedge dst_clk_i, negedge dst_rst_ni) begin
if (!dst_rst_ni)
dst_rptr_q <= 0;
else if (dst_valid_o && dst_ready_i)
dst_rptr_q <= dst_rptr_q + 1;
end
assign src_ready_o = ((src_wptr_q ^ src_rptr) != PtrFull);
assign dst_valid_o = ((dst_rptr_q ^ dst_wptr) != PtrEmpty);
cdc_2phase #( .T(pointer_t) ) i_cdc_wptr (
.src_rst_ni ( src_rst_ni ),
.src_clk_i ( src_clk_i ),
.src_data_i ( src_wptr_q ),
.src_valid_i ( 1'b1 ),
.src_ready_o ( ),
.dst_rst_ni ( dst_rst_ni ),
.dst_clk_i ( dst_clk_i ),
.dst_data_o ( dst_wptr ),
.dst_valid_o ( ),
.dst_ready_i ( 1'b1 )
);
cdc_2phase #( .T(pointer_t) ) i_cdc_rptr (
.src_rst_ni ( dst_rst_ni ),
.src_clk_i ( dst_clk_i ),
.src_data_i ( dst_rptr_q ),
.src_valid_i ( 1'b1 ),
.src_ready_o ( ),
.dst_rst_ni ( src_rst_ni ),
.dst_clk_i ( src_clk_i ),
.dst_data_o ( src_rptr ),
.dst_valid_o ( ),
.dst_ready_i ( 1'b1 )
);
assign fifo_widx = src_wptr_q;
assign fifo_wdata = src_data_i;
assign fifo_write = src_valid_i && src_ready_o;
assign fifo_ridx = dst_rptr_q;
assign dst_data_o = fifo_rdata;
endmodule
`begin_keywords "1800-2023"
module clk_mux_glitch_free #(
parameter int unsigned NUM_INPUTS = 2,
parameter int unsigned NUM_SYNC_STAGES = 2,
parameter bit CLOCK_DURING_RESET = 1'b1,
localparam int unsigned SelWidth = $clog2(NUM_INPUTS)
) (
input logic [NUM_INPUTS-1:0] clks_i,
input logic test_clk_i,
input logic test_en_i,
input logic async_rstn_i,
input logic [SelWidth-1:0] async_sel_i,
output logic clk_o
);
if (NUM_INPUTS<2)
$error("Num inputs must be parametrized to a value >= 2.");
logic [NUM_INPUTS-1:0] s_sel_onehot;
(*dont_touch*)
(*async_reg*)
logic [NUM_INPUTS-1:0][1:0] glitch_filter_d, glitch_filter_q;
logic [NUM_INPUTS-1:0] s_gate_enable_unfiltered_async;
logic [NUM_INPUTS-1:0] s_glitch_filter_output_async;
logic [NUM_INPUTS-1:0] s_gate_enable_sync;
logic [NUM_INPUTS-1:0] s_gate_enable;
logic [NUM_INPUTS-1:0] clock_has_been_disabled_q;
logic [NUM_INPUTS-1:0] s_gated_clock;
logic s_output_clock;
logic [NUM_INPUTS-1:0] s_reset_synced;
logic [NUM_INPUTS-1:0] async_reset_bypass_active_q;
always_comb begin
s_sel_onehot = '0;
s_sel_onehot[async_sel_i] = 1'b1;
end
for (genvar i = 0; i < NUM_INPUTS; i++) begin : gen_input_stages
rstgen i_rstgen(
.clk_i ( clks_i[i] ),
.rst_ni ( async_rstn_i ),
.test_mode_i ( test_en_i ),
.rst_no ( s_reset_synced[i] ),
.init_no ( )
);
always_comb begin
s_gate_enable_unfiltered_async[i] = 1'b1;
for (int j = 0; j < NUM_INPUTS; j++) begin
if (i==j) begin
s_gate_enable_unfiltered_async[i] &= s_sel_onehot[j];
end else begin
s_gate_enable_unfiltered_async[i] &= clock_has_been_disabled_q[j];
end
end
end
assign glitch_filter_d[i][0] = s_gate_enable_unfiltered_async[i];
assign glitch_filter_d[i][1] = glitch_filter_q[i][0];
always_ff @(posedge clks_i[i], negedge s_reset_synced[i]) begin
if (!s_reset_synced[i]) begin
glitch_filter_q[i] <= '0;
end else begin
glitch_filter_q[i] <= glitch_filter_d[i];
end
end
assign s_glitch_filter_output_async[i] = glitch_filter_q[i][1] &
glitch_filter_q[i][0] &
s_gate_enable_unfiltered_async[i];
sync #(.STAGES(NUM_SYNC_STAGES)) i_sync_en(
.clk_i ( clks_i[i] ),
.rst_ni ( s_reset_synced[i] ),
.serial_i ( s_glitch_filter_output_async[i] ),
.serial_o ( s_gate_enable_sync[i] )
);
if (CLOCK_DURING_RESET) begin : gen_async_reset_clock_bypass_logic
always_ff @(posedge clks_i[i], negedge s_reset_synced[i]) begin
if (!s_reset_synced[i]) begin
async_reset_bypass_active_q[i] <= 1'b1;
end else begin
async_reset_bypass_active_q[i] <= 1'b0;
end
end
assign s_gate_enable[i] = async_reset_bypass_active_q[i]?
s_gate_enable_unfiltered_async[i]
: s_gate_enable_sync[i];
end else begin : gen_no_async_reset_bypass_logic
assign s_gate_enable[i] = s_gate_enable_sync[i];
end
tc_clk_gating #(
.IS_FUNCTIONAL(1'b1)
) i_clk_gate (
.clk_i ( clks_i[i] ),
.en_i ( s_gate_enable[i] ),
.test_en_i ( 1'b0 ),
.clk_o ( s_gated_clock[i] )
);
always_ff @(posedge clks_i[i], negedge s_reset_synced[i]) begin
if (!s_reset_synced[i]) begin
clock_has_been_disabled_q[i] <= 1'b1;
end else begin
clock_has_been_disabled_q[i] <= ~s_gate_enable[i];
end
end
end
clk_or_tree #(NUM_INPUTS) i_clk_or_tree (
.clks_i(s_gated_clock),
.clk_o(s_output_clock)
);
tc_clk_mux2 i_test_clk_mux(
.clk0_i(s_output_clock),
.clk1_i(test_clk_i),
.clk_sel_i(test_en_i),
.clk_o
);
endmodule
module clk_or_tree #(
parameter int unsigned NUM_INPUTS
) (
input logic [NUM_INPUTS-1:0] clks_i,
output logic clk_o
);
if (NUM_INPUTS < 1) begin : gen_error
$error("Cannot parametrize clk_or with less then 1 input but was %0d", NUM_INPUTS);
end else if (NUM_INPUTS == 1) begin : gen_leaf
assign clk_o = clks_i[0];
end else if (NUM_INPUTS == 2) begin : gen_leaf
tc_clk_or2 i_clk_or2 (
.clk0_i(clks_i[0]),
.clk1_i(clks_i[1]),
.clk_o
);
end else begin : gen_recursive
logic branch_a, branch_b;
clk_or_tree #(NUM_INPUTS/2) i_or_branch_a (
.clks_i(clks_i[0+:NUM_INPUTS/2]),
.clk_o(branch_a)
);
clk_or_tree #(NUM_INPUTS/2 + NUM_INPUTS%2) i_or_branch_b (
.clks_i(clks_i[NUM_INPUTS-1:NUM_INPUTS/2]),
.clk_o(branch_b)
);
tc_clk_or2 i_clk_or2 (
.clk0_i(branch_a),
.clk1_i(branch_b),
.clk_o
);
end
endmodule
`begin_keywords "1800-2023"
module counter #(
parameter int unsigned WIDTH = 4,
parameter bit STICKY_OVERFLOW = 1'b0
)(
input logic clk_i,
input logic rst_ni,
input logic clear_i,
input logic en_i,
input logic load_i,
input logic down_i,
input logic [WIDTH-1:0] d_i,
output logic [WIDTH-1:0] q_o,
output logic overflow_o
);
delta_counter #(
.WIDTH (WIDTH),
.STICKY_OVERFLOW (STICKY_OVERFLOW)
) i_counter (
.clk_i,
.rst_ni,
.clear_i,
.en_i,
.load_i,
.down_i,
.delta_i({{WIDTH-1{1'b0}}, 1'b1}),
.d_i,
.q_o,
.overflow_o
);
endmodule
`begin_keywords "1800-2023"
module ecc_decode import ecc_pkg::*; #(
parameter int unsigned DataWidth = 64,
parameter type data_t = logic [DataWidth-1:0],
parameter type parity_t = logic [get_parity_width(DataWidth)-1:0],
parameter type code_word_t = logic [get_cw_width(DataWidth)-1:0],
parameter type encoded_data_t = struct packed {
logic parity;
code_word_t code_word;
}
) (
input encoded_data_t data_i,
output data_t data_o,
output parity_t syndrome_o,
output logic single_error_o,
output logic parity_error_o,
output logic double_error_o
);
logic parity;
data_t data_wo_parity;
parity_t syndrome;
logic syndrome_not_zero;
code_word_t correct_data;
assign parity = data_i.parity ^ (^data_i.code_word);
always_comb begin : calculate_syndrome
syndrome = 0;
for (int unsigned i = 0; i < unsigned'($bits(parity_t)); i++) begin
for (int unsigned j = 0; j < unsigned'($bits(code_word_t)); j++) begin
if (|(unsigned'(2**i) & (j + 1))) syndrome[i] = syndrome[i] ^ data_i.code_word[j];
end
end
end
assign syndrome_not_zero = |syndrome;
always_comb begin
correct_data = data_i.code_word;
if (syndrome_not_zero) begin
correct_data[syndrome - 1] = ~data_i.code_word[syndrome - 1];
end
end
assign single_error_o = parity & syndrome_not_zero;
assign parity_error_o = parity & ~syndrome_not_zero;
assign double_error_o = ~parity & syndrome_not_zero;
always_comb begin
automatic int unsigned idx;
data_wo_parity = '0;
idx = 0;
for (int unsigned i = 1; i < unsigned'($bits(code_word_t)) + 1; i++) begin
if (unsigned'(2**$clog2(i)) != i) begin
data_wo_parity[idx] = correct_data[i - 1];
idx++;
end
end
end
assign data_o = data_wo_parity;
endmodule
`begin_keywords "1800-2023"
module ecc_encode import ecc_pkg::*; #(
parameter int unsigned DataWidth = 64,
parameter type data_t = logic [DataWidth-1:0],
parameter type parity_t = logic [get_parity_width(DataWidth)-1:0],
parameter type code_word_t = logic [get_cw_width(DataWidth)-1:0],
parameter type encoded_data_t = struct packed {
logic parity;
code_word_t code_word;
}
) (
input data_t data_i,
output encoded_data_t data_o
);
parity_t parity_code_word;
code_word_t data, codeword;
always_comb begin : expand_data
automatic int unsigned idx;
data = '0;
idx = 0;
for (int unsigned i = 1; i < unsigned'($bits(code_word_t)) + 1; i++) begin
if (unsigned'(2**$clog2(i)) != i) begin
data[i - 1] = data_i[idx];
idx++;
end
end
end
always_comb begin : calculate_syndrome
parity_code_word = 0;
for (int unsigned i = 0; i < unsigned'($bits(parity_t)); i++) begin
for (int unsigned j = 1; j < unsigned'($bits(code_word_t)) + 1; j++) begin
if (|(unsigned'(2**i) & j)) parity_code_word[i] = parity_code_word[i] ^ data[j - 1];
end
end
end
always_comb begin : generate_codeword
codeword = data;
for (int unsigned i = 0; i < unsigned'($bits(parity_t)); i++) begin
codeword[2**i-1] = parity_code_word[i];
end
end
assign data_o.code_word = codeword;
assign data_o.parity = ^codeword;
endmodule
`begin_keywords "1800-2023"
module edge_detect (
input logic clk_i,
input logic rst_ni,
input logic d_i,
output logic re_o,
output logic fe_o
);
sync_wedge i_sync_wedge (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.en_i ( 1'b1 ),
.serial_i ( d_i ),
.r_edge_o ( re_o ),
.f_edge_o ( fe_o ),
.serial_o ( )
);
endmodule
`begin_keywords "1800-2023"
module lzc #(
parameter int unsigned WIDTH = 2,
parameter bit MODE = 1'b0,
parameter int unsigned CNT_WIDTH = cf_math_pkg::idx_width(WIDTH)
) (
input logic [WIDTH-1:0] in_i,
output logic [CNT_WIDTH-1:0] cnt_o,
output logic empty_o
);
initial begin
width_0: assert (WIDTH > 0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "width_0", "input must be at least one bit wide", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/lzc.sv", 36);
end
end
if (WIDTH <= 1) begin : gen_degenerate_lzc
assign cnt_o[0] = !in_i[0];
assign empty_o = !in_i[0];
end else begin : gen_lzc
localparam int unsigned NumLevels = $clog2(WIDTH);
logic [WIDTH-1:0][NumLevels-1:0] index_lut;
logic [2**NumLevels-1:0] sel_nodes /*verilator split_var*/;
logic [2**NumLevels-1:0][NumLevels-1:0] index_nodes /*verilator split_var*/;
logic [WIDTH-1:0] in_tmp;
if (MODE) begin : g_flip
always_comb begin : flip_vector
for (int unsigned i = 0; i < WIDTH; i++) begin
in_tmp[i] = in_i[WIDTH-1-i];
end
end
end else begin : g_no_flip
assign in_tmp = in_i;
end
for (genvar j = 0; unsigned'(j) < WIDTH; j++) begin : g_index_lut
assign index_lut[j] = (NumLevels)'(unsigned'(j));
end
for (genvar level = 0; unsigned'(level) < NumLevels; level++) begin : g_levels
if (unsigned'(level) == NumLevels - 1) begin : g_last_level
for (genvar k = 0; k < 2 ** level; k++) begin : g_level
if (unsigned'(k) * 2 < WIDTH - 1) begin : g_reduce
assign sel_nodes[2 ** level - 1 + k] = in_tmp[k * 2] | in_tmp[k * 2 + 1];
assign index_nodes[2 ** level - 1 + k] = (in_tmp[k * 2] == 1'b1)
? index_lut[k * 2] :
index_lut[k * 2 + 1];
end
if (unsigned'(k) * 2 == WIDTH - 1) begin : g_base
assign sel_nodes[2 ** level - 1 + k] = in_tmp[k * 2];
assign index_nodes[2 ** level - 1 + k] = index_lut[k * 2];
end
if (unsigned'(k) * 2 > WIDTH - 1) begin : g_out_of_range
assign sel_nodes[2 ** level - 1 + k] = 1'b0;
assign index_nodes[2 ** level - 1 + k] = '0;
end
end
end else begin : g_not_last_level
for (genvar l = 0; l < 2 ** level; l++) begin : g_level
assign sel_nodes[2 ** level - 1 + l] =
sel_nodes[2 ** (level + 1) - 1 + l * 2] | sel_nodes[2 ** (level + 1) - 1 + l * 2 + 1];
assign index_nodes[2 ** level - 1 + l] = (sel_nodes[2 ** (level + 1) - 1 + l * 2] == 1'b1)
? index_nodes[2 ** (level + 1) - 1 + l * 2] :
index_nodes[2 ** (level + 1) - 1 + l * 2 + 1];
end
end
end
assign cnt_o = NumLevels > unsigned'(0) ? index_nodes[0] : {($clog2(WIDTH)) {1'b0}};
assign empty_o = NumLevels > unsigned'(0) ? ~sel_nodes[0] : ~(|in_i);
end : gen_lzc
endmodule : lzc
`begin_keywords "1800-2023"
module max_counter #(
parameter int unsigned WIDTH = 4
) (
input logic clk_i,
input logic rst_ni,
input logic clear_i,
input logic clear_max_i,
input logic en_i,
input logic load_i,
input logic down_i,
input logic [WIDTH-1:0] delta_i,
input logic [WIDTH-1:0] d_i,
output logic [WIDTH-1:0] q_o,
output logic [WIDTH-1:0] max_o,
output logic overflow_o,
output logic overflow_max_o
);
logic [WIDTH-1:0] max_d, max_q;
logic overflow_max_d, overflow_max_q;
delta_counter #(
.WIDTH (WIDTH),
.STICKY_OVERFLOW (1'b1)
) i_counter (
.clk_i,
.rst_ni,
.clear_i,
.en_i,
.load_i,
.down_i,
.delta_i,
.d_i,
.q_o,
.overflow_o
);
always_comb begin
max_d = max_q;
max_o = max_q;
overflow_max_d = overflow_max_q;
if (clear_max_i) begin
max_d = '0;
overflow_max_d = 1'b0;
end else if (q_o > max_q) begin
max_d = q_o;
max_o = q_o;
if (overflow_o) begin
overflow_max_d = 1'b1;
end
end
end
assign overflow_max_o = overflow_max_q;
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
max_q <= '0;
overflow_max_q <= 1'b0;
end else begin
max_q <= max_d;
overflow_max_q <= overflow_max_d;
end
end
endmodule
`begin_keywords "1800-2023"
module rstgen (
input logic clk_i,
input logic rst_ni,
input logic test_mode_i,
output logic rst_no,
output logic init_no
);
rstgen_bypass i_rstgen_bypass (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.rst_test_mode_ni ( rst_ni ),
.test_mode_i ( test_mode_i ),
.rst_no ( rst_no ),
.init_no ( init_no )
);
endmodule
`begin_keywords "1800-2023"
module spill_register #(
parameter type T = logic,
parameter bit Bypass = 1'b0
) (
input logic clk_i ,
input logic rst_ni ,
input logic valid_i ,
output logic ready_o ,
input T data_i ,
output logic valid_o ,
input logic ready_i ,
output T data_o
);
spill_register_flushable #(
.T(T),
.Bypass(Bypass)
) spill_register_flushable_i (
.clk_i,
.rst_ni,
.valid_i,
.flush_i(1'b0),
.ready_o,
.data_i,
.valid_o,
.ready_i,
.data_o
);
endmodule
`begin_keywords "1800-2023"
module stream_delay #(
parameter bit StallRandom = 0,
parameter int FixedDelay = 1,
parameter type payload_t = logic,
parameter logic [15:0] Seed = '0
)(
input logic clk_i,
input logic rst_ni,
input payload_t payload_i,
output logic ready_o,
input logic valid_i,
output payload_t payload_o,
input logic ready_i,
output logic valid_o
);
if (FixedDelay == 0 && !StallRandom) begin : gen_pass_through
assign ready_o = ready_i;
assign valid_o = valid_i;
assign payload_o = payload_i;
end else begin : gen_delay
localparam int unsigned CounterBits = 32;
typedef enum logic [1:0] {
Idle, Valid, Ready
} state_e;
state_e state_d, state_q;
logic load;
logic [CounterBits-1:0] count_out;
logic en;
logic [CounterBits-1:0] counter_load;
assign payload_o = payload_i;
always_comb begin
state_d = state_q;
valid_o = 1'b0;
ready_o = 1'b0;
load = 1'b0;
en = 1'b0;
unique case (state_q)
Idle: begin
if (valid_i) begin
load = 1'b1;
state_d = Valid;
if (FixedDelay == 1 || (StallRandom && counter_load == 1)) begin
state_d = Ready;
end
if (StallRandom && counter_load == 0) begin
valid_o = 1'b1;
ready_o = ready_i;
if (ready_i) state_d = Idle;
else state_d = Ready;
end
end
end
Valid: begin
en = 1'b1;
if (count_out == 0) begin
state_d = Ready;
end
end
Ready: begin
valid_o = 1'b1;
ready_o = ready_i;
if (ready_i) state_d = Idle;
end
default : ;
endcase
end
if (StallRandom) begin : gen_random_stall
lfsr_16bit #(
.WIDTH ( 16 ),
.SEED ( Seed )
) i_lfsr_16bit (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.en_i ( load ),
.refill_way_oh ( ),
.refill_way_bin ( counter_load )
);
end else begin : gen_fixed_delay
assign counter_load = FixedDelay;
end
counter #(
.WIDTH ( CounterBits )
) i_counter (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.clear_i ( 1'b0 ),
.en_i ( en ),
.load_i ( load ),
.down_i ( 1'b1 ),
.d_i ( counter_load ),
.q_o ( count_out ),
.overflow_o ( )
);
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
state_q <= Idle;
end else begin
state_q <= state_d;
end
end
end
endmodule
`begin_keywords "1800-2023"
module stream_fifo #(
parameter bit FALL_THROUGH = 1'b0,
parameter int unsigned DATA_WIDTH = 32,
parameter int unsigned DEPTH = 8,
parameter type T = logic [DATA_WIDTH-1:0],
parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1
) (
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input logic testmode_i,
output logic [ADDR_DEPTH-1:0] usage_o,
input T data_i,
input logic valid_i,
output logic ready_o,
output T data_o,
output logic valid_o,
input logic ready_i
);
logic push, pop;
logic empty, full;
assign push = valid_i & ~full;
assign pop = ready_i & ~empty;
assign ready_o = ~full;
assign valid_o = ~empty;
fifo_v3 #(
.FALL_THROUGH (FALL_THROUGH),
.DATA_WIDTH (DATA_WIDTH),
.DEPTH (DEPTH),
.dtype(T)
) fifo_i (
.clk_i,
.rst_ni,
.flush_i,
.testmode_i,
.full_o (full),
.empty_o (empty),
.usage_o,
.data_i,
.push_i (push),
.data_o,
.pop_i (pop)
);
endmodule
`begin_keywords "1800-2023"
module stream_fork_dynamic #(
parameter int unsigned N_OUP = 32'd0
) (
input logic clk_i,
input logic rst_ni,
input logic valid_i,
output logic ready_o,
input logic [N_OUP-1:0] sel_i,
input logic sel_valid_i,
output logic sel_ready_o,
output logic [N_OUP-1:0] valid_o,
input logic [N_OUP-1:0] ready_i
);
logic int_inp_valid, int_inp_ready;
logic [N_OUP-1:0] int_oup_valid, int_oup_ready;
for (genvar i = 0; i < N_OUP; i++) begin : gen_oups
always_comb begin
valid_o[i] = 1'b0;
int_oup_ready[i] = 1'b0;
if (sel_valid_i) begin
if (sel_i[i]) begin
valid_o[i] = int_oup_valid[i];
int_oup_ready[i] = ready_i[i];
end else begin
int_oup_ready[i] = 1'b1;
end
end
end
end
always_comb begin
int_inp_valid = 1'b0;
ready_o = 1'b0;
sel_ready_o = 1'b0;
if (sel_valid_i) begin
int_inp_valid = valid_i;
ready_o = int_inp_ready;
sel_ready_o = int_inp_ready;
end
end
stream_fork #(
.N_OUP ( N_OUP )
) i_fork (
.clk_i,
.rst_ni,
.valid_i ( int_inp_valid ),
.ready_o ( int_inp_ready ),
.valid_o ( int_oup_valid ),
.ready_i ( int_oup_ready )
);
initial begin
n_oup_0: assert (N_OUP >= 1)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "n_oup_0", "N_OUP must be at least 1!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_fork_dynamic.sv", 91);
end
end
endmodule
`begin_keywords "1800-2023"
module stream_join #(
parameter int unsigned N_INP = 32'd0
) (
input logic [N_INP-1:0] inp_valid_i,
output logic [N_INP-1:0] inp_ready_o,
output logic oup_valid_o,
input logic oup_ready_i
);
stream_join_dynamic #(
.N_INP(N_INP)
) i_stream_join_dynamic (
.inp_valid_i(inp_valid_i),
.inp_ready_o(inp_ready_o),
.sel_i ({N_INP{1'b1}}),
.oup_valid_o(oup_valid_o),
.oup_ready_i(oup_ready_i)
);
endmodule
`begin_keywords "1800-2023"
module cdc_reset_ctrlr
import cdc_reset_ctrlr_pkg::*;
#(
parameter int unsigned SYNC_STAGES = 2,
parameter logic CLEAR_ON_ASYNC_RESET = 1'b1
)(
input logic a_clk_i,
input logic a_rst_ni,
input logic a_clear_i,
output logic a_clear_o,
input logic a_clear_ack_i,
output logic a_isolate_o,
input logic a_isolate_ack_i,
input logic b_clk_i,
input logic b_rst_ni,
input logic b_clear_i,
output logic b_clear_o,
input logic b_clear_ack_i,
output logic b_isolate_o,
input logic b_isolate_ack_i
);
(* dont_touch = "true" *)
logic async_a2b_req, async_b2a_ack;
(* dont_touch = "true" *)
clear_seq_phase_e async_a2b_next_phase;
(* dont_touch = "true" *)
logic async_b2a_req, async_a2b_ack;
(* dont_touch = "true" *)
clear_seq_phase_e async_b2a_next_phase;
cdc_reset_ctrlr_half #(
.SYNC_STAGES ( SYNC_STAGES ),
.CLEAR_ON_ASYNC_RESET ( CLEAR_ON_ASYNC_RESET )
) i_cdc_reset_ctrlr_half_a (
.clk_i ( a_clk_i ),
.rst_ni ( a_rst_ni ),
.clear_i ( a_clear_i ),
.clear_o ( a_clear_o ),
.clear_ack_i ( a_clear_ack_i ),
.isolate_o ( a_isolate_o ),
.isolate_ack_i ( a_isolate_ack_i ),
(* async *) .async_next_phase_o ( async_a2b_next_phase ),
(* async *) .async_req_o ( async_a2b_req ),
(* async *) .async_ack_i ( async_b2a_ack ),
(* async *) .async_next_phase_i ( async_b2a_next_phase ),
(* async *) .async_req_i ( async_b2a_req ),
(* async *) .async_ack_o ( async_a2b_ack )
);
cdc_reset_ctrlr_half #(
.SYNC_STAGES ( SYNC_STAGES ),
.CLEAR_ON_ASYNC_RESET ( CLEAR_ON_ASYNC_RESET )
) i_cdc_reset_ctrlr_half_b (
.clk_i ( b_clk_i ),
.rst_ni ( b_rst_ni ),
.clear_i ( b_clear_i ),
.clear_o ( b_clear_o ),
.clear_ack_i ( b_clear_ack_i ),
.isolate_o ( b_isolate_o ),
.isolate_ack_i ( b_isolate_ack_i ),
(* async *) .async_next_phase_o ( async_b2a_next_phase ),
(* async *) .async_req_o ( async_b2a_req ),
(* async *) .async_ack_i ( async_a2b_ack ),
(* async *) .async_next_phase_i ( async_a2b_next_phase ),
(* async *) .async_req_i ( async_a2b_req ),
(* async *) .async_ack_o ( async_b2a_ack )
);
endmodule
module cdc_reset_ctrlr_half
import cdc_reset_ctrlr_pkg::*;
#(
parameter int unsigned SYNC_STAGES = 2,
parameter logic CLEAR_ON_ASYNC_RESET = 1'b1
)(
input logic clk_i,
input logic rst_ni,
input logic clear_i,
output logic isolate_o,
input logic isolate_ack_i,
output logic clear_o,
input logic clear_ack_i,
output clear_seq_phase_e async_next_phase_o,
output logic async_req_o,
input logic async_ack_i,
input clear_seq_phase_e async_next_phase_i,
input logic async_req_i,
output logic async_ack_o
);
typedef enum logic[3:0] {
IDLE,
ISOLATE,
WAIT_ISOLATE_PHASE_ACK,
WAIT_ISOLATE_ACK,
CLEAR,
WAIT_CLEAR_PHASE_ACK,
WAIT_CLEAR_ACK,
POST_CLEAR,
FINISHED
} initiator_state_e;
initiator_state_e initiator_state_d, initiator_state_q;
clear_seq_phase_e initiator_clear_seq_phase;
logic initiator_phase_transition_req;
logic initiator_phase_transition_ack;
logic initiator_isolate_out;
logic initiator_clear_out;
always_comb begin
initiator_state_d = initiator_state_q;
initiator_phase_transition_req = 1'b0;
initiator_isolate_out = 1'b0;
initiator_clear_out = 1'b0;
initiator_clear_seq_phase = CLEAR_PHASE_IDLE;
case (initiator_state_q)
IDLE: begin
if (clear_i) begin
initiator_state_d = ISOLATE;
end
end
ISOLATE: begin
initiator_phase_transition_req = 1'b1;
initiator_clear_seq_phase = CLEAR_PHASE_ISOLATE;
initiator_isolate_out = 1'b1;
initiator_clear_out = 1'b0;
if (initiator_phase_transition_ack && isolate_ack_i) begin
initiator_state_d = CLEAR;
end else if (initiator_phase_transition_ack) begin
initiator_state_d = WAIT_ISOLATE_ACK;
end else if (isolate_ack_i) begin
initiator_state_d = WAIT_ISOLATE_PHASE_ACK;
end
end
WAIT_ISOLATE_ACK: begin
initiator_isolate_out = 1'b1;
initiator_clear_out = 1'b0;
initiator_clear_seq_phase = CLEAR_PHASE_ISOLATE;
if (isolate_ack_i) begin
initiator_state_d = CLEAR;
end
end
WAIT_ISOLATE_PHASE_ACK: begin
initiator_phase_transition_req = 1'b1;
initiator_clear_seq_phase = CLEAR_PHASE_ISOLATE;
initiator_isolate_out = 1'b1;
initiator_clear_out = 1'b0;
if (initiator_phase_transition_ack) begin
initiator_state_d = CLEAR;
end
end
CLEAR: begin
initiator_isolate_out = 1'b1;
initiator_clear_out = 1'b1;
initiator_phase_transition_req = 1'b1;
initiator_clear_seq_phase = CLEAR_PHASE_CLEAR;
if (initiator_phase_transition_ack && clear_ack_i) begin
initiator_state_d = POST_CLEAR;
end else if (initiator_phase_transition_ack) begin
initiator_state_d = WAIT_CLEAR_ACK;
end else if (clear_ack_i) begin
initiator_state_d = WAIT_CLEAR_PHASE_ACK;
end
end
WAIT_CLEAR_ACK: begin
initiator_isolate_out = 1'b1;
initiator_clear_out = 1'b1;
initiator_clear_seq_phase = CLEAR_PHASE_CLEAR;
if (clear_ack_i) begin
initiator_state_d = POST_CLEAR;
end
end
WAIT_CLEAR_PHASE_ACK: begin
initiator_phase_transition_req = 1'b1;
initiator_clear_seq_phase = CLEAR_PHASE_CLEAR;
initiator_isolate_out = 1'b1;
initiator_clear_out = 1'b1;
if (initiator_phase_transition_ack) begin
initiator_state_d = POST_CLEAR;
end
end
POST_CLEAR: begin
initiator_isolate_out = 1'b1;
initiator_clear_out = 1'b0;
initiator_phase_transition_req = 1'b1;
initiator_clear_seq_phase = CLEAR_PHASE_POST_CLEAR;
if (initiator_phase_transition_ack) begin
initiator_state_d = FINISHED;
end
end
FINISHED: begin
initiator_isolate_out = 1'b1;
initiator_clear_out = 1'b0;
initiator_phase_transition_req = 1'b1;
initiator_clear_seq_phase = CLEAR_PHASE_IDLE;
if (initiator_phase_transition_ack) begin
initiator_state_d = IDLE;
end
end
default: begin
initiator_state_d = ISOLATE;
end
endcase
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
if (CLEAR_ON_ASYNC_RESET) begin
initiator_state_q <= ISOLATE;
end else begin
initiator_state_q <= IDLE;
end
end else begin
initiator_state_q <= initiator_state_d;
end
end
cdc_4phase_src #(
.T(clear_seq_phase_e),
.SYNC_STAGES(2),
.DECOUPLED(0),
.SEND_RESET_MSG(CLEAR_ON_ASYNC_RESET),
.RESET_MSG(CLEAR_PHASE_ISOLATE)
) i_state_transition_cdc_src(
.clk_i,
.rst_ni,
.data_i(initiator_clear_seq_phase),
.valid_i(initiator_phase_transition_req),
.ready_o(initiator_phase_transition_ack),
.async_req_o,
.async_ack_i,
.async_data_o(async_next_phase_o)
);
clear_seq_phase_e receiver_phase_q;
clear_seq_phase_e receiver_next_phase;
logic receiver_phase_req, receiver_phase_ack;
logic receiver_isolate_out;
logic receiver_clear_out;
cdc_4phase_dst #(
.T(clear_seq_phase_e),
.SYNC_STAGES(2),
.DECOUPLED(0)
) i_state_transition_cdc_dst(
.clk_i,
.rst_ni,
.data_o(receiver_next_phase),
.valid_o(receiver_phase_req),
.ready_i(receiver_phase_ack),
.async_req_i,
.async_ack_o,
.async_data_i(async_next_phase_i)
);
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
receiver_phase_q <= CLEAR_PHASE_IDLE;
end else if (receiver_phase_req && receiver_phase_ack) begin
receiver_phase_q <= receiver_next_phase;
end
end
always_comb begin
receiver_isolate_out = 1'b0;
receiver_clear_out = 1'b0;
receiver_phase_ack = 1'b0;
if (receiver_phase_req) begin
case (receiver_next_phase)
CLEAR_PHASE_IDLE: begin
receiver_clear_out = 1'b0;
receiver_isolate_out = 1'b0;
receiver_phase_ack = 1'b1;
end
CLEAR_PHASE_ISOLATE: begin
receiver_clear_out = 1'b0;
receiver_isolate_out = 1'b1;
receiver_phase_ack = isolate_ack_i;
end
CLEAR_PHASE_CLEAR: begin
receiver_clear_out = 1'b1;
receiver_isolate_out = 1'b1;
receiver_phase_ack = clear_ack_i;
end
CLEAR_PHASE_POST_CLEAR: begin
receiver_clear_out = 1'b0;
receiver_isolate_out = 1'b1;
receiver_phase_ack = 1'b1;
end
default: begin
receiver_clear_out = 1'b0;
receiver_isolate_out = 1'b0;
receiver_phase_ack = 1'b0;
end
endcase
end else begin
case (receiver_phase_q)
CLEAR_PHASE_IDLE: begin
receiver_clear_out = 1'b0;
receiver_isolate_out = 1'b0;
end
CLEAR_PHASE_ISOLATE: begin
receiver_clear_out = 1'b0;
receiver_isolate_out = 1'b1;
end
CLEAR_PHASE_CLEAR: begin
receiver_clear_out = 1'b1;
receiver_isolate_out = 1'b1;
end
CLEAR_PHASE_POST_CLEAR: begin
receiver_clear_out = 1'b0;
receiver_isolate_out = 1'b1;
end
default: begin
receiver_clear_out = 1'b0;
receiver_isolate_out = 1'b0;
receiver_phase_ack = 1'b0;
end
endcase
end
end
assign clear_o = initiator_clear_out || receiver_clear_out;
assign isolate_o = initiator_isolate_out || receiver_isolate_out;
endmodule : cdc_reset_ctrlr_half
`begin_keywords "1800-2023"
(* no_ungroup *)
(* no_boundary_optimization *)
module cdc_fifo_gray #(
parameter int unsigned WIDTH = 1,
parameter type T = logic [WIDTH-1:0],
parameter int LOG_DEPTH = 3,
parameter int SYNC_STAGES = 2
) (
input logic src_rst_ni,
input logic src_clk_i,
input T src_data_i,
input logic src_valid_i,
output logic src_ready_o,
input logic dst_rst_ni,
input logic dst_clk_i,
output T dst_data_o,
output logic dst_valid_o,
input logic dst_ready_i
);
T [2**LOG_DEPTH-1:0] async_data;
logic [LOG_DEPTH:0] async_wptr;
logic [LOG_DEPTH:0] async_rptr;
cdc_fifo_gray_src #(
.T ( T ),
.LOG_DEPTH ( LOG_DEPTH )
) i_src (
.src_rst_ni,
.src_clk_i,
.src_data_i,
.src_valid_i,
.src_ready_o,
(* async *) .async_data_o ( async_data ),
(* async *) .async_wptr_o ( async_wptr ),
(* async *) .async_rptr_i ( async_rptr )
);
cdc_fifo_gray_dst #(
.T ( T ),
.LOG_DEPTH ( LOG_DEPTH )
) i_dst (
.dst_rst_ni,
.dst_clk_i,
.dst_data_o,
.dst_valid_o,
.dst_ready_i,
(* async *) .async_data_i ( async_data ),
(* async *) .async_wptr_i ( async_wptr ),
(* async *) .async_rptr_o ( async_rptr )
);
initial begin
log_depth_0: assert (LOG_DEPTH > 0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "log_depth_0", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_fifo_gray.sv", 162);
end
end
initial begin
sync_stages_gt_2: assert (SYNC_STAGES >= 2)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "sync_stages_gt_2", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_fifo_gray.sv", 163);
end
end
endmodule
(* no_ungroup *)
(* no_boundary_optimization *)
module cdc_fifo_gray_src #(
parameter type T = logic,
parameter int LOG_DEPTH = 3,
parameter int SYNC_STAGES = 2
)(
input logic src_rst_ni,
input logic src_clk_i,
input T src_data_i,
input logic src_valid_i,
output logic src_ready_o,
output T [2**LOG_DEPTH-1:0] async_data_o,
output logic [LOG_DEPTH:0] async_wptr_o,
input logic [LOG_DEPTH:0] async_rptr_i
);
localparam int PtrWidth = LOG_DEPTH+1;
localparam logic [PtrWidth-1:0] PtrFull = (1 << LOG_DEPTH);
T [2**LOG_DEPTH-1:0] data_q, data_d;
logic [PtrWidth-1:0] wptr_q, wptr_d, wptr_bin, wptr_next, rptr, rptr_bin;
assign async_data_o = data_q;
always_comb begin
data_d = data_q;
data_d[wptr_bin[LOG_DEPTH-1:0]] = src_data_i;
end
always_ff @(posedge (src_clk_i) or negedge (src_rst_ni)) begin
if (!src_rst_ni) begin
data_q <= ('0);
end else begin
if (src_valid_i & src_ready_o) begin
data_q <= (data_d);
end
end
end
for (genvar i = 0; i < PtrWidth; i++) begin : gen_sync
sync #(.STAGES(SYNC_STAGES)) i_sync (
.clk_i ( src_clk_i ),
.rst_ni ( src_rst_ni ),
.serial_i ( async_rptr_i[i] ),
.serial_o ( rptr[i] )
);
end
gray_to_binary #(PtrWidth) i_rptr_g2b (.A(rptr), .Z(rptr_bin));
assign wptr_next = wptr_bin+1;
gray_to_binary #(PtrWidth) i_wptr_g2b (.A(wptr_q), .Z(wptr_bin));
binary_to_gray #(PtrWidth) i_wptr_b2g (.A(wptr_next), .Z(wptr_d));
always_ff @(posedge (src_clk_i) or negedge (src_rst_ni)) begin
if (!src_rst_ni) begin
wptr_q <= ('0);
end else begin
if (src_valid_i & src_ready_o) begin
wptr_q <= (wptr_d);
end
end
end
assign async_wptr_o = wptr_q;
assign src_ready_o = ((wptr_bin ^ rptr_bin) != PtrFull);
endmodule
(* no_ungroup *)
(* no_boundary_optimization *)
module cdc_fifo_gray_dst #(
parameter type T = logic,
parameter int LOG_DEPTH = 3,
parameter int SYNC_STAGES = 2
)(
input logic dst_rst_ni,
input logic dst_clk_i,
output T dst_data_o,
output logic dst_valid_o,
input logic dst_ready_i,
input T [2**LOG_DEPTH-1:0] async_data_i,
input logic [LOG_DEPTH:0] async_wptr_i,
output logic [LOG_DEPTH:0] async_rptr_o
);
localparam int PtrWidth = LOG_DEPTH+1;
localparam logic [PtrWidth-1:0] PtrEmpty = '0;
T dst_data;
logic [PtrWidth-1:0] rptr_q, rptr_d, rptr_bin, rptr_bin_d, rptr_next, wptr, wptr_bin;
logic dst_valid, dst_ready;
assign dst_data = async_data_i[rptr_bin[LOG_DEPTH-1:0]];
assign rptr_next = rptr_bin+1;
gray_to_binary #(PtrWidth) i_rptr_g2b (.A(rptr_q), .Z(rptr_bin));
binary_to_gray #(PtrWidth) i_rptr_b2g (.A(rptr_next), .Z(rptr_d));
always_ff @(posedge (dst_clk_i) or negedge (dst_rst_ni)) begin
if (!dst_rst_ni) begin
rptr_q <= ('0);
end else begin
if (dst_valid & dst_ready) begin
rptr_q <= (rptr_d);
end
end
end
assign async_rptr_o = rptr_q;
for (genvar i = 0; i < PtrWidth; i++) begin : gen_sync
sync #(.STAGES(SYNC_STAGES)) i_sync (
.clk_i ( dst_clk_i ),
.rst_ni ( dst_rst_ni ),
.serial_i ( async_wptr_i[i] ),
.serial_o ( wptr[i] )
);
end
gray_to_binary #(PtrWidth) i_wptr_g2b (.A(wptr), .Z(wptr_bin));
assign dst_valid = ((wptr_bin ^ rptr_bin) != PtrEmpty);
spill_register #(
.T ( T )
) i_spill_register (
.clk_i ( dst_clk_i ),
.rst_ni ( dst_rst_ni ),
.valid_i ( dst_valid ),
.ready_o ( dst_ready ),
.data_i ( dst_data ),
.valid_o ( dst_valid_o ),
.ready_i ( dst_ready_i ),
.data_o ( dst_data_o )
);
endmodule
`begin_keywords "1800-2023"
module fall_through_register #(
parameter type T = logic
) (
input logic clk_i,
input logic rst_ni,
input logic clr_i,
input logic testmode_i,
input logic valid_i,
output logic ready_o,
input T data_i,
output logic valid_o,
input logic ready_i,
output T data_o
);
logic fifo_empty,
fifo_full;
fifo_v3 #(
.FALL_THROUGH (1'b1),
.DEPTH (1),
.dtype (T)
) i_fifo (
.clk_i (clk_i),
.rst_ni (rst_ni),
.flush_i (clr_i),
.testmode_i (testmode_i),
.full_o (fifo_full),
.empty_o (fifo_empty),
.usage_o (),
.data_i (data_i),
.push_i (valid_i & ~fifo_full),
.data_o (data_o),
.pop_i (ready_i & ~fifo_empty)
);
assign ready_o = ~fifo_full;
assign valid_o = ~fifo_empty;
endmodule
`begin_keywords "1800-2023"
module id_queue #(
parameter int ID_WIDTH = 0,
parameter int CAPACITY = 0,
parameter bit FULL_BW = 0,
parameter bit CUT_OUP_POP_INP_GNT = 0,
parameter int NUM_CMP_PORTS = 1,
parameter type data_t = logic[31:0],
localparam type id_t = logic[ID_WIDTH-1:0]
) (
input logic clk_i,
input logic rst_ni,
input id_t inp_id_i,
input data_t inp_data_i,
input logic inp_req_i,
output logic inp_gnt_o,
input data_t [NUM_CMP_PORTS-1:0] exists_data_i,
input data_t [NUM_CMP_PORTS-1:0] exists_mask_i,
input logic [NUM_CMP_PORTS-1:0] exists_req_i,
output logic [NUM_CMP_PORTS-1:0] exists_o,
output logic [NUM_CMP_PORTS-1:0] exists_gnt_o,
input id_t oup_id_i,
input logic oup_pop_i,
input logic oup_req_i,
output data_t oup_data_o,
output logic oup_data_valid_o,
output logic oup_gnt_o,
output logic full_o,
output logic empty_o
);
localparam int NIds = 2**ID_WIDTH;
localparam int HtCapacity = (NIds <= CAPACITY) ? NIds : CAPACITY;
localparam int unsigned HtIdxWidth = cf_math_pkg::idx_width(HtCapacity);
localparam int unsigned LdIdxWidth = cf_math_pkg::idx_width(CAPACITY);
typedef logic [HtIdxWidth-1:0] ht_idx_t;
typedef logic [LdIdxWidth-1:0] ld_idx_t;
typedef struct packed {
id_t id;
ld_idx_t head,
tail;
logic free;
} head_tail_t;
typedef struct packed {
data_t data;
ld_idx_t next;
logic free;
} linked_data_t;
head_tail_t [HtCapacity-1:0] head_tail_d, head_tail_q;
linked_data_t [CAPACITY-1:0] linked_data_d, linked_data_q;
logic full,
match_in_id_valid,
match_out_id_valid,
no_in_id_match,
no_out_id_match;
logic [HtCapacity-1:0] head_tail_free,
idx_matches_in_id,
idx_matches_out_id;
logic [NUM_CMP_PORTS-1:0][CAPACITY-1:0] exists_match;
logic [CAPACITY-1:0] linked_data_free;
id_t match_in_id, match_out_id;
ht_idx_t head_tail_free_idx,
match_in_idx,
match_out_idx;
ld_idx_t linked_data_free_idx,
oup_data_free_idx;
logic oup_data_popped,
oup_ht_popped;
for (genvar i = 0; i < HtCapacity; i++) begin: gen_idx_match
assign idx_matches_in_id[i] = match_in_id_valid && (head_tail_q[i].id == match_in_id) &&
!head_tail_q[i].free;
assign idx_matches_out_id[i] = match_out_id_valid && (head_tail_q[i].id == match_out_id) &&
!head_tail_q[i].free;
end
assign no_in_id_match = !(|idx_matches_in_id);
assign no_out_id_match = !(|idx_matches_out_id);
onehot_to_bin #(
.ONEHOT_WIDTH ( HtCapacity )
) i_id_ohb_in (
.onehot ( idx_matches_in_id ),
.bin ( match_in_idx )
);
onehot_to_bin #(
.ONEHOT_WIDTH ( HtCapacity )
) i_id_ohb_out (
.onehot ( idx_matches_out_id ),
.bin ( match_out_idx )
);
for (genvar i = 0; i < HtCapacity; i++) begin: gen_head_tail_free
assign head_tail_free[i] = head_tail_q[i].free;
end
lzc #(
.WIDTH ( HtCapacity ),
.MODE ( 0 )
) i_ht_free_lzc (
.in_i ( head_tail_free ),
.cnt_o ( head_tail_free_idx ),
.empty_o ( )
);
for (genvar i = 0; i < CAPACITY; i++) begin: gen_linked_data_free
assign linked_data_free[i] = linked_data_q[i].free;
end
lzc #(
.WIDTH ( CAPACITY ),
.MODE ( 0 )
) i_ld_free_lzc (
.in_i ( linked_data_free ),
.cnt_o ( linked_data_free_idx ),
.empty_o ( )
);
assign full = !(|linked_data_free);
assign empty = &linked_data_free;
assign oup_data_free_idx = head_tail_q[match_out_idx].head;
assign inp_gnt_o = ~full || (oup_data_popped && FULL_BW && ~CUT_OUP_POP_INP_GNT);
always_comb begin
match_in_id = '0;
match_out_id = '0;
match_in_id_valid = 1'b0;
match_out_id_valid = 1'b0;
head_tail_d = head_tail_q;
linked_data_d = linked_data_q;
oup_gnt_o = 1'b0;
oup_data_o = data_t'('0);
oup_data_valid_o = 1'b0;
oup_data_popped = 1'b0;
oup_ht_popped = 1'b0;
if (!FULL_BW) begin
if (inp_req_i && !full) begin
match_in_id = inp_id_i;
match_in_id_valid = 1'b1;
if (no_in_id_match) begin
head_tail_d[head_tail_free_idx] = '{
id: inp_id_i,
head: linked_data_free_idx,
tail: linked_data_free_idx,
free: 1'b0
};
end else begin
linked_data_d[head_tail_q[match_in_idx].tail].next = linked_data_free_idx;
head_tail_d[match_in_idx].tail = linked_data_free_idx;
end
linked_data_d[linked_data_free_idx] = '{
data: inp_data_i,
next: '0,
free: 1'b0
};
end else if (oup_req_i) begin
match_in_id = oup_id_i;
match_in_id_valid = 1'b1;
if (!no_in_id_match) begin
oup_data_o = data_t'(linked_data_q[head_tail_q[match_in_idx].head].data);
oup_data_valid_o = 1'b1;
if (oup_pop_i) begin
linked_data_d[head_tail_q[match_in_idx].head] = '0;
linked_data_d[head_tail_q[match_in_idx].head].free = 1'b1;
if (head_tail_q[match_in_idx].head == head_tail_q[match_in_idx].tail) begin
head_tail_d[match_in_idx] = '{free: 1'b1, default: '0};
end else begin
head_tail_d[match_in_idx].head =
linked_data_q[head_tail_q[match_in_idx].head].next;
end
end
end
oup_gnt_o = 1'b1;
end
end else begin
if (oup_req_i) begin
match_out_id = oup_id_i;
match_out_id_valid = 1'b1;
if (!no_out_id_match) begin
oup_data_o = data_t'(linked_data_q[head_tail_q[match_out_idx].head].data);
oup_data_valid_o = 1'b1;
if (oup_pop_i) begin
oup_data_popped = 1'b1;
linked_data_d[head_tail_q[match_out_idx].head] = '0;
linked_data_d[head_tail_q[match_out_idx].head].free = 1'b1;
if (head_tail_q[match_out_idx].head
== head_tail_q[match_out_idx].tail) begin
oup_ht_popped = 1'b1;
head_tail_d[match_out_idx] = '{free: 1'b1, default: '0};
end else begin
head_tail_d[match_out_idx].head =
linked_data_q[head_tail_q[match_out_idx].head].next;
end
end
end
oup_gnt_o = 1'b1;
end
if (inp_req_i && inp_gnt_o) begin
match_in_id = inp_id_i;
match_in_id_valid = 1'b1;
if (oup_ht_popped && (oup_id_i==inp_id_i)) begin
head_tail_d[match_out_idx] = '{
id: inp_id_i,
head: oup_data_free_idx,
tail: oup_data_free_idx,
free: 1'b0
};
linked_data_d[oup_data_free_idx] = '{
data: inp_data_i,
next: '0,
free: 1'b0
};
end else if (no_in_id_match) begin
if (oup_ht_popped) begin
head_tail_d[match_out_idx] = '{
id: inp_id_i,
head: oup_data_free_idx,
tail: oup_data_free_idx,
free: 1'b0
};
linked_data_d[oup_data_free_idx] = '{
data: inp_data_i,
next: '0,
free: 1'b0
};
end else begin
if (oup_data_popped) begin
head_tail_d[head_tail_free_idx] = '{
id: inp_id_i,
head: oup_data_free_idx,
tail: oup_data_free_idx,
free: 1'b0
};
linked_data_d[oup_data_free_idx] = '{
data: inp_data_i,
next: '0,
free: 1'b0
};
end else begin
head_tail_d[head_tail_free_idx] = '{
id: inp_id_i,
head: linked_data_free_idx,
tail: linked_data_free_idx,
free: 1'b0
};
linked_data_d[linked_data_free_idx] = '{
data: inp_data_i,
next: '0,
free: 1'b0
};
end
end
end else begin
if (oup_data_popped) begin
linked_data_d[head_tail_q[match_in_idx].tail].next = oup_data_free_idx;
head_tail_d[match_in_idx].tail = oup_data_free_idx;
linked_data_d[oup_data_free_idx] = '{
data: inp_data_i,
next: '0,
free: 1'b0
};
end else begin
linked_data_d[head_tail_q[match_in_idx].tail].next = linked_data_free_idx;
head_tail_d[match_in_idx].tail = linked_data_free_idx;
linked_data_d[linked_data_free_idx] = '{
data: inp_data_i,
next: '0,
free: 1'b0
};
end
end
end
end
end
for (genvar k = 0; k < NUM_CMP_PORTS; k++) begin: gen_lookup_port
for (genvar i = 0; i < CAPACITY; i++) begin: gen_lookup
assign exists_match[k][i] = ~linked_data_q[i].free &
((linked_data_q[i].data & exists_mask_i[k]) ==
(exists_data_i[k] & exists_mask_i[k]));
end
always_comb begin
exists_gnt_o[k] = 1'b0;
exists_o[k] = '0;
if (exists_req_i[k]) begin
exists_gnt_o[k] = 1'b1;
exists_o[k] = (|exists_match[k]);
end
end
end
for (genvar i = 0; i < HtCapacity; i++) begin: gen_ht_ffs
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
head_tail_q[i] <= '{free: 1'b1, default: '0};
end else begin
head_tail_q[i] <= head_tail_d[i];
end
end
end
for (genvar i = 0; i < CAPACITY; i++) begin: gen_data_ffs
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
linked_data_q[i] <= '0;
linked_data_q[i].free <= 1'b1;
end else begin
linked_data_q[i] <= linked_data_d[i];
end
end
end
assign full_o = full;
assign empty_o = empty;
initial begin
id_width_0: assert (ID_WIDTH >= 1)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "id_width_0", "The ID must at least be one bit wide!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/id_queue.sv", 414);
end
end
initial begin
capacity_0: assert (CAPACITY >= 1)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "capacity_0", "The queue must have capacity of at least one entry!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/id_queue.sv", 415);
end
end
endmodule
`begin_keywords "1800-2023"
module stream_to_mem #(
parameter type mem_req_t = logic,
parameter type mem_resp_t = logic,
parameter int unsigned BufDepth = 32'd1
) (
input logic clk_i,
input logic rst_ni,
input mem_req_t req_i,
input logic req_valid_i,
output logic req_ready_o,
output mem_resp_t resp_o,
output logic resp_valid_o,
input logic resp_ready_i,
output mem_req_t mem_req_o,
output logic mem_req_valid_o,
input logic mem_req_ready_i,
input mem_resp_t mem_resp_i,
input logic mem_resp_valid_i
);
typedef logic [$clog2(BufDepth+1):0] cnt_t;
cnt_t cnt_d, cnt_q;
logic buf_ready,
req_ready;
if (BufDepth > 0) begin : gen_buf
always_comb begin
cnt_d = cnt_q;
if (req_valid_i && req_ready_o) begin
cnt_d++;
end
if (resp_valid_o && resp_ready_i) begin
cnt_d--;
end
end
assign req_ready = (cnt_q < BufDepth) | (resp_valid_o & resp_ready_i);
assign req_ready_o = mem_req_ready_i & req_ready;
assign mem_req_valid_o = req_valid_i & req_ready;
stream_fifo #(
.FALL_THROUGH ( 1'b1 ),
.DEPTH ( BufDepth ),
.T ( mem_resp_t )
) i_resp_buf (
.clk_i,
.rst_ni,
.flush_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.data_i ( mem_resp_i ),
.valid_i ( mem_resp_valid_i ),
.ready_o ( buf_ready ),
.data_o ( resp_o ),
.valid_o ( resp_valid_o ),
.ready_i ( resp_ready_i ),
.usage_o ( )
);
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
cnt_q <= ('0);
end else begin
cnt_q <= (cnt_d);
end
end
end else begin : gen_no_buf
assign mem_req_valid_o = req_valid_i;
assign resp_valid_o = mem_req_valid_o & mem_req_ready_i & mem_resp_valid_i;
assign req_ready_o = resp_ready_i & resp_valid_o;
assign resp_o = mem_resp_i;
end
assign mem_req_o = req_i;
if (BufDepth > 0) begin : gen_buf_asserts
memory_response_lost: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (mem_resp_valid_i |-> buf_ready))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "memory_response_lost", "Memory response lost!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_to_mem.sv", 124);
end
counter_underflowed: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (cnt_q == '0 |=> cnt_q != '1))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "counter_underflowed", "Counter underflowed!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_to_mem.sv", 126);
end
counter_overflowed: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (cnt_q == BufDepth |=> cnt_q != BufDepth + 1))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "counter_overflowed", "Counter overflowed!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_to_mem.sv", 128);
end
end else begin : gen_no_buf_asserts
no_memory_response: assume property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (mem_req_valid_o & mem_req_ready_i |-> mem_resp_valid_i))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "no_memory_response", "Without BufDepth = 0, the memory must respond in the same cycle!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_to_mem.sv", 131);
end
end
endmodule
`begin_keywords "1800-2023"
module stream_arbiter_flushable #(
parameter type DATA_T = logic,
parameter integer N_INP = -1,
parameter ARBITER = "rr"
) (
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input DATA_T [N_INP-1:0] inp_data_i,
input logic [N_INP-1:0] inp_valid_i,
output logic [N_INP-1:0] inp_ready_o,
output DATA_T oup_data_o,
output logic oup_valid_o,
input logic oup_ready_i
);
if (ARBITER == "rr") begin : gen_rr_arb
rr_arb_tree #(
.NumIn (N_INP),
.DataType (DATA_T),
.ExtPrio (1'b0),
.AxiVldRdy (1'b1),
.LockIn (1'b1)
) i_arbiter (
.clk_i,
.rst_ni,
.flush_i,
.rr_i ('0),
.req_i (inp_valid_i),
.gnt_o (inp_ready_o),
.data_i (inp_data_i),
.gnt_i (oup_ready_i),
.req_o (oup_valid_o),
.data_o (oup_data_o),
.idx_o ()
);
end else if (ARBITER == "prio") begin : gen_prio_arb
rr_arb_tree #(
.NumIn (N_INP),
.DataType (DATA_T),
.ExtPrio (1'b1),
.AxiVldRdy (1'b1),
.LockIn (1'b0)
) i_arbiter (
.clk_i,
.rst_ni,
.flush_i,
.rr_i ('0),
.req_i (inp_valid_i),
.gnt_o (inp_ready_o),
.data_i (inp_data_i),
.gnt_i (oup_ready_i),
.req_o (oup_valid_o),
.data_o (oup_data_o),
.idx_o ()
);
end else begin : gen_arb_error
$fatal(1, "Invalid value for parameter 'ARBITER'!");
end
endmodule
`begin_keywords "1800-2023"
module stream_fifo_optimal_wrap #(
parameter int unsigned Depth = 32'd8,
parameter type type_t = logic,
parameter bit PrintInfo = 1'b0,
parameter int unsigned AddrDepth = (Depth > 32'd1) ? $clog2(Depth) : 32'd1
) (
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input logic testmode_i,
output logic [AddrDepth-1:0] usage_o,
input type_t data_i,
input logic valid_i,
output logic ready_o,
output type_t data_o,
output logic valid_o,
input logic ready_i
);
if (Depth < 32'd2) begin : gen_fatal
initial begin
$fatal(1, "FIFO of depth %d does not make any sense!", Depth);
end
end
if (Depth == 32'd2) begin : gen_spill
if (PrintInfo) begin : gen_info
initial begin
$display("[%m] Instantiate spill register (of depth %d)", Depth);
end
end
spill_register_flushable #(
.T ( type_t ),
.Bypass ( 1'b0 )
) i_spill_register_flushable (
.clk_i,
.rst_ni,
.flush_i,
.valid_i,
.ready_o,
.data_i,
.valid_o,
.ready_i,
.data_o
);
assign usage_o = 'x;
end
if (Depth > 32'd2) begin : gen_fifo
if (PrintInfo) begin : gen_info
initial begin
$info("[%m] Instantiate stream FIFO of depth %d", Depth);
end
end
stream_fifo #(
.DEPTH ( Depth ),
.T ( type_t )
) i_stream_fifo (
.clk_i,
.rst_ni,
.flush_i,
.testmode_i,
.usage_o,
.data_i,
.valid_i,
.ready_o,
.data_o,
.valid_o,
.ready_i
);
end
endmodule : stream_fifo_optimal_wrap
`begin_keywords "1800-2023"
module stream_register #(
parameter type T = logic
) (
input logic clk_i,
input logic rst_ni,
input logic clr_i,
input logic testmode_i,
input logic valid_i,
output logic ready_o,
input T data_i,
output logic valid_o,
input logic ready_i,
output T data_o
);
logic reg_ena;
assign ready_o = ready_i | ~valid_o;
assign reg_ena = valid_i & ready_o;
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
valid_o <= (1'b0);
end else begin
if (clr_i) begin
valid_o <= (1'b0);
end else if (ready_o) begin
valid_o <= (valid_i);
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
data_o <= (T'('0));
end else begin
if (clr_i) begin
data_o <= (T'('0));
end else if (reg_ena) begin
data_o <= (data_i);
end
end
end
endmodule
`begin_keywords "1800-2023"
module stream_xbar #(
parameter int unsigned NumInp = 32'd0,
parameter int unsigned NumOut = 32'd0,
parameter int unsigned DataWidth = 32'd1,
parameter type payload_t = logic [DataWidth-1:0],
parameter bit OutSpillReg = 1'b0,
parameter int unsigned ExtPrio = 1'b0,
parameter int unsigned AxiVldRdy = 1'b1,
parameter int unsigned LockIn = 1'b1,
parameter payload_t AxiVldMask = '1,
parameter int unsigned SelWidth = (NumOut > 32'd1) ? unsigned'($clog2(NumOut)) : 32'd1,
parameter type sel_oup_t = logic[SelWidth-1:0],
parameter int unsigned IdxWidth = (NumInp > 32'd1) ? unsigned'($clog2(NumInp)) : 32'd1,
parameter type idx_inp_t = logic[IdxWidth-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input idx_inp_t [NumOut-1:0] rr_i,
input payload_t [NumInp-1:0] data_i,
input sel_oup_t [NumInp-1:0] sel_i,
input logic [NumInp-1:0] valid_i,
output logic [NumInp-1:0] ready_o,
output payload_t [NumOut-1:0] data_o,
output idx_inp_t [NumOut-1:0] idx_o,
output logic [NumOut-1:0] valid_o,
input logic [NumOut-1:0] ready_i
);
typedef struct packed {
payload_t data;
idx_inp_t idx;
} spill_data_t;
logic [NumInp-1:0][NumOut-1:0] inp_valid;
logic [NumInp-1:0][NumOut-1:0] inp_ready;
payload_t [NumOut-1:0][NumInp-1:0] out_data;
logic [NumOut-1:0][NumInp-1:0] out_valid;
logic [NumOut-1:0][NumInp-1:0] out_ready;
for (genvar i = 0; unsigned'(i) < NumInp; i++) begin : gen_inps
stream_demux #(
.N_OUP ( NumOut )
) i_stream_demux (
.inp_valid_i ( valid_i[i] ),
.inp_ready_o ( ready_o[i] ),
.oup_sel_i ( sel_i[i] ),
.oup_valid_o ( inp_valid[i] ),
.oup_ready_i ( inp_ready[i] )
);
for (genvar j = 0; unsigned'(j) < NumOut; j++) begin : gen_cross
assign out_data[j][i] = data_i[i];
assign out_valid[j][i] = inp_valid[i][j];
assign inp_ready[i][j] = out_ready[j][i];
end
end
for (genvar j = 0; unsigned'(j) < NumOut; j++) begin : gen_outs
spill_data_t arb;
logic arb_valid, arb_ready;
rr_arb_tree #(
.NumIn ( NumInp ),
.DataType ( payload_t ),
.ExtPrio ( ExtPrio ),
.AxiVldRdy ( AxiVldRdy ),
.LockIn ( LockIn )
) i_rr_arb_tree (
.clk_i,
.rst_ni,
.flush_i,
.rr_i ( rr_i[j] ),
.req_i ( out_valid[j] ),
.gnt_o ( out_ready[j] ),
.data_i ( out_data[j] ),
.req_o ( arb_valid ),
.gnt_i ( arb_ready ),
.data_o ( arb.data ),
.idx_o ( arb.idx )
);
spill_data_t spill;
spill_register #(
.T ( spill_data_t ),
.Bypass ( !OutSpillReg )
) i_spill_register (
.clk_i,
.rst_ni,
.valid_i ( arb_valid ),
.ready_o ( arb_ready ),
.data_i ( arb ),
.valid_o ( valid_o[j] ),
.ready_i ( ready_i[j] ),
.data_o ( spill )
);
always_comb begin
data_o[j] = spill.data;
idx_o[j] = spill.idx;
end
end
for (genvar i = 0; unsigned'(i) < NumInp; i++) begin : gen_sel_assertions
non_existing_output: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (valid_i[i] |-> sel_i[i] < NumOut))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "non_existing_output", "Non-existing output is selected!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_xbar.sv", 176);
end
end
if (AxiVldRdy) begin : gen_handshake_assertions
for (genvar i = 0; unsigned'(i) < NumInp; i++) begin : gen_inp_assertions
input_data_unstable: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (valid_i[i] && !ready_o[i] |=> $stable(data_i[i] & AxiVldMask)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "input_data_unstable", $sformatf("data_i is unstable at input: %0d", i), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_xbar.sv", 182);
end
input_sel_unstable: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (valid_i[i] && !ready_o[i] |=> $stable(sel_i[i])))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "input_sel_unstable", $sformatf("sel_i is unstable at input: %0d", i), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_xbar.sv", 184);
end
input_valid_taken: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (valid_i[i] && !ready_o[i] |=> valid_i[i]))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "input_valid_taken", $sformatf("valid_i at input %0d has been taken away without a ready.", i), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_xbar.sv", 186);
end
end
for (genvar i = 0; unsigned'(i) < NumOut; i++) begin : gen_out_assertions
output_data_unstable: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (valid_o[i] && !ready_i[i] |=> $stable(data_o[i] & AxiVldMask)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "output_data_unstable", $sformatf("data_o is unstable at output: %0d Check that parameter LockIn is set.", i), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_xbar.sv", 191);
end
output_idx_unstable: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (valid_o[i] && !ready_i[i] |=> $stable(idx_o[i])))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "output_idx_unstable", $sformatf("idx_o is unstable at output: %0d Check that parameter LockIn is set.", i), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_xbar.sv", 193);
end
output_valid_taken: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (valid_o[i] && !ready_i[i] |=> valid_o[i]))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "output_valid_taken", $sformatf("valid_o at output %0d has been taken away without a ready.", i), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_xbar.sv", 195);
end
end
end
initial begin
numinp_0: assert (NumInp > 32'd0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "numinp_0", "NumInp has to be > 0!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_xbar.sv", 199);
end
end
initial begin
numout_0: assert (NumOut > 32'd0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "numout_0", "NumOut has to be > 0!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_xbar.sv", 200);
end
end
endmodule
`begin_keywords "1800-2023"
(* no_ungroup *)
(* no_boundary_optimization *)
module cdc_fifo_gray_clearable #(
parameter int unsigned WIDTH = 1,
parameter type T = logic [WIDTH-1:0],
parameter int LOG_DEPTH = 3,
parameter int SYNC_STAGES = 3,
parameter int CLEAR_ON_ASYNC_RESET = 1
) (
input logic src_rst_ni,
input logic src_clk_i,
input logic src_clear_i,
output logic src_clear_pending_o,
input T src_data_i,
input logic src_valid_i,
output logic src_ready_o,
input logic dst_rst_ni,
input logic dst_clk_i,
input logic dst_clear_i,
output logic dst_clear_pending_o,
output T dst_data_o,
output logic dst_valid_o,
input logic dst_ready_i
);
logic s_src_clear_req;
logic s_src_clear_ack_q;
logic s_src_ready;
logic s_src_isolate_req;
logic s_src_isolate_ack_q;
logic s_dst_clear_req;
logic s_dst_clear_ack_q;
logic s_dst_valid;
logic s_dst_isolate_req;
logic s_dst_isolate_ack_q;
T [2**LOG_DEPTH-1:0] async_data;
logic [LOG_DEPTH:0] async_wptr;
logic [LOG_DEPTH:0] async_rptr;
if (CLEAR_ON_ASYNC_RESET) begin : gen_elaboration_assertion
if (SYNC_STAGES < 3)
$error("The clearable CDC FIFO with async reset synchronization requires at least",
"3 synchronizer stages for the FIFO.");
end else begin : gen_elaboration_assertion
if (SYNC_STAGES < 2) begin : gen_elaboration_assertion
$error("A minimum of 2 synchronizer stages is required for proper functionality.");
end
end
if (2*SYNC_STAGES > 2**LOG_DEPTH) begin : gen_elaboration_assertion2
$warning("The FIFOs depth of %0d is insufficient to completely hide the latency of",
" %0d SYNC_STAGES. The FIFO will stall in the case where f_src ~= f_dst. ",
"It is reccomended to increase the FIFO's log depth to at least %0d.",
2**LOG_DEPTH, SYNC_STAGES, $clog2(2*SYNC_STAGES));
end
cdc_fifo_gray_src_clearable #(
.T ( T ),
.LOG_DEPTH ( LOG_DEPTH ),
.SYNC_STAGES ( SYNC_STAGES )
) i_src (
.src_rst_ni,
.src_clk_i,
.src_clear_i ( s_src_clear_req ),
.src_data_i,
.src_valid_i ( src_valid_i & !s_src_isolate_req ),
.src_ready_o ( s_src_ready ),
(* async *) .async_data_o ( async_data ),
(* async *) .async_wptr_o ( async_wptr ),
(* async *) .async_rptr_i ( async_rptr )
);
assign src_ready_o = s_src_ready & !s_src_isolate_req;
cdc_fifo_gray_dst_clearable #(
.T ( T ),
.LOG_DEPTH ( LOG_DEPTH ),
.SYNC_STAGES ( SYNC_STAGES )
) i_dst (
.dst_rst_ni,
.dst_clk_i,
.dst_clear_i ( s_dst_clear_req ),
.dst_data_o,
.dst_valid_o ( s_dst_valid ),
.dst_ready_i ( dst_ready_i & !s_dst_isolate_req ),
(* async *) .async_data_i ( async_data ),
(* async *) .async_wptr_i ( async_wptr ),
(* async *) .async_rptr_o ( async_rptr )
);
assign dst_valid_o = s_dst_valid & !s_dst_isolate_req;
cdc_reset_ctrlr #(
.SYNC_STAGES(SYNC_STAGES-1)
) i_cdc_reset_ctrlr (
.a_clk_i ( src_clk_i ),
.a_rst_ni ( src_rst_ni ),
.a_clear_i ( src_clear_i ),
.a_clear_o ( s_src_clear_req ),
.a_clear_ack_i ( s_src_clear_ack_q ),
.a_isolate_o ( s_src_isolate_req ),
.a_isolate_ack_i ( s_src_isolate_ack_q ),
.b_clk_i ( dst_clk_i ),
.b_rst_ni ( dst_rst_ni ),
.b_clear_i ( dst_clear_i ),
.b_clear_o ( s_dst_clear_req ),
.b_clear_ack_i ( s_dst_clear_ack_q ),
.b_isolate_o ( s_dst_isolate_req ),
.b_isolate_ack_i ( s_dst_isolate_ack_q )
);
always_ff @(posedge src_clk_i, negedge src_rst_ni) begin
if (!src_rst_ni) begin
s_src_isolate_ack_q <= 1'b0;
s_src_clear_ack_q <= 1'b0;
end else begin
s_src_isolate_ack_q <= s_src_isolate_req;
s_src_clear_ack_q <= s_src_clear_req;
end
end
always_ff @(posedge dst_clk_i, negedge dst_rst_ni) begin
if (!dst_rst_ni) begin
s_dst_isolate_ack_q <= 1'b0;
s_dst_clear_ack_q <= 1'b0;
end else begin
s_dst_isolate_ack_q <= s_dst_isolate_req;
s_dst_clear_ack_q <= s_dst_clear_req;
end
end
assign src_clear_pending_o = s_src_isolate_req;
assign dst_clear_pending_o = s_dst_isolate_req;
initial begin
log_depth_0: assert (LOG_DEPTH > 0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "log_depth_0", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_fifo_gray_clearable.sv", 259);
end
end
initial begin
sync_stages_lt_2: assert (SYNC_STAGES >= 2)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "sync_stages_lt_2", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_fifo_gray_clearable.sv", 260);
end
end
endmodule
(* no_ungroup *)
(* no_boundary_optimization *)
module cdc_fifo_gray_src_clearable #(
parameter type T = logic,
parameter int LOG_DEPTH = 3,
parameter int SYNC_STAGES = 2
)(
input logic src_rst_ni,
input logic src_clk_i,
input logic src_clear_i,
input T src_data_i,
input logic src_valid_i,
output logic src_ready_o,
output T [2**LOG_DEPTH-1:0] async_data_o,
output logic [LOG_DEPTH:0] async_wptr_o,
input logic [LOG_DEPTH:0] async_rptr_i
);
localparam int PtrWidth = LOG_DEPTH+1;
localparam logic [PtrWidth-1:0] PtrFull = (1 << LOG_DEPTH);
T [2**LOG_DEPTH-1:0] data_q, data_d;
logic [PtrWidth-1:0] wptr_q, wptr_d, wptr_bin, wptr_next, rptr, rptr_bin;
assign async_data_o = data_q;
always_comb begin
data_d = data_q;
data_d[wptr_bin[LOG_DEPTH-1:0]] = src_data_i;
end
always_ff @(posedge (src_clk_i) or negedge (src_rst_ni)) begin
if (!src_rst_ni) begin
data_q <= ('0);
end else begin
if (src_valid_i & src_ready_o) begin
data_q <= (data_d);
end
end
end
for (genvar i = 0; i < PtrWidth; i++) begin : gen_sync
sync #(.STAGES(SYNC_STAGES)) i_sync (
.clk_i ( src_clk_i ),
.rst_ni ( src_rst_ni ),
.serial_i ( async_rptr_i[i] ),
.serial_o ( rptr[i] )
);
end
gray_to_binary #(PtrWidth) i_rptr_g2b (.A(rptr), .Z(rptr_bin));
assign wptr_next = wptr_bin+1;
gray_to_binary #(PtrWidth) i_wptr_g2b (.A(wptr_q), .Z(wptr_bin));
binary_to_gray #(PtrWidth) i_wptr_b2g (.A(wptr_next), .Z(wptr_d));
always_ff @(posedge (src_clk_i) or negedge (src_rst_ni)) begin
if (!src_rst_ni) begin
wptr_q <= ('0);
end else begin
if (src_clear_i) begin
wptr_q <= ('0);
end else if (src_valid_i & src_ready_o) begin
wptr_q <= (wptr_d);
end
end
end
assign async_wptr_o = wptr_q;
assign src_ready_o = ((wptr_bin ^ rptr_bin) != PtrFull);
endmodule
(* no_ungroup *)
(* no_boundary_optimization *)
module cdc_fifo_gray_dst_clearable #(
parameter type T = logic,
parameter int LOG_DEPTH = 3,
parameter int SYNC_STAGES = 2
)(
input logic dst_rst_ni,
input logic dst_clk_i,
input logic dst_clear_i,
output T dst_data_o,
output logic dst_valid_o,
input logic dst_ready_i,
input T [2**LOG_DEPTH-1:0] async_data_i,
input logic [LOG_DEPTH:0] async_wptr_i,
output logic [LOG_DEPTH:0] async_rptr_o
);
localparam int PtrWidth = LOG_DEPTH+1;
localparam logic [PtrWidth-1:0] PtrEmpty = '0;
T dst_data;
logic [PtrWidth-1:0] rptr_q, rptr_d, rptr_bin, rptr_next, wptr, wptr_bin;
logic dst_valid, dst_ready;
assign dst_data = async_data_i[rptr_bin[LOG_DEPTH-1:0]];
assign rptr_next = rptr_bin+1;
gray_to_binary #(PtrWidth) i_rptr_g2b (.A(rptr_q), .Z(rptr_bin));
binary_to_gray #(PtrWidth) i_rptr_b2g (.A(rptr_next), .Z(rptr_d));
always_ff @(posedge (dst_clk_i) or negedge (dst_rst_ni)) begin
if (!dst_rst_ni) begin
rptr_q <= ('0);
end else begin
if (dst_clear_i) begin
rptr_q <= ('0);
end else if (dst_valid & dst_ready) begin
rptr_q <= (rptr_d);
end
end
end
assign async_rptr_o = rptr_q;
for (genvar i = 0; i < PtrWidth; i++) begin : gen_sync
sync #(.STAGES(SYNC_STAGES)) i_sync (
.clk_i ( dst_clk_i ),
.rst_ni ( dst_rst_ni ),
.serial_i ( async_wptr_i[i] ),
.serial_o ( wptr[i] )
);
end
gray_to_binary #(PtrWidth) i_wptr_g2b (.A(wptr), .Z(wptr_bin));
assign dst_valid = ((wptr_bin ^ rptr_bin) != PtrEmpty);
spill_register_flushable #(
.T ( T )
) i_spill_register (
.clk_i ( dst_clk_i ),
.rst_ni ( dst_rst_ni ),
.flush_i ( dst_clear_i ),
.valid_i ( dst_valid & !dst_clear_i ),
.ready_o ( dst_ready ),
.data_i ( dst_data ),
.valid_o ( dst_valid_o ),
.ready_i ( dst_ready_i ),
.data_o ( dst_data_o )
);
endmodule
`begin_keywords "1800-2023"
/*verilator lint_off DECLFILENAME*/
module cdc_2phase_clearable #(
parameter type T = logic,
parameter int unsigned SYNC_STAGES = 3,
parameter int CLEAR_ON_ASYNC_RESET = 1
)(
input logic src_rst_ni,
input logic src_clk_i,
input logic src_clear_i,
output logic src_clear_pending_o,
input T src_data_i,
input logic src_valid_i,
output logic src_ready_o,
input logic dst_rst_ni,
input logic dst_clk_i,
input logic dst_clear_i,
output logic dst_clear_pending_o,
output T dst_data_o,
output logic dst_valid_o,
input logic dst_ready_i
);
logic s_src_clear_req;
logic s_src_clear_ack_q;
logic s_src_ready;
logic s_src_isolate_req;
logic s_src_isolate_ack_q;
logic s_dst_clear_req;
logic s_dst_clear_ack_q;
logic s_dst_valid;
logic s_dst_isolate_req;
logic s_dst_isolate_ack_q;
(* dont_touch = "true" *) logic async_req;
(* dont_touch = "true" *) logic async_ack;
(* dont_touch = "true" *) T async_data;
if (CLEAR_ON_ASYNC_RESET) begin : gen_elaboration_assertion
if (SYNC_STAGES < 3)
$error("The clearable 2-phase CDC with async reset",
"synchronization requires at least 3 synchronizer stages for the FIFO.");
end else begin : gen_elaboration_assertion
if (SYNC_STAGES < 2) begin : gen_elaboration_assertion
$error("A minimum of 2 synchronizer stages is required for proper functionality.");
end
end
cdc_2phase_src_clearable #(
.T ( T ),
.SYNC_STAGES ( SYNC_STAGES )
) i_src (
.rst_ni ( src_rst_ni ),
.clk_i ( src_clk_i ),
.clear_i ( s_src_clear_req ),
.data_i ( src_data_i ),
.valid_i ( src_valid_i & !s_src_isolate_req ),
.ready_o ( s_src_ready ),
.async_req_o ( async_req ),
.async_ack_i ( async_ack ),
.async_data_o ( async_data )
);
assign src_ready_o = s_src_ready & !s_src_isolate_req;
cdc_2phase_dst_clearable #(
.T ( T ),
.SYNC_STAGES ( SYNC_STAGES )
) i_dst (
.rst_ni ( dst_rst_ni ),
.clk_i ( dst_clk_i ),
.clear_i ( s_dst_clear_req ),
.data_o ( dst_data_o ),
.valid_o ( s_dst_valid ),
.ready_i ( dst_ready_i & !s_dst_isolate_req ),
.async_req_i ( async_req ),
.async_ack_o ( async_ack ),
.async_data_i ( async_data )
);
assign dst_valid_o = s_dst_valid & !s_dst_isolate_req;
cdc_reset_ctrlr #(
.SYNC_STAGES(SYNC_STAGES-1)
) i_cdc_reset_ctrlr (
.a_clk_i ( src_clk_i ),
.a_rst_ni ( src_rst_ni ),
.a_clear_i ( src_clear_i ),
.a_clear_o ( s_src_clear_req ),
.a_clear_ack_i ( s_src_clear_ack_q ),
.a_isolate_o ( s_src_isolate_req ),
.a_isolate_ack_i ( s_src_isolate_ack_q ),
.b_clk_i ( dst_clk_i ),
.b_rst_ni ( dst_rst_ni ),
.b_clear_i ( dst_clear_i ),
.b_clear_o ( s_dst_clear_req ),
.b_clear_ack_i ( s_dst_clear_ack_q ),
.b_isolate_o ( s_dst_isolate_req ),
.b_isolate_ack_i ( s_dst_isolate_ack_q )
);
always_ff @(posedge src_clk_i, negedge src_rst_ni) begin
if (!src_rst_ni) begin
s_src_isolate_ack_q <= 1'b0;
s_src_clear_ack_q <= 1'b0;
end else begin
s_src_isolate_ack_q <= s_src_isolate_req;
s_src_clear_ack_q <= s_src_clear_req;
end
end
always_ff @(posedge dst_clk_i, negedge dst_rst_ni) begin
if (!dst_rst_ni) begin
s_dst_isolate_ack_q <= 1'b0;
s_dst_clear_ack_q <= 1'b0;
end else begin
s_dst_isolate_ack_q <= s_dst_isolate_req;
s_dst_clear_ack_q <= s_dst_clear_req;
end
end
assign src_clear_pending_o = s_src_isolate_req;
assign dst_clear_pending_o = s_dst_isolate_req;
no_valid_i_during_clear_i: assert property (@(posedge src_clk_i) disable iff ((!src_rst_ni) !== '0) (src_clear_i |-> !src_valid_i))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "no_valid_i_during_clear_i", "", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_2phase_clearable.sv", 191);
end
endmodule
module cdc_2phase_src_clearable #(
parameter type T = logic,
parameter int unsigned SYNC_STAGES = 2
) (
input logic rst_ni,
input logic clk_i,
input logic clear_i,
input T data_i,
input logic valid_i,
output logic ready_o,
output logic async_req_o,
input logic async_ack_i,
output T async_data_o
);
(* dont_touch = "true" *)
logic req_src_d, req_src_q, ack_synced;
(* dont_touch = "true" *)
T data_src_d, data_src_q;
sync #(
.STAGES(SYNC_STAGES)
) i_sync(
.clk_i,
.rst_ni,
.serial_i( async_ack_i ),
.serial_o( ack_synced )
);
always_comb begin
data_src_d = data_src_q;
req_src_d = req_src_q;
if (clear_i) begin
req_src_d = 1'b0;
end else if (valid_i && ready_o) begin
req_src_d = ~req_src_q;
data_src_d = data_i;
end
end
always_ff @(posedge (clk_i)) begin
data_src_q <= (data_src_d);
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
req_src_q <= 0;
end else begin
req_src_q <= req_src_d;
end
end
assign ready_o = (req_src_q == ack_synced);
assign async_req_o = req_src_q;
assign async_data_o = data_src_q;
no_clear_and_request: assume property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (clear_i |-> ~valid_i))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "no_clear_and_request", "No request allowed while clear_i is asserted.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/cdc_2phase_clearable.sv", 261);
end
endmodule
module cdc_2phase_dst_clearable #(
parameter type T = logic,
parameter int unsigned SYNC_STAGES = 2
)(
input logic rst_ni,
input logic clk_i,
input logic clear_i,
output T data_o,
output logic valid_o,
input logic ready_i,
input logic async_req_i,
output logic async_ack_o,
input T async_data_i
);
(* dont_touch = "true" *)
(* async_reg = "true" *)
logic ack_dst_d, ack_dst_q, req_synced, req_synced_q1;
(* dont_touch = "true" *)
T data_dst_d, data_dst_q;
sync #(
.STAGES(SYNC_STAGES)
) i_sync(
.clk_i,
.rst_ni,
.serial_i( async_req_i ),
.serial_o( req_synced )
);
always_comb begin
ack_dst_d = ack_dst_q;
if (clear_i) begin
ack_dst_d = 1'b0;
end else if (valid_o && ready_i) begin
ack_dst_d = ~ack_dst_q;
end
end
always_comb begin
data_dst_d = data_dst_q;
if (req_synced != req_synced_q1 && !valid_o) begin
data_dst_d = async_data_i;
end
end
always_ff @(posedge (clk_i)) begin
data_dst_q <= (data_dst_d);
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
ack_dst_q <= 0;
req_synced_q1 <= 1'b0;
end else begin
ack_dst_q <= ack_dst_d;
req_synced_q1 <= req_synced;
end
end
assign valid_o = (ack_dst_q != req_synced_q1);
assign data_o = data_dst_q;
assign async_ack_o = ack_dst_q;
endmodule
/*verilator lint_on DECLFILENAME*/
`begin_keywords "1800-2023"
module mem_to_banks_detailed #(
parameter int unsigned AddrWidth = 32'd0,
parameter int unsigned DataWidth = 32'd0,
parameter int unsigned WUserWidth = 32'd0,
parameter int unsigned RUserWidth = 32'd0,
parameter int unsigned NumBanks = 32'd1,
parameter bit HideStrb = 1'b0,
parameter int unsigned MaxTrans = 32'd1,
parameter int unsigned FifoDepth = 32'd1,
parameter type wuser_t = logic [WUserWidth-1:0],
localparam type addr_t = logic [AddrWidth-1:0],
localparam type inp_data_t = logic [DataWidth-1:0],
localparam type inp_strb_t = logic [DataWidth/8-1:0],
localparam type inp_ruser_t = logic [NumBanks-1:0][RUserWidth-1:0],
localparam type oup_data_t = logic [DataWidth/NumBanks-1:0],
localparam type oup_strb_t = logic [DataWidth/NumBanks/8-1:0],
localparam type oup_ruser_t = logic [RUserWidth-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic req_i,
output logic gnt_o,
input addr_t addr_i,
input inp_data_t wdata_i,
input inp_strb_t strb_i,
input wuser_t wuser_i,
input logic we_i,
output logic rvalid_o,
output inp_data_t rdata_o,
output inp_ruser_t ruser_o,
output logic [NumBanks-1:0] bank_req_o,
input logic [NumBanks-1:0] bank_gnt_i,
output addr_t [NumBanks-1:0] bank_addr_o,
output oup_data_t [NumBanks-1:0] bank_wdata_o,
output oup_strb_t [NumBanks-1:0] bank_strb_o,
output wuser_t [NumBanks-1:0] bank_wuser_o,
output logic [NumBanks-1:0] bank_we_o,
input logic [NumBanks-1:0] bank_rvalid_i,
input oup_data_t [NumBanks-1:0] bank_rdata_i,
input oup_ruser_t [NumBanks-1:0] bank_ruser_i
);
localparam int unsigned DataBytes = $bits(inp_strb_t);
localparam int unsigned BitsPerBank = $bits(oup_data_t);
localparam int unsigned BytesPerBank = $bits(oup_strb_t);
typedef struct packed {
addr_t addr;
oup_data_t wdata;
oup_strb_t strb;
wuser_t wuser;
logic we;
} req_t;
logic req_valid;
logic [NumBanks-1:0] req_ready,
resp_valid, resp_ready;
req_t [NumBanks-1:0] bank_req,
bank_oup;
logic [NumBanks-1:0] bank_req_internal,
bank_gnt_internal,
zero_strobe,
dead_response,
dead_response_unmasked;
logic dead_write_fifo_full,
dead_write_fifo_empty;
function automatic addr_t align_addr(input addr_t addr);
return (addr >> $clog2(DataBytes)) << $clog2(DataBytes);
endfunction
assign req_valid = req_i & gnt_o;
for (genvar i = 0; unsigned'(i) < NumBanks; i++) begin : gen_reqs
assign bank_req[i].addr = align_addr(addr_i) + i * BytesPerBank;
assign bank_req[i].wdata = wdata_i[i*BitsPerBank+:BitsPerBank];
assign bank_req[i].strb = strb_i[i*BytesPerBank+:BytesPerBank];
assign bank_req[i].wuser = wuser_i;
assign bank_req[i].we = we_i;
stream_fifo #(
.FALL_THROUGH ( 1'b1 ),
.DATA_WIDTH ( $bits(req_t) ),
.DEPTH ( FifoDepth ),
.T ( req_t )
) i_ft_reg (
.clk_i,
.rst_ni,
.flush_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.usage_o (),
.data_i ( bank_req[i] ),
.valid_i ( req_valid ),
.ready_o ( req_ready[i] ),
.data_o ( bank_oup[i] ),
.valid_o ( bank_req_internal[i] ),
.ready_i ( bank_gnt_internal[i] )
);
assign bank_addr_o[i] = bank_oup[i].addr;
assign bank_wdata_o[i] = bank_oup[i].wdata;
assign bank_strb_o[i] = bank_oup[i].strb;
assign bank_wuser_o[i] = bank_oup[i].wuser;
assign bank_we_o[i] = bank_oup[i].we;
assign zero_strobe[i] = (bank_req[i].strb == '0);
if (HideStrb) begin : gen_hide_strb
assign bank_req_o[i] = (bank_oup[i].we && (bank_oup[i].strb == '0)) ?
1'b0 : bank_req_internal[i];
assign bank_gnt_internal[i] = (bank_oup[i].we && (bank_oup[i].strb == '0)) ?
1'b1 : bank_gnt_i[i];
end else begin : gen_legacy_strb
assign bank_req_o[i] = bank_req_internal[i];
assign bank_gnt_internal[i] = bank_gnt_i[i];
end
end
assign gnt_o = (&req_ready) & (&resp_ready) & !dead_write_fifo_full;
if (HideStrb) begin : gen_dead_write_fifo
fifo_v3 #(
.FALL_THROUGH ( 1'b0 ),
.DEPTH ( MaxTrans+1 ),
.DATA_WIDTH ( NumBanks )
) i_dead_write_fifo (
.clk_i,
.rst_ni,
.flush_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.full_o ( dead_write_fifo_full ),
.empty_o ( dead_write_fifo_empty ),
.usage_o (),
.data_i ( {NumBanks{we_i}} & zero_strobe ),
.push_i ( req_i & gnt_o ),
.data_o ( dead_response_unmasked ),
.pop_i ( rvalid_o )
);
assign dead_response = dead_response_unmasked & {NumBanks{~dead_write_fifo_empty}};
end else begin : gen_no_dead_write_fifo
assign dead_response_unmasked = '0;
assign dead_response = '0;
assign dead_write_fifo_full = 1'b0;
assign dead_write_fifo_empty = 1'b1;
end
for (genvar i = 0; unsigned'(i) < NumBanks; i++) begin : gen_resp_regs
stream_fifo #(
.FALL_THROUGH ( 1'b1 ),
.DATA_WIDTH ( $bits(oup_data_t) + $bits(oup_ruser_t) ),
.DEPTH ( FifoDepth )
) i_ft_reg (
.clk_i,
.rst_ni,
.flush_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.usage_o (),
.data_i ( {bank_rdata_i[i], bank_ruser_i[i]} ),
.valid_i ( bank_rvalid_i[i] ),
.ready_o ( resp_ready[i] ),
.data_o ( {rdata_o[i*BitsPerBank+:BitsPerBank], ruser_o[i]} ),
.valid_o ( resp_valid[i] ),
.ready_i ( rvalid_o & !dead_response[i] )
);
end
assign rvalid_o = &(resp_valid | dead_response);
initial begin
datawidth_not_power_of_2: assume (DataWidth != 0 && 2**$clog2(DataWidth) == DataWidth)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "datawidth_not_power_of_2", "Data width must be a power of two!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/mem_to_banks_detailed.sv", 226);
end
datawidth_not_divisible_by_banks: assume (DataWidth % NumBanks == 0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "datawidth_not_divisible_by_banks", "Data width must be evenly divisible over banks!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/mem_to_banks_detailed.sv", 228);
end
bank_datawidth_not_divisible_by_8: assume ((DataWidth / NumBanks) % 8 == 0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "bank_datawidth_not_divisible_by_8", "Data width of each bank must be divisible into 8-bit bytes!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/mem_to_banks_detailed.sv", 230);
end
end
endmodule
`begin_keywords "1800-2023"
module stream_arbiter #(
parameter type DATA_T = logic,
parameter integer N_INP = -1,
parameter ARBITER = "rr"
) (
input logic clk_i,
input logic rst_ni,
input DATA_T [N_INP-1:0] inp_data_i,
input logic [N_INP-1:0] inp_valid_i,
output logic [N_INP-1:0] inp_ready_o,
output DATA_T oup_data_o,
output logic oup_valid_o,
input logic oup_ready_i
);
stream_arbiter_flushable #(
.DATA_T (DATA_T),
.N_INP (N_INP),
.ARBITER (ARBITER)
) i_arb (
.clk_i (clk_i),
.rst_ni (rst_ni),
.flush_i (1'b0),
.inp_data_i (inp_data_i),
.inp_valid_i (inp_valid_i),
.inp_ready_o (inp_ready_o),
.oup_data_o (oup_data_o),
.oup_valid_o (oup_valid_o),
.oup_ready_i (oup_ready_i)
);
endmodule
`begin_keywords "1800-2023"
module stream_omega_net #(
parameter int unsigned NumInp = 32'd0,
parameter int unsigned NumOut = 32'd0,
parameter int unsigned Radix = 32'd2,
parameter int unsigned DataWidth = 32'd1,
parameter type payload_t = logic [DataWidth-1:0],
parameter bit SpillReg = 1'b0,
parameter int unsigned ExtPrio = 1'b0,
parameter int unsigned AxiVldRdy = 1'b1,
parameter int unsigned LockIn = 1'b1,
parameter payload_t AxiVldMask = '1,
parameter int unsigned SelWidth = (NumOut > 32'd1) ? unsigned'($clog2(NumOut)) : 32'd1,
parameter type sel_oup_t = logic[SelWidth-1:0],
parameter int unsigned IdxWidth = (NumInp > 32'd1) ? unsigned'($clog2(NumInp)) : 32'd1,
parameter type idx_inp_t = logic[IdxWidth-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input idx_inp_t [NumOut-1:0] rr_i,
input payload_t [NumInp-1:0] data_i,
input sel_oup_t [NumInp-1:0] sel_i,
input logic [NumInp-1:0] valid_i,
output logic [NumInp-1:0] ready_o,
output payload_t [NumOut-1:0] data_o,
output idx_inp_t [NumOut-1:0] idx_o,
output logic [NumOut-1:0] valid_o,
input logic [NumOut-1:0] ready_i
);
if (NumInp <= Radix && NumOut <= Radix) begin : gen_degenerate_omega_net
stream_xbar #(
.NumInp ( NumInp ),
.NumOut ( NumOut ),
.payload_t ( payload_t ),
.OutSpillReg ( SpillReg ),
.ExtPrio ( ExtPrio ),
.AxiVldRdy ( AxiVldRdy ),
.LockIn ( LockIn )
) i_stream_xbar (
.clk_i,
.rst_ni,
.flush_i,
.rr_i ( rr_i ),
.data_i ( data_i ),
.sel_i ( sel_i ),
.valid_i ( valid_i ),
.ready_o ( ready_o ),
.data_o ( data_o ),
.idx_o ( idx_o ),
.valid_o ( valid_o ),
.ready_i ( ready_i )
);
end else begin : gen_omega_net
localparam int unsigned NumLanes = (NumOut > NumInp) ?
unsigned'(Radix**(cf_math_pkg::ceil_div($clog2(NumOut), $clog2(Radix)))) :
unsigned'(Radix**(cf_math_pkg::ceil_div($clog2(NumInp), $clog2(Radix))));
localparam int unsigned NumLevels = unsigned'(($clog2(NumLanes)+$clog2(Radix)-1)/$clog2(Radix));
localparam int unsigned NumRouters = NumLanes / Radix;
typedef logic [$clog2(NumLanes)-1:0] sel_dst_t;
localparam int unsigned SelW = unsigned'($clog2(Radix));
initial begin : proc_selw
$display("SelW is: %0d", SelW);
$display("SelDstW is: %0d", $bits(sel_dst_t));
end
typedef logic [SelW-1:0] sel_t;
typedef struct packed {
sel_dst_t sel_oup;
payload_t payload;
idx_inp_t idx_inp;
} omega_data_t;
omega_data_t [NumLevels-1:0][NumRouters-1:0][Radix-1:0] inp_router_data;
logic [NumLevels-1:0][NumRouters-1:0][Radix-1:0] inp_router_valid, inp_router_ready;
omega_data_t [NumLevels-1:0][NumRouters-1:0][Radix-1:0] out_router_data;
logic [NumLevels-1:0][NumRouters-1:0][Radix-1:0] out_router_valid, out_router_ready;
for (genvar i = 0; unsigned'(i) < NumLevels-1; i++) begin : gen_shuffle_levels
for (genvar j = 0; unsigned'(j) < NumRouters; j++) begin : gen_shuffle_routers
for (genvar k = 0; unsigned'(k) < Radix; k++) begin : gen_shuffle_radix
localparam int unsigned IdxLane = Radix * j + k;
assign inp_router_data[i+1][IdxLane%NumRouters][IdxLane/NumRouters] =
out_router_data[i][j][k];
assign inp_router_valid[i+1][IdxLane%NumRouters][IdxLane/NumRouters] =
out_router_valid[i][j][k];
assign out_router_ready[i][j][k] =
inp_router_ready[i+1][IdxLane%NumRouters][IdxLane/NumRouters];
if (i == 0) begin : gen_shuffle_inp
if ((NumLanes-IdxLane) <= NumInp) begin : gen_inp_ports
localparam int unsigned IdxInp = NumLanes - IdxLane - 32'd1;
assign inp_router_data[0][IdxLane%NumRouters][IdxLane/NumRouters] = '{
sel_oup: sel_dst_t'(sel_i[IdxInp]),
payload: data_i[IdxInp],
idx_inp: idx_inp_t'(IdxInp)
};
assign inp_router_valid[0][IdxLane%NumRouters][IdxLane/NumRouters] = valid_i[IdxInp];
assign ready_o[IdxInp] = inp_router_ready[0][IdxLane%NumRouters][IdxLane/NumRouters];
end else begin : gen_tie_off
assign inp_router_data[0][IdxLane%NumRouters][IdxLane/NumRouters] = '{ default: '0};
assign inp_router_valid[0][IdxLane%NumRouters][IdxLane/NumRouters] = 1'b0;
end
end
end
end
end
for (genvar i = 0; unsigned'(i) < NumLevels; i++) begin : gen_router_levels
for (genvar j = 0; unsigned'(j) < NumRouters; j++) begin : gen_routers
sel_t [Radix-1:0] sel_router;
for (genvar k = 0; unsigned'(k) < Radix; k++) begin : gen_router_sel
assign sel_router[k] = inp_router_data[i][j][k].sel_oup[SelW*(NumLevels-i-1)+:SelW];
end
stream_xbar #(
.NumInp ( Radix ),
.NumOut ( Radix ),
.payload_t ( omega_data_t ),
.OutSpillReg ( SpillReg ),
.ExtPrio ( 1'b0 ),
.AxiVldRdy ( AxiVldRdy ),
.LockIn ( LockIn )
) i_stream_xbar (
.clk_i,
.rst_ni,
.flush_i,
.rr_i ( '0 ),
.data_i ( inp_router_data[i][j] ),
.sel_i ( sel_router ),
.valid_i ( inp_router_valid[i][j] ),
.ready_o ( inp_router_ready[i][j] ),
.data_o ( out_router_data[i][j] ),
.idx_o ( ),
.valid_o ( out_router_valid[i][j] ),
.ready_i ( out_router_ready[i][j] )
);
end
end
for (genvar i = 0; unsigned'(i) < NumLanes; i++) begin : gen_outputs
if (i < NumOut) begin : gen_connect
assign data_o[i] = out_router_data[NumLevels-1][i/Radix][i%Radix].payload;
assign idx_o[i] = out_router_data[NumLevels-1][i/Radix][i%Radix].idx_inp;
assign valid_o[i] = out_router_valid[NumLevels-1][i/Radix][i%Radix];
assign out_router_ready[NumLevels-1][i/Radix][i%Radix] = ready_i[i];
end else begin : gen_tie_off
assign out_router_ready[NumLevels-1][i/Radix][i%Radix] = 1'b0;
end
end
initial begin : proc_debug_print
$display("NumInp: %0d", NumInp);
$display("NumOut: %0d", NumOut);
$display("Radix: %0d", Radix);
$display("NumLanes: %0d", NumLanes);
$display("NumLevels: %0d", NumLevels);
$display("NumRouters: %0d", NumRouters);
end
for (genvar i = 0; unsigned'(i) < NumInp; i++) begin : gen_sel_assertions
non_existing_output: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (valid_i[i] |-> sel_i[i] < NumOut))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "non_existing_output", "Non-existing output is selected!", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_omega_net.sv", 272);
end
end
if (AxiVldRdy) begin : gen_handshake_assertions
for (genvar i = 0; unsigned'(i) < NumInp; i++) begin : gen_inp_assertions
input_data_unstable: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (valid_i[i] && !ready_o[i] |=> $stable(data_i[i] & AxiVldMask)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "input_data_unstable", $sformatf("data_i is unstable at input: %0d", i), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_omega_net.sv", 278);
end
input_sel_unstable: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (valid_i[i] && !ready_o[i] |=> $stable(sel_i[i])))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "input_sel_unstable", $sformatf("sel_i is unstable at input: %0d", i), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_omega_net.sv", 280);
end
input_valid_taken: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (valid_i[i] && !ready_o[i] |=> valid_i[i]))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "input_valid_taken", $sformatf("valid_i at input %0d has been taken away without a ready.", i), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_omega_net.sv", 282);
end
end
for (genvar i = 0; unsigned'(i) < NumOut; i++) begin : gen_out_assertions
output_data_unstable: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (valid_o[i] && !ready_i[i] |=> $stable(data_o[i] & AxiVldMask)))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "output_data_unstable", $sformatf("data_o is unstable at output: %0d Check that parameter LockIn is set.", i), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_omega_net.sv", 288);
end
output_idx_unstable: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (valid_o[i] && !ready_i[i] |=> $stable(idx_o[i])))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "output_idx_unstable", $sformatf("idx_o is unstable at output: %0d Check that parameter LockIn is set.", i), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_omega_net.sv", 292);
end
output_valid_taken: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (valid_o[i] && !ready_i[i] |=> valid_o[i]))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "output_valid_taken", $sformatf("valid_o at output %0d has been taken away without a ready.", i), "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_omega_net.sv", 294);
end
end
end
initial begin
radix_not_power_of_2: assert ((2**$clog2(Radix) == Radix) && (Radix > 32'd1))
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "radix_not_power_of_2", "Radix is not power of two.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_omega_net.sv", 299);
end
end
initial begin
num_routers_not_power_of_2: assert (2**$clog2(NumRouters) == NumRouters)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "num_routers_not_power_of_2", "NumRouters is not power of two.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_omega_net.sv", 301);
end
end
initial begin
bit_slicing_broken: assert ($clog2(NumLanes) % SelW == 0)
else begin
$error("[ASSERT FAILED] [%m] %s: %s (%s:%0d)", "bit_slicing_broken", "Bit slicing of the internal selection signal is broken.", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/src/stream_omega_net.sv", 303);
end
end
end
endmodule
`begin_keywords "1800-2023"
module mem_to_banks #(
parameter int unsigned AddrWidth = 32'd0,
parameter int unsigned DataWidth = 32'd0,
parameter int unsigned AtopWidth = 32'd0,
parameter int unsigned NumBanks = 32'd1,
parameter bit HideStrb = 1'b0,
parameter int unsigned MaxTrans = 32'd1,
parameter int unsigned FifoDepth = 32'd1,
parameter type atop_t = logic [AtopWidth-1:0],
localparam type addr_t = logic [AddrWidth-1:0],
localparam type inp_data_t = logic [DataWidth-1:0],
localparam type inp_strb_t = logic [DataWidth/8-1:0],
localparam type oup_data_t = logic [DataWidth/NumBanks-1:0],
localparam type oup_strb_t = logic [DataWidth/NumBanks/8-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic req_i,
output logic gnt_o,
input addr_t addr_i,
input inp_data_t wdata_i,
input inp_strb_t strb_i,
input atop_t atop_i,
input logic we_i,
output logic rvalid_o,
output inp_data_t rdata_o,
output logic [NumBanks-1:0] bank_req_o,
input logic [NumBanks-1:0] bank_gnt_i,
output addr_t [NumBanks-1:0] bank_addr_o,
output oup_data_t [NumBanks-1:0] bank_wdata_o,
output oup_strb_t [NumBanks-1:0] bank_strb_o,
output atop_t [NumBanks-1:0] bank_atop_o,
output logic [NumBanks-1:0] bank_we_o,
input logic [NumBanks-1:0] bank_rvalid_i,
input oup_data_t [NumBanks-1:0] bank_rdata_i
);
mem_to_banks_detailed #(
.AddrWidth ( AddrWidth ),
.DataWidth ( DataWidth ),
.WUserWidth ( AtopWidth ),
.RUserWidth ( 1 ),
.NumBanks ( NumBanks ),
.HideStrb ( HideStrb ),
.MaxTrans ( MaxTrans ),
.FifoDepth ( FifoDepth ),
.wuser_t ( atop_t )
) i_mem_to_banks_detailed (
.clk_i,
.rst_ni,
.req_i,
.gnt_o,
.addr_i,
.wdata_i,
.strb_i,
.wuser_i ( atop_i ),
.we_i,
.rvalid_o,
.rdata_o,
.ruser_o (),
.bank_req_o,
.bank_gnt_i,
.bank_addr_o,
.bank_wdata_o,
.bank_strb_o,
.bank_wuser_o ( bank_atop_o ),
.bank_we_o,
.bank_rvalid_i,
.bank_rdata_i,
.bank_ruser_i ('0)
);
endmodule
`begin_keywords "1800-2023"
module addr_decode_tb;
localparam int unsigned NoIndices = 2;
localparam int unsigned NoRules = 3;
localparam int unsigned AddrWidth = 12;
typedef logic [AddrWidth-1:0] addr_t;
typedef logic [$clog2(NoIndices)-1:0] idx_t;
typedef struct packed {
int unsigned idx;
addr_t start_addr;
addr_t end_addr;
} tb_rule_t;
localparam tb_rule_t [NoRules-1:0] map_0 = '{
'{idx: 32'd0, start_addr: 12'h000, end_addr: 12'h010},
'{idx: 32'd1, start_addr: 12'h010, end_addr: 12'h020},
'{idx: 32'd0, start_addr: 12'hF00, end_addr: 12'hFFF}
};
localparam tb_rule_t [NoRules-1:0] map_1 = '{
'{idx: 32'd0, start_addr: 12'h000, end_addr: 12'h010},
'{idx: 32'd1, start_addr: 12'h00D, end_addr: 12'h020},
'{idx: 32'd1, start_addr: 12'h100, end_addr: 12'hFFF}
};
addr_t addr;
tb_rule_t [NoRules-1:0] addr_map;
idx_t idx;
logic dec_valid, dec_error;
logic en_default_idx;
idx_t default_idx;
longint unsigned passed_checks = 0;
longint unsigned failed_checks = 0;
initial begin : stimulus
passed_checks <= 0;
failed_checks <= 0;
addr_map <= map_0;
en_default_idx <= 1'b0;
default_idx <= idx_t'(1);
#500;
$info("Start address application");
for (int i = 0; i < 2**AddrWidth; i++) begin
addr <= addr_t'(i);
#1;
end
$info("Change addr map to an overlapping one expect warning");
addr_map <= map_1;
#100;
$info("Change addr map back and enable default decode to idx 1");
addr_map <= map_0;
en_default_idx <= 1'b1;
#100;
for (int i = 0; i < 2**AddrWidth; i++) begin
addr <= addr_t'(i);
#1;
end
#500
$info("Finished Simulation");
$display("Passed: %d", passed_checks);
$display("Failed: %d", failed_checks);
$stop();
end
always @(addr) #0 begin : proc_check_decode
for (int unsigned i = 0; i < NoRules; i++) begin
if ((addr >= addr_map[i].start_addr) && (addr < addr_map[i].end_addr )) begin
check_decode: assert (idx == addr_map[i].idx) passed_checks++; else begin
failed_checks++;
$warning("Decoder did not decode correctly.");
end
check_valid: assert (dec_valid == 1'b1 && dec_error == 1'b0) passed_checks++; else begin
failed_checks++;
$warning("Unexpected decode flag on assumed valid decode.");
end
end else begin
if (dec_valid == 1'b0) begin
if (en_default_idx) begin
check_default: assert (default_idx == idx) passed_checks++; else begin
failed_checks++;
$warning("Enabled default index, however wrong default decoding.");
end
check_flags: assert (dec_error == 1'b0) passed_checks++; else begin
failed_checks++;
$warning("Unexpected decode flags on default decode enabled.");
end
end else begin
check_error: assert (dec_error == 1'b1) passed_checks++; else begin
failed_checks++;
$warning("Unexpected decode flags on assumed decode error.");
end
end
end
end
end
end
addr_decode #(
.NoIndices ( NoIndices ),
.NoRules ( NoRules ),
.addr_t ( addr_t ),
.rule_t ( tb_rule_t )
) i_addr_decode_dut (
.addr_i ( addr ),
.addr_map_i ( addr_map ),
.idx_o ( idx ),
.dec_valid_o ( dec_valid ),
.dec_error_o ( dec_error ),
.en_default_idx_i( en_default_idx ),
.default_idx_i ( default_idx )
);
endmodule
`begin_keywords "1800-2023"
module cb_filter_tb;
localparam time TCycle = 10ns;
localparam time TAppli = 2ns;
localparam time TTest = 8ns;
localparam int unsigned RunCycles = 10000000;
localparam int unsigned NoHashes = 32'd3;
localparam int unsigned HashWidth = 32'd6;
localparam int unsigned HashRounds = 32'd1;
localparam int unsigned DataWidth = 32'd11;
localparam int unsigned BucketWidth = 32'd3;
typedef logic [DataWidth-1:0] data_t;
localparam cb_filter_pkg::cb_seed_t [NoHashes-1:0] Seeds = '{
'{PermuteSeed: 32'd299034753, XorSeed: 32'd4094834 },
'{PermuteSeed: 32'd19921030, XorSeed: 32'd995713 },
'{PermuteSeed: 32'd294388, XorSeed: 32'd65146511}
};
logic control_array [*];
int unsigned max_items;
int unsigned min_items;
longint unsigned no_tests;
longint unsigned no_positives;
longint unsigned no_false_positives;
longint unsigned no_negatives;
longint unsigned no_false_negatives;
logic clk;
logic rst_n;
logic sim_done;
data_t look_data;
logic look_valid;
data_t incr_data;
logic incr_valid;
data_t decr_data;
logic decr_valid;
logic filter_clear;
logic [HashWidth-1:0] filter_usage;
logic filter_full, filter_empty, filter_error;
clk_rst_gen #(
.ClkPeriod ( TCycle ),
.RstClkCycles ( 5 )
) i_clk_gen (
.clk_o ( clk ),
.rst_no ( rst_n )
);
initial begin : stimulus
sim_done = 1'b0;
no_tests = 64'd0;
no_positives = 64'd0;
no_false_positives = 64'd0;
no_negatives = 64'd0;
no_false_negatives = 64'd0;
init_signals();
fork
begin
max_items = 10;
min_items = 3;
@(posedge rst_n);
repeat (RunCycles) @(posedge clk);
sim_done = 1'b1;
end
begin
@(posedge rst_n);
run_lookup(sim_done);
end
begin
@(posedge rst_n);
run_increment(sim_done, decr_valid);
end
begin
@(posedge rst_n);
run_decrement(sim_done);
end
join
print_result(no_tests, no_positives, no_false_positives, no_negatives, no_false_negatives);
empty_filter();
$stop();
end
task cycle_start();
#TTest;
endtask : cycle_start
task cycle_end();
@(posedge clk);
endtask : cycle_end
task reset_filter();
filter_clear <= #TAppli '1;
cycle_end();
filter_clear <= #TAppli '0;
endtask : reset_filter
task init_signals();
look_data <= #TAppli '0;
incr_data <= #TAppli '0;
incr_valid <= #TAppli '0;
decr_data <= #TAppli '0;
decr_valid <= #TAppli '0;
filter_clear <= #TAppli '0;
endtask : init_signals
task automatic run_lookup(ref logic sim_done);
while (!sim_done) begin
logic [DataWidth-1:0] lookup = $urandom_range(0,2**DataWidth-1);;
rand_wait(0,6);
look_data <= #TAppli lookup;
cycle_start();
no_tests++;
if(control_array.exists(lookup)) begin
if(!look_valid) begin
$warning(1, "Had a false negative!!!\nIndex: %d", lookup);
no_false_negatives++;
end else begin
no_positives++;
end
end else begin
if(look_valid) begin
no_false_positives++;
end else begin
no_negatives++;
end
end
cycle_end();
end
endtask : run_lookup
task automatic run_increment(ref logic sim_done, ref logic decr_valid);
while (!sim_done) begin
logic [DataWidth-1:0] data = $urandom_range(0,2**DataWidth-1);
if(!control_array.exists(data)) begin
rand_wait(0,5);
incr_data <= #TAppli data;
while (filter_full | (control_array.num() > max_items))
begin if (sim_done | decr_valid) break; cycle_end(); end
incr_valid <= #TAppli 1'b1;
cycle_end();
control_array[data] = 1'b1;
incr_data <= #TAppli '0;
incr_valid <= #TAppli '0;
end else begin
cycle_end();
end
end
endtask : run_increment
task automatic run_decrement(ref logic sim_done);
int unsigned nb_tryes = 0;
while (!sim_done) begin
logic [DataWidth-1:0] data = $urandom_range(0,2**DataWidth-1);;
if(control_array.exists(data)) begin
if(control_array.num() > min_items) begin
rand_wait(0,5);
decr_data <= #TAppli data;
decr_valid <= #TAppli 1'b1;
cycle_start();
control_array.delete(data);
cycle_end();
decr_data <= #TAppli '0;
decr_valid <= #TAppli 1'b0;
end else begin
cycle_end();
end
end else begin
if(nb_tryes < 100) begin
nb_tryes++;
end else begin
nb_tryes = 0;
cycle_end();
end
end
end
endtask : run_decrement
task empty_filter();
rand_wait(10,15);
for (int unsigned i = 0; i < 2**DataWidth; i++) begin
if(control_array.exists(i)) begin
decr_data <= #TAppli i;
decr_valid <= #TAppli 1'b1;
cycle_start();
control_array.delete(i);
cycle_end();
end
end
decr_data <= #TAppli '0;
decr_valid <= #TAppli 1'b0;
cycle_start();
cycle_end();
$display("Filter empty is: %b", filter_empty);
endtask : empty_filter
task print_result(input longint unsigned n_test, n_pos, n_f_pos, n_neg, n_f_neg);
$info( "######################################################");
if (n_f_neg == 64'h0) begin
$display("***SUCCESS***");
end else begin
$display("!!!FAILED!!!");
end
$display("Finished Tests");
$display("NO Testes: %d", n_test);
$display("NO Positive: %d", n_pos);
$display("NO False Pos: %d", n_f_pos);
$display("NO Negatives: %d", n_neg);
$display("NO False Neg: %d <--- Success if this is 0!", n_f_neg);
$display("######################################################");
endtask : print_result
task automatic rand_wait(input int unsigned min, max);
int unsigned rand_success, cycles;
rand_success = std::randomize(cycles) with {
cycles >= min;
cycles <= max;
};
assert (rand_success) else $error("Failed to randomize wait cycles!");
repeat (cycles) @(posedge clk);
endtask : rand_wait
cb_filter #(
.KHashes ( NoHashes ),
.HashWidth ( HashWidth ),
.HashRounds ( HashRounds ),
.InpWidth ( DataWidth ),
.BucketWidth ( BucketWidth ),
.Seeds ( Seeds )
) i_dut (
.clk_i ( clk ),
.rst_ni ( rst_n ),
.look_data_i ( look_data ),
.look_valid_o ( look_valid ),
.incr_data_i ( incr_data ),
.incr_valid_i ( incr_valid ),
.decr_data_i ( decr_data ),
.decr_valid_i ( decr_valid ),
.filter_clear_i ( filter_clear ),
.filter_usage_o ( filter_usage ),
.filter_full_o ( filter_full ),
.filter_empty_o ( filter_empty ),
.filter_error_o ( filter_error )
);
endmodule
`begin_keywords "1800-2023"
module cdc_2phase_tb;
parameter int UNTIL = 100000;
parameter bit INJECT_DELAYS = 1;
parameter bit POST_SYNTHESIS = 0;
time tck_src = 10ns;
time tck_dst = 10ns;
bit src_done = 0;
bit dst_done = 0;
bit done;
assign done = src_done & dst_done;
logic src_rst_ni = 1;
logic src_clk_i = 0;
logic [31:0] src_data_i = 0;
logic src_valid_i = 0;
logic src_ready_o;
logic dst_rst_ni = 1;
logic dst_clk_i = 0;
logic [31:0] dst_data_o;
logic dst_valid_o;
logic dst_ready_i = 0;
if (POST_SYNTHESIS) begin : g_dut
cdc_2phase_synth i_dut (.*);
end else if (INJECT_DELAYS) begin : g_dut
cdc_2phase_tb_delay_injector #(0.8ns) i_dut (.*);
end else begin : g_dut
cdc_2phase #(logic [31:0]) i_dut (.*);
end
mailbox #(int) dst_mbox = new();
int num_sent = 0;
int num_received = 0;
int num_failed = 0;
initial begin
static int num_items, num_clks;
num_items = 10;
num_clks = 0;
#10ns;
src_rst_ni = 0;
#10ns;
src_rst_ni = 1;
#10ns;
while (!done) begin
src_clk_i = 1;
#(tck_src/2);
src_clk_i = 0;
#(tck_src/2);
num_clks++;
if (num_sent >= num_items && num_clks > 10) begin
num_items = num_sent + 10;
num_clks = 0;
tck_src = $urandom_range(1000, 10000) * 1ps;
assert(tck_src > 0);
end
end
end
initial begin
static int num_items, num_clks;
num_items = 10;
num_clks = 0;
#10ns;
dst_rst_ni = 0;
#10ns;
dst_rst_ni = 1;
#10ns;
while (!done) begin
dst_clk_i = 1;
#(tck_dst/2);
dst_clk_i = 0;
#(tck_dst/2);
num_clks++;
if (num_received >= num_items && num_clks > 10) begin
num_items = num_received + 10;
num_clks = 0;
tck_dst = $urandom_range(1000, 10000) * 1ps;
assert(tck_dst > 0);
end
end
end
task src_cycle_start;
#(tck_src*0.8);
endtask
task src_cycle_end;
@(posedge src_clk_i);
endtask
initial begin
@(negedge src_rst_ni);
@(posedge src_rst_ni);
repeat(3) @(posedge src_clk_i);
for (int i = 0; i < UNTIL; i++) begin
static integer stimulus;
stimulus = $random();
src_data_i <= #(tck_src*0.2) stimulus;
src_valid_i <= #(tck_src*0.2) 1;
dst_mbox.put(stimulus);
num_sent++;
src_cycle_start();
while (!src_ready_o) begin
src_cycle_end();
src_cycle_start();
end
src_cycle_end();
src_valid_i <= #(tck_src*0.2) 0;
end
src_done = 1;
end
task dst_cycle_start;
#(tck_dst*0.8);
endtask
task dst_cycle_end;
@(posedge dst_clk_i);
endtask
initial begin
@(negedge dst_rst_ni);
@(posedge dst_rst_ni);
repeat(3) @(posedge dst_clk_i);
while (!src_done || dst_mbox.num() > 0) begin
static integer expected, actual;
static int cooldown;
dst_ready_i <= #(tck_dst*0.2) 1;
dst_cycle_start();
while (!dst_valid_o) begin
dst_cycle_end();
dst_cycle_start();
end
actual = dst_data_o;
num_received++;
if (dst_mbox.num() == 0) begin
$error("unexpected transaction: data=%0h", actual);
num_failed++;
end else begin
dst_mbox.get(expected);
if (actual != expected) begin
$error("transaction mismatch: exp=%0h, act=%0h", expected, actual);
num_failed++;
end
end
dst_cycle_end();
dst_ready_i <= #(tck_dst*0.2) 0;
cooldown = $urandom_range(0, 40);
if (cooldown < 20) repeat(cooldown) @(posedge dst_clk_i);
end
if (num_sent != num_received) begin
$error("%0d items sent, but %0d items received", num_sent, num_received);
end
if (num_failed > 0) begin
$error("%0d/%0d items mismatched", num_failed, num_sent);
end else begin
$info("%0d items passed", num_sent);
end
dst_done = 1;
end
endmodule
module cdc_2phase_tb_delay_injector #(
parameter time MAX_DELAY = 0ns
)(
input logic src_rst_ni,
input logic src_clk_i,
input logic [31:0] src_data_i,
input logic src_valid_i,
output logic src_ready_o,
input logic dst_rst_ni,
input logic dst_clk_i,
output logic [31:0] dst_data_o,
output logic dst_valid_o,
input logic dst_ready_i
);
logic async_req_o, async_req_i;
logic async_ack_o, async_ack_i;
logic [31:0] async_data_o, async_data_i;
always @(async_req_o) begin
automatic time d = $urandom_range(0, MAX_DELAY);
async_req_i <= #d async_req_o;
end
always @(async_ack_o) begin
automatic time d = $urandom_range(0, MAX_DELAY);
async_ack_i <= #d async_ack_o;
end
for (genvar i = 0; i < 32; i++) begin
always @(async_data_o[i]) begin
automatic time d = $urandom_range(0, MAX_DELAY);
async_data_i[i] <= #d async_data_o[i];
end
end
cdc_2phase_src #(logic [31:0]) i_src (
.rst_ni ( src_rst_ni ),
.clk_i ( src_clk_i ),
.data_i ( src_data_i ),
.valid_i ( src_valid_i ),
.ready_o ( src_ready_o ),
.async_req_o ( async_req_o ),
.async_ack_i ( async_ack_i ),
.async_data_o ( async_data_o )
);
cdc_2phase_dst #(logic [31:0]) i_dst (
.rst_ni ( dst_rst_ni ),
.clk_i ( dst_clk_i ),
.data_o ( dst_data_o ),
.valid_o ( dst_valid_o ),
.ready_i ( dst_ready_i ),
.async_req_i ( async_req_i ),
.async_ack_o ( async_ack_o ),
.async_data_i ( async_data_i )
);
endmodule
`begin_keywords "1800-2023"
module cdc_2phase_clearable_tb;
parameter int UNTIL = 100000;
parameter bit INJECT_DELAYS = 1;
parameter int CLEAR_PPM = 2000;
parameter int SYNC_STAGES = 3;
time tck_src = 10ns;
time tck_dst = 10ns;
bit src_done = 0;
bit dst_done = 0;
bit done;
assign done = src_done & dst_done;
logic src_rst_ni = 1;
logic src_clk_i = 0;
logic [31:0] src_data_i = 0;
logic src_clear_i = 0;
logic src_clear_pending_o;
logic src_valid_i = 0;
logic src_ready_o;
logic dst_rst_ni = 1;
logic dst_clk_i = 0;
logic dst_clear_i = 0;
logic dst_clear_pending_o;
logic [31:0] dst_data_o;
logic dst_valid_o;
logic dst_ready_i = 0;
if (INJECT_DELAYS) begin : g_dut
cdc_2phase_clearable_tb_delay_injector #(0.8ns) i_dut (.*);
end else begin : g_dut
cdc_2phase_clearable #(logic [31:0]) i_dut (.*);
end
typedef struct {
int data;
bit is_stale;
} item_t;
item_t dst_mbox[$];
int num_sent = 0;
int num_received = 0;
int num_failed = 0;
initial begin
static int num_items, num_clks;
num_items = 10;
num_clks = 0;
#10ns;
src_rst_ni = 0;
#10ns;
src_rst_ni = 1;
#10ns;
while (!done) begin
src_clk_i = 1;
#(tck_src/2);
src_clk_i = 0;
#(tck_src/2);
num_clks++;
if (num_sent >= num_items && num_clks > 10) begin
num_items = num_sent + 10;
num_clks = 0;
tck_src = $urandom_range(1000, 10000) * 1ps;
assert(tck_src > 0);
end
end
end
initial begin
static int num_items, num_clks;
num_items = 10;
num_clks = 0;
#10ns;
dst_rst_ni = 0;
#10ns;
dst_rst_ni = 1;
#10ns;
while (!done) begin
dst_clk_i = 1;
#(tck_dst/2);
dst_clk_i = 0;
#(tck_dst/2);
num_clks++;
if (num_received >= num_items && num_clks > 10) begin
num_items = num_received + 10;
num_clks = 0;
tck_dst = $urandom_range(1000, 10000) * 1ps;
assert(tck_dst > 0);
end
end
end
task src_cycle_start;
#(tck_src*0.8);
endtask
task src_cycle_end;
@(posedge src_clk_i);
endtask
initial begin
@(negedge src_rst_ni);
@(posedge src_rst_ni);
repeat(3) @(posedge src_clk_i);
for (int i = 0; i < UNTIL; i++) begin
static item_t stimulus;
static bit clear_cdc;
stimulus.data = $random();
stimulus.is_stale = 1'b0;
src_data_i <= #(tck_src*0.2) stimulus.data;
src_valid_i <= #(tck_src*0.2) 1;
dst_mbox.push_front(stimulus);
num_sent++;
src_cycle_start();
while (!src_ready_o) begin
src_cycle_end();
src_cycle_start();
clear_cdc = $urandom_range(0,1e6) < CLEAR_PPM;
if (clear_cdc && !src_clear_pending_o) begin
foreach(dst_mbox[i]) begin
if (!dst_mbox[i].is_stale) begin
dst_mbox[i].is_stale = 1'b1;
num_sent--;
end
end
if ($urandom_range(0,1) == 1) begin
$info("Randomly clearing CDC source-side synchronously");
src_cycle_start();
src_clear_i = 1'b1;
src_valid_i = 1'b0;
src_cycle_end();
src_clear_i = #(tck_src*0.2) 1'b0;
end else begin
$info("Randomly resetting CDC source-side asynchronously");
src_cycle_start();
src_rst_ni = 1'b0;
src_valid_i = 1'b0;
src_cycle_end();
src_rst_ni = #(tck_src*0.2) 1'b1;
end
break;
end
end
src_cycle_end();
src_valid_i <= #(tck_src*0.2) 0;
end
src_done = 1;
end
task dst_cycle_start;
#(tck_dst*0.8);
endtask
task dst_cycle_end;
@(posedge dst_clk_i);
endtask
initial begin
@(negedge dst_rst_ni);
@(posedge dst_rst_ni);
repeat(3) @(posedge dst_clk_i);
while (!src_done || dst_mbox.size() > 0) begin
static item_t expected;
static integer actual;
static int cooldown;
static bit clear_cdc;
clear_cdc = $urandom_range(0,1e6) < CLEAR_PPM;
if (clear_cdc && !dst_clear_pending_o) begin
if ($urandom_range(0,1) == 1) begin
$info("Randomly clearing CDC destination-side synchronously");
dst_cycle_start();
dst_clear_i = 1'b1;
dst_ready_i = 1'b0;
dst_cycle_end();
dst_clear_i = #(tck_dst*0.2) 1'b0;
end else begin
$info("Randomly resetting CDC destination-side asynchronously");
dst_cycle_start();
dst_rst_ni = 1'b0;
dst_ready_i = 1'b0;
dst_cycle_end();
dst_rst_ni = #(tck_dst*0.2) 1'b1;
end
@(posedge dst_clk_i);
repeat(SYNC_STAGES) @(posedge src_clk_i);
dst_cycle_end();
while (dst_mbox.size() > 1) begin
expected = dst_mbox.pop_back();
end
end else begin
dst_ready_i <= #(tck_dst*0.2) 1;
dst_cycle_start();
while (!dst_valid_o) begin
dst_cycle_end();
dst_cycle_start();
end
actual = dst_data_o;
num_received++;
if (dst_mbox.size() == 0) begin
$error("unexpected transaction: data=%0h", actual);
num_failed++;
end else begin
expected = dst_mbox.pop_back();
if (actual != expected.data) begin
while (dst_mbox.size() > 0 && expected.is_stale && expected.data != actual) begin
expected = dst_mbox.pop_back();
end
if (actual != expected.data) begin
$error("transaction mismatch: exp=%0h, act=%0h", expected.data, actual);
num_failed++;
end else begin
if (!expected.is_stale) begin
num_received++;
end
end
end else if (expected.is_stale) begin
$info("Received stale item after clear. This is expected to happen for some cycles after the clear until the clear propagated to the other side.");
end else begin
num_received++;
end
end
dst_cycle_end();
dst_ready_i <= #(tck_dst*0.2) 0;
cooldown = $urandom_range(0, 40);
if (cooldown < 20) repeat(cooldown) @(posedge dst_clk_i);
end
end
if (num_failed > 0) begin
$error("%0d/%0d items mismatched", num_failed, num_sent);
end else begin
$info("%0d items passed", num_sent);
end
dst_done = 1;
end
endmodule
module cdc_2phase_clearable_tb_delay_injector #(
parameter time MAX_DELAY = 0ns,
parameter int SYNC_STAGES = 3
)(
input logic src_rst_ni,
input logic src_clk_i,
input logic src_clear_i,
output logic src_clear_pending_o,
input logic [31:0] src_data_i,
input logic src_valid_i,
output logic src_ready_o,
input logic dst_rst_ni,
input logic dst_clk_i,
input logic dst_clear_i,
output logic dst_clear_pending_o,
output logic [31:0] dst_data_o,
output logic dst_valid_o,
input logic dst_ready_i
);
logic async_req_o, async_req_i;
logic async_ack_o, async_ack_i;
logic [31:0] async_data_o, async_data_i;
logic s_src_clear;
logic s_src_ready;
logic s_dst_clear;
logic s_dst_valid;
always @(async_req_o) begin
automatic time d = $urandom_range(1ps, MAX_DELAY);
async_req_i <= #d async_req_o;
end
always @(async_ack_o) begin
automatic time d = $urandom_range(1ps, MAX_DELAY);
async_ack_i <= #d async_ack_o;
end
for (genvar i = 0; i < 32; i++) begin
always @(async_data_o[i]) begin
automatic time d = $urandom_range(1ps, MAX_DELAY);
async_data_i[i] <= #d async_data_o[i];
end
end
cdc_2phase_src_clearable #(logic [31:0], SYNC_STAGES) i_src (
.rst_ni ( src_rst_ni ),
.clk_i ( src_clk_i ),
.clear_i ( s_src_clear ),
.data_i ( src_data_i ),
.valid_i ( src_valid_i & !s_src_clear ),
.ready_o ( s_src_ready ),
.async_req_o ( async_req_o ),
.async_ack_i ( async_ack_i ),
.async_data_o ( async_data_o )
);
assign src_ready_o = s_src_ready & !s_src_clear;
cdc_2phase_dst_clearable #(logic [31:0], SYNC_STAGES) i_dst (
.rst_ni ( dst_rst_ni ),
.clk_i ( dst_clk_i ),
.clear_i ( s_dst_clear ),
.data_o ( dst_data_o ),
.valid_o ( s_dst_valid ),
.ready_i ( dst_ready_i & !s_dst_clear ),
.async_req_i ( async_req_i ),
.async_ack_o ( async_ack_o ),
.async_data_i ( async_data_i )
);
assign dst_valid_o = s_dst_valid & !s_dst_clear;
cdc_reset_ctrlr #(
.SYNC_STAGES(SYNC_STAGES-1)
) i_cdc_reset_ctrlr (
.a_clk_i ( src_clk_i ),
.a_rst_ni ( src_rst_ni ),
.a_clear_i ( src_clear_i ),
.a_clear_o ( s_src_clear ),
.a_clear_ack_i ( '0 ),
.a_isolate_o ( ),
.a_isolate_ack_i( '0 ),
.b_clk_i ( dst_clk_i ),
.b_rst_ni ( dst_rst_ni ),
.b_clear_i ( dst_clear_i ),
.b_clear_o ( s_dst_clear ),
.b_clear_ack_i ( '0 ),
.b_isolate_o ( ),
.b_isolate_ack_i( '0 )
);
assign src_clear_pending_o = s_src_clear;
assign dst_clear_pending_o = s_dst_clear;
endmodule
`begin_keywords "1800-2023"
module cdc_fifo_tb;
parameter bit INJECT_SRC_STALLS = 0;
parameter bit INJECT_DST_STALLS = 0;
parameter int UNTIL = 100000;
parameter int DEPTH = 0;
parameter bit GRAY = 0;
time tck_src = 10ns;
time tck_dst = 10ns;
bit src_done = 0;
bit dst_done = 0;
bit done;
assign done = src_done & dst_done;
logic src_rst_ni = 1;
logic src_clk_i = 0;
logic [31:0] src_data_i = 0;
logic src_valid_i = 0;
logic src_ready_o;
logic dst_rst_ni = 1;
logic dst_clk_i = 0;
logic [31:0] dst_data_o;
logic dst_valid_o;
logic dst_ready_i = 0;
assert property (@(posedge src_clk_i) !$isunknown(src_valid_i) && !$isunknown(src_ready_o));
assert property (@(posedge dst_clk_i) !$isunknown(dst_valid_o) && !$isunknown(dst_ready_i));
assert property (@(posedge src_clk_i) src_valid_i |-> !$isunknown(src_data_i));
assert property (@(posedge dst_clk_i) dst_valid_o |-> !$isunknown(dst_data_o));
if (GRAY)
cdc_fifo_gray #(.T(logic [31:0]), .LOG_DEPTH(DEPTH)) i_dut (.*);
else
cdc_fifo_2phase #(.T(logic [31:0]), .LOG_DEPTH(DEPTH)) i_dut (.*);
mailbox #(int) dst_mbox = new();
int num_sent = 0;
int num_received = 0;
int num_failed = 0;
initial begin
static int num_items, num_clks;
num_items = 10;
num_clks = 0;
#10ns;
src_rst_ni = 0;
#10ns;
src_rst_ni = 1;
#10ns;
while (!done) begin
src_clk_i = 1;
#(tck_src/2);
src_clk_i = 0;
#(tck_src/2);
num_clks++;
if (num_sent >= num_items && num_clks > 10) begin
num_items = num_sent + 10;
num_clks = 0;
tck_src = $urandom_range(1000, 10000) * 1ps;
assert(tck_src > 0);
end
end
end
initial begin
static int num_items, num_clks;
num_items = 10;
num_clks = 0;
#10ns;
dst_rst_ni = 0;
#10ns;
dst_rst_ni = 1;
#10ns;
while (!done) begin
dst_clk_i = 1;
#(tck_dst/2);
dst_clk_i = 0;
#(tck_dst/2);
num_clks++;
if (num_received >= num_items && num_clks > 10) begin
num_items = num_received + 10;
num_clks = 0;
tck_dst = $urandom_range(1000, 10000) * 1ps;
assert(tck_dst > 0);
end
end
end
task src_cycle_start;
#(tck_src*0.8);
endtask
task src_cycle_end;
@(posedge src_clk_i);
endtask
initial begin
@(negedge src_rst_ni);
@(posedge src_rst_ni);
repeat(3) @(posedge src_clk_i);
for (int i = 0; i < UNTIL; i++) begin
static integer stimulus;
static int cooldown;
stimulus = $random();
src_data_i <= #(tck_src*0.2) stimulus;
src_valid_i <= #(tck_src*0.2) 1;
dst_mbox.put(stimulus);
num_sent++;
src_cycle_start();
while (!src_ready_o) begin
src_cycle_end();
src_cycle_start();
end
src_cycle_end();
src_valid_i <= #(tck_src*0.2) 0;
if (INJECT_SRC_STALLS) begin
cooldown = $urandom_range(0, 40);
if (cooldown < 20) repeat(cooldown) @(posedge dst_clk_i);
end
end
src_done = 1;
end
task dst_cycle_start;
#(tck_dst*0.8);
endtask
task dst_cycle_end;
@(posedge dst_clk_i);
endtask
initial begin
@(negedge dst_rst_ni);
@(posedge dst_rst_ni);
repeat(3) @(posedge dst_clk_i);
while (!src_done || dst_mbox.num() > 0) begin
static integer expected, actual;
static int cooldown;
dst_ready_i <= #(tck_dst*0.2) 1;
dst_cycle_start();
while (!dst_valid_o) begin
dst_cycle_end();
dst_cycle_start();
end
actual = dst_data_o;
num_received++;
if (dst_mbox.num() == 0) begin
$error("unexpected transaction: data=%0h", actual);
num_failed++;
end else begin
dst_mbox.get(expected);
if (actual != expected) begin
$error("transaction mismatch: exp=%0h, act=%0h", expected, actual);
num_failed++;
end
end
dst_cycle_end();
dst_ready_i <= #(tck_dst*0.2) 0;
if (INJECT_DST_STALLS) begin
cooldown = $urandom_range(0, 40);
if (cooldown < 20) repeat(cooldown) @(posedge dst_clk_i);
end
end
if (num_sent != num_received) begin
$error("%0d items sent, but %0d items received", num_sent, num_received);
end
if (num_failed > 0) begin
$error("%0d/%0d items mismatched", num_failed, num_sent);
end else begin
$info("%0d items passed", num_sent);
end
dst_done = 1;
end
endmodule
`begin_keywords "1800-2023"
module cdc_fifo_clearable_tb;
parameter bit INJECT_SRC_STALLS = 0;
parameter bit INJECT_DST_STALLS = 0;
parameter int UNTIL = 100000;
parameter int DEPTH = 3;
parameter int CLEAR_PPM = 2000;
time tck_src = 10ns;
time tck_dst = 27ns;
bit src_done = 0;
bit dst_done = 0;
bit done;
assign done = src_done & dst_done;
logic src_rst_ni = 1;
logic src_clk_i = 0;
logic src_clear_i = 0;
logic src_clear_pending_o;
logic [31:0] src_data_i = 0;
logic src_valid_i = 0;
logic src_ready_o;
logic dst_rst_ni = 1;
logic dst_clk_i = 0;
logic dst_clear_i = 0;
logic dst_clear_pending_o;
logic [31:0] dst_data_o;
logic dst_valid_o;
logic dst_ready_i = 0;
assert property (@(posedge src_clk_i) !$isunknown(src_valid_i) && !$isunknown(src_ready_o));
assert property (@(posedge dst_clk_i) !$isunknown(dst_valid_o) && !$isunknown(dst_ready_i));
assert property (@(posedge src_clk_i) src_valid_i |-> !$isunknown(src_data_i));
assert property (@(posedge dst_clk_i) dst_valid_o |-> !$isunknown(dst_data_o));
cdc_fifo_gray_clearable #(.T(logic [31:0]), .LOG_DEPTH(DEPTH)) i_dut (.*);
typedef struct {
int data;
bit is_stale;
} item_t;
item_t dst_mbox[$];
int num_sent = 0;
int num_received = 0;
int num_failed = 0;
initial begin
static int num_items, num_clks;
num_items = 10;
num_clks = 0;
#10ns;
src_rst_ni = 0;
#10ns;
src_rst_ni = 1;
#10ns;
while (!done) begin
src_clk_i = 1;
#(tck_src/2);
src_clk_i = 0;
#(tck_src/2);
num_clks++;
if (num_sent >= num_items && num_clks > 10) begin
num_items = num_sent + 10;
num_clks = 0;
tck_src = $urandom_range(1000, 10000) * 1ps;
assert(tck_src > 0);
end
end
end
initial begin
static int num_items, num_clks;
num_items = 10;
num_clks = 0;
#10ns;
dst_rst_ni = 0;
#10ns;
dst_rst_ni = 1;
#10ns;
while (!done) begin
dst_clk_i = 1;
#(tck_dst/2);
dst_clk_i = 0;
#(tck_dst/2);
num_clks++;
if (num_received >= num_items && num_clks > 10) begin
num_items = num_received + 10;
num_clks = 0;
tck_dst = $urandom_range(1000, 10000) * 1ps;
assert(tck_dst > 0);
end
end
end
task src_cycle_start;
#(tck_src*0.8);
endtask
task src_cycle_end;
@(posedge src_clk_i);
endtask
initial begin
@(negedge src_rst_ni);
@(posedge src_rst_ni);
repeat(3) @(posedge src_clk_i);
for (int i = 0; i < UNTIL; i++) begin
item_t item;
static integer stimulus;
static int cooldown;
static bit clear_cdc;
clear_cdc = $urandom_range(0,1e6) < CLEAR_PPM;
if (!clear_cdc || src_clear_pending_o) begin
stimulus = $random();
item.data = stimulus;
item.is_stale = 1'b0;
src_data_i <= #(tck_src*0.2) stimulus;
src_valid_i <= #(tck_src*0.2) 1;
num_sent++;
src_cycle_start();
while (!src_ready_o) begin
src_cycle_end();
src_cycle_start();
end
dst_mbox.push_front(item);
src_cycle_end();
src_valid_i <= #(tck_src*0.2) 0;
if (INJECT_SRC_STALLS) begin
cooldown = $urandom_range(0, 40);
if (cooldown < 20) repeat(cooldown) @(posedge src_clk_i);
end
end else begin
foreach(dst_mbox[i]) begin
if (!dst_mbox[i].is_stale) begin
dst_mbox[i].is_stale = 1'b1;
num_sent--;
end
end
if ($urandom_range(0,1) == 1) begin
$info("Randomly clearing CDC synchronously and marking all pending items as stale");
src_cycle_start();
src_clear_i = 1'b1;
src_cycle_end();
src_clear_i = #(tck_src*0.2) 1'b0;
end else begin
$info("Randomly resetting CDC asynchronously and marking all pending items as stale");
src_cycle_start();
src_rst_ni = 1'b0;
src_cycle_end();
src_rst_ni = #(tck_src*0.2) 1'b1;
end
end
end
src_done = 1;
end
task dst_cycle_start;
#(tck_dst*0.8);
endtask
task dst_cycle_end;
@(posedge dst_clk_i);
endtask
initial begin
@(negedge dst_rst_ni);
@(posedge dst_rst_ni);
repeat(3) @(posedge dst_clk_i);
while (!src_done || dst_mbox.size() > 0) begin
static item_t expected_item;
static integer actual;
static int cooldown;
static bit clear_cdc;
clear_cdc = $urandom_range(0,1e6) < CLEAR_PPM;
if (!clear_cdc || dst_clear_pending_o) begin
dst_ready_i <= #(tck_dst*0.2) 1;
dst_cycle_start();
while (!dst_valid_o && !src_done) begin
dst_cycle_end();
dst_cycle_start();
end
if (src_done) break;
actual = dst_data_o;
if (dst_mbox.size() == 0) begin
$error("unexpected transaction: data=%0h", actual);
num_failed++;
end else begin
expected_item = dst_mbox.pop_back();
if (actual != expected_item.data) begin
while (dst_mbox.size() > 0 && expected_item.is_stale && expected_item.data != actual) begin
expected_item = dst_mbox.pop_back();
end
if (actual != expected_item.data) begin
$error("transaction mismatch: exp=%0h, act=%0h", expected_item.data, actual);
num_failed++;
end else begin
if (!expected_item.is_stale) begin
num_received++;
end
end
end else if (expected_item.is_stale) begin
$info("Received stale item after clear. This is expected to happen for some cycles after the clear until the clear propagated to the other side.");
end else begin
num_received++;
end
end
dst_cycle_end();
dst_ready_i <= #(tck_dst*0.2) 0;
if (INJECT_DST_STALLS) begin
cooldown = $urandom_range(0, 40);
if (cooldown < 20) repeat(cooldown) @(posedge dst_clk_i);
end
end else begin
if ($urandom_range(0,1) == 1) begin
$info("Randomly clearing CDC synchronously from the destination side");
dst_cycle_start();
dst_clear_i = 1'b1;
dst_cycle_end();
dst_clear_i <= #(tck_dst*0.2) 1'b0;
end else begin
$info("Randomly resettting CDC asynchronously from the destination side");
dst_cycle_start();
dst_rst_ni = 1'b0;
dst_cycle_end();
dst_rst_ni <= #(tck_dst*0.2) 1'b1;
end
@(posedge dst_clk_i);
repeat(DEPTH) @(posedge src_clk_i);
num_sent-=dst_mbox.size();
dst_mbox.delete();
dst_cycle_end();
end
end
if (num_failed > 0) begin
$error("%0d/%0d items mismatched", num_failed, num_sent);
end else begin
$info("%0d items passed", num_sent);
end
dst_done = 1;
end
endmodule
`begin_keywords "1800-2023"
module fifo_inst_tb #(
parameter bit FALL_THROUGH,
parameter int unsigned DEPTH,
parameter int unsigned DATA_WIDTH = 8,
parameter int unsigned N_CHECKS,
parameter time TA,
parameter time TT
) (
input logic clk_i,
input logic rst_ni,
output logic done_o
);
import rand_verif_pkg::rand_wait;
typedef logic [DATA_WIDTH-1:0] data_t;
logic clk,
flush,
full,
empty,
push,
pop,
try_push,
try_pop;
data_t wdata,
rdata;
int unsigned n_checks = 0;
assign clk = clk_i;
fifo_v3 #(
.FALL_THROUGH ( FALL_THROUGH ),
.DATA_WIDTH ( DATA_WIDTH ),
.DEPTH ( DEPTH )
) dut (
.clk_i,
.rst_ni,
.flush_i ( flush ),
.testmode_i ( 1'b0 ),
.full_o ( full ),
.empty_o ( empty ),
.usage_o ( ),
.data_i ( wdata ),
.push_i ( push ),
.data_o ( rdata ),
.pop_i ( pop )
);
initial begin
done_o = 1'b0;
$display("%m: Running test with FALL_THROUGH=%0d, DEPTH=%0d", FALL_THROUGH, DEPTH);
wait (n_checks >= N_CHECKS);
done_o = 1'b1;
$display("%m: Checked %0d stimuli", n_checks);
end
class random_action_t;
rand logic [1:0] action;
constraint random_action {
action dist {
0 := 40,
1 := 40,
3 := 2,
0 := 0
};
}
endclass
assign push = try_push & ~full;
initial begin
automatic random_action_t rand_act = new();
flush <= 1'b0;
wdata <= 'x;
try_push <= 1'b0;
wait (rst_ni);
forever begin
static logic rand_success;
rand_wait(1, 8, clk);
rand_success = rand_act.randomize(); assert(rand_success);
case (rand_act.action)
0: begin
wdata <= #TA $random();
try_push <= #TA 1'b1;
end
1: begin
wdata <= #TA $random();
try_push <= #TA 1'b0;
end
2: begin
flush <= #TA 1'b1;
rand_wait(1, 8, clk);
flush <= #TA 1'b0;
end
endcase
end
end
assign pop = try_pop & ~empty;
initial begin
try_pop <= 1'b0;
wait (rst_ni);
forever begin
rand_wait(1, 8, clk);
try_pop <= #TA $random();
end
end
initial begin
data_t queue[$];
wait (rst_ni);
forever begin
@(posedge clk_i);
#(TT);
if (flush) begin
queue = {};
end else begin
if (push && !full) begin
queue.push_back(wdata);
end
if (pop && !empty) begin
automatic data_t data = queue.pop_front();
assert (rdata == data) else $error("Queue output %0x != %0x", rdata, data);
n_checks++;
end
end
end
end
endmodule
module fifo_tb #(
parameter int unsigned N_CHECKS = 100000,
parameter time TCLK = 10ns,
parameter time TA = TCLK * 1/4,
parameter time TT = TCLK * 3/4
);
logic clk,
rst_n;
logic [5:0] done;
clk_rst_gen #(.ClkPeriod(TCLK), .RstClkCycles(10)) i_clk_rst_gen (
.clk_o (clk),
.rst_no (rst_n)
);
fifo_inst_tb #(
.FALL_THROUGH (1'b0),
.DEPTH (8),
.N_CHECKS (N_CHECKS),
.TA (TA),
.TT (TT)
) i_tb_8 (
.clk_i (clk),
.rst_ni (rst_n),
.done_o (done[0])
);
fifo_inst_tb #(
.FALL_THROUGH (1'b1),
.DEPTH (8),
.N_CHECKS (N_CHECKS),
.TA (TA),
.TT (TT)
) i_tb_ft_8 (
.clk_i (clk),
.rst_ni (rst_n),
.done_o (done[1])
);
fifo_inst_tb #(
.FALL_THROUGH (1'b0),
.DEPTH (1),
.N_CHECKS (N_CHECKS),
.TA (TA),
.TT (TT)
) i_tb_1 (
.clk_i (clk),
.rst_ni (rst_n),
.done_o (done[2])
);
fifo_inst_tb #(
.FALL_THROUGH (1'b1),
.DEPTH (1),
.N_CHECKS (N_CHECKS),
.TA (TA),
.TT (TT)
) i_tb_ft_1 (
.clk_i (clk),
.rst_ni (rst_n),
.done_o (done[3])
);
fifo_inst_tb #(
.FALL_THROUGH (1'b0),
.DEPTH (9),
.N_CHECKS (N_CHECKS),
.TA (TA),
.TT (TT)
) i_tb_9 (
.clk_i (clk),
.rst_ni (rst_n),
.done_o (done[4])
);
fifo_inst_tb #(
.FALL_THROUGH (1'b1),
.DEPTH (9),
.N_CHECKS (N_CHECKS),
.TA (TA),
.TT (TT)
) i_tb_ft_9 (
.clk_i (clk),
.rst_ni (rst_n),
.done_o (done[5])
);
initial begin
wait ((&done));
$finish();
end
endmodule
`begin_keywords "1800-2023"
module graycode_tb #(
parameter int N = 9
);
logic [N-1:0] a, b, c, bp = '0;
binary_to_gray #(N) dut_ab (a,b);
gray_to_binary #(N) dut_bc (b,c);
task check;
assert(a == c);
assert($signed($countones(b) - $countones(bp)) inside {-1,0,1});
bp = b;
endtask
initial begin : p_stim
logic [N:0] i;
repeat(2) for (i = 0; i < 2**N; i++) begin
a = i;
#1;
check();
end
for (i = 0; i < 2**N; i++) begin
a = N-i-1;
#1;
check();
end
end
endmodule
`begin_keywords "1800-2023"
module id_queue_tb #(
parameter int ID_WIDTH = 10,
parameter int CAPACITY = 30,
parameter int unsigned INP_MIN_WAIT_CYCLES = 0,
parameter int unsigned INP_MAX_WAIT_CYCLES = 40,
parameter int unsigned OUP_MIN_WAIT_CYCLES = 0,
parameter int unsigned OUP_MAX_WAIT_CYCLES = INP_MAX_WAIT_CYCLES/2,
parameter int unsigned N_CHECKS = 10000,
parameter bit VERBOSE = 1'b0,
parameter type data_t = logic[3:0]
);
localparam time TCLK = 10ns;
localparam time TA = TCLK * 1/4;
localparam time TT = TCLK * 3/4;
typedef logic [ID_WIDTH-1:0] id_t;
typedef logic [$bits(data_t)-1:0] mask_t;
typedef struct packed {
id_t id;
data_t data;
} queue_t;
typedef struct packed {
data_t data;
mask_t mask;
} exists_t;
logic clk,
rst_n;
data_t inp_data,
oup_data;
exists_t exists_inp;
id_t inp_id,
oup_id;
queue_t queue_inp;
logic exists,
exists_req, exists_gnt,
inp_req, inp_gnt,
oup_req, oup_gnt,
oup_pop,
oup_data_valid;
clk_rst_gen #(
.ClkPeriod (TCLK),
.RstClkCycles (5)
) i_clk_rst_gen (
.clk_o (clk),
.rst_no (rst_n)
);
id_queue #(
.ID_WIDTH (ID_WIDTH),
.CAPACITY (CAPACITY),
.data_t (data_t)
) dut (
.clk_i (clk),
.rst_ni (rst_n),
.inp_id_i (inp_id),
.inp_data_i (inp_data),
.inp_req_i (inp_req),
.inp_gnt_o (inp_gnt),
.exists_data_i (exists_inp.data),
.exists_mask_i (exists_inp.mask),
.exists_req_i (exists_req),
.exists_o (exists),
.exists_gnt_o (exists_gnt),
.oup_id_i (oup_id),
.oup_pop_i (oup_pop),
.oup_req_i (oup_req),
.oup_data_o (oup_data),
.oup_data_valid_o (oup_data_valid),
.oup_gnt_o (oup_gnt)
);
rand_stream_mst #(
.data_t (queue_t),
.MinWaitCycles (INP_MIN_WAIT_CYCLES),
.MaxWaitCycles (INP_MAX_WAIT_CYCLES),
.ApplDelay (TA),
.AcqDelay (TT)
) i_inp_mst (
.clk_i (clk),
.rst_ni (rst_n),
.data_o (queue_inp),
.valid_o (inp_req),
.ready_i (inp_gnt)
);
assign inp_id = queue_inp.id;
assign inp_data = queue_inp.data;
rand_stream_mst #(
.data_t (logic),
.MinWaitCycles (OUP_MIN_WAIT_CYCLES),
.MaxWaitCycles (OUP_MAX_WAIT_CYCLES),
.ApplDelay (TA),
.AcqDelay (TT)
) i_oup_mst (
.clk_i (clk),
.rst_ni (rst_n),
.data_o (),
.valid_o (oup_req),
.ready_i (oup_gnt)
);
rand_stream_mst #(
.data_t (exists_t),
.MinWaitCycles (OUP_MIN_WAIT_CYCLES),
.MaxWaitCycles (OUP_MAX_WAIT_CYCLES),
.ApplDelay (TA),
.AcqDelay (TT)
) i_exists_mst (
.clk_i (clk),
.rst_ni (rst_n),
.data_o (exists_inp),
.valid_o (exists_req),
.ready_i (exists_gnt)
);
import rand_id_queue_pkg::*;
rand_id_queue #(
.data_t (data_t),
.ID_WIDTH (ID_WIDTH)
) exp_queue = new;
initial begin
wait (rst_n);
forever begin
@(posedge clk);
if (inp_req && inp_gnt) begin
exp_queue.push(inp_id, inp_data);
if (VERBOSE) begin
$display("%0t: new entry %0x at ID %0x", $time, inp_data, inp_id);
end
end
if (oup_req && oup_gnt && oup_pop) begin
if (VERBOSE) begin
$display("%0t: removed entry from ID %0x", $time, oup_id);
end
void'(exp_queue.pop_id(oup_id));
end
end
end
initial begin
wait (rst_n);
forever begin
@(posedge clk);
#(TT);
if (exists_req && exists_gnt) begin
automatic logic match = 1'b0;
automatic mask_t mask = exists_inp.mask;
automatic data_t masked_exists = exists_inp.data & mask;
for (int unsigned id = 0; id < 2**ID_WIDTH; id++) begin
for (int unsigned idx = 0; idx < exp_queue.queues[id].size(); idx++) begin
match = ((exp_queue.queues[id][idx] & mask) == masked_exists);
if (match) begin
break;
end
end
if (match) begin
break;
end
end
assert (exists == match) else begin
if (match) begin
$error("Entry with value %0x and mask %0b should exist but ID queue did not find it!",
exists_inp.data, exists_inp.mask);
end else begin
$error("Entry with value %0x and mask %0b should NOT exist but ID queue found it!",
exists_inp.data, exists_inp.mask);
end
end
end
if (oup_req && oup_gnt) begin
if (oup_data_valid) begin
automatic data_t exp_data = exp_queue.get(oup_id);
assert (exp_data == oup_data)
else $error("Expected to read %0x from ID %0x but got %0x!",
exp_data, oup_id, oup_data);
if (VERBOSE) begin
$display("%0t: read %0x at ID %0x!", $time, oup_data, oup_id);
end
end else begin
assert (exp_queue.queues[oup_id].size() == 0)
else $error("Expected to get valid output from ID %0x but did not!",
oup_id);
end
end
end
end
initial begin
void'(std::randomize(oup_id));
oup_pop = 1'b0;
wait (rst_n);
@(posedge clk);
#(TT);
forever begin
@(posedge clk);
#(TA);
if (exp_queue.empty()) begin
oup_pop = 1'b0;
end else begin
void'(std::randomize(oup_pop));
oup_id = exp_queue.rand_id();
end
#(TT-TA);
while (oup_req && !oup_gnt) begin
@(posedge clk);
#(TT);
end
end
end
initial begin
static int unsigned n_pops = 0;
wait (rst_n);
forever begin
@(posedge clk);
#(TT);
if (oup_req && oup_gnt && oup_pop && oup_data_valid) begin
n_pops++;
end
#(TCLK-TT);
if (n_pops >= N_CHECKS) begin
$display("Finished with a total of %0d random entries fed through the ID queue.",
n_pops);
$finish(0);
end
end
end
endmodule
`begin_keywords "1800-2023"
`timescale 1ns/1ns
module passthrough_stream_fifo_tb #(
parameter int unsigned TCK = 10,
parameter int unsigned DataWidth = 8,
parameter int unsigned Depth = 10,
parameter int unsigned NumStims = 1000,
parameter int unsigned WriteProbability = 10,
parameter int unsigned ReadProbability = 10,
parameter bit SameCycleRW = 1'b1
) ();
typedef logic [DataWidth-1:0] data_t;
int unsigned applied_stims, acquired_stims;
logic clk, rst_n;
data_t in_data, out_data;
logic in_valid, in_ready, out_valid, out_ready;
data_t app_queue[$], acq_queue[$];
clk_rst_gen #(
.ClkPeriod ( TCK ),
.RstClkCycles ( 1 )
) i_clk_rst_gen (
.clk_o ( clk ),
.rst_no ( rst_n )
);
passthrough_stream_fifo #(
.Depth ( Depth ),
.type_t ( data_t ),
.PrintInfo ( 1'b1 ),
.SameCycleRW ( SameCycleRW )
) i_passthrough_stream_fifo (
.clk_i ( clk ),
.rst_ni ( rst_n ),
.flush_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.data_i ( (in_valid && in_ready) ? in_data : 'x ),
.valid_i ( in_valid && in_ready ),
.ready_o ( in_ready ),
.data_o ( out_data ),
.valid_o ( out_valid ),
.ready_i ( out_ready && out_valid )
);
initial begin
applied_stims = 0;
in_data = '0;
in_valid = 1'b0;
wait(rst_n);
$display("Started application!");
while(applied_stims < NumStims) begin
@(negedge clk);
in_valid = $urandom_range(0, WriteProbability) == 0;
in_data = $urandom();
@(posedge clk);
if (in_valid && in_ready) begin
$display("%d Applied: %d", applied_stims, in_data);
app_queue.push_back(in_data);
applied_stims++;
end
end
in_valid = 1'b0;
$display("Applied %d stimuli", applied_stims);
end
initial begin
acquired_stims = 0;
out_ready = 1'b0;
wait(rst_n);
$display("Started acquisition!");
forever begin
@(negedge clk);
out_ready = $urandom_range(0, ReadProbability) == 0;
@(posedge clk);
if (out_valid && out_ready) begin
$display("%d Acquired: %d", acquired_stims, out_data);
acq_queue.push_back(out_data);
acquired_stims++;
end
end
end
initial begin
int unsigned num_errors;
data_t acq_data, app_data;
num_errors = 0;
while((acquired_stims < NumStims) || (applied_stims < NumStims)) begin
wait((app_queue.size() != 0) && (acq_queue.size() != 0));
acq_data = acq_queue.pop_front();
app_data = app_queue.pop_front();
if (app_data != acq_data) begin
$display("Missmatch! Applied: %d Acquired: %d", app_data, acq_data);
num_errors++;
end else begin
$display("Match! Applied: %d Acquired: %d", app_data, acq_data);
end
end
$display("Applied %d stimuli and acquired %d responses", applied_stims, acquired_stims);
$display("Errors: %d", num_errors);
$stop();
end
endmodule
`begin_keywords "1800-2023"
module popcount_tb;
logic data_w1;
logic popcount_w1;
logic [4:0] data_w5;
logic [3:0] popcount_w5;
logic [15:0] data_w16;
logic [4:0] popcount_w16;
logic [31:0] data_w32;
logic [5:0] popcount_w32;
logic [63:0] data_w64;
logic [6:0] popcount_w64;
logic [980:0] data_w981;
logic [10:0] popcount_w981;
popcount #(.INPUT_WIDTH(1)) i_popcount_w1
(.data_i(data_w1),
.popcount_o(popcount_w1));
popcount #(.INPUT_WIDTH(5)) i_popcount_w5
(.data_i(data_w5),
.popcount_o(popcount_w5));
popcount #(.INPUT_WIDTH(16)) i_popcount_w16
(.data_i(data_w16),
.popcount_o(popcount_w16));
popcount #(.INPUT_WIDTH(32)) i_popcount_w32
(.data_i(data_w32),
.popcount_o(popcount_w32));
popcount #(.INPUT_WIDTH(64)) i_popcount_w64
(.data_i(data_w64),
.popcount_o(popcount_w64));
popcount #(.INPUT_WIDTH(981)) i_popcount_w981
(.data_i(data_w981),
.popcount_o(popcount_w981));
initial begin
data_w1 = 0;
for(int i = 0; i<100; i++)
begin
do begin
if (!(randomize(data_w1))) begin
$display("%s:%0d: Randomization failed \"%s\"", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/popcount_tb.sv", 86, "randomize(data_w1)");
$finish;
end
end while (0);
#5ns;
assert(popcount_w1 == $countones(data_w1)) else $error("Popcount of %b was %d but should be %d.", data_w1, popcount_w1, $countones(data_w1));
end
data_w5 = 0;
#5ns;
assert(popcount_w5 == $countones(data_w5)) else $error("Popcount of %b was %d but should be %d.", data_w5, popcount_w5, $countones(data_w5));
data_w5 = 1;
#5ns;
assert(popcount_w5 == $countones(data_w5)) else $error("Popcount of %b was %d but should be %d.", data_w5, popcount_w5, $countones(data_w5));
data_w5 = '1;
#5ns;
assert(popcount_w5 == $countones(data_w5)) else $error("Popcount of %b was %d but should be %d.", data_w5, popcount_w5, $countones(data_w5));
for(int i = 0; i<100; i++)
begin
do begin
if (!(randomize(data_w5))) begin
$display("%s:%0d: Randomization failed \"%s\"", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/popcount_tb.sv", 104, "randomize(data_w5)");
$finish;
end
end while (0);
#5ns;
assert(popcount_w5 == $countones(data_w5)) else $error("Popcount of %b was %d but should be %d.", data_w5, popcount_w5, $countones(data_w5));
end
data_w16 = 0;
#5ns;
assert(popcount_w16 == $countones(data_w16)) else $error("Popcount of %b was %d but should be %d.", data_w16, popcount_w16, $countones(data_w16));
data_w16 = 1;
#5ns;
assert(popcount_w16 == $countones(data_w16)) else $error("Popcount of %b was %d but should be %d.", data_w16, popcount_w16, $countones(data_w16));
data_w16 = '1;
#5ns;
assert(popcount_w16 == $countones(data_w16)) else $error("Popcount of %b was %d but should be %d.", data_w16, popcount_w16, $countones(data_w16));
for(int i = 0; i<100; i++)
begin
do begin
if (!(randomize(data_w16))) begin
$display("%s:%0d: Randomization failed \"%s\"", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/popcount_tb.sv", 121, "randomize(data_w16)");
$finish;
end
end while (0);
#5ns;
assert(popcount_w16 == $countones(data_w16)) else $error("Popcount of %b was %d but should be %d.", data_w16, popcount_w16, $countones(data_w16));
end
data_w32 = 0;
#5ns;
assert(popcount_w32 == $countones(data_w32)) else $error("Popcount of %b was %d but should be %d.", data_w32, popcount_w32, $countones(data_w32));
data_w32 = 1;
#5ns;
assert(popcount_w32 == $countones(data_w32)) else $error("Popcount of %b was %d but should be %d.", data_w32, popcount_w32, $countones(data_w32));
data_w32 = '1;
#5ns;
assert(popcount_w32 == $countones(data_w32)) else $error("Popcount of %b was %d but should be %d.", data_w32, popcount_w32, $countones(data_w32));
for(int i = 0; i<100; i++)
begin
do begin
if (!(randomize(data_w32))) begin
$display("%s:%0d: Randomization failed \"%s\"", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/popcount_tb.sv", 138, "randomize(data_w32)");
$finish;
end
end while (0);
#5ns;
assert(popcount_w32 == $countones(data_w32)) else $error("Popcount of %b was %d but should be %d.", data_w32, popcount_w32, $countones(data_w32));
end
data_w64 = 0;
#5ns;
assert(popcount_w64 == $countones(data_w64)) else $error("Popcount of %b was %d but should be %d.", data_w64, popcount_w64, $countones(data_w64));
data_w64 = 1;
#5ns;
assert(popcount_w64 == $countones(data_w64)) else $error("Popcount of %b was %d but should be %d.", data_w64, popcount_w64, $countones(data_w64));
data_w64 = '1;
#5ns;
assert(popcount_w64 == $countones(data_w64)) else $error("Popcount of %b was %d but should be %d.", data_w64, popcount_w64, $countones(data_w64));
for(int i = 0; i<100; i++)
begin
do begin
if (!(randomize(data_w64))) begin
$display("%s:%0d: Randomization failed \"%s\"", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/popcount_tb.sv", 155, "randomize(data_w64)");
$finish;
end
end while (0);
#5ns;
assert(popcount_w64 == $countones(data_w64)) else $error("Popcount of %b was %d but should be %d.", data_w64, popcount_w64, $countones(data_w64));
end
data_w981 = 0;
#5ns;
assert(popcount_w981 == $countones(data_w981)) else $error("Popcount of %b was %d but should be %d.", data_w981, popcount_w981, $countones(data_w981));
data_w981 = 1;
#5ns;
assert(popcount_w981 == $countones(data_w981)) else $error("Popcount of %b was %d but should be %d.", data_w981, popcount_w981, $countones(data_w981));
data_w981 = '1;
#5ns;
assert(popcount_w981 == $countones(data_w981)) else $error("Popcount of %b was %d but should be %d.", data_w981, popcount_w981, $countones(data_w981));
for(int i = 0; i<100; i++)
begin
do begin
if (!(randomize(data_w981))) begin
$display("%s:%0d: Randomization failed \"%s\"", "/home/mel/build/axi/.bender/git/checkouts/common_cells-3e2fcccecd7aee7b/test/popcount_tb.sv", 172, "randomize(data_w981)");
$finish;
end
end while (0);
#5ns;
assert(popcount_w981 == $countones(data_w981)) else $error("Popcount of %b was %d but should be %d.", data_w981, popcount_w981, $countones(data_w981));
end
end
endmodule : popcount_tb
`begin_keywords "1800-2023"
module rr_arb_tree_tb #(
parameter int unsigned NumInp = 32'd7,
parameter int unsigned NumReqs = 32'd20000,
parameter bit AxiVldRdy = 1'b1,
parameter bit LockIn = 1'b1,
parameter bit FairArb = 1'b1
);
localparam time CyclTime = 10ns;
localparam time ApplTime = 2ns;
localparam time TestTime = 8ns;
localparam real error_threshold = 0.1;
localparam int unsigned IdxWidth = (NumInp > 32'd1) ? unsigned'($clog2(NumInp)) : 32'd1;
localparam int unsigned DataWidth = 32'd45;
typedef logic [IdxWidth-1:0] idx_t;
typedef logic [DataWidth-1:0] data_t;
logic clk;
logic rst_n;
logic flush;
idx_t rr, idx;
logic [NumInp-1:0] req_inp, gnt_inp, end_of_sim;
data_t [NumInp-1:0] data_inp;
logic req_oup, gnt_oup;
data_t data_oup;
clk_rst_gen #(
.ClkPeriod ( CyclTime ),
.RstClkCycles ( 5 )
) i_clk_rst_gen (
.clk_o ( clk ),
.rst_no ( rst_n )
);
for (genvar i = 0; i < NumInp; i++) begin : gen_stream_gen
initial begin : proc_stream_gen
automatic data_t stimuli;
automatic int unsigned rand_wait;
end_of_sim[i] = 1'b0;
@(posedge rst_n);
data_inp[i] = '0;
req_inp[i] = 1'b0;
for (int unsigned j = 0; j < (i+1) * NumReqs; j++) begin
data_inp[i] <= #ApplTime data_t'(i);
req_inp[i] <= #ApplTime 1'b1;
@(posedge clk);
end
data_inp[i] <= #ApplTime '0;
req_inp[i] <= #ApplTime 1'b0;
repeat ((NumInp-i)*NumReqs) @(posedge clk);
repeat (1000) @(posedge clk);
for (int unsigned j = 0; j < (NumInp-i) * NumReqs; j++) begin
data_inp[i] <= #ApplTime data_t'(i);
req_inp[i] <= #ApplTime 1'b1;
@(posedge clk);
end
data_inp[i] <= #ApplTime '0;
req_inp[i] <= #ApplTime 1'b0;
repeat ((1+i)*NumReqs) @(posedge clk);
repeat (1000) @(posedge clk);
for (int unsigned j = 0; j < (NumInp-i) * NumReqs; j++) begin
if ((i % 2) == 0) begin
data_inp[i] <= #ApplTime data_t'(i);
req_inp[i] <= #ApplTime 1'b1;
end
@(posedge clk);
end
data_inp[i] <= #ApplTime '0;
req_inp[i] <= #ApplTime 1'b0;
repeat ((1+i)*NumReqs) @(posedge clk);
repeat (1000) @(posedge clk);
for (int unsigned j = 0; j < NumReqs; j++) begin
data_inp[i] <= #ApplTime new_stimuli();
req_inp[i] <= #ApplTime 1'b1;
rand_wait = $urandom_range(1, 2*NumInp);
if (LockIn) begin
#TestTime;
while (!gnt_inp[i]) begin
@(posedge clk);
#TestTime;
end
end else begin
repeat (rand_wait) @(posedge clk);
end
@(posedge clk);
data_inp[i] <= #ApplTime '0;
req_inp[i] <= #ApplTime 1'b0;
rand_wait = $urandom_range(0, NumInp);
repeat (rand_wait) @(posedge clk);
end
end_of_sim[i] = 1'b1;
end
end
function data_t new_stimuli();
for (int unsigned i = 0; i < DataWidth; i++) begin
new_stimuli[i] = $urandom();
end
endfunction : new_stimuli
initial begin : proc_stream_consume
@(posedge rst_n);
gnt_oup = 1'b0;
forever begin
gnt_oup <= #ApplTime 1'b1;
@(posedge clk);
end
end
initial begin : proc_flush
automatic int unsigned rand_wait;
flush = 1'b0;
@(posedge rst_n);
forever begin
rand_wait = $urandom_range(2000, 20000);
repeat (rand_wait) @(posedge clk);
flush <= #ApplTime 1'b1;
@(posedge clk);
flush <= #ApplTime 1'b0;
end
end
initial begin : proc_sim_end
@(posedge rst_n);
wait (&end_of_sim);
repeat (10) @(posedge clk);
$stop();
end
for (genvar i = 0; i < NumInp; i++) begin : gen_throughput_checker
initial begin : proc_throughput_checker
automatic longint unsigned tot_active [NumInp:1];
automatic longint unsigned tot_served [NumInp:1];
automatic int unsigned num_active;
automatic real throughput, exp_through, error;
for (int unsigned j = 0; j < NumInp; j++) begin
tot_active[j] = 0;
tot_served[j] = 0;
end
@(posedge rst_n);
while (!(&end_of_sim)) begin
#TestTime;
if (req_inp[i] && gnt_oup) begin
num_active = 0;
for (int unsigned j = 0; j < NumInp; j++) begin
if (req_inp[j]) begin
num_active++;
end
end
tot_active[num_active] = tot_active[num_active] + 1;
if (gnt_inp[i]) begin
tot_served[num_active] = tot_served[num_active] + 1;
end
end
@(posedge clk);
end
for (int unsigned j = 1; j <= NumInp; j++) begin
if (tot_active[j] > 0) begin
throughput = real'(tot_served[j])/real'(tot_active[j]);
exp_through = real'(1)/real'(j);
error = throughput - exp_through;
if (FairArb && LockIn) begin
assert(error < error_threshold && error > -error_threshold) else
$warning("Line: %0d is unfair!", i);
end
$display("Line: %0d, TotActice: %0d Throughput: %0f Ideal: %0f Diff: %0f",
i, j, throughput, exp_through, error); end
end
end
end
initial begin : proc_check_data
automatic data_t data_queues[NumInp-1:0][$];
automatic data_t exp_data;
forever begin
@(posedge clk);
#TestTime;
for (int unsigned i = 0; i < NumInp; i++) begin
if (req_inp[i] && gnt_inp[i]) begin
data_queues[i].push_back(data_inp[i]);
end
end
if (req_oup && gnt_oup) begin
exp_data = data_queues[idx].pop_front();
assert(exp_data === data_oup);
end
end
end
rr_arb_tree #(
.NumIn ( NumInp ),
.DataWidth ( DataWidth ),
.ExtPrio ( 1'b0 ),
.AxiVldRdy ( AxiVldRdy ),
.LockIn ( LockIn ),
.FairArb ( FairArb )
) i_rr_arb_tree_dut (
.clk_i ( clk ),
.rst_ni ( rst_n ),
.flush_i( flush ),
.rr_i ( '0 ),
.req_i ( req_inp ),
.gnt_o ( gnt_inp ),
.data_i ( data_inp ),
.gnt_i ( gnt_oup ),
.req_o ( req_oup ),
.data_o ( data_oup ),
.idx_o ( idx )
);
endmodule
`begin_keywords "1800-2023"
package stream_test;
class stream_driver #(
parameter type payload_t = logic,
parameter time TA = 2ns,
parameter time TT = 8ns
);
virtual STREAM_DV #(
.payload_t (payload_t)
) stream;
function new (
virtual STREAM_DV #(
.payload_t (payload_t)
) stream
);
this.stream = stream;
endfunction
function void reset_in();
stream.valid = 1'b0;
endfunction
function void reset_out();
stream.ready = 1'b0;
endfunction
task automatic cycle_start;
#TT;
endtask
task automatic cycle_end;
@(posedge stream.clk_i);
endtask
task automatic send (input payload_t data);
stream.data <= #TA data;
stream.valid <= #TA 1'b1;
cycle_start();
while (stream.ready != 1) begin cycle_end(); cycle_start(); end
cycle_end();
stream.valid <= #TA 1'b0;
endtask
task automatic recv(output payload_t data);
stream.ready <= #TA 1'b1;
cycle_start();
while (stream.valid != 1) begin cycle_end(); cycle_start(); end
data = stream.data;
cycle_end();
stream.ready <= #TA 1'b0;
endtask
endclass
endpackage
`begin_keywords "1800-2023"
module stream_register_tb #(
parameter type T = logic[7:0]
);
logic clk,
rst_n,
clr,
inp_valid, inp_ready,
oup_valid, oup_ready;
T inp_data,
oup_data;
int unsigned nr_checks;
stream_register #(
.T (T)
) dut (
.clk_i (clk),
.rst_ni (rst_n),
.clr_i (clr),
.testmode_i (1'b0),
.valid_i (inp_valid),
.ready_o (inp_ready),
.data_i (inp_data),
.valid_o (oup_valid),
.ready_i (oup_ready),
.data_o (oup_data)
);
initial begin
clk = 1'b0;
rst_n = 1'b0;
repeat(8)
#10ns clk = ~clk;
rst_n = 1'b1;
forever
#10ns clk = ~clk;
end
initial begin
#100ms
$display("Checked %d stimuli", nr_checks);
$stop;
end
class random_action_t;
rand logic [1:0] action;
constraint random_action {
action dist {
0 := 40,
1 := 40,
3 := 2,
0 := 0
};
}
endclass
logic[7:0] queue [$];
clocking cb @(posedge clk);
default input #2 output #4;
output clr, inp_data, inp_valid, oup_ready;
input inp_ready, oup_valid, oup_data;
endclocking
clocking pck @(posedge clk);
default input #2 output #4;
input clr, inp_data, inp_valid, inp_ready, oup_data, oup_valid, oup_ready;
endclocking
initial begin
automatic random_action_t random_action = new();
cb.clr <= 1'b0;
wait (rst_n == 1'b1);
cb.inp_valid <= 1'b0;
forever begin
void'(random_action.randomize());
repeat($urandom_range(0, 8)) @(cb);
case (random_action.action)
0: begin
cb.inp_data <= $urandom_range(0,256);
cb.inp_valid <= 1'b1;
end
1: begin
cb.clr <= 1'b0;
cb.inp_data <= $urandom_range(0,256);
cb.inp_valid <= 1'b0;
end
default: begin
cb.clr <= 1'b1;
cb.inp_valid <= 1'b0;
@(cb);
cb.clr <= 1'b0;
end
endcase
end
end
initial begin
wait (rst_n == 1'b1);
forever begin
@(cb)
cb.oup_ready <= 1'b1;
repeat($urandom_range(0, 8)) @(cb);
cb.oup_ready <= 1'b0;
end
end
initial begin
automatic T data;
nr_checks = 0;
forever begin
@(pck)
if (pck.inp_valid && pck.inp_ready && !pck.clr) begin
queue.push_back(pck.inp_data);
end
if (pck.oup_valid && pck.oup_ready) begin
data = queue.pop_front();
assert(data == pck.oup_data)
else $error("Mismatch, Expected: %0h Got %0h", data, pck.oup_data);
nr_checks++;
end
if (pck.clr) begin
queue = {};
end
end
end
endmodule
`begin_keywords "1800-2023"
module stream_to_mem_tb #(
parameter int unsigned NumReq = 32'd10000,
parameter int unsigned BufDepth = 32'd1
);
localparam time CyclTime = 10ns;
localparam time ApplTime = 2ns;
localparam time TestTime = 8ns;
typedef logic [15:0] payload_t;
logic clk, rst_n, sim_done;
payload_t req, resp, mem_req, mem_resp;
logic req_valid, resp_valid, mem_req_valid, mem_resp_valid;
logic req_ready, resp_ready, mem_req_ready;
payload_t data_fifo[$];
initial begin : proc_stream_master
automatic payload_t test_data;
automatic int unsigned stall_cycles;
@(posedge rst_n);
req = '0;
req_valid = '0;
repeat (5) @(posedge clk);
for (int unsigned i = 0; i < NumReq; i++) begin
stall_cycles = $urandom_range(0, 5);
repeat (stall_cycles) @(posedge clk);
test_data = payload_t'($urandom());
data_fifo.push_back(test_data);
req <= #ApplTime payload_t'(test_data);
req_valid <= #ApplTime 1'b1;
#TestTime;
while (!req_ready) begin
@(posedge clk);
#TestTime;
end
@(posedge clk);
req <= #ApplTime '0;
req_valid <= #ApplTime 1'b0;
end
end
initial begin : proc_stream_slave
automatic int unsigned stall_cycles;
automatic payload_t test_data;
automatic int unsigned num_tested = 32'd0;
sim_done = 0;
@(posedge rst_n);
resp_ready = '0;
repeat (5) @(posedge clk);
while (num_tested < NumReq) begin
resp_ready <= #ApplTime $urandom();
#TestTime;
if (resp_valid && resp_ready) begin
test_data = data_fifo.pop_front();
assert(test_data === resp) else $error("test_data: %h, resp_data: %0h", test_data, resp);
num_tested++;
end
@(posedge clk);
end
repeat (50) @(posedge clk);
sim_done = 1'b1;
end
initial begin : proc_mem_reflect
automatic payload_t reflect_fifo[$];
@(posedge rst_n);
mem_req_ready = '0;
mem_resp = '0;
mem_resp_valid = '0;
forever begin
mem_req_ready <= #ApplTime $urandom();
#(CyclTime / 2);
if (mem_req_valid && mem_req_ready) begin
reflect_fifo.push_back(mem_req);
fork
begin
if (BufDepth) begin
repeat (BufDepth) @(posedge clk);
#ApplTime;
end
mem_resp = reflect_fifo.pop_front();
mem_resp_valid = 1'b1;
@(posedge clk);
#(ApplTime / 2);
mem_resp_valid = 1'b0;
end
join_none
end
@(posedge clk);
end
end
initial begin : proc_sim_stop
@(posedge rst_n);
wait (sim_done);
$stop();
end
clk_rst_gen #(
.ClkPeriod ( CyclTime ),
.RstClkCycles ( 10 )
) i_clk_rst_gen (
.clk_o ( clk ),
.rst_no ( rst_n )
);
stream_to_mem #(
.mem_req_t ( payload_t ),
.mem_resp_t ( payload_t ),
.BufDepth ( BufDepth )
) i_stream_to_mem_dut (
.clk_i ( clk ),
.rst_ni ( rst_n ),
.req_i ( req ),
.req_valid_i ( req_valid ),
.req_ready_o ( req_ready ),
.resp_o ( resp ),
.resp_valid_o ( resp_valid ),
.resp_ready_i ( resp_ready ),
.mem_req_o ( mem_req ),
.mem_req_valid_o ( mem_req_valid ),
.mem_req_ready_i ( mem_req_ready ),
.mem_resp_i ( mem_resp ),
.mem_resp_valid_i ( mem_resp_valid )
);
endmodule
`begin_keywords "1800-2023"
module sub_per_hash_tb;
localparam time TCycle = 10ns;
localparam time TAppli = 2ns;
localparam time TTest = 8ns;
localparam longint unsigned MaxCycles = 64'd100000000;
localparam int unsigned DataWidth = 32'd11;
localparam int unsigned HashWidth = 32'd5;
localparam int unsigned NoHashes = 32'd3;
localparam int unsigned NoRounds = 32'd1;
typedef logic [DataWidth-1:0] data_t;
typedef logic [HashWidth-1:0] hash_t;
typedef logic [2**HashWidth-1:0] onehot_hash_t;
localparam cb_filter_pkg::cb_seed_t [NoHashes-1:0] Seeds = '{
'{PermuteSeed: 32'd299034753, XorSeed: 32'd4094834 },
'{PermuteSeed: 32'd19921030, XorSeed: 32'd995713 },
'{PermuteSeed: 32'd294388, XorSeed: 32'd65146511}
};
logic clk;
logic rst_n;
data_t data;
hash_t [NoHashes-1:0] hash;
onehot_hash_t [NoHashes-1:0] onehot_hash;
clk_rst_gen #(
.ClkPeriod ( TCycle ),
.RstClkCycles ( 1 )
) i_clk_gen (
.clk_o ( clk ),
.rst_no ( rst_n )
);
initial begin : shutdown_sim
repeat (MaxCycles) @(posedge clk);
$info("Stop, because max cycles was reached.");
$stop();
end
initial begin : stimulus
set_data(0);
@(posedge rst_n);
repeat (10) @(posedge clk);
for (longint unsigned i = 0; i < 2**DataWidth; i++) begin
set_data(i);
end
repeat (10) @(posedge clk);
$info("Stop, because all possible inputs were applied.");
$stop();
end
task cycle_start();
#TTest;
endtask : cycle_start
task cycle_end();
@(posedge clk);
endtask : cycle_end
task set_data (input longint unsigned nbr);
data <= #TAppli data_t'(nbr);
cycle_end();
endtask : set_data
task init_signals();
data <= '0;
endtask : init_signals
for (genvar i = 0; i < NoHashes; i++) begin : gen_hash_dut
sub_per_hash #(
.InpWidth ( DataWidth ),
.HashWidth ( HashWidth ),
.NoRounds ( NoRounds ),
.PermuteKey ( Seeds[i].PermuteSeed ),
.XorKey ( Seeds[i].XorSeed )
) i_hash (
.data_i ( data ),
.hash_o ( hash[i] ),
.hash_onehot_o ( onehot_hash[i] )
);
end
endmodule
`begin_keywords "1800-2023"
module isochronous_crossing_tb #(
parameter int unsigned NumReq = 32'd10000,
parameter string DUT = "spill_register",
parameter int unsigned TCK_SRC_MULT = 2,
parameter int unsigned TCK_DST_MULT = 6
);
localparam time CyclTime = 10ns;
logic src_clk, dst_clk;
logic src_rst_n, dst_rst_n;
logic sim_done;
typedef logic [15:0] payload_t;
payload_t data_fifo[$];
mailbox #(payload_t) data_mbx = new();
STREAM_DV #(
.payload_t (payload_t)
) dut_in (
.clk_i (src_clk)
);
STREAM_DV #(
.payload_t (payload_t)
) dut_out (
.clk_i (dst_clk)
);
typedef stream_test::stream_driver #(
.payload_t (payload_t),
.TA (TCK_SRC_MULT*CyclTime*0.2),
.TT (TCK_SRC_MULT*CyclTime*0.8)
) stream_driver_in_t;
typedef stream_test::stream_driver #(
.payload_t (payload_t),
.TA (TCK_DST_MULT*CyclTime*0.2),
.TT (TCK_DST_MULT*CyclTime*0.8)
) stream_driver_out_t;
stream_driver_in_t in_driver = new(dut_in);
stream_driver_out_t out_driver = new(dut_out);
int unsigned handshake_mst = 0;
int unsigned handshake_slv = 0;
initial begin : proc_stream_master
automatic payload_t test_data;
automatic int unsigned stall_cycles;
in_driver.reset_in();
@(posedge src_rst_n);
repeat (5) @(posedge src_clk);
for (int unsigned i = 0; i < NumReq; i++) begin
test_data = payload_t'($urandom());
stall_cycles = $urandom_range(0, 5);
handshake_mst++;
repeat (stall_cycles) @(posedge src_clk);
in_driver.send(test_data);
data_mbx.put(test_data);
end
end
initial begin : proc_stream_slave
automatic int unsigned stall_cycles;
automatic payload_t expected, actual;
automatic int unsigned num_tested = 32'd0;
sim_done = 0;
out_driver.reset_out();
@(posedge dst_rst_n);
repeat (5) @(posedge dst_clk);
while (num_tested < NumReq) begin
stall_cycles = $urandom_range(0, 5);
repeat (stall_cycles) @(posedge dst_clk);
out_driver.recv(actual);
data_mbx.get(expected);
handshake_slv++;
assert(expected === actual) else $error("expected: %h, actual: %0h", expected, actual);
num_tested++;
end
repeat (50) @(posedge dst_clk);
sim_done = 1'b1;
assert(handshake_mst == handshake_slv) else $error("Amount of handshakes differed.");
end
initial begin : proc_sim_stop
@(posedge src_rst_n);
wait (sim_done);
$stop();
end
initial begin
$display("Simulating %d", DUT);
src_clk = 1'b0;
dst_clk = 1'b0;
forever begin
fork
forever begin
src_clk = ~src_clk;
#((CyclTime * TCK_SRC_MULT) / 2);
end
forever begin
dst_clk = ~dst_clk;
#((CyclTime * TCK_DST_MULT) / 2);
end
join
end
end
initial begin
static int unsigned rst_cnt = 0;
src_rst_n = 1'b0;
while (rst_cnt <= 10) begin
@(posedge src_clk);
rst_cnt++;
end
src_rst_n = 1'b1;
end
initial begin
static int unsigned rst_cnt = 0;
dst_rst_n = 1'b0;
while (rst_cnt <= 10) begin
@(posedge src_clk);
rst_cnt++;
end
dst_rst_n = 1'b1;
end
if (DUT == "spill_register") begin
isochronous_spill_register #(
.T (payload_t)
) i_isochronous_spill_register (
.src_clk_i (dut_in.clk_i),
.src_rst_ni (src_rst_n),
.src_valid_i (dut_in.valid),
.src_ready_o (dut_in.ready),
.src_data_i (dut_in.data),
.dst_clk_i (dut_out.clk_i),
.dst_rst_ni (dst_rst_n),
.dst_valid_o (dut_out.valid),
.dst_ready_i (dut_out.ready),
.dst_data_o (dut_out.data)
);
end if (DUT == "4phase_handshake") begin
isochronous_4phase_handshake
isochronous_4phase_handshake (
.src_clk_i (dut_in.clk_i),
.src_rst_ni (src_rst_n),
.src_valid_i (dut_in.valid),
.src_ready_o (dut_in.ready),
.dst_clk_i (dut_out.clk_i),
.dst_rst_ni (dst_rst_n),
.dst_valid_o (dut_out.valid),
.dst_ready_i (dut_out.ready)
);
always_ff @(posedge dut_in.clk_i)
if (dut_in.valid & dut_in.ready)
dut_out.data <= dut_in.data;
end
endmodule
`begin_keywords "1800-2023"
module stream_omega_net_tb #(
parameter int unsigned NumReq = 32'd20000,
parameter int unsigned DutNumInp = 32'd10,
parameter int unsigned DutNumOut = 32'd10,
parameter int unsigned DutRadix = 32'd2,
parameter bit DutSpillReg = 1'b0,
parameter time CyclTime = 20ns
);
localparam OutSelWidth = (DutNumOut > 32'd1) ? unsigned'($clog2(DutNumOut)) : 32'd1;
localparam InpIdxWidth = (DutNumInp > 32'd1) ? unsigned'($clog2(DutNumInp)) : 32'd1;
typedef logic [OutSelWidth-1:0] sel_t;
typedef logic [InpIdxWidth-1:0] idx_t;
typedef struct packed {
logic [15:0] payload;
idx_t index;
} payload_t;
logic clk;
logic rst_n;
logic flush;
logic [DutNumInp-1:0] sim_done;
assign flush = 1'b0;
clk_rst_gen #(
.ClkPeriod ( CyclTime ),
.RstClkCycles ( 5 )
) i_clk_rst_gen (
.clk_o ( clk ),
.rst_no ( rst_n )
);
payload_t data_fifo [DutNumInp-1:0][DutNumOut-1:0][$];
typedef stream_test::stream_driver #(
.payload_t (payload_t),
.TA (CyclTime*0.2),
.TT (CyclTime*0.8)
) stream_driver_in_t;
typedef stream_test::stream_driver #(
.payload_t (payload_t),
.TA (CyclTime*0.2),
.TT (CyclTime*0.8)
) stream_driver_out_t;
payload_t [DutNumInp-1:0] inp_data;
logic [DutNumInp-1:0] inp_valid, inp_ready;
sel_t [DutNumInp-1:0] out_sel;
for (genvar i = 0; i < DutNumInp; i++) begin : gen_inp
STREAM_DV #(
.payload_t (payload_t)
) dut_in (
.clk_i (clk)
);
assign inp_data[i] = dut_in.data;
assign inp_valid[i] = dut_in.valid;
assign dut_in.ready = inp_ready[i];
stream_driver_in_t in_driver = new(dut_in);
initial begin : proc_source
automatic payload_t data;
automatic int unsigned wait_cycl;
data.index = idx_t'(i);
@(posedge rst_n);
in_driver.reset_in();
out_sel[i] = 1'b0;
sim_done[i] = 1'b0;
for (int unsigned i_stim = 0; i_stim < (NumReq/DutNumInp); i_stim++) begin
wait_cycl = $urandom_range(0, 5);
repeat (wait_cycl) @(posedge clk);
data.payload = $urandom();
out_sel[i] = sel_t'($urandom_range(0, DutNumOut-1));
data_fifo[i][out_sel[i]].push_back(data);
in_driver.send(data);
end
sim_done[i] = 1'b1;
end
end
payload_t [DutNumOut-1:0] out_data;
logic [DutNumOut-1:0] out_valid, out_ready;
idx_t [DutNumOut-1:0] out_idx;
for (genvar j = 0; j < DutNumOut; j++) begin : gen_out
STREAM_DV #(
.payload_t (payload_t)
) dut_out (
.clk_i (clk)
);
assign dut_out.data = out_data[j];
assign dut_out.valid = out_valid[j];
assign out_ready[j] = dut_out.ready;
stream_driver_out_t out_driver = new(dut_out);
initial begin : proc_sink
automatic payload_t data, exp;
automatic int unsigned wait_cycl;
@(posedge rst_n);
out_driver.reset_out();
forever begin
wait_cycl = $urandom_range(0, 5);
repeat (wait_cycl) @(posedge clk);
out_driver.recv(data);
exp = data_fifo[out_idx[j]][j].pop_front();
assert(data == exp) else
$error("Out %d: Payload data does not match. Observed: %0h Expected: %0h", j, data, exp);
assert(data.index == out_idx[j]) else
$error("Index in payload: %0d does not match idx_o[%0d]: %0d", data.index, j, out_idx[j]);
end
end
end
initial begin : proc_stop_sim
@(posedge rst_n);
wait (&sim_done);
repeat (20) @(posedge clk);
$display("Sim done.");
$stop();
end
stream_omega_net #(
.NumInp ( DutNumInp ),
.NumOut ( DutNumOut ),
.payload_t ( payload_t ),
.SpillReg ( DutSpillReg ),
.Radix ( DutRadix ),
.ExtPrio ( 1'b0 ),
.AxiVldRdy ( 1'b1 ),
.LockIn ( 1'b1 )
) i_stream_omega_net_dut (
.clk_i ( clk ),
.rst_ni ( rst_n ),
.flush_i ( flush ),
.rr_i ( '0 ),
.data_i ( inp_data ),
.sel_i ( out_sel ),
.valid_i ( inp_valid ),
.ready_o ( inp_ready ),
.data_o ( out_data ),
.idx_o ( out_idx ),
.valid_o ( out_valid ),
.ready_i ( out_ready )
);
endmodule
`begin_keywords "1800-2023"
module stream_xbar_tb #(
parameter int unsigned NumReq = 32'd10000,
parameter int unsigned NumInp = 32'd10,
parameter int unsigned NumOut = 32'd10,
parameter bit SpillReg = 1'b0,
parameter time CyclTime = 20ns
);
localparam OutSelWidth = (NumOut > 32'd1) ? unsigned'($clog2(NumOut)) : 32'd1;
localparam InpIdxWidth = (NumInp > 32'd1) ? unsigned'($clog2(NumInp)) : 32'd1;
typedef logic [OutSelWidth-1:0] sel_t;
typedef logic [InpIdxWidth-1:0] idx_t;
typedef struct packed {
logic [15:0] payload;
idx_t index;
} payload_t;
logic clk;
logic rst_n;
logic flush;
logic [NumInp-1:0] sim_done;
assign flush = 1'b0;
clk_rst_gen #(
.ClkPeriod ( CyclTime ),
.RstClkCycles ( 5 )
) i_clk_rst_gen (
.clk_o ( clk ),
.rst_no ( rst_n )
);
payload_t data_fifo [NumInp-1:0][NumOut-1:0][$];
typedef stream_test::stream_driver #(
.payload_t (payload_t),
.TA (CyclTime*0.2),
.TT (CyclTime*0.8)
) stream_driver_in_t;
typedef stream_test::stream_driver #(
.payload_t (payload_t),
.TA (CyclTime*0.2),
.TT (CyclTime*0.8)
) stream_driver_out_t;
payload_t [NumInp-1:0] inp_data;
logic [NumInp-1:0] inp_valid, inp_ready;
sel_t [NumInp-1:0] out_sel;
for (genvar i = 0; i < NumInp; i++) begin : gen_inp
STREAM_DV #(
.payload_t (payload_t)
) dut_in (
.clk_i (clk)
);
assign inp_data[i] = dut_in.data;
assign inp_valid[i] = dut_in.valid;
assign dut_in.ready = inp_ready[i];
stream_driver_in_t in_driver = new(dut_in);
initial begin : proc_source
automatic payload_t data;
automatic int unsigned wait_cycl;
data.index = idx_t'(i);
@(posedge rst_n);
in_driver.reset_in();
out_sel[i] = 1'b0;
sim_done[i] = 1'b0;
for (int unsigned i_stim = 0; i_stim < NumReq; i_stim++) begin
wait_cycl = $urandom_range(0, 5);
repeat (wait_cycl) @(posedge clk);
data.payload = $urandom();
out_sel[i] = sel_t'($urandom_range(0, NumOut-1));
data_fifo[i][out_sel[i]].push_back(data);
in_driver.send(data);
end
sim_done[i] = 1'b1;
end
end
payload_t [NumOut-1:0] out_data;
logic [NumOut-1:0] out_valid, out_ready;
idx_t [NumOut-1:0] out_idx;
for (genvar j = 0; j < NumOut; j++) begin : gen_out
STREAM_DV #(
.payload_t (payload_t)
) dut_out (
.clk_i (clk)
);
assign dut_out.data = out_data[j];
assign dut_out.valid = out_valid[j];
assign out_ready[j] = dut_out.ready;
stream_driver_out_t out_driver = new(dut_out);
initial begin : proc_sink
automatic payload_t data, exp;
automatic int unsigned wait_cycl;
@(posedge rst_n);
out_driver.reset_out();
forever begin
wait_cycl = $urandom_range(0, 5);
repeat (wait_cycl) @(posedge clk);
out_driver.recv(data);
exp = data_fifo[out_idx[j]][j].pop_front();
assert(data == exp) else
$error("Out %d: Payload data does not match. Observed: %0h Expected: %0h", j, data, exp);
assert(data.index == out_idx[j]) else
$error("Index in payload: %0d does not match idx_o[%0d]: %0d", data.index, j, out_idx[j]);
end
end
end
initial begin : proc_stop_sim
@(posedge rst_n);
wait (&sim_done);
repeat (20) @(posedge clk);
$display("Sim done.");
$stop();
end
stream_xbar #(
.NumInp ( NumInp ),
.NumOut ( NumOut ),
.payload_t ( payload_t ),
.OutSpillReg ( SpillReg ),
.ExtPrio ( 1'b0 ),
.AxiVldRdy ( 1'b1 ),
.LockIn ( 1'b1 )
) i_stream_xbar_dut (
.clk_i ( clk ),
.rst_ni ( rst_n ),
.flush_i ( flush ),
.rr_i ( '0 ),
.data_i ( inp_data ),
.sel_i ( out_sel ),
.valid_i ( inp_valid ),
.ready_o ( inp_ready ),
.data_o ( out_data ),
.idx_o ( out_idx ),
.valid_o ( out_valid ),
.ready_i ( out_ready )
);
endmodule
`begin_keywords "1800-2023"
module clk_int_div_tb;
import stream_test::*;
parameter int unsigned NumTests = 10000;
parameter time TClkIn = 10ns;
parameter int DivWidth = 3;
parameter int MaxWaitCycles = 20;
localparam time t_delta = 1ns;
localparam int unsigned RstClkCycles = 10;
localparam time TA = TClkIn*0.2;
localparam time TT = TClkIn*0.8;
localparam clock_disable_probability = 5;
logic clk, rstn;
logic test_mode_en;
logic enable;
logic clk_out;
semaphore semphr_is_transitioning;
bit is_transitioning = 1'b0;
int wait_cycl;
time target_tclk_half_max;
time target_tclk_half_min;
logic [DivWidth-1:0] current_div_value;
logic [DivWidth-1:0] next_div_value;
time last_rising_edge;
time last_falling_edge;
int error_count = 0;
typedef logic [DivWidth-1:0] payload_t;
let max(a,b) = (a > b) ? a : b;
let min(a,b) = (a < b) ? a : b;
typedef stream_test::stream_driver #(
.payload_t (payload_t),
.TA (TA),
.TT (TT)
) stream_driver_t;
STREAM_DV #(
.payload_t (payload_t)
) dut_in (
.clk_i (clk)
);
stream_driver_t in_driver = new(dut_in);
clk_rst_gen #(
.ClkPeriod ( TClkIn ),
.RstClkCycles ( RstClkCycles )
) i_clk_rst_gen_reg (
.clk_o ( clk ),
.rst_no ( rstn )
);
clk_int_div #(
.DIV_VALUE_WIDTH(DivWidth)
) i_dut(
.clk_i ( clk ),
.rst_ni ( rstn ),
.en_i ( enable ),
.test_mode_en_i ( test_mode_en ),
.div_i ( dut_in.data ),
.div_valid_i ( dut_in.valid ),
.div_ready_o ( dut_in.ready ),
.clk_o ( clk_out ),
.cycl_count_o ( )
);
initial begin : apply_stimuli
semphr_is_transitioning = new();
test_mode_en = 1'b0;
enable = 1'b1;
next_div_value = 1;
current_div_value = 1;
$info("Resetting clock divider...");
@(posedge rstn);
in_driver.reset_in();
test_mode_en = 1'b1;
semphr_is_transitioning.put();
repeat (100) @(clk);
test_mode_en = 1'b0;
$info("Testing programming divider while clock disabled...");
enable = 1'b0;
next_div_value = 3;
semphr_is_transitioning.put(1);
wait_cycl = $urandom_range(5*current_div_value, MaxWaitCycles*current_div_value);
repeat(wait_cycl) @(posedge clk);
in_driver.send(next_div_value);
current_div_value = next_div_value;
semphr_is_transitioning.put(1);
@(posedge clk);
enable = 1'b1;
repeat(20) @(posedge clk);
$info("Starting randomized reconfiguration while clock is enabled...");
for (int i = 0; i < NumTests; i++) begin
logic [DivWidth-1:0] div_value_temp;
assert(std::randomize(div_value_temp)) else
$error("Randomization failure");
$info("Setting clock divider value to %0d", next_div_value);
next_div_value = (div_value_temp == 0)? 1: div_value_temp;
in_driver.send(div_value_temp);
semphr_is_transitioning.put(1);
current_div_value = next_div_value;
wait_cycl = $urandom_range(0, MaxWaitCycles);
repeat(wait_cycl) @(posedge clk_out);
if ($urandom_range(0, 100) < clock_disable_probability) begin
repeat(4) @(posedge clk_out);
enable = 1'b0;
semphr_is_transitioning.put(1);
wait_cycl = $urandom_range(5*current_div_value, MaxWaitCycles*current_div_value);
repeat(wait_cycl) @(posedge clk);
enable = 1'b1;
repeat(wait_cycl) @(posedge clk_out);
end
end
$info("Test finished");
$info("Total error count: %0d", error_count);
$stop();
end
initial begin : check_clock
last_rising_edge = $realtime();
last_falling_edge = $realtime();
target_tclk_half_max = TClkIn+t_delta;
target_tclk_half_min = TClkIn-t_delta;
@(posedge rstn);
forever begin
@(posedge clk_out);
is_transitioning = semphr_is_transitioning.try_get(1);
if (is_transitioning) begin
target_tclk_half_max = TClkIn*max(current_div_value, next_div_value)/2+t_delta;
target_tclk_half_min = TClkIn*min(current_div_value, next_div_value)/2-t_delta;
end else begin
target_tclk_half_max = TClkIn*current_div_value/2+t_delta;
target_tclk_half_min = TClkIn*current_div_value/2-t_delta;
assert($realtime()-last_falling_edge < target_tclk_half_max) else begin
$error("Detected wrong duty cycle. Target t_low period should be lower than %0t ns but was %0t ns", target_tclk_half_max, $realtime()-last_falling_edge);
error_count++;
end
end
assert($realtime()-last_falling_edge > target_tclk_half_min) else begin
$error("Detected clock glitch. Last low period was to short (%0t ns < %0t ns).", $realtime()-last_falling_edge, target_tclk_half_min);
error_count++;
end
last_rising_edge = $realtime();
@(negedge clk_out);
assert($realtime()-last_rising_edge > target_tclk_half_min) else begin
$error("Detected wrong duty cycle. Last high period was to short (%0t ns < %0t ns).", $realtime()-last_rising_edge, target_tclk_half_min);
error_count++;
end
assert($realtime()-last_rising_edge < target_tclk_half_max) else begin
$error("Detected wrong duty cycle. Last high period was to long (%0t ns > %0t ns).", $realtime()-last_rising_edge, target_tclk_half_max);
error_count++;
end
last_falling_edge = $realtime();
end
end
endmodule
`begin_keywords "1800-2023"
module clk_int_div_static_tb;
parameter int unsigned NumTestCycles = 10000;
parameter realtime TClkIn = 10ns;
localparam int unsigned RstClkCycles = 10;
localparam int unsigned MaxClkDiv = 100;
realtime t_delta = 100ps;
logic clk, rstn;
logic test_mode_en;
logic enable;
logic clk_out [MaxClkDiv];
clk_rst_gen #(
.ClkPeriod ( TClkIn ),
.RstClkCycles ( RstClkCycles )
) i_clk_rst_gen_reg (
.clk_o ( clk ),
.rst_no ( rstn )
);
for (genvar i = 1; i < MaxClkDiv; i++) begin :gen_clk_divs
clk_int_div_static #(
.DIV_VALUE(i),
.ENABLE_CLOCK_IN_RESET(1'b1)
) i_dut(
.clk_i ( clk ),
.rst_ni ( rstn ),
.en_i ( enable ),
.test_mode_en_i ( test_mode_en ),
.clk_o ( clk_out[i] )
);
end
initial begin : apply_stimuli
test_mode_en = 1'b0;
enable = 1'b1;
$info("Resetting clock dividers...");
@(posedge rstn);
repeat(NumTestCycles) begin
@(posedge clk);
if ($urandom_range(0, 1000)<5) begin
enable = 1'b0;
repeat($urandom_range(1, 100)) @(posedge clk);
enable = 1'b1;
end
end
$info("Test finished");
$stop();
end
endmodule
`begin_keywords "1800-2023"
module clk_mux_glitch_free_tb;
timeunit 1ns;
timeprecision 1ps;
parameter int unsigned NUM_INPUTS = 10;
localparam int unsigned SEL_WIDTH = $clog2(NUM_INPUTS);
parameter realtime MIN_PERIOD = 1ns;
parameter realtime MAX_PERIOD = 3ns;
parameter realtime TIME_RESOLUTION = 0.1ns;
parameter int TEST_LENGTH = 1000;
logic [SEL_WIDTH-1:0] s_sel = '0;
logic [NUM_INPUTS-1:0] s_clocks = '0;
logic s_rstn;
logic s_clock_output;
realtime target_periods [NUM_INPUTS-1:0];
int num_errors = 0;
task automatic delay_random(input realtime min_delay, input realtime max_delay);
int delay_int = $urandom_range($rtoi(min_delay/TIME_RESOLUTION), $rtoi(max_delay/TIME_RESOLUTION));
repeat(delay_int) #TIME_RESOLUTION;
endtask
for (genvar i = 0; i < NUM_INPUTS; i++) begin : gen_clocks
initial begin : clock_gen
automatic int period_int;
period_int = $urandom_range($rtoi(MIN_PERIOD/TIME_RESOLUTION), $rtoi(MAX_PERIOD/TIME_RESOLUTION));
target_periods[i] = period_int * TIME_RESOLUTION;
delay_random(0, MAX_PERIOD);
forever begin
s_clocks[i] = 1'b1;
repeat(period_int/2) #(TIME_RESOLUTION);
s_clocks[i] = 1'b0;
repeat(period_int/2) #(TIME_RESOLUTION);
end
end
end
initial begin : stimulate_sel_input
$info("Starting Test");
$info("Asserting hard reset");
s_rstn = 1'b0;
s_sel = $urandom_range(0, NUM_INPUTS-1);
delay_random(0, MAX_PERIOD*1000);
$info("Deasserting hard reset.");
s_rstn = 1'b1;
$info("Switching between clock inputs %0d times", TEST_LENGTH);
for (int i = 0; i < TEST_LENGTH; i++) begin
delay_random(MAX_PERIOD*10, MAX_PERIOD*30);
s_sel = $urandom_range(0, NUM_INPUTS-1);
end
repeat(10) @(posedge s_clock_output);
$info("Test finished with %0d errors.", num_errors);
$stop();
end
initial begin : check_clock
automatic realtime last_high_pulse_duration = 0ns;
automatic realtime last_low_pulse_duration = 0ns;
automatic realtime pulse_duraton = 0ns;
automatic realtime last_edge = 0ns;
$timeformat(-9, 3, "ns", 0);
forever begin
@(posedge s_clock_output);
pulse_duraton = $realtime - last_edge;
if ((((last_low_pulse_duration - pulse_duraton) < 0 )? -(last_low_pulse_duration - pulse_duraton) : (last_low_pulse_duration - pulse_duraton)) > TIME_RESOLUTION) begin
assert(pulse_duraton + TIME_RESOLUTION >= target_periods[s_sel]/2) else
$error("Error #%0d: Clock low pulse duration was %t but should be larger than %t", num_errors++, pulse_duraton, target_periods[s_sel]/2);
end
last_edge = $realtime;
last_low_pulse_duration = pulse_duraton;
@(negedge s_clock_output);
pulse_duraton = $realtime - last_edge;
if ((((last_high_pulse_duration - pulse_duraton) < 0 )? -(last_high_pulse_duration - pulse_duraton) : (last_high_pulse_duration - pulse_duraton)) > TIME_RESOLUTION) begin
assert( (((pulse_duraton - target_periods[s_sel]/2) < 0 )? -(pulse_duraton - target_periods[s_sel]/2) : (pulse_duraton - target_periods[s_sel]/2)) <= TIME_RESOLUTION) else
$error("Error #%0d: Clock high pulse duration was %t but should be equal to %t", num_errors++, pulse_duraton, target_periods[s_sel]/2);
end
last_edge = $realtime;
last_high_pulse_duration = pulse_duraton;
end
end
clk_mux_glitch_free #(
.NUM_INPUTS(NUM_INPUTS)
) i_dut (
.clks_i ( s_clocks ),
.test_clk_i ( 1'b0 ),
.test_en_i ( 1'b0 ),
.async_rstn_i ( s_rstn ),
.async_sel_i ( s_sel ),
.clk_o ( s_clock_output )
);
endmodule
`begin_keywords "1800-2023"
module lossy_valid_to_stream_tb #(
parameter int unsigned NumReq = 32'd10000,
parameter time CyclTime = 20ns
);
logic clk;
logic rst_n;
localparam type payload_t = logic [$clog2(NumReq)-1:0];
clk_rst_gen #(
.ClkPeriod (CyclTime),
.RstClkCycles(5)
) i_clk_rst_gen (
.clk_o (clk),
.rst_no(rst_n)
);
typedef stream_test::stream_driver#(
.payload_t(payload_t),
.TA(CyclTime * 0.2),
.TT(CyclTime * 0.8)
) stream_driver_in_t;
STREAM_DV #(.payload_t(payload_t)) dut_in (.clk_i(clk));
stream_driver_in_t stream_source = new(dut_in);
typedef stream_test::stream_driver#(
.payload_t(payload_t),
.TA(CyclTime * 0.2),
.TT(CyclTime * 0.8)
) stream_driver_out_t;
STREAM_DV #(.payload_t(payload_t)) dut_out (.clk_i(clk));
stream_driver_out_t stream_sink = new(dut_out);
payload_t payload_queue[$];
logic is_busy;
assign dut_in.ready = 1'b1;
lossy_valid_to_stream #(
.T(payload_t)
) i_lossy_valid_to_stream (
.clk_i (clk),
.rst_ni (rst_n),
.valid_i(dut_in.valid),
.data_i (dut_in.data),
.data_o (dut_out.data),
.valid_o(dut_out.valid),
.ready_i(dut_out.ready),
.busy_o(is_busy)
);
initial begin : apply_stimuli
automatic int unsigned wait_cycl;
@(posedge rst_n);
stream_source.reset_in();
for (int i = 0; i < NumReq; i++) begin
wait_cycl = $urandom_range(0, 5);
repeat (wait_cycl) @(posedge clk);
stream_source.send(i);
if (payload_queue.size() == 2 && !dut_out.ready)
payload_queue[0] = i;
else
payload_queue.push_front(i);
end
$stop();
end
initial begin : receive_responses
automatic payload_t data;
automatic payload_t expected_data;
automatic int unsigned wait_cycl;
@(posedge rst_n);
stream_sink.reset_out();
forever begin
wait_cycl = $urandom_range(0, 5);
repeat (wait_cycl) @(posedge clk);
stream_sink.recv(data);
assert (payload_queue.size() > 0) else
$error("Receieved transaction at output even though the input side did not send any new data.");
expected_data = payload_queue.pop_back();
assert (data == expected_data) else
$error("Received the wrong data.x Was %d instead of %d", data, expected_data);
end
end
endmodule
`begin_keywords "1800-2023"
module clock_divider_counter
#(
parameter BYPASS_INIT = 1,
parameter DIV_INIT = 'hFF
)
(
input logic clk,
input logic rstn,
input logic test_mode,
input logic [7:0] clk_div,
input logic clk_div_valid,
output logic clk_out
);
logic [7:0] counter;
logic [7:0] counter_next;
logic [7:0] clk_cnt;
logic en1;
logic en2;
logic is_odd;
logic div1;
logic div2;
logic div2_neg_sync;
logic [7:0] clk_cnt_odd;
logic [7:0] clk_cnt_odd_incr;
logic [7:0] clk_cnt_even;
logic [7:0] clk_cnt_en2;
logic bypass;
logic clk_out_gen;
logic clk_div_valid_reg;
logic clk_inv_test;
logic clk_inv;
assign clk_cnt_odd = clk_div - 8'h1;
assign clk_cnt_even = (clk_div == 8'h2) ? 8'h0 : ({1'b0,clk_div[7:1]} - 8'h1);
assign clk_cnt_en2 = {1'b0,clk_cnt[7:1]} + 8'h1;
always_comb
begin
if (counter == 'h0)
en1 = 1'b1;
else
en1 = 1'b0;
if (clk_div_valid)
counter_next = 'h0;
else if (counter == clk_cnt)
counter_next = 'h0;
else
counter_next = counter + 1;
if (clk_div_valid)
en2 = 1'b0;
else if (counter == clk_cnt_en2)
en2 = 1'b1;
else
en2 = 1'b0;
end
always_ff @(posedge clk, negedge rstn)
begin
if (~rstn)
begin
counter <= 'h0;
div1 <= 1'b0;
bypass <= BYPASS_INIT;
clk_cnt <= DIV_INIT;
is_odd <= 1'b0;
clk_div_valid_reg <= 1'b0;
end
else
begin
if (!bypass)
counter <= counter_next;
clk_div_valid_reg <= clk_div_valid;
if (clk_div_valid)
begin
if ((clk_div == 8'h0) || (clk_div == 8'h1))
begin
bypass <= 1'b1;
clk_cnt <= 'h0;
is_odd <= 1'b0;
end
else
begin
bypass <= 1'b0;
if (clk_div[0])
begin
is_odd <= 1'b1;
clk_cnt <= clk_cnt_odd;
end
else
begin
is_odd <= 1'b0;
clk_cnt <= clk_cnt_even;
end
end
div1 <= 1'b0;
end
else
begin
if (en1 && !bypass)
div1 <= ~div1;
end
end
end
pulp_clock_inverter clk_inv_i
(
.clk_i(clk),
.clk_o(clk_inv)
);
assign clk_inv_test = clk_inv;
always_ff @(posedge clk_inv_test or negedge rstn)
begin
if (!rstn)
begin
div2 <= 1'b0;
end
else
begin
if (clk_div_valid_reg)
div2 <= 1'b0;
else if (en2 && is_odd && !bypass)
div2 <= ~div2;
end
end
pulp_clock_xor2 clock_xor_i
(
.clk_o(clk_out_gen),
.clk0_i(div1),
.clk1_i(div2)
);
pulp_clock_mux2 clk_mux_i
(
.clk0_i(clk_out_gen),
.clk1_i(clk),
.clk_sel_i(bypass || test_mode),
.clk_o(clk_out)
);
endmodule
`begin_keywords "1800-2023"
module clk_div #(
parameter int unsigned RATIO = 4,
parameter bit SHOW_WARNING = 1'b1
)(
input logic clk_i,
input logic rst_ni,
input logic testmode_i,
input logic en_i,
output logic clk_o
);
logic [RATIO-1:0] counter_q;
logic clk_q;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
clk_q <= 1'b0;
counter_q <= '0;
end else begin
clk_q <= 1'b0;
if (en_i) begin
if (counter_q == (RATIO[RATIO-1:0] - 1)) begin
clk_q <= 1'b1;
end else begin
counter_q <= counter_q + 1;
end
end
end
end
assign clk_o = testmode_i ? clk_i : clk_q;
if (SHOW_WARNING) begin : gen_elab_warning
$warning(
"This clock divider is deprecated and not reccomended since ",
"the generated output clock has a very unbalanced duty cycle ",
"(1/RATIO). For new designs we reccomend using the at-runtime ",
"configurable clk_int_div module which always generates 50%% ",
"duty cycle clock. If you don't need at runtime configuration ",
"support, you can instantiate clk_int_div as follows to ",
"obtain a module with roughly the same behavior (except for ",
"the 50 %% duty cycle):\n ",
"\n ",
" clk_int_div #(\n ",
" .DIV_VALUE_WIDTH($clog2(RATIO+1)),\n ",
" .DEFAULT_DIV_VALUE(RATIO)\n ",
" ) i_clk_int_div(\n ",
" .clk_i,\n ",
" .rst_ni,\n ",
" .test_mode_en_i(testmode_i),\n ",
" .en_i,\n ",
" .div_i('1), // Ignored, used default value\n ",
" .div_valid_i(1'b0),\n ",
" .div_ready_o(),\n ",
" .clk_o\n ",
" ); ",
"\n ",
"If you know what your are doing and want to disable this ",
"warning message, you can disable it by overriding the new ",
"optional clk_div parameter SHOW_WARNING to 1'b0.");
end
endmodule
`begin_keywords "1800-2023"
module find_first_one #(
parameter int WIDTH = -1,
parameter int FLIP = 0
)(
input logic [WIDTH-1:0] in_i,
output logic [$clog2(WIDTH)-1:0] first_one_o,
output logic no_ones_o
);
localparam int NUM_LEVELS = $clog2(WIDTH);
initial begin
assert(WIDTH >= 0);
end
logic [WIDTH-1:0][NUM_LEVELS-1:0] index_lut;
logic [2**NUM_LEVELS-1:0] sel_nodes;
logic [2**NUM_LEVELS-1:0][NUM_LEVELS-1:0] index_nodes;
logic [WIDTH-1:0] in_tmp;
for (genvar i = 0; i < WIDTH; i++) begin
assign in_tmp[i] = FLIP ? in_i[WIDTH-1-i] : in_i[i];
end
for (genvar j = 0; j < WIDTH; j++) begin
assign index_lut[j] = j;
end
for (genvar level = 0; level < NUM_LEVELS; level++) begin
if (level < NUM_LEVELS-1) begin
for (genvar l = 0; l < 2**level; l++) begin
assign sel_nodes[2**level-1+l] = sel_nodes[2**(level+1)-1+l*2] | sel_nodes[2**(level+1)-1+l*2+1];
assign index_nodes[2**level-1+l] = (sel_nodes[2**(level+1)-1+l*2] == 1'b1) ?
index_nodes[2**(level+1)-1+l*2] : index_nodes[2**(level+1)-1+l*2+1];
end
end
if (level == NUM_LEVELS-1) begin
for (genvar k = 0; k < 2**level; k++) begin
if (k * 2 < WIDTH-1) begin
assign sel_nodes[2**level-1+k] = in_tmp[k*2] | in_tmp[k*2+1];
assign index_nodes[2**level-1+k] = (in_tmp[k*2] == 1'b1) ? index_lut[k*2] : index_lut[k*2+1];
end
if (k * 2 == WIDTH-1) begin
assign sel_nodes[2**level-1+k] = in_tmp[k*2];
assign index_nodes[2**level-1+k] = index_lut[k*2];
end
if (k * 2 > WIDTH-1) begin
assign sel_nodes[2**level-1+k] = 1'b0;
assign index_nodes[2**level-1+k] = '0;
end
end
end
end
assign first_one_o = NUM_LEVELS > 0 ? index_nodes[0] : '0;
assign no_ones_o = NUM_LEVELS > 0 ? ~sel_nodes[0] : '1;
endmodule
`begin_keywords "1800-2023"
module generic_LFSR_8bit
#(
parameter OH_WIDTH = 4,
parameter BIN_WIDTH = $clog2(OH_WIDTH),
parameter SEED = 8'b00000000
)
(
output logic [OH_WIDTH-1:0] data_OH_o,
output logic [BIN_WIDTH-1:0] data_BIN_o,
input logic enable_i,
input logic clk,
input logic rst_n
);
logic [7:0] out;
logic linear_feedback;
logic [BIN_WIDTH-1:0] temp_ref_way;
assign linear_feedback = !(out[7] ^ out[3] ^ out[2] ^ out[1]);
assign data_BIN_o = temp_ref_way;
always_ff @(posedge clk, negedge rst_n)
begin
if (rst_n == 1'b0)
begin
out <= SEED ;
end
else if (enable_i)
begin
out <= {out[6],out[5],out[4],out[3],out[2],out[1],out[0], linear_feedback};
end
end
generate
if(OH_WIDTH == 2)
assign temp_ref_way = out[1];
else
assign temp_ref_way = out[BIN_WIDTH:1];
endgenerate
always_comb
begin
data_OH_o = '0;
data_OH_o[temp_ref_way] = 1'b1;
end
endmodule
`begin_keywords "1800-2023"
module generic_fifo
#(
parameter int unsigned DATA_WIDTH = 32,
parameter int unsigned DATA_DEPTH = 8
)
(
input logic clk,
input logic rst_n,
input logic [DATA_WIDTH-1:0] data_i,
input logic valid_i,
output logic grant_o,
output logic [DATA_WIDTH-1:0] data_o,
output logic valid_o,
input logic grant_i,
input logic test_mode_i
);
localparam int unsigned ADDR_DEPTH = $clog2(DATA_DEPTH);
enum logic [1:0] { EMPTY, FULL, MIDDLE } CS, NS;
logic gate_clock;
logic clk_gated;
logic [ADDR_DEPTH-1:0] Pop_Pointer_CS, Pop_Pointer_NS;
logic [ADDR_DEPTH-1:0] Push_Pointer_CS, Push_Pointer_NS;
logic [DATA_WIDTH-1:0] FIFO_REGISTERS[DATA_DEPTH-1:0];
int unsigned i;
initial begin : parameter_check
integer param_err_flg;
param_err_flg = 0;
if (DATA_WIDTH < 1) begin
param_err_flg = 1;
$display("ERROR: %m :\n Invalid value (%d) for parameter DATA_WIDTH (legal range: greater than 1)", DATA_WIDTH );
end
if (DATA_DEPTH < 1) begin
param_err_flg = 1;
$display("ERROR: %m :\n Invalid value (%d) for parameter DATA_DEPTH (legal range: greater than 1)", DATA_DEPTH );
end
end
cluster_clock_gating cg_cell
(
.clk_i ( clk ),
.en_i (~gate_clock ),
.test_en_i ( test_mode_i ),
.clk_o ( clk_gated )
);
always_ff @(posedge clk, negedge rst_n)
begin
if(rst_n == 1'b0)
begin
CS <= EMPTY;
Pop_Pointer_CS <= {ADDR_DEPTH {1'b0}};
Push_Pointer_CS <= {ADDR_DEPTH {1'b0}};
end
else
begin
CS <= NS;
Pop_Pointer_CS <= Pop_Pointer_NS;
Push_Pointer_CS <= Push_Pointer_NS;
end
end
always_comb
begin
gate_clock = 1'b0;
case(CS)
EMPTY:
begin
grant_o = 1'b1;
valid_o = 1'b0;
case(valid_i)
1'b0 :
begin
NS = EMPTY;
Push_Pointer_NS = Push_Pointer_CS;
Pop_Pointer_NS = Pop_Pointer_CS;
gate_clock = 1'b1;
end
1'b1:
begin
NS = MIDDLE;
Push_Pointer_NS = Push_Pointer_CS + 1'b1;
Pop_Pointer_NS = Pop_Pointer_CS;
end
endcase
end
MIDDLE:
begin
grant_o = 1'b1;
valid_o = 1'b1;
case({valid_i,grant_i})
2'b01:
begin
gate_clock = 1'b1;
if((Pop_Pointer_CS == Push_Pointer_CS -1 ) || ((Pop_Pointer_CS == DATA_DEPTH-1) && (Push_Pointer_CS == 0) ))
NS = EMPTY;
else
NS = MIDDLE;
Push_Pointer_NS = Push_Pointer_CS;
if(Pop_Pointer_CS == DATA_DEPTH-1)
Pop_Pointer_NS = 0;
else
Pop_Pointer_NS = Pop_Pointer_CS + 1'b1;
end
2'b00 :
begin
gate_clock = 1'b1;
NS = MIDDLE;
Push_Pointer_NS = Push_Pointer_CS;
Pop_Pointer_NS = Pop_Pointer_CS;
end
2'b11:
begin
NS = MIDDLE;
if(Push_Pointer_CS == DATA_DEPTH-1)
Push_Pointer_NS = 0;
else
Push_Pointer_NS = Push_Pointer_CS + 1'b1;
if(Pop_Pointer_CS == DATA_DEPTH-1)
Pop_Pointer_NS = 0;
else
Pop_Pointer_NS = Pop_Pointer_CS + 1'b1;
end
2'b10:
begin
if(( Push_Pointer_CS == Pop_Pointer_CS - 1) || ( (Push_Pointer_CS == DATA_DEPTH-1) && (Pop_Pointer_CS == 0) ))
NS = FULL;
else
NS = MIDDLE;
if(Push_Pointer_CS == DATA_DEPTH - 1)
Push_Pointer_NS = 0;
else
Push_Pointer_NS = Push_Pointer_CS + 1'b1;
Pop_Pointer_NS = Pop_Pointer_CS;
end
endcase
end
FULL:
begin
grant_o = 1'b0;
valid_o = 1'b1;
gate_clock = 1'b1;
case(grant_i)
1'b1:
begin
NS = MIDDLE;
Push_Pointer_NS = Push_Pointer_CS;
if(Pop_Pointer_CS == DATA_DEPTH-1)
Pop_Pointer_NS = 0;
else
Pop_Pointer_NS = Pop_Pointer_CS + 1'b1;
end
1'b0:
begin
NS = FULL;
Push_Pointer_NS = Push_Pointer_CS;
Pop_Pointer_NS = Pop_Pointer_CS;
end
endcase
end
default :
begin
gate_clock = 1'b1;
grant_o = 1'b0;
valid_o = 1'b0;
NS = EMPTY;
Pop_Pointer_NS = 0;
Push_Pointer_NS = 0;
end
endcase
end
always_ff @(posedge clk_gated, negedge rst_n)
begin
if(rst_n == 1'b0)
begin
for (i=0; i< DATA_DEPTH; i++)
FIFO_REGISTERS[i] <= {DATA_WIDTH {1'b0}};
end
else
begin
if((grant_o == 1'b1) && (valid_i == 1'b1))
FIFO_REGISTERS[Push_Pointer_CS] <= data_i;
end
end
assign data_o = FIFO_REGISTERS[Pop_Pointer_CS];
endmodule
`begin_keywords "1800-2023"
module prioarbiter #(
parameter int unsigned NUM_REQ = 13,
parameter int unsigned LOCK_IN = 0
) (
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input logic en_i,
input logic [NUM_REQ-1:0] req_i,
output logic [NUM_REQ-1:0] ack_o,
output logic vld_o,
output logic [$clog2(NUM_REQ)-1:0] idx_o
);
localparam SEL_WIDTH = $clog2(NUM_REQ);
logic [SEL_WIDTH-1:0] arb_sel_lock_d, arb_sel_lock_q;
logic lock_d, lock_q;
logic [$clog2(NUM_REQ)-1:0] idx;
assign vld_o = (|req_i) & en_i;
assign idx_o = (lock_q) ? arb_sel_lock_q : idx;
assign ack_o[0] = (req_i[0]) ? en_i : 1'b0;
for (genvar i = 1; i < NUM_REQ; i++) begin : gen_arb_req_ports
assign ack_o[i] = (req_i[i] & ~(|ack_o[i-1:0])) ? en_i : 1'b0;
end
onehot_to_bin #(
.ONEHOT_WIDTH ( NUM_REQ )
) i_onehot_to_bin (
.onehot ( ack_o ),
.bin ( idx )
);
if (LOCK_IN) begin : gen_lock_in
assign lock_d = (|req_i) & ~en_i;
assign arb_sel_lock_d = idx_o;
end else begin
assign lock_d = '0;
assign arb_sel_lock_d = '0;
end
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
if (!rst_ni) begin
lock_q <= 1'b0;
arb_sel_lock_q <= '0;
end else begin
if (flush_i) begin
lock_q <= 1'b0;
arb_sel_lock_q <= '0;
end else begin
lock_q <= lock_d;
arb_sel_lock_q <= arb_sel_lock_d;
end
end
end
endmodule : prioarbiter
`begin_keywords "1800-2023"
module pulp_sync
#(
parameter STAGES = 2
)
(
input logic clk_i,
input logic rstn_i,
input logic serial_i,
output logic serial_o
);
logic [STAGES-1:0] r_reg;
always_ff @(posedge clk_i, negedge rstn_i)
begin
if(!rstn_i)
r_reg <= 'h0;
else
r_reg <= {r_reg[STAGES-2:0], serial_i};
end
assign serial_o = r_reg[STAGES-1];
endmodule
`begin_keywords "1800-2023"
module pulp_sync_wedge #(
parameter int unsigned STAGES = 2
) (
input logic clk_i,
input logic rstn_i,
input logic en_i,
input logic serial_i,
output logic r_edge_o,
output logic f_edge_o,
output logic serial_o
);
logic clk;
logic serial, serial_q;
assign serial_o = serial_q;
assign f_edge_o = ~serial & serial_q;
assign r_edge_o = serial & ~serial_q;
pulp_sync #(
.STAGES(STAGES)
) i_pulp_sync (
.clk_i,
.rstn_i,
.serial_i,
.serial_o ( serial )
);
pulp_clock_gating i_pulp_clock_gating (
.clk_i,
.en_i,
.test_en_i ( 1'b0 ),
.clk_o ( clk )
);
always_ff @(posedge clk, negedge rstn_i) begin
if (!rstn_i) begin
serial_q <= 1'b0;
end else begin
serial_q <= serial;
end
end
endmodule
`begin_keywords "1800-2023"
module rrarbiter #(
parameter int unsigned NUM_REQ = 64,
parameter bit LOCK_IN = 1'b0
) (
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input logic en_i,
input logic [NUM_REQ-1:0] req_i,
output logic [NUM_REQ-1:0] ack_o,
output logic vld_o,
output logic [$clog2(NUM_REQ)-1:0] idx_o
);
logic req;
assign vld_o = (|req_i) & en_i;
rr_arb_tree #(
.NumIn ( NUM_REQ ),
.DataWidth ( 1 ),
.LockIn ( LOCK_IN ))
i_rr_arb_tree (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( flush_i ),
.rr_i ( '0 ),
.req_i ( req_i ),
.gnt_o ( ack_o ),
.data_i ( '0 ),
.gnt_i ( en_i & req ),
.req_o ( req ),
.data_o ( ),
.idx_o ( idx_o )
);
endmodule : rrarbiter
`begin_keywords "1800-2023"
module clock_divider
#(
parameter DIV_INIT = 0,
parameter BYPASS_INIT = 1
)
(
input logic clk_i,
input logic rstn_i,
input logic test_mode_i,
input logic clk_gate_async_i,
input logic [7:0] clk_div_data_i,
input logic clk_div_valid_i,
output logic clk_div_ack_o,
output logic clk_o
);
enum logic [1:0] {IDLE, STOP, WAIT, RELEASE} state, state_next;
logic s_clk_out;
logic s_clock_enable;
logic s_clock_enable_gate;
logic s_clk_div_valid;
logic [7:0] reg_clk_div;
logic s_clk_div_valid_sync;
logic s_rstn_sync;
logic [1:0] reg_ext_gate_sync;
assign s_clock_enable_gate = s_clock_enable & reg_ext_gate_sync;
rstgen i_rst_gen
(
.clk_i(clk_i),
.rst_ni(rstn_i),
.test_mode_i(test_mode_i),
.rst_no(s_rstn_sync),
.init_no()
);
pulp_sync_wedge i_edge_prop
(
.clk_i(clk_i),
.rstn_i(s_rstn_sync),
.en_i(1'b1),
.serial_i(clk_div_valid_i),
.serial_o(clk_div_ack_o),
.r_edge_o(s_clk_div_valid_sync),
.f_edge_o()
);
clock_divider_counter
#(
.BYPASS_INIT(BYPASS_INIT),
.DIV_INIT(DIV_INIT)
)
i_clkdiv_cnt
(
.clk(clk_i),
.rstn(s_rstn_sync),
.test_mode(test_mode_i),
.clk_div(reg_clk_div),
.clk_div_valid(s_clk_div_valid),
.clk_out(s_clk_out)
);
pulp_clock_gating i_clk_gate
(
.clk_i(s_clk_out),
.en_i(s_clock_enable_gate),
.test_en_i(test_mode_i),
.clk_o(clk_o)
);
always_comb
begin
case(state)
IDLE:
begin
s_clock_enable = 1'b1;
s_clk_div_valid = 1'b0;
if (s_clk_div_valid_sync)
state_next = STOP;
else
state_next = IDLE;
end
STOP:
begin
s_clock_enable = 1'b0;
s_clk_div_valid = 1'b1;
state_next = WAIT;
end
WAIT:
begin
s_clock_enable = 1'b0;
s_clk_div_valid = 1'b0;
state_next = RELEASE;
end
RELEASE:
begin
s_clock_enable = 1'b0;
s_clk_div_valid = 1'b0;
state_next = IDLE;
end
endcase
end
always_ff @(posedge clk_i or negedge s_rstn_sync)
begin
if (!s_rstn_sync)
state <= IDLE;
else
state <= state_next;
end
always_ff @(posedge clk_i or negedge s_rstn_sync)
begin
if (!s_rstn_sync)
reg_clk_div <= '0;
else if (s_clk_div_valid_sync)
reg_clk_div <= clk_div_data_i;
end
always_ff @(posedge clk_i or negedge s_rstn_sync)
begin
if (!s_rstn_sync)
reg_ext_gate_sync <= 2'b00;
else
reg_ext_gate_sync <= {clk_gate_async_i, reg_ext_gate_sync[1]};
end
endmodule
`begin_keywords "1800-2023"
module fifo_v2 #(
parameter bit FALL_THROUGH = 1'b0,
parameter int unsigned DATA_WIDTH = 32,
parameter int unsigned DEPTH = 8,
parameter int unsigned ALM_EMPTY_TH = 1,
parameter int unsigned ALM_FULL_TH = 1,
parameter type dtype = logic [DATA_WIDTH-1:0],
parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1
)(
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input logic testmode_i,
output logic full_o,
output logic empty_o,
output logic alm_full_o,
output logic alm_empty_o,
input dtype data_i,
input logic push_i,
output dtype data_o,
input logic pop_i
);
logic [ADDR_DEPTH-1:0] usage;
if (DEPTH == 0) begin
assign alm_full_o = 1'b0;
assign alm_empty_o = 1'b0;
end else begin
assign alm_full_o = (usage >= ALM_FULL_TH[ADDR_DEPTH-1:0]);
assign alm_empty_o = (usage <= ALM_EMPTY_TH[ADDR_DEPTH-1:0]);
end
fifo_v3 #(
.FALL_THROUGH ( FALL_THROUGH ),
.DATA_WIDTH ( DATA_WIDTH ),
.DEPTH ( DEPTH ),
.dtype ( dtype )
) i_fifo_v3 (
.clk_i,
.rst_ni,
.flush_i,
.testmode_i,
.full_o,
.empty_o,
.usage_o (usage),
.data_i,
.push_i,
.data_o,
.pop_i
);
initial begin
assert (ALM_FULL_TH <= DEPTH) else $error("ALM_FULL_TH can't be larger than the DEPTH.");
assert (ALM_EMPTY_TH <= DEPTH) else $error("ALM_EMPTY_TH can't be larger than the DEPTH.");
end
endmodule
`begin_keywords "1800-2023"
/*verilator lint_off DECLFILENAME*/
module fifo #(
parameter bit FALL_THROUGH = 1'b0,
parameter int unsigned DATA_WIDTH = 32,
parameter int unsigned DEPTH = 8,
parameter int unsigned THRESHOLD = 1,
parameter type dtype = logic [DATA_WIDTH-1:0]
)(
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input logic testmode_i,
output logic full_o,
output logic empty_o,
output logic threshold_o,
input dtype data_i,
input logic push_i,
output dtype data_o,
input logic pop_i
);
fifo_v2 #(
.FALL_THROUGH ( FALL_THROUGH ),
.DATA_WIDTH ( DATA_WIDTH ),
.DEPTH ( DEPTH ),
.ALM_FULL_TH ( THRESHOLD ),
.dtype ( dtype )
) impl (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( flush_i ),
.testmode_i ( testmode_i ),
.full_o ( full_o ),
.empty_o ( empty_o ),
.alm_full_o ( threshold_o ),
.alm_empty_o ( ),
.data_i ( data_i ),
.push_i ( push_i ),
.data_o ( data_o ),
.pop_i ( pop_i )
);
endmodule
/*verilator lint_on DECLFILENAME*/
`begin_keywords "1800-2023"
module edge_propagator_ack (
input logic clk_tx_i,
input logic rstn_tx_i,
input logic edge_i,
output logic ack_tx_o,
input logic clk_rx_i,
input logic rstn_rx_i,
output logic edge_o
);
logic [1:0] sync_a;
logic sync_b;
logic r_input_reg;
logic s_input_reg_next;
assign ack_tx_o = sync_a[0];
assign s_input_reg_next = edge_i | (r_input_reg & ~sync_a[0]);
always @(negedge rstn_tx_i or posedge clk_tx_i) begin
if (~rstn_tx_i) begin
r_input_reg <= 1'b0;
sync_a <= 2'b00;
end else begin
r_input_reg <= s_input_reg_next;
sync_a <= {sync_b,sync_a[1]};
end
end
pulp_sync_wedge u_sync_clkb (
.clk_i ( clk_rx_i ),
.rstn_i ( rstn_rx_i ),
.en_i ( 1'b1 ),
.serial_i ( r_input_reg ),
.r_edge_o ( edge_o ),
.f_edge_o ( ),
.serial_o ( sync_b )
);
endmodule
`begin_keywords "1800-2023"
module edge_propagator (
input logic clk_tx_i,
input logic rstn_tx_i,
input logic edge_i,
input logic clk_rx_i,
input logic rstn_rx_i,
output logic edge_o
);
edge_propagator_ack i_edge_propagator_ack (
.clk_tx_i,
.rstn_tx_i,
.edge_i,
.ack_tx_o ( ),
.clk_rx_i,
.rstn_rx_i,
.edge_o
);
endmodule
`begin_keywords "1800-2023"
module edge_propagator_rx (
input logic clk_i,
input logic rstn_i,
input logic valid_i,
output logic ack_o,
output logic valid_o
);
pulp_sync_wedge i_sync_clkb (
.clk_i ( clk_i ),
.rstn_i ( rstn_i ),
.en_i ( 1'b1 ),
.serial_i ( valid_i ),
.r_edge_o ( valid_o ),
.f_edge_o ( ),
.serial_o ( ack_o )
);
endmodule
`begin_keywords "1800-2023"
package axi_pkg;
parameter int unsigned BurstWidth = 32'd2;
parameter int unsigned RespWidth = 32'd2;
parameter int unsigned CacheWidth = 32'd4;
parameter int unsigned ProtWidth = 32'd3;
parameter int unsigned QosWidth = 32'd4;
parameter int unsigned RegionWidth = 32'd4;
parameter int unsigned LenWidth = 32'd8;
parameter int unsigned SizeWidth = 32'd3;
parameter int unsigned LockWidth = 32'd1;
parameter int unsigned AtopWidth = 32'd6;
parameter int unsigned NsaidWidth = 32'd4;
typedef logic [1:0] burst_t;
typedef logic [1:0] resp_t;
typedef logic [3:0] cache_t;
typedef logic [2:0] prot_t;
typedef logic [3:0] qos_t;
typedef logic [3:0] region_t;
typedef logic [7:0] len_t;
typedef logic [2:0] size_t;
typedef logic [5:0] atop_t;
typedef logic [3:0] nsaid_t;
localparam BURST_FIXED = 2'b00;
localparam BURST_INCR = 2'b01;
localparam BURST_WRAP = 2'b10;
localparam RESP_OKAY = 2'b00;
localparam RESP_EXOKAY = 2'b01;
localparam RESP_SLVERR = 2'b10;
localparam RESP_DECERR = 2'b11;
localparam CACHE_BUFFERABLE = 4'b0001;
localparam CACHE_MODIFIABLE = 4'b0010;
localparam CACHE_RD_ALLOC = 4'b0100;
localparam CACHE_WR_ALLOC = 4'b1000;
function automatic shortint unsigned num_bytes(size_t size);
return shortint'(1 << size);
endfunction
typedef logic [127:0] largest_addr_t;
function automatic largest_addr_t aligned_addr(largest_addr_t addr, size_t size);
return (addr >> size) << size;
endfunction
function automatic largest_addr_t wrap_boundary (largest_addr_t addr, size_t size, len_t len);
largest_addr_t wrap_addr;
unique case (len)
len_t'(4'b1 ) : wrap_addr = (addr >> (unsigned'(size) + 1)) << (unsigned'(size) + 1);
len_t'(4'b11 ) : wrap_addr = (addr >> (unsigned'(size) + 2)) << (unsigned'(size) + 2);
len_t'(4'b111 ) : wrap_addr = (addr >> (unsigned'(size) + 3)) << (unsigned'(size) + 3);
len_t'(4'b1111) : wrap_addr = (addr >> (unsigned'(size) + 4)) << (unsigned'(size) + 4);
default : wrap_addr = '0;
endcase
return wrap_addr;
endfunction
function automatic largest_addr_t
beat_addr(largest_addr_t addr, size_t size, len_t len, burst_t burst, shortint unsigned i_beat);
largest_addr_t ret_addr = addr;
largest_addr_t wrp_bond = '0;
if (burst == BURST_WRAP) begin
wrp_bond = wrap_boundary(addr, size, len);
end
if (i_beat != 0 && burst != BURST_FIXED) begin
ret_addr = aligned_addr(addr, size) + i_beat * num_bytes(size);
if (burst == BURST_WRAP && ret_addr >= wrp_bond + (num_bytes(size) * (largest_addr_t'(len) + 1))) begin
ret_addr = ret_addr - (num_bytes(size) * (largest_addr_t'(len) + 1));
end
end
return ret_addr;
endfunction
function automatic shortint unsigned
beat_lower_byte(largest_addr_t addr, size_t size, len_t len, burst_t burst,
shortint unsigned strobe_width, shortint unsigned i_beat);
largest_addr_t _addr = beat_addr(addr, size, len, burst, i_beat);
return shortint'(($bits(_addr) + $bits(strobe_width))'(_addr) - (_addr / largest_addr_t'(strobe_width)) * strobe_width);
endfunction
function automatic shortint unsigned
beat_upper_byte(largest_addr_t addr, size_t size, len_t len, burst_t burst,
shortint unsigned strobe_width, shortint unsigned i_beat);
typedef shortint unsigned SU;
if (i_beat == 0) begin
return SU'(aligned_addr(addr, size) + (largest_addr_t'(num_bytes(size)) - 1) - (addr / largest_addr_t'(strobe_width)) * strobe_width);
end else begin
return beat_lower_byte(addr, size, len, burst, strobe_width, i_beat) + num_bytes(size) - 1;
end
endfunction
function automatic logic bufferable(cache_t cache);
return |(cache & CACHE_BUFFERABLE);
endfunction
function automatic logic modifiable(cache_t cache);
return |(cache & CACHE_MODIFIABLE);
endfunction
typedef enum logic [3:0] {
DEVICE_NONBUFFERABLE,
DEVICE_BUFFERABLE,
NORMAL_NONCACHEABLE_NONBUFFERABLE,
NORMAL_NONCACHEABLE_BUFFERABLE,
WTHRU_NOALLOCATE,
WTHRU_RALLOCATE,
WTHRU_WALLOCATE,
WTHRU_RWALLOCATE,
WBACK_NOALLOCATE,
WBACK_RALLOCATE,
WBACK_WALLOCATE,
WBACK_RWALLOCATE
} mem_type_t;
function automatic logic [3:0] get_arcache(mem_type_t mtype);
unique case (mtype)
DEVICE_NONBUFFERABLE : return 4'b0000;
DEVICE_BUFFERABLE : return 4'b0001;
NORMAL_NONCACHEABLE_NONBUFFERABLE : return 4'b0010;
NORMAL_NONCACHEABLE_BUFFERABLE : return 4'b0011;
WTHRU_NOALLOCATE : return 4'b1010;
WTHRU_RALLOCATE : return 4'b1110;
WTHRU_WALLOCATE : return 4'b1010;
WTHRU_RWALLOCATE : return 4'b1110;
WBACK_NOALLOCATE : return 4'b1011;
WBACK_RALLOCATE : return 4'b1111;
WBACK_WALLOCATE : return 4'b1011;
WBACK_RWALLOCATE : return 4'b1111;
default : return 4'bxxxx;
endcase
endfunction
function automatic logic [3:0] get_awcache(mem_type_t mtype);
unique case (mtype)
DEVICE_NONBUFFERABLE : return 4'b0000;
DEVICE_BUFFERABLE : return 4'b0001;
NORMAL_NONCACHEABLE_NONBUFFERABLE : return 4'b0010;
NORMAL_NONCACHEABLE_BUFFERABLE : return 4'b0011;
WTHRU_NOALLOCATE : return 4'b0110;
WTHRU_RALLOCATE : return 4'b0110;
WTHRU_WALLOCATE : return 4'b1110;
WTHRU_RWALLOCATE : return 4'b1110;
WBACK_NOALLOCATE : return 4'b0111;
WBACK_RALLOCATE : return 4'b0111;
WBACK_WALLOCATE : return 4'b1111;
WBACK_RWALLOCATE : return 4'b1111;
default : return 4'bxxxx;
endcase
endfunction
function automatic resp_t resp_precedence(resp_t resp_a, resp_t resp_b);
unique case (resp_a)
RESP_OKAY: begin
if (resp_b == RESP_EXOKAY) begin
return resp_a;
end else begin
return resp_b;
end
end
RESP_EXOKAY: begin
return resp_b;
end
RESP_SLVERR: begin
if (resp_b == RESP_DECERR) begin
return resp_b;
end else begin
return resp_a;
end
end
RESP_DECERR: begin
return resp_a;
end
endcase
endfunction
function automatic int unsigned aw_width(int unsigned addr_width, int unsigned id_width,
int unsigned user_width );
return (id_width + addr_width + LenWidth + SizeWidth + BurstWidth + LockWidth + CacheWidth +
ProtWidth + QosWidth + RegionWidth + AtopWidth + user_width );
endfunction
function automatic int unsigned w_width(int unsigned data_width, int unsigned user_width );
return (data_width + data_width / 32'd8 + 32'd1 + user_width);
endfunction
function automatic int unsigned b_width(int unsigned id_width, int unsigned user_width );
return (id_width + RespWidth + user_width);
endfunction
function automatic int unsigned ar_width(int unsigned addr_width, int unsigned id_width,
int unsigned user_width );
return (id_width + addr_width + LenWidth + SizeWidth + BurstWidth + LockWidth + CacheWidth +
ProtWidth + QosWidth + RegionWidth + user_width );
endfunction
function automatic int unsigned r_width(int unsigned data_width, int unsigned id_width,
int unsigned user_width );
return (id_width + data_width + RespWidth + 32'd1 + user_width);
endfunction
function automatic int unsigned req_width(int unsigned addr_width, int unsigned data_width,
int unsigned id_width, int unsigned aw_user_width,
int unsigned ar_user_width, int unsigned w_user_width );
return (aw_width(addr_width, id_width, aw_user_width) + 32'd1 +
w_width(data_width, w_user_width) + 32'd1 +
ar_width(addr_width, id_width, ar_user_width) + 32'd1 + 32'd1 + 32'd1 );
endfunction
function automatic int unsigned rsp_width(int unsigned data_width, int unsigned id_width,
int unsigned r_user_width, int unsigned b_user_width );
return (r_width(data_width, id_width, r_user_width) + 32'd1 +
b_width(id_width, b_user_width) + 32'd1 + 32'd1 + 32'd1 + 32'd1);
endfunction
localparam ATOP_ATOMICSWAP = 6'b110000;
localparam ATOP_ATOMICCMP = 6'b110001;
localparam ATOP_NONE = 2'b00;
localparam ATOP_ATOMICSTORE = 2'b01;
localparam ATOP_ATOMICLOAD = 2'b10;
localparam ATOP_LITTLE_END = 1'b0;
localparam ATOP_BIG_END = 1'b1;
localparam ATOP_ADD = 3'b000;
localparam ATOP_CLR = 3'b001;
localparam ATOP_EOR = 3'b010;
localparam ATOP_SET = 3'b011;
localparam ATOP_SMAX = 3'b100;
localparam ATOP_SMIN = 3'b101;
localparam ATOP_UMAX = 3'b110;
localparam ATOP_UMIN = 3'b111;
localparam ATOP_R_RESP = 32'd5;
localparam bit [9:0] DemuxAw = (1 << 9);
localparam bit [9:0] DemuxW = (1 << 8);
localparam bit [9:0] DemuxB = (1 << 7);
localparam bit [9:0] DemuxAr = (1 << 6);
localparam bit [9:0] DemuxR = (1 << 5);
localparam bit [9:0] MuxAw = (1 << 4);
localparam bit [9:0] MuxW = (1 << 3);
localparam bit [9:0] MuxB = (1 << 2);
localparam bit [9:0] MuxAr = (1 << 1);
localparam bit [9:0] MuxR = (1 << 0);
typedef enum bit [9:0] {
NO_LATENCY = 10'b000_00_000_00,
CUT_SLV_AX = DemuxAw | DemuxAr,
CUT_MST_AX = MuxAw | MuxAr,
CUT_ALL_AX = DemuxAw | DemuxAr | MuxAw | MuxAr,
CUT_SLV_PORTS = DemuxAw | DemuxW | DemuxB | DemuxAr | DemuxR,
CUT_MST_PORTS = MuxAw | MuxW | MuxB | MuxAr | MuxR,
CUT_ALL_PORTS = 10'b111_11_111_11
} xbar_latency_e;
typedef struct packed {
int unsigned NoSlvPorts;
int unsigned NoMstPorts;
int unsigned MaxMstTrans;
int unsigned MaxSlvTrans;
bit FallThrough;
bit [9:0] LatencyMode;
int unsigned PipelineStages;
int unsigned AxiIdWidthSlvPorts;
int unsigned AxiIdUsedSlvPorts;
bit UniqueIds;
int unsigned AxiAddrWidth;
int unsigned AxiDataWidth;
int unsigned NoAddrRules;
} xbar_cfg_t;
typedef struct packed {
int unsigned idx;
logic [63:0] start_addr;
logic [63:0] end_addr;
} xbar_rule_64_t;
typedef struct packed {
int unsigned idx;
logic [31:0] start_addr;
logic [31:0] end_addr;
} xbar_rule_32_t;
function automatic integer unsigned iomsb (input integer unsigned width);
return (width != 32'd0) ? unsigned'(width-1) : 32'd0;
endfunction
endpackage
`begin_keywords "1800-2023"
module axi_demux_id_counters #(
parameter int unsigned AxiIdBits = 2,
parameter int unsigned CounterWidth = 4,
parameter type mst_port_select_t = logic
) (
input logic clk_i,
input logic rst_ni,
input logic [AxiIdBits-1:0] lookup_axi_id_i,
output mst_port_select_t lookup_mst_select_o,
output logic lookup_mst_select_occupied_o,
output logic full_o,
input logic [AxiIdBits-1:0] push_axi_id_i,
input mst_port_select_t push_mst_select_i,
input logic push_i,
input logic [AxiIdBits-1:0] inject_axi_id_i,
input logic inject_i,
input logic [AxiIdBits-1:0] pop_axi_id_i,
input logic pop_i,
output logic any_outstanding_trx_o
);
localparam int unsigned NoCounters = 2**AxiIdBits;
typedef logic [CounterWidth-1:0] cnt_t;
mst_port_select_t [NoCounters-1:0] mst_select_q;
logic [NoCounters-1:0] push_en, inject_en, pop_en, occupied, cnt_full;
assign lookup_mst_select_o = mst_select_q[lookup_axi_id_i];
assign lookup_mst_select_occupied_o = occupied[lookup_axi_id_i];
assign push_en = (push_i) ? (1 << push_axi_id_i) : '0;
assign inject_en = (inject_i) ? (1 << inject_axi_id_i) : '0;
assign pop_en = (pop_i) ? (1 << pop_axi_id_i) : '0;
assign full_o = |cnt_full;
assign any_outstanding_trx_o = |occupied;
for (genvar i = 0; i < NoCounters; i++) begin : gen_counters
logic cnt_en, cnt_down, overflow;
cnt_t cnt_delta, in_flight;
always_comb begin
unique case ({push_en[i], inject_en[i], pop_en[i]})
3'b001 : begin
cnt_en = 1'b1;
cnt_down = 1'b1;
cnt_delta = cnt_t'(1);
end
3'b010 : begin
cnt_en = 1'b1;
cnt_down = 1'b0;
cnt_delta = cnt_t'(1);
end
3'b100 : begin
cnt_en = 1'b1;
cnt_down = 1'b0;
cnt_delta = cnt_t'(1);
end
3'b110 : begin
cnt_en = 1'b1;
cnt_down = 1'b0;
cnt_delta = cnt_t'(2);
end
3'b111 : begin
cnt_en = 1'b1;
cnt_down = 1'b0;
cnt_delta = cnt_t'(1);
end
default : begin
cnt_en = 1'b0;
cnt_down = 1'b0;
cnt_delta = cnt_t'(0);
end
endcase
end
delta_counter #(
.WIDTH ( CounterWidth ),
.STICKY_OVERFLOW ( 1'b0 )
) i_in_flight_cnt (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.clear_i ( 1'b0 ),
.en_i ( cnt_en ),
.load_i ( 1'b0 ),
.down_i ( cnt_down ),
.delta_i ( cnt_delta ),
.d_i ( '0 ),
.q_o ( in_flight ),
.overflow_o ( overflow )
);
assign occupied[i] = |in_flight;
assign cnt_full[i] = overflow | (&in_flight);
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
mst_select_q[i] <= ('0);
end else begin
if (push_en[i]) begin
mst_select_q[i] <= (push_mst_select_i);
end
end
end
end
endmodule
`begin_keywords "1800-2023"
interface AXI_BUS #(
parameter int unsigned AXI_ADDR_WIDTH = 0,
parameter int unsigned AXI_DATA_WIDTH = 0,
parameter int unsigned AXI_ID_WIDTH = 0,
parameter int unsigned AXI_USER_WIDTH = 0
);
localparam int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8;
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_STRB_WIDTH-1:0] strb_t;
typedef logic [AXI_USER_WIDTH-1:0] user_t;
id_t aw_id;
addr_t aw_addr;
axi_pkg::len_t aw_len;
axi_pkg::size_t aw_size;
axi_pkg::burst_t aw_burst;
logic aw_lock;
axi_pkg::cache_t aw_cache;
axi_pkg::prot_t aw_prot;
axi_pkg::qos_t aw_qos;
axi_pkg::region_t aw_region;
axi_pkg::atop_t aw_atop;
user_t aw_user;
logic aw_valid;
logic aw_ready;
data_t w_data;
strb_t w_strb;
logic w_last;
user_t w_user;
logic w_valid;
logic w_ready;
id_t b_id;
axi_pkg::resp_t b_resp;
user_t b_user;
logic b_valid;
logic b_ready;
id_t ar_id;
addr_t ar_addr;
axi_pkg::len_t ar_len;
axi_pkg::size_t ar_size;
axi_pkg::burst_t ar_burst;
logic ar_lock;
axi_pkg::cache_t ar_cache;
axi_pkg::prot_t ar_prot;
axi_pkg::qos_t ar_qos;
axi_pkg::region_t ar_region;
user_t ar_user;
logic ar_valid;
logic ar_ready;
id_t r_id;
data_t r_data;
axi_pkg::resp_t r_resp;
logic r_last;
user_t r_user;
logic r_valid;
logic r_ready;
modport Master (
output aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_atop, aw_user, aw_valid, input aw_ready,
output w_data, w_strb, w_last, w_user, w_valid, input w_ready,
input b_id, b_resp, b_user, b_valid, output b_ready,
output ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_valid, input ar_ready,
input r_id, r_data, r_resp, r_last, r_user, r_valid, output r_ready
);
modport Slave (
input aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_atop, aw_user, aw_valid, output aw_ready,
input w_data, w_strb, w_last, w_user, w_valid, output w_ready,
output b_id, b_resp, b_user, b_valid, input b_ready,
input ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_valid, output ar_ready,
output r_id, r_data, r_resp, r_last, r_user, r_valid, input r_ready
);
modport Monitor (
input aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_atop, aw_user, aw_valid, aw_ready,
w_data, w_strb, w_last, w_user, w_valid, w_ready,
b_id, b_resp, b_user, b_valid, b_ready,
ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_valid, ar_ready,
r_id, r_data, r_resp, r_last, r_user, r_valid, r_ready
);
endinterface
interface AXI_BUS_DV #(
parameter int unsigned AXI_ADDR_WIDTH = 0,
parameter int unsigned AXI_DATA_WIDTH = 0,
parameter int unsigned AXI_ID_WIDTH = 0,
parameter int unsigned AXI_USER_WIDTH = 0
)(
input logic clk_i
);
localparam int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8;
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_STRB_WIDTH-1:0] strb_t;
typedef logic [AXI_USER_WIDTH-1:0] user_t;
id_t aw_id;
addr_t aw_addr;
axi_pkg::len_t aw_len;
axi_pkg::size_t aw_size;
axi_pkg::burst_t aw_burst;
logic aw_lock;
axi_pkg::cache_t aw_cache;
axi_pkg::prot_t aw_prot;
axi_pkg::qos_t aw_qos;
axi_pkg::region_t aw_region;
axi_pkg::atop_t aw_atop;
user_t aw_user;
logic aw_valid;
logic aw_ready;
data_t w_data;
strb_t w_strb;
logic w_last;
user_t w_user;
logic w_valid;
logic w_ready;
id_t b_id;
axi_pkg::resp_t b_resp;
user_t b_user;
logic b_valid;
logic b_ready;
id_t ar_id;
addr_t ar_addr;
axi_pkg::len_t ar_len;
axi_pkg::size_t ar_size;
axi_pkg::burst_t ar_burst;
logic ar_lock;
axi_pkg::cache_t ar_cache;
axi_pkg::prot_t ar_prot;
axi_pkg::qos_t ar_qos;
axi_pkg::region_t ar_region;
user_t ar_user;
logic ar_valid;
logic ar_ready;
id_t r_id;
data_t r_data;
axi_pkg::resp_t r_resp;
logic r_last;
user_t r_user;
logic r_valid;
logic r_ready;
modport Master (
output aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_atop, aw_user, aw_valid, input aw_ready,
output w_data, w_strb, w_last, w_user, w_valid, input w_ready,
input b_id, b_resp, b_user, b_valid, output b_ready,
output ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_valid, input ar_ready,
input r_id, r_data, r_resp, r_last, r_user, r_valid, output r_ready
);
modport Slave (
input aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_atop, aw_user, aw_valid, output aw_ready,
input w_data, w_strb, w_last, w_user, w_valid, output w_ready,
output b_id, b_resp, b_user, b_valid, input b_ready,
input ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_valid, output ar_ready,
output r_id, r_data, r_resp, r_last, r_user, r_valid, input r_ready
);
modport Monitor (
input aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_atop, aw_user, aw_valid, aw_ready,
w_data, w_strb, w_last, w_user, w_valid, w_ready,
b_id, b_resp, b_user, b_valid, b_ready,
ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_valid, ar_ready,
r_id, r_data, r_resp, r_last, r_user, r_valid, r_ready
);
endinterface
interface AXI_BUS_ASYNC
#(
parameter int unsigned AXI_ADDR_WIDTH = 0,
parameter int unsigned AXI_DATA_WIDTH = 0,
parameter int unsigned AXI_ID_WIDTH = 0,
parameter int unsigned AXI_USER_WIDTH = 0,
parameter int unsigned BUFFER_WIDTH = 0
);
localparam int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8;
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_STRB_WIDTH-1:0] strb_t;
typedef logic [AXI_USER_WIDTH-1:0] user_t;
typedef logic [BUFFER_WIDTH-1:0] buffer_t;
id_t aw_id;
addr_t aw_addr;
axi_pkg::len_t aw_len;
axi_pkg::size_t aw_size;
axi_pkg::burst_t aw_burst;
logic aw_lock;
axi_pkg::cache_t aw_cache;
axi_pkg::prot_t aw_prot;
axi_pkg::qos_t aw_qos;
axi_pkg::region_t aw_region;
axi_pkg::atop_t aw_atop;
user_t aw_user;
buffer_t aw_writetoken;
buffer_t aw_readpointer;
data_t w_data;
strb_t w_strb;
logic w_last;
user_t w_user;
buffer_t w_writetoken;
buffer_t w_readpointer;
id_t b_id;
axi_pkg::resp_t b_resp;
user_t b_user;
buffer_t b_writetoken;
buffer_t b_readpointer;
id_t ar_id;
addr_t ar_addr;
axi_pkg::len_t ar_len;
axi_pkg::size_t ar_size;
axi_pkg::burst_t ar_burst;
logic ar_lock;
axi_pkg::cache_t ar_cache;
axi_pkg::prot_t ar_prot;
axi_pkg::qos_t ar_qos;
axi_pkg::region_t ar_region;
user_t ar_user;
buffer_t ar_writetoken;
buffer_t ar_readpointer;
id_t r_id;
data_t r_data;
axi_pkg::resp_t r_resp;
logic r_last;
user_t r_user;
buffer_t r_writetoken;
buffer_t r_readpointer;
modport Master (
output aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_atop, aw_user, aw_writetoken, input aw_readpointer,
output w_data, w_strb, w_last, w_user, w_writetoken, input w_readpointer,
input b_id, b_resp, b_user, b_writetoken, output b_readpointer,
output ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_writetoken, input ar_readpointer,
input r_id, r_data, r_resp, r_last, r_user, r_writetoken, output r_readpointer
);
modport Slave (
input aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_atop, aw_user, aw_writetoken, output aw_readpointer,
input w_data, w_strb, w_last, w_user, w_writetoken, output w_readpointer,
output b_id, b_resp, b_user, b_writetoken, input b_readpointer,
input ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_writetoken, output ar_readpointer,
output r_id, r_data, r_resp, r_last, r_user, r_writetoken, input r_readpointer
);
endinterface
interface AXI_BUS_ASYNC_GRAY #(
parameter int unsigned AXI_ADDR_WIDTH = 0,
parameter int unsigned AXI_DATA_WIDTH = 0,
parameter int unsigned AXI_ID_WIDTH = 0,
parameter int unsigned AXI_USER_WIDTH = 0,
parameter int unsigned LOG_DEPTH = 0
);
localparam int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8;
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_STRB_WIDTH-1:0] strb_t;
typedef logic [AXI_USER_WIDTH-1:0] user_t;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_pkg::atop_t atop;
user_t user;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
logic last;
user_t user;
} w_chan_t;
typedef struct packed {
id_t id;
axi_pkg::resp_t resp;
user_t user;
} b_chan_t;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
user_t user;
} ar_chan_t;
typedef struct packed {
id_t id;
data_t data;
axi_pkg::resp_t resp;
logic last;
user_t user;
} r_chan_t;
aw_chan_t [2**LOG_DEPTH-1:0] aw_data;
w_chan_t [2**LOG_DEPTH-1:0] w_data;
b_chan_t [2**LOG_DEPTH-1:0] b_data;
ar_chan_t [2**LOG_DEPTH-1:0] ar_data;
r_chan_t [2**LOG_DEPTH-1:0] r_data;
logic [LOG_DEPTH:0] aw_wptr, aw_rptr,
w_wptr, w_rptr,
b_wptr, b_rptr,
ar_wptr, ar_rptr,
r_wptr, r_rptr;
modport Master (
output aw_data, aw_wptr, input aw_rptr,
output w_data, w_wptr, input w_rptr,
input b_data, b_wptr, output b_rptr,
output ar_data, ar_wptr, input ar_rptr,
input r_data, r_wptr, output r_rptr);
modport Slave (
input aw_data, aw_wptr, output aw_rptr,
input w_data, w_wptr, output w_rptr,
output b_data, b_wptr, input b_rptr,
input ar_data, ar_wptr, output ar_rptr,
output r_data, r_wptr, input r_rptr);
endinterface
interface AXI_LITE #(
parameter int unsigned AXI_ADDR_WIDTH = 0,
parameter int unsigned AXI_DATA_WIDTH = 0
);
localparam int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8;
typedef logic [AXI_ADDR_WIDTH-1:0] addr_t;
typedef logic [AXI_DATA_WIDTH-1:0] data_t;
typedef logic [AXI_STRB_WIDTH-1:0] strb_t;
addr_t aw_addr;
axi_pkg::prot_t aw_prot;
logic aw_valid;
logic aw_ready;
data_t w_data;
strb_t w_strb;
logic w_valid;
logic w_ready;
axi_pkg::resp_t b_resp;
logic b_valid;
logic b_ready;
addr_t ar_addr;
axi_pkg::prot_t ar_prot;
logic ar_valid;
logic ar_ready;
data_t r_data;
axi_pkg::resp_t r_resp;
logic r_valid;
logic r_ready;
modport Master (
output aw_addr, aw_prot, aw_valid, input aw_ready,
output w_data, w_strb, w_valid, input w_ready,
input b_resp, b_valid, output b_ready,
output ar_addr, ar_prot, ar_valid, input ar_ready,
input r_data, r_resp, r_valid, output r_ready
);
modport Slave (
input aw_addr, aw_prot, aw_valid, output aw_ready,
input w_data, w_strb, w_valid, output w_ready,
output b_resp, b_valid, input b_ready,
input ar_addr, ar_prot, ar_valid, output ar_ready,
output r_data, r_resp, r_valid, input r_ready
);
modport Monitor (
input aw_addr, aw_prot, aw_valid, aw_ready,
w_data, w_strb, w_valid, w_ready,
b_resp, b_valid, b_ready,
ar_addr, ar_prot, ar_valid, ar_ready,
r_data, r_resp, r_valid, r_ready
);
endinterface
interface AXI_LITE_DV #(
parameter int unsigned AXI_ADDR_WIDTH = 0,
parameter int unsigned AXI_DATA_WIDTH = 0
)(
input logic clk_i
);
localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8;
typedef logic [AXI_ADDR_WIDTH-1:0] addr_t;
typedef logic [AXI_DATA_WIDTH-1:0] data_t;
typedef logic [AXI_STRB_WIDTH-1:0] strb_t;
addr_t aw_addr;
axi_pkg::prot_t aw_prot;
logic aw_valid;
logic aw_ready;
data_t w_data;
strb_t w_strb;
logic w_valid;
logic w_ready;
axi_pkg::resp_t b_resp;
logic b_valid;
logic b_ready;
addr_t ar_addr;
axi_pkg::prot_t ar_prot;
logic ar_valid;
logic ar_ready;
data_t r_data;
axi_pkg::resp_t r_resp;
logic r_valid;
logic r_ready;
modport Master (
output aw_addr, aw_prot, aw_valid, input aw_ready,
output w_data, w_strb, w_valid, input w_ready,
input b_resp, b_valid, output b_ready,
output ar_addr, ar_prot, ar_valid, input ar_ready,
input r_data, r_resp, r_valid, output r_ready
);
modport Slave (
input aw_addr, aw_prot, aw_valid, output aw_ready,
input w_data, w_strb, w_valid, output w_ready,
output b_resp, b_valid, input b_ready,
input ar_addr, ar_prot, ar_valid, output ar_ready,
output r_data, r_resp, r_valid, input r_ready
);
modport Monitor (
input aw_addr, aw_prot, aw_valid, aw_ready,
w_data, w_strb, w_valid, w_ready,
b_resp, b_valid, b_ready,
ar_addr, ar_prot, ar_valid, ar_ready,
r_data, r_resp, r_valid, r_ready
);
endinterface
interface AXI_LITE_ASYNC_GRAY #(
parameter int unsigned AXI_ADDR_WIDTH = 0,
parameter int unsigned AXI_DATA_WIDTH = 0,
parameter int unsigned LOG_DEPTH = 0
);
localparam int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8;
typedef logic [AXI_ADDR_WIDTH-1:0] addr_t;
typedef logic [AXI_DATA_WIDTH-1:0] data_t;
typedef logic [AXI_STRB_WIDTH-1:0] strb_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
} w_chan_t;
typedef struct packed {
axi_pkg::resp_t resp;
} b_chan_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} ar_chan_t;
typedef struct packed {
data_t data;
axi_pkg::resp_t resp;
} r_chan_t;
aw_chan_t [2**LOG_DEPTH-1:0] aw_data;
w_chan_t [2**LOG_DEPTH-1:0] w_data;
b_chan_t [2**LOG_DEPTH-1:0] b_data;
ar_chan_t [2**LOG_DEPTH-1:0] ar_data;
r_chan_t [2**LOG_DEPTH-1:0] r_data;
logic [LOG_DEPTH:0] aw_wptr, aw_rptr,
w_wptr, w_rptr,
b_wptr, b_rptr,
ar_wptr, ar_rptr,
r_wptr, r_rptr;
modport Master (
output aw_data, aw_wptr, input aw_rptr,
output w_data, w_wptr, input w_rptr,
input b_data, b_wptr, output b_rptr,
output ar_data, ar_wptr, input ar_rptr,
input r_data, r_wptr, output r_rptr);
modport Slave (
input aw_data, aw_wptr, output aw_rptr,
input w_data, w_wptr, output w_rptr,
output b_data, b_wptr, input b_rptr,
input ar_data, ar_wptr, output ar_rptr,
output r_data, r_wptr, input r_rptr);
endinterface
`begin_keywords "1800-2023"
module axi_atop_filter #(
parameter int unsigned AxiIdWidth = 0,
parameter int unsigned AxiMaxWriteTxns = 0,
parameter type axi_req_t = logic,
parameter type axi_resp_t = logic
) (
input logic clk_i,
input logic rst_ni,
input axi_req_t slv_req_i,
output axi_resp_t slv_resp_o,
output axi_req_t mst_req_o,
input axi_resp_t mst_resp_i
);
localparam int unsigned COUNTER_WIDTH = (AxiMaxWriteTxns == 1) ? 2 : $clog2(AxiMaxWriteTxns+1);
typedef struct packed {
logic underflow;
logic [COUNTER_WIDTH-1:0] cnt;
} cnt_t;
cnt_t w_cnt_d, w_cnt_q;
typedef enum logic [2:0] {
W_RESET, W_FEEDTHROUGH, BLOCK_AW, ABSORB_W, HOLD_B, INJECT_B, WAIT_R
} w_state_e;
w_state_e w_state_d, w_state_q;
typedef enum logic [1:0] { R_RESET, R_FEEDTHROUGH, INJECT_R, R_HOLD } r_state_e;
r_state_e r_state_d, r_state_q;
typedef logic [AxiIdWidth-1:0] id_t;
id_t id_d, id_q;
typedef logic [7:0] len_t;
len_t r_beats_d, r_beats_q;
typedef struct packed {
len_t len;
} r_resp_cmd_t;
r_resp_cmd_t r_resp_cmd_push, r_resp_cmd_pop;
logic aw_without_complete_w_downstream,
complete_w_without_aw_downstream,
r_resp_cmd_push_valid, r_resp_cmd_push_ready,
r_resp_cmd_pop_valid, r_resp_cmd_pop_ready;
assign aw_without_complete_w_downstream = !w_cnt_q.underflow && (w_cnt_q.cnt > 0);
assign complete_w_without_aw_downstream = w_cnt_q.underflow && &(w_cnt_q.cnt);
always_comb begin
mst_req_o.aw_valid = 1'b0;
slv_resp_o.aw_ready = 1'b0;
mst_req_o.w_valid = 1'b0;
slv_resp_o.w_ready = 1'b0;
mst_req_o.b_ready = slv_req_i.b_ready;
slv_resp_o.b_valid = mst_resp_i.b_valid;
slv_resp_o.b = mst_resp_i.b;
id_d = id_q;
r_resp_cmd_push_valid = 1'b0;
w_state_d = w_state_q;
unique case (w_state_q)
W_RESET: w_state_d = W_FEEDTHROUGH;
W_FEEDTHROUGH: begin
if (complete_w_without_aw_downstream || (w_cnt_q.cnt < AxiMaxWriteTxns)) begin
mst_req_o.aw_valid = slv_req_i.aw_valid;
slv_resp_o.aw_ready = mst_resp_i.aw_ready;
end
if (aw_without_complete_w_downstream
|| ((slv_req_i.aw_valid && slv_req_i.aw.atop[5:4] == axi_pkg::ATOP_NONE)
&& !complete_w_without_aw_downstream)
) begin
mst_req_o.w_valid = slv_req_i.w_valid;
slv_resp_o.w_ready = mst_resp_i.w_ready;
end
if (slv_req_i.aw_valid && slv_req_i.aw.atop[5:4] != axi_pkg::ATOP_NONE) begin
mst_req_o.aw_valid = 1'b0;
slv_resp_o.aw_ready = 1'b1;
id_d = slv_req_i.aw.id;
if (slv_req_i.aw.atop[axi_pkg::ATOP_R_RESP]) begin
r_resp_cmd_push_valid = 1'b1;
end
if (aw_without_complete_w_downstream) begin
w_state_d = BLOCK_AW;
end else begin
mst_req_o.w_valid = 1'b0;
slv_resp_o.w_ready = 1'b1;
if (slv_req_i.w_valid && slv_req_i.w.last) begin
if (slv_resp_o.b_valid && !slv_req_i.b_ready) begin
w_state_d = HOLD_B;
end else begin
w_state_d = INJECT_B;
end
end else begin
w_state_d = ABSORB_W;
end
end
end
end
BLOCK_AW: begin
if (aw_without_complete_w_downstream) begin
mst_req_o.w_valid = slv_req_i.w_valid;
slv_resp_o.w_ready = mst_resp_i.w_ready;
end else begin
slv_resp_o.w_ready = 1'b1;
if (slv_req_i.w_valid && slv_req_i.w.last) begin
if (slv_resp_o.b_valid && !slv_req_i.b_ready) begin
w_state_d = HOLD_B;
end else begin
w_state_d = INJECT_B;
end
end else begin
w_state_d = ABSORB_W;
end
end
end
ABSORB_W: begin
slv_resp_o.w_ready = 1'b1;
if (slv_req_i.w_valid && slv_req_i.w.last) begin
if (slv_resp_o.b_valid && !slv_req_i.b_ready) begin
w_state_d = HOLD_B;
end else begin
w_state_d = INJECT_B;
end
end
end
HOLD_B: begin
if (slv_resp_o.b_valid && slv_req_i.b_ready) begin
w_state_d = INJECT_B;
end
end
INJECT_B: begin
mst_req_o.b_ready = 1'b0;
slv_resp_o.b = '0;
slv_resp_o.b.id = id_q;
slv_resp_o.b.resp = axi_pkg::RESP_SLVERR;
slv_resp_o.b_valid = 1'b1;
if (slv_req_i.b_ready) begin
if (r_resp_cmd_pop_valid && !r_resp_cmd_pop_ready) begin
w_state_d = WAIT_R;
end else begin
w_state_d = W_FEEDTHROUGH;
end
end
end
WAIT_R: begin
if (!r_resp_cmd_pop_valid) begin
w_state_d = W_FEEDTHROUGH;
end
end
default: w_state_d = W_RESET;
endcase
end
always_comb begin
mst_req_o.aw = slv_req_i.aw;
mst_req_o.aw.atop = '0;
end
assign mst_req_o.w = slv_req_i.w;
always_comb begin
slv_resp_o.r = mst_resp_i.r;
slv_resp_o.r_valid = mst_resp_i.r_valid;
mst_req_o.r_ready = slv_req_i.r_ready;
r_resp_cmd_pop_ready = 1'b0;
r_beats_d = r_beats_q;
r_state_d = r_state_q;
unique case (r_state_q)
R_RESET: r_state_d = R_FEEDTHROUGH;
R_FEEDTHROUGH: begin
if (mst_resp_i.r_valid && !slv_req_i.r_ready) begin
r_state_d = R_HOLD;
end else if (r_resp_cmd_pop_valid) begin
r_beats_d = r_resp_cmd_pop.len;
r_state_d = INJECT_R;
end
end
INJECT_R: begin
mst_req_o.r_ready = 1'b0;
slv_resp_o.r = '0;
slv_resp_o.r.id = id_q;
slv_resp_o.r.resp = axi_pkg::RESP_SLVERR;
slv_resp_o.r.last = (r_beats_q == '0);
slv_resp_o.r_valid = 1'b1;
if (slv_req_i.r_ready) begin
if (slv_resp_o.r.last) begin
r_resp_cmd_pop_ready = 1'b1;
r_state_d = R_FEEDTHROUGH;
end else begin
r_beats_d -= 1;
end
end
end
R_HOLD: begin
if (mst_resp_i.r_valid && slv_req_i.r_ready) begin
r_state_d = R_FEEDTHROUGH;
end
end
default: r_state_d = R_RESET;
endcase
end
assign mst_req_o.ar = slv_req_i.ar;
assign mst_req_o.ar_valid = slv_req_i.ar_valid;
assign slv_resp_o.ar_ready = mst_resp_i.ar_ready;
always_comb begin
w_cnt_d = w_cnt_q;
if (mst_req_o.aw_valid && mst_resp_i.aw_ready) begin
w_cnt_d.cnt += 1;
end
if (mst_req_o.w_valid && mst_resp_i.w_ready && mst_req_o.w.last) begin
w_cnt_d.cnt -= 1;
end
if (w_cnt_q.underflow && (w_cnt_d.cnt == '0)) begin
w_cnt_d.underflow = 1'b0;
end else if (w_cnt_q.cnt == '0 && &(w_cnt_d.cnt)) begin
w_cnt_d.underflow = 1'b1;
end
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (!rst_ni) begin
id_q <= '0;
r_beats_q <= '0;
r_state_q <= R_RESET;
w_cnt_q <= '{default: '0};
w_state_q <= W_RESET;
end else begin
id_q <= id_d;
r_beats_q <= r_beats_d;
r_state_q <= r_state_d;
w_cnt_q <= w_cnt_d;
w_state_q <= w_state_d;
end
end
stream_register #(
.T(r_resp_cmd_t)
) r_resp_cmd (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (1'b0),
.testmode_i (1'b0),
.valid_i (r_resp_cmd_push_valid),
.ready_o (r_resp_cmd_push_ready),
.data_i (r_resp_cmd_push),
.valid_o (r_resp_cmd_pop_valid),
.ready_i (r_resp_cmd_pop_ready),
.data_o (r_resp_cmd_pop)
);
assign r_resp_cmd_push.len = slv_req_i.aw.len;
endmodule
module axi_atop_filter_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,
parameter int unsigned AXI_MAX_WRITE_TXNS = 0
) (
input logic clk_i,
input logic rst_ni,
AXI_BUS.Slave slv,
AXI_BUS.Master mst
);
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;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_pkg::atop_t atop;
user_t user;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
logic last;
user_t user;
} w_chan_t;
typedef struct packed {
id_t id;
axi_pkg::resp_t resp;
user_t user;
} b_chan_t;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
user_t user;
} ar_chan_t;
typedef struct packed {
id_t id;
data_t data;
axi_pkg::resp_t resp;
logic last;
user_t user;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} axi_req_t;
typedef struct packed {
logic aw_ready;
logic ar_ready;
logic w_ready;
logic b_valid;
b_chan_t b;
logic r_valid;
r_chan_t r;
} axi_resp_t;
axi_req_t slv_req, mst_req;
axi_resp_t slv_resp, mst_resp;
assign slv_req.aw.id = slv.aw_id;
assign slv_req.aw.addr = slv.aw_addr;
assign slv_req.aw.len = slv.aw_len;
assign slv_req.aw.size = slv.aw_size;
assign slv_req.aw.burst = slv.aw_burst;
assign slv_req.aw.lock = slv.aw_lock;
assign slv_req.aw.cache = slv.aw_cache;
assign slv_req.aw.prot = slv.aw_prot;
assign slv_req.aw.qos = slv.aw_qos;
assign slv_req.aw.region = slv.aw_region;
assign slv_req.aw.atop = slv.aw_atop;
assign slv_req.aw.user = slv.aw_user;
assign slv_req.aw_valid = slv.aw_valid;
assign slv_req.w.data = slv.w_data;
assign slv_req.w.strb = slv.w_strb;
assign slv_req.w.last = slv.w_last;
assign slv_req.w.user = slv.w_user;
assign slv_req.w_valid = slv.w_valid;
assign slv_req.b_ready = slv.b_ready;
assign slv_req.ar.id = slv.ar_id;
assign slv_req.ar.addr = slv.ar_addr;
assign slv_req.ar.len = slv.ar_len;
assign slv_req.ar.size = slv.ar_size;
assign slv_req.ar.burst = slv.ar_burst;
assign slv_req.ar.lock = slv.ar_lock;
assign slv_req.ar.cache = slv.ar_cache;
assign slv_req.ar.prot = slv.ar_prot;
assign slv_req.ar.qos = slv.ar_qos;
assign slv_req.ar.region = slv.ar_region;
assign slv_req.ar.user = slv.ar_user;
assign slv_req.ar_valid = slv.ar_valid;
assign slv_req.r_ready = slv.r_ready;
assign slv.aw_ready = slv_resp.aw_ready;
assign slv.ar_ready = slv_resp.ar_ready;
assign slv.w_ready = slv_resp.w_ready;
assign slv.b_valid = slv_resp.b_valid;
assign slv.b_id = slv_resp.b.id;
assign slv.b_resp = slv_resp.b.resp;
assign slv.b_user = slv_resp.b.user;
assign slv.r_valid = slv_resp.r_valid;
assign slv.r_id = slv_resp.r.id;
assign slv.r_data = slv_resp.r.data;
assign slv.r_resp = slv_resp.r.resp;
assign slv.r_last = slv_resp.r.last;
assign slv.r_user = slv_resp.r.user;
assign mst.aw_id = mst_req.aw.id;
assign mst.aw_addr = mst_req.aw.addr;
assign mst.aw_len = mst_req.aw.len;
assign mst.aw_size = mst_req.aw.size;
assign mst.aw_burst = mst_req.aw.burst;
assign mst.aw_lock = mst_req.aw.lock;
assign mst.aw_cache = mst_req.aw.cache;
assign mst.aw_prot = mst_req.aw.prot;
assign mst.aw_qos = mst_req.aw.qos;
assign mst.aw_region = mst_req.aw.region;
assign mst.aw_atop = mst_req.aw.atop;
assign mst.aw_user = mst_req.aw.user;
assign mst.aw_valid = mst_req.aw_valid;
assign mst.w_data = mst_req.w.data;
assign mst.w_strb = mst_req.w.strb;
assign mst.w_last = mst_req.w.last;
assign mst.w_user = mst_req.w.user;
assign mst.w_valid = mst_req.w_valid;
assign mst.b_ready = mst_req.b_ready;
assign mst.ar_id = mst_req.ar.id;
assign mst.ar_addr = mst_req.ar.addr;
assign mst.ar_len = mst_req.ar.len;
assign mst.ar_size = mst_req.ar.size;
assign mst.ar_burst = mst_req.ar.burst;
assign mst.ar_lock = mst_req.ar.lock;
assign mst.ar_cache = mst_req.ar.cache;
assign mst.ar_prot = mst_req.ar.prot;
assign mst.ar_qos = mst_req.ar.qos;
assign mst.ar_region = mst_req.ar.region;
assign mst.ar_user = mst_req.ar.user;
assign mst.ar_valid = mst_req.ar_valid;
assign mst.r_ready = mst_req.r_ready;
assign mst_resp.aw_ready = mst.aw_ready;
assign mst_resp.ar_ready = mst.ar_ready;
assign mst_resp.w_ready = mst.w_ready;
assign mst_resp.b_valid = mst.b_valid;
assign mst_resp.b.id = mst.b_id;
assign mst_resp.b.resp = mst.b_resp;
assign mst_resp.b.user = mst.b_user;
assign mst_resp.r_valid = mst.r_valid;
assign mst_resp.r.id = mst.r_id;
assign mst_resp.r.data = mst.r_data;
assign mst_resp.r.resp = mst.r_resp;
assign mst_resp.r.last = mst.r_last;
assign mst_resp.r.user = mst.r_user;
axi_atop_filter #(
.AxiIdWidth ( AXI_ID_WIDTH ),
.AxiMaxWriteTxns ( AXI_MAX_WRITE_TXNS ),
.axi_req_t ( axi_req_t ),
.axi_resp_t ( axi_resp_t )
) i_axi_atop_filter (
.clk_i,
.rst_ni,
.slv_req_i ( slv_req ),
.slv_resp_o ( slv_resp ),
.mst_req_o ( mst_req ),
.mst_resp_i ( mst_resp )
);
endmodule
`begin_keywords "1800-2023"
module axi_burst_splitter_gran #(
parameter int unsigned MaxReadTxns = 32'd0,
parameter int unsigned MaxWriteTxns = 32'd0,
parameter bit FullBW = 1'b0,
parameter bit CutPath = 1'b0,
parameter bit DisableChecks = 1'b0,
parameter int unsigned AddrWidth = 32'd0,
parameter int unsigned DataWidth = 32'd0,
parameter int unsigned IdWidth = 32'd0,
parameter int unsigned UserWidth = 32'd0,
parameter type axi_req_t = logic,
parameter type axi_resp_t = logic,
parameter type axi_aw_chan_t = logic,
parameter type axi_w_chan_t = logic,
parameter type axi_b_chan_t = logic,
parameter type axi_ar_chan_t = logic,
parameter type axi_r_chan_t = logic
) (
input logic clk_i,
input logic rst_ni,
input axi_pkg::len_t len_limit_i,
input axi_req_t slv_req_i,
output axi_resp_t slv_resp_o,
output axi_req_t mst_req_o,
input axi_resp_t mst_resp_i
);
axi_req_t slv_req, act_req, unsupported_req;
axi_resp_t slv_resp, act_resp, unsupported_resp;
axi_multicut #(
.NoCuts ( CutPath ),
.aw_chan_t ( axi_aw_chan_t ),
.w_chan_t ( axi_w_chan_t ),
.b_chan_t ( axi_b_chan_t ),
.ar_chan_t ( axi_ar_chan_t ),
.r_chan_t ( axi_r_chan_t ),
.axi_req_t ( axi_req_t ),
.axi_resp_t( axi_resp_t )
) i_axi_multicut (
.clk_i,
.rst_ni,
.slv_req_i ,
.slv_resp_o,
.mst_req_o ( slv_req ),
.mst_resp_i ( slv_resp )
);
logic sel_aw_unsupported, sel_ar_unsupported;
localparam int unsigned MaxTxns = (MaxReadTxns > MaxWriteTxns) ? MaxReadTxns : MaxWriteTxns;
axi_demux_simple #(
.AxiIdWidth ( IdWidth ),
.axi_req_t ( axi_req_t ),
.axi_resp_t ( axi_resp_t ),
.NoMstPorts ( 2 ),
.MaxTrans ( MaxTxns ),
.AxiLookBits ( IdWidth )
) i_demux_supported_vs_unsupported (
.clk_i,
.rst_ni,
.test_i ( 1'b0 ),
.slv_req_i ( slv_req ),
.slv_aw_select_i ( sel_aw_unsupported ),
.slv_ar_select_i ( sel_ar_unsupported ),
.slv_resp_o ( slv_resp ),
.mst_reqs_o ( {unsupported_req, act_req} ),
.mst_resps_i ( {unsupported_resp, act_resp} )
);
function bit txn_supported(axi_pkg::atop_t atop, axi_pkg::burst_t burst, axi_pkg::cache_t cache,
axi_pkg::len_t len, axi_pkg::len_t len_limit);
if (len >= len_limit) begin
return 1'b1;
end else begin
if (burst == axi_pkg::BURST_WRAP) return 1'b0;
if (atop != '0 & len > 0) return 1'b0;
if (!axi_pkg::modifiable(cache)) begin
return (burst == axi_pkg::BURST_INCR) & (len > 16);
end
return 1'b1;
end
endfunction
assign sel_aw_unsupported = DisableChecks ? 1'b0 : ~txn_supported(slv_req.aw.atop,
slv_req.aw.burst, slv_req.aw.cache, slv_req.aw.len,
len_limit_i);
assign sel_ar_unsupported = DisableChecks ? 1'b0 : ~txn_supported('0, slv_req.ar.burst,
slv_req.ar.cache, slv_req.ar.len, len_limit_i);
axi_err_slv #(
.AxiIdWidth ( IdWidth ),
.axi_req_t ( axi_req_t ),
.axi_resp_t ( axi_resp_t ),
.Resp ( axi_pkg::RESP_SLVERR ),
.ATOPs ( 1'b0 ),
.MaxTrans ( 1 )
) i_err_slv (
.clk_i,
.rst_ni,
.test_i ( 1'b0 ),
.slv_req_i ( unsupported_req ),
.slv_resp_o ( unsupported_resp )
);
logic w_cnt_dec, w_cnt_req, w_cnt_gnt, w_cnt_err;
axi_pkg::len_t w_cnt_len;
axi_burst_splitter_gran_ax_chan #(
.chan_t ( axi_aw_chan_t ),
.IdWidth ( IdWidth ),
.MaxTxns ( MaxWriteTxns ),
.CutPath ( CutPath ),
.FullBW ( FullBW )
) i_axi_burst_splitter_gran_aw_chan (
.clk_i,
.rst_ni,
.len_limit_i,
.ax_i ( act_req.aw ),
.ax_valid_i ( act_req.aw_valid ),
.ax_ready_o ( act_resp.aw_ready ),
.ax_o ( mst_req_o.aw ),
.ax_valid_o ( mst_req_o.aw_valid ),
.ax_ready_i ( mst_resp_i.aw_ready ),
.cnt_id_i ( mst_resp_i.b.id ),
.cnt_len_o ( w_cnt_len ),
.cnt_set_err_i ( mst_resp_i.b.resp[1] ),
.cnt_err_o ( w_cnt_err ),
.cnt_dec_i ( w_cnt_dec ),
.cnt_req_i ( w_cnt_req ),
.cnt_gnt_o ( w_cnt_gnt )
);
axi_pkg::len_t w_len_d, w_len_q;
logic w_len_vld_q, w_len_vld_d;
always_comb begin : proc_w_frag
mst_req_o.w = act_req.w;
w_len_d = w_len_q;
w_len_vld_d = w_len_vld_q;
if (len_limit_i != 8'h00) begin
mst_req_o.w.last = (w_len_vld_q & (w_len_q == 8'h00)) | act_req.w.last;
if (act_resp.w_ready & act_req.w_valid) begin
if (!w_len_vld_q) begin
w_len_vld_d = 1'b1;
w_len_d = len_limit_i - 8'h01;
end else begin
w_len_d = w_len_q - 8'h01;
if (w_len_q == 8'h00) begin
w_len_d = len_limit_i;
end
end
if (act_req.w.last) begin
w_len_vld_d = 1'b0;
w_len_d = 8'h00;
end
end
end else begin
mst_req_o.w.last = 1'b1;
end
end
assign mst_req_o.w_valid = act_req.w_valid;
assign act_resp.w_ready = mst_resp_i.w_ready;
enum logic {BReady, BWait} b_state_d, b_state_q;
logic b_err_d, b_err_q;
always_comb begin
mst_req_o.b_ready = 1'b0;
act_resp.b = '0;
act_resp.b_valid = 1'b0;
w_cnt_dec = 1'b0;
w_cnt_req = 1'b0;
b_err_d = b_err_q;
b_state_d = b_state_q;
unique case (b_state_q)
BReady: begin
if (mst_resp_i.b_valid) begin
w_cnt_req = 1'b1;
if (w_cnt_gnt) begin
if (w_cnt_len < ({1'b0, len_limit_i} + 9'h001)) begin
act_resp.b = mst_resp_i.b;
if (w_cnt_err) begin
act_resp.b.resp = axi_pkg::RESP_SLVERR;
end
act_resp.b_valid = 1'b1;
w_cnt_dec = 1'b1;
if (act_req.b_ready) begin
mst_req_o.b_ready = 1'b1;
end else begin
b_state_d = BWait;
b_err_d = w_cnt_err;
end
end else begin
mst_req_o.b_ready = 1'b1;
w_cnt_dec = 1'b1;
end
end
end
end
BWait: begin
act_resp.b = mst_resp_i.b;
if (b_err_q) begin
act_resp.b.resp = axi_pkg::RESP_SLVERR;
end
act_resp.b_valid = 1'b1;
if (mst_resp_i.b_valid && act_req.b_ready) begin
mst_req_o.b_ready = 1'b1;
b_state_d = BReady;
end
end
default: ;
endcase
end
logic r_cnt_dec, r_cnt_req, r_cnt_gnt;
axi_pkg::len_t r_cnt_len;
axi_burst_splitter_gran_ax_chan #(
.chan_t ( axi_ar_chan_t ),
.IdWidth ( IdWidth ),
.MaxTxns ( MaxReadTxns ),
.CutPath ( CutPath ),
.FullBW ( FullBW )
) i_axi_burst_splitter_gran_ar_chan (
.clk_i,
.rst_ni,
.len_limit_i,
.ax_i ( act_req.ar ),
.ax_valid_i ( act_req.ar_valid ),
.ax_ready_o ( act_resp.ar_ready ),
.ax_o ( mst_req_o.ar ),
.ax_valid_o ( mst_req_o.ar_valid ),
.ax_ready_i ( mst_resp_i.ar_ready ),
.cnt_id_i ( mst_resp_i.r.id ),
.cnt_len_o ( r_cnt_len ),
.cnt_set_err_i ( 1'b0 ),
.cnt_err_o ( ),
.cnt_dec_i ( r_cnt_dec ),
.cnt_req_i ( r_cnt_req ),
.cnt_gnt_o ( r_cnt_gnt )
);
logic r_last_d, r_last_q;
enum logic {RFeedthrough, RWait} r_state_d, r_state_q;
always_comb begin
r_cnt_dec = 1'b0;
r_cnt_req = 1'b0;
r_last_d = r_last_q;
r_state_d = r_state_q;
mst_req_o.r_ready = 1'b0;
act_resp.r = mst_resp_i.r;
act_resp.r.last = 1'b0;
act_resp.r_valid = 1'b0;
unique case (r_state_q)
RFeedthrough: begin
if (mst_resp_i.r_valid) begin
if (mst_resp_i.r.last) begin
r_cnt_req = 1'b1;
if (r_cnt_gnt) begin
r_last_d = (r_cnt_len < ({1'b0, len_limit_i} + 9'h001));
act_resp.r.last = r_last_d;
r_cnt_dec = 1'b1;
act_resp.r_valid = 1'b1;
if (act_req.r_ready) begin
mst_req_o.r_ready = 1'b1;
end else begin
r_state_d = RWait;
end
end
end else begin
r_last_d = 1'b0;
act_resp.r.last = r_last_d;
act_resp.r_valid = 1'b1;
if (act_req.r_ready) begin
mst_req_o.r_ready = 1'b1;
end else begin
r_state_d = RWait;
end
end
end
end
RWait: begin
act_resp.r.last = r_last_q;
act_resp.r_valid = mst_resp_i.r_valid;
if (mst_resp_i.r_valid && act_req.r_ready) begin
mst_req_o.r_ready = 1'b1;
r_state_d = RFeedthrough;
end
end
default: ;
endcase
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
b_err_q <= (1'b0);
end else begin
b_err_q <= (b_err_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
b_state_q <= (BReady);
end else begin
b_state_q <= (b_state_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
r_last_q <= (1'b0);
end else begin
r_last_q <= (r_last_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
r_state_q <= (RFeedthrough);
end else begin
r_state_q <= (r_state_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
w_len_q <= (8'h00);
end else begin
w_len_q <= (w_len_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
w_len_vld_q <= (1'b0);
end else begin
w_len_vld_q <= (w_len_vld_d);
end
end
endmodule
module axi_burst_splitter_gran_ax_chan #(
parameter type chan_t = logic,
parameter int unsigned IdWidth = 32'd0,
parameter int unsigned MaxTxns = 32'd0,
parameter bit CutPath = 1'b0,
parameter bit FullBW = 1'b0,
parameter type id_t = logic[IdWidth-1:0]
) (
input logic clk_i,
input logic rst_ni,
input axi_pkg::len_t len_limit_i,
input chan_t ax_i,
input logic ax_valid_i,
output logic ax_ready_o,
output chan_t ax_o,
output logic ax_valid_o,
input logic ax_ready_i,
input id_t cnt_id_i,
output axi_pkg::len_t cnt_len_o,
input logic cnt_set_err_i,
output logic cnt_err_o,
input logic cnt_dec_i,
input logic cnt_req_i,
output logic cnt_gnt_o
);
typedef logic[IdWidth-1:0] cnt_id_t;
typedef logic[axi_pkg::LenWidth:0] num_beats_t;
chan_t ax_d, ax_q;
num_beats_t num_beats_d, num_beats_q;
num_beats_t max_beats;
logic cnt_alloc_req, cnt_alloc_gnt;
axi_burst_splitter_gran_counters #(
.MaxTxns ( MaxTxns ),
.IdWidth ( IdWidth ),
.CutPath ( CutPath ),
.FullBW ( FullBW )
) i_axi_burst_splitter_gran_counters (
.clk_i,
.rst_ni,
.alloc_id_i ( ax_i.id ),
.alloc_len_i ( ax_i.len ),
.alloc_req_i ( cnt_alloc_req ),
.alloc_gnt_o ( cnt_alloc_gnt ),
.cnt_id_i ( cnt_id_i ),
.cnt_len_o ( cnt_len_o ),
.cnt_set_err_i ( cnt_set_err_i ),
.cnt_err_o ( cnt_err_o ),
.cnt_dec_i ( cnt_dec_i ),
.cnt_delta_i ( max_beats ),
.cnt_req_i ( cnt_req_i ),
.cnt_gnt_o ( cnt_gnt_o )
);
assign max_beats = {1'b0, len_limit_i} + 9'h001;
enum logic {Idle, Busy} state_d, state_q;
always_comb begin
cnt_alloc_req = 1'b0;
ax_d = ax_q;
state_d = state_q;
num_beats_d = num_beats_q;
ax_o = '0;
ax_valid_o = 1'b0;
ax_ready_o = 1'b0;
unique case (state_q)
Idle: begin
if (ax_valid_i && cnt_alloc_gnt) begin
if (ax_i.len <= len_limit_i) begin
ax_o = ax_i;
ax_valid_o = 1'b1;
if (ax_ready_i) begin
cnt_alloc_req = 1'b1;
ax_ready_o = 1'b1;
end
end else begin
ax_d = ax_i;
cnt_alloc_req = 1'b1;
ax_ready_o = 1'b1;
state_d = Busy;
num_beats_d = ({1'b0, ax_i.len} + 9'h001);
ax_o = ax_d;
ax_o.len = len_limit_i;
ax_valid_o = 1'b1;
if (ax_ready_i) begin
num_beats_d = ({1'b0, ax_i.len} + 9'h001) - max_beats;
if (ax_d.burst == axi_pkg::BURST_INCR) begin
ax_d.addr = axi_pkg::aligned_addr(axi_pkg::largest_addr_t'(ax_d.addr), ax_d.size);
ax_d.addr += (1 << ax_d.size) * max_beats;
end
end
end
end
end
Busy: begin
ax_o = ax_q;
ax_valid_o = 1'b1;
if (num_beats_q <= max_beats) begin
ax_o.len = axi_pkg::len_t'(num_beats_q - 9'h001);
end else begin
ax_o.len = len_limit_i;
end
if (ax_ready_i) begin
if (num_beats_q <= max_beats) begin
state_d = Idle;
end else begin
num_beats_d = num_beats_q - max_beats;
if (ax_q.burst == axi_pkg::BURST_INCR) begin
ax_d.addr = axi_pkg::aligned_addr(axi_pkg::largest_addr_t'(ax_q.addr), ax_q.size);
ax_d.addr += (1 << ax_q.size) * max_beats;
end
end
end
end
default: ;
endcase
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
ax_q <= ('0);
end else begin
ax_q <= (ax_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
state_q <= (Idle);
end else begin
state_q <= (state_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
num_beats_q <= (9'h000);
end else begin
num_beats_q <= (num_beats_d);
end
end
endmodule
module axi_burst_splitter_gran_counters #(
parameter int unsigned MaxTxns = 32'd0,
parameter int unsigned IdWidth = 32'd0,
parameter bit CutPath = 1'b0,
parameter bit FullBW = 1'b0,
parameter type id_t = logic [IdWidth-1:0],
parameter type cnt_t = logic [axi_pkg::LenWidth:0]
) (
input logic clk_i,
input logic rst_ni,
input id_t alloc_id_i,
input axi_pkg::len_t alloc_len_i,
input logic alloc_req_i,
output logic alloc_gnt_o,
input id_t cnt_id_i,
output axi_pkg::len_t cnt_len_o,
input logic cnt_set_err_i,
output logic cnt_err_o,
input logic cnt_dec_i,
input cnt_t cnt_delta_i,
input logic cnt_req_i,
output logic cnt_gnt_o
);
typedef struct packed {
id_t id;
axi_pkg::len_t len;
} alloc_pld_t;
alloc_pld_t alloc_pld_in, alloc_pld_out;
logic alloc_req;
logic alloc_gnt;
assign alloc_pld_in.id = alloc_id_i;
assign alloc_pld_in.len = alloc_len_i;
if (CutPath) begin : gen_spill
spill_register #(
.T ( alloc_pld_t ),
.Bypass ( 1'b0 )
) i_spill_register_alloc (
.clk_i,
.rst_ni,
.valid_i ( alloc_req_i ),
.ready_o ( alloc_gnt_o ),
.data_i ( alloc_pld_in ),
.valid_o ( alloc_req ),
.ready_i ( alloc_gnt ),
.data_o ( alloc_pld_out )
);
end else begin : gen_no_spill
assign alloc_req = alloc_req_i;
assign alloc_gnt_o = alloc_gnt;
assign alloc_pld_out = alloc_pld_in;
end
localparam int unsigned CntIdxWidth = (MaxTxns > 1) ? $clog2(MaxTxns) : 32'd1;
typedef logic [CntIdxWidth-1:0] cnt_idx_t;
logic [MaxTxns-1:0] cnt_dec, cnt_free, cnt_set, err_d, err_q, cnt_clr;
cnt_t cnt_inp;
cnt_t [MaxTxns-1:0] cnt_oup;
cnt_idx_t cnt_free_idx, cnt_r_idx;
for (genvar i = 0; i < MaxTxns; i++) begin : gen_cnt
delta_counter #(
.WIDTH ( $bits(cnt_t) )
) i_cnt (
.clk_i,
.rst_ni,
.clear_i ( cnt_clr[i] ),
.en_i ( cnt_dec[i] ),
.load_i ( cnt_set[i] ),
.down_i ( 1'b1 ),
.delta_i ( cnt_delta_i ),
.d_i ( cnt_inp ),
.q_o ( cnt_oup[i] ),
.overflow_o ( cnt_clr[i] )
);
assign cnt_free[i] = (cnt_oup[i] == '0);
end
assign cnt_inp = {1'b0, alloc_pld_out.len} + 1;
lzc #(
.WIDTH ( MaxTxns ),
.MODE ( 1'b0 )
) i_lzc (
.in_i ( cnt_free ),
.cnt_o ( cnt_free_idx ),
.empty_o ( )
);
logic idq_inp_req, idq_inp_gnt,
idq_oup_gnt, idq_oup_valid, idq_oup_pop;
id_queue #(
.ID_WIDTH ( $bits(id_t) ),
.CAPACITY ( MaxTxns ),
.FULL_BW ( FullBW ),
.data_t ( cnt_idx_t )
) i_idq (
.clk_i,
.rst_ni,
.inp_id_i ( alloc_pld_out.id ),
.inp_data_i ( cnt_free_idx ),
.inp_req_i ( idq_inp_req ),
.inp_gnt_o ( idq_inp_gnt ),
.exists_data_i ( '0 ),
.exists_mask_i ( '0 ),
.exists_req_i ( 1'b0 ),
.exists_o ( ),
.exists_gnt_o ( ),
.oup_id_i ( cnt_id_i ),
.oup_pop_i ( idq_oup_pop ),
.oup_req_i ( cnt_req_i ),
.oup_data_o ( cnt_r_idx ),
.oup_data_valid_o ( idq_oup_valid ),
.oup_gnt_o ( idq_oup_gnt ),
.full_o ( ),
.empty_o ( )
);
assign idq_inp_req = alloc_req & alloc_gnt;
assign alloc_gnt = idq_inp_gnt & |(cnt_free);
assign cnt_gnt_o = idq_oup_gnt & idq_oup_valid;
logic [8:0] read_len;
assign read_len = cnt_oup[cnt_r_idx] - 1;
assign cnt_len_o = read_len[7:0];
assign idq_oup_pop = cnt_req_i & cnt_gnt_o & cnt_dec_i & (cnt_len_o < cnt_delta_i);
always_comb begin
cnt_dec = '0;
cnt_dec[cnt_r_idx] = cnt_req_i & cnt_gnt_o & cnt_dec_i;
end
always_comb begin
cnt_set = '0;
cnt_set[cnt_free_idx] = alloc_req & alloc_gnt;
end
always_comb begin
err_d = err_q;
cnt_err_o = err_q[cnt_r_idx];
if (cnt_req_i && cnt_gnt_o && cnt_set_err_i) begin
err_d[cnt_r_idx] = 1'b1;
cnt_err_o = 1'b1;
end
if (alloc_req && alloc_gnt) begin
err_d[cnt_free_idx] = 1'b0;
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
err_q <= ('0);
end else begin
err_q <= (err_d);
end
end
endmodule
`begin_keywords "1800-2023"
module axi_burst_unwrap #(
parameter int unsigned MaxReadTxns = 32'd0,
parameter int unsigned MaxWriteTxns = 32'd0,
parameter int unsigned AddrWidth = 32'd0,
parameter int unsigned DataWidth = 32'd0,
parameter int unsigned IdWidth = 32'd0,
parameter int unsigned UserWidth = 32'd0,
parameter type axi_req_t = logic,
parameter type axi_resp_t = logic
) (
input logic clk_i,
input logic rst_ni,
input axi_req_t slv_req_i,
output axi_resp_t slv_resp_o,
output axi_req_t mst_req_o,
input axi_resp_t mst_resp_i
);
typedef logic [AddrWidth-1:0] addr_t;
typedef logic [DataWidth-1:0] data_t;
typedef logic [IdWidth-1:0] id_t;
typedef logic [DataWidth/8-1:0] strb_t;
typedef logic [UserWidth-1:0] user_t;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_pkg::atop_t atop;
user_t user;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
logic last;
user_t user;
} w_chan_t;
typedef struct packed {
id_t id;
axi_pkg::resp_t resp;
user_t user;
} b_chan_t;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
user_t user;
} ar_chan_t;
typedef struct packed {
id_t id;
data_t data;
axi_pkg::resp_t resp;
logic last;
user_t user;
} r_chan_t;
axi_req_t act_req, unsupported_req;
axi_resp_t act_resp, unsupported_resp;
logic sel_aw_unsupported, sel_ar_unsupported;
localparam int unsigned MaxTxns = (MaxReadTxns > MaxWriteTxns) ? MaxReadTxns : MaxWriteTxns;
axi_demux #(
.AxiIdWidth ( IdWidth ),
.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 ),
.NoMstPorts ( 2 ),
.MaxTrans ( MaxTxns ),
.AxiLookBits ( IdWidth ),
.SpillAw ( 1'b0 ),
.SpillW ( 1'b0 ),
.SpillB ( 1'b0 ),
.SpillAr ( 1'b0 ),
.SpillR ( 1'b0 )
) i_demux_supported_vs_unsupported (
.clk_i,
.rst_ni,
.test_i ( 1'b0 ),
.slv_req_i,
.slv_aw_select_i ( sel_aw_unsupported ),
.slv_ar_select_i ( sel_ar_unsupported ),
.slv_resp_o,
.mst_reqs_o ( {unsupported_req, act_req} ),
.mst_resps_i ( {unsupported_resp, act_resp} )
);
function bit txn_supported(axi_pkg::atop_t atop, axi_pkg::burst_t burst, axi_pkg::cache_t cache,
axi_pkg::len_t len);
if (len == '0) return 1'b1;
if (atop != '0) return 1'b0;
if (!axi_pkg::modifiable(cache) && (burst == axi_pkg::BURST_WRAP)) begin
return 1'b0;
end
return 1'b1;
endfunction
assign sel_aw_unsupported = ~txn_supported(slv_req_i.aw.atop, slv_req_i.aw.burst,
slv_req_i.aw.cache, slv_req_i.aw.len);
assign sel_ar_unsupported = ~txn_supported('0, slv_req_i.ar.burst,
slv_req_i.ar.cache, slv_req_i.ar.len);
axi_err_slv #(
.AxiIdWidth ( IdWidth ),
.axi_req_t ( axi_req_t ),
.axi_resp_t ( axi_resp_t ),
.Resp ( axi_pkg::RESP_SLVERR ),
.ATOPs ( 1'b0 ),
.MaxTrans ( 1 )
) i_err_slv (
.clk_i,
.rst_ni,
.test_i ( 1'b0 ),
.slv_req_i ( unsupported_req ),
.slv_resp_o ( unsupported_resp )
);
logic b_cnt_dec, b_cnt_req, b_cnt_gnt, b_cnt_err;
logic w_cnt_dec, w_cnt_req, w_cnt_gnt;
axi_pkg::len_t b_cnt_len, w_cnt_len;
axi_burst_unwrap_ax_chan #(
.AwChan ( 1'b1 ),
.chan_t ( aw_chan_t ),
.AddrWidth ( AddrWidth ),
.IdWidth ( IdWidth ),
.MaxTxns ( MaxWriteTxns )
) i_axi_burst_unwrap_aw_chan (
.clk_i,
.rst_ni,
.ax_i ( act_req.aw ),
.ax_valid_i ( act_req.aw_valid ),
.ax_ready_o ( act_resp.aw_ready ),
.ax_o ( mst_req_o.aw ),
.ax_valid_o ( mst_req_o.aw_valid ),
.ax_ready_i ( mst_resp_i.aw_ready ),
.cnt_id_i ( mst_resp_i.b.id ),
.cnt_len_o ({ w_cnt_len , b_cnt_len }),
.cnt_set_err_i ( mst_resp_i.b.resp[1] ),
.cnt_err_o ( b_cnt_err ),
.cnt_dec_i ({ w_cnt_dec , b_cnt_dec }),
.cnt_req_i ({ w_cnt_req , b_cnt_req }),
.cnt_gnt_o ({ w_cnt_gnt , b_cnt_gnt })
);
logic w_last_d, w_last_q;
enum logic [1:0] {WReady, WWait, WFeedthrough} w_state_d, w_state_q;
always_comb begin
w_cnt_dec = 1'b0;
w_cnt_req = 1'b0;
w_last_d = w_last_q;
w_state_d = w_state_q;
mst_req_o.w_valid = 1'b0;
mst_req_o.w = act_req.w;
act_resp.w_ready = 1'b0;
unique case (w_state_q)
WReady: begin
if (act_req.w_valid) begin
w_cnt_req = 1'b1;
if (w_cnt_gnt) begin
w_last_d = act_req.w.last | (w_cnt_len == 8'd0);
mst_req_o.w.last = w_last_d;
w_cnt_dec = 1'b1;
mst_req_o.w_valid = 1'b1;
if (mst_resp_i.w_ready) begin
act_resp.w_ready = 1'b1;
if (w_last_d && !act_req.w.last) begin
w_state_d = WFeedthrough;
end
end else begin
w_state_d = WWait;
end
end
end
end
WWait: begin
mst_req_o.w.last = w_last_q;
mst_req_o.w_valid = 1'b1;
if (mst_resp_i.w_ready) begin
act_resp.w_ready = 1'b1;
w_state_d = (!w_last_q || act_req.w.last) ? WReady : WFeedthrough;
end
end
WFeedthrough: begin
mst_req_o.w_valid = act_req.w_valid;
act_resp.w_ready = mst_resp_i.w_ready;
if (act_req.w_valid && mst_resp_i.w_ready && act_req.w.last) begin
w_state_d = WReady;
end
end
default: ;
endcase
end
enum logic {BReady, BWait} b_state_d, b_state_q;
logic b_err_d, b_err_q;
always_comb begin
mst_req_o.b_ready = 1'b0;
act_resp.b = '0;
act_resp.b_valid = 1'b0;
b_cnt_dec = 1'b0;
b_cnt_req = 1'b0;
b_err_d = b_err_q;
b_state_d = b_state_q;
unique case (b_state_q)
BReady: begin
if (mst_resp_i.b_valid) begin
b_cnt_req = 1'b1;
if (b_cnt_gnt) begin
if (b_cnt_len == 8'd0) begin
act_resp.b = mst_resp_i.b;
if (b_cnt_err) begin
act_resp.b.resp = axi_pkg::RESP_SLVERR;
end
act_resp.b_valid = 1'b1;
b_cnt_dec = 1'b1;
if (act_req.b_ready) begin
mst_req_o.b_ready = 1'b1;
end else begin
b_state_d = BWait;
b_err_d = b_cnt_err;
end
end else begin
mst_req_o.b_ready = 1'b1;
b_cnt_dec = 1'b1;
end
end
end
end
BWait: begin
act_resp.b = mst_resp_i.b;
if (b_err_q) begin
act_resp.b.resp = axi_pkg::RESP_SLVERR;
end
act_resp.b_valid = 1'b1;
if (mst_resp_i.b_valid && act_req.b_ready) begin
mst_req_o.b_ready = 1'b1;
b_state_d = BReady;
end
end
default: ;
endcase
end
logic r_cnt_dec, r_cnt_req, r_cnt_gnt, unc0;
axi_pkg::len_t r_cnt_len, unc1;
axi_burst_unwrap_ax_chan #(
.AwChan ( 0 ),
.chan_t ( ar_chan_t ),
.AddrWidth ( AddrWidth ),
.IdWidth ( IdWidth ),
.MaxTxns ( MaxReadTxns )
) i_axi_burst_unwrap_ar_chan (
.clk_i,
.rst_ni,
.ax_i ( act_req.ar ),
.ax_valid_i ( act_req.ar_valid ),
.ax_ready_o ( act_resp.ar_ready ),
.ax_o ( mst_req_o.ar ),
.ax_valid_o ( mst_req_o.ar_valid ),
.ax_ready_i ( mst_resp_i.ar_ready ),
.cnt_id_i ( mst_resp_i.r.id ),
.cnt_len_o ({ unc1 , r_cnt_len }),
.cnt_set_err_i ( 1'b0 ),
.cnt_err_o ( ),
.cnt_dec_i ({ 1'b0 , r_cnt_dec }),
.cnt_req_i ({ 1'b0 , r_cnt_req }),
.cnt_gnt_o ({ unc0 , r_cnt_gnt })
);
logic r_last_d, r_last_q;
enum logic {RFeedthrough, RWait} r_state_d, r_state_q;
always_comb begin
r_cnt_dec = 1'b0;
r_cnt_req = 1'b0;
r_last_d = r_last_q;
r_state_d = r_state_q;
mst_req_o.r_ready = 1'b0;
act_resp.r = mst_resp_i.r;
act_resp.r.last = 1'b0;
act_resp.r_valid = 1'b0;
unique case (r_state_q)
RFeedthrough: begin
if (mst_resp_i.r_valid) begin
r_cnt_req = 1'b1;
if (r_cnt_gnt) begin
r_last_d = (r_cnt_len == 8'd0);
act_resp.r.last = r_last_d;
r_cnt_dec = 1'b1;
act_resp.r_valid = 1'b1;
if (act_req.r_ready) begin
mst_req_o.r_ready = 1'b1;
end else begin
r_state_d = RWait;
end
end
end
end
RWait: begin
act_resp.r.last = r_last_q;
act_resp.r_valid = mst_resp_i.r_valid;
if (mst_resp_i.r_valid && act_req.r_ready) begin
mst_req_o.r_ready = 1'b1;
r_state_d = RFeedthrough;
end
end
default: ;
endcase
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
b_err_q <= (1'b0);
end else begin
b_err_q <= (b_err_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
b_state_q <= (BReady);
end else begin
b_state_q <= (b_state_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
r_last_q <= (1'b0);
end else begin
r_last_q <= (r_last_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
r_state_q <= (RFeedthrough);
end else begin
r_state_q <= (r_state_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
w_last_q <= (1'b0);
end else begin
w_last_q <= (w_last_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
w_state_q <= (WReady);
end else begin
w_state_q <= (w_state_d);
end
end
endmodule
module axi_burst_unwrap_ax_chan #(
parameter bit AwChan = 0,
parameter type chan_t = logic,
parameter int unsigned AddrWidth = 0,
parameter int unsigned IdWidth = 0,
parameter int unsigned MaxTxns = 0,
parameter type id_t = logic[IdWidth-1:0]
) (
input logic clk_i,
input logic rst_ni,
input chan_t ax_i,
input logic ax_valid_i,
output logic ax_ready_o,
output chan_t ax_o,
output logic ax_valid_o,
input logic ax_ready_i,
input id_t cnt_id_i,
output axi_pkg::len_t [1:0] cnt_len_o,
input logic cnt_set_err_i,
output logic cnt_err_o,
input logic [1:0] cnt_dec_i,
input logic [1:0] cnt_req_i,
output logic [1:0] cnt_gnt_o
);
typedef logic[IdWidth-1:0] cnt_id_t;
logic [1:0] cnt_alloc_req, cnt_alloc_gnt;
axi_pkg::len_t split_len, alloc_len_0;
axi_burst_counters #(
.MaxTxns ( MaxTxns ),
.IdWidth ( IdWidth )
) i_axi_burst_counters0 (
.clk_i,
.rst_ni,
.alloc_id_i ( ax_i.id ),
.alloc_len_i ( alloc_len_0 ),
.alloc_req_i ( cnt_alloc_req[0] ),
.alloc_gnt_o ( cnt_alloc_gnt[0] ),
.cnt_id_i ( cnt_id_i ),
.cnt_len_o ( cnt_len_o[0] ),
.cnt_set_err_i ( cnt_set_err_i ),
.cnt_err_o ( cnt_err_o ),
.cnt_dec_i ( cnt_dec_i[0] ),
.cnt_req_i ( cnt_req_i[0] ),
.cnt_gnt_o ( cnt_gnt_o[0] )
);
assign alloc_len_0 = AwChan ? split_len : ax_i.len;
axi_burst_counters #(
.MaxTxns ( MaxTxns ),
.IdWidth ( 1 )
) i_axi_burst_counters1 (
.clk_i,
.rst_ni,
.alloc_id_i ( 1'b0 ),
.alloc_len_i ( ax_o.len ),
.alloc_req_i ( cnt_alloc_req[1] ),
.alloc_gnt_o ( cnt_alloc_gnt[1] ),
.cnt_id_i ( 1'b0 ),
.cnt_len_o ( cnt_len_o[1] ),
.cnt_set_err_i ( 1'b0 ),
.cnt_err_o ( ),
.cnt_dec_i ( cnt_dec_i[1] ),
.cnt_req_i ( cnt_req_i[1] ),
.cnt_gnt_o ( cnt_gnt_o[1] )
);
chan_t ax_d, ax_q;
logic [10:0] container_size;
logic [AddrWidth-1:0] wrap_boundary;
assign container_size = (ax_i.len + 1) << ax_i.size;
assign wrap_boundary = ax_i.addr & ~(AddrWidth'(container_size) - 1);
enum logic {Idle, Busy} state_d, state_q;
always_comb begin
cnt_alloc_req = '0;
ax_d = ax_q;
state_d = state_q;
ax_o = '0;
ax_valid_o = 1'b0;
ax_ready_o = 1'b0;
split_len = 8'd0;
unique case (state_q)
Idle: begin
if (ax_valid_i && &cnt_alloc_gnt) begin
if (ax_i.burst == axi_pkg::BURST_WRAP && ax_i.addr != wrap_boundary) begin
ax_d = ax_i;
ax_d.burst = axi_pkg::BURST_INCR;
split_len = 8'd1;
ax_o = ax_d;
ax_o.len = ((wrap_boundary + container_size - ax_i.addr) >> ax_i.size) - 1;
ax_d.len = ((ax_i.addr - wrap_boundary) >> ax_i.size) - 1;
ax_d.addr = wrap_boundary;
ax_valid_o = 1'b1;
if (ax_ready_i) begin
ax_ready_o = 1'b1;
state_d = Busy;
cnt_alloc_req = { AwChan, 1'b1 };
end
end else begin
ax_o = ax_i;
if (ax_i.burst == axi_pkg::BURST_WRAP) begin
ax_o.burst = axi_pkg::BURST_INCR;
end
ax_valid_o = 1'b1;
if (ax_ready_i) begin
cnt_alloc_req = { AwChan, 1'b1 };
ax_ready_o = 1'b1;
end
end
end
end
Busy: begin
ax_o = ax_q;
ax_valid_o = 1'b1;
if (ax_ready_i) begin
state_d = Idle;
end
end
default: ;
endcase
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
ax_q <= ('0);
end else begin
ax_q <= (ax_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
state_q <= (Idle);
end else begin
state_q <= (state_d);
end
end
endmodule
module axi_burst_counters #(
parameter int unsigned MaxTxns = 0,
parameter int unsigned IdWidth = 0,
parameter type id_t = logic [IdWidth-1:0]
) (
input logic clk_i,
input logic rst_ni,
input id_t alloc_id_i,
input axi_pkg::len_t alloc_len_i,
input logic alloc_req_i,
output logic alloc_gnt_o,
input id_t cnt_id_i,
output axi_pkg::len_t cnt_len_o,
input logic cnt_set_err_i,
output logic cnt_err_o,
input logic cnt_dec_i,
input logic cnt_req_i,
output logic cnt_gnt_o
);
localparam int unsigned CntIdxWidth = (MaxTxns > 1) ? $clog2(MaxTxns) : 32'd1;
typedef logic [CntIdxWidth-1:0] cnt_idx_t;
typedef logic [$bits(axi_pkg::len_t):0] cnt_t;
logic [MaxTxns-1:0] cnt_dec, cnt_free, cnt_set, err_d, err_q;
cnt_t cnt_inp;
cnt_t [MaxTxns-1:0] cnt_oup;
cnt_idx_t cnt_free_idx, cnt_r_idx;
for (genvar i = 0; i < MaxTxns; i++) begin : gen_cnt
counter #(
.WIDTH ( $bits(cnt_t) )
) i_cnt (
.clk_i,
.rst_ni,
.clear_i ( 1'b0 ),
.en_i ( cnt_dec[i] ),
.load_i ( cnt_set[i] ),
.down_i ( 1'b1 ),
.d_i ( cnt_inp ),
.q_o ( cnt_oup[i] ),
.overflow_o ( )
);
assign cnt_free[i] = (cnt_oup[i] == '0);
end
assign cnt_inp = {1'b0, alloc_len_i} + 1;
lzc #(
.WIDTH ( MaxTxns ),
.MODE ( 1'b0 )
) i_lzc (
.in_i ( cnt_free ),
.cnt_o ( cnt_free_idx ),
.empty_o ( )
);
logic idq_inp_req, idq_inp_gnt,
idq_oup_gnt, idq_oup_valid, idq_oup_pop;
id_queue #(
.ID_WIDTH ( $bits(id_t) ),
.CAPACITY ( MaxTxns ),
.data_t ( cnt_idx_t )
) i_idq (
.clk_i,
.rst_ni,
.inp_id_i ( alloc_id_i ),
.inp_data_i ( cnt_free_idx ),
.inp_req_i ( idq_inp_req ),
.inp_gnt_o ( idq_inp_gnt ),
.exists_data_i ( '0 ),
.exists_mask_i ( '0 ),
.exists_req_i ( 1'b0 ),
.exists_o ( ),
.exists_gnt_o ( ),
.oup_id_i ( cnt_id_i ),
.oup_pop_i ( idq_oup_pop ),
.oup_req_i ( cnt_req_i ),
.oup_data_o ( cnt_r_idx ),
.oup_data_valid_o ( idq_oup_valid ),
.oup_gnt_o ( idq_oup_gnt ),
.full_o ( ),
.empty_o ( )
);
assign idq_inp_req = alloc_req_i & alloc_gnt_o;
assign alloc_gnt_o = idq_inp_gnt & |(cnt_free);
assign cnt_gnt_o = idq_oup_gnt & idq_oup_valid;
logic [8:0] read_len;
assign read_len = cnt_oup[cnt_r_idx] - 1;
assign cnt_len_o = read_len[7:0];
assign idq_oup_pop = cnt_req_i & cnt_gnt_o & cnt_dec_i & (cnt_len_o == 8'd0);
always_comb begin
cnt_dec = '0;
cnt_dec[cnt_r_idx] = cnt_req_i & cnt_gnt_o & cnt_dec_i;
end
always_comb begin
cnt_set = '0;
cnt_set[cnt_free_idx] = alloc_req_i & alloc_gnt_o;
end
always_comb begin
err_d = err_q;
cnt_err_o = err_q[cnt_r_idx];
if (cnt_req_i && cnt_gnt_o && cnt_set_err_i) begin
err_d[cnt_r_idx] = 1'b1;
cnt_err_o = 1'b1;
end
if (alloc_req_i && alloc_gnt_o) begin
err_d[cnt_free_idx] = 1'b0;
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
err_q <= ('0);
end else begin
err_q <= (err_d);
end
end
endmodule
`begin_keywords "1800-2023"
module axi_bus_compare #(
parameter int unsigned AxiIdWidth = 32'd0,
parameter int unsigned FifoDepth = 32'd0,
parameter bit UseSize = 1'b0,
parameter int unsigned DataWidth = 32'd8,
parameter type axi_aw_chan_t = logic,
parameter type axi_w_chan_t = logic,
parameter type axi_b_chan_t = logic,
parameter type axi_ar_chan_t = logic,
parameter type axi_r_chan_t = logic,
parameter type axi_req_t = logic,
parameter type axi_rsp_t = logic,
parameter type id_t = logic [2**AxiIdWidth-1:0]
)(
input logic clk_i,
input logic rst_ni,
input logic testmode_i,
input axi_req_t axi_a_req_i,
output axi_rsp_t axi_a_rsp_o,
output axi_req_t axi_a_req_o,
input axi_rsp_t axi_a_rsp_i,
input axi_req_t axi_b_req_i,
output axi_rsp_t axi_b_rsp_o,
output axi_req_t axi_b_req_o,
input axi_rsp_t axi_b_rsp_i,
output id_t aw_mismatch_o,
output logic w_mismatch_o,
output id_t b_mismatch_o,
output id_t ar_mismatch_o,
output id_t r_mismatch_o,
output logic mismatch_o,
output logic busy_o
);
assign axi_a_req_o.aw.id = axi_a_req_i.aw.id;
assign axi_a_req_o.aw.addr = axi_a_req_i.aw.addr;
assign axi_a_req_o.aw.len = axi_a_req_i.aw.len;
assign axi_a_req_o.aw.size = axi_a_req_i.aw.size;
assign axi_a_req_o.aw.burst = axi_a_req_i.aw.burst;
assign axi_a_req_o.aw.lock = axi_a_req_i.aw.lock;
assign axi_a_req_o.aw.cache = axi_a_req_i.aw.cache;
assign axi_a_req_o.aw.prot = axi_a_req_i.aw.prot;
assign axi_a_req_o.aw.qos = axi_a_req_i.aw.qos;
assign axi_a_req_o.aw.region = axi_a_req_i.aw.region;
assign axi_a_req_o.aw.atop = axi_a_req_i.aw.atop;
assign axi_a_req_o.aw.user = axi_a_req_i.aw.user;
assign axi_a_req_o.w.data = axi_a_req_i.w.data;
assign axi_a_req_o.w.strb = axi_a_req_i.w.strb;
assign axi_a_req_o.w.last = axi_a_req_i.w.last;
assign axi_a_req_o.w.user = axi_a_req_i.w.user;
assign axi_a_req_o.ar.id = axi_a_req_i.ar.id;
assign axi_a_req_o.ar.addr = axi_a_req_i.ar.addr;
assign axi_a_req_o.ar.len = axi_a_req_i.ar.len;
assign axi_a_req_o.ar.size = axi_a_req_i.ar.size;
assign axi_a_req_o.ar.burst = axi_a_req_i.ar.burst;
assign axi_a_req_o.ar.lock = axi_a_req_i.ar.lock;
assign axi_a_req_o.ar.cache = axi_a_req_i.ar.cache;
assign axi_a_req_o.ar.prot = axi_a_req_i.ar.prot;
assign axi_a_req_o.ar.qos = axi_a_req_i.ar.qos;
assign axi_a_req_o.ar.region = axi_a_req_i.ar.region;
assign axi_a_req_o.ar.user = axi_a_req_i.ar.user;
assign axi_a_rsp_o.r.id = axi_a_rsp_i.r.id;
assign axi_a_rsp_o.r.data = axi_a_rsp_i.r.data;
assign axi_a_rsp_o.r.resp = axi_a_rsp_i.r.resp;
assign axi_a_rsp_o.r.last = axi_a_rsp_i.r.last;
assign axi_a_rsp_o.r.user = axi_a_rsp_i.r.user;
assign axi_a_rsp_o.b.id = axi_a_rsp_i.b.id;
assign axi_a_rsp_o.b.resp = axi_a_rsp_i.b.resp;
assign axi_a_rsp_o.b.user = axi_a_rsp_i.b.user;
assign axi_b_req_o.aw.id = axi_b_req_i.aw.id;
assign axi_b_req_o.aw.addr = axi_b_req_i.aw.addr;
assign axi_b_req_o.aw.len = axi_b_req_i.aw.len;
assign axi_b_req_o.aw.size = axi_b_req_i.aw.size;
assign axi_b_req_o.aw.burst = axi_b_req_i.aw.burst;
assign axi_b_req_o.aw.lock = axi_b_req_i.aw.lock;
assign axi_b_req_o.aw.cache = axi_b_req_i.aw.cache;
assign axi_b_req_o.aw.prot = axi_b_req_i.aw.prot;
assign axi_b_req_o.aw.qos = axi_b_req_i.aw.qos;
assign axi_b_req_o.aw.region = axi_b_req_i.aw.region;
assign axi_b_req_o.aw.atop = axi_b_req_i.aw.atop;
assign axi_b_req_o.aw.user = axi_b_req_i.aw.user;
assign axi_b_req_o.w.data = axi_b_req_i.w.data;
assign axi_b_req_o.w.strb = axi_b_req_i.w.strb;
assign axi_b_req_o.w.last = axi_b_req_i.w.last;
assign axi_b_req_o.w.user = axi_b_req_i.w.user;
assign axi_b_req_o.ar.id = axi_b_req_i.ar.id;
assign axi_b_req_o.ar.addr = axi_b_req_i.ar.addr;
assign axi_b_req_o.ar.len = axi_b_req_i.ar.len;
assign axi_b_req_o.ar.size = axi_b_req_i.ar.size;
assign axi_b_req_o.ar.burst = axi_b_req_i.ar.burst;
assign axi_b_req_o.ar.lock = axi_b_req_i.ar.lock;
assign axi_b_req_o.ar.cache = axi_b_req_i.ar.cache;
assign axi_b_req_o.ar.prot = axi_b_req_i.ar.prot;
assign axi_b_req_o.ar.qos = axi_b_req_i.ar.qos;
assign axi_b_req_o.ar.region = axi_b_req_i.ar.region;
assign axi_b_req_o.ar.user = axi_b_req_i.ar.user;
assign axi_b_rsp_o.r.id = axi_b_rsp_i.r.id;
assign axi_b_rsp_o.r.data = axi_b_rsp_i.r.data;
assign axi_b_rsp_o.r.resp = axi_b_rsp_i.r.resp;
assign axi_b_rsp_o.r.last = axi_b_rsp_i.r.last;
assign axi_b_rsp_o.r.user = axi_b_rsp_i.r.user;
assign axi_b_rsp_o.b.id = axi_b_rsp_i.b.id;
assign axi_b_rsp_o.b.resp = axi_b_rsp_i.b.resp;
assign axi_b_rsp_o.b.user = axi_b_rsp_i.b.user;
id_t fifo_valid_aw_a, fifo_ready_aw_a;
id_t fifo_valid_b_a, fifo_ready_b_a;
id_t fifo_valid_ar_a, fifo_ready_ar_a;
id_t fifo_valid_r_a, fifo_ready_r_a;
logic fifo_sel_valid_aw_a, fifo_sel_ready_aw_a;
logic fifo_sel_valid_w_a, fifo_sel_ready_w_a;
logic fifo_sel_valid_b_a, fifo_sel_ready_b_a;
logic fifo_sel_valid_ar_a, fifo_sel_ready_ar_a;
logic fifo_sel_valid_r_a, fifo_sel_ready_r_a;
id_t fifo_valid_aw_b, fifo_ready_aw_b;
id_t fifo_valid_b_b, fifo_ready_b_b;
id_t fifo_valid_ar_b, fifo_ready_ar_b;
id_t fifo_valid_r_b, fifo_ready_r_b;
logic fifo_sel_valid_aw_b, fifo_sel_ready_aw_b;
logic fifo_sel_valid_w_b, fifo_sel_ready_w_b;
logic fifo_sel_valid_b_b, fifo_sel_ready_b_b;
logic fifo_sel_valid_ar_b, fifo_sel_ready_ar_b;
logic fifo_sel_valid_r_b, fifo_sel_ready_r_b;
id_t fifo_cmp_valid_aw_a;
logic fifo_cmp_valid_w_a;
id_t fifo_cmp_valid_b_a;
id_t fifo_cmp_valid_ar_a;
id_t fifo_cmp_valid_r_a;
id_t fifo_cmp_valid_aw_b;
logic fifo_cmp_valid_w_b;
id_t fifo_cmp_valid_b_b;
id_t fifo_cmp_valid_ar_b;
id_t fifo_cmp_valid_r_b;
axi_aw_chan_t [2**AxiIdWidth-1:0] fifo_cmp_data_aw_a;
axi_w_chan_t fifo_cmp_data_w_a;
axi_b_chan_t [2**AxiIdWidth-1:0] fifo_cmp_data_b_a;
axi_ar_chan_t [2**AxiIdWidth-1:0] fifo_cmp_data_ar_a;
axi_r_chan_t [2**AxiIdWidth-1:0] fifo_cmp_data_r_a;
axi_aw_chan_t [2**AxiIdWidth-1:0] fifo_cmp_data_aw_b;
axi_w_chan_t fifo_cmp_data_w_b;
axi_b_chan_t [2**AxiIdWidth-1:0] fifo_cmp_data_b_b;
axi_ar_chan_t [2**AxiIdWidth-1:0] fifo_cmp_data_ar_b;
axi_r_chan_t [2**AxiIdWidth-1:0] fifo_cmp_data_r_b;
logic [2:0] w_size;
logic [$clog2(DataWidth/8)-1:0] w_lower, w_offset, w_increment;
logic [2**AxiIdWidth-1:0][2:0] r_size;
logic [2**AxiIdWidth-1:0][$clog2(DataWidth/8)-1:0] r_lower, r_offset, r_increment;
stream_fork #(
.N_OUP ( 32'd2 )
) i_stream_fork_aw_a (
.clk_i,
.rst_ni,
.valid_i ( axi_a_req_i.aw_valid ),
.ready_o ( axi_a_rsp_o.aw_ready ),
.valid_o ( {fifo_sel_valid_aw_a, axi_a_req_o.aw_valid} ),
.ready_i ( {fifo_sel_ready_aw_a, axi_a_rsp_i.aw_ready} )
);
stream_fork #(
.N_OUP ( 32'd2 )
) i_stream_fork_w_a (
.clk_i,
.rst_ni,
.valid_i ( axi_a_req_i.w_valid ),
.ready_o ( axi_a_rsp_o.w_ready ),
.valid_o ( {fifo_sel_valid_w_a, axi_a_req_o.w_valid} ),
.ready_i ( {fifo_sel_ready_w_a, axi_a_rsp_i.w_ready} )
);
stream_fork #(
.N_OUP ( 32'd2 )
) i_stream_fork_b_a (
.clk_i,
.rst_ni,
.valid_i ( axi_a_rsp_i.b_valid ),
.ready_o ( axi_a_req_o.b_ready ),
.valid_o ( {fifo_sel_valid_b_a, axi_a_rsp_o.b_valid} ),
.ready_i ( {fifo_sel_ready_b_a, axi_a_req_i.b_ready} )
);
stream_fork #(
.N_OUP ( 32'd2 )
) i_stream_fork_ar_a (
.clk_i,
.rst_ni,
.valid_i ( axi_a_req_i.ar_valid ),
.ready_o ( axi_a_rsp_o.ar_ready ),
.valid_o ( {fifo_sel_valid_ar_a, axi_a_req_o.ar_valid} ),
.ready_i ( {fifo_sel_ready_ar_a, axi_a_rsp_i.ar_ready} )
);
stream_fork #(
.N_OUP ( 32'd2 )
) i_stream_fork_r_a (
.clk_i,
.rst_ni,
.valid_i ( axi_a_rsp_i.r_valid ),
.ready_o ( axi_a_req_o.r_ready ),
.valid_o ( {fifo_sel_valid_r_a, axi_a_rsp_o.r_valid} ),
.ready_i ( {fifo_sel_ready_r_a, axi_a_req_i.r_ready} )
);
for (genvar id = 0; id < 2**AxiIdWidth; id++) begin : gen_fifos_a
stream_fifo #(
.FALL_THROUGH ( 1'b0 ),
.DATA_WIDTH ( 1'b0 ),
.DEPTH ( FifoDepth ),
.T ( axi_aw_chan_t )
) i_stream_fifo_aw_a (
.clk_i,
.rst_ni,
.testmode_i,
.flush_i ( 1'b0 ),
.usage_o ( ),
.data_i ( axi_a_req_i.aw ),
.valid_i ( fifo_valid_aw_a [id] ),
.ready_o ( fifo_ready_aw_a [id] ),
.data_o ( fifo_cmp_data_aw_a [id] ),
.valid_o ( fifo_cmp_valid_aw_a [id] ),
.ready_i ( fifo_cmp_valid_aw_a [id] & fifo_cmp_valid_aw_b [id] )
);
stream_fifo #(
.FALL_THROUGH ( 1'b0 ),
.DATA_WIDTH ( 1'b0 ),
.DEPTH ( FifoDepth ),
.T ( axi_b_chan_t )
) i_stream_fifo_b_a (
.clk_i,
.rst_ni,
.testmode_i,
.flush_i ( 1'b0 ),
.usage_o ( ),
.data_i ( axi_a_rsp_i.b ),
.valid_i ( fifo_valid_b_a [id] ),
.ready_o ( fifo_ready_b_a [id] ),
.data_o ( fifo_cmp_data_b_a [id] ),
.valid_o ( fifo_cmp_valid_b_a [id] ),
.ready_i ( fifo_cmp_valid_b_a [id] & fifo_cmp_valid_b_b [id] )
);
stream_fifo #(
.FALL_THROUGH ( 1'b0 ),
.DATA_WIDTH ( 1'b0 ),
.DEPTH ( FifoDepth ),
.T ( axi_ar_chan_t )
) i_stream_fifo_ar_a (
.clk_i,
.rst_ni,
.testmode_i,
.flush_i ( 1'b0 ),
.usage_o ( ),
.data_i ( axi_a_req_i.ar ),
.valid_i ( fifo_valid_ar_a [id] ),
.ready_o ( fifo_ready_ar_a [id] ),
.data_o ( fifo_cmp_data_ar_a [id] ),
.valid_o ( fifo_cmp_valid_ar_a [id] ),
.ready_i ( fifo_cmp_valid_ar_a [id] & fifo_cmp_valid_ar_b [id] )
);
if (UseSize) begin : gen_r_size
stream_fifo #(
.FALL_THROUGH ( 1'b0 ),
.DATA_WIDTH ( $clog2(DataWidth/8)+3 ),
.DEPTH ( 2*FifoDepth )
) i_stream_fifo_w_size (
.clk_i,
.rst_ni,
.testmode_i,
.flush_i ( 1'b0 ),
.usage_o (),
.data_i ( {axi_a_req_i.ar.addr[$clog2(DataWidth/8)-1:0], axi_a_req_i.ar.size} ),
.valid_i ( fifo_valid_ar_a [id] & fifo_ready_ar_a [id] ),
.ready_o (),
.data_o ( {r_offset[id], r_size[id]} ),
.valid_o (),
.ready_i ( fifo_cmp_valid_r_a[id] & fifo_cmp_valid_r_b[id] & fifo_cmp_data_r_a[id].last )
);
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_r_increment
if(!rst_ni) begin
r_increment[id] <= '0;
end else begin
if (fifo_cmp_valid_r_a[id] && fifo_cmp_valid_r_b[id]) begin
if (fifo_cmp_data_r_a[id].last) begin
r_increment[id] <= '0;
end else begin
r_increment[id] <= r_increment[id] + 2**r_size[id] - ((r_offset[id]+r_increment[id])%(2**r_size[id]));
end
end
end
end
assign r_lower[id] = r_offset[id] + r_increment[id];
end else begin : gen_no_size
assign r_offset[id] = '0;
assign r_size[id] = '1;
assign r_lower[id] = '0;
end
stream_fifo #(
.FALL_THROUGH ( 1'b0 ),
.DATA_WIDTH ( 1'b0 ),
.DEPTH ( FifoDepth ),
.T ( axi_r_chan_t )
) i_stream_fifo_r_a (
.clk_i,
.rst_ni,
.testmode_i,
.flush_i ( 1'b0 ),
.usage_o ( ),
.data_i ( axi_a_rsp_i.r ),
.valid_i ( fifo_valid_r_a [id] ),
.ready_o ( fifo_ready_r_a [id] ),
.data_o ( fifo_cmp_data_r_a [id] ),
.valid_o ( fifo_cmp_valid_r_a [id] ),
.ready_i ( fifo_cmp_valid_r_a [id] & fifo_cmp_valid_r_b [id] )
);
end
if (UseSize) begin : gen_w_size
stream_fifo #(
.FALL_THROUGH ( 1'b0 ),
.DATA_WIDTH ( $clog2(DataWidth/8)+3 ),
.DEPTH ( FifoDepth )
) i_stream_fifo_w_size (
.clk_i,
.rst_ni,
.testmode_i,
.flush_i ( 1'b0 ),
.usage_o (),
.data_i ( {axi_a_req_i.aw.addr[$clog2(DataWidth/8)-1:0], axi_a_req_i.aw.size} ),
.valid_i ( axi_a_req_i.aw_valid & axi_a_rsp_o.aw_ready ),
.ready_o (),
.data_o ( {w_offset, w_size} ),
.valid_o (),
.ready_i ( fifo_cmp_valid_w_a & fifo_cmp_valid_w_b & fifo_cmp_data_w_a.last )
);
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_w_increment
if(!rst_ni) begin
w_increment <= '0;
end else begin
if (fifo_cmp_valid_w_a && fifo_cmp_valid_w_b) begin
if (fifo_cmp_data_w_a.last) begin
w_increment <= '0;
end else begin
w_increment <= (w_increment + 2**w_size) - ((w_offset+w_increment)%(2**w_size));
end
end
end
end
assign w_lower = w_offset + w_increment;
end else begin : gen_no_size
assign w_offset = '0;
assign w_size = '1;
assign w_lower = '0;
end
stream_fifo #(
.FALL_THROUGH ( 1'b0 ),
.DATA_WIDTH ( 1'b0 ),
.DEPTH ( FifoDepth ),
.T ( axi_w_chan_t )
) i_stream_fifo_w_a (
.clk_i,
.rst_ni,
.testmode_i,
.flush_i ( 1'b0 ),
.usage_o ( ),
.data_i ( axi_a_req_i.w ),
.valid_i ( fifo_sel_valid_w_a ),
.ready_o ( fifo_sel_ready_w_a ),
.data_o ( fifo_cmp_data_w_a ),
.valid_o ( fifo_cmp_valid_w_a ),
.ready_i ( fifo_cmp_valid_w_a & fifo_cmp_valid_w_b )
);
always_comb begin : gen_handshaking_a
fifo_valid_aw_a = '0;
fifo_sel_ready_aw_a = '0;
fifo_valid_aw_a [axi_a_req_i.aw.id] = fifo_sel_valid_aw_a;
fifo_sel_ready_aw_a = fifo_ready_aw_a[axi_a_req_i.aw.id];
fifo_valid_b_a = '0;
fifo_sel_ready_b_a = '0;
fifo_valid_b_a [axi_a_rsp_i.b.id] = fifo_sel_valid_b_a;
fifo_sel_ready_b_a = fifo_ready_b_a[axi_a_rsp_i.b.id];
fifo_valid_ar_a = '0;
fifo_sel_ready_ar_a = '0;
fifo_valid_ar_a [axi_a_req_i.ar.id] = fifo_sel_valid_ar_a;
fifo_sel_ready_ar_a = fifo_ready_ar_a[axi_a_req_i.ar.id];
fifo_valid_r_a = '0;
fifo_sel_ready_r_a = '0;
fifo_valid_r_a [axi_a_rsp_i.r.id] = fifo_sel_valid_r_a;
fifo_sel_ready_r_a = fifo_ready_r_a[axi_a_rsp_i.r.id];
end
stream_fork #(
.N_OUP ( 32'd2 )
) i_stream_fork_aw_b (
.clk_i,
.rst_ni,
.valid_i ( axi_b_req_i.aw_valid ),
.ready_o ( axi_b_rsp_o.aw_ready ),
.valid_o ( {fifo_sel_valid_aw_b, axi_b_req_o.aw_valid} ),
.ready_i ( {fifo_sel_ready_aw_b, axi_b_rsp_i.aw_ready} )
);
stream_fork #(
.N_OUP ( 32'd2 )
) i_stream_fork_w_b (
.clk_i,
.rst_ni,
.valid_i ( axi_b_req_i.w_valid ),
.ready_o ( axi_b_rsp_o.w_ready ),
.valid_o ( {fifo_sel_valid_w_b, axi_b_req_o.w_valid} ),
.ready_i ( {fifo_sel_ready_w_b, axi_b_rsp_i.w_ready} )
);
stream_fork #(
.N_OUP ( 32'd2 )
) i_stream_fork_b_b (
.clk_i,
.rst_ni,
.valid_i ( axi_b_rsp_i.b_valid ),
.ready_o ( axi_b_req_o.b_ready ),
.valid_o ( {fifo_sel_valid_b_b, axi_b_rsp_o.b_valid} ),
.ready_i ( {fifo_sel_ready_b_b, axi_b_req_i.b_ready} )
);
stream_fork #(
.N_OUP ( 32'd2 )
) i_stream_fork_ar_b (
.clk_i,
.rst_ni,
.valid_i ( axi_b_req_i.ar_valid ),
.ready_o ( axi_b_rsp_o.ar_ready ),
.valid_o ( {fifo_sel_valid_ar_b, axi_b_req_o.ar_valid} ),
.ready_i ( {fifo_sel_ready_ar_b, axi_b_rsp_i.ar_ready} )
);
stream_fork #(
.N_OUP ( 32'd2 )
) i_stream_fork_r_b (
.clk_i,
.rst_ni,
.valid_i ( axi_b_rsp_i.r_valid ),
.ready_o ( axi_b_req_o.r_ready ),
.valid_o ( {fifo_sel_valid_r_b, axi_b_rsp_o.r_valid} ),
.ready_i ( {fifo_sel_ready_r_b, axi_b_req_i.r_ready} )
);
for (genvar id = 0; id < 2**AxiIdWidth; id++) begin : gen_fifos_b
stream_fifo #(
.FALL_THROUGH ( 1'b0 ),
.DATA_WIDTH ( 1'b0 ),
.DEPTH ( FifoDepth ),
.T ( axi_aw_chan_t )
) i_stream_fifo_aw_b (
.clk_i,
.rst_ni,
.testmode_i,
.flush_i ( 1'b0 ),
.usage_o ( ),
.data_i ( axi_b_req_i.aw ),
.valid_i ( fifo_valid_aw_b [id] ),
.ready_o ( fifo_ready_aw_b [id] ),
.data_o ( fifo_cmp_data_aw_b [id] ),
.valid_o ( fifo_cmp_valid_aw_b [id] ),
.ready_i ( fifo_cmp_valid_aw_a [id] & fifo_cmp_valid_aw_b [id] )
);
stream_fifo #(
.FALL_THROUGH ( 1'b0 ),
.DATA_WIDTH ( 1'b0 ),
.DEPTH ( FifoDepth ),
.T ( axi_b_chan_t )
) i_stream_fifo_b_b (
.clk_i,
.rst_ni,
.testmode_i,
.flush_i ( 1'b0 ),
.usage_o ( ),
.data_i ( axi_b_rsp_i.b ),
.valid_i ( fifo_valid_b_b [id] ),
.ready_o ( fifo_ready_b_b [id] ),
.data_o ( fifo_cmp_data_b_b [id] ),
.valid_o ( fifo_cmp_valid_b_b [id] ),
.ready_i ( fifo_cmp_valid_b_a [id] & fifo_cmp_valid_b_b [id] )
);
stream_fifo #(
.FALL_THROUGH ( 1'b0 ),
.DATA_WIDTH ( 1'b0 ),
.DEPTH ( FifoDepth ),
.T ( axi_ar_chan_t )
) i_stream_fifo_ar_b (
.clk_i,
.rst_ni,
.testmode_i,
.flush_i ( 1'b0 ),
.usage_o ( ),
.data_i ( axi_b_req_i.ar ),
.valid_i ( fifo_valid_ar_b [id] ),
.ready_o ( fifo_ready_ar_b [id] ),
.data_o ( fifo_cmp_data_ar_b [id] ),
.valid_o ( fifo_cmp_valid_ar_b [id] ),
.ready_i ( fifo_cmp_valid_ar_a [id] & fifo_cmp_valid_ar_b [id] )
);
stream_fifo #(
.FALL_THROUGH ( 1'b0 ),
.DATA_WIDTH ( 1'b0 ),
.DEPTH ( FifoDepth ),
.T ( axi_r_chan_t )
) i_stream_fifo_r_b (
.clk_i,
.rst_ni,
.testmode_i,
.flush_i ( 1'b0 ),
.usage_o ( ),
.data_i ( axi_b_rsp_i.r ),
.valid_i ( fifo_valid_r_b [id] ),
.ready_o ( fifo_ready_r_b [id] ),
.data_o ( fifo_cmp_data_r_b [id] ),
.valid_o ( fifo_cmp_valid_r_b [id] ),
.ready_i ( fifo_cmp_valid_r_a [id] & fifo_cmp_valid_r_b [id] )
);
end
stream_fifo #(
.FALL_THROUGH ( 1'b0 ),
.DATA_WIDTH ( 1'b0 ),
.DEPTH ( FifoDepth ),
.T ( axi_w_chan_t )
) i_stream_fifo_w_b (
.clk_i,
.rst_ni,
.testmode_i,
.flush_i ( 1'b0 ),
.usage_o ( ),
.data_i ( axi_b_req_i.w ),
.valid_i ( fifo_sel_valid_w_b ),
.ready_o ( fifo_sel_ready_w_b ),
.data_o ( fifo_cmp_data_w_b ),
.valid_o ( fifo_cmp_valid_w_b ),
.ready_i ( fifo_cmp_valid_w_a & fifo_cmp_valid_w_b )
);
always_comb begin : gen_handshaking_b
fifo_valid_aw_b = '0;
fifo_sel_ready_aw_b = '0;
fifo_valid_aw_b [axi_b_req_i.aw.id] = fifo_sel_valid_aw_b;
fifo_sel_ready_aw_b = fifo_ready_aw_b[axi_b_req_i.aw.id];
fifo_valid_b_b = '0;
fifo_sel_ready_b_b = '0;
fifo_valid_b_b [axi_b_rsp_i.b.id] = fifo_sel_valid_b_b;
fifo_sel_ready_b_b = fifo_ready_b_b[axi_b_rsp_i.b.id];
fifo_valid_ar_b = '0;
fifo_sel_ready_ar_b = '0;
fifo_valid_ar_b [axi_b_req_i.ar.id] = fifo_sel_valid_ar_b;
fifo_sel_ready_ar_b = fifo_ready_ar_b[axi_b_req_i.ar.id];
fifo_valid_r_b = '0;
fifo_sel_ready_r_b = '0;
fifo_valid_r_b [axi_b_rsp_i.r.id] = fifo_sel_valid_r_b;
fifo_sel_ready_r_b = fifo_ready_r_b[axi_b_rsp_i.r.id];
end
for (genvar id = 0; id < 2**AxiIdWidth; id++) begin : gen_cmp
logic [DataWidth/8-1:0] r_data_partial_mismatch;
logic r_data_mismatch;
if (UseSize) begin : gen_r_mismatch_sized
for (genvar j = 0; j < DataWidth/8; j++) begin : gen_r_partial_mismatch
assign r_data_partial_mismatch[j] = fifo_cmp_data_r_a[id].data[8*j+:8] != fifo_cmp_data_r_b[id].data[8*j+:8];
end
always_comb begin : proc_r_data_mismatch
r_data_mismatch = '0;
for (int unsigned j = 0; j < DataWidth/8; j++) begin
if (j >= r_lower[id] && j < (r_lower[id] + 2**r_size[id])-((r_lower[id] + 2**r_size[id])%(2**r_size[id])) ) begin
r_data_mismatch |= r_data_partial_mismatch[j];
end
end
end
end else begin : gen_r_mismatch_unsized
assign r_data_mismatch = fifo_cmp_data_r_a[id].data != fifo_cmp_data_r_b[id].data;
end
assign aw_mismatch_o [id] = (fifo_cmp_valid_aw_a [id] & fifo_cmp_valid_aw_b [id]) ?
fifo_cmp_data_aw_a [id] != fifo_cmp_data_aw_b [id] : '0;
assign b_mismatch_o [id] = (fifo_cmp_valid_b_a [id] & fifo_cmp_valid_b_b [id]) ?
fifo_cmp_data_b_a [id] != fifo_cmp_data_b_b [id] : '0;
assign ar_mismatch_o [id] = (fifo_cmp_valid_ar_a [id] & fifo_cmp_valid_ar_b [id]) ?
fifo_cmp_data_ar_a [id] != fifo_cmp_data_ar_b [id] : '0;
assign r_mismatch_o [id] = (fifo_cmp_valid_r_a [id] & fifo_cmp_valid_r_b [id]) ?
( fifo_cmp_data_r_a[id].id != fifo_cmp_data_r_b[id].id |
r_data_mismatch |
fifo_cmp_data_r_a[id].resp != fifo_cmp_data_r_b[id].resp |
fifo_cmp_data_r_a[id].last != fifo_cmp_data_r_b[id].last |
fifo_cmp_data_r_a[id].user != fifo_cmp_data_r_b[id].user )
: '0;
end
logic [DataWidth/8-1:0] w_data_partial_mismatch;
logic w_data_mismatch;
if (UseSize) begin : gen_w_mismatch_sized
for (genvar j = 0; j < DataWidth/8; j++) begin : gen_w_partial_mismatch
assign w_data_partial_mismatch[j] = fifo_cmp_data_w_a.data[8*j+:8] != fifo_cmp_data_w_b.data[8*j+:8] |
fifo_cmp_data_w_a.strb[ j ] != fifo_cmp_data_w_b.strb[ j ];
end
always_comb begin : proc_w_data_mismatch
w_data_mismatch = '0;
for (int unsigned j = 0; j < DataWidth/8; j++) begin
if (j >= w_lower && j < (w_lower + 2**w_size)-((w_lower + 2**w_size)%(2**w_size)) ) begin
w_data_mismatch |= w_data_partial_mismatch[j];
end
end
end
end else begin : gen_w_mismatch_unsized
assign w_data_mismatch = fifo_cmp_data_w_a.data != fifo_cmp_data_w_b.data |
fifo_cmp_data_w_a.strb != fifo_cmp_data_w_b.strb;
end
assign w_mismatch_o = (fifo_cmp_valid_w_a & fifo_cmp_valid_w_b ) ?
( w_data_mismatch |
fifo_cmp_data_w_a.last != fifo_cmp_data_w_b.last |
fifo_cmp_data_w_a.user != fifo_cmp_data_w_b.user )
: '0;
assign busy_o = (|fifo_cmp_valid_aw_a) | (|fifo_cmp_valid_aw_b) |
(|fifo_cmp_valid_w_a) | (|fifo_cmp_valid_w_b) |
(|fifo_cmp_valid_b_a) | (|fifo_cmp_valid_b_b) |
(|fifo_cmp_valid_ar_a) | (|fifo_cmp_valid_ar_b) |
(|fifo_cmp_valid_r_a) | (|fifo_cmp_valid_r_b);
assign mismatch_o = (|aw_mismatch_o) | (|w_mismatch_o) | (|b_mismatch_o) |
(|ar_mismatch_o) | (|r_mismatch_o);
endmodule
`begin_keywords "1800-2023"
module axi_cdc_dst #(
parameter int unsigned LogDepth = 1,
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
) (
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,
input logic dst_clk_i,
input logic dst_rst_ni,
output axi_req_t dst_req_o,
input axi_resp_t dst_resp_i
);
cdc_fifo_gray_dst #(
.T ( aw_chan_t ),
.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_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 #(
.T ( w_chan_t ),
.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_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 #(
.T ( b_chan_t ),
.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_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 #(
.T ( ar_chan_t ),
.LOG_DEPTH ( LogDepth ),
.SYNC_STAGES ( SyncStages )
) i_cdc_fifo_gray_dst_ar (
.dst_clk_i,
.dst_rst_ni,
.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 #(
.T ( r_chan_t ),
.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_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_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,
parameter int unsigned LOG_DEPTH = 1,
parameter int unsigned SYNC_STAGES = 2
) (
AXI_BUS_ASYNC_GRAY.Slave src,
input logic dst_clk_i,
input logic dst_rst_ni,
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;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_pkg::atop_t atop;
user_t user;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
logic last;
user_t user;
} w_chan_t;
typedef struct packed {
id_t id;
axi_pkg::resp_t resp;
user_t user;
} b_chan_t;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
user_t user;
} ar_chan_t;
typedef struct packed {
id_t id;
data_t data;
axi_pkg::resp_t resp;
logic last;
user_t user;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} req_t;
typedef struct packed {
logic aw_ready;
logic ar_ready;
logic w_ready;
logic b_valid;
b_chan_t b;
logic r_valid;
r_chan_t r;
} resp_t;
req_t dst_req;
resp_t dst_resp;
axi_cdc_dst #(
.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_req_o ( dst_req ),
.dst_resp_i ( dst_resp )
);
assign dst.aw_id = dst_req.aw.id;
assign dst.aw_addr = dst_req.aw.addr;
assign dst.aw_len = dst_req.aw.len;
assign dst.aw_size = dst_req.aw.size;
assign dst.aw_burst = dst_req.aw.burst;
assign dst.aw_lock = dst_req.aw.lock;
assign dst.aw_cache = dst_req.aw.cache;
assign dst.aw_prot = dst_req.aw.prot;
assign dst.aw_qos = dst_req.aw.qos;
assign dst.aw_region = dst_req.aw.region;
assign dst.aw_atop = dst_req.aw.atop;
assign dst.aw_user = dst_req.aw.user;
assign dst.aw_valid = dst_req.aw_valid;
assign dst.w_data = dst_req.w.data;
assign dst.w_strb = dst_req.w.strb;
assign dst.w_last = dst_req.w.last;
assign dst.w_user = dst_req.w.user;
assign dst.w_valid = dst_req.w_valid;
assign dst.b_ready = dst_req.b_ready;
assign dst.ar_id = dst_req.ar.id;
assign dst.ar_addr = dst_req.ar.addr;
assign dst.ar_len = dst_req.ar.len;
assign dst.ar_size = dst_req.ar.size;
assign dst.ar_burst = dst_req.ar.burst;
assign dst.ar_lock = dst_req.ar.lock;
assign dst.ar_cache = dst_req.ar.cache;
assign dst.ar_prot = dst_req.ar.prot;
assign dst.ar_qos = dst_req.ar.qos;
assign dst.ar_region = dst_req.ar.region;
assign dst.ar_user = dst_req.ar.user;
assign dst.ar_valid = dst_req.ar_valid;
assign dst.r_ready = dst_req.r_ready;
assign dst_resp.aw_ready = dst.aw_ready;
assign dst_resp.ar_ready = dst.ar_ready;
assign dst_resp.w_ready = dst.w_ready;
assign dst_resp.b_valid = dst.b_valid;
assign dst_resp.b.id = dst.b_id;
assign dst_resp.b.resp = dst.b_resp;
assign dst_resp.b.user = dst.b_user;
assign dst_resp.r_valid = dst.r_valid;
assign dst_resp.r.id = dst.r_id;
assign dst_resp.r.data = dst.r_data;
assign dst_resp.r.resp = dst.r_resp;
assign dst_resp.r.last = dst.r_last;
assign dst_resp.r.user = dst.r_user;
endmodule
module axi_lite_cdc_dst_intf #(
parameter int unsigned AXI_ADDR_WIDTH = 0,
parameter int unsigned AXI_DATA_WIDTH = 0,
parameter int unsigned LOG_DEPTH = 1,
parameter int unsigned SYNC_STAGES = 2
) (
AXI_LITE_ASYNC_GRAY.Slave src,
input logic dst_clk_i,
input logic dst_rst_ni,
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;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
} w_chan_t;
typedef struct packed {
axi_pkg::resp_t resp;
} b_chan_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} ar_chan_t;
typedef struct packed {
data_t data;
axi_pkg::resp_t resp;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} req_t;
typedef struct packed {
logic aw_ready;
logic w_ready;
b_chan_t b;
logic b_valid;
logic ar_ready;
r_chan_t r;
logic r_valid;
} resp_t;
req_t dst_req;
resp_t dst_resp;
axi_cdc_dst #(
.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_req_o ( dst_req ),
.dst_resp_i ( dst_resp )
);
assign dst.aw_addr = dst_req.aw.addr;
assign dst.aw_prot = dst_req.aw.prot;
assign dst.aw_valid = dst_req.aw_valid;
assign dst.w_data = dst_req.w.data;
assign dst.w_strb = dst_req.w.strb;
assign dst.w_valid = dst_req.w_valid;
assign dst.b_ready = dst_req.b_ready;
assign dst.ar_addr = dst_req.ar.addr;
assign dst.ar_prot = dst_req.ar.prot;
assign dst.ar_valid = dst_req.ar_valid;
assign dst.r_ready = dst_req.r_ready;
assign dst_resp.aw_ready = dst.aw_ready;
assign dst_resp.ar_ready = dst.ar_ready;
assign dst_resp.w_ready = dst.w_ready;
assign dst_resp.b_valid = dst.b_valid;
assign dst_resp.b.resp = dst.b_resp;
assign dst_resp.r_valid = dst.r_valid;
assign dst_resp.r.data = dst.r_data;
assign dst_resp.r.resp = dst.r_resp;
endmodule
`begin_keywords "1800-2023"
module axi_cdc_src #(
parameter int unsigned LogDepth = 1,
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
) (
input logic src_clk_i,
input logic src_rst_ni,
input axi_req_t src_req_i,
output axi_resp_t src_resp_o,
output aw_chan_t [2**LogDepth-1:0] async_data_master_aw_data_o,
output logic [LogDepth:0] async_data_master_aw_wptr_o,
input logic [LogDepth:0] async_data_master_aw_rptr_i,
output w_chan_t [2**LogDepth-1:0] async_data_master_w_data_o,
output logic [LogDepth:0] async_data_master_w_wptr_o,
input logic [LogDepth:0] async_data_master_w_rptr_i,
input b_chan_t [2**LogDepth-1:0] async_data_master_b_data_i,
input logic [LogDepth:0] async_data_master_b_wptr_i,
output logic [LogDepth:0] async_data_master_b_rptr_o,
output ar_chan_t [2**LogDepth-1:0] async_data_master_ar_data_o,
output logic [LogDepth:0] async_data_master_ar_wptr_o,
input logic [LogDepth:0] async_data_master_ar_rptr_i,
input r_chan_t [2**LogDepth-1:0] async_data_master_r_data_i,
input logic [LogDepth:0] async_data_master_r_wptr_i,
output logic [LogDepth:0] async_data_master_r_rptr_o
);
cdc_fifo_gray_src #(
.T ( aw_chan_t ),
.LOG_DEPTH ( LogDepth ),
.SYNC_STAGES ( SyncStages )
) i_cdc_fifo_gray_src_aw (
.src_clk_i,
.src_rst_ni,
.src_data_i ( src_req_i.aw ),
.src_valid_i ( src_req_i.aw_valid ),
.src_ready_o ( src_resp_o.aw_ready ),
.async_data_o ( async_data_master_aw_data_o ),
.async_wptr_o ( async_data_master_aw_wptr_o ),
.async_rptr_i ( async_data_master_aw_rptr_i )
);
cdc_fifo_gray_src #(
.T ( w_chan_t ),
.LOG_DEPTH ( LogDepth ),
.SYNC_STAGES ( SyncStages )
) i_cdc_fifo_gray_src_w (
.src_clk_i,
.src_rst_ni,
.src_data_i ( src_req_i.w ),
.src_valid_i ( src_req_i.w_valid ),
.src_ready_o ( src_resp_o.w_ready ),
.async_data_o ( async_data_master_w_data_o ),
.async_wptr_o ( async_data_master_w_wptr_o ),
.async_rptr_i ( async_data_master_w_rptr_i )
);
cdc_fifo_gray_dst #(
.T ( b_chan_t ),
.LOG_DEPTH ( LogDepth ),
.SYNC_STAGES ( SyncStages )
) i_cdc_fifo_gray_dst_b (
.dst_clk_i ( src_clk_i ),
.dst_rst_ni ( src_rst_ni ),
.dst_data_o ( src_resp_o.b ),
.dst_valid_o ( src_resp_o.b_valid ),
.dst_ready_i ( src_req_i.b_ready ),
.async_data_i ( async_data_master_b_data_i ),
.async_wptr_i ( async_data_master_b_wptr_i ),
.async_rptr_o ( async_data_master_b_rptr_o )
);
cdc_fifo_gray_src #(
.T ( ar_chan_t ),
.LOG_DEPTH ( LogDepth ),
.SYNC_STAGES ( SyncStages )
) i_cdc_fifo_gray_src_ar (
.src_clk_i,
.src_rst_ni,
.src_data_i ( src_req_i.ar ),
.src_valid_i ( src_req_i.ar_valid ),
.src_ready_o ( src_resp_o.ar_ready ),
.async_data_o ( async_data_master_ar_data_o ),
.async_wptr_o ( async_data_master_ar_wptr_o ),
.async_rptr_i ( async_data_master_ar_rptr_i )
);
cdc_fifo_gray_dst #(
.T ( r_chan_t ),
.LOG_DEPTH ( LogDepth ),
.SYNC_STAGES ( SyncStages )
) i_cdc_fifo_gray_dst_r (
.dst_clk_i ( src_clk_i ),
.dst_rst_ni ( src_rst_ni ),
.dst_data_o ( src_resp_o.r ),
.dst_valid_o ( src_resp_o.r_valid ),
.dst_ready_i ( src_req_i.r_ready ),
.async_data_i ( async_data_master_r_data_i ),
.async_wptr_i ( async_data_master_r_wptr_i ),
.async_rptr_o ( async_data_master_r_rptr_o )
);
endmodule
module axi_cdc_src_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,
parameter int unsigned LOG_DEPTH = 1,
parameter int unsigned SYNC_STAGES = 2
) (
input logic src_clk_i,
input logic src_rst_ni,
AXI_BUS.Slave src,
AXI_BUS_ASYNC_GRAY.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;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_pkg::atop_t atop;
user_t user;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
logic last;
user_t user;
} w_chan_t;
typedef struct packed {
id_t id;
axi_pkg::resp_t resp;
user_t user;
} b_chan_t;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
user_t user;
} ar_chan_t;
typedef struct packed {
id_t id;
data_t data;
axi_pkg::resp_t resp;
logic last;
user_t user;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} req_t;
typedef struct packed {
logic aw_ready;
logic ar_ready;
logic w_ready;
logic b_valid;
b_chan_t b;
logic r_valid;
r_chan_t r;
} resp_t;
req_t src_req;
resp_t src_resp;
assign src_req.aw.id = src.aw_id;
assign src_req.aw.addr = src.aw_addr;
assign src_req.aw.len = src.aw_len;
assign src_req.aw.size = src.aw_size;
assign src_req.aw.burst = src.aw_burst;
assign src_req.aw.lock = src.aw_lock;
assign src_req.aw.cache = src.aw_cache;
assign src_req.aw.prot = src.aw_prot;
assign src_req.aw.qos = src.aw_qos;
assign src_req.aw.region = src.aw_region;
assign src_req.aw.atop = src.aw_atop;
assign src_req.aw.user = src.aw_user;
assign src_req.aw_valid = src.aw_valid;
assign src_req.w.data = src.w_data;
assign src_req.w.strb = src.w_strb;
assign src_req.w.last = src.w_last;
assign src_req.w.user = src.w_user;
assign src_req.w_valid = src.w_valid;
assign src_req.b_ready = src.b_ready;
assign src_req.ar.id = src.ar_id;
assign src_req.ar.addr = src.ar_addr;
assign src_req.ar.len = src.ar_len;
assign src_req.ar.size = src.ar_size;
assign src_req.ar.burst = src.ar_burst;
assign src_req.ar.lock = src.ar_lock;
assign src_req.ar.cache = src.ar_cache;
assign src_req.ar.prot = src.ar_prot;
assign src_req.ar.qos = src.ar_qos;
assign src_req.ar.region = src.ar_region;
assign src_req.ar.user = src.ar_user;
assign src_req.ar_valid = src.ar_valid;
assign src_req.r_ready = src.r_ready;
assign src.aw_ready = src_resp.aw_ready;
assign src.ar_ready = src_resp.ar_ready;
assign src.w_ready = src_resp.w_ready;
assign src.b_valid = src_resp.b_valid;
assign src.b_id = src_resp.b.id;
assign src.b_resp = src_resp.b.resp;
assign src.b_user = src_resp.b.user;
assign src.r_valid = src_resp.r_valid;
assign src.r_id = src_resp.r.id;
assign src.r_data = src_resp.r.data;
assign src.r_resp = src_resp.r.resp;
assign src.r_last = src_resp.r.last;
assign src.r_user = src_resp.r.user;
axi_cdc_src #(
.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_src (
.src_clk_i,
.src_rst_ni,
.src_req_i ( src_req ),
.src_resp_o ( src_resp ),
.async_data_master_aw_data_o ( dst.aw_data ),
.async_data_master_aw_wptr_o ( dst.aw_wptr ),
.async_data_master_aw_rptr_i ( dst.aw_rptr ),
.async_data_master_w_data_o ( dst.w_data ),
.async_data_master_w_wptr_o ( dst.w_wptr ),
.async_data_master_w_rptr_i ( dst.w_rptr ),
.async_data_master_b_data_i ( dst.b_data ),
.async_data_master_b_wptr_i ( dst.b_wptr ),
.async_data_master_b_rptr_o ( dst.b_rptr ),
.async_data_master_ar_data_o ( dst.ar_data ),
.async_data_master_ar_wptr_o ( dst.ar_wptr ),
.async_data_master_ar_rptr_i ( dst.ar_rptr ),
.async_data_master_r_data_i ( dst.r_data ),
.async_data_master_r_wptr_i ( dst.r_wptr ),
.async_data_master_r_rptr_o ( dst.r_rptr )
);
endmodule
module axi_lite_cdc_src_intf #(
parameter int unsigned AXI_ADDR_WIDTH = 0,
parameter int unsigned AXI_DATA_WIDTH = 0,
parameter int unsigned LOG_DEPTH = 1,
parameter int unsigned SYNC_STAGES = 2
) (
input logic src_clk_i,
input logic src_rst_ni,
AXI_BUS.Slave src,
AXI_LITE_ASYNC_GRAY.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;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
} w_chan_t;
typedef struct packed {
axi_pkg::resp_t resp;
} b_chan_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} ar_chan_t;
typedef struct packed {
data_t data;
axi_pkg::resp_t resp;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} req_t;
typedef struct packed {
logic aw_ready;
logic w_ready;
b_chan_t b;
logic b_valid;
logic ar_ready;
r_chan_t r;
logic r_valid;
} resp_t;
req_t src_req;
resp_t src_resp;
assign src_req.aw.addr = src.aw_addr;
assign src_req.aw.prot = src.aw_prot;
assign src_req.aw_valid = src.aw_valid;
assign src_req.w.data = src.w_data;
assign src_req.w.strb = src.w_strb;
assign src_req.w_valid = src.w_valid;
assign src_req.b_ready = src.b_ready;
assign src_req.ar.addr = src.ar_addr;
assign src_req.ar.prot = src.ar_prot;
assign src_req.ar_valid = src.ar_valid;
assign src_req.r_ready = src.r_ready;
assign src.aw_ready = src_resp.aw_ready;
assign src.ar_ready = src_resp.ar_ready;
assign src.w_ready = src_resp.w_ready;
assign src.b_valid = src_resp.b_valid;
assign src.b_resp = src_resp.b.resp;
assign src.r_valid = src_resp.r_valid;
assign src.r_data = src_resp.r.data;
assign src.r_resp = src_resp.r.resp;
axi_cdc_src #(
.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_src (
.src_clk_i,
.src_rst_ni,
.src_req_i ( src_req ),
.src_resp_o ( src_resp ),
.async_data_master_aw_data_o ( dst.aw_data ),
.async_data_master_aw_wptr_o ( dst.aw_wptr ),
.async_data_master_aw_rptr_i ( dst.aw_rptr ),
.async_data_master_w_data_o ( dst.w_data ),
.async_data_master_w_wptr_o ( dst.w_wptr ),
.async_data_master_w_rptr_i ( dst.w_rptr ),
.async_data_master_b_data_i ( dst.b_data ),
.async_data_master_b_wptr_i ( dst.b_wptr ),
.async_data_master_b_rptr_o ( dst.b_rptr ),
.async_data_master_ar_data_o ( dst.ar_data ),
.async_data_master_ar_wptr_o ( dst.ar_wptr ),
.async_data_master_ar_rptr_i ( dst.ar_rptr ),
.async_data_master_r_data_i ( dst.r_data ),
.async_data_master_r_wptr_i ( dst.r_wptr ),
.async_data_master_r_rptr_o ( dst.r_rptr )
);
endmodule
`begin_keywords "1800-2023"
module axi_cut #(
parameter bit Bypass = 1'b0,
parameter bit BypassAw = Bypass,
parameter bit BypassW = Bypass,
parameter bit BypassB = Bypass,
parameter bit BypassAr = Bypass,
parameter bit BypassR = Bypass,
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
) (
input logic clk_i,
input logic rst_ni,
input axi_req_t slv_req_i,
output axi_resp_t slv_resp_o,
output axi_req_t mst_req_o,
input axi_resp_t mst_resp_i
);
spill_register #(
.T ( aw_chan_t ),
.Bypass ( BypassAw )
) i_reg_aw (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( slv_req_i.aw_valid ),
.ready_o ( slv_resp_o.aw_ready ),
.data_i ( slv_req_i.aw ),
.valid_o ( mst_req_o.aw_valid ),
.ready_i ( mst_resp_i.aw_ready ),
.data_o ( mst_req_o.aw )
);
spill_register #(
.T ( w_chan_t ),
.Bypass ( BypassW )
) i_reg_w (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( slv_req_i.w_valid ),
.ready_o ( slv_resp_o.w_ready ),
.data_i ( slv_req_i.w ),
.valid_o ( mst_req_o.w_valid ),
.ready_i ( mst_resp_i.w_ready ),
.data_o ( mst_req_o.w )
);
spill_register #(
.T ( b_chan_t ),
.Bypass ( BypassB )
) i_reg_b (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( mst_resp_i.b_valid ),
.ready_o ( mst_req_o.b_ready ),
.data_i ( mst_resp_i.b ),
.valid_o ( slv_resp_o.b_valid ),
.ready_i ( slv_req_i.b_ready ),
.data_o ( slv_resp_o.b )
);
spill_register #(
.T ( ar_chan_t ),
.Bypass ( BypassAr )
) i_reg_ar (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( slv_req_i.ar_valid ),
.ready_o ( slv_resp_o.ar_ready ),
.data_i ( slv_req_i.ar ),
.valid_o ( mst_req_o.ar_valid ),
.ready_i ( mst_resp_i.ar_ready ),
.data_o ( mst_req_o.ar )
);
spill_register #(
.T ( r_chan_t ),
.Bypass ( BypassR )
) i_reg_r (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( mst_resp_i.r_valid ),
.ready_o ( mst_req_o.r_ready ),
.data_i ( mst_resp_i.r ),
.valid_o ( slv_resp_o.r_valid ),
.ready_i ( slv_req_i.r_ready ),
.data_o ( slv_resp_o.r )
);
endmodule
module axi_cut_intf #(
parameter bit BYPASS = 1'b0,
parameter bit BYPASS_AW = BYPASS,
parameter bit BYPASS_W = BYPASS,
parameter bit BYPASS_B = BYPASS,
parameter bit BYPASS_AR = BYPASS,
parameter bit BYPASS_R = BYPASS,
parameter int unsigned ADDR_WIDTH = 0,
parameter int unsigned DATA_WIDTH = 0,
parameter int unsigned ID_WIDTH = 0,
parameter int unsigned USER_WIDTH = 0
) (
input logic clk_i ,
input logic rst_ni ,
AXI_BUS.Slave in ,
AXI_BUS.Master out
);
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;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_pkg::atop_t atop;
user_t user;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
logic last;
user_t user;
} w_chan_t;
typedef struct packed {
id_t id;
axi_pkg::resp_t resp;
user_t user;
} b_chan_t;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
user_t user;
} ar_chan_t;
typedef struct packed {
id_t id;
data_t data;
axi_pkg::resp_t resp;
logic last;
user_t user;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} axi_req_t;
typedef struct packed {
logic aw_ready;
logic ar_ready;
logic w_ready;
logic b_valid;
b_chan_t b;
logic r_valid;
r_chan_t r;
} axi_resp_t;
axi_req_t slv_req, mst_req;
axi_resp_t slv_resp, mst_resp;
assign slv_req.aw.id = in.aw_id;
assign slv_req.aw.addr = in.aw_addr;
assign slv_req.aw.len = in.aw_len;
assign slv_req.aw.size = in.aw_size;
assign slv_req.aw.burst = in.aw_burst;
assign slv_req.aw.lock = in.aw_lock;
assign slv_req.aw.cache = in.aw_cache;
assign slv_req.aw.prot = in.aw_prot;
assign slv_req.aw.qos = in.aw_qos;
assign slv_req.aw.region = in.aw_region;
assign slv_req.aw.atop = in.aw_atop;
assign slv_req.aw.user = in.aw_user;
assign slv_req.aw_valid = in.aw_valid;
assign slv_req.w.data = in.w_data;
assign slv_req.w.strb = in.w_strb;
assign slv_req.w.last = in.w_last;
assign slv_req.w.user = in.w_user;
assign slv_req.w_valid = in.w_valid;
assign slv_req.b_ready = in.b_ready;
assign slv_req.ar.id = in.ar_id;
assign slv_req.ar.addr = in.ar_addr;
assign slv_req.ar.len = in.ar_len;
assign slv_req.ar.size = in.ar_size;
assign slv_req.ar.burst = in.ar_burst;
assign slv_req.ar.lock = in.ar_lock;
assign slv_req.ar.cache = in.ar_cache;
assign slv_req.ar.prot = in.ar_prot;
assign slv_req.ar.qos = in.ar_qos;
assign slv_req.ar.region = in.ar_region;
assign slv_req.ar.user = in.ar_user;
assign slv_req.ar_valid = in.ar_valid;
assign slv_req.r_ready = in.r_ready;
assign in.aw_ready = slv_resp.aw_ready;
assign in.ar_ready = slv_resp.ar_ready;
assign in.w_ready = slv_resp.w_ready;
assign in.b_valid = slv_resp.b_valid;
assign in.b_id = slv_resp.b.id;
assign in.b_resp = slv_resp.b.resp;
assign in.b_user = slv_resp.b.user;
assign in.r_valid = slv_resp.r_valid;
assign in.r_id = slv_resp.r.id;
assign in.r_data = slv_resp.r.data;
assign in.r_resp = slv_resp.r.resp;
assign in.r_last = slv_resp.r.last;
assign in.r_user = slv_resp.r.user;
assign out.aw_id = mst_req.aw.id;
assign out.aw_addr = mst_req.aw.addr;
assign out.aw_len = mst_req.aw.len;
assign out.aw_size = mst_req.aw.size;
assign out.aw_burst = mst_req.aw.burst;
assign out.aw_lock = mst_req.aw.lock;
assign out.aw_cache = mst_req.aw.cache;
assign out.aw_prot = mst_req.aw.prot;
assign out.aw_qos = mst_req.aw.qos;
assign out.aw_region = mst_req.aw.region;
assign out.aw_atop = mst_req.aw.atop;
assign out.aw_user = mst_req.aw.user;
assign out.aw_valid = mst_req.aw_valid;
assign out.w_data = mst_req.w.data;
assign out.w_strb = mst_req.w.strb;
assign out.w_last = mst_req.w.last;
assign out.w_user = mst_req.w.user;
assign out.w_valid = mst_req.w_valid;
assign out.b_ready = mst_req.b_ready;
assign out.ar_id = mst_req.ar.id;
assign out.ar_addr = mst_req.ar.addr;
assign out.ar_len = mst_req.ar.len;
assign out.ar_size = mst_req.ar.size;
assign out.ar_burst = mst_req.ar.burst;
assign out.ar_lock = mst_req.ar.lock;
assign out.ar_cache = mst_req.ar.cache;
assign out.ar_prot = mst_req.ar.prot;
assign out.ar_qos = mst_req.ar.qos;
assign out.ar_region = mst_req.ar.region;
assign out.ar_user = mst_req.ar.user;
assign out.ar_valid = mst_req.ar_valid;
assign out.r_ready = mst_req.r_ready;
assign mst_resp.aw_ready = out.aw_ready;
assign mst_resp.ar_ready = out.ar_ready;
assign mst_resp.w_ready = out.w_ready;
assign mst_resp.b_valid = out.b_valid;
assign mst_resp.b.id = out.b_id;
assign mst_resp.b.resp = out.b_resp;
assign mst_resp.b.user = out.b_user;
assign mst_resp.r_valid = out.r_valid;
assign mst_resp.r.id = out.r_id;
assign mst_resp.r.data = out.r_data;
assign mst_resp.r.resp = out.r_resp;
assign mst_resp.r.last = out.r_last;
assign mst_resp.r.user = out.r_user;
axi_cut #(
.Bypass ( BYPASS ),
.BypassAw ( BYPASS_AW ),
.BypassW ( BYPASS_W ),
.BypassB ( BYPASS_B ),
.BypassAr ( BYPASS_AR ),
.BypassR ( BYPASS_R ),
.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_cut (
.clk_i,
.rst_ni,
.slv_req_i ( slv_req ),
.slv_resp_o ( slv_resp ),
.mst_req_o ( mst_req ),
.mst_resp_i ( mst_resp )
);
endmodule
module axi_lite_cut_intf #(
parameter bit BYPASS = 1'b0,
parameter bit BYPASS_AW = BYPASS,
parameter bit BYPASS_W = BYPASS,
parameter bit BYPASS_B = BYPASS,
parameter bit BYPASS_AR = BYPASS,
parameter bit BYPASS_R = BYPASS,
parameter int unsigned ADDR_WIDTH = 0,
parameter int unsigned DATA_WIDTH = 0
) (
input logic clk_i ,
input logic rst_ni ,
AXI_LITE.Slave in ,
AXI_LITE.Master out
);
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 struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
} w_chan_t;
typedef struct packed {
axi_pkg::resp_t resp;
} b_chan_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} ar_chan_t;
typedef struct packed {
data_t data;
axi_pkg::resp_t resp;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} axi_req_t;
typedef struct packed {
logic aw_ready;
logic w_ready;
b_chan_t b;
logic b_valid;
logic ar_ready;
r_chan_t r;
logic r_valid;
} axi_resp_t;
axi_req_t slv_req, mst_req;
axi_resp_t slv_resp, mst_resp;
assign slv_req.aw.addr = in.aw_addr;
assign slv_req.aw.prot = in.aw_prot;
assign slv_req.aw_valid = in.aw_valid;
assign slv_req.w.data = in.w_data;
assign slv_req.w.strb = in.w_strb;
assign slv_req.w_valid = in.w_valid;
assign slv_req.b_ready = in.b_ready;
assign slv_req.ar.addr = in.ar_addr;
assign slv_req.ar.prot = in.ar_prot;
assign slv_req.ar_valid = in.ar_valid;
assign slv_req.r_ready = in.r_ready;
assign in.aw_ready = slv_resp.aw_ready;
assign in.ar_ready = slv_resp.ar_ready;
assign in.w_ready = slv_resp.w_ready;
assign in.b_valid = slv_resp.b_valid;
assign in.b_resp = slv_resp.b.resp;
assign in.r_valid = slv_resp.r_valid;
assign in.r_data = slv_resp.r.data;
assign in.r_resp = slv_resp.r.resp;
assign out.aw_addr = mst_req.aw.addr;
assign out.aw_prot = mst_req.aw.prot;
assign out.aw_valid = mst_req.aw_valid;
assign out.w_data = mst_req.w.data;
assign out.w_strb = mst_req.w.strb;
assign out.w_valid = mst_req.w_valid;
assign out.b_ready = mst_req.b_ready;
assign out.ar_addr = mst_req.ar.addr;
assign out.ar_prot = mst_req.ar.prot;
assign out.ar_valid = mst_req.ar_valid;
assign out.r_ready = mst_req.r_ready;
assign mst_resp.aw_ready = out.aw_ready;
assign mst_resp.ar_ready = out.ar_ready;
assign mst_resp.w_ready = out.w_ready;
assign mst_resp.b_valid = out.b_valid;
assign mst_resp.b.resp = out.b_resp;
assign mst_resp.r_valid = out.r_valid;
assign mst_resp.r.data = out.r_data;
assign mst_resp.r.resp = out.r_resp;
axi_cut #(
.Bypass ( BYPASS ),
.BypassAw ( BYPASS_AW ),
.BypassW ( BYPASS_W ),
.BypassB ( BYPASS_B ),
.BypassAr ( BYPASS_AR ),
.BypassR ( BYPASS_R ),
.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_cut (
.clk_i,
.rst_ni,
.slv_req_i ( slv_req ),
.slv_resp_o ( slv_resp ),
.mst_req_o ( mst_req ),
.mst_resp_i ( mst_resp )
);
endmodule
`begin_keywords "1800-2023"
module axi_delayer #(
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,
parameter bit StallRandomInput = 0,
parameter bit StallRandomOutput = 0,
parameter int unsigned FixedDelayInput = 1,
parameter int unsigned FixedDelayOutput = 1
) (
input logic clk_i,
input logic rst_ni,
input axi_req_t slv_req_i,
output axi_resp_t slv_resp_o,
output axi_req_t mst_req_o,
input axi_resp_t mst_resp_i
);
stream_delay #(
.StallRandom ( StallRandomInput ),
.FixedDelay ( FixedDelayInput ),
.payload_t ( aw_chan_t )
) i_stream_delay_aw (
.clk_i,
.rst_ni,
.payload_i ( slv_req_i.aw ),
.ready_o ( slv_resp_o.aw_ready ),
.valid_i ( slv_req_i.aw_valid ),
.payload_o ( mst_req_o.aw ),
.ready_i ( mst_resp_i.aw_ready ),
.valid_o ( mst_req_o.aw_valid )
);
stream_delay #(
.StallRandom ( StallRandomInput ),
.FixedDelay ( FixedDelayInput ),
.payload_t ( ar_chan_t )
) i_stream_delay_ar (
.clk_i,
.rst_ni,
.payload_i ( slv_req_i.ar ),
.ready_o ( slv_resp_o.ar_ready ),
.valid_i ( slv_req_i.ar_valid ),
.payload_o ( mst_req_o.ar ),
.ready_i ( mst_resp_i.ar_ready ),
.valid_o ( mst_req_o.ar_valid )
);
stream_delay #(
.StallRandom ( StallRandomInput ),
.FixedDelay ( FixedDelayInput ),
.payload_t ( w_chan_t )
) i_stream_delay_w (
.clk_i,
.rst_ni,
.payload_i ( slv_req_i.w ),
.ready_o ( slv_resp_o.w_ready ),
.valid_i ( slv_req_i.w_valid ),
.payload_o ( mst_req_o.w ),
.ready_i ( mst_resp_i.w_ready ),
.valid_o ( mst_req_o.w_valid )
);
stream_delay #(
.StallRandom ( StallRandomOutput ),
.FixedDelay ( FixedDelayOutput ),
.payload_t ( b_chan_t )
) i_stream_delay_b (
.clk_i,
.rst_ni,
.payload_i ( mst_resp_i.b ),
.ready_o ( mst_req_o.b_ready ),
.valid_i ( mst_resp_i.b_valid ),
.payload_o ( slv_resp_o.b ),
.ready_i ( slv_req_i.b_ready ),
.valid_o ( slv_resp_o.b_valid )
);
stream_delay #(
.StallRandom ( StallRandomOutput ),
.FixedDelay ( FixedDelayOutput ),
.payload_t ( r_chan_t )
) i_stream_delay_r (
.clk_i,
.rst_ni,
.payload_i ( mst_resp_i.r ),
.ready_o ( mst_req_o.r_ready ),
.valid_i ( mst_resp_i.r_valid ),
.payload_o ( slv_resp_o.r ),
.ready_i ( slv_req_i.r_ready ),
.valid_o ( slv_resp_o.r_valid )
);
endmodule
module axi_delayer_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,
parameter bit STALL_RANDOM_INPUT = 0,
parameter bit STALL_RANDOM_OUTPUT = 0,
parameter int unsigned FIXED_DELAY_INPUT = 1,
parameter int unsigned FIXED_DELAY_OUTPUT = 1
) (
input logic clk_i,
input logic rst_ni,
AXI_BUS.Slave slv,
AXI_BUS.Master mst
);
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;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_pkg::atop_t atop;
user_t user;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
logic last;
user_t user;
} w_chan_t;
typedef struct packed {
id_t id;
axi_pkg::resp_t resp;
user_t user;
} b_chan_t;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
user_t user;
} ar_chan_t;
typedef struct packed {
id_t id;
data_t data;
axi_pkg::resp_t resp;
logic last;
user_t user;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} axi_req_t;
typedef struct packed {
logic aw_ready;
logic ar_ready;
logic w_ready;
logic b_valid;
b_chan_t b;
logic r_valid;
r_chan_t r;
} axi_resp_t;
axi_req_t slv_req, mst_req;
axi_resp_t slv_resp, mst_resp;
assign slv_req.aw.id = slv.aw_id;
assign slv_req.aw.addr = slv.aw_addr;
assign slv_req.aw.len = slv.aw_len;
assign slv_req.aw.size = slv.aw_size;
assign slv_req.aw.burst = slv.aw_burst;
assign slv_req.aw.lock = slv.aw_lock;
assign slv_req.aw.cache = slv.aw_cache;
assign slv_req.aw.prot = slv.aw_prot;
assign slv_req.aw.qos = slv.aw_qos;
assign slv_req.aw.region = slv.aw_region;
assign slv_req.aw.atop = slv.aw_atop;
assign slv_req.aw.user = slv.aw_user;
assign slv_req.aw_valid = slv.aw_valid;
assign slv_req.w.data = slv.w_data;
assign slv_req.w.strb = slv.w_strb;
assign slv_req.w.last = slv.w_last;
assign slv_req.w.user = slv.w_user;
assign slv_req.w_valid = slv.w_valid;
assign slv_req.b_ready = slv.b_ready;
assign slv_req.ar.id = slv.ar_id;
assign slv_req.ar.addr = slv.ar_addr;
assign slv_req.ar.len = slv.ar_len;
assign slv_req.ar.size = slv.ar_size;
assign slv_req.ar.burst = slv.ar_burst;
assign slv_req.ar.lock = slv.ar_lock;
assign slv_req.ar.cache = slv.ar_cache;
assign slv_req.ar.prot = slv.ar_prot;
assign slv_req.ar.qos = slv.ar_qos;
assign slv_req.ar.region = slv.ar_region;
assign slv_req.ar.user = slv.ar_user;
assign slv_req.ar_valid = slv.ar_valid;
assign slv_req.r_ready = slv.r_ready;
assign slv.aw_ready = slv_resp.aw_ready;
assign slv.ar_ready = slv_resp.ar_ready;
assign slv.w_ready = slv_resp.w_ready;
assign slv.b_valid = slv_resp.b_valid;
assign slv.b_id = slv_resp.b.id;
assign slv.b_resp = slv_resp.b.resp;
assign slv.b_user = slv_resp.b.user;
assign slv.r_valid = slv_resp.r_valid;
assign slv.r_id = slv_resp.r.id;
assign slv.r_data = slv_resp.r.data;
assign slv.r_resp = slv_resp.r.resp;
assign slv.r_last = slv_resp.r.last;
assign slv.r_user = slv_resp.r.user;
assign mst.aw_id = mst_req.aw.id;
assign mst.aw_addr = mst_req.aw.addr;
assign mst.aw_len = mst_req.aw.len;
assign mst.aw_size = mst_req.aw.size;
assign mst.aw_burst = mst_req.aw.burst;
assign mst.aw_lock = mst_req.aw.lock;
assign mst.aw_cache = mst_req.aw.cache;
assign mst.aw_prot = mst_req.aw.prot;
assign mst.aw_qos = mst_req.aw.qos;
assign mst.aw_region = mst_req.aw.region;
assign mst.aw_atop = mst_req.aw.atop;
assign mst.aw_user = mst_req.aw.user;
assign mst.aw_valid = mst_req.aw_valid;
assign mst.w_data = mst_req.w.data;
assign mst.w_strb = mst_req.w.strb;
assign mst.w_last = mst_req.w.last;
assign mst.w_user = mst_req.w.user;
assign mst.w_valid = mst_req.w_valid;
assign mst.b_ready = mst_req.b_ready;
assign mst.ar_id = mst_req.ar.id;
assign mst.ar_addr = mst_req.ar.addr;
assign mst.ar_len = mst_req.ar.len;
assign mst.ar_size = mst_req.ar.size;
assign mst.ar_burst = mst_req.ar.burst;
assign mst.ar_lock = mst_req.ar.lock;
assign mst.ar_cache = mst_req.ar.cache;
assign mst.ar_prot = mst_req.ar.prot;
assign mst.ar_qos = mst_req.ar.qos;
assign mst.ar_region = mst_req.ar.region;
assign mst.ar_user = mst_req.ar.user;
assign mst.ar_valid = mst_req.ar_valid;
assign mst.r_ready = mst_req.r_ready;
assign mst_resp.aw_ready = mst.aw_ready;
assign mst_resp.ar_ready = mst.ar_ready;
assign mst_resp.w_ready = mst.w_ready;
assign mst_resp.b_valid = mst.b_valid;
assign mst_resp.b.id = mst.b_id;
assign mst_resp.b.resp = mst.b_resp;
assign mst_resp.b.user = mst.b_user;
assign mst_resp.r_valid = mst.r_valid;
assign mst_resp.r.id = mst.r_id;
assign mst_resp.r.data = mst.r_data;
assign mst_resp.r.resp = mst.r_resp;
assign mst_resp.r.last = mst.r_last;
assign mst_resp.r.user = mst.r_user;
axi_delayer #(
.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 ),
.StallRandomInput ( STALL_RANDOM_INPUT ),
.StallRandomOutput ( STALL_RANDOM_OUTPUT ),
.FixedDelayInput ( FIXED_DELAY_INPUT ),
.FixedDelayOutput ( FIXED_DELAY_OUTPUT )
) i_axi_delayer (
.clk_i,
.rst_ni,
.slv_req_i ( slv_req ),
.slv_resp_o ( slv_resp ),
.mst_req_o ( mst_req ),
.mst_resp_i ( mst_resp )
);
endmodule
`begin_keywords "1800-2023"
module axi_demux_simple #(
parameter int unsigned AxiIdWidth = 32'd0,
parameter bit AtopSupport = 1'b1,
parameter type axi_req_t = logic,
parameter type axi_resp_t = logic,
parameter int unsigned NoMstPorts = 32'd0,
parameter int unsigned MaxTrans = 32'd8,
parameter int unsigned AxiLookBits = 32'd3,
parameter bit UniqueIds = 1'b0,
parameter int unsigned SelectWidth = (NoMstPorts > 32'd1) ? $clog2(NoMstPorts) : 32'd1,
parameter type select_t = logic [SelectWidth-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic test_i,
input axi_req_t slv_req_i,
input select_t slv_aw_select_i,
input select_t slv_ar_select_i,
output axi_resp_t slv_resp_o,
output axi_req_t [NoMstPorts-1:0] mst_reqs_o,
input axi_resp_t [NoMstPorts-1:0] mst_resps_i
);
localparam int unsigned IdCounterWidth = cf_math_pkg::idx_width(MaxTrans);
typedef logic [IdCounterWidth-1:0] id_cnt_t;
if (NoMstPorts == 32'h1) begin : gen_no_demux
assign mst_reqs_o[0].aw.id = slv_req_i.aw.id;
assign mst_reqs_o[0].aw.addr = slv_req_i.aw.addr;
assign mst_reqs_o[0].aw.len = slv_req_i.aw.len;
assign mst_reqs_o[0].aw.size = slv_req_i.aw.size;
assign mst_reqs_o[0].aw.burst = slv_req_i.aw.burst;
assign mst_reqs_o[0].aw.lock = slv_req_i.aw.lock;
assign mst_reqs_o[0].aw.cache = slv_req_i.aw.cache;
assign mst_reqs_o[0].aw.prot = slv_req_i.aw.prot;
assign mst_reqs_o[0].aw.qos = slv_req_i.aw.qos;
assign mst_reqs_o[0].aw.region = slv_req_i.aw.region;
assign mst_reqs_o[0].aw.atop = slv_req_i.aw.atop;
assign mst_reqs_o[0].aw.user = slv_req_i.aw.user;
assign mst_reqs_o[0].aw_valid = slv_req_i.aw_valid;
assign mst_reqs_o[0].w.data = slv_req_i.w.data;
assign mst_reqs_o[0].w.strb = slv_req_i.w.strb;
assign mst_reqs_o[0].w.last = slv_req_i.w.last;
assign mst_reqs_o[0].w.user = slv_req_i.w.user;
assign mst_reqs_o[0].w_valid = slv_req_i.w_valid;
assign mst_reqs_o[0].b_ready = slv_req_i.b_ready;
assign mst_reqs_o[0].ar.id = slv_req_i.ar.id;
assign mst_reqs_o[0].ar.addr = slv_req_i.ar.addr;
assign mst_reqs_o[0].ar.len = slv_req_i.ar.len;
assign mst_reqs_o[0].ar.size = slv_req_i.ar.size;
assign mst_reqs_o[0].ar.burst = slv_req_i.ar.burst;
assign mst_reqs_o[0].ar.lock = slv_req_i.ar.lock;
assign mst_reqs_o[0].ar.cache = slv_req_i.ar.cache;
assign mst_reqs_o[0].ar.prot = slv_req_i.ar.prot;
assign mst_reqs_o[0].ar.qos = slv_req_i.ar.qos;
assign mst_reqs_o[0].ar.region = slv_req_i.ar.region;
assign mst_reqs_o[0].ar.user = slv_req_i.ar.user;
assign mst_reqs_o[0].ar_valid = slv_req_i.ar_valid;
assign mst_reqs_o[0].r_ready = slv_req_i.r_ready;
assign slv_resp_o.aw_ready = mst_resps_i[0].aw_ready;
assign slv_resp_o.ar_ready = mst_resps_i[0].ar_ready;
assign slv_resp_o.w_ready = mst_resps_i[0].w_ready;
assign slv_resp_o.b_valid = mst_resps_i[0].b_valid;
assign slv_resp_o.b.id = mst_resps_i[0].b.id;
assign slv_resp_o.b.resp = mst_resps_i[0].b.resp;
assign slv_resp_o.b.user = mst_resps_i[0].b.user;
assign slv_resp_o.r_valid = mst_resps_i[0].r_valid;
assign slv_resp_o.r.id = mst_resps_i[0].r.id;
assign slv_resp_o.r.data = mst_resps_i[0].r.data;
assign slv_resp_o.r.resp = mst_resps_i[0].r.resp;
assign slv_resp_o.r.last = mst_resps_i[0].r.last;
assign slv_resp_o.r.user = mst_resps_i[0].r.user;
end else begin
logic lock_aw_valid_d, lock_aw_valid_q, load_aw_lock;
logic aw_valid, aw_ready;
select_t lookup_aw_select;
logic aw_select_occupied, aw_id_cnt_full;
logic atop_inject;
select_t w_select, w_select_q;
logic w_select_valid;
id_cnt_t w_open;
logic w_cnt_up, w_cnt_down;
logic [NoMstPorts-1:0] mst_b_valids, mst_b_readies;
select_t lookup_ar_select;
logic ar_select_occupied, ar_id_cnt_full;
logic ar_push;
logic lock_ar_valid_d, lock_ar_valid_q, load_ar_lock;
logic ar_valid, ar_ready;
logic [NoMstPorts-1:0] mst_r_valids, mst_r_readies;
always_comb begin
slv_resp_o.aw_ready = 1'b0;
aw_valid = 1'b0;
lock_aw_valid_d = lock_aw_valid_q;
load_aw_lock = 1'b0;
w_cnt_up = 1'b0;
atop_inject = 1'b0;
if (lock_aw_valid_q) begin
aw_valid = 1'b1;
if (aw_ready) begin
slv_resp_o.aw_ready = 1'b1;
lock_aw_valid_d = 1'b0;
load_aw_lock = 1'b1;
atop_inject = slv_req_i.aw.atop[axi_pkg::ATOP_R_RESP] & AtopSupport;
end
end else begin
if (!aw_id_cnt_full && (w_open != {IdCounterWidth{1'b1}}) &&
(!(ar_id_cnt_full && slv_req_i.aw.atop[axi_pkg::ATOP_R_RESP]) ||
!AtopSupport)) begin
if (slv_req_i.aw_valid &&
((w_open == '0) || (w_select == slv_aw_select_i)) &&
(!aw_select_occupied || (slv_aw_select_i == lookup_aw_select))) begin
aw_valid = 1'b1;
w_cnt_up = 1'b1;
if (aw_ready) begin
slv_resp_o.aw_ready = 1'b1;
atop_inject = slv_req_i.aw.atop[axi_pkg::ATOP_R_RESP] & AtopSupport;
end else begin
lock_aw_valid_d = 1'b1;
load_aw_lock = 1'b1;
end
end
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
lock_aw_valid_q <= ('0);
end else begin
if (load_aw_lock) begin
lock_aw_valid_q <= (lock_aw_valid_d);
end
end
end
if (UniqueIds) begin : gen_unique_ids_aw
assign lookup_aw_select = slv_aw_select_i;
assign aw_select_occupied = 1'b0;
assign aw_id_cnt_full = 1'b0;
end else begin : gen_aw_id_counter
axi_demux_id_counters #(
.AxiIdBits ( AxiLookBits ),
.CounterWidth ( IdCounterWidth ),
.mst_port_select_t ( select_t )
) i_aw_id_counter (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.lookup_axi_id_i ( slv_req_i.aw.id[0+:AxiLookBits] ),
.lookup_mst_select_o ( lookup_aw_select ),
.lookup_mst_select_occupied_o ( aw_select_occupied ),
.full_o ( aw_id_cnt_full ),
.inject_axi_id_i ( '0 ),
.inject_i ( 1'b0 ),
.push_axi_id_i ( slv_req_i.aw.id[0+:AxiLookBits] ),
.push_mst_select_i ( slv_aw_select_i ),
.push_i ( w_cnt_up ),
.pop_axi_id_i ( slv_resp_o.b.id[0+:AxiLookBits] ),
.pop_i ( slv_resp_o.b_valid & slv_req_i.b_ready ),
.any_outstanding_trx_o ( )
);
end
counter #(
.WIDTH ( IdCounterWidth ),
.STICKY_OVERFLOW ( 1'b0 )
) i_counter_open_w (
.clk_i,
.rst_ni,
.clear_i ( 1'b0 ),
.en_i ( w_cnt_up ^ w_cnt_down ),
.load_i ( 1'b0 ),
.down_i ( w_cnt_down ),
.d_i ( '0 ),
.q_o ( w_open ),
.overflow_o ( )
);
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
w_select_q <= (select_t'(0));
end else begin
if (w_cnt_up) begin
w_select_q <= (slv_aw_select_i);
end
end
end
assign w_select = (|w_open) ? w_select_q : slv_aw_select_i;
assign w_select_valid = w_cnt_up | (|w_open);
logic [cf_math_pkg::idx_width(NoMstPorts)-1:0] b_idx;
rr_arb_tree #(
.NumIn ( NoMstPorts ),
.DataType ( logic ),
.AxiVldRdy( 1'b1 ),
.LockIn ( 1'b1 )
) i_b_mux (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i( 1'b0 ),
.rr_i ( '0 ),
.req_i ( mst_b_valids ),
.gnt_o ( mst_b_readies ),
.data_i ( '0 ),
.gnt_i ( slv_req_i.b_ready ),
.req_o ( slv_resp_o.b_valid ),
.data_o ( ),
.idx_o ( b_idx )
);
always_comb begin
if (slv_resp_o.b_valid) begin
slv_resp_o.b.id = mst_resps_i[b_idx].b.id;
slv_resp_o.b.resp = mst_resps_i[b_idx].b.resp;
slv_resp_o.b.user = mst_resps_i[b_idx].b.user;
end else begin
slv_resp_o.b = '0;
end
end
always_comb begin
slv_resp_o.ar_ready = 1'b0;
ar_valid = 1'b0;
lock_ar_valid_d = lock_ar_valid_q;
load_ar_lock = 1'b0;
ar_push = 1'b0;
if (lock_ar_valid_q) begin
ar_valid = 1'b1;
if (ar_ready) begin
slv_resp_o.ar_ready = 1'b1;
ar_push = 1'b1;
lock_ar_valid_d = 1'b0;
load_ar_lock = 1'b1;
end
end else begin
if (!ar_id_cnt_full) begin
if (slv_req_i.ar_valid && (!ar_select_occupied ||
(slv_ar_select_i == lookup_ar_select))) begin
ar_valid = 1'b1;
if (ar_ready) begin
slv_resp_o.ar_ready = 1'b1;
ar_push = 1'b1;
end else begin
lock_ar_valid_d = 1'b1;
load_ar_lock = 1'b1;
end
end
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
lock_ar_valid_q <= ('0);
end else begin
if (load_ar_lock) begin
lock_ar_valid_q <= (lock_ar_valid_d);
end
end
end
if (UniqueIds) begin : gen_unique_ids_ar
assign lookup_ar_select = slv_ar_select_i;
assign ar_select_occupied = 1'b0;
assign ar_id_cnt_full = 1'b0;
end else begin : gen_ar_id_counter
axi_demux_id_counters #(
.AxiIdBits ( AxiLookBits ),
.CounterWidth ( IdCounterWidth ),
.mst_port_select_t ( select_t )
) i_ar_id_counter (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.lookup_axi_id_i ( slv_req_i.ar.id[0+:AxiLookBits] ),
.lookup_mst_select_o ( lookup_ar_select ),
.lookup_mst_select_occupied_o ( ar_select_occupied ),
.full_o ( ar_id_cnt_full ),
.inject_axi_id_i ( slv_req_i.aw.id[0+:AxiLookBits] ),
.inject_i ( atop_inject ),
.push_axi_id_i ( slv_req_i.ar.id[0+:AxiLookBits] ),
.push_mst_select_i ( slv_ar_select_i ),
.push_i ( ar_push ),
.pop_axi_id_i ( slv_resp_o.r.id[0+:AxiLookBits] ),
.pop_i ( slv_resp_o.r_valid & slv_req_i.r_ready & slv_resp_o.r.last ),
.any_outstanding_trx_o ( )
);
end
logic [cf_math_pkg::idx_width(NoMstPorts)-1:0] r_idx;
rr_arb_tree #(
.NumIn ( NoMstPorts ),
.DataType ( logic ),
.AxiVldRdy( 1'b1 ),
.LockIn ( 1'b1 )
) i_r_mux (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i( 1'b0 ),
.rr_i ( '0 ),
.req_i ( mst_r_valids ),
.gnt_o ( mst_r_readies ),
.data_i ( '0 ),
.gnt_i ( slv_req_i.r_ready ),
.req_o ( slv_resp_o.r_valid ),
.data_o (),
.idx_o ( r_idx )
);
always_comb begin
if (slv_resp_o.r_valid) begin
slv_resp_o.r.id = mst_resps_i[r_idx].r.id;
slv_resp_o.r.data = mst_resps_i[r_idx].r.data;
slv_resp_o.r.resp = mst_resps_i[r_idx].r.resp;
slv_resp_o.r.last = mst_resps_i[r_idx].r.last;
slv_resp_o.r.user = mst_resps_i[r_idx].r.user;
end else begin
slv_resp_o.r = '0;
end
end
assign ar_ready = ar_valid & mst_resps_i[slv_ar_select_i].ar_ready;
assign aw_ready = aw_valid & mst_resps_i[slv_aw_select_i].aw_ready;
always_comb begin
mst_reqs_o = '0;
slv_resp_o.w_ready = 1'b0;
w_cnt_down = 1'b0;
for (int unsigned i = 0; i < NoMstPorts; i++) begin
mst_reqs_o[i].aw = slv_req_i.aw;
mst_reqs_o[i].aw_valid = 1'b0;
if (aw_valid && (slv_aw_select_i == i)) begin
mst_reqs_o[i].aw_valid = 1'b1;
end
mst_reqs_o[i].w = slv_req_i.w;
mst_reqs_o[i].w_valid = 1'b0;
if (w_select_valid && (w_select == i)) begin
mst_reqs_o[i].w_valid = slv_req_i.w_valid;
slv_resp_o.w_ready = mst_resps_i[i].w_ready;
w_cnt_down = slv_req_i.w_valid & mst_resps_i[i].w_ready & slv_req_i.w.last;
end
mst_reqs_o[i].b_ready = mst_b_readies[i];
mst_reqs_o[i].ar = slv_req_i.ar;
mst_reqs_o[i].ar_valid = 1'b0;
if (ar_valid && (slv_ar_select_i == i)) begin
mst_reqs_o[i].ar_valid = 1'b1;
end
mst_reqs_o[i].r_ready = mst_r_readies[i];
end
end
for (genvar i = 0; i < NoMstPorts; i++) begin : gen_b_channels
assign mst_b_valids[i] = mst_resps_i[i].b_valid;
assign mst_r_valids[i] = mst_resps_i[i].r_valid;
end
end
endmodule
`begin_keywords "1800-2023"
module axi_dw_downsizer #(
parameter int unsigned AxiMaxReads = 1 ,
parameter int unsigned AxiSlvPortDataWidth = 8 ,
parameter int unsigned AxiMstPortDataWidth = 8 ,
parameter int unsigned AxiAddrWidth = 1 ,
parameter int unsigned AxiIdWidth = 1 ,
parameter type aw_chan_t = logic,
parameter type mst_w_chan_t = logic,
parameter type slv_w_chan_t = logic,
parameter type b_chan_t = logic,
parameter type ar_chan_t = logic,
parameter type mst_r_chan_t = logic,
parameter type slv_r_chan_t = logic,
parameter type axi_mst_req_t = logic,
parameter type axi_mst_resp_t = logic,
parameter type axi_slv_req_t = logic,
parameter type axi_slv_resp_t = logic
) (
input logic clk_i,
input logic rst_ni,
input axi_slv_req_t slv_req_i,
output axi_slv_resp_t slv_resp_o,
output axi_mst_req_t mst_req_o,
input axi_mst_resp_t mst_resp_i
);
import axi_pkg::aligned_addr;
import axi_pkg::modifiable ;
import cf_math_pkg::idx_width;
localparam TranIdWidth = AxiMaxReads > 1 ? $clog2(AxiMaxReads) : 1;
typedef logic [TranIdWidth-1:0] tran_id_t;
localparam AxiSlvPortStrbWidth = AxiSlvPortDataWidth / 8;
localparam AxiMstPortStrbWidth = AxiMstPortDataWidth / 8;
localparam AxiSlvPortMaxSize = $clog2(AxiSlvPortStrbWidth);
localparam AxiMstPortMaxSize = $clog2(AxiMstPortStrbWidth);
localparam SlvPortByteMask = AxiSlvPortStrbWidth - 1;
localparam MstPortByteMask = AxiMstPortStrbWidth - 1;
typedef logic [AxiMstPortStrbWidth-1:0][7:0] mst_data_t;
typedef logic [AxiSlvPortStrbWidth-1:0][7:0] slv_data_t;
typedef logic [AxiAddrWidth-1:0] addr_t;
typedef logic [AxiIdWidth-1:0] id_t;
typedef logic [$clog2(AxiSlvPortStrbWidth/AxiMstPortStrbWidth) + 7:0] burst_len_t;
axi_mst_req_t mst_req;
axi_mst_resp_t mst_resp;
slv_r_chan_t [AxiMaxReads-1:0] slv_r_tran;
logic [AxiMaxReads-1:0] slv_r_valid_tran;
logic [AxiMaxReads-1:0] slv_r_ready_tran;
rr_arb_tree #(
.NumIn (AxiMaxReads ),
.DataType (slv_r_chan_t),
.AxiVldRdy(1'b1 ),
.ExtPrio (1'b0 ),
.LockIn (1'b1 )
) i_slv_r_arb (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.flush_i(1'b0 ),
.rr_i ('0 ),
.req_i (slv_r_valid_tran ),
.gnt_o (slv_r_ready_tran ),
.data_i (slv_r_tran ),
.gnt_i (slv_req_i.r_ready ),
.req_o (slv_resp_o.r_valid),
.data_o (slv_resp_o.r ),
.idx_o ( )
);
logic [AxiMaxReads-1:0] mst_r_ready_tran;
assign mst_req.r_ready = |mst_r_ready_tran;
id_t arb_slv_ar_id;
logic arb_slv_ar_req;
logic arb_slv_ar_gnt;
logic [AxiMaxReads-1:0] arb_slv_ar_gnt_tran;
logic inject_aw_into_ar;
logic inject_aw_into_ar_req;
logic inject_aw_into_ar_gnt;
assign arb_slv_ar_gnt = |arb_slv_ar_gnt_tran;
rr_arb_tree #(
.NumIn (2 ),
.DataWidth (AxiIdWidth),
.ExtPrio (1'b0 ),
.AxiVldRdy (1'b1 ),
.LockIn (1'b0 )
) i_slv_ar_arb (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.flush_i (1'b0 ),
.rr_i ('0 ),
.req_i ({inject_aw_into_ar_req, slv_req_i.ar_valid} ),
.gnt_o ({inject_aw_into_ar_gnt, slv_resp_o.ar_ready}),
.data_i ({slv_req_i.aw.id, slv_req_i.ar.id} ),
.req_o (arb_slv_ar_req ),
.gnt_i (arb_slv_ar_gnt ),
.data_o (arb_slv_ar_id ),
.idx_o (inject_aw_into_ar )
);
ar_chan_t [AxiMaxReads-1:0] mst_ar_tran;
id_t [AxiMaxReads-1:0] mst_ar_id;
logic [AxiMaxReads-1:0] mst_ar_valid_tran;
logic [AxiMaxReads-1:0] mst_ar_ready_tran;
tran_id_t mst_req_idx;
rr_arb_tree #(
.NumIn (AxiMaxReads),
.DataType (ar_chan_t ),
.AxiVldRdy(1'b1 ),
.ExtPrio (1'b0 ),
.LockIn (1'b1 )
) i_mst_ar_arb (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.flush_i(1'b0 ),
.rr_i ('0 ),
.req_i (mst_ar_valid_tran),
.gnt_o (mst_ar_ready_tran),
.data_i (mst_ar_tran ),
.gnt_i (mst_resp.ar_ready),
.req_o (mst_req.ar_valid ),
.data_o (mst_req.ar ),
.idx_o (mst_req_idx )
);
axi_mst_req_t axi_err_req;
axi_mst_resp_t axi_err_resp;
axi_err_slv #(
.AxiIdWidth(AxiIdWidth ),
.Resp (axi_pkg::RESP_SLVERR),
.axi_req_t (axi_mst_req_t ),
.axi_resp_t(axi_mst_resp_t )
) i_axi_err_slv (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.test_i (1'b0 ),
.slv_req_i (axi_err_req ),
.slv_resp_o(axi_err_resp)
);
logic [AxiMaxReads-1:0] mst_req_ar_err;
logic mst_req_aw_err;
axi_demux #(
.AxiIdWidth (AxiIdWidth ),
.AxiLookBits(AxiIdWidth ),
.aw_chan_t (aw_chan_t ),
.w_chan_t (mst_w_chan_t ),
.b_chan_t (b_chan_t ),
.ar_chan_t (ar_chan_t ),
.r_chan_t (mst_r_chan_t ),
.axi_req_t (axi_mst_req_t ),
.axi_resp_t (axi_mst_resp_t),
.NoMstPorts (2 ),
.MaxTrans (AxiMaxReads ),
.SpillAw (1'b1 )
) i_axi_demux (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.test_i (1'b0 ),
.mst_reqs_o ({axi_err_req, mst_req_o} ),
.mst_resps_i ({axi_err_resp, mst_resp_i} ),
.slv_ar_select_i(mst_req_ar_err[mst_req_idx]),
.slv_aw_select_i(mst_req_aw_err ),
.slv_req_i (mst_req ),
.slv_resp_o (mst_resp )
);
typedef enum logic [2:0] {
R_IDLE ,
R_INJECT_AW ,
R_PASSTHROUGH ,
R_INCR_DOWNSIZE,
R_SPLIT_INCR_DOWNSIZE
} r_state_e;
typedef struct packed {
ar_chan_t ar ;
logic ar_valid ;
logic ar_throw_error ;
slv_r_chan_t r ;
logic r_valid ;
burst_len_t burst_len ;
axi_pkg::size_t orig_ar_size;
logic injected_aw ;
} r_req_t;
typedef struct packed {
aw_chan_t aw ;
logic aw_valid ;
logic aw_throw_error ;
burst_len_t burst_len ;
axi_pkg::len_t orig_aw_len ;
axi_pkg::burst_t orig_aw_burst;
axi_pkg::resp_t burst_resp ;
axi_pkg::size_t orig_aw_size ;
} w_req_t;
w_req_t w_req_d, w_req_q;
logic [AxiMaxReads-1:0] idle_read_downsizer;
tran_id_t idx_ar_downsizer;
tran_id_t idx_idle_downsizer;
lzc #(
.WIDTH(AxiMaxReads)
) i_idle_lzc (
.in_i (idle_read_downsizer),
.cnt_o (idx_idle_downsizer ),
.empty_o( )
);
logic [AxiMaxReads-1:0] id_clash_downsizer;
tran_id_t idx_id_clash_downsizer;
for (genvar t = 0; t < AxiMaxReads; t++) begin: gen_id_clash
assign id_clash_downsizer[t] = arb_slv_ar_id == mst_ar_id[t] && !idle_read_downsizer[t];
end
onehot_to_bin #(
.ONEHOT_WIDTH(AxiMaxReads)
) i_id_clash_onehot_to_bin (
.onehot(id_clash_downsizer ),
.bin (idx_id_clash_downsizer)
);
assign idx_ar_downsizer = (|id_clash_downsizer) ? idx_id_clash_downsizer : idx_idle_downsizer;
logic [AxiMaxReads-1:0] idqueue_push;
logic [AxiMaxReads-1:0] idqueue_pop;
tran_id_t idqueue_id;
logic idqueue_valid;
id_queue #(
.ID_WIDTH(AxiIdWidth ),
.CAPACITY(AxiMaxReads),
.data_t (tran_id_t )
) i_read_id_queue (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.inp_id_i (arb_slv_ar_id ),
.inp_data_i (idx_ar_downsizer),
.inp_req_i (|idqueue_push ),
.inp_gnt_o ( ),
.oup_id_i (mst_resp.r.id ),
.oup_pop_i (|idqueue_pop ),
.oup_req_i (1'b1 ),
.oup_data_o (idqueue_id ),
.oup_data_valid_o(idqueue_valid ),
.oup_gnt_o ( ),
.exists_data_i ('0 ),
.exists_mask_i ('0 ),
.exists_req_i ('0 ),
.exists_o ( ),
.exists_gnt_o ( ),
.full_o ( ),
.empty_o ( )
);
for (genvar t = 0; unsigned'(t) < AxiMaxReads; t++) begin: gen_read_downsizer
r_state_e r_state_d, r_state_q;
r_req_t r_req_d , r_req_q ;
assign idle_read_downsizer[t] = (r_state_q == R_IDLE) || (r_state_q == R_INJECT_AW);
slv_data_t r_data;
always_comb begin
r_state_d = r_state_q;
r_req_d = r_req_q ;
mst_ar_tran[t] = r_req_q.ar ;
mst_ar_id[t] = r_req_q.ar.id ;
mst_ar_valid_tran[t] = r_req_q.ar_valid;
mst_req_ar_err[t] = r_req_q.ar_throw_error;
slv_r_tran[t] = r_req_q.r ;
slv_r_valid_tran[t] = r_req_q.r_valid;
idqueue_push[t] = '0;
idqueue_pop[t] = '0;
arb_slv_ar_gnt_tran[t] = 1'b0;
mst_r_ready_tran[t] = 1'b0;
if (mst_ar_valid_tran[t] && mst_ar_ready_tran[t]) begin
r_req_d.ar_valid = 1'b0;
r_req_d.ar_throw_error = 1'b0;
end
r_data = r_req_q.r.data;
case (r_state_q)
R_IDLE : begin
r_req_d.ar = '0;
r_req_d.r = '0;
if (arb_slv_ar_req && (idx_ar_downsizer == t)) begin
arb_slv_ar_gnt_tran[t] = 1'b1;
idqueue_push[t] = 1'b1;
if (inject_aw_into_ar) begin
r_state_d = R_INJECT_AW;
end else begin
r_state_d = R_PASSTHROUGH;
r_req_d.ar = slv_req_i.ar ;
r_req_d.ar_valid = 1'b1 ;
r_req_d.burst_len = slv_req_i.ar.len ;
r_req_d.orig_ar_size = slv_req_i.ar.size ;
r_req_d.injected_aw = 1'b0 ;
r_req_d.r.resp = axi_pkg::RESP_EXOKAY;
case (r_req_d.ar.burst)
axi_pkg::BURST_INCR : begin
automatic addr_t size_mask;
automatic addr_t conv_ratio;
automatic addr_t align_adj;
size_mask = (1 << r_req_d.ar.size) - 1 ;
conv_ratio = ((1 << r_req_d.ar.size) + AxiMstPortStrbWidth - 1) / AxiMstPortStrbWidth;
align_adj = (r_req_d.ar.addr & size_mask & ~MstPortByteMask) / AxiMstPortStrbWidth;
r_req_d.burst_len = (r_req_d.ar.len + 1) * conv_ratio - align_adj - 1 ;
if (conv_ratio != 1) begin
r_req_d.ar.size = AxiMstPortMaxSize;
if (r_req_d.burst_len <= 255) begin
r_state_d = R_INCR_DOWNSIZE ;
r_req_d.ar.len = r_req_d.burst_len;
end else begin
r_state_d = R_SPLIT_INCR_DOWNSIZE;
r_req_d.ar.len = 255 - align_adj ;
end
end
end
axi_pkg::BURST_FIXED: begin
if (r_req_d.ar.len == '0) begin
automatic addr_t size_mask;
automatic addr_t conv_ratio;
automatic addr_t align_adj;
size_mask = (1 << r_req_d.ar.size) - 1 ;
conv_ratio = ((1 << r_req_d.ar.size) + AxiMstPortStrbWidth - 1) / AxiMstPortStrbWidth;
align_adj = (r_req_d.ar.addr & size_mask & ~MstPortByteMask) / AxiMstPortStrbWidth;
r_req_d.burst_len = (conv_ratio >= align_adj + 1) ? (conv_ratio - align_adj - 1) : 0 ;
if (conv_ratio != 1) begin
r_state_d = R_INCR_DOWNSIZE ;
r_req_d.ar.len = r_req_d.burst_len ;
r_req_d.ar.size = AxiMstPortMaxSize ;
r_req_d.ar.burst = axi_pkg::BURST_INCR;
end
end else begin
r_req_d.ar_throw_error = 1'b1;
end
end
axi_pkg::BURST_WRAP: begin
r_state_d = R_PASSTHROUGH;
r_req_d.ar_throw_error = 1'b1 ;
end
default: ;
endcase
end
end
end
R_INJECT_AW : begin
r_req_d.ar.id = w_req_q.aw.id ;
r_req_d.ar.addr = w_req_q.aw.addr ;
r_req_d.ar.size = w_req_q.orig_aw_size ;
r_req_d.ar.burst = w_req_q.orig_aw_burst;
r_req_d.ar.len = w_req_q.orig_aw_len ;
r_req_d.ar.lock = w_req_q.aw.lock ;
r_req_d.ar.cache = w_req_q.aw.cache ;
r_req_d.ar.prot = w_req_q.aw.prot ;
r_req_d.ar.qos = w_req_q.aw.qos ;
r_req_d.ar.region = w_req_q.aw.region ;
r_req_d.ar.user = w_req_q.aw.user ;
r_req_d.ar_valid = 1'b0 ;
r_req_d.burst_len = w_req_q.orig_aw_len ;
r_req_d.orig_ar_size = w_req_q.orig_aw_size ;
r_req_d.injected_aw = 1'b1 ;
r_req_d.r.resp = axi_pkg::RESP_EXOKAY ;
r_state_d = R_PASSTHROUGH;
case (r_req_d.ar.burst)
axi_pkg::BURST_INCR : begin
automatic addr_t size_mask;
automatic addr_t conv_ratio;
automatic addr_t align_adj;
size_mask = (1 << r_req_d.ar.size) - 1 ;
conv_ratio = ((1 << r_req_d.ar.size) + AxiMstPortStrbWidth - 1) / AxiMstPortStrbWidth;
align_adj = (r_req_d.ar.addr & size_mask & ~MstPortByteMask) / AxiMstPortStrbWidth;
r_req_d.burst_len = (r_req_d.ar.len + 1) * conv_ratio - align_adj - 1 ;
if (conv_ratio != 1) begin
r_req_d.ar.size = AxiMstPortMaxSize;
if (r_req_d.burst_len <= 255) begin
r_state_d = R_INCR_DOWNSIZE ;
r_req_d.ar.len = r_req_d.burst_len;
end else begin
r_state_d = R_SPLIT_INCR_DOWNSIZE;
r_req_d.ar.len = 255 - align_adj ;
end
end
end
axi_pkg::BURST_FIXED: begin
if (r_req_d.ar.len == '0) begin
automatic addr_t size_mask;
automatic addr_t conv_ratio;
automatic addr_t align_adj;
size_mask = (1 << r_req_d.ar.size) - 1 ;
conv_ratio = ((1 << r_req_d.ar.size) + AxiMstPortStrbWidth - 1) / AxiMstPortStrbWidth;
align_adj = (r_req_d.ar.addr & size_mask & ~MstPortByteMask) / AxiMstPortStrbWidth;
r_req_d.burst_len = (conv_ratio >= align_adj + 1) ? (conv_ratio - align_adj - 1) : 0;
if (conv_ratio != 1) begin
r_state_d = R_INCR_DOWNSIZE ;
r_req_d.ar.len = r_req_d.burst_len ;
r_req_d.ar.size = AxiMstPortMaxSize ;
r_req_d.ar.burst = axi_pkg::BURST_INCR;
end
end else begin
r_req_d.ar_throw_error = 1'b1;
end
end
axi_pkg::BURST_WRAP: begin
r_state_d = R_PASSTHROUGH;
r_req_d.ar_throw_error = 1'b1 ;
end
default: ;
endcase
end
R_PASSTHROUGH, R_INCR_DOWNSIZE, R_SPLIT_INCR_DOWNSIZE: begin
if (slv_r_valid_tran[t] && slv_r_ready_tran[t]) begin
r_req_d.r = '0 ;
r_req_d.r_valid = 1'b0;
r_data = '0 ;
end
if (!r_req_q.ar_valid) begin
if ((idqueue_id == t) && idqueue_valid) begin
if (!slv_r_valid_tran[t] || (slv_r_valid_tran[t] && slv_r_ready_tran[t])) begin
mst_r_ready_tran[t] = 1'b1;
if (mst_resp.r_valid) begin
automatic addr_t mst_port_offset;
automatic addr_t slv_port_offset;
mst_port_offset = AxiMstPortStrbWidth == 1 ? '0 : r_req_q.ar.addr[idx_width(AxiMstPortStrbWidth)-1:0];
slv_port_offset = AxiSlvPortStrbWidth == 1 ? '0 : r_req_q.ar.addr[idx_width(AxiSlvPortStrbWidth)-1:0];
for (int b = 0; b < AxiSlvPortStrbWidth; b++) begin
if ((b >= slv_port_offset) &&
(b - slv_port_offset < (1 << r_req_q.orig_ar_size)) &&
(b + mst_port_offset - slv_port_offset < AxiMstPortStrbWidth)) begin
r_data[b] = mst_resp.r.data[8*(b + mst_port_offset - slv_port_offset) +: 8];
end
end
r_req_d.burst_len = r_req_q.burst_len - 1 ;
r_req_d.ar.len = r_req_q.ar.len - 1 ;
r_req_d.r.data = r_data ;
r_req_d.r.last = (r_req_q.burst_len == 0);
r_req_d.r.id = mst_resp.r.id ;
r_req_d.r.user = mst_resp.r.user ;
r_req_d.r.resp = axi_pkg::resp_precedence(r_req_q.r.resp, mst_resp.r.resp);
case (r_req_d.ar.burst)
axi_pkg::BURST_INCR: begin
r_req_d.ar.addr = aligned_addr(axi_pkg::largest_addr_t'(r_req_q.ar.addr), r_req_q.ar.size) + (1 << r_req_q.ar.size);
end
axi_pkg::BURST_FIXED: begin
r_req_d.ar.addr = r_req_q.ar.addr;
end
endcase
if (r_req_q.burst_len == 0) begin
idqueue_pop[t] = 1'b1;
end
case (r_state_q)
R_PASSTHROUGH : begin
r_req_d.r_valid = 1'b1;
end
R_INCR_DOWNSIZE, R_SPLIT_INCR_DOWNSIZE: begin
if (r_req_q.burst_len == 0 ||
(aligned_addr(axi_pkg::largest_addr_t'(r_req_d.ar.addr), r_req_q.orig_ar_size) !=
aligned_addr(axi_pkg::largest_addr_t'(r_req_q.ar.addr), r_req_q.orig_ar_size) )) begin
r_req_d.r_valid = 1'b1;
end
end
endcase
if (r_state_q == R_SPLIT_INCR_DOWNSIZE) begin
if (r_req_q.ar.len == '0 && r_req_q.burst_len != '0) begin
r_req_d.ar_valid = !r_req_q.injected_aw;
r_req_d.ar.len = (r_req_d.burst_len <= 255) ? r_req_d.burst_len : 255;
end
end
end
end
end
end
if (slv_r_valid_tran[t] && slv_r_ready_tran[t]) begin
if (r_req_q.burst_len == '1) begin
r_state_d = R_IDLE;
end
end
end
default: ;
endcase
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
r_state_q <= R_IDLE;
r_req_q <= '0 ;
end else begin
r_state_q <= r_state_d;
r_req_q <= r_req_d ;
end
end
end : gen_read_downsizer
typedef enum logic [1:0] {
W_IDLE ,
W_PASSTHROUGH ,
W_INCR_DOWNSIZE,
W_SPLIT_INCR_DOWNSIZE
} w_state_e;
w_state_e w_state_d, w_state_q;
logic forward_b_beat_i;
logic forward_b_beat_o;
logic forward_b_beat_push;
logic forward_b_beat_pop;
logic forward_b_beat_full;
fifo_v3 #(
.DATA_WIDTH (1 ),
.DEPTH (AxiMaxReads),
.FALL_THROUGH(1'b1 )
) i_forward_b_beats_queue (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.flush_i (1'b0 ),
.testmode_i(1'b0 ),
.data_i (forward_b_beat_i ),
.push_i (forward_b_beat_push ),
.full_o (forward_b_beat_full ),
.data_o (forward_b_beat_o ),
.pop_i (forward_b_beat_pop ),
.empty_o ( ),
.usage_o ( )
);
mst_data_t w_data;
always_comb begin
inject_aw_into_ar_req = 1'b0;
forward_b_beat_i = '0 ;
forward_b_beat_push = 1'b0;
forward_b_beat_pop = 1'b0;
w_state_d = w_state_q;
w_req_d = w_req_q ;
mst_req.aw = w_req_q.aw ;
mst_req.aw_valid = w_req_q.aw_valid;
slv_resp_o.aw_ready = '0 ;
mst_req_aw_err = w_req_q.aw_throw_error;
mst_req.w = '0;
mst_req.w_valid = '0;
slv_resp_o.w_ready = '0;
w_data = '0;
if (mst_resp.b_valid) begin
w_req_d.burst_resp = axi_pkg::resp_precedence(w_req_q.burst_resp, mst_resp.b.resp);
end
slv_resp_o.b = mst_resp.b ;
slv_resp_o.b.resp = w_req_d.burst_resp;
if (forward_b_beat_o) begin
slv_resp_o.b_valid = mst_resp.b_valid ;
mst_req.b_ready = slv_req_i.b_ready;
if (mst_req.b_ready && mst_resp.b_valid) begin
forward_b_beat_pop = 1'b1;
end
end else begin
slv_resp_o.b_valid = 1'b0 ;
mst_req.b_ready = 1'b1 ;
forward_b_beat_pop = mst_resp.b_valid;
end
if (mst_req.aw_valid & mst_resp.aw_ready) begin
w_req_d.aw_valid = 1'b0;
w_req_d.aw_throw_error = 1'b0;
end
case (w_state_q)
W_PASSTHROUGH, W_INCR_DOWNSIZE, W_SPLIT_INCR_DOWNSIZE: begin
if (!w_req_q.aw_valid) begin
if (slv_req_i.w_valid) begin
automatic logic [idx_width(AxiMstPortStrbWidth)-1:0] mst_port_offset;
automatic logic [idx_width(AxiSlvPortStrbWidth)-1:0] slv_port_offset;
mst_port_offset = AxiMstPortStrbWidth == 1 ? '0 : w_req_q.aw.addr[idx_width(AxiMstPortStrbWidth)-1:0];
slv_port_offset = AxiSlvPortStrbWidth == 1 ? '0 : w_req_q.aw.addr[idx_width(AxiSlvPortStrbWidth)-1:0];
mst_req.w_valid = !(forward_b_beat_full && w_req_q.aw.len == 0);
mst_req.w.last = w_req_q.aw.len == 0;
mst_req.w.user = slv_req_i.w.user ;
for (int b = 0; b < AxiSlvPortStrbWidth; b++) begin
if ((b >= slv_port_offset) &&
(b - slv_port_offset < (1 << w_req_q.orig_aw_size)) &&
(b + mst_port_offset - slv_port_offset < AxiMstPortStrbWidth)) begin
w_data[b + mst_port_offset - slv_port_offset] = slv_req_i.w.data[8*b +: 8];
mst_req.w.strb[b + mst_port_offset - slv_port_offset] = slv_req_i.w.strb[b] ;
end
end
mst_req.w.data = w_data;
end
end
if (mst_resp.w_ready && mst_req.w_valid) begin
w_req_d.burst_len = w_req_q.burst_len - 1;
w_req_d.aw.len = w_req_q.aw.len - 1 ;
case (w_req_d.aw.burst)
axi_pkg::BURST_INCR: begin
w_req_d.aw.addr = aligned_addr(axi_pkg::largest_addr_t'(w_req_q.aw.addr), w_req_q.aw.size) + (1 << w_req_q.aw.size);
end
axi_pkg::BURST_FIXED: begin
w_req_d.aw.addr = w_req_q.aw.addr;
end
endcase
case (w_state_q)
W_PASSTHROUGH: begin
slv_resp_o.w_ready = 1'b1;
end
W_INCR_DOWNSIZE, W_SPLIT_INCR_DOWNSIZE: begin
if (w_req_q.burst_len == 0 ||
(aligned_addr(axi_pkg::largest_addr_t'(w_req_d.aw.addr), w_req_q.orig_aw_size) !=
aligned_addr(axi_pkg::largest_addr_t'(w_req_q.aw.addr), w_req_q.orig_aw_size) )) begin
slv_resp_o.w_ready = 1'b1;
end
end
endcase
if (w_state_q == W_SPLIT_INCR_DOWNSIZE) begin
if (w_req_q.aw.len == '0 && w_req_q.burst_len != '0) begin
w_req_d.aw_valid = 1'b1;
w_req_d.aw.len = (w_req_d.burst_len <= 255) ? w_req_d.burst_len : 255;
forward_b_beat_i = 1'b0;
forward_b_beat_push = 1'b1;
end
end
if (w_req_q.burst_len == 0) begin
w_state_d = W_IDLE;
forward_b_beat_push = 1'b1;
forward_b_beat_i = 1'b1;
end
end
end
default: ;
endcase
if (w_state_d == W_IDLE) begin
w_req_d.aw = '0 ;
w_req_d.aw_valid = 1'b0 ;
w_req_d.aw_throw_error = 1'b0 ;
w_req_d.burst_resp = axi_pkg::RESP_EXOKAY;
if (!forward_b_beat_full) begin
if (slv_req_i.aw_valid && slv_req_i.aw.atop[axi_pkg::ATOP_R_RESP]) begin
inject_aw_into_ar_req = 1'b1 ;
slv_resp_o.aw_ready = inject_aw_into_ar_gnt;
end else begin
slv_resp_o.aw_ready = 1'b1;
end
if (slv_req_i.aw_valid && slv_resp_o.aw_ready) begin
w_state_d = W_PASSTHROUGH;
w_req_d.aw = slv_req_i.aw ;
w_req_d.aw_valid = 1'b1 ;
w_req_d.burst_len = slv_req_i.aw.len ;
w_req_d.orig_aw_len = slv_req_i.aw.len ;
w_req_d.orig_aw_size = slv_req_i.aw.size ;
w_req_d.orig_aw_burst = slv_req_i.aw.burst;
case (slv_req_i.aw.burst)
axi_pkg::BURST_INCR: begin
automatic addr_t size_mask;
automatic addr_t conv_ratio;
automatic addr_t align_adj;
size_mask = (1 << slv_req_i.aw.size) - 1 ;
conv_ratio = ((1 << slv_req_i.aw.size) + AxiMstPortStrbWidth - 1) / AxiMstPortStrbWidth;
align_adj = (slv_req_i.aw.addr & size_mask & ~MstPortByteMask) / AxiMstPortStrbWidth;
w_req_d.burst_len = (slv_req_i.aw.len + 1) * conv_ratio - align_adj - 1 ;
if (conv_ratio != 1) begin
w_req_d.aw.size = AxiMstPortMaxSize;
if (w_req_d.burst_len <= 255) begin
w_state_d = W_INCR_DOWNSIZE ;
w_req_d.aw.len = w_req_d.burst_len;
end else begin
w_state_d = W_SPLIT_INCR_DOWNSIZE;
w_req_d.aw.len = 255 - align_adj ;
end
end
end
axi_pkg::BURST_FIXED: begin
if (slv_req_i.aw.len == '0) begin
automatic addr_t size_mask;
automatic addr_t conv_ratio;
automatic addr_t align_adj;
size_mask = (1 << slv_req_i.aw.size) - 1 ;
conv_ratio = ((1 << slv_req_i.aw.size) + AxiMstPortStrbWidth - 1) / AxiMstPortStrbWidth;
align_adj = (slv_req_i.aw.addr & size_mask & ~MstPortByteMask) / AxiMstPortStrbWidth;
w_req_d.burst_len = (conv_ratio >= align_adj + 1) ? (conv_ratio - align_adj - 1) : 0 ;
if (conv_ratio != 1) begin
w_state_d = W_INCR_DOWNSIZE ;
w_req_d.aw.len = w_req_d.burst_len ;
w_req_d.aw.size = AxiMstPortMaxSize ;
w_req_d.aw.burst = axi_pkg::BURST_INCR;
end
end else begin
w_req_d.aw_throw_error = 1'b1;
end
end
axi_pkg::BURST_WRAP: begin
w_state_d = W_PASSTHROUGH;
w_req_d.aw_throw_error = 1'b1 ;
end
default: ;
endcase
end
end
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
w_state_q <= W_IDLE;
w_req_q <= '0 ;
end else begin
w_state_q <= w_state_d;
w_req_q <= w_req_d ;
end
end
endmodule : axi_dw_downsizer
`begin_keywords "1800-2023"
module axi_dw_upsizer #(
parameter int unsigned AxiMaxReads = 1 ,
parameter int unsigned AxiSlvPortDataWidth = 8 ,
parameter int unsigned AxiMstPortDataWidth = 8 ,
parameter int unsigned AxiAddrWidth = 1 ,
parameter int unsigned AxiIdWidth = 1 ,
parameter type aw_chan_t = logic,
parameter type mst_w_chan_t = logic,
parameter type slv_w_chan_t = logic,
parameter type b_chan_t = logic,
parameter type ar_chan_t = logic,
parameter type mst_r_chan_t = logic,
parameter type slv_r_chan_t = logic,
parameter type axi_mst_req_t = logic,
parameter type axi_mst_resp_t = logic,
parameter type axi_slv_req_t = logic,
parameter type axi_slv_resp_t = logic
) (
input logic clk_i,
input logic rst_ni,
input axi_slv_req_t slv_req_i,
output axi_slv_resp_t slv_resp_o,
output axi_mst_req_t mst_req_o,
input axi_mst_resp_t mst_resp_i
);
import axi_pkg::aligned_addr;
import axi_pkg::beat_addr ;
import axi_pkg::modifiable ;
import cf_math_pkg::idx_width;
localparam TranIdWidth = AxiMaxReads > 1 ? $clog2(AxiMaxReads) : 1;
typedef logic [TranIdWidth-1:0] tran_id_t;
localparam AxiSlvPortStrbWidth = AxiSlvPortDataWidth / 8;
localparam AxiMstPortStrbWidth = AxiMstPortDataWidth / 8;
localparam AxiSlvPortMaxSize = $clog2(AxiSlvPortStrbWidth);
localparam AxiMstPortMaxSize = $clog2(AxiMstPortStrbWidth);
typedef logic [AxiMstPortStrbWidth-1:0][7:0] mst_data_t;
typedef logic [AxiSlvPortStrbWidth-1:0][7:0] slv_data_t;
typedef logic [AxiAddrWidth-1:0] addr_t;
typedef logic [AxiIdWidth-1:0] id_t;
typedef logic [$clog2(AxiMstPortStrbWidth/AxiSlvPortStrbWidth) + 7:0] burst_len_t;
axi_mst_req_t mst_req;
axi_mst_resp_t mst_resp;
slv_r_chan_t [AxiMaxReads-1:0] slv_r_tran;
logic [AxiMaxReads-1:0] slv_r_valid_tran;
logic [AxiMaxReads-1:0] slv_r_ready_tran;
rr_arb_tree #(
.NumIn (AxiMaxReads ),
.DataType (slv_r_chan_t),
.AxiVldRdy(1'b1 ),
.ExtPrio (1'b0 ),
.LockIn (1'b1 )
) i_slv_r_arb (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.flush_i(1'b0 ),
.rr_i ('0 ),
.req_i (slv_r_valid_tran ),
.gnt_o (slv_r_ready_tran ),
.data_i (slv_r_tran ),
.gnt_i (slv_req_i.r_ready ),
.req_o (slv_resp_o.r_valid),
.data_o (slv_resp_o.r ),
.idx_o ( )
);
logic [AxiMaxReads-1:0] mst_r_ready_tran;
assign mst_req.r_ready = |mst_r_ready_tran;
id_t arb_slv_ar_id;
logic arb_slv_ar_req;
logic arb_slv_ar_gnt;
logic [AxiMaxReads-1:0] arb_slv_ar_gnt_tran;
logic inject_aw_into_ar;
logic inject_aw_into_ar_req;
logic inject_aw_into_ar_gnt;
assign arb_slv_ar_gnt = |arb_slv_ar_gnt_tran;
rr_arb_tree #(
.NumIn (2 ),
.DataWidth (AxiIdWidth),
.ExtPrio (1'b0 ),
.AxiVldRdy (1'b1 ),
.LockIn (1'b0 )
) i_slv_ar_arb (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.flush_i(1'b0 ),
.rr_i ('0 ),
.req_i ({inject_aw_into_ar_req, slv_req_i.ar_valid} ),
.gnt_o ({inject_aw_into_ar_gnt, slv_resp_o.ar_ready}),
.data_i ({slv_req_i.aw.id, slv_req_i.ar.id} ),
.req_o (arb_slv_ar_req ),
.gnt_i (arb_slv_ar_gnt ),
.data_o (arb_slv_ar_id ),
.idx_o (inject_aw_into_ar )
);
ar_chan_t [AxiMaxReads-1:0] mst_ar_tran;
id_t [AxiMaxReads-1:0] mst_ar_id;
logic [AxiMaxReads-1:0] mst_ar_valid_tran;
logic [AxiMaxReads-1:0] mst_ar_ready_tran;
tran_id_t mst_req_idx;
rr_arb_tree #(
.NumIn (AxiMaxReads),
.DataType (ar_chan_t ),
.AxiVldRdy(1'b1 ),
.ExtPrio (1'b0 ),
.LockIn (1'b1 )
) i_mst_ar_arb (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.flush_i(1'b0 ),
.rr_i ('0 ),
.req_i (mst_ar_valid_tran),
.gnt_o (mst_ar_ready_tran),
.data_i (mst_ar_tran ),
.gnt_i (mst_resp.ar_ready),
.req_o (mst_req.ar_valid ),
.data_o (mst_req.ar ),
.idx_o (mst_req_idx )
);
axi_mst_req_t axi_err_req;
axi_mst_resp_t axi_err_resp;
axi_err_slv #(
.AxiIdWidth(AxiIdWidth ),
.Resp (axi_pkg::RESP_SLVERR),
.axi_req_t (axi_mst_req_t ),
.axi_resp_t(axi_mst_resp_t )
) i_axi_err_slv (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.test_i (1'b0 ),
.slv_req_i (axi_err_req ),
.slv_resp_o(axi_err_resp)
);
logic [AxiMaxReads-1:0] mst_req_ar_err;
logic mst_req_aw_err;
axi_demux #(
.AxiIdWidth (AxiIdWidth ),
.AxiLookBits(AxiIdWidth ),
.aw_chan_t (aw_chan_t ),
.w_chan_t (mst_w_chan_t ),
.b_chan_t (b_chan_t ),
.ar_chan_t (ar_chan_t ),
.r_chan_t (mst_r_chan_t ),
.axi_req_t (axi_mst_req_t ),
.axi_resp_t (axi_mst_resp_t),
.NoMstPorts (2 ),
.MaxTrans (AxiMaxReads ),
.SpillAw (1'b1 )
) i_axi_demux (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.test_i (1'b0 ),
.mst_reqs_o ({axi_err_req, mst_req_o} ),
.mst_resps_i ({axi_err_resp, mst_resp_i} ),
.slv_ar_select_i(mst_req_ar_err[mst_req_idx]),
.slv_aw_select_i(mst_req_aw_err ),
.slv_req_i (mst_req ),
.slv_resp_o (mst_resp )
);
typedef enum logic [1:0] {
R_IDLE ,
R_INJECT_AW ,
R_PASSTHROUGH,
R_INCR_UPSIZE
} r_state_e;
typedef struct packed {
aw_chan_t aw ;
logic aw_valid ;
logic aw_throw_error ;
mst_w_chan_t w ;
logic w_valid ;
axi_pkg::len_t burst_len ;
axi_pkg::size_t orig_aw_size;
} w_req_t;
w_req_t w_req_d, w_req_q;
logic [AxiMaxReads-1:0] idle_read_upsizer;
tran_id_t idx_ar_upsizer ;
tran_id_t idx_idle_upsizer;
lzc #(
.WIDTH(AxiMaxReads)
) i_idle_lzc (
.in_i (idle_read_upsizer),
.cnt_o (idx_idle_upsizer ),
.empty_o( )
);
logic [AxiMaxReads-1:0] id_clash_upsizer;
tran_id_t idx_id_clash_upsizer ;
for (genvar t = 0; t < AxiMaxReads; t++) begin: gen_id_clash
assign id_clash_upsizer[t] = arb_slv_ar_id == mst_ar_id[t] && !idle_read_upsizer[t];
end
onehot_to_bin #(
.ONEHOT_WIDTH(AxiMaxReads)
) i_id_clash_onehot_to_bin (
.onehot(id_clash_upsizer ),
.bin (idx_id_clash_upsizer)
);
assign idx_ar_upsizer = (|id_clash_upsizer) ? idx_id_clash_upsizer : idx_idle_upsizer;
logic r_upsizer_valid;
tran_id_t idx_r_upsizer;
logic [AxiMaxReads-1:0] rid_upsizer_match;
assign r_upsizer_valid = |rid_upsizer_match;
for (genvar t = 0; t < AxiMaxReads; t++) begin: gen_rid_match
assign rid_upsizer_match[t] = (mst_resp.r.id == mst_ar_id[t]) && !idle_read_upsizer[t];
end
onehot_to_bin #(
.ONEHOT_WIDTH(AxiMaxReads)
) i_rid_upsizer_lzc (
.onehot(rid_upsizer_match),
.bin (idx_r_upsizer )
);
typedef struct packed {
ar_chan_t ar ;
logic ar_valid ;
logic ar_throw_error ;
axi_pkg::len_t burst_len ;
axi_pkg::size_t orig_ar_size;
} r_req_t;
for (genvar t = 0; unsigned'(t) < AxiMaxReads; t++) begin: gen_read_upsizer
r_state_e r_state_d, r_state_q;
r_req_t r_req_d , r_req_q ;
assign idle_read_upsizer[t] = (r_state_q == R_IDLE) || (r_state_q == R_INJECT_AW);
slv_data_t r_data;
always_comb begin
r_state_d = r_state_q;
r_req_d = r_req_q ;
mst_ar_tran[t] = r_req_q.ar ;
mst_ar_id[t] = r_req_q.ar.id ;
mst_ar_valid_tran[t] = r_req_q.ar_valid;
mst_req_ar_err[t] = r_req_q.ar_throw_error;
slv_r_tran[t] = '0 ;
slv_r_tran[t].id = mst_resp.r.id ;
slv_r_tran[t].resp = mst_resp.r.resp;
slv_r_tran[t].user = mst_resp.r.user;
arb_slv_ar_gnt_tran[t] = 1'b0;
mst_r_ready_tran[t] = 1'b0;
slv_r_valid_tran[t] = 1'b0;
if (mst_ar_valid_tran[t] && mst_ar_ready_tran[t]) begin
r_req_d.ar_valid = 1'b0;
r_req_d.ar_throw_error = 1'b0;
end
r_data = '0;
unique case (r_state_q)
R_IDLE : begin
r_req_d.ar = '0;
if (arb_slv_ar_req && (idx_ar_upsizer == t)) begin
arb_slv_ar_gnt_tran[t] = 1'b1;
if (inject_aw_into_ar) begin
r_state_d = R_INJECT_AW;
end else begin
r_state_d = R_PASSTHROUGH;
r_req_d.ar = slv_req_i.ar ;
r_req_d.ar_valid = 1'b1 ;
r_req_d.burst_len = slv_req_i.ar.len ;
r_req_d.orig_ar_size = slv_req_i.ar.size;
unique case (r_req_d.ar.burst)
axi_pkg::BURST_INCR: begin
if (modifiable(r_req_d.ar.cache)) begin
if (r_req_d.ar.len != '0) begin
automatic addr_t start_addr;
automatic addr_t end_addr;
start_addr = aligned_addr(r_req_d.ar.addr, AxiMstPortMaxSize);
end_addr = aligned_addr(beat_addr(r_req_d.ar.addr,
r_req_d.orig_ar_size, r_req_d.burst_len, r_req_d.ar.burst,
r_req_d.burst_len), AxiMstPortMaxSize);
r_req_d.ar.len = (end_addr - start_addr) >> AxiMstPortMaxSize;
r_req_d.ar.size = AxiMstPortMaxSize ;
r_state_d = R_INCR_UPSIZE ;
end
end
end
axi_pkg::BURST_FIXED: begin
r_state_d = R_PASSTHROUGH;
end
axi_pkg::BURST_WRAP: begin
r_state_d = R_PASSTHROUGH;
r_req_d.ar_throw_error = 1'b1 ;
if (r_req_d.ar.len == '0)
r_req_d.ar_throw_error = 1'b0;
end
default: ;
endcase
end
end
end
R_INJECT_AW : begin
r_req_d.ar.id = w_req_q.aw.id ;
r_req_d.ar.addr = w_req_q.aw.addr ;
r_req_d.ar.size = w_req_q.orig_aw_size;
r_req_d.ar.burst = w_req_q.aw.burst ;
r_req_d.ar.len = w_req_q.burst_len ;
r_req_d.ar.lock = w_req_q.aw.lock ;
r_req_d.ar.cache = w_req_q.aw.cache ;
r_req_d.ar.prot = w_req_q.aw.prot ;
r_req_d.ar.qos = w_req_q.aw.qos ;
r_req_d.ar.region = w_req_q.aw.region ;
r_req_d.ar.user = w_req_q.aw.user ;
r_req_d.ar_valid = 1'b0 ;
r_req_d.burst_len = w_req_q.burst_len ;
r_req_d.orig_ar_size = w_req_q.orig_aw_size;
r_state_d = R_PASSTHROUGH;
unique case (r_req_d.ar.burst)
axi_pkg::BURST_INCR: begin
if (modifiable(r_req_d.ar.cache)) begin
if (r_req_d.ar.len != '0) begin
automatic addr_t start_addr;
automatic addr_t end_addr;
start_addr = aligned_addr(r_req_d.ar.addr, AxiMstPortMaxSize);
end_addr = aligned_addr(beat_addr(r_req_d.ar.addr,
r_req_d.orig_ar_size, r_req_d.burst_len, r_req_d.ar.burst,
r_req_d.burst_len), AxiMstPortMaxSize);
r_req_d.ar.len = (end_addr - start_addr) >> AxiMstPortMaxSize;
r_req_d.ar.size = AxiMstPortMaxSize ;
r_state_d = R_INCR_UPSIZE ;
end
end
end
axi_pkg::BURST_FIXED: begin
r_state_d = R_PASSTHROUGH;
end
axi_pkg::BURST_WRAP: begin
r_state_d = R_PASSTHROUGH;
r_req_d.ar_throw_error = 1'b1 ;
if (r_req_d.ar.len == '0)
r_req_d.ar_throw_error = 1'b0;
end
default: ;
endcase
end
R_PASSTHROUGH, R_INCR_UPSIZE: begin
if (!r_req_q.ar_valid)
if (mst_resp.r_valid && (idx_r_upsizer == t) && r_upsizer_valid) begin
automatic logic [idx_width(AxiMstPortStrbWidth)-1:0] mst_port_offset;
automatic logic [idx_width(AxiSlvPortStrbWidth)-1:0] slv_port_offset;
mst_port_offset = AxiMstPortStrbWidth == 1 ? '0 : r_req_q.ar.addr[idx_width(AxiMstPortStrbWidth)-1:0];
slv_port_offset = AxiSlvPortStrbWidth == 1 ? '0 : r_req_q.ar.addr[idx_width(AxiSlvPortStrbWidth)-1:0];
slv_r_valid_tran[t] = 1'b1 ;
slv_r_tran[t].last = mst_resp.r.last && (r_req_q.burst_len == 0);
for (int b = 0; b < AxiMstPortStrbWidth; b++) begin
if ((b >= mst_port_offset) &&
(b - mst_port_offset < (1 << r_req_q.orig_ar_size)) &&
(b + slv_port_offset - mst_port_offset < AxiSlvPortStrbWidth)) begin
r_data[b + slv_port_offset - mst_port_offset] = mst_resp.r.data[8*b +: 8];
end
end
slv_r_tran[t].data = r_data;
if (slv_r_ready_tran[t]) begin
r_req_d.burst_len = r_req_q.burst_len - 1;
unique case (r_req_q.ar.burst)
axi_pkg::BURST_INCR: begin
r_req_d.ar.addr = aligned_addr(r_req_q.ar.addr, r_req_q.orig_ar_size) + (1 << r_req_q.orig_ar_size);
end
axi_pkg::BURST_FIXED: begin
r_req_d.ar.addr = r_req_q.ar.addr;
end
default: ;
endcase
unique case (r_state_q)
R_PASSTHROUGH:
mst_r_ready_tran[t] = 1'b1;
R_INCR_UPSIZE:
if (r_req_q.burst_len == 0 || (aligned_addr(r_req_d.ar.addr, AxiMstPortMaxSize) != aligned_addr(r_req_q.ar.addr, AxiMstPortMaxSize)))
mst_r_ready_tran[t] = 1'b1;
default: ;
endcase
if (r_req_q.burst_len == '0)
r_state_d = R_IDLE;
end
end
end
default: ;
endcase
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
r_state_q <= R_IDLE;
r_req_q <= '0 ;
end else begin
r_state_q <= r_state_d;
r_req_q <= r_req_d ;
end
end
end : gen_read_upsizer
typedef enum logic [1:0] {
W_IDLE ,
W_PASSTHROUGH,
W_INCR_UPSIZE
} w_state_e;
w_state_e w_state_d, w_state_q;
mst_data_t w_data;
always_comb begin
inject_aw_into_ar_req = 1'b0;
w_state_d = w_state_q;
w_req_d = w_req_q ;
mst_req.aw = w_req_q.aw ;
mst_req.aw_valid = w_req_q.aw_valid;
slv_resp_o.aw_ready = '0 ;
mst_req_aw_err = w_req_q.aw_throw_error;
mst_req.w = w_req_q.w ;
mst_req.w_valid = w_req_q.w_valid;
slv_resp_o.w_ready = '0 ;
w_data = w_req_q.w.data;
slv_resp_o.b = mst_resp.b ;
slv_resp_o.b_valid = mst_resp.b_valid ;
mst_req.b_ready = slv_req_i.b_ready;
if (mst_req.aw_valid && mst_resp.aw_ready) begin
w_req_d.aw_valid = 1'b0;
w_req_d.aw_throw_error = 1'b0;
end
unique case (w_state_q)
W_PASSTHROUGH, W_INCR_UPSIZE: begin
if (mst_req.w_valid && mst_resp.w_ready) begin
w_data = '0 ;
w_req_d.w = '0 ;
w_req_d.w_valid = 1'b0;
end
if (!w_req_q.aw_valid) begin
slv_resp_o.w_ready = ~mst_req.w_valid || mst_resp.w_ready;
if (slv_req_i.w_valid && slv_resp_o.w_ready) begin
automatic addr_t mst_port_offset;
automatic addr_t slv_port_offset;
mst_port_offset = AxiMstPortStrbWidth == 1 ? '0 : w_req_q.aw.addr[idx_width(AxiMstPortStrbWidth)-1:0];
slv_port_offset = AxiSlvPortStrbWidth == 1 ? '0 : w_req_q.aw.addr[idx_width(AxiSlvPortStrbWidth)-1:0];
for (int b = 0; b < AxiMstPortStrbWidth; b++)
if ((b >= mst_port_offset) &&
(b - mst_port_offset < (1 << w_req_q.orig_aw_size)) &&
(b + slv_port_offset - mst_port_offset < AxiSlvPortStrbWidth)) begin
w_data[b] = slv_req_i.w.data[8*(b + slv_port_offset - mst_port_offset) +: 8];
w_req_d.w.strb[b] = slv_req_i.w.strb[b + slv_port_offset - mst_port_offset] ;
end
w_req_d.burst_len = w_req_q.burst_len - 1 ;
w_req_d.w.data = w_data ;
w_req_d.w.last = (w_req_q.burst_len == 0);
w_req_d.w.user = slv_req_i.w.user ;
unique case (w_req_q.aw.burst)
axi_pkg::BURST_INCR: begin
w_req_d.aw.addr = aligned_addr(w_req_q.aw.addr, w_req_q.orig_aw_size) + (1 << w_req_q.orig_aw_size);
end
axi_pkg::BURST_FIXED: begin
w_req_d.aw.addr = w_req_q.aw.addr;
end
default: ;
endcase
unique case (w_state_q)
W_PASSTHROUGH:
w_req_d.w_valid = 1'b1;
W_INCR_UPSIZE:
if (w_req_q.burst_len == 0 || (aligned_addr(w_req_d.aw.addr, AxiMstPortMaxSize) != aligned_addr(w_req_q.aw.addr, AxiMstPortMaxSize)))
w_req_d.w_valid = 1'b1;
default: ;
endcase
end
end
if (mst_req.w_valid && mst_resp.w_ready)
if (w_req_q.burst_len == '1) begin
slv_resp_o.w_ready = 1'b0 ;
w_state_d = W_IDLE;
end
end
default: ;
endcase
if (w_state_d == W_IDLE) begin
w_req_d.aw = '0 ;
w_req_d.aw_valid = 1'b0;
w_req_d.aw_throw_error = 1'b0;
w_req_d.w = '0 ;
w_req_d.w_valid = 1'b0;
if (slv_req_i.aw_valid && slv_req_i.aw.atop[axi_pkg::ATOP_R_RESP]) begin
inject_aw_into_ar_req = 1'b1 ;
slv_resp_o.aw_ready = inject_aw_into_ar_gnt;
end else begin
slv_resp_o.aw_ready = 1'b1;
end
if (slv_req_i.aw_valid & slv_resp_o.aw_ready) begin
w_state_d = W_PASSTHROUGH;
w_req_d.aw = slv_req_i.aw;
w_req_d.aw_valid = 1'b1 ;
w_req_d.burst_len = slv_req_i.aw.len ;
w_req_d.orig_aw_size = slv_req_i.aw.size;
unique case (slv_req_i.aw.burst)
axi_pkg::BURST_INCR: begin
if (modifiable(slv_req_i.aw.cache))
if (slv_req_i.aw.len != '0) begin
automatic addr_t start_addr;
automatic addr_t end_addr;
start_addr = aligned_addr(slv_req_i.aw.addr, AxiMstPortMaxSize);
end_addr = aligned_addr(beat_addr(slv_req_i.aw.addr,
slv_req_i.aw.size, slv_req_i.aw.len, slv_req_i.aw.burst, slv_req_i.aw.len),
AxiMstPortMaxSize);
w_req_d.aw.len = (end_addr - start_addr) >> AxiMstPortMaxSize;
w_req_d.aw.size = AxiMstPortMaxSize ;
w_state_d = W_INCR_UPSIZE ;
end
end
axi_pkg::BURST_FIXED: begin
w_state_d = W_PASSTHROUGH;
end
axi_pkg::BURST_WRAP: begin
w_state_d = W_PASSTHROUGH;
w_req_d.aw_throw_error = 1'b1 ;
if (slv_req_i.aw.len == '0)
w_req_d.aw_throw_error = 1'b0;
end
default: ;
endcase
end
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
w_state_q <= W_IDLE;
w_req_q <= '0 ;
end else begin
w_state_q <= w_state_d;
w_req_q <= w_req_d ;
end
end
endmodule : axi_dw_upsizer
`begin_keywords "1800-2023"
module axi_fifo #(
parameter int unsigned Depth = 32'd1,
parameter bit FallThrough = 1'b0,
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
) (
input logic clk_i,
input logic rst_ni,
input logic test_i,
input axi_req_t slv_req_i,
output axi_resp_t slv_resp_o,
output axi_req_t mst_req_o,
input axi_resp_t mst_resp_i
);
if (Depth == '0) begin : gen_no_fifo
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;
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
endmodule
module axi_fifo_intf #(
parameter int unsigned ADDR_WIDTH = 0,
parameter int unsigned DATA_WIDTH = 0,
parameter int unsigned ID_WIDTH = 0,
parameter int unsigned USER_WIDTH = 0,
parameter int unsigned DEPTH = 0,
parameter int unsigned FALL_THROUGH = 0
) (
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;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_pkg::atop_t atop;
user_t user;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
logic last;
user_t user;
} w_chan_t;
typedef struct packed {
id_t id;
axi_pkg::resp_t resp;
user_t user;
} b_chan_t;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
user_t user;
} ar_chan_t;
typedef struct packed {
id_t id;
data_t data;
axi_pkg::resp_t resp;
logic last;
user_t user;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} axi_req_t;
typedef struct packed {
logic aw_ready;
logic ar_ready;
logic w_ready;
logic b_valid;
b_chan_t b;
logic r_valid;
r_chan_t r;
} axi_resp_t;
axi_req_t slv_req, mst_req;
axi_resp_t slv_resp, mst_resp;
assign slv_req.aw.id = slv.aw_id;
assign slv_req.aw.addr = slv.aw_addr;
assign slv_req.aw.len = slv.aw_len;
assign slv_req.aw.size = slv.aw_size;
assign slv_req.aw.burst = slv.aw_burst;
assign slv_req.aw.lock = slv.aw_lock;
assign slv_req.aw.cache = slv.aw_cache;
assign slv_req.aw.prot = slv.aw_prot;
assign slv_req.aw.qos = slv.aw_qos;
assign slv_req.aw.region = slv.aw_region;
assign slv_req.aw.atop = slv.aw_atop;
assign slv_req.aw.user = slv.aw_user;
assign slv_req.aw_valid = slv.aw_valid;
assign slv_req.w.data = slv.w_data;
assign slv_req.w.strb = slv.w_strb;
assign slv_req.w.last = slv.w_last;
assign slv_req.w.user = slv.w_user;
assign slv_req.w_valid = slv.w_valid;
assign slv_req.b_ready = slv.b_ready;
assign slv_req.ar.id = slv.ar_id;
assign slv_req.ar.addr = slv.ar_addr;
assign slv_req.ar.len = slv.ar_len;
assign slv_req.ar.size = slv.ar_size;
assign slv_req.ar.burst = slv.ar_burst;
assign slv_req.ar.lock = slv.ar_lock;
assign slv_req.ar.cache = slv.ar_cache;
assign slv_req.ar.prot = slv.ar_prot;
assign slv_req.ar.qos = slv.ar_qos;
assign slv_req.ar.region = slv.ar_region;
assign slv_req.ar.user = slv.ar_user;
assign slv_req.ar_valid = slv.ar_valid;
assign slv_req.r_ready = slv.r_ready;
assign slv.aw_ready = slv_resp.aw_ready;
assign slv.ar_ready = slv_resp.ar_ready;
assign slv.w_ready = slv_resp.w_ready;
assign slv.b_valid = slv_resp.b_valid;
assign slv.b_id = slv_resp.b.id;
assign slv.b_resp = slv_resp.b.resp;
assign slv.b_user = slv_resp.b.user;
assign slv.r_valid = slv_resp.r_valid;
assign slv.r_id = slv_resp.r.id;
assign slv.r_data = slv_resp.r.data;
assign slv.r_resp = slv_resp.r.resp;
assign slv.r_last = slv_resp.r.last;
assign slv.r_user = slv_resp.r.user;
assign mst.aw_id = mst_req.aw.id;
assign mst.aw_addr = mst_req.aw.addr;
assign mst.aw_len = mst_req.aw.len;
assign mst.aw_size = mst_req.aw.size;
assign mst.aw_burst = mst_req.aw.burst;
assign mst.aw_lock = mst_req.aw.lock;
assign mst.aw_cache = mst_req.aw.cache;
assign mst.aw_prot = mst_req.aw.prot;
assign mst.aw_qos = mst_req.aw.qos;
assign mst.aw_region = mst_req.aw.region;
assign mst.aw_atop = mst_req.aw.atop;
assign mst.aw_user = mst_req.aw.user;
assign mst.aw_valid = mst_req.aw_valid;
assign mst.w_data = mst_req.w.data;
assign mst.w_strb = mst_req.w.strb;
assign mst.w_last = mst_req.w.last;
assign mst.w_user = mst_req.w.user;
assign mst.w_valid = mst_req.w_valid;
assign mst.b_ready = mst_req.b_ready;
assign mst.ar_id = mst_req.ar.id;
assign mst.ar_addr = mst_req.ar.addr;
assign mst.ar_len = mst_req.ar.len;
assign mst.ar_size = mst_req.ar.size;
assign mst.ar_burst = mst_req.ar.burst;
assign mst.ar_lock = mst_req.ar.lock;
assign mst.ar_cache = mst_req.ar.cache;
assign mst.ar_prot = mst_req.ar.prot;
assign mst.ar_qos = mst_req.ar.qos;
assign mst.ar_region = mst_req.ar.region;
assign mst.ar_user = mst_req.ar.user;
assign mst.ar_valid = mst_req.ar_valid;
assign mst.r_ready = mst_req.r_ready;
assign mst_resp.aw_ready = mst.aw_ready;
assign mst_resp.ar_ready = mst.ar_ready;
assign mst_resp.w_ready = mst.w_ready;
assign mst_resp.b_valid = mst.b_valid;
assign mst_resp.b.id = mst.b_id;
assign mst_resp.b.resp = mst.b_resp;
assign mst_resp.b.user = mst.b_user;
assign mst_resp.r_valid = mst.r_valid;
assign mst_resp.r.id = mst.r_id;
assign mst_resp.r.data = mst.r_data;
assign mst_resp.r.resp = mst.r_resp;
assign mst_resp.r.last = mst.r_last;
assign mst_resp.r.user = mst.r_user;
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)
);
endmodule
`begin_keywords "1800-2023"
module axi_fifo_delay_dyn #(
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,
parameter int unsigned DepthAR = 4,
parameter int unsigned DepthAW = 4,
parameter int unsigned DepthR = 4,
parameter int unsigned DepthW = 4,
parameter int unsigned DepthB = 4,
parameter int unsigned MaxDelay = 1024,
localparam int unsigned DelayWidth = $clog2(MaxDelay) + 1
) (
input logic clk_i,
input logic rst_ni,
input logic [DelayWidth-1:0] aw_delay_i,
input logic [DelayWidth-1:0] w_delay_i,
input logic [DelayWidth-1:0] b_delay_i,
input logic [DelayWidth-1:0] ar_delay_i,
input logic [DelayWidth-1:0] r_delay_i,
input axi_req_t slv_req_i,
output axi_resp_t slv_resp_o,
output axi_req_t mst_req_o,
input axi_resp_t mst_resp_i
);
if (DepthAR > 0) begin
stream_fifo_delay_dyn #(
.payload_t ( ar_chan_t ),
.MaxDelay ( MaxDelay ),
.Depth ( DepthAR )
) i_ar_fifo_delay (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.delay_i ( ar_delay_i ),
.payload_i ( slv_req_i.ar ),
.ready_o ( slv_resp_o.ar_ready ),
.valid_i ( slv_req_i.ar_valid ),
.payload_o ( mst_req_o.ar ),
.ready_i ( mst_resp_i.ar_ready ),
.valid_o ( mst_req_o.ar_valid )
);
end else begin
assign mst_req_o.ar = slv_req_i.ar;
assign mst_req_o.ar_valid = slv_req_i.ar_valid;
assign slv_resp_o.ar_ready = mst_resp_i.ar_ready;
end
if (DepthAW > 0) begin
stream_fifo_delay_dyn #(
.payload_t ( aw_chan_t ),
.MaxDelay ( MaxDelay ),
.Depth ( DepthAW )
) i_aw_fifo_delay (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.delay_i ( aw_delay_i ),
.payload_i ( slv_req_i.aw ),
.ready_o ( slv_resp_o.aw_ready ),
.valid_i ( slv_req_i.aw_valid ),
.payload_o ( mst_req_o.aw ),
.ready_i ( mst_resp_i.aw_ready ),
.valid_o ( mst_req_o.aw_valid )
);
end else begin
assign mst_req_o.aw = slv_req_i.aw;
assign mst_req_o.aw_valid = slv_req_i.aw_valid;
assign slv_resp_o.aw_ready = mst_resp_i.aw_ready;
end
if (DepthR > 0) begin
stream_fifo_delay_dyn #(
.payload_t ( r_chan_t ),
.MaxDelay ( MaxDelay ),
.Depth ( DepthR )
) i_r_fifo_delay (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.delay_i ( r_delay_i ),
.payload_i ( mst_resp_i.r ),
.ready_o ( mst_req_o.r_ready ),
.valid_i ( mst_resp_i.r_valid ),
.payload_o ( slv_resp_o.r ),
.ready_i ( slv_req_i.r_ready ),
.valid_o ( slv_resp_o.r_valid )
);
end else begin
assign mst_req_o.r_ready = slv_req_i.r_ready;
assign slv_resp_o.r_valid = mst_resp_i.r_valid;
assign slv_resp_o.r = mst_resp_i.r;
end
if (DepthW > 0) begin
stream_fifo_delay_dyn #(
.payload_t ( w_chan_t ),
.MaxDelay ( MaxDelay ),
.Depth ( DepthW )
) i_w_fifo_delay (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.delay_i ( w_delay_i ),
.payload_i ( slv_req_i.w ),
.ready_o ( slv_resp_o.w_ready ),
.valid_i ( slv_req_i.w_valid ),
.payload_o ( mst_req_o.w ),
.ready_i ( mst_resp_i.w_ready ),
.valid_o ( mst_req_o.w_valid )
);
end else begin
assign mst_req_o.w = slv_req_i.w;
assign mst_req_o.w_valid = slv_req_i.w_valid;
assign slv_resp_o.w_ready = mst_resp_i.w_ready;
end
if (DepthB > 0) begin
stream_fifo_delay_dyn #(
.payload_t ( b_chan_t ),
.MaxDelay ( MaxDelay ),
.Depth ( DepthB )
) i_b_fifo_delay (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.delay_i ( b_delay_i ),
.payload_i ( mst_resp_i.b ),
.ready_o ( mst_req_o.b_ready ),
.valid_i ( mst_resp_i.b_valid ),
.payload_o ( slv_resp_o.b ),
.ready_i ( slv_req_i.b_ready ),
.valid_o ( slv_resp_o.b_valid )
);
end else begin
assign mst_req_o.b_ready = slv_req_i.b_ready;
assign slv_resp_o.b = mst_resp_i.b;
assign slv_resp_o.b_valid = mst_resp_i.b_valid;
end
endmodule
module axi_fifo_delay_dyn_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,
parameter int unsigned DEPTH_AR = 4,
parameter int unsigned DEPTH_AW = 4,
parameter int unsigned DEPTH_R = 4,
parameter int unsigned DEPTH_W = 4,
parameter int unsigned DEPTH_B = 4,
parameter int unsigned MAX_DELAY = 0,
parameter int unsigned DELAY_WIDTH = $clog2(MAX_DELAY) + 1
) (
input logic clk_i,
input logic rst_ni,
input logic [DELAY_WIDTH-1:0] aw_delay_i,
input logic [DELAY_WIDTH-1:0] w_delay_i,
input logic [DELAY_WIDTH-1:0] b_delay_i,
input logic [DELAY_WIDTH-1:0] ar_delay_i,
input logic [DELAY_WIDTH-1:0] r_delay_i,
AXI_BUS.Slave slv,
AXI_BUS.Master mst
);
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;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_pkg::atop_t atop;
user_t user;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
logic last;
user_t user;
} w_chan_t;
typedef struct packed {
id_t id;
axi_pkg::resp_t resp;
user_t user;
} b_chan_t;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
user_t user;
} ar_chan_t;
typedef struct packed {
id_t id;
data_t data;
axi_pkg::resp_t resp;
logic last;
user_t user;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} axi_req_t;
typedef struct packed {
logic aw_ready;
logic ar_ready;
logic w_ready;
logic b_valid;
b_chan_t b;
logic r_valid;
r_chan_t r;
} axi_resp_t;
axi_req_t slv_req, mst_req;
axi_resp_t slv_resp, mst_resp;
assign slv_req.aw.id = slv.aw_id;
assign slv_req.aw.addr = slv.aw_addr;
assign slv_req.aw.len = slv.aw_len;
assign slv_req.aw.size = slv.aw_size;
assign slv_req.aw.burst = slv.aw_burst;
assign slv_req.aw.lock = slv.aw_lock;
assign slv_req.aw.cache = slv.aw_cache;
assign slv_req.aw.prot = slv.aw_prot;
assign slv_req.aw.qos = slv.aw_qos;
assign slv_req.aw.region = slv.aw_region;
assign slv_req.aw.atop = slv.aw_atop;
assign slv_req.aw.user = slv.aw_user;
assign slv_req.aw_valid = slv.aw_valid;
assign slv_req.w.data = slv.w_data;
assign slv_req.w.strb = slv.w_strb;
assign slv_req.w.last = slv.w_last;
assign slv_req.w.user = slv.w_user;
assign slv_req.w_valid = slv.w_valid;
assign slv_req.b_ready = slv.b_ready;
assign slv_req.ar.id = slv.ar_id;
assign slv_req.ar.addr = slv.ar_addr;
assign slv_req.ar.len = slv.ar_len;
assign slv_req.ar.size = slv.ar_size;
assign slv_req.ar.burst = slv.ar_burst;
assign slv_req.ar.lock = slv.ar_lock;
assign slv_req.ar.cache = slv.ar_cache;
assign slv_req.ar.prot = slv.ar_prot;
assign slv_req.ar.qos = slv.ar_qos;
assign slv_req.ar.region = slv.ar_region;
assign slv_req.ar.user = slv.ar_user;
assign slv_req.ar_valid = slv.ar_valid;
assign slv_req.r_ready = slv.r_ready;
assign slv.aw_ready = slv_resp.aw_ready;
assign slv.ar_ready = slv_resp.ar_ready;
assign slv.w_ready = slv_resp.w_ready;
assign slv.b_valid = slv_resp.b_valid;
assign slv.b_id = slv_resp.b.id;
assign slv.b_resp = slv_resp.b.resp;
assign slv.b_user = slv_resp.b.user;
assign slv.r_valid = slv_resp.r_valid;
assign slv.r_id = slv_resp.r.id;
assign slv.r_data = slv_resp.r.data;
assign slv.r_resp = slv_resp.r.resp;
assign slv.r_last = slv_resp.r.last;
assign slv.r_user = slv_resp.r.user;
assign mst.aw_id = mst_req.aw.id;
assign mst.aw_addr = mst_req.aw.addr;
assign mst.aw_len = mst_req.aw.len;
assign mst.aw_size = mst_req.aw.size;
assign mst.aw_burst = mst_req.aw.burst;
assign mst.aw_lock = mst_req.aw.lock;
assign mst.aw_cache = mst_req.aw.cache;
assign mst.aw_prot = mst_req.aw.prot;
assign mst.aw_qos = mst_req.aw.qos;
assign mst.aw_region = mst_req.aw.region;
assign mst.aw_atop = mst_req.aw.atop;
assign mst.aw_user = mst_req.aw.user;
assign mst.aw_valid = mst_req.aw_valid;
assign mst.w_data = mst_req.w.data;
assign mst.w_strb = mst_req.w.strb;
assign mst.w_last = mst_req.w.last;
assign mst.w_user = mst_req.w.user;
assign mst.w_valid = mst_req.w_valid;
assign mst.b_ready = mst_req.b_ready;
assign mst.ar_id = mst_req.ar.id;
assign mst.ar_addr = mst_req.ar.addr;
assign mst.ar_len = mst_req.ar.len;
assign mst.ar_size = mst_req.ar.size;
assign mst.ar_burst = mst_req.ar.burst;
assign mst.ar_lock = mst_req.ar.lock;
assign mst.ar_cache = mst_req.ar.cache;
assign mst.ar_prot = mst_req.ar.prot;
assign mst.ar_qos = mst_req.ar.qos;
assign mst.ar_region = mst_req.ar.region;
assign mst.ar_user = mst_req.ar.user;
assign mst.ar_valid = mst_req.ar_valid;
assign mst.r_ready = mst_req.r_ready;
assign mst_resp.aw_ready = mst.aw_ready;
assign mst_resp.ar_ready = mst.ar_ready;
assign mst_resp.w_ready = mst.w_ready;
assign mst_resp.b_valid = mst.b_valid;
assign mst_resp.b.id = mst.b_id;
assign mst_resp.b.resp = mst.b_resp;
assign mst_resp.b.user = mst.b_user;
assign mst_resp.r_valid = mst.r_valid;
assign mst_resp.r.id = mst.r_id;
assign mst_resp.r.data = mst.r_data;
assign mst_resp.r.resp = mst.r_resp;
assign mst_resp.r.last = mst.r_last;
assign mst_resp.r.user = mst.r_user;
axi_fifo_delay_dyn #(
.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 ),
.DepthAR ( DEPTH_AR ),
.DepthAW ( DEPTH_AW ),
.DepthR ( DEPTH_R ),
.DepthW ( DEPTH_W ),
.DepthB ( DEPTH_B ),
.MaxDelay ( MAX_DELAY )
) i_axi_fifo_delay_dyn (
.clk_i,
.rst_ni,
.aw_delay_i ( aw_delay_i ),
.w_delay_i ( w_delay_i ),
.b_delay_i ( b_delay_i ),
.ar_delay_i ( ar_delay_i ),
.r_delay_i ( r_delay_i ),
.slv_req_i ( slv_req ),
.slv_resp_o ( slv_resp ),
.mst_req_o ( mst_req ),
.mst_resp_i ( mst_resp )
);
endmodule
module stream_fifo_delay_dyn #(
parameter type payload_t = logic,
parameter int unsigned MaxDelay = 1024,
parameter int unsigned Depth = 4,
parameter int unsigned CounterWidth = $clog2(MaxDelay) + 1
)(
input logic clk_i,
input logic rst_ni,
input logic [CounterWidth-1:0] delay_i,
input payload_t payload_i,
output logic ready_o,
input logic valid_i,
output payload_t payload_o,
input logic ready_i,
output logic valid_o
);
if (Depth & (Depth - 1) == 0)
$fatal(1, "Depth must be a power of two");
localparam int unsigned BookeepingBits = $clog2(Depth) + 1;
logic [BookeepingBits-1:0] ready_count_d, ready_count_q;
logic [CounterWidth-1:0] count_val;
logic [CounterWidth-1:0] head_deadline;
logic [CounterWidth-1:0] tail_deadline;
payload_t head_data;
logic fifo_dead_full, fifo_dead_empty, fifo_dead_push, fifo_dead_pop;
logic fifo_data_full, fifo_data_empty, fifo_data_push, fifo_data_pop;
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
ready_count_q <= ('0);
end else begin
ready_count_q <= (ready_count_d);
end
end
always_comb begin
ready_count_d = ready_count_q;
if (fifo_dead_pop)
ready_count_d += 1;
if (fifo_data_pop)
ready_count_d -= 1;
end
assign tail_deadline = count_val + delay_i + 1;
assign fifo_data_push = ~fifo_data_full & valid_i;
assign fifo_dead_push = fifo_data_push;
assign fifo_dead_pop = (count_val == head_deadline) & ~fifo_dead_empty;
assign fifo_data_pop = valid_o & ready_i;
assign valid_o = (ready_count_q > 0);
assign ready_o = ~fifo_data_full;
assign payload_o = head_data;
counter #(
.WIDTH ( CounterWidth )
) i_counter (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.clear_i ( 1'b0 ),
.en_i ( 1'b1 ),
.load_i ( 1'b0 ),
.down_i ( 1'b0 ),
.d_i ( '0 ),
.q_o ( count_val ),
.overflow_o ( )
);
fifo_v3 #(
.DATA_WIDTH ( $bits(payload_t) ),
.DEPTH ( Depth ),
.FALL_THROUGH ( 1'b0 )
) data_fifo (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.data_i ( payload_i ),
.push_i ( fifo_data_push ),
.full_o ( fifo_data_full ),
.data_o ( head_data ),
.pop_i ( fifo_data_pop ),
.empty_o ( fifo_data_empty ),
.usage_o ( )
);
fifo_v3 #(
.DATA_WIDTH ( CounterWidth ),
.DEPTH ( Depth ),
.FALL_THROUGH ( 1'b0 )
) deadline_fifo (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.data_i ( tail_deadline ),
.push_i ( fifo_dead_push ),
.full_o ( fifo_dead_full ),
.data_o ( head_deadline ),
.pop_i ( fifo_dead_pop ),
.empty_o ( fifo_dead_empty ),
.usage_o ( )
);
endmodule
`begin_keywords "1800-2023"
module axi_id_remap #(
parameter int unsigned AxiSlvPortIdWidth = 32'd0,
parameter int unsigned AxiSlvPortMaxUniqIds = 32'd0,
parameter int unsigned AxiMaxTxnsPerId = 32'd0,
parameter int unsigned AxiMstPortIdWidth = 32'd0,
parameter type slv_req_t = logic,
parameter type slv_resp_t = logic,
parameter type mst_req_t = logic,
parameter type mst_resp_t = logic
) (
input logic clk_i,
input logic rst_ni,
input slv_req_t slv_req_i,
output slv_resp_t slv_resp_o,
output mst_req_t mst_req_o,
input mst_resp_t mst_resp_i
);
assign mst_req_o.aw.addr = slv_req_i.aw.addr;
assign mst_req_o.aw.len = slv_req_i.aw.len;
assign mst_req_o.aw.size = slv_req_i.aw.size;
assign mst_req_o.aw.burst = slv_req_i.aw.burst;
assign mst_req_o.aw.lock = slv_req_i.aw.lock;
assign mst_req_o.aw.cache = slv_req_i.aw.cache;
assign mst_req_o.aw.prot = slv_req_i.aw.prot;
assign mst_req_o.aw.qos = slv_req_i.aw.qos;
assign mst_req_o.aw.region = slv_req_i.aw.region;
assign mst_req_o.aw.atop = slv_req_i.aw.atop;
assign mst_req_o.aw.user = slv_req_i.aw.user;
assign mst_req_o.w = slv_req_i.w;
assign mst_req_o.w_valid = slv_req_i.w_valid;
assign slv_resp_o.w_ready = mst_resp_i.w_ready;
assign slv_resp_o.b.resp = mst_resp_i.b.resp;
assign slv_resp_o.b.user = mst_resp_i.b.user;
assign slv_resp_o.b_valid = mst_resp_i.b_valid;
assign mst_req_o.b_ready = slv_req_i.b_ready;
assign mst_req_o.ar.addr = slv_req_i.ar.addr;
assign mst_req_o.ar.len = slv_req_i.ar.len;
assign mst_req_o.ar.size = slv_req_i.ar.size;
assign mst_req_o.ar.burst = slv_req_i.ar.burst;
assign mst_req_o.ar.lock = slv_req_i.ar.lock;
assign mst_req_o.ar.cache = slv_req_i.ar.cache;
assign mst_req_o.ar.prot = slv_req_i.ar.prot;
assign mst_req_o.ar.qos = slv_req_i.ar.qos;
assign mst_req_o.ar.region = slv_req_i.ar.region;
assign mst_req_o.ar.user = slv_req_i.ar.user;
assign slv_resp_o.r.data = mst_resp_i.r.data;
assign slv_resp_o.r.resp = mst_resp_i.r.resp;
assign slv_resp_o.r.last = mst_resp_i.r.last;
assign slv_resp_o.r.user = mst_resp_i.r.user;
assign slv_resp_o.r_valid = mst_resp_i.r_valid;
assign mst_req_o.r_ready = slv_req_i.r_ready;
localparam int unsigned IdxWidth = cf_math_pkg::idx_width(AxiSlvPortMaxUniqIds);
typedef logic [AxiSlvPortMaxUniqIds-1:0] field_t;
typedef logic [AxiSlvPortIdWidth-1:0] id_inp_t;
typedef logic [IdxWidth-1:0] idx_t;
field_t wr_free, rd_free, both_free;
id_inp_t rd_push_inp_id;
idx_t wr_free_oup_id, rd_free_oup_id, both_free_oup_id,
wr_push_oup_id, rd_push_oup_id,
wr_exists_id, rd_exists_id;
logic wr_exists, rd_exists,
wr_exists_full, rd_exists_full,
wr_full, rd_full,
wr_push, rd_push;
axi_id_remap_table #(
.InpIdWidth ( AxiSlvPortIdWidth ),
.MaxUniqInpIds ( AxiSlvPortMaxUniqIds ),
.MaxTxnsPerId ( AxiMaxTxnsPerId )
) i_wr_table (
.clk_i,
.rst_ni,
.free_o ( wr_free ),
.free_oup_id_o ( wr_free_oup_id ),
.full_o ( wr_full ),
.push_i ( wr_push ),
.push_inp_id_i ( slv_req_i.aw.id ),
.push_oup_id_i ( wr_push_oup_id ),
.exists_inp_id_i ( slv_req_i.aw.id ),
.exists_o ( wr_exists ),
.exists_oup_id_o ( wr_exists_id ),
.exists_full_o ( wr_exists_full ),
.pop_i ( slv_resp_o.b_valid && slv_req_i.b_ready ),
.pop_oup_id_i ( mst_resp_i.b.id[IdxWidth-1:0] ),
.pop_inp_id_o ( slv_resp_o.b.id )
);
axi_id_remap_table #(
.InpIdWidth ( AxiSlvPortIdWidth ),
.MaxUniqInpIds ( AxiSlvPortMaxUniqIds ),
.MaxTxnsPerId ( AxiMaxTxnsPerId )
) i_rd_table (
.clk_i,
.rst_ni,
.free_o ( rd_free ),
.free_oup_id_o ( rd_free_oup_id ),
.full_o ( rd_full ),
.push_i ( rd_push ),
.push_inp_id_i ( rd_push_inp_id ),
.push_oup_id_i ( rd_push_oup_id ),
.exists_inp_id_i ( slv_req_i.ar.id ),
.exists_o ( rd_exists ),
.exists_oup_id_o ( rd_exists_id ),
.exists_full_o ( rd_exists_full ),
.pop_i ( slv_resp_o.r_valid && slv_req_i.r_ready && slv_resp_o.r.last ),
.pop_oup_id_i ( mst_resp_i.r.id[IdxWidth-1:0] ),
.pop_inp_id_o ( slv_resp_o.r.id )
);
assign both_free = wr_free & rd_free;
lzc #(
.WIDTH ( AxiSlvPortMaxUniqIds ),
.MODE ( 1'b0 )
) i_lzc (
.in_i ( both_free ),
.cnt_o ( both_free_oup_id ),
.empty_o ( )
);
localparam ZeroWidth = AxiMstPortIdWidth - IdxWidth;
assign mst_req_o.ar.id = {{ZeroWidth{1'b0}}, rd_push_oup_id};
assign mst_req_o.aw.id = {{ZeroWidth{1'b0}}, wr_push_oup_id};
enum logic [1:0] {Ready, HoldAR, HoldAW, HoldAx} state_d, state_q;
idx_t ar_id_d, ar_id_q,
aw_id_d, aw_id_q;
logic ar_prio_d, ar_prio_q;
always_comb begin
mst_req_o.aw_valid = 1'b0;
slv_resp_o.aw_ready = 1'b0;
wr_push = 1'b0;
wr_push_oup_id = '0;
mst_req_o.ar_valid = 1'b0;
slv_resp_o.ar_ready = 1'b0;
rd_push = 1'b0;
rd_push_inp_id = '0;
rd_push_oup_id = '0;
ar_id_d = ar_id_q;
aw_id_d = aw_id_q;
ar_prio_d = ar_prio_q;
state_d = state_q;
unique case (state_q)
Ready: begin
if (slv_req_i.ar_valid) begin
if ((rd_exists && !rd_exists_full) || (!rd_exists && !rd_full)) begin
rd_push_inp_id = slv_req_i.ar.id;
rd_push_oup_id = rd_exists ? rd_exists_id : rd_free_oup_id;
mst_req_o.ar_valid = 1'b1;
rd_push = 1'b1;
end
end
if (slv_req_i.aw_valid) begin
if (!slv_req_i.aw.atop[axi_pkg::ATOP_R_RESP]) begin
if ((wr_exists && !wr_exists_full) || (!wr_exists && !wr_full)) begin
wr_push_oup_id = wr_exists ? wr_exists_id : wr_free_oup_id;
mst_req_o.aw_valid = 1'b1;
wr_push = 1'b1;
end
end else if (!(ar_prio_q && mst_req_o.ar_valid)) begin
mst_req_o.ar_valid = 1'b0;
slv_resp_o.ar_ready = 1'b0;
rd_push = 1'b0;
if ((|both_free)) begin
wr_push_oup_id = both_free_oup_id;
rd_push_inp_id = slv_req_i.aw.id;
rd_push_oup_id = both_free_oup_id;
mst_req_o.aw_valid = 1'b1;
rd_push = 1'b1;
wr_push = 1'b1;
ar_prio_d = 1'b1;
end
end
end
if (mst_req_o.ar_valid) begin
slv_resp_o.ar_ready = mst_resp_i.ar_ready;
if (!mst_resp_i.ar_ready) begin
ar_id_d = rd_push_oup_id;
end
end
if (mst_req_o.aw_valid) begin
slv_resp_o.aw_ready = mst_resp_i.aw_ready;
if (!mst_resp_i.aw_ready) begin
aw_id_d = wr_push_oup_id;
end
end
if ({mst_req_o.ar_valid, mst_resp_i.ar_ready,
mst_req_o.aw_valid, mst_resp_i.aw_ready} == 4'b1010) begin
state_d = HoldAx;
end else if ({mst_req_o.ar_valid, mst_resp_i.ar_ready} == 2'b10) begin
state_d = HoldAR;
end else if ({mst_req_o.aw_valid, mst_resp_i.aw_ready} == 2'b10) begin
state_d = HoldAW;
end else begin
state_d = Ready;
end
if (mst_req_o.ar_valid && mst_resp_i.ar_ready) begin
ar_prio_d = 1'b0;
end
end
HoldAR: begin
rd_push_oup_id = ar_id_q;
mst_req_o.ar_valid = 1'b1;
slv_resp_o.ar_ready = mst_resp_i.ar_ready;
if (mst_resp_i.ar_ready) begin
state_d = Ready;
ar_prio_d = 1'b0;
end
end
HoldAW: begin
wr_push_oup_id = aw_id_q;
mst_req_o.aw_valid = 1'b1;
slv_resp_o.aw_ready = mst_resp_i.aw_ready;
if (mst_resp_i.aw_ready) begin
state_d = Ready;
end
end
HoldAx: begin
rd_push_oup_id = ar_id_q;
mst_req_o.ar_valid = 1'b1;
slv_resp_o.ar_ready = mst_resp_i.ar_ready;
wr_push_oup_id = aw_id_q;
mst_req_o.aw_valid = 1'b1;
slv_resp_o.aw_ready = mst_resp_i.aw_ready;
unique case ({mst_resp_i.ar_ready, mst_resp_i.aw_ready})
2'b01: state_d = HoldAR;
2'b10: state_d = HoldAW;
2'b11: state_d = Ready;
default: ;
endcase
if (mst_resp_i.ar_ready) begin
ar_prio_d = 1'b0;
end
end
default: state_d = Ready;
endcase
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
ar_id_q <= ('0);
end else begin
ar_id_q <= (ar_id_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
ar_prio_q <= (1'b0);
end else begin
ar_prio_q <= (ar_prio_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
aw_id_q <= ('0);
end else begin
aw_id_q <= (aw_id_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
state_q <= (Ready);
end else begin
state_q <= (state_d);
end
end
endmodule
module axi_id_remap_table #(
parameter int unsigned InpIdWidth = 32'd0,
parameter int unsigned MaxUniqInpIds = 32'd0,
parameter int unsigned MaxTxnsPerId = 32'd0,
localparam type id_inp_t = logic [InpIdWidth-1:0],
localparam int unsigned IdxWidth = cf_math_pkg::idx_width(MaxUniqInpIds),
localparam type idx_t = logic [IdxWidth-1:0],
localparam type field_t = logic [MaxUniqInpIds-1:0]
) (
input logic clk_i,
input logic rst_ni,
output field_t free_o,
output idx_t free_oup_id_o,
output logic full_o,
input logic push_i,
input id_inp_t push_inp_id_i,
input idx_t push_oup_id_i,
input id_inp_t exists_inp_id_i,
output logic exists_o,
output idx_t exists_oup_id_o,
output logic exists_full_o,
input logic pop_i,
input idx_t pop_oup_id_i,
output id_inp_t pop_inp_id_o
);
localparam int unsigned CntWidth = $clog2(MaxTxnsPerId+1);
typedef logic [CntWidth-1:0] cnt_t;
typedef struct packed {
id_inp_t inp_id;
cnt_t cnt;
} entry_t;
entry_t [MaxUniqInpIds-1:0] table_d, table_q;
for (genvar i = 0; i < MaxUniqInpIds; i++) begin : gen_free_o
assign free_o[i] = table_q[i].cnt == '0;
end
lzc #(
.WIDTH ( MaxUniqInpIds ),
.MODE ( 1'b0 )
) i_lzc_free (
.in_i ( free_o ),
.cnt_o ( free_oup_id_o ),
.empty_o ( full_o )
);
if (MaxUniqInpIds == 1) begin : gen_pop_for_single_unique_inp_id
assign pop_inp_id_o = table_q[0].inp_id;
end else begin : gen_pop_for_multiple_unique_inp_ids
assign pop_inp_id_o = table_q[pop_oup_id_i].inp_id;
end
field_t match;
for (genvar i = 0; i < MaxUniqInpIds; i++) begin : gen_match
assign match[i] = table_q[i].cnt > 0 && table_q[i].inp_id == exists_inp_id_i;
end
logic no_match;
lzc #(
.WIDTH ( MaxUniqInpIds ),
.MODE ( 1'b0 )
) i_lzc_match (
.in_i ( match ),
.cnt_o ( exists_oup_id_o ),
.empty_o ( no_match )
);
assign exists_o = ~no_match;
if (MaxUniqInpIds == 1) begin : gen_exists_full_for_single_unique_inp_id
assign exists_full_o = table_q[0].cnt == MaxTxnsPerId;
end else begin : gen_exists_full_for_multiple_unique_inp_ids
assign exists_full_o = table_q[exists_oup_id_o].cnt == MaxTxnsPerId;
end
always_comb begin
table_d = table_q;
if (push_i) begin
table_d[push_oup_id_i].inp_id = push_inp_id_i;
table_d[push_oup_id_i].cnt += 1;
end
if (pop_i) begin
table_d[pop_oup_id_i].cnt -= 1;
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
table_q <= ('0);
end else begin
table_q <= (table_d);
end
end
endmodule
module axi_id_remap_intf #(
parameter int unsigned AXI_SLV_PORT_ID_WIDTH = 32'd0,
parameter int unsigned AXI_SLV_PORT_MAX_UNIQ_IDS = 32'd0,
parameter int unsigned AXI_MAX_TXNS_PER_ID = 32'd0,
parameter int unsigned AXI_MST_PORT_ID_WIDTH = 32'd0,
parameter int unsigned AXI_ADDR_WIDTH = 32'd0,
parameter int unsigned AXI_DATA_WIDTH = 32'd0,
parameter int unsigned AXI_USER_WIDTH = 32'd0
) (
input logic clk_i,
input logic rst_ni,
AXI_BUS.Slave slv,
AXI_BUS.Master mst
);
typedef logic [AXI_SLV_PORT_ID_WIDTH-1:0] slv_id_t;
typedef logic [AXI_MST_PORT_ID_WIDTH-1:0] mst_id_t;
typedef logic [AXI_ADDR_WIDTH-1:0] axi_addr_t;
typedef logic [AXI_DATA_WIDTH-1:0] axi_data_t;
typedef logic [AXI_DATA_WIDTH/8-1:0] axi_strb_t;
typedef logic [AXI_USER_WIDTH-1:0] axi_user_t;
typedef struct packed {
slv_id_t id;
axi_addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_pkg::atop_t atop;
axi_user_t user;
} slv_aw_chan_t;
typedef struct packed {
axi_data_t data;
axi_strb_t strb;
logic last;
axi_user_t user;
} slv_w_chan_t;
typedef struct packed {
slv_id_t id;
axi_pkg::resp_t resp;
axi_user_t user;
} slv_b_chan_t;
typedef struct packed {
slv_id_t id;
axi_addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_user_t user;
} slv_ar_chan_t;
typedef struct packed {
slv_id_t id;
axi_data_t data;
axi_pkg::resp_t resp;
logic last;
axi_user_t user;
} slv_r_chan_t;
typedef struct packed {
slv_aw_chan_t aw;
logic aw_valid;
slv_w_chan_t w;
logic w_valid;
logic b_ready;
slv_ar_chan_t ar;
logic ar_valid;
logic r_ready;
} slv_req_t;
typedef struct packed {
logic aw_ready;
logic ar_ready;
logic w_ready;
logic b_valid;
slv_b_chan_t b;
logic r_valid;
slv_r_chan_t r;
} slv_resp_t;
typedef struct packed {
mst_id_t id;
axi_addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_pkg::atop_t atop;
axi_user_t user;
} mst_aw_chan_t;
typedef struct packed {
axi_data_t data;
axi_strb_t strb;
logic last;
axi_user_t user;
} mst_w_chan_t;
typedef struct packed {
mst_id_t id;
axi_pkg::resp_t resp;
axi_user_t user;
} mst_b_chan_t;
typedef struct packed {
mst_id_t id;
axi_addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_user_t user;
} mst_ar_chan_t;
typedef struct packed {
mst_id_t id;
axi_data_t data;
axi_pkg::resp_t resp;
logic last;
axi_user_t user;
} mst_r_chan_t;
typedef struct packed {
mst_aw_chan_t aw;
logic aw_valid;
mst_w_chan_t w;
logic w_valid;
logic b_ready;
mst_ar_chan_t ar;
logic ar_valid;
logic r_ready;
} mst_req_t;
typedef struct packed {
logic aw_ready;
logic ar_ready;
logic w_ready;
logic b_valid;
mst_b_chan_t b;
logic r_valid;
mst_r_chan_t r;
} mst_resp_t;
slv_req_t slv_req;
slv_resp_t slv_resp;
mst_req_t mst_req;
mst_resp_t mst_resp;
assign slv_req.aw.id = slv.aw_id;
assign slv_req.aw.addr = slv.aw_addr;
assign slv_req.aw.len = slv.aw_len;
assign slv_req.aw.size = slv.aw_size;
assign slv_req.aw.burst = slv.aw_burst;
assign slv_req.aw.lock = slv.aw_lock;
assign slv_req.aw.cache = slv.aw_cache;
assign slv_req.aw.prot = slv.aw_prot;
assign slv_req.aw.qos = slv.aw_qos;
assign slv_req.aw.region = slv.aw_region;
assign slv_req.aw.atop = slv.aw_atop;
assign slv_req.aw.user = slv.aw_user;
assign slv_req.aw_valid = slv.aw_valid;
assign slv_req.w.data = slv.w_data;
assign slv_req.w.strb = slv.w_strb;
assign slv_req.w.last = slv.w_last;
assign slv_req.w.user = slv.w_user;
assign slv_req.w_valid = slv.w_valid;
assign slv_req.b_ready = slv.b_ready;
assign slv_req.ar.id = slv.ar_id;
assign slv_req.ar.addr = slv.ar_addr;
assign slv_req.ar.len = slv.ar_len;
assign slv_req.ar.size = slv.ar_size;
assign slv_req.ar.burst = slv.ar_burst;
assign slv_req.ar.lock = slv.ar_lock;
assign slv_req.ar.cache = slv.ar_cache;
assign slv_req.ar.prot = slv.ar_prot;
assign slv_req.ar.qos = slv.ar_qos;
assign slv_req.ar.region = slv.ar_region;
assign slv_req.ar.user = slv.ar_user;
assign slv_req.ar_valid = slv.ar_valid;
assign slv_req.r_ready = slv.r_ready;
assign slv.aw_ready = slv_resp.aw_ready;
assign slv.ar_ready = slv_resp.ar_ready;
assign slv.w_ready = slv_resp.w_ready;
assign slv.b_valid = slv_resp.b_valid;
assign slv.b_id = slv_resp.b.id;
assign slv.b_resp = slv_resp.b.resp;
assign slv.b_user = slv_resp.b.user;
assign slv.r_valid = slv_resp.r_valid;
assign slv.r_id = slv_resp.r.id;
assign slv.r_data = slv_resp.r.data;
assign slv.r_resp = slv_resp.r.resp;
assign slv.r_last = slv_resp.r.last;
assign slv.r_user = slv_resp.r.user;
assign mst.aw_id = mst_req.aw.id;
assign mst.aw_addr = mst_req.aw.addr;
assign mst.aw_len = mst_req.aw.len;
assign mst.aw_size = mst_req.aw.size;
assign mst.aw_burst = mst_req.aw.burst;
assign mst.aw_lock = mst_req.aw.lock;
assign mst.aw_cache = mst_req.aw.cache;
assign mst.aw_prot = mst_req.aw.prot;
assign mst.aw_qos = mst_req.aw.qos;
assign mst.aw_region = mst_req.aw.region;
assign mst.aw_atop = mst_req.aw.atop;
assign mst.aw_user = mst_req.aw.user;
assign mst.aw_valid = mst_req.aw_valid;
assign mst.w_data = mst_req.w.data;
assign mst.w_strb = mst_req.w.strb;
assign mst.w_last = mst_req.w.last;
assign mst.w_user = mst_req.w.user;
assign mst.w_valid = mst_req.w_valid;
assign mst.b_ready = mst_req.b_ready;
assign mst.ar_id = mst_req.ar.id;
assign mst.ar_addr = mst_req.ar.addr;
assign mst.ar_len = mst_req.ar.len;
assign mst.ar_size = mst_req.ar.size;
assign mst.ar_burst = mst_req.ar.burst;
assign mst.ar_lock = mst_req.ar.lock;
assign mst.ar_cache = mst_req.ar.cache;
assign mst.ar_prot = mst_req.ar.prot;
assign mst.ar_qos = mst_req.ar.qos;
assign mst.ar_region = mst_req.ar.region;
assign mst.ar_user = mst_req.ar.user;
assign mst.ar_valid = mst_req.ar_valid;
assign mst.r_ready = mst_req.r_ready;
assign mst_resp.aw_ready = mst.aw_ready;
assign mst_resp.ar_ready = mst.ar_ready;
assign mst_resp.w_ready = mst.w_ready;
assign mst_resp.b_valid = mst.b_valid;
assign mst_resp.b.id = mst.b_id;
assign mst_resp.b.resp = mst.b_resp;
assign mst_resp.b.user = mst.b_user;
assign mst_resp.r_valid = mst.r_valid;
assign mst_resp.r.id = mst.r_id;
assign mst_resp.r.data = mst.r_data;
assign mst_resp.r.resp = mst.r_resp;
assign mst_resp.r.last = mst.r_last;
assign mst_resp.r.user = mst.r_user;
axi_id_remap #(
.AxiSlvPortIdWidth ( AXI_SLV_PORT_ID_WIDTH ),
.AxiSlvPortMaxUniqIds ( AXI_SLV_PORT_MAX_UNIQ_IDS ),
.AxiMaxTxnsPerId ( AXI_MAX_TXNS_PER_ID ),
.AxiMstPortIdWidth ( AXI_MST_PORT_ID_WIDTH ),
.slv_req_t ( slv_req_t ),
.slv_resp_t ( slv_resp_t ),
.mst_req_t ( mst_req_t ),
.mst_resp_t ( mst_resp_t )
) i_axi_id_remap (
.clk_i,
.rst_ni,
.slv_req_i ( slv_req ),
.slv_resp_o ( slv_resp ),
.mst_req_o ( mst_req ),
.mst_resp_i ( mst_resp )
);
endmodule
`begin_keywords "1800-2023"
module axi_id_prepend #(
parameter int unsigned NoBus = 1,
parameter int unsigned AxiIdWidthSlvPort = 4,
parameter int unsigned AxiIdWidthMstPort = 6,
parameter type slv_aw_chan_t = logic,
parameter type slv_w_chan_t = logic,
parameter type slv_b_chan_t = logic,
parameter type slv_ar_chan_t = logic,
parameter type slv_r_chan_t = logic,
parameter type mst_aw_chan_t = logic,
parameter type mst_w_chan_t = logic,
parameter type mst_b_chan_t = logic,
parameter type mst_ar_chan_t = logic,
parameter type mst_r_chan_t = logic,
parameter int unsigned PreIdWidth = AxiIdWidthMstPort - AxiIdWidthSlvPort
) (
input logic [PreIdWidth-1:0] pre_id_i,
input slv_aw_chan_t [NoBus-1:0] slv_aw_chans_i,
input logic [NoBus-1:0] slv_aw_valids_i,
output logic [NoBus-1:0] slv_aw_readies_o,
input slv_w_chan_t [NoBus-1:0] slv_w_chans_i,
input logic [NoBus-1:0] slv_w_valids_i,
output logic [NoBus-1:0] slv_w_readies_o,
output slv_b_chan_t [NoBus-1:0] slv_b_chans_o,
output logic [NoBus-1:0] slv_b_valids_o,
input logic [NoBus-1:0] slv_b_readies_i,
input slv_ar_chan_t [NoBus-1:0] slv_ar_chans_i,
input logic [NoBus-1:0] slv_ar_valids_i,
output logic [NoBus-1:0] slv_ar_readies_o,
output slv_r_chan_t [NoBus-1:0] slv_r_chans_o,
output logic [NoBus-1:0] slv_r_valids_o,
input logic [NoBus-1:0] slv_r_readies_i,
output mst_aw_chan_t [NoBus-1:0] mst_aw_chans_o,
output logic [NoBus-1:0] mst_aw_valids_o,
input logic [NoBus-1:0] mst_aw_readies_i,
output mst_w_chan_t [NoBus-1:0] mst_w_chans_o,
output logic [NoBus-1:0] mst_w_valids_o,
input logic [NoBus-1:0] mst_w_readies_i,
input mst_b_chan_t [NoBus-1:0] mst_b_chans_i,
input logic [NoBus-1:0] mst_b_valids_i,
output logic [NoBus-1:0] mst_b_readies_o,
output mst_ar_chan_t [NoBus-1:0] mst_ar_chans_o,
output logic [NoBus-1:0] mst_ar_valids_o,
input logic [NoBus-1:0] mst_ar_readies_i,
input mst_r_chan_t [NoBus-1:0] mst_r_chans_i,
input logic [NoBus-1:0] mst_r_valids_i,
output logic [NoBus-1:0] mst_r_readies_o
);
for (genvar i = 0; i < NoBus; i++) begin : gen_id_prepend
if (PreIdWidth == 0) begin : gen_no_prepend
assign mst_aw_chans_o[i] = slv_aw_chans_i[i];
assign mst_ar_chans_o[i] = slv_ar_chans_i[i];
end else begin : gen_prepend
always_comb begin
mst_aw_chans_o[i] = mst_aw_chan_t'(slv_aw_chans_i[i]);
mst_ar_chans_o[i] = mst_ar_chan_t'(slv_ar_chans_i[i]);
mst_aw_chans_o[i].id = {pre_id_i, slv_aw_chans_i[i].id[AxiIdWidthSlvPort-1:0]};
mst_ar_chans_o[i].id = {pre_id_i, slv_ar_chans_i[i].id[AxiIdWidthSlvPort-1:0]};
end
end
assign slv_b_chans_o[i] = slv_b_chan_t'(mst_b_chans_i[i]);
assign slv_r_chans_o[i] = slv_r_chan_t'(mst_r_chans_i[i]);
end
assign mst_w_chans_o = slv_w_chans_i;
assign mst_aw_valids_o = slv_aw_valids_i;
assign slv_aw_readies_o = mst_aw_readies_i;
assign mst_w_valids_o = slv_w_valids_i;
assign slv_w_readies_o = mst_w_readies_i;
assign slv_b_valids_o = mst_b_valids_i;
assign mst_b_readies_o = slv_b_readies_i;
assign mst_ar_valids_o = slv_ar_valids_i;
assign slv_ar_readies_o = mst_ar_readies_i;
assign slv_r_valids_o = mst_r_valids_i;
assign mst_r_readies_o = slv_r_readies_i;
endmodule
`begin_keywords "1800-2023"
module axi_inval_filter #(
parameter int unsigned MaxTxns = 32'd0,
parameter int unsigned AddrWidth = 32'd0,
parameter int unsigned L1LineWidth = 32'd0,
parameter type aw_chan_t = logic,
parameter type req_t = logic,
parameter type resp_t = logic
) (
input logic clk_i,
input logic rst_ni,
input logic en_i,
input req_t slv_req_i,
output resp_t slv_resp_o,
output req_t mst_req_o,
input resp_t mst_resp_i,
output logic [AddrWidth-1:0] inval_addr_o,
output logic inval_valid_o,
input logic inval_ready_i
);
import cf_math_pkg::idx_width;
logic aw_fifo_full, aw_fifo_empty;
logic aw_fifo_push, aw_fifo_pop;
aw_chan_t aw_fifo_data;
assign aw_fifo_push = en_i & slv_req_i.aw_valid & slv_resp_o.aw_ready;
logic [AddrWidth-1:0] inval_offset_d, inval_offset_q;
assign inval_addr_o = aw_fifo_data.addr + inval_offset_q;
assign inval_valid_o = ~aw_fifo_empty;
always_comb begin : axi
mst_req_o = slv_req_i;
slv_resp_o = mst_resp_i;
if (aw_fifo_full) begin
slv_resp_o.aw_ready = 1'b0;
mst_req_o.aw_valid = 1'b0;
end
end
enum logic { Idle, Invalidating } state_d, state_q;
always_comb begin : inval_fsm
state_d = state_q;
aw_fifo_pop = 1'b0;
inval_offset_d = inval_offset_q;
unique case (state_q)
Idle: begin
if (!aw_fifo_empty) begin
if (inval_ready_i) begin
if ((L1LineWidth - aw_fifo_data.addr[idx_width(L1LineWidth)-1:0]) < ((aw_fifo_data.len + 1) << aw_fifo_data.size)) begin
state_d = Invalidating;
inval_offset_d = L1LineWidth - aw_fifo_data.addr[idx_width(L1LineWidth)-1:0];
end else begin
aw_fifo_pop = 1'b1;
end
end
end
end
Invalidating: begin
if (inval_ready_i) begin
inval_offset_d = inval_offset_q + L1LineWidth;
if (inval_offset_d >= ((aw_fifo_data.len + 1) << aw_fifo_data.size)) begin
state_d = Idle;
inval_offset_d = '0;
aw_fifo_pop = 1'b1;
end
end
end
endcase
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
state_q <= Idle;
inval_offset_q <= '0;
end else begin
state_q <= state_d;
inval_offset_q <= inval_offset_d;
end
end
fifo_v3 #(
.FALL_THROUGH ( 1'b1 ),
.DEPTH ( MaxTxns ),
.dtype ( aw_chan_t )
) i_aw_fifo (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.full_o ( aw_fifo_full ),
.empty_o ( aw_fifo_empty ),
.usage_o ( ),
.data_i ( slv_req_i.aw ),
.push_i ( aw_fifo_push ),
.data_o ( aw_fifo_data ),
.pop_i ( aw_fifo_pop )
);
endmodule : axi_inval_filter
`begin_keywords "1800-2023"
module axi_isolate #(
parameter int unsigned NumPending = 32'd16,
parameter bit TerminateTransaction = 1'b0,
parameter bit AtopSupport = 1'b1,
parameter int signed AxiAddrWidth = 32'd0,
parameter int signed AxiDataWidth = 32'd0,
parameter int signed AxiIdWidth = 32'd0,
parameter int signed AxiUserWidth = 32'd0,
parameter type axi_req_t = logic,
parameter type axi_resp_t = logic
) (
input logic clk_i,
input logic rst_ni,
input axi_req_t slv_req_i,
output axi_resp_t slv_resp_o,
output axi_req_t mst_req_o,
input axi_resp_t mst_resp_i,
input logic isolate_i,
output logic isolated_o
);
typedef logic [AxiIdWidth-1:0] id_t;
typedef logic [AxiAddrWidth-1:0] addr_t;
typedef logic [AxiDataWidth-1:0] data_t;
typedef logic [AxiDataWidth/8-1:0] strb_t;
typedef logic [AxiUserWidth-1:0] user_t;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_pkg::atop_t atop;
user_t user;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
logic last;
user_t user;
} w_chan_t;
typedef struct packed {
id_t id;
axi_pkg::resp_t resp;
user_t user;
} b_chan_t;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
user_t user;
} ar_chan_t;
typedef struct packed {
id_t id;
data_t data;
axi_pkg::resp_t resp;
logic last;
user_t user;
} r_chan_t;
axi_req_t [1:0] demux_req;
axi_resp_t [1:0] demux_rsp;
if (TerminateTransaction) begin
axi_demux #(
.AxiIdWidth ( AxiIdWidth ),
.AtopSupport ( AtopSupport ),
.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 ),
.NoMstPorts ( 2 ),
.MaxTrans ( NumPending ),
.AxiLookBits ( 1 ),
.UniqueIds ( 1'b0 ),
.SpillAw ( 1'b0 ),
.SpillW ( 1'b0 ),
.SpillB ( 1'b0 ),
.SpillAr ( 1'b0 ),
.SpillR ( 1'b0 )
) i_axi_demux (
.clk_i,
.rst_ni,
.test_i ( 1'b0 ),
.slv_req_i,
.slv_aw_select_i ( isolated_o ),
.slv_ar_select_i ( isolated_o ),
.slv_resp_o,
.mst_reqs_o ( demux_req ),
.mst_resps_i ( demux_rsp )
);
axi_err_slv #(
.AxiIdWidth ( AxiIdWidth ),
.axi_req_t ( axi_req_t ),
.axi_resp_t ( axi_resp_t ),
.Resp ( axi_pkg::RESP_DECERR ),
.RespData ( 'h1501A7ED ),
.ATOPs ( AtopSupport ),
.MaxTrans ( 1 )
) i_axi_err_slv (
.clk_i,
.rst_ni,
.test_i ( 1'b0 ),
.slv_req_i ( demux_req[1] ),
.slv_resp_o ( demux_rsp[1] )
);
end else begin
assign demux_req[0] = slv_req_i;
assign slv_resp_o = demux_rsp[0];
assign demux_req[1] = '0;
assign demux_rsp[1] = '0;
end
axi_isolate_inner #(
.NumPending ( NumPending ),
.axi_req_t ( axi_req_t ),
.axi_resp_t ( axi_resp_t )
) i_axi_isolate (
.clk_i,
.rst_ni,
.slv_req_i ( demux_req[0] ),
.slv_resp_o ( demux_rsp[0] ),
.mst_req_o,
.mst_resp_i,
.isolate_i,
.isolated_o
);
endmodule
module axi_isolate_inner #(
parameter int unsigned NumPending = 32'd16,
parameter type axi_req_t = logic,
parameter type axi_resp_t = logic
) (
input logic clk_i,
input logic rst_ni,
input axi_req_t slv_req_i,
output axi_resp_t slv_resp_o,
output axi_req_t mst_req_o,
input axi_resp_t mst_resp_i,
input logic isolate_i,
output logic isolated_o
);
localparam int unsigned CounterWidth = $clog2(NumPending + 32'd1) + 32'd1;
typedef logic [CounterWidth-1:0] cnt_t;
typedef enum logic [1:0] {
Normal,
Hold,
Drain,
Isolate
} isolate_state_e;
isolate_state_e state_aw_d, state_aw_q, state_ar_d, state_ar_q;
logic update_aw_state, update_ar_state;
cnt_t pending_aw_d, pending_aw_q;
logic update_aw_cnt;
cnt_t pending_w_d, pending_w_q;
logic update_w_cnt, connect_w;
cnt_t pending_ar_d, pending_ar_q;
logic update_ar_cnt;
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
pending_aw_q <= ('0);
end else begin
if (update_aw_cnt) begin
pending_aw_q <= (pending_aw_d);
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
pending_w_q <= ('0);
end else begin
if (update_w_cnt) begin
pending_w_q <= (pending_w_d);
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
pending_ar_q <= ('0);
end else begin
if (update_ar_cnt) begin
pending_ar_q <= (pending_ar_d);
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
state_aw_q <= (Isolate);
end else begin
if (update_aw_state) begin
state_aw_q <= (state_aw_d);
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
state_ar_q <= (Isolate);
end else begin
if (update_ar_state) begin
state_ar_q <= (state_ar_d);
end
end
end
always_comb begin
pending_aw_d = pending_aw_q;
update_aw_cnt = 1'b0;
pending_w_d = pending_w_q;
update_w_cnt = 1'b0;
connect_w = 1'b0;
pending_ar_d = pending_ar_q;
update_ar_cnt = 1'b0;
if (mst_req_o.aw_valid && (state_aw_q == Normal)) begin
pending_aw_d++;
update_aw_cnt = 1'b1;
pending_w_d++;
update_w_cnt = 1'b1;
connect_w = 1'b1;
if (mst_req_o.aw.atop[axi_pkg::ATOP_R_RESP]) begin
pending_ar_d++;
update_ar_cnt = 1'b1;
end
end
if (mst_req_o.w_valid && mst_resp_i.w_ready && mst_req_o.w.last) begin
pending_w_d--;
update_w_cnt = 1'b1;
end
if (mst_resp_i.b_valid && mst_req_o.b_ready) begin
pending_aw_d--;
update_aw_cnt = 1'b1;
end
if (mst_req_o.ar_valid && (state_ar_q == Normal)) begin
pending_ar_d++;
update_ar_cnt = 1'b1;
end
if (mst_resp_i.r_valid && mst_req_o.r_ready && mst_resp_i.r.last) begin
pending_ar_d--;
update_ar_cnt = 1'b1;
end
end
always_comb begin
state_aw_d = state_aw_q;
update_aw_state = 1'b0;
state_ar_d = state_ar_q;
update_ar_state = 1'b0;
mst_req_o = slv_req_i;
slv_resp_o = mst_resp_i;
unique case (state_aw_q)
Normal: begin
if (pending_aw_q >= cnt_t'(NumPending) || pending_ar_q >= cnt_t'(2*NumPending)
|| (pending_w_q >= cnt_t'(NumPending))) begin
mst_req_o.aw_valid = 1'b0;
slv_resp_o.aw_ready = 1'b0;
if (isolate_i) begin
state_aw_d = Drain;
update_aw_state = 1'b1;
end
end else begin
if (slv_req_i.aw_valid && !mst_resp_i.aw_ready) begin
state_aw_d = Hold;
update_aw_state = 1'b1;
end else begin
if (isolate_i) begin
state_aw_d = Drain;
update_aw_state = 1'b1;
end
end
end
end
Hold: begin
mst_req_o.aw_valid = 1'b1;
if (mst_resp_i.aw_ready) begin
update_aw_state = 1'b1;
state_aw_d = isolate_i ? Drain : Normal;
end
end
Drain: begin
mst_req_o.aw = '0;
mst_req_o.aw_valid = 1'b0;
slv_resp_o.aw_ready = 1'b0;
if (pending_aw_q == '0) begin
state_aw_d = Isolate;
update_aw_state = 1'b1;
end
end
Isolate: begin
mst_req_o.aw = '0;
mst_req_o.aw_valid = 1'b0;
slv_resp_o.aw_ready = 1'b0;
slv_resp_o.b = '0;
slv_resp_o.b_valid = 1'b0;
mst_req_o.b_ready = 1'b0;
if (!isolate_i) begin
state_aw_d = Normal;
update_aw_state = 1'b1;
end
end
default: ;
endcase
if ((pending_w_q == '0) && !connect_w ) begin
mst_req_o.w = '0;
mst_req_o.w_valid = 1'b0;
slv_resp_o.w_ready = 1'b0;
end
unique case (state_ar_q)
Normal: begin
if (pending_ar_q >= NumPending) begin
mst_req_o.ar_valid = 1'b0;
slv_resp_o.ar_ready = 1'b0;
if (isolate_i) begin
state_ar_d = Drain;
update_ar_state = 1'b1;
end
end else begin
if (slv_req_i.ar_valid && !mst_resp_i.ar_ready) begin
state_ar_d = Hold;
update_ar_state = 1'b1;
end else begin
if (isolate_i) begin
state_ar_d = Drain;
update_ar_state = 1'b1;
end
end
end
end
Hold: begin
mst_req_o.ar_valid = 1'b1;
if (mst_resp_i.ar_ready) begin
update_ar_state = 1'b1;
state_ar_d = isolate_i ? Drain : Normal;
end
end
Drain: begin
mst_req_o.ar = '0;
mst_req_o.ar_valid = 1'b0;
slv_resp_o.ar_ready = 1'b0;
if (pending_ar_q == '0) begin
state_ar_d = Isolate;
update_ar_state = 1'b1;
end
end
Isolate: begin
mst_req_o.ar = '0;
mst_req_o.ar_valid = 1'b0;
slv_resp_o.ar_ready = 1'b0;
slv_resp_o.r = '0;
slv_resp_o.r_valid = 1'b0;
mst_req_o.r_ready = 1'b0;
if (!isolate_i) begin
state_ar_d = Normal;
update_ar_state = 1'b1;
end
end
default: ;
endcase
end
assign isolated_o = (state_aw_q == Isolate && state_ar_q == Isolate);
endmodule
module axi_isolate_intf #(
parameter int unsigned NUM_PENDING = 32'd16,
parameter bit TERMINATE_TRANSACTION = 1'b0,
parameter bit ATOP_SUPPORT = 1'b1,
parameter int unsigned AXI_ID_WIDTH = 32'd0,
parameter int unsigned AXI_ADDR_WIDTH = 32'd0,
parameter int unsigned AXI_DATA_WIDTH = 32'd0,
parameter int unsigned AXI_USER_WIDTH = 32'd0
) (
input logic clk_i,
input logic rst_ni,
AXI_BUS.Slave slv,
AXI_BUS.Master mst,
input logic isolate_i,
output logic isolated_o
);
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;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_pkg::atop_t atop;
user_t user;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
logic last;
user_t user;
} w_chan_t;
typedef struct packed {
id_t id;
axi_pkg::resp_t resp;
user_t user;
} b_chan_t;
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
user_t user;
} ar_chan_t;
typedef struct packed {
id_t id;
data_t data;
axi_pkg::resp_t resp;
logic last;
user_t user;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} axi_req_t;
typedef struct packed {
logic aw_ready;
logic ar_ready;
logic w_ready;
logic b_valid;
b_chan_t b;
logic r_valid;
r_chan_t r;
} axi_resp_t;
axi_req_t slv_req, mst_req;
axi_resp_t slv_resp, mst_resp;
assign slv_req.aw.id = slv.aw_id;
assign slv_req.aw.addr = slv.aw_addr;
assign slv_req.aw.len = slv.aw_len;
assign slv_req.aw.size = slv.aw_size;
assign slv_req.aw.burst = slv.aw_burst;
assign slv_req.aw.lock = slv.aw_lock;
assign slv_req.aw.cache = slv.aw_cache;
assign slv_req.aw.prot = slv.aw_prot;
assign slv_req.aw.qos = slv.aw_qos;
assign slv_req.aw.region = slv.aw_region;
assign slv_req.aw.atop = slv.aw_atop;
assign slv_req.aw.user = slv.aw_user;
assign slv_req.aw_valid = slv.aw_valid;
assign slv_req.w.data = slv.w_data;
assign slv_req.w.strb = slv.w_strb;
assign slv_req.w.last = slv.w_last;
assign slv_req.w.user = slv.w_user;
assign slv_req.w_valid = slv.w_valid;
assign slv_req.b_ready = slv.b_ready;
assign slv_req.ar.id = slv.ar_id;
assign slv_req.ar.addr = slv.ar_addr;
assign slv_req.ar.len = slv.ar_len;
assign slv_req.ar.size = slv.ar_size;
assign slv_req.ar.burst = slv.ar_burst;
assign slv_req.ar.lock = slv.ar_lock;
assign slv_req.ar.cache = slv.ar_cache;
assign slv_req.ar.prot = slv.ar_prot;
assign slv_req.ar.qos = slv.ar_qos;
assign slv_req.ar.region = slv.ar_region;
assign slv_req.ar.user = slv.ar_user;
assign slv_req.ar_valid = slv.ar_valid;
assign slv_req.r_ready = slv.r_ready;
assign slv.aw_ready = slv_resp.aw_ready;
assign slv.ar_ready = slv_resp.ar_ready;
assign slv.w_ready = slv_resp.w_ready;
assign slv.b_valid = slv_resp.b_valid;
assign slv.b_id = slv_resp.b.id;
assign slv.b_resp = slv_resp.b.resp;
assign slv.b_user = slv_resp.b.user;
assign slv.r_valid = slv_resp.r_valid;
assign slv.r_id = slv_resp.r.id;
assign slv.r_data = slv_resp.r.data;
assign slv.r_resp = slv_resp.r.resp;
assign slv.r_last = slv_resp.r.last;
assign slv.r_user = slv_resp.r.user;
assign mst.aw_id = mst_req.aw.id;
assign mst.aw_addr = mst_req.aw.addr;
assign mst.aw_len = mst_req.aw.len;
assign mst.aw_size = mst_req.aw.size;
assign mst.aw_burst = mst_req.aw.burst;
assign mst.aw_lock = mst_req.aw.lock;
assign mst.aw_cache = mst_req.aw.cache;
assign mst.aw_prot = mst_req.aw.prot;
assign mst.aw_qos = mst_req.aw.qos;
assign mst.aw_region = mst_req.aw.region;
assign mst.aw_atop = mst_req.aw.atop;
assign mst.aw_user = mst_req.aw.user;
assign mst.aw_valid = mst_req.aw_valid;
assign mst.w_data = mst_req.w.data;
assign mst.w_strb = mst_req.w.strb;
assign mst.w_last = mst_req.w.last;
assign mst.w_user = mst_req.w.user;
assign mst.w_valid = mst_req.w_valid;
assign mst.b_ready = mst_req.b_ready;
assign mst.ar_id = mst_req.ar.id;
assign mst.ar_addr = mst_req.ar.addr;
assign mst.ar_len = mst_req.ar.len;
assign mst.ar_size = mst_req.ar.size;
assign mst.ar_burst = mst_req.ar.burst;
assign mst.ar_lock = mst_req.ar.lock;
assign mst.ar_cache = mst_req.ar.cache;
assign mst.ar_prot = mst_req.ar.prot;
assign mst.ar_qos = mst_req.ar.qos;
assign mst.ar_region = mst_req.ar.region;
assign mst.ar_user = mst_req.ar.user;
assign mst.ar_valid = mst_req.ar_valid;
assign mst.r_ready = mst_req.r_ready;
assign mst_resp.aw_ready = mst.aw_ready;
assign mst_resp.ar_ready = mst.ar_ready;
assign mst_resp.w_ready = mst.w_ready;
assign mst_resp.b_valid = mst.b_valid;
assign mst_resp.b.id = mst.b_id;
assign mst_resp.b.resp = mst.b_resp;
assign mst_resp.b.user = mst.b_user;
assign mst_resp.r_valid = mst.r_valid;
assign mst_resp.r.id = mst.r_id;
assign mst_resp.r.data = mst.r_data;
assign mst_resp.r.resp = mst.r_resp;
assign mst_resp.r.last = mst.r_last;
assign mst_resp.r.user = mst.r_user;
axi_isolate #(
.NumPending ( NUM_PENDING ),
.TerminateTransaction ( TERMINATE_TRANSACTION ),
.AtopSupport ( ATOP_SUPPORT ),
.AxiAddrWidth ( AXI_ADDR_WIDTH ),
.AxiDataWidth ( AXI_DATA_WIDTH ),
.AxiIdWidth ( AXI_ID_WIDTH ),
.AxiUserWidth ( AXI_USER_WIDTH ),
.axi_req_t ( axi_req_t ),
.axi_resp_t ( axi_resp_t )
) i_axi_isolate (
.clk_i,
.rst_ni,
.slv_req_i ( slv_req ),
.slv_resp_o ( slv_resp ),
.mst_req_o ( mst_req ),
.mst_resp_i ( mst_resp ),
.isolate_i,
.isolated_o
);
endmodule
`begin_keywords "1800-2023"
module axi_join_intf (
AXI_BUS.Slave in,
AXI_BUS.Master out
);
assign out.aw_id = in.aw_id;
assign out.aw_addr = in.aw_addr;
assign out.aw_len = in.aw_len;
assign out.aw_size = in.aw_size;
assign out.aw_burst = in.aw_burst;
assign out.aw_lock = in.aw_lock;
assign out.aw_cache = in.aw_cache;
assign out.aw_prot = in.aw_prot;
assign out.aw_qos = in.aw_qos;
assign out.aw_region = in.aw_region;
assign out.aw_atop = in.aw_atop;
assign out.aw_user = in.aw_user;
assign out.aw_valid = in.aw_valid;
assign in.aw_ready = out.aw_ready;
assign out.w_data = in.w_data;
assign out.w_strb = in.w_strb;
assign out.w_last = in.w_last;
assign out.w_user = in.w_user;
assign out.w_valid = in.w_valid;
assign in.w_ready = out.w_ready;
assign in.b_id = out.b_id;
assign in.b_resp = out.b_resp;
assign in.b_user = out.b_user;
assign in.b_valid = out.b_valid;
assign out.b_ready = in.b_ready;
assign out.ar_id = in.ar_id;
assign out.ar_addr = in.ar_addr;
assign out.ar_len = in.ar_len;
assign out.ar_size = in.ar_size;
assign out.ar_burst = in.ar_burst;
assign out.ar_lock = in.ar_lock;
assign out.ar_cache = in.ar_cache;
assign out.ar_prot = in.ar_prot;
assign out.ar_qos = in.ar_qos;
assign out.ar_region = in.ar_region;
assign out.ar_user = in.ar_user;
assign out.ar_valid = in.ar_valid;
assign in.ar_ready = out.ar_ready;
assign in.r_id = out.r_id;
assign in.r_data = out.r_data;
assign in.r_resp = out.r_resp;
assign in.r_last = out.r_last;
assign in.r_user = out.r_user;
assign in.r_valid = out.r_valid;
assign out.r_ready = in.r_ready;
endmodule
`begin_keywords "1800-2023"
module axi_lite_demux #(
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,
parameter int unsigned NoMstPorts = 32'd0,
parameter int unsigned MaxTrans = 32'd0,
parameter bit FallThrough = 1'b0,
parameter bit SpillAw = 1'b1,
parameter bit SpillW = 1'b0,
parameter bit SpillB = 1'b0,
parameter bit SpillAr = 1'b1,
parameter bit SpillR = 1'b0,
parameter type select_t = logic [$clog2(NoMstPorts)-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic test_i,
input axi_req_t slv_req_i,
input select_t slv_aw_select_i,
input select_t slv_ar_select_i,
output axi_resp_t slv_resp_o,
output axi_req_t [NoMstPorts-1:0] mst_reqs_o,
input axi_resp_t [NoMstPorts-1:0] mst_resps_i
);
typedef struct packed {
aw_chan_t aw;
select_t select;
} aw_chan_select_t;
typedef struct packed {
ar_chan_t ar;
select_t select;
} ar_chan_select_t;
if (NoMstPorts == 32'd1) begin : gen_no_demux
spill_register #(
.T ( aw_chan_t ),
.Bypass ( ~SpillAw )
) i_aw_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( slv_req_i.aw_valid ),
.ready_o ( slv_resp_o.aw_ready ),
.data_i ( slv_req_i.aw ),
.valid_o ( mst_reqs_o[0].aw_valid ),
.ready_i ( mst_resps_i[0].aw_ready ),
.data_o ( mst_reqs_o[0].aw )
);
spill_register #(
.T ( w_chan_t ),
.Bypass ( ~SpillW )
) i_w_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( slv_req_i.w_valid ),
.ready_o ( slv_resp_o.w_ready ),
.data_i ( slv_req_i.w ),
.valid_o ( mst_reqs_o[0].w_valid ),
.ready_i ( mst_resps_i[0].w_ready ),
.data_o ( mst_reqs_o[0].w )
);
spill_register #(
.T ( b_chan_t ),
.Bypass ( ~SpillB )
) i_b_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( mst_resps_i[0].b_valid ),
.ready_o ( mst_reqs_o[0].b_ready ),
.data_i ( mst_resps_i[0].b ),
.valid_o ( slv_resp_o.b_valid ),
.ready_i ( slv_req_i.b_ready ),
.data_o ( slv_resp_o.b )
);
spill_register #(
.T ( ar_chan_t ),
.Bypass ( ~SpillAr )
) i_ar_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( slv_req_i.ar_valid ),
.ready_o ( slv_resp_o.ar_ready ),
.data_i ( slv_req_i.ar ),
.valid_o ( mst_reqs_o[0].ar_valid ),
.ready_i ( mst_resps_i[0].ar_ready ),
.data_o ( mst_reqs_o[0].ar )
);
spill_register #(
.T ( r_chan_t ),
.Bypass ( ~SpillR )
) i_r_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( mst_resps_i[0].r_valid ),
.ready_o ( mst_reqs_o[0].r_ready ),
.data_i ( mst_resps_i[0].r ),
.valid_o ( slv_resp_o.r_valid ),
.ready_i ( slv_req_i.r_ready ),
.data_o ( slv_resp_o.r )
);
end else begin : gen_demux
aw_chan_select_t slv_aw_chan;
logic slv_aw_valid, slv_aw_ready;
logic [NoMstPorts-1:0] mst_aw_valids, mst_aw_readies;
logic lock_aw_valid_d, lock_aw_valid_q, load_aw_lock;
logic w_fifo_push, w_fifo_pop;
logic w_fifo_full, w_fifo_empty;
w_chan_t slv_w_chan;
select_t w_select;
logic slv_w_valid, slv_w_ready;
logic b_fifo_pop;
logic b_fifo_full, b_fifo_empty;
b_chan_t slv_b_chan;
select_t b_select;
logic slv_b_valid, slv_b_ready;
ar_chan_select_t slv_ar_chan;
logic slv_ar_valid, slv_ar_ready;
logic r_fifo_push, r_fifo_pop;
logic r_fifo_full, r_fifo_empty;
r_chan_t slv_r_chan;
select_t r_select;
logic slv_r_valid, slv_r_ready;
typedef aw_chan_select_t aw_chan_select_flat_t;
aw_chan_select_flat_t slv_aw_chan_select_in_flat,
slv_aw_chan_select_out_flat;
assign slv_aw_chan_select_in_flat = {slv_req_i.aw, slv_aw_select_i};
spill_register #(
.T ( aw_chan_select_flat_t ),
.Bypass ( ~SpillAw )
) i_aw_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( slv_req_i.aw_valid ),
.ready_o ( slv_resp_o.aw_ready ),
.data_i ( slv_aw_chan_select_in_flat ),
.valid_o ( slv_aw_valid ),
.ready_i ( slv_aw_ready ),
.data_o ( slv_aw_chan_select_out_flat )
);
assign slv_aw_chan = slv_aw_chan_select_out_flat;
for (genvar i = 0; i < NoMstPorts; i++) begin : gen_mst_aw
assign mst_reqs_o[i].aw = slv_aw_chan.aw;
assign mst_reqs_o[i].aw_valid = mst_aw_valids[i];
assign mst_aw_readies[i] = mst_resps_i[i].aw_ready;
end
always_comb begin
lock_aw_valid_d = lock_aw_valid_q;
load_aw_lock = 1'b0;
slv_aw_ready = 1'b0;
mst_aw_valids = '0;
w_fifo_push = 1'b0;
if (lock_aw_valid_q) begin
mst_aw_valids[slv_aw_chan.select] = 1'b1;
if (mst_aw_readies[slv_aw_chan.select]) begin
slv_aw_ready = 1'b1;
lock_aw_valid_d = 1'b0;
load_aw_lock = 1'b1;
end
end else begin
if (!w_fifo_full && slv_aw_valid) begin
w_fifo_push = 1'b1;
mst_aw_valids[slv_aw_chan.select] = 1'b1;
if (mst_aw_readies[slv_aw_chan.select]) begin
slv_aw_ready = 1'b1;
end else begin
lock_aw_valid_d = 1'b1;
load_aw_lock = 1'b1;
end
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
lock_aw_valid_q <= ('0);
end else begin
if (load_aw_lock) begin
lock_aw_valid_q <= (lock_aw_valid_d);
end
end
end
fifo_v3 #(
.FALL_THROUGH( FallThrough ),
.DEPTH ( MaxTrans ),
.dtype ( select_t )
) i_w_fifo (
.clk_i ( clk_i ),
.rst_ni ( 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_aw_chan.select ),
.push_i ( w_fifo_push ),
.data_o ( w_select ),
.pop_i ( w_fifo_pop )
);
spill_register #(
.T ( w_chan_t ),
.Bypass ( ~SpillW )
) i_w_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( slv_req_i.w_valid ),
.ready_o ( slv_resp_o.w_ready ),
.data_i ( slv_req_i.w ),
.valid_o ( slv_w_valid ),
.ready_i ( slv_w_ready ),
.data_o ( slv_w_chan )
);
for (genvar i = 0; i < NoMstPorts; i++) begin : gen_mst_w
assign mst_reqs_o[i].w = slv_w_chan;
assign mst_reqs_o[i].w_valid = ~w_fifo_empty & ~b_fifo_full &
slv_w_valid & (w_select == select_t'(i));
end
assign slv_w_ready = ~w_fifo_empty & ~b_fifo_full & mst_resps_i[w_select].w_ready;
assign w_fifo_pop = slv_w_valid & slv_w_ready;
fifo_v3 #(
.FALL_THROUGH( FallThrough ),
.DEPTH ( MaxTrans ),
.dtype ( select_t )
) i_b_fifo (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.testmode_i ( test_i ),
.full_o ( b_fifo_full ),
.empty_o ( b_fifo_empty ),
.usage_o ( ),
.data_i ( w_select ),
.push_i ( w_fifo_pop ),
.data_o ( b_select ),
.pop_i ( b_fifo_pop )
);
spill_register #(
.T ( b_chan_t ),
.Bypass ( ~SpillB )
) i_b_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( slv_b_valid ),
.ready_o ( slv_b_ready ),
.data_i ( slv_b_chan ),
.valid_o ( slv_resp_o.b_valid ),
.ready_i ( slv_req_i.b_ready ),
.data_o ( slv_resp_o.b )
);
assign slv_b_chan = (!b_fifo_empty) ? mst_resps_i[b_select].b : '0;
assign slv_b_valid = ~b_fifo_empty & mst_resps_i[b_select].b_valid;
for (genvar i = 0; i < NoMstPorts; i++) begin : gen_mst_b
assign mst_reqs_o[i].b_ready = ~b_fifo_empty & slv_b_ready & (b_select == select_t'(i));
end
assign b_fifo_pop = slv_b_valid & slv_b_ready;
typedef ar_chan_select_t ar_chan_select_flat_t;
ar_chan_select_flat_t slv_ar_chan_select_in_flat,
slv_ar_chan_select_out_flat;
assign slv_ar_chan_select_in_flat = {slv_req_i.ar, slv_ar_select_i};
spill_register #(
.T ( ar_chan_select_flat_t ),
.Bypass ( ~SpillAr )
) i_ar_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( slv_req_i.ar_valid ),
.ready_o ( slv_resp_o.ar_ready ),
.data_i ( slv_ar_chan_select_in_flat ),
.valid_o ( slv_ar_valid ),
.ready_i ( slv_ar_ready ),
.data_o ( slv_ar_chan_select_out_flat )
);
assign slv_ar_chan = slv_ar_chan_select_out_flat;
for (genvar i = 0; i < NoMstPorts; i++) begin : gen_mst_ar
assign mst_reqs_o[i].ar = slv_ar_chan.ar;
assign mst_reqs_o[i].ar_valid = ~r_fifo_full & slv_ar_valid &
(slv_ar_chan.select == select_t'(i));
end
assign slv_ar_ready = ~r_fifo_full & mst_resps_i[slv_ar_chan.select].ar_ready;
assign r_fifo_push = slv_ar_valid & slv_ar_ready;
fifo_v3 #(
.FALL_THROUGH( FallThrough ),
.DEPTH ( MaxTrans ),
.dtype ( select_t )
) i_r_fifo (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.testmode_i ( test_i ),
.full_o ( r_fifo_full ),
.empty_o ( r_fifo_empty ),
.usage_o ( ),
.data_i ( slv_ar_chan.select ),
.push_i ( r_fifo_push ),
.data_o ( r_select ),
.pop_i ( r_fifo_pop )
);
spill_register #(
.T ( r_chan_t ),
.Bypass ( ~SpillR )
) i_r_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( slv_r_valid ),
.ready_o ( slv_r_ready ),
.data_i ( slv_r_chan ),
.valid_o ( slv_resp_o.r_valid ),
.ready_i ( slv_req_i.r_ready ),
.data_o ( slv_resp_o.r )
);
always_comb begin
slv_r_chan = '0;
slv_r_valid = '0;
if (!r_fifo_empty) begin
slv_r_chan = mst_resps_i[r_select].r;
slv_r_valid = mst_resps_i[r_select].r_valid;
end
end
for (genvar i = 0; i < NoMstPorts; i++) begin : gen_mst_r
assign mst_reqs_o[i].r_ready = ~r_fifo_empty & slv_r_ready & (r_select == select_t'(i));
end
assign r_fifo_pop = slv_r_valid & slv_r_ready;
end
endmodule
module axi_lite_demux_intf #(
parameter int unsigned AxiAddrWidth = 32'd0,
parameter int unsigned AxiDataWidth = 32'd0,
parameter int unsigned NoMstPorts = 32'd0,
parameter int unsigned MaxTrans = 32'd0,
parameter bit FallThrough = 1'b0,
parameter bit SpillAw = 1'b1,
parameter bit SpillW = 1'b0,
parameter bit SpillB = 1'b0,
parameter bit SpillAr = 1'b1,
parameter bit SpillR = 1'b0,
parameter type select_t = logic [$clog2(NoMstPorts)-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic test_i,
input select_t slv_aw_select_i,
input select_t slv_ar_select_i,
AXI_LITE.Slave slv,
AXI_LITE.Master mst [NoMstPorts-1:0]
);
typedef logic [AxiAddrWidth-1:0] addr_t;
typedef logic [AxiDataWidth-1:0] data_t;
typedef logic [AxiDataWidth/8-1:0] strb_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
} w_chan_t;
typedef struct packed {
axi_pkg::resp_t resp;
} b_chan_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} ar_chan_t;
typedef struct packed {
data_t data;
axi_pkg::resp_t resp;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} axi_req_t;
typedef struct packed {
logic aw_ready;
logic w_ready;
b_chan_t b;
logic b_valid;
logic ar_ready;
r_chan_t r;
logic r_valid;
} axi_resp_t;
axi_req_t slv_req;
axi_resp_t slv_resp;
axi_req_t [NoMstPorts-1:0] mst_reqs;
axi_resp_t [NoMstPorts-1:0] mst_resps;
assign slv_req.aw.addr = slv.aw_addr;
assign slv_req.aw.prot = slv.aw_prot;
assign slv_req.aw_valid = slv.aw_valid;
assign slv_req.w.data = slv.w_data;
assign slv_req.w.strb = slv.w_strb;
assign slv_req.w_valid = slv.w_valid;
assign slv_req.b_ready = slv.b_ready;
assign slv_req.ar.addr = slv.ar_addr;
assign slv_req.ar.prot = slv.ar_prot;
assign slv_req.ar_valid = slv.ar_valid;
assign slv_req.r_ready = slv.r_ready;
assign slv.aw_ready = slv_resp.aw_ready;
assign slv.ar_ready = slv_resp.ar_ready;
assign slv.w_ready = slv_resp.w_ready;
assign slv.b_valid = slv_resp.b_valid;
assign slv.b_resp = slv_resp.b.resp;
assign slv.r_valid = slv_resp.r_valid;
assign slv.r_data = slv_resp.r.data;
assign slv.r_resp = slv_resp.r.resp;
for (genvar i = 0; i < NoMstPorts; i++) begin : gen_assign_mst_ports
assign mst[i].aw_addr = mst_reqs[i].aw.addr;
assign mst[i].aw_prot = mst_reqs[i].aw.prot;
assign mst[i].aw_valid = mst_reqs[i].aw_valid;
assign mst[i].w_data = mst_reqs[i].w.data;
assign mst[i].w_strb = mst_reqs[i].w.strb;
assign mst[i].w_valid = mst_reqs[i].w_valid;
assign mst[i].b_ready = mst_reqs[i].b_ready;
assign mst[i].ar_addr = mst_reqs[i].ar.addr;
assign mst[i].ar_prot = mst_reqs[i].ar.prot;
assign mst[i].ar_valid = mst_reqs[i].ar_valid;
assign mst[i].r_ready = mst_reqs[i].r_ready;
assign mst_resps[i].aw_ready = mst[i].aw_ready;
assign mst_resps[i].ar_ready = mst[i].ar_ready;
assign mst_resps[i].w_ready = mst[i].w_ready;
assign mst_resps[i].b_valid = mst[i].b_valid;
assign mst_resps[i].b.resp = mst[i].b_resp;
assign mst_resps[i].r_valid = mst[i].r_valid;
assign mst_resps[i].r.data = mst[i].r_data;
assign mst_resps[i].r.resp = mst[i].r_resp;
end
axi_lite_demux #(
.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 ),
.NoMstPorts ( NoMstPorts ),
.MaxTrans ( MaxTrans ),
.FallThrough ( FallThrough ),
.SpillAw ( SpillAw ),
.SpillW ( SpillW ),
.SpillB ( SpillB ),
.SpillAr ( SpillAr ),
.SpillR ( SpillR )
) i_axi_demux (
.clk_i,
.rst_ni,
.test_i,
.slv_req_i ( slv_req ),
.slv_aw_select_i ( slv_aw_select_i ),
.slv_ar_select_i ( slv_ar_select_i ),
.slv_resp_o ( slv_resp ),
.mst_reqs_o ( mst_reqs ),
.mst_resps_i ( mst_resps )
);
endmodule
`begin_keywords "1800-2023"
module axi_lite_dw_converter #(
parameter int unsigned AxiAddrWidth = 32'd0,
parameter int unsigned AxiSlvPortDataWidth = 32'd0,
parameter int unsigned AxiMstPortDataWidth = 32'd0,
parameter type axi_lite_aw_t = logic,
parameter type axi_lite_slv_w_t = logic,
parameter type axi_lite_mst_w_t = logic,
parameter type axi_lite_b_t = logic,
parameter type axi_lite_ar_t = logic,
parameter type axi_lite_slv_r_t = logic,
parameter type axi_lite_mst_r_t = logic,
parameter type axi_lite_slv_req_t = logic,
parameter type axi_lite_slv_res_t = logic,
parameter type axi_lite_mst_req_t = logic,
parameter type axi_lite_mst_res_t = logic
) (
input logic clk_i,
input logic rst_ni,
input axi_lite_slv_req_t slv_req_i,
output axi_lite_slv_res_t slv_res_o,
output axi_lite_mst_req_t mst_req_o,
input axi_lite_mst_res_t mst_res_i
);
localparam int unsigned AxiSlvPortStrbWidth = AxiSlvPortDataWidth / 32'd8;
localparam int unsigned AxiMstPortStrbWidth = AxiMstPortDataWidth / 32'd8;
typedef logic [AxiAddrWidth-1:0] addr_t;
if (AxiSlvPortDataWidth > AxiMstPortDataWidth) begin : gen_downsizer
localparam int unsigned DownsizeFactor = AxiSlvPortDataWidth / AxiMstPortDataWidth;
localparam int unsigned SelWidth = $clog2(DownsizeFactor);
typedef logic [SelWidth-1:0] sel_t;
localparam int unsigned SelOffset = $clog2(AxiMstPortStrbWidth);
function automatic addr_t out_address(input addr_t address, input sel_t sel);
out_address = address;
out_address[SelOffset+:SelWidth] = sel;
out_address[SelOffset-1:0] = SelOffset'(0);
endfunction : out_address
axi_lite_aw_t aw_chan_spill;
logic aw_chan_spill_valid, aw_chan_spill_ready;
spill_register #(
.T ( axi_lite_aw_t ),
.Bypass ( 1'b0 )
) i_spill_register_aw (
.clk_i,
.rst_ni,
.valid_i ( slv_req_i.aw_valid ),
.ready_o ( slv_res_o.aw_ready ),
.data_i ( slv_req_i.aw ),
.valid_o ( aw_chan_spill_valid ),
.ready_i ( aw_chan_spill_ready ),
.data_o ( aw_chan_spill )
);
sel_t aw_sel_q, aw_sel_d;
logic aw_sel_load;
always_comb begin : proc_aw_chan_oup
mst_req_o.aw = aw_chan_spill;
mst_req_o.aw.addr = out_address(aw_chan_spill.addr, aw_sel_q);
end
assign mst_req_o.aw_valid = aw_chan_spill_valid;
assign aw_chan_spill_ready = mst_res_i.aw_ready & (&aw_sel_q);
assign aw_sel_load = mst_req_o.aw_valid & mst_res_i.aw_ready;
assign aw_sel_d = sel_t'(aw_sel_q + 1'b1);
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
aw_sel_q <= ('0);
end else begin
if (aw_sel_load) begin
aw_sel_q <= (aw_sel_d);
end
end
end
axi_lite_slv_w_t w_chan_spill;
logic w_chan_spill_valid, w_chan_spill_ready;
spill_register #(
.T ( axi_lite_slv_w_t ),
.Bypass ( 1'b0 )
) i_spill_register_w (
.clk_i,
.rst_ni,
.valid_i ( slv_req_i.w_valid ),
.ready_o ( slv_res_o.w_ready ),
.data_i ( slv_req_i.w ),
.valid_o ( w_chan_spill_valid ),
.ready_i ( w_chan_spill_ready ),
.data_o ( w_chan_spill )
);
sel_t w_sel_q, w_sel_d;
logic w_sel_load;
assign mst_req_o.w = axi_lite_mst_w_t'{
data: w_chan_spill.data[w_sel_q*AxiMstPortDataWidth+:AxiMstPortDataWidth],
strb: w_chan_spill.strb[w_sel_q*AxiMstPortStrbWidth+:AxiMstPortStrbWidth],
default: '0
};
assign mst_req_o.w_valid = w_chan_spill_valid;
assign w_chan_spill_ready = mst_res_i.w_ready & (&w_sel_q);
assign w_sel_load = mst_req_o.w_valid & mst_res_i.w_ready;
assign w_sel_d = sel_t'(w_sel_q + 1'b1);
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
w_sel_q <= ('0);
end else begin
if (w_sel_load) begin
w_sel_q <= (w_sel_d);
end
end
end
sel_t b_sel_q, b_sel_d;
axi_pkg::resp_t b_resp_q, b_resp_d;
logic b_resp_load;
assign slv_res_o.b = axi_lite_b_t'{
resp: b_resp_q | mst_res_i.b.resp,
default: '0
};
assign slv_res_o.b_valid = mst_res_i.b_valid & (&b_sel_q);
assign mst_req_o.b_ready = (&b_sel_q) ? slv_req_i.b_ready : 1'b1;
assign b_sel_d = sel_t'(b_sel_q + 1'b1);
assign b_resp_d = (&b_sel_q) ? axi_pkg::RESP_OKAY : (b_resp_q | mst_res_i.b.resp);
assign b_resp_load = mst_res_i.b_valid & mst_req_o.b_ready;
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
b_sel_q <= ('0);
end else begin
if (b_resp_load) begin
b_sel_q <= (b_sel_d);
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
b_resp_q <= (axi_pkg::RESP_OKAY);
end else begin
if (b_resp_load) begin
b_resp_q <= (b_resp_d);
end
end
end
axi_lite_ar_t ar_chan_spill;
logic ar_chan_spill_valid, ar_chan_spill_ready;
spill_register #(
.T ( axi_lite_ar_t ),
.Bypass ( 1'b0 )
) i_spill_register_ar (
.clk_i,
.rst_ni,
.valid_i ( slv_req_i.ar_valid ),
.ready_o ( slv_res_o.ar_ready ),
.data_i ( slv_req_i.ar ),
.valid_o ( ar_chan_spill_valid ),
.ready_i ( ar_chan_spill_ready ),
.data_o ( ar_chan_spill )
);
sel_t ar_sel_q, ar_sel_d;
logic ar_sel_load;
always_comb begin : proc_ar_chan_oup
mst_req_o.ar = ar_chan_spill;
mst_req_o.ar.addr = out_address(ar_chan_spill.addr, ar_sel_q);
end
assign mst_req_o.ar_valid = ar_chan_spill_valid;
assign ar_chan_spill_ready = mst_res_i.ar_ready & (&ar_sel_q);
assign ar_sel_load = mst_req_o.ar_valid & mst_res_i.ar_ready;
assign ar_sel_d = sel_t'(ar_sel_q + 1'b1);
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
ar_sel_q <= ('0);
end else begin
if (ar_sel_load) begin
ar_sel_q <= (ar_sel_d);
end
end
end
sel_t r_sel_q, r_sel_d;
logic r_sel_load;
axi_lite_mst_r_t [DownsizeFactor-2:0] r_chan_mst_q;
logic [DownsizeFactor-2:0] r_chan_mst_load;
for (genvar i = 0; unsigned'(i) < (DownsizeFactor-1); i++) begin : gen_r_chan_ff
assign r_chan_mst_load[i] = (sel_t'(i) == r_sel_q) & mst_res_i.r_valid & mst_req_o.r_ready;
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
r_chan_mst_q[i] <= (axi_lite_mst_r_t'{default: '0});
end else begin
if (r_chan_mst_load[i]) begin
r_chan_mst_q[i] <= (mst_res_i.r);
end
end
end
end
assign r_sel_load = mst_res_i.r_valid & mst_req_o.r_ready;
assign r_sel_d = sel_t'(r_sel_q + 1'b1);
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
r_sel_q <= ('0);
end else begin
if (r_sel_load) begin
r_sel_q <= (r_sel_d);
end
end
end
always_comb begin : proc_r_chan_oup
slv_res_o.r = axi_lite_slv_r_t'{
resp: mst_res_i.r.resp,
default: '0
};
for (int unsigned i = 0; i < (DownsizeFactor-1); i++) begin
slv_res_o.r.resp = slv_res_o.r.resp | r_chan_mst_q[i].resp;
slv_res_o.r.data[i*AxiMstPortDataWidth+:AxiMstPortDataWidth] = r_chan_mst_q[i].data;
end
slv_res_o.r.data[(DownsizeFactor-1)*AxiMstPortDataWidth+:AxiMstPortDataWidth] =
mst_res_i.r.data;
end
assign slv_res_o.r_valid = (&r_sel_q) ? mst_res_i.r_valid : 1'b0;
assign mst_req_o.r_ready = (&r_sel_q) ? slv_req_i.r_ready : 1'b1;
end else if (AxiMstPortDataWidth > AxiSlvPortDataWidth) begin : gen_upsizer
localparam int unsigned UpsizeFactor = AxiMstPortDataWidth / AxiSlvPortDataWidth;
localparam int unsigned SelOffset = $clog2(AxiSlvPortStrbWidth);
localparam int unsigned SelWidth = $clog2(UpsizeFactor);
typedef logic [SelWidth-1:0] sel_t;
assign mst_req_o.aw = slv_req_i.aw;
logic lock_aw_q, lock_aw_d, load_aw_lock;
logic w_full, w_empty, w_push, w_pop;
sel_t aw_sel, w_sel;
always_comb begin : proc_aw_handshake
load_aw_lock = 1'b0;
mst_req_o.aw_valid = 1'b0;
slv_res_o.aw_ready = 1'b0;
w_push = 1'b0;
if (lock_aw_q) begin
mst_req_o.aw_valid = 1'b1;
slv_res_o.aw_ready = mst_res_i.aw_ready;
if (mst_res_i.aw_ready) begin
load_aw_lock = 1'b1;
end
end else begin
if (!w_full) begin
mst_req_o.aw_valid = slv_req_i.aw_valid;
slv_res_o.aw_ready = mst_res_i.aw_ready;
if (slv_req_i.aw_valid) begin
w_push = 1'b1;
if (!mst_res_i.aw_ready) begin
load_aw_lock = 1'b1;
end
end
end
end
end
assign lock_aw_d = ~lock_aw_q;
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
lock_aw_q <= (1'b0);
end else begin
if (load_aw_lock) begin
lock_aw_q <= (lock_aw_d);
end
end
end
assign aw_sel = sel_t'(slv_req_i.aw.addr >> SelOffset);
fifo_v3 #(
.FALL_THROUGH ( 1'b1 ),
.DEPTH ( UpsizeFactor ),
.dtype ( sel_t )
) i_fifo_w_sel (
.clk_i,
.rst_ni,
.flush_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.full_o ( w_full ),
.empty_o ( w_empty ),
.usage_o ( ),
.data_i ( aw_sel ),
.push_i ( w_push ),
.data_o ( w_sel ),
.pop_i ( w_pop )
);
assign w_pop = mst_req_o.w_valid & mst_res_i.w_ready;
assign mst_req_o.w = axi_lite_mst_w_t'{
data: {UpsizeFactor{slv_req_i.w.data}},
strb: {AxiMstPortStrbWidth{1'b0}} | (slv_req_i.w.strb << (w_sel * AxiSlvPortStrbWidth)),
default: '0
};
assign mst_req_o.w_valid = slv_req_i.w_valid & ~w_empty;
assign slv_res_o.w_ready = mst_res_i.w_ready & ~w_empty;
assign slv_res_o.b = mst_res_i.b;
assign slv_res_o.b_valid = mst_res_i.b_valid;
assign mst_req_o.b_ready = slv_req_i.b_ready;
assign mst_req_o.ar = slv_req_i.ar;
logic lock_ar_q, lock_ar_d, load_ar_lock;
logic r_full, r_empty, r_push, r_pop;
sel_t ar_sel, r_sel;
always_comb begin : proc_ar_handshake
load_ar_lock = 1'b0;
mst_req_o.ar_valid = 1'b0;
slv_res_o.ar_ready = 1'b0;
r_push = 1'b0;
if (lock_ar_q) begin
mst_req_o.ar_valid = 1'b1;
slv_res_o.ar_ready = mst_res_i.ar_ready;
if (mst_res_i.ar_ready) begin
load_ar_lock = 1'b1;
end
end else begin
if (!r_full) begin
mst_req_o.ar_valid = slv_req_i.ar_valid;
slv_res_o.ar_ready = mst_res_i.ar_ready;
if (slv_req_i.ar_valid) begin
r_push = 1'b1;
if (!mst_res_i.ar_ready) begin
load_ar_lock = 1'b1;
end
end
end
end
end
assign lock_ar_d = ~lock_ar_q;
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
lock_ar_q <= (1'b0);
end else begin
if (load_ar_lock) begin
lock_ar_q <= (lock_ar_d);
end
end
end
assign ar_sel = sel_t'(slv_req_i.ar.addr >> SelOffset);
fifo_v3 #(
.FALL_THROUGH ( 1'b1 ),
.DEPTH ( UpsizeFactor ),
.dtype ( sel_t )
) i_fifo_r_sel (
.clk_i,
.rst_ni,
.flush_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.full_o ( r_full ),
.empty_o ( r_empty ),
.usage_o ( ),
.data_i ( ar_sel ),
.push_i ( r_push ),
.data_o ( r_sel ),
.pop_i ( r_pop )
);
assign r_pop = slv_res_o.r_valid & slv_req_i.r_ready;
assign slv_res_o.r = axi_lite_slv_r_t'{
data: mst_res_i.r.data[(r_sel*AxiSlvPortDataWidth)+:AxiSlvPortDataWidth],
resp: mst_res_i.r.resp,
default: '0
};
assign slv_res_o.r_valid = mst_res_i.r_valid & ~r_empty;
assign mst_req_o.r_ready = slv_req_i.r_ready & ~r_empty;
end else begin : gen_passthrough
assign mst_req_o = slv_req_i;
assign slv_res_o = mst_res_i;
end
endmodule
module axi_lite_dw_converter_intf #(
parameter int unsigned AXI_ADDR_WIDTH = 32'd0,
parameter int unsigned AXI_SLV_PORT_DATA_WIDTH = 32'd0,
parameter int unsigned AXI_MST_PORT_DATA_WIDTH = 32'd0
) (
input logic clk_i,
input logic rst_ni,
AXI_LITE.Slave slv,
AXI_LITE.Master mst
);
localparam int unsigned AxiStrbWidthSlv = AXI_SLV_PORT_DATA_WIDTH / 32'd8;
localparam int unsigned AxiStrbWidthMst = AXI_MST_PORT_DATA_WIDTH / 32'd8;
typedef logic [AXI_ADDR_WIDTH-1:0] lite_addr_t;
typedef logic [AXI_SLV_PORT_DATA_WIDTH-1:0] lite_data_slv_t;
typedef logic [AxiStrbWidthSlv-1:0] lite_strb_slv_t;
typedef logic [AXI_MST_PORT_DATA_WIDTH-1:0] lite_data_mst_t;
typedef logic [AxiStrbWidthMst-1:0] lite_strb_mst_t;
typedef struct packed {
lite_addr_t addr;
axi_pkg::prot_t prot;
} aw_chan_lite_t;
typedef struct packed {
lite_data_slv_t data;
lite_strb_slv_t strb;
} w_chan_lite_slv_t;
typedef struct packed {
lite_data_mst_t data;
lite_strb_mst_t strb;
} w_chan_lite_mst_t;
typedef struct packed {
axi_pkg::resp_t resp;
} b_chan_lite_t;
typedef struct packed {
lite_addr_t addr;
axi_pkg::prot_t prot;
} ar_chan_lite_t;
typedef struct packed {
lite_data_slv_t data;
axi_pkg::resp_t resp;
} r_chan_lite_slv_t;
typedef struct packed {
lite_data_mst_t data;
axi_pkg::resp_t resp;
} r_chan_lite_mst_t;
typedef struct packed {
aw_chan_lite_t aw;
logic aw_valid;
w_chan_lite_slv_t w;
logic w_valid;
logic b_ready;
ar_chan_lite_t ar;
logic ar_valid;
logic r_ready;
} req_lite_slv_t;
typedef struct packed {
logic aw_ready;
logic w_ready;
b_chan_lite_t b;
logic b_valid;
logic ar_ready;
r_chan_lite_slv_t r;
logic r_valid;
} res_lite_slv_t;
typedef struct packed {
aw_chan_lite_t aw;
logic aw_valid;
w_chan_lite_mst_t w;
logic w_valid;
logic b_ready;
ar_chan_lite_t ar;
logic ar_valid;
logic r_ready;
} req_lite_mst_t;
typedef struct packed {
logic aw_ready;
logic w_ready;
b_chan_lite_t b;
logic b_valid;
logic ar_ready;
r_chan_lite_mst_t r;
logic r_valid;
} res_lite_mst_t;
req_lite_slv_t slv_req;
res_lite_slv_t slv_res;
req_lite_mst_t mst_req;
res_lite_mst_t mst_res;
assign slv_req.aw.addr = slv.aw_addr;
assign slv_req.aw.prot = slv.aw_prot;
assign slv_req.aw_valid = slv.aw_valid;
assign slv_req.w.data = slv.w_data;
assign slv_req.w.strb = slv.w_strb;
assign slv_req.w_valid = slv.w_valid;
assign slv_req.b_ready = slv.b_ready;
assign slv_req.ar.addr = slv.ar_addr;
assign slv_req.ar.prot = slv.ar_prot;
assign slv_req.ar_valid = slv.ar_valid;
assign slv_req.r_ready = slv.r_ready;
assign slv.aw_ready = slv_res.aw_ready;
assign slv.ar_ready = slv_res.ar_ready;
assign slv.w_ready = slv_res.w_ready;
assign slv.b_valid = slv_res.b_valid;
assign slv.b_resp = slv_res.b.resp;
assign slv.r_valid = slv_res.r_valid;
assign slv.r_data = slv_res.r.data;
assign slv.r_resp = slv_res.r.resp;
assign mst.aw_addr = mst_req.aw.addr;
assign mst.aw_prot = mst_req.aw.prot;
assign mst.aw_valid = mst_req.aw_valid;
assign mst.w_data = mst_req.w.data;
assign mst.w_strb = mst_req.w.strb;
assign mst.w_valid = mst_req.w_valid;
assign mst.b_ready = mst_req.b_ready;
assign mst.ar_addr = mst_req.ar.addr;
assign mst.ar_prot = mst_req.ar.prot;
assign mst.ar_valid = mst_req.ar_valid;
assign mst.r_ready = mst_req.r_ready;
assign mst_res.aw_ready = mst.aw_ready;
assign mst_res.ar_ready = mst.ar_ready;
assign mst_res.w_ready = mst.w_ready;
assign mst_res.b_valid = mst.b_valid;
assign mst_res.b.resp = mst.b_resp;
assign mst_res.r_valid = mst.r_valid;
assign mst_res.r.data = mst.r_data;
assign mst_res.r.resp = mst.r_resp;
axi_lite_dw_converter #(
.AxiAddrWidth ( AXI_ADDR_WIDTH ),
.AxiSlvPortDataWidth ( AXI_SLV_PORT_DATA_WIDTH ),
.AxiMstPortDataWidth ( AXI_MST_PORT_DATA_WIDTH ),
.axi_lite_aw_t ( aw_chan_lite_t ),
.axi_lite_slv_w_t ( w_chan_lite_slv_t ),
.axi_lite_mst_w_t ( w_chan_lite_mst_t ),
.axi_lite_b_t ( b_chan_lite_t ),
.axi_lite_ar_t ( ar_chan_lite_t ),
.axi_lite_slv_r_t ( r_chan_lite_slv_t ),
.axi_lite_mst_r_t ( r_chan_lite_mst_t ),
.axi_lite_slv_req_t ( req_lite_slv_t ),
.axi_lite_slv_res_t ( res_lite_slv_t ),
.axi_lite_mst_req_t ( req_lite_mst_t ),
.axi_lite_mst_res_t ( res_lite_mst_t )
) i_axi_lite_dw_converter (
.clk_i,
.rst_ni,
.slv_req_i ( slv_req ),
.slv_res_o ( slv_res ),
.mst_req_o ( mst_req ),
.mst_res_i ( mst_res )
);
endmodule
`begin_keywords "1800-2023"
module axi_lite_from_mem #(
parameter int unsigned MemAddrWidth = 32'd0,
parameter int unsigned AxiAddrWidth = 32'd0,
parameter int unsigned DataWidth = 32'd0,
parameter int unsigned MaxRequests = 32'd0,
parameter axi_pkg::prot_t AxiProt = 3'b000,
parameter type axi_req_t = logic,
parameter type axi_rsp_t = logic,
parameter type mem_addr_t = logic[MemAddrWidth-1:0],
parameter type axi_addr_t = logic[AxiAddrWidth-1:0],
parameter type data_t = logic[DataWidth-1:0],
parameter type strb_t = logic[DataWidth/8-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic mem_req_i,
input mem_addr_t mem_addr_i,
input logic mem_we_i,
input data_t mem_wdata_i,
input strb_t mem_be_i,
output logic mem_gnt_o,
output logic mem_rsp_valid_o,
output data_t mem_rsp_rdata_o,
output logic mem_rsp_error_o,
output axi_req_t axi_req_o,
input axi_rsp_t axi_rsp_i
);
logic fifo_full, fifo_empty;
logic aw_sent_q, aw_sent_d;
logic w_sent_q, w_sent_d;
always_comb begin
axi_req_o.aw = '0;
axi_req_o.aw.addr = axi_addr_t'(mem_addr_i);
axi_req_o.aw.prot = AxiProt;
axi_req_o.aw_valid = 1'b0;
axi_req_o.w = '0;
axi_req_o.w.data = mem_wdata_i;
axi_req_o.w.strb = mem_be_i;
axi_req_o.w_valid = 1'b0;
axi_req_o.ar = '0;
axi_req_o.ar.addr = axi_addr_t'(mem_addr_i);
axi_req_o.ar.prot = AxiProt;
axi_req_o.ar_valid = 1'b0;
mem_gnt_o = 1'b0;
aw_sent_d = aw_sent_q;
w_sent_d = w_sent_q;
if (mem_req_i && !fifo_full) begin
if (!mem_we_i) begin
axi_req_o.ar_valid = 1'b1;
mem_gnt_o = axi_rsp_i.ar_ready;
end else begin
unique case ({aw_sent_q, w_sent_q})
2'b00 : begin
axi_req_o.aw_valid = 1'b1;
axi_req_o.w_valid = 1'b1;
unique case ({axi_rsp_i.aw_ready, axi_rsp_i.w_ready})
2'b01 : begin
w_sent_d = 1'b1;
end
2'b10 : begin
aw_sent_d = 1'b1;
end
2'b11 : begin
mem_gnt_o = 1'b1;
end
default : ;
endcase
end
2'b10 : begin
axi_req_o.w_valid = 1'b1;
if (axi_rsp_i.w_ready) begin
aw_sent_d = 1'b0;
mem_gnt_o = 1'b1;
end
end
2'b01 : begin
axi_req_o.aw_valid = 1'b1;
if (axi_rsp_i.aw_ready) begin
w_sent_d = 1'b0;
mem_gnt_o = 1'b1;
end
end
default : begin
aw_sent_d = 1'b0;
w_sent_d = 1'b0;
end
endcase
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
aw_sent_q <= (1'b0);
end else begin
aw_sent_q <= (aw_sent_d);
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
w_sent_q <= (1'b0);
end else begin
w_sent_q <= (w_sent_d);
end
end
logic rsp_sel;
fifo_v3 #(
.FALL_THROUGH ( 1'b0 ),
.DEPTH ( MaxRequests ),
.dtype ( logic )
) i_fifo_rsp_mux (
.clk_i,
.rst_ni,
.flush_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.full_o ( fifo_full ),
.empty_o ( fifo_empty ),
.usage_o ( ),
.data_i ( mem_we_i ),
.push_i ( mem_gnt_o ),
.data_o ( rsp_sel ),
.pop_i ( mem_rsp_valid_o )
);
assign axi_req_o.b_ready = !fifo_empty && rsp_sel;
assign axi_req_o.r_ready = !fifo_empty && !rsp_sel;
assign mem_rsp_rdata_o = axi_rsp_i.r.data;
assign mem_rsp_error_o = rsp_sel ?
(axi_rsp_i.b.resp inside {axi_pkg::RESP_SLVERR, axi_pkg::RESP_DECERR}) :
(axi_rsp_i.r.resp inside {axi_pkg::RESP_SLVERR, axi_pkg::RESP_DECERR});
assign mem_rsp_valid_o = (axi_rsp_i.b_valid && axi_req_o.b_ready) ||
(axi_rsp_i.r_valid && axi_req_o.r_ready);
endmodule
`begin_keywords "1800-2023"
module axi_lite_join_intf (
AXI_LITE.Slave in,
AXI_LITE.Master out
);
assign out.aw_addr = in.aw_addr;
assign out.aw_prot = in.aw_prot;
assign out.aw_valid = in.aw_valid;
assign in.aw_ready = out.aw_ready;
assign out.w_data = in.w_data;
assign out.w_strb = in.w_strb;
assign out.w_valid = in.w_valid;
assign in.w_ready = out.w_ready;
assign in.b_resp = out.b_resp;
assign in.b_valid = out.b_valid;
assign out.b_ready = in.b_ready;
assign out.ar_addr = in.ar_addr;
assign out.ar_prot = in.ar_prot;
assign out.ar_valid = in.ar_valid;
assign in.ar_ready = out.ar_ready;
assign in.r_data = out.r_data;
assign in.r_resp = out.r_resp;
assign in.r_valid = out.r_valid;
assign out.r_ready = in.r_ready;
endmodule
`begin_keywords "1800-2023"
module axi_lite_lfsr #(
parameter int unsigned DataWidth = 32'd0,
parameter type axi_lite_req_t = logic,
parameter type axi_lite_rsp_t = logic
)(
input logic clk_i,
input logic rst_ni,
input logic testmode_i,
input axi_lite_req_t req_i,
output axi_lite_rsp_t rsp_o,
input logic w_ser_data_i,
output logic w_ser_data_o,
input logic w_ser_en_i,
input logic r_ser_data_i,
output logic r_ser_data_o,
input logic r_ser_en_i
);
localparam int unsigned StrbWidth = DataWidth / 8;
logic w_lfsr_en;
logic r_lfsr_en;
logic w_b_fifo_ready;
logic w_b_fifo_valid;
logic [DataWidth-1:0] w_data_in, w_data_out;
assign rsp_o.aw_ready = !w_ser_en_i;
axi_opt_lfsr #(
.Width ( DataWidth )
) i_axi_opt_lfsr_w (
.clk_i,
.rst_ni,
.en_i ( w_lfsr_en ),
.ser_data_i ( w_ser_data_i ),
.ser_data_o ( w_ser_data_o ),
.ser_en_i ( w_ser_en_i ),
.inp_en_i ( w_lfsr_en ),
.data_i ( w_data_in ),
.data_o ( w_data_out )
);
assign w_lfsr_en = req_i.w_valid & rsp_o.w_ready;
assign rsp_o.w_ready = !w_ser_en_i & w_b_fifo_ready;
always_comb begin : gen_data_strb_connect
for (int unsigned i = 0; i < StrbWidth; i++) begin : gen_strb_en
if (req_i.w.strb[i] == 1'b0) begin
w_data_in[i*8+:8] = w_data_out[i*8+:8];
end else if (req_i.w.strb[i] == 1'b1) begin
w_data_in[i*8+:8] = req_i.w.data[i*8+:8];
end else begin
w_data_in[i*8+:8] = 'x;
end
end
end
stream_fifo #(
.FALL_THROUGH ( 1'b0 ),
.DATA_WIDTH ( 'd1 ),
.DEPTH ( 'd2 )
) i_stream_fifo_w_b (
.clk_i,
.rst_ni,
.testmode_i,
.flush_i ( 1'b0 ),
.usage_o ( ),
.data_i ( 1'b0 ),
.valid_i ( req_i.w_valid ),
.ready_o ( w_b_fifo_ready ),
.data_o ( ),
.valid_o ( w_b_fifo_valid ),
.ready_i ( req_i.b_ready )
);
assign rsp_o.b.resp = axi_pkg::RESP_OKAY;
assign rsp_o.b_valid = w_b_fifo_valid;
assign rsp_o.ar_ready = !w_ser_en_i;
axi_opt_lfsr #(
.Width ( DataWidth )
) i_axi_opt_lfsr_r (
.clk_i,
.rst_ni,
.en_i ( r_lfsr_en ),
.ser_data_i ( r_ser_data_i ),
.ser_data_o ( r_ser_data_o ),
.ser_en_i ( r_ser_en_i ),
.inp_en_i ( 1'b0 ),
.data_i ( ),
.data_o ( rsp_o.r.data )
);
assign rsp_o.r.resp = axi_pkg::RESP_OKAY;
assign r_lfsr_en = req_i.r_ready & rsp_o.r_valid;
assign rsp_o.r_valid = !r_ser_en_i;
endmodule : axi_lite_lfsr
module axi_opt_lfsr #(
parameter int unsigned Width = 32'd0
) (
input logic clk_i,
input logic rst_ni,
input logic en_i,
input logic ser_data_i,
output logic ser_data_o,
input logic ser_en_i,
input logic inp_en_i,
input logic [Width-1:0] data_i,
output logic [Width-1:0] data_o
);
localparam int unsigned LfsrIdxWidth = cf_math_pkg::idx_width(Width);
localparam int unsigned MaxNumTabs = 4;
typedef logic [LfsrIdxWidth:0] xnor_entry_t [MaxNumTabs-1:0];
xnor_entry_t XnorFeedback;
logic [Width-1:0] reg_d, reg_q;
logic xnor_feedback;
always_comb begin : gen_register
xnor_feedback = reg_q[XnorFeedback[MaxNumTabs-1]-1];
case (Width)
'd8 : XnorFeedback = { 'd8, 'd6, 'd5, 'd4 };
'd16 : XnorFeedback = { 'd16, 'd14, 'd13, 'd11 };
'd32 : XnorFeedback = { 'd32, 'd30, 'd26, 'd25 };
'd64 : XnorFeedback = { 'd64, 'd63, 'd61, 'd60 };
'd128 : XnorFeedback = { 'd128, 'd127, 'd126, 'd119 };
'd256 : XnorFeedback = { 'd256, 'd256, 'd521, 'd246 };
'd512 : XnorFeedback = { 'd512, 'd510, 'd507, 'd504 };
'd1024 : XnorFeedback = { 'd1024, 'd1015, 'd1002, 'd1001 };
default : XnorFeedback = { 'x, 'x, 'x, 'x };
endcase
if (inp_en_i) begin
for (int unsigned i = 0; i < Width - 1; i++) begin : gen_comp_conection
reg_d[i] = reg_q[i+1] ^ data_i[i];
end
end else begin
for (int unsigned i = 0; i < Width - 1; i++) begin : gen_gen_conection
reg_d[i] = reg_q[i+1];
end
end
if (ser_en_i) begin
reg_d[Width-1] = ser_data_i;
end else begin
for (int unsigned t = 0; t < MaxNumTabs - 1; t++) begin : gen_feedback_path
xnor_feedback = xnor_feedback;
if (XnorFeedback[t] != 0) begin
xnor_feedback = xnor_feedback ^ reg_q[XnorFeedback[t]-1];
end
end
reg_d[Width-1] = inp_en_i ? xnor_feedback ^ data_i[Width-1] : xnor_feedback;
end
end
assign ser_data_o = reg_q[0];
assign data_o = reg_q;
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
reg_q <= ('1);
end else begin
if (en_i | ser_en_i) begin
reg_q <= (reg_d);
end
end
end
endmodule : axi_opt_lfsr
`begin_keywords "1800-2023"
module axi_lite_mailbox #(
parameter int unsigned MailboxDepth = 32'd0,
parameter bit unsigned IrqEdgeTrig = 1'b0,
parameter bit unsigned IrqActHigh = 1'b1,
parameter int unsigned AxiAddrWidth = 32'd0,
parameter int unsigned AxiDataWidth = 32'd0,
parameter type req_lite_t = logic,
parameter type resp_lite_t = logic,
parameter type addr_t = logic [AxiAddrWidth-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic test_i,
input req_lite_t [1:0] slv_reqs_i,
output resp_lite_t [1:0] slv_resps_o,
output logic [1:0] irq_o,
input addr_t [1:0] base_addr_i
);
localparam int unsigned FifoUsageWidth = $clog2(MailboxDepth);
typedef logic [AxiDataWidth-1:0] data_t;
typedef logic [FifoUsageWidth:0] usage_t;
logic [1:0] mbox_full, mbox_empty;
logic [1:0] mbox_push, mbox_pop;
logic [1:0] w_mbox_flush, r_mbox_flush;
data_t [1:0] mbox_w_data, mbox_r_data;
usage_t [1:0] mbox_usage;
logic [1:0] slv_irq;
logic [1:0] clear_irq;
axi_lite_mailbox_slave #(
.MailboxDepth ( MailboxDepth ),
.AxiAddrWidth ( AxiAddrWidth ),
.AxiDataWidth ( AxiDataWidth ),
.req_lite_t ( req_lite_t ),
.resp_lite_t ( resp_lite_t ),
.addr_t ( addr_t ),
.data_t ( data_t ),
.usage_t ( usage_t )
) i_slv_port_0 (
.clk_i,
.rst_ni,
.slv_req_i ( slv_reqs_i[0] ),
.slv_resp_o ( slv_resps_o[0] ),
.base_addr_i ( base_addr_i[0] ),
.mbox_w_data_o ( mbox_w_data[0] ),
.mbox_w_full_i ( mbox_full[0] ),
.mbox_w_push_o ( mbox_push[0] ),
.mbox_w_flush_o ( w_mbox_flush[0] ),
.mbox_w_usage_i ( mbox_usage[0] ),
.mbox_r_data_i ( mbox_r_data[0] ),
.mbox_r_empty_i ( mbox_empty[1] ),
.mbox_r_pop_o ( mbox_pop[0] ),
.mbox_r_flush_o ( r_mbox_flush[0] ),
.mbox_r_usage_i ( mbox_usage[1] ),
.irq_o ( slv_irq[0] ),
.clear_irq_o ( clear_irq[0] )
);
axi_lite_mailbox_slave #(
.MailboxDepth ( MailboxDepth ),
.AxiAddrWidth ( AxiAddrWidth ),
.AxiDataWidth ( AxiDataWidth ),
.req_lite_t ( req_lite_t ),
.resp_lite_t ( resp_lite_t ),
.addr_t ( addr_t ),
.data_t ( data_t ),
.usage_t ( usage_t )
) i_slv_port_1 (
.clk_i,
.rst_ni,
.slv_req_i ( slv_reqs_i[1] ),
.slv_resp_o ( slv_resps_o[1] ),
.base_addr_i ( base_addr_i[1] ),
.mbox_w_data_o ( mbox_w_data[1] ),
.mbox_w_full_i ( mbox_full[1] ),
.mbox_w_push_o ( mbox_push[1] ),
.mbox_w_flush_o ( w_mbox_flush[1] ),
.mbox_w_usage_i ( mbox_usage[1] ),
.mbox_r_data_i ( mbox_r_data[1] ),
.mbox_r_empty_i ( mbox_empty[0] ),
.mbox_r_pop_o ( mbox_pop[1] ),
.mbox_r_flush_o ( r_mbox_flush[1] ),
.mbox_r_usage_i ( mbox_usage[0] ),
.irq_o ( slv_irq[1] ),
.clear_irq_o ( clear_irq[1] )
);
logic [FifoUsageWidth-1:0] mbox_0_to_1_usage, mbox_1_to_0_usage;
fifo_v3 #(
.FALL_THROUGH ( 1'b0 ),
.DEPTH ( MailboxDepth ),
.dtype ( data_t )
) i_mbox_0_to_1 (
.clk_i,
.rst_ni,
.testmode_i( test_i ),
.flush_i ( w_mbox_flush[0] | r_mbox_flush[1] ),
.full_o ( mbox_full[0] ),
.empty_o ( mbox_empty[0] ),
.usage_o ( mbox_0_to_1_usage ),
.data_i ( mbox_w_data[0] ),
.push_i ( mbox_push[0] ),
.data_o ( mbox_r_data[1] ),
.pop_i ( mbox_pop[1] )
);
assign mbox_usage[0] = {mbox_full[0], mbox_0_to_1_usage};
fifo_v3 #(
.FALL_THROUGH ( 1'b0 ),
.DEPTH ( MailboxDepth ),
.dtype ( data_t )
) i_mbox_1_to_0 (
.clk_i,
.rst_ni,
.testmode_i( test_i ),
.flush_i ( w_mbox_flush[1] | r_mbox_flush[0] ),
.full_o ( mbox_full[1] ),
.empty_o ( mbox_empty[1] ),
.usage_o ( mbox_1_to_0_usage ),
.data_i ( mbox_w_data[1] ),
.push_i ( mbox_push[1] ),
.data_o ( mbox_r_data[0] ),
.pop_i ( mbox_pop[0] )
);
assign mbox_usage[1] = {mbox_full[1], mbox_1_to_0_usage};
for (genvar i = 0; i < 2; i++) begin : gen_irq_conversion
if (IrqEdgeTrig) begin : gen_irq_edge
logic irq_q, irq_d, update_irq;
always_comb begin
irq_d = irq_q;
update_irq = 1'b0;
irq_o[i] = ~IrqActHigh;
if (clear_irq[i]) begin
irq_d = 1'b0;
update_irq = 1'b1;
end else if (!irq_q && slv_irq[i]) begin
irq_d = 1'b1;
update_irq = 1'b1;
irq_o[i] = IrqActHigh;
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
irq_q <= ('0);
end else begin
if (update_irq) begin
irq_q <= (irq_d);
end
end
end
end else begin : gen_irq_level
assign irq_o[i] = (IrqActHigh) ? slv_irq[i] : ~slv_irq[i];
end
end
endmodule
module axi_lite_mailbox_slave #(
parameter int unsigned MailboxDepth = 32'd16,
parameter int unsigned AxiAddrWidth = 32'd32,
parameter int unsigned AxiDataWidth = 32'd32,
parameter type req_lite_t = logic,
parameter type resp_lite_t = logic,
parameter type addr_t = logic [AxiAddrWidth-1:0],
parameter type data_t = logic [AxiDataWidth-1:0],
parameter type usage_t = logic
) (
input logic clk_i,
input logic rst_ni,
input req_lite_t slv_req_i,
output resp_lite_t slv_resp_o,
input addr_t base_addr_i,
output data_t mbox_w_data_o,
input logic mbox_w_full_i,
output logic mbox_w_push_o,
output logic mbox_w_flush_o,
input usage_t mbox_w_usage_i,
input data_t mbox_r_data_i,
input logic mbox_r_empty_i,
output logic mbox_r_pop_o,
output logic mbox_r_flush_o,
input usage_t mbox_r_usage_i,
output logic irq_o,
output logic clear_irq_o
);
typedef struct packed {
axi_pkg::resp_t resp;
} b_chan_lite_t;
typedef struct packed {
data_t data;
axi_pkg::resp_t resp;
} r_chan_lite_t;
localparam int unsigned NoRegs = 32'd10;
typedef enum logic [3:0] {
MBOXW = 4'd0,
MBOXR = 4'd1,
STATUS = 4'd2,
ERROR = 4'd3,
WIRQT = 4'd4,
RIRQT = 4'd5,
IRQS = 4'd6,
IRQEN = 4'd7,
IRQP = 4'd8,
CTRL = 4'd9
} reg_e;
typedef struct packed {
int unsigned idx;
addr_t start_addr;
addr_t end_addr;
} rule_t;
typedef logic [$clog2(NoRegs)-1:0] idx_t;
logic b_valid, b_ready;
b_chan_lite_t b_chan;
logic r_valid, r_ready;
r_chan_lite_t r_chan;
rule_t [NoRegs-1:0] addr_map;
for (genvar i = 0; i < NoRegs; i++) begin : gen_addr_map
assign addr_map[i] = '{
idx: i,
start_addr: base_addr_i + i * (AxiDataWidth / 8),
end_addr: base_addr_i + (i + 1) * (AxiDataWidth / 8),
default: '0
};
end
idx_t w_reg_idx, r_reg_idx;
logic dec_w_valid, dec_r_valid;
logic [3:0] status_q;
logic [1:0] error_q, error_d;
data_t wirqt_q, wirqt_d;
data_t rirqt_q, rirqt_d;
logic [2:0] irqs_q, irqs_d;
logic [2:0] irqen_q, irqen_d;
logic [2:0] irqp_q;
logic [1:0] ctrl_q;
logic update_regs;
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
error_q <= ('0);
end else begin
if (update_regs) begin
error_q <= (error_d);
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
wirqt_q <= ('0);
end else begin
if (update_regs) begin
wirqt_q <= (wirqt_d);
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
rirqt_q <= ('0);
end else begin
if (update_regs) begin
rirqt_q <= (rirqt_d);
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
irqs_q <= ('0);
end else begin
if (update_regs) begin
irqs_q <= (irqs_d);
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
irqen_q <= ('0);
end else begin
if (update_regs) begin
irqen_q <= (irqen_d);
end
end
end
for (genvar i = 0; i < (AxiDataWidth/8); i++) begin : gen_w_mbox_data
assign mbox_w_data_o[i*8+:8] = slv_req_i.w.strb[i] ? slv_req_i.w.data[i*8+:8] : '0;
end
assign status_q = { mbox_r_usage_i > usage_t'(rirqt_q),
mbox_w_usage_i > usage_t'(wirqt_q),
mbox_w_full_i,
mbox_r_empty_i };
assign irqp_q = irqs_q & irqen_q;
assign ctrl_q = {mbox_r_flush_o, mbox_w_flush_o};
assign irq_o = |irqp_q;
always_comb begin
slv_resp_o.aw_ready = 1'b0;
slv_resp_o.w_ready = 1'b0;
b_chan = '{resp: axi_pkg::RESP_SLVERR};
b_valid = 1'b0;
slv_resp_o.ar_ready = 1'b0;
r_chan = '{data: '0, resp: axi_pkg::RESP_SLVERR};
r_valid = 1'b0;
error_d = error_q;
wirqt_d = wirqt_q;
rirqt_d = rirqt_q;
irqs_d = irqs_q;
irqen_d = irqen_q;
update_regs = 1'b0;
mbox_w_push_o = 1'b0;
mbox_w_flush_o = 1'b0;
mbox_r_pop_o = 1'b0;
mbox_r_flush_o = 1'b0;
clear_irq_o = 1'b0;
if (!irqs_q[1] && status_q[3]) begin
irqs_d[1] = 1'b1;
update_regs = 1'b1;
end
if (!irqs_q[0] && status_q[2]) begin
irqs_d[0] = 1'b1;
update_regs = 1'b1;
end
if (slv_req_i.ar_valid) begin
if (dec_r_valid) begin
unique case (reg_e'(r_reg_idx))
MBOXW: r_chan = '{data: data_t'( 32'hFEEDC0DE ), resp: axi_pkg::RESP_OKAY};
MBOXR: begin
if (!mbox_r_empty_i) begin
r_chan = '{data: data_t'( mbox_r_data_i ), resp: axi_pkg::RESP_OKAY};
mbox_r_pop_o = 1'b1;
end else begin
r_chan = '{data: data_t'( 32'hFEEDDEAD ), resp: axi_pkg::RESP_SLVERR};
error_d[0] = 1'b1;
irqs_d[2] = 1'b1;
update_regs = 1'b1;
end
end
STATUS: r_chan = '{data: data_t'( status_q ), resp: axi_pkg::RESP_OKAY};
ERROR: begin
r_chan = '{data: data_t'( error_q ), resp: axi_pkg::RESP_OKAY};
error_d = '0;
update_regs = 1'b1;
end
WIRQT: r_chan = '{data: data_t'( wirqt_q ), resp: axi_pkg::RESP_OKAY};
RIRQT: r_chan = '{data: data_t'( rirqt_q ), resp: axi_pkg::RESP_OKAY};
IRQS: r_chan = '{data: data_t'( irqs_q ), resp: axi_pkg::RESP_OKAY};
IRQEN: r_chan = '{data: data_t'( irqen_q ), resp: axi_pkg::RESP_OKAY};
IRQP: r_chan = '{data: data_t'( irqp_q ), resp: axi_pkg::RESP_OKAY};
CTRL: r_chan = '{data: data_t'( ctrl_q ), resp: axi_pkg::RESP_OKAY};
default: ;
endcase
end
r_valid = 1'b1;
if (r_ready) begin
slv_resp_o.ar_ready = 1'b1;
end
end
if (slv_req_i.aw_valid && slv_req_i.w_valid) begin
b_valid = 1'b1;
if (b_ready) begin
if (dec_w_valid) begin
unique case (reg_e'(w_reg_idx))
MBOXW: begin
if (!mbox_w_full_i) begin
mbox_w_push_o = 1'b1;
b_chan = '{resp: axi_pkg::RESP_OKAY};
end else begin
error_d[1] = 1'b1;
irqs_d[2] = 1'b1;
update_regs = 1'b1;
end
end
WIRQT: begin
for (int unsigned i = 0; i < AxiDataWidth/8; i++) begin
wirqt_d[i*8+:8] = slv_req_i.w.strb[i] ? slv_req_i.w.data[i*8+:8] : wirqt_d[i*8+:8];
end
if (wirqt_d >= data_t'(MailboxDepth)) begin
wirqt_d = data_t'(MailboxDepth) - data_t'(32'd1);
end
update_regs = 1'b1;
b_chan = '{resp: axi_pkg::RESP_OKAY};
end
RIRQT: begin
for (int unsigned i = 0; i < AxiDataWidth/8; i++) begin
rirqt_d[i*8+:8] = slv_req_i.w.strb[i] ? slv_req_i.w.data[i*8+:8] : rirqt_d[i*8+:8];
end
if (rirqt_d >= data_t'(MailboxDepth)) begin
rirqt_d = data_t'(MailboxDepth) - data_t'(32'd1);
end
update_regs = 1'b1;
b_chan = '{resp: axi_pkg::RESP_OKAY};
end
IRQS: begin
if (slv_req_i.w.strb[0]) begin
irqs_d[2] = slv_req_i.w.data[2] ? 1'b0 : irqs_d[2];
irqs_d[1] = slv_req_i.w.data[1] ? 1'b0 : irqs_d[1];
irqs_d[0] = slv_req_i.w.data[0] ? 1'b0 : irqs_d[0];
clear_irq_o = 1'b1;
update_regs = 1'b1;
end
b_chan = '{resp: axi_pkg::RESP_OKAY};
end
IRQEN: begin
if (slv_req_i.w.strb[0]) begin
irqen_d[2:0] = slv_req_i.w.data[2:0];
update_regs = 1'b1;
end
b_chan = '{resp: axi_pkg::RESP_OKAY};
end
CTRL: begin
if (slv_req_i.w.strb[0]) begin
mbox_r_flush_o = slv_req_i.w.data[1];
mbox_w_flush_o = slv_req_i.w.data[0];
end
b_chan = '{resp: axi_pkg::RESP_OKAY};
end
default : ;
endcase
end
slv_resp_o.aw_ready = 1'b1;
slv_resp_o.w_ready = 1'b1;
end
end
end
addr_decode #(
.NoIndices( NoRegs ),
.NoRules ( NoRegs ),
.addr_t ( addr_t ),
.rule_t ( rule_t )
) i_waddr_decode (
.addr_i ( slv_req_i.aw.addr ),
.addr_map_i ( addr_map ),
.idx_o ( w_reg_idx ),
.dec_valid_o ( dec_w_valid ),
.dec_error_o ( ),
.en_default_idx_i ( 1'b0 ),
.default_idx_i ( '0 )
);
spill_register #(
.T ( b_chan_lite_t )
) i_b_chan_outp (
.clk_i,
.rst_ni,
.valid_i ( b_valid ),
.ready_o ( b_ready ),
.data_i ( b_chan ),
.valid_o ( slv_resp_o.b_valid ),
.ready_i ( slv_req_i.b_ready ),
.data_o ( slv_resp_o.b )
);
addr_decode #(
.NoIndices( NoRegs ),
.NoRules ( NoRegs ),
.addr_t ( addr_t ),
.rule_t ( rule_t )
) i_raddr_decode (
.addr_i ( slv_req_i.ar.addr ),
.addr_map_i ( addr_map ),
.idx_o ( r_reg_idx ),
.dec_valid_o ( dec_r_valid ),
.dec_error_o ( ),
.en_default_idx_i ( 1'b0 ),
.default_idx_i ( '0 )
);
spill_register #(
.T ( r_chan_lite_t )
) i_r_chan_outp (
.clk_i,
.rst_ni,
.valid_i ( r_valid ),
.ready_o ( r_ready ),
.data_i ( r_chan ),
.valid_o ( slv_resp_o.r_valid ),
.ready_i ( slv_req_i.r_ready ),
.data_o ( slv_resp_o.r )
);
endmodule
module axi_lite_mailbox_intf #(
parameter int unsigned MAILBOX_DEPTH = 32'd0,
parameter bit unsigned IRQ_EDGE_TRIG = 1'b0,
parameter bit unsigned IRQ_ACT_HIGH = 1'b1,
parameter int unsigned AXI_ADDR_WIDTH = 32'd0,
parameter int unsigned AXI_DATA_WIDTH = 32'd0,
parameter type addr_t = logic [AXI_ADDR_WIDTH-1:0]
) (
input logic clk_i,
input logic rst_ni,
input logic test_i,
AXI_LITE.Slave slv [1:0],
output logic [1:0] irq_o,
input addr_t [1:0] base_addr_i
);
typedef logic [AXI_DATA_WIDTH-1:0] data_t;
typedef logic [AXI_DATA_WIDTH/8-1:0] strb_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} aw_chan_lite_t;
typedef struct packed {
data_t data;
strb_t strb;
} w_chan_lite_t;
typedef struct packed {
axi_pkg::resp_t resp;
} b_chan_lite_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} ar_chan_lite_t;
typedef struct packed {
data_t data;
axi_pkg::resp_t resp;
} r_chan_lite_t;
typedef struct packed {
aw_chan_lite_t aw;
logic aw_valid;
w_chan_lite_t w;
logic w_valid;
logic b_ready;
ar_chan_lite_t ar;
logic ar_valid;
logic r_ready;
} req_lite_t;
typedef struct packed {
logic aw_ready;
logic w_ready;
b_chan_lite_t b;
logic b_valid;
logic ar_ready;
r_chan_lite_t r;
logic r_valid;
} resp_lite_t;
req_lite_t [1:0] slv_reqs;
resp_lite_t [1:0] slv_resps;
for (genvar i = 0; i < 2; i++) begin : gen_port_assign
assign slv_reqs[i].aw.addr = slv[i].aw_addr;
assign slv_reqs[i].aw.prot = slv[i].aw_prot;
assign slv_reqs[i].aw_valid = slv[i].aw_valid;
assign slv_reqs[i].w.data = slv[i].w_data;
assign slv_reqs[i].w.strb = slv[i].w_strb;
assign slv_reqs[i].w_valid = slv[i].w_valid;
assign slv_reqs[i].b_ready = slv[i].b_ready;
assign slv_reqs[i].ar.addr = slv[i].ar_addr;
assign slv_reqs[i].ar.prot = slv[i].ar_prot;
assign slv_reqs[i].ar_valid = slv[i].ar_valid;
assign slv_reqs[i].r_ready = slv[i].r_ready;
assign slv[i].aw_ready = slv_resps[i].aw_ready;
assign slv[i].ar_ready = slv_resps[i].ar_ready;
assign slv[i].w_ready = slv_resps[i].w_ready;
assign slv[i].b_valid = slv_resps[i].b_valid;
assign slv[i].b_resp = slv_resps[i].b.resp;
assign slv[i].r_valid = slv_resps[i].r_valid;
assign slv[i].r_data = slv_resps[i].r.data;
assign slv[i].r_resp = slv_resps[i].r.resp;
end
axi_lite_mailbox #(
.MailboxDepth ( MAILBOX_DEPTH ),
.IrqEdgeTrig ( IRQ_EDGE_TRIG ),
.IrqActHigh ( IRQ_ACT_HIGH ),
.AxiAddrWidth ( AXI_ADDR_WIDTH ),
.AxiDataWidth ( AXI_DATA_WIDTH ),
.req_lite_t ( req_lite_t ),
.resp_lite_t ( resp_lite_t )
) i_axi_lite_mailbox (
.clk_i,
.rst_ni,
.test_i,
.slv_reqs_i ( slv_reqs ),
.slv_resps_o ( slv_resps ),
.irq_o,
.base_addr_i
);
endmodule
`begin_keywords "1800-2023"
module axi_lite_mux #(
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,
parameter int unsigned NoSlvPorts = 32'd0,
parameter int unsigned MaxTrans = 32'd0,
parameter bit FallThrough = 1'b0,
parameter bit SpillAw = 1'b1,
parameter bit SpillW = 1'b0,
parameter bit SpillB = 1'b0,
parameter bit SpillAr = 1'b1,
parameter bit SpillR = 1'b0
) (
input logic clk_i,
input logic rst_ni,
input logic test_i,
input axi_req_t [NoSlvPorts-1:0] slv_reqs_i,
output axi_resp_t [NoSlvPorts-1:0] slv_resps_o,
output axi_req_t mst_req_o,
input axi_resp_t mst_resp_i
);
if (NoSlvPorts == 32'h1) begin : gen_no_mux
spill_register #(
.T ( aw_chan_t ),
.Bypass ( ~SpillAw )
) i_aw_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( slv_reqs_i[0].aw_valid ),
.ready_o ( slv_resps_o[0].aw_ready ),
.data_i ( slv_reqs_i[0].aw ),
.valid_o ( mst_req_o.aw_valid ),
.ready_i ( mst_resp_i.aw_ready ),
.data_o ( mst_req_o.aw )
);
spill_register #(
.T ( w_chan_t ),
.Bypass ( ~SpillW )
) i_w_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( slv_reqs_i[0].w_valid ),
.ready_o ( slv_resps_o[0].w_ready ),
.data_i ( slv_reqs_i[0].w ),
.valid_o ( mst_req_o.w_valid ),
.ready_i ( mst_resp_i.w_ready ),
.data_o ( mst_req_o.w )
);
spill_register #(
.T ( b_chan_t ),
.Bypass ( ~SpillB )
) i_b_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( mst_resp_i.b_valid ),
.ready_o ( mst_req_o.b_ready ),
.data_i ( mst_resp_i.b ),
.valid_o ( slv_resps_o[0].b_valid ),
.ready_i ( slv_reqs_i[0].b_ready ),
.data_o ( slv_resps_o[0].b )
);
spill_register #(
.T ( ar_chan_t ),
.Bypass ( ~SpillAr )
) i_ar_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( slv_reqs_i[0].ar_valid ),
.ready_o ( slv_resps_o[0].ar_ready ),
.data_i ( slv_reqs_i[0].ar ),
.valid_o ( mst_req_o.ar_valid ),
.ready_i ( mst_resp_i.ar_ready ),
.data_o ( mst_req_o.ar )
);
spill_register #(
.T ( r_chan_t ),
.Bypass ( ~SpillR )
) i_r_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( mst_resp_i.r_valid ),
.ready_o ( mst_req_o.r_ready ),
.data_i ( mst_resp_i.r ),
.valid_o ( slv_resps_o[0].r_valid ),
.ready_i ( slv_reqs_i[0].r_ready ),
.data_o ( slv_resps_o[0].r )
);
end else begin : gen_mux
localparam int unsigned CLog2NoSlvPorts = $clog2(NoSlvPorts);
typedef logic [CLog2NoSlvPorts-1:0] select_t;
aw_chan_t [NoSlvPorts-1:0] slv_aw_chans;
logic [NoSlvPorts-1:0] slv_aw_valids, slv_aw_readies;
select_t aw_select;
aw_chan_t mst_aw_chan;
logic mst_aw_valid, mst_aw_ready;
logic aw_valid, aw_ready;
logic lock_aw_valid_d, lock_aw_valid_q;
logic load_aw_lock;
logic w_fifo_full, w_fifo_empty;
logic w_fifo_push, w_fifo_pop;
select_t w_select;
w_chan_t mst_w_chan;
logic mst_w_valid, mst_w_ready;
select_t b_select;
logic b_fifo_full, b_fifo_empty;
logic b_fifo_pop;
b_chan_t mst_b_chan;
logic mst_b_valid, mst_b_ready;
ar_chan_t [NoSlvPorts-1:0] slv_ar_chans;
logic [NoSlvPorts-1:0] slv_ar_valids, slv_ar_readies;
select_t ar_select;
ar_chan_t mst_ar_chan;
logic mst_ar_valid, mst_ar_ready;
logic ar_valid, ar_ready;
select_t r_select;
logic r_fifo_full, r_fifo_empty;
logic r_fifo_push, r_fifo_pop;
r_chan_t mst_r_chan;
logic mst_r_valid, mst_r_ready;
for (genvar i = 0; i < NoSlvPorts; i++) begin : gen_aw_arb_input
assign slv_aw_chans[i] = slv_reqs_i[i].aw;
assign slv_aw_valids[i] = slv_reqs_i[i].aw_valid;
assign slv_resps_o[i].aw_ready = slv_aw_readies[i];
end
rr_arb_tree #(
.NumIn ( NoSlvPorts ),
.DataType ( aw_chan_t ),
.AxiVldRdy( 1'b1 ),
.LockIn ( 1'b1 )
) i_aw_arbiter (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i( 1'b0 ),
.rr_i ( '0 ),
.req_i ( slv_aw_valids ),
.gnt_o ( slv_aw_readies ),
.data_i ( slv_aw_chans ),
.gnt_i ( aw_ready ),
.req_o ( aw_valid ),
.data_o ( mst_aw_chan ),
.idx_o ( aw_select )
);
always_comb begin
lock_aw_valid_d = lock_aw_valid_q;
load_aw_lock = 1'b0;
w_fifo_push = 1'b0;
mst_aw_valid = 1'b0;
aw_ready = 1'b0;
if (lock_aw_valid_q) begin
mst_aw_valid = 1'b1;
if (mst_aw_ready) begin
aw_ready = 1'b1;
lock_aw_valid_d = 1'b0;
load_aw_lock = 1'b1;
end
end else begin
if (!w_fifo_full && aw_valid) begin
mst_aw_valid = 1'b1;
w_fifo_push = 1'b1;
if (mst_aw_ready) begin
aw_ready = 1'b1;
end else begin
lock_aw_valid_d = 1'b1;
load_aw_lock = 1'b1;
end
end
end
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
lock_aw_valid_q <= ('0);
end else begin
if (load_aw_lock) begin
lock_aw_valid_q <= (lock_aw_valid_d);
end
end
end
fifo_v3 #(
.FALL_THROUGH ( FallThrough ),
.DEPTH ( MaxTrans ),
.dtype ( select_t )
) i_w_fifo (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.testmode_i( test_i ),
.full_o ( w_fifo_full ),
.empty_o ( w_fifo_empty ),
.usage_o ( ),
.data_i ( aw_select ),
.push_i ( w_fifo_push ),
.data_o ( w_select ),
.pop_i ( w_fifo_pop )
);
spill_register #(
.T ( aw_chan_t ),
.Bypass ( ~SpillAw )
) i_aw_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( mst_aw_valid ),
.ready_o ( mst_aw_ready ),
.data_i ( mst_aw_chan ),
.valid_o ( mst_req_o.aw_valid ),
.ready_i ( mst_resp_i.aw_ready ),
.data_o ( mst_req_o.aw )
);
assign mst_w_chan = slv_reqs_i[w_select].w;
assign mst_w_valid = (!w_fifo_empty && !b_fifo_full) ? slv_reqs_i[w_select].w_valid : 1'b0;
for (genvar i = 0; i < NoSlvPorts; i++) begin : gen_slv_w_ready
assign slv_resps_o[i].w_ready = mst_w_ready & ~w_fifo_empty &
~b_fifo_full & (w_select == select_t'(i));
end
assign w_fifo_pop = mst_w_valid & mst_w_ready;
fifo_v3 #(
.FALL_THROUGH ( FallThrough ),
.DEPTH ( MaxTrans ),
.dtype ( select_t )
) i_b_fifo (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.testmode_i( test_i ),
.full_o ( b_fifo_full ),
.empty_o ( b_fifo_empty ),
.usage_o ( ),
.data_i ( w_select ),
.push_i ( w_fifo_pop ),
.data_o ( b_select ),
.pop_i ( b_fifo_pop )
);
spill_register #(
.T ( w_chan_t ),
.Bypass ( ~SpillW )
) i_w_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( mst_w_valid ),
.ready_o ( mst_w_ready ),
.data_i ( mst_w_chan ),
.valid_o ( mst_req_o.w_valid ),
.ready_i ( mst_resp_i.w_ready ),
.data_o ( mst_req_o.w )
);
for (genvar i = 0; i < NoSlvPorts; i++) begin : gen_slv_resps_b
assign slv_resps_o[i].b = mst_b_chan;
assign slv_resps_o[i].b_valid = mst_b_valid & ~b_fifo_empty & (b_select == select_t'(i));
end
assign mst_b_ready = ~b_fifo_empty & slv_reqs_i[b_select].b_ready;
assign b_fifo_pop = mst_b_valid & mst_b_ready;
spill_register #(
.T ( b_chan_t ),
.Bypass ( ~SpillB )
) i_b_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( mst_resp_i.b_valid ),
.ready_o ( mst_req_o.b_ready ),
.data_i ( mst_resp_i.b ),
.valid_o ( mst_b_valid ),
.ready_i ( mst_b_ready ),
.data_o ( mst_b_chan )
);
for (genvar i = 0; i < NoSlvPorts; i++) begin : gen_ar_arb_input
assign slv_ar_chans[i] = slv_reqs_i[i].ar;
assign slv_ar_valids[i] = slv_reqs_i[i].ar_valid;
assign slv_resps_o[i].ar_ready = slv_ar_readies[i];
end
rr_arb_tree #(
.NumIn ( NoSlvPorts ),
.DataType ( ar_chan_t ),
.AxiVldRdy( 1'b1 ),
.LockIn ( 1'b1 )
) i_ar_arbiter (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i( 1'b0 ),
.rr_i ( '0 ),
.req_i ( slv_ar_valids ),
.gnt_o ( slv_ar_readies ),
.data_i ( slv_ar_chans ),
.gnt_i ( ar_ready ),
.req_o ( ar_valid ),
.data_o ( mst_ar_chan ),
.idx_o ( ar_select )
);
assign mst_ar_valid = (!r_fifo_full) ? ar_valid : 1'b0;
assign ar_ready = (!r_fifo_full) ? mst_ar_ready : 1'b0;
assign r_fifo_push = mst_ar_valid & mst_ar_ready;
fifo_v3 #(
.FALL_THROUGH ( FallThrough ),
.DEPTH ( MaxTrans ),
.dtype ( select_t )
) i_r_fifo (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.testmode_i( test_i ),
.full_o ( r_fifo_full ),
.empty_o ( r_fifo_empty ),
.usage_o ( ),
.data_i ( ar_select ),
.push_i ( r_fifo_push ),
.data_o ( r_select ),
.pop_i ( r_fifo_pop )
);
spill_register #(
.T ( ar_chan_t ),
.Bypass ( ~SpillAr )
) i_ar_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( mst_ar_valid ),
.ready_o ( mst_ar_ready ),
.data_i ( mst_ar_chan ),
.valid_o ( mst_req_o.ar_valid ),
.ready_i ( mst_resp_i.ar_ready ),
.data_o ( mst_req_o.ar )
);
for (genvar i = 0; i < NoSlvPorts; i++) begin : gen_slv_resps_r
assign slv_resps_o[i].r = mst_r_chan;
assign slv_resps_o[i].r_valid = mst_r_valid & ~r_fifo_empty & (r_select == select_t'(i));
end
assign mst_r_ready = ~r_fifo_empty & slv_reqs_i[r_select].r_ready;
assign r_fifo_pop = mst_r_valid & mst_r_ready;
spill_register #(
.T ( r_chan_t ),
.Bypass ( ~SpillR )
) i_r_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( mst_resp_i.r_valid ),
.ready_o ( mst_req_o.r_ready ),
.data_i ( mst_resp_i.r ),
.valid_o ( mst_r_valid ),
.ready_i ( mst_r_ready ),
.data_o ( mst_r_chan )
);
end
endmodule
module axi_lite_mux_intf #(
parameter int unsigned AxiAddrWidth = 32'd0,
parameter int unsigned AxiDataWidth = 32'd0,
parameter int unsigned NoSlvPorts = 32'd0,
parameter int unsigned MaxTrans = 32'd0,
parameter bit FallThrough = 1'b0,
parameter bit SpillAw = 1'b1,
parameter bit SpillW = 1'b0,
parameter bit SpillB = 1'b0,
parameter bit SpillAr = 1'b1,
parameter bit SpillR = 1'b0
) (
input logic clk_i,
input logic rst_ni,
input logic test_i,
AXI_LITE.Slave slv [NoSlvPorts-1:0],
AXI_LITE.Master mst
);
typedef logic [AxiAddrWidth-1:0] addr_t;
typedef logic [AxiDataWidth-1:0] data_t;
typedef logic [AxiDataWidth/8-1:0] strb_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
} w_chan_t;
typedef struct packed {
axi_pkg::resp_t resp;
} b_chan_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} ar_chan_t;
typedef struct packed {
data_t data;
axi_pkg::resp_t resp;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} axi_req_t;
typedef struct packed {
logic aw_ready;
logic w_ready;
b_chan_t b;
logic b_valid;
logic ar_ready;
r_chan_t r;
logic r_valid;
} axi_resp_t;
axi_req_t [NoSlvPorts-1:0] slv_reqs;
axi_resp_t [NoSlvPorts-1:0] slv_resps;
axi_req_t mst_req;
axi_resp_t mst_resp;
for (genvar i = 0; i < NoSlvPorts; i++) begin : gen_assign_slv_ports
assign slv_reqs[i].aw.addr = slv[i].aw_addr;
assign slv_reqs[i].aw.prot = slv[i].aw_prot;
assign slv_reqs[i].aw_valid = slv[i].aw_valid;
assign slv_reqs[i].w.data = slv[i].w_data;
assign slv_reqs[i].w.strb = slv[i].w_strb;
assign slv_reqs[i].w_valid = slv[i].w_valid;
assign slv_reqs[i].b_ready = slv[i].b_ready;
assign slv_reqs[i].ar.addr = slv[i].ar_addr;
assign slv_reqs[i].ar.prot = slv[i].ar_prot;
assign slv_reqs[i].ar_valid = slv[i].ar_valid;
assign slv_reqs[i].r_ready = slv[i].r_ready;
assign slv[i].aw_ready = slv_resps[i].aw_ready;
assign slv[i].ar_ready = slv_resps[i].ar_ready;
assign slv[i].w_ready = slv_resps[i].w_ready;
assign slv[i].b_valid = slv_resps[i].b_valid;
assign slv[i].b_resp = slv_resps[i].b.resp;
assign slv[i].r_valid = slv_resps[i].r_valid;
assign slv[i].r_data = slv_resps[i].r.data;
assign slv[i].r_resp = slv_resps[i].r.resp;
end
assign mst.aw_addr = mst_req.aw.addr;
assign mst.aw_prot = mst_req.aw.prot;
assign mst.aw_valid = mst_req.aw_valid;
assign mst.w_data = mst_req.w.data;
assign mst.w_strb = mst_req.w.strb;
assign mst.w_valid = mst_req.w_valid;
assign mst.b_ready = mst_req.b_ready;
assign mst.ar_addr = mst_req.ar.addr;
assign mst.ar_prot = mst_req.ar.prot;
assign mst.ar_valid = mst_req.ar_valid;
assign mst.r_ready = mst_req.r_ready;
assign mst_resp.aw_ready = mst.aw_ready;
assign mst_resp.ar_ready = mst.ar_ready;
assign mst_resp.w_ready = mst.w_ready;
assign mst_resp.b_valid = mst.b_valid;
assign mst_resp.b.resp = mst.b_resp;
assign mst_resp.r_valid = mst.r_valid;
assign mst_resp.r.data = mst.r_data;
assign mst_resp.r.resp = mst.r_resp;
axi_lite_mux #(
.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 ),
.NoSlvPorts ( NoSlvPorts ),
.MaxTrans ( MaxTrans ),
.FallThrough ( FallThrough ),
.SpillAw ( SpillAw ),
.SpillW ( SpillW ),
.SpillB ( SpillB ),
.SpillAr ( SpillAr ),
.SpillR ( SpillR )
) i_axi_mux (
.clk_i,
.rst_ni,
.test_i,
.slv_reqs_i ( slv_reqs ),
.slv_resps_o ( slv_resps ),
.mst_req_o ( mst_req ),
.mst_resp_i ( mst_resp )
);
endmodule
`begin_keywords "1800-2023"
module axi_lite_regs #(
parameter int unsigned RegNumBytes = 32'd0,
parameter int unsigned AxiAddrWidth = 32'd0,
parameter int unsigned AxiDataWidth = 32'd0,
parameter bit PrivProtOnly = 1'b0,
parameter bit SecuProtOnly = 1'b0,
parameter logic [RegNumBytes-1:0] AxiReadOnly = {RegNumBytes{1'b0}},
parameter type byte_t = logic [7:0],
parameter byte_t [RegNumBytes-1:0] RegRstVal = {RegNumBytes{8'h00}},
parameter type req_lite_t = logic,
parameter type resp_lite_t = logic
) (
input logic clk_i,
input logic rst_ni,
input req_lite_t axi_req_i,
output resp_lite_t axi_resp_o,
output logic [RegNumBytes-1:0] wr_active_o,
output logic [RegNumBytes-1:0] rd_active_o,
input byte_t [RegNumBytes-1:0] reg_d_i,
input logic [RegNumBytes-1:0] reg_load_i,
output byte_t [RegNumBytes-1:0] reg_q_o
);
localparam int unsigned AxiStrbWidth = AxiDataWidth / 32'd8;
localparam int unsigned NumChunks = cf_math_pkg::ceil_div(RegNumBytes, AxiStrbWidth);
localparam int unsigned ChunkIdxWidth = (NumChunks > 32'd1) ? $clog2(NumChunks) : 32'd1;
typedef logic [ChunkIdxWidth-1:0] chunk_idx_t;
localparam int unsigned AddrWidth = (RegNumBytes > 32'd1) ? ($clog2(RegNumBytes)+1) : 32'd2;
typedef logic [AddrWidth-1:0] addr_t;
typedef struct packed {
int unsigned idx;
addr_t start_addr;
addr_t end_addr;
} axi_rule_t;
axi_rule_t [NumChunks-1:0] addr_map;
for (genvar i = 0; i < NumChunks; i++) begin : gen_addr_map
assign addr_map[i] = axi_rule_t'{
idx: i,
start_addr: addr_t'( i * AxiStrbWidth),
end_addr: addr_t'((i+1)* AxiStrbWidth)
};
end
typedef logic [AxiDataWidth-1:0] axi_data_t;
typedef struct packed {
axi_pkg::resp_t resp;
} b_chan_lite_t;
typedef struct packed {
axi_data_t data;
axi_pkg::resp_t resp;
} r_chan_lite_t;
byte_t [RegNumBytes-1:0] reg_q, reg_d;
logic [RegNumBytes-1:0] reg_update;
chunk_idx_t aw_chunk_idx;
logic aw_dec_valid;
b_chan_lite_t b_chan;
logic b_valid, b_ready;
logic aw_prot_ok;
logic chunk_loaded, chunk_ro;
assign aw_prot_ok = (PrivProtOnly ? axi_req_i.aw.prot[0] : 1'b1) &
(SecuProtOnly ? axi_req_i.aw.prot[1] : 1'b1);
logic [AxiStrbWidth-1:0] load;
logic [AxiStrbWidth-1:0] read_only;
addr_t byte_w_addr;
assign byte_w_addr = addr_t'(aw_chunk_idx * AxiStrbWidth);
for (genvar i = 0; i < AxiStrbWidth; i++) begin : gen_load_assign
addr_t reg_w_idx;
assign reg_w_idx = byte_w_addr + addr_t'(i);
assign load[i] = (reg_w_idx < RegNumBytes) ?
(reg_load_i[reg_w_idx] && !AxiReadOnly[reg_w_idx]) : 1'b0;
assign read_only[i] = (reg_w_idx < RegNumBytes) ? AxiReadOnly[reg_w_idx] : 1'b1;
end
assign chunk_loaded = |(load & axi_req_i.w.strb);
assign chunk_ro = &read_only;
always_comb begin
automatic addr_t reg_byte_idx = '0;
reg_d = reg_q;
reg_update = '0;
axi_resp_o.aw_ready = 1'b0;
axi_resp_o.w_ready = 1'b0;
b_chan = b_chan_lite_t'{resp: axi_pkg::RESP_SLVERR, default: '0};
b_valid = 1'b0;
wr_active_o = '0;
for (int unsigned i = 0; i < RegNumBytes; i++) begin
if (reg_load_i[i]) begin
reg_d[i] = reg_d_i[i];
reg_update[i] = 1'b1;
end
end
if (axi_req_i.aw_valid && axi_req_i.w_valid && b_ready) begin
if (aw_dec_valid && aw_prot_ok) begin
if (!chunk_loaded) begin
for (int unsigned i = 0; i < AxiStrbWidth; i++) begin
reg_byte_idx = byte_w_addr + addr_t'(i);
if (reg_byte_idx < RegNumBytes) begin
if (!AxiReadOnly[reg_byte_idx] && axi_req_i.w.strb[i]) begin
reg_d[reg_byte_idx] = axi_req_i.w.data[8*i+:8];
reg_update[reg_byte_idx] = 1'b1;
end
wr_active_o[reg_byte_idx] = axi_req_i.w.strb[i];
end
end
b_chan.resp = chunk_ro ? axi_pkg::RESP_SLVERR : axi_pkg::RESP_OKAY;
b_valid = 1'b1;
axi_resp_o.aw_ready = 1'b1;
axi_resp_o.w_ready = 1'b1;
end
end else begin
b_valid = 1'b1;
axi_resp_o.aw_ready = 1'b1;
axi_resp_o.w_ready = 1'b1;
end
end
end
chunk_idx_t ar_chunk_idx;
logic ar_dec_valid;
r_chan_lite_t r_chan;
logic r_valid, r_ready;
logic ar_prot_ok;
assign ar_prot_ok = (PrivProtOnly ? axi_req_i.ar.prot[0] : 1'b1) &
(SecuProtOnly ? axi_req_i.ar.prot[1] : 1'b1);
always_comb begin
automatic int unsigned reg_byte_idx = '0;
r_chan = r_chan_lite_t'{
data: axi_data_t'(32'hBA5E1E55),
resp: axi_pkg::RESP_SLVERR,
default: '0
};
rd_active_o = '0;
if (ar_dec_valid && ar_prot_ok) begin
for (int unsigned i = 0; i < AxiStrbWidth; i++) begin
reg_byte_idx = unsigned'(ar_chunk_idx) * AxiStrbWidth + i;
if (reg_byte_idx < RegNumBytes) begin
r_chan.data[8*i+:8] = reg_q_o[reg_byte_idx];
rd_active_o[reg_byte_idx] = r_valid & r_ready;
end else begin
r_chan.data[8*i+:8] = 8'h00;
end
end
r_chan.resp = axi_pkg::RESP_OKAY;
end
end
assign r_valid = axi_req_i.ar_valid;
assign axi_resp_o.ar_ready = r_ready;
for (genvar i = 0; i < RegNumBytes; i++) begin : gen_rw_regs
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
reg_q[i] <= (RegRstVal[i]);
end else begin
if (reg_update[i]) begin
reg_q[i] <= (reg_d[i]);
end
end
end
assign reg_q_o[i] = reg_q[i];
end
addr_decode #(
.NoIndices ( NumChunks ),
.NoRules ( NumChunks ),
.addr_t ( addr_t ),
.rule_t ( axi_rule_t )
) i_aw_decode (
.addr_i ( addr_t'(axi_req_i.aw.addr) ),
.addr_map_i ( addr_map ),
.idx_o ( aw_chunk_idx ),
.dec_valid_o ( aw_dec_valid ),
.dec_error_o ( ),
.en_default_idx_i ( '0 ),
.default_idx_i ( '0 )
);
addr_decode #(
.NoIndices ( NumChunks ),
.NoRules ( NumChunks ),
.addr_t ( addr_t ),
.rule_t ( axi_rule_t )
) i_ar_decode (
.addr_i ( addr_t'(axi_req_i.ar.addr) ),
.addr_map_i ( addr_map ),
.idx_o ( ar_chunk_idx ),
.dec_valid_o ( ar_dec_valid ),
.dec_error_o ( ),
.en_default_idx_i ( '0 ),
.default_idx_i ( '0 )
);
spill_register #(
.T ( b_chan_lite_t ),
.Bypass ( 1'b0 )
) i_b_spill_register (
.clk_i,
.rst_ni,
.valid_i ( b_valid ),
.ready_o ( b_ready ),
.data_i ( b_chan ),
.valid_o ( axi_resp_o.b_valid ),
.ready_i ( axi_req_i.b_ready ),
.data_o ( axi_resp_o.b )
);
spill_register #(
.T ( r_chan_lite_t ),
.Bypass ( 1'b0 )
) i_r_spill_register (
.clk_i,
.rst_ni,
.valid_i ( r_valid ),
.ready_o ( r_ready ),
.data_i ( r_chan ),
.valid_o ( axi_resp_o.r_valid ),
.ready_i ( axi_req_i.r_ready ),
.data_o ( axi_resp_o.r )
);
endmodule
module axi_lite_regs_intf #(
parameter type byte_t = logic [7:0],
parameter int unsigned REG_NUM_BYTES = 32'd0,
parameter int unsigned AXI_ADDR_WIDTH = 32'd0,
parameter int unsigned AXI_DATA_WIDTH = 32'd0,
parameter bit PRIV_PROT_ONLY = 1'd0,
parameter bit SECU_PROT_ONLY = 1'd0,
parameter logic [REG_NUM_BYTES-1:0] AXI_READ_ONLY = {REG_NUM_BYTES{1'b0}},
parameter byte_t [REG_NUM_BYTES-1:0] REG_RST_VAL = {REG_NUM_BYTES{8'h00}}
) (
input logic clk_i,
input logic rst_ni,
AXI_LITE.Slave slv,
output logic [REG_NUM_BYTES-1:0] wr_active_o,
output logic [REG_NUM_BYTES-1:0] rd_active_o,
input byte_t [REG_NUM_BYTES-1:0] reg_d_i,
input logic [REG_NUM_BYTES-1:0] reg_load_i,
output byte_t [REG_NUM_BYTES-1:0] reg_q_o
);
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 struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} aw_chan_lite_t;
typedef struct packed {
data_t data;
strb_t strb;
} w_chan_lite_t;
typedef struct packed {
axi_pkg::resp_t resp;
} b_chan_lite_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} ar_chan_lite_t;
typedef struct packed {
data_t data;
axi_pkg::resp_t resp;
} r_chan_lite_t;
typedef struct packed {
aw_chan_lite_t aw;
logic aw_valid;
w_chan_lite_t w;
logic w_valid;
logic b_ready;
ar_chan_lite_t ar;
logic ar_valid;
logic r_ready;
} req_lite_t;
typedef struct packed {
logic aw_ready;
logic w_ready;
b_chan_lite_t b;
logic b_valid;
logic ar_ready;
r_chan_lite_t r;
logic r_valid;
} resp_lite_t;
req_lite_t axi_lite_req;
resp_lite_t axi_lite_resp;
assign axi_lite_req.aw.addr = slv.aw_addr;
assign axi_lite_req.aw.prot = slv.aw_prot;
assign axi_lite_req.aw_valid = slv.aw_valid;
assign axi_lite_req.w.data = slv.w_data;
assign axi_lite_req.w.strb = slv.w_strb;
assign axi_lite_req.w_valid = slv.w_valid;
assign axi_lite_req.b_ready = slv.b_ready;
assign axi_lite_req.ar.addr = slv.ar_addr;
assign axi_lite_req.ar.prot = slv.ar_prot;
assign axi_lite_req.ar_valid = slv.ar_valid;
assign axi_lite_req.r_ready = slv.r_ready;
assign slv.aw_ready = axi_lite_resp.aw_ready;
assign slv.ar_ready = axi_lite_resp.ar_ready;
assign slv.w_ready = axi_lite_resp.w_ready;
assign slv.b_valid = axi_lite_resp.b_valid;
assign slv.b_resp = axi_lite_resp.b.resp;
assign slv.r_valid = axi_lite_resp.r_valid;
assign slv.r_data = axi_lite_resp.r.data;
assign slv.r_resp = axi_lite_resp.r.resp;
axi_lite_regs #(
.RegNumBytes ( REG_NUM_BYTES ),
.AxiAddrWidth ( AXI_ADDR_WIDTH ),
.AxiDataWidth ( AXI_DATA_WIDTH ),
.PrivProtOnly ( PRIV_PROT_ONLY ),
.SecuProtOnly ( SECU_PROT_ONLY ),
.AxiReadOnly ( AXI_READ_ONLY ),
.RegRstVal ( REG_RST_VAL ),
.req_lite_t ( req_lite_t ),
.resp_lite_t ( resp_lite_t )
) i_axi_lite_regs (
.clk_i,
.rst_ni,
.axi_req_i ( axi_lite_req ),
.axi_resp_o ( axi_lite_resp ),
.wr_active_o,
.rd_active_o,
.reg_d_i,
.reg_load_i,
.reg_q_o
);
endmodule
`begin_keywords "1800-2023"
module axi_lite_to_apb #(
parameter int unsigned NoApbSlaves = 32'd1,
parameter int unsigned NoRules = 32'd1,
parameter int unsigned AddrWidth = 32'd32,
parameter int unsigned DataWidth = 32'd32,
parameter bit PipelineRequest = 1'b0,
parameter bit PipelineResponse = 1'b0,
parameter type axi_lite_req_t = logic,
parameter type axi_lite_resp_t = logic,
parameter type apb_req_t = logic,
parameter type apb_resp_t = logic,
parameter type rule_t = logic
) (
input logic clk_i,
input logic rst_ni,
input axi_lite_req_t axi_lite_req_i,
output axi_lite_resp_t axi_lite_resp_o,
output apb_req_t [NoApbSlaves-1:0] apb_req_o,
input apb_resp_t [NoApbSlaves-1:0] apb_resp_i,
input rule_t [NoRules-1:0] addr_map_i
);
localparam logic RD = 1'b0;
localparam logic WR = 1'b1;
localparam int unsigned SelIdxWidth = (NoApbSlaves > 32'd1) ? $clog2(NoApbSlaves) : 32'd1;
typedef logic [AddrWidth-1:0] addr_t;
typedef logic [DataWidth-1:0] data_t;
typedef logic [DataWidth/8-1:0] strb_t;
typedef logic [SelIdxWidth-1:0] sel_idx_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
data_t data;
strb_t strb;
logic write;
} int_req_t;
typedef struct packed {
data_t data;
axi_pkg::resp_t resp;
} int_resp_t;
typedef enum logic {
Setup = 1'b0,
Access = 1'b1
} apb_state_e;
int_req_t [1:0] axi_req;
logic [1:0] axi_req_valid, axi_req_ready;
axi_pkg::resp_t axi_bresp;
logic axi_bresp_valid, axi_bresp_ready;
int_resp_t axi_rresp;
logic axi_rresp_valid, axi_rresp_ready;
assign axi_req[RD] = '{
addr: axi_lite_req_i.ar.addr,
prot: axi_lite_req_i.ar.prot,
data: '0,
strb: '0,
write: RD
};
assign axi_req_valid[RD] = axi_lite_req_i.ar_valid;
assign axi_req[WR] = '{
addr: axi_lite_req_i.aw.addr,
prot: axi_lite_req_i.aw.prot,
data: axi_lite_req_i.w.data,
strb: axi_lite_req_i.w.strb,
write: WR
};
assign axi_req_valid[WR] = axi_lite_req_i.aw_valid & axi_lite_req_i.w_valid;
assign axi_lite_resp_o = '{
aw_ready: axi_req_valid[WR] & axi_req_ready[WR],
w_ready: axi_req_valid[WR] & axi_req_ready[WR],
b: '{resp: axi_bresp},
b_valid: axi_bresp_valid,
ar_ready: axi_req_valid[RD] & axi_req_ready[RD],
r: '{data: axi_rresp.data, resp: axi_rresp.resp},
r_valid: axi_rresp_valid
};
int_req_t arb_req, apb_req;
logic arb_req_valid, arb_req_ready, apb_req_valid, apb_req_ready;
axi_pkg::resp_t apb_wresp;
logic apb_wresp_valid, apb_wresp_ready;
int_resp_t apb_rresp;
logic apb_rresp_valid, apb_rresp_ready;
rr_arb_tree #(
.NumIn ( 32'd2 ),
.DataType ( int_req_t ),
.ExtPrio ( 1'b0 ),
.AxiVldRdy( 1'b1 ),
.LockIn ( 1'b1 )
) i_req_arb (
.clk_i,
.rst_ni,
.flush_i ( '0 ),
.rr_i ( '0 ),
.req_i ( axi_req_valid ),
.gnt_o ( axi_req_ready ),
.data_i ( axi_req ),
.gnt_i ( arb_req_ready ),
.req_o ( arb_req_valid ),
.data_o ( arb_req ),
.idx_o ( )
);
if (PipelineRequest) begin : gen_req_spill
spill_register #(
.T ( int_req_t ),
.Bypass ( 1'b0 )
) i_req_spill (
.clk_i,
.rst_ni,
.valid_i ( arb_req_valid ),
.ready_o ( arb_req_ready ),
.data_i ( arb_req ),
.valid_o ( apb_req_valid ),
.ready_i ( apb_req_ready ),
.data_o ( apb_req )
);
end else begin : gen_req_ft_reg
fall_through_register #(
.T ( int_req_t )
) i_req_ft_reg (
.clk_i,
.rst_ni,
.clr_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.valid_i ( arb_req_valid ),
.ready_o ( arb_req_ready ),
.data_i ( arb_req ),
.valid_o ( apb_req_valid ),
.ready_i ( apb_req_ready ),
.data_o ( apb_req )
);
end
if (PipelineResponse) begin : gen_resp_spill
spill_register #(
.T ( axi_pkg::resp_t ),
.Bypass ( 1'b0 )
) i_write_resp_spill (
.clk_i,
.rst_ni,
.valid_i ( apb_wresp_valid ),
.ready_o ( apb_wresp_ready ),
.data_i ( apb_wresp ),
.valid_o ( axi_bresp_valid ),
.ready_i ( axi_lite_req_i.b_ready ),
.data_o ( axi_bresp )
);
spill_register #(
.T ( int_resp_t ),
.Bypass ( 1'b0 )
) i_read_resp_spill (
.clk_i,
.rst_ni,
.valid_i ( apb_rresp_valid ),
.ready_o ( apb_rresp_ready ),
.data_i ( apb_rresp ),
.valid_o ( axi_rresp_valid ),
.ready_i ( axi_lite_req_i.r_ready ),
.data_o ( axi_rresp )
);
end else begin : gen_resp_ft_reg
fall_through_register #(
.T ( axi_pkg::resp_t )
) i_write_resp_ft_reg (
.clk_i,
.rst_ni,
.clr_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.valid_i ( apb_wresp_valid ),
.ready_o ( apb_wresp_ready ),
.data_i ( apb_wresp ),
.valid_o ( axi_bresp_valid ),
.ready_i ( axi_lite_req_i.b_ready ),
.data_o ( axi_bresp )
);
fall_through_register #(
.T ( int_resp_t )
) i_read_resp_ft_reg (
.clk_i,
.rst_ni,
.clr_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.valid_i ( apb_rresp_valid ),
.ready_o ( apb_rresp_ready ),
.data_i ( apb_rresp ),
.valid_o ( axi_rresp_valid ),
.ready_i ( axi_lite_req_i.r_ready ),
.data_o ( axi_rresp )
);
end
apb_state_e apb_state_q, apb_state_d;
logic apb_update;
logic apb_dec_valid;
sel_idx_t apb_sel_idx;
addr_decode #(
.NoIndices( NoApbSlaves ),
.NoRules ( NoRules ),
.addr_t ( addr_t ),
.rule_t ( rule_t )
) i_apb_decode (
.addr_i ( apb_req.addr ),
.addr_map_i ( addr_map_i ),
.idx_o ( apb_sel_idx ),
.dec_valid_o ( apb_dec_valid ),
.dec_error_o ( ),
.en_default_idx_i ( '0 ),
.default_idx_i ( '0 )
);
always_comb begin
apb_state_d = apb_state_q;
apb_update = 1'b0;
apb_req_o = '0;
apb_req_ready = 1'b0;
apb_wresp = axi_pkg::RESP_SLVERR;
apb_wresp_valid = 1'b0;
apb_rresp = '{data: data_t'(32'hDEA110C8), resp: axi_pkg::RESP_SLVERR};
apb_rresp_valid = 1'b0;
unique case (apb_state_q)
Setup: begin
if (apb_req_valid && apb_wresp_ready && apb_rresp_ready) begin
if (apb_dec_valid && ((apb_req.write && (|apb_req.strb)) || (!apb_req.write))) begin
apb_req_o[apb_sel_idx] = '{
paddr: axi_pkg::aligned_addr(axi_pkg::largest_addr_t'(apb_req.addr), $clog2(DataWidth/8)),
pprot: apb_req.prot,
psel: 1'b1,
penable: 1'b0,
pwrite: apb_req.write,
pwdata: apb_req.data,
pstrb: apb_req.strb
};
apb_state_d = Access;
apb_update = 1'b1;
end else begin
apb_req_ready = 1'b1;
if (apb_req.write) begin
apb_wresp = ~(|apb_req.strb) ? axi_pkg::RESP_OKAY : axi_pkg::RESP_DECERR;
apb_wresp_valid = 1'b1;
end else begin
apb_rresp.resp = axi_pkg::RESP_DECERR;
apb_rresp_valid = 1'b1;
end
end
end
end
Access: begin
apb_req_o[apb_sel_idx] = '{
paddr: axi_pkg::aligned_addr(axi_pkg::largest_addr_t'(apb_req.addr), $clog2(DataWidth/8)),
pprot: apb_req.prot,
psel: 1'b1,
penable: 1'b1,
pwrite: apb_req.write,
pwdata: apb_req.data,
pstrb: apb_req.strb
};
if (apb_resp_i[apb_sel_idx].pready) begin
apb_req_ready = 1'b1;
if (apb_req.write) begin
apb_wresp = apb_resp_i[apb_sel_idx].pslverr ?
axi_pkg::RESP_SLVERR : axi_pkg::RESP_OKAY;
apb_wresp_valid = 1'b1;
end else begin
apb_rresp.data = apb_resp_i[apb_sel_idx].prdata;
apb_rresp.resp = apb_resp_i[apb_sel_idx].pslverr ?
axi_pkg::RESP_SLVERR : axi_pkg::RESP_OKAY;
apb_rresp_valid = 1'b1;
end
apb_state_d = Setup;
apb_update = 1'b1;
end
end
default: ;
endcase
end
always_ff @(posedge (clk_i) or negedge (rst_ni)) begin
if (!rst_ni) begin
apb_state_q <= (Setup);
end else begin
if (apb_update) begin
apb_state_q <= (apb_state_d);
end
end
end
endmodule
module axi_lite_to_apb_intf #(
parameter int unsigned NoApbSlaves = 32'd1,
parameter int unsigned NoRules = 32'd1,
parameter int unsigned AddrWidth = 32'd32,
parameter int unsigned DataWidth = 32'd32,
parameter bit PipelineRequest = 1'b0,
parameter bit PipelineResponse = 1'b0,
parameter type rule_t = logic,
parameter type addr_t = logic [AddrWidth-1:0],
parameter type data_t = logic [DataWidth-1:0],
parameter type strb_t = logic [DataWidth/8-1:0],
parameter type sel_t = logic [NoApbSlaves-1:0]
) (
input logic clk_i,
input logic rst_ni,
AXI_LITE.Slave slv,
output addr_t paddr_o,
output logic [2:0] pprot_o,
output sel_t pselx_o,
output logic penable_o,
output logic pwrite_o,
output data_t pwdata_o,
output strb_t pstrb_o,
input logic [NoApbSlaves-1:0] pready_i,
input data_t [NoApbSlaves-1:0] prdata_i,
input [NoApbSlaves-1:0] pslverr_i,
input rule_t [NoRules-1:0] addr_map_i
);
localparam int unsigned SelIdxWidth = NoApbSlaves > 1 ? $clog2(NoApbSlaves) : 1;
typedef struct packed {
addr_t paddr;
axi_pkg::prot_t pprot;
logic psel;
logic penable;
logic pwrite;
data_t pwdata;
strb_t pstrb;
} apb_req_t;
typedef struct packed {
logic pready;
data_t prdata;
logic pslverr;
} apb_resp_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} aw_chan_t;
typedef struct packed {
data_t data;
strb_t strb;
} w_chan_t;
typedef struct packed {
axi_pkg::resp_t resp;
} b_chan_t;
typedef struct packed {
addr_t addr;
axi_pkg::prot_t prot;
} ar_chan_t;
typedef struct packed {
data_t data;
axi_pkg::resp_t resp;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} axi_req_t;
typedef struct packed {
logic aw_ready;
logic w_ready;
b_chan_t b;
logic b_valid;
logic ar_ready;
r_chan_t r;
logic r_valid;
} axi_resp_t;
axi_req_t axi_req;
axi_resp_t axi_resp;
apb_req_t [NoApbSlaves-1:0] apb_req;
apb_resp_t [NoApbSlaves-1:0] apb_resp;
logic [SelIdxWidth-1:0] apb_sel;
assign axi_req.aw.addr = slv.aw_addr;
assign axi_req.aw.prot = slv.aw_prot;
assign axi_req.aw_valid = slv.aw_valid;
assign axi_req.w.data = slv.w_data;
assign axi_req.w.strb = slv.w_strb;
assign axi_req.w_valid = slv.w_valid;
assign axi_req.b_ready = slv.b_ready;
assign axi_req.ar.addr = slv.ar_addr;
assign axi_req.ar.prot = slv.ar_prot;
assign axi_req.ar_valid = slv.ar_valid;
assign axi_req.r_ready = slv.r_ready;
assign slv.aw_ready = axi_resp.aw_ready;
assign slv.ar_ready = axi_resp.ar_ready;
assign slv.w_ready = axi_resp.w_ready;
assign slv.b_valid = axi_resp.b_valid;
assign slv.b_resp = axi_resp.b.resp;
assign slv.r_valid = axi_resp.r_valid;
assign slv.r_data = axi_resp.r.data;
assign slv.r_resp = axi_resp.r.resp;
onehot_to_bin #(
.ONEHOT_WIDTH ( NoApbSlaves )
) i_onehot_to_bin (
.onehot ( pselx_o ),
.bin ( apb_sel )
);
assign paddr_o = apb_req[apb_sel].paddr;
assign pprot_o = apb_req[apb_sel].pprot;
assign penable_o = apb_req[apb_sel].penable;
assign pwrite_o = apb_req[apb_sel].pwrite;
assign pwdata_o = apb_req[apb_sel].pwdata;
assign pstrb_o = apb_req[apb_sel].pstrb;
for (genvar i = 0; i < NoApbSlaves; i++) begin : gen_apb_resp_assign
assign pselx_o[i] = apb_req[i].psel;
assign apb_resp[i].pready = pready_i[i];
assign apb_resp[i].prdata = prdata_i[i];
assign apb_resp[i].pslverr = pslverr_i[i];
end
axi_lite_to_apb #(
.NoApbSlaves ( NoApbSlaves ),
.NoRules ( NoRules ),
.AddrWidth ( AddrWidth ),
.DataWidth ( DataWidth ),
.PipelineRequest ( PipelineRequest ),
.PipelineResponse ( PipelineResponse ),
.axi_lite_req_t ( axi_req_t ),
.axi_lite_resp_t ( axi_resp_t ),
.apb_req_t ( apb_req_t ),
.apb_resp_t ( apb_resp_t ),
.rule_t ( rule_t )
) i_axi_lite_to_apb (
.clk_i,
.rst_ni,
.axi_lite_req_i ( axi_req ),
.axi_lite_resp_o ( axi_resp ),
.apb_req_o ( apb_req ),
.apb_resp_i ( apb_resp ),
.addr_map_i
);
endmodule
`begin_keywords "1800-2023"
module axi_lite_to_axi #(
parameter int unsigned AxiDataWidth = 32'd0,
parameter type req_lite_t = logic,
parameter type resp_lite_t = logic,
parameter type axi_req_t = logic,
parameter type axi_resp_t = logic
) (
input req_lite_t slv_req_lite_i,
output resp_lite_t slv_resp_lite_o,
input axi_pkg::cache_t slv_aw_cache_i,
input axi_pkg::cache_t slv_ar_cache_i,
output axi_req_t mst_req_o,
input axi_resp_t mst_resp_i
);
localparam int unsigned AxiSize = axi_pkg::size_t'($unsigned($clog2(AxiDataWidth/8)));
assign mst_req_o = '{
aw: '{
addr: slv_req_lite_i.aw.addr,
prot: slv_req_lite_i.aw.prot,
size: AxiSize,
burst: axi_pkg::BURST_FIXED,
cache: slv_aw_cache_i,
default: '0
},
aw_valid: slv_req_lite_i.aw_valid,
w: '{
data: slv_req_lite_i.w.data,
strb: slv_req_lite_i.w.strb,
last: 1'b1,
default: '0
},
w_valid: slv_req_lite_i.w_valid,
b_ready: slv_req_lite_i.b_ready,
ar: '{
addr: slv_req_lite_i.ar.addr,
prot: slv_req_lite_i.ar.prot,
size: AxiSize,
burst: axi_pkg::BURST_FIXED,
cache: slv_ar_cache_i,
default: '0
},
ar_valid: slv_req_lite_i.ar_valid,
r_ready: slv_req_lite_i.r_ready,
default: '0
};
assign slv_resp_lite_o = '{
aw_ready: mst_resp_i.aw_ready,
w_ready: mst_resp_i.w_ready,
b: '{
resp: mst_resp_i.b.resp,
default: '0
},
b_valid: mst_resp_i.b_valid,
ar_ready: mst_resp_i.ar_ready,
r: '{
data: mst_resp_i.r.data,
resp: mst_resp_i.r.resp,
default: '0
},
r_valid: mst_resp_i.r_valid,
default: '0
};
endmodule
module axi_lite_to_axi_intf #(
parameter int unsigned AXI_DATA_WIDTH = 32'd0
) (
AXI_LITE.Slave in,
input axi_pkg::cache_t slv_aw_cache_i,
input axi_pkg::cache_t slv_ar_cache_i,
AXI_BUS.Master out
);
localparam int unsigned AxiSize = axi_pkg::size_t'($unsigned($clog2(AXI_DATA_WIDTH/8)));
initial begin
assert(in.AXI_ADDR_WIDTH == out.AXI_ADDR_WIDTH);
assert(in.AXI_DATA_WIDTH == out.AXI_DATA_WIDTH);
assert(AXI_DATA_WIDTH == out.AXI_DATA_WIDTH);
end
assign out.aw_id = '0;
assign out.aw_addr = in.aw_addr;
assign out.aw_len = '0;
assign out.aw_size = axi_pkg::size_t'(AxiSize);
assign out.aw_burst = axi_pkg::BURST_FIXED;
assign out.aw_lock = '0;
assign out.aw_cache = slv_aw_cache_i;
assign out.aw_prot = '0;
assign out.aw_qos = '0;
assign out.aw_region = '0;
assign out.aw_atop = '0;
assign out.aw_user = '0;
assign out.aw_valid = in.aw_valid;
assign in.aw_ready = out.aw_ready;
assign out.w_data = in.w_data;
assign out.w_strb = in.w_strb;
assign out.w_last = '1;
assign out.w_user = '0;
assign out.w_valid = in.w_valid;
assign in.w_ready = out.w_ready;
assign in.b_resp = out.b_resp;
assign in.b_valid = out.b_valid;
assign out.b_ready = in.b_ready;
assign out.ar_id = '0;
assign out.ar_addr = in.ar_addr;
assign out.ar_len = '0;
assign out.ar_size = axi_pkg::size_t'(AxiSize);
assign out.ar_burst = axi_pkg::BURST_FIXED;
assign out.ar_lock = '0;
assign out.ar_cache = slv_ar_cache_i;
assign out.ar_prot = '0;
assign out.ar_qos = '0;
assign o
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment