56. Decoder

A. Dataflow

module decoder3to8 (
    input  [2:0] s,
    output [7:0] y
);
    assign y = (8'b0000_0001 << s);
endmodule

B. Behavioral case 

module decoder3to8_case (
    input  [2:0] s,
    output reg [7:0] y
);
    always @* begin
        y = 8'b0000_0000;
        case (s)
            3'b000: y[0] = 1'b1;
            3'b001: y[1] = 1'b1;
            3'b010: y[2] = 1'b1;
            3'b011: y[3] = 1'b1;
            3'b100: y[4] = 1'b1;
            3'b101: y[5] = 1'b1;
            3'b110: y[6] = 1'b1;
            3'b111: y[7] = 1'b1;
        endcase
    end
endmodule

C. Structural (gate-level) — optional

module decoder3to8 (
    input  [2:0] s,
    output [7:0] y
);
    wire n2, n1, n0;
    not (n2, s[2]); not (n1, s[1]); not (n0, s[0]);
    and (y[0], n2, n1, n0);
    and (y[1], n2, n1, s[0]);
    and (y[2], n2, s[1], n0);
    and (y[3], n2, s[1], s[0]);
    and (y[4], s[2], n1, n0);
    and (y[5], s[2], n1, s[0]);
    and (y[6], s[2], s[1], n0);
    and (y[7], s[2], s[1], s[0]);
endmodule

💡Remember

  • A decoder produces a one-hot output: exactly one bit high for valid s.
  • With always @*, always give a default assignment to avoid latches.
  • For unknown selects (s contains X/Z), the dataflow shift may produce X; if you want explicit handling, use casez and decide what to drive (e.g., y = 8'bxxxx_xxxx;).

Testbench Code

`timescale 1ns/1ps

module tb_decoder3to8;
    // 1) Inputs
    reg  [2:0] s;

    // 2) DUT outputs
    wire [7:0] y;

    // 3) Expected (purely combinational from inputs)
    wire [7:0] expected_y = (8'b0000_0001 << s);

    // 4) Single mismatch flag (case-inequality catches X/Z differences)
    wire mismatch = (y !== expected_y);

    // Accounting
    integer TOTAL_TEST_CASES        = 0;
    integer TOTAL_PASSED_TEST_CASES = 0;
    integer TOTAL_FAILED_TEST_CASES = 0;

    // Limits
    integer VCD_MAX_CASES   = 64; // normal rows printed
    integer ERROR_MAX_CASES = 64; // error rows printed
    integer printed_rows    = 0;
    integer printed_errors  = 0;

    // DUT (pick one implementation)
    decoder3to8 dut(.s(s), .y(y));

    // VCD dump
    initial begin
        $dumpfile("tb_decoder3to8.vcd");
        $dumpvars(0,
            tb_decoder3to8.s,
            tb_decoder3to8.y,
            tb_decoder3to8.expected_y,
            tb_decoder3to8.mismatch
        );
        $dumpon;
    end

    // Header + init
    initial begin
        s = 3'b000;
        $display("  s  |   y     | expected_y | mismatch");
        $display("---------------------------------------------------");
    end

    // Apply + check (drive -> wait -> read combinational mismatch)
    task apply_and_check;
        input [2:0] ts;
        begin
            s = ts;
            #1; // settle

            TOTAL_TEST_CASES = TOTAL_TEST_CASES + 1;
            if (!mismatch) begin
                TOTAL_PASSED_TEST_CASES = TOTAL_PASSED_TEST_CASES + 1;
                if (printed_rows < VCD_MAX_CASES) begin
                    $display(" %0d  | 0x%02h  |   0x%02h    |    %0d",
                             s, y, expected_y, mismatch);
                    printed_rows = printed_rows + 1;
                end
            end else begin
                TOTAL_FAILED_TEST_CASES = TOTAL_FAILED_TEST_CASES + 1;
                if (printed_errors < ERROR_MAX_CASES) begin
                    $display("ERR: s=%0d => y=0x%02h (expected 0x%02h)",
                             s, y, expected_y);
                    printed_errors = printed_errors + 1;
                end
            end

            // Optional: stop VCD after cap of total vectors
            if (TOTAL_TEST_CASES == VCD_MAX_CASES) $dumpoff;
        end
    endtask

    integer i;
    initial begin
        // Exhaustive over valid 0..7
        for (i = 0; i < 8; i = i + 1)
            apply_and_check(i[2:0]);

        // Summary
        $display("---------------------------------------------------");
        $display("TOTAL_TEST_CASES=%0d", TOTAL_TEST_CASES);
        $display("TOTAL_PASSED_TEST_CASES=%0d", TOTAL_PASSED_TEST_CASES);
        $display("TOTAL_FAILED_TEST_CASES=%0d", TOTAL_FAILED_TEST_CASES);
        $display("ALL_TEST_CASES_PASSED=%s", (TOTAL_FAILED_TEST_CASES==0) ? "true" : "false");

        #2 $finish;
    end
endmodule