# 🧱 Kiến trúc phần cứng: pipeline và song song tài nguyên

By Everwise Intern

## Từ phương trình sai phân đến sơ đồ mạch

Bài trước đã chốt hệ số lượng tử hóa fixed-point và kiểm chứng đáp ứng tần số bằng scipy.signal. Bài này bắt đầu từ chính phương trình sai phân đó và hỏi câu hỏi của người làm phần cứng: mạch nào chạy kịp tần số lấy mẫu (sample rate), và cái giá phải trả là bao nhiêu DSP slice cùng bao nhiêu ràng buộc định thời (timing).

Sau 35 phút này, bạn cần làm được:

- Đọc đường tới hạn (critical path) của một sơ đồ nhân cộng (MAC) và suy ra tần số xung nhịp tối đa.
- Ánh xạ bộ lọc sang sơ đồ pipeline, tính số tầng thanh ghi (register) cần chèn.
- Chọn mức song song tài nguyên (resource parallelism) theo $f_s$ và $f_{clk}$.
- Ước lượng số DSP slice trước khi viết dòng Verilog đầu tiên.
- Nhận diện chỗ pipeline phá vỡ chức năng, đặc biệt trong vòng hồi tiếp (feedback loop) của IIR.

## Đường tới hạn quyết định tần số xung nhịp

Với FIR $N$ tap, dạng trực tiếp (direct form) tính

$$
y[n] = \sum_{k=0}^{N-1} h[k]\,x[n-k]
$$

Nếu nối tiếp một bộ nhân với $N-1$ bộ cộng, đường tổ hợp dài nhất giữa hai thanh ghi chính là chuỗi đó:

$$
T_{cp} = T_{mult} + (N-1)\,T_{add}
$$

và mạch chỉ chạy được ở $f_{clk} \le 1/T_{cp}$. Với $N = 64$, $T_{mult} = 4$ ns, $T_{add} = 0{,}4$ ns, ta có $T_{cp} \approx 29$ ns, tức khoảng 34 MHz. Đây là lý do tuyệt đối không được tổng hợp nguyên một chuỗi cộng nối tiếp.

Hai đòn bẩy độc lập, và phải phân biệt rõ:

- **Pipeline** giữ nguyên số chu kỳ cần cho một mẫu, nhưng rút ngắn mỗi chu kỳ, nên tăng thông lượng (throughput).
- **Song song tài nguyên** giữ nguyên chu kỳ, nhưng giảm số chu kỳ cần cho một mẫu.

Độ trễ (latency) là số chu kỳ từ lúc mẫu vào đến lúc kết quả ra. Trong luồng dữ liệu liên tục kiểu mẫu-nối-tiếp (sample-by-sample streaming), độ trễ cố định không gây hại, miễn là thông lượng đủ lớn.

## Pipeline: chèn thanh ghi để rút ngắn đường tới hạn

Nguyên tắc: chèn thanh ghi vào giữa đường tổ hợp để chia nó thành các đoạn đều nhau, mỗi đoạn ngắn hơn $T_{clk}$. Số tầng tối thiểu:

$$
L \ge \left\lceil \frac{T_{cp}}{T_{clk}} \right\rceil
$$

Với FIR, hai kỹ thuật đi kèm luôn dùng cùng nhau:

1. **Cây cộng cân bằng (balanced adder tree):** thay $N-1$ phép cộng nối tiếp bằng $\log_2 N$ tầng, ví dụ 63 phép cộng thành 6 tầng.
2. **Định thời lại (retiming):** dịch chuyển thanh ghi qua logic tổ hợp để cân bằng các tầng, chức năng không đổi, nhưng khi thanh ghi nằm ở điểm rẽ nhánh (fanout) thì phải nhân bản thanh ghi.

```mermaid
flowchart TD
    A["Tham số: f_s, N tap, f_clk"] --> B["Ngân sách chu kỳ mỗi mẫu<br/>C = f_clk / f_s"]
    B --> C{"So sánh C với N"}
    C -->|"C lớn hơn hoặc bằng N"| D["🔁<br/>Một MAC dùng lại N lần"]
    C -->|"C nhỏ hơn N"| E["⚡<br/>Tách K nhánh song song"]
    E --> F["Cây cộng cân bằng<br/>và thanh ghi pipeline"]
```

> **Note:** 
> Pipeline tiêu tốn flip-flop theo bit: một thanh ghi 18 bit nhân cho 32 tầng đã là tài nguyên đáng kể. Hãy chèn thanh ghi ở chỗ thật sự cần, không rải đều theo cảm tính.

**Bài tập 1 (gắn với capstone).** FIR 32 tap, $T_{mult} = 4{,}0$ ns, $T_{add} = 0{,}4$ ns, cộng nối tiếp. (a) Tính $T_{cp}$ và $f_{clk}$ tối đa. (b) Cần mấy tầng pipeline để đạt 100 MHz? (c) Độ trễ là bao nhiêu?

**Xem gợi ý**

(a) $T_{cp} = 4{,}0 + 31 \times 0{,}4 = 16{,}4$ ns, suy ra $f_{clk,max} \approx 61$ MHz. (b) Với $T_{clk} = 10$ ns, cần $L \ge \lceil 16{,}4/10 \rceil = 2$ tầng. Lưu ý: nếu thay chuỗi cộng bằng cây cân bằng, $T_{cp} = 4{,}0 + 5 \times 0{,}4 = 6{,}0$ ns, đủ 100 MHz mà không cần thêm tầng nào. (c) Độ trễ pipeline là 2 chu kỳ, tức 20 ns, cộng với độ trễ nhóm $(N-1)/2$ mẫu của bản thân bộ lọc.

## Song song tài nguyên: nhân bản phép nhân thay vì tăng nhịp

Pipeline chỉ rút ngắn đường tổ hợp, nó không giảm số phép tính. Khi $f_s$ quá cao khiến $C = f_{clk}/f_s < N$, một bộ nhân không kịp phục vụ $N$ tap trong một mẫu, buộc phải nhân bản phần cứng. Số nhánh song song tối thiểu:

$$
K \ge \left\lceil \frac{N}{C} \right\rceil = \left\lceil \frac{N \cdot f_s}{f_{clk}} \right\rceil
$$

Mỗi nhánh nhận một nhóm hệ số, tính tổng riêng, rồi cộng gộp $K$ kết quả bằng cây cân bằng. Với dòng mẫu liên tục, nhánh thứ $k$ xử lý các mẫu $n \equiv k \pmod{K}$, đây chính là kỹ thuật mở rộng luồng (unfolding).

| $f_s$ | $f_{clk}$ | $C$ | $N$ | $K$ | DSP slice |
| --- | --- | --- | --- | --- | --- |
| 1 MSPS | 100 MHz | 100 | 64 | 1 | 1 |
| 25 MSPS | 100 MHz | 4 | 64 | 16 | 16 |
| 100 MSPS | 200 MHz | 2 | 64 | 32 | 32 |

Trên FPGA, mỗi phép nhân thường ánh xạ vào một DSP slice (ví dụ DSP48E1: nhân $25 \times 18$, bộ tiền cộng (pre-adder), tích lũy 48 bit). Vì vậy số DSP slice xấp xỉ $K$, còn flip-flop thì tỉ lệ với số tầng pipeline nhân với độ rộng bit dữ liệu. Ngân sách của bạn là cả hai: thiếu DSP thì phải tăng $f_{clk}$ hoặc giảm $N$, thiếu flip-flop thì phải giảm số tầng hoặc cắt bớt bit.

> **Tip:** 
> Trước khi viết một dòng Verilog nào, hãy lập bảng ba cột: yêu cầu ($f_s$, $N$, độ rộng bit), ngân sách ($f_{clk}$, số DSP slice, số flip-flop), và kiến trúc chọn ($C$, $K$, $L$). Bảng này là hợp đồng thiết kế của capstone.

**Bài tập 2 (gắn với capstone).** Cần FIR 64 tap cho luồng 100 MSPS, $f_{clk} = 200$ MHz, mỗi DSP slice chứa một bộ nhân. (a) Chọn $C$, $K$, số DSP slice. (b) Nếu chip chỉ còn 24 DSP slice, phương án hợp lý là gì?

**Xem gợi ý**

(a) $C = 200/100 = 2$, suy ra $K \ge 32$, cần 32 DSP slice và một cây cộng 32 đầu vào (5 tầng).
(b) Tăng $f_{clk}$ lên 300 MHz thì $C = 3$ và $K = 22$, vừa 24 slice; hoặc giảm $N$ xuống 48 tap với $K = 24$. Cả hai đều phải kiểm tra lại timing bằng báo cáo trễ (timing report) trước khi chốt.

## Cân bằng giữa thanh ghi, bộ nhân và tần số

Ba đại lượng $f_{clk}$, $K$, $L$ ràng buộc lẫn nhau. Tăng $f_{clk}$ giúp giảm $K$ (tiết kiệm DSP slice) nhưng làm $T_{clk}$ nhỏ đi, buộc phải tăng $L$ (tốn flip-flop) và dễ vi phạm timing. Giảm $f_{clk}$ thì ngược lại. Điểm cân bằng thực tế thường là $f_{clk}$ bằng 60 đến 70 phần trăm tần số ước lượng từ đường tới hạn, để chừa biên cho nhiệt độ và góc bo mạch chậm (slow corner).

Một lưu ý về độ trễ: kiến trúc càng nhiều tầng và nhiều nhánh thì độ trễ càng lớn nhưng vẫn cố định. Với lọc thời gian thực, độ trễ cố định được phép, miễn là thông lượng đạt $f_s$ và độ trễ nằm trong ngân sách của ứng dụng (ví dụ dưới 1 ms cho vòng điều khiển).

## Cạm bẫy khi đẩy thiết kế lên tầng phần cứng

- **Chèn pipeline mà quên timing report:** đường tới hạn sau khi tổng hợp mới là sự thật, không phải con số bạn tính tay. Luôn chạy báo cáo trễ ở góc chậm nhất.
- **Định thời lại qua điểm rẽ nhánh:** dịch chuyển thanh ghi qua một node có fanout lớn sẽ làm thay đổi chức năng. Muốn giữ nguyên hành vi, phải nhân bản thanh ghi tại nhánh đó.
- **Quên thanh ghi vào và ra:** chân I/O của FPGA thường là đường chậm nhất. Đăng ký đầu vào và đầu ra trước, rồi mới tối ưu phần giữa.
- **Đặt tên tín hiệu theo ý thích:** tên tín hiệu nên phản ánh tầng và nhánh, ví dụ `acc_k03_l2`, để báo cáo trễ chỉ đúng vị trí cần sửa.
- **Tối ưu sớm:** hãy để công cụ tổng hợp làm phần việc của nó, chỉ can thiệp khi báo cáo trễ chỉ ra đường tới hạn cụ thể.

Đường tới hạn (critical path) quyết định _____ của thiết kế.
Số tầng pipeline tối thiểu là L ≥ _____.
Ngân sách chu kỳ cho mỗi mẫu là C = _____.
Số nhánh song song tối thiểu là K ≥ _____.
Cây cộng cân bằng đưa độ sâu phép cộng từ N − 1 xuống _____ tầng.

## Ôn tập nhanh kiến trúc

Front: Mục đích của pipeline trong thiết kế DSP?
Back: Rút ngắn đường tới hạn để tăng tần số xung nhịp, không làm giảm số phép tính.

Front: Đường tới hạn (critical path) là gì?
Back: Đường tổ hợp dài nhất giữa hai thanh ghi, quyết định tần số xung nhịp tối đa.

Front: Công thức số tầng pipeline tối thiểu?
Back: L ≥ ⌈T_cp / T_clk⌉, với T_cp là độ trễ đường tổ hợp.

Front: Ngân sách chu kỳ cho mỗi mẫu C tính thế nào?
Back: C = f_clk / f_s, số chu kỳ có thể dùng để xử lý một mẫu.

Front: Công thức số nhánh song song tối thiểu K?
Back: K ≥ ⌈N / C⌉, tức ⌈N · f_s / f_clk⌉.

Front: Cây cộng cân bằng cải thiện điều gì?
Back: Giảm độ sâu cộng từ N − 1 tầng xuống log₂N tầng.

Front: Một DSP48E1 gồm những khối nào?
Back: Bộ nhân 25 × 18, bộ tiền cộng (pre-adder) và bộ tích lũy 48 bit.

Front: Số DSP slice xấp xỉ bằng đại lượng nào?
Back: Xấp xỉ K, vì mỗi nhánh song song thường dùng một bộ nhân.

Front: Tại sao phải nhân bản thanh ghi ở điểm fanout khi định thời lại?
Back: Vì dịch chuyển một thanh ghi qua nhánh rẽ làm thay đổi chức năng; nhân bản giữ nguyên hành vi.

Front: Pipeline có làm giảm số bộ nhân không?
Back: Không. Pipeline chỉ thêm thanh ghi; song song tài nguyên mới thêm bộ nhân.

Front: Báo cáo trễ (timing report) dùng để làm gì?
Back: Kiểm tra slack dương ở tần số mục tiêu và xác định đường tới hạn thực tế sau tổng hợp.

Front: FIR 63 tap, f_s = 1 MSPS, f_clk = 100 MHz chọn kiến trúc nào?
Back: C = 100 > 63, một MAC dùng lại 63 lần là đủ, không cần song song.

## Trước khi bước vào capstone

Ba con số cần mang theo: $C = f_{clk}/f_s$ cho biết bạn có bao nhiêu chu kỳ, $K = \lceil N/C \rceil$ cho biết phải nhân bản bao nhiêu bộ nhân, và $L = \lceil T_{cp}/T_{clk} \rceil$ cho biết phải chèn bao nhiêu tầng thanh ghi. Toàn bộ phần còn lại của thiết kế chỉ là hiện thực hóa ba con số này bằng Verilog và kiểm chứng chúng bằng báo cáo trễ.

Bài tiếp theo sẽ đưa các quyết định kiến trúc ở đây vào capstone: viết bộ lọc thời gian thực bằng Verilog, nối với testbench lấy dữ liệu từ mô hình `scipy.signal` ở bài trước, và đối chiếu đầu ra phần cứng với đầu ra tham chiếu số thực.

---

## Contents

Part of [🎛️ Thiết kế DSP trên FPGA: triển khai bộ lọc thời gian thực](https://everwise.study/courses/thiet-ke-dsp-tren-fpga-trien-khai-bo-loc-thoi-gian-thuc.md)

- **📐 Thiết kế bộ lọc số từ đặc tả**
  - [🧭 Đặc tả thiết kế và ôn nhanh nền tảng DSP](https://everwise.study/courses/thiet-ke-dsp-tren-fpga-trien-khai-bo-loc-thoi-gian-thuc/dsp-spec-and-foundations-review.md)
  - [🪟 Thiết kế bộ lọc FIR: cửa sổ (window) và Parks-McClellan](https://everwise.study/courses/thiet-ke-dsp-tren-fpga-trien-khai-bo-loc-thoi-gian-thuc/fir-filter-design-window-parks-mcclellan.md) (sign-in required)
  - [🌀 Thiết kế bộ lọc IIR: biến đổi song tuyến tính (bilinear transform)](https://everwise.study/courses/thiet-ke-dsp-tren-fpga-trien-khai-bo-loc-thoi-gian-thuc/iir-filter-design-bilinear-transform.md)
  - [✅ Checkpoint: thiết kế bộ lọc số](https://everwise.study/courses/thiet-ke-dsp-tren-fpga-trien-khai-bo-loc-thoi-gian-thuc/checkpoint-filter-design.md)
- **⚙️ Mô phỏng và triển khai nhúng thời gian thực trên FPGA**
  - [🧪 Mô phỏng, kiểm thử với scipy.signal và lượng tử hóa fixed-point](https://everwise.study/courses/thiet-ke-dsp-tren-fpga-trien-khai-bo-loc-thoi-gian-thuc/simulation-and-fixed-point-quantization.md)
  - [🧱 Kiến trúc phần cứng: pipeline và song song tài nguyên](https://everwise.study/courses/thiet-ke-dsp-tren-fpga-trien-khai-bo-loc-thoi-gian-thuc/fpga-pipeline-and-resource-parallelism.md) — this lesson
  - [🛠️ Capstone: bộ lọc thời gian thực trên FPGA bằng Verilog](https://everwise.study/courses/thiet-ke-dsp-tren-fpga-trien-khai-bo-loc-thoi-gian-thuc/capstone-realtime-filter-on-fpga.md) (premium content)
  - [✅ Checkpoint: triển khai nhúng trên FPGA](https://everwise.study/courses/thiet-ke-dsp-tren-fpga-trien-khai-bo-loc-thoi-gian-thuc/checkpoint-fpga-implementation.md) (premium content)
- [Course cheatsheet](https://everwise.study/courses/thiet-ke-dsp-tren-fpga-trien-khai-bo-loc-thoi-gian-thuc/cheatsheet.md) (premium content)
