( ESNUG 290 Item 8 ) ----------------------------------------------- [5/19/98]
Subject: What Are The Differences Between RTL & Behavioral Code ?
> I am confused: what on earth the differences between RTL and behavioral
> level code. Is there any obvious instruction for RTL only or for
> behavioral only in Verilog? And there is another confusion. Whether the
> result of the synthesis written by behavioral code is worse than RTL code?
> And how do I start to write RTL code instead of behavioral ?
>
> - Wang Yueh-yi
> National Chiao-Tung University Taiwan
---- ---- ---- ---- ---- ---- ----
From: Ganapathy Subbaraman <subbu@eng.adaptec.com>
Both RTL and behavioral are the same. After u synthesise RTL or behavioral
u get the netlist in gates.
- Ganapathy Subbaraman
Adaptec
---- ---- ---- ---- ---- ---- ----
From: tcoonan@mindspring.com (Thomas A. Coonan)
I think I disagree. "Register Transfer Level" implies logic between clocked
registered/latches) stages. Implies synthesizable. Behavioral means any
model that implements any behavior - no restrictions. I use behavioral
verilog models, for example, for A/D converters. They use real numbers,
arbitrary math and programming constructs, and there's no presumption of
synthesizability (although, advanced tools push the edge of what can be
synthesized (e.g. Behavioral Compiler from Synopsys), RTL is the traditional
breakpoint).
If you modeled a car cruise control system in verilog, with a bunch of
arbitrary delays, real numbers, math, etc. it'd be behavioral. If you
modeled it with register element, boolean equations and some combination
of clocks; it'd be RTL. You can mix-n-match; an RTL or gate-level netlist
will often have a memory module within it, that is.. Behavioral!
Maybe you were looking for something more precise?
- Tom Coonan
Scientific Atlanta
---- ---- ---- ---- ---- ---- ----
From: ravelx <ravelx@ozu.ccl.itri.org.tw>
Synopsys has the new Behavior Compiler. Check it out. As Tcoonan says,
behavioral is that you just describe the behavior of the circuit or the
object, without concerning the real circuit. It may be realized or may
not. Therefore we have the term 'synthesizable'.
Behavioral Compiler synthesizes and optimizes the synthesizable subset of
behavioral code. But I'm not sure if it does do so well as they describe.
- "ravelx"
Industrial Technology Research Institute
---- ---- ---- ---- ---- ---- ----
From: Lars Rzymianowicz <lr@mufasa.informatik.uni-mannheim.de>
Hi Yueh-Yi,
Behavioral code is more abstract than RTL (Register Transfer) code. Language
constructs like loops (for), initial-blocks or events are pure behavioral
Verilog. RTL code is written with synthesis in mind, since tools like
Synopsys can map RTL code much better than behavioral (most synthesis tools
accept only a subset of an HDL).
Behavioral code compilers are on the way, but you have to know a lot of
tricks to get reasonable results.
- Lars Rzymianowicz
University of Mannheim Germany
---- ---- ---- ---- ---- ---- ----
> Both RTL and behavioral are the same. After u synthesise RTL or behavioral
> u get the netlist in gates.
>
> - Ganapathy Subbaraman
> Adaptec
From: zoltan@bendor.com.au ( Zoltan Kocsi )
Well, how do you synthesise this:
//
// When A has rising edge, 3 clocks later B changes state.
// (2-3 clocks actually, depending on the relation between A and clock)
//
always begin
@ ( posedge A );
@ ( posedge clock );
@ ( posedge clock );
@ ( posedge clock );
B = ! B;
end
It is certainly a valid behavioural statement but not RTL and RTL synthesis
tools would choke on it.
- Zoltan Kocsi
Bendor Research Pty. Ltd. Austrailia
---- ---- ---- ---- ---- ---- ----
From: "John H. E. Fiskio-Lasseter" <johnfl@cs.uoregon.edu>
Zoltan,
Is this really the behavioral equivalent? Or will all three of those
"posedge clock" guards fire in the same tic, since there is "zero time"
between each one?
- John H. E. Fiskio-Lasseter
University of Oregon
---- ---- ---- ---- ---- ---- ----
From: "Matthew Morris" <mmorris@@lace.colorado.edu>
That is equivalent to saying that
#100
#100
#100
b = !b;
will happen instantaneously since there is "zero time" between each #100..
The @ is a sequential statement.
- Matt Morris
University of Colorado at Boulder
---- ---- ---- ---- ---- ---- ----
From: "John H. E. Fiskio-Lasseter" <johnfl@cs.uoregon.edu>
Matt, that's actually the heart of my question. They aren't really the
same, because a delay control guarantees that this thread will be suspended
for an amount of time that is determined when the delay is encountered.
I can tell from a glance at this code that it will take 300 tics to reach
"b = !b".
Event controls don't have any such property, however. A statement
guarded by "@(posedge x)" executes (with zero delay) as soon as there's
a change in x from low to high (I realize you know all this). The
question is: across what time boundary must this change happen?
Between simulation tics? Or will any sequential block that sets x to 0
and then to 1 in "zero time" do the trick? And will every "posedge x"
guard in the example above see this change or just the first one?
I believe you're right, by the way. What I'm interested in is how
precise the semantics are on the matter.
- John H. E. Fiskio-Lasseter
University of Oregon
---- ---- ---- ---- ---- ---- ----
> always begin
>
> @ ( posedge A );
> @ ( posedge clock );
> @ ( posedge clock );
> @ ( posedge clock );
> B = ! B;
> end
>
> Is this really the behavioral equivalent? Or will all three of those
> "posedge clock" guards fire in the same tic, since there is "zero time"
> between each one?
>
> - John H. E. Fiskio-Lasseter
> University of Oregon
From: zoltan@bendor.com.au ( Zoltan Kocsi )
Well, according to my book (Thomas & Moorby) one @(event) eats one event
so the subsequent ones waiting for the same event will not see it, they
have to wait for the second, third ... event. You can think of @(event),
if event happens at T, letting your program run at T+0 which is
infinitesimally small time later than T. (Actually, T+epsilon and
epsilon -> 0 :-)
Fire up your simulator and test it. I did, and it works.
- Zoltan Kocsi
Bendor Research Pty. Ltd. Austrailia
---- ---- ---- ---- ---- ---- ----
From: sharp@cadence.com (Steven Sharp)
The three statements are still sequential. The first @(posedge clock)
executes after the posedge. Therefore the second @(posedge clock) does
not start waiting until after the first posedge has occurred. An event
can be treated as an atomic occurrence; it has no duration. By the time
anything wakes up on it, it is over. If there is only one posedge, the
block can only proceed past one guard.
That much is definite. The opposite situation is not. If you have
always
begin
@(posedge clk) ;
@(posedge clk) ;
@(posedge clk) ;
do_something;
end
initial
begin
clk = 0;
clk = 1;
clk = 0;
clk = 1;
clk = 0;
clk = 1;
#1 ;
end
the initial block produces 3 posedges, so it is possible we could get to
do_something. However, we probably won't. Execution of statements within
a begin-end block can be suspended in favor of other processes in the model.
However, there is no good reason for a simulator to do so, since it will
probably complicate and slow down execution. If the simulator suspended
in favor of the always block whenever it produced a posedge on clk, it
would get to do_something. However, it will probably just schedule the
always block to execute and then continue with the initial block. Only at
the #1 will it switch to execute the always block and end up waiting at
the second @.
Waiting on nets is generally better behaved than waiting on regs, since
they aren't assigned to directly by process code.
- Steve Sharp
Cadence
---- ---- ---- ---- ---- ---- ----
> #100
> #100
> #100
> b = !b;
>
> I can tell from a glance at this code that it will take 300 tics to reach
> "b = !b". Event controls don't have any such property, however. A
> statement guarded by "@(posedge x)" executes (with zero delay) as soon as
> there's a change in x from low to high (I realize you know all this).
> The question is: across what time boundary must this change happen?
>
> - John H. E. Fiskio-Lasseter
> University of Oregon
From: "Matthew Morris" <mmorris@@lace.colorado.edu>
The time boundary is up to your design. The @ and the # are the very same
section of the spec. Both just wait. # waits a fixed amount of time after
this delta. @ waits for an event *after* this delta.
Incidentally, food for thought.. This should give you some intuition.
How/why do these act differently?
repeat (5)
@posedge clk
b = ~b;
and
repeat (5)
@posedge clk ;
b = ~b;
( besides the obvious semi after clk... )
- Matt Morris
University of Colorado at Boulder
---- ---- ---- ---- ---- ---- ----
From: "John H. E. Fiskio-Lasseter" <johnfl@cs.uoregon.edu>
Forgive me for being obtuse, but I don't get your point, Matt. The first
one inverts b 5 times, once for each time the clk goes high. The second
does nothing through the next five rising edges of clk. Then it inverts
b once.
Is your point that the second statement is equivalent to "#5 b =~b"
(assuming clk is inverted every unit of simulation time)? If I have
instead in a separate thread:
repeat (5)
#0 clk = ~clk;
Is it possible that I will exhaust all five guards in one tic of the
simulation clock (since processes can, in principle, be interleaved)?
- John H. E. Fiskio-Lasseter
University of Oregon
---- ---- ---- ---- ---- ---- ----
> If you have
>
> always
> begin
> @(posedge clk) ;
> @(posedge clk) ;
> @(posedge clk) ;
> do_something;
> end
>
> initial
> begin
> clk = 0;
> clk = 1;
> clk = 0;
> clk = 1;
> clk = 0;
> clk = 1;
> #1 ;
> end
>
> the initial block produces 3 posedges, so it is possible we could get to
> do_something. However, we probably won't. Execution of statements within
> a begin-end block can be suspended in favor of other processes in the model.
> However, there is no good reason for a simulator to do so, since it will
> probably complicate and slow down execution. If the simulator suspended
> in favor of the always block whenever it produced a posedge on clk, it
> would get to do_something. However, it will probably just schedule the
> always block to execute and then continue with the initial block. Only at
> the #1 will it switch to execute the always block and end up waiting at
> the second @.
>
> - Steven Sharp
> Cadence
From: "John H. E. Fiskio-Lasseter" <johnfl@cs.uoregon.edu>
I think I'm becoming convinced of Matthew Morris's argument on this. If
I'm right, your example will only fire at most one guard, and that only
if the two processes are interleaved. When a guarded statement is
released, it is executed during the "delayed thread" stage of the
cycle. In other words "@(1) some_statement" (where the @(1) indicates a
firing guard) is equivalent to "#0 some_statement". If, however, we
modify the code to be:
always
begin
@(posedge clk) ;
@(posedge clk) ;
@(posedge clk) ;
do_something;
end
initial
begin
#0 clk = 0;
#0 clk = 1;
#0 clk = 0;
#0 clk = 1;
#0 clk = 0;
#0 clk = 1;
#1 ;
end
I believe that we can guarantee all three guards will fire, in the sense
of being able to prove some determinacy of execution order. The
execution within the always thread should unroll to:
#0#0#0 #0#0#0 #0#0#0 do_something;
I hate zero delay :-)
- John H. E. Fiskio-Lasseter
University of Oregon
---- ---- ---- ---- ---- ---- ----
> Is your point that the second statement is equivalent to "#5 b =~b"
> (assuming clk is inverted every unit of simulation time)? If I have
> instead in a separate thread:
>
> repeat (5)
> #0 clk = ~clk;
>
> Is it possible that I will exhaust all five guards in one tic of the
> simulation clock (since processes can, in principle, be interleaved)?
>
> - John H. E. Fiskio-Lasseter
> University of Oregon
From: sharp@cadence.com (Steven Sharp)
I am not sure what point he was illustrating. However, the answer to
your final question is yes. In fact, good old section 5 states that #0
forces a process to suspend and be re-queued, forcing the interleaving
you suggest. So by that rule, it is not only possible but required that
all five guards be triggered by the separate edges. Adding #0 makes the
pulses "wider", though still with a width of zero in simulation time units.
- Steven Sharp
Cadence
---- ---- ---- ---- ---- ---- ----
> Just consider if there's additional guard in the always block, how will
> b behave? My simulator shows nothing happens to b.
>
> always
> begin
> @(posedge clk) ;
> @(posedge clk) ;
> @(posedge clk) ;
> @(posedge clk);
> b = 1;
> end
>
> initial
> begin
> #0 clk = 0;
> #400 clk = 0;
> #0 clk = 1;
> #0 clk = 0;
> #0 clk = 1;
> #0 clk = 0;
> #0 clk = 1;
> #1 ;
> end
>
> - Wenzhong
> Beijing Telegraph Administration
From: "John H. E. Fiskio-Lasseter" <johnfl@cs.uoregon.edu>
Nothing should happen to b. You have four guards and only three positive
edges. With the changes scheduled in the initial block, the always-loop
unrolls to:
#0#400#0#0 ; #0#0#0 ; #0#0#0 ;
@(posedge x);
the_rest_of_the_block_which_you_cant_reach;
In other words, this is equivalent to scheduling a delayed-execution
guarded thread at time 400 (which is guaranteed to be the eighth or
later later thread to run at that time), with no other thread which can
release the guard.
- John H. E. Fiskio-Lasseter
University of Oregon
|
|