RFC on VHDL LRM 93[8.4.1]

  • Thread starter yaveh (Yet Another Vhdl E
  • Start date
Y

yaveh (Yet Another Vhdl E

Guest
Hello!

I am currently doing some testbench pre-studies involving some Mixed
Analogue Digital (MAD:)
components, and have tried an implementation using global signals
(signals defined in a package)
to communicate events between the different instances.

I have tried to provide the final testbench user with procedures (that
I had planned to write in the
package body) that drive these global signals with statements like
(code complexity reduced for posting):

procedure pulseA is
begin
sigA <= '1', '0' after 50 ns;
end;

only to find out that, according to LRM 93[8.4.1]:

[..]
If a given procedure is declared by a declarative item that is not
contained within a process statement, and if a signal assignment
statement appears in that procedure, then the target of the assignment
statement must be a formal parameter of the given procedure or of a
parent of that procedure, or an aggregate of such formal parameters.
[..]

NOTES
1--These rules guarantee that the driver affected by a signal
assignment statement is always statically determinable [..] In this
case, the affected driver is the one defined by the process[..]

In short words: My implementation doesn´t work.

However, I would say that if the main purpose of these particular rules
is to "guarantee that the driver affected by a signal assignment
statement is always statically determinable", the driver that the
signal assignment
statement in the package body affects is in my opinion static.

Any other opinion?

Best thanks in advance for a fruitful conversation,

yaveh (Yet Another Vhdl/Verification Engineer Hoping)
 
yaveh (Yet Another Vhdl Engineer Hoping) a écrit :

Hello!
Hello,

[...]
In short words: My implementation doesn´t work.
Yes :-(

However, I would say that if the main purpose of these particular rules
is to "guarantee that the driver affected by a signal assignment
statement is always statically determinable", the driver that the
signal assignment
statement in the package body affects is in my opinion static.
Yes it is. The note is not well written.

The drivers of a process must be easily extracted. Easily means during
process analysis.

JD.
 
I'm not sure, but I think the goal of the LRM limitation was to be able
to _locally_ statically determine the list of signals that a process
(implied or explicit) drives. Changing that would mean that the list
would not be available until during/after elaboration, which is when
the list of drivers for each signal is trying to be built. Your
proposed change would not be trivial to implement. Perhaps the LRM
limitation could be restated in such terms (assuming that was the
goal), to allow procedures declared within an architecture to drive
signals/ports declared within that entity/architecture, but that would
not help your situation.

To simplify the argument list on testbench procedures, I have used
record types, with an inout mode on the entire record port. That means
you can only use resolved types in the record, and every procedure must
drive a 'Z' on every element that is not really being driven from the
procedure. This works well for procedures like read(bus, addr, data),
etc. where bus is a record of all the signals of the bus (pci, vme,
60x, etc.)

One of the proposed new things to work on in future versions of VHDL is
"interfaces", whatever they mean by that... One nice thing to have
would be user-defined modes that define individual modes (in, out,
inout, etc.) on elements of record definitions, thus you could have a
"master" mode for a bus port on a procedure that initiates transactions
(like read(), write(), etc.), a "slave" mode for a bus port on a
procedure that only responds to transactions (like a memory, etc.), and
a "monitor" mode for procedures or entities that perform protocol
checking, etc. That would allow you to avoid using inout on everthing,
and to use unresolved data types in bus records that would greatly
speed up simulations.

Andy




yaveh (Yet Another Vhdl Engineer Hoping) wrote:
Hello!

I am currently doing some testbench pre-studies involving some Mixed
Analogue Digital (MAD:)
components, and have tried an implementation using global signals
(signals defined in a package)
to communicate events between the different instances.

I have tried to provide the final testbench user with procedures (that
I had planned to write in the
package body) that drive these global signals with statements like
(code complexity reduced for posting):

procedure pulseA is
begin
sigA <= '1', '0' after 50 ns;
end;

only to find out that, according to LRM 93[8.4.1]:

[..]
If a given procedure is declared by a declarative item that is not
contained within a process statement, and if a signal assignment
statement appears in that procedure, then the target of the assignment
statement must be a formal parameter of the given procedure or of a
parent of that procedure, or an aggregate of such formal parameters.
[..]

NOTES
1--These rules guarantee that the driver affected by a signal
assignment statement is always statically determinable [..] In this
case, the affected driver is the one defined by the process[..]

In short words: My implementation doesn´t work.

However, I would say that if the main purpose of these particular rules
is to "guarantee that the driver affected by a signal assignment
statement is always statically determinable", the driver that the
signal assignment
statement in the package body affects is in my opinion static.

Any other opinion?

Best thanks in advance for a fruitful conversation,

yaveh (Yet Another Vhdl/Verification Engineer Hoping)
 
yaveh (Yet Another Vhdl Engineer Hoping) wrote:
Dependencies are on primary design units. A package
body is a secondary design unit. Hence, you can
compile a new package body. Run a simulation with
a new package body without recompiling any of the
designs that reference it. Hence, "... no static at all" [Steely Dan].

Lets pretend that we removed the restriction in 8.4.1.
This would mean that you could drive global signals in
a procedure defined in a package. This does not seem like
a huge win. You could also write a procedure in an
architecture declaration region that drives signals in
the architecture - this is not a win at all since this
can already be done in a process.

One change in Accellera VHDL 2006 standard 3.0 (approved
at DAC and ready for adoption by industry) is the keyword
all in the sensitivity list in place of signal names.
This new feature is greatly simplified by 8.4.1. If I had
to choose, I would rather have this than that driving
global signals directly from a procedure.

To communicate between models in a testbench I use records.
See the second half of the paper: "Accelerating Verification
Through Pre-Use of System-Level Testbench Components"
which is posted at: http://www.synthworks.com/papers/
I will be writing a paper just on using the records as I
have some improvements over what is in the paper.

Cheers,
Jim


Hello!

I am currently doing some testbench pre-studies involving some Mixed
Analogue Digital (MAD:)
components, and have tried an implementation using global signals
(signals defined in a package)
to communicate events between the different instances.

I have tried to provide the final testbench user with procedures (that
I had planned to write in the
package body) that drive these global signals with statements like
(code complexity reduced for posting):

procedure pulseA is
begin
sigA <= '1', '0' after 50 ns;
end;

only to find out that, according to LRM 93[8.4.1]:

[..]
If a given procedure is declared by a declarative item that is not
contained within a process statement, and if a signal assignment
statement appears in that procedure, then the target of the assignment
statement must be a formal parameter of the given procedure or of a
parent of that procedure, or an aggregate of such formal parameters.
[..]

NOTES
1--These rules guarantee that the driver affected by a signal
assignment statement is always statically determinable [..] In this
case, the affected driver is the one defined by the process[..]

In short words: My implementation doesn´t work.

However, I would say that if the main purpose of these particular rules
is to "guarantee that the driver affected by a signal assignment
statement is always statically determinable", the driver that the
signal assignment
statement in the package body affects is in my opinion static.

Any other opinion?

Best thanks in advance for a fruitful conversation,

yaveh (Yet Another Vhdl/Verification Engineer Hoping)

--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jim Lewis
Director of Training mailto:Jim@SynthWorks.com
SynthWorks Design Inc. http://www.SynthWorks.com
1-503-590-4787

Expert VHDL Training for Hardware Design and Verification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
yaveh (Yet Another Vhdl Engineer Hoping) wrote:

procedure pulseA is
begin
sigA <= '1', '0' after 50 ns;
end;

In short words: My implementation doesn´t work.
I pass signal arguments to such procedures.
That works fine.
See the procedure toggle in the testbench here:

http://home.comcast.net/~mike_treseler/test_uart.vhd

-- Mike Treseler
 
Andy wrote:
One of the proposed new things to work on in future versions of VHDL is
"interfaces", whatever they mean by that... One nice thing to have
would be user-defined modes that define individual modes (in, out,
inout, etc.) on elements of record definitions, thus you could have a
"master" mode for a bus port on a procedure that initiates transactions
(like read(), write(), etc.), a "slave" mode for a bus port on a
procedure that only responds to transactions (like a memory, etc.), and
a "monitor" mode for procedures or entities that perform protocol
checking, etc. That would allow you to avoid using inout on everthing,
and to use unresolved data types in bus records that would greatly
speed up simulations.

I'm not sure what future VHDL 'interfaces' are either (perhaps Jim
would like to toss in a comment here) but I second you (almost totally)
about the concept of master and slave but would suggest that if you
have this concept you won't need to define directions for the
individual signals since they will be implied by the interface that it
is a part of.

Presumably an 'interface' would consist of some collection of signals,
so once you know if that a particular collection is a 'master' or a
'slave' then you know the following (which could all be checked at
compile time)...
- The direction of each signal within that collection had better agree
with the entire concept of 'master' and 'slave' or it's an error (i.e.
'read' is an output of a master, 'wait' is an input, etc.)
- Unless the interface is specifically declared to be multi-masterable,
there had better be only one master for each slave.

A component (or entity) then would consist of a number of interfaces
plus the inevitable occasional stragglers that don't want to fit into
the concept of an 'interface' without a struggle.

KJ
 
KJ wrote:

Andy wrote:

One of the proposed new things to work on in future versions of
VHDL is
"interfaces", whatever they mean by that... One nice thing to have
would be user-defined modes that define individual modes (in, out,
inout, etc.) on elements of record definitions, thus you could have
a "master" mode for a bus port on a procedure that initiates
transactions (like read(), write(), etc.), a "slave" mode for a bus
port on a procedure that only responds to transactions (like a
memory, etc.), and a "monitor" mode for procedures or entities that
perform protocol checking, etc. That would allow you to avoid using
inout on everthing, and to use unresolved data types in bus records
that would greatly speed up simulations.

I'm not sure what future VHDL 'interfaces' are either (perhaps Jim
would like to toss in a comment here)
See
http://groups.google.com/group/comp.lang.vhdl/msg/3b4a4deaaf8dca06?dmode=source&hl=en&output=gplain

Pretty much the same what you want. :)

--
Paul.
www.aimcom.nl
 
Thanks a lot to everyone for contributing to the discussion!

Jim Lewis wrote:
Dependencies are on primary design units. A package
body is a secondary design unit. Hence, you can
compile a new package body. Run a simulation with
a new package body without recompiling any of the
designs that reference it. Hence, "... no static at all" [Steely Dan].
I must agree then: It is actually "no static at all".

I just wanted to hide the implementation of these procedures in
the package body, so that the end user could just call them from
his/her process, withouth having to pass too many parameters or
knowing about the implementation.

I will have to think of other ways.

Jim Lewis wrote:
One change in Accellera VHDL 2006 standard 3.0 (approved
at DAC and ready for adoption by industry) is the keyword
all in the sensitivity list in place of signal names.
This new feature is greatly simplified by 8.4.1. If I had
to choose, I would rather have this than that driving
global signals directly from a procedure.
I also would find this "all" keyword very useful. But I must wait
until my simulator supports it...

Jim Lewis wrote:
To communicate between models in a testbench I use records.
That was my first approach too. However I work in a MAD (Mixed Analogue
Digital) environment, where the top level is a Verilog netlist, that is
why
I ressorted to global (in a package defined) signal records, then to
shared
variables, only to realise that I do need some event driven parts where
I must
use signals to synchronise, but that I could still use the shared
variables for
"information broadcast", but not for event triggering.

I definitively have to rethink my strategy.

yaveh()
 
"Paul Uiterlinden" <paulu@sx4all.nl> wrote in message
news:45354513$0$11688$e4fe514c@dreader14.news.xs4all.nl...
KJ wrote:


Andy wrote:

One of the proposed new things to work on in future versions of
VHDL is
"interfaces", whatever they mean by that... One nice thing to have
would be user-defined modes that define individual modes (in, out,
inout, etc.) on elements of record definitions, thus you could have
a "master" mode for a bus port on a procedure that initiates
transactions (like read(), write(), etc.), a "slave" mode for a bus
port on a procedure that only responds to transactions (like a
memory, etc.), and a "monitor" mode for procedures or entities that
perform protocol checking, etc. That would allow you to avoid using
inout on everthing, and to use unresolved data types in bus records
that would greatly speed up simulations.

I'm not sure what future VHDL 'interfaces' are either (perhaps Jim
would like to toss in a comment here)

See
http://groups.google.com/group/comp.lang.vhdl/msg/3b4a4deaaf8dca06?dmode=source&hl=en&output=gplain

Pretty much the same what you want. :)
Yep, exactly. On top of what Andy outlined I would add...

- One would need to have a 'complementary' set of each set of interface
signals. By that I mean, where you have a record type that defines the 'in'
and 'out' modes of each signal for 'master' and 'slave' you would then need
a different record type that has the same elements but the modes are
reversed. Andy's example didn't show it very well since he was indicating
how you would implement an interface for a simple point to point connection.
In a real design though the outputs of the 'master' would go to some address
decoding and/or arbitration logic which would then generate the signals
needed for the actual 'slave'. Given that picture one could see that the
slave peripheral's address would typically be narrower than the master
device and that the decode/arbitration logic would need to deal with both
record types as he defined as well as two that are the 'complements'. In
Andy's example the 'slave' record type happens to form this complement for
the 'master' record type but in general this would not be the case....it
would be handy if this type could be easily derived without copy/paste from
the original record type definition.
- One would not want to be limited to having address and data widths defined
as global bus constants. One should be able to define appropriate address
widths to match the address space of each peripheral and not require master
and slave peripherals to all act on globally defined data widths.

KJ
 
yaveh (Yet Another Vhdl Engineer Hoping) wrote:

I just wanted to hide the implementation of these procedures in
the package body, so that the end user could just call them from
his/her process, withouth having to pass too many parameters or
knowing about the implementation.
I will have to think of other ways.
One work-around is to package the procedure with
signal parameters that are then overloaded
in the calling process. The result is a small signal overload
procedure in each calling process but a common package.
The package hides the implementation from the processes
and the local procedure hides the signal list from
all of the calls in the process.

I ressorted to global (in a package defined) signal records, then to
shared
variables, only to realise that I do need some event driven parts where
I must
use signals to synchronise, but that I could still use the shared
variables for
"information broadcast", but not for event triggering.
I definitively have to rethink my strategy.
Any process can synchronize its inputs using local variables.
Signals or global variables are required to connect processes.

-- Mike Treseler
 
KJ,

For demonstration purposes, "master" and "slave" are admittedly simple.
Are you wanting to be able to declare a mode "master", and then be able
to declare a slave mode as "inverse of master"? I think the actual
occurrences of one mode being the true complement of another in real
life would not be that common, especially for the largest busses where
it would save the most typing. That would be a little extra frosting on
the cake, though.

As for things like address decoding, etc., I prefer to distribute that
to the slaves (with appropriate parameters passed to them as generics
or ports), and send the entire bus to them. The synthesis tool will
throw out what it doesn't need. This greatly simplifies the
higher-level architecture and plumbing. Multi-master arbitration
probably would be centralized, and would have a unique mode defined for
it. The arbiter could hook up to the entire record, and just not use
most of it, or you could have a separate (or sub-) record that was just
the arbitration portion of the bus, with it's own master (for the
arbiter) and slave (for the requesters) modes, with the arbiter only
attaching to the arbitration bus.

In addition, you would probably need a "monitor" mode for such busses,
to facilitate testbenches, etc., althought the predefined "in" mode
would likely work in most cases, and perhaps a combined master/slave
mode for nodes that could do both.

Andy


KJ wrote:
"Paul Uiterlinden" <paulu@sx4all.nl> wrote in message
news:45354513$0$11688$e4fe514c@dreader14.news.xs4all.nl...
KJ wrote:


Andy wrote:

One of the proposed new things to work on in future versions of
VHDL is
"interfaces", whatever they mean by that... One nice thing to have
would be user-defined modes that define individual modes (in, out,
inout, etc.) on elements of record definitions, thus you could have
a "master" mode for a bus port on a procedure that initiates
transactions (like read(), write(), etc.), a "slave" mode for a bus
port on a procedure that only responds to transactions (like a
memory, etc.), and a "monitor" mode for procedures or entities that
perform protocol checking, etc. That would allow you to avoid using
inout on everthing, and to use unresolved data types in bus records
that would greatly speed up simulations.

I'm not sure what future VHDL 'interfaces' are either (perhaps Jim
would like to toss in a comment here)

See
http://groups.google.com/group/comp.lang.vhdl/msg/3b4a4deaaf8dca06?dmode=source&hl=en&output=gplain

Pretty much the same what you want. :)

Yep, exactly. On top of what Andy outlined I would add...

- One would need to have a 'complementary' set of each set of interface
signals. By that I mean, where you have a record type that defines the 'in'
and 'out' modes of each signal for 'master' and 'slave' you would then need
a different record type that has the same elements but the modes are
reversed. Andy's example didn't show it very well since he was indicating
how you would implement an interface for a simple point to point connection.
In a real design though the outputs of the 'master' would go to some address
decoding and/or arbitration logic which would then generate the signals
needed for the actual 'slave'. Given that picture one could see that the
slave peripheral's address would typically be narrower than the master
device and that the decode/arbitration logic would need to deal with both
record types as he defined as well as two that are the 'complements'. In
Andy's example the 'slave' record type happens to form this complement for
the 'master' record type but in general this would not be the case....it
would be handy if this type could be easily derived without copy/paste from
the original record type definition.
- One would not want to be limited to having address and data widths defined
as global bus constants. One should be able to define appropriate address
widths to match the address space of each peripheral and not require master
and slave peripherals to all act on globally defined data widths.

KJ
 
yaveh
To communicate between models in a testbench I use records.

That was my first approach too. However I work in a MAD (Mixed Analogue
Digital) environment, where the top level is a Verilog netlist, that is
why
I ressorted to global (in a package defined) signal records, then to
shared
variables, only to realise that I do need some event driven parts where
I must
use signals to synchronise, but that I could still use the shared
variables for
"information broadcast", but not for event triggering.

I definitively have to rethink my strategy.
You can use global signals. You just can't reference
them by side-effect. You must pass them in as parameters.


Cheers,
Jim

--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jim Lewis
Director of Training mailto:Jim@SynthWorks.com
SynthWorks Design Inc. http://www.SynthWorks.com
1-503-590-4787

Expert VHDL Training for Hardware Design and Verification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
Andy wrote:
KJ,

For demonstration purposes, "master" and "slave" are admittedly simple.
Yes, I caught that. Just didn't want to get dinged for not 'noticing'
that the way you defined the slave and master that they already were
complements (I think so...pretty close if not exact). The fact that
they were is because of the particular example (and or bus definition)
that you hand in mind since your point was to demonstrate the
usefulness of being able to use signal direction as something
inherently useful for elements of a record and not just signals.

Are you wanting to be able to declare a mode "master", and then be able
to declare a slave mode as "inverse of master"? I think the actual
occurrences of one mode being the true complement of another in real
life would not be that common, especially for the largest busses where
it would save the most typing. That would be a little extra frosting on
the cake, though.
What I'm thinking is that an actual 'master' device and a 'slave'
device would not communicate directly. Instead each would talk to some
'glue logic'. The 'glue logic' is not just miscellaneous logic that
doesn't fit but would be (should be) automatically generated code that
would perform address decoding and arbitration functions. If you
consider that this 'glue logic' can be a simple VHDL entity
parameterized for things like address and data widths for both master
and slave side then this single entity can implement the bus protocol.

Unfortunately, I do this quite a bit when tying together components
using Altera's Avalon bus because the tool that they have for
generating this logic is fragile and tends to not work...at least not
for me. Although I've been primarily working with that bus protocol it
would apply to OpenCore's Wishbone bus as well. In any case, the code
you need to tie together masters and slave is what would need the
'complemented' modes. If you have in mind a different bus definition
where it is expected that every slave decode the full address the
usefulness of what I'm talking about may not be apparent. I'll simply
add that whether the full address decoding gets done either in some
'glue logic' + slave decoding or completely in the slave should produce
the exact same synthesis result.

As for things like address decoding, etc., I prefer to distribute that
to the slaves (with appropriate parameters passed to them as generics
or ports), and send the entire bus to them. The synthesis tool will
throw out what it doesn't need. This greatly simplifies the
higher-level architecture and plumbing.
Is this bus any sort of standard bus though? If it's 'your own' bus
then you can design it how you want but will have trouble finding
commerical IP that you can integrate it with. If it's a published or
industry standard (like Wishbone) or even something like Avalon that
comes from a particular FPGA vendor but is not really tied in any way
to their devices then how you do decoding, arbitration, etc. is
basically defined by that bus definition.

In the cases of Wishbone and Avalon, synthesis does quite well reducing
things down to their essentials without wasting much if anything as
well.

Multi-master arbitration
probably would be centralized, and would have a unique mode defined for
it. The arbiter could hook up to the entire record, and just not use
most of it, or you could have a separate (or sub-) record that was just
the arbitration portion of the bus, with it's own master (for the
arbiter) and slave (for the requesters) modes, with the arbiter only
attaching to the arbitration bus.
Again, once a bus definition exists, (standard or proprietary) this
would no longer be a design choice about where to put it.

KJ
 
Mike Treseler wrote:
yaveh (Yet Another Vhdl Engineer Hoping) wrote:

I just wanted to hide the implementation of these procedures in
the package body, so that the end user could just call them from
his/her process, withouth having to pass too many parameters or
knowing about the implementation.
I will have to think of other ways.


One work-around is to package the procedure with
signal parameters that are then overloaded
in the calling process. The result is a small signal overload
procedure in each calling process but a common package.
The package hides the implementation from the processes
and the local procedure hides the signal list from
all of the calls in the process.
-- Mike Treseler
I'm sorry Mike but I didn't understand what do you have to package if
than you will overload them all. I've run through your "uart" example
and I haven't seen any packaging, just overloading (but I might be
wrong). So what's the point of packaging? Can you post an example, please?

Thanks a lot

Al

--
Alessandro Basili
CERN, PH/UGC
Hardware Designer
 
Al wrote:

I'm sorry Mike but I didn't understand what do you have to package if
than you will overload them all.
A package is not required for a single process entity.
For multiple processes (or entities), the choices are to
either cut and paste the procedure and manually edit
the signal IDs or to package the the procedure with
signal IDs as arguments.

Can you post an example, please?
OK.

-- Mike Treseler
 
Al,
Mike Treseler wrote:
yaveh (Yet Another Vhdl Engineer Hoping) wrote:

I just wanted to hide the implementation of these procedures in
the package body, so that the end user could just call them from
his/her process, withouth having to pass too many parameters or
knowing about the implementation.
I will have to think of other ways.


One work-around is to package the procedure with
signal parameters that are then overloaded
in the calling process. The result is a small signal overload
procedure in each calling process but a common package.
The package hides the implementation from the processes
and the local procedure hides the signal list from
all of the calls in the process.
-- Mike Treseler

I'm sorry Mike but I didn't understand what do you have to package if
than you will overload them all. I've run through your "uart" example
and I haven't seen any packaging, just overloading (but I might be
wrong). So what's the point of packaging? Can you post an example, please?

Thanks a lot

Al
You actually use both.

The procedure in the package has implementation of the
algorithm/sequencing however, it also often has lots of
signals as parameters. Many of these signals just go
along for the ride.

The purpose of the procedure in the process is to simplify
the call interface. Since it is in a process, it can
leave off the signals that just go along for the ride since
it can access them via side-effects and it typically just
calls the procedure that is in the package.

Use this approach when you have multiple test architectures
that implement the test suite. This way changes to the
algorithm/sequencing gets limited to the subprogram in
the package. When there is just one test in a test suite,
there is not a compelling reason to use a package.

The downside to subprogram approaches is that they are
sequential. While sequential programs work well for many
things, there are many problems where the concurrency
is alot easier to visualize and write. So while a UART
transmitter is easy to implement sequentially, a UART
receiver (with its hunt state and 16X reference clock)
is much easier to implement concurrently - particularly if
you are coming from a hardware design background.

To get concurrency, I prefer to implement the algorithm/sequencing
in a BFM (Bus Functional Model) (aka Driver or Monitor in
Mentor's AVM) and communicate to it using a record
(see also the Analog_Guy post or the paper
"Accelerating Verification Through Pre-Use of System-Level
Testbench Components" on the synthworks website).
Using a BFM allows you to collect additional logic
with the functionality (such as protocol checkers and
assertions, ...). To the normal transactions I add
transactions to query the model about error status
when the testbench completes. This approach also works well
for side-band access to memory models (allowing peek,
poke, read file, and write file capability).

Cheers,
Jim
--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jim Lewis
Director of Training mailto:Jim@SynthWorks.com
SynthWorks Design Inc. http://www.SynthWorks.com
1-503-590-4787

Expert VHDL Training for Hardware Design and Verification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
Jim Lewis wrote:

The downside to subprogram approaches is that they are
sequential. While sequential programs work well for many
things, there are many problems where the concurrency
is alot easier to visualize and write. So while a UART
transmitter is easy to implement sequentially, a UART
receiver (with its hunt state and 16X reference clock)
is much easier to implement concurrently - particularly if
you are coming from a hardware design background.
However, for a hardware guy who has done
enough C to turn on a new circuit board,
a sequential hardware description can be addictive.
A good editor and interactive sim waveforms
can safely move the focus from gates and wires
to source code and functional performance.

Is the procedure rx_state in
http://home.comcast.net/~mike_treseler/uart.vhd
more difficult to follow than a
ten process version of the same thing?

-- Mike Treseler
 
Mike,
The downside to subprogram approaches is that they are
sequential. While sequential programs work well for many
things, there are many problems where the concurrency
is alot easier to visualize and write. So while a UART
transmitter is easy to implement sequentially, a UART
receiver (with its hunt state and 16X reference clock)
is much easier to implement concurrently - particularly if
you are coming from a hardware design background.

However, for a hardware guy who has done
enough C to turn on a new circuit board,
a sequential hardware description can be addictive.
A good editor and interactive sim waveforms
can safely move the focus from gates and wires
to source code and functional performance.

Is the procedure rx_state in
http://home.comcast.net/~mike_treseler/uart.vhd
more difficult to follow than a
ten process version of the same thing?
So you have coded the functionality as a single process,
however, there is more in verification model than just
functionality. There are protocol checkers, timing
checkers (such as a pulse width that spans multiple
clocks), results logging, ... Some of these execute based
on clock (as does everything in your design) and some execute
on a signal changing.

Going further, the point is that if I have an entity/BFM,
I have a choice of using independent processes or sequential
code and the coding style employed can suit the style of the
coder. With a subprogram one is limited to sequential code
- there is no fork and join and hence no concurrency. And
why would I want fork and join if I can use separate processes?

Back to your statement, anyone can write bad code such as you
suggest with a 10 process version. Or if you read one of the
VHDL texts, anyone can implement a simple 2-input "OR" in a
process with if statements or implement an adder with "AND",
"OR" and "XOR".

I find a well written 2 process or even a 1 process state machine
with independent support logic in separate processes easy to
read. It suits me, I am productive writing it, and
others find it reasonable to read.

With yours, since it has so many nested procedure
calls, I have to spend some time descending through it
before I can understand any of it. Perhaps it is
something I could make friends with, perhaps not,
I find I really can't comment on some coding styles
until I have tried it myself.

Having done synthesis for some time, I value separability
of code so that when a synthesis tool does a poor
implementing a particular construct, I can easily isolate
it and make attempts at improving the implementation
by changing the code. Having worked as a consultant the
statement a customer does not want to here is that the
synthesis tool they just spent $$$$K on sucks. Instead
they would prefer to hear, the synthesis tool is giving
us some issues with some code, however, with some small
tweaks we will get it to produce the implementation
we need. Ok so I have suffered through more than one
project using either Synopsys DC or FPGA compiler for an
FPGA design. As a result, I tend to protect myself
more than the coding style you enjoy affords.

Cheers,
Jim
--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jim Lewis
Director of Training mailto:Jim@SynthWorks.com
SynthWorks Design Inc. http://www.SynthWorks.com
1-503-590-4787

Expert VHDL Training for Hardware Design and Verification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
Jim Lewis wrote:

So you have coded the functionality as a single process,
however, there is more in verification model than just
functionality. There are protocol checkers, timing
checkers (such as a pulse width that spans multiple
clocks), results logging, ... Some of these execute based
on clock (as does everything in your design) and some execute
on a signal changing.
I agree. I also use multiple processes
for a verification architecture.

Going further, the point is that if I have an entity/BFM,
I have a choice of using independent processes or sequential
code and the coding style employed can suit the style of the
coder. With a subprogram one is limited to sequential code
- there is no fork and join and hence no concurrency. And
why would I want fork and join if I can use separate processes?
For synthesis I like to use a single threaded description
for each entity that updates variables and output
ports every clock tick. The only way to arrange
this is to use a single process per entity.

I use functions and procedures to collect duplicate blocks of
code and to give them plain English identifiers.
I leave it to synthesis to convert this logical
description to a netlist of real, concurrent gates and flops.
There is no requirement for the design code itself to
be concurrent. It's just a question of style.

Back to your statement, anyone can write bad code such as you
suggest with a 10 process version. Or if you read one of the
VHDL texts, anyone can implement a simple 2-input "OR" in a
process with if statements or implement an adder with "AND",
"OR" and "XOR".
I agree.
The point I was after, is that most conventional
design entities have more than several processes
with more than several signals dedicated to
wiring them together. In a single process design,
all of this carefully described wiring melts
away for synthesis to infer.

I find a well written 2 process or even a 1 process state machine
with independent support logic in separate processes easy to
read. It suits me, I am productive writing it, and
others find it reasonable to read.
I'm sure I would too.
If you promise not to and a fourth process later :)

With yours, since it has so many nested procedure
calls, I have to spend some time descending through it
before I can understand any of it. Perhaps it is
something I could make friends with, perhaps not,
I find I really can't comment on some coding styles
until I have tried it myself.
So I guess the choice is a nest of procedures
or nest of wires :)

Having done synthesis for some time, I value separability
of code so that when a synthesis tool does a poor
implementing a particular construct, I can easily isolate
it and make attempts at improving the implementation
by changing the code. Having worked as a consultant the
statement a customer does not want to here is that the
synthesis tool they just spent $$$$K on sucks. Instead
they would prefer to hear, the synthesis tool is giving
us some issues with some code, however, with some small
tweaks we will get it to produce the implementation
we need.
Very smooth.
Too bad that the customer is always right :)

Ok so I have suffered through more than one
project using either Synopsys DC or FPGA compiler for an
FPGA design. As a result, I tend to protect myself
more than the coding style you enjoy affords.
You've got me there.
My stuff is guaranteed *not* to work with any of those.
But it does work fine with all the others.

Thanks for the chat.

-- Mike Treseler
 

Welcome to EDABoard.com

Sponsor

Back
Top