Support SystemVerilog ==? and !=? operators.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@945 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
parent
4a9bea6980
commit
5f6d69affd
4
Changes
4
Changes
|
@ -3,6 +3,10 @@ Revision history for Verilator
|
|||
The contributors that suggested a given feature are shown in []. [by ...]
|
||||
indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
* Verilator 3.65***
|
||||
|
||||
**** Support SystemVerilog ==? and !=? operators.
|
||||
|
||||
* Verilator 3.652 6/21/2007
|
||||
|
||||
**** Report as many warning types as possible before exiting.
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
# This file is part of Verilator.
|
||||
#
|
||||
# Author: Wilson Snyder <wsnyder@wsnyder.org> or <wsnyder@world.std.com>
|
||||
# Author: Wilson Snyder <wsnyder@wsnyder.org>
|
||||
#
|
||||
# Code available from: http://www.veripool.com/verilator
|
||||
#
|
||||
|
|
|
@ -1010,12 +1010,14 @@ Verilator currently has very minimal support for SystemVerilog. As
|
|||
SystemVerilog features enter common usage they will be added. Contact the
|
||||
author if a feature you need is missing.
|
||||
|
||||
Verilator implements the full SystemVerilog 1800-2005 preprocessor subset,
|
||||
Verilator implements the full SystemVerilog 1800-2005 preprocessor,
|
||||
including function call-like preprocessor defines.
|
||||
|
||||
Verilator supports $bits, $countones, $error, $fatal, $info, $isunknown,
|
||||
$onehot, $onehot0, $warning, always_comb, always_ff, always_latch,
|
||||
do-while, and final. It also supports .name and .* interconnection.
|
||||
Verilator supports ==? and !=? operators, $bits, $countones, $error,
|
||||
$fatal, $info, $isunknown, $onehot, $onehot0, $warning, always_comb,
|
||||
always_ff, always_latch, do-while, and final.
|
||||
|
||||
It also supports .name and .* interconnection.
|
||||
|
||||
Verilator partially supports assert.
|
||||
|
||||
|
|
|
@ -2606,6 +2606,39 @@ struct AstNeqCase : public AstNodeBiCom {
|
|||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstEqWild : public AstNodeBiop {
|
||||
// Note wildcard operator rhs differs from lhs
|
||||
AstEqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
virtual ~AstEqWild() {}
|
||||
virtual AstType type() const { return AstType::EQWILD;}
|
||||
virtual AstNode* clone() { return new AstEqWild(*this); }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildEq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k==? %r)"; }
|
||||
virtual string emitOperator() { return "VL_EQ"; } // Until have 4 state anyways
|
||||
virtual string emitSimpleOperator() { return "=="; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstNeqWild : public AstNodeBiop {
|
||||
AstNeqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
virtual ~AstNeqWild() {}
|
||||
virtual AstType type() const { return AstType::NEQWILD;}
|
||||
virtual AstNode* clone() { return new AstNeqWild(*this); }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildNeq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k!=? %r)"; }
|
||||
virtual string emitOperator() { return "VL_NEQ"; } // Until have 4 state anyways
|
||||
virtual string emitSimpleOperator() { return "!="; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstConcat : public AstNodeBiop {
|
||||
// If you're looking for {#{}}, see AstReplicate
|
||||
AstConcat(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
|
|
|
@ -1110,6 +1110,10 @@ private:
|
|||
TREEOP ("AstLogNot{$lhsp.castEqCase}", "AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
|
||||
TREEOPV("AstNot {$lhsp.castNeqCase, $lhsp.width1}","AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
|
||||
TREEOP ("AstLogNot{$lhsp.castNeqCase}", "AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
|
||||
TREEOPV("AstNot {$lhsp.castEqWild, $lhsp.width1}","AstNeqWild{$lhsp->op1p(),$lhsp->op2p()}");
|
||||
TREEOP ("AstLogNot{$lhsp.castEqWild}", "AstNeqWild{$lhsp->op1p(),$lhsp->op2p()}");
|
||||
TREEOPV("AstNot {$lhsp.castNeqWild, $lhsp.width1}","AstEqWild {$lhsp->op1p(),$lhsp->op2p()}");
|
||||
TREEOP ("AstLogNot{$lhsp.castNeqWild}", "AstEqWild {$lhsp->op1p(),$lhsp->op2p()}");
|
||||
TREEOPV("AstNot {$lhsp.castEq, $lhsp.width1}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}");
|
||||
TREEOP ("AstLogNot{$lhsp.castEq}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}");
|
||||
TREEOPV("AstNot {$lhsp.castNeq, $lhsp.width1}", "AstEq {$lhsp->op1p(),$lhsp->op2p()}");
|
||||
|
@ -1151,6 +1155,7 @@ private:
|
|||
TREEOP("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
|
||||
TREEOP("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
|
@ -1161,6 +1166,7 @@ private:
|
|||
TREEOP("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstLogOr {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
|
||||
///=== Verilog operators
|
||||
|
|
|
@ -814,6 +814,28 @@ last:
|
|||
return setSingleBits(outc);
|
||||
}
|
||||
|
||||
V3Number& V3Number::opWildEq (const V3Number& lhs, const V3Number& rhs) {
|
||||
char outc = 1;
|
||||
for (int bit=0; bit<max(lhs.width(),rhs.width()); bit++) {
|
||||
if (!rhs.bitIsXZ(bit)
|
||||
&& lhs.bitIs(bit) != rhs.bitIs(bit)) { outc=0; goto last; }
|
||||
if (lhs.bitIsXZ(bit)) outc='x';
|
||||
}
|
||||
last:
|
||||
return setSingleBits(outc);
|
||||
}
|
||||
|
||||
V3Number& V3Number::opWildNeq (const V3Number& lhs, const V3Number& rhs) {
|
||||
char outc = 0;
|
||||
for (int bit=0; bit<max(lhs.width(),rhs.width()); bit++) {
|
||||
if (!rhs.bitIsXZ(bit)
|
||||
&& lhs.bitIs(bit) != rhs.bitIs(bit)) { outc=1; goto last; }
|
||||
if (lhs.bitIsXZ(bit)) outc='x';
|
||||
}
|
||||
last:
|
||||
return setSingleBits(outc);
|
||||
}
|
||||
|
||||
V3Number& V3Number::opGt (const V3Number& lhs, const V3Number& rhs) {
|
||||
// i op j, 1 bit return, max(L(lhs),L(rhs)) calculation, careful need to X/Z extend.
|
||||
char outc = 0;
|
||||
|
|
|
@ -174,6 +174,8 @@ public:
|
|||
V3Number& opCond (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
|
||||
V3Number& opCaseEq (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opWildEq (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opWildNeq (const V3Number& lhs, const V3Number& rhs);
|
||||
// "standard" math
|
||||
V3Number& opNot (const V3Number& lhs);
|
||||
V3Number& opLogNot (const V3Number& lhs);
|
||||
|
|
|
@ -65,7 +65,10 @@ void test(string lhss, string op, string rhss, string exps) {
|
|||
else if (op=="<<") gotnum.opShiftL (lhnum,rhnum);
|
||||
else if (op=="==") gotnum.opEq (lhnum,rhnum);
|
||||
else if (op=="===") gotnum.opCaseEq (lhnum,rhnum);
|
||||
else if (op=="==?") gotnum.opWildEq (lhnum,rhnum);
|
||||
else if (op=="!=") gotnum.opNeq (lhnum,rhnum);
|
||||
else if (op=="!==") gotnum.opCaseNeq (lhnum,rhnum);
|
||||
else if (op=="!=?") gotnum.opWildNeq (lhnum,rhnum);
|
||||
else if (op=="<=") gotnum.opLte (lhnum,rhnum);
|
||||
else if (op==">=") gotnum.opGte (lhnum,rhnum);
|
||||
else if (op=="&&") gotnum.opLogAnd (lhnum,rhnum);
|
||||
|
|
|
@ -98,8 +98,10 @@ private:
|
|||
// ... (Though they should match. We don't check.)
|
||||
virtual void visit(AstEq* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||
virtual void visit(AstEqCase* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||
virtual void visit(AstEqWild* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||
virtual void visit(AstNeq* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||
virtual void visit(AstNeqCase* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
|
||||
virtual void visit(AstNeqWild* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
|
||||
|
||||
//=======
|
||||
// Signed: Output signed iff LHS signed; unary operator
|
||||
|
|
|
@ -106,6 +106,42 @@ private:
|
|||
newp->iterateChildren(*this);
|
||||
}
|
||||
}
|
||||
void visitEqNeqWild(AstNodeBiop* nodep) {
|
||||
UINFO(4," N/EQWILD->EQ "<<nodep<<endl);
|
||||
V3Const::constifyTree(nodep->lhsp());
|
||||
V3Const::constifyTree(nodep->rhsp());
|
||||
if (nodep->lhsp()->castConst() && nodep->rhsp()->castConst()) {
|
||||
// Both sides are constant, node can be constant
|
||||
V3Const::constifyTree(nodep); nodep=NULL;
|
||||
return;
|
||||
} else {
|
||||
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
|
||||
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
|
||||
AstNode* newp;
|
||||
if (!rhsp->castConst()) {
|
||||
nodep->v3error("Unsupported: RHS of ==? or !=? must be constant to be synthesizable"); // Says spec.
|
||||
// Replace with anything that won't cause more errors
|
||||
newp = new AstEq (nodep->fileline(), lhsp, rhsp);
|
||||
} else {
|
||||
// X or Z's become mask, ala case statements.
|
||||
V3Number nummask (rhsp->fileline(), rhsp->width());
|
||||
nummask.opBitsNonX(rhsp->castConst()->num());
|
||||
V3Number numval (rhsp->fileline(), rhsp->width());
|
||||
numval.opBitsOne (rhsp->castConst()->num());
|
||||
AstNode* and1p = new AstAnd(nodep->fileline(), lhsp,
|
||||
new AstConst(nodep->fileline(), nummask));
|
||||
AstNode* and2p = new AstConst(nodep->fileline(), numval);
|
||||
if (nodep->castEqWild())
|
||||
newp = new AstEq (nodep->fileline(), and1p, and2p);
|
||||
else newp = new AstNeq (nodep->fileline(), and1p, and2p);
|
||||
rhsp->deleteTree(); rhsp=NULL;
|
||||
}
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
// Iterate tree now that we may have gotten rid of the compare
|
||||
newp->iterateChildren(*this);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstEqCase* nodep, AstNUser*) {
|
||||
visitEqNeqCase(nodep);
|
||||
|
@ -113,6 +149,12 @@ private:
|
|||
virtual void visit(AstNeqCase* nodep, AstNUser*) {
|
||||
visitEqNeqCase(nodep);
|
||||
}
|
||||
virtual void visit(AstEqWild* nodep, AstNUser*) {
|
||||
visitEqNeqWild(nodep);
|
||||
}
|
||||
virtual void visit(AstNeqWild* nodep, AstNUser*) {
|
||||
visitEqNeqWild(nodep);
|
||||
}
|
||||
virtual void visit(AstIsUnknown* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
// Ahh, we're two state, so this is easy
|
||||
|
|
|
@ -117,6 +117,7 @@ private:
|
|||
void width_O1_L_Rlhs(AstNode* nodep, AstNUser* vup);
|
||||
virtual void visit(AstEq* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
|
||||
virtual void visit(AstEqCase* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
|
||||
virtual void visit(AstEqWild* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
|
||||
virtual void visit(AstGt* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
|
||||
virtual void visit(AstGtS* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
|
||||
virtual void visit(AstGte* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
|
||||
|
@ -127,6 +128,7 @@ private:
|
|||
virtual void visit(AstLteS* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
|
||||
virtual void visit(AstNeq* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
|
||||
virtual void visit(AstNeqCase* nodep, AstNUser* vup){ width_O1_L_Rlhs(nodep,vup); }
|
||||
virtual void visit(AstNeqWild* nodep, AstNUser* vup){ width_O1_L_Rlhs(nodep,vup); }
|
||||
|
||||
// Widths: out width = lhs width = rhs width
|
||||
void width_Omax_L_Rlhs(AstNode* nodep, AstNUser* vup);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//
|
||||
// This file is part of Verilator.
|
||||
//
|
||||
// Author: Wilson Snyder <wsnyder@wsnyder.org> or <wsnyder@world.std.com>
|
||||
// Author: Wilson Snyder <wsnyder@wsnyder.org>
|
||||
//
|
||||
// Code available from: http://www.veripool.com/verilator
|
||||
//
|
||||
|
|
|
@ -578,6 +578,12 @@ escid \\[^ \t\f\r\n]+
|
|||
"-:" {yylval.fileline = CRELINE(); return yP_MINUSCOLON;}
|
||||
}
|
||||
|
||||
/* SystemVerilog Operators */
|
||||
<S05>{
|
||||
"==?" {yylval.fileline = CRELINE(); return yP_WILDEQUAL;}
|
||||
"!=?" {yylval.fileline = CRELINE(); return yP_WILDNOTEQUAL;}
|
||||
}
|
||||
|
||||
/* PSL Operators */
|
||||
<PSL>{
|
||||
"{" {yylval.fileline = CRELINE(); return yPSL_BRA;} // Avoid parser hitting concatenate.
|
||||
|
@ -659,7 +665,7 @@ escid \\[^ \t\f\r\n]+
|
|||
<ATTRMODE>"*)" { yy_pop_state(); }
|
||||
<ATTRMODE>. { yymore(); }
|
||||
<ATTRMODE><<EOF>> { yyerror("EOF in (*");
|
||||
yyleng = 0; }
|
||||
yyleng = 0; yy_pop_state(); }
|
||||
|
||||
/************************************************************************/
|
||||
/* Attributes */
|
||||
|
|
|
@ -269,7 +269,7 @@ class AstSenTree;
|
|||
%left<fileline> '^'
|
||||
%left<fileline> yP_XNOR
|
||||
%left<fileline> '&' yP_NAND
|
||||
%left<fileline> yP_EQUAL yP_NOTEQUAL yP_CASEEQUAL yP_CASENOTEQUAL
|
||||
%left<fileline> yP_EQUAL yP_NOTEQUAL yP_CASEEQUAL yP_CASENOTEQUAL yP_WILDEQUAL yP_WILDNOTEQUAL
|
||||
%left<fileline> '>' '<' yP_GTE yP_LTE
|
||||
%left<fileline> yP_SLEFT yP_SRIGHT yP_SSRIGHT
|
||||
%left<fileline> '+' '-'
|
||||
|
@ -912,6 +912,8 @@ exprNoStr: expr yP_OROR expr { $$ = new AstLogOr ($2,$1,$3); }
|
|||
| expr yP_NOTEQUAL expr { $$ = new AstNeq ($2,$1,$3); }
|
||||
| expr yP_CASEEQUAL expr { $$ = new AstEqCase ($2,$1,$3); }
|
||||
| expr yP_CASENOTEQUAL expr { $$ = new AstNeqCase ($2,$1,$3); }
|
||||
| expr yP_WILDEQUAL expr { $$ = new AstEqWild ($2,$1,$3); }
|
||||
| expr yP_WILDNOTEQUAL expr { $$ = new AstNeqWild ($2,$1,$3); }
|
||||
| expr '>' expr { $$ = new AstGt ($2,$1,$3); }
|
||||
| expr '<' expr { $$ = new AstLt ($2,$1,$3); }
|
||||
| expr yP_GTE expr { $$ = new AstGte ($2,$1,$3); }
|
||||
|
@ -1104,6 +1106,7 @@ specifyJunk: dlyTerm {} /* ignored */
|
|||
| yP_ANDAND {} | yP_GTE {} | yP_LTE {}
|
||||
| yP_EQUAL {} | yP_NOTEQUAL {}
|
||||
| yP_CASEEQUAL {} | yP_CASENOTEQUAL {}
|
||||
| yP_WILDEQUAL {} | yP_WILDNOTEQUAL {}
|
||||
| yP_XNOR {} | yP_NOR {} | yP_NAND {}
|
||||
| yP_OROR {}
|
||||
| yP_SLEFT {} | yP_SRIGHT {} | yP_SSRIGHT {}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
# $Id$
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
|
@ -0,0 +1,81 @@
|
|||
// $Id$
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2007 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
integer cyc=0;
|
||||
reg [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
// Take CRC data and apply to testblock inputs
|
||||
wire [31:0] in = crc[31:0];
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire [3:0] out; // From test of Test.v
|
||||
// End of automatics
|
||||
|
||||
Test test (/*AUTOINST*/
|
||||
// Outputs
|
||||
.out (out[3:0]),
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.in (in[31:0]));
|
||||
|
||||
// Aggregate outputs into a single result vector
|
||||
wire [63:0] result = {60'h0, out};
|
||||
|
||||
// What checksum will we end up with
|
||||
`define EXPECTED_SUM 64'h1a0d07009b6a30d2
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
if (sum !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test (/*AUTOARG*/
|
||||
// Outputs
|
||||
out,
|
||||
// Inputs
|
||||
clk, in
|
||||
);
|
||||
|
||||
input clk;
|
||||
input [31:0] in;
|
||||
output [3:0] out;
|
||||
|
||||
assign out[0] = in[3:0] ==? 4'b1001;
|
||||
assign out[1] = in[3:0] !=? 4'b1001;
|
||||
assign out[2] = in[3:0] ==? 4'bx01x;
|
||||
assign out[3] = in[3:0] !=? 4'bx01x;
|
||||
endmodule
|
Loading…
Reference in New Issue