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.
- Xilinx 7-series primitive: DSP48E1
- UltraScale / UltraScale+: DSP48E2 (wider A input: 34 bits vs 30 bits)
- Device counts: Artix-7 — 90 to 740 DSPs; Kintex-7 — 240 to 3600 DSPs; Zynq-7000 — 80 to 2020 DSPs
DSP48E1 Internal Architecture
The DSP48E1 data path has three main computation stages, each of which can be independently pipelined:
- Pre-adder: computes D ± A, producing a 27-bit result before the multiplier — allows (A+D)×B without an extra LUT adder
- Multiplier: 25×18-bit signed multiplier producing a 43-bit product
- Post-adder / accumulator: computes P = X + Y + CARRYIN where X and Y are selected from the muxes below
- X mux inputs: M (multiplier output), P (feedback for accumulate), A:B (48-bit concatenation), 0
- Y mux inputs: C input, P (cascade), 0
- Total output width: 48 bits
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:
- Stage 1: A1 / B1 registers — after the input ports
- Stage 2: A2 / B2 / M registers — after the pre-adder and multiplier
- Stage 3: P register — at the output of the post-adder
| 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:
- PCOUT[47:0] of DSPN connects to PCIN[47:0] of DSPN+1
- Zero additional routing delay — the cascade wire is hardwired between adjacent DSPs
- FIR filter implementation: each tap uses one DSP, PCOUT carries the running sum to the next tap
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:
- Coefficient h[k] is preloaded into the A or B port (or stored in a small distributed RAM)
- Delayed input sample x[n−k] is passed from a shift register chain
- PCOUT carries the running partial sum from tap to tap with zero routing overhead
- Total DSPs for an N-tap FIR = N
AI / ML Acceleration
Modern FPGA AI inference engines exploit DSP48E1 in two key ways:
- INT8 packing: two signed 9-bit values can be packed into the 18-bit B input, enabling two multiply-accumulate operations per DSP per cycle
- MACC chains: cascaded PCOUT chains implement dot products for fully-connected and convolution layers
- Kintex UltraScale+ KU15P: 5,520 DSPs → approximately 170 GOPS at INT8 precision
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
Q2. What is the output width of DSP48E1?
- A 43 bits
- B 48 bits
- C 36 bits
- D 64 bits
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
Q4. How many DSP48E1 slices are needed to implement a 4-tap FIR filter?
- A 1
- B 2
- C 3
- D 4
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" *)
(* 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
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.