Subject: Re: [sv-bc] Proposal to change interface ref-port default mode -or- documentation
From: Clifford E. Cummings (cliffc@sunburst-design.com)
Date: Fri Aug 29 2003 - 14:13:28 PDT
Dave -
I took a few days to cool off before responding to the snide remarks below.
Responses shown.
At 10:05 PM 8/20/03 -0700, Dave Rich wrote:
>Cliff,
>
>For the proposal on 9.6, why not add the fact that three continuous
>assignments are not allowed; when there are two instances a module with
>ref ports connected together. You might also want add that four continuous
>assignments are not allowed when there are two ref ports and one
>hierarchical reference.
>
>I did not add an emoticon to the above so it would add more punch,
>otherwise I would have typed it in. (Call me if you still don't get it).
I get it.
>The point is that maybe we didn't do a good enough job explaining the ref
>port semantics.
There is no "maybe" about it. The ref port semantics are very poorly
described. I made an attempt to at least semi-remedy the situation.
>Its not supposed to change any of the rules that apply to variables. Only
>one continuous assignment means only one continuous assignment, whether it
>be directly to the variable, via a plain hierarchical reference, through
>ref port of a module, or through a ref argument of a task/function. (A ref
>argument of a task/function could only place a procedural assignment on
>the variable, which could still create an illegal combination of assignments).
The point is, ref-ports are a whole new critter. SystemVerilog now permits
one continuous assignment to a variable. If the variable assignment is
through a ref-port, it seemed to me that the continuous assignment through
a ref-port was a short-hand method for making a procedural assignment to a
variable at a higher level of hierarchy, much like a VHDL concurrent signal
assignment is a shorthand for a process assignment, and both are permitted
to std_logic type variables.
As I showed below, ref-ports now make it possible to compile sub-blocks
with the top-level module successfully, and fail when the sub-blocks are
compiled together, something that has never been possible before.
Since ref-port behavior is so new and unique, I thought it was not too much
to ask to clarify the 2-3 terse descriptions related to ref-ports.
>The example you show is EXACTLY the behavior users have been asking for years.
In all the years I have taught Verilog and Verilog synthesis, nobody has
ever asked for this behavior. Do you have reference papers or customers
that would be willing to email me and explain why they have wanted this
behavior because I have never seen this request before.
>The two modules, sub1 and sub2 work fine in a testbench independently, but
>as soon as you try to connect the two of them together, you get a compiler
>error.
Why would an engineer want this late-error-detection behavior?
I know you have alluded to cache modeling being easier to do using
ref-ports but without a concrete example to rebuff and re-code using better
coding styles, it is hard to debate the merits of this feature that
engineers have "been asking for years."
For the SV 3.0 effort, I was able to take all of the working FSM examples
that used the now defunct "transition" keyword and show why the coding
styles were poor and to show superior replacement coding styles. This work
helped us to kill a rather useless transition coding style that would have
added clutter and confusion to SV. I would like to prove to myself that
ref-ports really are or are not a good idea, but I keep getting abstract
nebulous descriptions of how ref-ports are great for architectural
modeling. It is hard to debate a "trust-me" model.
If you have customers that use and love ref-ports, you may want them to
email me and convince me that I should not try to kill this strange
enhancement. Tell your customers that Cliff thinks ref-ports suck and he is
trying to kill them.
Ref-ports have two very distasteful side effects (in addition to the
late-error-detection side effect mentioned in my previous email):
(1) ref-ports introduce a new form of race condition when two sub-modules
try to make ref-port assignments in the same time-step (as if we didn't
have enough race conditions in Verilog without this "enhancement"). See the
first example below.
(2) ref-ports are used to change the values of a variable in a parent
module, a rather dangerous practice even in Verilog, except it is now
easier to do (no hierarchical references required) and the ability is now
the default mode when interfaces are used. Verilog lets you do this today
but it requires explicit hierarchical references and therefore is harder to
screw up. See the second example below.
Per Karen's request, I will re-submit my proposal in "WAS-PROPOSED" format.
If you can think of a better way of clarifying the functionality of a
ref-port using different changes, I will not be offended.
>Dave
Regards - Cliff
========= First Example with ref-ports and race conditions ==========
interface ff_if (bit clk, rst_n);
logic q; // a is a ref-port (no modport)
logic d1, d2; // ref-ports
endinterface
module dff1 (ff_if a);
always @(posedge a.clk or negedge a.rst_n)
if (!a.rst_n) a.q <= 0;
else a.q <= a.d1;
endmodule
module dff2 (ff_if b);
always @(posedge b.clk or negedge b.rst_n)
if (!b.rst_n) b.q <= 0;
else b.q <= b.d2;
endmodule
// +define+I2 for second instantiation order
`ifdef I2
module topr2;
`else
module topr1;
`endif
bit clk, rst_n;
ff_if x_if (.clk(clk), .rst_n(rst_n));
initial begin
clk <= 0;
forever #10 clk++;
end
// +define+I2 for second instantiation order
`ifdef I2
initial $display("===============================\n",
"*** Running %m +define+I2 ***\n",
"===============================");
dff2 u2 (.d2(d2), .clk(clk), .rst_n(rst_n));
dff1 u1 (.d1(d1), .clk(clk), .rst_n(rst_n));
`else
initial $display("=========================================\n",
"*** Running %m (without +define+I2) ***\n",
"=========================================");
dff1 u1 (.d1(d1), .clk(clk), .rst_n(rst_n));
dff2 u2 (.d2(d2), .clk(clk), .rst_n(rst_n));
`endif
initial $monitor("%m: q=%b d1=%b d2=%b clk=%b rst_n=%b",
x_if.q, x_if.d1, x_if.d2, clk, rst_n);
initial begin
rst_n <= 0;
d1 = 0;
d2 = 1;
@(posedge clk);
@(negedge clk) rst_n = 1;
repeat (4) @(negedge clk) {d1,d2} = ~{d1,d2};
$finish;
end
endmodule
========= Second Example with hierarchical references - still a race
condition ==========
module dff1 (input d1, clk, rst_n);
always @(posedge clk or negedge rst_n)
if (!rst_n) toph.q <= 0;
else toph.q <= d1;
endmodule
module dff2 (input d2, clk, rst_n);
always @(posedge clk or negedge rst_n)
if (!rst_n) toph.q <= 0;
else toph.q <= d2;
endmodule
module toph;
reg clk, rst_n;
reg d1, d2;
reg q;
initial begin
clk <= 0;
forever #10 clk = ~clk;
end
// +define+I2 for second instantiation order
`ifdef I2
initial $display("===============================\n",
"*** Running %m +define+I2 ***\n",
"===============================");
dff2 u2 (.d2(d2), .clk(clk), .rst_n(rst_n));
dff1 u1 (.d1(d1), .clk(clk), .rst_n(rst_n));
`else
initial $display("=========================================\n",
"*** Running %m (without +define+I2) ***\n",
"=========================================");
dff1 u1 (.d1(d1), .clk(clk), .rst_n(rst_n));
dff2 u2 (.d2(d2), .clk(clk), .rst_n(rst_n));
`endif
initial $monitor("%m: q=%b d1=%b d2=%b clk=%b rst_n=%b",
q, d1, d2, clk, rst_n);
initial begin
rst_n <= 0;
d1 = 0;
d2 = 1;
@(posedge clk);
@(negedge clk) rst_n = 1;
repeat (4) @(negedge clk) {d1,d2} = ~{d1,d2};
$finish;
end
endmodule
----------------------------------------------------
Cliff Cummings - Sunburst Design, Inc.
14314 SW Allen Blvd., PMB 501, Beaverton, OR 97005
Phone: 503-641-8446 / FAX: 503-641-8486
cliffc@sunburst-design.com / www.sunburst-design.com
Expert Verilog, Synthesis and Verification Training
This archive was generated by hypermail 2b28 : Fri Aug 29 2003 - 14:16:49 PDT