Structural vs Behavioral

Both of the following 2 always blocks should synthesize to a decoder.

always @(address) case (address) 2'b00 : row = 4'b0001; 2'b01 : row = 4'b0010; 2'b10 : row = 4'b0100; 2'b11 : row = 4'b1000; endcase

always @(address) row = 2**address;

  1. The first always block has 4 lines, and it will take much more lines for wider address, but anybody who reads it notices immediately that the code synthesizes to a decoder. The second always block only takes one line, irrespective of the address' width. But it's harder to find out what that line synthesize to. How do I know when to write my code in "brute force" way (the first always code), or the "high level" way (the second always block), which takes full advantage of HDLs with a lot less lines? From all my previous projects, I always do the brute force way. But sometimes I am wondering whether I am taking the right approach. The brute force way seems like schematic, which can be done as well by pulling components from the schematic library, which kind of defeating the purpose of HDLs. On the other hand, if I use the high level way, my code will take full advantage of HDLs, much shorter but more difficult to debug. How do I know which one to choose?

  1. When I do my projects, I always like to be able to see what my code synthesize to (the schematic equivalent of the HDLs). That gives me confident on the realibility of my projects. But should I forget about the schematic equivalent and treat it just like C and as long as it works then who cares about the schematic equivalent?

I need advise from professional engineers who have been in this field for several years. I appreciate if you can help me making the decision. Thank You!

Hendra

Reply to
Hendra
Loading thread data ...

[So, which is nicer...]

Personally I like neither of these descriptions of a decoder; how about the following:

always @(address) begin row = 0; row[address] = 1'b1; end

This is likely to be efficient both for synthesis and for simulation, and (at least to me) it is crystal-clear that it represents a decoder, unlike "1

Reply to
Jonathan Bromley

Well the third way juste requires a few extra bytes :

always @(address) // that's a decoder row = 2**address;

:-)

MB

--
Michel BILLAUD                  billaud@labri.fr
LABRI-Université Bordeaux I     tel 05 4000 6922 / 05 5684 5792
351, cours de la Libération     http://www.labri.fr/~billaud
33405 Talence  (FRANCE)
Reply to
Michel Billaud

Personally I would use

wire [3:0] row = 1

Reply to
John_H

Not that this answers your question... but I believe both of these code fragments are behavorial code. Structural code instantiates components.

The style of code I use is always based on the synthesis tool's guidelines doc. It's the first thing I read before writing any code.

Reply to
Petrov_101

Fascinating... I can't easily think of another four lines of text that could be as diametrically opposed to my own position as these.

Point by point...

Succinct - yes, but it needs a comment to make it easily comprehensible, thus dramatically reducing the (IMHO imaginary) benefit of brevity. Why is brevity good, for heavens' sake? Any half-decent piece of code will be at least 50% comment, so there is at the very most 50% saving to be made from brevity of code - and nothing, not even the tiniest thing, that compromises clarity and maintainability is worth that. Code is written once but read (and modified) often; saving a few keystrokes is not something that's worth chasing.

Commented - yes, for sure. But the comments are just that, comments; they can get out-of-step with the code, and nobody gets to check. If, by writing somewhat more verbose code, I can "animate" the comments so that they are part of the code's functionality, then I don't have that risk. In general I am deeply distrustful of comments that describe the behaviour of procedural code, which tends to be almost self-evident to anyone skilled in the language; the teacher in me still comes out in a cold sweat at the sight of this vacuity: i = i + 1; // increment i So, let's have the comments as far as possible embedded in the code itself. Intriguingly, the most useful part of your commentary, where you say "assert row[address]", could easily be a piece of procedural Verilog (see my earlier post). Note, by the way, that assertions provide an even better way to add "animated comments" that *are* checked by tools. An assertion could easily check for one-hot-ness of the output, for example.

Why bother with always? - Because it gives me a lot more room to manoeuvre if I later decide I need to change something. Especially in Verilog, where the change from "assign" to "always" also impacts the declaration of various things, I lean towards using "always" right from the start so that there's less to change later. Of course there are exceptions: some places you have little choice but to use assign (three-state drivers, etc); certain patterns of glue logic, like fixes for the polarity of strobe signals, are nicer done as assigns. But any logic with some real functionality behind it IMHO belongs in a procedural block.

These are emphatically my own opinions and I am very much aware that many skilled people will profoundly disagree with me. I'm sure there is a place for both points of view, and for many in between. Just so long as everyone is aware that the choice is not obvious :-)

--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL, Verilog, SystemC, Perl, Tcl/Tk, Verification, Project Services

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, BH24 1AW, UK
Tel: +44 (0)1425 471223          mail:jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573                Web: http://www.doulos.com

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

I'd have to vote with John_H here but I know many won't.

wire [3:0] row = 1

Reply to
JJ

I could also say it wasn't that long ago that I would have written

DEC4_1 u0 (.addr(i), .out(o)); // or whatever the std cell was called

Now that synthesis has fully taken over except at the very top end of the speed curve, its not so necessary, only on interesting block level.

Although instancing of blocks is usually considered structural or schematic thinking, you can then put anything at all into the module that describes that it even the original case statement as the visual clutter from it is now elsewhere.

There is another way to have it both ways and that is to use a folding text editor, click on the 1 liner and see the the 1 or 5 or 100 lines it represents. Pretty much a schematic thing to do to when you could push down into sub sheets.

Does anyone actually use such a thing, recomendations esp Windows,

I half suspect Emacs can do it but never took to it.

johnjakson at usa dot com

Reply to
JJ

I used to use CodeWright - dunno if it even still exists, but that did folding IIRC.

:-) Yes, I use folding-mode a lot in my VHDL - the emacs VHDL-mode is the reason I finally took the plunge with emacs!

I don't think the verilog-mode is as fully-featured - so maybe it won't suit you so much...

Cheers, Martin

--
martin.j.thompson@trw.com
TRW Conekt, Solihull, UK
http://www.trw.com/conekt
Reply to
Martin Thompson

I'd say that a compiler that warns about unnecessary parenthesis in expressions with bit manipulation is broken. It is far more helpful for the compiler to warn about not having enough parenthesis to make the meaning clear - gcc does this, with appropriate flags.

Code should be written to be easily read and easily understood - not to be typed with the minimal number of characters. When C was first used, minimal character count was a priority - and the results of that language design decision have been felt ever since. Writing long-winded or excessively commented code is just as bad as overly terse and compact code, however.

Reply to
David

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.