SemiMatrix / TOPICS / RTL DESIGN & DIGITAL ARCHITECTURES
DIGITAL IC DESIGN — FRONT-END IMPLEMENTATION

RTL Design & Digital Microarchitectures
Synthesizable SystemVerilog, Pipeline Hazard Resolution & Safe FSM Design

อ่าน 30 นาที อัปเดต 2026–2028 Standard Frontend RTL & Architecture

เจาะลึกศาสตร์การออกแบบสถาปัตยกรรมดิจิทัลระดับ Register Transfer Level: การเขียนโค้ด SystemVerilog 2023 ที่พร้อมสำหรับการสังเคราะห์วงจร (Synthesizable RTL), กลไกการป้องกัน Race Conditions, สถาปัตยกรรม 3-Process FSM ที่ปราศจากสัญญาณรบกวน, การแบ่งไปป์ไลน์และการขจัดปัญหา Data/Control Hazards, โพรโทคอล Valid-Ready Handshake และการออกแบบ FIFO ข้ามโดเมนสัญญาณนาฬิกา

01 นิยาม RTL และกระบวนทัศน์ฮาร์ดแวร์ (Hardware vs Software Thinking)

ในสายงานออกแบบวงจรรวมดิจิทัล (Digital IC Design) RTL (Register Transfer Level) คือระดับนามธรรม (Abstraction Level) ที่ใช้อธิบายการไหลของข้อมูล (Data Flow) ระหว่างหน่วยความจำชั่วคราวหรือรีจิสเตอร์ (Registers) ผ่านวงจรตรรกะเชิงผสม (Combinational Logic) ในแต่ละคาบสัญญาณนาฬิกา

การเขียนโค้ดฮาร์ดแวร์ด้วยภาษา SystemVerilog หรือ VHDL แตกต่างจากการเขียนโปรแกรมซอฟต์แวร์ (C/C++, Python) อย่างสิ้นเชิง:

  • ซอฟต์แวร์ (Software): ทำงานตามลำดับทีละบรรทัด (Sequential Execution) บนตัวประมวลผลที่มีอยู่แล้ว
  • ฮาร์ดแวร์ (RTL): ทุกบรรทัดของโค้ดคือ "พิมพ์เขียวของวงจรกายภาพ (Physical Blueprint)" ที่ทำงานพร้อมกันทั้งหมดแบบคู่ขนาน (Massive Parallel Execution) ในโลกความเป็นจริงบนแผ่นซิลิคอน
💡
The Golden Rule of RTL Engineering
"If you cannot visualize the gates, multiplexers, and flip-flops that your code will synthesize into, do not write the code." วิศวกร RTL ระดับแนวหน้าจะมองเห็นโครงสร้างฮาร์ดแวร์ในใจเสมอก่อนลงมือพิมพ์โค้ด เพื่อป้องกันไม่ให้เกิด Inferred Latches, Timing Violations, หรือ Routing Congestion ในขั้นตอน Physical Design
📍 CAREER ROADMAP CONTEXT
STAGE 02 — DIGITAL DESIGN & HDL: RTL Design & Hardware Description
เขียน RTL ด้วย Verilog/SystemVerilog — FSM, pipeline, CDC (Clock Domain Crossing), reset strategy, coding style ที่ synthesis-friendly
Tools: Synopsys VCS / Design Compiler, Cadence Xcelium / Genus, Siemens Questa, Verilator
Related: CMOS Digital Logic · Clock Domain Crossing (CDC) · Logic Synthesis
Path: RTL Design Engineer, ASIC Architect, SoC Integration Engineer

02 ไวยากรณ์ SystemVerilog เชิงสังเคราะห์ (Synthesizable Constructs)

มาตรฐาน IEEE 1800 SystemVerilog ได้เพิ่มคำสั่งจำเพาะเพื่อช่วยให้เครื่องมือสังเคราะห์วงจร (Synthesis Tools เช่น Design Compiler / Genus) และโปรแกรมจำลอง (Simulators) เข้าใจเจตนารมณ์ของผู้ออกแบบได้อย่างถูกต้องแม่นยำ ป้องกันข้อผิดพลาดจากการตีความผิด:

คำสั่ง SystemVerilog ประเภทวงจรที่สร้างขึ้น กลไกการตรวจจับความผิดพลาดของ Linter / Compiler
always_ff @(posedge clk or negedge rst_n) Sequential Logic (Flip-Flops / Registers) คอมไพเลอร์จะฟ้อง Error ทันทีหากมีสัญญาณในวงจรที่ไม่ได้ถูกกระตุ้นด้วย Clock Edge ป้องกันการเกิด Combinational Loop
always_comb Combinational Logic (Mux, Adders, Encoders) คำนวณ Sensitivity List โดยอัตโนมัติ และจะฟ้อง Warning ทันทีหากตรวจพบว่าโค้ดมีความเสี่ยงที่จะสร้าง Inferred Latch
always_latch Level-Sensitive Latches ใช้เฉพาะในจุดที่ตั้งใจสร้าง Latch จริงๆ (เช่น ในโครงสร้าง Time-Borrowing หรือ Clock Gating Cell)
logic data type Single 4-state Data Type ('0', '1', 'X', 'Z') แทนที่ความสับสนระหว่าง reg และ wire ใน Verilog รุ่นเก่า ป้องกันการประกาศชนิดพอร์ตผิด
⚠️
มหันตภัย Inferred Latch (Unintentional Latches)
หากในบล็อก Combinational Logic มีการเขียนคำสั่ง if-else หรือ case โดยครอบคลุมเงื่อนไขอินพุตไม่ครบทุกกรณี และไม่มีการกำหนดค่าเริ่มต้น (Default Value) เครื่องมือสังเคราะห์จะสันนิษฐานว่าคุณต้องการ "จำค่าเดิมไว้" และจะแอบใส่ Latch กายภาพลงในชิป ซึ่งส่งผลเสียอย่างรุนแรง: ทำให้วงจรไม่ผ่านการทดสอบ Timing Analysis (STA) และทำให้การทดสอบความผิดพลาด (ATPG / Scan Chain) ล้มเหลว

03 กลไก Blocking (=) vs Non-Blocking (<=) Assignment

ความสับสนเรื่องตัวดำเนินการกำหนดค่าเป็นสาเหตุอันดับหนึ่งของการเกิดสภาวะแข่งขัน (Race Conditions) ที่ทำให้ผลการรัน Simulation ในระดับ RTL ไม่ตรงกับพฤติกรรมของ Gate-Level Netlist (RTL-to-Gate Mismatch):

THE 2 GOLDEN RULES OF SYSTEMVERILOG ASSIGNMENTS
$$ \text{Rule 1: Use Non-Blocking } (<=) \text{ inside } \mathbf{always\_ff} \text{ blocks} $$
$$ \text{Rule 2: Use Blocking } (=) \text{ inside } \mathbf{always\_comb} \text{ blocks} $$
ห้ามผสมผสานตัวดำเนินการทั้งสองประเภทภายในบล็อก always เดียวกันโดยเด็ดขาด และห้ามกำหนดค่าให้สัญญาณตัวเดียวกันจากหลายบล็อก always พร้อมกัน (Multiple Drivers Error)

ตัวดำเนินการ Non-Blocking (<=) ทำงานในคิว NBA (Non-Blocking Assignment Queue) ของสแต็กเหตุการณ์จำลอง (Event Scheduler) โดยจะประเมินค่าฝั่งขวามือของทุกสมการพร้อมกันก่อน แล้วจึงอัปเดตค่าไปยังฝั่งซ้ายมือพร้อมกันที่ขอบสัญญาณนาฬิกา ซึ่งสะท้อนพฤติกรรมของฟลิปฟลอปจริงในฮาร์ดแวร์อย่างสมบูรณ์แบบ

04 สถาปัตยกรรม Finite State Machine (FSM) และการออกแบบที่ปลอดภัย

Finite State Machine คือหัวใจในการควบคุมลำดับขั้นตอน (Control Path) ของสถาปัตยกรรมดิจิทัล การออกแบบ FSM ระดับโปรดักชันต้องใช้โครงสร้าง 3-Always Process Pattern เพื่อแยกหน้าที่การทำงานออกจากกันอย่างชัดเจน:

PROCESS 1 (always_ff)
State Register Updating
ทำหน้าที่สลับสถานะปัจจุบัน (current_state <= next_state) ตามขอบสัญญาณนาฬิกาและรองรับการรีเซ็ตระบบ (Asynchronous/Synchronous Reset)
PROCESS 2 (always_comb)
Next-State Transition Logic
ประเมินสถานะปัจจุบันและอินพุตภายนอก เพื่อคำนวณว่าในรอบถัดไปจะต้องกระโดดไปยังสถานะใด (คำสั่ง unique case (current_state))
PROCESS 3 (always_ff / comb)
Registered Output Logic
ส่งสัญญาณควบคุมออกสู่ภายนอก นิยมต่อผ่านฟลิปฟลอป (Registered Outputs) เพื่อขจัดสัญญาณรบกวนแหลมสั้น (Glitches) และลด Propagation Delay ของวงจรถัดไป

การเลือกรูปแบบการเข้ารหัสสถานะ (State Encoding Trade-offs)

รูปแบบการเข้ารหัส จำนวนฟลิปฟลอปที่ใช้ ความเร็ว / ความถี่สูงสุด การประยุกต์ใช้งานที่เหมาะสม
One-Hot Encoding $N$ บิตสำหรับ $N$ สถานะ (มีบิต '1' ตัวเดียวเสมอ) เร็วที่สุด ลอจิกถอดรหัสใช้เพียงเกต OR ขนาดเล็ก นิยมสูงสุดใน FPGA และ ASIC ที่ต้องการความเร็วสัญญาณนาฬิกาขีดสุด
Binary Sequential $\lceil \log_2 N \rceil$ บิต ปานกลาง ลอจิกลึกขึ้นตามจำนวนสถานะ ชิปที่ต้องการประหยัดพื้นที่ซิลิคอนและมีสถานะจำนวนมาก
Gray Code Encoding $\lceil \log_2 N \rceil$ บิต ปานกลาง สลับสถานะทีละ 1 บิตเสมอ ลดพลังงานไดนามิก (Low Dynamic Power) และใช้ในพอยน์เตอร์ของ Asynchronous FIFO

05 เทคนิคการแบ่งไปป์ไลน์ (Pipelining) และการขจัดปัญหา Hazards

การทำ Pipelining คือการแทรกแถวรีจิสเตอร์ (Pipeline Registers) เข้าไปคั่นกลางเส้นทางลอจิกเชิงผสมที่มีขนาดยาว เพื่อลดความล่าช้าวิกฤต (Critical Path Delay $T_{comb}$) ทำให้สามารถเพิ่มความถี่สัญญาณนาฬิกาได้ตามสมการ:

PIPELINE THROUGHPUT & MAXIMUM CLOCK FREQUENCY
$$ f_{clk, max} = \frac{1}{\max(T_{stage\_i}) + T_{cq} + T_{setup}} $$
$$ \text{Throughput} = f_{clk} \times \text{Instructions Per Cycle (IPC)} $$
แม้ Pipelining จะเพิ่มความล่าช้าต่อหนึ่งคำสั่งในหน่วยเวลา (Latency = $N \times T_{clk}$) แต่ช่วยเพิ่มอัตราการผลิตงานรวม (Throughput) ได้มหาศาล อย่างไรก็ตาม ไปป์ไลน์จะเผชิญหน้ากับอุปสรรค 3 ประการเรียกว่า Hazards:
HAZARD 01
Data Hazards (RAW, WAR, WAW)
เกิดขึ้นเมื่อคำสั่งปัจจุบันต้องการใช้ผลลัพธ์จากคำสั่งก่อนหน้าที่ยังประมวลผลไม่เสร็จสิ้นในสเตจท้าย แก้ไขด้วย Operand Forwarding / Bypassing หรือการหยุดไปป์ไลน์ชั่วคราว (Pipeline Stalling / Bubble Injection)
HAZARD 02
Control Hazards (Branching)
เกิดขึ้นเมื่อเจอคำสั่งกระโดดหรือเงื่อนไข (Branch/Jump) ทำให้ไม่ทราบว่าจะต้องดึงคำสั่งถัดไปจากแอดเดรสใด แก้ไขด้วยวงจร Branch Predictor (เช่น 2-bit Saturating Counter หรือ TAGE) หากทายผิดจะต้องล้างท่อไปป์ไลน์ทิ้ง (Pipeline Flush)
HAZARD 03
Structural Hazards (Hardware Conflict)
เกิดขึ้นเมื่อมีสองคำสั่งต้องการใช้ทรัพยากรฮาร์ดแวร์ตัวเดียวกันในรอบสัญญาณนาฬิกาเดียวกัน (เช่น มีพอร์ตหน่วยความจำพอร์ตเดียวแต่ต้องการ Fetch คำสั่งและ Load ข้อมูลพร้อมกัน) แก้ไขด้วยการแยกหน่วยความจำ (Harvard Architecture) หรือใช้ Dual-Port Memories

06 โครงสร้าง Valid-Ready Handshake และคิวส่งผ่านข้อมูล (FIFOs)

ในการเชื่อมต่อระหว่างโมดูลที่มีอัตราการประมวลผลไม่เท่ากัน โพรโทคอล Valid-Ready Handshake (มาตรฐานเดียวกับ AXI4-Stream / TileLink) เป็นสถาปัตยกรรมที่แข็งแกร่งที่สุด:

VALID-READY TRANSFER CONDITION
$$ \text{Data Transfer Occurs} \iff (\text{TVALID} == 1\text{'b1}) \;\land\; (\text{TREADY} == 1\text{'b1}) $$
กฎเหล็ก: ฝั่งส่ง (Producer) ห้ามรอให้ Ready ขึ้นก่อนจึงจะส่ง Valid (ห้าม Combinational Loop ระหว่าง Ready และ Valid) และเมื่อ Valid ขึ้นแล้ว ข้อมูลและ Valid จะต้องนิ่งคงที่จนกว่า Ready จะตอบรับการถ่ายโอนสำเร็จ

เมื่อมีความจำเป็นต้องพักข้อมูลหรือจับคู่ความเร็ว จะใช้ FIFO (First-In First-Out) Buffer โดยแบ่งเป็น:

  • Synchronous FIFO: ขาเขียนและขาอ่านใช้สัญญาณนาฬิกาชุดเดียวกัน ใช้พอยน์เตอร์แบบไบนารีธรรมดาในการตรวจสอบสถานะ full และ empty
  • Asynchronous (Dual-Clock) FIFO: ขาเขียนและขาอ่านอยู่คนละโดเมนนาฬิกา ต้องแปลงพอยน์เตอร์เป็น Gray Code ก่อนส่งข้ามโดเมนผ่าน 2-Stage Flip-Flop Synchronizers เพื่อป้องกัน Metastability และตรวจจับเงื่อนไขเต็ม/ว่างได้อย่างแม่นยำ 100%

07 ยุทธศาสตร์การรีเซ็ตระบบ (Reset Architecture & CDC Synchronizers)

การเลือกวิธีกำหนดสถานะเริ่มต้นของฟลิปฟลอปมีผลกระทบโดยตรงต่อความน่าเชื่อถือของชิป:

สถาปัตยกรรมการรีเซ็ต ข้อดี ข้อเสีย / ข้อควรระวัง
Synchronous Reset กรองสัญญาณรบกวนได้ดี วงจรนิ่ง 100% สอดคล้องกับเครื่องมือ STA และ Formal Verification ต้องการสัญญาณนาฬิกาที่ทำงานปกติจึงจะรีเซ็ตได้ หาก Clock ค้างจะไม่สามารถรีเซ็ตชิปได้
Asynchronous Reset สามารถรีเซ็ตชิปได้ทันทีแม้สัญญาณนาฬิกายังไม่เริ่มทำงาน ประหยัดดาต้าพาธ ไวต่อสัญญาณรบกวน (Spurious Glitches) และมีความเสี่ยงสูงมากในจังหวะปลดรีเซ็ต (Reset Removal / Recovery Violation)
Asynchronous Assert / Synchronous Deassert (แนะนำสูงสุด) เข้าสู่สภาวะรีเซ็ตได้ทันทีแบบอะซิงโครนัส แต่จังหวะปลดรีเซ็ตจะถูกซิงโครไนซ์ให้ตรงกับขอบสัญญาณนาฬิกาเสมอ เป็นมาตรฐานทองคำของอุตสาหกรรมชิป ASIC/SoC ระดับโลก ใช้โครงสร้าง Reset Synchronizer ร่วมกับ Reset Tree Buffer

08 กฎการเขียนโค้ดที่พร้อมสังเคราะห์ (RTL Linting & Synthesis Guidelines)

ก่อนที่โค้ด RTL จะถูกส่งเข้าสู่กระบวนการ Logic Synthesis วิศวกรจะต้องรันการตรวจสอบคุณภาพเชิงสถิต (Static RTL Linting ด้วยเครื่องมืออย่าง Synopsys SpyGlass หรือ Cadence JasperGold) โดยต้องปฏิบัติตามข้อกำหนดดังต่อไปนี้:

  1. Zero Latches Tolerance: ตรวจสอบรายงาน Netlist ว่ามีจำนวน Latch กายภาพเป็นศูนย์ (Zero Inferred Latches) เสมอ ยกเว้นเซลล์ Clock Gating ที่ตั้งใจติดตั้ง
  2. Explicit Width Declarations: ระบุขนาดความกว้างของตัวเลขคงที่ให้ชัดเจน เช่น 8'd12 แทนการเขียนเลขลอยๆ อย่าง 12 เพื่อป้องกันปัญหาบิตล้น (Bit Truncation)
  3. Named Port Mapping: เชื่อมต่อพอร์ตของโมดูลย่อยด้วยชื่อพอร์ตเสมอ (.clk(clk), .rst_n(rst_n)) ห้ามใช้การเชื่อมต่อตามลำดับตำแหน่ง (Positional Mapping) เพราะอาจเกิดข้อผิดพลาดรุนแรงเมื่อมีการแก้ไขพอร์ตในอนาคต
  4. No Hardcoded Delays in Synthesizable Code: ห้ามใส่คำสั่งหน่วงเวลาจำลอง (เช่น #10) ในโค้ด RTL สำหรับสร้างชิป เพราะเครื่องมือสังเคราะห์จะตัดคำสั่งเหล่านี้ทิ้งทั้งหมด
// QUICK CONCEPT CHECK
ในการออกแบบวงจรไปป์ไลน์ เมื่อเกิดปัญหา Data Hazard แบบ Read-After-Write (RAW) ระหว่างสองคำสั่งที่อยู่ติดกัน วิธีการแก้ปัญหาที่ช่วยรักษา Throughput ให้สูงที่สุดโดยไม่ทำให้ไปป์ไลน์หยุดชะงัก (No Stalls) คือวิธีใด?