• 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, 8 tháng 9, 2017

[Basic Knowledge][Bài 1] Hướng dẫn phân tích thiết kế lõi IP step-by-step - Phân tích tổng quan

Bạn đang muốn bắt tay vào thiết kế một lõi IP (IP core) nhưng không biết bắt đầu từ đâu? Bài viết này là một phần trong chuỗi bài viết hướng dẫn bạn đi từng bước để có thể thiết kế được một lõi IP hoàn chỉnh. Phương pháp được sử dụng ở đây là top-down, phân tích từ tổng quan đến chi tiết. Ví dụ được trình bày là một thiết kế CPU cơ bản (simple CPU).

1. Tổng quan
Phân tích thiết kế (thiết kế ở đây là lõi IP) là một công đoạn biến một "yêu cầu thiết kế" thành RTL code hoàn chỉnh. Công đoạn này gồm các bước cơ bản sau đây:
  1. Nghiên cứu và tìm hiểu
  2. Phân tích tổng quan
  3. Phân tích chi tiết
  4. Mô tả RTL code
  5. Kiểm tra RTL code

Hình 1. Các bước phân tích thiết kế một lõi IP
Để minh họa cụ thể việc làm thế nào để thiết kế được 1 lõi IP. Chúng ta sẽ thực hiện yêu cầu thiết kế sau:

Thiết kế một lõi CPU 8 bit, gọi là SCPU, hỗ trợ tập lệnh sau (tham khảo ví dụ ở trang http://minnie.tuhs.org):
Hình 2. Tập lệnh của SCPU

2. Nghiên cứu và tìm hiểu
2.1 Hướng dẫn

Nghiên cứu và tìm hiểu là thực hiện tìm kiếm và phân tích những lý thuyết, nguyên lý và các khái niệm liên quan đến yêu cầu thiết kế với mục tiêu nắm rõ các vấn đề.

Vấn đề cần nghiên cứu và tìm hiểu được thực hiện tùy vào mức độ hiểu biết của người thực hiện thiết kế. Nó có thể là nguyên lý hoạt động, các chuẩn giao tiếp, các giao thức, các cấu trúc, ứng dụng của thiết kế, ...

Hình thức nghiên cứu: Với sự phát triển của công nghệ thông tin như hiện nay, việc tìm kiếm thông tin trở nên đơn giản hơn rất nhiều. Ngoài sách, bài báo khoa học, báo cáo khoa học, các sản phẩm ứng dụng thực tiễn, kinh nghiệm và hiểu biết của người khác, ... thì internet là một công cụ đắc lực. Điểm quan trọng của việc nghiên cứu lúc này không phải là tìm kiếm thông tin mà là đánh giá và phân tích thông tin có được.

Mục tiêu: hiểu rõ những lý thuyết liên quan đến thiết kế để phân tích, đánh giá, so sánh và lựa chọn hướng thiết kế.

Cách thức thực hiện: Phân chia yêu cầu thiết kế thành những vấn đề từ tổng quan đến chi tiết để tìm hiểu. Mỗi vấn đề là một câu hỏi mà người thiết kế chưa có câu trả lời hoặc không chắc chắn về câu trả lời.
Hình 2. Phân chia yêu cầu thiết kế thành các vấn đề cần nghiên cứu ở nhiều cấp độ
Khi nhận được một yêu cầu thiết kế, người thiết kế có thể không thể phân chia được đầy đủ những vấn đề rõ ràng ngay từ đầu mà chỉ có thể liệ kê được một vài vấn đề cơ bản để tìm hiểu dựa trên các từ khóa (keyword) có trong yêu cầu. Trong quá trình tìm hiểu các vấn đề cơ bản này, chúng sẽ được từ từ mở rộng thêm và các vấn đề khác sẽ được đặt ra để tiếp tục tìm hiểu.

2.2 Thực hiện ví dụ CPU 8 bit

Giả sử rằng bạn là người mới bắt đầu, yêu cầu thiết kế đã cho bạn những từ khóa qua trọng là CPU, 8 bit và tập lệnh. Hãy bắt đầu tìm hiểu từ những từ khóa này, mỗi câu hỏi và thắc mắc cảu bạn là một vấn đề cần phải tìm hiểu.
Hình 3. Liệt kê vấn đề dựa trên yêu cầu đề bài
Sau khi có khái niệm cơ bản, bạn sẽ tiếp tục gặp phải những thắc mắc tiếp theo, những câu hỏi lại xuất hiện và những vấn đề tiếp tục được liệt kê để tìm hiểu tiếp. Bạn sẽ lặp lại bước này nhiều lần cho đến khi nhận thấy đã đủ lượng kiến thức để hình dung cách thức hiện yêu cầu thiết kế. Trong quá trình thực hiện thiết kế, bạn có thể gặp tiếp những vấn đề khác cần giải quyết thì hãy quay lại bước này, liệt kê thêm vấn đề để tìm hiểu.
Hình 3. Mở rộng vấn đề cần tìm hiểu
Lưu ý, việc liệt kê và phân chia đề mục các vấn đề cần tìm hiểu là khác nhau đối với mỗi người thiết kế. Khi tìm hiểu, các vấn đề nên được thống kê chi tiết lại sẽ rất hữu ích khi bạn cần tham khảo lại hoặc chuyển giao cho người khác tiếp tục công việc hoặc khi bạn phát hiện có sai sót khi hiểu một vấn đề và cần xem xét lại.
Hình 4. Thống kê lại những thông tin đã tìm hiểu
Sau khi tìm hiểu, một CPU có cấu trúc cơ bản gồm những thành phần sau (lưu ý, bài viết chỉ trình bày ngắn gọn những thành phần cơ bản và cần thiết để phục vụ minh họa cho những phần sau):
  • Hoạt động cơ bản của một CPU gồm các bước sau:
    • Lấy lệnh (Fetch) từ bộ nhớ lưu mã lệnh (instruction memory), còn gọi là bộ nhớ chương trình (program memory). Từng mã lệnh (Instruction code) mà CPU phải thực thi được lưu sẵn trong bộ nhớ chương trình. Các mã lệnh là chuỗi binary được biên dịch từ code C/C++ hoặc assembly code.
    • Giải mã lệnh (Decode) dựa trên mã binary của từng lệnh CPU sẽ giải mã xem lệnh đó là lệnh gì và tích cực các tín hiệu điều khiển tương ứng
    • Thực thi lệnh (Execute) là thực hiện các tính toán và xử lý tương ứng với mã lệnh đã được giả mã như cộng, trừ, nhân, chia, dịch, ...
    • Truy xuất bộ nhớ (Memory Access) đọc/ghi bộ nhớ
    • Lưu kết quả (Write Back) là thực hiện lưu lại các kết quả sau quá trình Execute đến vị trí mà lệnh yêu cầu, ví dụ như các thanh ghi
Hình 5. Minh họa hoạt động cơ bản của một CPU
  • Các thành phần cơ bản của CPU
    • Bộ đêm chương trình PC (Program Counter) tạo giá trị địa chỉ truy cập bộ nhớ chương trình để lấy lệnh
    • Bộ nhớ chương trình (Program memory) lưu các lệnh mà CPU sẽ thực thi
    • Thanh ghi lưu mã lệnh IR (Instruction Register) lưu mã binary lấy từ bộ nhớ lệnh
    • Bộ giải mã lệnh Decoder
    • Các thanh ghi dùng để lưu giá trị trước và sau khi CPU thực thi tính toán (execute)
    • Bộ tính toán số học ALU (Arithmetic Logic Unit) thực thi các phép tính cộng, trừ, nhân, chia, dịch, ....
    • Bộ nhớ dữ liệu (Data memory) lưu các dữ liệu được sử dụng bởi các lệnh truy xuất bộ nhớ
  • Cấu trúc lệnh cơ bản
    • RISC (Reduced Instruction Set Computing) có độ dài mã lệnh cố định
    • CISC (Complex Instruction Set Computing) có độ dài mã lệnh có thể khác nhau giữa các lệnh
Lưu ý, đối với bài viết này, chúng ta chỉ thực hiện các thành phần cơ bản nhất từ đó các bạn có thể hiểu:
  1. Làm thế nào để thiết kế một lõi IP - mục đích chính
  2. Một thiết kế CPU cơ bản - mục đích phụ

3. Phân tích tổng quan
3.1 Hướng dẫn
Phân tích tổng quan là thực hiện xây dựng đặc điểm, cấu trúc đáp ứng yêu cầu thiết kế.

Phương thức thực hiện là lựa chọn những lý thuyết đã "nghiên cứu và tìm hiểu" có thể áp dụng được đối với từng yêu cầu thiết kế.

Mục tiêu là hình dung được tổng quan toàn bộ thiết kế trước khi phân tích chi tiết từng mạch nguyên lý.

Kết quả của bước này là:
  1. Đặc điểm và chức năng chính (features & function) mà thiết kế sẽ hỗ trợ
  2. Sơ đồ khối (Block diagram) Thể hiện mối liên hệ giữa các thành phần chức năng chính
  3. Sơ đồ tín hiệu giao tiếp (Signal/Pin/Port diagram) và mô tả tín hiệu: thể hiện các tín hiệu ngõ vào, ngõ ra. Các tín hiệu  được mô tả rõ chức năng, độ rộng, chiều, mức tích cực và lưu ý khác nếu có.
  4. Thanh ghi (Register table) thể hiện thông tin thanh ghi cấu hình trạng thái mà người sử dụng thiết kế có thể truy cập hoặc sử dụng.
  5. Sơ đồ định thời (Timing diagram) thể hiện sự ràng buộc và liên hệ giữa các tín hiệu giao tiếp. Sơ đồ này thường phải có đối với các giao thức yêu cầu một chuỗi bắt tay nhiều bước để thực hiện một tác vụ.
  6. Các yêu cầu khác: yêu cầu về công suất, tốc độ, tần số hoạt động, ...
Sau khi hoàn thành, những kết quả trên đây thường được đưa vào datasheet, user guide hoặc user manual của một chip hoặc lõi IP. Ví dụ, lõi "IP CAN v5.0, LogiCORE IP Product Guide, August 2, 2016" của Xilinx thể hiện các thành phần trên như sau:
  • Đặc điểm chức năng

  • Sơ đồ khối
  • Sơ đồ tín hiệu giao tiếp và mô tả
  • Mô tả thanh ghi
Một phần bảng mô tả thanh ghi

Mô tả chi tiết một thanh ghi với vị trí bit, tên, thuộc tính Read/Write/, giá trị mặc định và chức năng
  • Sơ đồ định thời
Minh họa một sơ đồ định thời

3.2 Thực hiện ví dụ CPU 8 bit (gọi tắt là SCPU)
Đây là một yêu cầu mở, không ràng buộc chi tiết đến từng đặc điểm cụ thể, chỉ yêu cầu một CPU xử lý dữ liệu 8 bit và hỗ trợ 16 lệnh như trong danh sách. Sẽ có rất nhiều cách để thực hiện được yêu cầu này và sau đây là một cách.

Phân tích tập lệnh của SPCU
CPU là một thiết kế đặc biệt, trong đó cấu trúc tập lệnh sẽ có ảnh hưởng lớn đến cấu trúc phần cứng sẽ thực hiện nên từng lệnh của CPU cần được phân tích cụ thể trước khi phân tích chi tiết hơn. Cấu trúc mã lệnh được lựa chọn ở đây là:

  • 16 bit
  • Độ dài cố định (kiểu RISC)
Hình 6. Phân tích cấu trúc các lệnh của SCPU (màu xám là trường không sử dụng)

Đặc điểm và chức năng

  1. Chức năng theo yêu cầu thiết kế
    1. Hỗ trợ 16 lệnh
    2. Bus dữ liệu 8 bit
  2. Chức năng được lựa chọn để thiết kế
    1. Kiến trúc RISC với độ dài mã lệnh là 16 bit
    2. Bộ nhớ chương trình và bộ nhớ dữ liệu dùng chung có dung lượng 256 byte
    3. Bộ tính toán số học ALU hỗ trợ ADD, SUB, AND và OR
    4. Hỗ trợ 4 thanh ghi tính toán R0, R1, R2 và R3 ứng với trường Rd và Rs chỉ có 2 bit

**Chú ý: Vì mỗi ô nhớ là 8 bit nên các lệnh có trường IMM sẽ được lưu trong 2 ô nhớ liên tiếp. 1 ô lưu 8 bit MSB và ô lưu giá trị IMM.

Sơ đồ khối
Từ những phân tích ở bước "nghiên cứu và tìm hiểu" và đặc điểm hỗ trợ, một sơ đồ khối cho ví dụ SCPU được thể hiện như sau:

  • Khối Fetch
    • Khối Memory là bộ nhớ chương trình và cũng là bộ nhớ dữ liệu 
    • Khối IR là thanh ghi 8 bit lưu mã lệnh lấy từ memory
    • Khối DR là thanh ghi 8 bit lưu dữ liệu từ memory. Thanh ghi này sẽ lưu giá trị IMM của các lệnh nhảy, lệnh LW và SW (số thứ tự từ 9 đến 16 trong bảng mã lệnh)
    • Khối PC: Tính toán giá trị PC truy xuất bộ nhớ chương trình lấy đầu vào từ:
      • Ngõ ra Decoder để lấy địa chỉ truy xuất đối với lệnh đọc bộ nhớ LW và ghi bộ nhớ SW
      • Thanh ghi DR để lấy giá trị IMM cho các lệnh nhảy
  • Khối Decoder giải mã lệnh tạo tín hiệu điều khiển các khối khác và cấp dữ liệu ghi vào Memory đối với lệnh SW. Đây là khối sẽ chứa các thanh ghi R0, R1, R2 và R3
  • Khối Execute chứa ALU thực thi tính toán số học và tạo giá trị cập nhật các thanh ghi tính toán R0, R1, R2 và R3
Hình 7. Sơ đồ khối SCPU
Sơ đồ tín hiệu giao tiếp và mô tả
Đối với thiết CPU này, chúng ta chỉ có 2 tín hiệu giao tiếp là:
  • Xung clock đồng bộ để SCPU chạy liên tục. Xung clock sẽ tích cực cạnh lên.
  • Tín hiệu reset để khởi động SCPU. Tín hiệu reset tích cực mức thấp

Mô tả thanh ghi
Thiết kế có các thanh ghi mà người dùng có thể tác động khi lập trình gồm:

  • Thanh ghi chương trình PC:
    • Chức năng: Chứa địa chỉ truy xuất bộ nhớ chương trình. Người sử dụng có thể tác động bởi lệnh nhảy
    • Độ rộng: 8 bit
  • Thanh ghi tính toán R0, R1, R2, R3:
    • Chức năng: Chứa giá trị dùng để tính toán và kết quả tính toán. Người sử dụng có thể tác động bởi các lệnh có trường hoặc vùng Rd hoặc Rs.
    • Độ rộng: 8 bit
Chúng ta đã kết thúc 2 bước trong quy trình phân tích thiết kế gồm "Nghiên cứu và tìm hiểu" và "Phân tích tổng quan".

**Mọi ý kiến góp ý và đóng góp, các bạn có thể email hoặc comment dưới bài viết để cùng chia sẻ và phát triển.

Thứ Tư, 6 tháng 9, 2017

[IP core] FIFO và LIFO đồng bộ - phiên bản hỗ trợ một số trường hợp đặc biệt

Bài này trình bày về một số trường hợp đặc biệt của FIFO và LIFO (STACK) đồng bộ và cách thực hiện mạch xử lý các trường hợp riêng này. Với FIFO, các trường hợp đặc biệt là khả năng ghi thêm khi FIFO đã đầy (full), khả năng đọc khi FIFO đang rỗng (empty). Với LIFO (STACK),  khả năng đọc và ghi cùng một thời điểm là vấn đề sẽ được đề cập đến.
Hai bài viết them khảo cần đọc trước khi đọc và hiểu bài viết này:

1. FIFO đồng bộ

1.1 Phân tích
Đầu tiên các bạn hãy tham khảo bài FIFO đồng bộ phiên bản 1 trong wesite này vì bài viết này sẽ chỉ trình bày những điểm khác biệt và các mạch mới sẽ được thêm vào dựa trên thiết kế có sẵn này.

Trong phiên bản này, gọi là phiên bản 1, khi FIFO đã đầy, tín hiệu sfifo_full=1 thì FIFO hoàn toàn không thể ghi tiếp. Nếu tiếp tục ghi khi FIFO đang đầy, wr=1, thì trạng thái tiếp theo sẽ là overflow, sfifo_ov=1. Khi FIFO đã rỗng, sfifo_empty=1, thì FIFO hoàn toàn không thể đọc được một giá trị dữ liệu hợp lệ nào. Nếu tiếp tục đọc, rd=1, khi FIFO đang rỗng thì trạng thái tiếp theo là underflow, sfifo_ud=1.

Phiên bản 1 có thể được nâng cấp với một vài điều chỉnh nhỏ để hỗ trợ thêm:
  1. Ghi khi FIFO đã đầy, sfifo_full=1
  2. Đọc khi FIFO đã rỗng, sfifo_empty=1

Hai điều trên có thể thực hiện được trong một trường hợp đặc biệt khi cả tín hiệu đọc (rd) và tín hiệu ghi (wr) cùng tích cực khi FIFO đang đầy hoặc đang rỗng. Cụ thể:
  1. Khi FIFO đầy (sfifo_full=1), nếu wr=rd=1 thì dữ liệu cần đọc sẽ được lấy ra khỏi FIFO và dữ liệu cần ghi sẽ được ghi vào FIFO ở cùng 1 cạch xung clock. Lúc này, cả hai con trỏ đọc và ghi cùng tăng. Trạng thái FIFO đầy vẫn được duy trì vì FIFO được lấy ra 1 dữ liệu nhưng đồng thời cũng nạp thêm 1 dữ liệu mới.
  2. Khi FIFO rỗng (sfifo_empty=1), nếu wr=rd=1 thì dữ liệu cần đọc sẽ được truyền trực tiếp từ ngõ vào FIFO đến ngõ ra FIFO mà không cần lưu vào bộ nhớ trung gian mem_array. Trạng thái FIFO rỗng vẫn được duy trì vì FIFO không lưu giá trị dữ liệu mới. Lúc này, cả hai con trỏ đọc và ghi không thay đổi giá trị.

Hình 1. Minh họa hai trường hợp đặc biệt của FIFO khi FULL và EMPTY
Một số điều chỉnh được thực hiện như sau:

Mạch tạo tín hiệu ghi vào FIFO, đồng thời là tín hiệu tăng con trỏ ghi:
  • Mạch này thêm trường hợp cho phép ghi khi FIFO đang FULL nhưng đang được đọc (sfifo_full AND rd)
  • Mạch này loại bỏ trường hợp ghi khi FIFO đang EMPTY nhưng đang được đọc (sfifo_empty AND rd NOR sfifo_full) vì lúc này dữ liệu đầu vào FIFO được chuyển trực tiếp đến đầu ra FIFO

Hình 2. Mạch tạo tín hiệu cho phép ghi vào FIFO
Mạch dữ liệu đầu ra FIFO được thêm phần xử lý chuyển tiếp dữ liệu khi FIFO đang EMPTY:
Hình 3. Mạch tạo dữ liệu đầu ra của FIFO
Mạch set/clear của tín hiệu báo overflow (sfifo_ov) và underflow (sfifo_ud):
  • Set khi không xuất hiện đọc/ghi cùng thời điểm
  • Clear dùng trực tiếp tín hiệu rd, đối với sfifo_ov, và wr đối với sfifo_ud

Hình 4. Mạch tạo set/clear tín hiệu báo overflow và underflow

Mạch tạo tín hiệu báo hợp lệ cho ngõ ra dữ liệu: Để hỗ trợ tốt cho việc phát hiện đúng giá trị dữ liệu hợp lệ được đọc ra từ FIFO. Thiết kế có thể thêm một tín hiệu báo hợp lệ, sfifo_valid đi kèm với dữ liệu data_out. Tín hiệu này chỉ tích cực nếu ngõ ra data_out là dữ liệu hợp lệ.
Hình 5. Mạch tạo tín hiệu báo valid cho ngõ ra data_out
1.2 RTL code và Testbench

Pass (nếu có): nguyenquanicd
Source File:
  • sfifo_v2.v - RTL code
  • sfifo_define.h - chứa các định nghĩa để cấu hình trước khi tổng hợp. Nếu bạn không muốn sử dụng phần tín hiệu hay mạch nào thì chỉ cần comment che định nghĩa đó đi. Thêm 2 định nghĩa mới:
    • `define WRITE_FULL_EN - Cho phép hỗ trợ ghi khi FULL
    • `define READ_EMPTY_EN - Cho phép hỗ trợ đọc khi EMPTY
  • sfifo_parameter.h - chứa thông số cấu hình dung lượng FIFO
  • tb_sfifo_v2.v - một basic testbench
Lưu ý:
  • Chỉ hỗ trợ ghi khi FULL và đọc khi EMPTY khi không định nghĩa TWO_CLOCK (nghĩa là chỉ sử dụng 1 xung clock)
1.3 Tổng hợp trên FPGA
Cấu hình trong file sfifo_define.h
`define EMPTY_SIGNAL
`define FULL_SIGNAL
`define SET_LOW_EN
`define SET_HIGH_EN
`define LOW_TH_SIGNAL
`define HIGH_TH_SIGNAL
`define OV_SIGNAL
`define UD_SIGNAL
//`define OUTPUT_REG
//`define TWO_CLOCK
//The new defines of the version 2
//Only use the following options when TWO_CLOCK is not defined
`define WRITE_FULL_EN

`define READ_EMPTY_EN



2. LIFO (STACK) đồng bộ
2.1 Phân tích
Đầu tiên các bạn hãy tham khảo bài LIFO đồng bộ phiên bản 1 trong wesite này.

Trong phiên bản này, gọi là phiên bản 1, LIFO không hỗ trợ việc đọc và ghi cùng một thời điểm, nghĩa là khi wr=rd=1 thì LIFO không hoạt động. Để hỗ trợ chức năng này, một số điều chỉnh thiết kế cần được thực hiện.
Hình 6. Chuyển tiếp dữ liệu khi wr=rd=1

Mạch tạo dữ liệu ngõ ra LIFO
thực hiện chuyển tiếp dữ liệu từ ngõ vào đến ngõ ra khi có sự kiện đọc/ghi cùng xuất hiện.
Hình 7. Mạch tạo ngõ ra LIFO phiên bản 2
Mạch tạo tín hiệu cho phép đọc/ghi LIFO chỉ tích cực tín hiệu lifo_we hoặc lifo_re khi không có sự kiện đọc/ghi đồng thời.
Hình 8. Mạch tạo tín hiệu cho phép đọc/ghi LIFO phiên bản 2
Mạch set/clear tín hiệu báo overflow và underflow cũng được điều chỉnh để:

  • Không báo overflow khi xuất hiện sự kiện ghi vào LIFO khi đang đầy nếu sự kiện đọc cũng xuất hiện, vì lúc này dữ liệu ghi vào LIFO được chuyển tiếp đến ngõ ra LIFO
  • Không báo underflow khi xuất hiện sự kiện đọc từ LIFO khi đang rỗng nếu sự kiện ghi cũng xuất hiện, vì lúc này dữ liệu ghi vào LIFO được chuyển tiếp đến ngõ ra LIFO

Hình 9. Mạch tạo tín hiệu set/clear tín hiệu báo trạng thái overflow và underflow
Mạch tạo tín hiệu báo dữ liệu ngõ ra LIFO hợp lệ được tích cực khi dữ liệu được đọc ở ngõ ra LIFO là hợp lệ.
Hình 10. Mạch tạo tín hiệu báo giá trị hợp lệ của ngõ ra LIFO
2.2 RTL code và testbench


Pass (nếu có): nguyenquanicd

Source File:
  • slifo_v2.v - RTL code
  • slifo_define.h - chứa các định nghĩa để cấu hình trước khi tổng hợp. Nếu bạn không muốn sử dụng phần tín hiệu hay mạch nào thì chỉ cần comment che định nghĩa đó đi. Thêm định nghĩa mới:
    • `define WR_SAME_TIME_EN - cho phép chức năng đọc/ghi đồng thời được tạo ra
  • slifo_parameter.h - chứa thông số cấu hình dung lượng LIFO
  • tb_slifo_v2.v - một basic testbench
2.3 Tổng hợp trên FPGA
Cấu hình trong file slifo_define.h
`define EMPTY_SIGNAL
`define FULL_SIGNAL
`define SET_LOW_EN
`define SET_HIGH_EN
`define LOW_TH_SIGNAL
`define HIGH_TH_SIGNAL
`define OV_SIGNAL
`define UD_SIGNAL
`define OUTPUT_REG
//The new defines of the version 2
`define WR_SAME_TIME_EN

*Nếu có bất cứ ý kiến cần trao đổi, các bạn có thể comment dưới bài viết