A decoder with a k-bit input produces 2ᵏ outputs of which exactly one is high. With an enable input, all outputs are low when the enable is low, which is how a decoder gates a write strobe.
sel[1:0] | en | y[3:0] |
|---|---|---|
00 | 1 | 0001 |
01 | 1 | 0010 |
10 | 1 | 0100 |
11 | 1 | 1000 |
xx | 0 | 0000 |
Watch the bottom row, y. Exactly one bit is ever high.
The diagram shows y in hex, so the four one-hot values appear as 1, 2, 4 and 8.
Slot 1: en is 0, so y is 0000 and no line wakes.
Slot 2: en is 1 and sel is 0, so y is 0001.
Slot 3: sel is 1, so y is 0010.
Slot 4: sel is 2, so y is 0100.
Slot 5: sel is 3, so y is 1000.
Four registers share one write strobe. A write to address 2 must wake register 2 and no other.
A bus write to address addr should update exactly one register. The decoder turns the address into per-register enables; each register's clock-enable or write-enable comes from one output line.
module reg_write_decode (
input logic wr,
input logic [1:0] addr,
output logic we_ctrl, we_status, we_data, we_irq
);
logic [3:0] we;
always_comb begin
we = '0;
if (wr) we[addr] = 1'b1;
end
assign {we_irq, we_data, we_status, we_ctrl} = we;
endmoduleOne-hot enables carry a strong invariant.
At each write-sampling edge, every enable must be known and at most one bit may be set. Check both: assert property (@(posedge clk) !$isunknown(we) && $onehot0(we)); during normal operation.
One-hot enables can safely drive a clock-enable or an AND-OR data select, because only one source is active.
If two enables can ever be active at once, you have a bus contention or a lost-write bug waiting to happen.
$onehot0(x) is true when zero or one bits of x are set. $onehot(x) is true when exactly one bit is set.
These functions count known ones; they do not reject unknown bits. For example, $onehot0(4'b00x1) is true. Pair the one-hot check with !$isunknown(we) so an unknown second enable cannot pass as safe. This is a sampled write-enable check; asynchronous bus drivers also need between-edge checks.
y is high?Bit 2 only: y reads 0100. The decoder sets exactly the selected bit.
y read now?All zeros. A disabled decoder wakes no line, which is how it gates a write strobe.
16 outputs. Every additional select bit doubles the number of outputs (and roughly the gate count), so wide address decodes are normally built hierarchically (decode the upper bits first, then the lower ones).
The parameterized decoder plus a testbench that checks every select and the disabled case.
module decoder #(parameter int K = 2) (
input logic [K-1:0] sel,
input logic en,
output logic [(1<<K)-1:0] y // one-hot
);
always_comb begin
y = '0;
if (en) y[sel] = 1'b1; // set exactly one bit
end
endmodule