|
用verilog实现两种同步FIFO的方法,非常适合初学者理解时序的控制过程和方法!
理解了这个东西,很多verilog 的实现方法和思想你会有一个深入的理解的!
慢慢积累呀!
//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
assign fifo_empty=(counter==0); //标志位赋值 组合电路
assign fifo_half=(counter==8);
assign fifo_full=(counter==15);
endmodule
//4*16 fifo
//方法2
//
module fifo_four(clk,rstp,din,readp,writep,dout,emptyp,fullp);
input clk; //时钟
input rstp; //复位
input[15:0]din; //16位输入信号
input readp; //读指令
input writep; //写指令
output[15:0]dout; //16位输出信号
output emptyp; //空指示信号
output fullp; //满指示信号
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)
tail<=1;
else
tail<=0;
endmodule |
|