41. Opcode Decoder

Map a 2-bit opcode to a 4-bit one-hot alu_op. This is a parallel decode task (exactly one output bit high).

Requirements

  • Module: alu_decoder
  • Inputs: opcode[1:0]
  • Outputs: alu_op[3:0]

Behaviour

  • opcode = 2'b00alu_op = 4'b0001
  • opcode = 2'b01alu_op = 4'b0010
  • opcode = 2'b10alu_op = 4'b0100
  • opcode = 2'b11alu_op = 4'b1000
  • default → alu_op = 4'b0000

Testbench Code

`timescale 1ns/1ps

module tb_alu_decoder;
    // Input
    reg  [1:0] opcode;
    // DUT output
    wire [3:0] alu_op;

    // Expected (prefixed expected_)
    wire [3:0] expected_alu_op;

    // Mismatch signal (HIGH if outputs do not match expected)
    reg  mismatch;
    wire mismatch_w = (alu_op !== expected_alu_op);

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

    // VCD control
    integer VCD_MAX_CASES = 32;

    // DUT
    alu_decoder dut (.opcode(opcode), .alu_op(alu_op));

    // Golden model (parallel decode)
    assign expected_alu_op =
        (opcode == 2'b00) ? 4'b0001 :
        (opcode == 2'b01) ? 4'b0010 :
        (opcode == 2'b10) ? 4'b0100 :
        (opcode == 2'b11) ? 4'b1000 : 4'b0000;

    // VCD dump (Inputs -> Outputs -> Expected -> Mismatch)
    initial begin
        $dumpfile("tb_alu_decoder.vcd");
        $dumpvars(0,
            tb_alu_decoder.opcode,                // Input
            tb_alu_decoder.alu_op,                // Output
            tb_alu_decoder.expected_alu_op,       // Expected
            tb_alu_decoder.mismatch               // Mismatch
        );
        $dumpon; // start at time 0
    end

    // Init + header
    initial begin
        opcode = 2'b00;
        mismatch = 1'b0;
        $display("opcode | alu_op | expected_alu_op | mismatch");
        $display("--------------------------------------------");
    end

    // Apply one vector, settle, compare, print table row, stop VCD after 32 rows
    task apply_and_check;
        input [1:0] t_opcode;
        begin
            opcode = t_opcode;
            #1; // combinational settle

            mismatch = mismatch_w;

            TOTAL_TEST_CASES = TOTAL_TEST_CASES + 1;
            if (!mismatch) TOTAL_PASSED_TEST_CASES = TOTAL_PASSED_TEST_CASES + 1;
            else           TOTAL_FAILED_TEST_CASES = TOTAL_FAILED_TEST_CASES + 1;

            $display("  %b   |  %b  |       %b       |    %0d",
                     opcode, alu_op, expected_alu_op, mismatch);

            if (TOTAL_TEST_CASES == VCD_MAX_CASES) $dumpoff;
        end
    endtask

    // Stimulus — full truth table (4 cases)
    initial begin
        apply_and_check(2'b00);
        apply_and_check(2'b01);
        apply_and_check(2'b10);
        apply_and_check(2'b11);

        // Summary logs
        $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