// Copyright 2019 ETH Zurich and University of Bologna. // Copyright and related rights are licensed under the Solderpad Hardware // License, Version 0.51 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law // or agreed to in writing, software, hardware and materials distributed under // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. // // Authors: // - Wolfgang Roenninger <wroennin@iis.ee.ethz.ch> // - Andreas Kurth <akurth@iis.ee.ethz.ch> // AXI ID Prepend: This module prepends/strips the MSB from the AXI IDs. // Constraints enforced through assertions: ID width of slave and master port module axi_id_prepend #( parameter int unsigned NoBus = 1, // Can take multiple axi busses parameter int unsigned AxiIdWidthSlvPort = 4, // AXI ID Width of the Slave Ports parameter int unsigned AxiIdWidthMstPort = 6, // AXI ID Width of the Master Ports parameter type slv_aw_chan_t = logic, // AW Channel Type for slv port parameter type slv_w_chan_t = logic, // W Channel Type for slv port parameter type slv_b_chan_t = logic, // B Channel Type for slv port parameter type slv_ar_chan_t = logic, // AR Channel Type for slv port parameter type slv_r_chan_t = logic, // R Channel Type for slv port parameter type mst_aw_chan_t = logic, // AW Channel Type for mst port parameter type mst_w_chan_t = logic, // W Channel Type for mst port parameter type mst_b_chan_t = logic, // B Channel Type for mst port parameter type mst_ar_chan_t = logic, // AR Channel Type for mst port parameter type mst_r_chan_t = logic, // R Channel Type for mst port // DEPENDENT PARAMETER DO NOT OVERWRITE! parameter int unsigned PreIdWidth = AxiIdWidthMstPort - AxiIdWidthSlvPort ) ( input logic [PreIdWidth-1:0] pre_id_i, // ID to be prepended // slave port (input), connect master modules here // AW channel 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, // W channel 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, // B channel 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, // AR channel 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, // R channel 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, // master ports (output), connect slave modules here // AW channel 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, // W channel 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, // B channel 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, // AR channel 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, // R channel 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 ); // prepend the ID 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] = slv_aw_chans_i[i]; mst_ar_chans_o[i] = 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 // The ID is in the highest bits of the struct, so an assignment from a channel with a wide ID // to a channel with a shorter ID correctly cuts the prepended ID. assign slv_b_chans_o[i] = mst_b_chans_i[i]; assign slv_r_chans_o[i] = mst_r_chans_i[i]; end // assign the handshaking's and w channel 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; // pragma translate_off `ifndef VERILATOR initial begin : p_assert assert(NoBus > 0) else $fatal(1, "Input must be at least one element wide."); assert(PreIdWidth == ($bits(mst_aw_chans_o[0].id) - $bits(slv_aw_chans_i[0].id))) else $fatal(1, "Prepend ID Width must be: $bits(mst_aw_chans_o.id)-$bits(slv_aw_chans_i.id)"); assert ($bits(mst_aw_chans_o[0].id) > $bits(slv_aw_chans_i[0].id)) else $fatal(1, "The master AXI port has to have a wider ID than the slave port."); end aw_id : assert final( mst_aw_chans_o[0].id[$bits(slv_aw_chans_i[0].id)-1:0] === slv_aw_chans_i[0].id) else $fatal (1, "Something with the AW channel ID prepending went wrong."); aw_addr : assert final(mst_aw_chans_o[0].addr === slv_aw_chans_i[0].addr) else $fatal (1, "Something with the AW channel ID prepending went wrong."); aw_len : assert final(mst_aw_chans_o[0].len === slv_aw_chans_i[0].len) else $fatal (1, "Something with the AW channel ID prepending went wrong."); aw_size : assert final(mst_aw_chans_o[0].size === slv_aw_chans_i[0].size) else $fatal (1, "Something with the AW channel ID prepending went wrong."); aw_qos : assert final(mst_aw_chans_o[0].qos === slv_aw_chans_i[0].qos) else $fatal (1, "Something with the AW channel ID prepending went wrong."); b_id : assert final( mst_b_chans_i[0].id[$bits(slv_b_chans_o[0].id)-1:0] === slv_b_chans_o[0].id) else $fatal (1, "Something with the B channel ID stripping went wrong."); b_resp : assert final(mst_b_chans_i[0].resp === slv_b_chans_o[0].resp) else $fatal (1, "Something with the B channel ID stripping went wrong."); ar_id : assert final( mst_ar_chans_o[0].id[$bits(slv_ar_chans_i[0].id)-1:0] === slv_ar_chans_i[0].id) else $fatal (1, "Something with the AR channel ID prepending went wrong."); ar_addr : assert final(mst_ar_chans_o[0].addr === slv_ar_chans_i[0].addr) else $fatal (1, "Something with the AR channel ID prepending went wrong."); ar_len : assert final(mst_ar_chans_o[0].len === slv_ar_chans_i[0].len) else $fatal (1, "Something with the AR channel ID prepending went wrong."); ar_size : assert final(mst_ar_chans_o[0].size === slv_ar_chans_i[0].size) else $fatal (1, "Something with the AR channel ID prepending went wrong."); ar_qos : assert final(mst_ar_chans_o[0].qos === slv_ar_chans_i[0].qos) else $fatal (1, "Something with the AR channel ID prepending went wrong."); r_id : assert final(mst_r_chans_i[0].id[$bits(slv_r_chans_o[0].id)-1:0] === slv_r_chans_o[0].id) else $fatal (1, "Something with the R channel ID stripping went wrong."); r_data : assert final(mst_r_chans_i[0].data === slv_r_chans_o[0].data) else $fatal (1, "Something with the R channel ID stripping went wrong."); r_resp : assert final(mst_r_chans_i[0].resp === slv_r_chans_o[0].resp) else $fatal (1, "Something with the R channel ID stripping went wrong."); `endif // pragma translate_on endmodule