Fix concatenates and vectored bufif1, bug326.
This commit is contained in:
parent
2e67a91982
commit
cfdb852843
2
Changes
2
Changes
|
|
@ -7,6 +7,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
|||
|
||||
**** Support $bits(data_type), bug327. [Alex Solomatnikov]
|
||||
|
||||
**** Fix concatenates and vectored bufif1, bug326. [Iztok Jeras]
|
||||
|
||||
* Verilator 3.811 2011/02/14
|
||||
|
||||
**** Report errors on duplicated or empty pins, bug321. [Christian Leber]
|
||||
|
|
|
|||
|
|
@ -3152,6 +3152,19 @@ struct AstReplicate : public AstNodeBiop {
|
|||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*2; }
|
||||
};
|
||||
struct AstBufIf1 : public AstNodeBiop {
|
||||
// lhs is enable, rhs is data to drive
|
||||
AstBufIf1(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(BufIf1, BUFIF1)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opBufIf1(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "bufif(%r,%l)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return false;} // Lclean || Rclean
|
||||
virtual string emitSimpleOperator() { V3ERROR_NA; return false;} // Lclean || Rclean
|
||||
virtual bool cleanOut() {V3ERROR_NA; return false;} // Lclean || Rclean
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstFGetS : public AstNodeBiop {
|
||||
AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {}
|
||||
ASTNODE_NODE_FUNCS(FGetS, FGETS)
|
||||
|
|
|
|||
|
|
@ -1061,6 +1061,24 @@ private:
|
|||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
void replaceSelIntoBiop(AstSel* nodep) {
|
||||
// SEL(BUFIF1(a,b),1,bit) => BUFIF1(SEL(a,1,bit),SEL(b,1,bit))
|
||||
AstNodeBiop* fromp = nodep->fromp()->unlinkFrBack()->castNodeBiop();
|
||||
if (!fromp) nodep->v3fatalSrc("Called on non biop");
|
||||
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
|
||||
AstNode* widthp = nodep->widthp()->unlinkFrBack();
|
||||
//
|
||||
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
|
||||
AstNode* birhsp = fromp->rhsp()->unlinkFrBack();
|
||||
//
|
||||
fromp->lhsp(new AstSel(nodep->fileline(),
|
||||
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
|
||||
fromp->rhsp(new AstSel(nodep->fileline(),
|
||||
birhsp, lsbp, widthp));
|
||||
fromp->widthSignedFrom(nodep);
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
|
||||
|
|
@ -1767,6 +1785,10 @@ private:
|
|||
TREEOPC("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)");
|
||||
// V3Tristate requires selects below BufIf1.
|
||||
// We can probably extend this to additional logical operators, but only definite
|
||||
// win if bit select is a constant (otherwise we may need to compute bit index several times)
|
||||
TREEOPV("AstSel{$fromp.castBufIf1}", "replaceSelIntoBiop(nodep)");
|
||||
// Conversions
|
||||
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
|
||||
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
|
||||
|
|
|
|||
|
|
@ -1318,6 +1318,15 @@ V3Number& V3Number::opPowS (const V3Number& lhs, const V3Number& rhs) {
|
|||
return setAllBitsX();
|
||||
}
|
||||
|
||||
V3Number& V3Number::opBufIf1 (const V3Number& ens, const V3Number& if1s) {
|
||||
setZero();
|
||||
for(int bit=0; bit<this->width(); bit++) {
|
||||
if (ens.bitIs1(bit)) { setBit(bit, if1s.bitIs(bit)); }
|
||||
else setBit(bit,'z');
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
V3Number& V3Number::opAssign (const V3Number& lhs) {
|
||||
// Note may be a width change during the assign
|
||||
setZero();
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@ public:
|
|||
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opWildEq (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opWildNeq (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opBufIf1 (const V3Number& lhs, const V3Number& rhs);
|
||||
// "standard" math
|
||||
V3Number& opNot (const V3Number& lhs);
|
||||
V3Number& opLogNot (const V3Number& lhs);
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ private:
|
|||
virtual void visit(AstLogOr* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||
virtual void visit(AstLogIf* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||
virtual void visit(AstLogIff* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||
virtual void visit(AstBufIf1* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||
// ... These shouldn't matter, just make unsigned
|
||||
virtual void visit(AstScopeName* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||
virtual void visit(AstText* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||
|
|
|
|||
|
|
@ -159,8 +159,8 @@ private:
|
|||
// assign x = (OE) ? 'hz : y;
|
||||
|
||||
// see if this a COND and separate out the __en logic from the output logic if it is
|
||||
if (nodep->rhsp()->castCond()) {
|
||||
AstCond* condp = nodep->rhsp()->castCond();
|
||||
if (AstCond* condp = nodep->rhsp()->castCond()) {
|
||||
//if (debug()>=9) nodep->dumpTree(cout,"- cond-in: ");
|
||||
AstNode* oep = condp->condp();
|
||||
AstNode* expr1p = condp->expr1p();
|
||||
AstNode* expr2p = condp->expr2p();
|
||||
|
|
@ -192,17 +192,44 @@ private:
|
|||
|
||||
// replace the old assign logic with the new one
|
||||
AstAssignW* newassp = new AstAssignW(nodep->fileline(), outp,outrhsp);
|
||||
//if (debug()>=9) newassp->dumpTreeAndNext(cout,"- cond-out: ");
|
||||
nodep->replaceWith(newassp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
newassp->iterateChildren(*this);
|
||||
|
||||
} else {
|
||||
}
|
||||
// How about a tri gate?
|
||||
else if (AstBufIf1* bufp = nodep->rhsp()->castBufIf1()) {
|
||||
//if (debug()>=9) nodep->dumpTree(cout,"- tri-in : ");
|
||||
AstNode* enrhsp = bufp->lhsp()->unlinkFrBack();
|
||||
AstNode* outrhsp = bufp->rhsp()->unlinkFrBack();
|
||||
|
||||
AstNode* outp = nodep->lhsp()->unlinkFrBack();;
|
||||
AstVarRef* outrefp = NULL;
|
||||
if (outp->castVarRef()) {
|
||||
outrefp = outp->castVarRef();
|
||||
} else if (outp->castSel()) {
|
||||
outrefp = outp->castSel()->fromp()->castVarRef();
|
||||
} else {
|
||||
nodep->v3error("Can't find LHS varref");
|
||||
}
|
||||
|
||||
createEnableVar(outp, outrefp, enrhsp, outrhsp->width());
|
||||
|
||||
// replace the old assign logic with the new one
|
||||
AstAssignW* newassp = new AstAssignW(nodep->fileline(), outp,outrhsp);
|
||||
//if (debug()>=9) newassp->dumpTreeAndNext(cout,"- tri-out: ");
|
||||
nodep->replaceWith(newassp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
newassp->iterateChildren(*this);
|
||||
}
|
||||
else {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
}
|
||||
|
||||
AstVar* createEnableVar(AstNode* outp, AstVarRef* outrefp, AstNode* enrhsp, int width, string suffix="") {
|
||||
// this function creates an __en Var that cooresponds to
|
||||
// this function creates an __en Var that corresponds to
|
||||
// the outp and outrefp and creates an assignw to enrhsp
|
||||
AstVar* enp = new AstVar (outrefp->varp()->fileline(),
|
||||
AstVarType::MODULETEMP,
|
||||
|
|
@ -218,10 +245,14 @@ private:
|
|||
enrhsp->v3error("Don't know how to deal with selection logic wider than 1 bit");
|
||||
}
|
||||
}
|
||||
|
||||
AstNode* newassp = new AstAssignW (enp->fileline(),
|
||||
new AstVarRef (enp->fileline(), enp, true),
|
||||
enrhsp);
|
||||
if (debug()>=9) enp->dumpTreeAndNext(cout,"- cev-out: ");
|
||||
if (debug()>=9) newassp->dumpTreeAndNext(cout,"- cev-out: ");
|
||||
m_modp->addStmtp(enp);
|
||||
m_modp->addStmtp(new AstAssignW (enp->fileline(),
|
||||
new AstVarRef (enp->fileline(), enp, true),
|
||||
enrhsp));
|
||||
m_modp->addStmtp(newassp);
|
||||
|
||||
outrefp->user1p(enp); // put __en signal into varref for later usage
|
||||
outrefp->varp()->user1p(enp); // put __en signal into var as well in the event this is a single lhs driver and this needs passed up one level
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ private:
|
|||
virtual void visit(AstOr* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
|
||||
virtual void visit(AstXnor* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
|
||||
virtual void visit(AstXor* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
|
||||
virtual void visit(AstBufIf1* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
|
||||
// Multiple possible reasonable division width conversions. Just keep our code simple, they aren't common.
|
||||
virtual void visit(AstModDiv* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
|
||||
virtual void visit(AstModDivS* nodep, AstNUser* vup) { width_Omax_L_Rlhs(nodep,vup); }
|
||||
|
|
|
|||
|
|
@ -2682,46 +2682,58 @@ gateUnsupList<nodep>:
|
|||
;
|
||||
|
||||
gateBuf<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ',' expr ')' { $$ = new AstAssignW ($3,$4,$6); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' expr ')'
|
||||
{ $$ = new AstAssignW ($3,$4,$6); }
|
||||
;
|
||||
gateBufif0<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstConst($3,V3Number($3,"1'bz")), $6)); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,new AstNot($3,$8),$6)); }
|
||||
;
|
||||
gateBufif1<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, $6, new AstConst($3,V3Number($3,"1'bz")))); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,$8,$6)); }
|
||||
;
|
||||
gateNot<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' expr ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
|
||||
;
|
||||
gateNotif0<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstConst($3,V3Number($3,"1'bz")), new AstNot($3, $6))); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,new AstNot($3,$8), new AstNot($3, $6))); }
|
||||
;
|
||||
gateNotif1<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstNot($3,$6), new AstConst($3,V3Number($3,"1'bz")))); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,$8, new AstNot($3,$6))); }
|
||||
;
|
||||
gateAnd<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ',' gateAndPinList ')' { $$ = new AstAssignW ($3,$4,$6); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateAndPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,$6); }
|
||||
;
|
||||
gateNand<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ',' gateAndPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateAndPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
|
||||
;
|
||||
gateOr<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ',' gateOrPinList ')' { $$ = new AstAssignW ($3,$4,$6); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateOrPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,$6); }
|
||||
;
|
||||
gateNor<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ',' gateOrPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateOrPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
|
||||
;
|
||||
gateXor<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ',' gateXorPinList ')' { $$ = new AstAssignW ($3,$4,$6); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateXorPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,$6); }
|
||||
;
|
||||
gateXnor<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ',' gateXorPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateXorPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
|
||||
;
|
||||
gatePullup<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ')' { $$ = new AstPull ($3, $4, true); }
|
||||
gateIdE instRangeE '(' variable_lvalue ')' { $$ = new AstPull ($3, $4, true); }
|
||||
;
|
||||
gatePulldown<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ')' { $$ = new AstPull ($3, $4, false); }
|
||||
gateIdE instRangeE '(' variable_lvalue ')' { $$ = new AstPull ($3, $4, false); }
|
||||
;
|
||||
gateUnsup<nodep>:
|
||||
gateIdE instRangeE '(' gateUnsupPinList ')' { $$ = new AstImplicit ($3,$4); }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# 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
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2011 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
integer cyc=0;
|
||||
reg [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
parameter DW = 4;
|
||||
wire [3:0] drv_a = crc[3:0];
|
||||
wire [3:0] drv_b = crc[7:4];
|
||||
wire [3:0] drv_e = crc[19:16];
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire [DW-1:0] drv; // To/From test1 of Test1.v
|
||||
wire [DW-1:0] drv2; // From test2 of Test2.v
|
||||
// End of automatics
|
||||
|
||||
Test1 test1 (/*AUTOINST*/
|
||||
// Inouts
|
||||
.drv (drv[DW-1:0]),
|
||||
// Inputs
|
||||
.drv_a (drv_a[DW-1:0]),
|
||||
.drv_b (drv_b[DW-1:0]),
|
||||
.drv_e (drv_e[DW-1:0]));
|
||||
Test2 test2 (/*AUTOINST*/
|
||||
// Outputs
|
||||
.drv2 (drv2[DW-1:0]),
|
||||
// Inputs
|
||||
.drv_a (drv_a[DW-1:0]),
|
||||
.drv_b (drv_b[DW-1:0]),
|
||||
.drv_e (drv_e[DW-1:0]));
|
||||
|
||||
// Aggregate outputs into a single result vector
|
||||
wire [63:0] result = {60'h0, drv};
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x drv=%x %x (%b??%b:%b)\n",$time, cyc, crc, drv, drv2, drv_e,drv_a,drv_b);
|
||||
`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;
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
if (drv2 != drv) $stop;
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
// What checksum will we end up with (above print should match)
|
||||
`define EXPECTED_SUM 64'hd95d216c5a2945d0
|
||||
if (sum !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test1 #(
|
||||
parameter DW = 4
|
||||
)(
|
||||
input wire [DW-1:0] drv_a,
|
||||
input wire [DW-1:0] drv_b,
|
||||
input wire [DW-1:0] drv_e,
|
||||
inout wire [DW-1:0] drv
|
||||
);
|
||||
|
||||
wire drv_0, drv_1, drv_2, drv_3;
|
||||
bufif1 bufa0 (drv_0, drv_a[0], drv_e[0]);
|
||||
bufif1 bufb0 (drv_0, drv_b[0], ~drv_e[0]);
|
||||
bufif1 bufa1 (drv_1, drv_a[1], drv_e[1]);
|
||||
bufif1 bufb1 (drv_1, drv_b[1], ~drv_e[1]);
|
||||
bufif1 bufa2 (drv_2, drv_a[2], drv_e[2]);
|
||||
bufif1 bufb2 (drv_2, drv_b[2], ~drv_e[2]);
|
||||
bufif1 bufa3 (drv_3, drv_a[3], drv_e[3]);
|
||||
bufif1 bufb3 (drv_3, drv_b[3], ~drv_e[3]);
|
||||
assign drv = {drv_3,drv_2,drv_1,drv_0};
|
||||
|
||||
endmodule
|
||||
|
||||
module Test2 #(
|
||||
parameter DW = 4
|
||||
)(
|
||||
input wire [DW-1:0] drv_a,
|
||||
input wire [DW-1:0] drv_b,
|
||||
input wire [DW-1:0] drv_e,
|
||||
inout wire [DW-1:0] drv2
|
||||
);
|
||||
|
||||
wire [DW-1:0] drv_all;
|
||||
bufif1 bufa [DW-1:0] (drv_all, drv_a, drv_e);
|
||||
// Below ~= bufif1 bufb [DW-1:0] (drv_all, drv_b, ~drv_e);
|
||||
bufif1 bufb [DW-1:0] ({drv_all[3], drv_all[2], drv_all[1], drv_all[0]},
|
||||
{drv_b[3], drv_b[2], drv_b[1], drv_b[0]},
|
||||
{~drv_e[3], ~drv_e[2], ~drv_e[1], ~drv_e[0]});
|
||||
assign drv2 = drv_all;
|
||||
|
||||
endmodule
|
||||
Loading…
Reference in New Issue