// 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. // Author: Wolfgang Roenninger <wroennin@ethz.ch> // test bench for addr_decode module 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; // struct to be used in the tb typedef struct packed { int unsigned idx; addr_t start_addr; addr_t end_addr; } tb_rule_t; // normal map 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} }; // overlapping map 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} }; // DUT signal definitions addr_t addr; // input address tb_rule_t [NoRules-1:0] addr_map; // input address map idx_t idx; // output index logic dec_valid, dec_error; // output flags logic en_default_idx; // default enable idx_t default_idx; // default index longint unsigned passed_checks = 0; longint unsigned failed_checks = 0; // application of stimuli initial begin : stimulus passed_checks <= 0; failed_checks <= 0; addr_map <= map_0; en_default_idx <= 1'b0; default_idx <= idx_t'(1); #500; // count over all addresses $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; // count over all addresses 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 // checker assertions, these assertion get triggered every time the input address changes // serves as model for the address decoder 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 // decode should pass 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 // check for the right decode error 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 // DUT instantiation addr_decode #( .NoIndices ( NoIndices ), // number indices in rules .NoRules ( NoRules ), // total number of rules .addr_t ( addr_t ), // address type .rule_t ( tb_rule_t ) // has to be overridden, see above! ) i_addr_decode_dut ( .addr_i ( addr ), // address to decode .addr_map_i ( addr_map ), // address map: rule with the highest position wins .idx_o ( idx ), // decoded index .dec_valid_o ( dec_valid ), // decode is valid .dec_error_o ( dec_error ), // decode is not valid // Default index mapping enable .en_default_idx_i( en_default_idx ), // enable default port mapping .default_idx_i ( default_idx ) // default port index ); endmodule