29. Half Added using NAND Primitive

module ha_nand_only(
  input  wire a,
  input  wire b,
  output wire sum,
  output wire cout
);
  wire n1, n2, n3;
  nand g0(n1, a, b);
  nand g1(n2, a, n1);
  nand g2(n3, b, n1);
  nand g3(sum, n2, n3);
  nand g4(cout, n1, n1);
endmodule

💡 Remember

  • Inverter: ~x via nand(x,x). AND: x&y via nand(x,y) then invert with another nand.
  • XOR with 4 NANDs: n1=~(a&b), n2=~(a&n1), n3=~(b&n1), sum=~(n2&n3).
  • Structural designs with primitives are combinational; every output is a pure function of inputs.

Testbench Code

`timescale 1ns/1ps
module tb_ha_nand_only;
  reg  a, b;
  wire sum, cout;

  wire expected_sum, expected_cout;
  wire mismatch;

  ha_nand_only dut(.a(a), .b(b), .sum(sum), .cout(cout));

  assign expected_sum  = a ^ b;
  assign expected_cout = a & b;

  assign mismatch = (sum !== expected_sum) | (cout !== expected_cout);

  initial begin
    $dumpfile("tb_ha_nand_only.vcd");
    $dumpvars(0,
      a, b,
      sum, cout,
      expected_sum, expected_cout,
      mismatch
    );
  end

  integer TOTAL_TEST_CASES, TOTAL_PASSED_TEST_CASES, TOTAL_FAILED_TEST_CASES;
  integer ia, ib;

  initial begin
    TOTAL_TEST_CASES = 0; TOTAL_PASSED_TEST_CASES = 0; TOTAL_FAILED_TEST_CASES = 0;

    for (ia = 0; ia < 2; ia = ia + 1) begin
      for (ib = 0; ib < 2; ib = ib + 1) begin
        a = ia[0]; b = ib[0]; #1;
        $display("CASE=a%0d_b%0d : sum=%0b expected_sum=%0b  cout=%0b expected_cout=%0b  %s",
                 a, b, sum, expected_sum, cout, expected_cout, mismatch ? "MISMATCH" : "OK");
        TOTAL_TEST_CASES = TOTAL_TEST_CASES + 1;
        if (!mismatch) TOTAL_PASSED_TEST_CASES = TOTAL_PASSED_TEST_CASES + 1;
        else begin
          TOTAL_FAILED_TEST_CASES = TOTAL_FAILED_TEST_CASES + 1;
          $display("  FAILED INPUTS: a=%0b b=%0b", a, b);
        end
        #4;
      end
    end

    $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");
    $finish;
  end
endmodule