Verilog RTL Coding Guideline Ando KI June 2009
Copyright © by Ando KiLecture overview ( 2 ) Contents Purposes of coding guidelines Principles of coding guidelines Categories of coding guidelines Basic coding practices Coding for portability Guidelines for clocks and resets Coding for synthesis Partitioning for synthesis
Copyright © by Ando KiLecture overview ( 3 ) Purposes of coding guidelines HDL code should be readable, modifiable, and reusable. As a result, the HDL code is optimal result in synthesis and simulation.
Copyright © by Ando KiLecture overview ( 4 ) Principles of coding guidelines To develop RTL code that is simple and regular. Simple and regular structures are easier to design, code, verify, and synthesis than more complex designs. General recommendations Use simple construct, basic types, and simple clock schemes. Use a consistent coding style, consistent naming conventions, and a consistent structure for processes and state machines. Use a regular partitioning scheme, with all module outputs registered and with modules roughly of the same size. Make the RTL code easy to understand, by using comments, meaningful names and constants or parameters instead of hard-coded numbers.
Copyright © by Ando KiLecture overview ( 5 ) Categories of coding guidelines Basic coding practices Coding for portability Guidelines for clocks and resets Coding for synthesis Partitioning for synthesis
Copyright © by Ando KiLecture overview ( 6 ) Basic coding practices Addressing basic coding practices, focusing on lexical conventions and basic RTL constructs. General naming conventions Including headers in source files Use comments Keep commands on separate lines Line length Indentation Do not use HDL reserved words Port ordering Port maps and generic maps Use functions
Copyright © by Ando KiLecture overview ( 7 ) General naming conventions (1/2) Rule: develop a naming convention for the design, which must be documented and used consistently throughout the design. Guidelines Use lowercase letters for all signal names, variable names, and port names. Use uppercase letters for names of constants and user-defined types. Use meaningful names for signals, ports, functions, and parameters. Use short name, but descriptive names for parameters. Use clk as the prefix for all clock signals. Use _n (or _b) as the postfix for all active low signals. Use rst for reset signals. If it is active low, then use rst_n. Use a consistent ordering of bits for multi- bit buses. Use the same name or similar names for ports and signals that are connected.
Copyright © by Ando KiLecture overview ( 8 ) General naming conventions (2/2) Signal name conventions conventionUse *_bActive low signal (rst_b) *_rOutput of a register (count_r) *_aAsynchronous signal (addr_strobe_a) *_pnSignal used in the nth phase (enable_p2) *_nxtData before being registered into a register with the same name *_zTrisate internal signal clk*Use clk as a prefix for clock signals rst*Use rst as a prefix for reset signals
Copyright © by Ando KiLecture overview ( 9 ) Include headers in source files Rule: include a header file at the top of every source file, including scripts. Syntax of header Filename Author Description of functions List of key features Date the file was created Modification history including date, name of modifier, and description of the change /*********************************************** * Copyright (c) 2005 by Ando Ki. * All right reserved. * * *********************************************** * File: euclide.v * Author: Ando Ki * Abstract: Euclide GCD (greatest common divisor) * computes the greatest common divisor * of two non-negative integers. * Date: * Revision history: * Ando Ki 0.2 refinement * Ando Ki 0.1 original *********************************************** */ module GCD ( clk, reset, a, b, valid, c, done); … endmodule
Copyright © by Ando KiLecture overview ( 10 ) Use comments Rule: use comments appropriately to explain all processes, functions, and declarations of types and subtypes. Guidelines Use comments to explain ports, signals, and variables, or groups of signals or variables. Comments should be brief, concise, and explanatory. Comments should be placed logically, near the code that they describe.
Copyright © by Ando KiLecture overview ( 11 ) Keep commands on separate lines Rule: use a separate line for each HDL statement. In order to be more readable and maintainable.
Copyright © by Ando KiLecture overview ( 12 ) Line length Rule: keep the line length to 72 character or less.
Copyright © by Ando KiLecture overview ( 13 ) Indentation Rule: use indentation to improve the readability of continued code lines and nested loops. Guideline Use indentation of 2 spaces. Large indentation restricts line length when there are several levels of nesting. Avoid using tabs. Differences in editors and user setups make the positioning of tabs unpredictable and can corrupt the intended indentation.
Copyright © by Ando KiLecture overview ( 14 ) Do not use HDL reserved words Rule: do not use HDL (Verilog and VHDL) reserved words for names of any elements in RTL source files. Macro designs must be translatable from Verilog to VHDL and vice verse.
Copyright © by Ando KiLecture overview ( 15 ) Port ordering Rule: declare ports in a logical order, and keep this order consistent throughout the design. Guideline Declare one port per line, with a comment following it. Declare the ports in the following order. inputs Clocks, resets, enables, controls, data and address Outputs Clocks, resets, enables, controls, data
Copyright © by Ando KiLecture overview ( 16 ) Port maps and generic maps Guideline: always use explicit mapping for ports and generics, using named association rather than positional association. Guideline Leave a blank line between the input and output ports to improve readability. // gcd Ugcd (.clk (clk),.reset(reset),.A (A),.B (B),.valid (valid),.C (C),.done (done) );
Copyright © by Ando KiLecture overview ( 17 ) Use functions Guideline Use functions when possible, instead of repeating the same sections of code. // function [`WIDTH-1:0] conv_addr; input [`WIDTH-1:0] input_addr; input offset; begin … end endfunction
Copyright © by Ando KiLecture overview ( 18 ) Coding for portability Create code that is technology- independent, compatible with various simulation tools, and easily translatable from Verilog to VHDL (or from VHDL to Verilog). Do not use hard-coded numeric values Include files Avoid embedding dc_shell scripts Use technology-independent libraries
Copyright © by Ando KiLecture overview ( 19 ) Do not use hard-coded numeric values Guideline Do not use hard-coded numeric values. Use constants instead of hard-coded values // wire [7:0] my_in_bus; reg [15:0] my_reg; `define MY_BUS_SIZE 8 `define MY_REG_SIZE 16 parameter MY_BUS_SIZR = `MY_BUS_SIZE parameter MY_REG_SIZE = `MY_REG_SIZE // wire [MY_BUS_SIZE-1:0] my_in_bus; reg [MY_REG_SIZE-1:0] my_reg;
Copyright © by Ando KiLecture overview ( 20 ) Include files Guideline Keep the `define statements for a design in a single separate file and name the file DesignName_params.v.
Copyright © by Ando KiLecture overview ( 21 ) Avoid embedding dc_shell scripts Guideline Avoid using dc_shell script in the source code in order to portability reason.
Copyright © by Ando KiLecture overview ( 22 ) Use technology-independent libraries Guideline Use the DesignWare Foundatioin Library to maintain technolgy independence. Avoid instantiating gates in the design Gate-level design is hard to read, and thus difficult to maintain and reuse. Technology-specific gates make the design non-portable. Use GTECH library, if gate must be used. GTECH library (Synopsys generic technology library – one of technology- independent library) contains technology independent logical components AND, OR, NOR, flip-flops,.. DesignWare Foundation Library includes the followings Adders, multipliers, comparators, incrementers, and decrementers. Sine, cos, modulus, divide, square root, arithmetic and barrel shifters. DesignWare library provides improved timing performance over the equivalent internal Design Compiler architectures. DesignWare library components are all high-performance designs that are portable across processes.
Copyright © by Ando KiLecture overview ( 23 ) Guidelines for clocks and resets A simple clocking structure is easier to understand, analyze, and maintain. In addition to this, a simple clocking structure helps to produce better synthesis results. Avoid mixed clock edges Avoid clock buffers Avoid gated clocks Avoid internally generated clocks Gated clocks and low power designs Avoid internally generated resets
Copyright © by Ando KiLecture overview ( 24 ) Ideal clocking structure The preferred clocking structure is A single global clock, and Positive edge-triggered flops as the only sequential devices. D Q D Q
Copyright © by Ando KiLecture overview ( 25 ) Avoid mixed clock edges (1/2) Guideline Avoid using both positive-edge and negative-edge triggered flip-flops. Mixed clock edges can be used for very aggressive timing goals, such as DDR (double data rate). The cares must be taken. The duty cycle is critical, since it is a critical issue in timing analysis in addition to frequency. Scan-based testing requires separate handing of positive and negative triggered flops. DQDQ FF1FF2 clk Bad example: mixed clock edges
Copyright © by Ando KiLecture overview ( 26 ) Avoid mixed clock edges (1/2) Rule: be sure to model the worst case duty cycle of the clock accurately in synthesis and timing analysis, if both edges are necessary. 50% duty cycle is optimistic Giving signals half the clock cycle to propagate from one register to the next. Rule: be sure to document the assumed duty cycle Guideline It may be useful to separate positive & negative edge flip-flops into different modules. DQDQ FF1FF2 clk Better example: separated modules
Copyright © by Ando KiLecture overview ( 27 ) Avoid clock buffers Guideline Avoid hand instantiating clock buffers in RTL code. Clock buffers are morally inserted after synthesis as port of the physical design. In synthesizable RTL code, clock nets are normally considered ideal nets, with no delays. During place and route, the clock tree insertion tool inserts the appropriate structure for creating as close to an ideal, balanced clock distribution network as possible.
Copyright © by Ando KiLecture overview ( 28 ) Avoid gated clocks Guideline Avoid coding gated clocks in RTL, since clock gating circuits tend to be technology specific and timing dependent. Improper timing of a gate clock can cause A false clock or glitch, Set-up and hold time violation. What will happen if this gate has long delay.
Copyright © by Ando KiLecture overview ( 29 ) Avoid internally generated clocks Guideline Avoid using internally generated clocks. It cause limited testability since logic driven by the internally generated clock cannot be made part of a scan chain. Bad example: internally generated clock
Copyright © by Ando KiLecture overview ( 30 ) Gated clocks and low power designs Guideline Keep the clock and/or reset generation circuitry (for a gate clock, an internally generated clock or reset) as a separate module at the top level. Partition the design so that all the logic in a single module uses a single clock and a single reset. A gated clock should never occur within a macro. Isolating clock and reset generation logic in a separate module enables to use the standard timing analysis and scan insertion techniques. Clock generation submodule1 submodule2 submodule3 clk1 clk2 clk3 top
Copyright © by Ando KiLecture overview ( 31 ) Avoid internally generated resets Guideline Avoid internally generated, conditional reset if possible. Generally, all the registers in the macro should be reset at the same time. If a conditional reset is required, create a separate signal for the reset signal, and isolate the conditional reset logic in a separate module. module poor_style (clk, rst, a, b); input clk; input rst; input a, b; reg [7:0] my_reg; (posedge clk or rst or a or b) begin if ((rst or a or b) == 1) my_reg = 8b0; else begin … end endmodule module better_style (rst_out, rst_in, a, b); output rest_out; input rst_in; input a, b; wire rst_out = rst_in | a | b; endmodule module better_style (clk, rst); input clk, rst; reg [7:0] my_reg; (posedge clk or rst) begin if (rst == 1) my_reg = 8b0; else begin … end endmodule
Copyright © by Ando KiLecture overview ( 32 ) Coding for synthesis In order to create code that achieves the best compile times and synthesis results. Testability Performance Simplification of static timing analysis Gate-level circuit behavior that matches that of the original RTL code Infer registers Avoid latches Avoid combinational feedback Specify complete sensitivity lists Blocking and non-blocking assignments Case statements v.s. if-then-else statements Coding state machines
Copyright © by Ando KiLecture overview ( 33 ) Infer registers Guideline Registers (flip-flops) are the preferred mechanism for sequential logic. Use designers reset signal to initialize registered signals. Do not use initial statement to initialize the signal, since it is not synthesizable construct. These can cause mismatches between pre- synthesis and port-synthesis simulation. // process with synchronous reset (posedge clk) begin : INFER_REG_PROC if (rst == 1b1) begin … something … end else begin … something else … end end // INFER_REG_PROC // process with asynchronous reset (posedge clk or negedge rst_n) begin : INFER_REG_PROC if (rst_n == 1b0) begin … reset behavior end else begin … normal behavior end end // INFER_REG_PROC
Copyright © by Ando KiLecture overview ( 34 ) Avoid latches (1/2) Rule: avoid using any latches Latch When CLK = 1, latch is transparent D flows through to Q like a buffer When CLK = 0, the latch is opaque Q holds its old value independent of D a.k.a. transparent latch or level-sensitive latch Flip-flop When CLK rises, D is copied to Q At all other times, Q holds its value a.k.a. positive edge-triggered flip-flop, master-slave flip- flop
Copyright © by Ando KiLecture overview ( 35 ) Avoid latches (2/2) What makes unintended latch inference. Missing assignment Missing condition How to avoid the unintended latch inference. Avoid latch by fully assigning outputs for all input conditions using else and default. // process causes latch inference (a or en) if (en==1b1) q = a; // its semantics imply that q must hold // its old value when en is low. // process without latch inference (a or en) if (en==1b1) q = a; else q = 1b0;
Copyright © by Ando KiLecture overview ( 36 ) Avoid combinational feedback Guideline Avoid combinational feedback.
Copyright © by Ando KiLecture overview ( 37 ) Specify complete sensitivity lists (1/2) Rule: include a complete sensitivity list in each of always blocks. If not, the behavior of the pre-synthesis design may differ from that of the post- synthesis netlist. Guideline For combinational blocks (blocks with no registers or latches), the sensitivity list must include every signal that is read by the process. For sequential blocks, the sensitivity list must include the clock signal that is read by the process. Make sure the sensitivity lists contains only necessary signals. Adding unnecessary signals to the sensitivity list slows down simulation.
Copyright © by Ando KiLecture overview ( 38 ) Specify complete sensitivity lists (2/2) // process with incomplete sensitivity list (a) c = a or b; // process with complete sensitivity list (a or b) c = a or b; Pre-synthesis simulation waveform Synthesis netlist Post-synthesis simulation waveform
Copyright © by Ando KiLecture overview ( 39 ) Blocking & non-blocking assignments (1/3) Blocking assignments execute in sequential order, While non-blocking assignments execute concurrently. Rule: use non-blocking assignment (<=) in always blocks.
Copyright © by Ando KiLecture overview ( 40 ) Blocking & non-blocking assignments (2/3) (posedge clk) begin a = y; b = a; end clk y a b Blocking assignments
Copyright © by Ando KiLecture overview ( 41 ) Blocking & non-blocking assignments (2/3) (posedge clk) begin a <= y; b <= a; end (posedge clk) begin b = a; a = y; end clk y a b Non-blocking assignments
Copyright © by Ando KiLecture overview ( 42 ) Case statements v.s. if-then-else statements (1/2) A case statement infers a single-level multiplexer, While an if-then-else statement infers a priority-encoded, cascaded combination of multiplexers. Guideline The multiplexer is a faster circuit.
Copyright © by Ando KiLecture overview ( 43 ) Case statements v.s. if-then-else statements (2/2) (sel or a or b or c or d) if (sel == 2b00) out = a; else if (sel == 2b01) out = b; else if (sel == 2b10) out = d; else out = d; (sel or a or b or c or d) case (sel) 2b00: out = a; 2b01: out = b; 2b10: out = c; default: out = d; endcase assign c = (s) ? b : a;
Copyright © by Ando KiLecture overview ( 44 ) Coding state machines Guideline Separate the state machine HDL description into two processes, one for the combinational logic and one for the sequential logic. Use `define statements to define the state vector. Keep FSM logic and non-FSM logic in separate modules. Assign a default state for the state machine. …… reg [1:0] state, next_state; // FSM state // parameter IDLE = 2'h0; parameter FOUND = 2'h1; parameter MODULUS = 2'h2; parameter DONE = 2'h3; // (state) case (state) IDLE: begin … next_state <= FOUND; end end // IDLE FOUND: begin … next_state <= DONE; end // FOUND endcase (posedge clk or negedge rst_b) if (rst_b == 1b0) state <= IDLE; else state <= next_state; endmodule
Copyright © by Ando KiLecture overview ( 45 ) State machine Mealy state machine The output logic is always a function of the current state (state vector) and the inputs. Moore state machine The output logic is only a function of the current state, i.e. inputs are not included. State vector out_signal in_signals clk Next State logic Output logic State vector out_signal in_signals clk Next State logic Output logic
Copyright © by Ando KiLecture overview ( 46 ) Partitioning for synthesis Register all outputs Locate related combinational logic in a single module Separate module that have different design goals Arithmetic operations: merging resources
Copyright © by Ando KiLecture overview ( 47 ) Register all outputs Guideline For each block of a hierarchical design, register all output signals from the block. Registering the output signals from each block simplifies the synthesis process because it makes output drive strengths and input delays predicable. DQ Reg A clk DQ Reg B clk DQ Reg C clk
Copyright © by Ando KiLecture overview ( 48 ) Locate related combinational logic in a single module Guideline Keep related combinational logic together in the same module. Synthesizer has more flexibility in optimizing a design when related combinational logic is located in the same module. Keep related combinational logic in the same module also eases time budgeting and allows for faster simulation. DQ Reg A clk DQ Reg C clk Comb. Logic B DQ Reg A clk DQ Reg C clk Comb. logic B and C Comb. Logic C Poor example Better example
Copyright © by Ando KiLecture overview ( 49 ) Separate modules that have different design goals Guideline Keep critical path logic in a separate module from non-critical path logic. Synthesizer can optimize the critical path logic for speed, while optimizing the non- critical path logic for area. DQ Reg A clk Critical path logic Poor example DQ Reg B clk Non-critical path logic DQ Reg A clk Critical path logic Speed optimization DQ Reg B clk Non-critical path logic Area optimization
Copyright © by Ando KiLecture overview ( 50 ) Avoid point-to-point exceptions Guideline Avoid multi-cycle paths Multi-cycle path is more difficult to analyze correctly. If needed, keep point-to-point exceptions within a single module. DQ Reg A clk DQ Reg B clk Comb. Logic B DQ Reg C clk Comb. Logic C DQ Reg D clk Comb. Logic D
Copyright © by Ando KiLecture overview ( 51 ) Avoid glue logic at the top level Guideline Do not instantiate gate-level logic at the top level of the design hierarchy. Let design hierarchy contain gates only at leaf levels of the hierarchy tree. DQ Reg A clk DQ Reg B clk Module AModule B Top Glue logi c