Merged r9433:9527 from features/gr-usrp2 into trunk. Adds usrp2 and gr-usrp2 top...
[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 [15:0] space,
19      output [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    wire [SIZE-1:0] fullness = wr_addr - rd_addr;  // Approximate, for simulation only
30    assign occupied = {{16-SIZE{1'b0}},fullness};
31
32    wire [SIZE-1:0] free_space = rd_addr - wr_addr - 2;  // Approximate, for SERDES flow control
33    assign space = {{16-SIZE{1'b0}},free_space};
34           
35    reg    empty_reg, full_reg;
36    always @(posedge clk)
37      if(rst)
38        wr_addr <= 0;
39      else if(clear)
40        wr_addr <= 0;
41      else if(write)
42        wr_addr <= wr_addr + 1;
43
44    ram_2port #(.DWIDTH(WIDTH),.AWIDTH(SIZE))
45      ram (.clka(clk),
46           .ena(1),
47           .wea(write),
48           .addra(wr_addr),
49           .dia(datain),
50           .doa(),
51
52           .clkb(clk),
53           .enb((read_state==PRE_READ)|read),
54           .web(0),
55           .addrb(rd_addr),
56           .dib(0),
57           .dob(dataout));
58
59    always @(posedge clk)
60      if(rst)
61        begin
62           read_state <= EMPTY;
63           rd_addr <= 0;
64           empty_reg <= 1;
65        end
66      else
67        if(clear)
68          begin
69             read_state <= EMPTY;
70             rd_addr <= 0;
71             empty_reg <= 1;
72          end
73        else 
74          case(read_state)
75            EMPTY :
76              if(write)
77                begin
78                   //rd_addr <= wr_addr;
79                   read_state <= PRE_READ;
80                end
81            PRE_READ :
82              begin
83                 read_state <= READING;
84                 empty_reg <= 0;
85                 rd_addr <= rd_addr + 1;
86              end
87            
88            READING :
89              if(read)
90                if(rd_addr == wr_addr)
91                  begin
92                     empty_reg <= 1;
93                     if(write)
94                       read_state <= PRE_READ;
95                     else
96                       read_state <= EMPTY;
97                  end
98                else
99                  rd_addr <= rd_addr + 1;
100          endcase // case(read_state)
101
102    wire [SIZE-1:0] dont_write_past_me = rd_addr - 3;
103    wire            becoming_full = wr_addr == dont_write_past_me;
104      
105    always @(posedge clk)
106      if(rst)
107        full_reg <= 0;
108      else if(clear)
109        full_reg <= 0;
110      else if(read & ~write)
111        full_reg <= 0;
112      //else if(write & ~read & (wr_addr == (rd_addr-3)))
113      else if(write & ~read & becoming_full)
114        full_reg <= 1;
115
116    //assign empty = (read_state != READING);
117    assign empty = empty_reg;
118
119    // assign full = ((rd_addr - 1) == wr_addr);
120    assign full = full_reg;
121    
122 endmodule // longfifo