ch10.10.htm
来自「介绍asci设计的一本书」· HTM 代码 · 共 490 行 · 第 1/3 页
HTM
490 行
is the closest equivalent to the assignment statement in a computer programming
language. Variable assignment statements are always sequential statements
and the LHS of a variable assignment statement is always updated immediately.
Here is the definition and an example:</P>
<PRE>variable_assignment_statement ::=
<U>[label:]</U> name|aggregate := expression ;
<B>entity</B> Var_Assignment <B>is</B> <B>end</B>;
<B>architecture</B> Behave <B>of</B> Var_Assignment <B>is</B>
<B>signal</B> s1 : INTEGER := 0;
<B>begin</B> <B>process variable</B> v1,v2 : INTEGER := 0; <B>begin</B>
<B>assert</B> (v1/=0) <B>report</B> "v1 is 0" <B>severity</B> note ; -- this prints
v1 := v1 + 1; -- after this statement v1 is 1
<B>assert</B> (v1=0) <B>report</B> "v1 isn't 0" <B>severity</B> note ; -- this prints
v2 := v2 + s1; -- signal and variable types must match
<B>wait</B>;
<B>end</B> <B>process</B>;
<B>end</B>;</PRE>
<P><A NAME="pgfId=115471"></A>This is the output from Cadence Leapfrog for
the preceding example:</P>
<PRE>ASSERT/NOTE (time 0 FS) from :$PROCESS_000 (design unit WORK.VAR_ASSIGNMENT:BEHAVE) v1 is 0
ASSERT/NOTE (time 0 FS) from :$PROCESS_000 (design unit WORK.VAR_ASSIGNMENT:BEHAVE) v1 isn't 0</PRE>
<P><A NAME="pgfId=10518"></A>A signal assignment statement schedules a future
assignment to a signal:</P>
<PRE>signal_assignment_statement::=
<U>[label:]</U> target <=
[<B>transport</B> <U>| [ reject time_expression ] inertial</U> ] waveform ;</PRE>
<P><A NAME="pgfId=238280"></A>The following example shows that, even with
no delay, a signal is updated at the end of a simulation cycle after all
the other assignments have been scheduled, just before simulation time is
advanced:</P>
<PRE><B>entity</B> Sig_Assignment_1 <B>is</B> <B>end</B>;
<B>architecture</B> Behave <B>of</B> Sig_Assignment_1 <B>is</B>
<B>signal</B> s1,s2,s3 : INTEGER := 0;
<B>begin</B> <B>process variable</B> v1 : INTEGER := 1; <B>begin</B>
<B>assert</B> (s1 /= 0) <B>report</B> "s1 is 0" <B>severity</B> note ; -- this prints.
s1 <= s1 + 1; -- after this statement s1 is still 0.
<B>assert</B> (s1 /= 0) <B>report</B> "s1 still 0" <B>severity</B> note ; -- this prints.
<B>wait</B>;
<B>end</B> <B>process</B>;
<B>end</B>;
ASSERT/NOTE (time 0 FS) from :$PROCESS_000 (design unit WORK.SIG_ASSIGNMENT_1:BEHAVE) s1 is 0
ASSERT/NOTE (time 0 FS) from :$PROCESS_000 (design unit WORK.SIG_ASSIGNMENT_1:BEHAVE) s1 still 0</PRE>
<P><A NAME="pgfId=116202"></A>Here is an another example to illustrate how
time is handled:</P>
<PRE><B>entity</B> Sig_Assignment_2 <B>is</B> <B>end</B>;
<B>architecture</B> Behave <B>of</B> Sig_Assignment_2 <B>is</B>
<B>signal</B> s1, s2, s3 : INTEGER := 0;
<B>begin</B> <B>process variable</B> v1 : INTEGER := 1; <B>begin</B>
-- s1, s2, s3 are initially 0; now consider the following:
s1 <= 1 ; -- schedules updates to s1 at end of 0 ns cycle.
s2 <= s1; -- s2 is 0, not 1.
<B>wait</B> <B>for</B> 1 ns;
s3 <= s1; -- now s3 will be 1 at 1 ns.
<B>wait</B>;
<B>end</B> <B>process</B>;
<B>end</B>;</PRE>
<P><A NAME="pgfId=116045"></A>The Compass simulator produces the following
trace file for this example:</P>
<PRE> Time(fs) + Cycle s1 s2 s3
---------------------- ------------ ------------ ------------
0+ 0: 0 0 0
0+ 1: * 1 * 0 0
...
1000000+ 1: 1 0 * 1</PRE>
<P><A NAME="pgfId=116049"></A>Time is indicated in femtoseconds for each
simulation cycle plus the number of delta cycles (we call this delta time,
measured in units of delta) needed to calculate all transactions on signals.
A transaction consists of a new value for a signal (which may be the same
as the old value) and the time delay for the value to take effect. An asterisk
'*' before a value in the preceding trace indicates that a transaction has
occurred and the corresponding signal updated at that time. A transaction
that does result in a change in value is an event. In the preceding simulation
trace for Sig_Assignment_2:Behave</P>
<UL>
<P><A NAME="pgfId=116070"></A>At <TT>0 ns + 0</TT> delta: all signals are
<TT>0</TT> .
<P><A NAME="pgfId=116073"></A>At <TT>0 ns + 1</TT> delta: <TT>s1</TT> is
updated to <TT>1</TT> , <TT>s2</TT> is updated to <TT>0</TT> (not to <TT>1</TT>
).
<P><A NAME="pgfId=116091"></A>At <TT>1 ns + 1</TT> delta: <TT>s3</TT> is
updated to a <TT>1</TT> .
</UL>
<P><A NAME="pgfId=108835"></A>The following example shows the behavior of
the different delay models: transport and inertial (the default):</P>
<PRE><B>entity</B> Transport_1 <B>is</B> <B>end</B>;
<B>architecture</B> Behave <B>of</B> Transport_1 <B>is</B>
<B>signal</B> s1, SLOW, FAST, WIRE : BIT := '0';
<B>begin process begin</B>
s1 <= '1' <B>after</B> 1 ns, '0' <B>after</B> 2 ns, '1' <B>after</B> 3 ns ;
-- schedules s1 to be '1' at t+1 ns, '0' at t+2 ns,'1' at t+3 ns
<B>wait</B>; <B>end</B> <B>process</B>;
-- inertial delay: SLOW rejects pulsewidths less than 5ns:
<B>process</B> (s1) <B>begin</B> SLOW <= s1 <B>after</B> 5 ns ; <B>end</B> <B>process</B>;
-- inertial delay: FAST rejects pulsewidths less than 0.5ns:
<B>process</B> (s1) <B>begin</B> FAST <= s1 <B>after</B> 0.5 ns ; <B>end</B> <B>process</B>;
-- transport delay: WIRE passes all pulsewidths...
<B>process</B> (s1) <B>begin</B> WIRE <= <B>transport</B> s1 <B>after</B> 5 ns ; <B>end</B> <B>process</B>;
<B>end</B>;</PRE>
<P><A NAME="pgfId=189300"></A>Here is the trace file from the Compass simulator:</P>
<PRE><A NAME="pgfId=189301"></A>
Time(fs) + Cycle s1 slow fast wire
---------------------- ---- ---- ---- ----
0+ 0: '0' '0' '0' '0'
500000+ 0: '0' '0' *'0' '0'
1000000+ 0: *'1' '0' '0' '0'
1500000+ 0: '1' '0' *'1' '0'
2000000+ 0: *'0' '0' '1' '0'
2500000+ 0: '0' '0' *'0' '0'
3000000+ 0: *'1' '0' '0' '0'
3500000+ 0: '1' '0' *'1' '0'
5000000+ 0: '1' '0' '1' *'0'
6000000+ 0: '1' '0' '1' *'1'
7000000+ 0: '1' '0' '1' *'0'
8000000+ 0: '1' *'1' '1' *'1'</PRE>
<P><A NAME="pgfId=116304"></A>Inertial delay mimics the behavior of real
logic gates, whereas transport delay more closely models the behavior of
wires. In VHDL-93 you can also add a separate <DFN CLASS="Definition">pulse
rejection limit</DFN> for the inertial delay model as in the following example:</P>
<PRE><B>process</B> (s1) <B>begin</B> RJCT <= <B>reject</B> 2 ns s1 <B>after</B> 5 ns ; <B>end</B> <B>process</B>;</PRE>
<H3><A NAME="pgfId=4858"></A>10.10.4 Procedure Call</H3>
<P><A NAME="pgfId=10519"></A>A procedure call in VHDL corresponds to calling
a subroutine in a conventional programming language [<A HREF="../../VHDL/LRM/HTML/1076_8.HTM#8.6">VHDL
LRM8.6</A>]. The parameters in a procedure call statement are the actual
procedure parameters (or actuals); the parameters in the procedure definition
are the formal procedure parameters (or formals). The two are linked using
an association list, which may use either positional or named association
(association works just as it does for ports--see Section 10.7.1):</P>
<PRE>procedure_call_statement ::=
<U>[label:]</U> procedure_name [(parameter_association_list)];</PRE>
<P><A NAME="pgfId=32499"></A>Here is an example:</P>
<PRE><B>package</B> And_Pkg <B>is </B>
<B> procedure</B> V_And(a, b : BIT; <B>signal</B> c : <B>out</B> BIT);
<B> </B>function V_And(a, b : BIT) <B>return</B> BIT;
<B>end</B>;
<B>package body</B> And_Pkg <B>is </B>
<B> procedure</B> V_And(a, b : BIT; <B>signal</B> c: <B>out</B> BIT) <B>is </B>
<B> begin</B> c <= a <B>and </B>b; <B>end</B>;
<B> </B>function V_And(a, b: BIT) <B>return</B> BIT <B>is </B>
<B> begin</B> <B>return</B> a <B>and </B>b; <B>end</B>;
<B>end</B> And_Pkg;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?