Goto page 1, 2 Next
pvwa
Guest
Fri Jul 09, 2010 3:32 pm
Hi,
i have the following (maybe strange) problem:
My design is very modular and will be configured by a setup file
(pkg)! This setup file defines wether specific modules are generated
or not.
For a special reason only the generated modules should now become an
individual (increasing) number as an address, e.g. in a generic! This
is only for configuration!!
I am thinking of a kind of a function with a "Global Variable" there,
which is intialized (to 0) at the beginning and increased by one every
time a module is instanciated (the function called)!! This is easy in
a procedural language but i can not find any construction in VHDL,
which could do this.
function NextAddress() return integer is
global variable addr : integer := 0;
begin
addr := addr+1;
return addr;
end;
I know this function does not work, but do you know a solution?
I already thought of shared variables, pointers (are these supported
in synthesis?) and File I/O. But nothing works?
Thanks ahead for any clue
Peter
Tricky
Guest
Fri Jul 09, 2010 5:59 pm
On 9 July, 13:32, pvwa <vwal...@physi.uni-heidelberg.de> wrote:
Quote:
Hi,
i have the following (maybe strange) problem:
My design is very modular and will be configured by a setup file
(pkg)! This setup file defines wether specific modules are generated
or not.
For a special reason only the generated modules should now become an
individual (increasing) number as an address, e.g. in a generic! This
is only for configuration!!
I am thinking of a kind of a function with a "Global Variable" there,
which is intialized (to 0) at the beginning and increased by one every
time a module is instanciated (the function called)!! This is easy in
a procedural language but i can not find any construction in VHDL,
which could do this.
function NextAddress() return integer is
global variable addr : integer := 0;
begin
addr := addr+1;
return addr;
end;
I know this function does not work, but do you know a solution?
I already thought of shared variables, pointers (are these supported
in synthesis?) and File I/O. But nothing works?
Thanks ahead for any clue
Peter
What are you actually trying to do? are you trying to created the
address map at elaboration time?
KJ
Guest
Sat Jul 10, 2010 1:36 am
On Jul 9, 8:32 am, pvwa <vwal...@physi.uni-heidelberg.de> wrote:
Quote:
Hi,
i have the following (maybe strange) problem:
My design is very modular and will be configured by a setup file
(pkg)! This setup file defines wether specific modules are generated
or not.
For a special reason only the generated modules should now become an
individual (increasing) number as an address, e.g. in a generic! This
is only for configuration!!
I am thinking of a kind of a function with a "Global Variable" there,
which is intialized (to 0) at the beginning and increased by one every
time a module is instanciated (the function called)!! This is easy in
a procedural language but i can not find any construction in VHDL,
which could do this.
function NextAddress() return integer is
global variable addr : integer := 0;
begin
addr := addr+1;
return addr;
end;
I know this function does not work, but do you know a solution?
I already thought of shared variables, pointers (are these supported
in synthesis?) and File I/O. But nothing works?
Thanks ahead for any clue
Peter
I'm not sure I totally understand what you want, but I'm assuming the
following:
- The 'setup file' that defines wether specific modules are generated
or not is also a VHDL file.
- The list of module addresses that come out are supposed to be
constants for a given setup file.
Given those assumptions, one approach would be:
- Have the 'setup file' be a simple list of flags in a vector. For
example, if the universe is a list of five modules that may (or may
not) be included, then you would have a five element vector with '1'
or '0' in a particular location to indicate that the item should be
included.
Ex:
constant List_Of_Modules_Included: std_ulogic_vector(1 to 5) :"10110";
- Now create a function that takes an input vector and creates a
vector of addresses.
Ex:
type arr_integer is array(integer range <>) of integer;
...
function Create_Addresses(V: std_ulogic_vector) return arr_integer
is
variable RetVal: arr_integer(V'range);
variable Start_Address: integer := 0; -- Or whatever initial value
begin
for i in V'range loop
if (V(i) = '1') then
RetVal(i) := Start_Address;
Start_Address := Start_Address + 1;
else
RetVal(i) := 0; -- Presuming unused can be any address
end if;
end loop;
return(RetVal);
end function Create_Addresses;
Now you can create your addresses like this...
constant List_Of_Addresses: arr_integer :Create_Addresses(List_Of_Modules_Included);
Not sure just how you then want to use these addresses, but at least
this should get you started on a possible approach.
Kevin Jennings
Mike Treseler
Guest
Sun Jul 11, 2010 8:42 pm
Quote:
I use for every module a specific function which evaluates, by
scanning my setupfile, a unique number, which is used as an address.
Unfortunately this gets very, very complicated and i thought of a much
simpler solution based on when (!) a module is instantiated!?
Is this possible?
A vhdl "setup file" is called a package.
These work fine with any kind of vhdl design unit.
Your package might want to contain a constant array of vectors
to be used directly by your module. Maybe something like the example below.
-- Mike Treseler
_____________________________
library ieee;
use ieee.std_logic_1164.all;
package adr_decode is
constant reg_len_c : positive := 16;
constant array_len_c : positive := 16;
subtype reg_t is std_logic_vector(reg_len_c-1 downto 0);
type regs_t is array (0 to array_len_c-1) of reg_t;
constant mem_size : natural := 2**add_length;
type mem_t is array (mem_size-1 downto 0) of
std_logic_vector (data_length-1 downto 0);
constant mem : mem_t := (0 => x"abcd", 1 => x"beef",
2 => x"5555", 3 => x"1010",
4 => x"5a6b", 5 => x"f0f0",
6 => x"1234", 7 => x"fabc",
8 => x"2345", 9 => x"9876",
10 => x"5432", 11 => x"6666",
12 => x"0101", 13 => x"abab",
others => x"4247");
end package adr_decode;
pvwa
Guest
Sun Jul 11, 2010 9:15 pm
Hi Kevin,
thanks for your elaborated answer!
I think, your proposal is actually what i am doing right now.
I use for every module a specific function which evaluates, by
scanning my setupfile, a unique number, which is used as an address.
Unfortunately this gets very, very complicated and i thought of a much
simpler solution based on when (!) a module is instanciated!?
Is this possible?
Quote:
I'm not sure I totally understand what you want, but I'm assuming the
following:
- The 'setup file' that defines wether specific modules are generated
or not is also a VHDL file.
Yes! Its a package file!
- The list of module addresses that come out are supposed to be
constants for a given setup file.
Also Yes!
Given those assumptions, one approach would be:
- Have the 'setup file' be a simple list of flags in a vector. For
example, if the universe is a list of five modules that may (or may
not) be included, then you would have a five element vector with '1'
or '0' in a particular location to indicate that the item should be
included.
Ex:
constant List_Of_Modules_Included: std_ulogic_vector(1 to 5) :> "10110";
- Now create a function that takes an input vector and creates a
vector of addresses.
Ex:
type arr_integer is array(integer range <>) of integer;
...
function Create_Addresses(V: std_ulogic_vector) return arr_integer
is
variable RetVal: arr_integer(V'range);
variable Start_Address: integer := 0; -- Or whatever initial value
begin
for i in V'range loop
if (V(i) = '1') then
RetVal(i) := Start_Address;
Start_Address := Start_Address + 1;
else
RetVal(i) := 0; -- Presuming unused can be any address
end if;
end loop;
return(RetVal);
end function Create_Addresses;
Now you can create your addresses like this...
constant List_Of_Addresses: arr_integer :> Create_Addresses(List_Of_Modules_Included);
Not sure just how you then want to use these addresses, but at least
this should get you started on a possible approach.
Kevin Jennings
pvwa
Guest
Sun Jul 11, 2010 9:17 pm
Hi Tricky,
Quote:
What are you actually trying to do? are you trying to created the
address map at elaboration time?
Yes!
Andy
Guest
Mon Jul 12, 2010 8:12 pm
On Jul 11, 2:42 pm, Mike Treseler <mtrese...@gmail.com> wrote:
Quote:
I use for every module a specific function which evaluates, by
scanning my setupfile, a unique number, which is used as an address.
Unfortunately this gets very, very complicated and i thought of a much
simpler solution based on when (!) a module is instantiated!?
Is this possible?
A vhdl "setup file" is called a package.
These work fine with any kind of vhdl design unit.
Your package might want to contain a constant array of vectors
to be used directly by your module. Maybe something like the example below.
-- Mike Treseler
_____________________________
library ieee;
use ieee.std_logic_1164.all;
package adr_decode is
constant reg_len_c : positive := 16;
constant array_len_c : positive := 16;
subtype reg_t is std_logic_vector(reg_len_c-1 downto 0);
type regs_t is array (0 to array_len_c-1) of reg_t;
constant mem_size : natural := 2**add_length;
type mem_t is array (mem_size-1 downto 0) of
std_logic_vector (data_length-1 downto 0);
constant mem : mem_t := (0 => x"abcd", 1 => x"beef",
2 => x"5555", 3 => x"1010",
4 => x"5a6b", 5 => x"f0f0",
6 => x"1234", 7 => x"fabc",
8 => x"2345", 9 => x"9876",
10 => x"5432", 11 => x"6666",
12 => x"0101", 13 => x"abab",
others => x"4247");
end package adr_decode;
Apparently the package will contain a set of flags (hopefully an
array) that determine whether the associated module is actually
generated.
Write a function that processes the array of flags, in the correct
order, and returns an array with the appropriate, incrementing
addresses. Initialize a constant address array with that function.
Mind you, the length of this array should be fixed (matching the
length of the array of flags), and only those elements whose modules
are instantiated will have meaningful values. Then pass the
corresponding address array element as a generic to the module when it
is generated.
if flag(this_one) generate
...
generic_map(address => address_array(this_one));
Andy
KJ
Guest
Tue Jul 13, 2010 2:32 am
On Jul 11, 2:15 pm, pvwa <vwal...@physi.uni-heidelberg.de> wrote:
Quote:
Hi Kevin,
thanks for your elaborated answer!
I think, your proposal is actually what i am doing right now.
I use for every module a specific function which evaluates, by
scanning my setupfile, a unique number, which is used as an address.
What exactly do you mean by "scanning my setupfile"? To me, that
sounds like you're literally reading some file from disk (the setup
file), parsing that file, performing some function on the parsed data
to create an address...if that's what you're doing, you're making
things very difficult on yourself
Quote:
Unfortunately this gets very, very complicated and i thought of a much
simpler solution
If it's how I interpret what you wrote, then yes, parsing files is not
always a simple thing, it's particularly tedious in VHDL...but it begs
the question of why you would even want to do it that way in the first
place?
Quote:
based on when (!) a module is instanciated!?
Is this possible?
Going back to my first post where I detailed how to create a vector of
addresses from a vector of flags that defines which modules are
included (or not)...you would use that same vector of flags to control
whether a module is included or not like this
gen_1 : if List_Of_Modules_Included(1) = '1' generate
inst_mod1 : entity work.module1
generic map (List_Of_Addresses(1)...)
port map(...)
end generate gen_1;
gen_2 : if List_Of_Modules_Included(2) = '1' generate
inst_mod2 : entity work.module2
generic map (List_Of_Addresses(2)...)
port map(...)
end generate gen_2;
etc...
So 'module1' is only included if List_Of_Modules_Included(1) = '1'.
Since 'List_Of_Modules_Included' is the simple string that you
configure with what you want included, simply editing this text string
controls which modules get instantiated, what the address for that
module is at and any other things you want to affect.
Kevin Jennings
pvwa
Guest
Wed Jul 14, 2010 10:35 am
Hi all,
On 13 Jul., 02:15, KJ <kkjenni...@sbcglobal.net> wrote:
Quote:
What exactly do you mean by "scanning my setupfile"? To me, that
sounds like you're literally reading some file from disk (the setup
file), parsing that file, performing some function on the parsed data
to create an address...if that's what you're doing, you're making
things very difficult on yourself
No, its not a file from disk but simply a VHDL package which contains
constant vectors, which define my modules with versionnumbers!
I think very similar to your proposal!?
See here an excerpt from my code:
------------------------------------------------------
type N_Vers is array ( NATURAL RANGE <> ) of integer;
constant Module_A: N_Vers := (8,0,1,0,2,2,0,0,0);
constant Module_B: N_Vers := (0);
constant Module_C: N_Vers := (2,0,0);
....
-- this is part of my setupfile
-- the first element of the constants are the number of modules of
that type, the other numbers are the according versions of that
type!...
-- Now these special functions "NextAddress.." (also in a pkg) take
care of the address calculation, similar to this:
function NextAddress_A(pos: integer) return integer is
begin
return pos; -- this is easy, because Module_A is the first module
type in the chain
end;
function NextAddress_B(pos: integer) return integer is
begin
return Module_A(0)+pos;
end;
function NextAddress_C(pos: integer) return integer is
begin
return Module_A(0)+Module_B(0)+pos; -- things getting more and more
complicated!
end;
....
-- finally here the mdoules according the setup constants are
generated
gen_Module_A : for i in 1 to Module_A(0) generate
iModule_A : entity work.ModuleA
generic map (Address => NextAddressA(i),
(Version => Module_A(i))
port map(...)
end generate;
gen_Module_B : for i in 1 to Module_B(0) generate
iModule_B : entity work.ModuleB
generic map (Address => NextAddressB(i),
(Version => Module_B(i))
port map(...)
end generate;
gen_Module_C : for i in 1 to Module_C(0) generate
iModule_C : entity work.ModuleC
generic map (Address => NextAddressC(i),
(Version => Module_C(i))
port map(...)
end generate;
...
------------------------------------------------------
I think you get the idea!
The code above is very simplified, because i don't have to generate
not only addresses but also other numbers, which are dependent on the
versionnumbers of the modules!
So i have to write for each module, according functions, which do the
calculations!
Now imagine i want to change my code, e.g. i remove Module_B, then ALL
the dependent functions have to be changed also!!
I simply search for another solution, where the calculation can be
done in the Modules itself and this is not depended on other modules
(or functions) but simply on the fact of beeing instanciated or not!
My thinking was of a kind of "global variable", which is simply
incremented
So there would be only one function "NextAddress" be needed, similar
to this:
function NextAddress() return integer is
global variable pos: integer := 0; this is the initialization of the
variable
begin
pos := pos +1;
return pos;
end;
But nothingh like this seems to be possible in VHDL!?
My thinking was also of writing out the number+1 to a file and read it
back, whenever the function is called, but i learned that file
read&write in VHDL is not possible??
Peter von Walter
Tricky
Guest
Wed Jul 14, 2010 12:24 pm
On 14 July, 08:35, pvwa <vwal...@physi.uni-heidelberg.de> wrote:
Quote:
Hi all,
On 13 Jul., 02:15, KJ <kkjenni...@sbcglobal.net> wrote:
What exactly do you mean by "scanning my setupfile"? To me, that
sounds like you're literally reading some file from disk (the setup
file), parsing that file, performing some function on the parsed data
to create an address...if that's what you're doing, you're making
things very difficult on yourself
No, its not a file from disk but simply a VHDL package which contains
constant vectors, which define my modules with versionnumbers!
I think very similar to your proposal!?
See here an excerpt from my code:
------------------------------------------------------
type N_Vers is array ( NATURAL RANGE <> ) of integer;
constant Module_A: N_Vers := (8,0,1,0,2,2,0,0,0);
constant Module_B: N_Vers := (0);
constant Module_C: N_Vers := (2,0,0);
...
-- this is part of my setupfile
-- the first element of the constants are the number of modules of
that type, the other numbers are the according versions of that
type!...
-- Now these special functions "NextAddress.." (also in a pkg) take
care of the address calculation, similar to this:
function NextAddress_A(pos: integer) return integer is
begin
return pos; -- this is easy, because Module_A is the first module
type in the chain
end;
function NextAddress_B(pos: integer) return integer is
begin
return Module_A(0)+pos;
end;
function NextAddress_C(pos: integer) return integer is
begin
return Module_A(0)+Module_B(0)+pos; -- things getting more and more
complicated!
end;
...
-- finally here the mdoules according the setup constants are
generated
gen_Module_A : for i in 1 to Module_A(0) generate
iModule_A : entity work.ModuleA
generic map (Address => NextAddressA(i),
(Version => Module_A(i))
port map(...)
end generate;
gen_Module_B : for i in 1 to Module_B(0) generate
iModule_B : entity work.ModuleB
generic map (Address => NextAddressB(i),
(Version => Module_B(i))
port map(...)
end generate;
gen_Module_C : for i in 1 to Module_C(0) generate
iModule_C : entity work.ModuleC
generic map (Address => NextAddressC(i),
(Version => Module_C(i))
port map(...)
end generate;
...
------------------------------------------------------
I think you get the idea!
The code above is very simplified, because i don't have to generate
not only addresses but also other numbers, which are dependent on the
versionnumbers of the modules!
So i have to write for each module, according functions, which do the
calculations!
Now imagine i want to change my code, e.g. i remove Module_B, then ALL
the dependent functions have to be changed also!!
I simply search for another solution, where the calculation can be
done in the Modules itself and this is not depended on other modules
(or functions) but simply on the fact of beeing instanciated or not!
My thinking was of a kind of "global variable", which is simply
incremented
So there would be only one function "NextAddress" be needed, similar
to this:
function NextAddress() return integer is
global variable pos: integer := 0; this is the initialization of the
variable
begin
pos := pos +1;
return pos;
end;
But nothingh like this seems to be possible in VHDL!?
My thinking was also of writing out the number+1 to a file and read it
back, whenever the function is called, but i learned that file
read&write in VHDL is not possible??
Peter von Walter
You could try using a shared variable in the package and impure
functions to access them.
shared variable pos : integer := 0;
impure function NextAddress() return integer is
begin
pos := pos + 1;
return pos;
end function NextAddress;
The only problem with this is I dont think you can guarantee the order
in which the entities are instantiated, and may even change from
compilation to compilation. I know Quartus does support shared
variables, but dont know whether it will support them in this way. I
know it wont let you use signals in packages and from past experience
it has treated shared variables as signals inside entites.
This is only VHDL 93 standard. From 2000 onwards shared variables are
supposed to be protected. But Quartus doesnt really support alot more
than 93 (and doesnt complain even when you switch 2008 mode on)
Give this a go and let us know what happens.
KJ
Guest
Wed Jul 14, 2010 4:22 pm
On Jul 14, 3:35 am, pvwa <vwal...@physi.uni-heidelberg.de> wrote:
Quote:
Hi all,
On 13 Jul., 02:15, KJ <kkjenni...@sbcglobal.net> wrote:
What exactly do you mean by "scanning my setupfile"? To me, that
sounds like you're literally reading some file from disk (the setup
file), parsing that file, performing some function on the parsed data
to create an address...if that's what you're doing, you're making
things very difficult on yourself
No, its not a file from disk but simply a VHDL package which contains
constant vectors, which define my modules with versionnumbers!
I think very similar to your proposal!?
See here an excerpt from my code:
------------------------------------------------------
type N_Vers is array ( NATURAL RANGE <> ) of integer;
constant Module_A: N_Vers := (8,0,1,0,2,2,0,0,0);
constant Module_B: N_Vers := (0);
constant Module_C: N_Vers := (2,0,0);
...
-- this is part of my setupfile
-- the first element of the constants are the number of modules of
that type, the other numbers are the according versions of that
type!...
-- Now these special functions "NextAddress.." (also in a pkg) take
care of the address calculation, similar to this:
function NextAddress_A(pos: integer) return integer is
begin
return pos; -- this is easy, because Module_A is the first module
type in the chain
end;
function NextAddress_B(pos: integer) return integer is
begin
return Module_A(0)+pos;
end;
function NextAddress_C(pos: integer) return integer is
begin
return Module_A(0)+Module_B(0)+pos; -- things getting more and more
complicated!
end;
Yes, because you didn't take my suggestion which was to create a
single function that loops through the list of all the modules and
return an array of constant addresses. Now that you've posted some
code to get a better idea of what you're trying to accomplish, let me
suggest the following which uses the 'Create_Addresses' function that
I posted earlier, modified slightly to take an extra input parameter
that is a 'start address' which would be used to initialize the first
element in the computed addresses
type arr_integer is array(integer range <>) of integer;
...
function Create_Addresses(V: std_ulogic_vector; Start_Address:
natural) return arr_integer
...
constant Module_A_Address: arr_integer(Module_A'range) :Create_Addresses(Module_A, 0);
constant Module_B_Address: arr_integer(Module_B'range) :Create_Addresses(Module_A, Module_A_Address(Module_A_Address'right)
+1);
constant Module_C_Address: arr_integer(Module_C'range) :Create_Addresses(Module_B, Module_B_Address
(Module_B_Address'right)+1);
Now you have three sets of arrays of integers for each of the three
modules, those would be used when instantiating the modules like
this...
Quote:
...
-- finally here the mdoules according the setup constants are
generated
gen_Module_A : for i in 1 to Module_A(0) generate
iModule_A : entity work.ModuleA
generic map (Address => Module_A_Address(i),
(Version => Module_A(i))
port map(...)
end generate;
The only change from your code then is to use the pre-computed
constants as the address generic.
Quote:
So i have to write for each module, according functions, which do the
calculations!
Not really. As I showed, one 'function' covered nearly all of the
computations. The only other calculation is the part that links
address from the end of the 'Module A' list to the address start of
the 'Module B' list. This is accomplished with the added parameter to
'Create_Addresses' which allows for an arbitrary 'first' address to
use and then invoking that function by passing it the address of the
end of the 'Module A' list and adding 1 (i.e. the
"Module_A_Address(Module_A_Address'right)+1" portion of the call to
define Module_B_Address
constant Module_B_Address: arr_integer(Module_B'range) :Create_Addresses(Module_A, Module_A_Address(Module_A_Address'right)
+1);
Module B and C are similarly linked.
Quote:
Now imagine i want to change my code, e.g. i remove Module_B, then ALL
the dependent functions have to be changed also!!
I would 'remove' a module by having a flag indicating whether the
module is to be generated or not. I'm not quite sure if that's what
you're doing or not.
Quote:
I simply search for another solution, where the calculation can be
done in the Modules itself and this is not depended on other modules
(or functions) but simply on the fact of beeing instanciated or not!
My thinking was of a kind of "global variable", which is simply
incremented
You can't do it with the way that you're viewing the problem which is
in terms of some *variable*. You can do it though by viewing the
problem in terms of generating a *constant* vector which is what I'm
trying to get across.
Quote:
So there would be only one function "NextAddress" be needed, similar
to this:
function NextAddress() return integer is
global variable pos: integer := 0; this is the initialization of the
variable
begin
pos := pos +1;
return pos;
end;
That function simply lacks an input to indicate whether something
should be included or not and some base address to start at. Other
than that it is doing essentially the same thing as the
'Create_Addresses' function that I posted, the crucial difference is
that my function returns something that can be used to generate the
vector of constants that you need.
Quote:
But nothingh like this seems to be possible in VHDL!?
It is...the mental hurdle is to stop viewing this address calculation
as being some variable that needs incrementing but instead see it as
the computation of a set of constants.
Quote:
My thinking was also of writing out the number+1 to a file and read it
back, whenever the function is called, but i learned that file
read&write in VHDL is not possible??
That approach would not be a good path to go down.
Kevin Jennings
pvwa
Guest
Wed Jul 14, 2010 4:34 pm
On 14 Jul., 11:24, Tricky <trickyh...@gmail.com> wrote:
Quote:
Give this a go and let us know what happens.
Ok, here is the result!
This is now my (complete) test code:
--------------------------------------------------------
-- This is the top entity
-- it is simply a group of 10 Modules which decode input a and give a
'1' signal if it matches with a
entity TestModules is
Port ( a : in std_logic_vector (7 downto 0);
b : out std_logic_vector (1 to 10));
end TestModules;
architecture Behavioral of TestModules is
shared variable pos : integer :=0;
impure function NextAddress return integer is
begin
pos := pos +1;
return pos;
end function NextAddress;
begin
gen: for i in 1 to 10 generate
Module: entity work.myModule
Generic Map(Addr => NextAddress)
Port Map(x => a,
y => b(i));
end generate;
end Behavioral;
-- and now here comes the module itself
entity MyModule is
Generic (Addr : integer);
Port ( x : in std_logic_vector(7 downto 0);
y : out std_logic);
end MyModule;
architecture Behavioral of MyModule is
begin
y <= '1' when Conv_integer(x)=Addr else '0';
end Behavioral;
---
unfortunately the syntax check (XILINX ISE 9.1) brings up the
following error:
ERROR: HDLParsers:3305 - "C:/VHDL/TestSharedVariable/TestModules.vhd"
Line 25. The actual value (result of operator) associated with a
generic must be a globally static expression.
pointing to line 25: Generic Map(Addr => NextAddress)
Can anybody give me a hint how to repair this!
Thanks
Peter
pvwa
Guest
Wed Jul 14, 2010 4:44 pm
On 14 Jul., 15:34, pvwa <vwal...@physi.uni-heidelberg.de> wrote:
Quote:
On 14 Jul., 11:24, Tricky <trickyh...@gmail.com> wrote:
impure function NextAddress return integer is
begin
pos := pos +1;
return pos;
end function NextAddress;
If i remove the keyword impure it gives me this warning:
WARNING: HDLParsers:3310 - "C:/VHDL/TestSharedVariable/
TestModules.vhd" Line 25. Function NextAddress is not pure. VHDL 87
allowed this; VHDL 93 requires the keyword IMPURE.
So what's going on?
Andy
Guest
Wed Jul 14, 2010 4:49 pm
On Jul 14, 2:35 am, pvwa <vwal...@physi.uni-heidelberg.de> wrote:
Quote:
Hi all,
On 13 Jul., 02:15, KJ <kkjenni...@sbcglobal.net> wrote:
What exactly do you mean by "scanning my setupfile"? To me, that
sounds like you're literally reading some file from disk (the setup
file), parsing that file, performing some function on the parsed data
to create an address...if that's what you're doing, you're making
things very difficult on yourself
No, its not a file from disk but simply a VHDL package which contains
constant vectors, which define my modules with versionnumbers!
I think very similar to your proposal!?
See here an excerpt from my code:
------------------------------------------------------
type N_Vers is array ( NATURAL RANGE <> ) of integer;
constant Module_A: N_Vers := (8,0,1,0,2,2,0,0,0);
constant Module_B: N_Vers := (0);
constant Module_C: N_Vers := (2,0,0);
...
-- this is part of my setupfile
-- the first element of the constants are the number of modules of
that type, the other numbers are the according versions of that
type!...
-- Now these special functions "NextAddress.." (also in a pkg) take
care of the address calculation, similar to this:
function NextAddress_A(pos: integer) return integer is
begin
return pos; -- this is easy, because Module_A is the first module
type in the chain
end;
function NextAddress_B(pos: integer) return integer is
begin
return Module_A(0)+pos;
end;
function NextAddress_C(pos: integer) return integer is
begin
return Module_A(0)+Module_B(0)+pos; -- things getting more and more
complicated!
end;
...
-- finally here the mdoules according the setup constants are
generated
gen_Module_A : for i in 1 to Module_A(0) generate
iModule_A : entity work.ModuleA
generic map (Address => NextAddressA(i),
(Version => Module_A(i))
port map(...)
end generate;
gen_Module_B : for i in 1 to Module_B(0) generate
iModule_B : entity work.ModuleB
generic map (Address => NextAddressB(i),
(Version => Module_B(i))
port map(...)
end generate;
gen_Module_C : for i in 1 to Module_C(0) generate
iModule_C : entity work.ModuleC
generic map (Address => NextAddressC(i),
(Version => Module_C(i))
port map(...)
end generate;
...
------------------------------------------------------
I think you get the idea!
The code above is very simplified, because i don't have to generate
not only addresses but also other numbers, which are dependent on the
versionnumbers of the modules!
So i have to write for each module, according functions, which do the
calculations!
Now imagine i want to change my code, e.g. i remove Module_B, then ALL
the dependent functions have to be changed also!!
I simply search for another solution, where the calculation can be
done in the Modules itself and this is not depended on other modules
(or functions) but simply on the fact of beeing instanciated or not!
My thinking was of a kind of "global variable", which is simply
incremented
So there would be only one function "NextAddress" be needed, similar
to this:
function NextAddress() return integer is
global variable pos: integer := 0; this is the initialization of the
variable
begin
pos := pos +1;
return pos;
end;
But nothingh like this seems to be possible in VHDL!?
My thinking was also of writing out the number+1 to a file and read it
back, whenever the function is called, but i learned that file
read&write in VHDL is not possible??
Peter von Walter
If you built an array of n_vers's (they would have to be fixed length
(i.e. padded with additional unused version numbers for uninstantiated
modules), then you could have one address function that iterated
through the array up to the current module/instance to calculate the
address, without using shared variables.
You could take it a step further by eliminating the number of modules
(1st) element in the array, and use -1 as a version number that
indicates the module is not instantiated.
Andy
Tricky
Guest
Wed Jul 14, 2010 6:10 pm
On 14 July, 14:44, pvwa <vwal...@physi.uni-heidelberg.de> wrote:
Quote:
On 14 Jul., 15:34, pvwa <vwal...@physi.uni-heidelberg.de> wrote:
On 14 Jul., 11:24, Tricky <trickyh...@gmail.com> wrote:
impure function NextAddress return integer is
begin
pos := pos +1;
return pos;
end function NextAddress;
If i remove the keyword impure it gives me this warning:
WARNING: HDLParsers:3310 - "C:/VHDL/TestSharedVariable/
TestModules.vhd" Line 25. Function NextAddress is not pure. VHDL 87
allowed this; VHDL 93 requires the keyword IMPURE.
So what's going on?
So the old globally static chestnut.
The only way round this I can think of is to create an array type and
create a constant, but I doubt this will work either:
type addr_array_t is array (0 to N_ENTITIES-1) of natural;
Constant addr_array : addr_array_t := ( others => NextAddress);
then when you instantiate the entity, you say:
Generic Map(Addr => addr_array(i))
For your second point - impure is needed because you are updating a
variable declared outside of the function. Pure functions can only
output 1 thing (the thing that they return) but impure ones can change
variables outside of the function. Any function can read things
declared outside of it.
Goto page 1, 2 Next