URL
https://opencores.org/ocsvn/yifive/yifive/trunk
Subversion Repositories yifive
[/] [yifive/] [trunk/] [caravel_yifive/] [verilog/] [rtl/] [lib/] [async_fifo.sv] - Rev 19
Compare with Previous | Blame | View Log
/*********************************************************************ASYNC FIFOThis file is part of the sdram controller projecthttp://www.opencores.org/cores/sdr_ctrl/Description: ASYNC FIFOTo Do:nothingAuthor(s): Dinesh Annayya, dinesha@opencores.orgCopyright (C) 2000 Authors and OPENCORES.ORGThis source file may be used and distributed withoutrestriction provided that this copyright statement is notremoved from the file and that any derivative work containsthe original copyright notice and the associated disclaimer.This source file is free software; you can redistribute itand/or modify it under the terms of the GNU Lesser GeneralPublic License as published by the Free Software Foundation;either version 2.1 of the License, or (at your option) anylater version.This source is distributed in the hope that it will beuseful, but WITHOUT ANY WARRANTY; without even the impliedwarranty of MERCHANTABILITY or FITNESS FOR A PARTICULARPURPOSE. See the GNU Lesser General Public License for moredetails.You should have received a copy of the GNU Lesser GeneralPublic License along with this source; if not, download itfrom http://www.opencores.org/lgpl.shtml*******************************************************************///-------------------------------------------// async FIFO//-----------------------------------------------//`timescale 1ns/1psmodule async_fifo (wr_clk,wr_reset_n,wr_en,wr_data,full, // sync'ed to wr_clkafull, // sync'ed to wr_clkrd_clk,rd_reset_n,rd_en,empty, // sync'ed to rd_clkaempty, // sync'ed to rd_clkrd_data);parameter W = 4'd8;parameter DP = 3'd4;parameter WR_FAST = 1'b1;parameter RD_FAST = 1'b1;parameter FULL_DP = DP;parameter EMPTY_DP = 1'b0;parameter AW = (DP == 2) ? 1 :(DP == 4) ? 2 :(DP == 8) ? 3 :(DP == 16) ? 4 :(DP == 32) ? 5 :(DP == 64) ? 6 :(DP == 128) ? 7 :(DP == 256) ? 8 : 0;output [W-1 : 0] rd_data;input [W-1 : 0] wr_data;input wr_clk, wr_reset_n, wr_en, rd_clk, rd_reset_n,rd_en;output full, empty;output afull, aempty; // about full and about to empty// synopsys translate_offinitial beginif (AW == 0) begin$display ("%m : ERROR!!! Fifo depth %d not in range 2 to 256", DP);end // if (AW == 0)end // initial begin// synopsys translate_onreg [W-1 : 0] mem[DP-1 : 0];/*********************** write side ************************/reg [AW:0] sync_rd_ptr_0, sync_rd_ptr_1;wire [AW:0] sync_rd_ptr;reg [AW:0] wr_ptr, grey_wr_ptr;reg [AW:0] grey_rd_ptr;reg full_q;wire full_c;wire afull_c;wire [AW:0] wr_ptr_inc = wr_ptr + 1'b1;wire [AW:0] wr_cnt = get_cnt(wr_ptr, sync_rd_ptr);assign full_c = (wr_cnt == FULL_DP) ? 1'b1 : 1'b0;assign afull_c = (wr_cnt == FULL_DP-1) ? 1'b1 : 1'b0;always @(posedge wr_clk or negedge wr_reset_n) beginif (!wr_reset_n) beginwr_ptr <= 0;grey_wr_ptr <= 0;full_q <= 0;endelse if (wr_en) beginwr_ptr <= wr_ptr_inc;grey_wr_ptr <= bin2grey(wr_ptr_inc);if (wr_cnt == (FULL_DP-1)) beginfull_q <= 1'b1;endendelse beginif (full_q && (wr_cnt<FULL_DP)) beginfull_q <= 1'b0;endendendassign full = (WR_FAST == 1) ? full_c : full_q;assign afull = afull_c;always @(posedge wr_clk) beginif (wr_en) beginmem[wr_ptr[AW-1:0]] <= wr_data;endendwire [AW:0] grey_rd_ptr_dly ;assign #1 grey_rd_ptr_dly = grey_rd_ptr;// read pointer synchronizeralways @(posedge wr_clk or negedge wr_reset_n) beginif (!wr_reset_n) beginsync_rd_ptr_0 <= 0;sync_rd_ptr_1 <= 0;endelse beginsync_rd_ptr_0 <= grey_rd_ptr_dly;sync_rd_ptr_1 <= sync_rd_ptr_0;endendassign sync_rd_ptr = grey2bin(sync_rd_ptr_1);/************************ read side *****************************/reg [AW:0] sync_wr_ptr_0, sync_wr_ptr_1;wire [AW:0] sync_wr_ptr;reg [AW:0] rd_ptr;reg empty_q;wire empty_c;wire aempty_c;wire [AW:0] rd_ptr_inc = rd_ptr + 1'b1;wire [AW:0] sync_wr_ptr_dec = sync_wr_ptr - 1'b1;wire [AW:0] rd_cnt = get_cnt(sync_wr_ptr, rd_ptr);assign empty_c = (rd_cnt == 0) ? 1'b1 : 1'b0;assign aempty_c = (rd_cnt == 1) ? 1'b1 : 1'b0;always @(posedge rd_clk or negedge rd_reset_n) beginif (!rd_reset_n) beginrd_ptr <= 0;grey_rd_ptr <= 0;empty_q <= 1'b1;endelse beginif (rd_en) beginrd_ptr <= rd_ptr_inc;grey_rd_ptr <= bin2grey(rd_ptr_inc);if (rd_cnt==(EMPTY_DP+1)) beginempty_q <= 1'b1;endendelse beginif (empty_q && (rd_cnt!=EMPTY_DP)) beginempty_q <= 1'b0;endendendendassign empty = (RD_FAST == 1) ? empty_c : empty_q;assign aempty = aempty_c;reg [W-1 : 0] rd_data_q;wire [W-1 : 0] rd_data_c = mem[rd_ptr[AW-1:0]];always @(posedge rd_clk) beginrd_data_q <= rd_data_c;endassign rd_data = (RD_FAST == 1) ? rd_data_c : rd_data_q;wire [AW:0] grey_wr_ptr_dly ;assign #1 grey_wr_ptr_dly = grey_wr_ptr;// write pointer synchronizeralways @(posedge rd_clk or negedge rd_reset_n) beginif (!rd_reset_n) beginsync_wr_ptr_0 <= 0;sync_wr_ptr_1 <= 0;endelse beginsync_wr_ptr_0 <= grey_wr_ptr_dly;sync_wr_ptr_1 <= sync_wr_ptr_0;endendassign sync_wr_ptr = grey2bin(sync_wr_ptr_1);/************************ functions ******************************/function [AW:0] bin2grey;input [AW:0] bin;reg [8:0] bin_8;reg [8:0] grey_8;beginbin_8 = bin;grey_8[1:0] = do_grey(bin_8[2:0]);grey_8[3:2] = do_grey(bin_8[4:2]);grey_8[5:4] = do_grey(bin_8[6:4]);grey_8[7:6] = do_grey(bin_8[8:6]);grey_8[8] = bin_8[8];bin2grey = grey_8;endendfunctionfunction [AW:0] grey2bin;input [AW:0] grey;reg [8:0] grey_8;reg [8:0] bin_8;begingrey_8 = grey;bin_8[8] = grey_8[8];bin_8[7:6] = do_bin({bin_8[8], grey_8[7:6]});bin_8[5:4] = do_bin({bin_8[6], grey_8[5:4]});bin_8[3:2] = do_bin({bin_8[4], grey_8[3:2]});bin_8[1:0] = do_bin({bin_8[2], grey_8[1:0]});grey2bin = bin_8;endendfunctionfunction [1:0] do_grey;input [2:0] bin;beginif (bin[2]) begin // do reverse greycase (bin[1:0])2'b00: do_grey = 2'b10;2'b01: do_grey = 2'b11;2'b10: do_grey = 2'b01;2'b11: do_grey = 2'b00;endcaseendelse begincase (bin[1:0])2'b00: do_grey = 2'b00;2'b01: do_grey = 2'b01;2'b10: do_grey = 2'b11;2'b11: do_grey = 2'b10;endcaseendendendfunctionfunction [1:0] do_bin;input [2:0] grey;beginif (grey[2]) begin // actually bin[2]case (grey[1:0])2'b10: do_bin = 2'b00;2'b11: do_bin = 2'b01;2'b01: do_bin = 2'b10;2'b00: do_bin = 2'b11;endcaseendelse begincase (grey[1:0])2'b00: do_bin = 2'b00;2'b01: do_bin = 2'b01;2'b11: do_bin = 2'b10;2'b10: do_bin = 2'b11;endcaseendendendfunctionfunction [AW:0] get_cnt;input [AW:0] wr_ptr, rd_ptr;beginif (wr_ptr >= rd_ptr) beginget_cnt = (wr_ptr - rd_ptr);endelse beginget_cnt = DP*2 - (rd_ptr - wr_ptr);endendendfunction// synopsys translate_offalways @(posedge wr_clk) beginif (wr_en && full) begin$display($time, "%m Error! afifo overflow!");$stop;endendalways @(posedge rd_clk) beginif (rd_en && empty) begin$display($time, "%m error! afifo underflow!");$stop;endend// synopsys translate_onendmodule
