When accessing memory-mapped hardware, we must check if the address lies between a base address and a higher, inclusive bound address within the decoded range. Rather than do so "manually" each time, we can create a single module that will decode any address range with minimal logic. In both of the designs that follow, we provide the CAD tools with enough information for them to perform Boolean optimization and minimize the decoding logic. We also don't have to figure out the width of the decoded address range ahead of time, but only have to give the width of the total address space.

The first decoder checks if the input address matches each possible valid address in the decoded range, then outputs the bitwise OR of all these checks. Some boolean algebra shows that this circuit will always optimize down to a minimal form: any sequence of address bits which iterate over their entire range become Boolean "don't care", leaving the other address bits to do the matching. The constant bits in the valid addresses range will also cause gates to simplify further.

This approach has one caveat: you may have to test, at synthesis time, up to all 2n possible valid addresses, and store the matches into a vector 2n bits wide. As far as I know, Verilog implementations have a maximum vector width of a few million, so this decoder may break for decoded address ranges more than 20-23 bits wide (1 to 8 Mega-locations), or have excessive synthesis times. However, this implementation yields the smallest, fastest logic possible for a fixed address range.

(It might be possible to avoid the wide vector by altering the implementation to cumulatively OR the address matches as they are generated, but that then describes a very long circuit, which the CAD tool may not optimize as expected. See the next decoder for such an optimization surprise.)

```// A *universal* address decoder.
// Works for any static address range at any starting point.

`default_nettype none

#(
)
(
output  reg                         hit
);
initial begin
hit = 0;
end

integer                     i              = 0;

// Check each valid address in range for match
always @(*) begin
end
end

// Do any of them match?
always @(*) begin
end
endmodule
```

If we want to decode address ranges that are much larger, or if we want to dynamically change the decoded address range, we have to use an arithmetic bounds test which involves two subtractions (i.e.: is the address >= to the base and <= to the bound?). This is one case where expressing the function behaviourally, rather than structurally with explicit full-adder logic, yields a better synthesis result (but your particular CAD tool may do otherwise).

This approach maps well to FPGAs, since it will use the built-in carry-chain hardware, which can reach high speeds without pipelining (e.g.: ~500 MHz for a 32-bit adder on Stratix IV). Furthermore, making the base and bound address inputs constants might optimize the hardware down to plain logic without using subtractors (Quartus does it). The resulting circuit is not as optimal as the static decoder above, but still small and fast.

```// A *universal* address decoder.
// Works for any address range at any starting point.

#(
)
(
output  reg                         hit
);
initial begin
hit = 0;
end

reg base_or_higher = 0;
reg bound_or_lower = 0;

always @(*) begin