動(dòng)漫設(shè)計(jì)與制作課程網(wǎng)站優(yōu)化設(shè)計(jì)公司
典型電路設(shè)計(jì)之FIFO設(shè)計(jì)
FIFO (First In First Out)是一種先進(jìn)先出的數(shù)據(jù)緩存器,通常用于接口電路的數(shù)據(jù)緩存。與普通存儲(chǔ)器的區(qū)別是沒有外部讀寫地址線,可以使用兩個(gè)時(shí)鐘分別進(jìn)行寫和讀操作。FIFO只能順序?qū)懭霐?shù)據(jù)和順序讀出數(shù)據(jù),其數(shù)據(jù)地址由內(nèi)部讀寫指針自動(dòng)加1完成,不能像普通存儲(chǔ)器那樣可以由地址線決定讀取或?qū)懭肽硞€(gè)指定的地址。
FIFO由存儲(chǔ)器塊和對(duì)數(shù)據(jù)進(jìn)出FIFO的通道進(jìn)行管理的控制器構(gòu)成,每次只對(duì)一個(gè)寄存器提供存取操作,而不是對(duì)整個(gè)寄存器陣列進(jìn)行。FIFO有兩個(gè)地址指針,一個(gè)用于將數(shù)據(jù)寫入下一個(gè)可用的存儲(chǔ)單元,一個(gè)用于讀取下一個(gè)未讀存儲(chǔ)單元的操作。讀寫數(shù)據(jù)必須一次進(jìn)行。
當(dāng)一個(gè)堆棧為空時(shí)(圖A),讀數(shù)據(jù)指針和寫數(shù)據(jù)指針都指向第一個(gè)存儲(chǔ)單元,如所示;當(dāng)寫入一個(gè)數(shù)據(jù)時(shí)(圖B)寫數(shù)據(jù)指針將指向下個(gè)存儲(chǔ)單元;經(jīng)過七次寫數(shù)據(jù)操作后(圖C)寫指針將指向最后一個(gè)數(shù)據(jù)單元;當(dāng)經(jīng)過連續(xù)八次寫操作之后寫指針將回到首單元并且顯示堆棧狀態(tài)為滿(圖D)。數(shù)據(jù)的讀操作和寫操作相似,當(dāng)讀出一個(gè)數(shù)據(jù)時(shí),讀數(shù)據(jù)指針將移向下一個(gè)存儲(chǔ)單元,直到讀出全部的數(shù)據(jù),此時(shí)讀指針回到首單元,堆棧狀態(tài)顯示為空。
一個(gè)FIFO的組成一般包括兩個(gè)部分:地址控制部分和存儲(chǔ)數(shù)據(jù)的RAM部分。如下圖所示。地址控制部分可以根據(jù)讀寫指令生成RAM地址。RAM用于存儲(chǔ)堆棧數(shù)據(jù),并根據(jù)控制部分生成的地址信號(hào)進(jìn)行數(shù)據(jù)的存儲(chǔ)和讀取操作。這里的RAM采用的是前面提到的雙口RAM。
例用Verilog HDL 設(shè)計(jì)深度為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