diff --git a/Bender.yml b/Bender.yml index 190f633cc..f5cb23636 100644 --- a/Bender.yml +++ b/Bender.yml @@ -21,8 +21,6 @@ sources: # Level 1 - src/axi_intf.sv # Level 2 - - src/axi_address_resolver.sv - - src/axi_arbiter.sv - src/axi_atop_filter.sv - src/axi_cut.sv - src/axi_delayer.sv @@ -33,7 +31,6 @@ sources: - src/axi_to_axi_lite.sv # Level 3 - src/axi_id_remap.sv - - src/axi_lite_xbar.sv - src/axi_multicut.sv - target: synth_test @@ -50,5 +47,4 @@ sources: - test/tb_axi_id_remap.sv - test/tb_axi_delayer.sv - test/tb_axi_lite_to_axi.sv - - test/tb_axi_lite_xbar.sv - test/tb_axi_to_axi_lite.sv diff --git a/CHANGELOG.md b/CHANGELOG.md index ff41ace08..ce91a5a78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,8 +19,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - typedef: fixed bugs ### Removed -- axi_lite_cut: removed file, functionality in axi_cut -- axi_lite_multicut: removed file, functionality in axi_multicut +- axi_address_resolver: removed file, superseded by `common_cells: addr_decoder` +- axi_arbiter: removed file, instead `axi_demux`, `axi_mux` annd `common_cells:rrarb_tree` should be used +- axi_lite_cut: removed file, functionality in axi_cut +- axi_lite_multicut: removed file, functionality in axi_multicut +- axi_lite_xbar: removed file, to be rewritten ## 0.7.2 - 2019-12-03 diff --git a/src/axi_address_resolver.sv b/src/axi_address_resolver.sv deleted file mode 100644 index 0bcd230a5..000000000 --- a/src/axi_address_resolver.sv +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2014-2018 ETH Zurich, University of Bologna -// -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. -// -// Fabian Schuiki - -/// An address resolver. -/// -/// Matches an address against a routing table and produces the index of the -/// matching slave. -module axi_address_resolver #( - /// The address width. - parameter int ADDR_WIDTH = -1, - /// The number of slaves. - parameter int NUM_SLAVE = -1, - /// The number of rules. - parameter int NUM_RULES = -1 -)( - AXI_ROUTING_RULES.xbar rules , - input logic [ADDR_WIDTH-1:0] addr_i , - output logic [$clog2(NUM_SLAVE)-1:0] match_idx_o , - output logic match_ok_o -); - - logic [NUM_SLAVE-1:0][NUM_RULES-1:0] matched_rules; - logic [NUM_SLAVE-1:0] matched_slaves; - - for (genvar i = 0; i < NUM_SLAVE; i++) begin : g_slave - // Match each of the rules. - for (genvar j = 0; j < NUM_RULES; j++) begin : g_rule - logic [ADDR_WIDTH-1:0] base, mask; - logic enabled; - assign base = rules.rules[i][j].base; - assign mask = rules.rules[i][j].mask; - assign enabled = rules.rules[i][j].enabled; - // If the rules is disabled, it matches nothing. - assign matched_rules[i][j] = (enabled && (addr_i & mask) == (base & mask)); - end - - // Check which slaves matched. - assign matched_slaves[i] = |matched_rules[i]; - end - - // // If anything matched the address, output ok. - assign match_ok_o = |matched_slaves; - - // Determine the index of the slave that matched. - find_first_one #(.WIDTH(NUM_SLAVE), .FLIP(0)) i_lzc ( - .in_i ( matched_slaves ), - .first_one_o ( match_idx_o ), - .no_ones_o ( ) - ); - - // Ensure that we have a one-hot match. If we don't, this implies that the - // rules in the routing table are not mututally exclusive. - `ifndef SYNTHESIS - always @(matched_rules, matched_slaves) begin - assert ($onehot0(matched_rules)) else $error("%m: more than one rule matches 0x%0h: %0b", addr_i, matched_rules); - assert ($onehot0(matched_slaves)) else $error("%m: more than one slave matches 0x%0h: %0b", addr_i, matched_slaves); - end - `endif - -endmodule diff --git a/src/axi_arbiter.sv b/src/axi_arbiter.sv deleted file mode 100644 index 94052a2c2..000000000 --- a/src/axi_arbiter.sv +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) 2014-2018 ETH Zurich, University of Bologna -// -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. -// -// Fabian Schuiki - - -/// A round-robin arbiter. -module axi_arbiter #( - /// The number of requestors. - parameter int NUM_REQ = -1 -)( - input logic clk_i , - input logic rst_ni , - AXI_ARBITRATION.arb arb -); - - `ifndef SYNTHESIS - initial begin - assert(NUM_REQ >= 0); - assert(arb.NUM_REQ == NUM_REQ); - end - `endif - - logic [$clog2(NUM_REQ)-1:0] count_d, count_q; - - axi_arbiter_tree #( - .NUM_REQ ( NUM_REQ ), - .ID_WIDTH ( 0 ) - ) i_tree ( - .in_req_i ( arb.in_req ), - .in_ack_o ( arb.in_ack ), - .in_id_i ( '0 ), - .out_req_o ( arb.out_req ), - .out_ack_i ( arb.out_ack ), - .out_id_o ( arb.out_sel ), - .shift_i ( count_q ) - ); - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (~rst_ni) begin - count_q <= '0; - end else if (arb.out_req && arb.out_ack) begin - count_q <= (count_d == NUM_REQ ? '0 : count_d); - end - end - - assign count_d = count_q + 1; - -endmodule - - -/// An arbitration tree. -module axi_arbiter_tree #( - /// The number of requestors. - parameter int NUM_REQ = -1, - /// The width of the ID on the requestor side. - parameter int ID_WIDTH = -1 -)( - input logic [NUM_REQ-1:0] in_req_i , - output logic [NUM_REQ-1:0] in_ack_o , - input logic [NUM_REQ-1:0][ID_WIDTH-1:0] in_id_i , - output logic out_req_o , - input logic out_ack_i , - output logic [ID_WIDTH+$clog2(NUM_REQ)-1:0] out_id_o , - input logic [$clog2(NUM_REQ)-1:0] shift_i -); - - `ifndef SYNTHESIS - initial begin - assert(NUM_REQ >= 0); - assert(ID_WIDTH >= 0); - end - `endif - - // Calculate the number of requests after the head multiplexers. This is equal - // to ceil(NUM_REQ/2). - localparam int NUM_INNER_REQ = NUM_REQ > 0 ? 2**($clog2(NUM_REQ)-1) : 0; - localparam logic [ID_WIDTH:0] ID_MASK = (1 << ID_WIDTH) - 1; - - // Extract the bit that we use for shifting the priorities in the head. - logic shift_bit; - assign shift_bit = shift_i[$high(shift_i)]; - - // Perform pairwise arbitration on the head. - logic [NUM_INNER_REQ-1:0] inner_req, inner_ack; - logic [NUM_INNER_REQ-1:0][ID_WIDTH:0] inner_id; - - for (genvar i = 0; i < NUM_INNER_REQ; i++) begin : g_head - localparam iA = i*2; - localparam iB = i*2+1; - if (iB < NUM_REQ) begin - - // Decide who wins arbitration. If both A and B issue a request, shift_bit - // is used as a tie breaker. Otherwise we simply grant the request. - logic sel; - always_comb begin - if (in_req_i[iA] && in_req_i[iB]) - sel = shift_bit; - else if (in_req_i[iA]) - sel = 0; - else if (in_req_i[iB]) - sel = 1; - else - sel = 0; - end - - assign inner_req[i] = in_req_i[iA] | in_req_i[iB]; - assign in_ack_o[iA] = inner_ack[i] && (sel == 0); - assign in_ack_o[iB] = inner_ack[i] && (sel == 1); - assign inner_id[i] = (sel << ID_WIDTH) | ((sel ? in_id_i[iB] : in_id_i[iA]) & ID_MASK); - end else if (iA < NUM_REQ) begin - assign inner_req[i] = in_req_i[iA]; - assign in_ack_o[iA] = inner_ack[i]; - assign inner_id[i] = in_id_i[iA] & ID_MASK; - end - end - - // Instantiate the tail of the tree. - if (NUM_INNER_REQ > 1) begin : g_tail - axi_arbiter_tree #( - .NUM_REQ ( NUM_INNER_REQ ), - .ID_WIDTH ( ID_WIDTH+1 ) - ) i_tail ( - .in_req_i ( inner_req ), - .in_ack_o ( inner_ack ), - .in_id_i ( inner_id ), - .out_req_o ( out_req_o ), - .out_ack_i ( out_ack_i ), - .out_id_o ( out_id_o ), - .shift_i ( shift_i[$high(shift_i)-1:0] ) - ); - end else if (NUM_INNER_REQ == 1) begin : g_tail - assign out_req_o = inner_req; - assign inner_ack = out_ack_i; - assign out_id_o = inner_id[0]; - end else begin : g_tail - assign out_req_o = in_req_i[0]; - assign in_ack_o[0] = out_ack_i; - assign out_id_o = in_id_i[0]; - end - -endmodule diff --git a/src/axi_lite_xbar.sv b/src/axi_lite_xbar.sv deleted file mode 100644 index 0e611c303..000000000 --- a/src/axi_lite_xbar.sv +++ /dev/null @@ -1,465 +0,0 @@ -// Copyright (c) 2014-2018 ETH Zurich, University of Bologna -// -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. -// -// Fabian Schuiki - -import axi_pkg::*; - - -/// An AXI4-Lite crossbar. -module axi_lite_xbar #( - /// The address width. - parameter int ADDR_WIDTH = -1, - /// The data width. - parameter int DATA_WIDTH = -1, - /// The number of master ports. - parameter int NUM_MASTER = 1, - /// The number of slave ports. - parameter int NUM_SLAVE = 1, - /// The number of routing rules. - parameter int NUM_RULES = -1 -)( - input logic clk_i , - input logic rst_ni , - AXI_LITE.Slave master [NUM_MASTER] , - AXI_LITE.Master slave [NUM_SLAVE] , - AXI_ROUTING_RULES.xbar rules -); - - // The arbitration bus. - AXI_ARBITRATION #(.NUM_REQ(NUM_MASTER)) s_arb_rd(), s_arb_wr(); - - // For now just instantiate the simple crossbar. We may want to add different - // implementations later. - axi_lite_xbar_simple #( - .ADDR_WIDTH ( ADDR_WIDTH ), - .DATA_WIDTH ( DATA_WIDTH ), - .NUM_MASTER ( NUM_MASTER ), - .NUM_SLAVE ( NUM_SLAVE ), - .NUM_RULES ( NUM_RULES ) - ) i_simple ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .master ( master ), - .slave ( slave ), - .rules ( rules ), - .arb_rd ( s_arb_rd.req ), - .arb_wr ( s_arb_wr.req ) - ); - - // Instantiate round-robin arbiters for the read and write channels. - axi_arbiter #( - .NUM_REQ ( NUM_MASTER ) - ) i_arb_rd ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .arb ( s_arb_rd.arb ) - ); - - axi_arbiter #( - .NUM_REQ ( NUM_MASTER ) - ) i_arb_wr ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .arb ( s_arb_wr.arb ) - ); - -endmodule - - -/// A simple implementation of an AXI4-Lite crossbar. Can only serve one master -/// at a time. -module axi_lite_xbar_simple #( - /// The address width. - parameter int ADDR_WIDTH = -1, - /// The data width. - parameter int DATA_WIDTH = -1, - /// The number of master ports. - parameter int NUM_MASTER = 1, - /// The number of slave ports. - parameter int NUM_SLAVE = 1, - /// The number of routing rules. - parameter int NUM_RULES = -1 -)( - input logic clk_i , - input logic rst_ni , - AXI_LITE.Slave master [NUM_MASTER] , - AXI_LITE.Master slave [NUM_SLAVE] , - AXI_ROUTING_RULES.xbar rules , - AXI_ARBITRATION.req arb_rd , - AXI_ARBITRATION.req arb_wr -); - - `ifndef SYNTHESIS - initial begin - assert(NUM_MASTER > 0); - assert(NUM_SLAVE > 0); - assert(NUM_RULES > 0); - assert(rules.AXI_ADDR_WIDTH == ADDR_WIDTH); - assert(rules.NUM_SLAVE == NUM_SLAVE); - end - - // Check master address widths are all equal. - for (genvar i = 0; i < NUM_MASTER; i++) begin : g_chk_master - initial begin - assert(master[i].AXI_ADDR_WIDTH == ADDR_WIDTH); - assert(master[i].AXI_DATA_WIDTH == DATA_WIDTH); - end - end - - // Check slave address widths are all equal. - for (genvar i = 0; i < NUM_SLAVE; i++) begin - initial begin - assert(slave[i].AXI_ADDR_WIDTH == ADDR_WIDTH); - assert(slave[i].AXI_DATA_WIDTH == DATA_WIDTH); - end - end - `endif - - 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 [$clog2(NUM_MASTER)-1:0] master_id_t; - typedef logic [$clog2(NUM_SLAVE)-1:0] slave_id_t; - - // The tag specifies which master is currently being served, and what slave it - // is targeting. There are independent tags for read and write. - struct packed { - master_id_t master; - slave_id_t slave; - } tag_rd_d, tag_wr_d, tag_rd_q, tag_wr_q; - - enum { RD_IDLE, RD_REQ, RD_RESP, RD_ERR_RESP } state_rd_d, state_rd_q; - enum { WR_IDLE, WR_REQ, WR_DATA, WR_RESP, WR_ERR_DATA, WR_ERR_RESP } state_wr_d, state_wr_q; - - always_ff @(posedge clk_i or negedge rst_ni) begin - if (~rst_ni) begin - state_rd_q <= RD_IDLE; - state_wr_q <= WR_IDLE; - tag_rd_q <= '0; - tag_wr_q <= '0; - end else begin - state_rd_q <= state_rd_d; - state_wr_q <= state_wr_d; - tag_rd_q <= tag_rd_d; - tag_wr_q <= tag_wr_d; - end - end - - // Generate the master-side multiplexer. This allows one of the masters to be - // contacted by setting the master_sel_{rd,wr} signal. - master_id_t master_sel_rd, master_sel_wr; - - addr_t [NUM_MASTER-1:0] master_araddr_pack; - logic [NUM_MASTER-1:0] master_rready_pack; - - addr_t [NUM_MASTER-1:0] master_awaddr_pack; - data_t [NUM_MASTER-1:0] master_wdata_pack; - strb_t [NUM_MASTER-1:0] master_wstrb_pack; - logic [NUM_MASTER-1:0] master_wvalid_pack; - logic [NUM_MASTER-1:0] master_bready_pack; - - addr_t master_araddr; - logic master_arready; - data_t master_rdata; - resp_t master_rresp; - logic master_rvalid; - logic master_rready; - - addr_t master_awaddr; - logic master_awready; - data_t master_wdata; - strb_t master_wstrb; - logic master_wvalid; - logic master_wready; - resp_t master_bresp; - logic master_bvalid; - logic master_bready; - - for (genvar i = 0; i < NUM_MASTER; i++) begin - assign master_araddr_pack[i] = master[i].ar_addr; - assign master[i].ar_ready = master_arready && (i == master_sel_rd); - assign master[i].r_data = master_rdata; - assign master[i].r_resp = master_rresp; - assign master[i].r_valid = master_rvalid && (i == master_sel_rd); - assign master_rready_pack[i] = master[i].r_ready; - - assign master_awaddr_pack[i] = master[i].aw_addr; - assign master[i].aw_ready = master_awready && (i == master_sel_wr); - assign master_wdata_pack[i] = master[i].w_data; - assign master_wstrb_pack[i] = master[i].w_strb; - assign master_wvalid_pack[i] = master[i].w_valid; - assign master[i].w_ready = master_wready && (i == master_sel_wr); - assign master[i].b_resp = master_bresp; - assign master_bready_pack[i] = master[i].b_ready; - assign master[i].b_valid = master_bvalid && (i == master_sel_wr); - end - - assign master_araddr = master_araddr_pack [master_sel_rd]; - assign master_rready = master_rready_pack [master_sel_rd]; - - assign master_awaddr = master_awaddr_pack [master_sel_wr]; - assign master_wdata = master_wdata_pack [master_sel_wr]; - assign master_wstrb = master_wstrb_pack [master_sel_wr]; - assign master_wvalid = master_wvalid_pack [master_sel_wr]; - assign master_bready = master_bready_pack [master_sel_wr]; - - // Generate the slave-side multiplexer. This allows one of the slaves to be - // contacted by setting the slave_sel_{rd,wr} signal. - slave_id_t slave_sel_rd, slave_sel_wr; - - logic [NUM_SLAVE-1:0] slave_arready_pack; - data_t [NUM_SLAVE-1:0] slave_rdata_pack; - resp_t [NUM_SLAVE-1:0] slave_rresp_pack; - logic [NUM_SLAVE-1:0] slave_rvalid_pack; - - logic [NUM_SLAVE-1:0] slave_awready_pack; - logic [NUM_SLAVE-1:0] slave_wready_pack; - resp_t [NUM_SLAVE-1:0] slave_bresp_pack; - logic [NUM_SLAVE-1:0] slave_bvalid_pack; - - addr_t slave_araddr; - logic slave_arvalid; - logic slave_arready; - data_t slave_rdata; - resp_t slave_rresp; - logic slave_rvalid; - logic slave_rready; - - addr_t slave_awaddr; - logic slave_awvalid; - logic slave_awready; - data_t slave_wdata; - strb_t slave_wstrb; - logic slave_wvalid; - logic slave_wready; - resp_t slave_bresp; - logic slave_bvalid; - logic slave_bready; - - for (genvar i = 0; i < NUM_SLAVE; i++) begin - assign slave[i].ar_addr = slave_araddr; - assign slave[i].ar_valid = slave_arvalid && (i == slave_sel_rd); - assign slave_arready_pack[i] = slave[i].ar_ready; - assign slave_rdata_pack[i] = slave[i].r_data; - assign slave_rresp_pack[i] = slave[i].r_resp; - assign slave_rvalid_pack[i] = slave[i].r_valid; - assign slave[i].r_ready = slave_rready && (i == slave_sel_rd); - - assign slave[i].aw_addr = slave_awaddr; - assign slave[i].aw_valid = slave_awvalid && (i == slave_sel_wr); - assign slave_awready_pack[i] = slave[i].aw_ready; - assign slave[i].w_data = slave_wdata; - assign slave[i].w_strb = slave_wstrb; - assign slave[i].w_valid = slave_wvalid && (i == slave_sel_wr); - assign slave_wready_pack[i] = slave[i].w_ready; - assign slave_bresp_pack[i] = slave[i].b_resp; - assign slave_bvalid_pack[i] = slave[i].b_valid; - assign slave[i].b_ready = slave_bready && (i == slave_sel_wr); - end - - assign slave_arready = slave_arready_pack [slave_sel_rd]; - assign slave_rdata = slave_rdata_pack [slave_sel_rd]; - assign slave_rresp = slave_rresp_pack [slave_sel_rd]; - assign slave_rvalid = slave_rvalid_pack [slave_sel_rd]; - - assign slave_awready = slave_awready_pack [slave_sel_wr]; - assign slave_wready = slave_wready_pack [slave_sel_wr]; - assign slave_bresp = slave_bresp_pack [slave_sel_wr]; - assign slave_bvalid = slave_bvalid_pack [slave_sel_wr]; - - // Route the valid signals of the masters to the arbiters. They will decide - // which request will be granted. - for (genvar i = 0; i < NUM_MASTER; i++) begin - assign arb_rd.in_req[i] = master[i].ar_valid; - assign arb_wr.in_req[i] = master[i].aw_valid; - end - - // Perform address resolution. - addr_t rd_resolve_addr, wr_resolve_addr; - logic [$clog2(NUM_SLAVE)-1:0] rd_match_idx, wr_match_idx; - logic rd_match_ok, wr_match_ok; - - axi_address_resolver #( - .ADDR_WIDTH( ADDR_WIDTH ), - .NUM_SLAVE ( NUM_SLAVE ), - .NUM_RULES ( NUM_RULES ) - ) i_rd_resolver ( - .rules ( rules ), - .addr_i ( rd_resolve_addr ), - .match_idx_o ( rd_match_idx ), - .match_ok_o ( rd_match_ok ) - ); - - axi_address_resolver #( - .ADDR_WIDTH( ADDR_WIDTH ), - .NUM_SLAVE ( NUM_SLAVE ), - .NUM_RULES ( NUM_RULES ) - ) i_wr_resolver ( - .rules ( rules ), - .addr_i ( wr_resolve_addr ), - .match_idx_o ( wr_match_idx ), - .match_ok_o ( wr_match_ok ) - ); - - // Read state machine. - always_comb begin - state_rd_d = state_rd_q; - tag_rd_d = tag_rd_q; - - arb_rd.out_ack = 0; - master_sel_rd = tag_rd_q.master; - slave_sel_rd = tag_rd_q.slave; - rd_resolve_addr = master_araddr; - - slave_araddr = master_araddr; - slave_arvalid = 0; - master_arready = 0; - master_rdata = slave_rdata; - master_rresp = slave_rresp; - master_rvalid = 0; - slave_rready = 0; - - case (state_rd_q) - RD_IDLE: begin - master_sel_rd = arb_rd.out_sel; - if (arb_rd.out_req) begin - arb_rd.out_ack = 1; - tag_rd_d.master = arb_rd.out_sel; - state_rd_d = RD_REQ; - end - end - - RD_REQ: begin - slave_sel_rd = rd_match_idx; - tag_rd_d.slave = rd_match_idx; - // If the address resolution was successful, propagate the request and - // wait for a response. Otherwise immediately return an error. - if (rd_match_ok) begin - slave_arvalid = 1; - if (slave_arready) begin - state_rd_d = RD_RESP; - master_arready = 1; - end - end else begin - state_rd_d = RD_ERR_RESP; - master_arready = 1; - end - end - - RD_RESP: begin - master_rvalid = slave_rvalid; - slave_rready = master_rready; - if (slave_rvalid && master_rready) begin - state_rd_d = RD_IDLE; - end - end - - // Address resolution failed. Return an error response. - RD_ERR_RESP: begin - master_rresp = axi_pkg::RESP_DECERR; - master_rvalid = 1; - if (master_rready) begin - state_rd_d = RD_IDLE; - end - end - - default: state_rd_d = RD_IDLE; - endcase - end - - // Write state machine. - always_comb begin - state_wr_d = state_wr_q; - tag_wr_d = tag_wr_q; - - arb_wr.out_ack = 0; - master_sel_wr = tag_wr_q.master; - slave_sel_wr = tag_wr_q.slave; - wr_resolve_addr = master_awaddr; - - slave_awaddr = master_awaddr; - slave_awvalid = 0; - master_awready = 0; - slave_wdata = master_wdata; - slave_wstrb = master_wstrb; - slave_wvalid = 0; - master_wready = 0; - master_bresp = slave_bresp; - master_bvalid = 0; - slave_bready = 0; - - case (state_wr_q) - WR_IDLE: begin - master_sel_wr = arb_wr.out_sel; - if (arb_wr.out_req) begin - arb_wr.out_ack = 1; - tag_wr_d.master = arb_wr.out_sel; - state_wr_d = WR_REQ; - end - end - - WR_REQ: begin - slave_sel_wr = wr_match_idx; - tag_wr_d.slave = wr_match_idx; - // If the address resolution was successful, propagate the request and - // wait for a response. Otherwise immediately return an error. - if (wr_match_ok) begin - slave_awvalid = 1; - if (slave_awready) begin - state_wr_d = WR_DATA; - master_awready = 1; - end - end else begin - state_wr_d = WR_ERR_DATA; - master_awready = 1; - end - end - - WR_DATA: begin - master_wready = slave_wready; - slave_wvalid = master_wvalid; - if (slave_wvalid && master_wready) begin - state_wr_d = WR_RESP; - end - end - - WR_RESP: begin - master_bvalid = slave_bvalid; - slave_bready = master_bready; - if (slave_bvalid && master_bready) begin - state_wr_d = WR_IDLE; - end - end - - // Address resolution failed. Discard the data transfer. - WR_ERR_DATA: begin - master_wready = 1; - if (master_wvalid) begin - state_wr_d = WR_ERR_RESP; - end - end - - // Address resolution failed. Return an error response. - WR_ERR_RESP: begin - master_bresp = axi_pkg::RESP_DECERR; - master_bvalid = 1; - if (master_bready) begin - state_wr_d = WR_IDLE; - end - end - - default: state_wr_d = WR_IDLE; - endcase - end - -endmodule diff --git a/test/tb_axi_lite_xbar.sv b/test/tb_axi_lite_xbar.sv deleted file mode 100644 index 54eb61db3..000000000 --- a/test/tb_axi_lite_xbar.sv +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright 2018 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. -// -// Fabian Schuiki - -`include "axi/assign.svh" - -module tb_axi_lite_xbar; - - parameter AW = 32; - parameter DW = 32; - parameter IW = 8; - parameter UW = 8; - - parameter NUM_MASTER = 2; - parameter NUM_SLAVE = 2; - parameter NUM_TRANSACTIONS = 1000; - - localparam tCK = 1ns; - - logic clk = 0; - logic rst = 1; - - AXI_LITE_DV #( - .AXI_ADDR_WIDTH(AW), - .AXI_DATA_WIDTH(DW) - ) master_dv [0:NUM_MASTER-1](clk); - - AXI_LITE #( - .AXI_ADDR_WIDTH(AW), - .AXI_DATA_WIDTH(DW) - ) master [0:NUM_MASTER-1](); - - for (genvar i = 0; i < NUM_MASTER; i++) begin: gen_conn_dv_masters - `AXI_LITE_ASSIGN(master[i], master_dv[i]); - end - - AXI_LITE_DV #( - .AXI_ADDR_WIDTH(AW), - .AXI_DATA_WIDTH(DW) - ) slave_dv [0:NUM_SLAVE-1](clk); - - AXI_LITE #( - .AXI_ADDR_WIDTH(AW), - .AXI_DATA_WIDTH(DW) - ) slave [0:NUM_SLAVE-1](); - - for (genvar i = 0; i < NUM_SLAVE; i++) begin: gen_conn_dv_slaves - `AXI_LITE_ASSIGN(slave_dv[i], slave[i]); - end - - AXI_ROUTING_RULES #( - .AXI_ADDR_WIDTH(AW), - .NUM_SLAVE(NUM_SLAVE), - .NUM_RULES(1) - ) routing(); - - localparam int SLAVE_SHIFT = (AW-$clog2(NUM_SLAVE)); - for (genvar i = 0; i < NUM_SLAVE; i++) begin - logic [AW-1:0] addr = i; - assign routing.rules[i][0].enabled = 1; - assign routing.rules[i][0].mask = '1 << SLAVE_SHIFT; - assign routing.rules[i][0].base = addr << SLAVE_SHIFT; - end - - axi_lite_xbar #( - .ADDR_WIDTH(AW), - .DATA_WIDTH(DW), - .NUM_MASTER(NUM_MASTER), - .NUM_SLAVE(NUM_SLAVE), - .NUM_RULES(1) - ) i_dut ( - .clk_i ( clk ), - .rst_ni ( rst ), - .master ( master ), - .slave ( slave ), - .rules ( routing ) - ); - - // Define the transaction queues. - class transaction_t; - rand logic [AW-1:0] addr; - rand logic [DW-1:0] data; - rand logic [DW/8-1:0] strb; - axi_pkg::resp_t resp; - endclass - - typedef axi_test::axi_lite_driver #( - .AW(AW), - .DW(DW), - .TA(0.2*tCK), - .TT(0.8*tCK) - ) driver_t; - - // Randomly block for a few clock cycles. - task random_delay; - automatic int i; - i = $urandom_range(0, 50); - if (i > 5) return; - repeat (i) @(posedge clk); - endtask - - // Setup a queue for reads and writes for each slave. - transaction_t queue_rd [NUM_SLAVE][$]; - transaction_t queue_wr [NUM_SLAVE][$]; - mailbox mailbox_rd [NUM_SLAVE]; - mailbox mailbox_wr [NUM_SLAVE]; - int tests_total = 0; - int tests_failed = 0; - - // Initialize the master driver processes. - logic [NUM_MASTER-1:0] master_done = '0; - assign done = &master_done; - for (genvar i = 0; i < NUM_MASTER; i++) initial begin : g_master - // Initialize and reset the driver. - static driver_t drv = new(master_dv[i]); - drv.reset_master(); - repeat(2) @(posedge clk); - - // Fork off multiple processes that will issue transactions on the read - // and write paths. - fork - for (int k = 0; k < NUM_TRANSACTIONS; k++) begin : t_read - static transaction_t t; - static logic [DW-1:0] data; - static axi_pkg::resp_t resp; - t = new(); - do begin - automatic int rand_success = t.randomize(); - assert(rand_success); - end while ((t.addr >> SLAVE_SHIFT) >= NUM_SLAVE); - t.resp = axi_pkg::RESP_OKAY; - fork - begin - random_delay(); - drv.send_ar(t.addr); - mailbox_rd[t.addr >> SLAVE_SHIFT].put(t); - end - begin - random_delay(); - drv.recv_r(data, resp); - end - join - random_delay(); - tests_total++; - if (t.data != data || t.resp != resp) begin - tests_failed++; - $info("MISMATCH: master [%0d] read, data exp=%h act=%h, resp exp=%h act=%h", - i, t.data, data, t.resp, resp - ); - end - end - for (int k = 0; k < NUM_TRANSACTIONS; k++) begin : t_write - static transaction_t t; - static axi_pkg::resp_t resp; - t = new(); - do begin - automatic int rand_success = t.randomize(); - assert(rand_success); - end while ((t.addr >> SLAVE_SHIFT) >= NUM_SLAVE); - t.resp = axi_pkg::RESP_OKAY; - fork - begin - random_delay(); - drv.send_aw(t.addr); - mailbox_wr[t.addr >> SLAVE_SHIFT].put(t); - end - begin - random_delay(); - drv.send_w(t.data, t.strb); - end - begin - random_delay(); - drv.recv_b(resp); - end - join - random_delay(); - tests_total++; - if (t.resp != resp) begin - tests_failed++; - $info("MISMATCH: master [%0d] write, resp exp=%h act=%h", - i, t.resp, resp - ); - end - end - join - - repeat(2) @(posedge clk); - master_done[i] = 1; - end - - // Initialize the slave driver processes. - for (genvar i = 0; i < NUM_SLAVE; i++) initial begin : g_slave - // Initialize and reset the driver. - static driver_t drv = new(slave_dv[i]); - drv.reset_slave(); - mailbox_rd[i] = new(); - mailbox_wr[i] = new(); - @(posedge clk); - - // Fork off mulitple processes that will respond to transactions on the read - // and write paths. - fork - while (!done) begin : t_read - static transaction_t t; - static logic [AW-1:0] addr; - random_delay(); - drv.recv_ar(addr); - // t = queue_rd[i].pop_front(); - mailbox_rd[i].get(t); - random_delay(); - drv.send_r(t.data, t.resp); - tests_total++; - if (t.addr != addr) begin - tests_failed++; - $info("MISMATCH: slave [%0d] read, addr exp=%h act=%h", - i, t.addr, addr - ); - end - end - while (!done) begin : t_write - static transaction_t t; - static logic [AW-1:0] addr; - static logic [DW-1:0] data; - static logic [DW/8-1:0] strb; - fork - begin - random_delay(); - drv.recv_aw(addr); - mailbox_wr[i].get(t); - end - begin - random_delay(); - drv.recv_w(data, strb); - end - join - random_delay(); - drv.send_b(t.resp); - tests_total++; - if (t.addr != addr || t.data != data || t.strb != strb) begin - tests_failed++; - $info("MISMATCH: slave [%0d] write, addr exp=%h act=%h, data exp=%h act=%h, strb exp=%h act=%h", - i, t.addr, addr, t.data, data, t.strb, strb - ); - end - end - join - end - - // Clock and reset generator. - initial begin - static int cycle = 0; - #tCK; - rst <= 0; - #tCK; - rst <= 1; - #tCK; - while (!done) begin - clk <= 1; - #(tCK/2); - clk <= 0; - #(tCK/2); - if (cycle >= 1000000) - $fatal(1, "timeout at %t", $time); - cycle++; - end - - if (tests_failed == 0) - $info("ALL %0d TESTS PASSED", tests_total); - else - $error("%0d / %0d TESTS FAILED", tests_failed, tests_total); - end - -endmodule diff --git a/test/tb_axi_lite_xbar.wave.do b/test/tb_axi_lite_xbar.wave.do deleted file mode 100644 index b15de92dd..000000000 --- a/test/tb_axi_lite_xbar.wave.do +++ /dev/null @@ -1,119 +0,0 @@ -onerror {resume} -quietly WaveActivateNextPane {} 0 -add wave -noupdate /tb_axi_lite_xbar/i_dut/clk_i -add wave -noupdate /tb_axi_lite_xbar/i_dut/rst_ni -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/aw_addr} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/aw_valid} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/aw_ready} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/w_data} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/w_strb} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/w_valid} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/w_ready} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/b_resp} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/b_valid} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/b_ready} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/ar_addr} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/ar_valid} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/ar_ready} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/r_data} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/r_resp} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/r_valid} -add wave -noupdate -expand -group {master[1]} {/tb_axi_lite_xbar/master[1]/r_ready} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/aw_addr} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/aw_valid} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/aw_ready} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/w_data} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/w_strb} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/w_valid} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/w_ready} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/b_resp} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/b_valid} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/b_ready} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/ar_addr} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/ar_valid} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/ar_ready} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/r_data} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/r_resp} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/r_valid} -add wave -noupdate -group {master[0]} {/tb_axi_lite_xbar/master[0]/r_ready} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/aw_addr} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/aw_valid} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/aw_ready} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/w_data} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/w_strb} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/w_valid} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/w_ready} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/b_resp} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/b_valid} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/b_ready} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/ar_addr} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/ar_valid} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/ar_ready} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/r_data} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/r_resp} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/r_valid} -add wave -noupdate -expand -group {slave[1]} {/tb_axi_lite_xbar/slave[1]/r_ready} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/aw_addr} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/aw_valid} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/aw_ready} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/w_data} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/w_strb} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/w_valid} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/w_ready} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/b_resp} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/b_valid} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/b_ready} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/ar_addr} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/ar_valid} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/ar_ready} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/r_data} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/r_resp} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/r_valid} -add wave -noupdate -group {slave[0]} {/tb_axi_lite_xbar/slave[0]/r_ready} -add wave -noupdate /tb_axi_lite_xbar/routing/rules -add wave -noupdate -group {dut arb} /tb_axi_lite_xbar/i_dut/s_arb_rd/in_req -add wave -noupdate -group {dut arb} /tb_axi_lite_xbar/i_dut/s_arb_rd/in_ack -add wave -noupdate -group {dut arb} /tb_axi_lite_xbar/i_dut/s_arb_rd/out_req -add wave -noupdate -group {dut arb} /tb_axi_lite_xbar/i_dut/s_arb_rd/out_ack -add wave -noupdate -group {dut arb} /tb_axi_lite_xbar/i_dut/s_arb_rd/out_sel -add wave -noupdate -group {dut arb} /tb_axi_lite_xbar/i_dut/s_arb_wr/in_req -add wave -noupdate -group {dut arb} /tb_axi_lite_xbar/i_dut/s_arb_wr/in_ack -add wave -noupdate -group {dut arb} /tb_axi_lite_xbar/i_dut/s_arb_wr/out_req -add wave -noupdate -group {dut arb} /tb_axi_lite_xbar/i_dut/s_arb_wr/out_ack -add wave -noupdate -group {dut arb} /tb_axi_lite_xbar/i_dut/s_arb_wr/out_sel -add wave -noupdate -group {rd addr resolver} /tb_axi_lite_xbar/i_dut/i_simple/i_rd_resolver/addr_i -add wave -noupdate -group {rd addr resolver} /tb_axi_lite_xbar/i_dut/i_simple/i_rd_resolver/match_idx_o -add wave -noupdate -group {rd addr resolver} /tb_axi_lite_xbar/i_dut/i_simple/i_rd_resolver/match_ok_o -add wave -noupdate -group {rd addr resolver} /tb_axi_lite_xbar/i_dut/i_simple/i_rd_resolver/matched_rules -add wave -noupdate -group {rd addr resolver} /tb_axi_lite_xbar/i_dut/i_simple/i_rd_resolver/matched_slaves -add wave -noupdate -group {wr addr resolver} /tb_axi_lite_xbar/i_dut/i_simple/i_wr_resolver/addr_i -add wave -noupdate -group {wr addr resolver} /tb_axi_lite_xbar/i_dut/i_simple/i_wr_resolver/match_idx_o -add wave -noupdate -group {wr addr resolver} /tb_axi_lite_xbar/i_dut/i_simple/i_wr_resolver/match_ok_o -add wave -noupdate -group {wr addr resolver} /tb_axi_lite_xbar/i_dut/i_simple/i_wr_resolver/matched_rules -add wave -noupdate -group {wr addr resolver} /tb_axi_lite_xbar/i_dut/i_simple/i_wr_resolver/matched_slaves -add wave -noupdate /tb_axi_lite_xbar/i_dut/i_simple/tag_rd_q -add wave -noupdate /tb_axi_lite_xbar/i_dut/i_simple/tag_wr_q -add wave -noupdate /tb_axi_lite_xbar/i_dut/i_simple/tag_rd_d -add wave -noupdate /tb_axi_lite_xbar/i_dut/i_simple/tag_wr_d -add wave -noupdate /tb_axi_lite_xbar/i_dut/i_simple/state_rd_q -add wave -noupdate /tb_axi_lite_xbar/i_dut/i_simple/state_wr_q -add wave -noupdate /tb_axi_lite_xbar/i_dut/i_simple/wr_wvalid -add wave -noupdate /tb_axi_lite_xbar/i_dut/i_simple/wr_wready -TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 1} {384109 ps} 0} -quietly wave cursor active 1 -configure wave -namecolwidth 439 -configure wave -valuecolwidth 100 -configure wave -justifyvalue left -configure wave -signalnamewidth 0 -configure wave -snapdistance 10 -configure wave -datasetprefix 0 -configure wave -rowmargin 4 -configure wave -childrowmargin 2 -configure wave -gridoffset 0 -configure wave -gridperiod 500 -configure wave -griddelta 40 -configure wave -timeline 0 -configure wave -timelineunits ns -update -WaveRestoreZoom {375443 ps} {391851 ps}