Thứ Tư, 30 tháng 8, 2017

[IP core] FIFO đồng bộ có thể cấu hình được

Bài này giới thiệu về thiết kế FIFO đồng bộ có thể cấu hình được độ rộng dữ liệu và dung lượng lưu trữ trước khi tổng hợp. FIFO đồng bộ thường được sử dụng như bộ đệm lưu trữ dữ liệu tạm thời giữa hai miền có tốc độ xử lý dữ liệu khác nhau.

1. Giới thiệu

Lưu ý, tốc độ xử lý dữ liệu khác nhau không có ý nghĩa là xung clock khác nhau hay bất đồng bộ với nhau. Trong trường hợp này, cả hai miền đều sử dụng các xung clock đồng bộ với nhau nhưng vì một miền xử lý nhanh, một miền xử lý chậm nên dữ liệu không thể truyền liên tục giữa hai miền. Giải pháp cho vấn đề này là sử dụng một bộ nhớ lưu dữ liệu tạm thời giữa hai miền để lưu những dữ liệu chưa được xử lý kịp.

FIFO hoạt động theo nguyên tắc dữ liệu được lưu vào trước sẽ là dữ liệu được lấy ra trước. Nghĩa là, thứ tự dữ liệu được đọc ra giống như thứ tự dữ liệu được ghi vào. Hai thông số đặc trưng của FIFO là:
  • Số lượng ô nhớ hay còn gọi là độ sâu của FIFO
  • Độ rộng ô nhớ tương ứng với độ rộng dữ liệu được ghi vào và đọc ra.
Hai thông số trên sẽ cho biết dung lượng của FIFO. Ví dụ, FIFO có 4 ô nhớ, mỗi ô nhớ lưu 8 bit dữ liệu thì dung lượng FIFO là 4*8 = 32 bit hoặc 4 byte. Để định địa chỉ các ô nhớ của FIFO, một phương pháp thường dùng là sử dụng con trỏ ghi và con trỏ đọc. Con trỏ ở đây thực chất là bộ đếm tuần tự.
Hình 1. Minh họa hoạt động của FIFO
2. Sơ đồ tín hiệu giao tiếp FIFO
FIFO thiết kế sẽ có các tín hiệu giao tiếp như sau:
Hình 2. Sơ đồ tín hiệu giao tiếp của FIFO đồng bộ tên SFIFO
  1. Ngõ vào (input)
    1. clk_rd:    xung clock đọc dữ liệu
    2. clk_wr: xung clock ghi dữ liệu, đồng bộ với xung clock đọc clk_rd
    3. rst_n: tín hiệu reset tích cực mức thấp
    4. wr:     tín hiệu ghi dữ liệu vào FIFO
    5. rd:      tín hiệu đọc dữ liệu từ FIFO
    6. data_in[DATA_WIDTH-1:0]: bus dữ liệu ghi có số bit là DATA_WIDTH
    7. low_th[TH_WIDTH-1:0]: tín hiệu cấu hình mức ngưỡng dưới có số bit là TH_WIDTH.
    8. high_th[TH_WIDTH-1:0]: tín hiệu cấu hình mức ngưỡng trên có số bit là TH_WIDTH.
  2. Ngõ ra (output)
    1. sfifo_empty:   tín hiệu báo FIFO rỗng
    2. sfifo_full:       tín hiệu báo FIFO đầy
    3. sfifo_low_th:  tín hiệu báo FIFO thấp hơn mức ngưỡng dưới 
    4. sfifo_high_th:  tín hiệu báo FIFO cao hơn hoặc bằng mức ngưỡng trên
    5. sfifo_ov: tín hiệu báo FIFO bị overflow
    6. sfifo_ud: tín hiệu báo FIFO bị underflow
    7. sfifo_data_out[DATA_WIDTH-1:0]: bus dữ liệu đọc có số bit là DATA_WIDTH
3. Các thông số cấu hình
FIFO sẽ có các thông số cấu hình như sau:
Thông số định nghĩa chức năng:
  1. EMPTY_SIGNAL: Thông số cho phép tạo tín hiệu ngõ ra báo trạng thái rỗng của FIFO, sfifo_empty
  2. FULL_SIGNAL: Thông số cho phép tạo tín hiệu ngõ ra báo trạng thái đầy của FIFO, sfifo_full
  3. SET_LOW_EN: Thông số cho phép tạo tín hiệu ngõ vào dùng để thiết lập giá trị ngưỡng dưới. Chú ý, thông số này chỉ được định nghĩa khi LOW_TH_SIGNAL được sử dụng.
  4. SET_HIGH_EN: Thông số cho phép tạo tín hiệu ngõ vào dùng để thiết lập giá trị ngưỡng trên. Chú ý, thông số này chỉ được định nghĩa khi HIGH_TH_SIGNAL được sử dụng.
  5. LOW_TH_SIGNAL: Thông số cho phép tạo tín hiệu ngõ ra báo dưới một mức ngưỡng được thiết lập sẵn, sfifo_low_th
  6. HIGH_TH_SIGNAL: Thông số cho phép tạo tín hiệu ngõ ra báo dưới mức ngưỡng được thiết lập của FIFO, sfifo_high_th
  7. OV_SIGNAL: Thông số cho phép tạo tín hiệu ngõ ra báo overflow, sfifo_ov
  8. UD_SIGNAL: Thông số cho phép tạo tín hiệu ngõ ra báo underflow, sfifo_ud
  9. OUTPUT_REG: Chèn thanh ghi tại ngõ ra của bus dữ liệu FIFO
  10. TWO_CLOCK: Tạo tín hiệu xung clock đọc và xung clock ghi khác nhau. Lưu ý, cấu hình này sẽ tạo ra hai tín hiệu xung clock ngõ vào sử dụng cho quá trình đọc và quá trình ghi nhưng hai xung clock cấp cho FIFO vẫn phải là 2 xung clock đồng bộ.
Thông số cấu hình giá trị:
  1. DATA_WIDTH: Thiết lập số bit của 1 ô dữ liệu FIFO, tương ứng là độ rộng của bus dữ liệu ghi/đọc
  2. POINTER_WIDTH: Thiết lập độ rộng của con trỏ ghi/đọc. Giá trị này sẽ quyết định số ô nhớ của FIFO theo công thức "Số ô nhớ của FIFO=2^POINTER_WIDTH. Ví dụ, cấu hình POINTER_WIDTH= 3 thì số ô nhớ của FIFO là 2^3 = 8 ô.
  3. TH_WIDTH = POINTER_WIDTH
4. Phân tích cấu trúc FIFO
Lưu ý, các phần tô đỏ là các phần có thể được lựa chọn sẽ được tạo ra hoặc không tạo ra khi tổng hợp thông qua việc định nghĩa các thông số tương ứng. Ví dụ, nếu bạn muốn có tín hiệu sfifo_ov thì hãy định nghĩa từ khóa OV_SIGNAL, ngược lại, nếu không định nghĩa OV_SIGNAL thì tín hiệu này sẽ không được tạo ra.
4.1 Mạch nguyên lý tổng quan

4.2 Con trỏ ghi và đọc

4.3 Mạch báo trạng thái full/empty/overflow/underflow

4.4 Mạch báo trạng thái ngưỡng trên và ngưỡng dưới

5. RTL code và testbench

Link: dowload RTL code của SFIFO

Pass (nếu có): nguyenquanicd

Source File:
  1.  sfifo.v  - RTL code
  2.  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.
  3.  sfifo_parameter.h - chứa thông số cấu hình dung lượng FIFO
  4.  tb_sfifo - một basic testbench

6. Kết quả
Một số hình ảnh tổng hợp trên Quartus II để các bạn có thể hình dung về cách cấu hình.

6.1 Cấu hình 1

Yêu cầu:
  1. Không sử dụng bất cứ tín hiệu báo trạng thái nào
  2. Ngõ ra không chốt thanh ghi
  3. Sử dụng 1 nguồn xung clock
  4. Dung lượng 8 bit * 8 ô nhớ
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

sfifo_parameter.h
parameter DATA_WIDTH    = 8;
parameter POINTER_WIDTH = 3;

Kết quả

6.2 Cấu hình 2

Yêu cầu:
  1. Sử dụng tín hiệu báo FIFO đầy và rỗng
  2. Ngõ ra chốt thanh ghi
  3. Sử dụng 2 nguồn xung clock đồng bộ
  4. Dung lượng 8 bit * 16 ô nhớ
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

sfifo_parameter.h
parameter DATA_WIDTH    = 8;
parameter POINTER_WIDTH = 4;

Kết quả

6.3 Cấu hình 3

Yêu cầu: Thiết lập đầy đủ chức năng
  1. Sử dụng tất cả tín hiệu báo trạng thái trong đó hai trạng thái báo ngưỡng trên và dưới có thể lập trình được (có SET_LOW_EN và SET_HIGH_EN)
  2. Ngõ ra chốt thanh ghi
  3. Sử dụng 2 nguồn xung clock đồng bộ
  4. Dung lượng 32 bit * 16 ô nhớ
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

sfifo_parameter.h
parameter DATA_WIDTH    = 8;
parameter POINTER_WIDTH = 4;

Kết quả


Note: Hãy trao đổi dưới bài viết nếu bạn gặp bất cứ vấn đề gì khi sử dụng.

0 bình luận:

Đăng nhận xét