Type conversion (to unsigned) can not have aggregate operand

O

Olaf

Guest
Hello,

I'm writing a loadable counter. To support different clocks I wrote a
function to determine the reload value:

entity ...
generic (
RESET_ACTIVE : std_ulogic := '1';
T_CLK : time := 20 ns); -- 50 MHz

port (
...

architecture ...

-- ceil(log2(T_MAX / T_CLK))-1 downto 0
signal delay_count : unsigned(19 downto 0);
signal enable_delay : std_ulogic;
signal delay_done : std_ulogic;

procedure set_delay (constant delay : time) is
constant value : natural := delay / T_CLK;
begin
assert (delay > T_CLK)
report "delay smaller than clock cycle!!"
severity WARNING;
assert (value < 2**delay_count'length - 1)
report "Error: count vector range doesn't match divider integer
range!"
severity error;
delay_count <= unsigned(value, delay_count'length); --XXX
end procedure;

begin ...

which results in the error:

** Error: Cannot drive signal 'delay_count' from this subprogram.
** Error: Type conversion (to unsigned) can not have aggregate operand.

value is an aggregate operand? It is constant, or what's wrong?

Thanks
Olaf
 
** Error: Cannot drive signal 'delay_count' from this subprogram.
** Error: Type conversion (to unsigned) can not have aggregate operand.

value is an aggregate operand? It is constant, or what's wrong?
Oh dear ... should be to_unsigned() ;-)

Anyway, the error

Cannot drive signal 'delay_count' from this subprogram.

is still here. Maybe I have to put this function inside a process but why?

Thanks,
Olaf
 
On Sun, 10 Jun 2007 10:18:51 +0200, Olaf <olaf@mdcc.de> wrote:

** Error: Cannot drive signal 'delay_count' from this subprogram.

Anyway, the error

Cannot drive signal 'delay_count' from this subprogram.

is still here. Maybe I have to put this function inside a process but why?
We've had this discussion here quite recently...
with you? someone else? can't remember.

Anyways, here's the deal: If a procedure wishes to
drive a signal, then EITHER the procedure must be
declared in a process in the same architecture that
declares the signal, OR the signal must be an output
or inout parameter of the procedure. This restriction
is related to the way VHDL determines the
set of drivers on a signal at elaboration time.

The practical consequences of this are roughly:

- It's generally useless to put procedures in an
architecture. Such procedures must have all their
driven signals as parameters, and therefore it's
probably much more useful to put the procedure into
a package so that it can be re-used elsewhere.

- It's OK to put procedures in a process, where they
can directly drive a signal, but of course this makes
sense only for procedures that are highly specialised
for a particular process and won't be re-used elsewhere.

As I have indicated many times before, there is a good
compromise available: Create a truly general-purpose
procedure, with its various signal parameters, in a
package; and then, for each process that intends to
use that procedure, create a wrapper procedure in the
process that simply calls the package procedure but
has fewer parameters because all the correct signals
are supplied by the wrapper. Here's an example:

package signal_utilities;
procedure toggle_pulse (
signal s: inout std_logic;
t: in time );
end;
package body signal_utilities;
procedure toggle_pulse (
signal s: inout std_logic;
t: in time ) is
begin
s <= not s;
wait for t;
s <= not s;
end;
end;

OK, nice procedure, but now whenever I use it I must supply
the appropriate signal as a parameter. So....

use work.signal_utilities.all;
...
architecture A of E is
signal P, Q: std_logic;
begin
P_sig_gen: process
procedure toggle_pulse (t: in time) is
begin
toggle_pulse(t, P); -- specialise toggle_pulse for signal P
end;
begin
...
toggle_pulse (5 ns); -- calls toggle_pulse(5ns, P);
...
toggle_pulse (10 ns);
...
end process;

For complicated bus-cycle generator procedures that drive
large numbers of signals, this is a big simplification of
typical process code.
--
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
jonathan.bromley@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.
 
On Sun, 10 Jun 2007 10:18:51 +0200, Olaf <olaf@mdcc.de> wrote:

** Error: Cannot drive signal 'delay_count' from this subprogram.
** Error: Type conversion (to unsigned) can not have aggregate operand.

value is an aggregate operand? It is constant, or what's wrong?

Oh dear ... should be to_unsigned() ;-)

Anyway, the error

Cannot drive signal 'delay_count' from this subprogram.

is still here. Maybe I have to put this function inside a process but why?
Because processes drive signals? That is, signals are the primary means
of inter-process communication.

If you don't want to make the procedure local to a process (which gives
it access to the process's signal drivers), you can give the procedure a
new signal argument, of mode "out", and pass "delay_count" as the
argument when you call the procedure.

- Brian
 
Jonathan Bromley wrote:

The practical consequences of this are roughly:
- It's generally useless to put procedures in an
architecture.
Yes. If there is proper use, I have yet to discover it.

- It's OK to put procedures in a process, where they
can directly drive a signal, but of course this makes
sense only for procedures that are highly specialised
for a particular process and won't be re-used elsewhere.
It also makes sense if I like to hide the details
of a complex register variable update with a call like
"update_error_counters;" after the process BEGIN.

The procedure body may end up
being called more than once,
but even if it isn't, I like having the option
of trying out different implementations without
having to comment out blocks of code.

For example, I could copy the
"update_error_counters" body
and rename one
"update_error_counters_proto"
then fearlessly update
and test the original routine.

As I have indicated many times before, there is a good
compromise available: Create a truly general-purpose
procedure, with its various signal parameters, in a
package; and then, for each process that intends to
use that procedure, create a wrapper procedure in the
process that simply calls the package procedure but
has fewer parameters because all the correct signals
are supplied by the wrapper. Here's an example:
....

I find this idea of yours
especially useful in my testbenches.
For example
http://home.comcast.net/~mike_treseler/proc_overload.vhd

For complicated bus-cycle generator procedures that drive
large numbers of signals, this is a big simplification of
typical process code.
Yes indeed. Thanks for the posting.

-- Mike Treseler
 

Welcome to EDABoard.com

Sponsor

Back
Top