50. Vector Min/Max Pair

module minmax4_task (
    input  [7:0] v0,
    input  [7:0] v1,
    input  [7:0] v2,
    input  [7:0] v3,
    output reg [7:0] min_val,
    output reg [7:0] max_val
);
    task minmax4;
        input  [7:0] a, b, c, d;
        output [7:0] min_o;
        output [7:0] max_o;

        reg [7:0] min01, max01;
        reg [7:0] min23, max23;
        begin
            // (a,b)
            max01 = (a > b) ? a : b;
            min01 = (a > b) ? b : a;
            // (c,d)
            max23 = (c > d) ? c : d;
            min23 = (c > d) ? d : c;
            // Across pairs
            max_o = (max01 > max23) ? max01 : max23;
            min_o = (min01 < min23) ? min01 : min23;
        end
    endtask

    reg [7:0] tmin, tmax;

    always @* begin
        minmax4(v0, v1, v2, v3, tmin, tmax);
        min_val = tmin;
        max_val = tmax;
    end
endmodule

💡Remember

  • Tasks can return multiple outputs — perfect for (min, max) pairs.
  • Keep the module combinational: call the task inside always @* and drive all outputs.
  • Pairwise reduction (compare in pairs, then compare the pair results) keeps logic depth small and code clear.

Testbench Code

`timescale 1ns/1ps

module tb_minmax4_task;
    // 1) Inputs
    reg  [7:0] v0, v1, v2, v3;

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

    // 3) Expected (prefixed expected_)
    reg  [7:0] expected_min_val;
    reg  [7:0] expected_max_val;

    // 4) Mismatch (HIGH on fail)
    reg  mismatch;
    wire mismatch_w = (min_val !== expected_min_val) ||
                      (max_val !== expected_max_val);

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

    // VCD limit
    integer VCD_MAX_CASES = 32;

    // DUT
    minmax4_task dut(
        .v0(v0), .v1(v1), .v2(v2), .v3(v3),
        .min_val(min_val), .max_val(max_val)
    );

    // ---------- Golden model (TB-only) ----------
    function [7:0] f_max2; input [7:0] a,b; begin f_max2 = (a > b) ? a : b; end endfunction
    function [7:0] f_min2; input [7:0] a,b; begin f_min2 = (a < b) ? a : b; end endfunction

    task compute_expected;
        input [7:0] a,b,c,d;
        reg   [7:0] max01, max23, min01, min23;
        begin
            max01 = f_max2(a,b);  min01 = f_min2(a,b);
            max23 = f_max2(c,d);  min23 = f_min2(c,d);
            expected_max_val = f_max2(max01, max23);
            expected_min_val = f_min2(min01, min23);
        end
    endtask

    // ---- VCD dump (Inputs -> Outputs -> Expected -> Mismatch) ----
    initial begin
        $dumpfile("tb_minmax4_task.vcd");
        $dumpvars(0,
            tb_minmax4_task.v0, tb_minmax4_task.v1, tb_minmax4_task.v2, tb_minmax4_task.v3, // Inputs
            tb_minmax4_task.min_val, tb_minmax4_task.max_val,                                // Outputs
            tb_minmax4_task.expected_min_val, tb_minmax4_task.expected_max_val,              // Expected
            tb_minmax4_task.mismatch                                                         // Mismatch
        );
        $dumpon; // start at #0
    end

    // Header + init
    initial begin
        v0=0; v1=0; v2=0; v3=0; mismatch=0;
        expected_min_val=0; expected_max_val=0;
        $display("    v0    v1    v2    v3  | min  max | exp_min exp_max | mismatch");
        $display("-----------------------------------------------------------------");
    end

    // Apply + check (EXPECTED FIRST -> WAIT -> COMPARE)
    task apply_and_check;
        input [7:0] a, b, c, d;
        begin
            v0 = a; v1 = b; v2 = c; v3 = d;

            compute_expected(a,b,c,d); // expected first
            #1;                        // let DUT settle

            mismatch = mismatch_w;

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

            $display("0x%02h 0x%02h 0x%02h 0x%02h | 0x%02h 0x%02h |  0x%02h   0x%02h |    %0d",
                     v0, v1, v2, v3,
                     min_val, max_val,
                     expected_min_val, expected_max_val,
                     mismatch);

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

    integer i;
    integer seed;
    initial begin
        seed = 32'hC0DE_FEED ^ $time;

        // Directed (≤ ~16 rows printed)
        apply_and_check(8'h00, 8'h00, 8'h00, 8'h00);
        apply_and_check(8'hFF, 8'hFF, 8'hFF, 8'hFF);
        apply_and_check(8'h01, 8'h02, 8'h03, 8'h04);
        apply_and_check(8'h04, 8'h03, 8'h02, 8'h01);
        apply_and_check(8'hAA, 8'h55, 8'hC3, 8'h3C);
        apply_and_check(8'h10, 8'h10, 8'hF0, 8'h0F);
        apply_and_check(8'h7F, 8'h80, 8'h00, 8'hFF);
        apply_and_check(8'h11, 8'h22, 8'h11, 8'h22);

        // Small patterned sweep (still printed; keep under 20 total)
        for (i = 0; i < 6; i = i + 1)
            apply_and_check(i, i+8, 8'hF0+i, 8'h0F+i);

        // A few randoms (ensure total cases ≤ 32)
        repeat (6) apply_and_check($random(seed), $random(seed), $random(seed), $random(seed));

        // 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