vhdl questions from a verilog person

Discussion in 'VHDL' started by Mark Brehob, Jan 28, 2009.

  1. Mark Brehob

    Mark Brehob Guest

    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
    Mark Brehob, Jan 28, 2009
    #1
    1. Advertising

  2. On 2009-01-28, Mark Brehob <> wrote:
    > 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
    Andreas Ehliar, Jan 28, 2009
    #2
    1. Advertising

  3. Mark Brehob

    KJ Guest

    "Mark Brehob" <> wrote in message
    news:...
    > 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
    KJ, Jan 28, 2009
    #3
  4. On 2009-01-28, Mark Brehob <> wrote:
    > 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
    Andreas Ehliar, Jan 28, 2009
    #4
  5. Mark Brehob

    Mark Brehob Guest

    On Jan 27, 9:00 pm, Andreas Ehliar <> wrote:
    > On 2009-01-28, Mark Brehob <> wrote:
    >


    >
    > 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
    Mark Brehob, Jan 28, 2009
    #5
  6. Mark Brehob

    Mark Brehob Guest

    On Jan 27, 8:53 pm, Jim Lewis <> wrote:
    > 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.
    >
    > > #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.

    >
    > 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
    >
    > > #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.

    >
    > 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))
    >
    > > #4 What's up with all the different ways to check for a rising edge of
    > > a clock?

    >
    > 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
    >
    > > 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 :).

    >
    > 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
    Mark Brehob, Jan 28, 2009
    #6
  7. Mark Brehob

    Mark Brehob Guest

    On Jan 28, 4:08 am, Jonathan Bromley <>
    wrote:
    > On Tue, 27 Jan 2009 17:33:44 -0800 (PST), Mark Brehob wrote:
    > >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
    > ://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
    Mark Brehob, Jan 28, 2009
    #7
  8. Mark Brehob

    Jan Decaluwe Guest

    Mark Brehob wrote:
    > On Jan 27, 9:00 pm, Andreas Ehliar <> wrote:
    >> On 2009-01-28, Mark Brehob <> wrote:
    >>

    >
    >> 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.


    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


    --
    Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
    Python as a hardware description language:
    http://www.myhdl.org
    Jan Decaluwe, Jan 28, 2009
    #8
  9. Mark Brehob

    Guest

    On Jan 28, 6:17 am, Andreas Ehliar <> wrote:
    > On 2009-01-28, Mark Brehob <> wrote:
    >
    > > 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.
    > > Seehttp://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


    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
    , Jan 28, 2009
    #9
  10. Mark Brehob

    Andy Guest

    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
    Andy, Jan 28, 2009
    #10
  11. Mark Brehob

    Andy Guest

    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
    Andy, Jan 28, 2009
    #11
  12. Mark Brehob

    Mark Brehob Guest

    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.

    On Jan 28, 9:30 am, Jan Decaluwe <> wrote:
    > Mark Brehob wrote:
    > > On Jan 27, 9:00 pm, Andreas Ehliar <> wrote:
    > >> On 2009-01-28, Mark Brehob <> wrote:

    >
    > >> 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.
    > > Seehttp://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?


    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

    >
    > --
    > Jan Decaluwe - Resources bvba -http://www.jandecaluwe.com
    >      Python as a hardware description language:
    >      http://www.myhdl.org
    Mark Brehob, Jan 29, 2009
    #12
  13. Mark Brehob

    Mark Brehob Guest

    On Jan 28, 9:43 am, Jonathan Bromley <>
    wrote:
    > On Wed, 28 Jan 2009 06:06:09 -0800 (PST), Mark Brehob wrote:
    > >We teach those rules as "required" and the problem go away.
    > >Seehttp://www.eecs.umich.edu/courses/eecs470/tools/verilog_guidelines.pdf
    > >for a short summary.

    >
    > 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
    > ://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
    Mark Brehob, Jan 29, 2009
    #13
  14. Mark Brehob

    Mark Brehob Guest

    On Jan 28, 6:17 am, Andreas Ehliar <> wrote:
    > On 2009-01-28, Mark Brehob <> wrote:
    >
    > > 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.
    > > Seehttp://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 :)


    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


    > /Andreas
    Mark Brehob, Jan 29, 2009
    #14
  15. Mark Brehob

    Mark Brehob Guest

    On Jan 28, 9:35 am, Brian Drummond <>
    wrote:
    > On Tue, 27 Jan 2009 17:33:44 -0800 (PST), Mark Brehob <>


    <clip>
    >
    > >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.  

    >
    > 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.

    >
    > > C/Verilog people should not
    > >have to deal with strict type checking :).

    >
    > 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
    >
    > - Brian


    Tha
    Mark Brehob, Jan 29, 2009
    #15
  16. On 2009-01-29, Mark Brehob <> wrote:
    > 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;
    Andreas Ehliar, Jan 29, 2009
    #16
  17. Mark Brehob

    Guest

    > 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.
    , Jan 29, 2009
    #17
  18. Mark Brehob

    Mark Brehob Guest

    On Jan 29, 5:59 am, Jonathan Bromley <>
    wrote:
    <clip>
    > --
    > 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
    > ://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
    Mark Brehob, Jan 29, 2009
    #18
  19. Mark Brehob

    Andy Guest

    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
    Andy, Jan 29, 2009
    #19
  20. Mark Brehob

    Andy Guest

    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
    Andy, Jan 29, 2009
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. walala
    Replies:
    0
    Views:
    8,667
    walala
    Aug 1, 2003
  2. walala
    Replies:
    3
    Views:
    5,650
    walala
    Aug 30, 2003
  3. shumon
    Replies:
    1
    Views:
    11,755
    Jim Wu
    Sep 24, 2003
  4. Elf

    Verilog/VHDL Simulation

    Elf, Oct 10, 2003, in forum: VHDL
    Replies:
    1
    Views:
    682
    Mike Treseler
    Oct 10, 2003
  5. afd
    Replies:
    1
    Views:
    8,270
    Colin Paul Gloster
    Mar 23, 2007
Loading...

Share This Page