可仿真与综合的异步FIFO设计(2)

Simulation and Synthesis Techniques for Asynchronous FIFO Design

簡介

本文大部分内容来自Clifford E. Cummings的《Simulation and Synthesis Techniques for Asynchronous FIFO Design》,同时加上一些自己的一些理解,有兴趣的朋友可以阅读原文,我有在我的下载文档里上传。
关于FIFO的设计方法Clifford总共有说明两种设计方法:
第一种是构造一个指针宽度为N+1,深度为2^N字节的FIFO(为便方比较将格雷码指针转换为二进制指针)。这有在上一篇文章里介绍过了。
第二种是将它将FIFO地址分成了4部分,每部分分别用高两位的MSB 00 、01、 11、 10决定FIFO是否为going full 或going empty (即将满或空)。

原理

Clifford E. Cummings的文章中提到的STYLE #2。
它将FIFO地址分成了4部分,每部分分别用高两位的MSB 00 、01、 11、 10决定FIFO是否为going full 或going empty (即将满或空)。如果写指针的高两位MSB小于读指针的高两位MSB则FIFO为“几乎满”,若写指针的高两位MSB大于读指针的高两位MSB则FIFO为“几乎空”。

如果写指针比读指针之后一个象限,则表明FIFO接近满。此时置标志位direction为1,并且锁存其值。相应的等式为:
wire dirset_n = ~(( wptr[N]^rptr[N-1]) & ~(wptr[N-1]^rptr[N]));

在这里插入图片描述
如果写指针比读指针超前一个象限,则表明FIFO为接近空状态,如图所示。此时置标志direction为0,并且锁存其值。相应的等式为:
wire dirclr_n = (((wptr[n]^rptr[n-1]) & (wptr[n-1] ^ rptr[n])) | ~wrst_n;
在这里插入图片描述

模块设计

FIFO模块结构
(1)顶层模块,对所有FIFO模块进行封装
(2)双口RAM模块,用于实现读写操作
(3)异步比较器,用于实现FIFO读写指针比较,并输出状态信号以生成正确的FIFO空满标志
(4)FIFO写指针与满逻辑控制模块,用于生成FIFO写地址指针并且生成FIFO满标志。
(5)FIFO读指针与空逻辑控制模块,用于生成FIFO读地址指针并且生成FIFO空标志。
在这里插入图片描述

顶层模块

module fifo2 (rdata, wfull, rempty, wdata,
                      winc, wclk, wrst_n, rinc, rclk, rrst_n);
parameter DSIZE = 8;
parameter ASIZE = 4;
                      output [DSIZE-1:0] rdata;
                      output wfull;
                      output rempty;
                      input [DSIZE-1:0] wdata;
                      input winc, wclk, wrst_n;
                      input rinc, rclk, rrst_n;
wire [ASIZE-1:0] wptr, rptr;
wire [ASIZE-1:0] waddr, raddr;
async_cmp #(ASIZE) async_cmp
                       (.aempty_n(aempty_n), 
                        .afull_n(afull_n),
                        .wptr(wptr), 
                        .rptr(rptr),
                         .wrst_n(wrst_n));
fifomem #(DSIZE, ASIZE) fifomem
                       (.rdata(rdata),
                        .wdata(wdata),
                        .waddr(wptr),
                        .raddr(rptr),
                        .wclken(winc),
                         .wclk(wclk));
rptr_empty #(ASIZE) rptr_empty
                        (.rempty(rempty), 
                         .rptr(rptr),
                        .aempty_n(aempty_n),
                         .rinc(rinc),
                         .rclk(rclk),
                         .rrst_n(rrst_n));
wptr_full #(ASIZE) wptr_full
                       (.wfull(wfull),
                        .wptr(wptr),
                        .afull_n(afull_n),
                         .winc(winc),
                        .wclk(wclk),
                         .wrst_n(wrst_n));
endmodule

双口RAM模块

FIFO内存缓冲区可以是一个实例化的ASIC或FPGA双端口同步内存设备。内存缓冲区也可以使用该模块中的RTL代码合成到ASIC或FPGA寄存器。
如果已实例化供应商RAM,强烈建议使用命名端口连接进行实例化。

 module fifomem (rdata, wdata, waddr, raddr, wclken, wclk);
    parameter DATASIZE = 8; // Memory data word width
    parameter ADDRSIZE = 4; // Number of memory address bits
    parameter DEPTH = 1<<ADDRSIZE; // DEPTH = 2**ADDRSIZE
                           output [DATASIZE-1:0] rdata;
                           input [DATASIZE-1:0] wdata;
                           input [ADDRSIZE-1:0] waddr, raddr;
                           input wclken, wclk;
      `ifdef VENDORRAM // instantiation of a vendor's dual-port RAM
    VENDOR_RAM MEM (.dout(rdata), 
                                         .din(wdata),
                                         .waddr(waddr), 
                                         .raddr(raddr),
                                        .wclken(wclken), 
                                        .clk(wclk));
    `else
    reg [DATASIZE-1:0] MEM [0:DEPTH-1];
    assign rdata = MEM[raddr];
    always @(posedge wclk)
           if (wclken) MEM[waddr] <= wdata;
    `endif
    endmodule

写满模块

此模块包含写入时钟域(同步器除外)内生成的所有FIFO逻辑。写入指针是一个n位灰色代码计数器。
与上一个FIFO寄存器没有什么区别。

module wptr_full (wfull, wptr, afull_n, winc, wclk, wrst_n);
parameter ADDRSIZE = 4;
output wfull;
output [ADDRSIZE-1:0] wptr;
input afull_n;
input winc, wclk, wrst_n;
reg [ADDRSIZE-1:0] wptr, wbin;
reg wfull, wfull2;
wire [ADDRSIZE-1:0] wgnext, wbnext;
//---------------------------------------------------------------
// GRAYSTYLE2 pointer
//---------------------------------------------------------------
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) begin
wbin <= 0;
wptr <= 0;
end
else begin
wbin <= wbnext;
wptr <= wgnext;
end
//---------------------------------------------------------------
// increment the binary count if not full
//---------------------------------------------------------------
assign wbnext = !wfull ? wbin + winc : wbin;
assign wgnext = (wbnext>>1) ^ wbnext; // binary-to-gray conversion
always @(posedge wclk or negedge wrst_n or negedge afull_n)
if (!wrst_n ) {wfull,wfull2} <= 2'b00;
else if (!afull_n) {wfull,wfull2} <= 2'b11;
else {wfull,wfull2} <= {wfull2,~afull_n};
endmodule

读空模块

module rptr_empty (rempty, rptr, aempty_n, rinc, rclk, rrst_n);
parameter ADDRSIZE = 4;
output rempty;
output [ADDRSIZE-1:0] rptr;
input aempty_n;
input rinc, rclk, rrst_n;
reg [ADDRSIZE-1:0] rptr, rbin;
reg rempty, rempty2;
wire [ADDRSIZE-1:0] rgnext, rbnext;
//---------------------------------------------------------------
// GRAYSTYLE2 pointer
//---------------------------------------------------------------
always @(posedge rclk or negedge rrst_n)
if (!rrst_n) begin
rbin <= 0;
rptr <= 0;
end
else begin
rbin <= rbnext;
rptr <= rgnext;
end
//---------------------------------------------------------------
// increment the binary count if not empty
//---------------------------------------------------------------
assign rbnext = !rempty ? rbin + rinc : rbin;
assign rgnext = (rbnext>>1) ^ rbnext; // binary-to-gray conversion
always @(posedge rclk or negedge aempty_n)
if (!aempty_n) {rempty,rempty2} <= 2'b11;
else {rempty,rempty2} <= {rempty2,~aempty_n};
endmodule

异步比较器

这是本文设计中的核心内容。
用於確定FIFO上的滿狀態或空狀態的邏輯是FIFO樣式#1和FIFO樣式#2之間最明顯的區別。
Async_cmp是一個異步比較模塊,用於比較讀寫指針以檢測full和empty的條件。

module async_cmp (aempty_n, afull_n, wptr, rptr, wrst_n);
    parameter ADDRSIZE = 4;
    parameter N = ADDRSIZE-1;
    output       aempty_n, afull_n;
    input [N:0]   wptr, rptr;
    input          wrst_n;
reg direction;
wire high = 1'b1;
wire dirset_n = ~( (wptr[N]^rptr[N-1]) & ~(wptr[N-1]^rptr[N]));
wire dirclr_n = ~((~(wptr[N]^rptr[N-1]) & (wptr[N-1]^rptr[N])) |~wrst_n);
always @(posedge high or negedge dirset_n or negedge dirclr_n)
    if (!dirclr_n) direction <= 1'b0;
     else if (!dirset_n) direction <= 1'b1;
         else direction <= high;
//always @(negedge dirset_n or negedge dirclr_n)
//if (!dirclr_n) direction <= 1'b0;
//else direction <= 1'b1;
assign aempty_n = ~((wptr == rptr) && !direction);
assign afull_n = ~((wptr == rptr) && direction);
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值