Discussion:
Constants and signals in procedures
(too old to reply)
Chris P
17 years ago
Permalink
I am trying to create a simulation environment in VHDL and I keep
running into this problem.

I have an register address map, which I'd like to maintain a single
copy of in a package file called "global_pkg". I define the address
values using constants, so I can use them in a case statement, which
requires static (i.e., non-signals) in the expressions.

constant ADDR_0 : std_logic_vector(15 downto 0) := X"0000";
constant ADDR_1 : std_logic_vector(15 downto 0) := X"0000";
constant ADDR_2 : std_logic_vector(15 downto 0) := X"0000";

Then I can reference these in my RTL:

case addr is
when ADDR_0 =>
reg_0 <= wrdata;
when ADDR_1 =>
reg_1 <= wrdata;

etc.

The trouble begins when I want to use procedures in my sim to access
these registers.

I have a procedure called "cpu_wr" that takes an address and data to
write:

procedure cpu_wr (
signal wr_addr : in std_logic_vector;
signal wr_data : in std_logic_vector) is
begin
-- Write the address registers
testbench.cpu_pkg.cpu_wr(
wr_addr,
wr_data);
wait for PERIOD_CLKCPU;
end procedure cpu_wr;


I'd like to call this procedure using the global address constants,
but VHDL doesn't allow a constant to be passed to a signal port on a
procedure:


cpu_wr(
work.global_pkg.ADDR_0,
wr_data);

My simulator gives me the following error:

Actual (constant "ADDR_0") for formal "wr_addr" is not a signal.

I've worked around this by maintaining two versions of the ADDR_*
paramaters; the constant version and the signal version:

constant ADDR_0 : std_logic_vector(15 downto 0) := X"0000";
signal ADDR_0_SIG : std_logic_vector(15 downto 0) := X"0000";

Is there another way to do this? It seems odd that VHDL won't allow a
constant of std_logic_vector to be passed to a signal of
std_logic_vector.

Thanks for your time.

-----------------------------------------------------------------------------
Mike Treseler
17 years ago
Permalink
Post by Chris P
I've worked around this by maintaining two versions of the ADDR_*
constant ADDR_0 : std_logic_vector(15 downto 0) := X"0000";
signal ADDR_0_SIG : std_logic_vector(15 downto 0) := X"0000";
Is there another way to do this?
Yes.
I use simulation procedures more to
collect repeated blocks of code
than to parametrize.

In this case, I can make things real
simple by declaring procedures like this,

procedure write_data is
begin
expect_v := random_byte_s;
address_s <= '0';
writedata_s <= std_logic_vector(expect_v);
tic;
toggle(write_stb_s);
end procedure write_data;

in the test process scope with few parameters.
For details, see the testbench here:
http://mysite.verizon.net/miketreseler/
Post by Chris P
It seems odd that VHDL won't allow a
constant of std_logic_vector to be passed to a signal of
std_logic_vector.
It makes sense.
You can pass a signal as a constant, but not vice-versa.
How could the process alter the value of a constant?

If you really want to use signal parameters
in a library, see the 'Remote Testbench Procedure'
example on the same page.

Good luck.

-- Mike Treseler
KJ
17 years ago
Permalink
Post by Chris P
I am trying to create a simulation environment in VHDL and I keep
running into this problem.
The trouble begins when I want to use procedures in my sim to access
these registers.
I have a procedure called "cpu_wr" that takes an address and data to
procedure cpu_wr (
signal wr_addr : in std_logic_vector;
signal wr_data : in std_logic_vector) is
begin
I'd like to call this procedure using the global address constants,
but VHDL doesn't allow a constant to be passed to a signal port on a
That's because a procedure 'could' use signal attributes (like 'event as an
example if you wanted to detect a rising edge). Constants don't have such
attributes. Even if your procedure doesn't happen to use these attributes,
the fact that it could means that if you really want to pass an input signal
into a procedure then you can't pass it a constant.
Post by Chris P
I've worked around this by maintaining two versions of the ADDR_*
Is there another way to do this? It seems odd that VHDL won't allow a
constant of std_logic_vector to be passed to a signal of
std_logic_vector.
Get rid of the 'signal' changing the procedure to this...

procedure cpu_wr (
wr_addr : in std_logic_vector;
wr_data : in std_logic_vector) is
...

Kevin Jennings
Jim Lewis
17 years ago
Permalink
Chris,
Post by KJ
Get rid of the 'signal' changing the procedure to this...
procedure cpu_wr (
wr_addr : in std_logic_vector;
wr_data : in std_logic_vector) is
Taking what Kevin said one step further, you can also put the
keyword constant in front of these:

procedure cpu_wr (
constant wr_addr : in std_logic_vector;
constant wr_data : in std_logic_vector) is

When you specify constant the object is passed by value.
For ports of mode in, the default class is constant, so
what it really means is the object is to be passed by
value (with normal programming language exceptions like
arrays which a programming language is permitted to
pass by reference).


Here are my subprogram parameter usage rules:

Class Usage Rules
Constant: Call with a value (any expression, signal, variable)
Signal: Call only with a signal object
Variable: Call only with a variable object

IN (Default Mode) procedures and functions
Use Signal for: Object that uses 'event or rising_edge(), or is
in a wait. All in objects from the DUT should be signal.
Value will change during execution if signal changes
Use Constant for: All other parameters (Default class for in mode)
Call contains a literal or an expression
Warning: Array values may be updated during execution

Out and InOut procedures only, functions only have inputs
Use Signal for: Objects to the DUT, Synthesis (my opinion)
Assign with <=
Use Variable for: Objects to the local process. (Default class for out and inout modes)
Assign with :=


Cheers,
Jim

P.S.
If you have your programs in a package, in addition to your current parameters,
you will need to add signal references to the objects you are reading and driving.
Jonathan Bromley
17 years ago
Permalink
Post by Chris P
procedure cpu_wr (
constant wr_addr : in std_logic_vector;
constant wr_data : in std_logic_vector) is
When you specify constant the object is passed by value.
Well, that would be nice. But it's not necessarily true...
Post by Chris P
For ports of mode in, the default class is constant, so
what it really means is the object is to be passed by
value (with normal programming language exceptions like
arrays which a programming language is permitted to
pass by reference).
Why, by any reasonable interpretation, is that a "normal
programming language exception"? I've long been mystified
by this horrible loophole in VHDL. Tools are *permitted*
to pass by reference, *even into a time-consuming procedure*.
Consequently, the semantics of such a procedure may change
depending on whether the tool chooses to perform this
"optimization". I've been screwed by this a couple of
times myself. Nowadays I force a copy by creating
a new constant inside the procedure, if there's any
risk of this causing trouble.
--
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
***@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
Continue reading on narkive:
Loading...