先看看双口RAM
同步FIFO 是指 读写时钟是同一个时钟 !
空满判断依据: 写指针追上读指针,就是满;读指针追上写,就是空。
直接上代码 ,在QII 中能直接运行。(参考了 opencores)
/////////////////////////////////////////////////////
// Function : synchronous fifo
// Structure: SRAM
// 读写fifo注意: 满时,只能读,不能写;空时,只能写,不能读
// Date : 2014.05.28
/////////////////////////////////////////////////////
module syn_fifo(clk,rst_n,din,we,dout,re,full,empty);
parameter dw=8; // 数据位宽
parameter aw=5; // RAM地址线宽度 fifo深度 2^5=32
input clk;
input rst_n;
input [dw-1:0] din; // 输入数据
input we; // 写使能
input re; // 读使能
output [dw-1:0] dout; // 输出数据
output full; // 满标志
output empty; // 空标志
wire [aw-1:0] wr_ptr1;
wire [aw-1:0] wr_ptr2;
wire [aw-1:0] rd_ptr1;
////////////////////////////////////////////////////
// SRAM 例化 , SRAM 使用 QII IP核
wire aclr;
assign aclr=~rst_n;
reg [aw-1:0] wr_ptr; // 写指针
reg [aw-1:0] rd_ptr; // 读指针
ram U1(
.aclr(aclr),
.clock(clk),
.data(din),
.rdaddress(rd_ptr),
.rden(re),
.wraddress(wr_ptr),
.wren(we),
.q(dout));
////////////////////////////////////////////////////
// 读写地址(指针变化)
always@(posedge clk or negedge rst_n)
if(!rst_n)
wr_ptr<={aw{1'b0}};
else if(we)
wr_ptr<=wr_ptr1;
assign wr_ptr1=wr_ptr+{{(aw-1){1'b0}},1'b1}; // 指向下一个地址
//assign wr_ptr2=wr_ptr+{{(aw-2){2'b0}},2'b10};
always@(posedge clk or negedge rst_n)
if(!rst_n)
rd_ptr<={aw{1'b0}};
else if(re)
rd_ptr<=rd_ptr1;
assign rd_ptr1=rd_ptr+{{(aw-1){1'b0}},1'b1}; // 指向下一个地址
////////////////////////////////////////////////////
// 空满标志
reg gb;
always@(posedge clk or negedge rst_n)
if(!rst_n)
gb<=1'b0;
else if((wr_ptr1==rd_ptr)&we) // 写赶上读 ,满
gb<=1'b1;
else if(re)
gb<=1'b0;
assign full = (wr_ptr==rd_ptr)& gb; // 组合逻辑,可能会产生毛刺,使用同步时序方
assign empty= (wr_ptr==rd_ptr)& (!gb); // 式可以避免毛刺
endmodule
仿真
影响此设计最高时钟速率的因素: 主要是存储器SRAM的读写速率 !
同步FIFO 用的很少 ,异步FIFO才是设计难点。。。。
文章评论(0条评论)
登录后参与讨论