Bài 14: Crossing Clock Domains trong FPGA (Chuyển đổi miền đồng hồ)
Xử lý các lỗi thời gian và metastability
Crossing clock domain trong FPGA là một nhiệm vụ phổ biến, nhưng nó là một trong nhiều thứ làm hà thiết kế kỹ thuật số gặp rắc rối. Vấn đề có thể xảy ra nếu nhà thiết kế kỹ thuật số không hiểu tất cả các chi tiết liên quan đến việc chuyển từ miền đồng hồ này sang miền khác. Một miền đồng hồ đơn yêu cầu tất cả Flip-Flops được điều khiển bởi một đồng hồ. Trong bài viết này, hai phần đầu tiên mô tả cách truyền các tín hiệu riêng lẻ từ miền đồng hồ này sang miền đồng hồ khác. Phần cuối cùng đi vào chi tiết về cách sử dụng FIFO để gửi một lượng lớn dữ liệu giữa hai miền đồng hồ. Sử dụng FIFO là phương pháp phổ biến nhất và đáng tin cậy nhất!
Chuyển từ tên miền đồng hồ chậm hơn sang miền đồng hồ nhanh hơn
Loại chuyển đổi đơn giản nhất sẽ chuyển từ một miền đồng hồ sang miền đồng hồ nhanh hơn. Trong chuyển đổi này, bạn vẫn còn phụ thuộc vào metastability , nhưng việc sửa chữa được mô tả trong bài viết đó hoạt động rất tốt trong tình huống này. Tất cả những gì bạn cần làm là dữ liệu "double-flop", được thể hiện trong hình bên dưới.
Đồng hồ chậm hơn là miền đồng hồ nguồn của bạn. Đồng hồ nhanh hơn là miền đồng hồ đích của bạn. Trong miền đồng hồ nhanh hơn, Flip-Flop đầu tiên có đầu ra metastability. Lý do điều này xảy ra là khi thực chuyển đổi là sẽ có vi phạm về thời gian thiết lập và thời gian giữ, nguyên nhan của metasibility . Chúng ta có thể giải quyết vấn đề này bằng cách đơn giản đăng ký lại hoặc nhân đôi dữ liệu trên miền đồng hồ nhanh hơn như trong hình trên. Đầu ra của Flip-Flop thứ hai sẽ ổn định và bây giờ dữ liệu có thể được sử dụng trong miền đồng hồ nhanh hơn.
Cách tìm kiếm các cạnh khi chuyển giữa các miền đồng hồ
Mã dưới đây cho thấy cách bạn có thể tìm kiếm một cạnh tăng trên tín hiệu khi chuyển từ miền chậm sang miền đồng hồ nhanh. Lưu ý rằng logic của bạn để phát hiện cạnh phải được thực hiện trong miền đồng hồ nhanh.
-- VHDL Example process (i_Fast_Clk) is begin if rising_edge(i_Fast_Clk) then -- r1_Data is METASTABLE, r2_Data and r3_Data are STABLE r1_Data <= i_Slow_Data; r2_Data <= r1_Data; r3_Data <= r2_Data; if r3_Data = '0' and r2_Data = '1' then -- Positive Edge Condition end if; end if; end process;
// Verilog Example: always @(posedge i_Fast_Clock) begin // r1_Data is METASTABLE, r2_Data and r3_Data are STABLE r1_Data <= i_Slow_Data; r2_Data <= r1_Data; r3_Data <= r2_Data; if (r3_Data == 1'b0 && r2_Data == 1'b1) begin // Positive Edge Condition end end
Chuyển từ miền đồng hồ nhanh hơn sang miền đồng hồ chậm hơn
Tình huống này hơi phức tạp hơn so với trước đó. Ở đây chúng ta đang đi từ một miền đồng hồ nhanh đến miền chậm hơn. Trong tình huống này, thật dễ dàng để tưởng tượng một ví dụ trong đó dữ liệu bên trong miền đồng hồ nhanh có thể thay đổi trước khi miền đồng hồ chậm nhìn thấy nó. Ví dụ, hãy xem xét một xung xảy ra cho 1 chu kỳ đồng hồ trong một miền đồng hồ 100 MHz, mà bạn đang cố gắng lấy mẫu trong một miền đồng hồ 25 MHz. Có một cơ hội tốt mà bạn sẽ không bao giờ nhìn thấy xung này nếu bạn chỉ cần lấy mẫu dữ liệu với đồng hồ 25 MHz. Để truyền tín hiệu từ miền đồng hồ nhanh sang miền đồng hồ chậm, bạn phải kéo dài tín hiệu của mình . Tham khảo các số liệu dưới đây để có một biểu diễn trực quan về điều này.
Kéo dài dữ liệu của bạn xảy ra khi bạn kéo dài một xung hoặc dữ liệu đủ lâu để đảm bảo rằng miền đồng hồ chậm có cơ hội lấy mẫu. Trong ví dụ trên, bạn cần phải kéo dài dữ liệu của mình để đảm bảo rằng thời gian thiết lập và thời gian giữ được đáp ứng bất kể khi dữ liệu được lấy mẫu. Để đảm bảo đúng thời gian thiết lập và giữ được đáp ứng, tôi khuyên bạn nên kéo dài xung của mình sao cho chúng mất ít nhất 2 chu kỳ đồng hồ trong miền đồng hồ chậm. Vì vậy, trong ví dụ trên, bạn nên kéo dài xung 100 MHz đến ít nhất 8 chu kỳ đồng hồ (bạn luôn có thể sử dụng nhiều hơn).
Chuyển giữa các miền đồng hồ với nhiều dữ liệu. (FIFO)
Tôi đã giữ gìn cái tốt nhất đến phút cuối. Đến nay, cách phổ biến nhất để gửi dữ liệu giữa hai miền đồng hồ là sử dụng FIFO . Một yêu cầu ở đây là bạn cần đảm bảo rằng FIFO bạn sử dụng hỗ trợ hai tần số xung nhịp khác nhau. Một số FIFO chỉ hỗ trợ một đồng hồ. Khi chuyển từ miền đồng hồ này sang tên miền đồng hồ khác, bạn phải đảm bảo rằng hai quy tắc của FIFO được duy trì:
- Không bao giờ viết thư cho FIFO đầy đủ
- Không bao giờ đọc từ một FIFO trống
Miễn là hai quy tắc đó được duy trì, bạn sẽ ổn thôi. Vì các miền đồng hồ của bạn khác nhau, bạn cần lưu ý mức độ của các từ trong FIFO của bạn. Điều này thường được thực hiện tốt nhất bằng cách sử dụng các cờ FIFO gần đầy (AF) và gần rỗng (AE) . Vì vậy, hãy suy nghĩ về tình hình của bạn và đảm bảo rằng cả hai mặt đọc và viết của FIFO sẽ không sao.
Cờ gần đầy (AF) và cờ gần rỗng (AE) là bạn thân nhất của bạn! Nhiều FIFO cung cấp cho bạn một số từ trong FIFO, nhưng tôi không khuyên bạn nên sử dụng điều này. Ngoài ra, nếu bạn viết mã của mình một cách chính xác, bạn cũng không cần phải dựa vào cờ Trống hoặc Cờ đầy đủ, chỉ cần dùng cờ AE / AF.
Hãy xem xét một trường hợp mà chúng tôi có một số dữ liệu mô-đun bằng văn bản cho một FIFO ở 33 MHz. Về phía đọc, chúng tôi đang đổ dữ liệu càng nhanh càng tốt vào bộ nhớ ngoài. Giả sử đồng hồ đọc là 110 MHz. Trong tình huống này, chúng ta có thể thấy rằng đồng hồ đọc nhanh hơn nhiều so với đồng hồ ghi, vì vậy ngay cả khi phần ghi xảy ra ở tất cả các chu kỳ đồng hồ, phía đọc vẫn sẽ không hoạt động nhiều. Cách để xử lý việc này là đặt cờ Hầu như Rỗng của bạn thành một số nào đó cho biết mã đọc của bạn rằng có một loạt dữ liệu sẵn sàng cho mô-đun đã đọc. Giả sử điều này được đặt thành 50 từ. Khi FIFO có 50 từ bên trong nó, cờ AE sẽ chuyển từ 1 sang 0, nó sẽ kích hoạt một số logic để rút chính xác 50 từ từ FIFO. Đây thường là cách chuyển đổi các miền đồng hồ được triển khai. Nếu bạn đang sử dụng cờ AE / AF, bạn đang thực hiện nó một cách chính xác. Cố gắng không dựa vào các lá cờ rỗng hoặc đầy tràn, và chắc chắn không sử dụng FIFO count mà sử dụng FIFO hỗ trợ.
Lỗi thời gian và chuyển đổi miền đồng hồ
Thông thường khi bạn chuyển đổi miền đồng hồ, bạn sẽ gặp phải lỗi thời gian. Điều này là bình thường! Đây là các công cụ cho bạn biết rằng bạn sẽ có một tình huống mà thời gian thiết lập và thời gian giữ bị vi phạm, và rằng bạn sẽ có một điều kiện metastability. Như tôi đã mô tả trước đây, metastability là phổ biến cho công việc này, miễn là bạn hiểu nó và có thể thiết kế xung quanh nó, bạn sẽ ổn thôi.
Bạn nên luôn luôn nhằm mục đích không có lỗi thời gian trong thiết kế của bạn. Cách tạo các ràng buộc thời gian này nằm ngoài phạm vi của bài viết này. Tham khảo hướng dẫn sử dụng của các nhà cung cấp FPGA để biết chi tiết về điều này. Đây là một tham khảo choXilinx và cho Altera . Tôi sẽ cảnh báo bạn, nếu đây là lần đầu tiên bạn nhìn vào những ràng buộc về thời gian, điều đó thật khó hiểu và áp đảo ngay từ đầu!
Tóm lại, với tư cách là một nhà thiết kế FPGA, bạn sẽ gặp phải tình huống khi chuyển dổi các miền đồng hồ. Bạn cần phải hiểu rõ những cạm bẫy phổ biến xảy ra trong những tình huống này. Nếu việc vượt qua đủ đơn giản, bạn chỉ có thể nhân đôi dữ liệu hoặc thực hiện việc kéo giãn xung. Đối với phần lớn các tình huống, bạn có thể sẽ cần phải sử dụng FIFO hỗ trợ hai đồng hồ, một để đọc và một để viết. Khi cấu trúc mã miền chéo của bạn, hãy cẩn thận để không trộn và kết hợp các tín hiệu từ cả hai miền đồng hồ.
Bình luận gần đây