Can a parameter be passed to a function

N

nv

Guest
Is it possible in verilog2k or system verilog to pass a parameter to a
function that can be used to determine the size of the other parameters
being passed to it. Can this be synthesized?.

Example

function [size :0] add;
input [31:0] size;
input [(size-1):0] A;
input [(size-1):0] B;

add = A + B;

endfunction
 
nv wrote:
Is it possible in verilog2k or system verilog to pass a parameter to a
function that can be used to determine the size of the other parameters
being passed to it.
No. Not only couldn't it be synthesized, but it couldn't be simulated
efficiently either. Sizes must be compile-time constants. It would be
possible to extend the language to allow instantiating tasks and
functions with a particular constant width for each particular call.
Behind the scenes this would result in creating a different task or
function instance for each call, each with its own code and static
data. If equivalently parameterized calls were allowed to share
static data, there would need to be a precise definition of what
constituted equivalence, since the sharing would have visible effects.

It is almost possible to do this kind of thing for yourself, using
generates. You could use a generate-for-loop to essentially create an
array of tasks or functions with different widths. Then each call
could reference the one of the appropriate width. However,
Verilog-2001 did not allow task and function declarations inside
generate loops, apparently because nobody considered that the
declarations in different iterations could be different from each other
and therefore useful. I think this was relaxed in Verilog-2005, and
some implementations may allow it.

I expect that the usual way of dealing with this kind of thing is to
declare the function to be as wide as the widest arguments that you
plan to pass. Then you can rely on implicit width conversions when
passing narrower values to it, and assigning the return value to a
narrower result. Synthesis tools may be able to optimize away the
unused parts of the intermediate calculations.
 
sharp@cadence.com wrote:
nv wrote:
Is it possible in verilog2k or system verilog to pass a parameter to a
function that can be used to determine the size of the other parameters
being passed to it.

No. Not only couldn't it be synthesized, but it couldn't be simulated
efficiently either. Sizes must be compile-time constants.
Sorry, but if you are talking about vector sizes then I think vector
sizes are elaboration time constant.

And, also we can use parameters (elab time const.) for declaring vector
sizes.

The example given by NV is not clear to me, there "size" is used as
some constant to declare vector size of function return type and same
identifier is declared as input port inside function. It is illegal.

Correct me if I am missing something here.

- Mukesh
 
Muks wrote:
No. Not only couldn't it be synthesized, but it couldn't be simulated
efficiently either. Sizes must be compile-time constants.

Sorry, but if you are talking about vector sizes then I think vector
sizes are elaboration time constant.
You are correct, and so am I. It is a matter of terminology. I am
using the term "compile" in the general sense, to refer to all the
steps of compiling a design before simulation, including the
elaboration step. You may be used to it being used for just the
parsing step before elaboration.


The example given by NV is not clear to me, there "size" is used as
some constant to declare vector size of function return type and same
identifier is declared as input port inside function. It is illegal.
You are correct that the example is illegal. It is trying to pass the
size in as an argument to the function. Some confusion may result
because the term "parameter" is often used in other languages to mean
an argument to a subroutine, which is not a compile-time (or
elaboration-time, if you prefer) constant. In Verilog, the term
"parameter" means a specific kind of compile-time constant. Vector
sizes can be set by parameters, but not by arguments. And parameter
values are not passed at runtime.
 
Thanks for your responses. The function I declared here as an example I
know is illegal. All I was
trying was to determine if there is a way to parametrize the data going
in and coming out of a function and determine these sizes at runtime
rather than be a constant.

If these functions are going to be used in several files then I could
create an include file with the largest value and extract only the bits
that I need as suggested by one of you and the synthesis tools to my
knowledge will optomize it out although with annoying warnings message
which will need to be filtered.

The only other way to do this is to declare them as modules and
instantiate them with different paramters.

Regards

NV

sharp@cadence.com wrote:
Muks wrote:
No. Not only couldn't it be synthesized, but it couldn't be simulated
efficiently either. Sizes must be compile-time constants.

Sorry, but if you are talking about vector sizes then I think vector
sizes are elaboration time constant.

You are correct, and so am I. It is a matter of terminology. I am
using the term "compile" in the general sense, to refer to all the
steps of compiling a design before simulation, including the
elaboration step. You may be used to it being used for just the
parsing step before elaboration.


The example given by NV is not clear to me, there "size" is used as
some constant to declare vector size of function return type and same
identifier is declared as input port inside function. It is illegal.

You are correct that the example is illegal. It is trying to pass the
size in as an argument to the function. Some confusion may result
because the term "parameter" is often used in other languages to mean
an argument to a subroutine, which is not a compile-time (or
elaboration-time, if you prefer) constant. In Verilog, the term
"parameter" means a specific kind of compile-time constant. Vector
sizes can be set by parameters, but not by arguments. And parameter
values are not passed at runtime.
 
nv <noel_vargese@yahoo.com> wrote:

Thanks for your responses. The function I declared here as an example I
know is illegal. All I was
trying was to determine if there is a way to parametrize the data going
in and coming out of a function and determine these sizes at runtime
rather than be a constant.
Your initial question asked if a parameter could be used
to determine the size of other parameters.

What you seem to now be asking is if a parameter could be
used to determine the size of ports. This is much simpler
to do.

Steve
 
Hi Steve,

My intent is to call the function several times in a module but with
different sizes for the input parameters which in turn will return a
value of a different size. I was hoping either a parameter could be
passed to it or the function could be called with a different value for
its internal parameters (like a module being instantiated with
different parameters). I dont think this can be done but if you know of
a method please advise.

NV
Steve Pope wrote:
nv <noel_vargese@yahoo.com> wrote:

Thanks for your responses. The function I declared here as an example I
know is illegal. All I was
trying was to determine if there is a way to parametrize the data going
in and coming out of a function and determine these sizes at runtime
rather than be a constant.

Your initial question asked if a parameter could be used
to determine the size of other parameters.

What you seem to now be asking is if a parameter could be
used to determine the size of ports. This is much simpler
to do.

Steve
 
You have to be careful with Verilog terminology. It is different from
standard programming language terminology. I got caught on that
myself several times. Please excuse the long tour, but I will
eventually get to parameters and ports.

The basic unit of computation in Verilog is a "module" and not a
"function". A module represents a logic piece of chip (circuit/
silicon) functionality. When designing a circuit, one wants to design
a set of muodules and their interconnections.

There are also functions in Verilog, but they do not necessarily
correspond to bits of circuitry. They are simply ways of writing
complex expressions (and naming them). A synthesizer is quite likely
going to expand all functions inline within a module and layout that
circuit. Verilog also has a concept similar to a suroutine, called a
task. In general, one should assume that tasks are not synthesizable
and should not be used to represent bits of circuitry.

Next, modules are not called, they are instantiated. The syntax of an
instantiation looks just like a call statement, except that it is not
embedded in some flow-of-control construct--it sits by itself as a
standalone statements in some other module. The importants of that is
that you don't get control of when a module runs, it runs all the time
(or perhaps better to say when it wants to, based on how the module
schedules events). That is you cannot say, if this is true, run this
module otherwise run this other module. The modules run and compute
their outputs on their own schedule. You can select which results you
want to read, when you want to read them, but you can't tell a module,
run now.

Another key difference between instantiation and normal language
function calls, is that instantiations cannot be recursive. You
should imagine the instantiations as a tree starting as some root
(called the top-level module). That tree has to be statically known
during a part of the Verilog compilation called elaboration. This is
because that actual hardware has to be layed out on a chip (or a
circuit board or some other physical representation) and that layout
must be known when the chip is actually created. Recursive modules
make laying out that tree computationally inconvenient, so the
language doesn't support them.

Ok, now about how one connects modules together, i.e. ports.
Remember, that a module instantiation looks like a subroutine call.
The things which would be subroutine arguments are called port
connections (if I recall the term correctly). The things inside the
module that look like "parameter" declarations are called ports (and
port declarations). You can do the same things with ports and port
connections, that one can do with subroutine parameters and arguments.
That is, you can pass values into a module and out of it, and even
have ports that connect both ways (inouts).

Now, ports have sizes and these sizes are configurable. And one of
the mechanisms to configure the sizes of those ports are refered to in
Verilog terms as "parameters" and they are declared with parameter
declarations. You should think of a parameter as a configuration
constant. In the parameter declaration, you will give that constant a
value (say 16) and that will be its default value. Now, you can use
that parameter as a constant in places where you need a 16, for
instance in the size (bit spec) of a port. If you do that
consistently in your module, you can then say I want a different copy
of the module where the port isn't 16 bits wide, but is 32 (or 8 or 6
or 54327) bits wide. Then, you can instantiate that module to
describe different bits of circuitry that meet your designs needs.

Notice that this meaning of parameter is not related to function call
parameters as one uses the term in other programming languages. It is
a Verilog specific term for how one configures modules to represent
circuits with different sizes of ports (and internal nets).

Now, you may implement you module as a function on the inside, but it
is the module and not the function that is the basic unit of work in
Verilog. Note, depending on your synthesizer you may (but more likely
may not) implement that function recursively. You can even size the
function arguments based on the parameter declarations in the module.
But, remember that a function in verilog is just a way of representing
a complex expression and it is the module that actually represents
some circuitry.

It is my belief that understanding and using these terms correctly,
will get you better insight into Verilog circuit design and better
help on this newsgroup. From what I've seen, Verilog looks
seductively like a programming language, but approaching Verilog as a
programming language and not thinking about circuits as circuits leads
one into errors in conceptualization.

Hope this helps,
-Chris

*****************************************************************************
Chris Clark Internet : compres@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
23 Bailey Rd voice : (508) 435-5016
Berlin, MA 01503 USA fax : (978) 838-0263 (24 hours)
------------------------------------------------------------------------------
 
I wished I'd read this before my last explanation, not that I regret
what I wrote, but I could have answer your question more directly. If
you want a function with resizable "parameters" (arguments), put the
function in its own module and use parameters (the Verilog meaning of
the term) to module to control the size of the function arguments,
return value, etc. Then, instantiate the module as many times as need
with the parameter overrides to get copies of the functions with the
different desired widths. Finally, refer to the function using a
heirarchical name using the istantiation which specifies the correct
width, something like the code shown below (correcting any errors I
may have made).

module func_wrap(); // no ports needed
parameter width = 8;
parameter high_bit = width - 1; // beter use local_param in 2001
function [bigh_bit:0] func;
input [high_bit:0] in;
func = in + 1;
endfunction
endmodule

module use_func
....
func_wrap #(8) func8();
func_wrap #(16) func16();

....

wire [7:0] x, y = func8.func( x ); // use an 8 bit copy of func
wire [15:0] a, b = func16.func( a );; // use a 16 bit copy of func

....
endmodule

Hope this helps,
-Chris

*****************************************************************************
Chris Clark Internet : compres@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
23 Bailey Rd voice : (508) 435-5016
Berlin, MA 01503 USA fax : (978) 838-0263 (24 hours)
------------------------------------------------------------------------------
 

Welcome to EDABoard.com

Sponsor

Back
Top