1-to-4 Demultiplexer Verilog Code (Behavioral + Dataflow)
A 1-to-4 demultiplexer routes a single data input to one of four outputs, while a 2-bit select line decides the destination and the other three outputs stay low. This tutorial gives you working, runnable demultiplexer Verilog code in two coding styles — behavioral (a case statement) and dataflow (gate-level assigns) — plus a testbench that drives every select combination. Copy either block into a .v file and simulate it with Icarus Verilog in under a minute.
📘 New to the concept? Read the theory first: Demultiplexer: working & truth table.
What a 1-to-4 demultiplexer does
A demux is the opposite of a multiplexer. Instead of picking one of many inputs, it takes one input and steers it to one of many outputs. Our module has three ports: a one-bit data input din, a two-bit select sel, and a four-bit output bus y. The selected output carries the value of din; every other output is forced to 0. Because a 2-bit select has four combinations, one data line fans out to exactly four possible destinations.
| sel[1:0] | Active output | y[3:0] when din = 1 |
|---|---|---|
| 00 | y[0] | 0001 |
| 01 | y[1] | 0010 |
| 10 | y[2] | 0100 |
| 11 | y[3] | 1000 |
Notice that when din = 0, the whole bus is 0 no matter what sel is, because din gates every output. That is the single most useful property to remember when you debug a demux.
Behavioral Verilog code
The behavioral style describes what the hardware should do using a procedural always block. It is the most readable version and the one most people reach for first.
// 1-to-4 demultiplexer -- behavioral style
module demux_1to4_behav (
input wire din, // single data input
input wire [1:0] sel, // 2-bit select
output reg [3:0] y // 4 outputs
);
always @(*) begin
y = 4'b0000; // default: every output low
case (sel)
2'b00: y[0] = din;
2'b01: y[1] = din;
2'b10: y[2] = din;
2'b11: y[3] = din;
endcase
end
endmodule
// Testbench: drive din through every select line
module tb_demux_behav;
reg din;
reg [1:0] sel;
wire [3:0] y;
integer i;
demux_1to4_behav dut (.din(din), .sel(sel), .y(y));
initial begin
$display("time din sel | y3 y2 y1 y0");
$display("------------+------------");
din = 1'b1;
for (i = 0; i < 4; i = i + 1) begin
sel = i[1:0];
#5;
$display("%4t %b %b | %b %b %b %b",
$time, din, sel, y[3], y[2], y[1], y[0]);
end
din = 1'b0; sel = 2'b10; #5;
$display("%4t %b %b | %b %b %b %b (din=0 => all low)",
$time, din, sel, y[3], y[2], y[1], y[0]);
$finish;
end
endmoduletime din sel | y3 y2 y1 y0 ------------+------------ 5 1 00 | 0 0 0 1 10 1 01 | 0 0 1 0 15 1 10 | 0 1 0 0 20 1 11 | 1 0 0 0 25 0 10 | 0 0 0 0 (din=0 => all low) /var/folders/l0/gs5hnkm56g54bmxg32r6nnwr0000gn/T/tmprje4x_e1/demux_1to4_behav.v:40: $finish called at 25 (1s)
Three details make this block correct. First, y is declared output reg because it is assigned inside a procedural block — reg here means "a variable assigned in an always", not a flip-flop. Second, the sensitivity list @(*) auto-includes both din and sel, so the output recomputes whenever either changes. Third, the default line y = 4'b0000; runs before the case, so the three unselected outputs are explicitly driven low on every evaluation. That default is what keeps the logic purely combinational.
Dataflow Verilog code
The dataflow style describes the same circuit as Boolean equations using continuous assign statements. Each output is din ANDed with one decoded combination of the select bits, which maps directly onto AND gates and inverters.
// 1-to-4 demultiplexer -- dataflow style
module demux_1to4_dataflow (
input wire din,
input wire [1:0] sel,
output wire [3:0] y
);
// Each output = din gated by one decoded select combination
assign y[0] = din & ~sel[1] & ~sel[0];
assign y[1] = din & ~sel[1] & sel[0];
assign y[2] = din & sel[1] & ~sel[0];
assign y[3] = din & sel[1] & sel[0];
endmodule
// Testbench: monitor outputs while select cycles 00 -> 11
module tb_demux_dataflow;
reg din;
reg [1:0] sel;
wire [3:0] y;
integer i;
demux_1to4_dataflow dut (.din(din), .sel(sel), .y(y));
initial begin
$monitor("t=%4t din=%b sel=%b -> y=%b", $time, din, sel, y);
din = 1'b1;
for (i = 0; i < 4; i = i + 1) begin
sel = i[1:0];
#5;
end
din = 1'b0; sel = 2'b11; #5;
$finish;
end
endmodulet= 0 din=1 sel=00 -> y=0001 t= 5 din=1 sel=01 -> y=0010 t= 10 din=1 sel=10 -> y=0100 t= 15 din=1 sel=11 -> y=1000 t= 20 din=0 sel=11 -> y=0000 /var/folders/l0/gs5hnkm56g54bmxg32r6nnwr0000gn/T/tmpn939o4gk/demux_1to4_dataflow.v:31: $finish called at 25 (1s)
Here y must be output wire, because continuous assign drives a net rather than a procedural variable. Read y[0] = din & ~sel[1] & ~sel[0] as "pass din through only when sel is 00". The four equations are mutually exclusive, so at most one output is ever high. Both modules produce identical hardware; the dataflow version just spells out the gates explicitly, which is handy when you want to reason about fan-out or gate count.
How the testbench drives every select line
Both testbenches instantiate the design under test, then use a for loop to walk sel through 00, 01, 10, and 11 with din held high, stepping 5 time units between changes. The behavioral bench prints a formatted table with $display; the dataflow bench uses $monitor, which automatically reprints the line whenever any watched signal changes. After the loop, each bench sets din = 0 to confirm the whole bus collapses to 0, then calls $finish to end the simulation. Build and run either file with:
iverilog -g2005 -o sim demux_1to4_behav.v && vvp sim
Common mistakes
- Dropping the default assignment. Without
y = 4'b0000;before thecase, the synthesizer infers a latch and unselected outputs hold their old value instead of going low. - Wrong port type. Using
output wirein the behavioral version (oroutput regin the dataflow version) is a compile error. Procedural assignment needsreg; continuousassignneedswire. - An incomplete sensitivity list. Writing
always @(sel)instead ofalways @(*)omitsdin, so simulation misses output changes when onlydintoggles. - Confusing a demux with a decoder. A 2-to-4 decoder has no data input — it just activates one line per select code. A demux additionally gates that line with
din. - Forgetting
$finish. A testbench built around$monitorwith no$finishnever terminates and the simulator appears to hang.
Quick check
Why assign y = 4’b0000 before the case statement in the behavioral version?
So the three unselected outputs are driven low on every evaluation. Without this default the tool infers a latch and stale output values persist, breaking the combinational behavior.
If sel = 2’b10 and din = 1, which output is high?
y[2]. Select code 10 routes din to output index 2, giving y = 0100; all other outputs stay 0.
Why is y declared output reg in the behavioral module but output wire in the dataflow module?
In the behavioral version y is written inside a procedural always block, which requires a reg-type variable. In the dataflow version continuous assign drives a net, which must be a wire.
What do all four outputs do when din = 0, regardless of sel?
They are all 0. Since din gates every output (ANDed into each equation, or copied in each case branch), a low data input forces the entire y bus low.
Share your question in comments or talk to our mentor team for batch guidance.
Learn Verilog with mentors, labs and placement support
This free series is maintained by the ChipXpert training team in Hyderabad & Bengaluru. Go deeper with instructor-led courses on real EDA tools.
Explore VLSI Courses