IMPORTANT: Rewrite tristate handling, tri0, tri1, etc.
This commit is contained in:
parent
0048b04540
commit
9734931f67
7
Changes
7
Changes
|
|
@ -5,8 +5,15 @@ indicates the contributor was also the author of the fix; Thanks!
|
|||
|
||||
* Verilator 3.840 devel
|
||||
|
||||
** Rewrote tristate handling; supports tri0, tri1, tristate bit selects,
|
||||
concatenates and pullup/pulldowns, bug395, bug56, bug54, bug51.
|
||||
[Alex Solomatnikov, Lane Brooks, et al]
|
||||
|
||||
*** Support tri0 and tri1, bug462. [Alex Solomatnikov]
|
||||
|
||||
*** Fix generate operators not short circuiting, bug413. [by Jeremy Bennett]
|
||||
|
||||
|
||||
* Verilator 3.833 2012/04/15
|
||||
|
||||
*** Support += and -= in standard for loops, bug463. [Alex Solomatnikov]
|
||||
|
|
|
|||
|
|
@ -2212,11 +2212,11 @@ optimizations will be disabled around the latch.
|
|||
|
||||
All delays (#) are ignored, as they are in synthesis.
|
||||
|
||||
=head2 Two State
|
||||
=head2 Unknown states
|
||||
|
||||
Verilator is a two state simulator, not a four state simulator. However, it
|
||||
has two features which uncover most initialization bugs (including many that
|
||||
a four state simulator will miss.)
|
||||
Verilator is mostly a two state simulator, not a four state simulator.
|
||||
However, it has two features which uncover most initialization bugs
|
||||
(including many that a four state simulator will miss.)
|
||||
|
||||
Identity comparisons (=== or !==) are converted to standard ==/!== when
|
||||
neither side is a constant. This may make the expression result differ
|
||||
|
|
@ -2238,19 +2238,21 @@ practice, just setting all variables to one at startup finds most problems.
|
|||
|
||||
=head2 Tri/Inout
|
||||
|
||||
Verilator converts some simple tristate structures into two state. An assignment
|
||||
of the form:
|
||||
Verilator converts some simple tristate structures into two state. Pullup,
|
||||
pulldown, bufif0, bufif1, notif0, notif1, tri0 and tri1 are also supported.
|
||||
Simple comparisons with === 1'bz are also supported.
|
||||
|
||||
An assignment of the form:
|
||||
|
||||
inout driver;
|
||||
wire driver = (enable) ? output_value : 1'bz;
|
||||
|
||||
Will be converted to
|
||||
|
||||
input driver__in; // Value being driven in from "external" drivers
|
||||
output driver__en; // True if driven from this module
|
||||
output driver__enout; // Value being driven from this module
|
||||
input driver; // Value being driven in from "external" drivers
|
||||
output driver__en; // True if driven from this module
|
||||
output driver__out; // Value being driven from this module
|
||||
|
||||
Pullup, pulldown, bufif0, bufif1, notif0, notif1 are also supported.
|
||||
External logic will be needed to combine these signals with any external
|
||||
drivers.
|
||||
|
||||
|
|
|
|||
1287
src/V3Tristate.cpp
1287
src/V3Tristate.cpp
File diff suppressed because it is too large
Load Diff
|
|
@ -32,7 +32,6 @@
|
|||
class V3Tristate {
|
||||
public:
|
||||
static void tristateAll(AstNetlist* nodep);
|
||||
static void inoutAll(AstNetlist* nodep);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -233,12 +233,6 @@ void process () {
|
|||
V3Const::constifyAllLint(v3Global.rootp());
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("const.tree"));
|
||||
|
||||
if (!v3Global.opt.xmlOnly()) {
|
||||
// Expand Inouts
|
||||
V3Tristate::inoutAll(v3Global.rootp());
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("inouts.tree"));
|
||||
}
|
||||
|
||||
if (!v3Global.opt.xmlOnly()) {
|
||||
// Remove cell arrays (must be between V3Width and scoping)
|
||||
V3Inst::dearrayAll(v3Global.rootp());
|
||||
|
|
|
|||
|
|
@ -296,6 +296,8 @@ word [a-zA-Z0-9_]+
|
|||
"tranif0" { FL; return yTRANIF0; }
|
||||
"tranif1" { FL; return yTRANIF1; }
|
||||
"tri" { FL; return yTRI; }
|
||||
"tri0" { FL; return yTRI0; }
|
||||
"tri1" { FL; return yTRI1; }
|
||||
"vectored" { FL; return yVECTORED; }
|
||||
"while" { FL; return yWHILE; }
|
||||
"wire" { FL; return yWIRE; }
|
||||
|
|
@ -333,8 +335,6 @@ word [a-zA-Z0-9_]+
|
|||
"triand" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
"trior" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
"trireg" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
"tri0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
"tri1" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
"wait" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
"wand" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
"weak0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
|
|
|
|||
|
|
@ -376,6 +376,8 @@ class AstSenTree;
|
|||
%token<fl> yTRANIF0 "tranif0"
|
||||
%token<fl> yTRANIF1 "tranif1"
|
||||
%token<fl> yTRI "tri"
|
||||
%token<fl> yTRI0 "tri0"
|
||||
%token<fl> yTRI1 "tri1"
|
||||
%token<fl> yTRUE "true"
|
||||
%token<fl> yTYPEDEF "typedef"
|
||||
%token<fl> yUNIQUE "unique"
|
||||
|
|
@ -1007,8 +1009,8 @@ net_type: // ==IEEE: net_type
|
|||
ySUPPLY0 { VARDECL(SUPPLY0); }
|
||||
| ySUPPLY1 { VARDECL(SUPPLY1); }
|
||||
| yTRI { VARDECL(TRIWIRE); }
|
||||
//UNSUP yTRI0 { VARDECL(TRI0); }
|
||||
//UNSUP yTRI1 { VARDECL(TRI1); }
|
||||
| yTRI0 { VARDECL(TRI0); }
|
||||
| yTRI1 { VARDECL(TRI1); }
|
||||
//UNSUP yTRIAND { VARDECL(TRIAND); }
|
||||
//UNSUP yTRIOR { VARDECL(TRIOR); }
|
||||
//UNSUP yTRIREG { VARDECL(TRIREG); }
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ module set (
|
|||
input clk,
|
||||
output enable
|
||||
);
|
||||
|
||||
assign enable = 1'b0;
|
||||
endmodule
|
||||
|
||||
module read (
|
||||
|
|
|
|||
|
|
@ -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,128 @@
|
|||
// 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;
|
||||
|
||||
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 [8:0] match1; // From test1 of Test1.v
|
||||
wire [8:0] match2; // From test2 of Test2.v
|
||||
// End of automatics
|
||||
|
||||
Test1 test1 (/*AUTOINST*/
|
||||
// Outputs
|
||||
.match1 (match1[8:0]),
|
||||
// Inputs
|
||||
.drv_a (drv_a[3:0]),
|
||||
.drv_e (drv_e[3:0]));
|
||||
Test2 test2 (/*AUTOINST*/
|
||||
// Outputs
|
||||
.match2 (match2[8:0]),
|
||||
// Inputs
|
||||
.drv_a (drv_a[3:0]),
|
||||
.drv_e (drv_e[3:0]));
|
||||
|
||||
// Aggregate outputs into a single result vector
|
||||
wire [63:0] result = {39'h0, match2, 7'h0, match1};
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x m1=%x m2=%x (%b??%b:%b)\n",$time, cyc, crc, match1, match2, 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
|
||||
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'hc0c4a2b9aea7c4b4
|
||||
if (sum !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test1
|
||||
(
|
||||
input wire [3:0] drv_a,
|
||||
input wire [3:0] drv_e,
|
||||
output wire [8:0] match1
|
||||
);
|
||||
|
||||
wire [2:1] drv_all;
|
||||
bufif1 bufa [2:1] (drv_all, drv_a[2:1], drv_e[2:1]);
|
||||
|
||||
`ifdef VERILATOR
|
||||
// At present Verilator only allows comparisons with Zs
|
||||
assign match1[0] = (drv_a[2:1]== 2'b00 && drv_e[2:1]==2'b11);
|
||||
assign match1[1] = (drv_a[2:1]== 2'b01 && drv_e[2:1]==2'b11);
|
||||
assign match1[2] = (drv_a[2:1]== 2'b10 && drv_e[2:1]==2'b11);
|
||||
assign match1[3] = (drv_a[2:1]== 2'b11 && drv_e[2:1]==2'b11);
|
||||
`else
|
||||
assign match1[0] = drv_all === 2'b00;
|
||||
assign match1[1] = drv_all === 2'b01;
|
||||
assign match1[2] = drv_all === 2'b10;
|
||||
assign match1[3] = drv_all === 2'b11;
|
||||
`endif
|
||||
assign match1[4] = drv_all === 2'bz0;
|
||||
assign match1[5] = drv_all === 2'bz1;
|
||||
assign match1[6] = drv_all === 2'bzz;
|
||||
assign match1[7] = drv_all === 2'b0z;
|
||||
assign match1[8] = drv_all === 2'b1z;
|
||||
endmodule
|
||||
|
||||
module Test2
|
||||
(
|
||||
input wire [3:0] drv_a,
|
||||
input wire [3:0] drv_e,
|
||||
output wire [8:0] match2
|
||||
);
|
||||
|
||||
wire [2:1] drv_all;
|
||||
bufif1 bufa [2:1] (drv_all, drv_a[2:1], drv_e[2:1]);
|
||||
|
||||
`ifdef VERILATOR
|
||||
assign match2[0] = (drv_all !== 2'b00 || drv_e[2:1]!=2'b11);
|
||||
assign match2[1] = (drv_all !== 2'b01 || drv_e[2:1]!=2'b11);
|
||||
assign match2[2] = (drv_all !== 2'b10 || drv_e[2:1]!=2'b11);
|
||||
assign match2[3] = (drv_all !== 2'b11 || drv_e[2:1]!=2'b11);
|
||||
`else
|
||||
assign match2[0] = drv_all !== 2'b00;
|
||||
assign match2[1] = drv_all !== 2'b01;
|
||||
assign match2[2] = drv_all !== 2'b10;
|
||||
assign match2[3] = drv_all !== 2'b11;
|
||||
`endif
|
||||
assign match2[4] = drv_all !== 2'bz0;
|
||||
assign match2[5] = drv_all !== 2'bz1;
|
||||
assign match2[6] = drv_all !== 2'bzz;
|
||||
assign match2[7] = drv_all !== 2'b0z;
|
||||
assign match2[8] = drv_all !== 2'b1z;
|
||||
endmodule
|
||||
|
|
@ -1,19 +1,20 @@
|
|||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2008 by Lane Brooks
|
||||
|
||||
module top (input SEL, input[1:0] A, output Z, output Y, output X, output W);
|
||||
module top (input SEL, input[1:0] A, output W, output X, output Y, output Z);
|
||||
mux mux2 (.A(A), .SEL(SEL), .Z(W));
|
||||
|
||||
pass mux1 (.A(A), .SEL(SEL), .Z(X));
|
||||
|
||||
tbuf mux0[1:0] (.A(A), .OE({SEL,!SEL}), .Z(Y));
|
||||
|
||||
assign Z = ( SEL) ? A[1] : 1'bz;
|
||||
tbuf tbuf(.A(A[0]), .OE(!SEL), .Z(Z));
|
||||
|
||||
tbuf mux0[1:0](.A(A), .OE({SEL,!SEL}), .Z(Y));
|
||||
|
||||
pass mux1(.A(A), .SEL(SEL), .Z(X));
|
||||
mux mux2(.A(A), .SEL(SEL), .Z(W));
|
||||
tbuf tbuf (.A(A[0]), .OE(!SEL), .Z(Z));
|
||||
endmodule
|
||||
|
||||
module pass (input[1:0] A, input SEL, output Z);
|
||||
tbuf tbuf1(.A(A[1]), .OE(SEL), .Z(Z));
|
||||
tbuf tbuf0(.A(A[0]), .OE(!SEL),.Z(Z));
|
||||
tbuf tbuf1 (.A(A[1]), .OE(SEL), .Z(Z));
|
||||
tbuf tbuf0 (.A(A[0]), .OE(!SEL),.Z(Z));
|
||||
endmodule
|
||||
|
||||
module tbuf (input A, input OE, output Z);
|
||||
|
|
@ -35,4 +36,5 @@ endmodule
|
|||
module mux (input[1:0] A, input SEL, output Z);
|
||||
assign Z = (SEL) ? A[1] : 1'bz;
|
||||
assign Z = (!SEL)? A[0] : 1'bz;
|
||||
assign Z = 1'bz;
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -4,13 +4,16 @@
|
|||
module top (input A, input B, input SEL, output Y1, output Y2, output Z);
|
||||
io io1(.A(A), .OE( SEL), .Z(Z), .Y(Y1));
|
||||
pass io2(.A(B), .OE(!SEL), .Z(Z), .Y(Y2));
|
||||
assign Z = 1'bz;
|
||||
endmodule
|
||||
|
||||
module pass (input A, input OE, inout Z, output Y);
|
||||
io io(.A(A), .OE(OE), .Z(Z), .Y(Y));
|
||||
assign Z = 1'bz;
|
||||
endmodule
|
||||
|
||||
module io (input A, input OE, inout Z, output Y);
|
||||
assign Z = (OE) ? A : 1'bz;
|
||||
assign Y = Z;
|
||||
assign Z = 1'bz;
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
#!/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
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2008 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
reg [2:0] in;
|
||||
|
||||
|
||||
wire a,y,y_fixed;
|
||||
wire b = in[0];
|
||||
wire en = in[1];
|
||||
|
||||
|
||||
pullup(a);
|
||||
|
||||
ChildA childa ( .A(a), .B(b), .en(en), .Y(y),.Yfix(y_fixed) );
|
||||
|
||||
initial in=0;
|
||||
initial en=0;
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
|
||||
|
||||
in <= in + 1;
|
||||
|
||||
$display ( "a %d b %d en %d y %d yfix: %d)" , a, b, en, y, y_fixed);
|
||||
if (en) begin
|
||||
// driving b
|
||||
// a should be b
|
||||
// y and yfix should also be b
|
||||
if (a!=b || y != b || y_fixed != b) begin
|
||||
$display ( "Expected a %d y %b yfix %b" , a, y, y_fixed);
|
||||
$stop;
|
||||
end
|
||||
|
||||
end else begin
|
||||
// not driving b
|
||||
// a should be 1 (pullup)
|
||||
// y and yfix shold be 1
|
||||
if (a!=1 || y != 1 || y_fixed != 1) begin
|
||||
$display( "Expected a,y,yfix == 1");
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
||||
if (in==3) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
module ChildA(inout A, input B, input en, output Y, output Yfix);
|
||||
|
||||
// workaround
|
||||
wire a_in = A;
|
||||
|
||||
ChildB childB(.A(A), .Y(Y));
|
||||
assign A = en ? B : 1'bz;
|
||||
|
||||
|
||||
ChildB childBfix(.A(a_in),.Y(Yfix));
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
module ChildB(input A, output Y);
|
||||
assign Y = A;
|
||||
endmodule
|
||||
|
||||
|
|
@ -7,8 +7,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
|||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug462");
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,15 +7,13 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
|||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, tri");
|
||||
|
||||
compile (
|
||||
fails=>$Self->{v3},
|
||||
expect=>
|
||||
'%Error: t/t_tri_bad_pull2.v:19: Unsupported: Conflicting pull directions.
|
||||
%Error: t/t_tri_bad_pull2.v:9: ... Location of conflicing pull.
|
||||
'%Error: t/t_tri_pull2_bad.v:\d+: Unsupported: Conflicting pull directions.
|
||||
%Error: t/t_tri_pull2_bad.v:\d+: ... Location of conflicing pull.
|
||||
%Error: Exiting due to',
|
||||
) if
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -7,15 +7,13 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
|||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, tri");
|
||||
|
||||
compile (
|
||||
fails=>$Self->{v3},
|
||||
expect=>
|
||||
'%Error: t/t_tri_bad_pull.v:9: Unsupported: Conflicting pull directions.
|
||||
%Error: t/t_tri_bad_pull.v:10: ... Location of conflicing pull.
|
||||
'%Error: t/t_tri_pull_bad.v:\d+: Unsupported: Conflicting pull directions.
|
||||
%Error: t/t_tri_pull_bad.v:\d+: ... Location of conflicing pull.
|
||||
%Error: Exiting due to',
|
||||
) if
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ module top (
|
|||
|
||||
// have 2 different 'chips' drive the PAD to act like a bi-directional bus
|
||||
wire [`WIDTH-1:0] PAD;
|
||||
io_ring io_ring1(.OE(OE1), .A(A1), .Y(Y1), .PAD(PAD));
|
||||
io_ring io_ring2(.OE(OE2), .A(A2), .Y(Y2), .PAD(PAD));
|
||||
io_ring io_ring1 (.OE(OE1), .A(A1), .Y(Y1), .PAD(PAD));
|
||||
io_ring io_ring2 (.OE(OE2), .A(A2), .Y(Y2), .PAD(PAD));
|
||||
|
||||
pullup p1(PAD);
|
||||
// pulldown p1(PAD);
|
||||
|
|
@ -29,7 +29,7 @@ module top (
|
|||
endmodule
|
||||
|
||||
module io_ring (input OE, input [`WIDTH-1:0] A, output [`WIDTH-1:0] Y, inout [`WIDTH-1:0] PAD);
|
||||
io io[`WIDTH-1:0](.OE(OE), .I(A), .O(Y), .PAD(PAD));
|
||||
io io[`WIDTH-1:0] (.OE(OE), .I(A), .O(Y), .PAD(PAD));
|
||||
endmodule
|
||||
|
||||
module io (input OE, input I, output O, inout PAD);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
|
||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, tri");
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ module t (clk);
|
|||
wire A = state[0];
|
||||
wire OE = state[1];
|
||||
wire Z1, Z2, Z3, Z4, Z5, Z6, Z7, Z8, Z9;
|
||||
|
||||
wire [3:0] Z10;
|
||||
wire Z11;
|
||||
|
||||
Test1 test1(/*AUTOINST*/
|
||||
// Inouts
|
||||
.Z1 (Z1),
|
||||
|
|
@ -45,58 +47,86 @@ module t (clk);
|
|||
.Z9 (Z9),
|
||||
// Inputs
|
||||
.OE (OE));
|
||||
|
||||
|
||||
|
||||
Test6 test6(/*AUTOINST*/
|
||||
// Inouts
|
||||
.Z10 (Z10[3:0]),
|
||||
// Inputs
|
||||
.OE (OE));
|
||||
|
||||
Test7 test7(/*AUTOINST*/
|
||||
// Outputs
|
||||
.Z11 (Z11),
|
||||
// Inputs
|
||||
.state (state[2:0]));
|
||||
|
||||
always @(posedge clk) begin
|
||||
state <= state + 1;
|
||||
`ifdef TEST_VERBOSE
|
||||
$display(" Z1=%b 2=%b 3=%b 4=%b 5=%b 6=%b 7=%b 8=%b 9=%b",Z1,Z2,Z3,Z4,Z5,Z6,Z7,Z8,Z9);
|
||||
$write("[%0t] state=%d Z1=%b 2=%b 3=%b 4=%b 5=%b 6=%b 7=%b 8=%b 9=%b 10=%b 11=%b\n",
|
||||
$time, state, Z1,Z2,Z3,Z4,Z5,Z6,Z7,Z8,Z9,Z10,Z11);
|
||||
`endif
|
||||
|
||||
if(state == 0) begin
|
||||
if(Z1 !== 1'b1) $stop; // tests pullups
|
||||
if(Z2 !== 1'b1) $stop;
|
||||
if(Z3 !== 1'b1) $stop;
|
||||
`ifndef VERILATOR
|
||||
if(Z4 !== 1'b1) $stop;
|
||||
`endif
|
||||
if(Z5 !== 1'b1) $stop;
|
||||
if(Z6 !== 1'b1) $stop;
|
||||
if(Z7 !== 1'b0) $stop;
|
||||
if(Z8 !== 1'b0) $stop;
|
||||
if(Z9 !== 1'b1) $stop;
|
||||
end
|
||||
if(Z10 !== 4'b0001) $stop;
|
||||
if(Z11 !== 1'b0) $stop;
|
||||
end
|
||||
else if(state == 1) begin
|
||||
if(Z1 !== 1'b1) $stop; // tests pullup
|
||||
if(Z2 !== 1'b1) $stop;
|
||||
if(Z3 !== 1'b1) $stop;
|
||||
`ifndef VERILATOR
|
||||
if(Z4 !== 1'b1) $stop;
|
||||
`endif
|
||||
if(Z5 !== 1'b1) $stop;
|
||||
if(Z6 !== 1'b1) $stop;
|
||||
if(Z7 !== 1'b0) $stop;
|
||||
if(Z8 !== 1'b0) $stop;
|
||||
if(Z9 !== 1'b1) $stop;
|
||||
if(Z10 !== 4'b0001) $stop;
|
||||
if(Z11 !== 1'b1) $stop;
|
||||
end
|
||||
else if(state == 2) begin
|
||||
if(Z1 !== 1'b0) $stop; // tests output driver low
|
||||
if(Z2 !== 1'b0) $stop;
|
||||
//if(Z3 !== 1'b1) $stop; // "X"
|
||||
if(Z3 !== 1'b1 && Z3 !== 1'bx) $stop; // Conflicts
|
||||
`ifndef VERILATOR
|
||||
if(Z4 !== 1'b1) $stop;
|
||||
`endif
|
||||
if(Z5 !== 1'b1) $stop;
|
||||
if(Z6 !== 1'b0) $stop;
|
||||
if(Z7 !== 1'b1) $stop;
|
||||
if(Z8 !== 1'b1) $stop;
|
||||
if(Z9 !== 1'b0) $stop;
|
||||
if(Z10 !== 4'b0010) $stop;
|
||||
//if(Z11 !== 1'bx) $stop; // Doesn't matter
|
||||
end
|
||||
else if(state == 3) begin
|
||||
if(Z1 !== 1'b1) $stop; // tests output driver high
|
||||
if(Z2 !== 1'b1) $stop;
|
||||
if(Z3 !== 1'b1) $stop;
|
||||
`ifndef VERILATOR
|
||||
if(Z4 !== 1'b1) $stop;
|
||||
`endif
|
||||
if(Z5 !== 1'b1) $stop;
|
||||
if(Z6 !== 1'b0) $stop;
|
||||
if(Z7 !== 1'b1) $stop;
|
||||
if(Z8 !== 1'b1) $stop;
|
||||
if(Z9 !== 1'b0) $stop;
|
||||
end
|
||||
if(Z10 !== 4'b0010) $stop;
|
||||
if(Z11 !== 1'b1) $stop;
|
||||
end
|
||||
else if(state == 4) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
|
|
@ -111,6 +141,7 @@ module t (clk);
|
|||
pulldown(Z7);
|
||||
pullup(Z8);
|
||||
pulldown(Z9);
|
||||
pulldown pd10[3:0] (Z10);
|
||||
endmodule
|
||||
|
||||
|
||||
|
|
@ -143,6 +174,26 @@ module Test5(input OE, inout Z6, inout Z7, inout Z8, inout Z9);
|
|||
assign Z9 = (OE) ? 1'bz : 1'b1;
|
||||
endmodule
|
||||
|
||||
// AND gate tristates
|
||||
module Test6(input OE, inout [3:0] Z10);
|
||||
wire [1:0] i;
|
||||
Test6a a (.OE(OE), .Z({Z10[0],Z10[1]}));
|
||||
Test6a b (.OE(~OE), .Z({Z10[2],Z10[0]}));
|
||||
endmodule
|
||||
|
||||
module Test6a(input OE, inout [1:0] Z);
|
||||
assign Z = (OE) ? 2'b01 : 2'bzz;
|
||||
endmodule
|
||||
|
||||
module Test7(input [2:0] state, output reg Z11);
|
||||
always @(*) begin
|
||||
casez (state)
|
||||
3'b000: Z11 = 1'b0;
|
||||
3'b0?1: Z11 = 1'b1;
|
||||
default: Z11 = 1'bx;
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
|
||||
// This is not implemented yet
|
||||
//module Test3(input OE, input A, inout Z3);
|
||||
|
|
|
|||
Loading…
Reference in New Issue