Lesson 18 of 25 · 15 MIN · 72% complete

DSP Slices

The DSP48E1 is a dedicated arithmetic block featuring a 25×18-bit multiplier, pre-adder, and 48-bit accumulator. It is the core engine behind FIR filters, FFTs, and AI/ML inference on Xilinx 7-series FPGAs.

What is a DSP Slice?

A DSP Slice is a dedicated silicon block for high-speed arithmetic — it is not built from LUTs or flip-flops. Implementing the equivalent function in LUT fabric would require 100+ LUTs and would run at a fraction of the speed. DSP slices give you that arithmetic free of LUT cost and at clock frequencies exceeding 700 MHz.

DSP48E1 Internal Architecture

The DSP48E1 data path has three main computation stages, each of which can be independently pipelined:

  1. Pre-adder: computes D ± A, producing a 27-bit result before the multiplier — allows (A+D)×B without an extra LUT adder
  2. Multiplier: 25×18-bit signed multiplier producing a 43-bit product
  3. Post-adder / accumulator: computes P = X + Y + CARRYIN where X and Y are selected from the muxes below
flowchart LR D([D 27b]) --> PREADD["Pre-adder\nD ± A"] A([A 30b]) --> PREADD PREADD --> MUL["Multiplier\n25×18b"] B([B 18b]) --> MUL MUL --> XMUX["X Mux"] C([C 48b]) --> YMUX["Y Mux"] XMUX --> POSTADD["Post-adder /\nAccumulator\n48b"] YMUX --> POSTADD POSTADD --> P([P 48b output]) P -->|"PCOUT cascade"| NEXTDSP([Next DSP]) P -->|"accumulate feedback"| XMUX style MUL fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd style POSTADD fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd style PREADD fill:#1e293b,stroke:#475569,color:#94a3b8

Key Input Ports

Port Width Description
A 30 bits Primary input (upper bits fed to pre-adder and multiplier)
B 18 bits Secondary multiplier input
C 48 bits Accumulator / adder third operand
D 27 bits Pre-adder input (combined with A before multiply)
P 48 bits Output (also fed back for accumulation)
PCIN / PCOUT 48 bits Dedicated cascade between adjacent DSPs
OPMODE 7 bits Controls X, Y, Z mux selections
ALUMODE 4 bits Selects add, subtract, or logic operation
CARRYCASCIN 1 bit Carry input from the previous DSP in a cascade

Pipeline Registers and Timing

DSP48E1 has three optional pipeline register stages. Enabling all three stages dramatically increases the achievable clock frequency at the cost of added latency:

Pipeline stages enabled Max frequency (Artix-7 -3) Latency
0 (combinational) ~300 MHz 0 cycles
2 (A1/B1 + M) ~550 MHz 2 cycles
3 (full pipeline) ~741 MHz 3 cycles

PCIN/PCOUT Cascade — Building Multi-DSP Architectures

Each DSP48E1 has dedicated 48-bit cascade wires that connect directly to the adjacent DSP above and below in the column. Using PCOUT → PCIN avoids the general routing fabric entirely and adds zero routing delay:

flowchart LR IN([x[n]]) --> DSP0["DSP0\nh[0] × x[n]"] DSP0 -->|PCOUT| DSP1["DSP1\nh[1] × x[n-1]"] DSP1 -->|PCOUT| DSP2["DSP2\nh[2] × x[n-2]"] DSP2 -->|PCOUT| OUT([y[n] sum]) style DSP0 fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd style DSP1 fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd style DSP2 fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd

What DSP48E1 Implements

Application DSPs Used Operation
18×18 multiplier 1 Direct multiply A×B
36×36 multiplier 4 Decomposition into four 18-bit partial products
MAC (multiply-accumulate) 1 P = P + A×B with P feedback
FIR filter (N taps) N One DSP per tap, cascade via PCIN/PCOUT
Complex multiply 3 (a+jb)(c+jd) using 3-DSP trick
Ternary adder 1 A + B + C in a single DSP post-adder
Barrel shifter 1–4 Using pre-adder and shift-by-1 cascades

Synthesis Inference

Vivado automatically infers DSP48E1 primitives from common arithmetic patterns in Verilog or VHDL:

// Simple multiply — infers 1 DSP48E1
assign p = a * b;

// Multiply-accumulate — infers DSP48E1 with P feedback
always @(posedge clk)
  p_reg <= p_reg + a * b;

// Force DSP inference
(* use_dsp = "yes" *)
wire [47:0] result;
assign result = a * b + c;

// Prevent DSP inference (use LUT fabric instead)
(* use_dsp = "no" *)
wire [17:0] product;
assign product = x * y;

After synthesis, check the Vivado Synthesis Report → Primitive Instantiation table for DSP48E1 count. Also search the synthesis log for "DSP48E1" to see which signals were mapped.

FIR Filter Implementation

A direct-form FIR filter computes y[n] = Σ h[k] × x[n−k]. Each tap requires exactly one multiply-accumulate operation — mapping directly to one DSP48E1 per tap with PCOUT cascade for the accumulation:

AI / ML Acceleration

Modern FPGA AI inference engines exploit DSP48E1 in two key ways:

Pipeline your DSPs DSP48E1 has 3 pipeline stages. Enabling all three increases maximum frequency from ~300 MHz to ~741 MHz. Always pipeline DSPs in high-speed designs — the latency cost is usually worth the frequency gain.
3-DSP complex multiply trick For complex multiplication (a+jb)(c+jd), use: p1=a×c, p2=b×d, p3=(a+b)×(c+d), then real=p1−p2, imag=p3−p1−p2. This requires only 3 DSPs instead of 4, saving 25% of DSP resources.
Check DSP availability before using LUTs for arithmetic A 32×32-bit multiplier takes ~400 LUTs but only 4 DSPs. Never implement wide multipliers in LUT fabric when DSPs are available. Check DSP counts in the device datasheet first.
Interview question Q: What is the pre-adder in DSP48E1 and why is it useful?
A: The pre-adder computes D±A before the multiplier, allowing (D+A)×B in a single DSP. This is critical for symmetric FIR filters where the same coefficient multiplies two symmetric input samples — cutting the required DSP count nearly in half.

Knowledge Check

Q1. What is the multiplier width in DSP48E1?

  • A 18×18 bits
  • B 25×18 bits
  • C 30×18 bits
  • D 48×18 bits
Correct! The multiplier in DSP48E1 is 25×18 bits, producing a 43-bit product. The 25-bit A input comes from the pre-adder output (which is 27 bits, truncated to 25 for the multiply stage).

Q2. What is the output width of DSP48E1?

  • A 43 bits
  • B 48 bits
  • C 36 bits
  • D 64 bits
Correct! The P output port (and the PCOUT cascade) are both 48 bits wide. This wide accumulator prevents overflow during multi-tap accumulation in FIR filters.

Q3. Which port cascades the output of one DSP48E1 to the next in a chain?

  • A ACOUT / ACIN
  • B PCOUT / PCIN
  • C CARRYCASCOUT
  • D BCOUT / BCIN
Correct! PCOUT[47:0] feeds directly into PCIN[47:0] of the adjacent DSP in the column. These are dedicated wires with zero routing delay, enabling high-speed cascade chains.

Q4. How many DSP48E1 slices are needed to implement a 4-tap FIR filter?

  • A 1
  • B 2
  • C 3
  • D 4
Correct! A direct-form FIR filter uses one DSP per tap — each tap computes h[k]×x[n−k] and adds it to the cascade. A 4-tap filter requires 4 DSPs with PCOUT chaining the partial sums.

Q5. Which RTL attribute forces DSP inference in Vivado?

  • A (* use_dsp = "no" *)
  • B (* ram_style = "dsp" *)
  • C (* use_dsp = "yes" *)
  • D (* dsp_style = "primitive" *)
Correct! The (* use_dsp = "yes" *) attribute forces Vivado to map arithmetic to DSP48E1 primitives. The opposite attribute (* use_dsp = "no" *) forces LUT-based implementation.

Q6. The pre-adder in DSP48E1 computes what operation?

  • A A + B before the multiplier
  • B P + C in the accumulator stage
  • C D ± A before the multiplier
  • D A × D in a 27-bit pre-multiply
Correct! The pre-adder computes D ± A, feeding the result into the 25-bit multiplier input. This enables (D+A)×B in one DSP — essential for symmetric FIR filters to halve the DSP count.

Practical Exercise

Design a 16-tap FIR low-pass filter in Verilog with signed 16-bit coefficients and 16-bit input:

module fir16 #(parameter TAPS=16) (
  input  wire        clk, rst,
  input  wire [15:0] x_in,
  output reg  [47:0] y_out
);
  reg  [15:0] h [0:TAPS-1];  // coefficients
  reg  [15:0] xd[0:TAPS-1];  // delay line
  integer i;

  // Load coefficients (LPF values)
  initial begin
    h[0]=16'd100; h[1]=16'd200; // ... etc
  end

  always @(posedge clk) begin
    if (rst) begin
      y_out <= 0;
      for(i=0;i<TAPS;i=i+1) xd[i] <= 0;
    end else begin
      xd[0] <= x_in;
      for(i=1;i<TAPS;i=i+1) xd[i] <= xd[i-1];
      y_out <= 0;
      for(i=0;i<TAPS;i=i+1) y_out <= y_out + $signed(h[i]) * $signed(xd[i]);
    end
  end
endmodule

Synthesize targeting Kintex-7 (xc7k70t). Verify that exactly 16 DSP48E1 primitives are inferred (one per tap). Then check the Timing Summary to find the achievable clock frequency with full 3-stage pipelining enabled via the DSP_REG attribute.