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
_______________________________________________ Discuss-gnuradio mailing list Discuss-gnuradio@gnu.org http://lists.gnu.org/mailman/listinfo/discuss-gnuradio