Generate statement with varying signal width

M

Matt Longbrake

Guest
Is there any way to use a signal from a previous generate loop
iteration in a later iteration? As an example, say you were building
a variable length adder chain. The output of each adder is one bit
wider than the previous adder. The inelegant solution would be to
create an array of std_logic_vector where the width of each vector is
as wide as the widest needed. These vectors are just selected based
on the loop index. The problem with this is that you get all kinds of
unused signal warnings when you synthesize.

As an alternative approach, you could use the declarative region of
the generate loop to create a signal of the appropriate width for the
current iteration. Then, if you could somehow access that signal from
the next iteration you could have variable width signals and avoid a
bunch of warnings. Is something like this possible?
 
On Nov 4, 5:19 pm, Matt Longbrake <longb...@gmail.com> wrote:
Is there any way to use a signal from a previous generate loop
iteration in a later iteration?  As an example, say you were building
a variable length adder chain.  The output of each adder is one bit
wider than the previous adder.  The inelegant solution would be to
create an array of std_logic_vector where the width of each vector is
as wide as the widest needed.  These vectors are just selected based
on the loop index.  The problem with this is that you get all kinds of
unused signal warnings when you synthesize.

As an alternative approach, you could use the declarative region of
the generate loop to create a signal of the appropriate width for the
current iteration.  Then, if you could somehow access that signal from
the next iteration you could have variable width signals and avoid a
bunch of warnings.  Is something like this possible?
There are a number of things you can do. You can declare signals
outside the generate block and make an assignment based on generate
index:

signal a : std_logic_vector(7 downto 0);
signal b : std_logic;

g_test: for i in 0 to 7 generate
if ( i = 0 ) then
b <= a(i);
end if
end generate : g_test

The other option you are looking for is possible by declaring signals
within the generate for:

g_test: for i in 0 to 7 generate
signal x : std_logic_vector(i+2 downto 0);

x(i+2 downto 0) <= whatever;

end generate : g_test

In this case, you will have 8 x's defined as: x(2:0), x(3:0), ...
x(9:0). But only accessible within the generate block.

Cheers,
-- Amal
 
On Thu, 4 Nov 2010 14:19:31 -0700 (PDT), Matt Longbrake <longbrmb@gmail.com>
wrote:

Is there any way to use a signal from a previous generate loop
iteration in a later iteration? As an example, say you were building
a variable length adder chain. The output of each adder is one bit
wider than the previous adder.
You may be able to do this by nesting two generate statements, using the outer
one's loop variable as the inner one's control parameter.

I would be wary of encountering synthesis bugs, and check the results unusually
carefully.

Alternatively, realise that synthesis warnings are merely warnings, not errors,
and can safely be ignored if you understand and expect them. Synthesis tools
will do an excellent job of trimming fixed-width adders down to the size
required.

- Brian
 
 The inelegant solution would be to
create an array of std_logic_vector where the width of each vector is
as wide as the widest needed.  
Very inelegent, because unsigned/signed types are what you should be
using if you're doing arithmatic, not std_logic_vector.

But otherwise, you cannot access signals out of scope (as you were
suggesting with the 2nd paragraph). Personally, Id probably just
convert them to integers and back to unsigned/signed at the end (if I
really need to - why not just keep it an integer?) and then let the
synthesiser chose the correct bit length.
 
There are a number of things you can do.  You can declare signals
outside the generate block and make an assignment based on generate
index:

  signal a : std_logic_vector(7 downto 0);
  signal b : std_logic;

  g_test: for i in 0 to 7 generate
    if ( i = 0 ) then
      b <= a(i);
    end if
  end generate : g_test

The other option you are looking for is possible by declaring signals
within the generate for:

  g_test: for i in 0 to 7 generate
    signal x : std_logic_vector(i+2 downto 0);

    x(i+2 downto 0) <= whatever;

  end generate : g_test

In this case, you will have 8 x's defined as: x(2:0), x(3:0), ...
x(9:0).  But only accessible within the generate block.

Cheers,
-- Amal

Here's an example of what I meant with option 1 (probably not
syntactically correct):

type input_array is array(0 to 3) of signed(3 downto 0);
signal inputs : input_array;
type sum_array is array(0 to 4) of signed(7 downto 0);
signal sums : sum_array;
signal input : signed(3 downto 0);
signal output : signed(7 downto 0);

sums(0)(3 downto 0) <= inputs(0);
output <= sums(4);

abc: for i in 0 to 3 generate
adder: adder2
generic map( width => i+4)
port map( A => resize(inputs(i+1), i+4),
B => sums(i),
S => sums(i+1)(i+4 downto 0));
end generate;

I wrote that off the cuff, but the point is that the width of the
adder is easily adjusted by the generate statement, but I can't see
any way to adjust the size of the signals feeding them. The above
solution works, but you get unused signal warnings.

Alternatively, realise that synthesis warnings are merely warnings, not errors,
and can safely be ignored if you understand and expect them. Synthesis tools
will do an excellent job of trimming fixed-width adders down to the size
required.
I try to reduce the warnings as much as possible so that they actually
have some meaning when they happen, maybe I'm being to optimistic. I
just know that if I see a list of 1000 warnings, most of which can be
ignored, it's hard to find the one that's actually something that
needs fixing.
 
On Fri, 5 Nov 2010 11:11:51 -0700 (PDT), Matt Longbrake wrote:

I try to reduce the warnings as much as possible so that they actually
have some meaning when they happen
Sounds good.

I am not sure whether you got a clear response about whether you can
reference one generate block's signals from within another; the answer
is "no" (except by using VHDL-2008 cross-scope references or whatever
they're called).

The pragmatic solution is definitely to use interconnect vectors of
sufficient width. To remove the warnings, consider driving unused
bits of those vectors with a common value that preserves the
arithmetic meaning (typically zero-pad or sign-extend the MSBs).
Synthesis will strip out the common or constant logic. You may
get some note-level messages about that too, but that happens all
the time and there's not a lot we can do about it.
--
Jonathan Bromley
 
Hello guys,

i saw it is an old topic but i'm struggling with such a problem in these days and unfortunately i saw no answer to Matt's question.
The problem is this can be done with Verilog (at least > 2005). you can access variables declared in a generate statement using label.variable.
There are lots of recursive structures with variable data size, and i guess VHDL can not easily provide a way to describe them.
I tried to use hierarchinal names with VHDL 2008 but i was not able to find a way to reference a signal from another loop iteration.

here is an example in Verilog (sorry for no indentation)

genvar i;
generate
for(i=0;i<pipe_num;i=i+1)
begin:u
reg [width-1:0] sh_r;
if(i==0)
begin
always @ (posedge clk)
sh_r <= din;
end
else
begin
always @ (posedge clk)
sh_r <= u[i-1].sh_r;
end
end
endgenerate
assign dout = u[pipe_num-1].sh_r;

here the width is constant over iterations, but the example shows how you can access u[pipe_num-1] local register using u[pipe_num-1].sh_r

it would be really appreciated if someone would know how to do that, even in VHDL 2008.

Cheers,

Andrea
 

Welcome to EDABoard.com

Sponsor

Back
Top