upside down generics or so

On Friday, August 12, 2016 at 1:12:48 PM UTC-4, 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.

Typically I have the package, entity and architecture all in the same file. There are cases where I've put the architecture in a separate file, I don't recall a single instance where the package and entity needed to be in separate files. But yes you still have to put that latency number change in.

What I do to 'remember' to make this package change is to put an assertion in to check that the actual latency through the module matches the number in the package. When the assertion fails, I suddenly 'remember' that the latency number needs to be updated...or sometimes that I've made an incorrect change to the algorithm.

The case of a constant (disregarding changes made during development) is easy, just put the number in the package. The more complex case where maybe the module has different, static ways of being used that are selected by entity generics simply means that the package should have a function that gets passed the values of the entity generics and uses those to compute the latency. To the user of the module, that means that yes they need to make sure that they use the same generics in the call to the function to determine the latency as they do when they instantiate the entity but once again, having an assertion in the architecture code that measures the actual latency and checks it to the expected latency as defined by the package function is the way that you can provide reasonable coverage of this type of misuse of the module.

Kevin Jennings
 
On Saturday, August 13, 2016 at 1:33:15 AM UTC-4, rickman wrote:
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.

No, the code in the module would use the constant defined in the package. The pipeline depth number or latency number whatever it is called would be in one place, in the package.

Kevin Jennings
 
On Saturday, August 13, 2016 at 12:45:26 PM UTC-4, Ilya Kalistru wrote:
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.

I don't think you've shown in what way it would be 'easier'. The only thing different is where you type in the value of the constant. Maybe it's 'easier' to type it in the architecture, but it's shouldn't really be 'harder' to type it into the package. Modules typically have packages that are paired with the entity/architecture.

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.

What were the details of the case where this was not possible?

Kevin Jennings
 
Don't get me wrong, I use the package constant like most of you. However, I tested the architecture internal constant accessed by the user using external names just to make sure that it works. Well, it works in simulation (ModelSim).

The user would get the latency or some other property with something like this

<<constant my_inst.properties.latency : natural>>

Very direct. Ask the object to which the property belongs (the instance). No need to know if the property is a function of the generics or not.

But, as can be expected, it doesn't pass synthesis. At least not with Vivado.
 
On 8/15/2016 7:55 AM, KJ wrote:
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.

No, and the fact that this will cause errors from forgetting to change
corresponding data in other modules is not rocket science either.


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.

I don't understand why you say this. If you could design the module to
return a value telling you the number of pipeline stages so the data did
not need to be separately maintained in other module it would be less
error prone. But there doesn't seem to be a way for a module to return
a generic.

--

Rick C
 
On 8/15/2016 8:17 AM, KJ wrote:
On Saturday, August 13, 2016 at 1:33:15 AM UTC-4, rickman wrote:

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.

No, the code in the module would use the constant defined in the
package. The pipeline depth number or latency number whatever it is
called would be in one place, in the package.

Whooosh! I am talking about the assert statement that verifies the
constant in the package has been updated to agree with the code in the
module. If you don't have error checking and the module is updated
without updating the constant in the package, you get messed up code and
a debug problem. That is why the assert statement was suggested. I'm
simply pointing out that this won't prevent the error, just detect it in
most cases. The returned generic from the module is still a better way
to go if it were possible.

It seems Lars has a method that might work for tools other than Vivaldo
and keep all the information in one place.

--

Rick C
 
On Tuesday, August 16, 2016 at 12:43:22 AM UTC-4, rickman wrote:
On 8/15/2016 7:55 AM, KJ wrote:

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.

No, and the fact that this will cause errors from forgetting to change
corresponding data in other modules is not rocket science either.

The error gets checked by the assertion in the testbench. So, on the assumption that one would run their testbench after entering a design change then the error gets immediately caught. Not much different in that regard then when I mistype something and the compiler catches the error. Yes you did have to write the code that does the checking and get that all working whereas the typo gets caught by code that has had a lot more eyeballs looking at it and a lot more users using it, but the point is that once that checking code is debugged and working then when a design error gets created via a design change, the code does catch it...if you simulate your design.

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.

I don't understand why you say this. If you could design the module to
return a value telling you the number of pipeline stages so the data did
not need to be separately maintained in other module it would be less
error prone. But there doesn't seem to be a way for a module to return
a generic.

I'm not disagreeing that if you could create a constant output that could in all cases be used just like a real constant then this would provide a different method to accomplish the goal. Some can see it as better, some just see it as different, that's OK.

I think it would be useful. But I would want to be able to use that output constant just like any other constant. So, based on the latency for a number of modules cascaded together, I could compute the depth of a memory that will be needed to collect up all the pipelined data that comes out after the output interface says to wait. Or to use that constant in a generate statement. Stuff like that.

But as far I've seen in this discussion, that number still looks like it gets typed into the architecture and is therefore potentially wrong. If you change the design to add another pipeline stage, that number doesn't magically change to the new number so you have an error. Bantering about whether to change a typed in number in the architecture or the package ***for that same module*** is splitting hairs.

For it truly to be correct by design, that constant output should be calculated from the number of pipeline stages in the design. So if you add/remove a pipeline stage, nothing else need be done because the output constant would have a formula to it not just a number (i.e. Pipe_Stages <= Pipeline'length). Maybe that is what the OP is doing anyway rather than actually having a physically typed in number (i.e. Pipe_Stages <= 3).

Maybe someone should suggest the idea of entity output constants that can be used as we use constants today as an enhancement to the VHDL standard. I know Jim Lewis is looking for more work (**not**) to pile on to the next revision of the standard. But if anyone wants to take up the torch, go to
http://www.eda-twiki.org/cgi-bin/view.cgi/P1076/WebHome

Kevin Jennings
 
Am 08/12/2016 um 07:12 PM schrieb Ilya Kalistru:
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.

Maybe you can use assertions to check the package defined value against
the one used in your entity. When the assertion fails, your synthesize
or simulation tool will stop working and reports the problem.
 
On Monday, August 15, 2016 at 3:22:13 PM UTC+3, KJ wrote:
On Saturday, August 13, 2016 at 12:45:26 PM UTC-4, Ilya Kalistru wrote:
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.


I don't think you've shown in what way it would be 'easier'. The only thing different is where you type in the value of the constant. Maybe it's 'easier' to type it in the architecture, but it's shouldn't really be 'harder' to type it into the package. Modules typically have packages that are paired with the entity/architecture.

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.

What were the details of the case where this was not possible?

Kevin Jennings


> I don't think you've shown in what way it would be 'easier'.

I mean that if you have it right in the architecture section it's more likely to
spot that constant during the process of code editing than if have it in a
package.


> What were the details of the case where this was not possible?

Sorry - maybe "possible" is a wrong word. It's better to say that it can be not so
handy. For example you have a module where data go without any distinct
Data.Valid or Data.Last signal and to implement that technique you add
artificial signal which goes along with data through all the stages and is
meant to be checked during simulation, but be removed by synsesizer as
a signal without load. In that case you have to do additional work to add that
superfluous signal. Moreover, when I was editing one of such modules once, I
added another stage to data processing but forgot to add another stage to
that additional signal. During testing process I didn't see reports on wrong
latencies but saw corrupted data and it took me awhile to find the mistake.
 
> I don't think you've shown in what way it would be 'easier'.

I mean that if you have it right in the architecture section it's more likely to
spot that constant during the process of code editing than if have it in a
package.


> What were the details of the case where this was not possible?

Sorry - maybe "possible" is a wrong word. It's better to say that it can be not so
handy. For example you have a module where data go without any distinct
Data.Valid or Data.Last signal and to implement that technique you add
artificial signal which goes along with data through all the stages and is
meant to be checked during simulation, but be removed by synthesizer as
a signal without load. In that case you have to do additional work to add that
superfluous signal. Moreover, when I was editing one of such modules once, I
added another stage to data processing but forgot to add another stage to
that additional signal. During testing process I didn't see reports on wrong
latencies but saw corrupted data and it took me awhile to find the mistake.
 
On 8/16/2016 9:41 AM, KJ wrote:
On Tuesday, August 16, 2016 at 12:43:22 AM UTC-4, rickman wrote:
On 8/15/2016 7:55 AM, KJ wrote:

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.

No, and the fact that this will cause errors from forgetting to
change corresponding data in other modules is not rocket science
either.


The error gets checked by the assertion in the testbench. So, on the
assumption that one would run their testbench after entering a design
change then the error gets immediately caught. Not much different in
that regard then when I mistype something and the compiler catches
the error. Yes you did have to write the code that does the checking
and get that all working whereas the typo gets caught by code that
has had a lot more eyeballs looking at it and a lot more users using
it, but the point is that once that checking code is debugged and
working then when a design error gets created via a design change,
the code does catch it...if you simulate your design.

Yes, there is the extra code which has to be made to work... but error
checking code is also extra testing. One mistake is to write it so it
doesn't flag errors at all so it has to be tested to show it catches
errors which is a PITA. Eyeballs are not a good way to catch errors
like this. Eyes glaze over reading code and miss important details.

Bottom line is having one location for a constant is a whole lot better
than maintaining values in two places with error checking.


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.

I don't understand why you say this. If you could design the
module to return a value telling you the number of pipeline stages
so the data did not need to be separately maintained in other
module it would be less error prone. But there doesn't seem to be
a way for a module to return a generic.

I'm not disagreeing that if you could create a constant output that
could in all cases be used just like a real constant then this would
provide a different method to accomplish the goal. Some can see it
as better, some just see it as different, that's OK.

I've identified specifically why this is preferred, unfortunately not
possible to do in the simple way hoped for, but there seems to be a way
to do it, perhaps.


I think it would be useful. But I would want to be able to use that
output constant just like any other constant. So, based on the
latency for a number of modules cascaded together, I could compute
the depth of a memory that will be needed to collect up all the
pipelined data that comes out after the output interface says to
wait. Or to use that constant in a generate statement. Stuff like
that.

That is exactly the point.


But as far I've seen in this discussion, that number still looks like
it gets typed into the architecture and is therefore potentially
wrong. If you change the design to add another pipeline stage, that
number doesn't magically change to the new number so you have an
error. Bantering about whether to change a typed in number in the
architecture or the package ***for that same module*** is splitting
hairs.

We can't eliminate mistakes. We can minimize the chance they will go
uncaught and minimize the difficulty in finding them. There is no
problem or difficulty with having one constant in the code module it is
related to that doesn't also exist in the method where the same constant
has to be maintained in two locations.


For it truly to be correct by design, that constant output should be
calculated from the number of pipeline stages in the design. So if
you add/remove a pipeline stage, nothing else need be done because
the output constant would have a formula to it not just a number
(i.e. Pipe_Stages <= Pipeline'length). Maybe that is what the OP is
doing anyway rather than actually having a physically typed in number
(i.e. Pipe_Stages <= 3).

Maybe someone should suggest the idea of entity output constants that
can be used as we use constants today as an enhancement to the VHDL
standard. I know Jim Lewis is looking for more work (**not**) to
pile on to the next revision of the standard. But if anyone wants to
take up the torch, go to
http://www.eda-twiki.org/cgi-bin/view.cgi/P1076/WebHome

Kevin Jennings

--

Rick C
 
Maybe that is what the OP is doing anyway rather than actually having a
physically typed in number (i.e. Pipe_Stages <= 3).

Upper levels of design calculate their latency based on the length of lower-lewel
modules and length of latency adjusting buffers of different sub-pipelines, but
modules on the lowest level of hierarchy which really do stuff have their latency
as a physically typed number.

Unfortunately, I don't know how to calculate it automatically. :(
 
> Bantering about whether to change a typed in number in the architecture or the package ***for that same module*** is splitting hairs.

Asking the object that actually creates the latency property (the module instance) rather than another object (the package) associated with that first object enables better information hiding. We saw that in the example of a latency depending on the generics. This is, to me, a significant difference.. Keeping the property close to its origin is probably less error-prone when we need to remember to keep things in sync but the difference to a package in the same file is probably minor.

> But I would want to be able to use that output constant just like any other constant

An external name like <<constant my_inst.properties.latency : natural>> can be used like any other constant. The only difference I can come to think of is that it can only be used after the target of the reference, in this case my_inst, has been elaborated. This is a bit inconvenient. If, for example, a module's latency depends on the latency for its submodules the latency constant cannot be placed in the architecture declarative part. It has to be placed after the submodules have been instantiated such that their latencies can be referenced with external names. One way of solving this, which I used in my example, is to have a block statement at the end of the architecture that contains the constant. I labeled this statement properties as can be seen in <<constant my_inst.properties.latency : natural>>

As an advocate for unit testing I don't mind at all if I have to add another unit test to check the provided latency. In case my module has no data valid signals there is no extra work since the latency constant will be used and verified anyway (to know when to verify the output for a given test input). If I have data valid signals it's easy to forget verifying the constant but such a design would often have a delayline between the input and output data valid defined as a std_logic_vector of latency length. If that doesn't match the main processing pipeline the tests will fail. There's still a risk that something like a "quick fix", adding an extra pipelining step on top of the original design, creates an off-by-one error in the latency constant not detected by the tests.
 

Welcome to EDABoard.com

Sponsor

Back
Top