Skip to content

Commit

Permalink
Add addr_decode_napot (#144)
Browse files Browse the repository at this point in the history
Co-authored-by: Florian Zaruba <[email protected]>
  • Loading branch information
paulsc96 and zarubaf authored Aug 10, 2022
1 parent 4868bb8 commit ed59d19
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 8 deletions.
1 change: 1 addition & 0 deletions Bender.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ sources:
- src/unread.sv
- src/cdc_reset_ctrlr_pkg.sv
# Level 1
- src/addr_decode_napot.sv
- src/cdc_2phase.sv
- src/cdc_4phase.sv
- src/addr_decode.sv
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## Unreleased
### Added
- Add `addr_decode_napot`: variant of `addr_decode` which uses a base address and mask instead of a start and end address.

### Changed
- Avoid using `$bits()` call in `id_queue`'s parameters.
- Remove `cb_filter` and `cb_filter_pkg` from from Vivado IP packager project sources due to compatibility issues.
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ Please note that cells with status *deprecated* are not to be used for new desig

| Name | Description | Status | Superseded By |
| -------------------------- | --------------------------------------------------------------------------------------------------------- | ------------ | ------------- |
| `addr_decode ` | Address map decoder | active | |
| `addr_decode` | Address map decoder | active | |
| `addr_decode_napot` | Address map decoder using naturally-aligned power of two (NAPOT) regions | active | |
| `ecc_decode` | SECDED Decoder (Single Error Correction, Double Error Detection) | active | |
| `ecc_encode` | SECDED Encoder (Single Error Correction, Double Error Detection) | active | |
| `binary_to_gray` | Binary to gray code converter | active | |
Expand Down
1 change: 1 addition & 0 deletions common_cells.core
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ filesets:
- src/cdc_2phase.sv
- src/cdc_4phase.sv
- src/addr_decode.sv
- src/addr_decode_napot.sv
- src/cb_filter.sv
- src/cdc_fifo_2phase.sv
- src/counter.sv
Expand Down
28 changes: 21 additions & 7 deletions src/addr_decode.sv
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@
/// for which no rule in `addr_map_i` exists to the default index specified by
/// `default_idx_i`. In this case, `dec_error_o` is always `1'b0`.
///
/// The `Napot` parameter allows using naturally-aligned power of two (NAPOT) regions,
/// using base addresses and masks instead of address ranges to specify rules.
///
/// Assertions: The module checks every time there is a change in the address mapping
/// if the resulting map is valid. It fatals if `start_addr` is higher than `end_addr`
/// or if a mapping targets an index that is outside the number of allowed indices.
/// It issues warnings if the address regions of any two mappings overlap.
/// if the resulting map is valid. It fatals if `start_addr` is higher than `end_addr` (non-NAPOT
/// only) or if a mapping targets an index that is outside the number of allowed indices.
/// It issues warnings if the address regions of any two mappings overlap (non-NAPOT only).
module addr_decode #(
/// Highest index which can happen in a rule.
parameter int unsigned NoIndices = 32'd0,
Expand All @@ -46,7 +49,13 @@ module addr_decode #(
/// - `idx`: index of the rule, has to be < `NoIndices`
/// - `start_addr`: start address of the range the rule describes, value is included in range
/// - `end_addr`: end address of the range the rule describes, value is NOT included in range
///
/// If `Napot` is 1, The field names remain the same, but the rule describes a naturally-aligned
/// power of two (NAPOT) region instead of an address range: `start_addr` becomes the base address
/// and `end_addr` the mask. See the wrapping module `addr_decode_napot` for details.
parameter type rule_t = logic,
// Whether this is a NAPOT (base and mask) or regular range decoder
parameter bit Napot = 0,
/// Dependent parameter, do **not** overwite!
///
/// Width of the `idx_o` output port.
Expand Down Expand Up @@ -89,7 +98,11 @@ module addr_decode #(

// match the rules
for (int unsigned i = 0; i < NoRules; i++) begin
if ((addr_i >= addr_map_i[i].start_addr) && (addr_i < addr_map_i[i].end_addr)) begin
if (
!Napot && (addr_i >= addr_map_i[i].start_addr) && (addr_i < addr_map_i[i].end_addr) ||
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] = 1'b1;
dec_valid_o = 1'b1;
dec_error_o = 1'b0;
Expand Down Expand Up @@ -126,7 +139,7 @@ module addr_decode #(
always @(addr_map_i) #0 begin : proc_check_addr_map
if (!$isunknown(addr_map_i)) begin
for (int unsigned i = 0; i < NoRules; i++) begin
check_start : assume (addr_map_i[i].start_addr < addr_map_i[i].end_addr) else
check_start : assume (Napot || addr_map_i[i].start_addr < addr_map_i[i].end_addr) else
$fatal(1, $sformatf("This rule has a higher start than end address!!!\n\
Violating rule %d.\n\
Rule> IDX: %h START: %h END: %h\n\
Expand All @@ -143,8 +156,9 @@ module addr_decode #(
(NoIndices-1)));
for (int unsigned j = i + 1; j < NoRules; j++) begin
// overlap check
check_overlap : assume (!((addr_map_i[j].start_addr < addr_map_i[i].end_addr) &&
(addr_map_i[j].end_addr > addr_map_i[i].start_addr))) else
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))) else
$warning($sformatf("Overlapping address region found!!!\n\
Rule %d: IDX: %h START: %h END: %h\n\
Rule %d: IDX: %h START: %h END: %h\n\
Expand Down
91 changes: 91 additions & 0 deletions src/addr_decode_napot.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// 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: Florian Zaruba <[email protected]>
// Author: Paul Scheffler <[email protected]>

/// This module wraps `addr_decode` in its naturally-aligned power of two (NAPOT) variant,
/// alleviating the need to set the `Napot` parameter and using more descriptive `rule_t`
/// field names. See the `addr_decode`documentation for details.
module addr_decode_napot #(
/// Highest index which can happen in a rule.
parameter int unsigned NoIndices = 32'd0,
/// Total number of rules.
parameter int unsigned NoRules = 32'd0,
/// Address type inside the rules and to decode.
parameter type addr_t = logic,
/// Rule packed struct type.
/// The NAPOT address decoder expects three fields in `rule_t`:
///
/// typedef struct packed {
/// int unsigned idx;
/// addr_t base;
/// addr_t mask;
/// } rule_t;
///
/// - `idx`: index of the rule, has to be < `NoIndices`.
/// - `base`: base address whose specified bits should match `addr_i`.
/// - `mask`: set for bits which are to be checked to determine a match.
parameter type rule_t = logic,
/// Dependent parameter, do **not** overwite!
///
/// Width of the `idx_o` output port.
parameter int unsigned IdxWidth = cf_math_pkg::idx_width(NoIndices),
/// Dependent parameter, do **not** overwite!
///
/// Type of the `idx_o` output port.
parameter type idx_t = logic [IdxWidth-1:0]
) (
/// Address to decode.
input addr_t addr_i,
/// Address map: rule with the highest array position wins on collision
input rule_t [NoRules-1:0] addr_map_i,
/// Decoded index.
output idx_t idx_o,
/// Decode is valid.
output logic dec_valid_o,
/// Decode is not valid, no matching rule found.
output logic dec_error_o,
/// Enable default port mapping.
///
/// When not used, tie to `0`.
input logic en_default_idx_i,
/// Default port index.
///
/// When `en_default_idx_i` is `1`, this will be the index when no rule matches.
///
/// When not used, tie to `0`.
input idx_t default_idx_i
);

// Rename struct field names to those expected by `addr_decode`
typedef struct packed {
int unsigned idx;
addr_t start_addr;
addr_t end_addr;
} rule_range_t;

addr_decode #(
.NoIndices ( NoIndices ) ,
.NoRules ( NoRules ),
.addr_t ( addr_t ),
.rule_t ( rule_range_t ),
.Napot ( 1 )
) i_addr_decode (
.addr_i,
.addr_map_i,
.idx_o,
.dec_valid_o,
.dec_error_o,
.en_default_idx_i,
.default_idx_i
);

endmodule
1 change: 1 addition & 0 deletions src_files.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ common_cells_all:
- src/cdc_2phase.sv
- src/cdc_4phase.sv
- src/addr_decode.sv
- src/addr_decode_napot.sv
- src/cb_filter.sv
- src/cdc_fifo_2phase.sv
- src/counter.sv
Expand Down

0 comments on commit ed59d19

Please sign in to comment.