用verilog实现两种同步FIFO的方法,非常适合初学者理解时序的控制过程和方法!
理解了这个东西,很多verilog 的实现方法和思想你会有一个深入的理解的!
慢慢积累呀!
★★一种风格的同步FIFO【我最喜欢的同步FIFO风格!】
//8×32bit的同步FIFO
module FIFO_Buffer(
Data_out,
stack_full,
stack_almost_full,
stack_half_full,
stack_almost_empty,
stack_empty,
Data_in,
write_to_stack,
read_from_stack,
clk,rst
);
parameter stack_width=32; //数据位宽
parameter stack_height=8; //FIFO深度
parameter stack_ptr_width=3;
parameter AE_level=2;
parameter AF_level=6;
parameter HF_level=4;
output [stack_width-1:0] Data_out;
output stack_full,stack_almost_full,stack_half_full;
output stack_almost_empty,stack_empty;
input[stack_width-1:0] Data_in;
input write_to_stack,read_from_stack;
input clk,rst;
reg[stack_ptr_width-1:0] read_ptr,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];
assign stack_full=(ptr_gap==stack_height);
assign stack_almost_full=(ptr_gap==AF_level);
assign stack_half_full=(ptr_gap==HF_level);
assign stack_almost_empty=(ptr_gap==AE_level);
assign stack_empty=(ptr_gap==0);
always @(posedge clk or posedge rst)
if(rst)begin
Data_out<=0;
read_ptr<=0;
write_ptr<=0;
ptr_gap<=0;
end
//①只有写入请求且FIFO不满
elseif(write_to_stack &&(!stack_full)&&(!read_from_stack))begin
stack[write_ptr]<=Data_in;
write_ptr<=write_ptr+1;
ptr_gap<=ptr_gap+1;
end
//②只有读出请求且FIFO不空
elseif((!write_to_stack)&&(!stack_empty)&&read_from_stack)begin
Data_out<=stack[read_ptr];
read_ptr<=read_ptr+1;
ptr_gap<=ptr_gap-1;
end
//同时有写入、读出请求,但FIFO为空,此时仅对写入做处理,同①
else if(write_to_stack&&read_from_stack&&stack_empty)begin
stack[write_ptr]<=Data_in;
write_ptr<=write_ptr+1;
ptr_gap<=ptr_gap+1;
end
//同时有写入、读出请求,但FIFO为满,此时仅对读出做处理,同②
else if(write_to_stack&&read_from_stack&&stack_full)begin
Data_out<=stack[read_ptr];
read_ptr<=read_ptr+1;
ptr_gap<=ptr_gap-1;
end
//③同时有写入、读出请求且FIFO既不满也不空
elseif(write_to_stack&&read_from_stack&&(!stack_full)&&(!stack_empty))
begin
Data_out<=stack[read_ptr];
stack[write_ptr]<=Data_in;
read_ptr<=read_ptr+1;
write_ptr<=write_ptr+1;
end
endmodule
//16*16 fifo//
//方法1
//
module fifo(clock,reset,read,write,fifo_in,fifo_out,fifo_empty,fifo_half,fifo_full);
input clock,reset,read,write;
input [15:0]fifo_in;
output[15:0]fifo_out;
output fifo_empty,fifo_half,fifo_full;//标志位
reg [15:0]fifo_out;
reg [15:0]ram[15:0];
reg [3:0]read_ptr,write_ptr,counter;//指针与计数
wire fifo_empty,fifo_half,fifo_full;
always@(posedge clock)
if(reset)
begin
read_ptr=0;
write_ptr=0;
counter=0;
fifo_out=0; //初始值
end
else
case({read,write})
2'b00:
counter=counter; //没有读写指令
2'b01: //写指令,数据输入fifo
begin
ram[write_ptr]=fifo_in;
counter=counter+1;
write_ptr=(write_ptr==15)?0:write_ptr+1;
end
2'b10: //读指令,数据读出fifo
begin
fifo_out=ram[read_ptr];
counter=counter-1;
read_ptr=(read_ptr==15)?0:read_ptr+1;
end
2'b11: //读写指令同时,数据可以直接输出
begin
if(counter==0)
fifo_out=fifo_in;
else
begin
ram[write_ptr]=fifo_in;
fifo_out=ram[read_ptr];
write_ptr=(write_ptr==15)?0:write_ptr+1;
read_ptr=(read_ptr==15)?0:write_ptr+1;
end
end
endcase
assignfifo_empty=(counter==0); //标志位赋值组合电路
assign fifo_half=(counter==8);
assign fifo_full=(counter==15);
endmodule
aaa
//4*16 fifo
//方法2
//
module fifo_four(clk,rstp,din,readp,writep,dout,emptyp,fullp);
inputclk; //时钟
inputrstp; //复位
input[15:0]din; //16位输入信号
inputreadp; //读指令
inputwritep; //写指令
output[15:0]dout; //16位输出信号
outputemptyp; //空指示信号
outputfullp; //满指示信号
parameter DEPTH=2,MAX_COUNT=2'b11;
reg[15:0]dout;
reg emptyp;
reg fullp;
reg[(DEPTH-1):0] tail; //读指针
reg[(DEPTH-1):0] head;//写指针
reg[(DEPTH-1):0] count; //计数器
reg[15:0]fifomem[0:MAX_COUNT]; //四个16位存储单元
//read
always@(posedge clk)
if(rstp==1)
dout<=0;
else if(readp==1&&emptyp==0)
dout<=fifomem[tail];
//write
always@(posedge clk)
if(rstp==1&&writep==1&&fullp==0)
fifomem[head]<=din;
//更新head指针
always@(posedge clk)
if(rstp==1)
head<=0;
else if(writep==1&&fullp==0)
head<=head+1;
//更新tail指针
always@(posedge clk)
if(rstp==1)
tail<=0;
else if(readp==1&&emptyp==0)
tail<=tail+1;
//count
always@(posedge clk)
if(rstp==1)
count<=0;
else
case({readp,writep})
2'b00:
count<=count;
2'b01:
if(count!=MAX_COUNT)
count<=count+1;
2'b10:
if(count!=0)
count<=count-1;
2'b11:
count<=count;
endcase
//更新标志位emptyp
always@(count)
if(count==0)
emptyp<=1;
else
emptyp<=0;
//更新标志位tail
always@(count)
if(count==MAX_COUNT)
fullp <=1;
else
fullp <=0;
endmodule
************************************************************
网上的代码读数据输出(dataout)部分不受读使能(rd)控制,显然不对,所以稍作修改,欢迎批评
************************************************************