parameterisable functions in verilog 2005?

  • Thread starter Charles Gardiner
  • Start date
C

Charles Gardiner

Guest
Hi,

from the LRM , I see that verilog functions can have parameters. Can I
use such a parameter to specify a variable length vector as input parameter.

e.g. something like
function [MSB:0] whatever
(input [MSB:0] vval);
parameter MSB = 15;
begin
. . . .
end
endfunction


How would I call this from a module body? I don't see a single example
in the LRM.

What I am looking for is a way to write a generic function that I can
use on different vector widths. In VHDL I would just specify a
std_logic_vector as input parameter and use 'length, 'left, 'right etc.
to make it reusable for different vector widths

Thanks for any info,
Charles
 
On Sat, 09 Jan 2010 01:23:50 +0100, Charles Gardiner wrote:

from the LRM , I see that verilog functions can have parameters.
Parameters in Verilog are simply compile-time constants,
with the extra wrinkle that their values can be overridden
at elaboration. Any named scope in Verilog can have parameters
declared inside it, although many people are unaware of this
and use parameters only at the top level of a module -
where they act somewhat like VHDL generics. You can also
have "localparam", which is a parameter that cannot be
overridden.

Can I use such a parameter to specify a variable
length vector as input parameter.

e.g. something like
function [MSB:0] whatever
(input [MSB:0] vval);
parameter MSB = 15;
begin
No, because the parameter is fixed at elaboration time
and can't be altered thereafter. You can, of course,
have a module that contains a function, and create
many instances of that module (inst1, inst2, ...)
each with different parameter values; you then get
several instances of the function, with names like
inst1.f(), inst2.f().

How would I call this from a module body?
I hope it's clear from what I've said that you can't
change a function's parameter at the time you call
the function. Only the function's arguments can
be passed at call time.

What I am looking for is a way to write a generic function that I can
use on different vector widths. In VHDL I would just specify a
std_logic_vector as input parameter and use 'length, 'left, 'right etc.
to make it reusable for different vector widths
Yes. Suggestion: continue to use VHDL for RTL design;
it's just better in almost every way. Use Verilog or,
better, SystemVerilog for verification; it's more flexible.
And will someone please be kind enough to bind and gag me
temporarily until this thread has gone quiet, so I won't
be heard ranting about why VHDL is better for RTL.....
<mnfufflsnff, mmblbl>

[rant-mode=OFF] Of course, the right solution is NOT to
try to do literal translation of a VHDL design into
Verilog; instead, write your designs in a Verilog-ish
way from the outset. Yes, I know that's not much help.
--
Jonathan Bromley
 
I hope it's clear from what I've said that you can't
change a function's parameter at the time you call
the function. Only the function's arguments can
be passed at call time.
That's what I was afraid of. I just hoped I had overlooked something.

Yes. Suggestion: continue to use VHDL for RTL design;
it's just better in almost every way. Use Verilog or,
better, SystemVerilog for verification; it's more flexible.
And will someone please be kind enough to bind and gag me
temporarily until this thread has gone quiet, so I won't
be heard ranting about why VHDL is better for RTL.....
mnfufflsnff, mmblbl
I agree with you 100%. But customer "has always been using verilog" and
only has an (expensive) verilog simulator in his tool-park, so I'm stuck
with it for this project. I don't think even SV for design is an option
for him.

[rant-mode=OFF] Of course, the right solution is NOT to
try to do literal translation of a VHDL design into
Verilog; instead, write your designs in a Verilog-ish
way from the outset. Yes, I know that's not much help.
Essentially I'm adapting one of my existing VHDL solutions for him. So I
don't want to sit down in front of an empty screen and start again from
scratch. I have a Java tool which converts all my existing VHDL Entities
to modules and also does most of the instantiation stuff and some of the
signal to wire/reg etc. stuff (at least the really boring parts are out
of the way). For the rest, I just go through it VHDL block for VHDL
block converting to verilog manually. I have a substantial collection of
VHDL utility packages etc. Converting the ones I need to Verilog is the
real pain. I really miss the function overloading, records etc.from VHDL
and desperatly trying to avoid resorting to solutions like

function do_something_with_an_8bit_vector()
function do_same_thing_with_a_12bit_vector()
function do_same_thing_again_with_a_24bit_vector()

Aaaaaaagh!

Do people really have re-use concepts in verilog which come anywhere
close to what you can with VHDL (would be interested in links, if
available). I'm only starting on this and it already feels like the
difference between Sputnik (basic and essentially reliable but hard
break-your-neck landing in Kasachstan, crew could theoretically walk
home or take the bus/train etc.) and Apollo (complexer. Gentle landing
in the ocean pick 'em up with helicopter/aircraft carrier, play trumpets
when you actually get 'em back on hard ground).


Thanks Jonathan for the bad news ;)
 
On Sat, 09 Jan 2010 11:56:12 +0100, Charles Gardiner wrote:

I really miss the function overloading, records etc.from VHDL
The ability to put concatenations on the left of an
assignment makes it fairly easy to decompose a big
vector into meaningful pieces:

// Three fields of an 8-bit record
reg enable;
reg [1:0] mode;
reg [4:0] data;
// The whole thing
reg [7:0] control_register;
...
// put values into the record
control_register <= {enable, mode, data};
// pick 'em out again
{enable, mode, data} <= control_register;

And then <squirm> you can use macros to fake
record-like syntax:

`define enable_bits 7:7
`define mode_bits 6:5
`define data_bits 4:0
...
reg [`mode_bits] mode; // [6:5] is just as good as [1:0]
mode <= control_register[`mode_bits];

desperatly trying to avoid resorting to solutions like

function do_something_with_an_8bit_vector()
function do_same_thing_with_a_12bit_vector()
function do_same_thing_again_with_a_24bit_vector()

Aaaaaaagh!
There may be a glimmer of light at the end of the tunnel.

Generally, when you're using subtype-aware functions like
this in an RTL design, the function itself represents some
combinational logic block and each use of the function
will synthesize to a new instance of the combinational
logic. So, at the cost of smashing your beautiful single
clocked VHDL processes into several pieces, you can get
a similar effect by capturing each function as a separate
Verilog module, and instantiating it manually at the
point of use. The syntax is uglier, of course, because
it doesn't look like a function call. But in most cases
it does the job.

VHDL:
~~~~~
function tweak_vector (v: in std_logic_vector)
return std_logic_vector
is
constant n_bits: integer := v'length;
variable result: std_logic_vector(v'range);
begin
...
return result;
end;

Verilog:
~~~~~~~~
module tweak_vector
#(parameter n_bits = 8)
(input [n_bits-1:0] v, output [n_bits-1:0] y);
// do something useful here, you know the size now;
// you can even use a function:
function [n_bits-1:0] tweak(input [n_bits-1:0] x);
...
endfunction
assign y = tweak(v);
endmodule


VHDL:
~~~~~
signal narrow_input, narrow_result:
std_logic_vector(7 downto 0);
signal wide_input, wide_result:
std_logic_vector(15 downto 0);
...
process (clk) begin
if rising_edge(clk) then
-- Just call the function - it adapts
-- according to the vector you pass to it
wide_result <= tweak_vector(wide_input);
narrow_result <= tweak_vector(narrow_input);
end if;
end process

Verilog:
~~~~~~~~
wire [7:0] narrow_input, narrow_value;
reg [7:0] narrow_result;
wire [15:0] wide_input, wide_value;
reg [15:0] wide_result;

// Instances of "function" module
tweak_vector #(8) narrow_tweak(narrow_input, narrow_value);
tweak_vector #(15) wide_tweak(wide_input, wide_value);
// Registers
always @(posedge clk) begin
wide_result <= wide_value;
narrow_result <= narrow_value;
end

Note how, as everyone always points out, Verilog is SOOOOO much
less verbose and clearer than VHDL.... yeah.

difference between Sputnik (basic and essentially reliable but hard
break-your-neck landing in Kasachstan, crew could theoretically walk
home or take the bus/train etc.) and Apollo (complexer. Gentle landing
in the ocean pick 'em up with helicopter/aircraft carrier, play trumpets
when you actually get 'em back on hard ground).
LOL!
--
Jonathan Bromley
 
On Sat, 09 Jan 2010 13:08:36 +0100, Jonathan Bromley wrote:

wide_input, wide_value;
reg [15:0] wide_result;

// Instances of "function" module
tweak_vector #(8) narrow_tweak(narrow_input, narrow_value);
tweak_vector #(15) wide_tweak(wide_input, wide_value);
obvious typo: ... #(16) wide_tweak ...

oops
--
Jonathan Bromley
 
Charles Gardiner wrote:

Essentially I'm adapting one of my existing VHDL solutions for him. So I
don't want to sit down in front of an empty screen and start again from
scratch.
If I had to do a verilog project from scratch,
I would use MyHDL, which generates clean verilog synthesis code
using an open source Python package.

MyHDL codes much like vhdl.

-- Mike Treseler
 
On Jan 8, 7:23 pm, Charles Gardiner <inva...@invalid.invalid> wrote:
What I am looking for is a way to write a generic function that I can
use on different vector widths. In VHDL I would just specify a
std_logic_vector as input parameter and use 'length, 'left, 'right etc.
to make it reusable for different vector widths
And it would simulate much slower than Verilog, which requires all
vector widths to be known at compile time. There are trade-offs in
language design.

In many cases, the function for a narrow width would be the same as
applying the function for a wider width to the narrower operands. And
Verilog doesn't have VHDL's pickiness about exact vector width
matching. In such cases, I suspect the usual solution is to write the
function for the widest width being used, and call that function for
all vector widths. The arguments get implicitly extended, and the
result gets implicitly truncated. As long as the synthesis tool
optimizes away the logic for the upper bits when they are unused, you
are fine.
 

Welcome to EDABoard.com

Sponsor

Back
Top