fifo1进行写,fifo2进行读(第一次没有可读,考虑数据流入的第一个周期很短)
fifo控制模块,写完fifo1指定深度后,拉低写使能,转而拉高fifo2的写使能
两块fifo,前提是一个fifo存储不够,或者写速率大于读速率
module fifo_pingpang(
input rst_n,
input clk,
input [7:0]data_in,
input wr_en,
output reg fifo1_wr_en,
output reg fifo2_wr_en,
output reg fifo1_rd_en,
output reg fifo2_rd_en,
output [7:0]data_out
);
wire [8:0] fifo_cnt1;
wire [8:0] fifo_cnt2;
wire [7:0]data_out1;
wire [7:0]data_out2;
assign data_out=fifo1_rd_en?data_out1:data_out2;
parameter idle = 4'b0000,
start = 4'b0001,
ping = 4'b0010,
pang = 4'b0100;
reg[3:0]state;
reg[3:0]next_state;
//
always@(posedge clk or negedge rst_n)begin
if(!rst_n) state<= idle;
else state <= next_state;
end
//
always@(posedge clk)begin
case(state)
idle:if(wr_en)
next_state <= start;
else next_state <= idle;
start:if(fifo_cnt1 == 9'd500)
next_state <= ping;
else next_state <= start;
ping:if(fifo_cnt2 == 9'd500)
next_state <= pang;
else next_state <= ping;
pang:if(fifo_cnt1 == 9'd500)
next_state <= ping;
else next_state <= pang;
default: next_state <= idle;
endcase
end
//
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
fifo1_wr_en <= 0;
fifo2_wr_en <= 0;
end
else case(state)
idle:begin
fifo1_wr_en <= 0;
fifo2_wr_en <= 0;
fifo2_rd_en <= 0;
fifo1_rd_en <= 0;
end
start:begin
fifo1_wr_en <= 1;
fifo2_wr_en <= 0;
fifo2_rd_en <= 1;
fifo1_rd_en <= 0;
end
ping:begin
fifo1_wr_en <= 0;
fifo2_wr_en <= 1;
fifo2_rd_en <= 0;
fifo1_rd_en <= 1;
end
pang:begin
fifo1_wr_en <= 1;
fifo2_wr_en <= 0;
fifo2_rd_en <= 1;
fifo1_rd_en <= 0;
end
default:begin
fifo1_wr_en <= 0;
fifo2_wr_en <= 0;
fifo2_rd_en <= 0;
fifo1_rd_en <= 0;
end
endcase
end
syn_fifo syn_fifo_1(
.wr_en(fifo1_wr_en),
.rd_en(fifo1_rd_en),
.data_in(data_in),
.rst_n(rst_n),
.clk(clk),
.data_out(data_out1),
.wr_full(),
.rd_empty(),
.fifo_cnt(fifo_cnt1)
);
syn_fifo syn_fifo_2(
.wr_en(fifo2_wr_en),
.rd_en(fifo2_rd_en),
.data_in(data_in),
.rst_n(rst_n),
.clk(clk),
.data_out(data_out2),
.wr_full(),
.rd_empty(),
.fifo_cnt(fifo_cnt2)
);
endmodule
同步FIFO
module syn_fifo(
input wr_en,
input rd_en,
input [7:0] data_in,
input rst_n,
input clk,
output reg [7:0] data_out,
output reg [8:0]fifo_cnt,
output wr_full,
output rd_empty
);
reg [8:0] rd_ptr,wr_ptr;
reg [7:0]fifo[0:512];
//
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rd_ptr <= 0;
wr_ptr <= 0;
end
else begin
if(!rd_empty && rd_en)begin
if(rd_ptr == 500) rd_ptr <= 0;
else rd_ptr <= rd_ptr + 1;
end
if(!wr_full && wr_en)begin
if(wr_ptr == 500) wr_ptr <= 0;
else wr_ptr <= wr_ptr + 1;
end
end
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n) fifo_cnt <= 0;
else if((!rd_empty && rd_en)&&(!wr_full && wr_en)) fifo_cnt <= fifo_cnt;
else if(!rd_empty && rd_en) fifo_cnt <= fifo_cnt - 1;
else if(!wr_full && wr_en) fifo_cnt <= fifo_cnt + 1;
else fifo_cnt <= fifo_cnt;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n) data_out <= 0;
else if(!rd_empty && rd_en) data_out <= fifo[rd_ptr];
else if(!wr_full && wr_en) fifo[wr_ptr] <= data_in;
end
assign wr_full = (fifo_cnt == 500);
assign rd_empty = (fifo_cnt == 0);
endmodule
测试文件
`timescale 1 ps/ 1 ps
module fifo_pingpang_vlg_tst();
// constants
// general purpose registers
reg clk;
reg [7:0]data_in;
reg rst_n;
reg wr_en;
// wires
wire [7:0] data_out;
wire fifo1_rd_en;
wire fifo1_wr_en;
wire fifo2_rd_en;
wire fifo2_wr_en;
// assign statements (if any)
fifo_pingpang i1 (
// port map - connection between master ports and signals/registers
.clk(clk),
.data_in(data_in),
.data_out(data_out),
.fifo1_rd_en(fifo1_rd_en),
.fifo1_wr_en(fifo1_wr_en),
.fifo2_rd_en(fifo2_rd_en),
.fifo2_wr_en(fifo2_wr_en),
.rst_n(rst_n),
.wr_en(wr_en)
);
initial
begin
clk=0;
rst_n=0;
data_in=0;
wr_en=0;
#50 rst_n=1;
#50 wr_en=1;
#200000 $stop;
end
always #10 clk=~clk;
always #18 data_in=data_in+1;
endmodule
很清楚从上图看出两块FIFO的读写使能在循环往复。
从上图可以看出写进去地址1是9,读出来地址1也是9,单一FIFO读写无误。