Writing a good HDL code?

Status
Not open for further replies.

madalin1990

Full Member level 2
Joined
Apr 4, 2012
Messages
124
Helped
2
Reputation
4
Reaction score
2
Trophy points
1,298
Activity points
2,090
HI!Since one day,not far in the future,I will need to write verilog/vhdl code in a professional way,i thoought it will not harm to get used on how to write this code so to be readable ,clean and easy to understand.So i turn to you,folks from edaboard,to guide me in reaching this goal.I only ask from you for some organized ideas,not only one or two tips.
Thank you in advance for your time!
See ya!:wink:
 

the 3 most important things:

1. Do your design work before you write any HDL
2. Write plenty of comments. These should be "why" the code does what it does, not just how.
3. be consistant with your style.
4. always use spaces, never tabs

Basically, the most important thing about good code is good documentation.
 
As an example,how do you generally make your design work.You have a pattern or something?
And about the consistancy of my style,well,I don't really have one,I have just begun (a couple of months) learning the language,learning about fpga,and all that stuff.So,if you would,can you describe me your style?Maybe I can borrow some of your codding style.I mean,no harm in borrowing from those better than you in this,right?:-D
 

MY prefered style:

1. Assess the problem. Do any bandwidth calculations and estimate resource usage (things like mults, mems etc). Make sure the design will probably fit. Document.
2. Ensure you have a set of test data, and preferably a model or known test output to test against.
3. Code HDL.
4. Write testbench and debug. Testbench should be fully self checking, using data or model from 2.
5. If you have more than 1 block, repeat steps 2-4 for each block.
6. Build a larger testbench to test the whole system, using the same theory as in 2 and 4.
7. Compile into FPGA (with timings etc). If you miss timings, you may need to go back to step 3 for certain blocks.

And there you have it.

- - - Updated - - -

most of your time should be spent on stages 1-6. This can minimise the time you spend in step 7.
 
1.) document the module interfaces, including any assumptions/requirements.
2.) make simple block diagram, avoid making complex meshes.
3.) avoid using simulations as a _design_ tool. Avoid quickly patching the code to make the waveforms "line up". (see #6,#7)
4.) avoid single-cycle feedback paths where possible. Design, or at least plan for interfaces to tolerate some amount of latency.
5.) do some sandbox designs to try out coding styles and see what works well in your FPGA. Avoid pre-emptive optimization when you don't have evidence it is required/helpful.
6.) Be aware of pipeline delays and the difference between simple register delays, and registers that are qualified with a clock enable. If a module has a valid/enable input, try connecting a PRBS for one simulation.
7.) Try to avoid registering signals just to change signal names, as it is easy to get confusing names like "is_active" which might specify that a state machine _was_ active last cycles while implying that the state machine _is_ active on this cycle.
8.) follow the standard advice from your FPGA vendor regarding safe clock domain crossing, avoiding latches, constraining clocks, etc...
 
Thank you TrickyDicky and permute for your valuable advices.I will take this tips step by step and try to implement in my coding style(although some of them i do not fully understand,probable because of my unexperience).
 

are you really talking about coding style, or engineering process?
 

Well I don't know about madalin1990, but I am certainly lurking this topic in the hopes of more hints on the engineering process from people that actually do this in a professional capacity. ;-)

1.) document the module interfaces, including any assumptions/requirements.
2.) make simple block diagram, avoid making complex meshes.

How do you document your module interfaces, besides comment in HDL? Do you maintain a spreadsheet? Visio? Something else?

What do you use for block diagrams? I find that I hardly ever get beyond the "scribbles on A4" stage because of the threshold of making a digital version. Any good tools for this? Visio would probably do the trick, EXCEPT that I don't have any useful templates. And no co-workers / company either to provide such.

On the subject of more documentation ... how do you document your medium sized FSM's? Lets say 10 - 20 states or so. Small enough that it still makes sense to put in FSM, but large enough that you'd like a bit more besides comments in your HDL. I've tried a couple of things, but I was wondering what's being used in The Real World [tm].

And potential tip for xilinx users ... the recent versions of PlanAhead actually produce reasonably useful schematics to be used in documentation. In the olden days you could not drag components around, so you'd end up with whatever autogenerated arrangement it came up with. And it usually came up with crap. But now you can rearrange things so that it actually looks fairly decent. Also see Jim Wu's blog on this. Oh, and the generated PDF looks better than the screenshots in that blog.

</hijack>
 

are you really talking about coding style, or engineering process?


Dear TrickyDicky I also find this post interesting, but you have introduced something new to me...
Me too don't know if the mandarin wants coding style or engineering process...

But I cannot understand fully what you mean by engineering process... Does it mean starting from the System design and going to final FPGA or ASIC implementation...?
What I think, usually in an industry each phase (like coding, then simulation, then implementing etc.) is deal by each separate teams. I am not sure since I am just a student. Can you shower some light over it.

To be called a perfect designer, what should be our best strength, e.g. while implementing the design in my lab, I find designing and coding relatively easy, even the difficult tasks are performed, but when it comes to hardware implementation I find it really really hard. Often times fail as well. Though I am sure my design is correct and simulation results verify this thing...


Bests,
Shan
 

are you really talking about coding style, or engineering process?
A bit of both. For pure style:
1.) spaces, not tabs
2.) ports ordered in logical groups going from outputs, inputs, to clk/rst. rst is the last port. This style is _not_ common though.
3.) never name an input "x_out", nor an output "x_in" unless there are no other logical choices. avoid naming ports based on the signal they will connect to in a specific instantiation. (eg, alu_in should not be an output)
4.) two spaces for indentation.
5.) port maps, signals, etc... should be columnized (eg, the ":" should be placed in the same text column on every line). This allows for easy b-editing using vim, emacs, or notepad++.
6.) use fold markers "--{{{" and "--}}}". this allows you to divide your code into logical sections instead of syntax sections. This is also supported in vim/emacs/notepad++, though emacs support is apparently not as good.
7.) when wraping lines, try to wrap on a keyword, like "and". this makes it clear that the next line is not independent. if an if-elsif condition wraps, indent it at a different level than the code inside the if/elsif.
8.) one module per file, named the same as the file, module/file name is lowercase. this aids in verbally discussing modules as systems like linux are case-sensitive.

#2 -- this places the most informative ports at the top of the declaration (the outputs are why you instantiate the module), and the least informative ports at the bottom. reset at the bottom also makes it easier to re-order lines as it will be the line without a trailing comma and won't be moved. The alternate places inputs followed by outputs, which provides a flow from top to file to bottom. This is more common. when used with #6, this style makes reading code easier as you no longer need to scroll to find a module and as a result do not read files from top to bottom as often.

#5 -- the same concept goes for signal names -- avoid actively misleading names. I had another example earlier of a signal "is_active" that indicated something was active.

- - - Updated - - -


I typically add comments above the entity declaration, or by the port declarations depending on how strong the requirements are. The key is to identify any concurrency (signals that can/cannot be active at the same time), latency (signals that require another signal to change N cycles later), and cadence (signals that can/cannot change within N cycles of themselves) issues. I try to avoid documentation outside of the code as it is less likely to be up to date. as it stands, many engineers already ignore comments as they are often misleading.

for big FSMs, i typically put a block of pseudocode outside of the state machine. again, the issue is that there will be small changes made to the code with one level of comments not updated. However, I still feel it is important to explain at least the original purpose of the code.
 

2.) ports ordered in logical groups going from outputs, inputs, to clk/rst. rst is the last port. This style is _not_ common though.
true - I use a different order system clock(s), reset on top, and then group ports based on which entity/component/device they are connecting to, example
Code:
[syntax=vhdl]
entity SerialAudioInterface_TX is
   port (
      pi_SysClk            :  in std_logic;
      pi_aRst              :  in std_logic;
      pi_AudioMCLK         :  in std_logic;
      --
      -- CS5381 I/F
      --
      po_MClk              : out std_logic;
      pi_LR_Clk            :  in std_logic;
      pi_SClk              :  in std_logic;
      po_ResetADC          : out std_logic;
      pi_SerAudioData      :  in std_logic;
      pi_OverFlow          :  in std_logic;
      po_MasterDiv         : out std_logic;
      po_MO                : out std_logic;
      po_M1                : out std_logic;
      po_MasterSlave       : out std_logic;
      po_I2S_LeftJust      : out std_logic;
      po_HighpassFilter    : out std_logic;
      --
      -- System Interface
      --
      po_InterfaceFromADC  : out t_InterfaceFromADC
   );
end entity SerialAudioInterface_TX;
[/syntax]

3.) never name an input "x_out", nor an output "x_in" unless there are no other logical choices. avoid naming ports based on the signal they will connect to in a specific instantiation. (eg, alu_in should not be an output)
most companies I work for (I'm a freelancer) tend to use coding guidelines; usually ports should be relatively easy to identify based on the first two or three characters (po_, pi_, pio_), the same for constants (c_), types (t_) and enums (e_)

and the most important ones: consistancy and documentation
 

Can someone recommend a good software for block diagrams drawing?
 

Visio is what I use. I can copy/paste the drawing in a Word document and it's still editable as a Visio drawing (Of course the drawing "window" is too small to work with ).
 

An excellent thread with most valuable info of VHDL programming loved each part of it

Guys one clarification I need is this

Comment lines should tell why you use the part and not how it works

Why is it so what benefit I get it if I know how the operations are done does it not seem t simplify the problem I am facing

Do clarify me
 


e.g.

Bad comment explaining the always block as what it does

Code Verilog - [expand]
1
2
// generate a toggle signal
always @ (posedge clock) toggle <= ~toggle;  // poor choice of signal name :-P



Good comment explaining the always block as to why it's needed.

Code Verilog - [expand]
1
2
3
// generate an enable every other clock cycle for the accumulator
// which operates at half the clock frequency.
always @ (posedge clock) accum_enable <= ~accum_enable;   // good descriptive signal name :-)



Hope that helps.

Regards,
-alan
 
For VHDL coding styles,
I prefer "VHDL coding styles and methodologies by Ben Cohen"
 

Why is it so what benefit I get it if I know how the operations are done does it not seem t simplify the problem I am facing

You can usually work out what the code is doing from the actual code or simulations. But it doesnt explain why you chose to do it like that.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…