异步FIFO代码分析

module Asyn_FIFO(data_out, full, empty, data_in, wen, wclk, wrst,ren, rclk, rrst);

parameter datasize = 8; 
parameter addrsize = 4;

input [datasize-1:0]data_in;
input wen,ren,wclk,rclk,wrst,rrst;
output [datasize-1:0]data_out;
output empty,full;
reg empty,full;
wire [datasize-1:0]data_out;
//写指针指向下一个要被写入的单元,复位时,指向第一个单元;读指针总指向当前要被读出的数据,复位时,指向第一个单元
wire [addrsize-1:0]raddr,waddr;        
wire [addrsize:0]rbinnext,wbinnext,rptrnext,wptrnext;
wire empty_val,full_val;
reg  [addrsize:0]rbin,wbin,rptr,wptr,rptr1,rptr2,wptr1,wptr2;
reg  [datasize-1:0]memory[0:(1<<addrsize)-1];


assign data_out=memory[raddr];  //双口RAM,无条件读出,写使能并且写时钟来临才会写入
always @(posedge wclk) begin 
  if(wen&&!full) memory[waddr]<=data_in; 
end


//同步wptr指针
always @(posedge rclk or negedge rrst) begin //读时钟来临,同步写地址,用于空满检测,打两拍
 if(!rrst) {rptr2,rptr1}<=0;
      else {rptr2,rptr1}<={rptr1,wptr};
end 
//同步rptr指针
always @(posedge wclk or negedge wrst)		//写时钟来临,同步读地址,用于空满检测,打两拍
begin if(!wrst) {wptr2,wptr1}<=0;
      else {wptr2,wptr1}<={wptr1,rptr};
end 


//产生raddr信号和empty信号
always @(posedge rclk or negedge rrst)		//读时钟来临,更新读地址rbin(用于读时钟域,作为读地址),并将读地址转换为格雷码rptr(传递到写地址域,用于空满检测)
begin if(!rrst) {rbin,rptr}<=0;
      else {rbin,rptr}<={rbinnext,rptrnext};
end
assign raddr=rbin[addrsize-1:0];//读数据的地址还是之前的读地址,但是在跨时钟的时候需要用格雷码来跨时钟;
assign rbinnext=rbin+(ren&&~empty);
assign rptrnext=(rbinnext>>1)^rbinnext;  //生成raddr 读地址
//FIFO empty
assign empty_val=(rptrnext==rptr2);//读时钟域,比较读指针和同步过来的写指针,判断FIFO是否空
always @(posedge rclk or negedge rrst)
begin if(!rrst) empty<=1;
      else empty<=empty_val;
end
//产生waddr信号和full信号
always @(posedge wclk or negedge wrst)		//写时钟来临,更新写地址wbin(用于写时钟域,作为写地址),并将读地址转换为格雷码wptr(传递到读地址域,用于空满检测)
begin if(!wrst) {wbin,wptr}<=0;
      else {wbin,wptr}<={wbinnext,wptrnext};
end
assign waddr=wbin[addrsize-1:0];
assign wbinnext=wbin+(wen&&~full);
assign wptrnext=(wbinnext>>1)^wbinnext;  //生成waddr
//生成 Full
assign full_val=(wptrnext=={~wptr2[addrsize:addrsize-1],wptr2[addrsize-2:0]});

always @(posedge wclk or negedge wrst)
begin if(!rrst) full<=0;
      else full<=full_val;
end

endmodule

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值