speed up the diagnostic signals, they were causing timing problems
[debian/gnuradio] / usrp2 / fpga / control_lib / longfifo.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 longfifo
9   #(parameter WIDTH=32, SIZE=9)
10     (input clk, input rst,
11      input [WIDTH-1:0] datain,
12      output [WIDTH-1:0] dataout,
13      input read,
14      input write,
15      input clear,
16      output full,
17      output empty,
18      output reg [15:0] space,
19      output reg [15:0] occupied);
20
21    // Read side states
22    localparam     EMPTY = 0;
23    localparam     PRE_READ = 1;
24    localparam     READING = 2;
25
26    reg [SIZE-1:0] wr_addr, rd_addr;
27    reg [1:0]      read_state;
28
29    reg    empty_reg, full_reg;
30    always @(posedge clk)
31      if(rst)
32        wr_addr <= 0;
33      else if(clear)
34        wr_addr <= 0;
35      else if(write)
36        wr_addr <= wr_addr + 1;
37
38    ram_2port #(.DWIDTH(WIDTH),.AWIDTH(SIZE))
39      ram (.clka(clk),
40           .ena(1'b1),
41           .wea(write),
42           .addra(wr_addr),
43           .dia(datain),
44           .doa(),
45
46           .clkb(clk),
47           .enb((read_state==PRE_READ)|read),
48           .web(0),
49           .addrb(rd_addr),
50           .dib(0),
51           .dob(dataout));
52
53    always @(posedge clk)
54      if(rst)
55        begin
56           read_state <= EMPTY;
57           rd_addr <= 0;
58           empty_reg <= 1;
59        end
60      else
61        if(clear)
62          begin
63             read_state <= EMPTY;
64             rd_addr <= 0;
65             empty_reg <= 1;
66          end
67        else 
68          case(read_state)
69            EMPTY :
70              if(write)
71                begin
72                   //rd_addr <= wr_addr;
73                   read_state <= PRE_READ;
74                end
75            PRE_READ :
76              begin
77                 read_state <= READING;
78                 empty_reg <= 0;
79                 rd_addr <= rd_addr + 1;
80              end
81            
82            READING :
83              if(read)
84                if(rd_addr == wr_addr)
85                  begin
86                     empty_reg <= 1;
87                     if(write)
88                       read_state <= PRE_READ;
89                     else
90                       read_state <= EMPTY;
91                  end
92                else
93                  rd_addr <= rd_addr + 1;
94          endcase // case(read_state)
95
96    wire [SIZE-1:0] dont_write_past_me = rd_addr - 3;
97    wire            becoming_full = wr_addr == dont_write_past_me;
98      
99    always @(posedge clk)
100      if(rst)
101        full_reg <= 0;
102      else if(clear)
103        full_reg <= 0;
104      else if(read & ~write)
105        full_reg <= 0;
106      //else if(write & ~read & (wr_addr == (rd_addr-3)))
107      else if(write & ~read & becoming_full)
108        full_reg <= 1;
109
110    //assign empty = (read_state != READING);
111    assign empty = empty_reg;
112
113    // assign full = ((rd_addr - 1) == wr_addr);
114    assign full = full_reg;
115
116    //////////////////////////////////////////////
117    // space and occupied are for diagnostics only
118    // not guaranteed exact
119
120    localparam NUMLINES = (1<<SIZE)-2;
121    always @(posedge clk)
122      if(rst)
123        space <= NUMLINES;
124      else if(clear)
125        space <= NUMLINES;
126      else if(read & ~write)
127        space <= space + 1;
128      else if(write & ~read)
129        space <= space - 1;
130    
131    always @(posedge clk)
132      if(rst)
133        occupied <= 0;
134      else if(clear)
135        occupied <= 0;
136      else if(read & ~write)
137        occupied <= occupied - 1;
138      else if(write & ~read)
139        occupied <= occupied + 1;
140    
141    /*
142    wire [SIZE-1:0] fullness = wr_addr - rd_addr;  // Approximate, for simulation only
143    assign occupied = {{16-SIZE{1'b0}},fullness};
144
145    wire [SIZE-1:0] free_space = rd_addr - wr_addr - 2;  // Approximate, for SERDES flow control
146    assign space = {{16-SIZE{1'b0}},free_space};
147     */  
148
149    
150 endmodule // longfifo