Opdracht - testbench ALU

Om de juiste werking van de ALU te verifiëren, wordt er opnieuw gebruikt gemaakt van een testbench. Het is een goed idee om tijdens het ontwikkelen van de ALU meteen de functionaliteit te testen. Hiervoor kunnen er heel gericht bepaalde instructies ingesteld worden. Bijvoorbeeld:

Om 12 + 3 te doen weet je dat inputs de volgende moeten zijn:

  • operand1 wordt 12
  • operand2 wordt 3
  • de instructie voor de optelling is
    • ALUOp is “100”
    • signed_unsigned_b is ‘0’
    • arith_logic_b is ‘0’

De uitgangen van de ALU moeten de volgende zijn:

  • result moet 15 zijn ( x"0000000F")
  • de equal-vlag moet ‘0’ zijn
  • de x_lt_y_u-vlag moet ‘0’ zijn
  • de x_lt_y_s-vlag moet ‘0’ zijn

Op deze manier kan je stapsgewijs de testbench opbouwen. Geef hierbij extra aandacht aan de randgevallen. Als jouw implementatie 12 + 3 correct kan berekenen, is de kans groot dat 13 + 3 ook wel zal lukken. De randgevallen zijn het echter wel waard om expliciet te testen. Kan jouw ALU 0xFFFFFFFF + 0xFFFFFFFF correct berekenen? Of -1 - (-1)?

    PSTIM: process
    begin
        operand1 <= x"0000000C";
        operand2 <= x"00000003";
        ALUOp <= "100";
        arith_logic_b <= '0';
        signed_unsigned_b <= '0';
        wait for 2 ns;
        -- check outputs
        if result /= x"0000000F" then
            bad_checks := bad_checks + 1;
        else
            good_checks := good_checks + 1;
        end if;

        if equal /= '0' then
            bad_checks := bad_checks + 1;
        else
            good_checks := good_checks + 1;
        end if;

        if x_lt_y_u /= '0' then
            bad_checks := bad_checks + 1;
        else
            good_checks := good_checks + 1;
        end if;

        if x_lt_y_s /= '0' then
            bad_checks := bad_checks + 1;
        else
            good_checks := good_checks + 1;
        end if;
        
        wait for 2 ns;

        wait;
    end process;

Wanneer je denkt alle implementaties gedaan te hebben, kan je een grotere testbench los laten op jouw design. Een voorbeeld hiervan kan je hier downloaden. Deze testbench is, zoals je misschien al vermoedde, gegenereerd. Voor de verbetering van de opdracht wordt een soortgelijke testbench gebruikt.


...
        operand1 <= x"8ffb9e07"; -- 2415631879
        operand2 <= x"fdcea5ee"; -- 4258178542
        ALUOp <= "000";
        arith_logic_b <= '0';
        signed_unsigned_b <= '0';
        wait for 2 ns;
        -- check outputs
        if result /= x"8dca8406" then
            bad_checks := bad_checks + 1;
        else
            good_checks := good_checks + 1;
        end if;
        if equal /= '0' then
            bad_checks := bad_checks + 1;
        else
            good_checks := good_checks + 1;
        end if;
        if x_lt_y_u /= '1' then
            bad_checks := bad_checks + 1;
        else
            good_checks := good_checks + 1;
        end if;
        if x_lt_y_s /= '1' then
            bad_checks := bad_checks + 1;
        else
            good_checks := good_checks + 1;
        end if;
        wait for 2 ns;
...
        report "DISCH_GRADING (good, bad, total): " & integer'image(good_checks) & " " & integer'image(bad_checks) & " " & integer'image(good_checks + bad_checks) & "" severity note;
...

Deze aangeleverde testbench controleert ook of de uitgang gelijk is aan de “juiste” uitgang. Hiervoor moet het resultaat kloppen, maar ook de relevante flags.

Na 2 ns wordt elke uitgange vergeleken en wordt ofwel de good_checks teller ofwel de bad_checks teller verhoogd. Op het einde van de testbench worden deze tellers en hun som in de console geprint om een overzicht te krijgen.

Voorbeeld van de rapportering

Voor de verbetering van deze taak wordt een soortgelijke testbench gebruikt. Er wordt enkel gekeken naar de rapportering.