This section provides a detailed description of different types of temporal expressions and temporal operators.
Basic temporal expressions are simple temporal expressions that contain the emission of a particular event. This section includes a discussion of the following:
Example 7-5 shows the usage of some basic temporal expressions.
Example shows the usage of basic temporal operators. <' struct m_str {\ //Definition of basic events event a_event is rise('~/top/start') @sim; event b_event is rise('~/top/end') @sim; event clk is rise('~/top/clk') @sim; event unary_e is @b_event @clk; //@b_event is a unary event temporal expression. //unary_e occurs at clk event when b_event occurs //in a sampling period. event boolean_e is true('~/top/clear' ==1) @clk; //boolean_e is emitted when the boolean //temporal operator checks whether HDL signal //~/top/clear is equal to 1 exactly at the rising //edge of clk. event edgep_e is rise('~/top/a' ==1) @clk; //edgep_e is emitted when the edge //temporal operator finds that ~/top/a //has gone from 0 to 1 in the current //sampling period of clk. event edgen_e is fall('~/top/a' ==1) @clk; //edgen_e is emitted when the edge //temporal operator finds that ~/top/a //has gone from 1 to 0 in the current //sampling period of clk. event edgec_e is change('~/top/a') @clk; //edgec_e is emitted when the edge //temporal operator finds that ~/top/a //has changed value in the //current sampling period of clk. temp_oper() @clk is { wait delay (10); //Wait for 10 simulation time units wait cycle; //Wait for the next emission of clk event }; }; '>
The semicolon (;) sequence operator evaluates a series of temporal expressions over successive emissions of a specified sampling event. Each temporal expression following a ";" starts evaluating in the sampling period following that in which the preceding temporal expression succeeded. The sequence succeeds whenever its final expression succeeds. If any one expression in the list of temporal expressions is missed, the sequence goes back to the beginning and restarts evaluation.
Figure 7-2 shows the results of evaluating the temporal sequence shown below over the series of ev_a, ev_b, and ev_c events shown at the top of the figure. Evaluation of the sequence starts whenever event ev_a occurs.
{@ev_a; @ev_b; @ev_c} @qclk;
The not temporal expression succeeds if the evaluation of the subexpression does not succeed during the sampling period. Thus not TE succeeds on every emission of the sampling event if TE does not succeed.
In Example 7-6, the event ev_d occurs every time there is an emission of ev_c that is not preceded by an emission of ev_a and then two consecutive emissions of ev_b.
event ev_d is {not{@ev_a; @ev_b; @ev_b}; @ev_c} @clk;
A fail succeeds whenever the temporal expression fails. If the temporal expression has multiple interpretations (for example, fail (TE1 or TE2)), the expression succeeds if and only if all the interpretations fail. The expression fail TE succeeds at the point where all possibilities to satisfy TE have been exhausted. Any TE can fail at most once per sampling event.
Example 7-7 shows the usage of a fail operator.
fail {@ev_b;@ev_c}
The expression above succeeds for any of the following conditions:
Event ev_b does not occur in the first cycle.
ev_b succeeds in the first cycle, but event ev_c is not emitted in the second cycle.
The fail operator differs from the not operator. Figure 7-3 illustrates the differences in behavior of not and fail for the sequence of ev_b and ev_c events shown at the top of the figure. To understand the differences, start with the emissions of ev_b and ev_c events shown at the beginning of the figure. Then look at the temporal expression {@ev_b; @ev_c}@pclk and how that succeeds. Then notice the difference between the application of not and fail operators to this temporal expression.
The temporal and succeeds when both temporal expressions start evaluating in the same sampling period and succeed in the same sampling period. Example 7-8 shows the usage of the and operator.
event TE3 is (TE1 and TE2) @qclk
Evaluation of the above and temporal expression for event emissions as shown in Figure 7-4 is as follows:
Evaluation of both TE1 and TE2 begins on the first qclk. Both TE1 and TE2 succeed between the second and third qclk so the event TE3 is emitted at the third qclk.
The evaluations of TE1 and TE2 that begin on the fourth qclk eventually result in success of both TE1 and TE2, but TE2 succeeds before the fifth qclk, and TE1 succeeds before the sixth qclk. Therefore, TE1 and TE2 does not succeed.
On the seventh qclk, evaluation of TE1 begins, and it succeeds before the ninth qclk. However, the corresponding evaluation of TE2 fails during that period, so TE3 fails.
The or temporal expression succeeds when either temporal expression succeeds. An or operator creates a parallel evaluation for each of its subexpressions. It can create multiple successes for a single temporal expression evaluation. Example 7-9 shows the usage of the or operator.
event TE3 is (@TE1 or @TE2) @qclk;
Evaluation of the above or temporal expression for event emissions as shown in Figure 7-5 is as follows:
Evaluation of both TE1 and TE2 begins on the first qclk and succeeds between the second and third qclk, so TE1 or TE2 succeeds at the third qclk.
The evaluations of TE1 or TE2 that begin on the fourth qclk result in success of TE2 before the fifth qclk, so TE3 succeeds at the fifth qclk.
Evaluation of TE1 or TE2 begins again at the seventh qclk, and TE1 succeeds before the ninth qclk, so TE3 succeeds at the ninth qclk.
Repetition of a temporal expression is frequently used to describe cyclic or periodic temporal behavior. The fixed repeat operator specifies a fixed number of emissions of the same temporal expression. If the numeric expression evaluates to zero, the temporal expression succeeds immediately.
In Example 7-10, the wait action proceeds after the sequence event ev_a, then three emissions of event ev_b, then event ev_c, all sampled at the sampling event @clk.
wait {@ev_a; [3]*@ev_b; @ev_c} @clk;
The first match repeat expression works on multiple emissions of a temporal expression from a lower bound to an upper bound. The first match repeat expression succeeds on the first success of the temporal expression. Example 7-11 shows the usage of the first match variable repeat operator.
wait {@ev_a; [0..2]*@ev_b; @ev_c}@pclk;
In Example 7-11, the wait action proceeds after any one of the three sequences sampled at consecutive sampling events:
{@ev_a; @ev_c} @pclk;
{@ev_a; @ev_b; @ev_c}@pclk;
{@ev_a; @ev_b; @ev_b; @ev_c}@pclk;
In the following example, the wait action proceeds after one or more emissions of ev_a at consecutive pclk events, followed by one emission of ev_b at the next @pclk event:
wait {[1..]*@ev_a; @ev_b}@pclk;
In the following example, the wait action proceeds after between zero and three occurrences of the sequence {ev_a; ev_b} (sampled by pclk), followed by an emission of ev_c at the next pclk event:
wait {[..3]*{@ev_a; @ev_b}; @ev_c}@pclk;
The true match repeat expression works on multiple occurrences of a temporal expression from a lower bound to an upper bound. True match variable repeat succeeds every time the subexpression succeeds. This expression creates a number of parallel repeat evaluations within the range.
In Example 7-12, the temporal expression succeeds three pclk cycles after reset occurs, again at four pclk cycles after reset, and again five pclk cycles after reset (with reset also sampled at pclk):
Example shows true match variable repeat operator <' struct t { event reset; event pclk; event TE1 is {@reset; ~[3..5]} @pclk; //~ causes true match //variable repeat operator }; extend sys { t_struct: t; }; '>
The following temporal expression succeeds after any of the sequences {A}, {A; B}, {A; B; B}, or {A; B; B; B}:
{@A;~[..3]*@B}@pclk;
This operator is used to indicate that the temporal expression should succeed at some unspecified time. Typically, eventually is used to specify that a temporal expression is expected to succeed sometime before the simulation ends.
In Example 7-13, the temporal expression succeeds after the event ev_c is followed by event ev_a in the next cycle, and then event ev_b is emitted sometime before the simulation terminates.
{@ev_c; @ev_a; eventually @ev_b} @pclk;
The yield operator is used to assert that success of one temporal expression depends on the success of another temporal expression. The yield expression TE1 => TE2 is equivalent to (fail TE1) or {TE1 ; TE2}. The yield expression succeeds without evaluating the second expression if the first expression fails. If the first expression succeeds, then the second expression must succeed in sequence.
In Example 7-14, the temporal expression succeeds if acknowledge is emitted 1 to 100 cycles after request is emitted. However, if @request never happens, then the yield expression succeeds without evaluating the second expression
Example shows the usage of a yield operator. <' struct t { event request; event acknowledge; event clk is rise('~/top/clk') @sim; expect @request => {[..99]; @acknowledge} @clk; //Note: We would expect @request and @acknowledge //to be emitted from a TCM in the same struct or //or another struct. }; '>