upside down generics or so

I

Ilya Kalistru

Guest
Sometimes I design complex pipeline which splits on several pipelines at some point and then these branch pipelines are joined in one pipeline again.

| root pipeline
|
|\
|\\
||| branch pipelines
|// joint point
|

At the pipeline joint point data from different branches have to be aligned relatively to each other, so sometimes I have to add shift registers to shorter branch pipelines. Branch pipelines usually consist of several modules and added delays depends on the latencies of each module. As long as modules can be changed and their latency can be changed, I have to adjust delays.

Is there a way to set latency of the module as some “property” in it, so that a top module could read it and adjust delay lines? Something like reversed generics – generics pass parameter to a module but I need to pass it from the module.

Any ideas?
 
On Thursday, August 11, 2016 at 10:55:20 AM UTC-4, Ilya Kalistru wrote:
Is there a way to set latency of the module as some “property” in it, so
that a top module could read it and adjust delay lines? Something like
reversed generics – generics pass parameter to a module but I need to pass
it from the module.

Presumably, the amount of latency of a particular module is either fixed or is a function of the generic inputs to that module. Since those generics are available to the top level module as well, then a function can be created that calculates the latency of all of the modules and then uses those latencies to define the amount of latency required at the top.

Kevin Jennings
 
On Thursday, August 11, 2016 at 7:30:20 PM UTC+3, KJ wrote:
On Thursday, August 11, 2016 at 10:55:20 AM UTC-4, Ilya Kalistru wrote:

Is there a way to set latency of the module as some “property” in it, so
that a top module could read it and adjust delay lines? Something like
reversed generics – generics pass parameter to a module but I need to pass
it from the module.

Presumably, the amount of latency of a particular module is either fixed or is a function of the generic inputs to that module. Since those generics are available to the top level module as well, then a function can be created that calculates the latency of all of the modules and then uses those latencies to define the amount of latency required at the top.

Kevin Jennings

I don't think so. Latency depends on algorithms, how they are implemented and how well the module is optimized. All that could (and will) change during product development.
 
On 8/11/2016 10:55 AM, Ilya Kalistru wrote:
Sometimes I design complex pipeline which splits on several pipelines at some point and then these branch pipelines are joined in one pipeline again.

| root pipeline
|
|\
|\\
||| branch pipelines
|// joint point
|

At the pipeline joint point data from different branches have to be aligned relatively to each other, so sometimes I have to add shift registers to shorter branch pipelines. Branch pipelines usually consist of several modules and added delays depends on the latencies of each module. As long as modules can be changed and their latency can be changed, I have to adjust delays.

Is there a way to set latency of the module as some “property” in it, so that a top module could read it and adjust delay lines? Something like reversed generics – generics pass parameter to a module but I need to pass it from the module.

Any ideas?

A module passes signals in and out. You can create a constant integer
output signal. Nothing fancy needed. Add up all the delays and
subtract from the longest to get the additional pipeline stages needed.

These values will only be used in generate statements so it won't create
any logic. You may get warnings of signals that are deleted for having
no source and/or no destination. Personally I hate that. A design
should be synthesized without warnings.

--

Rick C
 
On Thursday, August 11, 2016 at 7:55:11 PM UTC+3, rickman wrote:
On 8/11/2016 10:55 AM, Ilya Kalistru wrote:
Sometimes I design complex pipeline which splits on several pipelines at some point and then these branch pipelines are joined in one pipeline again.

| root pipeline
|
|\
|\\
||| branch pipelines
|// joint point
|

At the pipeline joint point data from different branches have to be aligned relatively to each other, so sometimes I have to add shift registers to shorter branch pipelines. Branch pipelines usually consist of several modules and added delays depends on the latencies of each module. As long as modules can be changed and their latency can be changed, I have to adjust delays.

Is there a way to set latency of the module as some “property” in it, so that a top module could read it and adjust delay lines? Something like reversed generics – generics pass parameter to a module but I need to pass it from the module.

Any ideas?

A module passes signals in and out. You can create a constant integer
output signal. Nothing fancy needed. Add up all the delays and
subtract from the longest to get the additional pipeline stages needed.

These values will only be used in generate statements so it won't create
any logic. You may get warnings of signals that are deleted for having
no source and/or no destination. Personally I hate that. A design
should be synthesized without warnings.

--

Rick C

With constant signal outputs you can neither define signals like
signal DelayLine : std_logic_vector(DelayFromTheModule downto 0);
nor use generate statements with this parameters.

The only way to use them (that I see) is to make excessively long delay lines and multiplexers from each stage of it, controlled by that constant signal. Then we have to hope that synthesizer will optimize it properly, remove unnecessary multiplexer and will be able to infer built-in shift registers there.
It's not very elegant solution and it has very limited use because we cannot use signals everywhere we want (but can use constants and generics).

Or I miss something?

I've seen that it's possible to define some objects inside entity declaration. I hope that there is something exotic like that which will allow to do what I want...
 
I would put a constant in a package that is associated with a particular entity. As you do your detailed design and update the pipeline in a particular block, simply update the corresponding constant in the package - even better would be to use that constant to define the number of pipeline stages in the block.

Then any design that references the package can see the constant.
 
On Friday, August 12, 2016 at 5:39:36 PM UTC+3, Jim Lewis wrote:
I would put a constant in a package that is associated with a particular entity. As you do your detailed design and update the pipeline in a particular block, simply update the corresponding constant in the package - even better would be to use that constant to define the number of pipeline stages in the block.

Then any design that references the package can see the constant.

That's exactly what I've done. But when you are modifying the module you have to remember that somewhere in a different file (package) there is a constant you have to adjust according to you changes.
 
On Fri, 12 Aug 2016 10:12:40 -0700, Ilya Kalistru wrote:

On Friday, August 12, 2016 at 5:39:36 PM UTC+3, Jim Lewis wrote:
I would put a constant in a package that is associated with a
particular entity. As you do your detailed design and update the
pipeline in a particular block, simply update the corresponding
constant in the package - even better would be to use that constant to
define the number of pipeline stages in the block.

Then any design that references the package can see the constant.

That's exactly what I've done. But when you are modifying the module you
have to remember that somewhere in a different file (package) there is a
constant you have to adjust according to you changes.

I contend that you *don't* have to remember to adjust that, as long as
you:

1. Write an assert statement inside your module that checks that the
package constant has the value that matches your design. I suggest a
higher severity level on the assertion, e.g. failure.

2. You remember to simulate your design (so that the assertion can be
checked). I wouldn't rely on a synthesiser to check an assertion, but
all simulators should work properly.


(In any reasonable development process) you'll already be required to
simulate your testbench before committing your code change.
The only new thing you have to do is add the 1 line of assertion
statement in your module.


Regards,
Allan
 
On 8/12/2016 11:09 PM, Allan Herriman wrote:
On Fri, 12 Aug 2016 10:12:40 -0700, Ilya Kalistru wrote:

On Friday, August 12, 2016 at 5:39:36 PM UTC+3, Jim Lewis wrote:
I would put a constant in a package that is associated with a
particular entity. As you do your detailed design and update the
pipeline in a particular block, simply update the corresponding
constant in the package - even better would be to use that constant to
define the number of pipeline stages in the block.

Then any design that references the package can see the constant.

That's exactly what I've done. But when you are modifying the module you
have to remember that somewhere in a different file (package) there is a
constant you have to adjust according to you changes.


I contend that you *don't* have to remember to adjust that, as long as
you:

1. Write an assert statement inside your module that checks that the
package constant has the value that matches your design. I suggest a
higher severity level on the assertion, e.g. failure.

2. You remember to simulate your design (so that the assertion can be
checked). I wouldn't rely on a synthesiser to check an assertion, but
all simulators should work properly.


(In any reasonable development process) you'll already be required to
simulate your testbench before committing your code change.
The only new thing you have to do is add the 1 line of assertion
statement in your module.

So when a change is made to the pipeline depth a change will need to be
made for adjusting the delay pipeline in two places. One to check the
other. I guess that's one way to make this work.

--

Rick C
 
On Fri, 12 Aug 2016 23:28:13 -0400, rickman wrote:

On 8/12/2016 11:09 PM, Allan Herriman wrote:
On Fri, 12 Aug 2016 10:12:40 -0700, Ilya Kalistru wrote:

On Friday, August 12, 2016 at 5:39:36 PM UTC+3, Jim Lewis wrote:
I would put a constant in a package that is associated with a
particular entity. As you do your detailed design and update the
pipeline in a particular block, simply update the corresponding
constant in the package - even better would be to use that constant
to define the number of pipeline stages in the block.

Then any design that references the package can see the constant.

That's exactly what I've done. But when you are modifying the module
you have to remember that somewhere in a different file (package)
there is a constant you have to adjust according to you changes.


I contend that you *don't* have to remember to adjust that, as long as
you:

1. Write an assert statement inside your module that checks that the
package constant has the value that matches your design. I suggest a
higher severity level on the assertion, e.g. failure.

2. You remember to simulate your design (so that the assertion can be
checked). I wouldn't rely on a synthesiser to check an assertion, but
all simulators should work properly.


(In any reasonable development process) you'll already be required to
simulate your testbench before committing your code change.
The only new thing you have to do is add the 1 line of assertion
statement in your module.

So when a change is made to the pipeline depth a change will need to be
made for adjusting the delay pipeline in two places.

A change is need in two places: the pipeline depth inside the module and
the constant in the package.

The assert statement checks one against the other and won't need to be
changed. You're doing something wrong if you need to change the assert
statement as well, because then you're not checking the constant in the
package directly against the thing it's meant to track.


One to check the
other. I guess that's one way to make this work.

Are you implying you have a better way (that works with the current
language and tools)? Please tell - I'm always happy to learn new
techniques.

Allan
 
On 8/13/2016 12:58 AM, Allan Herriman wrote:
On Fri, 12 Aug 2016 23:28:13 -0400, rickman wrote:

On 8/12/2016 11:09 PM, Allan Herriman wrote:
On Fri, 12 Aug 2016 10:12:40 -0700, Ilya Kalistru wrote:

On Friday, August 12, 2016 at 5:39:36 PM UTC+3, Jim Lewis wrote:
I would put a constant in a package that is associated with a
particular entity. As you do your detailed design and update the
pipeline in a particular block, simply update the corresponding
constant in the package - even better would be to use that constant
to define the number of pipeline stages in the block.

Then any design that references the package can see the constant.

That's exactly what I've done. But when you are modifying the module
you have to remember that somewhere in a different file (package)
there is a constant you have to adjust according to you changes.


I contend that you *don't* have to remember to adjust that, as long as
you:

1. Write an assert statement inside your module that checks that the
package constant has the value that matches your design. I suggest a
higher severity level on the assertion, e.g. failure.

2. You remember to simulate your design (so that the assertion can be
checked). I wouldn't rely on a synthesiser to check an assertion, but
all simulators should work properly.


(In any reasonable development process) you'll already be required to
simulate your testbench before committing your code change.
The only new thing you have to do is add the 1 line of assertion
statement in your module.

So when a change is made to the pipeline depth a change will need to be
made for adjusting the delay pipeline in two places.


A change is need in two places: the pipeline depth inside the module and
the constant in the package.

The assert statement checks one against the other and won't need to be
changed. You're doing something wrong if you need to change the assert
statement as well, because then you're not checking the constant in the
package directly against the thing it's meant to track.

Not sure what you are saying about "pipeline depth". The module has
functionality that uses some number of logic pipeline stages. This has
to be noted in the module as a constant to use in the assert statement,
otherwise it is not needed in the module. This value also must be noted
as a constant in the package to correspond to the module. These two
values must be kept in sync and also aligned with the design of the module.

Maybe this is not as big issue as I am thinking since it is not likely
the modules will change pipeline depths. Rather modules will be added
or replaced by other modules. But in addition to keeping the two
constants in sync with the module design, the use of the module has to
be kept in sync with the corresponding constant being passed into the
module as well as the use in defining the delay pipeline.

This sounds like a lot of work to me and potentially error prone which
is what it is trying to prevent. It also ends up being a bit verbose
which is one of the problems with VHDL. The use of various tools has
made design of VHDL code a bit easier, but I know I get tired of all the
typing I have to do when making changes which end up being manual mostly.


One to check the
other. I guess that's one way to make this work.

Are you implying you have a better way (that works with the current
language and tools)? Please tell - I'm always happy to learn new
techniques.

My opinion is to not do it at all. The documentation of the module can
provide the logic pipeline depth used and the designer can work it out
in the unit using the module. I think that would be easier and less
error prone in real usage. I can't tell how many times I have gone to
lengths to try to prevent errors only to find I have done more work that
is useful. Sometimes simpler is better.

--

Rick C
 
On Saturday, August 13, 2016 at 8:33:15 AM UTC+3, rickman wrote:
On 8/13/2016 12:58 AM, Allan Herriman wrote:
On Fri, 12 Aug 2016 23:28:13 -0400, rickman wrote:

On 8/12/2016 11:09 PM, Allan Herriman wrote:
On Fri, 12 Aug 2016 10:12:40 -0700, Ilya Kalistru wrote:

On Friday, August 12, 2016 at 5:39:36 PM UTC+3, Jim Lewis wrote:
I would put a constant in a package that is associated with a
particular entity. As you do your detailed design and update the
pipeline in a particular block, simply update the corresponding
constant in the package - even better would be to use that constant
to define the number of pipeline stages in the block.

Then any design that references the package can see the constant.

That's exactly what I've done. But when you are modifying the module
you have to remember that somewhere in a different file (package)
there is a constant you have to adjust according to you changes.


I contend that you *don't* have to remember to adjust that, as long as
you:

1. Write an assert statement inside your module that checks that the
package constant has the value that matches your design. I suggest a
higher severity level on the assertion, e.g. failure.

2. You remember to simulate your design (so that the assertion can be
checked). I wouldn't rely on a synthesiser to check an assertion, but
all simulators should work properly.


(In any reasonable development process) you'll already be required to
simulate your testbench before committing your code change.
The only new thing you have to do is add the 1 line of assertion
statement in your module.

So when a change is made to the pipeline depth a change will need to be
made for adjusting the delay pipeline in two places.


A change is need in two places: the pipeline depth inside the module and
the constant in the package.

The assert statement checks one against the other and won't need to be
changed. You're doing something wrong if you need to change the assert
statement as well, because then you're not checking the constant in the
package directly against the thing it's meant to track.

Not sure what you are saying about "pipeline depth". The module has
functionality that uses some number of logic pipeline stages. This has
to be noted in the module as a constant to use in the assert statement,
otherwise it is not needed in the module. This value also must be noted
as a constant in the package to correspond to the module. These two
values must be kept in sync and also aligned with the design of the module.

Maybe this is not as big issue as I am thinking since it is not likely
the modules will change pipeline depths. Rather modules will be added
or replaced by other modules. But in addition to keeping the two
constants in sync with the module design, the use of the module has to
be kept in sync with the corresponding constant being passed into the
module as well as the use in defining the delay pipeline.

This sounds like a lot of work to me and potentially error prone which
is what it is trying to prevent. It also ends up being a bit verbose
which is one of the problems with VHDL. The use of various tools has
made design of VHDL code a bit easier, but I know I get tired of all the
typing I have to do when making changes which end up being manual mostly.


One to check the
other. I guess that's one way to make this work.

Are you implying you have a better way (that works with the current
language and tools)? Please tell - I'm always happy to learn new
techniques.

My opinion is to not do it at all. The documentation of the module can
provide the logic pipeline depth used and the designer can work it out
in the unit using the module. I think that would be easier and less
error prone in real usage. I can't tell how many times I have gone to
lengths to try to prevent errors only to find I have done more work that
is useful. Sometimes simpler is better.

--

Rick C

hm... It's sad that there is no such thing like output generic. It would make a lot of things much easier.

BTW when it comes to simulation, I have a method I use to check correctness of pipelines length:
There is usually something like Data.Valid signal or Data.EndOfPacket signal or something like that. When you merge two pipelines you usually really need only one of them from one of the pipelines, but I make an assert to check that both of them are aligned.
Sometimes I even add such a signal just for debugging purposes.
Unfortunately, it's not always possible.
 
Often when I design a pipelined module I use the globally available latency property/constant to specify the signals holding the pipeline registers, for example to create the delayline/std_logic_vector between an input and an output data valid signal. If there is no data valid and the property isn't used elsewhere in the module's design it should still be used in the testbench for the module to check that the expected output is present latency clock cycles after the test input is applied. If you forget to update the property when changing the pipeline depth you will find out when running your testbench and not when someone starts using your module *and* your latency constant.

I would not like to maintain the same latency number at multiple places as that would violate the DRY principle (Don't Repeat Yourself). Note that the DRY principle applies to documentation as well. If the latency changes you have to update the documentation as well as all copies of that number made by users of that module after reading the documents (unless the docs points to the constant).

When talking about properties I think it's worth mentioning user-defined attributes. They are not well-supported by tools and I think the purpose was to use them as tools directives rather than within the VHDL model itself. Still, you can define a latency attribute and use that to decorate an entity with a latency value that can be accessed by other modules. With that approach there is no need to create a package in order to export this property.
 
On Sat, 13 Aug 2016 15:02:22 -0700, Lars Asplund wrote:

Often when I design a pipelined module I use the globally available
latency property/constant to specify the signals holding the pipeline
registers, for example to create the delayline/std_logic_vector between
an input and an output data valid signal. If there is no data valid and
the property isn't used elsewhere in the module's design it should still
be used in the testbench for the module to check that the expected
output is present latency clock cycles after the test input is applied.
If you forget to update the property when changing the pipeline depth
you will find out when running your testbench and not when someone
starts using your module *and* your latency constant.

I would not like to maintain the same latency number at multiple places
as that would violate the DRY principle (Don't Repeat Yourself). Note
that the DRY principle applies to documentation as well. If the latency
changes you have to update the documentation as well as all copies of
that number made by users of that module after reading the documents
(unless the docs points to the constant).

When talking about properties I think it's worth mentioning user-defined
attributes. They are not well-supported by tools and I think the purpose
was to use them as tools directives rather than within the VHDL model
itself. Still, you can define a latency attribute and use that to
decorate an entity with a latency value that can be accessed by other
modules. With that approach there is no need to create a package in
order to export this property.

I don't have a copy of the LRM handy to check this, but I thought (and
hopefully I am wrong here) that a user defined attribute associated with
an entity could only be used inside that entity or architectures of that
entity, and not in an architecture that instantiates that entity (which
is where we want it).

For example, I *wouldn't* be able to say:

my_label : work.my_entity
generic map ( ... )
port map ( ... );

report some_type'image(my_label'my_attribute);


I'd be very happy to be proven wrong on this.

Thanks,
Allan
 
You will have to do

report some_type'image(work.my_entity'my_attribute);

Your report statement would report the attribute for the instance label which would work if it was specified for that label. Not what we want in this case though.

/Lars
 
I think this approach would be somewhat limited to entities. The attribute should really be placed on the architecture since you may have several with different latencies but I don't think you can denote an architecture with a selected name like I did in the report statement to denote the entity. A workaround would be to have several attributes, one for each architecture or maybe an attribute of a record type which has an element for each architecture. Not great since you cannot use the same attribute for all modules but you have the same problem when using constants.
 
You're right, it wouldn't work when the latency is a function of the generics. I haven't experienced this to be the typical case but if you run into that situation the module would have to provide a latency function in a package.

If the latency of a module is a function of its submodules, for example the sum of the latency for two chained submodules plus some extra pipelining introduced by the module itself you would still be able to use the attribute since it can be assigned an expression

If we continue to ignore tool support and only discuss what's legal in the language I guess it would be possible to create a latency constant in the architecture which is initialized with a latency function based on the generics. That constant can then be referenced using external names. This would be DRY, there is no extra package, you can separate different instances, and you don't have to change the references if the generics and the latency function signature changes.
 
On Sat, 13 Aug 2016 23:59:10 -0700, lars.synective wrote:

You will have to do

report some_type'image(work.my_entity'my_attribute);

Your report statement would report the attribute for the instance label
which would work if it was specified for that label. Not what we want in
this case though.

/Lars

That doesn't really work for the original problem though, as the
attribute value will typically be a function of the generics (in the
generic map), and thus it will be different for each instantiation.

The label is the only thing that identifies an instantiation of an entity
(as opposed to the entity itself). But, as you say, it's not what we
want in this case. :(

Thanks,
Allan
 
On Thursday, August 11, 2016 at 4:53:11 PM UTC-4, Ilya Kalistru wrote:
On Thursday, August 11, 2016 at 7:30:20 PM UTC+3, KJ wrote:
On Thursday, August 11, 2016 at 10:55:20 AM UTC-4, Ilya Kalistru wrote:

Is there a way to set latency of the module as some “property” in it, so
that a top module could read it and adjust delay lines? Something like
reversed generics – generics pass parameter to a module but I need to pass
it from the module.

Presumably, the amount of latency of a particular module is either fixed or is a function of the generic inputs to that module. Since those generics are available to the top level module as well, then a function can be created that calculates the latency of all of the modules and then uses those latencies to define the amount of latency required at the top.

Kevin Jennings

I don't think so. Latency depends on algorithms, how they are implemented
and how well the module is optimized. All that could (and will) change
during product development.

It depends on the algorithm, period. Once the source code for the module is written, the latency number has been locked down. The number of pipeline stages will be determined once the algorithm is coded. At that point you know the number and that number can then be put into a package along with other module related things. If you later change the algorithm in some way that changes the number of pipeline stages, you change the number...to match the change in the algorithm. Not rocket science.

The point is to remove any dependency for the user of the module from having to know what the latency is exactly. The user of the module just needs to know where to reference that number from which is in the package that comes along with the module.

Suggesting that the module should be developed so that the module creator should somehow be off the hook for defining and publishing in the package the latency number is misguided.

Kevin Jennings
 
On Thursday, August 11, 2016 at 12:55:11 PM UTC-4, rickman wrote:
A module passes signals in and out. You can create a constant integer
output signal. Nothing fancy needed. Add up all the delays and
subtract from the longest to get the additional pipeline stages needed.

These values will only be used in generate statements so it won't create
any logic. You may get warnings of signals that are deleted for having
no source and/or no destination. Personally I hate that. A design
should be synthesized without warnings.

A signal cannot be used to control generate statements. A signal can also not be used to define the value of a constant. It doesn't matter if that signal is coded to be a constant within the module.

Kevin Jennings
 

Welcome to EDABoard.com

Sponsor

Back
Top