您当前的位置: 首页 > 

FPGA硅农

暂无认证

  • 2浏览

    0关注

    282博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

基于System verilog的异步FIFO实现

FPGA硅农 发布时间:2022-02-22 14:17:15 ,浏览量:2

异步FIFO读写分别采用相互异步的不同时钟。在现代集成电路芯片中,随着设计规模的不断扩大,一个系统中往往含有数个时钟,多时钟域带来的一个问题就是,如何设计异步时钟之间的接口电路。异步FIFO是这个问题的一种简便、快捷的解决方案,使用异步FIFO可以在两个不同时钟系统之间快速而方便地传输实时数据。 异步FIFO设计中,最重要的就是满和空信号的设计,具体的思路就是通过读写指针的比较,来生成相应的full或者empty信号,在之前同步FIFO的设计中已经讲到了这一判断方法,即: 在指针中添加一个额外的位(extra bit),当写指针增加并越过最后一个FIFO地址时,就将写指针这个未用的MSB加1,其它位回零。对读指针也进行同样的操作。当两指针重合时,如果两个指针的MSB不同,说明写指针比读指针多折回了一次,FIFO为满。如果两个指针的MSB相同,则说明两个指针折回的次数相等。其余位相等,说明FIFO为空。 然而,在异步FIFO中情况更加复杂,由于写指针和读指针所在的时钟域不同,因此两者在进行比较时,有可能因为建立时间、保持时间不满足,而生成错误的空满信号,从而使FIFO无法正常工作,因此,我们在比较之前,首先需要将写指针同步到读时钟域,再和读指针比较,生成empty信号;将读指针同步到写时钟域,再和写指针比较,生成full信号。 关于跨时钟域信号的同步,之前的博客也已经介绍过,单bit的信号通过打两拍的方式即可,而多bit信号,则可以采用格雷码的方式,转化为单bit信号的跨时钟域同步,在本博客中,我们就将读写指针转化为格雷码,然后通过打两拍的方式进行同步,最后比较生成相应的空或者满信号。其转化公式如下: wr_ptr_gray=wr_ptr>>1^wr_ptr; rd_ptr_gray=rd_ptr>>1^rd_ptr; 根据上式,我们不难得到格雷码的比较方式: 当wr_ptr_gray的高两位不同,其余位都相同时,FIFO为满; 当rd_ptr_gray的高两位相同,其余位也相同时,FIFO位空。 整个异步FIFO的System verilog代码如下:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/02/22 13:02:45
// Design Name: 
// Module Name: async_fifo
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module async_fifo
#(parameter DATA_WIDTH = 32,
  parameter FIFO_DEPTH = 32)
(
input logic rst,
//写端口
input logic wclk,
input logic [DATA_WIDTH-1:0] wdata,
input logic wr_en,
output logic full,
//读端口
input logic rclk,
input logic rd_en,
output logic [DATA_WIDTH-1:0] rdata,
output logic empty
    );
parameter ADDR_WIDTH=$clog2(FIFO_DEPTH);
logic [DATA_WIDTH-1:0] RAM [FIFO_DEPTH-1];

logic [ADDR_WIDTH-1:0] wr_addr;                  //RAM写地址(下一个将要写入的地址)
logic [ADDR_WIDTH-1:0] rd_addr;                  //RAM读地址(下一个将要读出的地址)
logic [ADDR_WIDTH:0] wr_ptr;                     //有额外标志位
logic [ADDR_WIDTH:0] rd_ptr;                     //有额外标志位
//
logic [ADDR_WIDTH:0] wr_ptr_gray;
logic [ADDR_WIDTH:0] wr_ptr_gray_d1;
logic [ADDR_WIDTH:0] wr_ptr_gray_d2;
//
logic [ADDR_WIDTH:0] rd_ptr_gray;
logic [ADDR_WIDTH:0] rd_ptr_gray_d1;
logic [ADDR_WIDTH:0] rd_ptr_gray_d2;
//wr_ptr
always_ff@(posedge wclk,posedge rst)
if(rst)
    wr_ptr            
关注
打赏
1658642721
查看更多评论
0.0357s