------------------------------------------------------------------------------------------------------------
Verilog Coding Guidelines
=========================
Updated 9 Dec 2003
This is a GUIDE for writing Verilog for synthesis. As such it is a list of
suggestions and recommendations, not rules. Some suggestions are very
subjective while others are almost mandatory - i.e. you should have a good
reason for not following them.
Feedback and suggestions to gwatson@stanford.edu
Naming
======
- Module Naming
You are free to name your modules as you please, with the following
exceptions:
- The final top level modules should be the chip name,
e.g. xbar.v.
- the top level minus pad-ring is pb_core.v. This should have
everything except the pad-ring and no synthesizable logic.
- in a multi-chip design any module that might conflict with a similar
module in the other chip should have a suitable suffix appended to
to the module. I suggest a letter that reflects the chip name.
e.g. A system has two chips, pb.v and xbar.v and both have a module
for their registers : regs_p.v and regs_x.v
- when instantiating a module the instance name should be the same
as the module name. If you have many instantiations, then use
a subscript after the module name.
- Signal naming
- All signals are lowercase alpha, numeric and underscore only.
- Avoid active low signals in the core. If you must have them then append
_b to the signal name.
e.g. active_low_b
(Active low signals at the pins is fine, but invert them in the core
before using them)
- Buses are numbered high order to low order: bus[31:0]
- Array locations are numbered low to high.
e.g. 2048x32 bit RAM:
reg [31:0] mem_array [0:2047];
- DONT try to indicate the direction of the signal in the name:
e.g. my_signal_in or my_signal_i is BAD.
Just use my_signal
This makes it much easier to hook up blocks.
- DO use the same name for the signal at all levels of hierarchy!
- DO indicate the direction of a signal as a comment in the signal list
e.g.
my_module (
my_signal, //I: Input from other_module
);
- DONT instantiate modules using positional arguments. ALWAYS use the
dot form:
my_module my_module_inst(
.signal (signal),
.a_bus (a_bus),
...
);
(There are some utilities for building instantiations of modules that
work if the signal names are consistent between levels.)
- Instantiate signals one per line whether as inputs or when
instantiating a block - it makes it easier on the scripts!
- Keep the 'miscellaneous' signals at the end of the signal list.
This will include clk, reset and anything else that generally has a
high fanout and goes between many modules.
e.g. my_module (
signals_to_from_block_A, // description
signals_to_from_block_B, // description
reset,
clk
);
- synchronizing flops
If you have signals that need to be synchronized (cross asynchronous
clock boundaries) then name the synch flops as synch_ e.g. reg synch_stage_1, synch_stage_2; These can be given special treatment for simulation, and you can apply automatic checks to ensure all synch domains have synch flops. Corollary: DONT use 'synch' in any other flop names. - core clock signal is 'clk'. - All other clocks should have the frequency embedded - it makes life easier for the synthesis person. e.g. clk_ddr_266 Verilog style / Simulation ========================== - Use whatever spacing/tabbing/indentation scheme you like - everyone has their own preferences and people become very attached to their Emacs-modes. - Sequential elements MUST only have non-blocking assignments (<=) - Combinatorial should only have blocking assignments (=) - Dont mix blocking and non-blocking assignments within a code block. - Sensitivity lists should be complete to avoid mis-match between synth and simulation. (linting your code should reveal any mismatches) - Dont try to write ultra-slick verilog - it makes it harder to read. - Avoid for loops - they are usually difficult to understand. BUT sometimes they are really useful : unrolling bit expressions that involve other bits. - Group your assertions at the end of the module, surrounded by synopsys translate_off and synopsys translate_on. - Comment your code. Someone will be coming back to this code in 6 months time, and that person will probably be YOU. Synthesis: ========= - keep to one clock per module if possible. (it's easier to understand and it will synthesize much faster) - reset signal is: - called 'reset' - active high within the core - asynchronous NOTE: An asynchronous reset is only asynchronous at the assertion edge. It is synchronous when de-asserted! A suggestion is to bring the reset signal in from the pin, and use it at the async resets on two back-to-back flops where the first has it's D input tied to 1. - try to flop all inputs and outputs to a block - it makes it much easier to set timing constraints. This means you will have to think about how modules are grouped for synthesis. It's fine not to have flops in a module if that module is going to be synthesized with the modules that do have the relevant source/sink flops. - All non data-path flops must have a reset. - All data-path flops must reset within 5 clocks. Usually this means that you only need to reset the input pipeline flops, and subsequent flops will reset within the specified number of clocks. If you're not sure then reset them explicitly. - If you do have some flops with reset and some without, then dont put them both in the same block of code: BAD: always @(posedge clk) if (reset) stage_1 <= 'h0; else begin stage_1 <= input; stage_2 <= stage_1; end This causes reset to be used as an enable on stage_2. Move stage_2 to a separate block or take it out of the if-then-else. - Specify ALL cases in a case statement (use default if you dont need them all). Bear in mind that DC will prioritize in top-to-bottom order. DONT use casex and casey Avoid using pragmas for cases : parallel_case full_case. If you specified all cases then DC will do the right thing. Sometimes though you need them. !!! Check the synthesis logs to see what DC decided. !!! - Assign default values at the start of conditional statements: this tends to shorten the code (mode readable) and helps to ensure that everything always gets a value. e.g. always @( sensitivity_list ) begin a = default_a; b = default_b; case (expr) state_1 : ... // if a should be default_a then we dont put it here. state_2 : ... endcase - Keep it simple. If you cannot envisage the final synthesized logic for your code then DC will probably have a hard time. - Use small-ish modules. They can be grouped together at synthesis time, so try to keep modules small and readable. - No TRI_STATES in the core! Only tri-state I/Os! - Try to avoid needing to specify lots of multi-cycle and false_paths - it can really slow up synthesis and static timing and be hard to maintain. - NO LATCHES! Check the results of synthesis and ensure you do not have any inferred latches - it usually means you missed something in your coding. - No asynchronous logic/ combinatorial feedback loops/ self timed logic. - Synthesis scripts should be established separately, but if you do your own then always use 'link' and 'check_design' and 'check_timing' and actually look at the log files! - Synthesizable logic goes in LEAF modules. As much as possible, try to keep all synthesizable code in leaf modules, and use hierarchical modules ONLY to hook things up. A single "!" at core can wreak havoc. For core (and other high-level hierarchical modules), I prefer to just read the code into synopsys, link it, and write it out. Turning that "!" into a single inverter requires a compile, which then requires that all the clocks be declared, resets dont_touched, etc - not to mention chewing up hours of compile time. - Don't mix hand-instantiated circuitry with rtl My scripts will automatically put a "dont_touch" on anything hand-instantiated, so individual hand-instantiated components are ok. The problem comes with hand-instantiated *circuits*. It is very difficult to prevent synopsys from inserting buffers, etc into these circuits during compile. So, these circuits should be put in a lower level of hierarchy and let the synth guy know so that he can just not compile that module. - Miscellaneous When entering multi-line comments, try to use the "/*..*/" commenting rather than putting "//" in front of every line. It makes editing much easier. The statements "input" and "output" will default their arguments to wires, so there is no need to put a wire statement in the code for anything that is an input or an output. Other wires (hookup wires) need to be declared only if they are multi-bit, although some people like to declare the single-bit ones as well. I very much prefer people to put inputs and outputs one-per-line. It makes grep'ing so much easier. If I want to find who drives a signal in code written this way, I can grep for "output.*signal". It also gives you a handy place to put a comment. - Don't use the "`include" directive in synthesizable code. This is never necessary, and introduces synthesis dependencies that are difficult to track. Use of parameterized designs is OK, but keep in mind the design will have to be separately built (compiled) for each combination of parameter settings. So, don't use parameterization just to avoid a few XOR's in a decode. Also, keep the parameter names SHORT, because the module name will include both the name and value of the parameter. ==================================================== Acknowledgements, Further Reading, and more stuff. Many of these recommendations are courtesy of Paul Zimmer. For further reading on verilog styles, synthesis techniques, useful scripts, etc I recommend the following papers: - "RTL Implementation Guide", Jack Marshall, Tera Systems http://www.terasystems.com/products/Marshall_RTL_Guide.pdf - Cliff Cummings' papers at: http://www.sunburst-design.com/papers/ - Steve Golson's papers at: http://www.trilobyte.com/papers/ Many of the above papers appeared at SNUG: http://www.snug-universal.org/papers/papers.htm Emacs-modes and other verilog goodies available at: http://www.parmita.com/verilogcenter/下载本文