From d3301005424e0077e47d1cbeafe7ac416678b25c Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Sat, 21 Oct 2023 17:20:36 +0100 Subject: [PATCH] Create implicit nets for inputs of gate primitives. Prior to this we failed to create implicit nets for inputs of gate primitives, which is required by the standard (IEEE 1800-2017 6.10). Note: outputs were covered due to being modeled as the LHS of assignments, which do create implicit nets. --- docs/CONTRIBUTORS | 1 + src/V3LinkDot.cpp | 2 +- src/verilog.y | 46 +++-- .../t/t_gate_primitives_implicit_net.out | 166 ++++++++++++++++++ .../t/t_gate_primitives_implicit_net.pl | 23 +++ .../t/t_gate_primitives_implicit_net.v | 101 +++++++++++ 6 files changed, 324 insertions(+), 15 deletions(-) create mode 100755 test_regress/t/t_gate_primitives_implicit_net.out create mode 100755 test_regress/t/t_gate_primitives_implicit_net.pl create mode 100755 test_regress/t/t_gate_primitives_implicit_net.v diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 80b58a622..5c0e7cf46 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -183,5 +183,6 @@ Yuri Victorovich Yutetsu TAKATSUKASA Yves Mathieu Zhanglei Wang +Zhou Shen Zixi Li أحمد المحمودي diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index a6f052659..df0028782 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1679,7 +1679,7 @@ private: } void visit(AstImplicit* nodep) override { // Unsupported gates need implicit creation - pinImplicitExprRecurse(nodep); + pinImplicitExprRecurse(nodep->exprsp()); // We're done with implicit gates VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } diff --git a/src/verilog.y b/src/verilog.y index 3bd0218ab..3d553f667 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -55,6 +55,7 @@ #define DELAY_LIST(delayp, assignsp) \ if (delayp) { \ for (auto* nodep = assignsp; nodep; nodep = nodep->nextp()) { \ + if (VN_IS(nodep, Implicit)) continue; \ auto* const assignp = VN_AS(nodep, NodeAssign); \ assignp->timingControlp(nodep == assignsp ? delayp : delayp->cloneTree(false)); \ } \ @@ -373,6 +374,7 @@ int V3ParseGrammar::s_modTypeImpNum = 0; { \ if (AstStrengthSpec* const specp = VN_CAST(strengthSpecNodep, StrengthSpec)) { \ for (auto* nodep = beginp; nodep; nodep = nodep->nextp()) { \ + if (VN_IS(nodep, Implicit)) continue; \ auto* const assignp = VN_AS(nodep, typeToCast); \ assignp->strengthSpecp(nodep == beginp ? specp : specp->cloneTree(false)); \ } \ @@ -5347,7 +5349,8 @@ gateBuf: gateFront variable_lvalue ',' exprList ')' { AstNodeExpr* inp = $4; while (inp->nextp()) inp = VN_AS(inp->nextp(), NodeExpr); - $$ = new AstAssignW{$1, $2, GRAMMARP->createGatePin(inp->cloneTree(false))}; + $$ = new AstImplicit{$1, inp->cloneTree(false)}; + $$->addNext(new AstAssignW{$1, $2, GRAMMARP->createGatePin(inp->cloneTree(false))}); for (AstNodeExpr* outp = $4; outp->nextp(); outp = VN_CAST(outp->nextp(), NodeExpr)) { $$->addNext(new AstAssignW{$1, outp->cloneTree(false), GRAMMARP->createGatePin(inp->cloneTree(false))}); @@ -5358,8 +5361,9 @@ gateNot: gateFront variable_lvalue ',' exprList ')' { AstNodeExpr* inp = $4; while (inp->nextp()) inp = VN_AS(inp->nextp(), NodeExpr); - $$ = new AstAssignW{$1, $2, new AstNot{$1, - GRAMMARP->createGatePin(inp->cloneTree(false))}}; + $$ = new AstImplicit{$1, inp->cloneTree(false)}; + $$->addNext(new AstAssignW{$1, $2, new AstNot{$1, + GRAMMARP->createGatePin(inp->cloneTree(false))}}); for (AstNodeExpr* outp = $4; outp->nextp(); outp = VN_CAST(outp->nextp(), NodeExpr)) { $$->addNext(new AstAssignW{$1, outp->cloneTree(false), new AstNot{$1, @@ -5369,44 +5373,58 @@ gateNot: ; gateBufif0: gateFront variable_lvalue ',' gatePinExpr ',' gatePinExpr ')' - { $$ = new AstAssignW{$1, $2, new AstBufIf1{$1, new AstNot{$1, $6}, $4}}; DEL($1); } + { $$ = new AstImplicit{$1, $6->cloneTree(false)}; + $$->addExprsp($4->cloneTree(false)); + $$->addNext(new AstAssignW{$1, $2, new AstBufIf1{$1, new AstNot{$1, $6}, $4}}); DEL($1); } ; gateBufif1: gateFront variable_lvalue ',' gatePinExpr ',' gatePinExpr ')' - { $$ = new AstAssignW{$1, $2, new AstBufIf1{$1, $6, $4}}; DEL($1); } + { $$ = new AstImplicit{$1, $6->cloneTree(false)}; + $$->addExprsp($4->cloneTree(false)); + $$->addNext(new AstAssignW{$1, $2, new AstBufIf1{$1, $6, $4}}); DEL($1); } ; gateNotif0: gateFront variable_lvalue ',' gatePinExpr ',' gatePinExpr ')' - { $$ = new AstAssignW{$1, $2, new AstBufIf1{$1, new AstNot{$1, $6}, - new AstNot{$1, $4}}}; DEL($1); } + { $$ = new AstImplicit{$1, $6->cloneTree(false)}; + $$->addExprsp($4->cloneTree(false)); + $$->addNext(new AstAssignW{$1, $2, new AstBufIf1{$1, new AstNot{$1, $6}, + new AstNot{$1, $4}}}); DEL($1); } ; gateNotif1: gateFront variable_lvalue ',' gatePinExpr ',' gatePinExpr ')' - { $$ = new AstAssignW{$1, $2, new AstBufIf1{$1, $6, new AstNot{$1, $4}}}; DEL($1); } + { $$ = new AstImplicit{$1, $6->cloneTree(false)}; + $$->addExprsp($4->cloneTree(false)); + $$->addNext(new AstAssignW{$1, $2, new AstBufIf1{$1, $6, new AstNot{$1, $4}}}); DEL($1); } ; gateAnd: gateFront variable_lvalue ',' gateAndPinList ')' - { $$ = new AstAssignW{$1, $2, $4}; DEL($1); } + { $$ = new AstImplicit{$1, $4->cloneTree(false)}; + $$->addNext(new AstAssignW{$1, $2, $4}); DEL($1); } ; gateNand: gateFront variable_lvalue ',' gateAndPinList ')' - { $$ = new AstAssignW{$1, $2, new AstNot{$1, $4}}; DEL($1); } + { $$ = new AstImplicit{$1, $4->cloneTree(false)}; + $$->addNext(new AstAssignW{$1, $2, new AstNot{$1, $4}}); DEL($1); } ; gateOr: gateFront variable_lvalue ',' gateOrPinList ')' - { $$ = new AstAssignW{$1, $2, $4}; DEL($1); } + { $$ = new AstImplicit{$1, $4->cloneTree(false)}; + $$->addNext(new AstAssignW{$1, $2, $4}); DEL($1); } ; gateNor: gateFront variable_lvalue ',' gateOrPinList ')' - { $$ = new AstAssignW{$1, $2, new AstNot{$1, $4}}; DEL($1); } + { $$ = new AstImplicit{$1, $4->cloneTree(false)}; + $$->addNext(new AstAssignW{$1, $2, new AstNot{$1, $4}}); DEL($1); } ; gateXor: gateFront variable_lvalue ',' gateXorPinList ')' - { $$ = new AstAssignW{$1, $2, $4}; DEL($1); } + { $$ = new AstImplicit{$1, $4->cloneTree(false)}; + $$->addNext(new AstAssignW{$1, $2, $4}); DEL($1); } ; gateXnor: gateFront variable_lvalue ',' gateXorPinList ')' - { $$ = new AstAssignW{$1, $2, new AstNot{$1, $4}}; DEL($1); } + { $$ = new AstImplicit{$1, $4->cloneTree(false)}; + $$->addNext(new AstAssignW{$1, $2, new AstNot{$1, $4}}); DEL($1); } ; gatePullup: gateFront variable_lvalue ')' { $$ = new AstPull{$1, $2, true}; DEL($1); } diff --git a/test_regress/t/t_gate_primitives_implicit_net.out b/test_regress/t/t_gate_primitives_implicit_net.out new file mode 100755 index 000000000..3f41c1ff9 --- /dev/null +++ b/test_regress/t/t_gate_primitives_implicit_net.out @@ -0,0 +1,166 @@ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:15:21: Signal definition not found, creating implicitly: 'i_and1' + 15 | and g_and(o_and, i_and1, i_and2, i_and3); + | ^~~~~~ + ... For warning description see https://verilator.org/warn/IMPLICIT?v=latest + ... Use "/* verilator lint_off IMPLICIT */" and lint_on around source to disable this message. +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:15:29: Signal definition not found, creating implicitly: 'i_and2' + : ... Suggested alternative: 'i_and1' + 15 | and g_and(o_and, i_and1, i_and2, i_and3); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:15:37: Signal definition not found, creating implicitly: 'i_and3' + : ... Suggested alternative: 'i_and1' + 15 | and g_and(o_and, i_and1, i_and2, i_and3); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:15:14: Signal definition not found, creating implicitly: 'o_and' + : ... Suggested alternative: 'i_and1' + 15 | and g_and(o_and, i_and1, i_and2, i_and3); + | ^~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:16:30: Signal definition not found, creating implicitly: 'i_not1' + 16 | not g_not(o_not1, o_not2, i_not1); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:16:14: Signal definition not found, creating implicitly: 'o_not1' + : ... Suggested alternative: 'i_not1' + 16 | not g_not(o_not1, o_not2, i_not1); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:16:22: Signal definition not found, creating implicitly: 'o_not2' + : ... Suggested alternative: 'o_not1' + 16 | not g_not(o_not1, o_not2, i_not1); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:17:21: Signal definition not found, creating implicitly: 'i_nor1' + : ... Suggested alternative: 'i_not1' + 17 | nor g_nor(o_nor, i_nor1, i_nor2, i_nor3); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:17:29: Signal definition not found, creating implicitly: 'i_nor2' + : ... Suggested alternative: 'i_nor1' + 17 | nor g_nor(o_nor, i_nor1, i_nor2, i_nor3); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:17:37: Signal definition not found, creating implicitly: 'i_nor3' + : ... Suggested alternative: 'i_nor1' + 17 | nor g_nor(o_nor, i_nor1, i_nor2, i_nor3); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:17:14: Signal definition not found, creating implicitly: 'o_nor' + : ... Suggested alternative: 'i_nor1' + 17 | nor g_nor(o_nor, i_nor1, i_nor2, i_nor3); + | ^~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:18:18: Signal definition not found, creating implicitly: 'i_or1' + : ... Suggested alternative: 'i_nor1' + 18 | or g_or(o_or, i_or1, i_or2, i_or3); + | ^~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:18:25: Signal definition not found, creating implicitly: 'i_or2' + : ... Suggested alternative: 'i_nor2' + 18 | or g_or(o_or, i_or1, i_or2, i_or3); + | ^~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:18:32: Signal definition not found, creating implicitly: 'i_or3' + : ... Suggested alternative: 'i_nor3' + 18 | or g_or(o_or, i_or1, i_or2, i_or3); + | ^~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:18:12: Signal definition not found, creating implicitly: 'o_or' + : ... Suggested alternative: 'o_nor' + 18 | or g_or(o_or, i_or1, i_or2, i_or3); + | ^~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:19:24: Signal definition not found, creating implicitly: 'i_nand1' + : ... Suggested alternative: 'i_and1' + 19 | nand g_nand(o_nand, i_nand1, i_nand2, i_nand3); + | ^~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:19:33: Signal definition not found, creating implicitly: 'i_nand2' + : ... Suggested alternative: 'i_and2' + 19 | nand g_nand(o_nand, i_nand1, i_nand2, i_nand3); + | ^~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:19:42: Signal definition not found, creating implicitly: 'i_nand3' + : ... Suggested alternative: 'i_and3' + 19 | nand g_nand(o_nand, i_nand1, i_nand2, i_nand3); + | ^~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:19:16: Signal definition not found, creating implicitly: 'o_nand' + : ... Suggested alternative: 'o_and' + 19 | nand g_nand(o_nand, i_nand1, i_nand2, i_nand3); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:20:21: Signal definition not found, creating implicitly: 'i_xor1' + : ... Suggested alternative: 'i_nor1' + 20 | xor g_xor(o_xor, i_xor1, i_xor2, i_xor3); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:20:29: Signal definition not found, creating implicitly: 'i_xor2' + : ... Suggested alternative: 'i_nor2' + 20 | xor g_xor(o_xor, i_xor1, i_xor2, i_xor3); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:20:37: Signal definition not found, creating implicitly: 'i_xor3' + : ... Suggested alternative: 'i_nor3' + 20 | xor g_xor(o_xor, i_xor1, i_xor2, i_xor3); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:20:14: Signal definition not found, creating implicitly: 'o_xor' + : ... Suggested alternative: 'o_nor' + 20 | xor g_xor(o_xor, i_xor1, i_xor2, i_xor3); + | ^~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:21:23: Signal definition not found, creating implicitly: 'i_xnor1' + : ... Suggested alternative: 'i_nor1' + 21 | xnor g_xor(o_xnor, i_xnor1, i_xnor2, i_xnor3); + | ^~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:21:32: Signal definition not found, creating implicitly: 'i_xnor2' + : ... Suggested alternative: 'i_nor2' + 21 | xnor g_xor(o_xnor, i_xnor1, i_xnor2, i_xnor3); + | ^~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:21:41: Signal definition not found, creating implicitly: 'i_xnor3' + : ... Suggested alternative: 'i_nor3' + 21 | xnor g_xor(o_xnor, i_xnor1, i_xnor2, i_xnor3); + | ^~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:21:15: Signal definition not found, creating implicitly: 'o_xnor' + : ... Suggested alternative: 'o_nor' + 21 | xnor g_xor(o_xnor, i_xnor1, i_xnor2, i_xnor3); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:22:30: Signal definition not found, creating implicitly: 'i_buf1' + 22 | buf g_buf(o_buf1, o_buf2, i_buf1); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:22:14: Signal definition not found, creating implicitly: 'o_buf1' + : ... Suggested alternative: 'i_buf1' + 22 | buf g_buf(o_buf1, o_buf2, i_buf1); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:22:22: Signal definition not found, creating implicitly: 'o_buf2' + : ... Suggested alternative: 'o_buf1' + 22 | buf g_buf(o_buf1, o_buf2, i_buf1); + | ^~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:23:41: Signal definition not found, creating implicitly: 'i_bufif02' + 23 | bufif0 g_bufif0(o_bufif0, i_bufif01, i_bufif02); + | ^~~~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:23:30: Signal definition not found, creating implicitly: 'i_bufif01' + : ... Suggested alternative: 'i_bufif02' + 23 | bufif0 g_bufif0(o_bufif0, i_bufif01, i_bufif02); + | ^~~~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:23:20: Signal definition not found, creating implicitly: 'o_bufif0' + : ... Suggested alternative: 'i_bufif01' + 23 | bufif0 g_bufif0(o_bufif0, i_bufif01, i_bufif02); + | ^~~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:24:41: Signal definition not found, creating implicitly: 'i_bufif12' + : ... Suggested alternative: 'i_bufif02' + 24 | bufif1 g_bufif1(o_bufif1, i_bufif11, i_bufif12); + | ^~~~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:24:30: Signal definition not found, creating implicitly: 'i_bufif11' + : ... Suggested alternative: 'i_bufif01' + 24 | bufif1 g_bufif1(o_bufif1, i_bufif11, i_bufif12); + | ^~~~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:24:20: Signal definition not found, creating implicitly: 'o_bufif1' + : ... Suggested alternative: 'o_bufif0' + 24 | bufif1 g_bufif1(o_bufif1, i_bufif11, i_bufif12); + | ^~~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:25:41: Signal definition not found, creating implicitly: 'i_notif02' + : ... Suggested alternative: 'i_bufif02' + 25 | notif0 g_notif0(o_notif0, i_notif01, i_notif02); + | ^~~~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:25:30: Signal definition not found, creating implicitly: 'i_notif01' + : ... Suggested alternative: 'i_notif02' + 25 | notif0 g_notif0(o_notif0, i_notif01, i_notif02); + | ^~~~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:25:20: Signal definition not found, creating implicitly: 'o_notif0' + : ... Suggested alternative: 'i_notif01' + 25 | notif0 g_notif0(o_notif0, i_notif01, i_notif02); + | ^~~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:26:41: Signal definition not found, creating implicitly: 'i_notif12' + : ... Suggested alternative: 'i_notif02' + 26 | notif1 g_notif1(o_notif1, i_notif11, i_notif12); + | ^~~~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:26:30: Signal definition not found, creating implicitly: 'i_notif11' + : ... Suggested alternative: 'i_notif01' + 26 | notif1 g_notif1(o_notif1, i_notif11, i_notif12); + | ^~~~~~~~~ +%Warning-IMPLICIT: t/t_gate_primitives_implicit_net.v:26:20: Signal definition not found, creating implicitly: 'o_notif1' + : ... Suggested alternative: 'o_notif0' + 26 | notif1 g_notif1(o_notif1, i_notif11, i_notif12); + | ^~~~~~~~ diff --git a/test_regress/t/t_gate_primitives_implicit_net.pl b/test_regress/t/t_gate_primitives_implicit_net.pl new file mode 100755 index 000000000..922c66457 --- /dev/null +++ b/test_regress/t/t_gate_primitives_implicit_net.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2023 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +compile( + verilator_flags2 => ["-Wno-fatal --no-skip-identical"], + expect_filename => $Self->{golden_filename}, + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_gate_primitives_implicit_net.v b/test_regress/t/t_gate_primitives_implicit_net.v new file mode 100755 index 000000000..7c1308524 --- /dev/null +++ b/test_regress/t/t_gate_primitives_implicit_net.v @@ -0,0 +1,101 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/ + // Inputs + clk + ); + input clk; + int cyc=1; + + // Instantiate the primitive gates to be tested. + and g_and(o_and, i_and1, i_and2, i_and3); + not g_not(o_not1, o_not2, i_not1); + nor g_nor(o_nor, i_nor1, i_nor2, i_nor3); + or g_or(o_or, i_or1, i_or2, i_or3); + nand g_nand(o_nand, i_nand1, i_nand2, i_nand3); + xor g_xor(o_xor, i_xor1, i_xor2, i_xor3); + xnor g_xor(o_xnor, i_xnor1, i_xnor2, i_xnor3); + buf g_buf(o_buf1, o_buf2, i_buf1); + bufif0 g_bufif0(o_bufif0, i_bufif01, i_bufif02); + bufif1 g_bufif1(o_bufif1, i_bufif11, i_bufif12); + notif0 g_notif0(o_notif0, i_notif01, i_notif02); + notif1 g_notif1(o_notif1, i_notif11, i_notif12); + + // Generate random data for inputs + reg rd_data1, rd_data2, rd_data3; + always @(posedge clk) begin + rd_data1 = 1'($random); + rd_data2 = 1'($random); + rd_data3 = 1'($random); + end + + // Assign the input of primitive gates. +`default_nettype none + assign i_and1 = rd_data1; + assign i_and2 = rd_data2; + assign i_and3 = rd_data3; + + assign i_not1 = rd_data1; + + assign i_nor1 = rd_data1; + assign i_nor2 = rd_data2; + assign i_nor3 = rd_data3; + + assign i_or1 = rd_data1; + assign i_or2 = rd_data2; + assign i_or3 = rd_data3; + + assign i_nand1 = rd_data1; + assign i_nand2 = rd_data2; + assign i_nand3 = rd_data3; + + assign i_xor1 = rd_data1; + assign i_xor2 = rd_data2; + assign i_xor3 = rd_data3; + + assign i_xnor1 = rd_data1; + assign i_xnor2 = rd_data2; + assign i_xnor3 = rd_data3; + + assign i_buf1 = rd_data1; + + assign i_bufif01 = rd_data1; + assign i_bufif02 = rd_data2; + + assign i_bufif11 = rd_data1; + assign i_bufif12 = rd_data2; + + assign i_notif01 = rd_data1; + assign i_notif02 = rd_data2; + + assign i_notif11 = rd_data1; + assign i_notif12 = rd_data2; + + // Check the outputs of the gate instances + always @(negedge clk) begin + if (o_and !== (i_and1 & i_and2 & i_and3)) $stop; + if ((o_not1 !== ~i_not1) || (o_not2 != ~i_not1)) $stop; + if (o_nor !== !(i_nor1 | i_nor2 | i_nor3)) $stop; + if (o_or !== (i_or1 | i_or2 | i_or3)) $stop; + if (o_nand !== !(i_nand1 & i_nand2 & i_nand3)) $stop; + if (o_xor !== (i_xor1 ^ i_xor2 ^ i_xor3)) $stop; + if (o_xnor !== !(i_xnor1 ^ i_xnor2 ^ i_xnor3)) $stop; + if ((o_buf1 !== i_buf1) || (o_buf2 !== i_buf1)) $stop; + if (!(o_bufif0 == (i_bufif01 & !i_bufif02))) $stop; + if (!(o_bufif1 == (i_bufif11 & i_bufif12))) $stop; + if (!(o_notif0 == (!i_notif01 & !i_notif02))) $stop; + if (!(o_notif1 == (!i_notif11 & i_notif12))) $stop; + end + + always @(posedge clk) begin + cyc = cyc + 1; + if (cyc == 100) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule