massive overhaul of fpga code
[fleet.git] / src / edu / berkeley / fleet / fpga / mem / async_fifo.v
1 //==========================================
2 // Function : Asynchronous FIFO (w/ 2 asynchronous clocks).
3 // Coder    : Alex Claros F.
4 // Date     : 15/May/2005.
5 // Notes    : This implementation is based on the article 
6 //            'Asynchronous FIFO in Virtex-II FPGAs'
7 //            writen by Peter Alfke. This TechXclusive 
8 //            article can be downloaded from the
9 //            Xilinx website. It has some minor modifications.
10 //=========================================
11
12 `timescale 1ns / 1ps
13
14 module async_fifo
15   #(parameter    DATA_WIDTH    = 8,
16                  ADDRESS_WIDTH = 4,
17                  FIFO_DEPTH    = (1 << ADDRESS_WIDTH))
18      //Reading port
19     (output wire [DATA_WIDTH-1:0]        Data_out, 
20      output reg                          Empty_out,
21      input wire                          ReadEn_in,
22      input wire                          RClk,        
23      //Writing port.     
24      input wire  [DATA_WIDTH-1:0]        Data_in,  
25      output reg                          Full_out,
26      input wire                          WriteEn_in,
27      input wire                          WClk,
28          
29      input wire                          Clear_in);
30
31     /////Internal connections & variables//////
32     reg   [DATA_WIDTH-1:0]              Mem [FIFO_DEPTH-1:0];
33     wire  [ADDRESS_WIDTH-1:0]           pNextWordToWrite, pNextWordToRead;
34     wire                                EqualAddresses;
35     wire                                NextWriteAddressEn, NextReadAddressEn;
36     wire                                Set_Status, Rst_Status;
37     reg                                 Status;
38     wire                                PresetFull, PresetEmpty;
39     
40     //////////////Code///////////////
41     //Data ports logic:
42     //(Uses a dual-port RAM).
43     //'Data_out' logic:
44     assign  Data_out = Mem[pNextWordToRead];
45 //    always @ (posedge RClk)
46 //        if (!PresetEmpty)
47 //            Data_out <= Mem[pNextWordToRead];
48 //        if (ReadEn_in & !Empty_out)
49             
50     //'Data_in' logic:
51     always @ (posedge WClk)
52         if (WriteEn_in & !Full_out)
53             Mem[pNextWordToWrite] <= Data_in;
54
55     //Fifo addresses support logic: 
56     //'Next Addresses' enable logic:
57     assign NextWriteAddressEn = WriteEn_in & ~Full_out;
58     assign NextReadAddressEn  = ReadEn_in  & ~Empty_out;
59            
60     //Addreses (Gray counters) logic:
61     GrayCounter #(
62                 .COUNTER_WIDTH( ADDRESS_WIDTH )
63     ) GrayCounter_pWr (
64         .GrayCount_out(pNextWordToWrite),
65         .Enable_in(NextWriteAddressEn),
66         .Clear_in(Clear_in),
67         
68         .Clk(WClk)
69        );
70        
71     GrayCounter #(
72                 .COUNTER_WIDTH( ADDRESS_WIDTH )
73     ) GrayCounter_pRd (
74         .GrayCount_out(pNextWordToRead),
75         .Enable_in(NextReadAddressEn),
76         .Clear_in(Clear_in),
77         .Clk(RClk)
78        );
79      
80
81     //'EqualAddresses' logic:
82     assign EqualAddresses = (pNextWordToWrite == pNextWordToRead);
83
84     //'Quadrant selectors' logic:
85     assign Set_Status = (pNextWordToWrite[ADDRESS_WIDTH-2] ~^ pNextWordToRead[ADDRESS_WIDTH-1]) &
86                          (pNextWordToWrite[ADDRESS_WIDTH-1] ^  pNextWordToRead[ADDRESS_WIDTH-2]);
87                             
88     assign Rst_Status = (pNextWordToWrite[ADDRESS_WIDTH-2] ^  pNextWordToRead[ADDRESS_WIDTH-1]) &
89                          (pNextWordToWrite[ADDRESS_WIDTH-1] ~^ pNextWordToRead[ADDRESS_WIDTH-2]);
90                          
91     //'Status' latch logic:
92     always @ (Set_Status, Rst_Status, Clear_in) //D Latch w/ Asynchronous Clear & Preset.
93         if (Rst_Status | Clear_in)
94             Status = 0;  //Going 'Empty'.
95         else if (Set_Status)
96             Status = 1;  //Going 'Full'.
97             
98     //'Full_out' logic for the writing port:
99     assign PresetFull = Status & EqualAddresses;  //'Full' Fifo.
100     
101     always @ (posedge WClk, posedge PresetFull) //D Flip-Flop w/ Asynchronous Preset.
102         if (PresetFull)
103             Full_out <= 1;
104         else
105             Full_out <= 0;
106             
107     //'Empty_out' logic for the reading port:
108     assign PresetEmpty = ~Status & EqualAddresses;  //'Empty' Fifo.
109     
110     always @ (posedge RClk, posedge PresetEmpty)  //D Flip-Flop w/ Asynchronous Preset.
111         if (PresetEmpty)
112             Empty_out <= 1;
113         else
114             Empty_out <= 0;
115             
116 endmodule