From c6baf9d41d452965fe6af642b61b2bb823dcf9ea Mon Sep 17 00:00:00 2001 From: jcorgan Date: Wed, 25 Apr 2007 23:38:21 +0000 Subject: [PATCH] Merged r5033:5116 from developer branch jcorgan/snd, with minor edits. Trunk passes distcheck. Adds gr-sounder component, see gr-sounder/README. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@5117 221aa14e-8319-0410-a670-987f0aec2ac5 --- config/Makefile.am | 1 + config/grc_gr_sounder.m4 | 50 ++ configure.ac | 1 + gr-sounder/Makefile.am | 24 + gr-sounder/README | 61 +++ gr-sounder/doc/Makefile.am | 23 + gr-sounder/src/Makefile.am | 24 + gr-sounder/src/fpga/Makefile.am | 24 + gr-sounder/src/fpga/lib/Makefile.am | 30 ++ gr-sounder/src/fpga/lib/dac_interface.v | 60 +++ gr-sounder/src/fpga/lib/dacpll.v | 291 ++++++++++++ gr-sounder/src/fpga/lib/lfsr.v | 46 ++ gr-sounder/src/fpga/lib/lfsr_constants.v | 51 ++ gr-sounder/src/fpga/lib/sounder.v | 86 ++++ gr-sounder/src/fpga/lib/sounder_rx.v | 84 ++++ gr-sounder/src/fpga/lib/sounder_tx.v | 45 ++ gr-sounder/src/fpga/rbf/Makefile.am | 44 ++ gr-sounder/src/fpga/rbf/rev2/usrp_sounder.rbf | Bin 0 -> 109446 bytes gr-sounder/src/fpga/rbf/rev4/usrp_sounder.rbf | Bin 0 -> 109446 bytes gr-sounder/src/fpga/top/Makefile.am | 43 ++ gr-sounder/src/fpga/top/config.vh | 22 + gr-sounder/src/fpga/top/usrp_sounder.csf | 444 ++++++++++++++++++ gr-sounder/src/fpga/top/usrp_sounder.esf | 14 + gr-sounder/src/fpga/top/usrp_sounder.psf | 312 ++++++++++++ gr-sounder/src/fpga/top/usrp_sounder.qpf | 29 ++ gr-sounder/src/fpga/top/usrp_sounder.qsf | 392 ++++++++++++++++ gr-sounder/src/fpga/top/usrp_sounder.v | 199 ++++++++ gr-sounder/src/lib/Makefile.am | 22 + gr-sounder/src/python/Makefile.am | 32 ++ gr-sounder/src/python/qa_nothing.py | 0 gr-sounder/src/python/run_tests.in | 10 + gr-sounder/src/python/usrp_sounder.py | 130 +++++ 32 files changed, 2594 insertions(+) create mode 100644 config/grc_gr_sounder.m4 create mode 100644 gr-sounder/Makefile.am create mode 100644 gr-sounder/README create mode 100644 gr-sounder/doc/Makefile.am create mode 100644 gr-sounder/src/Makefile.am create mode 100644 gr-sounder/src/fpga/Makefile.am create mode 100644 gr-sounder/src/fpga/lib/Makefile.am create mode 100644 gr-sounder/src/fpga/lib/dac_interface.v create mode 100644 gr-sounder/src/fpga/lib/dacpll.v create mode 100644 gr-sounder/src/fpga/lib/lfsr.v create mode 100755 gr-sounder/src/fpga/lib/lfsr_constants.v create mode 100644 gr-sounder/src/fpga/lib/sounder.v create mode 100644 gr-sounder/src/fpga/lib/sounder_rx.v create mode 100644 gr-sounder/src/fpga/lib/sounder_tx.v create mode 100644 gr-sounder/src/fpga/rbf/Makefile.am create mode 100755 gr-sounder/src/fpga/rbf/rev2/usrp_sounder.rbf create mode 100755 gr-sounder/src/fpga/rbf/rev4/usrp_sounder.rbf create mode 100644 gr-sounder/src/fpga/top/Makefile.am create mode 100644 gr-sounder/src/fpga/top/config.vh create mode 100644 gr-sounder/src/fpga/top/usrp_sounder.csf create mode 100644 gr-sounder/src/fpga/top/usrp_sounder.esf create mode 100644 gr-sounder/src/fpga/top/usrp_sounder.psf create mode 100644 gr-sounder/src/fpga/top/usrp_sounder.qpf create mode 100755 gr-sounder/src/fpga/top/usrp_sounder.qsf create mode 100644 gr-sounder/src/fpga/top/usrp_sounder.v create mode 100644 gr-sounder/src/lib/Makefile.am create mode 100644 gr-sounder/src/python/Makefile.am create mode 100644 gr-sounder/src/python/qa_nothing.py create mode 100644 gr-sounder/src/python/run_tests.in create mode 100755 gr-sounder/src/python/usrp_sounder.py diff --git a/config/Makefile.am b/config/Makefile.am index 35db62a6..dfe84580 100644 --- a/config/Makefile.am +++ b/config/Makefile.am @@ -46,6 +46,7 @@ m4macros = \ grc_gr_radar.m4 \ grc_gr_radio_astronomy.m4 \ grc_gr_rdf.m4 \ + grc_gr_sounder.m4 \ grc_gr_trellis.m4 \ grc_gr_usrp.m4 \ grc_gr_video_sdl.m4 \ diff --git a/config/grc_gr_sounder.m4 b/config/grc_gr_sounder.m4 new file mode 100644 index 00000000..a821ce4a --- /dev/null +++ b/config/grc_gr_sounder.m4 @@ -0,0 +1,50 @@ +dnl Copyright 2007 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, USA. + +AC_DEFUN([GRC_GR_SOUNDER],[ + GRC_ENABLE([gr-sounder]) + + AC_CONFIG_FILES([ \ + gr-sounder/Makefile \ + gr-sounder/doc/Makefile \ + gr-sounder/src/Makefile \ + gr-sounder/src/fpga/Makefile \ + gr-sounder/src/fpga/top/Makefile \ + gr-sounder/src/fpga/lib/Makefile \ + gr-sounder/src/fpga/rbf/Makefile \ + gr-sounder/src/lib/Makefile \ + gr-sounder/src/python/Makefile \ + gr-sounder/src/python/run_tests + ]) + + passed=yes + # Don't do gr-sounder if usrp skipped + for dir in $skipped_dirs + do + if test x$dir = xusrp; then + AC_MSG_RESULT([Component gr-sounder requires usrp, which is not being built.]) + passed=no + fi + done + + GRC_BUILD_CONDITIONAL([gr-sounder],[ + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_sounder], [chmod +x gr-sounder/src/python/run_tests]) + ]) +]) diff --git a/configure.ac b/configure.ac index 209d9f8b..d718b367 100644 --- a/configure.ac +++ b/configure.ac @@ -221,6 +221,7 @@ GRC_MBLOCK dnl this must come after GRC_PMT GRC_EZDOP GRC_GR_EZDOP dnl this must come after GRC_EZDOP GRC_GR_RDF +GRC_GR_SOUNDER dnl this must come after GRC_USRP GRC_GNURADIO_EXAMPLES dnl must come last # Each component is now either to be built, was skipped, or failed dependencies diff --git a/gr-sounder/Makefile.am b/gr-sounder/Makefile.am new file mode 100644 index 00000000..a5aff222 --- /dev/null +++ b/gr-sounder/Makefile.am @@ -0,0 +1,24 @@ +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = src doc diff --git a/gr-sounder/README b/gr-sounder/README new file mode 100644 index 00000000..ef495f1e --- /dev/null +++ b/gr-sounder/README @@ -0,0 +1,61 @@ +This is a work-in-progress implementation of a m-sequence based channel +sounder for GNU Radio and the USRP. + +At present, only the transmitter is implemented. When completed, you +will be able to place the sounder transmitter at one location, the +sounder receiver at another location, then determine in real-time the +channel impulse and frequency response between them. + +The sounder uses a custom FPGA bitstream that is able to generate and +receive a sounder waveform across a full 32 MHz wide swath of RF spectrum; +the waveform generation and impulse response processing occur in logic in +the USRP FPGA and not in the host PC. This avoids the USB throughput +bottleneck entirely. Unfortunately, there is still roll-off in the AD9862 +digital up-converter interpolation filter that impacts the outer 20% of +bandwidth, but this can be compensated for by measuring and subtracting +out this response during calibration. + +The sounder is based on sending a maximal-length PN code modulated as BPSK +with the supplied center frequency, with a chip-rate of 32 MHz. The +receiver (partially implemented at this time but not working yet) correlates +the received signal across all phases of the PN code and outputs an impulse +response vector. As auto-correlation of an m-sequence is near zero for +any relative phase shift, the actual measured energy at a particular +phase shift is related to the impulse response for that time delay. This +is the same principle used in spread-spectrum RAKE receivers such as are +used with GPS and CDMA. + +The transmitter and receiver are designed to work only with the board in +side A. This may be a standalone LFTX/LFRX or an RFX daughterboard. + +To use, the following script is installed into $prefix/bin: + +usage: usrp_sounder.py [options] + +options: + -h, --help show this help message and exit + -f FREQ, --frequency=FREQ + set frequency to FREQ in Hz, default is 0.0 + -t, --transmit enable sounding transmitter + -r, --receive enable sounding receiver + -d DEGREE, --degree=DEGREE + set souding sequence degree (len=2^degree-1), default + is 16 + -n SAMPLES, --samples=SAMPLES + number of samples to capture on receive, default is + infinite + -l, --loopback enable digital loopback, default is disabled + +To use with an LFTX board, set the center frequency to 16M: + +$ usrp_sounder.py -f 16M -t + +You can vary the m-sequence degree between 1 and 16, which will create +sequence lengths between 1 (DC) and 65535 (1.023 us). This will affect +how frequently the receiver can calculate impulse response vectors (to be +documented as the receiver is completed.) + +Johnathan Corgan +Corgan Enterprises LLC +jcorgan@corganenterprises.com +4/25/07 diff --git a/gr-sounder/doc/Makefile.am b/gr-sounder/doc/Makefile.am new file mode 100644 index 00000000..623c403e --- /dev/null +++ b/gr-sounder/doc/Makefile.am @@ -0,0 +1,23 @@ +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + diff --git a/gr-sounder/src/Makefile.am b/gr-sounder/src/Makefile.am new file mode 100644 index 00000000..71787e84 --- /dev/null +++ b/gr-sounder/src/Makefile.am @@ -0,0 +1,24 @@ +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = fpga lib python diff --git a/gr-sounder/src/fpga/Makefile.am b/gr-sounder/src/fpga/Makefile.am new file mode 100644 index 00000000..f4cd4fd4 --- /dev/null +++ b/gr-sounder/src/fpga/Makefile.am @@ -0,0 +1,24 @@ +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = top lib rbf diff --git a/gr-sounder/src/fpga/lib/Makefile.am b/gr-sounder/src/fpga/lib/Makefile.am new file mode 100644 index 00000000..450981f1 --- /dev/null +++ b/gr-sounder/src/fpga/lib/Makefile.am @@ -0,0 +1,30 @@ +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = \ + dac_interface.v \ + dacpll.v \ + sounder.v \ + sounder_rx.v \ + sounder_tx.v + diff --git a/gr-sounder/src/fpga/lib/dac_interface.v b/gr-sounder/src/fpga/lib/dac_interface.v new file mode 100644 index 00000000..b97ffa77 --- /dev/null +++ b/gr-sounder/src/fpga/lib/dac_interface.v @@ -0,0 +1,60 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2007 Corgan Enterprises LLC +// +// 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 +// + +`include "../top/config.vh" + +module dac_interface(clk_i,rst_i,ena_i,strobe_i,tx_i_i,tx_q_i,tx_data_o,tx_sync_o); + input clk_i; + input rst_i; + input ena_i; + input strobe_i; + + input [15:0] tx_i_i; + input [15:0] tx_q_i; + + output [15:0] tx_data_o; + output tx_sync_o; + +`ifdef TX_RATE_MAX + wire clk128; + reg clk64_d; + reg [15:0] tx_data_o; + + // Create a 128 MHz clock + dacpll pll128(.areset(rst_i),.inclk0(clk_i),.c0(clk128)); + + // Register the clk64 clock in the clk128 domain + always @(posedge clk128) + clk64_d <= clk_i; + + // Register the tx data in the clk128 domain + always @(posedge clk128) + tx_data_o <= clk64_d ? tx_i_i : tx_q_i; + + assign tx_sync_o = clk64_d; + + +`else // !`ifdef TX_RATE_MAX + assign tx_data_o = strobe_i ? tx_q_i : tx_i_i; + assign tx_sync_o = strobe_i; +`endif // !`ifdef TX_RATE_MAX + +endmodule // dac_interface diff --git a/gr-sounder/src/fpga/lib/dacpll.v b/gr-sounder/src/fpga/lib/dacpll.v new file mode 100644 index 00000000..25f584f4 --- /dev/null +++ b/gr-sounder/src/fpga/lib/dacpll.v @@ -0,0 +1,291 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: dacpll.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 7.0 Build 33 02/05/2007 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2007 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module dacpll ( + areset, + inclk0, + c0); + + input areset; + input inclk0; + output c0; + + wire [5:0] sub_wire0; + wire [0:0] sub_wire4 = 1'h0; + wire [0:0] sub_wire1 = sub_wire0[0:0]; + wire c0 = sub_wire1; + wire sub_wire2 = inclk0; + wire [1:0] sub_wire3 = {sub_wire4, sub_wire2}; + + altpll altpll_component ( + .inclk (sub_wire3), + .areset (areset), + .clk (sub_wire0), + .activeclock (), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b1), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbout (), + .locked (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.clk0_divide_by = 1, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 2, + altpll_component.clk0_phase_shift = "0000", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 15625, + altpll_component.intended_device_family = "Cyclone", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_USED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_UNUSED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_UNUSED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_CUSTOM STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "e0" +// Retrieval info: PRIVATE: DEVICE_FAMILY NUMERIC "11" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: DEV_FAMILY STRING "Cyclone" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "64.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "0" +// Retrieval info: PRIVATE: LOCK_LOSS_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "512.000" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "2" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "ns" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "2" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "15625" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: USED_PORT: @clk 0 0 6 0 OUTPUT_CLK_EXT VCC "@clk[5..0]" +// Retrieval info: USED_PORT: @extclk 0 0 4 0 OUTPUT_CLK_EXT VCC "@extclk[3..0]" +// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL dacpll.v TRUE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL dacpll.ppf TRUE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL dacpll.inc FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL dacpll.cmp FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL dacpll.bsf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL dacpll_inst.v TRUE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL dacpll_bb.v TRUE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL dacpll_waveforms.html TRUE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL dacpll_wave*.jpg FALSE FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/gr-sounder/src/fpga/lib/lfsr.v b/gr-sounder/src/fpga/lib/lfsr.v new file mode 100644 index 00000000..6ae967ba --- /dev/null +++ b/gr-sounder/src/fpga/lib/lfsr.v @@ -0,0 +1,46 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2007 Corgan Enterprises LLC +// +// 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 +// + +module lfsr(clk_i,rst_i,ena_i,strobe_i,mask_i,pn_o); + parameter width = 16; + + input clk_i; + input rst_i; + input ena_i; + input strobe_i; + input [width-1:0] mask_i; + + output pn_o; + + reg [width-1:0] shifter; + + wire parity = ^(shifter & mask_i); + + always @(posedge clk_i) + if (rst_i | ~ena_i) + shifter <= 1; + else + if (strobe_i) + shifter <= {shifter[width-2:0],parity}; + + assign pn_o = shifter[0]; + +endmodule // lfsr diff --git a/gr-sounder/src/fpga/lib/lfsr_constants.v b/gr-sounder/src/fpga/lib/lfsr_constants.v new file mode 100755 index 00000000..79fcb1a2 --- /dev/null +++ b/gr-sounder/src/fpga/lib/lfsr_constants.v @@ -0,0 +1,51 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2007 Corgan Enterprises LLC +// +// 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 +// + +module lfsr_constants(degree_i,mask_o,len_o); + input wire [4:0] degree_i; + output reg [15:0] mask_o; + output wire [15:0] len_o; + + assign len_o = (16'b1 << degree_i) - 1; + + always @* + case (degree_i) + 5'd00: mask_o = 16'h0000; + 5'd01: mask_o = 16'h0001; + 5'd02: mask_o = 16'h0003; + 5'd03: mask_o = 16'h0005; + 5'd04: mask_o = 16'h0009; + 5'd05: mask_o = 16'h0012; + 5'd06: mask_o = 16'h0021; + 5'd07: mask_o = 16'h0041; + 5'd08: mask_o = 16'h008E; + 5'd09: mask_o = 16'h0108; + 5'd10: mask_o = 16'h0204; + 5'd11: mask_o = 16'h0402; + 5'd12: mask_o = 16'h0829; + 5'd13: mask_o = 16'h100D; + 5'd14: mask_o = 16'h2015; + 5'd15: mask_o = 16'h4001; + 5'd16: mask_o = 16'h8016; + default: mask_o = 16'h0000; + endcase // case(degree_i) + +endmodule // lfsr_constants diff --git a/gr-sounder/src/fpga/lib/sounder.v b/gr-sounder/src/fpga/lib/sounder.v new file mode 100644 index 00000000..ea4007cb --- /dev/null +++ b/gr-sounder/src/fpga/lib/sounder.v @@ -0,0 +1,86 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2007 Corgan Enterprises LLC +// +// 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 +// + +`include "../../../../usrp/firmware/include/fpga_regs_common.v" +`include "../../../../usrp/firmware/include/fpga_regs_standard.v" + +module sounder(clk_i,saddr_i,sdata_i,s_strobe_i,tx_rst_i,tx_enable_i,tx_strobe_i, + tx_dac_i_o,tx_dac_q_o, + rx_rst_i,rx_enable_i,rx_strobe_i,rx_strobe_o, + rx_adc_i_i,rx_adc_q_i,rx_imp_i_o,rx_imp_q_o); + + // System interface + input clk_i; // Master clock @ 64 MHz + input [6:0] saddr_i; // Configuration bus address + input [31:0] sdata_i; // Configuration bus data + input s_strobe_i; // Configuration bus write + + // Transmit subsystem + input tx_rst_i; // Independent subsystem reset + input tx_enable_i; // Turn on transmitter functionality + input tx_strobe_i; // Generate an transmitter output sample + output [15:0] tx_dac_i_o; // I channel transmitter output to DAC + output [15:0] tx_dac_q_o; // Q channel transmitter output to DAC + + // Receive subsystem + input rx_rst_i; // Independent subsystem reset + input rx_enable_i; // Turn on receiver functionality + input rx_strobe_i; // Indicates receive sample ready from ADC + output rx_strobe_o; // Indicates output samples ready for Rx FIFO + input [15:0] rx_adc_i_i; // I channel input from ADC + input [15:0] rx_adc_q_i; // Q channel input from ADC + output [15:0] rx_imp_i_o; // I channel impulse response to Rx FIFO + output [15:0] rx_imp_q_o; // Q channel impulse response to Rx FIFO + + // Configuration + wire [4:0] degree; // LFSR register length + wire [15:0] mask; // LFSR parity mask + wire [15:0] len; // PN code sequence length + wire loopback; // Enable digital loopback + + // Loopback implementation + wire [15:0] tx_i, tx_q, rx_i, rx_q; // Internal transmit and receive data bus + + assign tx_dac_i_o = loopback ? 16'b0 : tx_i; + assign tx_dac_q_o = loopback ? 16'b0 : tx_q; + assign rx_i = loopback ? tx_i : rx_adc_i_i; + assign rx_q = loopback ? tx_q : rx_adc_q_i; + + setting_reg #(`FR_USER_0) sr_lfsr_degree + ( .clock(clk_i),.reset(1'b0),.strobe(s_strobe_i),.addr(saddr_i),.in(sdata_i),.out(degree) ); + + setting_reg #(`FR_USER_1) sr_mode + ( .clock(clk_i),.reset(1'b0),.strobe(s_strobe_i),.addr(saddr_i),.in(sdata_i), + .out({loopback}) ); + + lfsr_constants constants(.degree_i(degree),.mask_o(mask),.len_o(len)); + + sounder_tx transmitter + ( .clk_i(clk_i),.rst_i(tx_rst_i),.ena_i(tx_enable_i),.strobe_i(tx_strobe_i),.mask_i(mask), + .tx_i_o(tx_i),.tx_q_o(tx_q) ); + + sounder_rx receiver + ( .clk_i(clk_i),.rst_i(rx_rst_i),.ena_i(rx_enable_i), + .rx_strobe_i(rx_strobe_i),.tx_strobe_i(tx_strobe_i),.mask_i(mask),.len_i(len), + .rx_in_i_i(rx_i),.rx_in_q_i(rx_q),.rx_i_o(rx_imp_i_o),.rx_q_o(rx_imp_q_o), + .rx_strobe_o(rx_strobe_o) ); + +endmodule // sounder diff --git a/gr-sounder/src/fpga/lib/sounder_rx.v b/gr-sounder/src/fpga/lib/sounder_rx.v new file mode 100644 index 00000000..b7c5f487 --- /dev/null +++ b/gr-sounder/src/fpga/lib/sounder_rx.v @@ -0,0 +1,84 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2007 Corgan Enterprises LLC +// +// 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 +// + +module sounder_rx(clk_i,rst_i,ena_i,rx_strobe_i,tx_strobe_i,mask_i,len_i, + rx_in_i_i,rx_in_q_i,rx_i_o,rx_q_o,rx_strobe_o); + + input clk_i; // Master clock + input rst_i; // Subsystem reset + input ena_i; // Subsystem enable + input rx_strobe_i; // Strobe every received sample + input tx_strobe_i; // Strobe every transmitted sample + + input [15:0] mask_i; // PN code LFSR mask + input [15:0] len_i; // PN code LFSR sequence length + input [15:0] rx_in_i_i; // I channel on receive + input [15:0] rx_in_q_i; // Q channel on receive + + output [15:0] rx_i_o; // I channel of impulse response + output [15:0] rx_q_o; // Q channel of impulse response + output rx_strobe_o; // Impulse response value ready + + // LFSR phase counter + reg [15:0] count; + wire cycle = (count == (len_i - 1)); + + always @(posedge clk_i) + if (rst_i | ~ena_i) + count <= 16'b0; + else + if (cycle) + count <= 16'b0; + else + count <= count + 16'b1; + + // Retard LFSR phase once per cycle + wire lfsr_strobe = (tx_strobe_i & ~cycle); + + // Recreate local reference of transmitted PN code + wire pn; + lfsr reference + ( .clk_i(clk_i),.rst_i(rst_i),.ena_i(ena_i),.strobe_i(lfsr_strobe),.mask_i(mask_i),.pn_o(pn) ); + + wire [31:0] rx_i_ext, rx_q_ext; + sign_extend #(16,32) i_extend(rx_in_i_i, rx_i_ext); + sign_extend #(16,32) q_extend(rx_in_q_i, rx_q_ext); + + reg [31:0] accum; + always @(posedge clk_i) + if (rst_i | ~ena_i) + accum <= 32'b0; + else + if (rx_strobe_i) + if (cycle) + accum <= 32'b0; + else + if (pn) + accum <= accum + rx_i_ext; + else + accum <= accum - rx_i_ext; + + assign rx_i_o = accum[31:16]; + assign rx_q_o = accum[15:0]; + assign rx_strobe_o = rx_strobe_i & cycle; + +endmodule // sounder_rx + diff --git a/gr-sounder/src/fpga/lib/sounder_tx.v b/gr-sounder/src/fpga/lib/sounder_tx.v new file mode 100644 index 00000000..d5300fec --- /dev/null +++ b/gr-sounder/src/fpga/lib/sounder_tx.v @@ -0,0 +1,45 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2007 Corgan Enterprises LLC +// +// 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 +// + +`include "../../../../usrp/firmware/include/fpga_regs_common.v" +`include "../../../../usrp/firmware/include/fpga_regs_standard.v" + +`define MAX_VALUE 16'h7FFF // 2s complement +`define MIN_VALUE 16'h8000 + +module sounder_tx(clk_i,rst_i,ena_i,strobe_i,mask_i,tx_i_o,tx_q_o); + input clk_i; + input rst_i; + input ena_i; + input strobe_i; + input [15:0] mask_i; + output [15:0] tx_i_o; + output [15:0] tx_q_o; + + wire pn; + + lfsr pn_code + ( .clk_i(clk_i),.rst_i(rst_i),.ena_i(ena_i),.strobe_i(strobe_i),.mask_i(mask_i),.pn_o(pn) ); + + assign tx_i_o = pn ? `MAX_VALUE : `MIN_VALUE; // Bipolar + assign tx_q_o = 16'b0; + +endmodule // sounder_tx diff --git a/gr-sounder/src/fpga/rbf/Makefile.am b/gr-sounder/src/fpga/rbf/Makefile.am new file mode 100644 index 00000000..5a8b709d --- /dev/null +++ b/gr-sounder/src/fpga/rbf/Makefile.am @@ -0,0 +1,44 @@ +# +# Copyright 2005,2006,2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + +datadir = $(prefix)/share/usrp + +rbfs = \ + rev2/usrp_sounder.rbf \ + rev4/usrp_sounder.rbf + +EXTRA_DIST = \ + $(rbfs) + + +install-data-local: + @for file in $(rbfs); do \ + echo "$(INSTALL_DATA) $(srcdir)/$$file $(DESTDIR)$(datadir)/$$file"; \ + $(INSTALL_DATA) $(srcdir)/$$file $(DESTDIR)$(datadir)/$$file; \ + done + +uninstall-local: + @for file in $(rbfs); do \ + echo "$(RM) $(DESTDIR)$(datadir)/$$file"; \ + $(RM) $(DESTDIR)$(datadir)/$$file; \ + done diff --git a/gr-sounder/src/fpga/rbf/rev2/usrp_sounder.rbf b/gr-sounder/src/fpga/rbf/rev2/usrp_sounder.rbf new file mode 100755 index 0000000000000000000000000000000000000000..47a0c98fb527f741c17b15cf2564c2303713f80f GIT binary patch literal 109446 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

MB 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

MB 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" +set_global_assignment -name FAMILY Cyclone +set_global_assignment -name CYCLONE_OPTIMIZATION_TECHNIQUE BALANCED +set_global_assignment -name STRATIX_OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name APEX20K_OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name TOP_LEVEL_ENTITY usrp_sounder +set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name USER_LIBRARIES "h:\\gnuradio\\trunk\\usrp\\fpga\\megacells" +set_global_assignment -name AUTO_ENABLE_SMART_COMPILE ON + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP1C12Q240C8 +set_global_assignment -name CYCLONE_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED" +set_global_assignment -name OPTIMIZE_HOLD_TIMING OFF +set_global_assignment -name OPTIMIZE_TIMING "NORMAL COMPILATION" +set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC OFF +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION OFF +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING OFF +set_global_assignment -name IO_PLACEMENT_OPTIMIZATION OFF +set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT NORMAL +set_global_assignment -name INC_PLC_MODE OFF +set_global_assignment -name ROUTING_BACK_ANNOTATION_MODE OFF +set_instance_assignment -name IO_STANDARD LVTTL -to usbdata[12] +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD LVTTL +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 + +# Timing Analysis Assignments +# =========================== +set_global_assignment -name MAX_SCC_SIZE 50 + +# EDA Netlist Writer Assignments +# ============================== +set_global_assignment -name EDA_SIMULATION_TOOL "" +set_global_assignment -name EDA_TIMING_ANALYSIS_TOOL "" +set_global_assignment -name EDA_BOARD_DESIGN_TOOL "" +set_global_assignment -name EDA_FORMAL_VERIFICATION_TOOL "" +set_global_assignment -name EDA_RESYNTHESIS_TOOL "" + +# Assembler Assignments +# ===================== +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name RESERVE_ALL_UNUSED_PINS_NO_OUTPUT_GND "AS INPUT TRI-STATED" +set_global_assignment -name AUTO_RESTART_CONFIGURATION OFF + +# Simulator Assignments +# ===================== +set_global_assignment -name START_TIME "0 ns" +set_global_assignment -name GLITCH_INTERVAL "1 ns" + +# Design Assistant Assignments +# ============================ +set_global_assignment -name DRC_REPORT_TOP_FANOUT OFF +set_global_assignment -name DRC_REPORT_FANOUT_EXCEEDING OFF +set_global_assignment -name ASSG_CAT OFF +set_global_assignment -name ASSG_RULE_MISSING_FMAX OFF +set_global_assignment -name ASSG_RULE_MISSING_TIMING OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_ASYN_RAM OFF +set_global_assignment -name CLK_CAT OFF +set_global_assignment -name CLK_RULE_COMB_CLOCK OFF +set_global_assignment -name CLK_RULE_INV_CLOCK OFF +set_global_assignment -name CLK_RULE_GATING_SCHEME OFF +set_global_assignment -name CLK_RULE_INPINS_CLKNET OFF +set_global_assignment -name CLK_RULE_CLKNET_CLKSPINES OFF +set_global_assignment -name CLK_RULE_MIX_EDGES OFF +set_global_assignment -name RESET_CAT OFF +set_global_assignment -name RESET_RULE_INPINS_RESETNET OFF +set_global_assignment -name RESET_RULE_UNSYNCH_EXRESET OFF +set_global_assignment -name RESET_RULE_IMSYNCH_EXRESET OFF +set_global_assignment -name RESET_RULE_COMB_ASYNCH_RESET OFF +set_global_assignment -name RESET_RULE_UNSYNCH_ASYNCH_DOMAIN OFF +set_global_assignment -name RESET_RULE_IMSYNCH_ASYNCH_DOMAIN OFF +set_global_assignment -name TIMING_CAT OFF +set_global_assignment -name TIMING_RULE_SHIFT_REG OFF +set_global_assignment -name TIMING_RULE_COIN_CLKEDGE OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_COMB_DRIVES_RAM_WE OFF +set_global_assignment -name NONSYNCHSTRUCT_CAT OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_COMBLOOP OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_REG_LOOP OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_DELAY_CHAIN OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_RIPPLE_CLK OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_ILLEGAL_PULSE_GEN OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_MULTI_VIBRATOR OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_SRLATCH OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_LATCH_UNIDENTIFIED OFF +set_global_assignment -name SIGNALRACE_CAT OFF +set_global_assignment -name ACLK_CAT OFF +set_global_assignment -name ACLK_RULE_NO_SZER_ACLK_DOMAIN OFF +set_global_assignment -name ACLK_RULE_SZER_BTW_ACLK_DOMAIN OFF +set_global_assignment -name ACLK_RULE_IMSZER_ADOMAIN OFF +set_global_assignment -name HCPY_CAT OFF +set_global_assignment -name HCPY_VREF_PINS OFF + +# SignalTap II Assignments +# ======================== +set_global_assignment -name HUB_ENTITY_NAME SLD_HUB +set_global_assignment -name HUB_INSTANCE_NAME SLD_HUB_INST +set_global_assignment -name ENABLE_SIGNALTAP OFF + +# LogicLock Region Assignments +# ============================ +set_global_assignment -name LOGICLOCK_INCREMENTAL_COMPILE_ASSIGNMENT OFF + +# ----------------- +# start CLOCK(SCLK) + + # Timing Assignments + # ================== +set_global_assignment -name DUTY_CYCLE 50 -section_id SCLK +set_global_assignment -name FMAX_REQUIREMENT "1 MHz" -section_id SCLK + +# end CLOCK(SCLK) +# --------------- + +# ----------------------- +# start CLOCK(master_clk) + + # Timing Assignments + # ================== +set_global_assignment -name DUTY_CYCLE 50 -section_id master_clk +set_global_assignment -name FMAX_REQUIREMENT "64 MHz" -section_id master_clk + +# end CLOCK(master_clk) +# --------------------- + +# ------------------- +# start CLOCK(usbclk) + + # Timing Assignments + # ================== +set_global_assignment -name DUTY_CYCLE 50 -section_id usbclk +set_global_assignment -name FMAX_REQUIREMENT "48 MHz" -section_id usbclk + +# end CLOCK(usbclk) +# ----------------- + +# ---------------------- +# start ENTITY(usrp_sounder) + + # Timing Assignments + # ================== +set_instance_assignment -name CLOCK_SETTINGS SCLK -to SCLK +set_instance_assignment -name CLOCK_SETTINGS usbclk -to usbclk +set_instance_assignment -name CLOCK_SETTINGS master_clk -to master_clk + +# end ENTITY(usrp_sounder) +# -------------------- + +set_instance_assignment -name PARTITION_HIERARCHY no_file_for_top_partition -to | -section_id Top +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top + +set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/sign_extend.v +set_global_assignment -name VERILOG_FILE ../lib/lfsr_constants.v +set_global_assignment -name VERILOG_FILE ../lib/sounder.v +set_global_assignment -name VERILOG_FILE ../lib/lfsr.v +set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/atr_delay.v +set_global_assignment -name VERILOG_FILE ../lib/dac_interface.v +set_global_assignment -name VERILOG_FILE ../lib/dacpll.v +set_global_assignment -name VERILOG_FILE ../lib/sounder_rx.v +set_global_assignment -name VERILOG_FILE ../lib/sounder_tx.v +set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/rx_buffer.v +set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/setting_reg.v +set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/strobe_gen.v +set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/clk_divider.v +set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/bidir_reg.v +set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/adc_interface.v +set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/gen_sync.v +set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/io_pins.v +set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/master_control.v +set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/rssi.v +set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/rx_dcoffset.v +set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/serial_io.v +set_global_assignment -name VERILOG_FILE usrp_sounder.v \ No newline at end of file diff --git a/gr-sounder/src/fpga/top/usrp_sounder.v b/gr-sounder/src/fpga/top/usrp_sounder.v new file mode 100644 index 00000000..05b71bbb --- /dev/null +++ b/gr-sounder/src/fpga/top/usrp_sounder.v @@ -0,0 +1,199 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003,2004 Matt Ettus +// Copyright (C) 2007 Corgan Enterprises LLC +// +// 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 +// + +// Top level module for a full setup with DUCs and DDCs + +// Define DEBUG_OWNS_IO_PINS if we're using the daughterboard i/o pins +// for debugging info. NB, This can kill the m'board and/or d'board if you +// have anything except basic d'boards installed. + +// Uncomment the following to include optional circuitry + +module usrp_sounder +(output MYSTERY_SIGNAL, + input master_clk, + input SCLK, + input SDI, + inout SDO, + input SEN_FPGA, + + input FX2_1, + output FX2_2, + output FX2_3, + + input wire [11:0] rx_a_a, + input wire [11:0] rx_b_a, + input wire [11:0] rx_a_b, + input wire [11:0] rx_b_b, + + output wire [13:0] tx_a, + output wire [13:0] tx_b, + + output wire TXSYNC_A, + output wire TXSYNC_B, + + // USB interface + input usbclk, + input wire [2:0] usbctl, + output wire [1:0] usbrdy, + inout [15:0] usbdata, // NB Careful, inout + + // These are the general purpose i/o's that go to the daughterboard slots + inout wire [15:0] io_tx_a, + inout wire [15:0] io_tx_b, + inout wire [15:0] io_rx_a, + inout wire [15:0] io_rx_b + ); + wire [15:0] debugdata,debugctrl; + assign MYSTERY_SIGNAL = 1'b0; + + wire clk64; + + // wire WR = usbctl[0]; + wire RD = usbctl[1]; + wire OE = usbctl[2]; + + wire have_pkt_rdy; + assign usbrdy[0] = 1'b0; // have_space; + assign usbrdy[1] = have_pkt_rdy; + + wire tx_underrun, rx_overrun; + wire clear_status = FX2_1; + assign FX2_2 = rx_overrun; + assign FX2_3 = 1'b0; // tx_underrun; + + wire [15:0] usbdata_out; + + wire [3:0] rx_numchan; + wire enable_tx, enable_rx; + wire tx_dsp_reset, rx_dsp_reset, tx_bus_reset, rx_bus_reset; + + // Tri-state bus macro + bustri bustri( .data(usbdata_out),.enabledt(OE),.tridata(usbdata) ); + + assign clk64 = master_clk; + + // TX + wire tx_sample_strobe; + wire tx_empty; + + wire serial_strobe; + wire [6:0] serial_addr; + wire [31:0] serial_data; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Transmit Side + + wire [15:0] tx_i, tx_q; + wire [15:0] tx_dac; + + dac_interface dac(.clk_i(clk64),.rst_i(tx_dsp_reset),.ena_i(enable_tx), + .strobe_i(tx_sample_strobe),.tx_i_i(tx_i),.tx_q_i(tx_q), + .tx_data_o(tx_dac),.tx_sync_o(TXSYNC_A)); + + assign tx_a = tx_dac[15:2]; + + // Wedge DAC #2 at zero + assign TXSYNC_B = 1'b0; + assign tx_b = 14'b0; + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Receive Side + wire rx_sample_strobe, rx_strobe; + wire [15:0] rx_adc0_i, rx_adc0_q; + wire [15:0] rx_buf_i, rx_buf_q; + + adc_interface adc_interface(.clock(clk64),.reset(rx_dsp_reset),.enable(enable_rx), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .rx_a_a(rx_a_a),.rx_b_a(rx_b_a),.rx_a_b(),.rx_b_b(), + .rssi_0(),.rssi_1(),.rssi_2(),.rssi_3(), + .ddc0_in_i(rx_adc0_i),.ddc0_in_q(rx_adc0_q), + .ddc1_in_i(),.ddc1_in_q(), + .ddc2_in_i(),.ddc2_in_q(), + .ddc3_in_i(),.ddc3_in_q(),.rx_numchan(rx_numchan) ); + + rx_buffer rx_buffer + ( .usbclk(usbclk),.bus_reset(rx_bus_reset),.reset(rx_dsp_reset), + .reset_regs(rx_dsp_reset), + .usbdata(usbdata_out),.RD(RD),.have_pkt_rdy(have_pkt_rdy),.rx_overrun(rx_overrun), + .channels(rx_numchan), + .ch_0(rx_buf_i),.ch_1(rx_buf_q), + .ch_2(),.ch_3(), + .ch_4(),.ch_5(), + .ch_6(),.ch_7(), + .rxclk(clk64),.rxstrobe(rx_strobe), + .clear_status(clear_status), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .debugbus() ); + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Top level application + + sounder sounder + ( .clk_i(clk64),.saddr_i(serial_addr),.sdata_i(serial_data),.s_strobe_i(serial_strobe), + .tx_rst_i(tx_dsp_reset),.tx_enable_i(enable_tx),.tx_strobe_i(tx_sample_strobe), + .tx_dac_i_o(tx_i),.tx_dac_q_o(tx_q), + .rx_rst_i(rx_dsp_reset),.rx_enable_i(enable_rx),.rx_strobe_i(rx_sample_strobe),.rx_strobe_o(rx_strobe), + .rx_adc_i_i(rx_adc0_i),.rx_adc_q_i(rx_adc0_q),.rx_imp_i_o(rx_buf_i),.rx_imp_q_o(rx_buf_q) + ); + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Control Functions + + wire [31:0] capabilities; + assign capabilities[7] = 0; // `TX_CAP_HB; + assign capabilities[6:4] = 2; // `TX_CAP_NCHAN; + assign capabilities[3] = 0; // `RX_CAP_HB; + assign capabilities[2:0] = 2; // `RX_CAP_NCHAN; + + serial_io serial_io + ( .master_clk(clk64),.serial_clock(SCLK),.serial_data_in(SDI), + .enable(SEN_FPGA),.reset(1'b0),.serial_data_out(SDO), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .readback_0(),.readback_1(),.readback_2(capabilities),.readback_3(), + .readback_4(),.readback_5(),.readback_6(),.readback_7() + ); + + wire [15:0] reg_0,reg_1,reg_2,reg_3; + master_control master_control + ( .master_clk(clk64),.usbclk(usbclk), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .tx_bus_reset(tx_bus_reset),.rx_bus_reset(rx_bus_reset), + .tx_dsp_reset(tx_dsp_reset),.rx_dsp_reset(rx_dsp_reset), + .enable_tx(enable_tx),.enable_rx(enable_rx), + .interp_rate(),.decim_rate(), + .tx_sample_strobe(tx_sample_strobe),.strobe_interp(), + .rx_sample_strobe(rx_sample_strobe),.strobe_decim(), + .tx_empty(tx_empty), + .debug_0(),.debug_1(), + .debug_2(),.debug_3(), + .reg_0(reg_0),.reg_1(reg_1),.reg_2(reg_2),.reg_3(reg_3) ); + + io_pins io_pins + (.io_0(io_tx_a),.io_1(io_rx_a),.io_2(io_tx_b),.io_3(io_rx_b), + .reg_0(reg_0),.reg_1(reg_1),.reg_2(reg_2),.reg_3(reg_3), + .clock(clk64),.rx_reset(rx_dsp_reset),.tx_reset(tx_dsp_reset), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe)); + +endmodule // usrp_sounder diff --git a/gr-sounder/src/lib/Makefile.am b/gr-sounder/src/lib/Makefile.am new file mode 100644 index 00000000..1ae19f1b --- /dev/null +++ b/gr-sounder/src/lib/Makefile.am @@ -0,0 +1,22 @@ +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common diff --git a/gr-sounder/src/python/Makefile.am b/gr-sounder/src/python/Makefile.am new file mode 100644 index 00000000..ecc9d839 --- /dev/null +++ b/gr-sounder/src/python/Makefile.am @@ -0,0 +1,32 @@ +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = \ + usrp_sounder.py \ + qa_nothing.py \ + run_tests.in + +bin_SCRIPTS = \ + usrp_sounder.py + +MOSTLYCLEANFILES = *~ *.pyc *.pyo diff --git a/gr-sounder/src/python/qa_nothing.py b/gr-sounder/src/python/qa_nothing.py new file mode 100644 index 00000000..e69de29b diff --git a/gr-sounder/src/python/run_tests.in b/gr-sounder/src/python/run_tests.in new file mode 100644 index 00000000..b8f7830c --- /dev/null +++ b/gr-sounder/src/python/run_tests.in @@ -0,0 +1,10 @@ +#!/bin/sh + +# 1st parameter is absolute path to component source directory +# 2nd parameter is absolute path to component build directory +# 3rd parameter is path to Python QA directory + +@top_builddir@/run_tests.sh \ + @abs_top_srcdir@/gr-sounder \ + @abs_top_builddir@/gr-sounder \ + @srcdir@ diff --git a/gr-sounder/src/python/usrp_sounder.py b/gr-sounder/src/python/usrp_sounder.py new file mode 100755 index 00000000..ca722a49 --- /dev/null +++ b/gr-sounder/src/python/usrp_sounder.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys, time + +n2s = eng_notation.num_to_str + +# Set to 0 for 32 MHz tx clock, 1 for 64 MHz tx clock +# Must match config.vh in FPGA code +TX_RATE_MAX = 0 +_tx_freq_divisor = 32e6*(TX_RATE_MAX+1) + +class sounder_tx: + def __init__(self, frequency, degree, loopback): + self.trans = usrp.sink_s(fpga_filename='usrp_sounder.rbf') + self.subdev_spec = usrp.pick_tx_subdevice(self.trans) + self.subdev = usrp.selected_subdev(self.trans, self.subdev_spec) + self.trans.tune(0, self.subdev, frequency) + self.set_degree(degree); + self.set_loopback(loopback) + + def turn_on(self): + self.trans.start() + + def turn_off(self): + self.trans.stop() + + def set_degree(self, value): + return self.trans._write_fpga_reg(usrp.FR_USER_0, value); + + def set_loopback(self, value): + return self.trans._write_fpga_reg(usrp.FR_USER_1, value==True); + +class sounder_rx: + def __init__(self, frequency, degree, samples): + self.fg = gr.flow_graph() + self.rcvr = usrp.source_s(fpga_filename='usrp_sounder.rbf', decim_rate=8) + self.subdev_spec = usrp.pick_rx_subdevice(self.rcvr) + self.subdev = usrp.selected_subdev(self.rcvr, self.subdev_spec) + self.rcvr.tune(0, self.subdev, frequency) + self.set_degree(degree); + self.sink = gr.file_sink(gr.sizeof_short, "output.dat") + + if samples >= 0: + self.head = gr.head(gr.sizeof_short, 2*samples*gr.sizeof_short) + self.fg.connect(self.rcvr, self.head, self.sink) + else: + self.fg.connect(self.rcvr, self.sink) + + def receive(self): + self.fg.run() + + def set_degree(self, value): + return self.rcvr._write_fpga_reg(usrp.FR_USER_0, value); + +def main(): + parser = OptionParser(option_class=eng_option) + parser.add_option("-f", "--frequency", type="eng_float", default=0.0, + help="set frequency to FREQ in Hz, default is %default", metavar="FREQ") + + parser.add_option("-t", "--transmit", action="store_true", default=False, + help="enable sounding transmitter") + + parser.add_option("-r", "--receive", action="store_true", default=False, + help="enable sounding receiver") + + parser.add_option("-d", "--degree", type="int", default=16, + help="set souding sequence degree (len=2^degree-1), default is %default") + + parser.add_option("-n", "--samples", type="int", default=-1, + help="number of samples to capture on receive, default is infinite") + + parser.add_option("-l", "--loopback", action="store_true", default=False, + help="enable digital loopback, default is disabled") + + (options, args) = parser.parse_args() + + if len(args) != 0 or not (options.transmit | options.receive): + parser.print_help() + sys.exit(1) + + print "Using PN code degree of", options.degree, "length", 2**options.degree-1 + print "Sounding frequency range is", n2s(options.frequency-16e6), "to", n2s(options.frequency+16e6) + + if (options.transmit): + print "Enabling sounder transmitter." + if (options.loopback): + print "Enabling digital loopback." + tx = sounder_tx(options.frequency, options.degree, options.loopback) + tx.turn_on() + + try: + if (options.receive): + print "Enabling sounder receiver." + rx = sounder_rx(options.frequency, options.degree, options.samples) + rx.receive() + else: + if (options.transmit): + while (True): time.sleep(1.0) + + except KeyboardInterrupt: + if (options.transmit): + tx.turn_off() + + +if __name__ == "__main__": + main() -- 2.30.2