FIFO (First In First Out)
FIFO(First In First Out)는 먼저 넣은 것부터 먼저 나간다는 말입니다.
같은 말은 '선입선출'이 있습니다.
보통 회로에서 Buffer의 목적으로 FIFO를 사용합니다.
위에서부터 값을 하나씩 밀어내어 입력하면서 가장 먼저 입력한 값을 가장 먼저 OUT합니다.
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
값을 입력하기 전에는 EMPTY가 1로 올라갑니다.
wr_en=1일 때 쓰기가 진행되며 EMPTY = 0, 값이 다 입력되면 FULL이 1로 올라갑니다.
후에 rd_en이 1이면 RAM에 있는 값을 읽어옵니다.
'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 |