Thứ Bảy, 8 tháng 9, 2018

[DFT] Mô tả cơ bản về DFT - Design For Test

Bài viết này trình bày tổng quan về khái niệm DFT (Design For Test), tại sao cần phải có DFT? và kỹ thuật DFT được áp dụng như thế nào?

1) DFT là gì? Tại sao cần phải có DFT?
DFT là một kỹ thuật giúp cho một thiết kế có thể được kiểm tra (test) dễ dàng và đầy đủ hơn sau khi sản xuất thành chip mà không cần quan tâm đến chức năng của mạch (thiết kế). Một quy trình sản xuất không thể đảm bảo toàn bộ chip được sản xuất ra đều đạt chất lượng và không có lỗi. Lỗi ở đây là lỗi vật lý (physical fault) sinh ra so quá trình sản xuất, không phải lỗi chức năng hay lỗi logic (logical fault) do thiết kế sai. Lỗi chức năng do thiết kế sai phải được phát hiện khi mô phỏng và kiểm tra trước khi sản xuất.
Một số lỗi vật lý có thể gặp như nối đất GND (stuck-at-0, s-a-0), nối nguồn  VCC (stuck-at-1, s-a-1), ngắn mạch (short), hở mạch (open). Một lỗi vật lý sinh ra sẽ làm cho hoạt động của chip bị sai hoặc không thể hoạt động.
Hình 1: Các lỗi vật lý có thể sinh ra trong quá trình sản xuất chip
Để dễ hình dung, các bạn hãy liên tưởng đến việc kiểm tra các bo mạch in (PCB), một bo mạch in sau khi sản xuất phải được kiểm tra xem các đường mạch có bị nối GND, VCC, ngắn mạch hay hở mạch (bị đứt) hay không. Chip cũng cần được kiểm tra các lỗi như vậy. Một chip gồm hai phần logic là user logic và DFT logic. Trong đó, user (function) logic là thành phần xử lý các chức năng dành cho người dùng chip, DFT logic dùng để test chip.
Hình 2: Một vi mạch gồm User logic and DFT logic
Tóm lại, kỹ thuật DFT là kỹ thuật giúp kiểm tra chip dễ dàng và đầy đủ hơn bằng cách thêm các logic dùng cho việc test vào trong chip. Nếu không có DFT, một chip vẫn có thể được kiểm tra thông qua đo đạc và chạy các test chức năng (fucntion test) trên chip nhưng thời gian test rất lâu và không đảm bảo toàn bộ chip được test đầy đủ (coverage thấp). Ví dụ, một chip không có DFT, nếu chạy các test chức năng có thể mất 30 giây (hoặc nhiều hơn) cho một chip thì tổng thời gian test cho một lô sản phẩm 100.000 chip là khoảng 35 ngày, cho 1 triệu chip là 347 ngày. Nhưng với kỹ thuật DFT, tổng thời gian test có thể giảm hơn 10 lần. Tuy nhiên, việc áp dụng kỹ thuật DFT sẽ làm kích thước chip lớn hơn do phải thêm các logic phục vụ việc test.
2) Mạch DFT được thực hiện như thế nào?
Phần này sẽ trình bày một số ví dụ cơ bản để hiểu kỹ thuật DFT được thực hiện như thế nào? áp dụng ở bước nào trong quy trình thiết kế vi mạch số? và các khái niệm cơ bản liên quan đến kỹ thuật DFT. Để minh họa cho phần này, chúng ta xét ví dụ hình 3. Mạch này có chức năng tìm mức logic chiếm ưu thế từ các ngõ vào in1, in2 và in3:
  • Nếu 2 hoặc 3 ngõ vào có mức logic "0" thì ngõ ra out_z = 0
  • Nếu 2 hoặc 3 ngõ vào có mức logic "1" thì ngõ ra out_z = 1
Verilog code của mạch này như sau:
assign a12 = ~(in1 & in2);
assign a13 = ~(in1 & in3);
assign a23 = ~(in2 & in3);
assign out_z = ~(a12 & a13 & a23);
Hình 3: (a) Bảng sự thật (b) Sơ đồ nguyên lý
Trước khi gửi bản thiết kế đi sản xuất, các lỗi chức năng (function/logic fault) của mạch hình 3 sẽ được tìm thấy thông qua kiểm tra chức năng (function verification) bằng cách cung cấp các giá trị đầu vào cho in1, in2 và in3 và giám sát giá trị ngõ ra out_z thông qua một testbench nếu sử dụng phương pháp mô phỏng (simulation) hoặc bằng một mô hình tương đương nếu sử dụng phương pháp kiểm tra formal. Nếu out_z luôn đúng với tất cả các tập giá trị ngõ vào in1, in2 và in3 như bảng sự thật thì ta nói chức năng của mạch này được coverage 100% (function coverage).
Sau khi sản xuất thành chip hoàn chỉnh, để có thể phát hiện được các lỗi sinh ra trong quá trình sản xuất chúng ta có thể:
  • Chạy thử nghiệm từng chức năng cụ thể của chip. Cách này tốn nhiều thời gian test như đã trình bày ở phần trên.
  • Sử dụng kỹ thuật DFT. Cách này giảm thời gian test nhưng có thể phải thêm nhiều logic để hỗ trợ việc này.
Trước khi chip được sản xuất, người thiết kế phải phân tích "chiến lược" (kế hoạch) test chip để xác định xem thiết kế hiện tại có khả năng test được các lỗi vật lý ở mức chip hay không? Về cơ bản, hai hoạt động chính của việc phân tích và thiết kế DFT là:
  • Mô hình hóa các lỗi vật lý (fault modelling) để dự đoán các lỗi có thể xuất hiện và đưa ra giải pháp để phát hiện các lỗi này.
  • Thiết kế logic hỗ trợ việc phát hiện các lỗi vật lý nếu cần. Chú ý, việc thêm DFT logic là để giúp việc test ở mức chip dễ dàng hơn, tuy nhiên trong một số trường hợp, DFT logic không cần phải thêm mà vẫn có thể test được.
Giả sử, xét đường kết nối nội bộ a12, trong hoạt động thông thường, đường a12 sẽ đáp ứng theo các giá trị của hai ngõ vào in1 và in2. Nhưng nếu có lỗi vật lý xảy ra như bị nối GND hay nối VCC, giá trị đường này có thể bị giữ cố định ở mức logic "0" (stuck-at-0) hoặc "1" (stuck-at-1). Stuck-at-1 và stuck-at-0 chính là các mô hình lỗi (fault model). Làm thế nào để kiểm tra hai lỗi này trên đường a12?
  • Để kiểm tra stuck-at-1: Lái a12 được lái đến mức logic 0 và kiểm tra a12. Nếu a12 đúng bằng "0" thì kết luận a12 không bị lỗi stuck-at-1.
  • Để kiểm tra stuck-at-0: Lái a12 được lái đến mức logic 1 và kiểm tra a12. Nếu a12 đúng bằng "1" thì kết luận a12 không bị lỗi stuck-at-0.
Tiếp theo, giải pháp để phát hiện các lỗi đã được mô hình hóa cho đường a12 là gì? Làm sao để lái a12 đến giá trị mong muốn? Làm sao để giám sát giá trị trên đường a12 là đúng hay sai? Ở mức chip, việc điều khiển và giám sát các tín hiệu (đường) nội bộ, như a12, a13 và a23, chỉ có thể thông qua các chân (port, pin) chip, ví dụ như là in1, in2, in3 và out_z trong trường hợp này.
Một đường kết nối bên trong chip chỉ được kiểm tra khi nó có thể được điều khiển đến giá trị mong muốn (controllable) và có thể được giám sát (observable). Trong ví dụ hình 3, a12 có thể được điều khiển đến giá trị mong muốn thông qua in1 và in2. Đường a12 có thể được kiểm tra thông qua ngõ ra out_z. Như vậy, đường a12 có cả hai thuộc tính controllable và observable.
Hình 4: Khả năng test ở mức chip
Để kiểm tra một đường kết nối bên trong chip, một hoặc nhiều tập giá trị ngõ vào được tạo ra để lái đường cần test đến giá trị mong muốn. Các tập giá trị này gọi là các "mẫu kiểm tra" (test-pattern). Để test hai mô hình lỗi stuck-at-1 và stuck-at-0 cho đường a12, chúng ta cần các test-pattern như sau:
  • Stuck-at-1:
    • Test-pattern 1: in1=in2=1 để a12 = 0 và in3=0 để a13=a23=1, ngõ ra out_z sẽ được giám sát và kiểm tra với giá trị mong muốn là out_z=1. Nếu chỉ dùng test-pattern 1, kết quả không đủ để khẳng định "a12 không bị lỗi struck-at-1" vì out_z=1 có thể do a13=0 hoặc a23=0 nếu một trong hai đường này bị stuck-at-0. Vì vậy, chúng ta cần thêm test-pattern để khẳng định a13 và a23 không bị stuck-at-0.
    • Test-pattern 2: in1=in2=in3=0 để a12=a13=a23=1 và giám sát ngõ ra out_z=0. Kết quả của test-pattern này có thể khẳng định a13 và a23 không thể bị stuck-at-0 vì out_z=0 chỉ khi a12=a13=a23=1.
  • Stuck-at-0: Để kiểm tra trường hợp này, chúng ta có thể dùng test-pattern in1=in2=in3=0 và giám sát ngõ ra out_z=0. Chú ý, nếu out_z=0, chúng ta có thể kết luận "a12 không bị lỗi stuck-at-0" còn nếu out_z=1 chúng ta không thể kết luận "a12 bị lỗi stuck-at-0" vì có thể là do a13 hoặc a23 bị lỗi này. Tuy nhiên, việc xác định đường nào bị lỗi không quan trọng trong trường hợp này vì nếu test-pattern này FAIL vì bất cứ nguyên nhân nào thì chip sẽ bị loại bỏ và không được sử dụng.
Trong phân tích trên, lỗi struck-at-1 cần 2 test-pattern để kiểm tra, lỗi stuck-at-0 chỉ cần 1 test-pattern để kiểm tra. Trong đó, test-pattern để phát hiện lỗi stuck-at-0 có thể là trùng với test-pattern 2 dùng để phát hiện lỗi stuck-at-1. Bên cạnh đó, để phát hiện lỗi stuck-at-0, chúng ta có thể sử dụng một trong các test-pattern sau để giám sát out_z=0:
  • in1=in2=in3=0
  • in1=in2=0, in3=1
  • in1=in3=0, in2=1
  • in2=in3=0, in1=1
Với thiết kế trong ví dụ hình 2, giả sử đây là một thiết kế chip hoàn chỉnh, chúng ta không cần thêm DFT logic để test vì bản thân mạch này đã hỗ trợ khả năng test ở mức chip. Trường hợp này, chúng ta chỉ cần tạo ra các test-pattern để sử dụng. Các test-pattern này không cần phải đầy đủ toàn bộ các tổ hợp giá trị ngõ vào của in1, in2 và in3 vì mục tiêu của chúng ta là kiểm tra được các mô hình lỗi để tìm ra các lỗi vật lý chứ không phải kiểm tra đầy đủ chức năng.
Trước khi sản xuất, các test-pattern được sử dụng để đánh giá khả năng phát hiện lỗi thông qua bước mô phỏng lỗi (fault simulation). Fault simulation là mô phỏng một thiết kế trong điều kiện lỗi. Bước mô phỏng này dùng để đánh giá xem có bao nhiêu lỗi có thể được phát hiện trên một số lượng test-pattern cụ thể. Số lượng lỗi có thể phát hiện sẽ được thể hiện bằng thông số fault coverage.
fault coverage (%) = (tổng số lỗi được phát hiện/tổng số lỗi có thể phát hiện)*100
Fault coverage đánh giá khả năng phát hiện lỗi của một tập test-pattern ứng với một mô hình lỗi nhất định, ví dụ như mô hình lỗi stuck-at.
Hình 5: Mô hình mô phỏng lỗi - Fault simulation
Fault simulation được thực hiện bằng cách so sánh kết quả của một thiết kế không lỗi (golden design) và một thiết kế chứa các mô hình lỗi cần test (design with fault model) trên cùng một tập test-pattern. Nếu kết quả hai ngõ ra khác nhau, nghĩa là một lỗi đã được phát hiện. Nếu kết quả hai ngõ ra giống nhau, nghĩa là test-pattern hiện tại không thể phát hiện lỗi đã được giả định.
Ví dụ hình 3 là một mạch tổ hợp đơn thuần, trong trường hợp mạch tuần tự có chứa FF thì sao? chúng ta xét ví dụ về một thiết kế như hình 6, đây là một thanh ghi dịch cho phép ghi giá trị ban đầu khi we=1.
Hình 6: Một thanh ghi dịch cho phép ghi giá trị ban đầu
Làm sao để phát hiện lỗi trên các đường kết nối nội bộ như n0, a0, a1, a2, a3, or0 hay or1? Mạch tuần tự thực chất gồm 2 phần cơ bản là phần mạch tổ hợp và FF. Chúng ta có thể tách riêng các phần mạch tổ hợp ra để xem xét từng phần như hình 7.
  • com0 là phần mạch tổ hợp tại ngõ vào của FF0. com0 chỉ là một dây dẫn.
  • com1 là phần mạch tổ hợp tại ngõ vào của FF1.
  • com2 là phần mạch tổ hợp tại ngõ vào của FF2.

Hình 7: Phân tách phần mạch tổ hợp và FF để xem xét
Ví dụ, xét đường a0 của com1, đường này có thể được điều khiển dễ dàng thông qua các chân ngõ vào và kết quả được giám sát thông qua giá trị chân shift_out[1].
  • Kiểm tra stuck-at-1: we=0, FF0 được gán giá trị 0 thông qua din[0], kiểm tra giá trị trên shift_out[1] phải bằng 0.
  • Kiểm tra stuck-at-0:  we=0, FF0 được gán giá trị 1 thông qua din[0], kiểm tra giá trị trên shift_out[1] phải bằng 1.
Hình 8: Mô phỏng lỗi để xác định stuck-at-0 (trái) và stuck-at-1 (phải)
Đối với ví dụ này, các đường bên trong thiết kế vẫn có thể được lái dễ dàng thông qua các ngõ vào thiết kế và giám sát qua các ngõ ra thiết kế nên không cần thêm các DFT logic trong trường hợp này. Do mạch có FF nên cần chú ý thời điểm cung cấp test-pattern cho thiết kế và thời điểm giám sát kết quả là khác nhau. Trong hình 8, phía bên trái, test-pattern được cung cấp trong khoảng từ T1 đến T2 nhưng kết quả được giám sát trong khoảng từ T3 đến T4.
Xét một ví dụ khác hình 9, mạch này có chức năng "X", đối với kỹ thuật kiểm tra DFT, chúng ta không quan tâm đến chức năng (function) của mạch mà chỉ quan tâm làm thế nào để test dễ dàng một kết nối trong thiết kế nên tác giả gọi đây là mạch "X".
Hình 9: Sơ đồ mạch "X"
Trong mạch X, tương tự, chúng ta xác định được hai nhóm mạch tổ hợp của FF1 và FF2 là com0 và com1. Các kết nối nội bộ như n0, or0, a0, na0, a1 và x0 chỉ có thể được lái bởi ngõ ra của các FF0, FF1 và FF2 nên để test các đường kết nối nội bộ chúng ta phải biết chức năng của mạch để biết khi nào các FF lái đường cần test đến giá trị mong muốn. Thiết kế càng lớn thì việc test theo chức năng mạch sẽ phức tạp và mất thời gian vì khả năng điều khiển (controllable) và giám sát (observable) của các đường kết nối nội bộ càng khó, thậm chí là không thể được. Kỹ thuật DFT sẽ giúp giải quyết vấn đề này.
Như đã phân tích, trong thiết kế các FF là phần tử lưu giữ giá trị và lái các mạch tổ hợp. Ví dụ, để kiểm tra đường a1 của mạch com1 không bị stuck-at-0, a1 cần được lái đến giá trị 1. Trong trường hợp này, các giá trị cấp cho mạch tổ hợp com1 như sau:
  • a1 được lái bằng 1 khi out[1]=1 và n0=1. Trong đó, n0=1 khi FF0./Q=0 bằng cách lái in_0=1.
  • out[2] được lái bằng 0
Sau đó, giám sát giá trị tại x0 phải bằng "1". Nhận xét, việc test a1 sẽ đơn giản nếu các FF (FF0, FF1, FF2) có thể được lái (gán) giá trị dễ dàng. Như vậy, "làm sao để lái giá trị cho các FF khi test mà không phụ thuộc vào chức năng mạch?". Điều này được thực hiện bằng cách thêm một MUX để có thể lựa chọn giá trị cho FF khi cần test như hình 10:
  • test_mode = 0: mạch hoạt động theo chức năng thông thường (user mode)
  • test_mode = 1: giá trị tại chân "?" sẽ được nạp cho các FF. Vấn đề là "?" lấy từ đâu?
Hình 10: Thêm một MUX để điều khiển giá trị của FF khi test
Trong hình 10, chúng ta thấy để lái các FF đến giá trị mong muốn, các MUX phải được thêm vào cho mỗi FF và một chân (pin) mới của chip được sinh ra để điều khiển là chân test_mode. Mỗi dấu "?" có thể được nối đến một chân chip như hình 11. Tuy cách này hoàn toàn có thể thực hiện nhưng khi số lượng FF lớn, nó sẽ làm số chân chip sẽ tăng nên cách này không được sử dụng trên thực tế.
Hình 11: Một cách lái FF khi test_mode=1 nhưng sẽ không được dùng trên thực tế khi số lượng FF quá lớn
Thay vì nạp giá trị cho FF theo cách "song song" như hình 11, chúng ta sẽ nạp theo cách "nối tiếp" như hình 12. Theo cách này, khi test_mode=1, ngõ ra Q của một FF sẽ nối đến ngõ vào D của một FF khác tạo thành một chuỗi FF nối tiếp gọi là chuỗi scan (scan chain) và hoạt động như một thanh ghi dịch (shift regsiter) có đầu vào là scan_in và đầu ra là scan_out.
Hình 12: Mạch logic được áp dụng kỹ thuật DFT
Hình 12 là một ví dụ đặc biệt, trong trường hợp này, chân in_0 có thể dùng làm chân scan_in và MUX ngõ vào của FF0 có thể được loại bỏ. Chân out[2] có thể dùng làm chân scan_out. Như vậy, chip không cần có thêm hai chân mới. Tuy nhiên, trường hợp tổng quát chúng ta sẽ có 3 chân mới là test_mode, scan_in và scan_out.
Hình 13: (a) Mạch không có DFT và (b) có DFT
3) Quá trình test với mạch có DFT
Một chip khi đã áp dụng kỹ thuật DFT, quá trình test sẽ gồm các bước cơ bản sau:
  1. Cung cấp dữ liệu test (test pattern) cho các FF bằng cách lái test_mode=1 và dịch từng bit của test pattern vào chuỗi scan qua chân scan_in theo từng xung clock.
  2. Lấy mẫu (sample, capture) giá trị cần giám sát bằng cách lái test_mode=0 trong 1 chu kỳ xung clock. Giá trị ngõ ra của các mạch tổ hợp được nạp vào các FF trong chuỗi scan.
  3. Thu thập dữ liệu giám sát qua chân scan_out bằng cách lái test_mode=1.
Để test đường a1 không bị stuck-at-0, như đã phân tích chúng ta cần:
  • Lái FF0./Q là 0, tương ứng FF0.Q=1
  • Lái FF1.Q=1
  • Lái FF2.Q=0
Test pattern mong muốn là chuỗi bit 011, 0 được đưa vào trước vì nó dùng để lái FF2 nằm ở cuối chuỗi scan. Dữ liệu giám sát mong muốn là 1XX. Trong đó, "1" là giá trị mong muốn được lấy mẫu từ chân x0 của com1 và lưu trong FF2, còn "X" là giá trị được lưu vào FF1 và FF0. Chú ý, "X" biểu thị ý nghĩa "không quan tâm" (don't care) trong test pattern này chứ không phải là một giá trị bất kỳ hay không xác định.
Hình 14: Mô phỏng kiểm tra lỗi cho đường a1 ở hình 12
Chú ý, thứ tự kết nối các FF trong chuỗi scan có thể được chọn tùy ý chứ không nhất định là FF0->FF1->FF2 như ví dụ minh họa. Nghĩa là chân scan_in có thể đặt ở FF1 hoặc FF2; chân scan_out có thể đặt ở FF0 hoặc FF1. Nhưng khi thay đổi chuỗi scan, thứ tự giá trị của test pattern cũng phải được điều chỉnh tương ứng.
Tóm lại, bài viết này nhắm mục tiêu cung cấp một cái nhìn cơ bản về kỹ thuật DFT. Với kỹ thuật scan, test pattern được đưa vào chân scan_in và giá trị giám sát được lấy trên chân scan_out.
Nếu các bạn có ý kiến cần trao đổi học góp ý, xin comment dưới bài viết hoặc gửi email đến nguyenquan.icd@gmail.com.

2 bình luận:

  1. Bài viết giúp em hiểu dc quy trình shift bit của DFT (shift - capture - get sampled values) mà trước đây chưa thông được. Cảm ơn a rất nhiều ạ!

    Trả lờiXóa
  2. Bài viết rất hay cho người mới bắt đầu học về DFT, cảm ơn tác giả rất nhiều.

    Trả lờiXóa