典型電路設計之FIFO設計
FIFO (First In First Out)是一種先進先出的數據緩存器,通常用于接口電路的數據緩存。與普通存儲器的區別是沒有外部讀寫地址線,可以使用兩個時鐘分別進行寫和讀操作。FIFO只能順序寫入數據和順序讀出數據,其數據地址由內部讀寫指針自動加1完成,不能像普通存儲器那樣可以由地址線決定讀取或寫入某個指定的地址。
FIFO由存儲器塊和對數據進出FIFO的通道進行管理的控制器構成,每次只對一個寄存器提供存取操作,而不是對整個寄存器陣列進行。FIFO有兩個地址指針,一個用于將數據寫入下一個可用的存儲單元,一個用于讀取下一個未讀存儲單元的操作。讀寫數據必須一次進行。
當一個堆棧為空時(圖A),讀數據指針和寫數據指針都指向第一個存儲單元,如所示;當寫入一個數據時(圖B)寫數據指針將指向下個存儲單元;經過七次寫數據操作后(圖C)寫指針將指向最后一個數據單元;當經過連續八次寫操作之后寫指針將回到首單元并且顯示堆棧狀態為滿(圖D)。數據的讀操作和寫操作相似,當讀出一個數據時,讀數據指針將移向下一個存儲單元,直到讀出全部的數據,此時讀指針回到首單元,堆棧狀態顯示為空。
一個FIFO的組成一般包括兩個部分:地址控制部分和存儲數據的RAM部分。如下圖所示。地址控制部分可以根據讀寫指令生成RAM地址。RAM用于存儲堆棧數據,并根據控制部分生成的地址信號進行數據的存儲和讀取操作。這里的RAM采用的是前面提到的雙口RAM。
例用Verilog HDL 設計深度為8,位寬為8的FIFO
下面是verilog代碼
module FIFO_buffer(clk,rst,write_to_stack,read_from_stack,Data_in,Data_out);
input clk,rst;
input write_to_stack,read _from_stack;
input [7:0] Data_in;
output [7:0] Data_out;
wire [7:0]Data_out;
wire stack_full,stack_empty;
wire [2:0] addr_in, addr_out;
.write_to_stack(write_to_stack),.write_ptr(addr_in),
.write_to_stack(write_to_stack),.write_ptr(addr_in),.read_ptr(addr_out),.read_from_stack(read_from_stack),.clk(clk),.rst(rst));
ram_dual U2(.q(Data_out),.addr_in(addr_in),.addr_out(addr_out),.d(Data_in),.we(write_to_stack),.rd(read_from_stack),.clk1(clk),.clk2(Clk));
endmodule
module FIFO_control( write_ptr,read_ptr,stack_full, stack_empty,write_to_stack,
read_from_stack, clk, rst);
parameter stack_width=8;
parameter stack_height=8;
parameter stack_ptr_width=3;
output stack_full;
output stack_empty;
output [stack_ptr_width-1:0] read_ptr;
output [stack_ptr_width-1:0] write_ptr;
input write_to_stack;
input read_from_stack;
input clk;
inputrst;
reg[stack_ptr_width-1:0] read ptr;
reg[stack_ptr_width-1:0] write _ptr;
reg[stack _ptr_width:0] ptr_gap;
reg [stack_width-1:0] Data_out;
reg[stack_width-1:0]stack[stack_height-1:0];
always@(posedge clk or posedge rst)begin
if(rst)begin
Data_out<=0;
read_ptr<=0;
write_ptr<=0;
ptr_gap<=0;
end
else if(write_to_stack && (!stack_full) && (!read_from_stack))begin
write_ptr<=write_ptr+1;
ptr_gap<=ptr_gap+1;
end
else if(!write_to_stack && (!stack_empty) && (read_from_stack))begin
read_ptr<=read_ptr+1;
ptr_gap<=ptr_gap-1;
end
else if(write_to _stack && stack_empty &.& read _from_stack)begin
write_ptr<=write_ptr+1;
ptr_gap<=ptr_gap+1;
end
else if(write _to_stack && stack_full && read_from_stack)begin
read _ptr<=read_ptr+1;
ptr_gap<=ptr_gap-1;
end
else if(write_to_stack && read_from_stack
&& (!stack_full)&&(!stack_empty))begin
read_ptr<=read_ptr+1;
write_ptr<=write_ptr+1;
end
end
endmodule
下面是testbench
module FIFO_tb;
reg clk, rst;
reg [7:0]Data_in;
reg write_to_stack, read_from_stack;
wire[7:0] Data_out;
FIFO_buffer U1(.clk(clk),.rst(rst),.write_to_stack(write_to_stack),
.read_from_stack(read_from_stack),.Data_in(Data_in),
.Data_out(Data_out));
initial
begin
clk=0;
rst=1;
Data_in=0;
write_to_stack=1;
read_from_stack=0;
#5 rst=0;
#155 write_to_stack=0;
read_from_stack=1;
end
always #10 clk=~clk;
initial
begin
repeat(7)
#20 Data_in=Data_in+1;
end
endmodule