From: wallge on
I have written a custom SOPC builder component in VHDL.
Right now I have SOPC builder auto-generating a package
that contains custom type definitions that are used throughout my
custom SOPC builder component. These type definitions are based on the
settings input by the user in the SOPC builder GUI.

This package is then included in each of the VHDL
files of my custom component using the construct:

library work;
use work.custom_package.all;

Now, the problem with this formulation is that I can only have one
instance
of the component in my sopc system.

Does anyone have a workaround for this, where I can generate multiple
unique package files, each one associated with a particular
instantiation of my custom VHDL component?

In a perfect world, I might be able to use VHDL 2008 constructs which
allow for passing custom types as generic parameters on a component.
Quartus and SOPC do not support this.

Another intractable solution would be to remove all the custom types
which are used all throughout my custom component and use generic
parameters and std_logic_vectors types
all the way through the project. At this point the component is too
complex to try and remove all of the custom types and replace them
with standard types (whose bitwidths, etc would be set via generics).

A third undesirable workaround would involve auto-generating every
single
VHDL file used in my component and passing the name-decorated version
of my custom package to a VHDL generation script which could then
generate a customized, name-decorated version of each VHDL file needed
for my component.
This is kind of a nasty and inelegant way of doing what I want.

What I would like to be able to do is have two instances of my custom
component in my sopc system. Let's call them
Custom1 and Custom2. My custom_component_hw.tcl script could then
generate two unique VHDL packages associated with each instantiation.
It would generate Custom1_Package.vhd and Custom2_Package.vhd.

Is there a way to associate Custom1_Package.vhd with one instance of
all of my custom VHDL source files and associate Custom2_Package.vhd
with a
second instance of them. I would prefer to not have to write a complex
code generator script to allow for this.
From: KJ on
On May 5, 11:52 am, wallge <wal...(a)gmail.com> wrote:
>
> Another intractable solution would be to remove all the custom types
> which are used all throughout my custom component and use generic
> parameters and std_logic_vectors types
> all the way through the project. At this point the component is too
> complex to try and remove all of the custom types and replace them
> with standard types (whose bitwidths, etc would be set via generics).
>

Is it still too much work if only the top level entity used generics
and the rest is left nearly all alone? Seems to me like it shouldn't,
the 'intractable' part I'm suspecting has to do if you had to replace
all usages in the architecture.

The thought here would be...
- Modify the entity to parameterize with generics using
std_logic_vector types per your post
- For each custom type, write a 'to_std_ulogic_vector' and a
'from_std_ulogic_vector' function that converts between
std_ulogic_vector and a particular custom type.
- For each entity interface signal add a signal in the architecture
that converts to or from the custom type. Use the signal name of the
old entity signal in the architecture, come up with a new name for the
entity. That way, nothing else inside the architecture needs to be
changed.

As an example...

Before...

entity Foo is generic(...)
port(
Inp1: in t_type1;
Inp2: in t_type2;
Out3: out t_type3
);
end Foo;

After...
entity Foo is generic(
T1_WIDTH: natural;
T2_WIDTH: natural;
T3_WIDTH: natural
...)
port(
Inp1_sulv: in std_ulogic_vector(T1_WIDTH-1 downto 0);
Inp2_sulv: in std_ulogic_vector(T2_WIDTH-1 downto 0);
Out3_sulv: out std_ulogic_vector(T3_WIDTH-1 downto 0);
);

architecture RTL of Foo is
signal Inp1: t_type1;
signal Inp2: t_type2;
signal Out3: t_type3;

-- In most cases, the following functions reeeeeally should be put
in the package
-- where the types are defined, not in the architecture.
function to_std_ulogic_vector(L: t_type1) return std_ulogic_vector
is
begin
...
end function to_std_ulogic_vector;

function from_std_ulogic_vector(L: std_ulogic_vector) return t_type1
is
begin
...
end function from_std_ulogic_vector;

-- Repeat the to/from functions for each custom type

-- Strictly speaking, you only need the 'to' functions for custom
type
-- entity outputs and the 'from' functions for custom type entity
inputs.
--
-- The reality is that once you create these functions you'll find
many
-- uses for them beyond your immediate needs. It should take less
than
-- a minute to copy/paste/edit to convert a record type into to/
from
-- vector functions. Once you see that, you'll probably be able to
-- macro-ize the steps using whatever text editor you use.
begin
Inp1 <= from_std_ulogic_vector(Inp1_sulv);
Inp2 <= from_std_ulogic_vector(Inp2_sulv);
Out3_sulv <= to_std_ulogic_vector(Out3_sulv);

...rest of code that you currently have remains unchanged
);

Kevin Jennings