FIFO (First In First Out)

 

FIFO(First In First Out)는 먼저 넣은 것부터 먼저 나간다는 말입니다.

같은 말은 '선입선출'이 있습니다.

보통 회로에서 Buffer의 목적으로 FIFO를 사용합니다.

 

RAM

위에서부터 값을 하나씩 밀어내어 입력하면서 가장 먼저 입력한 값을 가장 먼저 OUT합니다.

FIFO Block Diagram

WR_EN은 쓰기모드

RD_EN은 읽기모드로 FIFO를 구성하였습니다.

WR_EN에서 쓸 공간이 없다면 FULL을 보내고, 

RD_EN에서 더 출력할 DATA가 없으면 EMPTY를 보냅니다.


fifo verilog code

`timescale 1ns / 1ps

module my_fifo(
    input RST,
    input CLK,
    input [7:0] DIN,
    input WR_EN,
    output FULL,
    output [7:0] DOUT,
    input RD_EN,
    output EMPTY
    );
    
reg [7:0]   ram [0:15]; //Define 4bit Memory
reg [4:0]   wr_addr, rd_addr; //Define write/read address.  Set 1bit at MSB for full and empty
wire        addr_pos;       //Temporary signal for full/empty signal making

always @(posedge CLK)
begin
    if (RST)
        wr_addr <= 5'd0; //wr_addr reset to zero at RST = 1
    else if(WR_EN)
        wr_addr <= wr_addr + 1; //when WR_EN = 1, wr_addr + 1
end //always
       
always @(posedge CLK)
    if(WR_EN)
        ram[wr_addr] <= DIN;    //when WR_EN = 1, execute the write. So save the DIN at the "wr_addr"th address of ram 
        
always @(posedge CLK)
begin
    if (RST)
        rd_addr <= 5'd0;    //Reset the rd_addr to zero at RST = 1
    else if(RD_EN)
        rd_addr <= rd_addr + 1; //when RD_EN = 1, rd_addr + 1
end

assign DOUT = ram[rd_addr]; // Apply "rd_addr"th number of ram to DOUT

wire addr_eq = (wr_addr[3:0] == rd_addr[3:0]); //check address equivalence

assign addr_pos = rd_addr[4] ^ wr_addr[4]; // Use XOR. when read and write addresses are different, make their output = 1

assign FULL = addr_eq &(~addr_pos);
assign EMPTY = addr_eq & addr_pos;

endmodule

 

 


Testbench

 


fifo testbench code

`timescale 1ns / 1ps

module ny_fifo_tb();

parameter CLK_PD = 8.0;

reg rst, clk, wr_en, rd_en;
reg [7:0] din;
wire full, empty;
wire [7:0] dout;

my_fifo uut0(
    .RST        (rst),
    .CLK        (clk),
    .DIN        (din),
    .WR_EN      (wr_en),
    .FULL       (full),
    .DOUT       (dout),
    .RD_EN      (rd_en),
    .EMPTY      (empty)
    );

always @(posedge clk)
begin
    if(rst)
        din <= 8'd0;    //din reset to zero at RST = 1로 초기화
    else if(wr_en)
        din <= din + 1;
end//always end

initial begin
        rst = 1'b1;
        #(CLK_PD * 10);
        rst = 1'b0;
end

initial clk = 1'b0;
always #(CLK_PD/2) clk = ~clk;

initial begin
        wr_en = 1'b0;
        rd_en = 1'b0;
        wait (rst == 1'b0);
        #(CLK_PD * 20);
        wr_en = 1'b1;
        repeat(17) @(posedge clk);
        wr_en = 1'b0;
        #(CLK_PD*20);
        rd_en = 1'b1;
        wait(empty == 1'b1);
        #(CLK_PD * 20);
        rd_en = 1'b0;
        wr_en = 1'b1;
        @(posedge clk);
        wr_en = 1'b0;
        rd_en = 1'b1;
        @(posedge clk);
        rd_en = 1'b0;
        #(CLK_PD*10); // 
        $finish;
end

endmodule

 

FIFO Testbench

값을 입력하기 전에는 EMPTY가 1로 올라갑니다.

wr_en=1일 때 쓰기가 진행되며 EMPTY = 0, 값이 다 입력되면 FULL이 1로 올라갑니다.

후에 rd_en이 1이면 RAM에 있는 값을 읽어옵니다.

 

Synthesized Design

 

'Circuit Design > 🔥HDL' 카테고리의 다른 글

[Verilog] 12. UART(3) TX  (0) 2024.06.10
[Verilog] 11. UART(2)  (0) 2024.06.03
[Verilog] 9. RAM(Random Access Memory)  (0) 2024.05.27
[Verilog] 8. Uart  (0) 2024.05.27
[Verilog] 7. 교통신호기 FSM  (0) 2024.04.29