updated wiki url
[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 FIFO interface of Buffer Pool
13      output [31:0] wr_dat_o,
14      output [3:0] wr_flags_o,
15      input wr_ready_i,
16      output wr_ready_o,
17
18      // From DSP Core
19      input [31:0] sample,
20      output run,
21      input strobe,
22
23      // FIFO Levels
24      output [15:0] fifo_occupied,
25      output fifo_full,
26      output fifo_empty,
27      
28      // Debug
29      output [31:0] debug_rx
30      );
31
32    wire [31:0]     new_time, new_command;
33    wire            sc_pre1, clear_overrun;
34    wire [31:0]     rcvtime_pre;
35    reg [31:0]      rcvtime;
36    wire [8:0]      lines_per_frame;
37    wire [20:0]     numlines;
38    wire            send_imm_pre, chain_pre;
39    reg             send_imm, chain;
40    wire            full_ctrl, read_ctrl, empty_ctrl, write_ctrl;
41
42    setting_reg #(.my_addr(`DSP_CORE_RX_BASE+3)) sr_3
43      (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
44       .in(set_data),.out(new_time),.changed(sc_pre1));
45    
46    setting_reg #(.my_addr(`DSP_CORE_RX_BASE+4)) sr_4
47      (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
48       .in(set_data),.out(new_command),.changed());
49
50    setting_reg #(.my_addr(`DSP_CORE_RX_BASE+5)) sr_5
51      (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
52       .in(set_data),.out(),.changed(clear_overrun));
53
54    reg         sc_pre2;
55    always @(posedge clk)
56      sc_pre2 <= sc_pre1;
57    assign      write_ctrl = sc_pre1 & ~sc_pre2;
58    
59    shortfifo #(.WIDTH(64)) commandfifo
60      (.clk(clk),.rst(rst),.clear(clear_overrun),
61       .datain({new_command,new_time}), .write(write_ctrl), .full(full_ctrl),
62       .dataout({send_imm_pre,chain_pre,numlines,lines_per_frame,rcvtime_pre}), 
63       .read(read_ctrl), .empty(empty_ctrl) );
64
65    // Buffer interface to internal FIFO
66    wire        have_space, write;
67    wire [35:0] fifo_line;
68    
69    // Internal FIFO, size 9 is 2K, size 10 is 4K
70    fifo_cascade #(.WIDTH(36),.SIZE(FIFOSIZE)) rxfifo
71      (.clk(clk),.reset(rst),.clear(clear_overrun),
72       .datain(fifo_line), .src_rdy_i(write), .dst_rdy_o(have_space),
73       .dataout({wr_flags_o,wr_dat_o}), .src_rdy_o(wr_ready_o), .dst_rdy_i(wr_ready_i),
74       .space(),.occupied(fifo_occupied) );
75    assign      fifo_full = ~have_space;
76    assign      fifo_empty = ~wr_ready_o;
77
78    // Internal FIFO to DSP interface
79    reg [22:0] lines_left;
80    reg [8:0]  lines_left_frame;
81    localparam IBS_IDLE = 0;
82    localparam IBS_WAITING = 1;
83    localparam IBS_FIRSTLINE = 2;
84    localparam IBS_RUNNING = 3;
85    localparam IBS_OVERRUN = 4;
86    
87    reg [2:0] ibs_state;
88   
89    wire [32:0] delta_time = {1'b0,rcvtime}-{1'b0,master_time};
90    wire        too_late = (delta_time[32:31] == 2'b11) & ~send_imm;
91    wire        go_now = send_imm | ( master_time == rcvtime );
92  
93    always @(posedge clk)
94      if(rst)
95        begin
96           ibs_state <= IBS_IDLE;
97           lines_left <= 0;
98           lines_left_frame <= 0;
99           rcvtime <= 0;
100           send_imm <= 0;
101           chain <= 0;
102        end
103      else
104        if(clear_overrun)
105          begin
106           ibs_state <= IBS_IDLE;
107           lines_left <= 0;
108           lines_left_frame <= 0;
109           rcvtime <= 0;
110           send_imm <= 0;
111           chain <= 0;
112          end
113        else 
114          case(ibs_state)
115            IBS_IDLE :
116              if(~empty_ctrl)
117                begin
118                   lines_left <= numlines;
119                   lines_left_frame <= lines_per_frame;
120                   rcvtime <= rcvtime_pre;
121                   ibs_state <= IBS_WAITING;
122                   send_imm <= send_imm_pre;
123                   chain <= chain_pre;
124                end
125            IBS_WAITING :
126              if(go_now)
127                ibs_state <= IBS_FIRSTLINE;
128              else if(too_late)
129                ibs_state <= IBS_OVERRUN;
130            IBS_FIRSTLINE :
131              if(~have_space | strobe)
132                ibs_state <= IBS_OVERRUN;
133              else
134                ibs_state <= IBS_RUNNING;
135            IBS_RUNNING :
136              if(strobe)
137                if(~have_space)
138                  ibs_state <= IBS_OVERRUN;
139                else
140                  begin
141                     lines_left <= lines_left - 1;
142                     if(lines_left == 1)
143                       if(~chain)
144                         ibs_state <= IBS_IDLE;
145                       else if(empty_ctrl)
146                         ibs_state <= IBS_OVERRUN;
147                       else
148                         begin
149                            lines_left <= numlines;
150                            lines_left_frame <= lines_per_frame;
151                            rcvtime <= rcvtime_pre;
152                            ibs_state <= IBS_FIRSTLINE;
153                            send_imm <= send_imm_pre;
154                            chain <= chain_pre;
155                         end
156                     else if(lines_left_frame == 1)
157                       begin
158                          lines_left_frame <= lines_per_frame;
159                          ibs_state <= IBS_FIRSTLINE;
160                       end
161                     else
162                       lines_left_frame <= lines_left_frame - 1;
163                  end // else: !if(~have_space)
164          endcase // case(ibs_state)
165    
166    assign fifo_line = (ibs_state == IBS_FIRSTLINE) ? {2'b0,1'b0,1'b1,master_time} :
167                       {2'b0,((lines_left==1)|(lines_left_frame==1)),1'b0,sample};
168    
169    assign write = ((ibs_state == IBS_FIRSTLINE) | strobe) & have_space;  // & (ibs_state == IBS_RUNNING) should strobe only when running
170    assign overrun = (ibs_state == IBS_OVERRUN);
171    assign run = (ibs_state == IBS_RUNNING) | (ibs_state == IBS_FIRSTLINE);
172    assign read_ctrl = ( (ibs_state == IBS_IDLE) | 
173                         ((ibs_state == IBS_RUNNING) & strobe & have_space & (lines_left==1) & chain) )
174           & ~empty_ctrl;
175    
176    assign debug_rx = { 8'd0,
177                        1'd0, send_imm, chain, wr_ready_i,wr_ready_o, 2'b0, run,
178                        write,have_space,wr_flags_o[1:0],write_ctrl,full_ctrl,read_ctrl,empty_ctrl,
179                        sc_pre1, clear_overrun, go_now, too_late, overrun, ibs_state[2:0] };
180 endmodule // rx_control