Trung tâm đào tạo thiết kế vi mạch Semicon


  • ĐĂNG KÝ TÀI KHOẢN ĐỂ TRUY CẬP NHIỀU TÀI LIỆU HƠN!
  • Create an account
    *
    *
    *
    *
    *
    Fields marked with an asterisk (*) are required.
semicon_lab.jpg

Tìm hiểu về FIFO đơn giản

E-mail Print PDF

1. FIFO và lý do sử dụng FIFO:

Về khái niệm, FIFO viết tắt của cụm từ First In First Out. Nó dùng để ám chỉ thứ tự đọc và ghi dữ liệu vào ra của FIFO. Dữ liệu nào được ghi vào trước thì sẽ được đọc ra trước.

Trong thiết kế logic cũng như thiết kế phần cứng, FIFO được sử dụng rất phổ biến:

    - Cần lưu 1 lượng dữ liệu tương đối lớn hơn so với các thanh ghi đơn lẻ. Lượng dữ liệu này thường có kích thước không quá lớn.

    - Cần lưu tạm một lượng dữ liệu phục vụ cho quá trình đồng bộ giữa 2 miền clock có xung nhịp khác nhau.

    - Cần lưu lại một lượng dữ liệu là đơn vị của quá trình tính toán nào đó.

Khi đó, người ta thường hay sử dụng đến FIFO.

 

2. Logic của FIFO:

    - Nếu hiểu theo tư duy phần mềm thì FIFO là một mảng có N phần tử, mỗi phần tử có độ rộng là M. Tương đương với một số lượng là N, mỗi FlipFlop có M bits. Dung lượng của FIFO theo bit là A = N x M ( bits ), hoặc A = N x M /8 ( bytes ).

    - Việc xác định phần tử để truy cập vào FIFO được thực hiện thông qua các con trỏ ( pointers ) hoặc địa chỉ ( address ).

        + Phần ghi FIFO sử dụng address ghi

        + Phần đọc FIFO sử dụng address đọc

    - Do FIFO là mảng FlipFlop cho nên nó có thể lưu lại giá trị. Giả sử FIFO đã được ghi đầy, về lý thuyết thì chúng ta có thể truy cập bất kỳ phần tử nào của FIFO thông qua address đọc.

    - Khi không được ghi, thì dữ liệu trong FIFO sẽ không thay đổi. Do đó, chỉ có việc ghi vào mới làm giá trị của FIFO thay đổi. Việc ghi vào sẽ vì thế mà được điều khiển ( control ) bằng tín hiệu "write_enable".

    - FIFO cũng như các loại memory nói chung, không dùng tín hiệu reset. Muốn thiết lập giá trị ban đầu cho FIFO thì cần phải thực hiện việc ghi vào FIFO các giá trị khởi tạo.

 

3. Block diagram:

Thật thiếu sót nếu như học thiết kế logic mà không dùng đến Diagram.

 

Đây là Block Diagram của một FIFO đơn giản nhất. FIFO này gồm 16 phần tử, mỗi phần tử có 8 bits. Bây giờ cùng tìm hiểu các code cho FIFO này như thế nào.

 

4. Coding:

- Khai báo FIFO trong verilog tương tự như khai báo mảng. Khi đó, cần có 2 thông số là số lượng phần tử và độ rộng của một phần tử.

 reg [M-1:0] FIFO [N-1:0];

- Code của FIFO trong always sẽ như sau:

reg [7:0] FIFO [15:0];

always @ ( posedge clock ) begin

    if ( write_enable == 1'b1 )

        FIFO[wr_pointer] <= data_in;

end

- write_enable:

    + 1'b0: Dữ liệu FIFO thứ n nào đó ( tùy theo giá trị của wr_pointer ) sẽ giữ nguyên giá trị của nó.

    + 1'b1: Dữ liệu FIFO thứ n nào đó ( tùy theo giá trị của wr_pointer ) sẽ được cập nhật giá trị của data_in.

        Lúc này, ta có thể hiểu đây là quá trình ghi vào FIFO.

Như vậy, code hoàn chỉnh cho 1 FIFO đơn giản sẽ như sau:

module simple_fifo (

    clock,

    write_enable,

    wr_pointer,

    rd_pointer,

    data_in,

    data_out

);

input clock;

input write_enable,;

input [3:0] wr_pointer,;

input [3:0] rd_pointer;

input [7:0] data_in;

output [7:0] data_out;

wire clock;

wire write_enable;

wire [3:0] wr_pointer,;

wire [3:0] rd_pointer;

wire [7:0] data_in;

wire [7:0] data_out;

// internal signals

reg [7:0] FIFO [15:0];

always @ ( posedge clock ) begin

    if ( write_enable == 1'b1 )

        FIFO[wr_pointer] <= data_in;

end

assign data_out = FIFO[rd_pointer];

endmodule

Schematic của khối FIFO sẽ có dạng như thế này trên Vivado.

 

Bên trong khối màu vàng:

- WE1 ( Write_Enable )

- RA ( Read Address )

- WA ( Write Address )

- WD ( Write Data )

- RO ( Read Output )

 

5. Simulation:

Để kiểm chứng lại chức năng và dạng sóng của FIFO, chúng ta dùng test bench như sau:

module simple_fifo_test();

    reg clock;

    reg write_enable;

    reg [3:0] wr_pointer;

    reg [3:0] rd_pointer;

    reg [7:0] data_in;

    wire [7:0] data_out;

    reg [4:0] i;

 

simple_fifo DUT (

    .clock (clock),

    .write_enable ( write_enable ),

    .wr_pointer(wr_pointer),

    .rd_pointer(rd_pointer),

    .data_in (data_in),

    .data_out (data_out)

);

 

always begin

    #5; clock = ! clock;

end

 

initial begin

    clock                = 1'b0;

    write_enable   = 1'b0;

    wr_pointer      = 4'h0;

    rd_pointer       = 4'h0;

    data_in            = 8'h00;

    i                        = 0 ;

end

initial begin

    #25;

    for ( i = 0; i < 16; i = i + 1 ) begin

        @ ( posedge clock );

        write_enable = 1'b1;

        wr_pointer = i;

        data_in = $random();

    end

    @ ( posedge clock );

    write_enable = 1'b0;

    #25;

end

endmodule

Chức năng của testbench:

    - Tạo clock

    - Tạo các tín hiệu điều khiển quá trình ghi.

    - Giá trị đầu vào là data_in được cho ngẫn nhiên ( random )

    - Quan sát giá trị của FIFO trên testbench.

    - Testbench bên trên chưa tạo sự thay đổi của read pointer, nên nếu các bạn muốn đọc FIFO thì có thể tạo sự thay đổi cho read pointer.

Waveform:

 

 

6. Các điểm lưu ý:

    - Chọn lựa dung lượng FIFO thích hợp với các tài nguyên trên board. Nếu chọn size FIFO lớn hơn mức hỗ trợ của chip FPGA, các bạn có thể nghĩ đến việc dùng DDRAM hoặc Flash, hoặc SDcard.

    - Trước khi đọc FIFO, phải chắc chắn là FIFO đã được khởi tạo ( bằng cách ghi giá trị bất kỳ vào FIFO ) . Nếu đọc FIFO chưa được khởi tạo, các giá trị trong FIFO là không xác định, có thể ảnh hưởng đển các mạch tiếp theo.

Nguồn: degic.freeforums

Bạn Có Đam Mê Với Vi Mạch hay Nhúng      -     Bạn Muốn Trau Dồi Thêm Kĩ Năng

Mong Muốn Có Thêm Cơ Hội Trong Công Việc

    Và Trở Thành Một Người Có Giá Trị Hơn

Bạn Chưa Biết Phương Thức Nào Nhanh Chóng Để Đạt Được Chúng

Hãy Để Chúng Tôi Hỗ Trợ Cho Bạn. SEMICON  

 

Hotline: 0972.800.931 - 0938.838.404 (Mr Long)

 

 

Related Articles

Chat Zalo