• Integrated Circuit Design - Chia sẻ kiến thức về vi mạch

    Vi mạch và Ứng dụng

  • Integrated Circuit Design - Chia sẻ kiến thức về vi mạch

    Vi mạch và Ứng dụng

  • Integrated Circuit Design - Chia sẻ kiến thức về vi mạch

    Vi mạch và Ứng dụng

Thứ Sáu, 18 tháng 8, 2017

[Multi-clock Design] Bài 1 - Đồng bộ tín hiệu bất đồng bộ

Bài viết này giới thiệu những vấn đề và các kỹ thuật được áp dụng trong thiết kế sử dụng nhiều nguồn clock bất đồng bộ. Một thiết kế an toàn và đơn giản nhất là thiết kế sử dụng một nguồn clock. Tuy nhiên, nhiều vi mạch ngày nay sử dụng rất nhiều nguồn clock khác nhau trong cùng một thiết kế nhằm đạt hiệu quả xử lý cao nhất nhưng vần đảm bảo tiết kiệm năng lượng.

Về các loại thiết kế trong vi mạch số các bạn có thể tham khảo ở bài viết [Basic Knowledge] Phân loại thiết kế trong thiết kế vi mạch số.

1. Trạng thái bất ổn định (Metastability)

Trạng thái bất ổn định chính là vấn đề chính được sinh ra tại các giao tiếp bất đồng bộ. Các kỹ thuật thiết kế đa miền clock bất đồng bộ đều nhằm mục đích tránh, hạn chế trạng thái này hoặc tìm cách "sống chung" với trạng thái này.

Trạng thái bất ổn định sinh ra khi xuất hiện sự vi phạm định thời (timing) giữa các tín hiệu đến và tín hiệu xung clock. Tín hiệu đến ở đây có thể là tín hiệu dữ liệu hoặc tín hiệu set/reset. Vi phạm định thời sẽ làm ngõ ra của Flip-Flop (FF) rơi vào trạng thái bất ổn định và xả ra hiện tượng dao động.
Hình 1. Trạng thái bất ổn định xảy ra trên giao tiếp giữa 2 miền clock bất đồng bộ

Hình 1 minh họa việc trạng thái bất ổn định xảy ra như thế nào. clk_a và clk_b là 2 xung clock bất đông bộ, nghĩa là 2 nguồn xung clock độc lập với nhau. d_outa thay đổi theo cạnh lên xung clock clk_a và vi phạm định thời, vi phạm setup time hoặc hold time, của miền xung clock clk_b. Lúc này, ngõ ra DFFB là d_outb rơi vào trạng thái bất ổn định và bắt đầu dao động. Trong trạng thái dao động, mức logic của d_outb là không xác định. Sau một thời gian khoảng thời gian không xác định, d_outb sẽ trở về trạng thái ổn định là mức "0" hoặc mức "1". Việc d_outb ổn định về trạng thái nào là ngẫu nhiên và không biết trước được.
Trạng thái bất ổn định thường được minh họa như việc thả một quả cầu lên một đỉnh một quả đồi. Nó luôn có xu hướng lăn xuống một trong hai bên sườn đồi và nằm cố định khi xuống đến chân đồi.
Hình 2. Minh họa trạng thái bất ổn định như việc thả một quả bóng trên đỉnh đồi
2. Những nguy hiểm sinh ra do trạng thái bất ổn định

Truyền sai giá trị: đây là nguy hiểm có thể thấy rõ. Xét đoạn thời gian ngõ ra d_outb dao động, đây là đoạn thời gian giá trị d_outb không xác định nếu d_outb tiếp tục được lan truyền trong các mạch tiếp theo thì giá trị logic ở các mạch tiếp theo cũng không chính xác. Thêm nữa, cho dù sau đó d_outb sẽ ổn định nhưng giá trị d_outb chưa chắc là đúng vì giá trị ổn định là "0" hay "1" là ngẫu nhiên. Tất nhiên, việc sai giá trị logic sẽ dẫn đến việc hoạt động sai không kiểm soát được khi lan truyền trong mạch.
Hình 3. Trạng thái bất ổn định sẽ lan truyền các giá trị logic sai trong mạch
Tiêu hao năng lượng lớn: Việc tiêu hao năng lượng lớn trên các cổng logic sinh ra do chuyển mạch (chuyển mức logic). Xét một ví dụ đơn giản về cổng đảo (inverter), khi chuyển mạch, điện áp ngõ vào IN thay đổi, tại thời điểm Vi không xác định rõ mức logic "0" hay "1" dòng điện sẽ tăng đột biến vì hiện tượng ngắn mạch tức thời Vdd-Vss khi cả PMOS và NMOS đều dẫn. Ở hiện tượng bất ổn định, tín hiệu dao động và không xác định rõ mức logic được suy trì trong một khoảng thời gian sẽ làm cho quá trình "ngắn mạch" này kéo dài hơn bình thường. Nếu tín hiệu bất ổn định nối đến càng nhiều các cổng logic (mạch tổ hợp) sẽ làm tiêu hao năng lượng lớn khi nhiều cổng bị "ngắn mạch" cùng lúc.

Hình 4. Mô hình cổng đảo mức CMOS (trái) và mối quan hệ dòng-áp khi chuyển mạch (phải). Ở đây, dòng ID tăng đạt mức cực đại tại điện áp trung gian VM khi hiện tượng "ngắn mạch" xảy ra do cả PMOS và NMOS cùng dẫn
Chính vì những nguy hiểm mà trạng thái bất ổn định mang lại mà khi thiết kế đa miền clock bất đồng bộ, nhiệm vụ chính và quan trọng hàng đầu là:
  1. Hạn chế hiện tượng này lan truyền trong mạch
  2. Dù hiện tượng này có xảy ra thì chức năng mạch vẫn phải đảm bảo hoạt động đúng.
3. Mạch đồng bộ
Mạch đồng bộ là mạch được sử dụng để đồng bộ các tín hiệu bất đồng bộ. Tín hiệu bất đồng bộ có thể chuyển trạng thái bất cứ lúc nào và không tuân theo định thời của miền clock nhận nó. Tín hiệu bất đồng bộ có nhiều dạng như:
  1. Tín hiệu input từ ngoài chip
  2. Tín hiệu đến từ một miền clock độc lập với miền clock nhận
  3. Tín hiệu giữa các miền clock sử dụng các clock sinh ra từ PLL
  4. ....
Hình 5. Minh họa một số trường hợp của tín hiệu bất đồng bộ
Để sử dụng một tín hiệu bất đồng bộ thì trong thiết kế phải có mạch đồng bộ. Mạch đồng bộ có nhiệm vụ lấy mẫu tín hiệu ngõ vào bất đồng bộ và cung cấp một ngõ ra đồng bộ theo xung clock được sử dụng bên trong thiết kế.
Mạch đồng bộ "huyền thoại" là mạch đồng bộ sử dụng 2 FF. Câu hỏi là tại sao lại sử dụng 2 FF?
Hình 6. Mạch đồng bộ tín hiệu 1 bit dùng 2 FF

Mạch đồng bộ dùng 2 FF được sử dụng với mong muốn giải quyết 2 vấn đề sau đây:
  1. Ngăn chặn việc truyền trạng thái bất ổn định đến các mạch phía sau
  2. Lấy mẫu đúng giá trị logic mong muốn
Hình 7. Sơ đồ dạng sóng mong muốn khi sử dụng mạch đồng bộ 2 FF
Tuy nhiên, vì d_outa có thể vi phạm timing của clk_b bất cứ lúc nào nên d_outb có thể dao động bất cứ lúc nào. Để trạng thái bất ổn định không lan truyền tiếp đến các mạch phía sau thì dao động của d_outb phải xong trước khi vi phạm timing của clk_b, nghĩa là phải ổn định trước thời gian setup của clk_b. Để ngõ ra d_outc mang giá trị chính xác như ngõ vào d_outa thì sau khoảng thời gian dao động, d_outb phải ổn định về logic 1. Theo những gì đã trình bày về trạng thái bất ổn định trên đây thì mạch dùng 2 FF không có đảm bảo được cả 2 mong muốn đã đề ra vì:
  1. Trạng thái bất ổn định có thể kéo dài hơn 1 chu kỳ xung clock clk_b nên trạng thái bất ổn định có thể lan truyền tiếp đến FF thứ 2 ở ngõ ra d_outc
  2. d_outb có thể ổn định về "0" hoặc "1" chứ không luôn là "1" nên ngõ ra d_outc chưa chắc có được giá trị logic mong muốn
4. Thời gian trung bình giữa các lỗi MTBF

Lý thuyết về thời gian trung bình giữa các lỗi MTBF (Mean Time Between Failures) sẽ giải thích vì sao 2 FF có thể hạn chế được trạng thái bất ổn định lan truyền trong thiết kế.
MTBF cung cấp cách ước lượng khoảng thời gian giữa các lần xảy ra trạng thái bất ổn định làm cho thiết kế bị lỗi. Lỗi này gọi là lỗi đồng bộ (synchronous failure).
Như đã trình bày ở trên, thời gian để thoát khởi trạng thái bất ổn định là không xác định. Gọi thời gian mong muốn để thoát khỏi trạng thái bất ổn định là tMET thì xác xuất để trạng thái bất ổn định không thể kết thúc trong khoảng thời gian này là:

Trong đó:
  • tMET (resolution time) là thời gian yêu cầu để tín hiệu đạt trạng thái ổn định sau khi rơi vào trạng trạng thái bất ổn định.
  • C2 (decay time constant) là hằng số thời gian suy hao được xác định bởi các thông số điện của FF. 
Hình 8. Minh họa về thời gian tMET
Bên cạnh đó, tốc độ trung bình (average rate) để FF rơi vào trạng thái bất ổn định được tính như sau:
Trong đó:
  • C1 (susceptible time window) là hằng số thời gian phụ thuộc vào thông số điện của FF. Đây là khoảng thời gian mà nếu có sự thay đổi của ngõ vào thì ngõ ra FF sẽ rơi vào trạng thái bất ổn định.
  • fCLK là tần số clock miền nhận tín hiệu bất đồng bộ. Như minh họa hình 6, fclk là tần số của clk_b
  • fDATA là tần số thay đổi mức logic của tín hiệu ngõ vào hay số lần tín hiệu ngõ vào thay đổi giá trị trong 1 giây. Ví dụ, theo hình 6, tín hiệu dữ liệu d_outa thay đổi theo xung clock clk_a nên fDATA = fclk_a.
Rmeta biểu thị số lần FF có thể sẽ rơi vào trạng thái bất ổn định trong 1 giây. Như vậy, số lỗi đồng bộ trung bình trong 1 giây là:

Thời gian trung bình giữa các lỗi MTBF ứng với một một giá trị tMET mong muốn là:

MTBF sẽ được dùng để đáng giá một mạch đồng bộ trong thiết kế có đáp ứng được yêu cầu hay không. Ví dụ, một FF có thông số C1 là 0,1 ns, thông số C2 là 0,5 ns, tần số clock hệ thống là fCLK = 50 Mhz và tốc độ dữ liệu là fDATA = 10 Mhz. Ở đây, tần số clock hệ thống là 50 Mhz, tương ứng chu kỳ là 20 ns. Chúng ta kỳ vọng tMET < (tCLK - setup time), tức là tín hiệu được mong muốn sẽ ổn định trước thời gian setup của xung clock fCLK nếu xảy ra trạng thái bất ổn định. Hình sau là bảng tính MTBF ứng với từng trường hợp kỳ vọng tMET từ 0ns đến 19ns.
Hình 9. Tính toán giá trị MTBF
Qua ví dụ trên, chúng ta có thể thấy thời gian dự trữ dành cho trạng thái bất ổn định càng lớn, tức tMET càng lớn, thì thời gian giữa 2 lần xuất hiện lỗi đồng bộ càng dài, tức MTBF càng lớn. Đồng nghĩa với việc xác suất xuất hiện lỗi đồng bộ càng thấp. Ví dụ, nếu kỳ vọng lỗi đồng bộ ngay lập tức có thể ổn định (tMET = 0), nghĩ là không có khoảng thời gian dự trữ cho trạng thái bất ổn định, thì cứ mỗi 0.02ms là có thể xuất hiện một lỗi đồng bộ. Nếu tMET tăng lên 19ns thì khoảng cách trung bình giữa 2 lỗi đồng bộ là khoảng 20202 năm. Tuy nhiên, MTBF là thời gian "trung bình" nên trên thực tế, không phải cứ sau 20202 năm mới xuất hiện một lỗi đồng bộ mà khoảng cách giữa 2 lần xuất hiện lỗi đồng bộ có thể ngắn hoặc dài hơn 20202 năm nhưng trong suốt quá trình hoạt động của thiết kế, khoảng cách trung bình là 20202 năm.

Như vậy để hạn chế lỗi đồng bộ thì MTBF phải đủ lớn để đáp ứng nhu cầu của ứng dụng thực tế và mạch đồng bộ là mạch có vai trò làm tăng MTBF để hạn chế tối đa sự xuất hiện lỗi đồng bộ.

Bên cạnh đó, MTBF rất nhạy với sự thay đổi của tMET vì phụ thuộc vào tMET theo hàm mũ, vì vậy chỉ cần sự thay đổi nhỏ của tMET cũng làm cho giá trị MTBF biến đổi lớn.

5. Tính toán MTBF cho mạch đồng bộ sử dụng chuỗi FF mắc nối tiếp

5.1 Trường hợp không sử dụng mạch đồng bộ

Trong hình minh họa sau không sử dụng mạch đồng bộ giữa hai miền clock bất đồng bộ. Gọi:
  • Tclk_b là chu kỳ clock clk_b
  • Tsu là thời gian setup (setup time) của FF miền clk_b
  • Tcom là thời gian trễ trên mạch tổ hợp ngõ vào
Hình 10. Giao tiếp giữa 2 miền clock không sử dụng mạch đồng bộ
Nếu tín hiệu bất đồng bộ được sử dụng trực tiếp thì không có thời gian dự trữ nào để để tín hiệu ổn định trước khi được sử dụng, tức là tMET=0. Theo bảng tính của ví dụ hình 9, khả năng xuất hiện lỗi đồng bộ là sau mỗi 0,02ms. Sau mỗi 0,02ms, một lỗi đồng bộ xuất hiện là không thể chấp nhận được đối với bất kỳ thiết kế nào.

5.1 Trường hợp sử dụng 1 FF để làm mạch đồng bộ

Nếu sử dụng một FF để đồng bộ tín hiệu thì khoảng thời gian dự trữ (khoảng thời gian mong muốn) để trạng thái bất ổn định trở về trạng thái ổn định nếu xảy ra vi phạm timing là:
tMET = Tclk_b - (Tcom + Tsu)

Trong đó Tsu là thông số của FF nên tMET phụ thuộc vào Tcom. Tcom càng lớn thì tMET càng nhỏ và MTBF càng nhỏ. Xét lại bảng tính hình 9, giả sử Tsu=1ns, nếu:
  1. Mạch tổ hợp đơn giản có độ trễ nhỏ, ví dụ Tcom=2ns thì tMET=20-3=17ns sẽ ứng với MTBF là 370 năm
  2. Mạch tổ hợp phức tạp có độ trễ lớn, ví dụ Tcom=13ns thì tMET=20-14=6ns sẽ ứng với MTBF là 3,255s
Hình 11. Sử dụng 1 FF để làm mạch đồng bộ
Việc sử dụng 1 FF làm cho Tcom ảnh hưởng trực tiếp đến tMET. Như đã trình bày trước đó, MTBF rất nhạy với sự thay đổi của tMET nên việc chỉ sử dụng một FF để đồng bộ là vô cùng rủi ro và phụ thuộc quá nhiều vào việc thiết kế phía sau mạch đồng bộ.

5.2 Trường hợp sử dụng 2 FF để làm mạch đồng bộ

Để thời gian dữ trữ cho việc giải phóng khỏi trạng thái bất ổn định tMET được lớn nhất thì Tcom phải nhỏ nhất. Chèn thêm 1 FF là cách đơn giản và không làm thay đổi mạch chức năng phía sau. Khi 2 FF được sử dụng, giữa 2 FF chỉ là dây dẫn và không có mạch tổ hợp nào. Để độ trễ dây dẫn là không đáng kể thì khi layout mạch 2 FF của mạch đồng bộ phải đặt gần nhau, Tcom xem như bằng 0.

tMET = Tclk_b - Tsu

Theo ví dụ trên nếu Tsu = 1ns thì tMET = 19ns và MTBF là 20202 năm.
Hình 12. Sử dụng 2 FF để làm mạch đồng bộ
Đến đây, chúng ta cần lưu ý hai điểm khi sử dụng chuỗi FF để đồng bộ:
  1. Mạch đồng bộ phải dùng ít nhất là 2 FF
  2. Giữa hai FF của mạch đồng bộ không được phép chèn thêm bất cứ logic mạch tổ hợp nào.
Tiếp theo nếu tăng tần số xung clock clk_b lên, chu kỳ Tclk_b sẽ giảm và thời gian tMET cũng sẽ giảm theo. Ví dụ, tăng tần số clk_b lên 100Mhz, chu kỳ là 10ns, tMET sẽ là:
tMET = Tclk_b - Tsu = 10 - 1 = 9ns

Tính lại MTBF, ta sẽ có:
MTBF ≈ 10,94 phút
Để giải quyết vấn đề này, nhiều thư viện công nghệ (thư viện để tổng hợp và chế tạo vi mạch) hỗ trợ loại D-FF đặc biệt gọi là metastablility-hardened D-FF, tạm dịch là "D-FF kháng bất ổn định", dùng riêng cho mạch đồng bộ. Loại FF này có các hệ số C1, C2 và Tsu nhỏ hơn các FF thông thường nên MTBF sẽ tăng đáng kể.

5.3 Sử dụng nhiều hơn 2 FF để thực hiện mạch đồng bộ

Nếu thư viện công nghệ không có FF đáp ứng được thông số MTBF cần thiết thì sao? Chúng ta có thể tăng MTBF bằng cách mắc nối tiếp nhiều hơn 2 FF. Xét ví dụ, mạch đồng bộ dùng 3 FF để xem tại sao mắc thêm nhiều FF hơn thì có thể đạt MTBF mong muốn.
Hình 13. Mạch đồng bộ sử dụng 3 FF
Tốc độ trung bình để FF đầu tiên rơi vào trạng thái bất ổn định:
Khi FF đầu tiên rơi vào trạng thái bất ổn định thì xác suất để điều kiện bất ổn định tồn tại vượt qua chu kỳ clock hiện tại là:

Nếu trạng thái bất ổn định của FF đầu tiên duy trì quá một chu kỳ xung clk_b thì FF thứ 2 sẽ rơi vào trạng thái bất ổn định và xác suất để điều kiện bất ổn định tồn tại vượt qua 1 chu kỳ clock là:


MTBF của mạch đồng bộ 3 FF sẽ là:

Nếu so với mạch đồng bộ dùng 2 FF, số mũ của tử số MTBF ở mạch dùng 3 FF lớn gấp 2 lần số mũ của tử số ở mạch dùng 2 FF. Sô mũ của tử số mạch dùng 3 FF:


Xét lại ví dụ trước, giá trị MTBF ứng với fclk_b = 100Mhz, fDATA = 10Mhz, C1 = 0,1ns, C2 = 0,5ns, Tsu = 1ns là 1367 năm. Như vậy, chỉ cần mắc thêm 1 FF mà MTBF tăng từ 10,94 phút ở mạch dùng 2 FF lên 1367 năm ở mạch dùng 3 FF.

6. Tóm tắt

Bài này giải thích rõ về:
  1. Trạng thái bất ổn định và những nguy hiểm của trạng thái này
  2. Tại sao mạch mắc nhiều FF nối tiếp lại hạn chế được trạng thái bất ổn định lan truyền trong thiết kế
Vấn đề kế tiếp đối với việc thiết kế mạch đồng bộ các tín hiệu bất đồng bộ là:
  1. Trường hợp nào sử dụng mạch đồng bộ mắc nối tiếp nhiều FF
  2. Làm sao để lấy mẫu đúng được dữ liệu mong muốn. Bạn đọc có thể quan sát lại hình 7, trong hình này, việc sử dụng 2 FF chỉ có thể hạn chế được sự lan truyền của trạng thái bất ổn định chứ không đảm bảo lấy được giá trị mong muốn ở ngõ vào.
Các vấn đề trên sẽ được trình bày trong những bài tiếp theo.

Lịch sử cập nhật:
2020.01.07 - Sửa link hình minh họa

Thứ Hai, 14 tháng 8, 2017

[Basic Knowledge] Quy trình cơ bản tạo ra vi mạch số

Một quy trình cơ bản để tạo ra một vi mạch số bao gồm các bước chính là phân tích thiết kế, kiểm tra và sửa lỗi, thiết kế vật lý, chế tạo/sản xuất.
Hình 1. Quy trình cơ bản để tạo ra một vi mạch số
1. Phân tích thiết kế (Design Analyzation)

Phân tích thiết kế bao gồm hai công đoạn chính là phân tích cấu trúc và mô tả mã nguồn.
Phân tích cấu trúc thiết kế là phân tích sơ đồ khối, sơ đồ tín hiệu giao tiếp, mạch nguyên lý, giản đồ định thời,... dựa trên các yêu cầu thiết kế. Các thông tin này được thể hiện bằng các hình vẽ
  hoặc mô tả. Các phần mềm có thể sử dụng là Microsoft Ofice (Microsoft), Open Office (Sun Microsystems) hoặc Kingsoft Office (Kingsoft),...

Hình 2. Minh họa cách biểu diễn sơ đồ tín hiệu giao tiếp, sơ đồ khối và mạch nguyên lý
Mô tả mã nguồn, thường gọi là mô tả RTL code, là sử dụng ngôn ngữ mô tả phần cứng để mô tả thiết kế dựa trên các phân tích cấu trúc đã thực hiện. Hai ngôn ngữ mô tả phần cứng thông dụng là Verilog và VHDL. Phần mềm có thể sử dụng là các trình soạn thảo có sẵn trong các phần mềm thiết kế hoặc Notepad++, EmEditor, VI, VIM, XEmacs, conTEXT, ...
Hình 3.  Một đoạn RTL code viết bằng ngôn ngữ Verilog mô tả cho mạch nguyên lý 
Sau khi đã hoàn thành RTL code, người thiết kế cần thực hiện kiểm tra các quy định về cú pháp (syntax), luật thiết kế vi mạch số (Design rule) hoặc các luật riêng của các phần mềm thiết kế,... Phần mềm có thể sử dụng là LEDA (Synopsys), NC-Verilog (Cadence) dùng cho thiết kế hướng ASIC hoặc Quartus II (Altera), Vivado (Xilinx) dùng cho thiết kế trên FPGA. 

Hình 3. Minh họa kiểm tra syntax và design rule với phần mềm LEDA - Synopsys
Kết quả chính của bước phân tích thiết kế:
  • Bản phân tích mạch nguyên lý của thiết kế
  • Các tập tin mã nguồn (RTL code)
  • Tài liệu mô tả thiết kế  
2. Kiểm tra và sửa lỗi (Verification and Debug)

Kiểm tra và sửa lỗi là công đoạn thực hiện mô phỏng thiết kế trên các phần mềm chuyên dụng. Có hai cấp độ mô phỏng là mô phỏng mã nguồn, hay mô phỏng mức RTL code, và mô phỏng mức cổng.


Mô phỏng mức RTL code là thực hiện mô phỏng thiết kế đối với RTL code. Công việc chính của bước này là mô phỏng chức năng mà không tính đến định thời và độ trễ vật lý của các tín hiệu.



Mô phỏng mức cổng là thực hiện mô phỏng thiết kế sau khi tổng hợp và sau khi layout. Công việc chính của bước này là mô phỏng chức năng có tính đến định thời và độ trễ của các tín hiệu.

Phần mềm sử dụng có thể là VCS (Synopsys), ModelSim hay Questa Sim (Mentor Graphic), Verilogger Extreme (SynaptiCAD), Verilogger Pro (SynaptiCAD),Veriwell (Wellspring) ... 

Hình 5. Waveform khi chạy mô phỏng 1 thiết kế trên Questa SIM
Kết quả chính của bước này gồm:
  • Môi trường mô phỏng của thiết kế
  • RTL code đã được sửa lỗi và đảm bảo thực thi đúng chức năng sau khi thực hiện mô phỏng mức RTL code
  • Các file tổng hợp và layout đã được sửa lỗi và đảm bảo thực thi đúng chức năng thiết kế và định thời sau khi thực thi mô phỏng mức cổng.  
3. Thiết kế vật lý (Physical Design)

Thiết kế vật lý thực hiện hai công đoạn chính là tổng hợp và layout. Tổng hợp là biên dịch RTL code trên một thư viện công nghệ xác định để tạo ra tập tin netlist. Phần mềm sử dụng để biên dịch có thể là Design Compiler (Synopsys), EncounterTM RTL Compiler (Cadence), Leonardo Spectrum (Mentor Graphics),...


Layout là sử dụng netlist để bố trí vị trí các thành phần logic trên một diện tích xác định để tạo thành bản thiết kế của lõi chip. Phần mềm layout có thể sử dụng là IC Compiler (Synopsys), Encounter Digital Implementation (Cadence), IC Station (Mentor Graphic),...

Kết quả chính của bước này gồm:

  • Sau tổng hợp: file netlist
  • Sau layout: file .gds
  • Các file liên quan khác  
Hình 6. Sơ đồ mạch của một thiết kế sau khi tổng hợp

Hình 7. Nội dung của một file netlist sau khi tổng hợp thể hiện sự kết nối của các cell thư viện

Hình 8. Minh họa bản layout của một chip

4. Chế tạo/sản xuất

Quy trình chế tạo và sản xuất chip trải qua nhiều công đoạn, trong đó, hai công việc chính là chế tạo các lõi chip trên wafer và đóng gói chip.

Chế tạo các lõi chip trên wafer là công đoạn sử dụng kết quả sau bước layout để chế tạo ra các lõi chip.

Đóng gói chip là cắt riêng từng lõi chip trên wafer và mỗi lõi chip được đóng gói trong một vỏ để tạo thành chip hoàn chỉnh. Kết quả của bước này là vi mạch (chip).  
Hình 9.  Các lõi chip trên wafer

Hiện nay, ở Việt Nam, không có công ty nào làm về chế tạo wafer cho vi mạch, chỉ có Intel là làm khâu đóng gói. Các công ty ở Việt Nam chỉ tuyển dụng và làm bước 1, 2 và 3. Trong đó, công việc về Verification và thiết kế vật lý là nhiều nhất. 






Chủ Nhật, 13 tháng 8, 2017

[Verilog][System Verilog] Máy trạng thái hữu hạn FSM

Bài viết này phân tích cấu trúc của máy trạng thái hữu hạn FSM (Finite State Machine), cách mô tả RTL code của FSM và các vấn đề liên quan khác trên một ví dụ cụ thể về điều khiển đèn giao thông.

1. Tổng quan về FSM

1.1 Khái niệm

Máy trạng thái hữu hạn, viết tắt là FSM, là một thành phần được sử dụng phổ biến trong thiết kế vi mạch số với ưu điểm là dễ kiểm soát quá trình hoạt động của thiết kế và dễ debug hoạt động của thiết kế.
Hình 1. Mô hình cơ bản của FSM
 FSM gồm có 3 thành phần cơ bản như sau:
  1. Mạch tạo trạng thái kế tiếp (Next state logic) là mạch tổ hợp phụ thuộc vào ngõ vào FSM và giá trị trạng thái hiện tại lấy từ bộ nhớ trạng thái (state memory)
  2. Bộ nhớ trạng thái (state memory) là phần tử lưu trạng thái hiện tại của FSM nó có thể là Flip-Flop, Latch, ... lấy ngõ vào từ mạch tạo trạng thái kế tiếp. Bộ nhớ trạng thái thường được sử dụng trong các thiết kế đồng bộ là FF hoạt động theo xung clock. Một tín hiệu reset có thể phải sử dụng để khởi động FSM đến một giá trị ban đầu. Reset không cần sử dụng đối với các FSM luôn hoạt động đúng dù giá trị ban đầu của FF là bao nhiêu.
  3. Mạch tạo ngõ ra (output logic) là mạch tổ hợp tạo giá trị ngõ ra tương ứng với trạng thái hiện tại của FSM. Mạch này lấy ngõ vào là giá trị trạng thái hiện tại và có thể tổ hợp thêm ngõ vào của FSM
1.2 Phân loại

FSM được chia làm 2 loại:
  1. FSM Moore là loại có mạch tạo ngõ ra không phụ thuộc trực tiếp vào ngõ vào FSM
  2. FSM Mealy là loại có mạch tạo ngõ ra phụ thuộc trực tiếp vào ngõ vào FSM
Hình 2. FSM Moore
Hình 3: FSM Mealy
Với FSM Mealy, mạch tạo trạng thái kế tiếp và ngõ ra có thể được thay bằng ROM trong một số FPGA. Thay vì sử dụng mạch logic để tính toán giá trị ngõ ra và trạng thái kế tiếp thì bộ ROM được sử dụng để lưu các giá trị này ứng với mỗi trạng thái hiện tại. Lúc này ngõ vào và giá trị trạng thái hiện tại được sử dụng để điều khiển và tạo địa chỉ truy cập ROM.
Hình 4. FSM sử dụng ROM để lưu giá trị ngõ ra và trạng thái kế tiếp
Các bạn có thể phân biệt đâu là FSM Moore và đâu là FSM Mealy ở các mạch trong hình sau đây? (Cấu trả lời có ở cuối bài viết nhưng các bạn hãy thử suy nghĩ và cho đáp án của riêng mình).
Hình 5.1 Phân biệt FSM Moore và FSM Mealy
1.3 So sánh FSM Moore và FSM Mealy

FSM Moore có tính an toàn cao hơn FSM Mealy vì ngõ ra FSM được tổ hợp từ giá trị FF nên nếu được kết nối đến các khối khác thì tín hiệu này có thể được sử dụng làm đường hồi tiếp trở lại tổ hợp với các mạch tạo ngõ vào cho FSM. Còn đối với FSM Mealy thì việc nay sẽ tạo ra mạch bất đồng bộ.
Hình 5.2 Sử dụng FSM Moore để tránh tạo mạch bất đồng bộ không mong muốn khi hồi tiếp ngõ ra

Độ trễ ngõ ra FSM Moore được xác định rõ ràng và giới hạn trong FSM tính từ FF đi qua mạch tổ hợp tạo ngõ ra. Trong khi ngõ ra FSM Mealy phụ thuộc cả vào ngõ vào nên độ trễ của các tầng trước nối đến ngõ vào FSM cũng được tính vào độ trễ ngõ ra FSM và có thể là đường critical path (đường có độ trễ lớn nhất).
Hình 5.3 Độ trễ ngõ ra của FSM Mealy phụ thuộc vào độ trễ ngõ vào nhưng FSM Moore thì không
Mealy có ưu điểm là số trạng thái ít hơn Moore với cùng một chức năng và ngõ ra đáp ứng ngay theo sự thay đổi của ngõ vào mà không cần chờ đến cạnh lên xung clock. Nếu dùng Mealy thì cần đặc biệt chú ý đến vấn đề hồi tiếp và độ trễ cộng dồn như đã trình bày ở trên.

2. Thiết kế FSM

2.1 Yêu cầu
Sử dụng FSM để thiết kế một bộ điều khiển đèn giao thông tại một ngã tư đường với yêu cầu:
  1. Thời gian dừng tại mỗi trạng thái đèn có thể cấu hình được trước khi biên dịch RTL code
  2. Tần số điều khiển đèn là 1 Hz, tương ứng với chu kỳ 1 s
  3. Sự chuyển trạng thái đèn được xác định như bảng sau
  4. Mỗi đường sẽ có 3 tín hiệu điều khiển đèn tương ứng với 3 màu Green/Yellow/Red
  5. Trạng thái khởi động là trạng thái đèn trên cả STREET A và STREET B đều đỏ (Red)
Hình 6. Bảng chuyển trạng thái đèn giao thông

Hình 7. Sơ đồ ngã tư với đèn giao thông
2.2 Phân tích tổng quan
Từ yêu cầu ban đầu, chúng ta sẽ có một thiết kế gồm các tín hiệu như sau:
Hình 8. Sơ đồ tín hiệu giao tiếp của bộ điều khiển đèn giao thông
Trong đó:
  1. clk là xung clock tần số 1 Hz
  2. rst_n là tín hiệu dùng để khởi động bộ điều khiển đến trạng thái ban đầu Red-Red khi nó tích cực mức thấp
  3. street_a[2:0] là tín hiệu điều khiển đèn trên đường STREET A. Thứ tự bit từ 0 đến 2 tương ứng với trạng thái Red/Yellow/Green. Tích cực mức 1.
  4. street_b[2:0] là tín hiệu điều khiển đèn trên đường STREET B. Thứ tự bit từ 0 đến 2 tương ứng với trạng thái Red/Yellow/Green. Tích cực mức 1.
Bảng giá trị ngõ ra tương ứng với các trạng thái đèn như sau:
Hình 9. Bảng giá trị ngõ ra bộ điều khiển tương ứng với trạng thái đèn
Căn cứ trên hoạt động mà yêu cầu đề ra, sơ đồ khối của bộ điều khiển đèn giao thông như sau:
  1. TIME_COUNTER: dùng để đếm xunh clock xác định thời gian duy trì trạng thái của đèn. Đây là thời gian có thể cấu hình được trước khi biên dịch như yêu cầu đặt ra. Ba tín hiệu g_end, r_end và y_end báo thời điểm kết thúc của trạng thái GREEN, RED và YELLOW. Ba tín hiệu fsm_g, fsm_r và fsm_y báo trạng thái GREEN, REG và YELLOW để bộ đếm hoạt động theo giá trị cấu hình phù hợp.
  2. FSM: là máy trạng thái sẽ tạo ngõ ra street_a, street_b và fsm_g, fsm_r, fsm_y
Hình 10. Sơ đồ khối của bộ điều khiển đèn giao thông

2.3 Phân tích khối FSM
Ứng với 6 cặp trạng thái nên chúng ta có FSM 6 trạng thái như sau:
Hình 11. FSM điều khiển đèn giao thông
Trong đó, ký hiệu A và B ứng với STREET A và STREET B. G là GREEN, R là RED và Y là YELLOW. Ví dụ, AG_BR nghĩa là trạng thái STREET A đang GREEN, STREET B đang RED.

Yêu cầu đặt ra, sau khi reset thì cả hai đèn phải RED-RED nên bạn có thể chọn AR_BR1 hoặc AR_BR2. Ở đây, trạng thái AR_BR1 được chọn làm trạng thái khởi động.

Việc chuyển trạng thái chỉ xảy ra khi tín hiệu báo độ trễ tương ứng của trạng thái đó tích cực. Ví dụ, khi đèn trên STREET A hoặc STREET B đang xanh thì g_end phải tích cực thì mới chuyển sang trạng thái tiếp theo.
Hình 12. Bảng giá trị ngõ ra FSM
Sơ đồ nguyên lý tương ứng của FSM như sau:
Hình 13. Sơ đồ nguyên lý của FSM
2.4 Phân tích khối TIME_COUNTER
Vì bài này chỉ tập trung vào việc giải thích cho FSM nên khối này chỉ được đưa ra sơ đồ nguyên lý chứ không giải thích thêm để bạn đọc có thể tự nghiên cứu. Chú ý, GREEN_TIME, YELLOW_TIME và RED_TIME là các hằng số được cấu hình trước khi biên dịch RTL code. Với tần số 1 Hz, nếu muốn thời gian dừng của đèn xanh là 30s, đèn vàng là 5s và trạng thái cả hai đèn cùng đỏ là 3s thì cần gán giá trị như sau:
  • GREEN_TIME = 29
  • YELLOW_TIME = 4
  • RED_TIME = 2
Hình 14. Sơ đồ nguyên lý khối TIME_COUNTER

2.5 Hướng dẫn mô tả RTL code cho FSM

Một FSM gồm 3 phần:
  1. Mạch tạo trạng thái kế tiếp (Next state logic)
  2. Bộ nhớ trạng thái (state memory)
  3. Mạch tạo ngõ ra (output logic)
Để mô tả một FSM hoàn chỉnh, bạn cần mô tả đầy đủ 3 phần trên và thêm mô tả mã hóa trạng thái (State code). Các bạn hãy đọc RTL code và só sánh với hình 11 và hình 13 để hiểu rõ hơn.

RTL code của khối FSM:
module fsm (/*AUTOARG*/
   // Outputs
   street_a, street_b, fsm_g, fsm_y, fsm_r,
   // Inputs
   clk, rst_n, g_end, y_end, r_end
   );
//
//interface
//
input clk;
input rst_n;
input g_end;
input y_end;
input r_end;
output reg [2:0] street_a;
output reg [2:0] street_b;
output wire fsm_g;
output wire fsm_y;
output wire fsm_r;
//
//Internal signals
//
reg [2:0] current_state, next_state;
//STATE code
localparam AG_BR  = 3'd0;
localparam AY_BR  = 3'd1;
localparam AR_BR1 = 3'd2;
localparam AR_BG  = 3'd3;
localparam AR_BY  = 3'd4;
localparam AR_BR2 = 3'd5;
//Next state logic
always @ (*) begin
  case (current_state[2:0])
    AG_BR: begin
      if (g_end) next_state[2:0] = AY_BR;
      else next_state[2:0] = current_state[2:0];
    end
    AY_BR: begin
      if (y_end) next_state[2:0] = AR_BR1;
      else next_state[2:0] = current_state[2:0];
    end
    AR_BR1: begin
      if (r_end) next_state[2:0] = AR_BG;
      else next_state[2:0] = current_state[2:0];
    end
    AR_BG: begin
      if (g_end) next_state[2:0] = AR_BY;
      else next_state[2:0] = current_state[2:0];
    end
    AR_BY: begin
      if (y_end) next_state[2:0] = AR_BR2;
      else next_state[2:0] = current_state[2:0];
    end
    AR_BR2: begin
      if (r_end) next_state[2:0] = AG_BR;
      else next_state[2:0] = current_state[2:0];
    end
    default: next_state[2:0] = current_state[2:0];
  endcase
end
//STATE MEMORY
always @ (posedge clk) begin
  if (~rst_n) current_state[2:0] <= AR_BR1;
  else current_state[2:0] <= next_state[2:0];
end
//Output logic
always @ (*) begin
  case (current_state[2:0])
    AG_BR: street_a[2:0] = 3'b100;
    AY_BR: street_a[2:0] = 3'b010;
    default: street_a[2:0] = 3'b001;
  endcase
end
//
always @ (*) begin
  case (current_state[2:0])
    AR_BG: street_b[2:0] = 3'b100;
    AR_BY: street_b[2:0] = 3'b010;
    default: street_b[2:0] = 3'b001;
  endcase
end
//
assign fsm_g = (current_state[2:0] == AG_BR) | (current_state[2:0] == AR_BG);
assign fsm_y = (current_state[2:0] == AY_BR) | (current_state[2:0] == AR_BY);
assign fsm_r = (current_state[2:0] == AR_BR1) | (current_state[2:0] == AR_BR2);
endmodule
2.6 RTL code và testbench đầy đủ

Download: https://www.mediafire.com/file/v2y6d42gw9zgu7w/rtl_code_traffic_light_controller_nguyenquanicd.zip

pass (nếu có): nguyenquanicd

3. FSM là một dạng biểu diễn của mạch tuần tự


FSM thực chất chỉ là một dạng biểu diễn của mạch tuần tự. Bất kỳ mạch tuần tự dùng FF nào cũng có thể biểu diễn được dưới dạng FSM và ngược lại. Hãy xem xét một ví dụ đơn giản như sau để thấy được sự tương quan giữa một mạch tuần tự dùng FF và FSM.

Xét một bộ đếm lên 2 bit có mạch nguyên lý như sau:
Hình 15. Mạch nguyên lý bộ đếm lên 1 đơn vị
Bộ đếm này có thể được biểu diễn dưới dạng FSM như sau:
Hình 16. Biểu diễn dạng FSM của bộ đếm lên 2 bit

Sơ đồ nguyên lý của FSM trên như sau:
Hình 17. Sơ đồ nguyên lý của FSM của bộ đếm lwn 2 bit
Chúng ta sẽ xem xét mối tương quan giữa sơ đồ nguyên lý hình 15 và hình 17thanh ghi bộ đếm inc_counter[1:0] tương ứng với thanh ghi trạng thái state[1:0].
Hình 18. So sánh tìm mối tương quan giữa biểu diễn mạch tuần tự và biểu diễn FSM
Nếu các trạng thái D0, D1, D2 và D3 được mã hóa theo thứ tự là 0, 1, 2 và 3 thì giá trị inc_counter[1:0] luôn bằng với giá trị state[1:0]. Với mạch tạo trạng thái kế tiếp, khi counter_en bằng 0 thì thanh ghi trạng thái state[1:0] giữ nguyên giá trị cũ tại tất cả các trạng thái nên có thể thay đổi vị trí của nhóm MUX phụ thuộc counter_en và MUX phụ thuộc state[1:0]. Kết quả đạt được thể hiện ở hình sau:
Hình 19. Biến đổi tương đương của sơ đồ nguyên lý FSM của bộ đếm 2 bit
Mạch nguyên lý của FSM hình 19 chỉ khác mạch nguyên lý hình 15 ở bộ MUX 4 ngõ vào. Khi counter_en bằng 1, trạng thái kế tiếp có giá trị như sau:
  • Bằng D1(1) khi state[1:0] bằng D0(0)
  • Bằng D2(2) khi state[1:0] bằng D1(1)
  • Bằng D3(3) khi state[1:0] bằng D2(2)
  • Bằng D0(0) khi state[1:0] bằng D3(3)
Giá trị trạng thái kế tiếp tăng tuần tự 1 đơn vị giống chức năng của bộ cộng. Như vậy mạch nguyên lý ở hình 19 có thể được thay thế tương đương bằng mạch nguyên lý ở hình 15.

Qua ví dụ đơn giản trên, bạn đọc có thể thấy một mạch tuần tự dùng FF có thể biểu diễn dưới dạng một FSM hoặc ngược lại.

4. Mã hóa trạng thái

Một vấn đề quan trọng trong biểu diễn FSM là mã hóa trạng thái. Mỗi trạng thái FSM cần được gán 1 giá trị khác nhau để phân biệt, giá trị này gọi là mã của trạng thái và việc gán các giá trị này gọi là mã hóa trạng thái.

Việc mã hóa trạng thái khác nhau sẽ cho kết quả tổng hợp mạch khác nhau hay netlist khác nhau. Xét lại ví dụ về bộ đếm lên ở mục 3. Nếu các trạng thái từ D0 đến D3 không được mã hóa tuần tự từ 0 đến 3 thì mạch sau khi tổng hợp RTL code với biểu diễn FSM và RTL code với biểu diễn theo hình 15 sẽ có sự khác biệt lớn dù vẫn thực hiện cùng một chức năng.

Việc mã hóa trạng thái sẽ ảnh hưởng đến sự tối ưu của mạch theo hướng khác nhau như mã hóa để tối ưu về diện tích, tối ưu về công suất hay tăng tốc độ đáp ứng của mạch.

Nhiều loại mã có thể sử dụng để mã hóa trạng thái như:
  • Binary tuần tự là gán theo thứ tự 0, 1, 2, 3, 4, ... Ưu điểm là số bit trạng thái được sử dụng là tối thiểu.
  • Gray hoặc cách mã hóa làm chỉ làm 1 bit thay đổi khi chuyển trạng thái. Ưu điểm là số bit trạng thái được sử dụng là tối thiểu và tiết kiệm năng lượng vì khi hoạt động số chuyển mạch ít hơn.
  • One-hot: mỗi trạng thái được mã hóa bằng 1 bit, tại một thời điểm chỉ có 1 bit tích cực. Ưu điểm, mã hóa kiểu này thường dùng cho mạch có tốc độ đáp ứng cao, độ trễ thấp tuy nhiên số lượng FF sử dụng lớn nên tài nguyên tổng hợp và diện tích mạch tăng và có khả năng tiêu tốn năng lượng hơn. Tốc độ đáp ứng cao có được là do mạch tổ hợp ngõ ra của FSM có trạng thái được mã hóa one-hot được tối ưu ít logic hơn.
Quay lại với ví dụ về đèn giao thông, nếu sử dụng mã hóa one-hot, số bit trạng thái tăng lên 6 bit, mỗi bit ứng với 1 trạng thái nhưng logic tạo ngõ ra thì lại giảm đáng kể như mạch nguyên lý ở hình sau.
Hình 20. Mạch tổ hợp tạo ngõ ra của khối FSM bộ điều khiển đèn giao thông khi mã hóa trạng thái bằng one-hot
Có hai cánh mô tả RTL code của FSM được mã hóa trạng thái one-hot:
  • Mô tả như cách mã hóa binary thông thường là sử dụng current_state làm case_expression cho phát biểu case mô tả mạch tạo trạng thái kế tiếp. Tên trạng thái lúc này chính là giá trị của STATE
  • Mô tả sử dụng case_expression = 1. Tên trạng thái được sử dụng làm chỉ số xác định bit quy định trạng thái.
Cách mô tả FSM one-hot dùng tên trạng thái làm giá trị của STATE:
module fsm_onehot (/*AUTOARG*/
   // Outputs
   street_a, street_b, fsm_g, fsm_y, fsm_r,
   // Inputs
   clk, rst_n, g_end, y_end, r_end
   );
//
//interface
//
input clk;
input rst_n;
input g_end;
input y_end;
input r_end;
output wire [2:0] street_a;
output wire [2:0] street_b;
output wire fsm_g;
output wire fsm_y;
output wire fsm_r;
//
//Internal signals
//
reg [5:0] current_state, next_state;
//STATE code
localparam AG_BR  = 6'b000001;
localparam AY_BR  = 6'b000010;
localparam AR_BR1 = 6'b000100;
localparam AR_BG  = 6'b001000;
localparam AR_BY  = 6'd010000;
localparam AR_BR2 = 6'd100000;
//Next state logic
always @ (*) begin
  case (current_state[5:0])
    AG_BR: begin
      if (g_end) next_state[5:0] = AY_BR;
      else next_state[5:0] = current_state[5:0];
    end
    AY_BR: begin
      if (y_end) next_state[5:0] = AR_BR1;
      else next_state[5:0] = current_state[5:0];
    end
    AR_BR1: begin
      if (r_end) next_state[5:0] = AR_BG;
      else next_state[5:0] = current_state[5:0];
    end
    AR_BG: begin
      if (g_end) next_state[5:0] = AR_BY;
      else next_state[5:0] = current_state[5:0];
    end
    AR_BY: begin
      if (y_end) next_state[5:0] = AR_BR2;
      else next_state[5:0] = current_state[5:0];
    end
    AR_BR2: begin
      if (r_end) next_state[5:0] = AG_BR;
      else next_state[5:0] = current_state[5:0];
    end
    default: next_state[5:0] = current_state[5:0];
  endcase
end
//STATE MEMORY
always @ (posedge clk) begin
  if (~rst_n) current_state[5:0] <= AR_BR1;
  else current_state[5:0] <= next_state[5:0];
end
//Output logic
assign street_a[2] = current_state[0]; //AG_BR
assign street_a[1] = current_state[1]; //AY_BR
assign street_a[0] = ~(street_a[2] | street_a[1]);
//
assign street_b[2] = current_state[3]; //AR_BG
assign street_b[1] = current_state[4]; //AR_BY
assign street_b[0] = ~(street_b[2] | street_b[1]);
//
assign fsm_g = (current_state[0] | current_state[3]);
assign fsm_y = (current_state[1] | current_state[4]);
assign fsm_r = (current_state[2] | current_state[5]);
endmodule
Cách mô tả FSM one-hot với tên trạng thái được sử dụng làm chỉ số xác định bit quy định trạng thái. Ví dụ, AG_BR dùng để xác định vị trí bit 0 trong thanh ghi trạng thái, AY_BR dùng để xác định vị trí bit 1 trong thanh ghi trạng thái, ...


module fsm_onehot (/*AUTOARG*/
   // Outputs
   street_a, street_b, fsm_g, fsm_y, fsm_r,
   // Inputs
   clk, rst_n, g_end, y_end, r_end
   );
//
//interface
//
input clk;
input rst_n;
input g_end;
input y_end;
input r_end;
output wire [2:0] street_a;
output wire [2:0] street_b;
output wire fsm_g;
output wire fsm_y;
output wire fsm_r;
//
//Internal signals
//
reg [5:0] current_state, next_state;
//Bit position of STATE code
localparam AG_BR  = 3'd0;
localparam AY_BR  = 3'd1;
localparam AR_BR1 = 3'd2;
localparam AR_BG  = 3'd3;
localparam AR_BY  = 3'd4;
localparam AR_BR2 = 3'd5;
//Next state logic
always @ (*) begin
  next_state[5:0] = 6'b000000;
  case (1)
    current_state[AG_BR]: begin
      if (g_end) next_state[AY_BR] = 1'b1;
      else next_state[AG_BR] = 1'b1;
    end
    current_state[AY_BR]: begin
      if (y_end) next_state[AR_BR1] = 1'b1;
      else next_state[AY_BR] = 1'b1;
    end
    current_state[AR_BR1]: begin
      if (r_end) next_state[AR_BG] = 1'b1;
      else next_state[AR_BR1] = 1'b1;
    end
    current_state[AR_BG]: begin
      if (g_end) next_state[AR_BY] = 1'b1;
      else next_state[AR_BG] = 1'b1;
    end
    current_state[AR_BY]: begin
      if (y_end) next_state[AR_BR2] = 1'b1;
      else next_state[AR_BY] = 1'b1;
    end
    current_state[AR_BR2]: begin
      if (r_end) next_state[AG_BR] = 1'b1;
      else next_state[AR_BR2] = 1'b1;
    end
  endcase
end
//STATE MEMORY
always @ (posedge clk) begin
  if (~rst_n) current_state[5:0] <= 6'b000100;
  else current_state[5:0] <= next_state[5:0];
end
//Output logic
assign street_a[2] = current_state[0]; //AG_BR
assign street_a[1] = current_state[1]; //AY_BR
assign street_a[0] = ~(street_a[2] | street_a[1]);
//
assign street_b[2] = current_state[3]; //AR_BG
assign street_b[1] = current_state[4]; //AR_BY
assign street_b[0] = ~(street_b[2] | street_b[1]);
//
assign fsm_g = (current_state[0] | current_state[3]);
assign fsm_y = (current_state[1] | current_state[4]);
assign fsm_r = (current_state[2] | current_state[5]);
endmodule
5. Trả lời câu hỏi hình 5.1

Muốn biết mạch nào là FSM Moore, mạch nào là FSM Mealy thì chỉ cần nhìn vào các ngõ ra.
  • Chỉ cần một ngõ ra phụ thuộc trực tiếp vào ngõ vào (không qua bất kỳ FF nào) thì đó là Mealy
  • Tất cả các ngõ ra đều được tổ hợp từ các ngõ ra của FF thì đó là Moore
Các bạn nên nhớ trong mô hình FSM chỉ có STATE MEMORY là FF còn các mạch khác đều là mạch tổ hợp.

Đáp án: A, B và D là FSM Moore   -    C là FSM Mealy


Lịch sủ cập nhật:
1) 2019.11.10 - Sửa link hình ảnh