if, case và loops: chọn nhánh đúng khi có X/Z
Tiên quyết
- Module A6: Verilog cấu trúc: Đang tải
- Initial, always và fork: đọc nhiều process cùng chạy: Đang tải
Sau bài này bạn sẽ
- Phân biệt ưu tiên if-else-if với phép so khớp của case
- Dự đoán tác động của X/Z và wildcard thay vì gọi mọi unknown là0
- Viết vòng lặp có điều kiện kết thúc và accumulator đúng
- Phân biệt lặp tính toán với lặp có timing control
Cùng selector, các cấu trúc có thể chọn khác
Một decoder chọn đường theo sel hai bit. Với sel=11, bạn muốn ưu tiên bit cao; với sel có X/Z, bạn muốn phát hiện dữ liệu chưa hợp lệ. Hai mục tiêu ấy cần được nói rõ trước khi đổi if sang case để code trông gọn hơn.
TB của bài dùng cùng một selector cho if ưu tiên, plain case, casez và casex. Với 0z, kết quả lần lượt 0/3/1/1; với 0x là 0/3/3/1. Khác biệt xuất phát từ ngữ nghĩa chọn nhánh, không phải simulator tự “đoán” X/Z thành một giá trị điện áp.
if-else-if xác định ưu tiên
Decoder xét if(sel[1]), tiếp theo else if(sel[0]), cuối cùng else. Khi cả hai bit bằng 1, chỉ nhánh đầu chạy và trả mã 2. Hai if độc lập không có cùng ý nghĩa: cả hai có thể chạy, lần gán sau có thể ghi đè kết quả trước.
Một branch điều khiển một statement; dùng begin/end khi nhiều statement cùng thuộc nhánh. Indentation không tạo scope. Đặt default cho output tổ hợp và gán đủ mọi đường đi giúp diễn đạt rõ ý định không lưu state; phần tổng hợp cụ thể cần kiểm riêng, không suy ra từ tên biến reg. [1]
Điều kiện một bit và vector chứa unknown
Trong if(sel[1]), điều kiện chỉ một bit; 1 chọn then, còn 0/X/Z không chọn then. Vì vậy sel=0x khiến cả hai phép kiểm bit không đúng và decoder vào else 0. Đó là hành vi mô phỏng có thể che unknown, thường gọi là X optimism ở kiểu quyết định này.
Không được rút gọn thành “vector có bất kỳ X thì luôn false”. TB còn kiểm trực tiếp if(sel): sel=1x có bit 1 đã biết nên vector vẫn chắc chắn khác 0, chọn true. Vét cạn 16 selector bằng cặp 0/1/X/Z xác nhận cả priority, plain case và vector truth cho đúng ví dụ.
Nguồn đào tạo mô tả điều kiện dạng ngắn; bài giới hạn và kiểm lại trường hợp vector thay vì mở rộng câu ấy thành mọi quy tắc ngôn ngữ. Chi tiết đầy đủ còn [2].
Plain case so khớp đủ bốn trạng thái
Plain case so khớp từng bit, phân biệt 0,1,X,Z. Decoder chỉ liệt kê 00,01,10,11; mọi selector có X/Z rơi vào default 3. Default ở đây là mã báo không khớp của ví dụ, không phải chữ X và cũng không tự tạo assertion.
Nếu case item chứa X/Z, plain case đòi đúng các giá trị ấy; chúng không tự là wildcard. Bài không dùng item kiểu đó để mô tả phần cứng tổng hợp. Cũng không coi default là bằng chứng toàn bộ input đều hợp lệ: muốn fail trên opcode chưa biết phải có checker riêng. [3]
Wildcard có thể giấu dữ liệu chưa biết
casez bỏ qua vị trí Z hoặc dấu hỏi trong phép match; casex còn bỏ qua X. Wildcard có thể nằm ở expression hoặc item, nên sel 0z có thể match item 01 và trả 1 dù bit thấp chưa biết.
Ở sel 0x, casez của ví dụ về default 3, còn casex match 01 và trả 1. Nhưng “casez thấy X thì luôn default” cũng sai: sel 1x vẫn match item 1?, trả 2. Chính dấu hỏi ở item đã bỏ qua bit thấp chứa X.
Do đó cần biết chỗ nào được phép don't-care theo thiết kế và chỗ nào phải báo lỗi. Bài đưa casex vào để làm lộ rủi ro, không khuyến nghị dùng nó để làm regression hết đỏ. Khi nhiều item match, thứ tự viết là điều cần xét. [4]
for và while không tự tạo clock
for có khởi tạo, điều kiện và bước; while kiểm điều kiện trước mỗi lượt. Cả hai có thể chạy hết ở cùng một timestamp nếu thân không chứa timing control. TB tính tổng 0+1+2+3 bằng cả hai cách và kiểm tổng 6, thời gian trước/sau vẫn 275 ns.
Ngược lại, repeat(3) #2 có ba lần chờ 2 ns nên kết thúc 281 ns. Không phải từ khóa repeat tự làm mất sáu ns; timing control trong thân mới làm process chờ.
Popcount của DUT dùng for cộng 8 bit vào accumulator bằng blocking, reset accumulator 0 mỗi lần evaluation. Oracle TB tra số bit 1 của từng nibble rồi cộng hai kết quả, tránh lặp lại nguyên thuật toán DUT. Các loop RTL có biên hằng thường được tool triển khai thành cấu trúc; bài chưa chạy synthesis nên không claim topology hay số gate. [5]
16 selector, 256 byte và hai loại thời gian lặp
Tính trước chạy: if ưu tiên bit cao đã biết 1, plain case chỉ match bốn mã nhị phân; ba ca wildcard nêu ở trên có expected riêng. Mọi byte nhị phân 0..255 được kiểm popcount bằng bảng nibble; ff có 8 bit 1.
16 lần chờ selector,3 ca đặc biệt và 256 byte tạo 275 ns trước các loop không delay. Repeat thêm 6 ns. Assertions kiểm cả dữ liệu lẫn thời gian; một vòng for có lỗi biên sẽ không được che bằng dòng output tổng hợp. [6]
Ranh giới cú pháp, mô phỏng và synthesis
- Đổi if-else-if thành hai if rồi vô tình đổi ưu tiên.
- Quên begin/end hoặc default cho output tổ hợp.
- Dùng biến đếm quá hẹp làm nó quay vòng trước khi đạt điều kiện dừng.
- Cộng dồn bằng NBA và mong mỗi iteration thấy accumulator mới ngay.
- Nghĩ for 8 lượt luôn cần 8 clock, dù không có event/delay trong thân.
- Coi wildcard che X/Z là sửa đúng nguyên nhân khởi tạo/reset.
- Dùng kết quả simulation để tuyên bố synthesis/PPA chưa thực chạy.
Trong RTL sản phẩm, kiểu loop và điều kiện phải phù hợp synthesis flow; không khái quát rằng mọi while đều tổng hợp được hoặc mọi loop trong TB đều tự tiến thời gian. Các quy tắc cú pháp Verilog và SystemVerilog cũng khác: bộ ví dụ này biên dịch ở chế độ SystemVerilog.
Tự kiểm tra
Kiểm nhánh biên trước khi tin biểu thức ngắn
Viết bảng quyết định cho trường hợp hai điều kiện cùng đúng, tất cả sai và input unknown. Với loop, kiểm giá trị khởi đầu, điều kiện thoát, độ rộng biến đếm và có hay không timing control.
Nguồn đào tạo đã đọc hỗ trợ cách phân loại; bằng chứng tool phủ các ca nêu rõ. Bài giữ draft/LRM needs-spec-check.
Nguồn và mức độ đối chiếu
- Verilog if-else-if — bản chụp trong resources.zip, Syntax và ưu tiên. Trích dẫn; nguồn đã đọc các mục liên quan.
- IEEE 1800-2023 SystemVerilog LRM, cần đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).
- Verilog case statement — bản chụp trong resources.zip, x and z in the case expression. Trích dẫn; nguồn đã đọc các mục liên quan.
- Verilog case statement — bản chụp trong resources.zip, casez and casex. Trích dẫn; nguồn đã đọc các mục liên quan.
- Verilog for Loop — bản chụp trong resources.zip, for loop. Trích dẫn; nguồn đã đọc các mục liên quan.
- Thí nghiệm nguyên bản ex.a7.control, Bằng chứng nguyên bản. Trích dẫn; nguồn đã đọc toàn văn.
- IEEE 1800-2023 SystemVerilog LRM, Conditional, case/casez/casex and loop statements; truth values. Chưa đối chiếu với văn bản nguồn (chưa mở).
- Thí nghiệm nguyên bản ex.a7.control, TB nguyên bản, assertions và verification.json. Trích dẫn; nguồn đã đọc toàn văn.
- IEEE 1800-2023 SystemVerilog LRM, Conditional/case/loop statements; logical truth values; wildcard matching. Chưa đối chiếu với văn bản nguồn (chưa mở).
- Verilog if-else-if — bản chụp trong resources.zip, Syntax; Priority in an if-else-if Chain. Trích dẫn; nguồn đã đọc các mục liên quan.
- Verilog case statement — bản chụp trong resources.zip, x and z in the case expression; casez and casex; How is a case different from if-else?. Trích dẫn; nguồn đã đọc các mục liên quan.
- Verilog for Loop — bản chụp trong resources.zip, Syntax; How Synthesis Handles a for Loop; for Loop in Combinational Logic. Trích dẫn; nguồn đã đọc các mục liên quan.
- Thí nghiệm nguyên bản ex.a7.control, control.sv, tb_control.sv và verification.json. Trích dẫn; nguồn đã đọc toàn văn.