Merged r9433:9527 from features/gr-usrp2 into trunk. Adds usrp2 and gr-usrp2 top...
[debian/gnuradio] / usrp2 / fpga / sdr_lib / rx_control.v
1
2 `define DSP_CORE_RX_BASE 160
3
4 module rx_control
5   #(parameter FIFOSIZE = 10)
6     (input clk, input rst,
7      input set_stb, input [7:0] set_addr, input [31:0] set_data,
8      
9      input [31:0] master_time,
10      output overrun,
11      
12      // To Buffer interface
13      output [31:0] wr_dat_o,
14      output wr_write_o,
15      output wr_done_o,
16      output wr_error_o,
17
18      input wr_ready_i,
19      input wr_full_i,
20      
21      // From DSP Core
22      input [31:0] sample,
23      output run,
24      input strobe,
25
26      // FIFO Levels
27      output [15:0] fifo_occupied,
28      output fifo_full,
29      output fifo_empty,
30      
31      // Debug
32      output [31:0] debug_rx
33      );
34
35    wire [31:0]     new_time, new_command;
36    wire            sc_pre1, clear_overrun;
37    wire [31:0]     rcvtime_pre;
38    reg [31:0]      rcvtime;
39    wire [8:0]      lines_per_frame;
40    wire [20:0]     numlines;
41    wire            send_imm_pre, chain_pre;
42    reg             send_imm, chain;
43    wire            full_ctrl, read_ctrl, empty_ctrl, write_ctrl;
44
45    setting_reg #(.my_addr(`DSP_CORE_RX_BASE+3)) sr_3
46      (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
47       .in(set_data),.out(new_time),.changed(sc_pre1));
48    
49    setting_reg #(.my_addr(`DSP_CORE_RX_BASE+4)) sr_4
50      (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
51       .in(set_data),.out(new_command),.changed());
52
53    setting_reg #(.my_addr(`DSP_CORE_RX_BASE+5)) sr_5
54      (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
55       .in(set_data),.out(),.changed(clear_overrun));
56
57    reg         sc_pre2;
58    always @(posedge clk)
59      sc_pre2 <= sc_pre1;
60    assign      write_ctrl = sc_pre1 & ~sc_pre2;
61    
62    shortfifo #(.WIDTH(64)) commandfifo
63      (.clk(clk),.rst(rst),.clear(clear_overrun),
64       .datain({new_command,new_time}), .write(write_ctrl), .full(full_ctrl),
65       .dataout({send_imm_pre,chain_pre,numlines,lines_per_frame,rcvtime_pre}), 
66       .read(read_ctrl), .empty(empty_ctrl) );
67
68    // Buffer interface to internal FIFO
69    wire    write, full, read, empty;
70    wire    sop_o, eop_o;
71
72    reg     xfer_state;
73    localparam XFER_IDLE = 1'b0;
74    localparam XFER_GO = 1'b1;
75
76    always @(posedge clk)
77      if(rst)
78        xfer_state <= XFER_IDLE;
79      else
80        if(clear_overrun)
81          xfer_state <= XFER_IDLE;
82        else
83          case(xfer_state)
84            XFER_IDLE :
85              if(wr_ready_i)
86                xfer_state <= XFER_GO;
87            XFER_GO :
88              if((eop_o | wr_full_i) & wr_write_o)
89                xfer_state <= XFER_IDLE;
90            default :
91              xfer_state <= XFER_IDLE;
92          endcase // case(xfer_state)
93    
94    assign     wr_write_o = (xfer_state == XFER_GO) & ~empty;
95    assign     wr_done_o = (eop_o & wr_write_o);
96    assign     wr_error_o = 0;   // FIXME add check here for eop if we have wr_full_i once we have IBS
97
98    assign     read = wr_write_o | (~empty & ~sop_o);   // FIXME  what if there is junk between packets?
99
100    wire [33:0] fifo_line;
101    
102    // Internal FIFO, size 9 is 2K, size 10 is 4K
103    cascadefifo2 #(.WIDTH(34),.SIZE(FIFOSIZE)) rxfifo
104      (.clk(clk),.rst(rst),.clear(clear_overrun),
105       .datain(fifo_line), .write(write), .full(full),
106       .dataout({sop_o,eop_o,wr_dat_o}), .read(read), .empty(empty),
107       .space(),.occupied(fifo_occupied) );
108    assign      fifo_full = full;
109    assign      fifo_empty = empty;
110
111    // Internal FIFO to DSP interface
112    reg [22:0] lines_left;
113    reg [8:0]  lines_left_frame;
114    localparam IBS_IDLE = 0;
115    localparam IBS_WAITING = 1;
116    localparam IBS_FIRSTLINE = 2;
117    localparam IBS_RUNNING = 3;
118    localparam IBS_OVERRUN = 4;
119    
120    reg [2:0] ibs_state;
121   
122    wire [32:0] delta_time = {1'b0,rcvtime}-{1'b0,master_time};
123    wire        too_late = (delta_time[32:31] == 2'b11) & ~send_imm;
124    wire        go_now = send_imm | ( master_time == rcvtime );
125  
126    always @(posedge clk)
127      if(rst)
128        begin
129           ibs_state <= IBS_IDLE;
130           lines_left <= 0;
131           lines_left_frame <= 0;
132           rcvtime <= 0;
133           send_imm <= 0;
134           chain <= 0;
135        end
136      else
137        if(clear_overrun)
138          begin
139           ibs_state <= IBS_IDLE;
140           lines_left <= 0;
141           lines_left_frame <= 0;
142           rcvtime <= 0;
143           send_imm <= 0;
144           chain <= 0;
145          end
146        else 
147          case(ibs_state)
148            IBS_IDLE :
149              if(~empty_ctrl)
150                begin
151                   lines_left <= numlines;
152                   lines_left_frame <= lines_per_frame;
153                   rcvtime <= rcvtime_pre;
154                   ibs_state <= IBS_WAITING;
155                   send_imm <= send_imm_pre;
156                   chain <= chain_pre;
157                end
158            IBS_WAITING :
159              if(go_now)
160                ibs_state <= IBS_FIRSTLINE;
161              else if(too_late)
162                ibs_state <= IBS_OVERRUN;
163            IBS_FIRSTLINE :
164              if(full | strobe)
165                ibs_state <= IBS_OVERRUN;
166              else
167                ibs_state <= IBS_RUNNING;
168            IBS_RUNNING :
169              if(strobe)
170                if(full)
171                  ibs_state <= IBS_OVERRUN;
172                else
173                  begin
174                     lines_left <= lines_left - 1;
175                     if(lines_left == 1)
176                       if(~chain)
177                         ibs_state <= IBS_IDLE;
178                       else if(empty_ctrl)
179                         ibs_state <= IBS_OVERRUN;
180                       else
181                         begin
182                            lines_left <= numlines;
183                            lines_left_frame <= lines_per_frame;
184                            rcvtime <= rcvtime_pre;
185                            ibs_state <= IBS_FIRSTLINE;
186                            send_imm <= send_imm_pre;
187                            chain <= chain_pre;
188                         end
189                     else if(lines_left_frame == 1)
190                       begin
191                          lines_left_frame <= lines_per_frame;
192                          ibs_state <= IBS_FIRSTLINE;
193                       end
194                     else
195                       lines_left_frame <= lines_left_frame - 1;
196                  end // else: !if(full)
197          endcase // case(ibs_state)
198    
199    assign fifo_line = (ibs_state == IBS_FIRSTLINE) ? {1'b1,1'b0,master_time} :
200                       {1'b0,((lines_left==1)|(lines_left_frame==1)),sample};
201    
202    assign write = ((ibs_state == IBS_FIRSTLINE) | strobe) & ~full;  // & (ibs_state == IBS_RUNNING) should strobe only when running
203    assign overrun = (ibs_state == IBS_OVERRUN);
204    assign run = (ibs_state == IBS_RUNNING) | (ibs_state == IBS_FIRSTLINE);
205    assign read_ctrl = ( (ibs_state == IBS_IDLE) | 
206                         ((ibs_state == IBS_RUNNING) & strobe & ~full & (lines_left==1) & chain) )
207           & ~empty_ctrl;
208    
209    assign debug_rx = { 6'd0,send_imm,chain,
210                        wr_write_o, wr_done_o, wr_ready_i, wr_full_i,xfer_state,eop_o, sop_o, run,
211                        write,full,read,empty,write_ctrl,full_ctrl,read_ctrl,empty_ctrl,
212                        sc_pre1, clear_overrun, go_now, too_late, overrun, ibs_state[2:0] };
213 endmodule // rx_control