Digital IC Design Flow Standards and Implementation Guidelines

Digital Frontand Development Workflow

The complete digital IC design process follows this sequence:

  1. Design specification creation
  2. RTL implementation
  3. RTL simulation and verification
  4. Spyglass static analysis
  5. FPGA prototyping
  6. Design Compiler synthesis
  7. Formality equivalence checking on synthesized netlist
  8. Post-synthesis netlist simulation
  9. Physical design and place-and-route
  10. Formality checking on final netlist
  11. Post-layout simulation verification
  12. LVS verification

Toolchain Configuration

  • Compiler: Synopsys VCS
  • Debugger: Synopsys Verdi
  • Synthesizer: Synopsys Design Compiler
  • Static Enalyzer: Synopsys Spyglass
  • Equivalence Checker: Synopsys Formality 2018

Coding Standards and Implementation

Naming Conventions

  • Active-low signals use "_n" suffix
  • Module names: lowercase_with_underscores
  • Instance names: u_ prefix with numbering (u_module_0, u_module_1)
  • Vector declaration: [high:low] with LSB at position 0
  • Clock signals: "clk" prefix
  • Reset signals: "rst" prefix
  • Divided clocks: "clk_ratio" suffix (e.g., clk_128)

Module Structure Template

module example_module #
(
    DATA_BITS = 32,
    ADDR_BITS = 5
)
(
    input clk,
    input rst_n,
    input [ADDR_BITS-1:0] cmd_addr,
    output reg [DATA_BITS-1:0] cmd_data
);

// Macro definitions
`define CHIP_ID 32'h1234_5678

// Parameters
parameter MEM_DEPTH = 32;

// Internal signals
reg [DATA_BITS-1:0] memory [MEM_DEPTH-1:0];

// Logic implementation
always @(posedge clk or negedge rst_n) begin
    // Implementation details
end

endmodule

Finite State Machine Implementation

module state_controller(
    input clk,
    input rst_n,
    input [1:0] cmd_input,
    output reg [1:0] state_out
);

parameter IDLE_ST = 2'b00;
parameter ACTIVE_ST = 2'b01;
parameter DONE_ST = 2'b10;

reg [1:0] curr_state, next_state;

// State register
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        curr_state <= IDLE_ST;
    end else begin
        curr_state <= next_state;
    end
end

// Next state logic
always @(*) begin
    case(curr_state)
        IDLE_ST: begin
            if(cmd_input == 2'b01) begin
                next_state = ACTIVE_ST;
            end else begin
                next_state = IDLE_ST;
            end
        end
        
        ACTIVE_ST: begin
            if(cmd_input == 2'b10) begin
                next_state = DONE_ST;
            end else begin
                next_state = ACTIVE_ST;
            end
        end
        
        DONE_ST: begin
            if(cmd_input == 2'b01) begin
                next_state = IDLE_ST;
            end else begin
                next_state = DONE_ST;
            end
        end
        
        default: next_state = IDLE_ST;
    endcase
end

// Output logic
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        state_out <= 2'b00;
    end else begin
        case(curr_state)
            IDLE_ST: state_out <= 2'b00;
            ACTIVE_ST: state_out <= 2'b01;
            DONE_ST: state_out <= 2'b10;
            default: state_out <= 2'b00;
        endcase
    end
end

endmodule

Register File Implementation

module register_bank #(
    parameter ADDR_BITS = 5,
    parameter DATA_BITS = 32,
    parameter REG_COUNT = 32
) (
    input clk,
    input rst_n,
    input write_en,
    input [ADDR_BITS-1:0] read_addr1,
    input [ADDR_BITS-1:0] read_addr2,
    input [ADDR_BITS-1:0] write_addr,
    input [DATA_BITS-1:0] write_data,
    output [DATA_BITS-1:0] read_data1,
    output [DATA_BITS-1:0] read_data2
);

reg [DATA_BITS-1:0] registers [REG_COUNT-1:0];

// Write port (synchronous)
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        for(int i=0; i<reg_count assign="" begin="" else="" end="" endmodule="" i="i+1)" if="" ports="" read="" read_data1="registers[read_addr1];" read_data2="registers[read_addr2];" registers="" write_data=""></reg_count>

Clock Divider Implementation

module clock_divider #(
    parameter DIV_FACTOR = 10
) (
    input clk,
    input rst_n,
    output reg div_clk
);

reg [7:0] counter;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        counter <= 0;
        div_clk <= 0;
    end else if (counter == DIV_FACTOR - 1) begin
        counter <= 0;
        div_clk <= ~div_clk;
    end else begin
        counter <= counter + 1;
    end
end

endmodule

Project Directory Structure

.
|-- documentation
|   `-- specifications.pdf
|-- libraries
|   `-- technology_lib
|-- outputs
|   |-- netlists
|   `-- gds_files
|-- project
|   |-- Makefile
|   `-- file_list.f
|-- source
|   |-- rtl
|   `-- constraints
|-- testbench
|   |-- test_data
|   `-- test_module.v
`-- workspace
    |-- synthesis
    |-- equivalence
    |-- analysis
    |-- simulation
    `-- debugging

Design Reliability Guidelines

  • Single clock per synchronous always block
  • Synchronous design methodology preferred
  • Avoid clock signals as data inputs
  • No logic in clock or reset paths
  • Non-blocking assignments in sequential logic
  • Blocking assignments in combinational logic
  • Prevent latch inference
  • Avoid combinational loops
  • UTF-8 encoding for all source files
  • ANSI-style port declarations
  • One module per file principle

Tags: RTL Design Verilog Coding Digital Synthesis IC Verification Formality Check

Posted on Sat, 25 Jul 2026 16:20:08 +0000 by airwinx