driving "external" signals from a procedure

E

Eli Bendersky

Hello,

Let ARC be an architecture:

architecture ARC of MY_ENTITY is
signal foo: std_logic;
begin
end ARC;

Now, I want to write a procedure that drives this 'foo' signal, but
without having it as an out / inout port (hence I refer to it as
"external" to the procedure):

procedure drive_foo is
begin
foo <= '0';
end drive_foo;

If I place this procedure in the declarative section of the
architecture, the compiler (of Modelsim) complains that I can't drive
the signal from there. However, if I place it in the declarative
section of some process, everything is OK.

Why is this so ? What are the rules for operations allowed to an
'architecture level' procedure versus a 'process level' procedure ?

Tx
Eli
 
J

Jonathan Bromley

procedure drive_foo is
begin
foo <= '0';
end drive_foo;

If I place this procedure in the declarative section of the
architecture, the compiler (of Modelsim) complains that I can't drive
the signal from there. However, if I place it in the declarative
section of some process, everything is OK.

Why is this so ? What are the rules for operations allowed to an
'architecture level' procedure versus a 'process level' procedure ?

If the proc. is in a process, then it's (easily) possible to determine
that the process has a driver on 'foo'. If the procedure is anywhere
else, then there might be multiple drivers on 'foo' because the
procedure could be called from many different processes.
(Note the consequence: If you write a proc. in a process, and
that proc drives some signal, then the process has a driver
on that signal EVEN IF THE PROCEDURE IS NEVER CALLED.)

You can *read* signals in any procedure, provided the signal
declaration is visible to the procedure.

It's a VHDL language rule; ModelSim is definitely right.

As I've mentioned before here, my preferred solution to this is:

(1) put the procedure in a package (if it's worth abstracting
out of your process, it's worth packaging); of course,
you then need to port in/out not only any value arguments
required by the procedure, but also all the signals it will
manipulate;
(2) in each process that uses the procedure, provide a "proxy"
procedure that hooks the general-purpose procedure to
the right signals, and then passes other arguments on
to it. (This works just as well if the procedure was
declared in the architecture, but that makes less sense
to me.)

Like this:

package sig_driver is
procedure drive_sig (
value: in std_logic;
signal target: out std_logic );
end;
end;
package body sig_driver is
procedure drive_sig (
value: in std_logic;
signal target: out std_logic ) is
begin
target <= value;
end;
end;
......
use work.sig_driver.all;
entity e is end;
architecture a of e is
signal foo: std_logic;
signal bar: std_logic;
begin
drives_foo: process
procedure drive_sig(value: in std_logic) is
drive_sig(value, foo);
end;
begin -- process
...
drive_sig('1');
...
end process;
drives_bar: process
procedure drive_sig(value: in std_logic) is
drive_sig(value, bar);
end;
begin -- process
...
drive_sig('0');
...
end process;
....

Of course, you can give the "proxy" procedures
different names if you prefer.

I've found this to be extremely useful as a way of
packaging and deploying complex bus-functional model
procedures that have lots of signals that (in any
given process) are always the same for every call to
the procedure.

This is my all-time top reason for choosing Verilog
in preference to VHDL :)
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
J

Jim Lewis

Jonathan
....
I've found this to be extremely useful as a way of
packaging and deploying complex bus-functional model
procedures that have lots of signals that (in any
given process) are always the same for every call to
the procedure.

This is my all-time top reason for choosing Verilog
in preference to VHDL :)
So what would you change?

Jim
 
M

Mike Treseler

Eli said:
If I place this procedure in the declarative section of the
architecture, the compiler (of Modelsim) complains that I can't drive
the signal from there. However, if I place it in the declarative
section of some process, everything is OK.

Why is this so ?

Because only a process can drive
an architecture or port signal.
A procedure in process scope has direct
access.

-- Mike Treseler
 
E

Eli Bendersky

If the proc. is in a process, then it's (easily) possible to determine
that the process has a driver on 'foo'. If the procedure is anywhere
else, then there might be multiple drivers on 'foo' because the
procedure could be called from many different processes.
(Note the consequence: If you write a proc. in a process, and
that proc drives some signal, then the process has a driver
on that signal EVEN IF THE PROCEDURE IS NEVER CALLED.)

You can *read* signals in any procedure, provided the signal
declaration is visible to the procedure.

It's a VHDL language rule; ModelSim is definitely right.

As I've mentioned before here, my preferred solution to this is:

(1) put the procedure in a package (if it's worth abstracting
out of your process, it's worth packaging); of course,
you then need to port in/out not only any value arguments
required by the procedure, but also all the signals it will
manipulate;
(2) in each process that uses the procedure, provide a "proxy"
procedure that hooks the general-purpose procedure to
the right signals, and then passes other arguments on
to it. (This works just as well if the procedure was
declared in the architecture, but that makes less sense
to me.)

Like this:

package sig_driver is
procedure drive_sig (
value: in std_logic;
signal target: out std_logic );
end;
end;
package body sig_driver is
procedure drive_sig (
value: in std_logic;
signal target: out std_logic ) is
begin
target <= value;
end;
end;
.....
use work.sig_driver.all;
entity e is end;
architecture a of e is
signal foo: std_logic;
signal bar: std_logic;
begin
drives_foo: process
procedure drive_sig(value: in std_logic) is
drive_sig(value, foo);
end;
begin -- process
...
drive_sig('1');
...
end process;
drives_bar: process
procedure drive_sig(value: in std_logic) is
drive_sig(value, bar);
end;
begin -- process
...
drive_sig('0');
...
end process;
...

Of course, you can give the "proxy" procedures
different names if you prefer.

I've found this to be extremely useful as a way of
packaging and deploying complex bus-functional model
procedures that have lots of signals that (in any
given process) are always the same for every call to
the procedure.

Thanks for the tip.
This is my all-time top reason for choosing Verilog
in preference to VHDL :)
--

Indeed, it seems like a very annoying limitation. Why infer
"potential" drivers as opposed to "real" drivers. VHDL is strict
enough to detect with 100% certainty when a process actually drives a
signal, so why make life harder for designers ? I must be missing
something, but this looks like a big smelly hole.

Eli
 
M

Mike Treseler

Jonathan said:
This is my all-time top reason for choosing Verilog
in preference to VHDL :)

This is my top reason for using single process
entities and variables for vhdl synthesis.
I very much appreciate and use your remote
procedure idea in testbenches.

-- Mike Treseler
 
A

Andy

Jonathan
...> I've found this to be extremely useful as a way of


So what would you change?

Jim

Duh... Make it so a procedure can drive any signals within scope even
if the procedure is not declared in a process. How hard can it be?
Yes, the analysis/elaboration would have a little harder time figuring
out what drivers are on what signals, but come on, this isn't rocket
science!

Is there some known case where it would be impossible to implement
this (i.e. unable to determine a driver for a signal)?

Every concurrent invocation of such a procedure would create a driver
for any signal assigned within the process. Any process CALLING said
procedure would create a driver for any signal assigned within the
procedure (unless of course the process already drove the signal
outside the procedure).

Isn't this a clean way of creating protected access to a signal (via
package body declaration of said signal)? Drivers are not created
until elaboration, at which time the package body definition (and the
body of the procedure and any signals it drives) is known.

If we can add unconstrained arrays of unconstrained arrays, surely we
can do this!

Andy
 
J

Jim Lewis

Andy,
Anyone can complain about issues. Just fishing for a few
who can make some sensible proposals and help get a change
started. I know you are out there. :) I have alot on my
plate already. If you want things to happen, we need more
contributors.
Duh... Make it so a procedure can drive any signals within scope even
if the procedure is not declared in a process. How hard can it be?

Scope of where the signals currently are would imply the procedure
must be declared in the same file as the architecture, so I doubt
many would be happy with the solution.

Isn't this a clean way of creating protected access to a signal (via
package body declaration of said signal)? Drivers are not created
until elaboration, at which time the package body definition (and the
body of the procedure and any signals it drives) is known.
If you define signals in a package, then it makes it difficult to have
more than one instance of the design.

Not defining it in the package means that the signal referenced does
not exist - which is problematic.

I have been churning on it a little and wondered about declaring
"external" signals. Something like:

package foo_pkg is
procedure drive_foo ;
end package foo_pkg ;
package body foo_pkg is
procedure drive_foo is
external signal foo : out std_logic ; -- out indicating a driver
begin
foo <= '0';
end drive_foo;
end package body foo_pkg ;
end package body foo_pkg ;

If we can add unconstrained arrays of unconstrained arrays, surely we
can do this!
That was a wonderful success story. We had this on our list. One user
was very interested and I asked if he wanted to write the proposal.
14 pages later we had something good.
 
A

Andy

Andy,
Anyone can complain about issues. Just fishing for a few
who can make some sensible proposals and help get a change
started. I know you are out there. :) I have alot on my
plate already. If you want things to happen, we need more
contributors.


Scope of where the signals currently are would imply the procedure
must be declared in the same file as the architecture, so I doubt
many would be happy with the solution.


If you define signals in a package, then it makes it difficult to have
more than one instance of the design.

Not defining it in the package means that the signal referenced does
not exist - which is problematic.

I have been churning on it a little and wondered about declaring
"external" signals. Something like:

package foo_pkg is
procedure drive_foo ;
end package foo_pkg ;
package body foo_pkg is
procedure drive_foo is
external signal foo : out std_logic ; -- out indicating a driver
begin
foo <= '0';
end drive_foo;
end package body foo_pkg ;
end package body foo_pkg ;


That was a wonderful success story. We had this on our list. One user
was very interested and I asked if he wanted to write the proposal.
14 pages later we had something good.

Jim,

Yes, I realize that the driven signal must be within the scope of the
procedure declaration, not necessarily the scope of the procedure
invocation. I'm not sure I understand your comment about "same file as
the architecture". Since there is no "file" scope in vhdl; what
exactly did you have in mind (obviously I've missed something)?

Now that we have the concept of "new packages" (from generic types on
packages), it is easy to make one or more "my_packages" from a package
template that declares the signals and the prodedures that drive/
access them. Each "my_package" would create separate copies of the
signals and their driving procedures in the template. One need not
invoke a generic map on a "new" package, IIRC.

"external" would work, but seems really ugly to me. I'd rather not
open that Pandora's Box.

If all you need is a written proposal, let me know. Give me a template
for what you want (an existing proposal, etc.) and I can write
something up. I'm pretty sure you have my email (andy.d.jones...)

Thanks,
Andy
 
J

Jim Lewis

Andy
Yes, I realize that the driven signal must be within the scope of the
procedure declaration, not necessarily the scope of the procedure
invocation. I'm not sure I understand your comment about "same file as
the architecture". Since there is no "file" scope in vhdl; what
exactly did you have in mind (obviously I've missed something)?
Obviously my mind was not fully switched on. :) I ment within
the architecture

If all you need is a written proposal, let me know. Give me a template
for what you want (an existing proposal, etc.) and I can write
something up. I'm pretty sure you have my email (andy.d.jones...)
I bounced it off a couple of group members and Peter
came up with something that I somewhat like. I have included
it below.

Cheers,
Jim

...... cutting from Peter's email ......

So can we (and should we) allow for some form of implicit association of an
actual? This use-case reminds me of the mechanism we have for default
association of an actual generic subprogram if the declaration of the formal
includes <> as the default. For example, if we write

generic ( ...; function f ( x : T ) return T is <>; ... );

Then we can omit an actual for f in the generic map. In that case, the
implicit actual is a function named f (if any) with conforming profile that
is visible at the place of the generic map.

We could write the function in the package as

procedure drive_foo(val : std_logic; signal foo : std_logic := <>) is
begin
foo <= val ;
end drive_foo;

Then call it in an architecture:

architecture ARC of MY_ENTITY is
signal foo: std_logic;
begin
drive_foo_proc : process
begin
wait until nReset = '1' and rising_edge(Clk) ;
drive_foo('0') ;
wait until Clk = '1' ;
drive_foo('1') ;
wait until Clk = '1' ;
...
end process drive_foo_proc ;
end ARC;

In the call, the signal foo is visible at the place of each call, and so is
implicitly associated with the parameter foo. This is just parameter
association with the normal semantics.

.................
 
J

Jonathan Bromley

[the ability to call procedures in a module from
outside that module]
So what would you change?

I'm sure I've ranted about this before.... I want
to be able to build modules (entity/architecture
pairs) that can have PROCEDURAL ports as well as
signal ports.

Ada already shows us how to do this in perfect
safety with its task/entry mechanism. Think of
a VHDL process as an Ada task that is automatically
started at time 0. Allow that process to wait on
an entry, i.e. stall until some external agent
calls the entry. The process then makes a
rendezvous with the external agent. Parameters
can be passed to and fro at the moment of the
rendezvous. Once the rendezvous has occurred,
the agent (caller) thread is in control but is
running code that's defined in the process (callee);
this code can introduce delays if it wishes, before
letting go of the rendezvous so that caller and callee
again proceed on their merry way independently. There
can be more than one entry into a task if you wish.

The challenge added by VHDL is the need to make the
entity have ports that are procedure (entry) prototypes
rather than signals. I'm not exactly sure how that
would work out in practice, although various pre-existing
academic efforts at extensions to VHDL have provided
something similar so it's clear it can be done. I don't
really care too much what the syntax looks like, as long
as I get the behaviour I want with the robust semantics
that VHDL rightly demands.

For me (and I emphasise that this is a personal view)
enhancements such as automatic promotion of std_logic
to boolean and the standardization of additional
arithmetic packages are just handy sugaring. It's
the lack of cross-module referencing that is the
Achilles heel of VHDL, and for my $0.02-worth that's
the place where you should be putting all your effort.

For all I know, you may already be doing all of this.
I've just been too busy with other things to follow
the current VHDL enhancement efforts, so I simply
don't know. If you are, then please accept my
apologies for the moan and my best wishes for your
success.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
J

Jim Lewis

Jonathan
I'm sure I've ranted about this before.... I want
to be able to build modules (entity/architecture
pairs) that can have PROCEDURAL ports as well as
signal ports.

Ada already shows us how to do this in perfect
safety with its task/entry mechanism.
> . . .
I will have to look at that some more.

See the other thread for another potential solution.
Not beautiful, but it does get the job in an easy,
effective manner.

For me (and I emphasise that this is a personal view)
enhancements such as automatic promotion of std_logic
to boolean and the standardization of additional
arithmetic packages are just handy sugaring.
Don't think I would enjoy doing fixed and floating
point without some language support.

A few other things I am excited about:
Type and Subprogram generics
Generics on Packages
Arrays of unconstrained arrays
PSL within VHDL
> It's
the lack of cross-module referencing that is the
Achilles heel of VHDL, and for my $0.02-worth that's
the place where you should be putting all your effort.
Did this one also in the Accellera 1076-2006-D3.0 standard.

If you are, then please accept my
apologies for the moan and my best wishes for your
success.
Did you think my skin that thin? I did not catch an
insult in there - did you intend one?

Cheers,
Jim
SynthWorks VHDL Training
www.synthworks.com
 
A

Andy

Andy> Yes, I realize that the driven signal must be within the scope of the

Obviously my mind was not fully switched on. :) I ment within
the architecture


I bounced it off a couple of group members and Peter
came up with something that I somewhat like. I have included
it below.

Cheers,
Jim

..... cutting from Peter's email ......

So can we (and should we) allow for some form of implicit association of an
actual? This use-case reminds me of the mechanism we have for default
association of an actual generic subprogram if the declaration of the formal
includes <> as the default. For example, if we write

generic ( ...; function f ( x : T ) return T is <>; ... );

Then we can omit an actual for f in the generic map. In that case, the
implicit actual is a function named f (if any) with conforming profile that
is visible at the place of the generic map.

We could write the function in the package as

procedure drive_foo(val : std_logic; signal foo : std_logic := <>) is
begin
foo <= val ;
end drive_foo;

Then call it in an architecture:

architecture ARC of MY_ENTITY is
signal foo: std_logic;
begin
drive_foo_proc : process
begin
wait until nReset = '1' and rising_edge(Clk) ;
drive_foo('0') ;
wait until Clk = '1' ;
drive_foo('1') ;
wait until Clk = '1' ;
...
end process drive_foo_proc ;
end ARC;

In the call, the signal foo is visible at the place of each call, and so is
implicitly associated with the parameter foo. This is just parameter
association with the normal semantics.

................

Jim,

That looks like a very useful feature, and I think I like it better
than the "external" keyword.

But I cannot for the life of me figure out how we could justify that
without first (or also) "fixing" the lowly procedure in the first
place. AFAIK, the only reason for the prohibition on driving signals
not passed as arguments was because it was "hard to do". Well if
something like what Peter is proposing can be done, then that old
argument just won't hunt anymore.

This procedure limitation just seems like one of those ugly little
backwater issues that it is high time we fixed.

Before we put a shiny new ring on the king's finger, somebody ought to
patch the holes in his robe. If we're not careful we're going to have
a language made up of arcane coding methods that were only ever half
developed, and new methods that really sing, all in one language.
IMHO, that's pretty ugly.

Please don't take this the wrong way. I applaud almost all of the sexy
new features you and others are working on to enhance VHDL. But
there's some termites in the floor beams that need to be taken care of
too.

Andy
 
J

Jim Lewis

Andy,
That looks like a very useful feature, and I think I like it better
than the "external" keyword.

But I cannot for the life of me figure out how we could justify that
without first (or also) "fixing" the lowly procedure in the first
place. AFAIK, the only reason for the prohibition on driving signals
not passed as arguments was because it was "hard to do". Well if
something like what Peter is proposing can be done, then that old
argument just won't hunt anymore.
I can't speak to what is easy and what is hard as
I find myself surprised often.

In the proposed solution, it clearly identifies external
signals that are driven and ones that are read only.
As such, it a much simpler problem to solve than the more
general case of "fixing" the lowly procedure.
But there's some termites in the floor beams
that need to be taken care of too.
There is so much to do that I try to do things on
a priority basis. I think this is good as vendors
are going to work their way through a standard in a
given order. I would rather give them my highest
priority items to work on first and then fix the other
problems later.

Cheers,
Jim
 
A

Andy

In the proposed solution, it clearly identifies external
signals that are driven and ones that are read only.
As such, it a much simpler problem to solve than the more
general case of "fixing" the lowly procedure.

Exactly the same problem exists with respect to determining read-only
vs driven signals in processes, and that has been handled without any
problems since before I started using VHDL (~17 years ago). That is
not a problem.

And the new syntax would not even give you access to signals in
packages (or new invocations thereof) unless the signal was also
visible (declared in the package rather than the body).

I agree with the need for priorities in the face of limited resources.
I just believe that priorities ought to be on "fixing" what we have
now, before or at least concurrent with adding new features.

Andy
 
J

Jonathan Bromley

Jim
See the other thread for another potential solution.

It doesn't really answer my concerns, but it's a
very interesting idea.
A few other things I am excited about:
Type and Subprogram generics
Generics on Packages
Arrays of unconstrained arrays
PSL within VHDL

Thumbs-up to all these. I didn't know you had done
something about subprogram generics, though I was
vaguely aware that there was ongoing work on the
other items.
Did this one also in the Accellera 1076-2006-D3.0 standard.

OK. Time for me to deliver on my many-months-old promise,
and try to catch up with what you guys have been doing!
Did you think my skin that thin? I did not catch an
insult in there - did you intend one?

Certainly not. I am genuinely unhappy that I've not been
able to give any attention at all to the recent efforts to
enhance VHDL, and I genuinely wish you all the best with them.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top