recursive description with generate and processes

J

Joerg Ritter

hi,
please consider the following recusive description of a component
calculating the flags 'a', 'p' and 'g' of an Ladner/Fisher-like adder.
This code is working and was validated using a VHDL-Simulator.

Lets exchange the part

POSTPROCESSING_B:
for i in n/2-1 downto 0 generate
flag_out(2*i+1) <= f_rec_out(i);
end generate;

with a process like this

process(f_rec_out)
begin
for i in n/2-1 downto 0 loop
flag_out(2*i+1) <= f_rec_out(i);
end loop;
end

This results in more then one drivers per signal for flag_out. It seems
to be, that the process doesnt use the flag_out signal at the specific
recursion level, instead assigns always to the port flag_out at the top
level.
Could anybody give a meaningful explanation ?

Thanks
Joerg




library IEEE;
library WORK;
use IEEE.std_logic_1164.all;
use WORK.apg_arithmetic.all;

entity flag_comp is
generic (n: positive);
port
(flag_in: in apg_vector (n-1 downto 0);
flag_out: out apg_vector (n-1 downto 0));
end flag_baustein;

architecture parallel_adder of flag_comp is
component con
port (l, r: in apgType;
flag_out: out apgType);
end component;
component flag_comp
generic (n: positive);
port (flag_in: in apg_vector (n-1 downto 0);
flag_out: out apg_vector (n-1 downto 0));
end component;
begin
rekursion: if n>2 generate
signal f_rec_out,f_rec_in: apg_vector (n/2-1 downto 0);
begin
PREPROCESSING:
for i in n/2-1 downto 0 generate
CON_CELL_1: con
port map (l => flag_in(2*i+1), r => flag_in(2*i),
flag_out => f_rec_in(i));
end generate;
RECURSIVE_CELL: flag_comp
generic map (n/2)
port map (flag_in => f_rec_in, flag_out => f_rec_out);
POSTPROCESSING_COMP:
for i in n/2-2 downto 0 generate
CON_CELL_2: con
port map (l => flag_in(2*i+2), r => f_rec_out(i) ,
flag_out => flag_out(2*i+2));
end generate;
POSTPROCESSING_B:
for i in n/2-1 downto 0 generate
flag_out(2*i+1) <= f_rec_out(i);
end generate;
flag_out(0) <= flag_in(0);
end generate;
stop_recursion2:
if n=2 generate
CON_CELL_3: con
port map (l => flag_in(1), r => flag_in(0),
flag_out => flag_out(1));
flag_out(0) <= flag_in(0);
end generate;
stop_recursion1: if n=1 generate
flag_out(0) <= flag_in(0);
end generate;
end parallel_adder;
 
M

Mike Treseler

Joerg said:
This code is working and was validated using a VHDL-Simulator.

Lets exchange the part

POSTPROCESSING_B:
for i in n/2-1 downto 0 generate
flag_out(2*i+1) <= f_rec_out(i);
end generate;

with a process like this

process(f_rec_out)
begin
for i in n/2-1 downto 0 loop
flag_out(2*i+1) <= f_rec_out(i);
end loop;
end

This results in more then one drivers per signal for flag_out. It seems
to be, that the process doesnt use the flag_out signal at the specific
recursion level, instead assigns always to the port flag_out at the top
level.
Could anybody give a meaningful explanation ?

Hard to say without seeing the apg_arithmetic package.
I looks like flag_out is in architecture scope
in both cases. The problem may be an index overlap
of some sort.

Note also:
end flag_baustein; -- syntax error


-- Mike Treseler
 
J

Joerg Ritter

Mike Treseler wrote:
enclosed please find the used apg package and the corrected code for the
e/a flag_comp.
Hard to say without seeing the apg_arithmetic package.
I looks like flag_out is in architecture scope
in both cases. The problem may be an index overlap
of some sort.

as you can see in the above statements, the two loops are identically.
One within a process, one with an generate statement.
The first one is working, so there is no index overlap/mismatch.

thanks
Joerg

-------------------------------------------------------
library IEEE;
library WORK;
use IEEE.std_logic_1164.all;
use WORK.apg_arithmetic.all;

entity flag_comp is
generic (n: positive);
port
(flag_in: in apg_vector (n-1 downto 0);
flag_out: out apg_vector (n-1 downto 0));
end flag_comp;

architecture parallel_adder of flag_comp is
component con
port (l, r: in apgType;
flag_out: out apgType);
end component;
component flag_comp
generic (n: positive);
port (flag_in: in apg_vector (n-1 downto 0);
flag_out: out apg_vector (n-1 downto 0));
end component;
begin
rekursion: if n>2 generate
signal f_rec_out,f_rec_in: apg_vector (n/2-1 downto 0);
begin
PREPROCESSING:
for i in n/2-1 downto 0 generate
CON_CELL_1: con
port map (l => flag_in(2*i+1), r => flag_in(2*i),
flag_out => f_rec_in(i));
end generate;
RECURSIVE_CELL: flag_comp
generic map (n/2)
port map (flag_in => f_rec_in, flag_out => f_rec_out);
POSTPROCESSING_COMP:
for i in n/2-2 downto 0 generate
CON_CELL_2: con
port map (l => flag_in(2*i+2), r => f_rec_out(i) ,
flag_out => flag_out(2*i+2));
end generate;
POSTPROCESSING_B:
for i in n/2-1 downto 0 generate
flag_out(2*i+1) <= f_rec_out(i);
end generate;
flag_out(0) <= flag_in(0);
end generate;
stop_recursion2:
if n=2 generate
CON_CELL_3: con
port map (l => flag_in(1), r => flag_in(0),
flag_out => flag_out(1));
flag_out(0) <= flag_in(0);
end generate;
stop_recursion1: if n=1 generate
flag_out(0) <= flag_in(0);
end generate;
end parallel_adder;

-------------------------------------------------------
library IEEE;
library WORK;
use IEEE.std_logic_1164.all;
use work.apg_arithmetic.all;


entity con is
port (l,r : in apgType;
flag_out : out apgType);
end con;

architecture verhalten of con is
begin
flag_out <= l + r;
end verhalten;
-------------------------------------------------------

library ieee;
package apg_arithmetic is
type apgType is ( a , p , g );
type apg_vector is array ( natural range <> ) of apgType;
constant ABSORBING : apgType := a;
constant PROPAGATING: apgType := p;
constant GENERATING : apgType := g;

function "+" (left_flag, right_flag: in apgType)
return apgType;
function stdlogic2apg (op1, op2: in std_logic)
return apgType;
function stdlogic2apg (op1, op2: in std_logic_vector)
return apg_vector;
end package apg_arithmetic;
package body apg_arithmetic is

function "+" (left_flag, right_flag: in apgType)
return apgType is
variable result: apgType;
begin
result:=left_flag;
if (left_flag=PROPAGATING) then
result:=right_flag;
end if;
return result;
end;
function stdlogic2apg (op1, op2: in std_logic)
return apgType is
variable result: apgType;
begin
if (op1 xor op2)='1' then
result:= PROPAGATING;
elsif (op1 and op2)='1' then
result:= GENERATING;
else
result:= ABSORBING;
end if;
return result;
end;
function stdlogic2apg (op1, op2: in std_logic_vector)
return apg_vector is
variable result: apg_vector(op1'length-1 downto 0);
begin
for i in op1'range loop
result(i):=stdlogic2apg(op1(i),op2(i));
end loop;
return result;
end;
end apg_arithmetic;
 
M

Mike Treseler

Joerg said:
Mike Treseler wrote:
enclosed please find the used apg package and the corrected code for the
e/a flag_comp.

This substitution works fine for sim and synth
as long as you don't touch the last two statements
of the "generate rekursion" loop.

Consider using labels on the end statements.

-- Mike Treseler

-----------------------------------------
POSTPROCESSING_B:
process(f_rec_out) begin
for i in n/2-1 downto 0 loop
flag_out(2*i+1) <= f_rec_out(i);
end loop;
end process POSTPROCESSING_B;

-- POSTPROCESSING_B:
-- for i in n/2-1 downto 0 generate
-- flag_out(2*i+1) <= f_rec_out(i);
-- end generate POSTPROCESSING_B;

flag_out(0) <= flag_in(0);
end generate rekursion;
------------------------------------------
 
J

Joerg Ritter

This substitution works fine for sim and synth
as long as you don't touch the last two statements
of the "generate rekursion" loop.

Consider using labels on the end statements.

-- Mike Treseler

-----------------------------------------
POSTPROCESSING_B:
process(f_rec_out) begin
for i in n/2-1 downto 0 loop
flag_out(2*i+1) <= f_rec_out(i);
end loop;
end process POSTPROCESSING_B;

-- POSTPROCESSING_B:
-- for i in n/2-1 downto 0 generate
-- flag_out(2*i+1) <= f_rec_out(i);
-- end generate POSTPROCESSING_B;

flag_out(0) <= flag_in(0);
end generate rekursion;
------------------------------------------

with exactly this substitution, the initialization of ActiveHDL 5.1
fails with the error message:
"Signal flag_out has multiple sources but is not resolved"

the labels after end generate are optional, isn't it ?



joerg
 
M

Mike Treseler

Joerg said:
with exactly this substitution, the initialization of ActiveHDL 5.1
fails with the error message:
"Signal flag_out has multiple sources but is not resolved"

It works fine on modelsim and leo.
Submit your code to aldec.
the labels after end generate are optional, isn't it ?

Yes.


-- Mike Treseler
 
J

Joerg Ritter

Hi Mike,

It works fine on modelsim and leo.
Submit your code to aldec.



Yes.

you are right.
with symphony sonata I can simulate the design. seems to be a bug in
activeHDL of aldec.
thanks a lot !
 
J

Jerry

Joerg Ritter said:
Hi Mike,



you are right.
with symphony sonata I can simulate the design. seems to be a bug in
activeHDL of aldec.
thanks a lot !


Sorry guys, but it is modelsim and leonardo and sonata misinterpreting VHDL.
A: FOR..GENERATE with concurrent signal assignment IS NOT an equivalent
of one process statement. FOR..GENERATE expands to the number of BLOCK
statements equal the number of values in the range. Each block contains one
concurrent signal assignment, which is equivalent of a process statement
with one sequential signal assignment inside.
B: Signal assignment inside the process creates driver for the LONGEST
STATIC PREFIX of the target. Since variable is used for indexing in the
signal assignment, the longest static prefix is the ENTIRE VECTOR, not just
one element.
As the result, each process created after expansion of FOR..GENERATE is
driving entire target; so we do have multiple drivers for unresolved signal...

Jerry
 
M

Mike Treseler

Jerry said:
As the result, each process created after expansion of FOR..GENERATE is
driving entire target; so we do have multiple drivers for unresolved signal...

In Joerg's original code, the FOR..GENERATE case worked fine.
It was the single process loop replacement that gave him errors.

Do you mean to say that both cases have multiple drivers?

-- Mike Treseler
 
J

Joerg Ritter

Sorry guys, but it is modelsim and leonardo and sonata misinterpreting VHDL.
A: FOR..GENERATE with concurrent signal assignment IS NOT an equivalent
of one process statement. FOR..GENERATE expands to the number of BLOCK
statements equal the number of values in the range. Each block contains one
concurrent signal assignment, which is equivalent of a process statement
with one sequential signal assignment inside.
B: Signal assignment inside the process creates driver for the LONGEST
STATIC PREFIX of the target. Since variable is used for indexing in the
signal assignment, the longest static prefix is the ENTIRE VECTOR, not just
one element.
As the result, each process created after expansion of FOR..GENERATE is
driving entire target; so we do have multiple drivers for unresolved signal...

the for..generate works as aspected, at least in my opinion.
could you explain your idea in more detail ?

thanks
joerg
 
M

Marcin

Mike,

For..generate along with flag_out(0) <= flag_in(0); assignment it is
still one driver for flag_out signal. Compiler elabortes it staticaly.
Process with loop statement is dynamicaly elaborated and compiler
assigns a new driver for flag_out, the second one is from flag_out(0)
<= flag_in(0);

Regards,

Marcin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top