Coding style: chức năng giống nhau, PPA phải đo riêng

Khoảng 35 phútMức 2/3Bản nháp: một số khẳng định chưa đối chiếu spec

Sau bài này bạn sẽ

  • Phân biệt cấu trúc viết ở RTL với netlist sau tối ưu
  • Giữ carry và latency khi đổi thứ tự mux với toán tử
  • Đánh giá kết luận resource sharing theo report và constraint thực

Một dòng code không phải một cell

Hai công thức đều chọn tổng a+b hoặc c+d theo sel. Công thức đầu viết hai phép cộng rồi chọn kết quả; công thức sau chọn hai operand rồi cộng. Cả hai có thể cùng ngắn, nhưng số toán tử trong text không phải báo cáo diện tích sau tối ưu.

Nguồn đào tạo dùng ví dụ resource sharing để gợi cách nghĩ về cấu trúc. Bài tự kiểm chức năng và giới hạn những gì có thể kết luận khi chưa có thư viện, timing constraint hoặc số liệu target. [1]

Chọn kết quả hay chọn operand

parallel_sums mô tả hai tổng 5 bit rồi mux. selected_sum mux cặp a/b hoặc c/d trước, sau đó thực hiện một phép cộng trong biểu thức RTL. Sel 1 phải chọn a+b ở cả hai module; sel 0 phải chọn c+d.

Đưa mux trước toán tử là một cách diễn đạt khả năng chia sẻ, nhưng optimizer còn được biến đổi mạch trong phạm vi flow. Không khẳng định mỗi dấu cộng luôn sống nguyên thành một cell adder cuối cùng, hoặc tool luôn tự tìm cùng cấu trúc từ hai mô tả.

Hai đầu ra đều là combinational, không có clock hoặc state. Nếu chuyển một kiểu sang pipeline để đạt timing, latency và hợp đồng interface đã đổi; đó không còn là thay style thuần túy.

Tương đương phải giữ cả width và thời điểm

Mỗi operand 4 bit được mở rộng thêm 0 trước phép cộng, để giữ tổng tối đa 15+15=30 trong 5 bit. Biến output rộng 5 không phải lý do để bỏ qua cách xác định width/sign của biểu thức khi đổi code.

TB chọn toàn bộ 65536 bộ a,b,c,d, thử cả hai giá trị sel. Oracle lấy bốn chữ số cơ số 16 từ index và tính tổng integer tương ứng, rồi so với cả hai output. Việc thử đủ 0/1 không chứng minh tương đương khi sel hoặc operand có X/Z; đó là một miền ngữ nghĩa khác cần kiểm riêng. [2]

RTL schematic khác optimized netlist

Sơ đồ ban đầu thường phản ánh nhánh if/mux/toán tử mà front-end nhận ra. Tối ưu có thể xóa điều kiện dư, gom toán tử hoặc chuyển cấu trúc. Vì vậy đếm box trên RTL view rồi kết luận area cuối thường không đủ.

Trong thí nghiệm, Yosys tổng hợp cả hai top và xác nhận không có FF/latch. Đó là kiểm đúng cho ý định combinational; nó không đo hai thiết kế đã dùng cùng số cell tổng hoặc cùng delay. Các report trung gian và report cuối cần được giữ nhãn để người đọc biết đang so cái gì. [3]

Chia sẻ resource không tự bảo đảm timing

Đặt mux trước adder làm đường dữ liệu đi qua mux rồi arithmetic; tính song song rồi mux đặt lựa chọn ở vị trí khác. Trực giác ấy hữu ích để đề xuất phương án, nhưng delay cuối còn phụ thuộc width, mapping, cell drive, fanout và routing.

Không suy “style B luôn nhỏ hơn” hoặc “style A luôn nhanh hơn” từ một hình vẽ tutorial. Khi có target, so cùng function, latency, clock/reset/enable contract và constraint; xem area/slack/power report của đúng flow. Nếu chưa đo, ghi là giả thuyết thiết kế.

Bài chưa chạy STA, power analysis hoặc công nghệ FPGA/ASIC cụ thể. Nó cũng không dùng hai kết quả đúng để tuyên bố mọi cách viết mux với toán tử đều tương đương.

Vét cạn 131072 vector nhị phân

Kỳ vọng trước chạy là 16^4×2=131072 lượt, output cuối 30 và không có state trong hai netlist generic. Mỗi vector phải khớp oracle; không chỉ so hai DUT với nhau, vì hai DUT có thể cùng mắc lỗi.

Chọn kết quả hay chọn operand trước phép cộng

Vét cạn hai kiểu mô tả sum 5 bit và kiểm không sinh state; không suy PPA từ độ ngắn source.

styles.sv RTL
`timescale 1ns/1psmodule parallel_sums(input wire [3:0] a,b,c,d, input wire sel, output wire [4:0] y);  assign y = sel ? ({1'b0,a}+{1'b0,b}) : ({1'b0,c}+{1'b0,d});endmodulemodule selected_sum(input wire [3:0] a,b,c,d, input wire sel, output wire [4:0] y);  wire [3:0] left=sel ? a:c;  wire [3:0] right=sel ? b:d;  assign y={1'b0,left}+{1'b0,right};endmodule
tb_styles.sv testbench
`timescale 1ns/1psmodule tb_styles;  reg [3:0] a,b,c,d;  reg sel;  wire [4:0] parallel_value,selected_value;  integer n,s,want,cases=0;  parallel_sums p(a,b,c,d,sel,parallel_value);  selected_sum m(a,b,c,d,sel,selected_value);  initial begin    for(n=0;n<65536;n=n+1) begin      {a,b,c,d}=n[15:0];      for(s=0;s<2;s=s+1) begin        sel=s[0];        want=s ? ((n/4096)%16+(n/256)%16) : ((n/16)%16+n%16);        #1;        if(parallel_value !== want[4:0] || selected_value !== want[4:0])          $fatal(1,"style mismatch n=%0d sel=%b expected=%0d",n,sel,want);        cases=cases+1;      end    end    if(cases!=131072 || parallel_value!==30 || selected_value!==30) $fatal(1,"style coverage/carry mismatch");    $display("STYLE CHECK cases=%0d max_sum=%0d",cases,parallel_value);    $finish;  endendmodule

Đã kiểm chứng thế nào

  • Phân tích và elaborate theo LRM (pyslang 12.1.0)
  • Lint -Wall (Verilator 5.050)
  • Mô phỏng, exit 0 và output khớp kỳ vọng tính tay (Icarus Verilog 11.0, 4-state)
  • Tổng hợp, số cell khớp kỳ vọng (Yosys 0.70)

Output phải khớp: STYLE CHECK cases=131072 max_sum=30

Kỳ vọng sau tổng hợp: parallel_sums: $_*DFF* = 0parallel_sums: $_*DLATCH* = 0selected_sum: $_*DFF* = 0selected_sum: $_*DLATCH* = 0

Kỳ vọng trước chạy:16^4 x2=131072 vector nhị phân; sum tối đa 15+15=30, giữ carry 5 bit. Oracle dùng các chữ số cơ số 16 của index.

Không claim hai adder luôn tồn tại sau tối ưu, một kiểu luôn nhanh/nhỏ hơn, hoặc tương đương 4-state chưa thử. Generic synthesis chỉ kiểm không có FF/latch.

Các kiểm tra chạy lúc xây dựng nội dung (2026-11-06), không chạy trong trình duyệt. Kỳ vọng được tính tay trước khi chạy.

MULTITOP là warning dự kiến do file chứa hai top độc lập, vẫn kiểm tập mã warning chính xác. Parser/Icarus/Yosys đạt các claim của ví dụ. [4]

Tự kiểm tra

Tự kiểm tra: coding-style

  1. Hai operand 4 bit đều 15; output 5 bit đúng của bài là gì?
  2. 65536 bộ a,b,c,d và cả hai sel tạo bao nhiêu lượt?
  3. Hai module đúng mọi vector nhị phân của bài. Có thể kết luận style nào luôn nhanh hơn chưa?
  4. Vét cạn input 0/1 có tự chứng minh tương đương mọi X/Z không?
  5. So area bằng số box của RTL schematic trước optimize có đủ không?

So chức năng trước, so chi phí sau

Trước khi đổi style, ghi function, width/sign và latency. Sau đó kiểm tương đương trong miền input cần thiết; chỉ dùng report của flow target để kết luận chi phí hoặc timing.

Bài giữ draft/LRM needs-spec-check; kết quả exhaustive nhị phân không thay mọi quy tắc biểu thức chuẩn hoặc báo cáo PPA chưa có.

Nguồn và mức độ đối chiếu

  1. Verilog Coding Style Effect — bản chụp trong resources.zip, Resource Sharing. Trích dẫn; nguồn đã đọc các mục liên quan.
  2. Thí nghiệm nguyên bản ex.a8.coding-style, Phạm vi oracle. Trích dẫn; nguồn đã đọc toàn văn.
  3. Verilog Coding Style Effect — bản chụp trong resources.zip, RTL Schematic vs Optimized Netlist. Trích dẫn; nguồn đã đọc các mục liên quan.
  4. Thí nghiệm nguyên bản ex.a8.coding-style, Bằng chứng nguyên bản. Trích dẫn; nguồn đã đọc toàn văn.
  5. IEEE 1800-2023 SystemVerilog LRM, RTL assignments and simulation semantics: coding-style. Chưa đối chiếu với văn bản nguồn (chưa mở).
  6. Thí nghiệm nguyên bản ex.a8.coding-style, Source, assertions, metadata và verification.json. Trích dẫn; nguồn đã đọc toàn văn.
  7. IEEE 1800-2023 SystemVerilog LRM, Expression width and conditional operator semantics. Chưa đối chiếu với văn bản nguồn (chưa mở).
  8. Verilog Coding Style Effect — bản chụp trong resources.zip, RTL Schematic vs Optimized Netlist; Resource Sharing. Trích dẫn; nguồn đã đọc các mục liên quan.
  9. Thí nghiệm nguyên bản ex.a8.coding-style, styles.sv, tb_styles.sv và verification.json. Trích dẫn; nguồn đã đọc toàn văn.