summaryrefslogtreecommitdiff
path: root/gr-sounder/src
diff options
context:
space:
mode:
authorjcorgan2007-05-21 05:58:05 +0000
committerjcorgan2007-05-21 05:58:05 +0000
commit2711e51f33e4c83b07d8293ceca5d6db7830656e (patch)
tree21be31385aa79dc8d6f3075acd093f8ca9775f3d /gr-sounder/src
parent9b7e0f924e4294bff46fa55b9a993b4d529f499a (diff)
downloadgnuradio-2711e51f33e4c83b07d8293ceca5d6db7830656e.tar.gz
gnuradio-2711e51f33e4c83b07d8293ceca5d6db7830656e.tar.bz2
gnuradio-2711e51f33e4c83b07d8293ceca5d6db7830656e.zip
Merged r5463:5504 from jcorgan/snd into trunk. Work in progress, adds digital loopback and receive to FPGA code. Host receive code is still debugging only.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@5505 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'gr-sounder/src')
-rw-r--r--gr-sounder/src/fpga/Makefile.am2
-rw-r--r--gr-sounder/src/fpga/lib/Makefile.am1
-rw-r--r--gr-sounder/src/fpga/lib/dac_interface.v8
-rwxr-xr-xgr-sounder/src/fpga/lib/lfsr_constants.v4
-rw-r--r--gr-sounder/src/fpga/lib/sounder.v74
-rw-r--r--gr-sounder/src/fpga/lib/sounder_rx.v87
-rw-r--r--gr-sounder/src/fpga/lib/sounder_tx.v12
-rw-r--r--gr-sounder/src/fpga/lib/strobe.v48
-rwxr-xr-xgr-sounder/src/fpga/rbf/rev2/usrp_sounder.rbfbin109446 -> 0 bytes
-rwxr-xr-xgr-sounder/src/fpga/rbf/rev4/usrp_sounder.rbfbin109446 -> 0 bytes
-rw-r--r--gr-sounder/src/fpga/tb/Makefile.am (renamed from gr-sounder/src/fpga/rbf/Makefile.am)26
-rw-r--r--gr-sounder/src/fpga/tb/sounder_tb.sav34
-rwxr-xr-xgr-sounder/src/fpga/tb/sounder_tb.sh7
-rw-r--r--gr-sounder/src/fpga/tb/sounder_tb.v212
-rwxr-xr-xgr-sounder/src/fpga/tb/sounder_tb_wave.sh2
-rw-r--r--gr-sounder/src/fpga/top/Makefile.am28
-rwxr-xr-xgr-sounder/src/fpga/top/usrp_sounder.qsf7
-rwxr-xr-xgr-sounder/src/fpga/top/usrp_sounder.rbfbin0 -> 112186 bytes
-rw-r--r--gr-sounder/src/fpga/top/usrp_sounder.v13
-rw-r--r--gr-sounder/src/python/Makefile.am2
-rwxr-xr-xgr-sounder/src/python/test_lp.sh4
-rwxr-xr-xgr-sounder/src/python/test_rx.sh4
-rwxr-xr-xgr-sounder/src/python/test_tx.sh3
-rwxr-xr-xgr-sounder/src/python/usrp_sounder.py195
24 files changed, 587 insertions, 186 deletions
diff --git a/gr-sounder/src/fpga/Makefile.am b/gr-sounder/src/fpga/Makefile.am
index f4cd4fd42..2e8d8e3f0 100644
--- a/gr-sounder/src/fpga/Makefile.am
+++ b/gr-sounder/src/fpga/Makefile.am
@@ -21,4 +21,4 @@
include $(top_srcdir)/Makefile.common
-SUBDIRS = top lib rbf
+SUBDIRS = top lib tb
diff --git a/gr-sounder/src/fpga/lib/Makefile.am b/gr-sounder/src/fpga/lib/Makefile.am
index 450981f1a..0a03147a2 100644
--- a/gr-sounder/src/fpga/lib/Makefile.am
+++ b/gr-sounder/src/fpga/lib/Makefile.am
@@ -28,3 +28,4 @@ EXTRA_DIST = \
sounder_rx.v \
sounder_tx.v
+MOSTLYCLEANFILES = *~ \ No newline at end of file
diff --git a/gr-sounder/src/fpga/lib/dac_interface.v b/gr-sounder/src/fpga/lib/dac_interface.v
index b97ffa77f..9042e1c53 100644
--- a/gr-sounder/src/fpga/lib/dac_interface.v
+++ b/gr-sounder/src/fpga/lib/dac_interface.v
@@ -27,16 +27,16 @@ module dac_interface(clk_i,rst_i,ena_i,strobe_i,tx_i_i,tx_q_i,tx_data_o,tx_sync_
input ena_i;
input strobe_i;
- input [15:0] tx_i_i;
- input [15:0] tx_q_i;
+ input [13:0] tx_i_i;
+ input [13:0] tx_q_i;
- output [15:0] tx_data_o;
+ output [13:0] tx_data_o;
output tx_sync_o;
`ifdef TX_RATE_MAX
wire clk128;
reg clk64_d;
- reg [15:0] tx_data_o;
+ reg [13:0] tx_data_o;
// Create a 128 MHz clock
dacpll pll128(.areset(rst_i),.inclk0(clk_i),.c0(clk128));
diff --git a/gr-sounder/src/fpga/lib/lfsr_constants.v b/gr-sounder/src/fpga/lib/lfsr_constants.v
index 79fcb1a2b..55ee613d2 100755
--- a/gr-sounder/src/fpga/lib/lfsr_constants.v
+++ b/gr-sounder/src/fpga/lib/lfsr_constants.v
@@ -24,8 +24,8 @@ module lfsr_constants(degree_i,mask_o,len_o);
output reg [15:0] mask_o;
output wire [15:0] len_o;
- assign len_o = (16'b1 << degree_i) - 1;
-
+ assign len_o = (1 << degree_i) - 1;
+
always @*
case (degree_i)
5'd00: mask_o = 16'h0000;
diff --git a/gr-sounder/src/fpga/lib/sounder.v b/gr-sounder/src/fpga/lib/sounder.v
index ea4007cb8..58b563448 100644
--- a/gr-sounder/src/fpga/lib/sounder.v
+++ b/gr-sounder/src/fpga/lib/sounder.v
@@ -22,10 +22,10 @@
`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);
+module sounder(clk_i, saddr_i, sdata_i, s_strobe_i,
+ tx_strobe_i, tx_dac_i_o,tx_dac_q_o,
+ rx_strobe_i, rx_adc_i_i,rx_adc_q_i,
+ rx_strobe_o, rx_imp_i_o,rx_imp_q_o);
// System interface
input clk_i; // Master clock @ 64 MHz
@@ -34,53 +34,59 @@ module sounder(clk_i,saddr_i,sdata_i,s_strobe_i,tx_rst_i,tx_enable_i,tx_strobe_i
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
+ output [13:0] tx_dac_i_o; // I channel transmitter output to DAC
+ output [13: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
+ input [15:0] rx_adc_i_i; // I channel input from ADC interface module
+ input [15:0] rx_adc_q_i; // Q channel input from ADC interface module
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
+
+ // Internal variables
+ wire reset;
+ wire transmit;
+ wire receive;
+ wire loopback;
- // 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
+ wire [4:0] degree;
+ wire [15:0] mask;
+ wire [15:0] len;
- // Loopback implementation
- wire [15:0] tx_i, tx_q, rx_i, rx_q; // Internal transmit and receive data bus
+ setting_reg #(`FR_USER_0) sr_mode
+ ( .clock(clk_i),.reset(1'b0),.strobe(s_strobe_i),.addr(saddr_i),.in(sdata_i),
+ .out({loopback,receive,transmit,reset}) );
- 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
+ setting_reg #(`FR_USER_1) sr_lfsr_degree
( .clock(clk_i),.reset(1'b0),.strobe(s_strobe_i),.addr(saddr_i),.in(sdata_i),.out(degree) );
+
+ lfsr_constants constants(.degree_i(degree),.mask_o(mask),.len_o(len));
- 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}) );
+ // Loopback implementation
+ wire [13:0] tx_i, tx_q;
+ wire [15:0] tx_i_ext, tx_q_ext;
+ wire [15:0] rx_i, rx_q;
- lfsr_constants constants(.degree_i(degree),.mask_o(mask),.len_o(len));
+ sign_extend #(14,16) tx_i_extender(tx_i, tx_i_ext);
+ sign_extend #(14,16) tx_q_extender(tx_q, tx_q_ext);
+ assign tx_dac_i_o = loopback ? 14'b0 : tx_i;
+ assign tx_dac_q_o = loopback ? 14'b0 : tx_q;
+ assign rx_i = loopback ? tx_i_ext : rx_adc_i_i;
+ assign rx_q = loopback ? tx_q_ext : rx_adc_q_i;
+
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),
+ ( .clk_i(clk_i),.rst_i(reset),.ena_i(transmit),
+ .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),
+ ( .clk_i(clk_i),.rst_i(reset),.ena_i(receive),
+ .rx_strobe_i(rx_strobe_i),.tx_strobe_i(tx_strobe_i),.mask_i(mask),.degree_i(degree),.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) );
-
+ .rx_strobe_o(rx_strobe_o),.loop_i(loopback));
+
endmodule // sounder
diff --git a/gr-sounder/src/fpga/lib/sounder_rx.v b/gr-sounder/src/fpga/lib/sounder_rx.v
index b7c5f4878..338afd55e 100644
--- a/gr-sounder/src/fpga/lib/sounder_rx.v
+++ b/gr-sounder/src/fpga/lib/sounder_rx.v
@@ -19,8 +19,9 @@
// 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);
+module sounder_rx(clk_i,rst_i,ena_i,rx_strobe_i,tx_strobe_i,mask_i,degree_i,len_i,
+ rx_in_i_i,rx_in_q_i,rx_i_o,rx_q_o,rx_strobe_o,
+ loop_i);
input clk_i; // Master clock
input rst_i; // Subsystem reset
@@ -29,6 +30,7 @@ module sounder_rx(clk_i,rst_i,ena_i,rx_strobe_i,tx_strobe_i,mask_i,len_i,
input tx_strobe_i; // Strobe every transmitted sample
input [15:0] mask_i; // PN code LFSR mask
+ input [4:0] degree_i; // PN code LFSR sequency degree
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
@@ -37,48 +39,57 @@ module sounder_rx(clk_i,rst_i,ena_i,rx_strobe_i,tx_strobe_i,mask_i,len_i,
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));
+ input loop_i; // Implement loopback
+
+ wire strobe_in = loop_i ? tx_strobe_i : rx_strobe_i;
+ wire [16:0] len = loop_i ? (len_i - 1) : ((len_i << 1) - 2);
+
+ strobe #(17) phase_strobe(.clk_i(clk_i),.rst_i(rst_i),.ena_i(ena_i),
+ .rate_i(len),.strobe_i(strobe_in),.strobe_o(rx_strobe_o),
+ .count_o());
- 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);
+ wire pn_ref;
+ wire ref_strobe = tx_strobe_i & ~rx_strobe_o; // Retard reference phase once per period
+ lfsr ref_code
+ ( .clk_i(clk_i),.rst_i(rst_i),.ena_i(ena_i),.strobe_i(ref_strobe),.mask_i(mask_i),.pn_o(pn_ref) );
- // 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 [5:0] offset = (5'd16-degree_i);
+
+ reg [31:0] sum_i, sum_q;
+ reg [31:0] total_i, total_q;
+ wire [31:0] scaled_i = total_i << offset;
+ wire [31:0] scaled_q = total_q << offset;
+ wire [31:0] i_ext, q_ext;
- 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);
+ sign_extend #(16,32) i_extender(rx_in_i_i, i_ext);
+ sign_extend #(16,32) q_extender(rx_in_q_i, q_ext);
- reg [31:0] accum;
+ wire [31:0] prod_i = pn_ref ? i_ext : -i_ext;
+ wire [31:0] prod_q = pn_ref ? q_ext : -q_ext;
+
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;
+ begin
+ sum_i <= 0;
+ sum_q <= 0;
+ total_i <= 0;
+ total_q <= 0;
+ end
+ else if (rx_strobe_o)
+ begin
+ total_i <= sum_i + prod_i;
+ total_q <= sum_q + prod_q;
+ sum_i <= 0;
+ sum_q <= 0;
+ end
+ else if (strobe_in)
+ begin
+ sum_i = sum_i + prod_i;
+ sum_q = sum_q + prod_q;
+ end
+
+ assign rx_i_o = scaled_i[31:16];
+ assign rx_q_o = scaled_q[31:16];
- 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
index d5300fecb..46165dde5 100644
--- a/gr-sounder/src/fpga/lib/sounder_tx.v
+++ b/gr-sounder/src/fpga/lib/sounder_tx.v
@@ -22,8 +22,8 @@
`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
+`define MAX_VALUE 14'h1FFF // 2s complement
+`define MIN_VALUE 14'h2001
module sounder_tx(clk_i,rst_i,ena_i,strobe_i,mask_i,tx_i_o,tx_q_o);
input clk_i;
@@ -31,15 +31,15 @@ module sounder_tx(clk_i,rst_i,ena_i,strobe_i,mask_i,tx_i_o,tx_q_o);
input ena_i;
input strobe_i;
input [15:0] mask_i;
- output [15:0] tx_i_o;
- output [15:0] tx_q_o;
+ output [13:0] tx_i_o;
+ output [13: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;
+ assign tx_i_o = ena_i ? (pn ? `MAX_VALUE : `MIN_VALUE) : 14'b0; // Bipolar
+ assign tx_q_o = 14'b0;
endmodule // sounder_tx
diff --git a/gr-sounder/src/fpga/lib/strobe.v b/gr-sounder/src/fpga/lib/strobe.v
new file mode 100644
index 000000000..ed07f21f4
--- /dev/null
+++ b/gr-sounder/src/fpga/lib/strobe.v
@@ -0,0 +1,48 @@
+// -*- 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 strobe(clk_i,rst_i,ena_i,rate_i,strobe_i,strobe_o,count_o);
+ parameter width = 16;
+
+ input clk_i;
+ input rst_i;
+ input ena_i;
+ input [width-1:0] rate_i; // Desired period minus one
+ input strobe_i;
+ output strobe_o;
+ output [width-1:0] count_o;
+
+
+ reg [width-1:0] counter;
+
+ always @(posedge clk_i)
+ if(rst_i | ~ena_i)
+ counter <= 32'hFFFFFFFF; // First period is short by one
+ else if(strobe_i)
+ if(counter == rate_i)
+ counter <= 0;
+ else
+ counter <= counter + 1;
+
+ assign strobe_o = (counter == rate_i) & strobe_i;
+ assign count_o = counter;
+
+endmodule // strobe
diff --git a/gr-sounder/src/fpga/rbf/rev2/usrp_sounder.rbf b/gr-sounder/src/fpga/rbf/rev2/usrp_sounder.rbf
deleted file mode 100755
index 47a0c98fb..000000000
--- a/gr-sounder/src/fpga/rbf/rev2/usrp_sounder.rbf
+++ /dev/null
Binary files differ
diff --git a/gr-sounder/src/fpga/rbf/rev4/usrp_sounder.rbf b/gr-sounder/src/fpga/rbf/rev4/usrp_sounder.rbf
deleted file mode 100755
index 47a0c98fb..000000000
--- a/gr-sounder/src/fpga/rbf/rev4/usrp_sounder.rbf
+++ /dev/null
Binary files differ
diff --git a/gr-sounder/src/fpga/rbf/Makefile.am b/gr-sounder/src/fpga/tb/Makefile.am
index 5a8b709d5..e668d4568 100644
--- a/gr-sounder/src/fpga/rbf/Makefile.am
+++ b/gr-sounder/src/fpga/tb/Makefile.am
@@ -1,5 +1,5 @@
#
-# Copyright 2005,2006,2007 Free Software Foundation, Inc.
+# Copyright 2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -21,24 +21,10 @@
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
+ sounder_tb.v \
+ sounder_tb.sav \
+ sounder_tb.sh \
+ sounder_tb_wave.sh
-uninstall-local:
- @for file in $(rbfs); do \
- echo "$(RM) $(DESTDIR)$(datadir)/$$file"; \
- $(RM) $(DESTDIR)$(datadir)/$$file; \
- done
+MOSTLYCLEANFILES = *~ *.vcd *.out* sounder_tb \ No newline at end of file
diff --git a/gr-sounder/src/fpga/tb/sounder_tb.sav b/gr-sounder/src/fpga/tb/sounder_tb.sav
new file mode 100644
index 000000000..74019f5ee
--- /dev/null
+++ b/gr-sounder/src/fpga/tb/sounder_tb.sav
@@ -0,0 +1,34 @@
+*-26.117517 250000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+@28
+sounder_tb.uut.clk_i
+sounder_tb.rst
+sounder_tb.s_strobe
+@22
+sounder_tb.sdata[31:0]
+@28
+sounder_tb.uut.reset
+sounder_tb.uut.transmit
+sounder_tb.uut.receive
+sounder_tb.uut.loopback
+@200
+-
+@22
+sounder_tb.uut.degree[4:0]
+sounder_tb.uut.len[15:0]
+@200
+-
+@28
+sounder_tb.tx_dac_i[13:0]
+@200
+-
+@22
+sounder_tb.fifo_strobe
+sounder_tb.fifo_i[15:0]
+sounder_tb.fifo_q[15:0]
+@200
+-
+@22
+sounder_tb.uut.transmitter.pn_code.pn_o
+sounder_tb.uut.receiver.pn_ref
+@200
+-
diff --git a/gr-sounder/src/fpga/tb/sounder_tb.sh b/gr-sounder/src/fpga/tb/sounder_tb.sh
new file mode 100755
index 000000000..9bc714387
--- /dev/null
+++ b/gr-sounder/src/fpga/tb/sounder_tb.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+iverilog -y ../lib/ -y ../../../../usrp/fpga/sdr_lib \
+ sounder_tb.v -o sounder_tb && \
+./sounder_tb > sounder_tb.out && \
+grep 'rst=0' sounder_tb.out | grep 'clk=1' > sounder_tb.out2 && \
+grep 'tx_strobe=1' sounder_tb.out2 > sounder_tb.out3
+
diff --git a/gr-sounder/src/fpga/tb/sounder_tb.v b/gr-sounder/src/fpga/tb/sounder_tb.v
new file mode 100644
index 000000000..045791e43
--- /dev/null
+++ b/gr-sounder/src/fpga/tb/sounder_tb.v
@@ -0,0 +1,212 @@
+// -*- 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
+//
+
+`timescale 1ns/1ps
+
+`include "../lib/sounder.v"
+
+`define FR_MODE 7'd64
+`define bmFR_MODE_RESET 32'h0001
+`define bmFR_MODE_TX 32'h0002
+`define bmFR_MODE_RX 32'h0004
+`define bmFR_MODE_LP 32'h0008
+
+`define FR_DEGREE 7'd65
+
+module sounder_tb;
+
+ // System bus
+ reg clk;
+ reg rst;
+ reg ena;
+
+ // Configuration bus
+ reg [6:0] saddr;
+ reg [31:0] sdata;
+ reg s_strobe;
+
+ // DAC bus
+ reg tx_strobe;
+ wire [13:0] tx_dac_i;
+ wire [13:0] tx_dac_q;
+
+ // ADC bus
+ reg rx_strobe;
+ reg [15:0] rx_adc_i;
+ reg [15:0] rx_adc_q;
+
+ // FIFO bus
+ wire fifo_strobe;
+ wire [15:0] fifo_i;
+ wire [15:0] fifo_q;
+
+ // Configuration shadow registers
+ reg [31:0] mode;
+ reg [31:0] degree;
+
+ sounder uut
+ (.clk_i(clk),.saddr_i(saddr),.sdata_i(sdata),.s_strobe_i(s_strobe),
+ .tx_strobe_i(tx_strobe),.tx_dac_i_o(tx_dac_i),.tx_dac_q_o(tx_dac_q),
+ .rx_strobe_i(rx_strobe),.rx_adc_i_i(rx_adc_i),.rx_adc_q_i(rx_adc_q),
+ .rx_strobe_o(fifo_strobe),.rx_imp_i_o(fifo_i),.rx_imp_q_o(fifo_q));
+
+ // Drive tx_strobe @ half clock rate
+ always @(posedge clk)
+ tx_strobe <= ~tx_strobe;
+
+ // Start up initialization
+ initial
+ begin
+ clk = 0;
+ rst = 0;
+ ena = 0;
+ saddr = 0;
+ sdata = 0;
+ s_strobe = 0;
+ tx_strobe = 0;
+ rx_strobe = 1;
+ rx_adc_i = 0;
+ rx_adc_q = 0;
+ mode = 0;
+ degree = 0;
+
+ @(posedge clk);
+ rst = 1;
+ @(posedge clk);
+ rst = 0;
+ @(posedge clk);
+ ena = 1;
+ end
+
+ always
+ #5 clk <= ~clk;
+
+ initial
+ begin
+ $monitor($time, " clk=%b rst=%b tx_strobe=%b fifo_strobe=%b phs=%x pn_o=%b pn_ref=%b fifo_i=%x fifo_q=",
+ clk, uut.reset, tx_strobe, fifo_strobe, uut.receiver.phase_strobe.count_o,
+ uut.transmitter.pn, uut.receiver.pn_ref, fifo_i, fifo_q);
+ $dumpfile("sounder_tb.vcd");
+ $dumpvars(0, sounder_tb);
+ end
+
+ // Test tasks
+ task write_cfg_register;
+ input [6:0] regno;
+ input [31:0] value;
+
+ begin
+ @(posedge clk);
+ saddr <= regno;
+ sdata <= value;
+ s_strobe <= 1'b1;
+ @(posedge clk);
+ s_strobe <= 0;
+ end
+ endtask // write_cfg_register
+
+ // Application reset line
+ task set_reset;
+ input reset;
+
+ begin
+ mode = reset ? (mode | `bmFR_MODE_RESET) : (mode & ~`bmFR_MODE_RESET);
+ write_cfg_register(`FR_MODE, mode);
+ end
+ endtask // reset
+
+ // Set the PN code degree
+ task set_degree;
+ input [5:0] degree;
+ begin
+ write_cfg_register(`FR_DEGREE, degree);
+ end
+ endtask // set_degree
+
+ // Turn on or off the transmitter
+ task enable_tx;
+ input tx;
+
+ begin
+ mode = tx ? (mode | `bmFR_MODE_TX) : (mode & ~`bmFR_MODE_TX);
+ write_cfg_register(`FR_MODE, mode);
+ end
+ endtask // enable_tx
+
+ // Turn on or off the receiver
+ task enable_rx;
+ input rx;
+
+ begin
+ mode = rx ? (mode | `bmFR_MODE_RX) : (mode & ~`bmFR_MODE_RX);
+ write_cfg_register(`FR_MODE, mode);
+ end
+ endtask // enable_rx
+
+
+ // Turn on or off digital loopback
+ task enable_lp;
+ input lp;
+
+ begin
+ mode = lp ? (mode | `bmFR_MODE_LP) : (mode & ~`bmFR_MODE_LP);
+ write_cfg_register(`FR_MODE, mode);
+ end
+ endtask // enable_lp
+
+ // Test transmitter functionality
+ task test_tx;
+ input [5:0] degree;
+
+ begin
+ #20 set_reset(1);
+ #20 set_degree(degree);
+ #20 enable_tx(1);
+ #20 set_reset(0);
+ #(uut.len*20); // One PN code period
+
+ end
+ endtask // test_tx
+
+ // Test loopback functionality
+ task test_lp;
+ input [5:0] degree;
+
+ begin
+ #20 set_reset(1);
+ #20 set_degree(degree);
+ #20 enable_tx(1);
+ #20 enable_rx(1);
+ #20 enable_lp(1);
+ #20 set_reset(0);
+ #((uut.len+1)*uut.len*20);
+ end
+ endtask // test_lp
+
+ // Execute tests
+ initial
+ begin
+ #20 test_tx(12);
+ #20 test_lp(12);
+ #100 $finish;
+ end
+endmodule
+
diff --git a/gr-sounder/src/fpga/tb/sounder_tb_wave.sh b/gr-sounder/src/fpga/tb/sounder_tb_wave.sh
new file mode 100755
index 000000000..4551d5c59
--- /dev/null
+++ b/gr-sounder/src/fpga/tb/sounder_tb_wave.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+gtkwave sounder_tb.vcd sounder_tb.sav
diff --git a/gr-sounder/src/fpga/top/Makefile.am b/gr-sounder/src/fpga/top/Makefile.am
index 69f6fef9d..9498d4342 100644
--- a/gr-sounder/src/fpga/top/Makefile.am
+++ b/gr-sounder/src/fpga/top/Makefile.am
@@ -21,23 +21,43 @@
include $(top_srcdir)/Makefile.common
+datadir = $(prefix)/share/usrp
+
EXTRA_DIST = \
config.vh \
usrp_sounder.v \
usrp_sounder.csf \
usrp_sounder.esf \
usrp_sounder.psf \
- usrp_sounder.qpf
+ usrp_sounder.qpf \
+ $(RBFS)
+
+RBFS = usrp_sounder.rbf
+
+install-data-local:
+ @for file in $(RBFS); do \
+ echo "$(INSTALL_DATA) $(srcdir)/$$file $(DESTDIR)$(datadir)/rev2/$$file"; \
+ $(INSTALL_DATA) $(srcdir)/$$file $(DESTDIR)$(datadir)/rev2/$$file; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$file $(DESTDIR)$(datadir)/rev4/$$file"; \
+ $(INSTALL_DATA) $(srcdir)/$$file $(DESTDIR)$(datadir)/rev4/$$file; \
+ done
+
+uninstall-local:
+ @for file in $(rbfs); do \
+ echo "$(RM) $(DESTDIR)$(datadir)/rev2/$$file"; \
+ $(RM) $(DESTDIR)$(datadir)/rev2/$$file; \
+ echo "$(RM) $(DESTDIR)$(datadir)/rev4/$$file"; \
+ $(RM) $(DESTDIR)$(datadir)/rev4/$$file; \
+ done
MOSTLYCLEANFILES = \
db/* \
*.rpt \
*.summary \
- *.rbf \
*.qws \
*.smsg \
*.done \
*.pin \
- *.sof
-
+ *.sof \
+ *~
diff --git a/gr-sounder/src/fpga/top/usrp_sounder.qsf b/gr-sounder/src/fpga/top/usrp_sounder.qsf
index bda317db6..5ff52583f 100755
--- a/gr-sounder/src/fpga/top/usrp_sounder.qsf
+++ b/gr-sounder/src/fpga/top/usrp_sounder.qsf
@@ -368,15 +368,16 @@ set_instance_assignment -name CLOCK_SETTINGS master_clk -to master_clk
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/strobe.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 ../lib/sounder.v
+set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/atr_delay.v
+set_global_assignment -name VERILOG_FILE ../../../../usrp/fpga/sdr_lib/sign_extend.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
diff --git a/gr-sounder/src/fpga/top/usrp_sounder.rbf b/gr-sounder/src/fpga/top/usrp_sounder.rbf
new file mode 100755
index 000000000..b6f494227
--- /dev/null
+++ b/gr-sounder/src/fpga/top/usrp_sounder.rbf
Binary files differ
diff --git a/gr-sounder/src/fpga/top/usrp_sounder.v b/gr-sounder/src/fpga/top/usrp_sounder.v
index 05b71bbbd..bb6305691 100644
--- a/gr-sounder/src/fpga/top/usrp_sounder.v
+++ b/gr-sounder/src/fpga/top/usrp_sounder.v
@@ -103,14 +103,14 @@ module usrp_sounder
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Transmit Side
- wire [15:0] tx_i, tx_q;
- wire [15:0] tx_dac;
+ wire [13:0] tx_i, tx_q;
+ wire [13: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];
+ assign tx_a = tx_dac;
// Wedge DAC #2 at zero
assign TXSYNC_B = 1'b0;
@@ -151,10 +151,9 @@ module usrp_sounder
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)
+ .tx_strobe_i(tx_sample_strobe),.tx_dac_i_o(tx_i),.tx_dac_q_o(tx_q),
+ .rx_strobe_i(rx_sample_strobe),.rx_adc_i_i(rx_adc0_i),.rx_adc_q_i(rx_adc0_q),
+ .rx_strobe_o(rx_strobe),.rx_imp_i_o(rx_buf_i),.rx_imp_q_o(rx_buf_q)
);
diff --git a/gr-sounder/src/python/Makefile.am b/gr-sounder/src/python/Makefile.am
index ecc9d8398..7ce181271 100644
--- a/gr-sounder/src/python/Makefile.am
+++ b/gr-sounder/src/python/Makefile.am
@@ -29,4 +29,4 @@ EXTRA_DIST = \
bin_SCRIPTS = \
usrp_sounder.py
-MOSTLYCLEANFILES = *~ *.pyc *.pyo
+MOSTLYCLEANFILES = *~ *.pyc *.pyo output.*
diff --git a/gr-sounder/src/python/test_lp.sh b/gr-sounder/src/python/test_lp.sh
new file mode 100755
index 000000000..fbcc3f533
--- /dev/null
+++ b/gr-sounder/src/python/test_lp.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+usrp_sounder.py -r -l -t -n5000 -d12
+hexdump output.dat >output.hex
diff --git a/gr-sounder/src/python/test_rx.sh b/gr-sounder/src/python/test_rx.sh
new file mode 100755
index 000000000..21998b4de
--- /dev/null
+++ b/gr-sounder/src/python/test_rx.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+usrp_sounder.py -r -n5000 -d12
+hexdump output.dat >output.hex
diff --git a/gr-sounder/src/python/test_tx.sh b/gr-sounder/src/python/test_tx.sh
new file mode 100755
index 000000000..f29ba1f34
--- /dev/null
+++ b/gr-sounder/src/python/test_tx.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+usrp_sounder.py -t -f 16M -d12
diff --git a/gr-sounder/src/python/usrp_sounder.py b/gr-sounder/src/python/usrp_sounder.py
index ca722a494..31e766ef5 100755
--- a/gr-sounder/src/python/usrp_sounder.py
+++ b/gr-sounder/src/python/usrp_sounder.py
@@ -28,68 +28,141 @@ 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()
+FR_MODE = usrp.FR_USER_0
+bmFR_MODE_RESET = 1 << 0 # bit 0: active high reset
+bmFR_MODE_TX = 1 << 1 # bit 1: enable transmitter
+bmFR_MODE_RX = 1 << 2 # bit 2: enable receiver
+bmFR_MODE_LP = 1 << 3 # bit 3: enable digital loopback
+
+FR_DEGREE = usrp.FR_USER_1
+
+class sounder:
+ def __init__(self, options):
+ self._options = options
+ self._mode = 0
- def turn_off(self):
- self.trans.stop()
-
- def set_degree(self, value):
- return self.trans._write_fpga_reg(usrp.FR_USER_0, value);
-
+ self._u = None
+ self._trans = None
+ self._rcvr = None
+ self._transmitting = False
+ self._receiving = False
+
+ if options.transmit:
+ print "Creating sounder transmitter."
+ self._trans = usrp.sink_s(fpga_filename='usrp_sounder.rbf')
+ self._trans_subdev_spec = usrp.pick_tx_subdevice(self._trans)
+ self._trans_subdev = usrp.selected_subdev(self._trans, self._trans_subdev_spec)
+ self._trans.start()
+ self._u = self._trans
+
+ if options.receive:
+ print "Creating sounder receiver."
+ self._fg = gr.flow_graph()
+ self._rcvr = usrp.source_s(fpga_filename='usrp_sounder.rbf', decim_rate=128)
+ self._rcvr_subdev_spec = usrp.pick_rx_subdevice(self._rcvr)
+ self._rcvr_subdev = usrp.selected_subdev(self._rcvr, self._rcvr_subdev_spec)
+ self._sink = gr.file_sink(gr.sizeof_short, "output.dat")
+
+ if options.samples >= 0:
+ self._head = gr.head(gr.sizeof_short, options.samples*gr.sizeof_short)
+ self._fg.connect(self._rcvr, self._head, self._sink)
+ else:
+ self._fg.connect(self._rcvr, self._sink)
+ self._u = self._rcvr # either receiver or transmitter object will do
+
+ self.set_reset(True)
+ self.set_freq(options.frequency)
+ self.set_degree(options.degree)
+ self.set_loopback(options.loopback)
+ self.set_reset(False)
+
+ def set_freq(self, frequency):
+ print "Setting center frequency to", n2s(frequency)
+ if self._rcvr:
+ self._rcvr.tune(0, self._rcvr_subdev, frequency)
+
+ if self._trans:
+ self._trans.tune(0, self._trans_subdev, frequency)
+
+ def set_degree(self, degree):
+ print "Setting PN code degree to", degree
+ self._u._write_fpga_reg(FR_DEGREE, degree);
+
+ def _write_mode(self):
+ print "Writing mode register with:", hex(self._mode)
+ self._u._write_fpga_reg(FR_MODE, self._mode)
+
+ def enable_tx(self, value):
+ if value:
+ print "Enabling transmitter."
+ self._mode |= bmFR_MODE_TX
+ self._transmitting = True
+ else:
+ print "Disabling transmitter."
+ self._mode &= ~bmFR_MODE_TX
+ self._write_mode()
+
+ def enable_rx(self, value):
+ if value:
+ print "Starting receiver flow graph."
+ self._mode |= bmFR_MODE_RX
+ self._write_mode()
+ self._fg.start()
+ self._receiving = True
+ if self._options.samples >= 0:
+ self._fg.wait()
+ else:
+ print "Stopping receiver flow graph."
+ if self._options.samples < 0:
+ self._fg.stop()
+ print "Waiting for threads..."
+ self._fg.wait()
+ print "Receiver flow graph stopped."
+ self._mode &= ~bmFR_MODE_RX
+ self._write_mode()
+ self._receiving = False
+
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)
+ if value:
+ print "Enabling digital loopback."
+ self._mode |= bmFR_MODE_LP
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);
-
+ print "Disabling digital loopback."
+ self._mode &= ~bmFR_MODE_LP
+ self._write_mode()
+
+ def set_reset(self, value):
+ if value:
+ print "Asserting reset."
+ self._mode |= bmFR_MODE_RESET
+ else:
+ print "De-asserting reset."
+ self._mode &= ~bmFR_MODE_RESET
+ self._write_mode()
+
+ def __del__(self):
+ if self._transmitting:
+ self.enable_tx(False)
+
+ if self._receiving:
+ self.enable_rx(False)
+
+# ------------------------------------------------------------------------------
+
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("-d", "--degree", type="int", default=16,
+ help="set souding sequence degree (len=2^degree-1), default is %default")
+
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")
@@ -105,26 +178,16 @@ def main():
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)
+ s = sounder(options)
+
+ if options.transmit:
+ s.enable_tx(True)
- except KeyboardInterrupt:
- if (options.transmit):
- tx.turn_off()
+ if options.receive:
+ s.enable_rx(True)
+ if options.samples < 0:
+ raw_input("Press enter to exit.")
if __name__ == "__main__":
main()