Verilog 16: Complete Guide to Logic Synthesis

1. Introduction to Logic Synthesis

Logic synthesis is the process of converting high-level hardware descriptions into gate-level implementations that can be physically realized on silicon (ASICs) or programmable devices (FPGAs).

In simpler words:

Logic synthesis translates your Verilog or VHDL code into a network of logic gates and flip-flops that can be physically built.


1.1. Life Before HDL and Synthesis

Before hardware description languages (HDL) like Verilog:

  • Engineers manually designed circuits using logic diagrams or schematics.

  • Large designs were error-prone, difficult to modify, and time-consuming to implement.

  • Optimizing gate count or timing was extremely hard.

Challenges:

  • Reusing a module in multiple projects was labor-intensive.

  • Making changes in design required redrawing entire schematics.

  • Verification and debugging were manual and slow.


1.2. Impact of HDL and Logic Synthesis

With HDL and synthesis:

  • Designers write behavioral or structural code.

  • Synthesis tools convert HDL code into a gate-level netlist.

  • Automation allows:

    • Faster development cycles

    • Easier modifications

    • Optimization for area, speed, and power

    • Reusability of modules

Example: Writing a 4-bit adder in Verilog automatically generates the AND, OR, and XOR gates needed for implementation.


1.3. What Do We Discuss Here?

This tutorial covers:

  1. Synthesizable vs Non-synthesizable constructs

  2. Supported operators and modeling techniques

  3. Combinational and sequential circuit design in Verilog

  4. Good coding practices for synthesis


2. Constructs Not Supported in Synthesis

Not all Verilog constructs can be converted into hardware. Non-synthesizable code is only valid for simulation, not for hardware implementation.


2.1. Example: Initial Statement

module test; reg [7:0] a; initial begin a = 8'hFF; // Works in simulation, ignored by synthesis end endmodule

Explanation:

  • initial blocks are used for simulation initialization.

  • Synthesis tools ignore them; hardware cannot “set” values at time 0 automatically.


2.2. Delays

always @(posedge clk) a <= #5 b; // #5 delay ignored in synthesis
  • Delay statements (#, @, etc.) are for timing simulation only.

  • In hardware, propagation delays are determined by gates and wires, not code delays.


2.3. Comparison to X and Z

  • Unknown (X) and high-impedance (Z) values exist in simulation for testing purposes.

  • Synthesis tools ignore X/Z comparisons, as hardware cannot have “unknown” states.


2.4. Summary

Non-synthesizable constructs include:

  • initial blocks

  • Timing delays (#)

  • Force/release statements

  • Non-hardware loops or file I/O

These are purely for simulation and cannot produce hardware.


3. Constructs Supported in Synthesis

3.1. Operators and Their Effects

Synthesis supports:

  • Arithmetic operators: +, -, *, / (multiplication often restricted to powers of 2)

  • Bitwise operators: &, |, ^, ~

  • Logical operators: &&, ||, !

  • Comparison operators: <, >, <=, >=, ==, !=

  • Concatenation and replication: {}, {N{bit}}

Note: Use operators carefully; division and modulus may not synthesize efficiently for arbitrary values.


4. Logic Circuit Modeling in Verilog

Verilog allows behavioral and structural modeling of digital logic.


4.1. Combinational Circuit Modeling Using assign

4.1.1. Simple AND/OR Gate

assign y = a & b; // AND assign z = a | b; // OR

4.1.2. Tri-State Buffer

assign y = enable ? data_in : 1'bz;
  • enable = 1 → drives data

  • enable = 0 → high-impedance


4.1.3. Multiplexer (2:1 MUX)

assign y = sel ? a : b;
  • If sel=1y=a

  • If sel=0y=b


4.1.4. Simple Concatenation

assign y = {a, b, c}; // combines bits of a, b, c

4.1.5. Arithmetic Example – 1-Bit Adder

assign sum = a ^ b ^ cin; // XOR for sum assign cout = (a & b) | (b & cin) | (a & cin); // Carry

4.1.6. Multiply by 2

assign y = a << 1; // left shift doubles the value

4.1.7. 3-to-8 Decoder

assign y[0] = ~a & ~b & ~c; assign y[1] = ~a & ~b & c; ... assign y[7] = a & b & c;

4.2. Combinational Modeling Using always

Example: 3-to-8 Decoder

always @(*) begin case({a,b,c}) 3'b000: y = 8'b00000001; 3'b001: y = 8'b00000010; 3'b010: y = 8'b00000100; 3'b011: y = 8'b00001000; 3'b100: y = 8'b00010000; 3'b101: y = 8'b00100000; 3'b110: y = 8'b01000000; 3'b111: y = 8'b10000000; default: y = 8'b00000000; endcase end
  • Using always @(*) ensures combinational sensitivity to all inputs.

  • Good practice: cover all possible input combinations to avoid latches.


4.3. Sequential Circuit Modeling

4.3.1. Simple Flip-Flop

always @(posedge clk or negedge reset) begin if(!reset) q <= 0; else q <= d; end
  • Triggered on rising clock edge

  • Asynchronous reset clears the flip-flop

  • Non-blocking assignment <= recommended for sequential logic


5. Verilog Coding Style for Synthesis

  1. Separate combinational and sequential logic:

    • Combinational: always @(*)

    • Sequential: always @(posedge clk or negedge reset)

  2. Avoid non-synthesizable constructs in RTL code.

  3. Use non-blocking assignment (<=) for sequential logic to prevent race conditions.

  4. Cover all cases in case or if-else statements to avoid unintended latches.

  5. Use constants, parameters, and defines for readable, maintainable code.

  6. Testbench separately: Keep testbench code (simulation-only) separate from RTL meant for synthesis.


6. Summary

  • Logic synthesis: transforms HDL code into hardware gates and flip-flops.

  • Non-synthesizable constructs (initial, delays, X/Z comparison) exist for simulation only.

  • Supported constructs: arithmetic, bitwise, logical, concatenation, replication.

  • Circuit modeling:

    • Combinational logic using assign or always @(*)

    • Sequential logic using flip-flops and always @(posedge clk)

  • Good coding style ensures synthesizable, efficient, and maintainable hardware.



Comments

Popular posts from this blog

Fundamental of python : 1.Python Numbers