discuss-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Discuss-gnuradio] Fewer than 8 bits per sample FPGA support


From: Peter Monta
Subject: Re: [Discuss-gnuradio] Fewer than 8 bits per sample FPGA support
Date: Sun, 04 Mar 2007 01:33:08 -0800
User-agent: Thunderbird 1.5.0.9 (X11/20070104)

Eric Blossom wrote:


I think that you're really going to want a configurable barrel
shifter -- to get the bits where you want them -- then pick them off with
round_X or round_X_nearest_even.

OK, the attached rx_buffer.v includes a barrel shifter in bit_pack.v;
I see this was anticipated with the bitwidth and bitshift parameters.
Except for the 1-bit case, the user is going to have to do some AGC
anyway, so the exact position of the bits is not too critical so long as
it's sufficiently out of the noise and sufficient analog gain is available,
but it doesn't hurt to have full support, I guess.

I've run the modified FPGA and verified that the USB data rates
are as expected using test_usrp_standard_rx and various
widths (1, 2, 4, 8, 16).  A couple of snags:  first, the sanity
check in rx_format_is_valid() (lib/usrp_standard.cc) has to go;
second, there seems to be no "raw" support in gr-usrp:  I'd
prefer that rx_cfile.py just dump exactly what comes over the
USB bus instead of converting to shorts or floats.  The
test_usrp_standard_rx app comes close to what I want, but
it doesn't seem to have daughterboard intelligence, so I can't
set gain properly.  Finally, it would be good to have support
for a decimation ratio of 2 (just the halfband filter) and 1
(no filtering).

I'd eventually like to dump to disk 2-bit samples at 32 Ms/s complex
using two dbs_rx cards, which should just fit within the 32 MByte/sec
USB limit.  This is for a dual-frequency GPS application (L1/L2C at first,
but the USRP provides enough bandwidth for the wider P/Y-code signals
as well).  I'm hoping the dbs_rx's close-in phase noise is low enough
to allow a small carrier-loop bandwidth---are there any measurements
I can look at?

Please let me know if anything else is needed for the patch.
There's a testbench for bit_pack.v I can send along if you like.
One possible issue is synchronization, to make sure that the
channels are properly distributed within the 16 bits after
changing width.

Cheers,
Peter Monta

// -*- verilog -*-
//
//  USRP - Universal Software Radio Peripheral
//
//  Copyright (C) 2003 Matt Ettus
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin Street, Boston, MA  02110-1301  USA
//

// Interface to Cypress FX2 bus
// A packet is 512 Bytes.  Each fifo line is 2 bytes
// Fifo has 1024 or 2048 lines

`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
    output [15:0] usbdata,
    input RD,
    output wire have_pkt_rdy,
    output reg rx_overrun,
    input wire [3:0] channels,
    input wire [15:0] ch_0,
    input wire [15:0] ch_1,
    input wire [15:0] ch_2,
    input wire [15:0] ch_3,
    input wire [15:0] ch_4,
    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,
    input [6:0] serial_addr, input [31:0] serial_data, input serial_strobe,
    output [15:0] debugbus
    );

   reg [15:0] fifodata;
   wire [15:0] bitpack_data;
   
   wire [11:0] rxfifolevel;
   wire rx_empty, bp_avail, bp_srdy;

   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)

   // 257 Bug Fix
   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;
     else
       read_count <= #1 RD ? read_count : 9'b0;
   
   // Detect overrun
   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;

   reg [3:0] store_next;
   always @(posedge rxclk)
     if(reset)
       store_next <= #1 4'd0;
     else if(rxstrobe & (store_next == 0))
       store_next <= #1 4'd1;
     else if(bp_avail & (store_next == channels))
       store_next <= #1 4'd0;
     else if(bp_avail & (store_next != 0))
       store_next <= #1 store_next + 4'd1;

   always @*
     case(store_next)
       4'd1 : fifodata = ch_0;
       4'd2 : fifodata = ch_1;
       4'd3 : fifodata = ch_2;
       4'd4 : fifodata = ch_3;
       4'd5 : fifodata = ch_4;
       4'd6 : fifodata = ch_5;
       4'd7 : fifodata = ch_6;
       4'd8 : fifodata = ch_7;
       default : fifodata = 16'hFFFF;
     endcase // case(store_next)
   
   bit_pack bitpack
     ( .clk ( rxclk ),
       .reset ( reset ),

       .in ( fifodata ),
       .in_srdy ( bp_avail & (store_next != 0) ),
       .in_drdy ( bp_avail ),
       .n ( bitwidth ),
       .shift ( bitshift ),

       .out ( bitpack_data ),
       .out_srdy ( bp_srdy ),
       .out_drdy ( ~rx_full )
       );

   fifo_4k rxfifo 
     ( .data ( bitpack_data ),
       .wrreq ( ~rx_full & bp_srdy ),
       .wrclk ( rxclk ),

       .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 (  )
       );
   
   assign have_pkt_rdy = (rxfifolevel >= 256);

   // 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;
   
endmodule // rx_buffer

// -*- verilog -*-
//
//  USRP - Universal Software Radio Peripheral
//
//  Copyright (C) 2003 Matt Ettus
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin Street, Boston, MA  02110-1301  USA
//


// This module transforms an input stream of 16-bit words into an
// output stream of packed n-bit words where n is 16, 8, 4, 2, or 1.
//
// The bit field from the input words is selectable with the "shift"
// port, which tells how far to shift the input right before extracting
// n LSBs:  out_fragment = (in>>shift) & ((1<<n)-1).  The sequence
// of out_fragments is packed bigendian into the output 16-bit payload.
//
// Handshaking is with a synchronous dataflow convention in which
// in_srdy indicates that an input word is available and in_drdy indicates
// that the bit_pack module can accept an input word.  Thus, on any given
// cycle, a word is transferred over the input interface if and only if
// both in_srdy and in_drdy are asserted.  Similarly, out_srdy indicates
// that the bit_pack module has an output word available and out_drdy
// indicates that the downstream entity can accept an output word;
// an output word is transferred if and only if both are asserted.
//
// Copyright 2007 Peter Monta

module bit_pack
  ( input clk,
    input reset,
    input [15:0] in,
    input in_srdy,
    output in_drdy,
    input [4:0] n,
    input [3:0] shift,
    output [15:0] out,
    output out_srdy,
    input out_drdy
  );

  reg [15:0] out1;
  reg [4:0] b1;

  wire in_en = in_srdy && in_drdy;
  wire out_en = out_srdy && out_drdy;

  wire [4:0] b = in_en ? (b1 + n) : b1;

  assign in_drdy = (b1<5'd16) && out_drdy;
  assign out_srdy = (b>=5'd16);

  reg [15:0] mask;

  assign out = (out1<<n) | ((in>>shift) & mask);

  always @*
    case (n)
      5'd1: mask = 16'b0000000000000001;
      5'd2: mask = 16'b0000000000000011;
      5'd4: mask = 16'b0000000000001111;
      5'd8: mask = 16'b0000000011111111;
      5'd16: mask = 16'b1111111111111111;
      default: mask = 16'd0;
    endcase

  always @(posedge clk)
    if (reset) begin
      out1 <= #1 0;
      b1 <= #1 0;
    end else
      if (in_en) begin
        out1 <= #1 out;
        b1 <= #1 out_en ? 0 : b;
      end

endmodule // bit_pack

reply via email to

[Prev in Thread] Current Thread [Next in Thread]