Thứ Tư, 29 tháng 5, 2019

[UVM] Bài 1 - Tổng quan về UVM và mô tả lõi DUT UART-APB

Bài viết này là bài đầu tiên trong chuỗi bài viết hướng dẫn xây dựng một môi trường mô phỏng UVM (Universal Verification Methodology). Trong bài này, nhóm tác giả trình bày một vài khái niệm cơ bản và mô tả tổng quan về DUT (Design Under Test) UART-APB. Bạn đọc mới bắt đầu hãy tập trung hiểu cấu trúc môi trường, khái niệm cơ bản về UVM và hiểu DUT để dễ dàng hiểu những bài tiếp theo.
1) UVM là gì?
UVM (Universal Verification Methodology) là một phương pháp  mô phỏng các thiết kế phần cứng, cái được mô tả bằng ngôn ngữ mô tả phần cứng Verilog hoặc VHDL. UVM được chuẩn hóa trong IEEE 1800.02. 
Thư viện UVM là một tập hợp các class và method được xây dựng trên ngôn ngữ System Verilog. Code của thư viện UVM hiện tại không phải là code được chuẩn hóa bởi IEEE mà nó được phát triển bởi tổ chức phi lợi nhuận Accellera. Các bạn có thể tải và sử dụng miễn phí bằng cách tích hợp vào các trình mô phỏng mà bạn có, ví dụ như QuestaSim.
2) Tại sao phải sử dụng UVM?
UVM được xây dựng với mục tiêu tạo ra một phương pháp mô phỏng chung cho công nghiệp vi mạch. Mô phỏng kiểm tra là một công đoạn tốn rất nhiều thời gian. Trong đó, thời gian dành cho việc xây dựng và chỉnh sửa môi trường mô phỏng là khá lớn. Nếu không có một phương pháp chung, một môi trường mô phỏng sẽ khó có thể tái sử dụng, mở rộng và hiểu bởi nhiều kỹ sư, tổ chức hay công ty khác nhau. 
Trước khi phương pháp mô phỏng UVM ra đời, một vài phương pháp mô phỏng khác như OVM (Open Verification Methodology), RVM (Reference Verification Methodology), VMM (Verification Methodology Manual), ... đã được tạo ra độc lập bởi nhiều công ty khác nhau như Synopsys, Mentor, Cadence, ... Tuy nhiên, chúng có những ưu nhược điểm nhất định. Một điểm quan trọng là các phương pháp mô phỏng cũ khó chia sẻ giữa các tổ chức khác nhau nếu các tổ chức này sử dụng các phương pháp mô phỏng khác nhau. Vì vậy, việc phát triển một phương pháp mô phỏng chung như UVM là cần thiết.

Hình 1: Lịch sử phát triển UVM (tham khảo thêm tại http://chipdesignmag.com)
3) Tổng quan về một môi trường UVM
Thư viện và các tài liệu về UVM có thể được tải miễn phí ở đây.
Phần này được mô tả trong nhiều tài liệu và các bạn có thể dễ dàng tìm thấy nhưng mô tả tổng quan về UVM trên internet nhưng trong bài viết này. Mục này nhắc lại một vài khái niệm cơ bản trước khi chúng ta tiến hành xây dựng một môi trường mô phỏng hoàn chỉnh.
Hình 2: Cấu trúc cơ bản của một môi trường UVM
UVM Testbench là thành phần chứa toàn bộ môi trường kiểm tra, bao gồm cả DUT.
  1. DUT (Design Under Test) chính là thiết kế cần kiểm tra. Trong loạt bài này, nó là lõi IP UART-APB.
  2. User checker là một thành phần giám sát và kiểm tra một vài điều kiện đặc biệt theo yêu cầu mô tả bởi người kiểm tra.
  3. User coverage là một thành phần kiểm tra yêu cầu coverage ở một số vị trí được mô tả bởi người kiểm tra.
  4. UVM Test là lớp bao trên cùng chứa tất cả các thành phần UVM
  • UVM Environment là thành phần nhóm các thành phần khác của môi trường UVM như UVM Agent, UVM Scoreboard hoặc UVM Environment khác:
    • UVM Agent nhóm các thành phần kiểm tra kết nối với giao tiếp của DUT. Nó có thể có nhiều thành phần khác nhau, nhưng thường có 3 thành phần chính:
      • UVM Monitor là thành phần giám sát thông tin và tín hiệu giao tiếp với DUT.
      • UVM Sequencer điều khiển quá trình truyền các transaction từ các seqence
      • UVM Driver nhận các transaction từ các sequence là lần lượt chuyển chúng thành các giá trị tương ứng để lái các tín hiệu trên giao tiếp với DUT
    • UVM Scoreboard là thành phần kiểm tra hành vi, hoạt động hoặc dữ liệu mong muốn của DUT.
  • UVM Sequence là đối tượng tạo ra các transaction và cung cấp chúng cho UVM Sequencer để đưa đến UVM Driver.
  • Transaction là gói dữ liệu test được sử dụng để kiểm tra DUT.
  • UVM Configuration là thành phần cấu hình môi trường UVM với các thông số mong muốn trước khi thực thi test.
Chi tiết hơn, các bạn hãy tham khảo tài liệu Universal Verification Methodology (UVM) 1.2 User’s Guide.
Bên cạnh đó, chi tiết cấu trúc và chức năng của các thành phần UVM sẽ được giải thích trong những bài viết sau trên ví dụ cụ thể để bạn đọc dễ dàng hình dung hơn.
4) Sơ đồ khối lõi IP UART-APB
Lõi IP UART-APB gồm các khối chức năng cơ bản sau:
  • uart_apb_if: Khối giao tiếp APB, tiếp nhận các transfer từ APB bus để đọc/ghi các thanh ghi cấu hình, trạng thái của UART.
    • APB insterface: Xử lý các tín hiệu giao tiếp APB
    • Baud rate: Tính toán tốc độ truyền "baud rate"
    • Control registers: Các thanh ghi cấu hình
    • Status registers: Các thanh ghi trạng thái
    • Interrupt: Tạo các tín hiệu ngắt
  • apb_transmitter: Bộ truyền nối tiếp theo giao thức UART. Dữ liệu truyền được bus APB đưa đến và lưu trong TXFIFO trước khi chuyển thành dữ liệu nối tiếp theo giao thức UART.
  • apb_receviver: Bộ nhận nối tiếp theo giao thức UART. Dữ liệu nhận được lấy mẫu trên chân uart_rx đưa đến RXFIFO trước khi chuyển thành dữ liệu nối song song để đọc bởi bus APB. 

Hình 3: Sơ đồ khối DUT UART-APB
TXFIFO và RXFIFO là hai FIFO có 16 ô (tầng) lưu dữ liệu. Mỗi ô (tầng) của TXFIFO chứa 8 bit dữ liệu. Mỗi ô của RXFIFO là 10 bit goomg 8 bit dữ liệu, 1 bit báo lỗi parity và 1 bit báo lỗi khung truyền.
Hình 4: Sơ đồ nguyên lý bộ truyền UART

Hình 5: Sơ đồ nguyên lý bộ nhận UART

5) Tổng quan về các giao tiếp của lõi IP UART-APB
Lõi IP UART-APB được sử dụng làm DUT trong loạt bài viết này là một ngoại vi truyền nhận dữ liệu nối tiếp theo giao thức UART (Universal Asynchronous Receiver Transmitter). Lõi IP này giao tiếp với bus AMBA 3 APB Protocol v1.0.
Hình 6: Sơ đồ tín hiệu giao tiếp của lõi IP UART-APB
5.1) Giao tiếp APB
Giao tiếp APB (phiên bản 3.0) gồm các tín hiệu sau:
  • pclk: Xung clock đồng bộ, tích cực cạnh lên
  • preset_n: Tín hiệu reset, tích cực mức thấp
  • psel: Tín hiệu chọn lõi IP
  • penable: xác định pha ACCESS của giao thức APB
  • pwrite: xác định transfer là ghi hay đọc
  • paddr[31:0]: Địa chỉ truy cập
  • pwdata[31:0]: Dữ liệu ghi
  • pstrb[3:0]: Xác định byte dữ liệu hợp lệ trong bus dữ liệu ghi pwdata. Bit pstrb 0, 1, 2 và 3 ứng với byte 0, 1, 2 và 3 của pwdata.
  • prdata[31:0]: Dữ liệu đọc
  • pready: Xác định trạng thái slave. Slave dùng tín hiệu này để mở rộng chu kỳ của một transfer.
  • pslverr: Tín hiệu báo transfer bị lỗi.
Đối với lõi IP UART-APB, DUT này có một số đặc điểm sau đây:
  • pstrb[3:0] chỉ hỗ trợ ghi khi tất cả các bit pstrb[3:0] bằng 1. DUT không thực thi ghi nếu transfer ghi có pstrb khác 4'b1111 và báo lỗi bằng cách tích cực pslverr.
  • pready luôn cố định bằng 1.
  • pslverr tích cực để báo lỗi trong các trường hợp sau:
    • Địa chỉ không align 32-bit, tức paddr[1:0] khác 0.
    • pstrb[3:0] khác 4'b1111 trong transfer ghi.
Việc đọc/ghi thông qua giao tiếp APB được thể hiện ở hai hình minh họa sau đây (lấy từ tài liệu AMBA® APB Protocol Version: 2.0 Specification).
Hình 7: Transfer ghi (trên) và đọc (dưới) của giao thức APB
Từ T0 đến T1: là trạng thái bus IDLE, lúc này PSEL = 0. Giá trị của các tín hiệu điều khiển khác như PWRITE, PADDR, PWDATA, PRDATA, PREADY, ... không cần quan tâm.
Từ T1 đến T2: là trạng thái bus SETUP, lúc này PSEL = 1 và PENABLE = 0. Một transfer bắt đầu. Các tín hiệu điều khiển gửi từ master như PADDR, PWRITE, PSTRB, PWDATA phải giữ một giá trị ổn định cho đến khi kết thúc một transfer.
Từ T2 đến T5: là trạng thái bus ACCESS, lúc này PSEL = 1 và PENABLE = 1. Đây là pha kết thúc một transfer. Master phải dữ cố định giá trị điều khiển trong suốt pha này. Slave lái PREADY để điều khiển pha này.
  • T2 đến T4: Slave lái PREADY=0 để kéo dài pha này nếu slave cần nhiều chu kỳ cho việc xử lý transfer như hình minh họa. Slave có thể lái PREADY=1 trong thời gian này nếu transfer đã xử lý xong.
  • T4 đến T5: Slave lái PREAD=1 thông báo cho master biết transfer đã hoàn thành.
T5 đến T6: Master phải lái PENABLE=0. Đối với  PSEL, master lái mức 0 nếu không có bất cứ transfer nào tiếp theo hoặc giữ mức 1 nếu master tiếp tục gửi transfer.
5.2) Giao tiếp UART
UART là một giao tiếp nối tiếp bất đồng bộ gồm 2 tín hiệu:
  • uart_tx: Truyền dữ liệu nối tiếp
  • uart_rx: Nhận dữ liệu nối tiếp
Hình 8: Cấu trúc một khung dữ liệu UART
Khung dữ liệu UART gồm các phần sau:
  • START bit: một bit 0
  • Data bit: tối đa là 8 bit dữ liệu, thường có thể từ 5 đến 8 bit
  • Parity bit: một bit kiểm tra chẵn hoặc lẻ
  • STOP bit: là bit 1 có độ dài 1, 1.5 hoặc 2 lần độ rộng bit.
Đối vói lõi IP UART-APB trong loạt bài này, cấu trúc khung dữ liệu UART là:
  • START bit: một bit 0
  • Data bit: 8 bit
  • Parity bit: một bit kiểm tra chẵn hoặc lẻ tùy cấu hình
  • STOP bit: là bit 1 có độ dài 1 độ rộng bit.
Hai UART truyền nhận bằng cách kết nối chân uart_tx của UART này với chân uart_rx của UART kia và ngược lại. Sau đó, hai UART phải được cấu hình cùng một tốc độ truyền dữ liệu, được biết với khái niệm "baud rate". Việc thiết lập cùng baud rate giúp độ rộng các bit trong khung dữ liệu của 2 UART là như nhau.
Việc tính baud rate của mỗi thiết kế UART có thể khác nhau, tần số sử dụng để xác định baud rate cũng khác nhau và ảnh hưởng bởi đường truyền (dây nối) nên độ rộng bit sẽ có sai lệch. Để đảm bảo, UART nhận đúng dữ liệu mong muốn, thiết kế UART sẽ lấy mẫu tại điểm giữa mỗi bit.
Hình 8: Vị trí lẫy mẫu 1 bit dữ liệu trong khung truyền UART
Công thức tính baud rate được dùng trong thiết kế lõi IP UART-APB trong loạt bài này là:
Baud rate = (tần số pclk)/(16x(BRG+1))
Trong đó, BRG là giá trị có thể cấu hình được.
5.3) Các tín hiệu interrupt
Lõi IP UART-APB hỗ trợ 5 loại ngắt:
  • ctrl_tif: ngắt truyền - báo ngắt khi TXFIFO rỗng
  • ctrl_rif: ngắt nhận - báo ngắt khi RXFIFO đầy
  • ctrl_oif: ngắt overflow - báo ngắt khi RXFIFO quá tải. Overflow xảy ra khi RXFIFO đầy nhưng lúc này vẫn có dữ liệu ghi vào RXFIFO. Điều này làm cho dữ liệu nhận được bị mất.
  • ctrl_pif: ngắt lỗi parity - báo ngắt khi lỗi parity.
  • ctrl_fif: ngắt lỗi khung truyền - báo ngắt khi UART nhận được một khung truyền bị lỗi STOP bit. STOP bit phải bằng 1, nhưng nếu UART thấy bit này bằng 0 thì khung truyền này bị lỗi.
5 loại ngắt trên có thể được OR lại và tạo ra tín hiệu ngắt tổng ctrl_if. Việc tạo ra tín hiệu ngắt tổng ctrl_if hay 5 tín hiệu ngắt riêng lẻ tùy thuộc vào define INTERRUPT_COM.
Hình 10: Mạch nguyên lý tín hiêu ngắt tổng ctrl_if
6) Bộ thanh ghi của lõi IP UART-APB
Thiết kế này có 7 thanh ghi chức năng như sau:
  • Control register (CON): Thanh ghi điều khiển
    • CON[1:0] là các bit TXT (Transmiter Threshold) thiết lập mức ngưỡng báo trạng thái rỗng của TXFIFO
      • 00: TXFIFO có tất cả 16 ô trống thì bit TXE của thanh ghi IR sẽ tích cực 
      • 01: TXFIFO có lớn hơn hoặc bằng 14 ô trống thì bit TXE của thanh ghi IR sẽ tích cực
      • 10: TXFIFO có lớn hơn hoặc bằng 12 ô trống thì bit TXE của thanh ghi IR sẽ tích cực
      • 11: TXFIFO có lớn hơn hoặc bằng 8 ô trống thì bit TXE của thanh ghi IR sẽ tích cực
    • CON[3:2] là các bit RXT (Receiver Threshold) thiết lập mức ngưỡng báo trạng thái đầy của RXFIFO
      • 00: RXFIFO đang chứa 16 dữ liệu thì bit RXF của thanh ghi IR sẽ tích cực
      • 01: RXFIFO đang chứa lớn hơn hoặc bằng 8 dữ liệu thì bit RXF của thanh ghi IR sẽ tích cực
      • 10: RXFIFO đang chứa lớn hơn hoặc bằng 4 dữ liệu thì bit RXF của thanh ghi IR sẽ tích cực
      • 11: RXFIFO đang chứa lớn hơn hoặc bằng 2 dữ liệu thì bit RXF của thanh ghi IR sẽ tích cực.
  • Status/Enable register (SE): Thanh ghi cho phép và trạng thái
    • SE[0] là bit EN, enable lõi IP
      • 0: Lõi IP không hoạt động
      • 1: Lõi IP bắt đầu thực thi truyền/nhận dữ liệu theo giao thức UART khi có dữ liệu truyền trong FIFO hoặc dữ liệu nhận trên đường uart_rx
    • SE[1] là bit D9, cho phép chế độ khung truyền có parity
      • 0: Không truyền nhận parity bit
      • 1: Có truyền nhận parity bit
    • SE[2] là bit EP, thiết lập loại parity sử dụng khi D9 = 1
      • 0: parity lẻ (tổng số bit 0, bao gồm cả bit parity là 1 số lẻ)
      • 1: parity chẵn (tổng số bit 0, bao gồm cả bit parity là 1 số chẵn)
    • SE[5] là bit TXNF, báo trạng thái TXFIFO không đầy
      • 0: TXFIFO đầy (16 ô đều có dữ liệu chưa truyền)
      • 1: TXFIFO không đầy (có ít nhất 1 ô trống)
    • SE[6] là bit RXNE, báo trạng thái RXFIFO không rỗng
      • 0: RXFIFO rỗng (16 ô đều không có dữ liệu)
      • 1: RXFIFO không rỗng (có ít nhất 1 ô có dữ liệu hợp lệ)
    • SE[7] là bit BUSY, báo trạng thái UART đang bận
      • 0: Cả bộ truyền và bộ nhận đều không đang hoạt động
        • Bộ truyền không bận khi TXFIFO không đang chứa bất kỳ dữ liệu nào cần truyền và bộ truyền đã về trạng thái IDLE.
        • Bộ nhận không bận khi nó không đang lấy mẫu bất kỳ khung dữ liêu UART nào trên uart_rx
      • 1: Bộ truyền hoặc bộ nhận hoặc cả hai đang bận
  • Baud rate register (BR): Thanh ghi thiết lập tốc độ baud (giá trị BRG trong công thức tính tốc độ baud)
    • 0 đến 7'b1111_1111
  • Data regsiter (DT): Thanh ghi dữ liệu
    • Ghi 8 bit dữ liệu vào thanh ghi này, nó sẽ được chuyển đến TXFIFO để truyền đi
    • Đọc 8 bit dữ liệu từ thanh ghi này, nó sẽ lấy 8 bit dữ liệu của RXFIFO để đưa đến prdata[7:0]
  • Interrupt enable register (IE): Thanh ghi cho phép ngắt
    • IE[0] là bit TIE, cho phép ngắt truyền
      • 0: Không cho phép
      • 1: Cho phép
    • IE[1] là bit RIE, cho phép ngắt nhận
      • 0: Không cho phép
      • 1: Cho phép
    • IE[2] là bit OIE, cho phép ngắt overflow
      • 0: Không cho phép
      • 1: Cho phép
    • IE[3] là bit PIE, cho phép ngắt lỗi parity
      • 0: Không cho phép
      • 1: Cho phép
    • IE[4] là bit FIE, cho phép ngắt lỗi khung UART
      • 0: Không cho phép
      • 1: Cho phép
  • Raw Interrupt register (IR): Thanh ghi trạng thái ngắt thô
    • IR[0] là bit TXE, ngắt truyền theo ngưỡng
      • 0: TXFIFO không rỗng theo ngưỡng thiết lập ở các bit TXT[1:0]
      • 1: TXFIFO rỗng theo ngưỡng thiết lập ở các bit TXT[1:0]
    • IR[1] là bit RXF, ngắt nhận theo ngưỡng
      • 0: RXFIFO không đầy theo ngưỡng thiết lập ở các bit RXT[1:0]
      • 1: RXFIFO đầy theo ngưỡng thiết lập ở các bit RXT[1:0]
    • IR[2] là bit OV, ngắt overflow
      • 0: RXFIFO không quá tải
      • 1: RXFIFO quá tải
    • IR[3] là bit PE, ngắt lỗi parity
      • 0: Không lỗi
      • 1: Lỗi
    • IR[4] là bit FE, ngắt lỗi khung UART
      • 0: Không lỗi
      • 1: Lỗi
  • Interrupt regsiter (IF): Thanh ghi trạng thái ngắt. Các bit này nối trực tiếp đến các tín hiệu ngắt ctrl_tif, ctrl_rif, ctrl_oif, ctrl_pif, ctrl_fif.
    • IF[0] = IR[0] & IE[0]
    • IF[1] = IR[1] & IE[1]
    • IF[2] = IR[2] & IE[2]
    • IF[3] = IR[3] & IE[3]
    • IF[4] = IR[4] & IE[4]
Hình 11: Bảng thanh ghi của lõi IP UART-APB
Qua bài viết này, các bạn có thể nghiên cứu về DUT sẽ sử dụng trong môi trường UVM sắp tới. Hãy cố gắng đọc và phân tích kỹ các khái niệm liên quan của DUT này trước khi đọc các bài tiếp theo.
Link tải RTL code của lõi IP UART được để ngay dưới bài viết.

Dữ liệu có thể tải:
RTL code của lõi IP UART-APB
Pass (nếu có): vlsi_technology

Lịch sử cập nhật:
1/ 2019.05.26 - Tạo lần đầu
2/ 2019.06.02 - Cập nhật thêm thông tin mục 1 và 2 để làm rõ hơn vai trò cần thiết của UVM

Danh sách tác giả:
1. Phạm Thanh Trâm
2. Nguyễn Sinh Tơn
3. Đoàn Đức Hoàng (email: hoangbk154@gmail.com)
4. Trương Công Hoàng Việt
5. Nguyễn Hùng Quân

3 bình luận: