new fifos copied over from other project
[debian/gnuradio] / usrp2 / fpga / control_lib / newfifo / fifo_long.v
1
2 // FIFO intended to be interchangeable with shortfifo, but
3 //  based on block ram instead of SRL16's
4 //  only one clock domain
5
6 // Port A is write port, Port B is read port
7
8 module fifo_long
9   #(parameter WIDTH=32, SIZE=9)
10    (input clk, input reset, input clear,
11     input [WIDTH-1:0] datain,
12     input src_rdy_i,
13     output dst_rdy_o,
14     output [WIDTH-1:0] dataout,
15     output src_rdy_o,
16     input dst_rdy_i,
17     
18     output reg [15:0] space,
19     output reg [15:0] occupied);
20    
21    wire write        = src_rdy_i & dst_rdy_o;
22    wire read         = dst_rdy_i & src_rdy_o;
23    wire full, empty;
24    
25    assign dst_rdy_o  = ~full;
26    assign src_rdy_o  = ~empty;
27    
28    // Read side states
29    localparam     EMPTY = 0;
30    localparam     PRE_READ = 1;
31    localparam     READING = 2;
32
33    reg [SIZE-1:0] wr_addr, rd_addr;
34    reg [1:0]      read_state;
35
36    reg    empty_reg, full_reg;
37    always @(posedge clk)
38      if(reset)
39        wr_addr <= 0;
40      else if(clear)
41        wr_addr <= 0;
42      else if(write)
43        wr_addr <= wr_addr + 1;
44
45    ram_2port #(.DWIDTH(WIDTH),.AWIDTH(SIZE))
46      ram (.clka(clk),
47           .ena(1'b1),
48           .wea(write),
49           .addra(wr_addr),
50           .dia(datain),
51           .doa(),
52
53           .clkb(clk),
54           .enb((read_state==PRE_READ)|read),
55           .web(0),
56           .addrb(rd_addr),
57           .dib(0),
58           .dob(dataout));
59
60    always @(posedge clk)
61      if(reset)
62        begin
63           read_state <= EMPTY;
64           rd_addr <= 0;
65           empty_reg <= 1;
66        end
67      else
68        if(clear)
69          begin
70             read_state <= EMPTY;
71             rd_addr <= 0;
72             empty_reg <= 1;
73          end
74        else 
75          case(read_state)
76            EMPTY :
77              if(write)
78                begin
79                   //rd_addr <= wr_addr;
80                   read_state <= PRE_READ;
81                end
82            PRE_READ :
83              begin
84                 read_state <= READING;
85                 empty_reg <= 0;
86                 rd_addr <= rd_addr + 1;
87              end
88            
89            READING :
90              if(read)
91                if(rd_addr == wr_addr)
92                  begin
93                     empty_reg <= 1;
94                     if(write)
95                       read_state <= PRE_READ;
96                     else
97                       read_state <= EMPTY;
98                  end
99                else
100                  rd_addr <= rd_addr + 1;
101          endcase // case(read_state)
102
103    wire [SIZE-1:0] dont_write_past_me = rd_addr - 3;
104    wire            becoming_full = wr_addr == dont_write_past_me;
105      
106    always @(posedge clk)
107      if(reset)
108        full_reg <= 0;
109      else if(clear)
110        full_reg <= 0;
111      else if(read & ~write)
112        full_reg <= 0;
113      //else if(write & ~read & (wr_addr == (rd_addr-3)))
114      else if(write & ~read & becoming_full)
115        full_reg <= 1;
116
117    //assign empty = (read_state != READING);
118    assign empty = empty_reg;
119
120    // assign full = ((rd_addr - 1) == wr_addr);
121    assign full = full_reg;
122
123    //////////////////////////////////////////////
124    // space and occupied are for diagnostics only
125    // not guaranteed exact
126
127    localparam NUMLINES = (1<<SIZE)-2;
128    always @(posedge clk)
129      if(reset)
130        space <= NUMLINES;
131      else if(clear)
132        space <= NUMLINES;
133      else if(read & ~write)
134        space <= space + 1;
135      else if(write & ~read)
136        space <= space - 1;
137    
138    always @(posedge clk)
139      if(reset)
140        occupied <= 0;
141      else if(clear)
142        occupied <= 0;
143      else if(read & ~write)
144        occupied <= occupied - 1;
145      else if(write & ~read)
146        occupied <= occupied + 1;
147    
148 endmodule // fifo_long