Imported Upstream version 3.2.2
[debian/gnuradio] / usrp / fpga / sdr_lib / rx_buffer.v
index ec5b8eefee0298dc92d428f7daa3d0211bc3b2a7..d17294b987ab918a24ae1a8dda1a59d315a8f924 100644 (file)
 //
 
 // Interface to Cypress FX2 bus
-// A packet is 512 Bytes.  Each fifo line is 2 bytes
-// Fifo has 1024 or 2048 lines
+// A packet is 512 Bytes, the fifo has 4096 lines of 18 bits each
 
 `include "../../firmware/include/fpga_regs_common.v"
 `include "../../firmware/include/fpga_regs_standard.v"
 
 module rx_buffer
-  ( input usbclk,
-    input bus_reset,  // Not used in RX
-    input reset,  // DSP side reset (used here), do not reset registers
-    input reset_regs, //Only reset registers
+  ( // Read/USB side
+    input usbclk,
+    input bus_reset,
     output [15:0] usbdata,
     input RD,
-    output wire have_pkt_rdy,
+    output reg have_pkt_rdy,
     output reg rx_overrun,
+    input clear_status,
+    // Write/DSP side
+    input rxclk,
+    input reset,  // DSP side reset (used here), do not reset registers
+    input rxstrobe,
     input wire [3:0] channels,
     input wire [15:0] ch_0,
     input wire [15:0] ch_1,
@@ -44,139 +47,191 @@ module rx_buffer
     input wire [15:0] ch_5,
     input wire [15:0] ch_6,
     input wire [15:0] ch_7,
-    input rxclk,
-    input rxstrobe,
-    input clear_status,
+    // Settings, on rxclk also
     input [6:0] serial_addr, input [31:0] serial_data, input serial_strobe,
-    output [15:0] debugbus
+    input reset_regs, //Only reset registers
+    output [31:0] debugbus
     );
-
-   wire [15:0] fifodata, fifodata_8;
-   reg [15:0]  fifodata_16;
    
-   wire [11:0] rxfifolevel;
-   wire rx_empty, rx_full;
-
-   wire bypass_hb, want_q;
-   wire [4:0] bitwidth;
-   wire [3:0] bitshift;
+   wire [15:0]           fifodata, fifodata_8;
+   reg [15:0]    fifodata_16;
+   
+   wire [11:0]           rxfifolevel;
+   wire          rx_full;
+   
+   wire          bypass_hb, want_q;
+   wire [4:0]    bitwidth;
+   wire [3:0]    bitshift;
    
    setting_reg #(`FR_RX_FORMAT) sr_rxformat(.clock(rxclk),.reset(reset_regs),
                                            .strobe(serial_strobe),.addr(serial_addr),.in(serial_data),
                                            .out({bypass_hb,want_q,bitwidth,bitshift}));
 
-   // Receive FIFO (ADC --> USB)
+   // USB Read Side of FIFO
+   always @(negedge usbclk)
+     have_pkt_rdy <= (rxfifolevel >= 256);
 
    // 257 Bug Fix
-   reg [8:0] read_count;
+   reg [8:0]     read_count;
    always @(negedge usbclk)
      if(bus_reset)
-       read_count <= #1 9'd0;
-     else if(RD & ~read_count[8])
-       read_count <= #1 read_count + 9'd1;
+       read_count <= 0;
+     else if(RD)
+       read_count <= read_count + 1;
      else
-       read_count <= #1 RD ? read_count : 9'b0;
+       read_count <= 0;
    
-   // Detect overrun
+   // FIFO
+   wire          ch0_in, ch0_out, iq_out;
+   assign        ch0_in = (phase == 1);
+
+   fifo_4k_18 rxfifo 
+     ( // DSP Write Side
+       .data ( {ch0_in, phase[0], fifodata} ),
+       .wrreq (~rx_full & (phase != 0)),
+       .wrclk ( rxclk ),
+       .wrfull ( rx_full ),
+       .wrempty ( ),
+       .wrusedw ( ),
+       // USB Read Side
+       .q ( {ch0_out,iq_out,usbdata} ),
+       .rdreq ( RD & ~read_count[8] ), 
+       .rdclk ( ~usbclk ),
+       .rdfull ( ),
+       .rdempty ( ),
+       .rdusedw ( rxfifolevel ),
+       // Async, shared
+       .aclr ( reset ) );
+
+   // DSP Write Side of FIFO
+   reg [15:0] ch_0_reg;
+   reg [15:0] ch_1_reg;
+   reg [15:0] ch_2_reg;
+   reg [15:0] ch_3_reg;
+   reg [15:0] ch_4_reg;
+   reg [15:0] ch_5_reg;
+   reg [15:0] ch_6_reg;
+   reg [15:0] ch_7_reg;
+
    always @(posedge rxclk)
-     if(reset)
-       rx_overrun <= 1'b0;
-     else if(rxstrobe & (store_next != 0))
-       rx_overrun <= 1'b1;
-     else if(clear_status)
-       rx_overrun <= 1'b0;
+     if (rxstrobe)
+       begin
+         ch_0_reg <= ch_0;
+         ch_1_reg <= ch_1;
+         ch_2_reg <= ch_2;
+         ch_3_reg <= ch_3;
+         ch_4_reg <= ch_4;
+         ch_5_reg <= ch_5;
+         ch_6_reg <= ch_6;
+         ch_7_reg <= ch_7;
+       end
 
-   reg [3:0] store_next;
+   reg [3:0] phase;
    always @(posedge rxclk)
      if(reset)
-       store_next <= #1 4'd0;
-     else if(rxstrobe & (store_next == 0))
-       store_next <= #1 4'd1;
-     else if(~rx_full & (store_next == channels))
-       store_next <= #1 4'd0;
-     else if(~rx_full & (bitwidth == 5'd8) & (store_next == (channels>>1)))
-       store_next <= #1 4'd0;
-     else if(~rx_full & (store_next != 0))
-       store_next <= #1 store_next + 4'd1;
-
+       phase <= 4'd0;
+     else if(phase == 0)
+       begin
+         if(rxstrobe)
+           phase <= 4'd1;
+       end
+     else if(~rx_full)
+       if(phase == ((bitwidth == 5'd8) ? (channels>>1) : channels))
+        phase <= 4'd0;
+       else
+        phase <= phase + 4'd1;
+   
    assign    fifodata = (bitwidth == 5'd8) ? fifodata_8 : fifodata_16;
-
+   
    assign    fifodata_8 = {round_8(top),round_8(bottom)};
    reg [15:0] top,bottom;
-
+   
    function [7:0] round_8;
       input [15:0] in_val;
-
+      
       round_8 = in_val[15:8] + (in_val[15] & |in_val[7:0]);
    endfunction // round_8
       
    always @*
-     case(store_next)
+     case(phase)
        4'd1 : begin
-         bottom = ch_0;
-         top = ch_1;
+         bottom = ch_0_reg;
+         top = ch_1_reg;
        end
        4'd2 : begin
-         bottom = ch_2;
-         top = ch_3;
+         bottom = ch_2_reg;
+         top = ch_3_reg;
        end
        4'd3 : begin
-         bottom = ch_4;
-         top = ch_5;
+         bottom = ch_4_reg;
+         top = ch_5_reg;
        end
        4'd4 : begin
-         bottom = ch_6;
-         top = ch_7;
+         bottom = ch_6_reg;
+         top = ch_7_reg;
        end
        default : begin
          top = 16'hFFFF;
          bottom = 16'hFFFF;
        end
-     endcase // case(store_next)
+     endcase // case(phase)
    
    always @*
-     case(store_next)
-       4'd1 : fifodata_16 = ch_0;
-       4'd2 : fifodata_16 = ch_1;
-       4'd3 : fifodata_16 = ch_2;
-       4'd4 : fifodata_16 = ch_3;
-       4'd5 : fifodata_16 = ch_4;
-       4'd6 : fifodata_16 = ch_5;
-       4'd7 : fifodata_16 = ch_6;
-       4'd8 : fifodata_16 = ch_7;
+     case(phase)
+       4'd1 : fifodata_16 = ch_0_reg;
+       4'd2 : fifodata_16 = ch_1_reg;
+       4'd3 : fifodata_16 = ch_2_reg;
+       4'd4 : fifodata_16 = ch_3_reg;
+       4'd5 : fifodata_16 = ch_4_reg;
+       4'd6 : fifodata_16 = ch_5_reg;
+       4'd7 : fifodata_16 = ch_6_reg;
+       4'd8 : fifodata_16 = ch_7_reg;
        default : fifodata_16 = 16'hFFFF;
-     endcase // case(store_next)
+     endcase // case(phase)
    
-   fifo_4k rxfifo 
-     ( .data ( fifodata ),
-       .wrreq (~rx_full & (store_next != 0)),
-       .wrclk ( rxclk ),
+   // Detect overrun
+   reg clear_status_dsp, rx_overrun_dsp;
+   always @(posedge rxclk)
+     clear_status_dsp <= clear_status;
 
-       .q ( usbdata ),
-       .rdreq ( RD & ~read_count[8] ), 
-       .rdclk ( ~usbclk ),
-       
-       .aclr ( reset ),  // This one is asynchronous, so we can use either reset
-       
-       .rdempty ( rx_empty ),
-       .rdusedw ( rxfifolevel ),
-       .wrfull ( rx_full ),
-       .wrusedw (  )
-       );
+   always @(negedge usbclk)
+     rx_overrun <= rx_overrun_dsp;
+
+   always @(posedge rxclk)
+     if(reset)
+       rx_overrun_dsp <= 1'b0;
+     else if(rxstrobe & (phase != 0))
+       rx_overrun_dsp <= 1'b1;
+     else if(clear_status_dsp)
+       rx_overrun_dsp <= 1'b0;
+
+   // Debug bus
+   //
+   // 15:0  rxclk  domain => TXA 15:0
+   // 31:16 usbclk domain => RXA 15:0
    
-   assign have_pkt_rdy = (rxfifolevel >= 256);
+   assign debugbus[0]     = reset;
+   assign debugbus[1]     = reset_regs;
+   assign debugbus[2]     = rxstrobe;
+   assign debugbus[6:3]   = channels;
+   assign debugbus[7]     = rx_full;
+   assign debugbus[11:8]  = phase;
+   assign debugbus[12]    = ch0_in;
+   assign debugbus[13]    = clear_status_dsp;
+   assign debugbus[14]    = rx_overrun_dsp;
+   assign debugbus[15]    = rxclk;
 
-   // Debugging Aids
-   assign debugbus[0] = RD;
-   assign debugbus[1] = rx_overrun;
-   assign debugbus[2] = read_count[8];
-   assign debugbus[3] = rx_full;
-   assign debugbus[4] = rxstrobe;
-   assign debugbus[5] = usbclk;
-   assign debugbus[6] = have_pkt_rdy;
-   assign debugbus[10:7] = store_next;
-   //assign debugbus[15:11] = rxfifolevel[4:0];
-   assign debugbus[15:11] = bitwidth;
+   assign debugbus[16]    = bus_reset;   
+   assign debugbus[17]    = RD;
+   assign debugbus[18]    = have_pkt_rdy;
+   assign debugbus[19]    = rx_overrun;
+   assign debugbus[20]    = read_count[0];
+   assign debugbus[21]    = read_count[8];
+   assign debugbus[22]    = ch0_out;
+   assign debugbus[23]    = iq_out;
+   assign debugbus[24]    = clear_status;
+   assign debugbus[30:25] = 0;   
+   assign debugbus[31]    = usbclk;
    
 endmodule // rx_buffer