`timescale 1ns/1ps
module test #(parameter data_width =4,depth =8,addr_width=3)(
wclk,rst_w,w_en,din,w_ptr,
rclk,rst_r,r_en,dout,r_ptr,
fifo_empty,fifo_full
);
input wclk,rst_w,w_en;
input rclk,rst_r,r_en;
input [data_width-1:0]din;
output fifo_empty,fifo_full;
output reg[data_width-1:0]dout;
output reg [addr_width:0]w_ptr,r_ptr;//读写指针
wire [addr_width:0] w_ptr2gray, r_ptr2gray;
reg [addr_width:0] w_ptr2gray1,w_ptr2gray2;
reg [addr_width:0] r_ptr2gray1,r_ptr2gray2;
wire [addr_width-1:0] w_addr,r_addr;//读写地址
reg [data_width-1:0]ram[depth-1:0];//ram存储器
//地址与指针的关系
assign w_addr=w_ptr[addr_width-1:0];
assign r_addr=r_ptr[addr_width-1:0];
//二进制码->格雷码
assign w_ptr2gray=w_ptr^(w_ptr>>1);
assign r_ptr2gray=r_ptr^(r_ptr>>1);
//格雷码同步,w_ptr同步到rclk时钟域
always @(posedge rclk or negedge rst_r) begin
if(!rst_r)begin
w_ptr2gray1<=0;
w_ptr2gray2<=0;
end
else begin
w_ptr2gray1<=w_ptr2gray;
w_ptr2gray2<=w_ptr2gray1;
end
end
//格雷码同步,r_ptr同步到wclk时钟域
always @(posedge wclk or negedge rst_w) begin
if(!rst_w)begin
r_ptr2gray1<=0;
r_ptr2gray2<=0;
end
else begin
r_ptr2gray1<=r_ptr2gray;
r_ptr2gray2<=r_ptr2gray1;
end
end
//写FIFO
always @(posedge wclk or negedge rst_w) begin
if(!rst_w)begin
w_ptr<=0;
end
else if(w_en && !fifo_full) begin
ram[w_addr]<=din;
w_ptr<=w_ptr+1;
end
else begin
w_ptr<=w_ptr;
ram[w_addr]<=ram[w_addr];
end
end
//读FIFO
always @(posedge rclk or negedge rst_r) begin
if(!rst_r)begin
r_ptr<=0;
dout<=0;
end
else if(r_en && !fifo_empty) begin
dout<=ram[r_addr];
r_ptr<=r_ptr+1;
end
else begin
r_ptr<=r_ptr;
end
end
//产生fifo_empty、fifo_full
assign fifo_empty=(w_ptr2gray2 == r_ptr2gray);
assign fifo_full=({~w_ptr2gray[addr_width:addr_width-1],w_ptr2gray[addr_width-2:0]} == r_ptr2gray2 );
endmodule
`timescale 1ns / 1ps
module test_sim;
parameter data_width =4,depth =8,addr_width=3;
reg wclk,rst_w,w_en;
reg rclk,rst_r,r_en;
reg [data_width-1:0]din;
wire fifo_empty,fifo_full;
wire[data_width-1:0]dout;
wire [addr_width:0]w_ptr,r_ptr;//读写指针
always #10 wclk=~wclk;
always #4 rclk=~rclk;
always @(posedge wclk) begin
din<={$random%16};
end
initial begin
wclk=0;rclk=0;
rst_w=1;rst_r=1;
din=0;
{w_en,r_en}=2'b00;
#4 rst_w=0;rst_r=0;
#10 rst_w=1;rst_r=1;
#200 {w_en,r_en}=2'b10;
#200 {w_en,r_en}=2'b01;
#100 {w_en,r_en}=2'b11;
// #200 $stop;
end
test m1(
.wclk(wclk),
.rst_w(rst_w),
.w_en(w_en),
.din(din),
.w_ptr(w_ptr),
.rclk(rclk),
.rst_r(rst_r),
.r_en(r_en),
.dout(dout),
.r_ptr(r_ptr),
.fifo_empty(fifo_empty),
.fifo_full(fifo_full)
);
endmodule
异步FIFO—Verilog实现
同步FIFO与异步FIFO
【FPGA——基础篇】同步FIFO与异步FIFO——Verilog实现