Merge branch 'new_eth' of http://gnuradio.org/git/matt into master
[debian/gnuradio] / usrp2 / fpga / control_lib / newfifo / buffer_int.v
1
2 // FIFO Interface to the 2K buffer RAMs
3 // Read port is read-acknowledge
4 // FIXME do we want to be able to interleave reads and writes?
5
6 module buffer_int
7   #(parameter BUF_NUM = 0,
8     parameter BUF_SIZE = 9)
9     (// Control Interface
10      input clk,
11      input rst,
12      input [31:0] ctrl_word,
13      input go,
14      output done,
15      output error,
16      output idle,
17      output [1:0] flag,
18      
19      // Buffer Interface
20      output en_o,
21      output we_o,
22      output reg [BUF_SIZE-1:0] addr_o,
23      output [31:0] dat_to_buf,
24      input [31:0] dat_from_buf,
25      
26      // Write FIFO Interface
27      input [31:0] wr_data_i,
28      input [3:0] wr_flags_i,
29      input wr_ready_i,
30      output wr_ready_o,
31      
32      // Read FIFO Interface
33      output [31:0] rd_data_o,
34      output [3:0] rd_flags_o,
35      output rd_ready_o,
36      input rd_ready_i
37      );
38    
39    reg [31:0] ctrl_reg;
40    reg        go_reg;
41    
42    always @(posedge clk)
43      go_reg <= go;
44    
45    always @(posedge clk)
46      if(rst)
47        ctrl_reg <= 0;
48      else
49        if(go & (ctrl_word[31:28] == BUF_NUM))
50          ctrl_reg <= ctrl_word;
51    
52    wire [BUF_SIZE-1:0] firstline = ctrl_reg[BUF_SIZE-1:0];
53    wire [BUF_SIZE-1:0] lastline = ctrl_reg[2*BUF_SIZE-1:BUF_SIZE];
54
55    wire       read = ctrl_reg[22];
56    wire       write = ctrl_reg[23];
57    wire       clear = ctrl_reg[24];
58    //wire [2:0] port = ctrl_reg[27:25];  // Ignored in this block
59    //wire [3:0] buff_num = ctrl_reg[31:28];  // Ignored here ?
60    
61    localparam IDLE = 3'd0;
62    localparam PRE_READ = 3'd1;
63    localparam READING = 3'd2;
64    localparam WRITING = 3'd3;
65    localparam ERROR = 3'd4;
66    localparam DONE = 3'd5;
67    
68    reg [2:0]  state;
69    reg        rd_sop, rd_eop;
70    wire       wr_sop, wr_eop, wr_error;
71    reg [1:0]  rd_occ;
72    wire [1:0] wr_occ;
73    
74    always @(posedge clk)
75      if(rst)
76        begin
77           state <= IDLE;
78           rd_sop <= 0;
79           rd_eop <= 0;
80           rd_occ <= 0;
81        end
82      else
83        if(clear)
84          begin
85             state <= IDLE;
86             rd_sop <= 0;
87             rd_eop <= 0;
88             rd_occ <= 0;
89          end
90        else 
91          case(state)
92            IDLE :
93              if(go_reg & read)
94                begin
95                   addr_o <= firstline;
96                   state <= PRE_READ;
97                end
98              else if(go_reg & write)
99                begin
100                   addr_o <= firstline;
101                   state <= WRITING;
102                end
103            
104            PRE_READ :
105              begin
106                 state <= READING;
107                 addr_o <= addr_o + 1;
108                 rd_occ <= 2'b00;
109                 rd_sop <= 1;
110                 rd_eop <= 0;
111              end
112            
113            READING :
114              if(rd_ready_i)
115                begin
116                   rd_sop <= 0;
117                   addr_o <= addr_o + 1;
118                   if(addr_o == lastline)
119                     begin
120                        rd_eop <= 1;
121                        // FIXME assign occ here
122                        rd_occ <= 0;
123                     end
124                   else
125                     rd_eop <= 0;
126                   if(rd_eop)
127                     state <= DONE;
128                end
129            
130            WRITING :
131              begin
132                 if(wr_ready_i)
133                   begin
134                      addr_o <= addr_o + 1;
135                      if(wr_error)
136                        begin
137                           state <= ERROR;
138                           // Save OCC flags here
139                        end
140                      else if((addr_o == lastline)||wr_eop)
141                        state <= DONE;
142                   end // if (wr_ready_i)
143              end // case: WRITING
144            
145          endcase // case(state)
146    
147    assign     dat_to_buf = wr_data_i;
148    assign     rd_data_o = dat_from_buf;
149
150    assign     rd_flags_o = { rd_occ[1:0], rd_eop, rd_sop };
151    assign     rd_ready_o = (state == READING);
152    
153    assign     wr_sop = wr_flags_i[0];
154    assign     wr_eop = wr_flags_i[1];
155    assign     wr_occ = wr_flags_i[3:2];
156    assign     wr_error = wr_sop & wr_eop;
157    assign     wr_ready_o = (state == WRITING);
158
159    assign     we_o = (state == WRITING);
160    //assign     we_o = (state == WRITING) && wr_ready_i;  // always write to avoid timing issue
161
162    assign     en_o = ~((state==READING)& ~rd_ready_i);   // FIXME potential critical path
163    
164    assign     done = (state == DONE);
165    assign     error = (state == ERROR);
166    assign     idle = (state == IDLE);
167
168 endmodule // buffer_int