vhdl questions from a verilog person

M

Mark Brehob

Hello all,
I'm a teacher who has been teaching students Verilog for a while, but
for various reasons I've had to jump to VHDL for a certain course.
I've been writing a fair bit of simple VHDL stuff (basic DSP
algorithms), and found it both powerful and frustrating. Mostly I'm
trying to figure out if there are better ways to do things and why
VHDL and/or VHDL coders do certain things.

As a note most of my verilog experience is doing synthesizable ASIC
(with some FPGA) while my VHDL stuff is all FPGA based.

#1 Why no process(*) statement similar to always@*?

The vast majority of all process statements are either modeling
combinational logic or something that changes only on clock/reset.
Why doesn't VHDL have a process(*) kind of statement as verilog does
saying "this is combinational logic, update if any of the inputs
change". Having to get the process statement right is painful to
student (add a variable and forget to update the process line) and
further, Xilinx software (at least) just adds things to the process
list anyways with just a warning.


#2 How do I add two values both of which are arbitrary in size?

So say I have one STD_LOGIC_VECTOR that is X bits and one that is Y
bits. Is there a clean way to add them (into something of Z bits for
sake of argument)? I find myself casting to an integer (and back) to
get stuff to work but that's neither pretty nor probably a good
idea.


#3 Is there a good way to index an array with a STD_LOGIC_VECTOR?

Again, I found myself casting back and forth. I suspect here there is
a right way to do this and I'm just missing it.


#4 What's up with all the different ways to check for a rising edge of
a clock?

The code base I inherited uses rising_edge, but that seems to be
fairly uncommon if code I find on the net is any indicator. I think
I've seen three other ways to do it. (Old value was 0 new is one,
current value is 1 and there was a change event, and one other.) Is
there a good reason everyone doesn't just use rising_edge? Is there
something I'm missing?



I had a bunch of other questions, but of course I've forgotten (did my
coding over the weekend and I guess 48 hours ago is enough time to
forget). I'm mostly enjoying it, but as you might expect, it's
bringing back Ada nightmares. At the current time I feel like I'm
jumping through hoops to get around the strict type checking (just
like I recall doing years ago with Ada). C/Verilog people should not
have to deal with strict type checking :).

Humm, I guess I'd like thoughts on my coding style, but the students
are finishing "filling in the blanks" on my code, so that will have to
wait until next week.

Thanks in advance,
Mark
 
A

Andreas Ehliar

As a note most of my verilog experience is doing synthesizable ASIC
(with some FPGA) while my VHDL stuff is all FPGA based.

#1 Why no process(*) statement similar to always@*?

Hi,

you have already gotten some nice answers but I thought I'd chip in with
a few additional notes:

* It is much easier to write combinational logic outside of a process
in VHDL. When I was going from VHDL to Verilog I was very frustrated that
the only way to create a condition outside an always block was to use
the ? operation. In VHDL you have the "with foo select ..." construct
which is very nice if you need to create a multiplexer for example.

* I believe that vhdl-mode for Emacs is able to automatically update
a process sensitivity list for you but I haven't tried that myself.


And some encouragement: Think of how nice it will be to know that the
students' code will not contain any blocking/non-blocking races.

/Andreas
 
K

KJ

Mark Brehob said:
Hello all,

#1 Why no process(*) statement similar to always@*?

To frustrate people mostly.
The vast majority of all process statements are either modeling
combinational logic or something that changes only on clock/reset.
Why doesn't VHDL have a process(*) kind of statement as verilog does
saying "this is combinational logic, update if any of the inputs
change".

I think that is part of VHDL-2008...whenever the vendors get around to
implementing it in the tools.
Having to get the process statement right is painful to
student (add a variable and forget to update the process line)

That's one reason why this newsgroup generally does not recommend using
combinatorial processes. Use only clocked processes (with or without
variables as needs and whims dictate) and concurrent statements. Use
functions and procedures.

Another reason is that combinatorial processes are 'bad' is that one needs
to make sure that every signal gets assigned through every path. Generally
this gets handled by applying the 'default' value at the start of the
process. This is just more typing, effort, and trouble then using clocked
processes and concurrent statements.
and
further, Xilinx software (at least) just adds things to the process
list anyways with just a warning.

And there is the other reason for avoiding such beasts...having simulation
be different than synthesis because you missed the 'warning'.

Try to avoid teaching use of these things, you'll be helping them in the
long run by showing how to avoid three common design errors that require
debug time to root out the cause.
#2 How do I add two values both of which are arbitrary in size?

So say I have one STD_LOGIC_VECTOR that is X bits and one that is Y
bits. Is there a clean way to add them (into something of Z bits for
sake of argument)? I find myself casting to an integer (and back) to
get stuff to work but that's neither pretty nor probably a good
idea.

Not every signal needs to be defined as std_logic_vector though. If
something is inherently an integer, than define it that way you'll avoid the
casting.

If you do need vectors, then look as ieee.numeric_std for your arithmetic,
it will do the things you've mentioned. That package defines two vector
types called 'signed' and 'unsigned' that apply a specific numeric
interpretation to the vector, as opposed to std_logic_vector which is simply
a collection of bits. Again, to avoid a lot of type casting, it is usually
best to define things using the correct type instead of always using
std_logic_vector and casting. One place where you should stick with
std_logic_vector though is at the top level entity ports.
#3 Is there a good way to index an array with a STD_LOGIC_VECTOR?

Yes...use an integer instead, which is what you're doing with the casting
X(to_integer(unsigned(my_slv)) <= '1';
Again, I found myself casting back and forth. I suspect here there is
a right way to do this and I'm just missing it.

Casting is the only way to do it...if you start with the mindset that
everything must be std_logic_vector. Use of other data types that are more
appropriate to start with is the way to avoid the ugliness of excessive type
casts.
#4 What's up with all the different ways to check for a rising edge of
a clock?

I only use "if rising_edge(clock) then..." or "wait until
rising_edge(clock);" It's self documenting. I have no idea why people use
less clear ways of expressing something so simple, but you're right they
certainly do.
The code base I inherited uses rising_edge, but that seems to be
fairly uncommon if code I find on the net is any indicator.

Not everything on the net is worth spit though...
I think
I've seen three other ways to do it. (Old value was 0 new is one,
current value is 1 and there was a change event, and one other.) Is
there a good reason everyone doesn't just use rising_edge? Is there
something I'm missing?

I think the others are the ones missing something, not you.

Kevin Jennings
 
A

Andreas Ehliar

Actually, good coding style in Verilog completely eliminates that
problem. In my other class, the students build a synthisizable out-of-
order processor starting with an in-order processor. We've found that
blocking/non-blocking problems just don't occur if you follow simple
rules. We teach those rules as "required" and the problem go away.
See http://www.eecs.umich.edu/courses/eecs470/tools/verilog_guidelines.pdf
for a short summary.

Well, we teach more or less the same rules as well, but there is always
at least one group per year who manages to come up with some nice and
interesting blocking/non-blocking race condition :)

The course you are talking about sounds very interesting by the way,
I wish I could have attended such a course as an undergraduate student.
Do you know roughly how much time students spend doing the projects in
this course? Do they have to care about the efficiency of their
RTL code or do they only have to get it synthesizable?

/Andreas
 
M

Mark Brehob

And some encouragement: Think of how nice it will be to know that the
students' code will not contain any blocking/non-blocking races.

/Andreas

Actually, good coding style in Verilog completely eliminates that
problem. In my other class, the students build a synthisizable out-of-
order processor starting with an in-order processor. We've found that
blocking/non-blocking problems just don't occur if you follow simple
rules. We teach those rules as "required" and the problem go away.
See http://www.eecs.umich.edu/courses/eecs470/tools/verilog_guidelines.pdf
for a short summary.

Verilog has lots of problems (generate statement can really be a pain,
multi-port memories can be a huge challenge, etc.), but blocking/non-
blocking problems don't pop up after the first 2 weeks of the class.
Heck, type-checking problems are rare (but certainly happen).
Mark
 
M

Mark Brehob

Mark> #1 Why no process(*) statement similar to always@*?

Process(all) is in the Accellera VHDL 3.0 2006 trial standard
and in IEEE 1076-2008.

To everyone out there, make sure your vendors know this is
important to you as they have had 2.5 years already to work on it.
I would recommend submitting it as a bug report.



Std_logic_vector is not a math type.  Types signed and unsigned are.
See the paper, VHDL Math Tricks of the Trade from the website:http://www.synthworks.com/papers/index.htm



You need to convert it to integer.  The conversion is as follows,
where a_slv is the value you need to convert.  See the referenced
paper for details.

   to_integer(unsigned(a_slv))


Rising_edge is the newer (from synthesis tool support) and more readable
way to do this.

When coding a simple register:

ARegProc : process(nReset, Clk)
begin
   if nReset = '0' then
     AReg <= '0' ;
   elsif rising_edge(Clk) then
     AReg <= A ;
   end if ;
end process ;

WRT portable coding styles, I recommend either rising_edge or the following
(note that I prefer rising_edge):
   elsif clk='1' and clk'event then
   elsif clk'event and clk='1' then

These are real old and may or may not be portable (work in all synthesis tools):
   elsif clk='1' and not clk'stable then
   elsif not clk'stable and clk='1' then

This one was supported by a particular tool (which is now gone) and
I doubt it is portable (which may be confusing as it is very similar
to the rising_edge procedure):
   elsif clk='1' and clk'event and clk ='0' then
   ... and its variations


Yes, but the DVCon paper that I saw that used a lint tool to apply
VHDL type checking rules to Verilog (to simplify code conversion)
indicated that 75% of the time there was a lint violation it was
a real bug.  Although you have some rules to learn, it is quite
a bit faster to find a bug at compile/lint time rather than having
debug it in a simulator.

Cheers,
Jim
--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jim Lewis    SynthWorks VHDL Training    http://www.synthworks.com

A bird in the hand may be worth two in the bush,
but it sure makes it hard to type.

Thanks to Jim and Kevin for the feedback. It was quite helpful. In
particular using integers in place of vectors seems interesting (and
unusual to a Verilog person). I'll have to think about that.

Thanks again,
Mark
 
M

Mark Brehob

Hello all,
I'm a teacher who has been teaching students Verilog for a while, but
for various reasons I've had to jump to VHDL for a certain course. [...]
#1 Why no process(*) statement similar to always@*?

Others have answered, but... as a teacher, I trust
you are aware of the various ways in which always@*
is broken?  Move to SystemVerilog always_comb instead,
if at all possible.  Most tools support it.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.

Actually I'm unaware of @* being broken. Is it that @* doesn't handle
functions correctly? I've seen something about that, but we rarely
use functions, so...

In any case, could you elaborate?

Thanks,
Mark
 
J

Jan Decaluwe

Mark said:
Actually, good coding style in Verilog completely eliminates that
problem. In my other class, the students build a synthisizable out-of-
order processor starting with an in-order processor. We've found that
blocking/non-blocking problems just don't occur if you follow simple
rules. We teach those rules as "required" and the problem go away.
See http://www.eecs.umich.edu/courses/eecs470/tools/verilog_guidelines.pdf
for a short summary.

Simple enough, but especially intolerably simplistic.

Do you realize that these rules forbid variable semantics?
Even if you don't want to use variables in synthesizable code
for some awkward reason, you surely want them in test benches,
right? Don't you think you can have races there too? So what rule
do you use then?

No, even in Verilog you need something more sophisticated that
still permits variables: use signals (non-blocking assignments)
for communication, and variables (blocking assignments) for
local computation. It always works, for Verilog, VHDL, synthesis,
test bench, high-level modeling, you name it.

http://www.myhdl.org/doku.php/why#y...cking_and_non-blocking_assignments_in_verilog
 
G

georgek2000

Well, we teach more or less the same rules as well, but there is always
at least one group per year who manages to come up with some nice and
interesting blocking/non-blocking race condition :)

The course you are talking about sounds very interesting by the way,
I wish I could have attended such a course as an undergraduate student.
Do you know roughly how much time students spend doing the projects in
this course?  Do they have to care about the efficiency of their
RTL code or do they only have to get it synthesizable?

/Andreas

I recently read a text titled "FPGA Prototyping by Verilog
Examples." There is a section discussing the use/mixing of blocking/
no-blocking statements. Perhaps the best explanation I've seen. If
you have a chance, borrow it from a library and look at sections 7.1
and 7.2.

GK
 
A

Andy

Just remember to restrict the range of your integers (or subtypes), or
synthesis will promote everything to 32 bits signed (integer'range).
For an integer of unsigned(n-1 downto 0):

variable count : integer range 0 to 2**n-1;

I like to use the natural subtype just for more readability, but both
are equivalent:

variable count : natural range 0 to 2**n-1;

Also, expressions are promoted to 32 bit signed, only assignments are
restricted. So something like this works with natural subtypes, but
not with unsigned vectors:

if count - 1 < 0 then
do_something;
count := 2**n - 1;
else
count := count - 1;
end if;

This also has the benefit of automatically using the carry output from
the decrement logic, which is sometimes quicker and smaller. The two
decrementors from the comparison and the assignment end up being
shared in synthesis.

This also works for an up counter:

if count + 1 > 2**n-1 then
do_something;
count := 0;
else
count := count + 1;
end if;

Don't worry, because storage is limited to N bits, the operation's
promotion is pruned anyway.

Similarly, if you want integer arithmetic to rollover, you need to
tell it to do so:

count := (count - 1) mod 2**n; -- don't forget the parentheses!

In simulation, integer arithmetic is MUCH faster than vector
arithmetic.

Andy
 
A

Andy

There is always a tendency to teach a new design method/langauge in
terms of translating the elements of the old method or language. When
teaching HDL to folks who know schematics with gates and registers, we
tend to focus on HDL descriptions of gates and registers. When we
teach vhdl to verilog users, we tend to focus on translating verilog
elements into their vhdl equivalents.

This method of teaching tends to restrict the use of the new language
to the limits imposed by the old one. Thus it is with vhdl's variables
and signals vs verilog's blocking and non-blocking assignment
statements. Because there are so many easy ways to get into trouble
with verilog blocking and non-blocking assignments, most tend not to
use one or the other effectively (usually blocking assignments).
However vhdl enforces Jan's restrictions on communication (signals) vs
local computation (variables), so using both effectively is much
safer.

This in turn allows one to focus on fewer, more complex, clocked vhdl
processes that describe the desired rusults in terms of cycle by cycle
behavior, instead of in terms of registers and gates. The increase in
abstraction allows designing something based on its intended behavior,
not its intended structure, which would have to be worked out
separately in one's head or on paper or whatever.

To be fair, with less concentration on the registers and gates it
takes to effect a desired behavior, it is easier to design something
that works, if only it would fit in the desired device or run at the
desired clock speed! However, even when faced with this dillema,
considering behavioral modifications in terms of adding cycles of
latency and spreading the behavioral complexity between them, instead
of structural additions of registered pipeline stages, is often
helpful, especially if the spreading step is an optimization available
in the synthesis tool (aka register retiming).

Hope this helps,

Andy
 
M

Mark Brehob

I guess the first point is to keep in mind the students will have done
a handful of trivial verilog modules before taking this class. And
they have to learn a huge number of other things. So we necessarily
oversimplify things. That said, it would be very useful for me to
understand why people believe these are over simplified. Even if we
don't change our rules, it's important for me to understand "truth" so
I can let them know the issues involved.

Simple enough, but especially intolerably simplistic.

Do you realize that these rules forbid variable semantics?
Even if you don't want to use variables in synthesizable code
for some awkward reason, you surely want them in test benches,
right? Don't you think you can have races there too? So what rule
do you use then?

It's in that list and I think it works fairly well. We change inputs
from the testbench only on the falling edge of the clock. As we don't
worry about the testbench being synthisizable we don't worry too much
about the "rules" there. It has caused occasional problems, but
nothing I can think of as a huge or common problem at all.

No, even in Verilog you need something more sophisticated that
still permits variables: use signals (non-blocking assignments)
for communication, and variables (blocking assignments) for
local computation. It always works, for Verilog, VHDL, synthesis,
test bench, high-level modeling, you name it.

http://www.myhdl.org/doku.php/why#you_are_confused_about_blocking_and...

At a quick glance, I'm not seeing the definition of communication vs.
local. It would seem that sometimes things are both, but I'd guess
you have a formal definition that handles that. However, I'll note
that our rules are really simple to understand and a lint program can
be written to check for it. (In fact there is one some students wrote
on sourceforge). This is really handy when dealing with fairly novice
coders.

Thanks again!



Mark
 
M

Mark Brehob

Ooooh, don't get me started about

    10. Do not mix blocking and nonblocking assignments
        in the same always block.

As a start, for beginners, it's fine.  For anything
serious, it cramps the style horribly.  Cliff Cummings
is an undoubted expert and a nice guy to boot, but he
and I part company in a big way on that point.  You can't
get the behaviour of VHDL variables in a clocked process
without breaking that rule.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.

Could you give an example or otherwise illustrate the issue here? I'm
not sure what "the behaviour of VHDL variables in a clocked process"
is, or why I'd want it.

Thanks!
Mark
 
M

Mark Brehob

Well, we teach more or less the same rules as well, but there is always
at least one group per year who manages to come up with some nice and
interesting blocking/non-blocking race condition :)

Other than with testbenches I can't think of a time it has come up.
And even then, it requires effort. Of course students seem really
good at generating that effort.
The course you are talking about sounds very interesting by the way,
I wish I could have attended such a course as an undergraduate student.
Do you know roughly how much time students spend doing the projects in
this course?  

A lot. We assign the project with 8-9 weeks left and they can count on
200+ hours of work each. It's crazy, but we have 80-100 people take
it a year and it certainly isn't required (though for computer
engineers there aren't a lot of other options...) We've also gotten
very good at giving them starting points (in-order processor, *very*
basic I-cache and RS) and teaching them exactly the right things to be
able to tackle the problem with the tools we have. Plus we have people
(instructor, TA, staff member) who are good a debugging when things
are really crazy. But they spend 15+ hours just on the high level
design before they even start coding. It's really cool to watch.
Do they have to care about the efficiency of their
RTL code or do they only have to get it synthesizable?

Clock cycle matters, but is a second-order issue. The way we grade
things about 20% of the grade is for performance, and that is
basically measured by how long it takes the various testbenches to
run. Good architecture can get you there (lots of CPI) but clock
cycle obviously plays a big role too. And as memory latency is held
constant, going slow isn't _that_ bad. Generally 1 group out of 10
will not have synthesis working, 1 other will have a cycle time that
is 2-3x what it should be and one will be very low indeed for the
process used.

The real problem is that until most everything is built it can be hard
for them to judge clock-cycle. Individual parts may come in quite
well, but their might be (will be) a combinational path they didn't
think about. So they have to hunt and fix these in 2-10 days
depending on how fast they were at everything else.

Mark
 
M

Mark Brehob

On Tue, 27 Jan 2009 17:33:44 -0800 (PST), Mark Brehob <[email protected]>


Like having code that actually worked first time once you got it through
the compiler?

First of all, thanks for the comments above. They help me understand
the "VHDL way". Which is important if I'm going to teach it.

That said, I never had that "problem" Ada. I guess I'm lucky, but
type problems rarely burn me. Logic errors or syntax errors do, but
type checking doesn't help much there.
It eats into their precious debugging time...

*laugh* that literally made me laugh out loud. Yeah, I understand
that viewpoint. Just doesn't match my experience for the most part.

Although thinking about it, I've had problems with C on Atmel
processors. But they were actual _bugs_ a real compiler with -Wall
would have caught. I will admit, the strong desire to save a few
bytes here and there on the small embedded processors can make you
dream of strict checking of sizes...

Again, thanks!
Mark

Tha
 
A

Andreas Ehliar

But it is _really_ helpful to understand why good people like to
"break our rules". Otherwise I just know people do, but can't give
examples to the students.

Another example for your consideration. Unrolling a CRC for Ethernet.
You could do this without variables by unrolling it manually, but why
do work yourself when the synthesis tool can do it for you?

/Andreas


-- (This could be done in a neater way using ranges)
process (clk)
variable crc_tmp : std_logic_vector(31 downto 0);
variable fb : std_logic;
begin -- process
if clk'event and clk = '1' then -- rising clock edge
if enable = '1' then
crc_tmp := crc;

-- Unrolled to process a nibble at a time.
for i in 0 to 3 loop
fb := crc_tmp(31);
crc_tmp(31) := crc_tmp(30);
crc_tmp(30) := crc_tmp(29);
crc_tmp(29) := crc_tmp(28);
crc_tmp(28) := crc_tmp(27);
crc_tmp(27) := crc_tmp(26);
crc_tmp(26) := d(i) xor fb xor crc_tmp(25); -- x^26
crc_tmp(25) := crc_tmp(24);
crc_tmp(24) := crc_tmp(23);
crc_tmp(23) := d(i) xor fb xor crc_tmp(22); -- x^23
crc_tmp(22) := d(i) xor fb xor crc_tmp(21); -- x^22
crc_tmp(21) := crc_tmp(20);
crc_tmp(20) := crc_tmp(19);
crc_tmp(19) := crc_tmp(18);
crc_tmp(18) := crc_tmp(17);
crc_tmp(17) := crc_tmp(16);
crc_tmp(16) := d(i) xor fb xor crc_tmp(15); -- x^16
crc_tmp(15) := crc_tmp(14);
crc_tmp(14) := crc_tmp(13);
crc_tmp(13) := crc_tmp(12);
crc_tmp(12) := d(i) xor fb xor crc_tmp(11); -- x^12
crc_tmp(11) := d(i) xor fb xor crc_tmp(10); -- x^11
crc_tmp(10) := d(i) xor fb xor crc_tmp(9); -- x^10
crc_tmp(9) := crc_tmp(8);
crc_tmp(8) := d(i) xor fb xor crc_tmp(7); -- x^8
crc_tmp(7) := d(i) xor fb xor crc_tmp(6); -- x^7
crc_tmp(6) := crc_tmp(5);
crc_tmp(5) := d(i) xor fb xor crc_tmp(4); -- x^5
crc_tmp(4) := d(i) xor fb xor crc_tmp(3); -- x^4
crc_tmp(3) := crc_tmp(2);
crc_tmp(2) := d(i) xor fb xor crc_tmp(1); -- x^2
crc_tmp(1) := d(i) xor fb xor crc_tmp(0); -- x^1
crc_tmp(0) := d(i) xor fb; -- 1

crc <= crc_tmp;


elsif clear = '1' then
crc <= (others => '1');
end if;
end if;
end process;
 
G

georgek2000

In a clocked process:
1.ALWAYS use nonblocking assignment to any variable
  whose value will be used outside the process;
2.NEVER mix blocking and nonblocking assignment
  to a single variable;
3.any variable assigned by blocking assignment must
  be declared locally in the process's begin-end, so
  that it can't be referenced from outside (at least,
  not for synthesis);
4.be aware of the immediate-update semantics of
  blocking assignment.  This means...
  - if you read such a variable before assigning
    to it, you get the value that it was given
    on the PREVIOUS clock - held in a flip-flop;
  - if you read such a variable after assigning
    to it, you get the combinational value that
    you just assigned to it.


This is the best blocking/non-blocking guideline I've seen. Thanks
for sharing.

George K.
 
M

Mark Brehob

On Jan 29, 5:59 am, Jonathan Bromley <[email protected]>
wrote:
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.

Thanks! For our courses, we try to avoid things like this and tell
them that while good people do code that way, our way is safer. When
they get more expert, they can be more brave.

But it is _really_ helpful to understand why good people like to
"break our rules". Otherwise I just know people do, but can't give
examples to the students.

Mark

Mark
 
A

Andy

Interesting references to Ada; back in the 90's I took a couple of ada
training classes so that I could learn some "software" techniqes for
vhdl that are not generally taught in vhdl classes (at least the ones
I had taken). I learned general stuff about using types/subtypes
effectively, using scope to control access, applications of packages,
deferred constants (still not synthesizable?!), procedures/functions,
etc. The type-based genericity of ada was really nice; completely
different from what vhdl generics offer.

Andy
 
A

Andy

I was fine with two process (combinatorial & clocked) styles, until I
had to infer clock enabled registers; so much for the simple
functional boundary between logic and registers.

Jonathan's "two-bubble" state machine example is one I do not
personally use. I use a single clocked process with variables, and any
outputs that need to be "on" in a given state are assigned at every
entrance to that state. Sometimes a little more coding, but not
usually. One tends to modify their approach to state machine design to
suit their favorite coding style anyway.

Andy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,905
Latest member
Kristy_Poole

Latest Threads

Top