"Global Variables" for configuration in VHDL

Discussion in 'VHDL' started by pvwa, Jul 9, 2010.

  1. pvwa

    pvwa Guest

    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
    pvwa, Jul 9, 2010
    #1
    1. Advertising

  2. pvwa

    Tricky Guest

    On 9 July, 13:32, pvwa <-heidelberg.de> wrote:
    > 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?
    Tricky, Jul 9, 2010
    #2
    1. Advertising

  3. pvwa

    KJ Guest

    On Jul 9, 8:32 am, pvwa <-heidelberg.de> wrote:
    > 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
    KJ, Jul 9, 2010
    #3
  4. pvwa

    pvwa Guest

    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?

    > 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, Jul 11, 2010
    #4
  5. pvwa

    pvwa Guest

    Hi Tricky,

    > What are you actually trying to do? are you trying to created the
    > address map at elaboration time?


    Yes!
    pvwa, Jul 11, 2010
    #5

  6. > 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;
    Mike Treseler, Jul 11, 2010
    #6
  7. pvwa

    Andy Guest

    On Jul 11, 2:42 pm, Mike Treseler <> wrote:
    > > 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
    Andy, Jul 12, 2010
    #7
  8. pvwa

    KJ Guest

    On Jul 11, 2:15 pm, pvwa <-heidelberg.de> wrote:
    > 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

    > 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?

    > 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
    KJ, Jul 13, 2010
    #8
  9. pvwa

    pvwa Guest

    Hi all,

    On 13 Jul., 02:15, KJ <> 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
    pvwa, Jul 14, 2010
    #9
  10. pvwa

    Tricky Guest

    On 14 July, 08:35, pvwa <-heidelberg.de> wrote:
    > Hi all,
    >
    > On 13 Jul., 02:15, KJ <> 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.
    Tricky, Jul 14, 2010
    #10
  11. pvwa

    KJ Guest

    On Jul 14, 3:35 am, pvwa <-heidelberg.de> wrote:
    > Hi all,
    >
    > On 13 Jul., 02:15, KJ <> 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...
    > ...
    >
    > -- 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.

    >
    > 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.

    > 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.

    > 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.

    > 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.

    > 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.

    > 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
    KJ, Jul 14, 2010
    #11
  12. pvwa

    pvwa Guest

    On 14 Jul., 11:24, Tricky <> wrote:
    > 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, Jul 14, 2010
    #12
  13. pvwa

    pvwa Guest

    On 14 Jul., 15:34, pvwa <-heidelberg.de> wrote:
    > On 14 Jul., 11:24, Tricky <> 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?
    pvwa, Jul 14, 2010
    #13
  14. pvwa

    Andy Guest

    On Jul 14, 2:35 am, pvwa <-heidelberg.de> wrote:
    > Hi all,
    >
    > On 13 Jul., 02:15, KJ <> 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
    Andy, Jul 14, 2010
    #14
  15. pvwa

    Tricky Guest

    On 14 July, 14:44, pvwa <-heidelberg.de> wrote:
    > On 14 Jul., 15:34, pvwa <-heidelberg.de> wrote:
    >
    > > On 14 Jul., 11:24, Tricky <> 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.
    Tricky, Jul 14, 2010
    #15
  16. pvwa

    pvwa Guest

    Kevin
    On 14 Jul., 15:22, KJ <> wrote:
    > 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...
    >
    > > ...

    >
    > > -- 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.
    >
    >
    >
    > > 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.
    >
    > > 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.


    This is really the main point!
    My code is still in work and constantly changing. This is meant by
    "removing"! I really want to be able to remove/substitute/add modules
    in the source code without having to change too much in other parts
    (functions)!

    As far as i understand, you put the task of address generation into
    the generation of constant vectors, which are then finally used! These
    vectors have to be linked "manually", by using the next proper start
    adresses (range.right) as paramter in "Create_Addresses()". The task
    of linking the addresses remains (the crucial problem!). And again, if
    i have to change my code i have to be very careful to reestablish the
    linking!

    Again, I thought there is a much simpler solution (something like
    "impure functions" see below!)

    But your proposal (in contrary to mine) is interesting anyway! Maybe
    it simplifies overall editing of my code! Give me some time and i will
    give it a try!

    >
    > > 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.
    >
    > > 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.
    >
    > > 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.
    >
    > > 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.


    Why? Would'nt it work?

    Greetings, appreciating you patience!
    Peter
    pvwa, Jul 15, 2010
    #16
  17. pvwa

    pvwa Guest

    On 14 Jul., 15:49, Andy <> wrote:
    > 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


    I would have preferred a solution with a kind of "shared variable",
    but this seems not to work!?
    Thanks
    Peter
    pvwa, Jul 15, 2010
    #17
  18. pvwa

    pvwa Guest

    On 14 Jul., 17:10, Tricky <> wrote:
    > On 14 July, 14:44, pvwa <-heidelberg.de> wrote:
    >
    >
    >
    >
    >
    > > On 14 Jul., 15:34, pvwa <-heidelberg.de> wrote:

    >
    > > > On 14 Jul., 11:24, Tricky <> 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))


    No this works, and is what Kevin (above) proposes!
    Using the impure function there does not help because then everything
    is static and i was looking for a solution which works with
    instantiation (calling the function in Generic Map or maybe even in
    the module itself!!).

    Peter
    pvwa, Jul 15, 2010
    #18
  19. pvwa

    pvwa Guest

    Hi all,

    it seems i have a solution!

    This is my code (only for testing!):

    I have a pkg File where the impure function NextAddress is defined:
    ----------------------------------------------------
    package Test_pkg is
    shared variable pos : integer := 0;
    impure function NextAddress return integer;
    end Test_pkg;

    package body Test_pkg is

    impure function NextAddress return integer is
    begin
    pos := pos+1;
    return pos;
    end function NextAddress;

    end Test_pkg;
    ----------------------------------------------------

    Now i use this function inside (not with Generic) in my Module:

    ----------------------------------------------------
    entity MyModule is
    Port ( x : in std_logic_vector(3 downto 0);
    y : out std_logic);
    end MyModule;

    architecture Behavioral of MyModule is
    constant ModuleAddress: integer := NextAddress;
    begin
    y <= '1' when Conv_integer(x)=ModuleAddressA else '0';
    end Behavioral;
    ----------------------------------------------------

    It is necessary to use the function for setting up a constant
    "ModuleAddress" and use this in the address decoder!
    Direct use of the function "NextAddress" in the comparator gives no
    syntax error it simply does not work!!??
    Has anybody a explanation for that!

    No my top entity, where i instantiate 10 Modules.
    Whenever a module is instantiated it should have a consecutive
    address:

    ----------------------------------------------------
    entity TestModules is
    Port ( a : in std_logic_vector (3 downto 0);
    b : out std_logic_vector (1 to 10));
    end TestModules;

    architecture Behavioral of TestModules is
    begin

    gen: for i in 1 to 10 generate
    Module: entity work.myModule
    Port Map(x => a,
    y => b(i));
    end generate;

    end Behavioral;
    ----------------------------------------------------

    No syntax error!
    Now i test my circuitry with this testbench:

    ----------------------------------------------------
    BEGIN

    uut: TestModules PORT MAP(
    a => a,
    b => b
    );

    tb : PROCESS
    BEGIN
    wait for 100 ns;
    a <= "0000"; --0
    wait for 100 ns;
    a <= "0001"; --1
    wait for 100 ns;
    a <= "0010"; --2
    wait for 100 ns;
    a <= "0011"; --3
    wait for 100 ns;
    a <= "0100"; --4
    wait;
    END PROCESS;

    END;
    ----------------------------------------------------

    Unfortunately i cannot give you a picture, but it shows the correct
    answers of 4 Modules!
    Now i have to synthesize and implement to be really sure everything
    works as expected!

    This seemes to me a very elegant possibility and simplifies my design
    significantly!

    One (little) disadvantage with not beeing able to transfer the address
    via Generic is the missing of this information in the report!
    I am not used to it, but how can i report (Assert?) my generated
    addresses?

    Thanks Tricky, to show me the way!
    Peter
    pvwa, Jul 15, 2010
    #19
  20. pvwa

    Tricky Guest


    >
    > It is necessary to use the function for setting up a constant
    > "ModuleAddress" and use this in the address decoder!
    > Direct use of the function "NextAddress" in the comparator gives no
    > syntax error it simply does not work!!??
    > Has anybody a explanation for that!


    Because every time you call NextAddress, it changes the address. So
    You would have to get lucky for the incoming address to match in the
    ever changing match. Setting it to a constant means it never changes.


    >
    > One (little) disadvantage with not beeing able to transfer the address
    > via Generic is the missing of this information in the report!
    > I am not used to it, but how can i report (Assert?) my generated
    > addresses?


    Asserts can be placed almost anywhere. for what you want, just put it
    inside the architecture.
    Try this:
    assert false report my_ent'PATH_NAME & ": Address of something = " &
    integer'image(ConstantAddress) severity NOTE;

    Now, as discussed previously in another thread, asserts get treated
    different by different synthesisors. I Know Quartus handles them very
    well, but other synthesisors either ignore them or mishandle them and
    just print Failures/errors as warnings!
    Tricky, Jul 15, 2010
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Wayne
    Replies:
    2
    Views:
    456
    Wayne
    Nov 11, 2003
  2. afd
    Replies:
    1
    Views:
    8,258
    Colin Paul Gloster
    Mar 23, 2007
  3. jubelbrus
    Replies:
    5
    Views:
    600
    JohnQ
    Jul 20, 2007
  4. mark4asp
    Replies:
    1
    Views:
    203
  5. Tony Archer

    Global Variables? Multi-Application Variables?

    Tony Archer, Nov 24, 2003, in forum: ASP General
    Replies:
    5
    Views:
    209
    Tony Archer
    Nov 25, 2003
Loading...

Share This Page