diff --git a/hw/floo_axi_chimney.sv b/hw/floo_axi_chimney.sv index 61d3f705..e6885682 100644 --- a/hw/floo_axi_chimney.sv +++ b/hw/floo_axi_chimney.sv @@ -98,7 +98,7 @@ module floo_axi_chimney #( // Duplicate AXI port signals to degenerate ports // in case they are not used axi_req_t axi_req_in; - axi_rsp_t axi_rsp_out; + axi_rsp_t axi_rsp_out, axi_in_rsp_err; // AX queue axi_aw_chan_t axi_aw_queue; @@ -158,6 +158,8 @@ module floo_axi_chimney #( meta_buf_t aw_out_hdr_in, aw_out_hdr_out; meta_buf_t ar_out_hdr_in, ar_out_hdr_out; + // Error signals from AR/AW address decoders + logic [NumAxiChannels-1:0] decode_error_d, decode_error_q; /////////////////////// // Spill registers // /////////////////////// @@ -165,7 +167,21 @@ module floo_axi_chimney #( if (ChimneyCfg.EnMgrPort) begin : gen_sbr_port assign axi_req_in = axi_in_req_i; - assign axi_in_rsp_o = axi_rsp_out; + assign axi_in_rsp_o = (decode_error_q[AxiAr] || decode_error_q[AxiAw]) ? axi_in_rsp_err : + axi_rsp_out; + + axi_err_slv #( + .AxiIdWidth ( AxiCfg.InIdWidth ), + .ATOPs ( AtopSupport ), + .axi_req_t ( axi_in_req_t ), + .axi_resp_t ( axi_in_rsp_t ) + ) i_axi_err_slv ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_i ( test_enable_i ), + .slv_req_i ( axi_in_req_i ), + .slv_resp_o ( axi_in_rsp_err ) + ); if (ChimneyCfg.CutAx) begin : gen_ax_cuts spill_register #( @@ -193,6 +209,9 @@ module floo_axi_chimney #( .valid_o ( axi_ar_queue_valid_out ), .ready_i ( axi_ar_queue_ready_in ) ); + + `FF(decode_error_q[AxiAr], decode_error_d[AxiAr], '0) + `FF(decode_error_q[AxiAw], decode_error_d[AxiAw], '0) end else begin : gen_no_ax_cuts assign axi_aw_queue = axi_in_req_i.aw; assign axi_aw_queue_valid_out = axi_in_req_i.aw_valid; @@ -201,6 +220,9 @@ module floo_axi_chimney #( assign axi_ar_queue = axi_in_req_i.ar; assign axi_ar_queue_valid_out = axi_in_req_i.ar_valid; assign axi_rsp_out.ar_ready = axi_ar_queue_ready_in; + + assign decode_error_q[AxiAr] = decode_error_d[AxiAr]; + assign decode_error_q[AxiAw] = decode_error_d[AxiAw]; end end else begin : gen_err_slv_port axi_err_slv #( @@ -398,11 +420,12 @@ module floo_axi_chimney #( .clk_i, .rst_ni, .route_table_i, - .addr_map_i ( Sam ), - .id_i ( id_t'('0) ), - .addr_i ( axi_req_addr[ch] ), - .route_o ( route_out[ch] ), - .id_o ( id_out[ch] ) + .addr_map_i ( Sam ), + .id_i ( id_t'('0) ), + .addr_i ( axi_req_addr[ch] ), + .route_o ( route_out[ch] ), + .id_o ( id_out[ch] ), + .decode_error_o ( decode_error_d[ch] ) ); end else if (RouteCfg.RouteAlgo == floo_pkg::SourceRouting && (Ch == AxiB || Ch == AxiR)) begin : gen_rsp_route_comp @@ -420,11 +443,12 @@ module floo_axi_chimney #( .clk_i, .rst_ni, .route_table_i, - .addr_i ( '0 ), - .addr_map_i ( '0 ), - .id_i ( axi_rsp_src_id[ch] ), - .route_o ( route_out[ch] ), - .id_o ( id_out[ch] ) + .addr_i ( '0 ), + .addr_map_i ( Sam ), + .id_i ( axi_rsp_src_id[ch] ), + .route_o ( route_out[ch] ), + .id_o ( id_out[ch] ), + .decode_error_o ( decode_error_d[ch] ) ); end end diff --git a/hw/floo_route_comp.sv b/hw/floo_route_comp.sv index 966f3c28..619bb5ba 100644 --- a/hw/floo_route_comp.sv +++ b/hw/floo_route_comp.sv @@ -27,7 +27,8 @@ module floo_route_comp input addr_rule_t [RouteCfg.NumSamRules-1:0] addr_map_i, input route_t [RouteCfg.NumRoutes-1:0] route_table_i, output route_t route_o, - output id_t id_o + output id_t id_o, + output logic decode_error_o ); // Use an address decoder to map the address to a destination ID. @@ -36,34 +37,31 @@ module floo_route_comp // Further, the `rule_t` requires an additional field `id`, which can be used for the return route. // The reason for that is that a request destination is given by a physical address, while the // response destination is given by the ID of the source. + + id_t addr_decode_id; + + addr_decode #( + .NoIndices ( RouteCfg.NumRoutes ), + .NoRules ( RouteCfg.NumSamRules ), + .addr_t ( addr_t ), + .rule_t ( addr_rule_t ), + .idx_t ( id_t ) + ) i_addr_dst_decode ( + .addr_i ( addr_i ), + .addr_map_i ( addr_map_i ), + .idx_o ( addr_decode_id ), + .dec_valid_o ( ), + .dec_error_o ( decode_error_o ), + .en_default_idx_i ( 1'b0 ), + .default_idx_i ( '0 ) + ); + if (UseIdTable && ((RouteCfg.RouteAlgo == IdTable) || (RouteCfg.RouteAlgo == XYRouting) || (RouteCfg.RouteAlgo == SourceRouting))) begin : gen_table_routing - logic dec_error; - - // This is simply to pass the assertions in addr_decode - // It is not used otherwise, since we specify `idx_t` - localparam int unsigned MaxPossibleId = 1 << $bits(id_o); - - addr_decode #( - .NoIndices ( MaxPossibleId ), - .NoRules ( RouteCfg.NumSamRules ), - .addr_t ( addr_t ), - .rule_t ( addr_rule_t ), - .idx_t ( id_t ) - ) i_addr_dst_decode ( - .addr_i ( addr_i ), - .addr_map_i ( addr_map_i ), - .idx_o ( id_o ), - .dec_valid_o ( ), - .dec_error_o ( dec_error ), - .en_default_idx_i ( 1'b0 ), - .default_idx_i ( '0 ) - ); - - `ASSERT(DecodeError, !dec_error) + assign id_o = addr_decode_id; end else if (RouteCfg.RouteAlgo == XYRouting) begin : gen_xy_bits_routing assign id_o.port_id = '0; assign id_o.x = addr_i[RouteCfg.XYAddrOffsetX +: $bits(id_o.x)]; @@ -71,7 +69,8 @@ module floo_route_comp end else if (RouteCfg.RouteAlgo == IdTable) begin : gen_id_bits_routing assign id_o = addr_i[RouteCfg.IdAddrOffset +: $bits(id_o)]; end else if (RouteCfg.RouteAlgo == SourceRouting) begin : gen_source_routing - // Nothing to do here + // Default the ID output to 0 + assign id_o = '0; end else begin : gen_error $fatal(1, "Routing algorithm not implemented"); end