Search code examples
vhdl

Variable generic assignment in generate loop


What I want to do doesn't seem particularly complex, but I can't think of a simple way to do it in VHDL.

I have a component with a generic parameter called FOO. I would like to generate 16 of these components and for the first 8 instances I want FOO to be set to 0 and the other 8 instances I want FOO to be set to 4096.

Ideally, I would be able to do something like this:

generate_loop: for I in 0 to 15 generate
begin
  comp_inst: my_component
  generic map
  (
    FOO => 0 when I < 8 else 4096
  )
  port map
  (
  ...
  );
end generate;

This is of course not valid VHDL, but that captures the idea of what I'd like to do.

So my question is: is there a way to implement this in a single generate loop (i.e. without having to have 2 separate generate loops with different indices), and if so, how do I do it?


Solution

  • As user1155120 mentions in the comments, the base type of a for-loop is a universal integer. The fractional part of an integer division will be truncated. You can use this fact to realize your specific system, as

    • for 0<=i<8, i/8=0
    • for 8<=i<15, i/8=1

    Thus the code could be

    generate_loop: for I in 0 to 15 generate
    begin
        comp_inst: entity work.my_component
            generic map (FOO => 4096 * (I/8))
            port map (
                ...
                );
    end generate;
    

    Alternatively, especially useful for more complex situations, you could do what Brian Drummond suggested: write a function

    architecture arch of ent is
        function gen_FOO(I : natural) return natural is begin
            if I<8 then
                return 0;
            else
                return 4096;
            end if;
        end function;
    begin
        generate_loop: for I in 0 to 15 generate
        begin
            comp_inst: entity work.my_component
                generic map (FOO => gen_FOO(I))
                port map (
                    ...
                    );
        end generate;