A constant signal in a case if hierarchical procedure calls

I

Ilya Kalistru

Guest
Hello.

I’d like to know your opinion on an issue I met.
I used a procedure in my code. Let’s say that it is the procedure
(It’s not. Just an example):

procedure p1(
signal clk : in std_logic;
signal A : in std_logic;
signal C : out std_logic
) is
begin
loop
wait until rising_edge(clk);
C <= A xor ‘1’;
end loop;
end procedure p1;

Then I decided that I needed extended version of the procedure,
so I rewrote it using a new procedure name p2 for extended version,
and I just called the new procedure p2 with a constant parameter in
the old procedure p1 like that:

procedure p2(
signal clk : in std_logic;
signal A : in std_logic;
signal B : in std_logic;
signal C : out std_logic
) is
begin
loop
wait until rising_edge(clk);
C <= A xor B;
end loop;
end procedure p2;

procedure p1(
signal clk : in std_logic;
signal A : in std_logic;
signal C : out std_logic
) is
begin
p2(clk, A, '1', C);
end procedure p1;

The problem is that I got an error
ERROR: [VRFC 10-275] actual '1' of formal b must be a signal [D:/VHDL_proj/test1/test1.srcs/sources_1/new/test.vhd:59]

Is it impossible to call a subprogram from an another subprogram,
assigning an actual constant to a formal signal parameter of the
internal subprogram?
 
On 8/30/2016 12:32 PM, Ilya Kalistru wrote:
Hello.

I’d like to know your opinion on an issue I met.
I used a procedure in my code. Let’s say that it is the procedure
(It’s not. Just an example):

procedure p1(
signal clk : in std_logic;
signal A : in std_logic;
signal C : out std_logic
) is
begin
loop
wait until rising_edge(clk);
C <= A xor ‘1’;
end loop;
end procedure p1;

Then I decided that I needed extended version of the procedure,
so I rewrote it using a new procedure name p2 for extended version,
and I just called the new procedure p2 with a constant parameter in
the old procedure p1 like that:

procedure p2(
signal clk : in std_logic;
signal A : in std_logic;
signal B : in std_logic;
signal C : out std_logic
) is
begin
loop
wait until rising_edge(clk);
C <= A xor B;
end loop;
end procedure p2;

procedure p1(
signal clk : in std_logic;
signal A : in std_logic;
signal C : out std_logic
) is
begin
p2(clk, A, '1', C);
end procedure p1;

The problem is that I got an error
ERROR: [VRFC 10-275] actual '1' of formal b must be a signal [D:/VHDL_proj/test1/test1.srcs/sources_1/new/test.vhd:59]

Is it impossible to call a subprogram from an another subprogram,
assigning an actual constant to a formal signal parameter of the
internal subprogram?

Instead of using a literal (what your '1' really is), what happens if
you declare a constant and use that?

I think the problem may be that the tool doesn't know the type of the
literal but a constant has a declared type.

Or you can try indicating the type with type casting such as
std_logic('1').

--

Rick C
 
On Wednesday, August 31, 2016 at 4:32:22 AM UTC+12, Ilya Kalistru wrote:
Hello.

I’d like to know your opinion on an issue I met.
I used a procedure in my code. Let’s say that it is the procedure
...
Then I decided that I needed extended version of the procedure,
so I rewrote it using a new procedure name p2 for extended version,
and I just called the new procedure p2 with a constant parameter in
the old procedure p1 like that:

procedure p2(
signal clk : in std_logic;
signal A : in std_logic;
signal B : in std_logic;
signal C : out std_logic
) is
begin
loop
wait until rising_edge(clk);
C <= A xor B;
end loop;
end procedure p2;

procedure p1(
signal clk : in std_logic;
signal A : in std_logic;
signal C : out std_logic
) is
begin
p2(clk, A, '1', C);
end procedure p1;

The problem is that I got an error
ERROR: [VRFC 10-275] actual '1' of formal b must be a signal [D:/VHDL_proj/test1/test1.srcs/sources_1/new/test.vhd:59]

Is it impossible to call a subprogram from an another subprogram,
assigning an actual constant to a formal signal parameter of the
internal subprogram?

Yes, it's impossible.

IEEE Std 1076-2008 4.2.2.1 Formal parameter lists

In a subprogram call, the actual designator (see 6.5.7.1) associated with a formal parameter of class signal shall be a name denoting a signal. The actual designator associated with a formal of class variable shall be a name denoting a variable. The actual designator associated with a formal of class constant shall be an expression. The actual designator associated with a formal of class file shall be a name denoting a file.

--

The actual in a subprogram call of a formal of class signal must be a signal.

Note that a signal name is a primary in an expression and an expression can consist solely of a primary. (9.1).

While an expression can be associated as an actual of a formal in a port map aspect the difference is that a subprogram call's parameter association elements are dynamically elaborated (14.6).

If you are not using predefined signal attributes your inputs can be class constant (the default). For use as a concurrent procedure call (11.4) the sensitivity list of the final wait statement in the equivalent process "is constructed by taking the union of the sets constructed by applying the rule of 10.2 to each actual part associated with a formal parameter".

In other words sensitivity stems from the actual and not the formal, allowing signals as primaries of expressions to provide events for resumption of the equivalent process to a concurrent procedure call with parameters of mode in or inout ("for which reading is permitted" (10.2) that are class constant.

The distinction is the inability to use predefined signal attributes of which 'STABLE, 'QUIET, 'TRANSACTION, and 'DELAYED are already disallowed for formal signal parameters (4.2.2.3).

So delete the reserved word signal in the declaration for parameter B in P2 resulting in class constant, or in general any signal you are not using a signal attribute from. The function rising_edge depends on a signal parameter and uses signal attributes.
 
Oh, thank you so much. It works.

I thought that if a formal is defined as constant, its value will be fixed at the moment of procedure call and won't change no matter what.
It's a surprise for me that value of a constant can be adjusted. )
 
On Wednesday, August 31, 2016 at 5:29:07 PM UTC+12, Ilya Kalistru wrote:
Oh, thank you so much. It works.

I thought that if a formal is defined as constant, its value will be fixed at the moment of procedure call and won't change no matter what.
It's a surprise for me that value of a constant can be adjusted. )

The value is passed as a parameter at elaboration time, which for subprograms is during evaluation when called - subprogram calls are dynamically elaborated.
 
On Wednesday, August 31, 2016 at 10:34:57 PM UTC+3, diog...@gmail.com wrote:
On Wednesday, August 31, 2016 at 5:29:07 PM UTC+12, Ilya Kalistru wrote:
Oh, thank you so much. It works.

I thought that if a formal is defined as constant, its value will be fixed at the moment of procedure call and won't change no matter what.
It's a surprise for me that value of a constant can be adjusted. )

The value is passed as a parameter at elaboration time, which for subprograms is during evaluation when called - subprogram calls are dynamically elaborated.

Then I don't understand why the process

procedure p2(
signal clk : in std_logic;
signal A : in std_logic;
B : in std_logic;
signal C : out std_logic
) is
begin
loop
wait until rising_edge(clk);
C <= A xor B;
end loop;
end procedure p2;

responds to changes of the constant B each cycle if the procedure was called
only once.
Does the process resuming after suspension count as a "call"? I can't find
this part in the standard...
 
On Thursday, September 1, 2016 at 9:15:41 AM UTC+12, Ilya Kalistru wrote:
On Wednesday, August 31, 2016 at 10:34:57 PM UTC+3, diog...@gmail.com wrote:
On Wednesday, August 31, 2016 at 5:29:07 PM UTC+12, Ilya Kalistru wrote:
Oh, thank you so much. It works.

I thought that if a formal is defined as constant, its value will be fixed at the moment of procedure call and won't change no matter what.
It's a surprise for me that value of a constant can be adjusted. )

The value is passed as a parameter at elaboration time, which for subprograms is during evaluation when called - subprogram calls are dynamically elaborated.

Then I don't understand why the process

procedure p2(
signal clk : in std_logic;
signal A : in std_logic;
B : in std_logic;
signal C : out std_logic
) is
begin
loop
wait until rising_edge(clk);
C <= A xor B;
end loop;
end procedure p2;

responds to changes of the constant B each cycle if the procedure was called
only once.
Does the process resuming after suspension count as a "call"? I can't find
this part in the standard...

It's not responding to B, it's responding to the condition rising_edge (clk) in the condition clause of the wait statement in p2.

IEEE Std 1076-2008 10.2 Wait statements paragraphs 8, 9 and 10:

The execution of a wait statement causes the time expression to be evaluated to determine the timeout interval. It also causes the execution of the corresponding process statement to be suspended, where the corresponding process statement is the one that either contains the wait statement or is the parent (see 4.3) of the procedure that contains the wait statement. The suspended process will resume, at the latest, immediately after the timeout interval has expired.

The suspended process also resumes as a result of an event occurring on any signal in the sensitivity set of the wait statement. If such an event occurs, the condition in the condition clause is evaluated. If the value of the condition is FALSE, the process suspends again. Such repeated suspension does not involve the recalculation of the timeout interval.

It is an error if a wait statement appears in a function subprogram or in a procedure that has a parent that is a function subprogram. Furthermore, it is an error if a wait statement appears in an explicit process statement that includes a sensitivity list or in a procedure that has a parent that is such a process statement. Finally, it is an error if a wait statement appears within any subprogram whose body is declared within a protected type body, or within any subprogram that has a parent whose body is declared within a protected type body.

--

(There's a default timeout clause described in paragraph 7, every wait statement will timeout at TIME'HIGH).

Neither procedure calls p1 nor p2 ever 'completes'. The parent process (whether constructed from p1 if p1 is a concurrent process, or enclosing p1 suspends and resumes executing the wait statement in p2. p2 has an endless loop with a wait statement. If there were any other sequential statements following the p2 sequential procedure call in p1 they'd never be executed. No other sequential statements in the parent process will be executed.

Any event on a signal in P2's wait statement sensitivity set derived from the condition clause will cause P2 to resume and evaluate it's condition.

When the condition is satisfied p2 will execute the next sequential statement. It's in an endless loop that will wrap around.

Wait statements are sequential statements, only one of them at a time can cause a parent process to suspend. To have a different wait statement cause the parent process to suspend it has to be reached. That can't happen here.
 
On Sunday, September 4, 2016 at 10:14:27 AM UTC+3, diog...@gmail.com wrote:
On Thursday, September 1, 2016 at 9:15:41 AM UTC+12, Ilya Kalistru wrote:
On Wednesday, August 31, 2016 at 10:34:57 PM UTC+3, diog...@gmail.com wrote:
On Wednesday, August 31, 2016 at 5:29:07 PM UTC+12, Ilya Kalistru wrote:
Oh, thank you so much. It works.

I thought that if a formal is defined as constant, its value will be fixed at the moment of procedure call and won't change no matter what.
It's a surprise for me that value of a constant can be adjusted. )

The value is passed as a parameter at elaboration time, which for subprograms is during evaluation when called - subprogram calls are dynamically elaborated.

Then I don't understand why the process

procedure p2(
signal clk : in std_logic;
signal A : in std_logic;
B : in std_logic;
signal C : out std_logic
) is
begin
loop
wait until rising_edge(clk);
C <= A xor B;
end loop;
end procedure p2;

responds to changes of the constant B each cycle if the procedure was called
only once.
Does the process resuming after suspension count as a "call"? I can't find
this part in the standard...

It's not responding to B, it's responding to the condition rising_edge (clk) in the condition clause of the wait statement in p2.

IEEE Std 1076-2008 10.2 Wait statements paragraphs 8, 9 and 10:

The execution of a wait statement causes the time expression to be evaluated to determine the timeout interval. It also causes the execution of the corresponding process statement to be suspended, where the corresponding process statement is the one that either contains the wait statement or is the parent (see 4.3) of the procedure that contains the wait statement. The suspended process will resume, at the latest, immediately after the timeout interval has expired.

The suspended process also resumes as a result of an event occurring on any signal in the sensitivity set of the wait statement. If such an event occurs, the condition in the condition clause is evaluated. If the value of the condition is FALSE, the process suspends again. Such repeated suspension does not involve the recalculation of the timeout interval.

It is an error if a wait statement appears in a function subprogram or in a procedure that has a parent that is a function subprogram. Furthermore, it is an error if a wait statement appears in an explicit process statement that includes a sensitivity list or in a procedure that has a parent that is such a process statement. Finally, it is an error if a wait statement appears within any subprogram whose body is declared within a protected type body, or within any subprogram that has a parent whose body is declared within a protected type body.

--

(There's a default timeout clause described in paragraph 7, every wait statement will timeout at TIME'HIGH).

Neither procedure calls p1 nor p2 ever 'completes'. The parent process (whether constructed from p1 if p1 is a concurrent process, or enclosing p1 suspends and resumes executing the wait statement in p2. p2 has an endless loop with a wait statement. If there were any other sequential statements following the p2 sequential procedure call in p1 they'd never be executed. No other sequential statements in the parent process will be executed.

Any event on a signal in P2's wait statement sensitivity set derived from the condition clause will cause P2 to resume and evaluate it's condition.

When the condition is satisfied p2 will execute the next sequential statement. It's in an endless loop that will wrap around.

Wait statements are sequential statements, only one of them at a time can cause a parent process to suspend. To have a different wait statement cause the parent process to suspend it has to be reached. That can't happen here.

I understand that. I don't understand other thing.
Let's suppose initially actual B=0. As long as P2 is a concurrent process it will be called at 0 ps.

STD 2.1.1.1
For a nonforeign subprogram having a parameter of a scalar type or an
access type, the parameter is passed by copy. At the start of each call,
if the mode is in or inout, the value of the actual parameter is copied
into the associated formal parameter;

At that moment value of the actual B=0 is copied to the formal B of the p2. After wait statement we resume p2 and execute "C <= A xor B" with formal B = 0. Let's suppose that at that moment the actual B outside of the p2 is changed to '1'. As I understand, after next "wait until rising_edge(clk);" statement in p2 when the actual B='1', formal B should still be '0' because it's the value copied from actual to formal during call of the p2.

In fact, the simulator behaves like it copies the actual B to the formal B each time it resumes p2 after wait statement.
 
On Sunday, September 4, 2016 at 9:18:54 PM UTC+12, Ilya Kalistru wrote:
On Sunday, September 4, 2016 at 10:14:27 AM UTC+3, diog...@gmail.com wrote:
On Thursday, September 1, 2016 at 9:15:41 AM UTC+12, Ilya Kalistru wrote:
On Wednesday, August 31, 2016 at 10:34:57 PM UTC+3, diog...@gmail.com wrote:
On Wednesday, August 31, 2016 at 5:29:07 PM UTC+12, Ilya Kalistru wrote:
Oh, thank you so much. It works.

I thought that if a formal is defined as constant, its value will be fixed at the moment of procedure call and won't change no matter what.
It's a surprise for me that value of a constant can be adjusted. )

The value is passed as a parameter at elaboration time, which for subprograms is during evaluation when called - subprogram calls are dynamically elaborated.

Then I don't understand why the process

procedure p2(
signal clk : in std_logic;
signal A : in std_logic;
B : in std_logic;
signal C : out std_logic
) is
begin
loop
wait until rising_edge(clk);
C <= A xor B;
end loop;
end procedure p2;

responds to changes of the constant B each cycle if the procedure was called
only once.
Does the process resuming after suspension count as a "call"? I can't find
this part in the standard...

It's not responding to B, it's responding to the condition rising_edge (clk) in the condition clause of the wait statement in p2.

IEEE Std 1076-2008 10.2 Wait statements paragraphs 8, 9 and 10:

The execution of a wait statement causes the time expression to be evaluated to determine the timeout interval. It also causes the execution of the corresponding process statement to be suspended, where the corresponding process statement is the one that either contains the wait statement or is the parent (see 4.3) of the procedure that contains the wait statement. The suspended process will resume, at the latest, immediately after the timeout interval has expired.

The suspended process also resumes as a result of an event occurring on any signal in the sensitivity set of the wait statement. If such an event occurs, the condition in the condition clause is evaluated. If the value of the condition is FALSE, the process suspends again. Such repeated suspension does not involve the recalculation of the timeout interval.

It is an error if a wait statement appears in a function subprogram or in a procedure that has a parent that is a function subprogram. Furthermore, it is an error if a wait statement appears in an explicit process statement that includes a sensitivity list or in a procedure that has a parent that is such a process statement. Finally, it is an error if a wait statement appears within any subprogram whose body is declared within a protected type body, or within any subprogram that has a parent whose body is declared within a protected type body.

--

(There's a default timeout clause described in paragraph 7, every wait statement will timeout at TIME'HIGH).

Neither procedure calls p1 nor p2 ever 'completes'. The parent process (whether constructed from p1 if p1 is a concurrent process, or enclosing p1 suspends and resumes executing the wait statement in p2. p2 has an endless loop with a wait statement. If there were any other sequential statements following the p2 sequential procedure call in p1 they'd never be executed. No other sequential statements in the parent process will be executed.

Any event on a signal in P2's wait statement sensitivity set derived from the condition clause will cause P2 to resume and evaluate it's condition.

When the condition is satisfied p2 will execute the next sequential statement. It's in an endless loop that will wrap around.

Wait statements are sequential statements, only one of them at a time can cause a parent process to suspend. To have a different wait statement cause the parent process to suspend it has to be reached. That can't happen here.

I understand that. I don't understand other thing.
Let's suppose initially actual B=0. As long as P2 is a concurrent process it will be called at 0 ps.

STD 2.1.1.1
For a nonforeign subprogram having a parameter of a scalar type or an
access type, the parameter is passed by copy. At the start of each call,
if the mode is in or inout, the value of the actual parameter is copied
into the associated formal parameter;

At that moment value of the actual B=0 is copied to the formal B of the p2. After wait statement we resume p2 and execute "C <= A xor B" with formal B = 0. Let's suppose that at that moment the actual B outside of the p2 is changed to '1'. As I understand, after next "wait until rising_edge(clk);" statement in p2 when the actual B='1', formal B should still be '0' because it's the value copied from actual to formal during call of the p2..

In fact, the simulator behaves like it copies the actual B to the formal B each time it resumes p2 after wait statement.

IEEE Std 1076-2008

4.2 Subprogram declarations (2.1 -1993)

4.2.2 Formal parameters (2.1.1 -1993)


4.2.2.2 Constant and variable parameters (2.1.1.1 -1993)

For parameters of class constant or variable, only the values of the actual or formal are transferred into or out of the subprogram call. The manner of such transfers, and the accompanying access privileges that are granted for constant and variable parameters, are described in this subclause.
...
__

4.2.2.3 Signal parameters (2.1.1.2 -1993)

For a formal parameter of class signal, references to the signal, the driver of the signal, or both, are passed into the subprogram call.

For a signal parameter of mode in or inout, the actual signal is associated with the corresponding formal signal parameter at the start of each call. Thereafter, during the execution of the subprogram body, a reference to the formal signal parameter within an expression is equivalent to a reference to the actual signal.
...
__

Unlike constants or variables where the value of the actual is passed, a signal reference (name) points to the effective value of a signal.

Then I don't understand why the process

procedure p2(
signal clk : in std_logic;
signal A : in std_logic;
B : in std_logic;
signal C : out std_logic
) is
. . .
responds to changes of the constant B each cycle if the procedure was called
only once.

I'll again point out p2 is only called once, and as you note if B is class constant it won't change.

You could note that the value of '1' for B in your original question is a static value and not a reference. Passing it requires passing a value, in this case class constant.

If you want the value of B to change the actual needs to be a signal and the formal B needs to be class signal, with the actual passed as a reference (name).

If on the other hand if B is class constant and you're seeing the value of C change, it's in response to a change of value of signal A. Because B was originally defined as a static value of '1' at the beginning of this thread, C is effectively the inversion of A after the rising edge of clk.

If you think you're getting behavior inconsistent with the standard you could provide a minimal, complete and verifiable example as well as specify who's VHDL tool implementation you're using and it's version.

Providing a minimal, complete and verifiable example with a testbench would give the opportunity to point to specific simulation times and signal value changes.
 

Welcome to EDABoard.com

Sponsor

Back
Top