【新】异步FIFO代码 verilog

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

提示:看完了很多篇异步FIFO代码 感觉都有或多或少的问题,现在提供一版修改后的代码分享给大家,大家一起讨论批评指教。谢谢。


代码如下(宽度为8,深度为5):

module  Afifo(
  input wr_clk,
  input rst_n,
  input wr_en,
  input [WSIZE-1 : 0]din,
  input rd_clk,
  input rd_en,
  output reg [WSIZE-1 : 0]dout,
  output reg rempty,
  output reg wfull
);
    parameter WSIZE = 8;
    parameter DSIZE = 32;
    parameter ASIZE = 5;
//定义变量
reg [WSIZE-1 :0] mem [DSIZE-1 : 0];
reg [ASIZE-1 : 0] waddr,raddr;//MEM中的读写地址
//或者写成 reg[@clog2(`DSIZE)-1:0] waddr,raddr;
reg [ASIZE : 0] wbin,rbin,wbin_next,rbin_next;//二进制的读写地址,最高位用于标志翻转次数

reg [ASIZE : 0] wgray_next,rgray_next;//读写时钟域下的格雷码地址
reg [ASIZE : 0] wp,rd1_wp,rd2_wp;//写地址转化为格雷码wp后,同步到读时钟域用于生产读满标志
reg [ASIZE : 0] rp,wr1_rp,wr2_rp;
wire rempty_val,wfull_val;
 
//输出数据??
assign dout = mem[raddr];

//输入数据
always@(posedge wr_clk)
  if(wr_en && !wfull)
    mem[waddr] <= din;
 
//1.产生存储实体的读地址raddr; 2.将普通二进制转化为格雷码,并赋给读指针rp
always@(posedge rd_clk or negedge rst_n)
  if(!rst_n)
    {rbin,rp} <= 0;
  else
    {rbin,rp} <= {rbin_next,rgray_next};
 
assign raddr = rbin[ASIZE-1 : 0];
assign rbin_next = rbin + (rd_en & ~rempty);//二进制的读地址标签加一
assign rgray_next = rbin_next ^ (rbin_next >> 1);//读时钟域下的格雷码
 
//1.产生存储实体的写地址waddr; 2.将普通二进制转化为格雷码,并赋给写指针wp
always@(posedge wr_clk or negedge rst_n)
  if(!rst_n)
    {wbin,wp} <= 0;
  else
    {wbin,wp} <= {wbin_next,wgray_next};
 
assign waddr = wbin[ASIZE-1 : 0];
assign wbin_next = wbin + (wr_en & ~wfull);
assign wgray_next = wbin_next ^ (wbin_next >> 1);
 
//将读指针rp同步到写时钟域
always@(posedge wr_clk or negedge rst_n)
  if(!rst_n)
    {wr2_rp,wr1_rp} <= 0;
  else
    {wr2_rp,wr1_rp} <= {wr1_rp,rp};
 
//将写指针wp同步到读时钟域
always@(posedge rd_clk or negedge rst_n)
  if(!rst_n)
    {rd2_wp,rd1_wp} <= 0;
  else
    {rd2_wp,rd1_wp} <= {rd1_wp,wp};
 
//将产生的Full信号和Empty信号同步的各自的时钟域上
//产生读空信号rempty:需要读时钟域的格雷码rgray_next和被同步到读时钟域的写指针rd2_wp每一位完全相同;
assign rempty_val = (rd2_wp == rgray_next);
always@(posedge rd_clk or negedge rst_n)
  if(!rst_n)
    rempty <= 1'b0;
  else
    rempty <= rempty_val;
//产生写满信号wfull:需要读时钟域的格雷码rgray_next和被同步到读时钟域的写指针rd2_wp每一位完全相同;
assign wfull_val = ((~(wr2_rp[WSIZE : WSIZE-1]),wr2_rp[WSIZE-2 : 0]) == wgray_next);
always@(posedge wr_clk or negedge rst_n)
  if(!rst_n)
    wfull <= 1'b0;
  else
    wfull <= wfull_val;
 
endmodule
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值