Synthesis Optimization Skill
Expert skill for FPGA synthesis optimization targeting Vivado and Quartus tools. Provides deep expertise in synthesis report analysis, attribute application, resource inference control, and QoR (Quality of Results) improvement.
Overview
The Synthesis Optimization skill enables comprehensive synthesis optimization for FPGA designs, supporting:
- Synthesis report analysis and resource utilization review
- Synthesis attributes (keep, max_fanout, ram_style, etc.)
- DSP and BRAM inference guidance
- FSM encoding optimization (one-hot, binary, Gray)
- Retiming and register balancing
- Logic optimization strategies
- High-fanout net reduction
- Multi-vendor synthesis flows
Capabilities
1. Synthesis Report Analysis
Parse and analyze synthesis reports:
# Vivado synthesis report analysis
report_utilization -hierarchical
report_utilization -cells [get_cells -hier -filter {IS_PRIMITIVE}]
report_timing_summary -setup -hold
# Resource utilization breakdown
report_utilization -format csv -file utilization.csv
# Check specific resource types
report_utilization -cells [get_cells -hier -filter {REF_NAME =~ DSP*}]
report_utilization -cells [get_cells -hier -filter {REF_NAME =~ RAM*}]
2. Synthesis Attributes
Apply Xilinx/Vivado synthesis attributes:
// Keep hierarchy for debugging
(* KEEP_HIERARCHY = "yes" *)
module critical_path_module (
// ...
);
// Prevent register optimization
(* DONT_TOUCH = "yes" *) logic debug_reg;
// Control register duplication for timing
(* MAX_FANOUT = 50 *) logic high_fanout_signal;
// Force specific implementation
(* KEEP = "true" *) logic preserved_signal;
// RAM style control
(* RAM_STYLE = "block" *) logic [7:0] large_mem [1024];
(* RAM_STYLE = "distributed" *) logic [7:0] small_mem [16];
(* RAM_STYLE = "registers" *) logic [7:0] tiny_mem [4];
(* RAM_STYLE = "ultra" *) logic [7:0] uram_mem [4096]; // UltraRAM
// ROM style control
(* ROM_STYLE = "block" *) logic [7:0] lookup_table [256];
// Use DSP for arithmetic
(* USE_DSP = "yes" *) logic [47:0] mult_result;
(* USE_DSP = "no" *) logic [15:0] small_mult; // Use fabric
// Shreg extraction control
(* SHREG_EXTRACT = "yes" *) logic [15:0] shift_reg;
(* SRL_STYLE = "register" *) logic [7:0] no_srl_shift;
// Async register for CDC synchronizers
(* ASYNC_REG = "TRUE" *) logic [1:0] sync_reg;
// FSM encoding
(* FSM_ENCODING = "one_hot" *) enum logic [3:0] {
IDLE, INIT, RUN, DONE
} state;
(* FSM_ENCODING = "sequential" *) // Binary encoding
(* FSM_ENCODING = "gray" *) // Gray code
(* FSM_ENCODING = "johnson" *) // Johnson encoding
(* FSM_ENCODING = "auto" *) // Tool decides
3. Intel/Quartus Attributes
Apply Quartus synthesis attributes:
// RAM style
(* ramstyle = "M20K" *) logic [7:0] intel_bram [1024];
(* ramstyle = "MLAB" *) logic [7:0] intel_lutram [32];
(* ramstyle = "logic" *) logic [7:0] intel_ff_mem [8];
(* ramstyle = "no_rw_check" *) logic [7:0] dual_port_mem [256];
// Preserve signal
(* preserve *) logic keep_signal;
(* noprune *) logic unused_but_keep;
// DSP usage
(* multstyle = "dsp" *) logic [31:0] use_dsp;
(* multstyle = "logic" *) logic [7:0] use_fabric;
// Synchronizer
(* altera_attribute = "-name SYNCHRONIZER_IDENTIFICATION FORCED" *)
logic [1:0] altera_sync;
// Maximum fanout
(* maxfan = 32 *) logic fanout_limited;
4. DSP Inference Optimization
Guide DSP48/DSP block inference:
// Optimal DSP48 inference pattern (multiply-accumulate)
module dsp_mac #(
parameter int A_WIDTH = 18,
parameter int B_WIDTH = 18,
parameter int P_WIDTH = 48
) (
input logic clk,
input logic rst_n,
input logic ce,
input logic signed [A_WIDTH-1:0] a,
input logic signed [B_WIDTH-1:0] b,
input logic signed [P_WIDTH-1:0] c,
input logic load, // Load C vs accumulate
output logic signed [P_WIDTH-1:0] p
);
// Pipeline registers for timing
logic signed [A_WIDTH-1:0] a_reg;
logic signed [B_WIDTH-1:0] b_reg;
logic signed [P_WIDTH-1:0] mult_reg;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
a_reg <= '0;
b_reg <= '0;
mult_reg <= '0;
p <= '0;
end else if (ce) begin
// Input registers (A and B)
a_reg <= a;
b_reg <= b;
// Multiplier register (M)
mult_reg <= a_reg * b_reg;
// Accumulator/output (P)
p <= load ? c + mult_reg : p + mult_reg;
end
end
endmodule
// Prevent DSP for small multiplies
(* USE_DSP = "no" *)
module small_mult (
input logic [7:0] a, b,
output logic [15:0] p
);
assign p = a * b; // Will use fabric LUTs
endmodule
5. BRAM Inference Optimization
Ensure correct Block RAM inference:
// Simple dual-port RAM (correct inference pattern)
module sdp_ram #(
parameter int DATA_WIDTH = 32,
parameter int DEPTH = 1024,
parameter int ADDR_WIDTH = $clog2(DEPTH)
) (
input logic clk,
// Write port
input logic wr_en,
input logic [ADDR_WIDTH-1:0] wr_addr,
input logic [DATA_WIDTH-1:0] wr_data,
// Read port
input logic [ADDR_WIDTH-1:0] rd_addr,
output logic [DATA_WIDTH-1:0] rd_data
);
(* RAM_STYLE = "block" *)
logic [DATA_WIDTH-1:0] mem [DEPTH];
// Write port
always_ff @(posedge clk) begin
if (wr_en) begin
mem[wr_addr] <= wr_data;
end
end
// Read port (registered output for BRAM)
always_ff @(posedge clk) begin
rd_data <= mem[rd_addr];
end
endmodule
// True dual-port RAM
module tdp_ram #(
parameter int DATA_WIDTH = 32,
parameter int DEPTH = 1024
) (
// Port A
input logic clk_a,
input logic en_a,
input logic wr_en_a,
input logic [$clog2(DEPTH)-1:0] addr_a,
input logic [DATA_WIDTH-1:0] wr_data_a,
output logic [DATA_WIDTH-1:0] rd_data_a,
// Port B
input logic clk_b,
input logic en_b,
input logic wr_en_b,
input logic [$clog2(DEPTH)-1:0] addr_b,
input logic [DATA_WIDTH-1:0] wr_data_b,
output logic [DATA_WIDTH-1:0] rd_data_b
);
(* RAM_STYLE = "block" *)
logic [DATA_WIDTH-1:0] mem [DEPTH];
// Port A
always_ff @(posedge clk_a) begin
if (en_a) begin
if (wr_en_a)
mem[addr_a] <= wr_data_a;
rd_data_a <= mem[addr_a]; // Read-first mode
end
end
// Port B
always_ff @(posedge clk_b) begin
if (en_b) begin
if (wr_en_b)
mem[addr_b] <= wr_data_b;
rd_data_b <= mem[addr_b]; // Read-first mode
end
end
endmodule
6. FSM Encoding Optimization
Choose optimal FSM encoding:
// One-hot encoding (fast, more registers)
(* FSM_ENCODING = "one_hot" *)
typedef enum logic [7:0] {
IDLE = 8'b00000001,
INIT = 8'b00000010,
CONFIG = 8'b00000100,
RUN = 8'b00001000,
PAUSE = 8'b00010000,
DONE = 8'b00100000,
ERROR = 8'b01000000,
RESET = 8'b10000000
} state_t;
// Binary encoding (compact, slower decode)
(* FSM_ENCODING = "sequential" *)
typedef enum logic [2:0] {
S_IDLE = 3'd0,
S_INIT = 3'd1,
S_RUN = 3'd2,
S_DONE = 3'd3
} compact_state_t;
// Gray encoding (low power, one-bit transitions)
(* FSM_ENCODING = "gray" *)
typedef enum logic [2:0] {
G_IDLE = 3'b000,
G_INIT = 3'b001,
G_RUN = 3'b011,
G_DONE = 3'b010
} gray_state_t;
// Safe FSM with illegal state recovery
module safe_fsm (
input logic clk,
input logic rst_n,
input logic start,
input logic done,
output state_t state
);
state_t current_state, next_state;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n)
current_state <= IDLE;
else
current_state <= next_state;
end
always_comb begin
next_state = current_state;
case (current_state)
IDLE: if (start) next_state = INIT;
INIT: next_state =