Friday, November 29, 2019

[Bài 1] Kiến thức từ cơ bản đến nâng cao về việc kiểm tra equivalence giữa 2 design

Tác giả: TrongTran
Ngày: 29/11/2019
Tài liệu tham khảo: https://www.synopsys.com/content/dam/synopsys/implementation&signoff/datasheets/formality-and-formality-ultra-ds.pdf

https://www.techdesignforums.com/practice/technique/equivalence-checking-eco-arm-core-subsystem-stmicroelectronics/

https://www.techdesignforums.com/practice/technique/using-sequential-equivalence-to-verify-clock-gating-strategies/

https://filebox.ece.vt.edu/~athanas/4514/ledadoc/html/pol_formality.html

Hình ảnh trong bài được lấy từ google image.


Sơ lược.

Trước đây mình có cơ hội để trải nghiệm với quá trình synthesis và debug formality rất nhiều và bài này, mình tham khảo một phần từ những kiến thức trên mạng và kiến thức bản thân. Mình không đi chi tiết mà chỉ tập trung giải thích những điểm trọng tâm. Chi tiết các bạn đọc spec của các tool nhé.


Nói tới việc kiểm tra equivalence chúng ta có 2 loại thông dụng đó là:
  • Boolean logic equivalence
  • Sequential equivalence
Trong bài này chúng ta sẽ tìm hiểu về loại thứ nhất đó là Boolean logic equivalence. Phương pháp này thường được sử dụng cho việc kiểm tra giữa RTL và gate hoặc giữa gate và gate. Một số tool hỗ trợ là: Formality (Synopsys), Smart LEC (Cadence)…

Các bạn tham khảo hình bên dưới:




Loại thứ hai là sequential equivalence: Thông thường nếu bạn dùng Boolean logic equivalence, nếu có 1 flip flop không thể map thì kết quả của bạn sẽ bị fail. Nghĩa là một số trường hợp không thể verify được bằng phương pháp 1 sẽ sử dụng phương pháp thứ 2, verify bằng sequential equivalence. Phương pháp này được sử dụng rộng rãi cho việc kiểm tra giữa RTL và RTL, tức là 2 model. Bạn có 1 RTL ban đầu, Sau đó bạn muốn optimize nó. Có thể là bạn sử dụng clock gating để tiết kiệm power (Tắt clock cho một số vùng không cần thiết một vài chu kì). Phương pháp 1 không thể kiểm tra cho clock gating hoặc nếu muốn bạn phải thêm constraint bằng thủ công. Lúc này sequential equivalence sẽ kiểm tra liệu output của các block sequential cùng input có tương đương nhau tại các cạnh lên của clock hay không. Chúng ta hay sử dụng tool VC formal cho việc kiểm tra này. Các bạn tham khảo hình bên dưới:





Tìm hiểu về Boolean logic equivalence

Đầu tiên, Để cho dễ hiểu mình nói đến mục đích của việc kiểm tra equivalence giữa hai design. Như hình bên dưới các bạn có thể thấy. Việc simulation cho RTL sẽ tốn rất nhiều thời gian. Sau khi quá trình verify hoàn tất bạn dùng RTL đó để synthesis ra gate net list.



Trong quá trình chuyển đổi từ RTL sang gate, Bạn có thể dùng 1 số tool phổ biến như: DC compiler, Fusion compiler, Physical compiler… Bạn không thể biết chính xác liệu quá trình từ RTL sang gate có bất kì sai sót nào không. Sai sót trong script hoặc sai sót của tool ..v.v.

Có hai cách để bạn biết điều đó:

Chạy simulation lại với gate net list: Việc này tốn rất nhiều thời gian, quá trình debug cũng khó khăn vì waveform của từng cell cũng sẽ được tạo ra (Mỗi cell được xem như là một submodule). Mình từng debug cho gate và phải nói để load 1 waveform mình tốn gần 1 giờ.

Kiểm tra xem function của gate và RTL có tương đương không: Cách này sẽ tốn ít time hơn, ít resource hơn. Các bạn lưu ý là phương pháp này không kiểm tra function đúng/sai nhé. Nó chỉ có tác dụng là kiểm tra tính giống nhau về mặt function của gate và RTL. Tính đúng sai của function đã được kiểm tra trong quá trình chạy simulation.

SVF file chính là file lưu lại toàn bộ các tiến trình mà các tool khác thực hiện (Ở đây là DC compiler). Các tiến trình đó là gì ? Đó là thay đổi tên của các instance, module, net…. Cũng có thể là optimize logic, delete logic. Quá trình load file này nhằm giúp các tool kiểm tra equivalence có thể biết được cách match các cặp điểm compare point dễ dàng hơn. Với tool DC compiler các file svf được mã hoá. Nhưng bạn không cần lo. Hầu hết các tool kiểm tra equivalence sau khi load xong đều giãi mã ra một file mà chúng ta dễ dàng đọc hiểu. File giải mả của svf chính là file vsdc (Smart LEC dùng file này cho đầu vào).

Để tạo được file svf hoặc vsdc chỉ cần bạn thêm câu lệnh sau vào script synthesis:

Set_svf ten_file.svf

Set_vsdc ten_file.vsdc

Việc kiểm tra giữa gate to gate được áp dụng tại 2 điểm:

Giữa gate trước optimize hoặc chèn các mạch test và gate kết quả.

Giữa gate ECO và gate ban đầu. Các bạn tham khảo hình bên dưới:






Hiện nay các tool trên thế giới có hai flow chạy phổ biến đó là:

  • Flat verification: Nghĩa là các pattern sẽ được đưa vào các input của logic cone và kiểm tra hàng loạt các điểm compare point. Không phân biệt hierarchy.

  • Hier verification: Tool sẽ verify cho các submodule nhỏ trước sau đó tiến hành black box chúng và verify cho những submodule lớn hơn. Phương pháp này có nhiều ưu điểm so với phương pháp flat verification bên trên. Giả sử trong 1 submodule ta có nhiều submodule nhỏ hơn cùng cấp. Vậy ta có thể chạy verify song song cho những submodule này. Điều này giúp giảm thời gian verification. Tuy nhiên bạn cần nhiều số core CPU hơn. Chúng ta sẽ có giới hạn số submodule được verify tối đa cho 1 lần chạy song song.

Đồng thời số CPU set cho việc chạy phải lớn hơn số submodule cần verify song song 1 lần để đạt hiệu quả tối đa.









Nhìn hình trên vậy thui chứ nó không đơn giản đâu nhé. Khó nhất là việc truyền tham số từ ngoài vào các submodule đó để verify.

Trong RTL thực tế ta có một module có thể được gọi nhiều lần. Tuy nhiên, Trong gate mỗi module chỉ được gọi 1 lần.


Một số thuật ngữ cần biết.

Để bắt đầu đi vào chi tiết bài này các ạn cần biết một số thuật ngữ bên dưới.

Logic cone:









Logic cone có thể hiểu là 1 mạch bao gồm các phần tử combinational logic hình nón như hình vẽ bên trên.

Các điểm khởi đầu của logic cone là:

  • Chân input của module.
  • Chân output của flip flop.
  • Ngõ ra của black box.

Black box:

Black box là một model rỗng của một module. Hay nói đúng hơn là chúng ta không biết function bên trong khối black box đó và cũng không cần kiểm tra equivalence của nó. Việc kiểm tra đã được verify trong một tiến trình khác hoặc được đảm bảo bởi nhà cung cấp.

Chân input của black box là các điểm cần compare.

Chân output của black box là input của logic cone.

Chân không xác định hướng được xem là inout

Trong thực tế black box có thể là:

  • Analog cell.
  • RAM
  • Module không cần verify. Trường hợp ta không muốn verify cho module nào đó ta có thể set black box cho nó.

Reference design: Là design ban đầu.
Implemetation design: Là design sau khi chỉnh sữa mà bạn cần kiểm tra xem liệu nó có equivalence với design ban đầu không. Lưu ý không nhầm lẫn giữa hai design này nhé.






Có 3 điểm cần verify:

  • Giá trị tại input của black box.
  • Giá trị ngõ vào của flip flop.
  • Giá trị tại chân output của module.




Giả sử điểm check là A trong hình trên, thì các bộ pattern sẽ được đưa vào tại 3 điểm:

  • Tại các chân input của module.
  • Tại chân output của flip flop.
  • Tại chân output của khối black box.

Các bạn có thể tham khảo hình bên trên.


Pattern là các bộ giá trị [1,0] đưa vào:
  • Chân output của black box.
  • Chân output của flip flop.
  • Chân input của module.

Quá trình kiểm tra equivalence của 2 design được chia thành:

Kiểm tra consistency: Đối với mọi pattern đầu vào, tại điểm so sánh, nếu design reference có kết quả là 1 hoặc 0 thì design implementation phải có cùng kết quả. Nếu design reference có kết quả là x và design implementation có kết quả tại điểm so sánh là 0 hoặc 1 thì quá trình kiểm tra vẫn cho kết quả PASS.


Kiểm tra equality: Quá trình này bao gồm cả quá trình kiểm tra consistency nhưng thêm một vài constraint. Nghĩa là nếu kết quả của design reference là x và design implementation là 0 hoặc 1 thì kết quả là FAIL. Để pass thì kết quả của design implementation cũng phải là x.

Thông thường ta có quy tắc kiểm tra sau:

  • RTL với GATE : Consistency

Cú pháp: set verification_passing_mode consistency

  • GATE vs GATE : equality

Cú pháp: set verification_passing_mode equality

Nếu chúng ta không set mode verify cho module thì mặc định là kiểm tra consistency.

Lưu ý: Design A consistency với Design B. Tuy nhiên, Design B có thể không consistency với design A.

Design A:

module A (in_0, out_0);

input [1:0] in_0;

output out_0;

reg out_0;

always @(*) begin

case (in_0)

2’b00: out = 1’b0;

2’b01: out = 1’b1;

2’b00: out = 1’b0;

2’b01: out = 1’b1;

endcase

end

endmodule



Design B:

module A (in_0, out_0);

input [1:0] in_0;

output out_0;

reg out_0;

always @(*) begin

case (in_0)

2’b00: out = 1’b0;

2’b01: out = 1’b1;

2’b00: out = 1’b0;

2’b01: out = 1’bx;

endcase

end

endmodule



Nếu design A là reference và design B là implementation thì 2 design consistency với nhau.

Nếu design A là implementation và design B là reference thì 2 design không consistency với nhau.

Design A và design B không equality với nhau bất kể là implementation hay reference.




Để tìm được các cặp 2 flip flop so sánh. Các tool sẽ tiến hành match dựa vào 2 phương pháp chính:

  • Match dựa vào name.

Đây là bước ưu tiên trong quá trình match vì nó tốn ít thời gian để tool analyze structure của design.

Tool sẽ tiến hành list ra tất cả:

  • Flop flip
  • Latch
  • Black box

Match dựa vào name được chia làm 3 bước nhỏ:

  • Exact name matching: Match dựa vào tên chính xác của các phần tử cần so sánh.

Ví dụ:

  • Reference: /WORK/top/FF_0
  • Implementation: /WORK/top/FF_0

Hai trường hợp trên tool sẽ match như là 1 cặp cần compare.

  • Reference: /WORK/top/FF_0
  • Implementation: /WORK/top/FF[0]

Nếu bạn có 2 flip flop tên như trên phương pháp “Exact name matching” không thể match chúng được.

  • Match dựa vào net names: Cái này đơn giản chỉ là nếu 2 flip flop khác tên nhau nhưng có các net name cùng tên đi vào thì sẽ được match. Các bạn tham khảo hình bên dưới:







Hai flip flop

  • reference: /WORK/top/submodule_0/FF_0

Và

  • implementation: /WORK/top/submodule_0/FF_0_1


Có tên không giống nhau nhưng các net name đi vào giống nhau nên sẽ được match để như là 1 cặp để so sánh.

Tuy nhiên, thực tế, trong một design lớn không ai dùng phương pháp match này.

Tên các net name trở nên rất đa dạng trong một design phức tạp và việc trùng net name giữa 2 flip flop không cùng chức năng có thể xảy ra. Việc này dẫn đến việc match sai và kết quả verify không đáng tin.

Một điểm lưu ý nữa là các bạn nên sắp xếp thứ tự các phương pháp match ưu tiên vì flip flop đã match trước đó sẽ không được match trong các rule sau.

  • Match với Name filtering

Cú pháp: name_match_filter_chars ‘~!@#$%^&*()_+= |\{}[]”:;<>?,./

Câu lệnh này phải đi kèm với câu lệnh bật tắt chế độ match filter:

Cú pháp: name_match_use_filter true/false

Với cách match này hai instance bên dưới được match với nhau

Reference: /WORK/top/submodule_0/FF_0

Implementation: /WORK/top/submodule_0/FF[0]



Nếu bạn đang synthesis với một số tool như DC compiler, Fusion compiler, Physical compier…

Phương pháp này nên được sử dụng thường xuyên.



Phương pháp thứ hai đó là match dựa vào topological equivalence. Phương pháp này tốn nhiều thời gian để tool phân tích structure của design.


Debug

Một số tool sẽ lưu lại session để giúp cho việc debug.

Để debug. Có 2 cách phổ biến:

Cách 1: Debug dựa vào log file. Bạn kiểm tra log file để xem các điểm fail nằm trong submodule nào. Bạn phải xác định được level của submodule đó.

Ví dụ: fail tại submodule top/sub_0/sub_1

Thì submodule sub_1 thuộc level 2

Sau đó trong script chạy bạn thêm dòng lệnh sau trước quá trình maching và verify:

write_hierarchical_verification_script -level 2 file_name –replace

Và dòng lệnh dưới sau quá trình matching và verify:

source file_name.tcl

Bạn chạy lại quá trình verify. Sau khi chạy xong bạn sẽ thấy được một file là: file_name.tcl

Bạn kiểm tra file file_name.tcl. File này là file giúp chạy verify cho từng submodule nhỏ để tìm lỗi bên trong.

Bạn tiến hành kiểm tra file kết quả: fm_file_name.log

Sau đó bạn mở file file_name.tcl lên tìm submodule bị fail và xem các tham số port đầu vào có truyền đúng không vì nguyên nhân fail có thể từ những submodule khác và truyền tham số qua sai.

Phương pháp này khá là phức tạp và tốn thời gian.



Cách 2: Dùng GUI.

Nếu trong script của bạn có lệnh save_session thì bạn có thể dùng output của lệnh này để debug. Nếu không bạn phải thêm lệnh bên dưới và cuối script chạy của bạn:

save_session –replace name_session

Output của file này là file name_session.

Để dùng GUI debug bạn phải vào chế độ command line của tool.

Để load file session bạn chạy lệnh:

restore_session name_session

và chạy lệnh start_gui để mở chế độ GUI mode lên.

Sau khi chế độ GUI được mở. Cửa sổ các điểm compare point hiện lên bạn dùng lệnh :

report_unmatched_points

hoặc

report_failing_points

Để in ra các điểm fail hoặc các điểm không match. Từ các điểm fail này bạn tìm trong list tương ứng và click chuột phải chọn “Show logic cone”

Trace theo các logic bạn sẽ dễ tìm ra điểm fail hơn.







Các bạn lưu ý: Mấu chốt của việc debug là bạn phải tìm ra các flip flop hoặc các output hoặc black box unmatched. Đây là các điểm dễ gây fail nhất. Vì sao? Mình lấy ví dụ:
Các bộ pattern sẽ được đưa vào :
  • Output của khối black box.
  • Output của flip flop (Chân Q).
  • Input của module.

Giả sử ta có hai module như bên dưới: 
Giả sử ta chỉ sử dụng phương pháp match bằng tên chính xác. Như vậy chỉ có cặp flip flop

r:/WORK/FF1
i:/WORK/FF1
là match với nhau. Còn flip flop FF2 và FF3 không match vì không giống tên nhau.
Nguyên tắc đưa pattern vào đó là nếu 2 điểm match với nhau thì giá trị đưa vào là giống nhau. Trường hợp pattern đưa vào tại 1 và 3 là giống nhau cùng bằng 1 hoặc 0.
Còn giá trị tại 2 và 4 có thễ khác nhau điều này dẫn đến kết quả so sánh bị sai. Các bạn tham khảo hình bên trên.


Nếu có bất kì sai sót nào, mong nhận được phản hồi từ bạn đọc.

Trong bài 2 mình sẽ trình bày về 1 số điểm fail phổ biến.











Friday, November 15, 2019

Phân tích timing violation thông qua một ví dụ cụ thể

Tác giả: TrongTran
Ngày: 15/11/2019
Tài liệu tham khảo: http://www.vlsi-expert.com/, wiki
và các nguồn tư liệu từ internet.



Nếu bạn đang làm về synthesis và các quá trình checker hậu synthesis. Hay nói đúng hơn là bạn đang làm việc với gate net list thì đây là bài tổng quan và rất chi tiết dành cho bạn.

Để phân tích timing có 4 loại path mà bạn cần quan tâm đó là:

  • Từ input đến chân D flip flop (IN2REG).
  • Từ chân CLK của 1 flip flip đến chân output (REG2OUT).
  • Từ chân input đến chân output (IN2OUT).
  • Từ chân CLK của flip flip thứ nhất đến chân D của flip flop thứ 2 (2 flip flop liền kề) (REG2REG).

4 loại path này đã được phân tích kĩ ở trang này nên mình sẽ không giải thích lại: 

http://nguyenquanicd.blogspot.com/2018/07/sta-tong-quan-ve-phan-tich-timing-tinh.html

Trong thực tế nếu bạn đang synthesis cho 1 module nhỏ thì bạn chỉ cần quan tâm đến path REG2REG. Những path khác sẽ được check bởi 1 nhóm khác (Nhóm dùng gate net list của bạn để connect đến module khác).


Trong hình trên, Giả sử bạn đang synthesis cho module A. Khi đó, nhiệm vụ ưu tiên của bạn là đảm bảo đường A3 (reg2reg, đường màu đỏ) không bị violate timing. Các đường A0, A1, A2 sự violation chỉ mang tính tương đối. Vì để kiểm tra timing violation cho các đường này bạn cần phải biết chúng connect đến các flip flop nào trong các module khác. Chỉ có team làm top module mới biết được điều này.

Nói như vậy không có nghĩa là bạn muốn để các path A0, A1, A2 violate bao nhiêu tuỳ thích. Bạn sẽ được cung cấp 1 giới hạn. Ví dụ thời gian delay tối đa là bao nhiêu. Điều này đảm bảo không gây khó khăn trong quá trình phân tích và chỉnh sửa timing ở chip top.

Trong kiểm tra timing chúng ta cần kiểm tra 2 loại violation chính đó là:

  • Hold violation
  • Setup violation



Trước tiên bạn cần hiểu hold violation và setup violation là gì?

Quan sát hình trên ta thấy: 
  • Nếu tín hiệu data chưa ổn định trong khoảng thời gian tsu thì ta gọi đó là setup violation. Ngược lại nếu tín hiệu data chưa ổn định trong khoảng thời gian thd thì được gọi là hold violation.
  • Nếu data thay đổi trong miền gạch chéo trước tsu thì data không bị delay 1 chu kì. Nếu data thay đổi trong miền gạch chéo sau thd thì data bị delay 1 cycle.

Chú ý tsu là setup time và thd là hold time của 1 flip flop. Với mỗi flip flop khác nhau chúng ta sẽ có tsu và thd khác nhau. Lí giải cho việc này các bạn có thể tham khảo hình bên dưới:

Cấu trúc D flip flop

                                   Cấu trúc jk flip flop. 
Với mỗi flip flop khác nhau, chúng ta sẽ có mạch combinational logic giữa chân clk và D, giữa chân D và Q khác nhau do đó hold time và setup time sẽ khác nhau. Cùng 1 loại D flip flop nhưng nếu được sản xuất bởi các linh kiện bên trong khác nhau sẽ có hold time và setup time khác nhau.


Tiếp theo mình sẽ hướng dẫn bạn cách tính timing violation chi tiết cho một mạch cụ thể.

Ta có một mạch như bên dưới:



Yêu cầu là bạn phải kiểm tra timing violation cho path REG2REG (Nghĩa là từ chân clock của FF1 sang chân D của FF2).

Trước tiên chúng ta xem xét hình bên dưới:



Hold violation

Để kiểm tra hold violation, chúng ta cần biết được timing delay của path:
  • Minimum delay của path: A0 -> A1 -> A2 -> A3 -> A4 (1)
  • Maximum delay của path: A0 -> A1 -> B1 -> A4 (2)

Nếu hiệu số (1) –(2) > 0 thì mạch không bị hold violation.

(1) = 1 + 9 + 1 + 6 + 1 = 18 ns

(2) = 3 + 9 + 3 + 2 = 17ns

Vì Hold slack = (1) – (2) = 18 – 17 = 1ns > 0. Mạch này không bị Hold violation.

Giả sử hold time = 4ns thay vì 2 ns như đề bài thì ta có

(3) = 3 + 9 + 3 + 4 = 19 ns

Lúc này Hold slack = 18 – 19 = -1 ns < 0

Lúc này mạch sẽ bị hold violation.

Setup violation

Để kiểm tra setup violation, chúng ta cần biết được timing delay của path:

Maximum delay của path: A0 -> A1 -> A2 -> A3 -> A4 (3)

Minimum delay của path: T (Chu kì clock) + A0 -> A1 -> B1 - tsu (setup time) (4)

Nếu hiệu số setup slack = (4) – (3) > 0, mạch của chúng ta không bị setup violation.

Xét mạch trên ta có: (3) = 2 + 11 + 2 + 9 + 2 = 26 ns

(4) = 15 + 2 + 5 + 2 - 4 = 20 ns

Ta thấy setup slack = 20 – 26 = -6 ns < 0 . Do đó mạch của chúng ta bị setup violation.

Trường hợp trên giả sử ta sử dụng clock chậm hơn, nghĩa là T = 22 ns khi đó

(4)= 22 + 2 + 5 + 2 – 4 = 27 ns

Setup slack = 27 – 26 = 1ns > 0 do đó setup violation sẽ không xảy ra.


Như vậy, Chúng ta có 1 số phương pháp để tránh setup violation và hold violation:

  • Thay đổi độ dài dây dẫn giữa hai flip flop: Như chúng ta tính toán trong ví dụ trên, Sự delay của dây dẫn cũng có thể gây ra setup violation hoặc hold violation. Nếu mạch của chúng ta bị hold violation chúng ta có thể di chuyển flip flop (Place and route) để delay trên đường data path lớn và delay trên đường clock path nhỏ lại. Thường thời gian delay của wire là không lớn nên phương pháp này được sử dụng để giải quyết các violation nhỏ và số lượng path bị violation không nhiều. Đây là một phương pháp phổ biến được sử dụng nhiều.
  • Thay đổi các phần tử trên đường bị violation. Các phần tử được sản xuất bởi các vật liệu khác nhau, cấu trúc khác nhau sẽ có cac thông số delay khác nhau.
  • Chèn buffer hoặc cặp inverter: Phương pháp này nhằm đạt được thời gian delay mong muốn. Buffer và cặp inverter sẽ không làm thay đổi giá trị logic của tín hiệu. Khi chúng ta muốn tăng thời gian delay của một số path như mong muốn ta có thể chèn các buffer hoặc cặp inverter vào.
  • Nếu timing violation rất lớn và chúng ta không thể giải quyết được bằng các phương pháp trên, thì bắt buộc ta phải thêm 1 flip flop vào giữa 2 flip flop trên. Việc này được thực hiện bởi designer và mang tính rủi ro cao. Lúc này ta phải tiến hành verification lại nhằm đảm bảo việc delay 1 cycle của tín hiệu data không gây fail function.
  • Cho module chạy với clock chậm (Tăng chu kì). Phương pháp này ít được sử dụng vì nó đòi hỏi phải thay đổi design rất nhiều. Việc cho module này chạy với clock chậm sau đó dùng mạch async để sync tín hiệu với clock nhanh. Phương pháp này được sử dụng khi mạch chúng ta đang bị setup violation (Xem công thức tính setup violation bên trên).
Nếu bài viết có gì sai sót mong nhận được ý kiến từ bạn đọc. Vui lòng gọi về số: 0339339692 hoặc e-mail trongk10@gmail.com để góp ý.

Tuesday, October 22, 2019

[Design][Bài 2] Tìm hiểu về clock crossing domain (Một số ví dụ vi phạm trong thiết kế mạch đồng bộ 2 FF)

Tác giả: TrongTran
Ngày: 22/10/2019
Tài liệu tham khảo: https://tel.archives-ouvertes.fr/tel-01053729/file/Distributed_clock_generator_for_synchronous_SoC_using_ADPLL_network.pdf
và các nguồn tư liệu từ internet,

Tham khảo một số hình ảnh waveform từ Wikipedia.


Hi, Lại là mình đây.

Hôm nay mình tiếp tục nói về các lỗi trong thiết kế mạch bất đồng bộ. Phần hôm nay tập trung vào tín hiệu data bất đồng bộ (không phải tín hiệu control nhé, tín hiệu control sẽ được nói trong bài tiếp theo).


Trường hợp 1

Đầu tiên và cơ bản nhất đó là lỗi không dùng mạch đồng bộ cho các tín hiệu bất đồng bộ.

Điều này sẽ gây ra hiện tượng bất ổn định hay còn gọi là metastabilities. 




Trong hình trên, nếu tín hiệu w1 thay đổi (0->1 hoặc 1->0) trong khoảng từ hold time hoặc setup time của clock c2 thì lúc này hiện tượng metastabilities xảy ra.


Trạng thái metastabilities là trạng thái data không xác định được giá trị. Phải mất một khoảng thời gian để đạt trạng thái ổn định.

(Ảnh nguồn : http://hardwarebee.com/metastability-in-fpgas/)

Trong hình bên trên chúng ta có thể thấy tín hiệu Din thay đổi ngay trong khoảng thời gian từ setup time đến hold time của clock clk2. Tuy nhiên tại đây Din không xác định giá trị là 0 hay 1 (Vì độ nghiên của cạnh data). Từ đó FF đầu tiên chạy với CLK2 không thể bắt chính xác giá trị từ Din và trạng thái bất ổn định xảy ra. Ta dùng 2 FF nhầm loại bỏ trạng thái này vì hầu như sau 1 chu kì xung clock CLK2,  tín hiệu ngõ ra Ds đã ổn định và FF thứ hai chạy với clock CLK2 đã bắt đúng giá trị ổn định đó.

Thời gian để tín hiệu trở nên ổn định. Nghĩa là từ khi xảy ra metastabilities đến khi đạt trạng thái 0 hoặc 1 gọi là closure time (Có thể gọi là metastable phase).

Close sure time được định nghĩa như bên dưới:


Clock cycle ≧ Closure time + Tsetup + Tskew + Tjitter

         ↑ ↑       ↑

       FF thứ nhất  FF thứ hai  clock properties

Như vậy MTBF sẽ phụ thuộc vào 3 yếu tố:

  • Tần số clock C1, C2.
  • Đặc điểm thư viện flip flop.
  • Closure time. 

Với một MTBF cho trước và thời gian closure time cho trước ta có thể lựa chọn thư viện cho FF đầu tiên trong mạch 2 FF phù hợp để có được design mong muốn.

Thế nên chúng ta mới có khái niệm meta FF, đó là các flip flop có tuổi thọ cao , bền và có các thông số phù hợp với MTBF và closure time cho trước.

Nếu điều kiện trên không thoả, nghĩa là chúng ta không thể chọn được FF đầu tiên phù hợp với mục đích ban đầu đưa ra thì có 2 cách giải quyết:

  • Tăng số tầng FF đến 3 FF hoặc 4 FF. Tuy nhiên, cách này sẽ làm tăng latency của hệ thống.
  • Trường hợp nếu tăng latency không được chấp nhận thì còn một cách là sử dụng bộ đồng bộ hoá pha.

Cái này thì mình chịu nè. Mình chưa biết đồng bộ khoá pha là gì. Chắc sẽ bổ sung sau. 

Một trường hợp khác cũng gây ra lỗi tương tự đó là fanout tín hiệu giữa 2 mạch 2FF như hình dưới:


Hoặc:



Tín hiệu metastabilities không nên đưa vào các mạch logic vì sẽ gây ra sai fucntion cũng như ảnh hưởng đến hệ thống.

Trường hợp 2

Lỗi thứ hai liên quan đến việc chèn các logic trước mạch async 2FF như hình bên dưới: 



Việc này sẽ gây ra glitch. Nghĩa là giả sử có sự delay giữa hai wire w1 và w2 như trên hình (Nguyên nhân có thể do dây dẫn, do combinational logic, ...). Thì lúc này glitch sẽ xuất hiện tại w3.
Các bạn tham khảo glitch như hình dưới:

Mình lấy ví dụ combinational logic là cổng AND.

Lúc này Glitch sẽ xuất hiện như sau:



Dữ liệu đúng phải là:
Tại xung clock lên X, tín hiệu w1 sẽ từ 1->0 và w2 sẽ từ 0->1. Lúc này kết qua w3 phải là = 0 vì 1 & 0 = 0. Tuy nhiên vì w1 vì một lí do nào đó bị delay như hình trên lúc này w3 sẽ có 1 khoảng 1&1 = 1. Hình trên clock C2 không bắt được glitch nên đầu ra không sao. Tuy nhiên, trường hợp glitch bị ngay trong khoảng thời gian từ setup time đến hold time của clock C2 thì glitch sẽ được capture và đầu ra sẽ bằng 1 trong 1 chu kì chứ không phải là 0 như kết quả ban đầu.

Vậy trong mạch đồng bộ, glitches có xuất hiện không. Câu trả lời là có. Tuy nhiên thời gian glitch tồn tại nhỏ và khi data truyền đến chu kì tiếp theo của clock (Cạnh lên clock tiếp theo) thì nó sẽ không capture được glitch để transfer. Ý mình là thời gian glitch kết thúc luôn sớm hơn thời gian bắt đầu một chu kì clock mới (data lúc này mới được capture).  Còn nếu delay quá nhiều dẫn đến glitch ảnh hưởng đến cạnh clock lên tiếp theo thì cái này STA sẽ control.

Glitches trở nên sai trong mạch bất đồng bộ trường hợp khi glitch vừa lên lúc này đúng ngay khoảng thời gian từ setup time hoặc hold time của clock phía nhận. Và data được transfer đi không đúng như chúng ta mong muốn.

Trường hợp 3

Trường hợp một output từ khối A bạn muốn nối đến nhiều input của khối B. Bạn phân nhánh nó tại khối A và dùng nhiều mạch đồng bộ cho từng nhánh đó. Điều đó có thể dẫn đến sự khác nhau về giá trị giữa các nhánh đó. 



Nguyên nhân là sau FF đầu , tín hiệu chuyển sang trạng thái metastabilities và lúc này FF 2 sẽ có thể bắt tín hiệu khác nhau là 0 hoặc 1. Dẫn đến tín hiệu ngõ ra có thể bị shift. Nghĩa là tín hiệu ngõ ra giữa out_2 và out_3 sẽ không giống nhau.

Hình dưới biểu thị data tại ngõ ra đã bị shift và không giống nhau.




Hãy dùng mạch 2 FF để đồng bộ tín hiệu output trước sau đó hãy phân nhánh nó vào từng input hợp lí. Điều này giúp giảm gate size của chip vì ta không cần đồng bộ cho từng nhánh mà chỉ đồng bộ 1 tín hiệu rồi phân nhánh nó sau khi đã đồng bộ.

Trường hợp 4

Phân nhánh data sau FF thứ nhất trong 2 FF. lúc này STA check không thể kiểm tra timing cho path này và sự delay khác nhau của các line này có thể gây ra việc shift data trong output của FF thứ 2.


Hiện tượng trong trường hợp này khá giống như trường hợp 3 bên trên.

Trường hợp 5

Data có thể bị lost nếu như độ rộng của xung data nhỏ hơn 1,5 lần chu kì clock nhận.

Mình nghĩ cái này khá là cơ bản và bạn nào cũng có thể biết. Có nhiều tài liệu nói về vấn đề này. Một số tài liệu ghi là xung data phải lớn hơn 2 lần. Tuy nhiên mình nghĩ 1,5 lần là đủ rồi.

Bạn thử nghĩ nếu xung data quá nhỏ. Lỗi hay gặp là transfer từ clock nhanh sang clock chậm. Data toggle sau khi cạnh clock lên và trước cạnh clock lên tiếp theo của clock C2 thì FF thứ 2 sẽ không capture được. Đây là một lỗi tưởng đơn giản nhưng rất nguy hiểm đấy nhé.

Hãy cẩn trọng với confirmation cho các path như thế này.

Trường hợp 6

Có lẽ đây là trường hợp cuối cùng trong phạm vi hiểu biết của mình về lỗi trong mạch đồng bộ tín hiệu data.



Trong 1 bus nhiều tín hiệu. Chúng ta không được sử dụng mạch đồng bộ cho từng tín hiệu riêng lẽ vì nhu vậy data trong bus sẽ bị thay đổi.

Với một bus chúng ta sẽ có mạch đồng bộ riêng để nhầm tránh sự sai biệt này.

Hôm nay viết dài rồi. Chắc bữa khác mình bổ sung hi vọng nó giúp bạn có cái nhìn tốt hơn về vấn đề đồng bộ mạch async. Nếu có gì sai sót vui lòng gửi comment hoặc gửi mail góp ý cho mình : Trongk10@gmail.com 

Sunday, October 20, 2019

[Design] Tìm hiểu về round robin arbiter

Tác giả: TrongTran
Ngày: 20/10/2019
Tài liệu tham khảo: https://sinhvientot.net/giai-thuat-dieu-phoi-round-robin-rr/
và các nguồn tư liệu từ internet.



Tình hình là mình đang gặp một issue trong quá trình verification và nó liên quan đến độ ưu tiên của khối arbiter.

Mình thấy nó khá là hay nên đã nghiên cứu và record lại. Mình không viết các bài liên tục vì mình không đủ thời gian. Khi mình gặp issue nào đó mình sẽ nhảy vào nghiên cứu và ghi lại như là một note. Dĩ nhiên note thì sẽ có sai sót. Hi vọng mọi người có thể học hỏi và góp ý cho mình.


1. Sơ lược về arbiter.

Mình lấy một ví dụ đơn giản trong cuộc sống hằng ngày. Có 3 người cần đi mua hàng tại một siêu thị.

Người thứ nhất (A) cần mua 20 gói mì, người thứ 2 (B) cần mua 2 gói mì, người thứ 3 (C) cần mua 4 gói mì.

Như vậy nhiệm vụ của một bộ arbiter cũng giống như cách mà chúng ta giải quyết bài toán này để đảm bảo sự công bằng cho cả 3 người. Cả 3 người đều được mua hàng nhưng không phải đợi quá lâu.

Trở lại vấn đề, Bây giờ ta xem người A như master A, tương tự cho người B, C như master B, C.

Có 3 khả năng xảy ra:

  • Master A gửi request đến slave trước. Lúc này chưa có master nào được gửi. Thì mặc nhiên A sẽ được đi qua.Đây là trường hợp các master gửi đến slave không cùng 1 lúc. Như vậy master nào gửi trước sẽ được qua trước, master nào gửi sau sẽ đi sau.
  • Các master đến cùng 1 lúc và không xét độ ưu tiên giữa các master. Khi đó ta sẽ gán 1 thông số biểu thị thứ tự của từng master để quyết định master nào được gửi trước và master nào gửi sau trong trường hợp cùng đến 1 lúc.
  • Các master đến cùng 1 lúc và có tính đến độ ưu tiên. Lúc này, Các master có độ ưu tiên cao hơn sẽ chiếm lấy quyền access đến slave bất kể khi nào nó access đến bộ arbiter.
Trên thực tế, trong một design, không phải lúc nào master cũng được xem xét có độ ưu tiên ngang nhau. Ví dụ các IP về xử lí ảnh sẽ được ưu tiên transfer data trước. Điều này dẫn đến người design cần thiết lập độ ưu tiên cho các master này.

Mình tóm lại, Bộ arbiter có chức năng xem xét để quyết định xem tại một thời điểm master nào sẽ được access vào slave đồng thời điều khiển BW cho từng master đó.


2. Round robin arbiter. 

Có một số RTL code trên mạng viết cho bộ arbiter, Mình thấy đa số chỉ dùng cấu trúc đơn giản:

if

else


Giả sử trong 1 chip thực tế khi chúng ta sử dụng cấu trúc như trên. Nghĩa là nếu có từ 2 master access liên tục cùng lúc đến cùng 1 slave thì master nào nằm trong vòng if trước sẽ được transfer liên tục và master còn lại cần phải đợi master kia transfer hết data mới bắt đầu transfer.

Điều này làm giảm performance của chip vì như vậy sẽ làm giảm khả năng thực hiện nhiều function cùng 1 lúc của 1 chip.

Hầu hết các thiết kế ngày nay, các nhà design đều sử dụng bộ round robin arbiter.
Một số ưu điểm của bộ này đó là cân bằng được bandwidth và phân bổ tài nguyên hợp lí giữa các master.

Trong 1 bộ round robin arbiter có thể có 2 mode hoạt động chính:

  • Điều khiển BW cho từng master. Nghĩa là mỗi master sẽ được thiết lập một độ ưu tiên. Các master đòi hỏi BW cao hơn hoặc tốc độ xử lí nhanh hơn thì sẽ cần nhiều BW hơn.
  • Không điều khiển BW cho các master. Đây là chế độ mặc định. Các master sẽ được phân bổ round robin với không thiết lập ưu tiên. Nghĩa là master nào cũng được cung cấp 1 BW như nhau.
Trong ví dụ phần trên về 3 người A, B, C đi mua mì, các bạn có thể thao khảo sự phân bổ round robin như hình dưới:




Mỗi người sẽ mua được tối đa 3 gói mì. A mua trước và mua 3 gói, khi đó A nhường cho B để B mua. Lúc này A muốn mua tiếp phải đợi B mua xong 3 gói rồi tới C sau đó mới tới A.

Ta có sơ đồ như hình bên dưới:



Trong hình trên sp đại diện cho số request được gửi tối đa trong một lần gửi (Hay còn gọi là số quantum). req là tổng số request của master còn lại chưa được gửi đến slave.

Mô hình một bộ arbiter như bên dưới:




Khối mux ở đây là để quyết định sẽ cho transaction từ master nào được đi qua.

Combinational logic là nhằm kiểm tra xem địa chỉ bạn đi vào có hợp lệ không.

Module control sẽ điều khiển chế độ hoạt động của bộ arbiter. Có 2 chế độ hoạt động như bên dưới:

Không control BW.

Control BW cho một số master.

Như vậy, Làm thế nào module control có thể điều khiển BW cho các master đi qua bộ arbiter. Đó là nhờ vào cập tín hiệu VALID/READY. Nghĩa là nhờ vào cơ chế bắt tay. Tín hiệu valid thì dĩ nhiên được gửi từ master và chúng ta không thể control được, như vậy ta sẽ control tín hiệu READY. Nghĩa là điều khiển việc khi nào slave sẽ sẵn sàng nhận tín hiệu từ master.

Trong chúng ta ai cũng biết, BW tỉ lệ thuận với số transaction giao dịch thành công trong một đơn vị thời gian. Vì vậy việc điều khiển tín hiệu READY sẽ giúp chúng ta tính toán được chính xác BW đi qua bộ arbiter.

Cơ chế round robin :
Mình lười viết quá nên mình lấy một hình trong 1 trang web về round robin cho CPU. Nó tương tự cho arbiter. Các bạn tham khảo bài đầy đủ ở đây ha:

https://sinhvientot.net/giai-thuat-dieu-phoi-round-robin-rr/



Hình trên mô tả round robin không có độ ưu tiên. P1 vào trước. Lúc này P1 sẽ sử dụng CPU. Ta xét số quantum = 4. Quantum là số thời gian tối đa 1 tiến trình dùng CPU liên tục. Trong bộ arbiter thì đó là số transaction được transfer trong 1 lượt từ 1 master qua bộ arbiter. Nếu vượt quá nó sẽ chặn lại và cho master kế tiếp qua.

Trường hợp nếu P1 không vào trước mà cả P1, P2, P3 vào cùng lúc thì sao. Chúng ta sẽ có 1 trọng số để quyết định tiến trình nào được thực hiện trước.


Trường hợp hình trên giống như xe cứu hoả vậy. bộ arbiter là đèn đỏ. Khi xe qua đèn đỏ thì mọi người phải dừng lại nhường cho đến khi xe cứu hoả qua xong. Đây là bộ arbiter có xét đến tính ưu tiên.

Bài tiếp theo mình sẽ design 1 arbiter nho nhỏ để các bạn tham khảo.





Tuesday, October 15, 2019

[Design][Bài 1] Tìm hiểu về clock domain crossing (CDC)

Tác giả: TrongTran
Ngày: 15/10/2019
Tài liệu tham khảo: https://tel.archives-ouvertes.fr/tel-01053729/file/Distributed_clock_generator_for_synchronous_SoC_using_ADPLL_network.pdf
và các nguồn tư liệu từ internet.


1. Tổng quan. 

Hiện nay , Để giảm thiểu thời gian design thì các nhà sản xuất chip trên thế giới thường sử dụng các IP sẵn có. Các IP này là những IP common. Nghĩa là chúng thực hiện một chức năng riêng biệt nào đó mà hầu hết mọi chip đều sử dụng với mục đích giống nhau. 

Ví dụ: IP chuyển đổi chuẩn PCIe và chuẩn AMBA của ARM, ipmmu …. 

Với việc sử dụng các IP có sẵn người design có thể tập trung vào những phần khác của design quan trọng hơn. Đó là các phần tạo nên sự khác biệt giữa chip của họ so với những chip khác trên thị trường. 

Với việc sử dụng các IP có sẵn, Một vấn đề khác đặt ra đó là các IP có sẳn chỉ chạy với một số tần số nhất định. Trong trường hợp chip của bạn hoạt động với tần số trùng với tần số của các IP này, điều đó khá là tốt. Tuy nhiên, Nếu IP của bạn hoạt động khác tần số với các IP này thì vô tình thiết kế của bạn sẽ có nhiều vùng clock trong một chip. Điều này dẫn đến việc design cho mạch đồng bộ giữa các miền clock async trở nên phức tạp. Bên cạnh đó nhằm tăng performance của chip, chúng ta cũng cần thiết kế các IP chạy với clock khác nhau.




Hình trên miêu tả tổng quan về các khối IP sử dụng các clock khác nhau. Đồng bộ trong từng khối nhỏ và bất đồng bộ giữa các khối với nhau.

Mạch đồng bộ các tín hiệu clock sẽ có thể được đặt tại 3 vị trí:

Trong IP nhận hoặc gửi: Thường được sử dùng nhiều trong các design trước đây.Điều này đòi hỏi IP nhận/gửi cần input clock của IP gửi/nhận để cung cấp clock cho các mạch 2 FF đồng bộ. Lưu ý ở đây là trong 1 chuẩn giao tiếp sẽ luôn có việc trao đổi tín hiệu hai chiều (Ví dụ chuẩn AMBA thì kênh AR/AW/W từ master qua slave, kênh R/B từ slave đến master) do đó dù đặt mạch async trong IP gửi hoặc nhận thì cũng phải cần input clock của khối còn lại. Mình ví dụ hình bên dưới block A là khối gửi (được thiết kế đồng bộ) nhưng phải input clock clk2 để cấp clock cho mạch đồng bộ trước khi out data ra ngoài. Đồng thời sử dụng clock clk1 để đồng bộ các tín hiệu feedback. Việc này khá rườm rà và khó quản lí. 




Trong cả IP gửi và nhận: Như mình nói bên trên, trong 1 chuẩn giao tiếp sẽ luôn có việc trao đổi tín hiệu hai chiều. Giả sử ta có 2 khối A và B. Một số tín hiệu từ A gửi sang B sẽ có mạch đồng bộ các tín hiệu này tại B (Khối nhận). Một số tín hiệu từ B gửi sang A sẽ có mạch đồng bộ các tín hiệu trong A (Khối nhận). Việc này thật sự rất khó control. Tốn nhiều tài nguyên và design sẽ trở nên phức tạp.

Trong Top module: Tức là người design sẽ thiết kế một cầu chỉ có chức năng đồng bộ 2 clock. Cầu này sẽ chứa các mạch 2FF để đồng bộ các tín hiệu async. Clock vào là 2 clock gồm clock IP nhận và clock IP gửi. 


Cách này đang là xu hướng design trên thế giới. Nó giúp việc verify trở nên dễ dàng, Người build top dễ xác định và chạy kiểm tra timing cho design cũng như các lỗi khác.

Ngoài ra, với cách design bên trên thì ta có thể merge các cầu async lại thành 1 cầu async duy nhất để dễ quản lí và làm giảm area cũng như sự phức tạp của chip. Lưu ý nếu chip quá to thì chúng ta không nên gộp lại vì chúng ta sẽ không thể met timing.
Điều này còn giúp ta quản lí skew của clock theo một khối riêng biệt như hình dưới:





2. Phân loại.

Dựa vào kiểu tín hiệu async, Ta có thể chia thành 2 loại:

  • Mạch đồng bộ cho tín hiệu control.

  • Mạch đồng bộ cho tín hiệu data.

Dựa vào cách xác định 2 tín hiệu async, Ta có thể chia thành 3 loại tín hiệu cơ bản đó là:

  • Tín hiệu data truyền từ bên ngoài vào mà không rõ timing. Thường đây là các tín hiệu bên ngoài chip chẳng hạn data truyền từ router, từ PCIe…

  • Tín hiệu truyền giữa hai miền clock khác nhau bao gồm: Khác về tần số, Khác pha, Tín hiệu chạy với clock nguồn và tín hiệu chạy với clock output của bộ PLL.

  • Tín hiệu reset bên ngoài vào mà không rõ timing.
Ngoài ra nếu hai tín hiệu chạy với clock cùng tần số, cùng pha nhưng khác clock source, thì chúng vẫn được xem là async với nhau.

Hình bên dưới cho thấy clock source và clock đi qua khối PLL là khác nhau:


3. Giải pháp.

Để đồng bộ các tín hiệu async, trong thiết kế ngày nay ta hay dùng mạch 2 FF. Dĩ nhiên có nhiều mạch sync mà không dùng 2FF nhưng ở đây mình chỉ biết mạch này (Mình sẽ bổ sung sau).Với mạch này ta có một thông số gọi là MTBF (mean time between failure) để đặc trưng cho thời gian giữa hai lần fail liên tiếp.

Failure rate = 1/MTBF (cho một mạch async) và Failure rate của toàn bộ design sẽ bằng tổng của tất cả các Failure rate trong thiết kế. Đơn vị đo lường của MTBF là đơn vị thời gian. Thường thì thời gian giữa hai lần fail rất lớn (MTBF từ 100 – 1000 năm).

Trong bài tiếp theo mình sẽ phân tích về một số mạch async có thể gây ra lỗi trong quá trình design.

Nếu bài của mình có sai sót gì mong nhận được sự góp ý nhiệt tình từ mọi người. Vì bản thân không phải là chuyên gia, cũng mài mò học hỏi nên không tránh khỏi sự sai sót.

Cách tính BW và latency trong 1 hệ thống SoC sử dụng chuẩn giao tiếp AXI protocol

Tác giả:  TrongTran Ngày:  31/12/2019 Nếu bạn nào đang làm về verification cho system performance (ST) thì bài này sẽ bổ ích cho bạn. Ngày ...