From 5d69a524f81f234b3fbc41d49ba18d6f6886baba Mon Sep 17 00:00:00 2001
From: jcorgan <jcorgan@221aa14e-8319-0410-a670-987f0aec2ac5>
Date: Thu, 3 Aug 2006 04:51:51 +0000
Subject: Houston, we have a trunk.

git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@3122 221aa14e-8319-0410-a670-987f0aec2ac5
---
 usrp/fpga/sdr_lib/adc_interface.v         |  71 ++++++++++
 usrp/fpga/sdr_lib/bidir_reg.v             |  29 ++++
 usrp/fpga/sdr_lib/bus_interface.v         | 213 ++++++++++++++++++++++++++++++
 usrp/fpga/sdr_lib/cic_decim.v             | 106 +++++++++++++++
 usrp/fpga/sdr_lib/cic_int_shifter.v       |  98 ++++++++++++++
 usrp/fpga/sdr_lib/cic_interp.v            |  88 ++++++++++++
 usrp/fpga/sdr_lib/clk_divider.v           |  43 ++++++
 usrp/fpga/sdr_lib/cordic.v                | 109 +++++++++++++++
 usrp/fpga/sdr_lib/cordic_stage.v          |  60 +++++++++
 usrp/fpga/sdr_lib/ddc.v                   |  97 ++++++++++++++
 usrp/fpga/sdr_lib/dpram.v                 |  47 +++++++
 usrp/fpga/sdr_lib/duc.v                   |  95 +++++++++++++
 usrp/fpga/sdr_lib/ext_fifo.v              | 126 ++++++++++++++++++
 usrp/fpga/sdr_lib/gen_cordic_consts.py    |  10 ++
 usrp/fpga/sdr_lib/gen_sync.v              |  43 ++++++
 usrp/fpga/sdr_lib/hb/acc.v                |  22 +++
 usrp/fpga/sdr_lib/hb/coeff_ram.v          |  26 ++++
 usrp/fpga/sdr_lib/hb/coeff_rom.v          |  19 +++
 usrp/fpga/sdr_lib/hb/halfband_decim.v     | 163 +++++++++++++++++++++++
 usrp/fpga/sdr_lib/hb/halfband_interp.v    | 121 +++++++++++++++++
 usrp/fpga/sdr_lib/hb/hbd_tb/HBD           |  80 +++++++++++
 usrp/fpga/sdr_lib/hb/hbd_tb/really_golden | 142 ++++++++++++++++++++
 usrp/fpga/sdr_lib/hb/hbd_tb/regression    |  95 +++++++++++++
 usrp/fpga/sdr_lib/hb/hbd_tb/run_hbd       |   4 +
 usrp/fpga/sdr_lib/hb/hbd_tb/test_hbd.v    |  75 +++++++++++
 usrp/fpga/sdr_lib/hb/mac.v                |  58 ++++++++
 usrp/fpga/sdr_lib/hb/mult.v               |  16 +++
 usrp/fpga/sdr_lib/hb/ram16_2port.v        |  22 +++
 usrp/fpga/sdr_lib/hb/ram16_2sum.v         |  27 ++++
 usrp/fpga/sdr_lib/hb/ram32_2sum.v         |  22 +++
 usrp/fpga/sdr_lib/io_pins.v               |  52 ++++++++
 usrp/fpga/sdr_lib/master_control.v        | 155 ++++++++++++++++++++++
 usrp/fpga/sdr_lib/master_control_multi.v  |  73 ++++++++++
 usrp/fpga/sdr_lib/phase_acc.v             |  52 ++++++++
 usrp/fpga/sdr_lib/ram.v                   |  16 +++
 usrp/fpga/sdr_lib/ram16.v                 |  17 +++
 usrp/fpga/sdr_lib/ram32.v                 |  17 +++
 usrp/fpga/sdr_lib/ram64.v                 |  16 +++
 usrp/fpga/sdr_lib/rssi.v                  |  30 +++++
 usrp/fpga/sdr_lib/rx_buffer.v             | 182 +++++++++++++++++++++++++
 usrp/fpga/sdr_lib/rx_chain.v              | 105 +++++++++++++++
 usrp/fpga/sdr_lib/rx_chain_dual.v         | 103 +++++++++++++++
 usrp/fpga/sdr_lib/rx_dcoffset.v           |  22 +++
 usrp/fpga/sdr_lib/serial_io.v             | 118 +++++++++++++++++
 usrp/fpga/sdr_lib/setting_reg.v           |  23 ++++
 usrp/fpga/sdr_lib/setting_reg_masked.v    |  26 ++++
 usrp/fpga/sdr_lib/sign_extend.v           |  35 +++++
 usrp/fpga/sdr_lib/strobe_gen.v            |  44 ++++++
 usrp/fpga/sdr_lib/tx_buffer.v             | 138 +++++++++++++++++++
 usrp/fpga/sdr_lib/tx_chain.v              |  65 +++++++++
 usrp/fpga/sdr_lib/tx_chain_hb.v           |  76 +++++++++++
 51 files changed, 3492 insertions(+)
 create mode 100644 usrp/fpga/sdr_lib/adc_interface.v
 create mode 100644 usrp/fpga/sdr_lib/bidir_reg.v
 create mode 100755 usrp/fpga/sdr_lib/bus_interface.v
 create mode 100755 usrp/fpga/sdr_lib/cic_decim.v
 create mode 100644 usrp/fpga/sdr_lib/cic_int_shifter.v
 create mode 100755 usrp/fpga/sdr_lib/cic_interp.v
 create mode 100755 usrp/fpga/sdr_lib/clk_divider.v
 create mode 100755 usrp/fpga/sdr_lib/cordic.v
 create mode 100755 usrp/fpga/sdr_lib/cordic_stage.v
 create mode 100755 usrp/fpga/sdr_lib/ddc.v
 create mode 100644 usrp/fpga/sdr_lib/dpram.v
 create mode 100755 usrp/fpga/sdr_lib/duc.v
 create mode 100644 usrp/fpga/sdr_lib/ext_fifo.v
 create mode 100755 usrp/fpga/sdr_lib/gen_cordic_consts.py
 create mode 100644 usrp/fpga/sdr_lib/gen_sync.v
 create mode 100644 usrp/fpga/sdr_lib/hb/acc.v
 create mode 100644 usrp/fpga/sdr_lib/hb/coeff_ram.v
 create mode 100644 usrp/fpga/sdr_lib/hb/coeff_rom.v
 create mode 100644 usrp/fpga/sdr_lib/hb/halfband_decim.v
 create mode 100644 usrp/fpga/sdr_lib/hb/halfband_interp.v
 create mode 100644 usrp/fpga/sdr_lib/hb/hbd_tb/HBD
 create mode 100644 usrp/fpga/sdr_lib/hb/hbd_tb/really_golden
 create mode 100644 usrp/fpga/sdr_lib/hb/hbd_tb/regression
 create mode 100755 usrp/fpga/sdr_lib/hb/hbd_tb/run_hbd
 create mode 100644 usrp/fpga/sdr_lib/hb/hbd_tb/test_hbd.v
 create mode 100644 usrp/fpga/sdr_lib/hb/mac.v
 create mode 100644 usrp/fpga/sdr_lib/hb/mult.v
 create mode 100644 usrp/fpga/sdr_lib/hb/ram16_2port.v
 create mode 100644 usrp/fpga/sdr_lib/hb/ram16_2sum.v
 create mode 100644 usrp/fpga/sdr_lib/hb/ram32_2sum.v
 create mode 100644 usrp/fpga/sdr_lib/io_pins.v
 create mode 100644 usrp/fpga/sdr_lib/master_control.v
 create mode 100644 usrp/fpga/sdr_lib/master_control_multi.v
 create mode 100755 usrp/fpga/sdr_lib/phase_acc.v
 create mode 100644 usrp/fpga/sdr_lib/ram.v
 create mode 100644 usrp/fpga/sdr_lib/ram16.v
 create mode 100644 usrp/fpga/sdr_lib/ram32.v
 create mode 100644 usrp/fpga/sdr_lib/ram64.v
 create mode 100644 usrp/fpga/sdr_lib/rssi.v
 create mode 100644 usrp/fpga/sdr_lib/rx_buffer.v
 create mode 100644 usrp/fpga/sdr_lib/rx_chain.v
 create mode 100644 usrp/fpga/sdr_lib/rx_chain_dual.v
 create mode 100644 usrp/fpga/sdr_lib/rx_dcoffset.v
 create mode 100644 usrp/fpga/sdr_lib/serial_io.v
 create mode 100644 usrp/fpga/sdr_lib/setting_reg.v
 create mode 100644 usrp/fpga/sdr_lib/setting_reg_masked.v
 create mode 100644 usrp/fpga/sdr_lib/sign_extend.v
 create mode 100644 usrp/fpga/sdr_lib/strobe_gen.v
 create mode 100644 usrp/fpga/sdr_lib/tx_buffer.v
 create mode 100644 usrp/fpga/sdr_lib/tx_chain.v
 create mode 100644 usrp/fpga/sdr_lib/tx_chain_hb.v

(limited to 'usrp/fpga/sdr_lib')

diff --git a/usrp/fpga/sdr_lib/adc_interface.v b/usrp/fpga/sdr_lib/adc_interface.v
new file mode 100644
index 0000000000..f18ffc104f
--- /dev/null
+++ b/usrp/fpga/sdr_lib/adc_interface.v
@@ -0,0 +1,71 @@
+
+
+`include "../../firmware/include/fpga_regs_common.v"
+`include "../../firmware/include/fpga_regs_standard.v"
+
+module adc_interface
+  (input clock, input reset, input enable,
+   input wire [6:0] serial_addr, input wire [31:0] serial_data, input serial_strobe,
+   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 [31:0] rssi_0, output wire [31:0] rssi_1, output wire [31:0] rssi_2, output wire [31:0] rssi_3,
+   output reg [15:0] ddc0_in_i, output reg [15:0] ddc0_in_q, 
+   output reg [15:0] ddc1_in_i, output reg [15:0] ddc1_in_q, 
+   output reg [15:0] ddc2_in_i, output reg [15:0] ddc2_in_q, 
+   output reg [15:0] ddc3_in_i, output reg [15:0] ddc3_in_q,
+   output wire [3:0] rx_numchan);
+      
+    // Buffer at input to chip
+   reg [11:0] adc0,adc1,adc2,adc3;
+   always @(posedge clock)
+     begin
+	adc0 <= #1 rx_a_a;
+	adc1 <= #1 rx_b_a;
+	adc2 <= #1 rx_a_b;
+	adc3 <= #1 rx_b_b;
+     end
+   
+   // then scale and subtract dc offset
+   wire [3:0] dco_en;
+   wire [15:0] 	adc0_corr,adc1_corr,adc2_corr,adc3_corr;
+   
+   setting_reg #(`FR_DC_OFFSET_CL_EN) sr_dco_en(.clock(clock),.reset(reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),
+				 .out(dco_en));
+
+   rx_dcoffset #(`FR_ADC_OFFSET_0) rx_dcoffset0(.clock(clock),.enable(dco_en[0]),.reset(reset),.adc_in({adc0[11],adc0,3'b0}),.adc_out(adc0_corr),
+						.serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe));
+   rx_dcoffset #(`FR_ADC_OFFSET_1) rx_dcoffset1(.clock(clock),.enable(dco_en[1]),.reset(reset),.adc_in({adc1[11],adc1,3'b0}),.adc_out(adc1_corr),
+						.serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe));
+   rx_dcoffset #(`FR_ADC_OFFSET_2) rx_dcoffset2(.clock(clock),.enable(dco_en[2]),.reset(reset),.adc_in({adc2[11],adc2,3'b0}),.adc_out(adc2_corr),
+						.serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe));
+   rx_dcoffset #(`FR_ADC_OFFSET_3) rx_dcoffset3(.clock(clock),.enable(dco_en[3]),.reset(reset),.adc_in({adc3[11],adc3,3'b0}),.adc_out(adc3_corr),
+						.serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe));
+
+   // Level sensing for AGC
+   rssi rssi_block_0 (.clock(clock),.reset(reset),.enable(enable),.adc(adc0),.rssi(rssi_0[15:0]),.over_count(rssi_0[31:16]));
+   rssi rssi_block_1 (.clock(clock),.reset(reset),.enable(enable),.adc(adc1),.rssi(rssi_1[15:0]),.over_count(rssi_1[31:16]));
+   rssi rssi_block_2 (.clock(clock),.reset(reset),.enable(enable),.adc(adc2),.rssi(rssi_2[15:0]),.over_count(rssi_2[31:16]));
+   rssi rssi_block_3 (.clock(clock),.reset(reset),.enable(enable),.adc(adc3),.rssi(rssi_3[15:0]),.over_count(rssi_3[31:16]));
+   
+   // And mux to the appropriate outputs
+   wire [3:0] 	ddc3mux,ddc2mux,ddc1mux,ddc0mux;
+   wire 	rx_realsignals;
+   
+   setting_reg #(`FR_RX_MUX) sr_rxmux(.clock(clock),.reset(reset),.strobe(serial_strobe),.addr(serial_addr),
+				      .in(serial_data),.out({ddc3mux,ddc2mux,ddc1mux,ddc0mux,rx_realsignals,rx_numchan[3:1]}));
+   assign 	rx_numchan[0] = 1'b0;
+   
+   always @(posedge clock)
+     begin
+	ddc0_in_i <= #1 ddc0mux[1] ? (ddc0mux[0] ? adc3_corr : adc2_corr) : (ddc0mux[0] ? adc1_corr : adc0_corr);
+	ddc0_in_q <= #1 rx_realsignals ? 16'd0 : ddc0mux[3] ? (ddc0mux[2] ? adc3_corr : adc2_corr) : (ddc0mux[2] ? adc1_corr : adc0_corr);
+	ddc1_in_i <= #1 ddc1mux[1] ? (ddc1mux[0] ? adc3_corr : adc2_corr) : (ddc1mux[0] ? adc1_corr : adc0_corr);
+	ddc1_in_q <= #1 rx_realsignals ? 16'd0 : ddc1mux[3] ? (ddc1mux[2] ? adc3_corr : adc2_corr) : (ddc1mux[2] ? adc1_corr : adc0_corr);
+	ddc2_in_i <= #1 ddc2mux[1] ? (ddc2mux[0] ? adc3_corr : adc2_corr) : (ddc2mux[0] ? adc1_corr : adc0_corr);
+	ddc2_in_q <= #1 rx_realsignals ? 16'd0 : ddc2mux[3] ? (ddc2mux[2] ? adc3_corr : adc2_corr) : (ddc2mux[2] ? adc1_corr : adc0_corr);
+	ddc3_in_i <= #1 ddc3mux[1] ? (ddc3mux[0] ? adc3_corr : adc2_corr) : (ddc3mux[0] ? adc1_corr : adc0_corr);
+	ddc3_in_q <= #1 rx_realsignals ? 16'd0 : ddc3mux[3] ? (ddc3mux[2] ? adc3_corr : adc2_corr) : (ddc3mux[2] ? adc1_corr : adc0_corr);
+     end
+
+endmodule // adc_interface
+
+   
diff --git a/usrp/fpga/sdr_lib/bidir_reg.v b/usrp/fpga/sdr_lib/bidir_reg.v
new file mode 100644
index 0000000000..b12441252c
--- /dev/null
+++ b/usrp/fpga/sdr_lib/bidir_reg.v
@@ -0,0 +1,29 @@
+// Bidirectional registers
+
+module bidir_reg
+  ( inout wire [15:0] tristate,
+    input wire [15:0] oe,
+    input wire [15:0] reg_val );
+
+   // This would be much cleaner if all the tools
+   // supported "for generate"........
+
+   assign 	 tristate[0] = oe[0] ? reg_val[0] : 1'bz;
+   assign 	 tristate[1] = oe[1] ? reg_val[1] : 1'bz;
+   assign 	 tristate[2] = oe[2] ? reg_val[2] : 1'bz;
+   assign 	 tristate[3] = oe[3] ? reg_val[3] : 1'bz;
+   assign 	 tristate[4] = oe[4] ? reg_val[4] : 1'bz;
+   assign 	 tristate[5] = oe[5] ? reg_val[5] : 1'bz;
+   assign 	 tristate[6] = oe[6] ? reg_val[6] : 1'bz;
+   assign 	 tristate[7] = oe[7] ? reg_val[7] : 1'bz;
+   assign 	 tristate[8] = oe[8] ? reg_val[8] : 1'bz;
+   assign 	 tristate[9] = oe[9] ? reg_val[9] : 1'bz;
+   assign 	 tristate[10] = oe[10] ? reg_val[10] : 1'bz;
+   assign 	 tristate[11] = oe[11] ? reg_val[11] : 1'bz;
+   assign 	 tristate[12] = oe[12] ? reg_val[12] : 1'bz;
+   assign 	 tristate[13] = oe[13] ? reg_val[13] : 1'bz;
+   assign 	 tristate[14] = oe[14] ? reg_val[14] : 1'bz;
+   assign 	 tristate[15] = oe[15] ? reg_val[15] : 1'bz;
+   
+endmodule // bidir_reg
+
diff --git a/usrp/fpga/sdr_lib/bus_interface.v b/usrp/fpga/sdr_lib/bus_interface.v
new file mode 100755
index 0000000000..3f5f748d5a
--- /dev/null
+++ b/usrp/fpga/sdr_lib/bus_interface.v
@@ -0,0 +1,213 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+// Interface to Cypress FX2 bus
+// A packet is 512 Bytes.  Each fifo line is 4 bytes
+// Fifo has 1024 or 2048 lines
+
+module bus_interface
+  (     input usbclk,
+	input reset,
+	inout [15:0] usbdata,   // TRISTATE
+	input wire [5:0] usbctl,
+	output wire [5:0] usbrdy,
+	output [31:0] txdata,
+	input [31:0] rxdata,
+	input txclk,
+	input txstrobe,
+	input rxclk,
+	input rxstrobe,
+	output [11:0] debugbus,
+	input clear_status
+	);
+
+   parameter   IN_CHANNELS = 1;
+   parameter   OUT_CHANNELS = 1;
+   parameter   bitmask = (IN_CHANNELS*2)-1;
+
+   wire have_space, have_pkt_rdy;
+   wire WR, RD, OE;
+   reg tx_underrun, rx_overrun;
+   
+   assign WR = usbctl[0];
+   assign RD = usbctl[1];
+   assign OE = usbctl[2];
+   
+   assign usbrdy[0] = have_space;
+   assign usbrdy[1] = have_pkt_rdy;
+   assign usbrdy[2] = tx_underrun;
+   assign usbrdy[3] = rx_overrun;
+   
+   reg [IN_CHANNELS*2*16-1:0] fifo_in;
+   wire [OUT_CHANNELS*2*16-1:0] fifo_out;
+   
+   wire [15:0] usbdata_in = usbdata;
+   
+   reg select_out;
+   reg select_in;
+   
+   reg commit;
+   reg rd_next;
+   reg [15:0] usbdata_out;
+   wire [10:0] txfifolevel,rxfifolevel;
+   reg [8:0] write_count;
+   wire tx_empty;
+   wire tx_full;
+   wire rx_empty;
+   wire rx_full;
+   wire [31:0] txd;
+   wire rdreq;
+	
+   // Tri-state bus macro
+   bustri bustri(.data(usbdata_out),
+		 .enabledt(OE),
+		 .tridata(usbdata)  );
+
+   //////////////////////////////////////////////
+   // TX Side (USB --> DAC)
+   always @(posedge usbclk, posedge reset)
+     begin
+	if(reset)
+	  begin
+	     fifo_in <= #1 0;
+	     write_count <= #1 0;
+	  end
+	else 
+	  if(WR & ~write_count[8])
+	    begin
+	       case(write_count[0])
+		 1'b0 : fifo_in[31:16] <= #1 usbdata_in;  // I
+		 1'b1 : fifo_in[15:0] <= #1 usbdata_in;   // Q
+	       endcase
+	       write_count <= #1 write_count + 9'd1;
+	    end
+	  else
+	    write_count <= #1 WR ? write_count : 9'b0;
+     end
+   
+   always @(posedge usbclk)
+     if(reset)
+       commit <= #1 1'b0;
+     else
+       if(write_count[0] && ~write_count[8] && WR)
+	 commit <= #1 1'b1;
+       else 
+	 commit <= #1 1'b0;
+   
+   assign rdreq = txstrobe & !tx_empty;
+   assign txdata = tx_empty ? 32'b0 : txd;
+   
+   always @(posedge txclk)
+     if(reset)
+       tx_underrun <= 1'b0;
+     else if(txstrobe & tx_empty)
+       tx_underrun <= 1'b1;
+     else if(clear_status)
+       tx_underrun <= 1'b0;
+
+   fifo_1c_2k	txfifo (.data ( fifo_in ),
+			.wrreq ( commit ),
+			.wrclk ( usbclk ),
+
+			.q ( txd ),			
+			.rdreq ( rdreq),
+			.rdclk ( txclk ),
+			
+			.aclr ( reset ),
+
+			.rdempty ( tx_empty ),
+			.rdusedw (  ),
+			.wrfull ( tx_full ),
+			.wrusedw ( txfifolevel )
+			);
+   
+   assign have_space = (txfifolevel <= (2048-128));
+   
+   //////////////////////////////
+   // Receive FIFO (ADC --> USB)
+
+   always @(posedge rxclk)
+     if(reset)
+       rx_overrun <= 1'b0;
+     else if(rxstrobe & rx_full)
+       rx_overrun <= 1'b1;
+     else if(clear_status)
+       rx_overrun <= 1'b0;
+
+   always @(select_out, fifo_out)
+     case(select_out)
+       0 : usbdata_out = fifo_out[31:16];  // I
+       1 : usbdata_out = fifo_out[15:0];   // Q
+     endcase
+  
+/*
+	always @(posedge usbclk, posedge reset)
+	if(reset)
+		usbdata_out <= #1 16'b0;
+	else
+		if(select_out)
+			usbdata_out = fifo_out[31:16];
+		else
+			usbdata_out = fifo_out[15:0];
+	*/
+	 
+   always @(negedge usbclk, posedge reset)
+     if(reset)
+       select_out <= #1 1'b0;
+     else if(~RD)
+       select_out <= #1 1'b0;
+     else 
+       select_out <= #1 ~select_out;
+ 
+   fifo_1c_2k	rxfifo (.data ( rxdata ), // counter ),
+			.wrreq (rxstrobe & ~rx_full ),
+			.wrclk ( rxclk ),
+			
+			.q ( fifo_out ),
+			.rdreq ( select_out ),// & RD ), // FIXME
+			.rdclk ( usbclk ),
+			
+			.aclr ( reset ),
+			
+			.rdempty ( rx_empty ),
+			.rdusedw ( rxfifolevel ),
+			.wrfull ( rx_full ),
+			.wrusedw (  )
+			);
+   
+   assign have_pkt_rdy = (rxfifolevel >= 128);
+
+   // Debugging Aids
+   assign debugbus[0] = tx_underrun;
+   assign debugbus[1] = rx_overrun;
+   assign debugbus[2] = tx_empty;
+   assign debugbus[3] = tx_full;
+   assign debugbus[4] = rx_empty;
+   assign debugbus[5] = rx_full;
+   assign debugbus[6] = txstrobe;
+   assign debugbus[7] = rxstrobe;
+   assign debugbus[8] = select_out;
+   assign debugbus[9] = rxstrobe & ~rx_full;
+   assign debugbus[10] = have_space;
+   assign debugbus[11] = have_pkt_rdy;
+   
+endmodule // bus_interface
+
diff --git a/usrp/fpga/sdr_lib/cic_decim.v b/usrp/fpga/sdr_lib/cic_decim.v
new file mode 100755
index 0000000000..45b863f162
--- /dev/null
+++ b/usrp/fpga/sdr_lib/cic_decim.v
@@ -0,0 +1,106 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+
+module cic_decim
+  ( clock,reset,enable,rate,strobe_in,strobe_out,signal_in,signal_out);
+   parameter bw = 16;
+   parameter N = 4;
+   parameter log2_of_max_rate = 8;
+   parameter maxbitgain = N * log2_of_max_rate;
+   
+   input clock;
+   input reset;
+   input enable;
+   input [7:0] rate;
+   input strobe_in,strobe_out;	
+   input [bw-1:0] signal_in;
+   output [bw-1:0] signal_out;
+   reg [bw-1:0] signal_out;
+
+   wire [bw+maxbitgain-1:0] signal_in_ext;
+   reg [bw+maxbitgain-1:0]  integrator [0:N-1];
+   reg [bw+maxbitgain-1:0] differentiator [0:N-1];
+   reg [bw+maxbitgain-1:0] pipeline [0:N-1];
+   reg [bw+maxbitgain-1:0] sampler;
+   
+   integer i;
+   
+   sign_extend #(bw,bw+maxbitgain) 
+      ext_input (.in(signal_in),.out(signal_in_ext));
+   
+   always @(posedge clock)
+     if(reset)
+       for(i=0;i<N;i=i+1)
+	 integrator[i] <= #1 0;
+     else if (enable && strobe_in)
+       begin
+	  integrator[0] <= #1 integrator[0] + signal_in_ext;
+	  for(i=1;i<N;i=i+1)
+	    integrator[i] <= #1 integrator[i] + integrator[i-1];
+       end	
+   
+   always @(posedge clock)
+     if(reset)
+       begin
+	  sampler <= #1 0;
+	  for(i=0;i<N;i=i+1)
+	    begin
+	       pipeline[i] <= #1 0;
+	       differentiator[i] <= #1 0;
+	    end
+       end
+     else if (enable && strobe_out)
+       begin
+	  sampler <= #1 integrator[N-1];
+	  differentiator[0] <= #1 sampler;
+	  pipeline[0] <= #1 sampler - differentiator[0];
+	  for(i=1;i<N;i=i+1)
+	    begin
+	       differentiator[i] <= #1 pipeline[i-1];
+	       pipeline[i] <= #1 pipeline[i-1] - differentiator[i];
+	    end
+       end // if (enable && strobe_out)
+      
+   wire [bw+maxbitgain-1:0] signal_out_unnorm = pipeline[N-1];
+
+   // Output Scaling to same width as input
+   function [2:0] log_ceil;
+      input [7:0] val;
+      log_ceil = val[6] ? 3'd7 : val[5] ? 3'd6 : val[4] ? 3'd5 :
+		 val[3] ? 3'd4 : val[2] ? 3'd3 : val[1] ? 3'd2 : 3'd1; 
+   endfunction // log_ceil
+   
+   wire [2:0] shift = log_ceil(rate);
+   
+   always @*
+     case(shift)
+       3'd2 : signal_out = signal_out_unnorm[2*N+bw-1:2*N]; //  Decim by 4
+       3'd3 : signal_out = signal_out_unnorm[3*N+bw-1:3*N];
+       3'd4 : signal_out = signal_out_unnorm[4*N+bw-1:4*N];
+       3'd5 : signal_out = signal_out_unnorm[5*N+bw-1:5*N];
+       3'd6 : signal_out = signal_out_unnorm[6*N+bw-1:6*N];
+       3'd7 : signal_out = signal_out_unnorm[7*N+bw-1:7*N];
+       default : signal_out = signal_out_unnorm[7*N+bw-1:7*N];
+     endcase // case(shift)
+   
+endmodule // cic_decim
+
diff --git a/usrp/fpga/sdr_lib/cic_int_shifter.v b/usrp/fpga/sdr_lib/cic_int_shifter.v
new file mode 100644
index 0000000000..112d8712bb
--- /dev/null
+++ b/usrp/fpga/sdr_lib/cic_int_shifter.v
@@ -0,0 +1,98 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+
+module cic_int_shifter(rate,signal_in,signal_out);
+   parameter bw = 16;
+   parameter N = 4;
+   parameter log2_of_max_rate = 7;
+   parameter maxbitgain = (N-1)*log2_of_max_rate;
+   
+   input [7:0] rate;
+   input       wire [bw+maxbitgain-1:0] signal_in;
+   output      reg [bw-1:0] signal_out;
+
+   function [2:0] log_ceil;
+      input [7:0] val;
+      log_ceil = val[6] ? 3'd7 : val[5] ? 3'd6 : val[4] ? 3'd5 : 
+		 val[3] ? 3'd4 : val[2] ? 3'd3 : val[1] ? 3'd2 : 3'd1; 
+   endfunction // log_ceil
+   
+   function [4:0] bitgain;
+      input [7:0] rate;
+      case(rate)
+	8'd4 : bitgain = 2*(N-1);
+	8'd8 : bitgain = 3*(N-1);
+	8'd16 : bitgain = 4*(N-1);
+	8'd32 : bitgain = 5*(N-1);
+	8'd64 : bitgain = 6*(N-1);
+	8'd128 : bitgain = 7*(N-1);
+	
+	8'd5 : bitgain = 7;
+	8'd6 : bitgain = 8;
+	8'd7 : bitgain = 9;
+	8'd9,8'd10 : bitgain = 10;
+	8'd12 : bitgain = 11;
+	8'd13,8'd14,8'd15 : bitgain = 12;
+	8'd17,8'd18,8'd19,8'd20 : bitgain = 13;
+	8'd21,8'd22,8'd23,8'd24,8'd25 : bitgain = 14;
+	8'd26,8'd27,8'd28,8'd29,8'd30,8'd31 : bitgain = 15;
+	8'd33,8'd34,8'd35,8'd36,8'd37,8'd38,8'd39,8'd40 : bitgain = 16;
+	8'd41,8'd42,8'd43,8'd44,8'd45,8'd46,8'd47,8'd48,8'd49,8'd50 : bitgain = 17;
+	8'd51,8'd52,8'd53,8'd54,8'd55,8'd56,8'd57,8'd58,8'd59,8'd60,8'd61,8'd62,8'd63 : bitgain = 18;
+	8'd65,8'd66,8'd67,8'd68,8'd69,8'd70,8'd71,8'd72,8'd73,8'd74,8'd75,8'd76,8'd77,8'd78,8'd79,8'd80 : bitgain = 19;
+	8'd81,8'd82,8'd83,8'd84,8'd85,8'd86,8'd87,8'd88,8'd89,8'd90,8'd91,8'd92,8'd93,8'd94,8'd95,8'd96,8'd97,8'd98,8'd99,8'd100,8'd101 : bitgain = 20;
+	
+	default : bitgain = 21;
+      endcase // case(rate)
+   endfunction // bitgain
+   
+   wire [4:0] 	  shift = bitgain(rate+1);
+   
+   // We should be able to do this, but can't ....
+   // assign 	  signal_out = signal_in[shift+bw-1:shift];
+   
+   always @*
+     case(shift)
+       5'd6  : signal_out = signal_in[6+bw-1:6];
+       5'd9  : signal_out = signal_in[9+bw-1:9];
+       5'd12 : signal_out = signal_in[12+bw-1:12];
+       5'd15 : signal_out = signal_in[15+bw-1:15];
+       5'd18 : signal_out = signal_in[18+bw-1:18];
+       5'd21 : signal_out = signal_in[21+bw-1:21];
+       
+       5'd7  : signal_out = signal_in[7+bw-1:7];
+       5'd8  : signal_out = signal_in[8+bw-1:8];
+       5'd10 : signal_out = signal_in[10+bw-1:10];
+       5'd11 : signal_out = signal_in[11+bw-1:11];
+       5'd13 : signal_out = signal_in[13+bw-1:13];
+       5'd14 : signal_out = signal_in[14+bw-1:14];
+       5'd16 : signal_out = signal_in[16+bw-1:16];
+       5'd17 : signal_out = signal_in[17+bw-1:17];
+       5'd19 : signal_out = signal_in[19+bw-1:19];
+       5'd20 : signal_out = signal_in[20+bw-1:20];
+       
+       
+       default : signal_out = signal_in[21+bw-1:21];
+     endcase // case(shift)
+
+endmodule // cic_int_shifter
+
diff --git a/usrp/fpga/sdr_lib/cic_interp.v b/usrp/fpga/sdr_lib/cic_interp.v
new file mode 100755
index 0000000000..43ab17d3b9
--- /dev/null
+++ b/usrp/fpga/sdr_lib/cic_interp.v
@@ -0,0 +1,88 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+
+module cic_interp(clock,reset,enable,rate,strobe_in,strobe_out,signal_in,signal_out);
+   parameter bw = 16;
+   parameter N = 4;
+   parameter log2_of_max_rate = 7;
+   parameter maxbitgain = (N-1)*log2_of_max_rate;
+   
+   input clock;
+   input reset;
+   input enable;
+   input [7:0] rate;
+   input strobe_in,strobe_out;	
+   input [bw-1:0] signal_in;
+   wire [bw-1:0] 	signal_in;
+   output [bw-1:0] signal_out;
+   wire [bw-1:0]   signal_out;
+
+   wire [bw+maxbitgain-1:0] signal_in_ext;
+   reg [bw+maxbitgain-1:0] integrator [0:N-1];
+   reg [bw+maxbitgain-1:0] differentiator [0:N-1];
+   reg [bw+maxbitgain-1:0] pipeline [0:N-1];
+
+   integer i;
+
+   sign_extend #(bw,bw+maxbitgain) 
+      ext_input (.in(signal_in),.out(signal_in_ext));
+   
+   //FIXME Note that this section has pipe and diff reversed
+   // It still works, but is confusing
+   always @(posedge clock)
+     if(reset)
+       for(i=0;i<N;i=i+1)
+	 integrator[i] <= #1 0;
+     else if (enable & strobe_out)
+       begin
+	  if(strobe_in)
+	    integrator[0] <= #1 integrator[0] + pipeline[N-1];
+	  for(i=1;i<N;i=i+1)
+	    integrator[i] <= #1 integrator[i] + integrator[i-1];
+       end
+   
+   always @(posedge clock)
+     if(reset)
+       begin
+	  for(i=0;i<N;i=i+1)
+	    begin
+	       differentiator[i] <= #1 0;
+	       pipeline[i] <= #1 0;
+ 	    end
+       end
+     else if (enable && strobe_in)
+       begin
+	  differentiator[0] <= #1 signal_in_ext;
+	  pipeline[0] <= #1 signal_in_ext - differentiator[0];
+	  for(i=1;i<N;i=i+1)
+	    begin
+	       differentiator[i] <= #1 pipeline[i-1];
+	       pipeline[i] <= #1 pipeline[i-1] - differentiator[i];
+	    end
+       end
+   
+   wire [bw+maxbitgain-1:0] signal_out_unnorm = integrator[N-1];
+
+   cic_int_shifter cic_int_shifter(rate,signal_out_unnorm,signal_out);
+   
+endmodule // cic_interp
+
diff --git a/usrp/fpga/sdr_lib/clk_divider.v b/usrp/fpga/sdr_lib/clk_divider.v
new file mode 100755
index 0000000000..a687297b47
--- /dev/null
+++ b/usrp/fpga/sdr_lib/clk_divider.v
@@ -0,0 +1,43 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+
+module clk_divider(input reset, input wire in_clk,output reg out_clk, input [7:0] ratio);
+   reg [7:0] counter;
+   
+   // FIXME maybe should use PLL or switch to double edge version	
+	
+   always @(posedge in_clk or posedge reset)
+     if(reset)
+       counter <= #1 8'd0;
+     else if(counter == 0)
+       counter <= #1 ratio[7:1] + (ratio[0] & out_clk) - 8'b1;
+     else
+       counter <= #1 counter-8'd1;
+   
+   always @(posedge in_clk or posedge reset)
+     if(reset)
+       out_clk <= #1 1'b0;
+     else if(counter == 0)
+       out_clk <= #1 ~out_clk;
+   
+endmodule // clk_divider
+
diff --git a/usrp/fpga/sdr_lib/cordic.v b/usrp/fpga/sdr_lib/cordic.v
new file mode 100755
index 0000000000..8c8c0ab0df
--- /dev/null
+++ b/usrp/fpga/sdr_lib/cordic.v
@@ -0,0 +1,109 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+module cordic(clock, reset, enable, xi, yi, zi, xo, yo, zo );
+   parameter bitwidth = 16;
+   parameter zwidth = 16;
+   
+   input clock;
+   input reset;
+   input enable;
+   input [bitwidth-1:0] xi, yi;
+   output [bitwidth-1:0] xo, yo;
+   input [zwidth-1:0] zi;
+   output [zwidth-1:0] zo;
+   
+   reg [bitwidth+1:0] 	 x0,y0;
+   reg [zwidth-2:0] 	 z0;
+   wire [bitwidth+1:0] 	 x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12;
+   wire [bitwidth+1:0] 	 y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12;
+   wire [zwidth-2:0] z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12;
+   
+   wire [bitwidth+1:0] xi_ext = {{2{xi[bitwidth-1]}},xi};
+   wire [bitwidth+1:0] yi_ext = {{2{yi[bitwidth-1]}},yi};
+
+   // Compute consts.  Would be easier if vlog had atan...
+   // see gen_cordic_consts.py
+   
+`define c00 16'd8192
+`define c01 16'd4836
+`define c02 16'd2555
+`define c03 16'd1297
+`define c04 16'd651
+`define c05 16'd326
+`define c06 16'd163
+`define c07 16'd81
+`define c08 16'd41
+`define c09 16'd20
+`define c10 16'd10
+`define c11 16'd5
+`define c12 16'd3
+`define c13 16'd1
+`define c14 16'd1
+`define c15 16'd0
+`define c16 16'd0
+
+   always @(posedge clock)
+     if(reset)
+       begin
+	  x0   <= #1 0; y0   <= #1 0;  z0   <= #1 0;
+       end
+     else// if(enable)
+       begin
+	  z0 <= #1 zi[zwidth-2:0];
+	  case (zi[zwidth-1:zwidth-2])
+	    2'b00, 2'b11 : 
+	      begin
+		 x0 <= #1 xi_ext;
+		 y0 <= #1 yi_ext;
+	      end
+	    2'b01, 2'b10 :
+	      begin
+		 x0 <= #1 -xi_ext;
+		 y0 <= #1 -yi_ext;
+	      end
+	  endcase // case(zi[zwidth-1:zwidth-2])
+       end // else: !if(reset)
+   
+   // FIXME need to handle variable number of stages
+   // FIXME should be able to narrow zwidth but quartus makes it bigger...
+   // This would be easier if arrays worked better in vlog...
+   cordic_stage #(bitwidth+2,zwidth-1,0) cordic_stage0 (clock,reset,enable,x0,y0,z0,`c00,x1,y1,z1);
+   cordic_stage #(bitwidth+2,zwidth-1,1) cordic_stage1 (clock,reset,enable,x1,y1,z1,`c01,x2,y2,z2);
+   cordic_stage #(bitwidth+2,zwidth-1,2) cordic_stage2 (clock,reset,enable,x2,y2,z2,`c02,x3,y3,z3);
+   cordic_stage #(bitwidth+2,zwidth-1,3) cordic_stage3 (clock,reset,enable,x3,y3,z3,`c03,x4,y4,z4);
+   cordic_stage #(bitwidth+2,zwidth-1,4) cordic_stage4 (clock,reset,enable,x4,y4,z4,`c04,x5,y5,z5);
+   cordic_stage #(bitwidth+2,zwidth-1,5) cordic_stage5 (clock,reset,enable,x5,y5,z5,`c05,x6,y6,z6);
+   cordic_stage #(bitwidth+2,zwidth-1,6) cordic_stage6 (clock,reset,enable,x6,y6,z6,`c06,x7,y7,z7);
+   cordic_stage #(bitwidth+2,zwidth-1,7) cordic_stage7 (clock,reset,enable,x7,y7,z7,`c07,x8,y8,z8);
+   cordic_stage #(bitwidth+2,zwidth-1,8) cordic_stage8 (clock,reset,enable,x8,y8,z8,`c08,x9,y9,z9);
+   cordic_stage #(bitwidth+2,zwidth-1,9) cordic_stage9 (clock,reset,enable,x9,y9,z9,`c09,x10,y10,z10);
+   cordic_stage #(bitwidth+2,zwidth-1,10) cordic_stage10 (clock,reset,enable,x10,y10,z10,`c10,x11,y11,z11);
+   cordic_stage #(bitwidth+2,zwidth-1,11) cordic_stage11 (clock,reset,enable,x11,y11,z11,`c11,x12,y12,z12);
+
+   assign xo = x12[bitwidth:1];  
+   assign yo = y12[bitwidth:1];
+   //assign xo = x12[bitwidth+1:2];  // CORDIC gain is ~1.6, plus gain from rotating vectors
+   //assign yo = y12[bitwidth+1:2];
+   assign zo = z12;		  
+
+endmodule // cordic
+
diff --git a/usrp/fpga/sdr_lib/cordic_stage.v b/usrp/fpga/sdr_lib/cordic_stage.v
new file mode 100755
index 0000000000..c9c0ef9a31
--- /dev/null
+++ b/usrp/fpga/sdr_lib/cordic_stage.v
@@ -0,0 +1,60 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+module cordic_stage( clock, reset, enable, xi,yi,zi,constant,xo,yo,zo);
+   parameter bitwidth = 16;
+   parameter zwidth = 16;
+   parameter shift = 1;
+   
+   input     clock;
+   input     reset;
+   input     enable;
+   input [bitwidth-1:0] xi,yi;
+   input [zwidth-1:0] zi;
+   input [zwidth-1:0] constant;
+   output [bitwidth-1:0] xo,yo;
+   output [zwidth-1:0] zo;
+   
+   wire z_is_pos = ~zi[zwidth-1];
+
+   reg [bitwidth-1:0] 	 xo,yo;
+   reg [zwidth-1:0] zo;
+   
+   always @(posedge clock)
+     if(reset)
+       begin
+	  xo <= #1 0;
+	  yo <= #1 0;
+	  zo <= #1 0;
+       end
+     else //if(enable)
+       begin
+	  xo <= #1 z_is_pos ?   
+		xi - {{shift+1{yi[bitwidth-1]}},yi[bitwidth-2:shift]} :
+		xi + {{shift+1{yi[bitwidth-1]}},yi[bitwidth-2:shift]};
+	  yo <= #1 z_is_pos ?   
+		yi + {{shift+1{xi[bitwidth-1]}},xi[bitwidth-2:shift]} :
+		yi - {{shift+1{xi[bitwidth-1]}},xi[bitwidth-2:shift]};
+	  zo <= #1 z_is_pos ?   
+		zi - constant :
+		zi + constant;
+       end
+endmodule
diff --git a/usrp/fpga/sdr_lib/ddc.v b/usrp/fpga/sdr_lib/ddc.v
new file mode 100755
index 0000000000..48bca9a799
--- /dev/null
+++ b/usrp/fpga/sdr_lib/ddc.v
@@ -0,0 +1,97 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+
+
+// DDC block
+
+module ddc(input clock,
+			input reset,
+			input enable,
+			input [3:0] rate1,
+			input [3:0] rate2,
+			output strobe,
+			input [31:0] freq,
+			input [15:0] i_in,
+			input [15:0] q_in,
+			output [15:0] i_out,
+			output [15:0] q_out
+			);
+   parameter bw = 16;
+   parameter zw = 16;
+
+	wire [15:0] i_cordic_out, q_cordic_out;
+	wire [31:0] phase;
+
+	wire strobe1, strobe2;
+	reg [3:0] strobe_ctr1,strobe_ctr2;
+
+	always @(posedge clock)
+		if(reset | ~enable)
+			strobe_ctr2 <= #1 4'd0;
+		else if(strobe2)
+			strobe_ctr2 <= #1 4'd0;
+		else	
+			strobe_ctr2 <= #1 strobe_ctr2 + 4'd1;
+				
+	always @(posedge clock)
+		if(reset | ~enable)
+			strobe_ctr1 <= #1 4'd0;
+		else if(strobe1)
+			strobe_ctr1 <= #1 4'd0;
+		else if(strobe2)
+			strobe_ctr1 <= #1 strobe_ctr1 + 4'd1;
+				
+
+	assign strobe2 = enable & ( strobe_ctr2 == rate2 );
+	assign strobe1 = strobe2 & ( strobe_ctr1 == rate1 );
+
+	assign strobe = strobe1;
+
+	function [2:0] log_ceil;
+	input [3:0] val;
+	
+		log_ceil = val[3] ? 3'd4 : val[2] ? 3'd3 : val[1] ? 3'd2 : 3'd1; 
+	endfunction	
+	
+	wire [2:0] shift1 = log_ceil(rate1);
+	wire [2:0] shift2 = log_ceil(rate2);
+	
+	cordic #(.bitwidth(bw),.zwidth(zw),.stages(16))
+		cordic(.clock(clock), .reset(reset), .enable(enable),
+			.xi(i_in), .yi(q_in), .zi(phase[31:32-zw]), 
+			.xo(i_cordic_out), .yo(q_cordic_out), .zo()  );
+		
+	cic_decim_2stage #(.bw(bw),.N(4)) 
+		decim_i(.clock(clock),.reset(reset),.enable(enable),
+			.strobe1(1'b1),.strobe2(strobe2),.strobe3(strobe1),.shift1(shift2),.shift2(shift1),
+			.signal_in(i_cordic_out),.signal_out(i_out));
+			
+	cic_decim_2stage #(.bw(bw),.N(4)) 
+		decim_q(.clock(clock),.reset(reset),.enable(enable),
+			.strobe1(1'b1),.strobe2(strobe2),.strobe3(strobe1),.shift1(shift2),.shift2(shift1),
+			.signal_in(q_cordic_out),.signal_out(q_out));
+	
+	phase_acc #(.resolution(32))
+		nco (.clk(clock),.reset(reset),.enable(enable),
+			.freq(freq),.phase(phase));
+		
+endmodule
diff --git a/usrp/fpga/sdr_lib/dpram.v b/usrp/fpga/sdr_lib/dpram.v
new file mode 100644
index 0000000000..5c38decce7
--- /dev/null
+++ b/usrp/fpga/sdr_lib/dpram.v
@@ -0,0 +1,47 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+
+
+module dpram(wclk,wdata,waddr,wen,rclk,rdata,raddr);
+   parameter depth = 4;
+   parameter width = 16;
+   parameter size = 16;
+   
+   input wclk;
+   input [width-1:0] wdata;
+   input [depth-1:0] waddr;
+   input 	     wen;
+
+   input rclk;
+   output reg [width-1:0] rdata;
+   input [depth-1:0]  raddr;
+   
+   reg [width-1:0]    ram [0:size-1];
+   
+   always @(posedge wclk)
+     if(wen)
+       ram[waddr] <= #1 wdata;
+   
+   always @(posedge rclk)
+     rdata <= #1 ram[raddr];
+   
+endmodule // dpram
diff --git a/usrp/fpga/sdr_lib/duc.v b/usrp/fpga/sdr_lib/duc.v
new file mode 100755
index 0000000000..780fc9f233
--- /dev/null
+++ b/usrp/fpga/sdr_lib/duc.v
@@ -0,0 +1,95 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+// DUC block
+
+module duc(input clock,
+			input reset,
+			input enable,
+			input [3:0] rate1,
+			input [3:0] rate2,
+			output strobe,
+			input [31:0] freq,
+			input [15:0] i_in,
+			input [15:0] q_in,
+			output [15:0] i_out,
+			output [15:0] q_out
+			);
+   parameter bw = 16;
+   parameter zw = 16;
+   
+	wire [15:0] i_interp_out, q_interp_out;
+	wire [31:0] phase;
+
+	wire strobe1, strobe2;
+	reg [3:0] strobe_ctr1,strobe_ctr2;
+
+	always @(posedge clock)
+		if(reset | ~enable)
+			strobe_ctr2 <= #1 4'd0;
+		else if(strobe2)
+			strobe_ctr2 <= #1 4'd0;
+		else	
+			strobe_ctr2 <= #1 strobe_ctr2 + 4'd1;
+				
+	always @(posedge clock)
+		if(reset | ~enable)
+			strobe_ctr1 <= #1 4'd0;
+		else if(strobe1)
+			strobe_ctr1 <= #1 4'd0;
+		else if(strobe2)
+			strobe_ctr1 <= #1 strobe_ctr1 + 4'd1;
+				
+
+	assign strobe2 = enable & ( strobe_ctr2 == rate2 );
+	assign strobe1 = strobe2 & ( strobe_ctr1 == rate1 );
+
+	assign strobe = strobe1;
+
+	function [2:0] log_ceil;
+	input [3:0] val;
+	
+		log_ceil = val[3] ? 3'd4 : val[2] ? 3'd3 : val[1] ? 3'd2 : 3'd1; 
+	endfunction	
+	
+	wire [2:0] shift1 = log_ceil(rate1);
+	wire [2:0] shift2 = log_ceil(rate2);
+	
+	cordic #(.bitwidth(bw),.zwidth(zw),.stages(16))
+		cordic(.clock(clock), .reset(reset), .enable(enable),
+			.xi(i_interp_out), .yi(q_interp_out), .zi(phase[31:32-zw]), 
+			.xo(i_out), .yo(q_out), .zo()  );
+		
+	cic_interp_2stage #(.bw(bw),.N(4)) 
+		interp_i(.clock(clock),.reset(reset),.enable(enable),
+			.strobe1(strobe1),.strobe2(strobe2),.strobe3(1'b1),.shift1(shift1),.shift2(shift2),
+			.signal_in(i_in),.signal_out(i_interp_out));
+
+	cic_interp_2stage #(.bw(bw),.N(4)) 
+		interp_q(.clock(clock),.reset(reset),.enable(enable),
+			.strobe1(strobe1),.strobe2(strobe2),.strobe3(1'b1),.shift1(shift1),.shift2(shift2),
+			.signal_in(q_in),.signal_out(q_interp_out));
+	
+	phase_acc #(.resolution(32))
+		nco (.clk(clock),.reset(reset),.enable(enable),
+			.freq(freq),.phase(phase));
+		
+endmodule
diff --git a/usrp/fpga/sdr_lib/ext_fifo.v b/usrp/fpga/sdr_lib/ext_fifo.v
new file mode 100644
index 0000000000..dfe1f2fe7a
--- /dev/null
+++ b/usrp/fpga/sdr_lib/ext_fifo.v
@@ -0,0 +1,126 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+ 
+// Vendor Independent FIFO module
+// Width and Depth should be parameterizable
+// Asynchronous clocks for each side
+// Read side is read-acknowledge, not read-request
+// FIFO does not enforce "don't write when full, don't read when empty"
+// That is up to the connecting modules
+// The FIFO only holds 2^N-1 entries, not 2^N
+
+module fifo (reset,data,write,wrclk,wr_used,q,read_ack,rdclk,rd_used);
+   parameter width=32;
+   parameter depth=10;
+
+   input reset;  // Asynchronous
+   input [width-1:0] data;
+   input write;
+   input wrclk;
+   output [depth-1:0] wr_used;
+   output [width-1:0] q;
+   input read_ack;
+   input rdclk;
+   output [depth-1:0] rd_used;
+
+   reg [depth-1:0] read_addr, write_addr, 
+		   read_addr_gray, read_addr_gray_sync,
+		   write_addr_gray, write_addr_gray_sync;
+
+   // Pseudo-dual-port RAM
+   dpram #(.depth(10),.width(width),.size(1024))
+         fifo_ram (.wclk(wrclk),.wdata(data),.waddr(write_addr),.wen(write),
+		   .rclk(rdclk), .rdata(q),.raddr(read_addr) );
+
+   wire [depth-1:0] wag,rag;
+
+   // Keep track of own side's pointer
+   always @(posedge wrclk or posedge reset)
+     if(reset) write_addr <= #1 0;
+     else if(write) write_addr <= #1 write_addr + 1;
+
+   always @(posedge rdclk or posedge reset)
+     if(reset) read_addr <= #1 0;
+     else if(read_ack) read_addr <= #1 read_addr + 1;
+
+   // Convert own side pointer to gray
+   bin2gray #(depth) write_b2g (write_addr,wag);
+   bin2gray #(depth) read_b2g (read_addr,rag);
+
+   // Latch it
+   always @(posedge wrclk or posedge reset)
+     if(reset) write_addr_gray <= #1 0;
+     else write_addr_gray <= #1 wag;
+
+   always @(posedge rdclk or posedge reset)
+     if(reset) read_addr_gray <= #1 0;
+     else read_addr_gray <= #1 rag;
+
+   // Send it to other side and latch
+   always @(posedge wrclk or posedge reset)
+     if(reset) read_addr_gray_sync <= #1 0;
+     else read_addr_gray_sync <= #1 read_addr_gray;
+
+   always @(posedge rdclk or posedge reset)
+     if(reset) write_addr_gray_sync <= #1 0;
+     else write_addr_gray_sync <= #1 write_addr_gray;
+
+   wire [depth-1:0] write_addr_sync, read_addr_sync;
+   
+   // Convert back to binary
+   gray2bin #(depth) write_g2b (write_addr_gray_sync, write_addr_sync);
+   gray2bin #(depth) read_g2b (read_addr_gray_sync, read_addr_sync);
+ 
+   assign rd_used = write_addr_sync - read_addr;
+   assign wr_used = write_addr - read_addr_sync;
+   		  
+endmodule // fifo
+
+module bin2gray(bin_val,gray_val);
+   parameter width = 8;
+   input [width-1:0] bin_val;
+   output reg [width-1:0] gray_val;
+   
+   integer i;
+
+   always @*
+     begin
+	gray_val[width-1] = bin_val[width-1];
+	for(i=0;i<width-1;i=i+1)
+	  gray_val[i] = bin_val[i] ^ bin_val[i+1];
+     end
+endmodule // bin2gray
+
+module gray2bin(gray_val,bin_val);
+   parameter width = 8;
+   input [width-1:0] gray_val;
+   output reg [width-1:0] bin_val;
+
+   integer i;
+   
+   always @*
+     begin
+	bin_val[width-1] = gray_val[width-1];
+	for(i=width-2;i>=0;i=i-1)
+	  bin_val[i] = bin_val[i+1] ^ gray_val[i];
+     end
+endmodule // gray2bin
diff --git a/usrp/fpga/sdr_lib/gen_cordic_consts.py b/usrp/fpga/sdr_lib/gen_cordic_consts.py
new file mode 100755
index 0000000000..ab66cfe01a
--- /dev/null
+++ b/usrp/fpga/sdr_lib/gen_cordic_consts.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+
+import math
+
+zwidth = 16
+
+for i in range(17):
+    c = math.atan (1.0/(2**i)) / (2 * math.pi) * (1 << zwidth)
+    print "`define c%02d %d'd%d" % (i, zwidth, round (c))
+    
diff --git a/usrp/fpga/sdr_lib/gen_sync.v b/usrp/fpga/sdr_lib/gen_sync.v
new file mode 100644
index 0000000000..d72b39d56e
--- /dev/null
+++ b/usrp/fpga/sdr_lib/gen_sync.v
@@ -0,0 +1,43 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+module gen_sync
+  ( input clock,
+    input reset,
+    input enable,
+    input [7:0] rate,
+    output wire sync );
+   
+//   parameter width = 8;
+   
+   reg [7:0] counter;
+   assign sync = |(((rate+1)>>1)& counter);
+      
+   always @(posedge clock)
+     if(reset || ~enable)
+       counter <= #1 0;
+     else if(counter == rate)
+       counter <= #1 0;
+     else 
+       counter <= #1 counter + 8'd1;
+   
+endmodule // gen_sync
+
diff --git a/usrp/fpga/sdr_lib/hb/acc.v b/usrp/fpga/sdr_lib/hb/acc.v
new file mode 100644
index 0000000000..195d5ea941
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/acc.v
@@ -0,0 +1,22 @@
+
+
+module acc (input clock, input reset, input clear, input enable_in, output reg enable_out,
+	    input signed [30:0] addend, output reg signed [33:0] sum );
+
+   always @(posedge clock)
+     if(reset)
+       sum <= #1 34'd0;
+     //else if(clear & enable_in)
+     //  sum <= #1 addend;
+     //else if(clear)
+     //  sum <= #1 34'd0;
+     else if(clear)
+       sum <= #1 addend;
+     else if(enable_in)
+       sum <= #1 sum + addend;
+
+   always @(posedge clock)
+     enable_out <= #1 enable_in;
+   
+endmodule // acc
+
diff --git a/usrp/fpga/sdr_lib/hb/coeff_ram.v b/usrp/fpga/sdr_lib/hb/coeff_ram.v
new file mode 100644
index 0000000000..65460822f8
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/coeff_ram.v
@@ -0,0 +1,26 @@
+
+
+module coeff_ram (input clock, input [3:0] rd_addr, output reg [15:0] rd_data);
+
+   always @(posedge clock)
+     case (rd_addr)
+       4'd0 : rd_data <= #1 -16'd16;
+       4'd1 : rd_data <= #1 16'd74;
+       4'd2 : rd_data <= #1 -16'd254;
+       4'd3 : rd_data <= #1 16'd669;
+       4'd4 : rd_data <= #1 -16'd1468;
+       4'd5 : rd_data <= #1 16'd2950;
+       4'd6 : rd_data <= #1 -16'd6158;
+       4'd7 : rd_data <= #1 16'd20585;
+       4'd8 : rd_data <= #1 16'd20585;
+       4'd9 : rd_data <= #1 -16'd6158;
+       4'd10 : rd_data <= #1 16'd2950;
+       4'd11 : rd_data <= #1 -16'd1468;
+       4'd12 : rd_data <= #1 16'd669;
+       4'd13 : rd_data <= #1 -16'd254;
+       4'd14 : rd_data <= #1 16'd74;
+       4'd15 : rd_data <= #1 -16'd16;
+       default : rd_data <= #1 16'd0;
+     endcase // case(rd_addr)
+   
+endmodule // ram
diff --git a/usrp/fpga/sdr_lib/hb/coeff_rom.v b/usrp/fpga/sdr_lib/hb/coeff_rom.v
new file mode 100644
index 0000000000..c287eaaad7
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/coeff_rom.v
@@ -0,0 +1,19 @@
+
+
+module coeff_rom (input clock, input [2:0] addr, output reg [15:0] data);
+
+   always @(posedge clock)
+     case (addr)
+       3'd0 : data <= #1 -16'd16;
+       3'd1 : data <= #1 16'd74;
+       3'd2 : data <= #1 -16'd254;
+       3'd3 : data <= #1 16'd669;
+       3'd4 : data <= #1 -16'd1468;
+       3'd5 : data <= #1 16'd2950;
+       3'd6 : data <= #1 -16'd6158;
+       3'd7 : data <= #1 16'd20585;
+     endcase // case(addr)
+      
+endmodule // coeff_rom
+
+
diff --git a/usrp/fpga/sdr_lib/hb/halfband_decim.v b/usrp/fpga/sdr_lib/hb/halfband_decim.v
new file mode 100644
index 0000000000..2a05ce52c6
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/halfband_decim.v
@@ -0,0 +1,163 @@
+/* -*- verilog -*-
+ * 
+ *  USRP - Universal Software Radio Peripheral
+ * 
+ *  Copyright (C) 2005 Matt Ettus
+ * 
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ * 
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ * 
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This implements a 31-tap halfband filter that decimates by two.
+ * The coefficients are symmetric, and with the exception of the middle tap,
+ * every other coefficient is zero.  The middle section of taps looks like this:
+ *
+ *  ..., -1468, 0, 2950, 0, -6158, 0, 20585, 32768, 20585, 0, -6158, 0, 2950, 0, -1468, ...
+ *                                             |
+ *                           middle tap -------+
+ *
+ * See coeff_rom.v for the full set.  The taps are scaled relative to 32768,
+ * thus the middle tap equals 1.0.  Not counting the middle tap, there are 8
+ * non-zero taps on each side, and they are symmetric.  A naive implementation
+ * requires a mulitply for each non-zero tap.  Because of symmetry, we can
+ * replace 2 multiplies with 1 add and 1 multiply.  Thus, to compute each output
+ * sample, we need to perform 8 multiplications.  Since the middle tap is 1.0,
+ * we just add the corresponding delay line value.
+ *
+ * About timing: We implement this with a single multiplier, so it takes
+ * 8 cycles to compute a single output.  However, since we're decimating by two 
+ * we can accept a new input value every 4 cycles.  strobe_in is asserted when
+ * there's a new input sample available.  Depending on the overall decimation
+ * rate, strobe_in may be asserted less frequently than once every 4 clocks.
+ * On the output side, we assert strobe_out when output contains a new sample.
+ *
+ * Implementation: Every time strobe_in is asserted we store the new data into
+ * the delay line.  We split the delay line into two components, one for the
+ * even samples, and one for the odd samples.  ram16_odd is the delay line for
+ * the odd samples.  This ram is written on each odd assertion of strobe_in, and
+ * is read on each clock when we're computing the dot product.  ram16_even is
+ * similar, although because it holds the even samples we must be able to read
+ * two samples from different addresses at the same time, while writing the incoming
+ * even samples. Thus it's "triple-ported".
+ */
+
+module halfband_decim
+  (input clock, input reset, input enable, input strobe_in, output wire strobe_out,
+   input wire [15:0] data_in, output reg [15:0] data_out,output wire [15:0] debugctrl);
+
+   reg [3:0] rd_addr1;
+   reg [3:0] rd_addr2;
+   reg [3:0] phase;
+   reg [3:0] base_addr;
+
+   wire      signed [15:0] mac_out,middle_data, sum, coeff;
+   wire      signed [30:0] product;
+   wire      signed [33:0] sum_even;
+   wire      clear;
+   reg 	     store_odd;
+   
+   always @(posedge clock)
+     if(reset)
+       store_odd <= #1 1'b0;
+     else
+       if(strobe_in)
+	 store_odd <= #1 ~store_odd;
+
+   wire      start = strobe_in & store_odd;
+   always @(posedge clock)
+     if(reset)
+       base_addr <= #1 4'd0;
+     else if(start)
+       base_addr <= #1 base_addr + 4'd1;
+
+   always @(posedge clock)
+     if(reset)
+       phase <= #1 4'd8;
+     else if (start)
+       phase <= #1 4'd0;
+     else if(phase != 4'd8)
+       phase <= #1 phase + 4'd1;
+
+   reg 	     start_d1,start_d2,start_d3,start_d4,start_d5,start_d6,start_d7,start_d8,start_d9,start_dA,start_dB,start_dC,start_dD;
+   always @(posedge clock)
+     begin
+	start_d1 <= #1 start;
+	start_d2 <= #1 start_d1;
+	start_d3 <= #1 start_d2;
+	start_d4 <= #1 start_d3;
+	start_d5 <= #1 start_d4;
+	start_d6 <= #1 start_d5;
+	start_d7 <= #1 start_d6;
+	start_d8 <= #1 start_d7;
+	start_d9 <= #1 start_d8;
+	start_dA <= #1 start_d9;
+	start_dB <= #1 start_dA;
+	start_dC <= #1 start_dB;
+	start_dD <= #1 start_dC;
+     end // always @ (posedge clock)
+   
+   reg 	  mult_en, mult_en_pre;
+   always @(posedge clock)
+     begin
+	mult_en_pre <= #1 phase!=8;
+	mult_en <= #1 mult_en_pre;
+     end
+   
+   assign clear = start_d4; // was dC
+   wire   latch_result = start_d4; // was dC
+   assign strobe_out = start_d5; // was dD
+   wire   acc_en;
+   
+   always @*
+     case(phase[2:0])
+       3'd0 : begin rd_addr1 = base_addr + 4'd0; rd_addr2 = base_addr + 4'd15; end
+       3'd1 : begin rd_addr1 = base_addr + 4'd1; rd_addr2 = base_addr + 4'd14; end
+       3'd2 : begin rd_addr1 = base_addr + 4'd2; rd_addr2 = base_addr + 4'd13; end
+       3'd3 : begin rd_addr1 = base_addr + 4'd3; rd_addr2 = base_addr + 4'd12; end
+       3'd4 : begin rd_addr1 = base_addr + 4'd4; rd_addr2 = base_addr + 4'd11; end
+       3'd5 : begin rd_addr1 = base_addr + 4'd5; rd_addr2 = base_addr + 4'd10; end
+       3'd6 : begin rd_addr1 = base_addr + 4'd6; rd_addr2 = base_addr + 4'd9; end
+       3'd7 : begin rd_addr1 = base_addr + 4'd7; rd_addr2 = base_addr + 4'd8; end
+       default: begin rd_addr1 = base_addr + 4'd0; rd_addr2 = base_addr + 4'd15; end
+     endcase // case(phase)
+   
+   coeff_rom coeff_rom (.clock(clock),.addr(phase[2:0]-3'd1),.data(coeff));
+   
+   ram16_2sum ram16_even (.clock(clock),.write(strobe_in & ~store_odd),
+			  .wr_addr(base_addr),.wr_data(data_in),
+			  .rd_addr1(rd_addr1),.rd_addr2(rd_addr2),
+			  .sum(sum));
+
+   ram16 ram16_odd (.clock(clock),.write(strobe_in & store_odd),  // Holds middle items
+		    .wr_addr(base_addr),.wr_data(data_in),
+		    //.rd_addr(base_addr+4'd7),.rd_data(middle_data));
+		    .rd_addr(base_addr+4'd6),.rd_data(middle_data));
+
+   mult mult(.clock(clock),.x(coeff),.y(sum),.product(product),.enable_in(mult_en),.enable_out(acc_en));
+
+   acc acc(.clock(clock),.reset(reset),.enable_in(acc_en),.enable_out(),
+	   .clear(clear),.addend(product),.sum(sum_even));
+
+   wire signed [33:0] dout = sum_even + {{4{middle_data[15]}},middle_data,14'b0}; // We already divided product by 2!!!!
+
+   always @(posedge clock)
+     if(reset)
+       data_out <= #1 16'd0;
+     else if(latch_result)
+       data_out <= #1 dout[30:15] + (dout[33]& |dout[14:0]);
+
+   assign  debugctrl = { clock,reset,acc_en,mult_en,clear,latch_result,store_odd,strobe_in,strobe_out,phase};
+   
+endmodule // halfband_decim
diff --git a/usrp/fpga/sdr_lib/hb/halfband_interp.v b/usrp/fpga/sdr_lib/hb/halfband_interp.v
new file mode 100644
index 0000000000..cdb11c1f6b
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/halfband_interp.v
@@ -0,0 +1,121 @@
+
+
+module halfband_interp 
+  (input clock, input reset, input enable,
+   input strobe_in, input strobe_out,
+   input [15:0] signal_in_i, input [15:0] signal_in_q, 
+   output reg [15:0] signal_out_i, output reg [15:0] signal_out_q,
+   output wire [12:0] debug);
+   
+   wire [15:0] 	coeff_ram_out;
+   wire [15:0] 	data_ram_out_i;
+   wire [15:0] 	data_ram_out_q;
+
+   wire [3:0] 	data_rd_addr;
+   reg [3:0] 	data_wr_addr;
+   reg [2:0] 	coeff_rd_addr;
+
+   wire 		filt_done;
+   
+   wire [15:0] 	mac_out_i;
+   wire [15:0] 	mac_out_q;
+   reg [15:0] 	delayed_middle_i, delayed_middle_q;
+   wire [7:0] 	shift = 8'd9;
+
+   reg 		stb_out_happened;
+
+   wire [15:0] 	data_ram_out_i_b;
+   
+   always @(posedge clock)
+     if(strobe_in)
+       stb_out_happened <= #1 1'b0;
+     else if(strobe_out)
+       stb_out_happened <= #1 1'b1;
+   
+assign debug = {filt_done,data_rd_addr,data_wr_addr,coeff_rd_addr};
+
+   wire [15:0] 	signal_out_i = stb_out_happened ? mac_out_i : delayed_middle_i;
+   wire [15:0] 	signal_out_q = stb_out_happened ? mac_out_q : delayed_middle_q;
+
+/*   always @(posedge clock)
+     if(reset)
+       begin
+	  signal_out_i <= #1 16'd0;
+	  signal_out_q <= #1 16'd0;
+       end
+     else if(strobe_in)
+       begin
+	  signal_out_i <= #1 delayed_middle_i; // Multiply by 1 for middle coeff
+	  signal_out_q <= #1 delayed_middle_q;
+       end
+     //else if(filt_done&stb_out_happened)
+     else if(stb_out_happened)
+       begin
+	  signal_out_i <= #1 mac_out_i;
+	  signal_out_q <= #1 mac_out_q;
+       end
+*/
+   
+   always @(posedge clock)
+     if(reset)
+       coeff_rd_addr <= #1 3'd0;
+     else if(coeff_rd_addr != 3'd0)
+       coeff_rd_addr <= #1 coeff_rd_addr + 3'd1;
+     else if(strobe_in)
+       coeff_rd_addr <= #1 3'd1;
+
+   reg filt_done_d1;
+   always@(posedge clock)
+     filt_done_d1 <= #1 filt_done;
+   
+   always @(posedge clock)
+     if(reset)
+       data_wr_addr <= #1 4'd0;
+   //else if(strobe_in)
+     else if(filt_done & ~filt_done_d1)
+       data_wr_addr <= #1 data_wr_addr + 4'd1;
+
+   always @(posedge clock)
+     if(coeff_rd_addr == 3'd7)
+       begin
+	  delayed_middle_i <= #1 data_ram_out_i_b;
+	//  delayed_middle_q <= #1 data_ram_out_q_b;
+       end
+   
+//   always @(posedge clock)
+//     if(reset)
+//       data_rd_addr <= #1 4'd0;
+//     else if(strobe_in)
+//       data_rd_addr <= #1 data_wr_addr + 4'd1;
+//     else if(!filt_done)
+//       data_rd_addr <= #1 data_rd_addr + 4'd1;
+//     else
+//       data_rd_addr <= #1 data_wr_addr;
+  
+   wire [3:0] data_rd_addr1 = data_wr_addr + {1'b0,coeff_rd_addr};
+   wire [3:0] data_rd_addr2 = data_wr_addr + 15 - {1'b0,coeff_rd_addr};
+//   always @(posedge clock)
+//     if(reset)
+//       filt_done <= #1 1'b1;
+//     else if(strobe_in)
+ //      filt_done <= #1 1'b0;
+//     else if(coeff_rd_addr == 4'd0)
+//       filt_done <= #1 1'b1;
+
+   assign filt_done = (coeff_rd_addr == 3'd0);
+   
+   coeff_ram coeff_ram ( .clock(clock),.rd_addr({1'b0,coeff_rd_addr}),.rd_data(coeff_ram_out) );
+   
+   ram16_2sum data_ram_i ( .clock(clock),.write(strobe_in),.wr_addr(data_wr_addr),.wr_data(signal_in_i),
+		      .rd_addr1(data_rd_addr1),.rd_addr2(data_rd_addr2),.rd_data(data_ram_out_i_b),.sum(data_ram_out_i));
+   
+   ram16_2sum data_ram_q ( .clock(clock),.write(strobe_in),.wr_addr(data_wr_addr),.wr_data(signal_in_q),
+		      .rd_addr1(data_rd_addr1),.rd_addr2(data_rd_addr2),.rd_data(data_ram_out_q));
+   
+   mac mac_i (.clock(clock),.reset(reset),.enable(~filt_done),.clear(strobe_in),
+	      .x(data_ram_out_i),.y(coeff_ram_out),.shift(shift),.z(mac_out_i) );
+   
+   mac mac_q (.clock(clock),.reset(reset),.enable(~filt_done),.clear(strobe_in),
+	      .x(data_ram_out_q),.y(coeff_ram_out),.shift(shift),.z(mac_out_q) );
+
+endmodule // halfband_interp
diff --git a/usrp/fpga/sdr_lib/hb/hbd_tb/HBD b/usrp/fpga/sdr_lib/hb/hbd_tb/HBD
new file mode 100644
index 0000000000..574fbba91d
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/hbd_tb/HBD
@@ -0,0 +1,80 @@
+*-6.432683 5736 -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
+test_hbd.clock
+test_hbd.reset
+@420
+test_hbd.halfband_decim.middle_data[15:0]
+@22
+test_hbd.halfband_decim.sum_even[33:0]
+test_hbd.halfband_decim.base_addr[3:0]
+@420
+test_hbd.i_in[15:0]
+@24
+test_hbd.halfband_decim.phase[3:0]
+test_hbd.halfband_decim.ram16_even.rd_addr1[3:0]
+test_hbd.halfband_decim.ram16_even.rd_addr2[3:0]
+test_hbd.halfband_decim.ram16_even.wr_addr[3:0]
+test_hbd.halfband_decim.ram16_even.wr_data[15:0]
+@28
+test_hbd.halfband_decim.ram16_even.write
+@420
+test_hbd.halfband_decim.sum[15:0]
+test_hbd.halfband_decim.product[30:0]
+test_hbd.halfband_decim.dout[33:0]
+test_hbd.halfband_decim.sum_even[33:0]
+@22
+test_hbd.halfband_decim.acc.addend[30:0]
+@28
+test_hbd.halfband_decim.acc.reset
+@420
+test_hbd.halfband_decim.acc.sum[33:0]
+test_hbd.halfband_decim.mult.x[15:0]
+test_hbd.halfband_decim.mult.y[15:0]
+@28
+test_hbd.halfband_decim.acc.clear
+test_hbd.strobe_in
+test_hbd.strobe_out
+test_hbd.halfband_decim.acc_en
+@420
+test_hbd.i_out[15:0]
+@28
+test_hbd.halfband_decim.mult_en
+test_hbd.halfband_decim.latch_result
+@420
+test_hbd.halfband_decim.sum[15:0]
+test_hbd.halfband_decim.sum_even[33:0]
+test_hbd.halfband_decim.dout[33:0]
+test_hbd.halfband_decim.data_out[15:0]
+@22
+test_hbd.halfband_decim.data_out[15:0]
+@28
+test_hbd.halfband_decim.dout[33:0]
+@29
+test_hbd.halfband_decim.acc_en
+@22
+test_hbd.halfband_decim.base_addr[3:0]
+@28
+test_hbd.halfband_decim.clear
+test_hbd.halfband_decim.latch_result
+test_hbd.halfband_decim.mult_en
+test_hbd.halfband_decim.mult_en_pre
+@22
+test_hbd.halfband_decim.phase[3:0]
+@28
+test_hbd.halfband_decim.start
+test_hbd.halfband_decim.start_d1
+test_hbd.halfband_decim.start_d2
+test_hbd.halfband_decim.start_d3
+test_hbd.halfband_decim.start_d4
+test_hbd.halfband_decim.start_d5
+test_hbd.halfband_decim.start_d6
+test_hbd.halfband_decim.start_d7
+test_hbd.halfband_decim.start_d8
+test_hbd.halfband_decim.start_d9
+test_hbd.halfband_decim.start_dA
+test_hbd.halfband_decim.start_dB
+test_hbd.halfband_decim.start_dC
+test_hbd.halfband_decim.start_dD
+test_hbd.halfband_decim.store_odd
+test_hbd.halfband_decim.strobe_in
+test_hbd.halfband_decim.strobe_out
diff --git a/usrp/fpga/sdr_lib/hb/hbd_tb/really_golden b/usrp/fpga/sdr_lib/hb/hbd_tb/really_golden
new file mode 100644
index 0000000000..2d24a9e149
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/hbd_tb/really_golden
@@ -0,0 +1,142 @@
+VCD info: dumpfile test_hbd.vcd opened for output.
+    x
+    x
+    x
+    x
+    x
+    x
+    x
+    x
+    x
+    x
+    x
+    x
+    x
+    x
+    x
+    x
+    0
+    0
+    0
+    0
+    0
+    0
+    0
+    0
+    0
+    0
+    0
+ 8192
+    0
+    0
+    0
+    0
+    0
+    0
+    0
+    0
+    0
+    0
+    0
+    0
+    0
+-     4
+   18
+-    63
+  167
+-   367
+  737
+-  1539
+ 5146
+ 5146
+-  1539
+  737
+-   367
+  167
+-    63
+   18
+-     4
+    0
+    0
+    0
+    0
+    0
+-     4
+   14
+-    49
+  118
+-   249
+  488
+ 7141
+12287
+17433
+15894
+16631
+16264
+16432
+16368
+16387
+16383
+16383
+16383
+16383
+16383
+16387
+16368
+16432
+16264
+16631
+15894
+ 9241
+ 4095
+-  1051
+  488
+-   249
+  118
+-    49
+   14
+-     4
+    0
+    0
+    0
+    0
+    0
+-     4
+   14
+-    49
+  118
+-   249
+  488
+-  1051
+12287
+17433
+15894
+16631
+16264
+16432
+16368
+16387
+16383
+16383
+16383
+16383
+16383
+16387
+16368
+16432
+16264
+16631
+15894
+17433
+ 4095
+-  1051
+  488
+-   249
+  118
+-    49
+   14
+-     4
+    0
+    0
+    0
+    0
diff --git a/usrp/fpga/sdr_lib/hb/hbd_tb/regression b/usrp/fpga/sdr_lib/hb/hbd_tb/regression
new file mode 100644
index 0000000000..fc279c2f2a
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/hbd_tb/regression
@@ -0,0 +1,95 @@
+echo "Baseline 1000"
+iverilog -y .. -o test_hbd -DRATE=1000 test_hbd.v  ; ./test_hbd >golden
+diff golden really_golden
+
+echo
+echo "Test 100"
+iverilog -y .. -o test_hbd -DRATE=100 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 50"
+iverilog -y .. -o test_hbd -DRATE=50 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 40"
+iverilog -y .. -o test_hbd -DRATE=40 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 30"
+iverilog -y .. -o test_hbd -DRATE=30 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 25"
+iverilog -y .. -o test_hbd -DRATE=25 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 20"
+iverilog -y .. -o test_hbd -DRATE=20 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 19"
+iverilog -y .. -o test_hbd -DRATE=19 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 18"
+iverilog -y .. -o test_hbd -DRATE=18 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 17"
+iverilog -y .. -o test_hbd -DRATE=17 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 16"
+iverilog -y .. -o test_hbd -DRATE=16 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 15"
+iverilog -y .. -o test_hbd -DRATE=15 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 14"
+iverilog -y .. -o test_hbd -DRATE=14 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 13"
+iverilog -y .. -o test_hbd -DRATE=13 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 12"
+iverilog -y .. -o test_hbd -DRATE=12 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 11"
+iverilog -y .. -o test_hbd -DRATE=11 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 10"
+iverilog -y .. -o test_hbd -DRATE=10 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 9"
+iverilog -y .. -o test_hbd -DRATE=9 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 8"
+iverilog -y .. -o test_hbd -DRATE=8 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 7"
+iverilog -y .. -o test_hbd -DRATE=7 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 6"
+iverilog -y .. -o test_hbd -DRATE=6 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 5"
+iverilog -y .. -o test_hbd -DRATE=5 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 4"
+iverilog -y .. -o test_hbd -DRATE=4 test_hbd.v  ; ./test_hbd >output ; diff output golden
+
+echo
+echo "Test 3"
+iverilog -y .. -o test_hbd -DRATE=3 test_hbd.v  ; ./test_hbd >output ; diff output golden
diff --git a/usrp/fpga/sdr_lib/hb/hbd_tb/run_hbd b/usrp/fpga/sdr_lib/hb/hbd_tb/run_hbd
new file mode 100755
index 0000000000..b8aec75741
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/hbd_tb/run_hbd
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+iverilog -y .. -o test_hbd test_hbd.v
+./test_hbd
diff --git a/usrp/fpga/sdr_lib/hb/hbd_tb/test_hbd.v b/usrp/fpga/sdr_lib/hb/hbd_tb/test_hbd.v
new file mode 100644
index 0000000000..01ab5e7e0d
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/hbd_tb/test_hbd.v
@@ -0,0 +1,75 @@
+
+
+module test_hbd();
+
+   reg clock;
+   initial clock = 1'b0;
+   always #5 clock <= ~clock;
+
+   reg reset;
+   initial reset = 1'b1;
+   initial #1000 reset = 1'b0;
+   
+   initial $dumpfile("test_hbd.vcd");
+   initial $dumpvars(0,test_hbd);
+
+   reg [15:0] i_in, q_in;
+   wire [15:0] i_out, q_out;
+
+   reg 	       strobe_in;
+   wire        strobe_out;
+   reg 	       coeff_write;
+   reg [15:0]  coeff_data;
+   reg [4:0]   coeff_addr;
+   
+   halfband_decim halfband_decim 
+     ( .clock(clock),.reset(reset),.enable(),.strobe_in(strobe_in),.strobe_out(strobe_out),
+       .data_in(i_in),.data_out(i_out) );
+   
+   always @(posedge strobe_out)
+     if(i_out[15])
+       $display("-%d",65536-i_out);
+     else
+       $display("%d",i_out);
+
+   initial
+     begin
+	strobe_in = 1'b0;
+	@(negedge reset);
+	@(posedge clock);
+	while(1)
+	  begin
+	     strobe_in <= #1 1'b1;
+	     @(posedge clock);
+	     strobe_in <= #1 1'b0;
+	     repeat (`RATE)
+	       @(posedge clock);
+	  end
+     end
+
+   initial #10000000 $finish;    // Just in case...
+
+   initial
+     begin
+	i_in <= #1 16'd0;
+	repeat (40) @(posedge strobe_in);
+	i_in <= #1 16'd16384;
+	@(posedge strobe_in);
+	i_in <= #1 16'd0;
+	repeat (40) @(posedge strobe_in);
+	i_in <= #1 16'd16384;
+	@(posedge strobe_in);
+	i_in <= #1 16'd0;
+	repeat (40) @(posedge strobe_in);
+	i_in <= #1 16'd16384;
+	repeat (40) @(posedge strobe_in);
+	i_in <= #1 16'd0;
+	repeat (41) @(posedge strobe_in);
+	i_in <= #1 16'd16384;
+	repeat (40) @(posedge strobe_in);
+	i_in <= #1 16'd0;
+	repeat (40) @(posedge strobe_in);
+	repeat (7) @(posedge clock);
+	$finish;
+     end // initial begin
+endmodule // test_hb
diff --git a/usrp/fpga/sdr_lib/hb/mac.v b/usrp/fpga/sdr_lib/hb/mac.v
new file mode 100644
index 0000000000..5a270bc73f
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/mac.v
@@ -0,0 +1,58 @@
+
+
+module mac (input clock, input reset, input enable, input clear,
+	    input signed [15:0] x, input signed [15:0] y,
+	    input [7:0] shift, output [15:0] z );
+
+   reg signed [30:0] product;
+   reg signed [39:0] z_int;
+   reg signed [15:0] z_shift;
+
+   reg enable_d1;
+   always @(posedge clock)
+     enable_d1 <= #1 enable;
+   
+   always @(posedge clock)
+     if(reset | clear)
+       z_int <= #1 40'd0;
+     else if(enable_d1)
+       z_int <= #1 z_int + {{9{product[30]}},product};
+
+   always @(posedge clock)
+     product <= #1 x*y;
+
+   always @*   // FIXME full case? parallel case?
+     case(shift)
+       //8'd0 : z_shift <= z_int[39:24];
+       //8'd1 : z_shift <= z_int[38:23];
+       //8'd2 : z_shift <= z_int[37:22];
+       //8'd3 : z_shift <= z_int[36:21];
+       //8'd4 : z_shift <= z_int[35:20];
+       //8'd5 : z_shift <= z_int[34:19];
+       8'd6 : z_shift <= z_int[33:18];
+       8'd7 : z_shift <= z_int[32:17];
+       8'd8 : z_shift <= z_int[31:16];
+       8'd9 : z_shift <= z_int[30:15];
+       8'd10 : z_shift <= z_int[29:14];
+       8'd11 : z_shift <= z_int[28:13];
+       //8'd12 : z_shift <= z_int[27:12];
+       //8'd13 : z_shift <= z_int[26:11];
+       //8'd14 : z_shift <= z_int[25:10];
+       //8'd15 : z_shift <= z_int[24:9];
+       //8'd16 : z_shift <= z_int[23:8];
+       //8'd17 : z_shift <= z_int[22:7];
+       //8'd18 : z_shift <= z_int[21:6];
+       //8'd19 : z_shift <= z_int[20:5];
+       //8'd20 : z_shift <= z_int[19:4];
+       //8'd21 : z_shift <= z_int[18:3];
+       //8'd22 : z_shift <= z_int[17:2];
+       //8'd23 : z_shift <= z_int[16:1];
+       //8'd24 : z_shift <= z_int[15:0];
+       default : z_shift <= z_int[15:0];
+     endcase // case(shift)
+   
+   // FIXME do we need to saturate?
+   //assign z = z_shift;
+   assign z = z_int[15:0];
+   
+endmodule // mac
diff --git a/usrp/fpga/sdr_lib/hb/mult.v b/usrp/fpga/sdr_lib/hb/mult.v
new file mode 100644
index 0000000000..a8d4cb1b74
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/mult.v
@@ -0,0 +1,16 @@
+
+
+module mult (input clock, input signed [15:0] x, input signed [15:0] y, output reg signed [30:0] product,
+	     input enable_in, output reg enable_out );
+
+   always @(posedge clock)
+     if(enable_in)
+       product <= #1 x*y;
+     else
+       product <= #1 31'd0;
+   
+   always @(posedge clock)
+     enable_out <= #1 enable_in;
+   
+endmodule // mult
+
diff --git a/usrp/fpga/sdr_lib/hb/ram16_2port.v b/usrp/fpga/sdr_lib/hb/ram16_2port.v
new file mode 100644
index 0000000000..e1761a9261
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/ram16_2port.v
@@ -0,0 +1,22 @@
+
+
+module ram16_2port (input clock, input write, 
+		    input [3:0] wr_addr, input [15:0] wr_data,
+		    input [3:0] rd_addr1, output reg [15:0] rd_data1,
+		    input [3:0] rd_addr2, output reg [15:0] rd_data2);
+   
+   reg [15:0] 			ram_array [0:31];
+   
+   always @(posedge clock)
+     rd_data1 <= #1 ram_array[rd_addr1];
+   
+   always @(posedge clock)
+     rd_data2 <= #1 ram_array[rd_addr2];
+   
+   always @(posedge clock)
+     if(write)
+       ram_array[wr_addr] <= #1 wr_data;
+   
+endmodule // ram16_2port
+
+
diff --git a/usrp/fpga/sdr_lib/hb/ram16_2sum.v b/usrp/fpga/sdr_lib/hb/ram16_2sum.v
new file mode 100644
index 0000000000..559b06fd58
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/ram16_2sum.v
@@ -0,0 +1,27 @@
+
+
+module ram16_2sum (input clock, input write, 
+		   input [3:0] wr_addr, input [15:0] wr_data,
+		   input [3:0] rd_addr1, input [3:0] rd_addr2,
+                   output reg [15:0] sum);
+   
+   reg signed [15:0] 	  ram_array [0:15];
+   reg signed [15:0] 	  a,b;
+   wire signed [16:0] 	  sum_int;
+   
+   always @(posedge clock)
+     if(write)
+       ram_array[wr_addr] <= #1 wr_data;
+      
+   always @(posedge clock)
+     begin
+	a <= #1 ram_array[rd_addr1];
+	b <= #1 ram_array[rd_addr2];
+     end
+   
+   assign sum_int = {a[15],a} + {b[15],b};
+   
+   always @(posedge clock)
+     sum <= #1 sum_int[16:1] + (sum_int[16]&sum_int[0]);
+     
+endmodule // ram16_2sum
diff --git a/usrp/fpga/sdr_lib/hb/ram32_2sum.v b/usrp/fpga/sdr_lib/hb/ram32_2sum.v
new file mode 100644
index 0000000000..d1f55b7d0f
--- /dev/null
+++ b/usrp/fpga/sdr_lib/hb/ram32_2sum.v
@@ -0,0 +1,22 @@
+
+
+module ram32_2sum (input clock, input write, 
+		   input [4:0] wr_addr, input [15:0] wr_data,
+		   input [4:0] rd_addr1, input [4:0] rd_addr2,
+		   output reg [15:0] sum);
+   
+   reg [15:0] 			ram_array [0:31];
+   wire [16:0] 			sum_int;
+   
+   always @(posedge clock)
+     if(write)
+       ram_array[wr_addr] <= #1 wr_data;
+
+   assign sum_int = ram_array[rd_addr1] + ram_array[rd_addr2];
+
+   always @(posedge clock)
+     sum <= #1 sum_int[16:1] + (sum_int[16]&sum_int[0]);
+
+   
+endmodule // ram32_2sum
+
diff --git a/usrp/fpga/sdr_lib/io_pins.v b/usrp/fpga/sdr_lib/io_pins.v
new file mode 100644
index 0000000000..da20b3b035
--- /dev/null
+++ b/usrp/fpga/sdr_lib/io_pins.v
@@ -0,0 +1,52 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2005,2006 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+`include "../../firmware/include/fpga_regs_common.v"
+`include "../../firmware/include/fpga_regs_standard.v"
+
+module io_pins
+  ( inout wire [15:0] io_0, inout wire [15:0] io_1, inout wire [15:0] io_2, inout wire [15:0] io_3,
+    input wire [15:0] reg_0, input wire [15:0] reg_1, input wire [15:0] reg_2, input wire [15:0] reg_3,
+    input clock, input rx_reset, input tx_reset,
+    input [6:0] serial_addr, input [31:0] serial_data, input serial_strobe);
+   
+   reg [15:0] io_0_oe,io_1_oe,io_2_oe,io_3_oe;
+   
+   bidir_reg bidir_reg_0 (.tristate(io_0),.oe(io_0_oe),.reg_val(reg_0));
+   bidir_reg bidir_reg_1 (.tristate(io_1),.oe(io_1_oe),.reg_val(reg_1));
+   bidir_reg bidir_reg_2 (.tristate(io_2),.oe(io_2_oe),.reg_val(reg_2));
+   bidir_reg bidir_reg_3 (.tristate(io_3),.oe(io_3_oe),.reg_val(reg_3));
+   
+   // Upper 16 bits are mask for lower 16
+   always @(posedge clock)
+     if(serial_strobe)
+       case(serial_addr)
+	 `FR_OE_0 : io_0_oe
+	   <= #1 (io_0_oe & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] );
+	 `FR_OE_1 : io_1_oe
+	   <= #1 (io_1_oe & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] );
+	 `FR_OE_2 : io_2_oe
+	   <= #1 (io_2_oe & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] );
+	 `FR_OE_3 : io_3_oe
+	   <= #1 (io_3_oe & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] );
+       endcase // case(serial_addr)
+
+endmodule // io_pins
diff --git a/usrp/fpga/sdr_lib/master_control.v b/usrp/fpga/sdr_lib/master_control.v
new file mode 100644
index 0000000000..d42817c729
--- /dev/null
+++ b/usrp/fpga/sdr_lib/master_control.v
@@ -0,0 +1,155 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003,2005 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+// Clock, enable, and reset controls for whole system
+
+module master_control
+  ( input master_clk, input usbclk,
+    input wire [6:0] serial_addr, input wire [31:0] serial_data, input wire serial_strobe,
+    output tx_bus_reset, output rx_bus_reset,
+    output wire tx_dsp_reset, output wire rx_dsp_reset,
+    output wire enable_tx, output wire enable_rx,
+    output wire [7:0] interp_rate, output wire [7:0] decim_rate,
+    output tx_sample_strobe, output strobe_interp,
+    output rx_sample_strobe, output strobe_decim,
+    input tx_empty,
+    input wire [15:0] debug_0,input wire [15:0] debug_1,input wire [15:0] debug_2,input wire [15:0] debug_3,
+    output wire [15:0] reg_0, output wire [15:0] reg_1, output wire [15:0] reg_2, output wire [15:0] reg_3
+    );
+   
+   // FIXME need a separate reset for all control settings 
+   // Master Controls assignments
+   wire [7:0] master_controls;
+   setting_reg #(`FR_MASTER_CTRL) sr_mstr_ctrl(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(master_controls));
+   assign     enable_tx = master_controls[0];
+   assign     enable_rx = master_controls[1];
+   assign     tx_dsp_reset = master_controls[2];
+   assign     rx_dsp_reset = master_controls[3];
+   // Unused - 4-7
+
+   // Strobe Generators
+   setting_reg #(`FR_INTERP_RATE) sr_interp(.clock(master_clk),.reset(tx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(interp_rate));
+   setting_reg #(`FR_DECIM_RATE) sr_decim(.clock(master_clk),.reset(rx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(decim_rate));
+   
+   strobe_gen da_strobe_gen
+     ( .clock(master_clk),.reset(tx_dsp_reset),.enable(enable_tx),
+       .rate(8'd1),.strobe_in(1'b1),.strobe(tx_sample_strobe) );
+
+   strobe_gen tx_strobe_gen
+     ( .clock(master_clk),.reset(tx_dsp_reset),.enable(enable_tx),
+       .rate(interp_rate),.strobe_in(tx_sample_strobe),.strobe(strobe_interp) );
+
+   assign  rx_sample_strobe = 1'b1;
+   
+   strobe_gen decim_strobe_gen
+     ( .clock(master_clk),.reset(rx_dsp_reset),.enable(enable_rx),
+       .rate(decim_rate),.strobe_in(rx_sample_strobe),.strobe(strobe_decim) );
+   
+   // Reset syncs for bus (usbclk) side
+   // The RX bus side reset isn't used, the TX bus side one may not be needed
+   reg 	  tx_reset_bus_sync1, rx_reset_bus_sync1, tx_reset_bus_sync2, rx_reset_bus_sync2;
+ 	   
+   always @(posedge usbclk)
+     begin
+   	tx_reset_bus_sync1 <= #1 tx_dsp_reset;
+   	rx_reset_bus_sync1 <= #1 rx_dsp_reset;
+   	tx_reset_bus_sync2 <= #1 tx_reset_bus_sync1;
+   	rx_reset_bus_sync2 <= #1 rx_reset_bus_sync1;
+     end
+
+   assign tx_bus_reset = tx_reset_bus_sync2;
+   assign rx_bus_reset = rx_reset_bus_sync2;
+
+   wire [7:0]   txa_refclk, rxa_refclk, txb_refclk, rxb_refclk;
+   wire        txaclk,txbclk,rxaclk,rxbclk;
+   wire [3:0]  debug_en, txcvr_ctrl;
+
+   wire [31:0] txcvr_rxlines, txcvr_txlines;
+      
+   setting_reg #(`FR_TX_A_REFCLK) sr_txaref(.clock(master_clk),.reset(tx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(txa_refclk));
+   setting_reg #(`FR_RX_A_REFCLK) sr_rxaref(.clock(master_clk),.reset(rx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(rxa_refclk));
+   setting_reg #(`FR_TX_B_REFCLK) sr_txbref(.clock(master_clk),.reset(tx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(txb_refclk));
+   setting_reg #(`FR_RX_B_REFCLK) sr_rxbref(.clock(master_clk),.reset(rx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(rxb_refclk));
+
+   setting_reg #(`FR_DEBUG_EN) sr_debugen(.clock(master_clk),.reset(rx_dsp_reset|tx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(debug_en));
+         
+   clk_divider clk_div_0 (.reset(tx_dsp_reset),.in_clk(master_clk),.out_clk(txaclk),.ratio(txa_refclk[6:0]));
+   clk_divider clk_div_1 (.reset(rx_dsp_reset),.in_clk(master_clk),.out_clk(rxaclk),.ratio(rxa_refclk[6:0]));
+   clk_divider clk_div_2 (.reset(tx_dsp_reset),.in_clk(master_clk),.out_clk(txbclk),.ratio(txb_refclk[6:0]));
+   clk_divider clk_div_3 (.reset(rx_dsp_reset),.in_clk(master_clk),.out_clk(rxbclk),.ratio(rxb_refclk[6:0]));
+   
+   reg [15:0]  io_0_reg,io_1_reg,io_2_reg,io_3_reg;
+   // Upper 16 bits are mask for lower 16
+   always @(posedge master_clk)
+     if(serial_strobe)
+       case(serial_addr)
+	 `FR_IO_0 : io_0_reg
+	   <= #1 (io_0_reg & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] );
+	 `FR_IO_1 : io_1_reg
+	   <= #1 (io_1_reg & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] );
+	 `FR_IO_2 : io_2_reg
+	   <= #1 (io_2_reg & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] );
+	 `FR_IO_3 : io_3_reg
+	   <= #1 (io_3_reg & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] );
+       endcase // case(serial_addr)
+
+   wire        transmit_now = !tx_empty & enable_tx;
+   wire        atr_ctl;
+   wire [15:0] atr_mask_0, atr_txval_0, atr_rxval_0, atr_mask_1, atr_txval_1, atr_rxval_1, atr_mask_2, atr_txval_2, atr_rxval_2, atr_mask_3, atr_txval_3, atr_rxval_3;
+      
+   setting_reg #(`FR_ATR_MASK_0) sr_atr_mask_0(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_mask_0));
+   setting_reg #(`FR_ATR_TXVAL_0) sr_atr_txval_0(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_txval_0));
+   setting_reg #(`FR_ATR_RXVAL_0) sr_atr_rxval_0(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_rxval_0));
+
+   setting_reg #(`FR_ATR_MASK_1) sr_atr_mask_1(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_mask_1));
+   setting_reg #(`FR_ATR_TXVAL_1) sr_atr_txval_1(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_txval_1));
+   setting_reg #(`FR_ATR_RXVAL_1) sr_atr_rxval_1(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_rxval_1));
+
+   setting_reg #(`FR_ATR_MASK_2) sr_atr_mask_2(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_mask_2));
+   setting_reg #(`FR_ATR_TXVAL_2) sr_atr_txval_2(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_txval_2));
+   setting_reg #(`FR_ATR_RXVAL_2) sr_atr_rxval_2(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_rxval_2));
+
+   setting_reg #(`FR_ATR_MASK_3) sr_atr_mask_3(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_mask_3));
+   setting_reg #(`FR_ATR_TXVAL_3) sr_atr_txval_3(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_txval_3));
+   setting_reg #(`FR_ATR_RXVAL_3) sr_atr_rxval_3(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_rxval_3));
+
+   //setting_reg #(`FR_ATR_CTL) sr_atr_ctl(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_ctl));
+   assign      atr_ctl = 1'b1;
+
+   wire [15:0] atr_selected_0 = transmit_now ? atr_txval_0 : atr_rxval_0;
+   wire [15:0] io_0 = ({{16{atr_ctl}}} &  atr_mask_0 & atr_selected_0) | (~({{16{atr_ctl}}} & atr_mask_0) & io_0_reg);
+   
+   wire [15:0] atr_selected_1 = transmit_now ? atr_txval_1 : atr_rxval_1;
+   wire [15:0] io_1 = ({{16{atr_ctl}}} &  atr_mask_1 & atr_selected_1) | (~({{16{atr_ctl}}} & atr_mask_1) & io_1_reg);
+   
+   wire [15:0] atr_selected_2 = transmit_now ? atr_txval_2 : atr_rxval_2;
+   wire [15:0] io_2 = ({{16{atr_ctl}}} &  atr_mask_2 & atr_selected_2) | (~({{16{atr_ctl}}} & atr_mask_2) & io_2_reg);
+   
+   wire [15:0] atr_selected_3 = transmit_now ? atr_txval_3 : atr_rxval_3;
+   wire [15:0] io_3 = ({{16{atr_ctl}}} &  atr_mask_3 & atr_selected_3) | (~({{16{atr_ctl}}} & atr_mask_3) & io_3_reg);
+   
+   assign reg_0 = debug_en[0] ? debug_0 : txa_refclk[7] ? {io_0[15:1],txaclk} : io_0;
+   assign reg_1 = debug_en[1] ? debug_1 : rxa_refclk[7] ? {io_1[15:1],rxaclk} : io_1;
+   assign reg_2 = debug_en[2] ? debug_2 : txb_refclk[7] ? {io_2[15:1],txbclk} : io_2;
+   assign reg_3 = debug_en[3] ? debug_3 : rxb_refclk[7] ? {io_3[15:1],rxbclk} : io_3;
+
+   
+endmodule // master_control
diff --git a/usrp/fpga/sdr_lib/master_control_multi.v b/usrp/fpga/sdr_lib/master_control_multi.v
new file mode 100644
index 0000000000..af1e0b1f14
--- /dev/null
+++ b/usrp/fpga/sdr_lib/master_control_multi.v
@@ -0,0 +1,73 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2006 Martin Dudok van Heel
+//
+//  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+`include "usrp_multi.vh"
+`include "../../../firmware/include/fpga_regs_common.v"
+`include "../../../firmware/include/fpga_regs_standard.v"
+// Clock, enable, and reset controls for whole system
+// Modified version to enable multi_usrp synchronisation
+
+module master_control_multi
+  ( input master_clk, input usbclk,
+    input wire [6:0] serial_addr, input wire [31:0] serial_data, input wire serial_strobe,
+    input wire rx_slave_sync,
+    output tx_bus_reset, output rx_bus_reset,
+    output wire tx_dsp_reset, output wire rx_dsp_reset,
+    output wire enable_tx, output wire enable_rx,
+    output wire sync_rx,
+    output wire [7:0] interp_rate, output wire [7:0] decim_rate,
+    output tx_sample_strobe, output strobe_interp,
+    output rx_sample_strobe, output strobe_decim,
+    input tx_empty,
+    input wire [15:0] debug_0,input wire [15:0] debug_1,input wire [15:0] debug_2,input wire [15:0] debug_3,
+    output wire [15:0] reg_0, output wire [15:0] reg_1, output wire [15:0] reg_2, output wire [15:0] reg_3
+    );
+   
+   wire [15:0] reg_1_std;
+
+   master_control master_control_standard
+     ( .master_clk(master_clk),.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(interp_rate),.decim_rate(decim_rate),
+       .tx_sample_strobe(tx_sample_strobe),.strobe_interp(strobe_interp),
+       .rx_sample_strobe(rx_sample_strobe),.strobe_decim(strobe_decim),
+       .tx_empty(tx_empty),
+       .debug_0(debug_0),.debug_1(debug_1),
+       .debug_2(debug_2),.debug_3(debug_3),
+       .reg_0(reg_0),.reg_1(reg_1_std),.reg_2(reg_2),.reg_3(reg_3) );
+
+   // FIXME need a separate reset for all control settings 
+   // Master/slave Controls assignments
+   wire [7:0] rx_master_slave_controls;
+   setting_reg_masked #(`FR_RX_MASTER_SLAVE) sr_rx_mstr_slv_ctrl(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(rx_master_slave_controls));
+ 
+   assign     sync_rx = rx_master_slave_controls[`bitnoFR_RX_SYNC] | (rx_master_slave_controls[`bitnoFR_RX_SYNC_SLAVE] & rx_slave_sync);
+  //sync if we are told by master_control or if we get a hardware slave sync
+  //TODO There can be a one sample difference between master and slave sync. 
+  //     Maybe use a register for sync_rx which uses the (neg or pos) edge of master_clock and/or rx_slave_sync to trigger
+  //     Or even use a seperate sync_rx_out and sync_rx_internal (which lags behind)
+  //TODO make output pin not hardwired
+assign reg_1 ={(rx_master_slave_controls[`bitnoFR_RX_SYNC_MASTER])? sync_rx:reg_1_std[15],reg_1_std[14:0]};
+
+   
+endmodule // master_control
diff --git a/usrp/fpga/sdr_lib/phase_acc.v b/usrp/fpga/sdr_lib/phase_acc.v
new file mode 100755
index 0000000000..d00716fd0c
--- /dev/null
+++ b/usrp/fpga/sdr_lib/phase_acc.v
@@ -0,0 +1,52 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+
+
+// Basic Phase accumulator for DDS
+
+
+module phase_acc (clk,reset,enable,strobe,serial_addr,serial_data,serial_strobe,phase);   
+   parameter FREQADDR = 0;
+   parameter PHASEADDR = 0;
+   parameter resolution = 32;
+   
+   input     clk, reset, enable, strobe;
+   input [6:0] serial_addr;
+   input [31:0] serial_data;
+   input 	serial_strobe;
+   
+   output reg [resolution-1:0] phase;
+   wire [resolution-1:0] freq;
+
+   setting_reg #(FREQADDR) sr_rxfreq0(.clock(clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(freq));
+
+   always @(posedge clk)
+     if(reset)
+       phase <= #1 32'b0;
+     else if(serial_strobe & (serial_addr == PHASEADDR))
+       phase <= #1 serial_data;
+     else if(enable & strobe)
+       phase <= #1 phase + freq;
+
+endmodule // phase_acc
+
+   
diff --git a/usrp/fpga/sdr_lib/ram.v b/usrp/fpga/sdr_lib/ram.v
new file mode 100644
index 0000000000..fb64cdeae1
--- /dev/null
+++ b/usrp/fpga/sdr_lib/ram.v
@@ -0,0 +1,16 @@
+
+
+module ram (input clock, input write, 
+	    input [4:0] wr_addr, input [15:0] wr_data,
+	    input [4:0] rd_addr, output reg [15:0] rd_data);
+
+   reg [15:0] 		ram_array [0:31];
+
+   always @(posedge clock)
+     rd_data <= #1 ram_array[rd_addr];
+
+   always @(posedge clock)
+     if(write)
+       ram_array[wr_addr] <= #1 wr_data;
+
+endmodule // ram
diff --git a/usrp/fpga/sdr_lib/ram16.v b/usrp/fpga/sdr_lib/ram16.v
new file mode 100644
index 0000000000..0c93da2be1
--- /dev/null
+++ b/usrp/fpga/sdr_lib/ram16.v
@@ -0,0 +1,17 @@
+
+
+module ram16 (input clock, input write, 
+	      input [3:0] wr_addr, input [15:0] wr_data,
+	      input [3:0] rd_addr, output reg [15:0] rd_data);
+
+   reg [15:0] 		ram_array [0:15];
+
+   always @(posedge clock)
+     rd_data <= #1 ram_array[rd_addr];
+
+   always @(posedge clock)
+     if(write)
+       ram_array[wr_addr] <= #1 wr_data;
+
+endmodule // ram16
+
diff --git a/usrp/fpga/sdr_lib/ram32.v b/usrp/fpga/sdr_lib/ram32.v
new file mode 100644
index 0000000000..064e2735a3
--- /dev/null
+++ b/usrp/fpga/sdr_lib/ram32.v
@@ -0,0 +1,17 @@
+
+
+module ram32 (input clock, input write, 
+	      input [4:0] wr_addr, input [15:0] wr_data,
+	      input [4:0] rd_addr, output reg [15:0] rd_data);
+
+   reg [15:0] 		ram_array [0:31];
+
+   always @(posedge clock)
+     rd_data <= #1 ram_array[rd_addr];
+
+   always @(posedge clock)
+     if(write)
+       ram_array[wr_addr] <= #1 wr_data;
+
+endmodule // ram32
+
diff --git a/usrp/fpga/sdr_lib/ram64.v b/usrp/fpga/sdr_lib/ram64.v
new file mode 100644
index 0000000000..084545808b
--- /dev/null
+++ b/usrp/fpga/sdr_lib/ram64.v
@@ -0,0 +1,16 @@
+
+
+module ram64 (input clock, input write, 
+	      input [5:0] wr_addr, input [15:0] wr_data,
+	      input [5:0] rd_addr, output reg [15:0] rd_data);
+
+   reg [15:0] 		ram_array [0:63];
+
+   always @(posedge clock)
+     rd_data <= #1 ram_array[rd_addr];
+
+   always @(posedge clock)
+     if(write)
+       ram_array[wr_addr] <= #1 wr_data;
+
+endmodule // ram64
diff --git a/usrp/fpga/sdr_lib/rssi.v b/usrp/fpga/sdr_lib/rssi.v
new file mode 100644
index 0000000000..e45e2148c9
--- /dev/null
+++ b/usrp/fpga/sdr_lib/rssi.v
@@ -0,0 +1,30 @@
+
+
+module rssi (input clock, input reset, input enable,
+	     input [11:0] adc, output [15:0] rssi, output [15:0] over_count);
+
+   wire 		  over_hi = (adc == 12'h7FF);
+   wire 		  over_lo = (adc == 12'h800);
+   wire 		  over = over_hi | over_lo;
+
+   reg [25:0] 		  over_count_int;
+   always @(posedge clock)
+     if(reset | ~enable)
+       over_count_int <= #1 26'd0;
+     else
+       over_count_int <= #1 over_count_int + (over ? 26'd65535 : 26'd0) - over_count_int[25:10];
+   
+   assign      over_count = over_count_int[25:10];
+   
+   wire [11:0] abs_adc = adc[11] ? ~adc : adc;
+
+   reg [25:0]  rssi_int;
+   always @(posedge clock)
+     if(reset | ~enable)
+       rssi_int <= #1 26'd0;
+     else
+       rssi_int <= #1 rssi_int + abs_adc - rssi_int[25:10];
+
+   assign      rssi = rssi_int[25:10];
+   
+endmodule // rssi
diff --git a/usrp/fpga/sdr_lib/rx_buffer.v b/usrp/fpga/sdr_lib/rx_buffer.v
new file mode 100644
index 0000000000..70c800e3df
--- /dev/null
+++ b/usrp/fpga/sdr_lib/rx_buffer.v
@@ -0,0 +1,182 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+// Interface to Cypress FX2 bus
+// A packet is 512 Bytes.  Each fifo line is 2 bytes
+// Fifo has 1024 or 2048 lines
+
+`include "../../firmware/include/fpga_regs_common.v"
+`include "../../firmware/include/fpga_regs_standard.v"
+
+module rx_buffer
+  ( input usbclk,
+    input bus_reset,  // Not used in RX
+    input reset,  // DSP side reset (used here), do not reset registers
+    input reset_regs, //Only reset registers
+    output [15:0] usbdata,
+    input RD,
+    output wire have_pkt_rdy,
+    output reg rx_overrun,
+    input wire [3:0] channels,
+    input wire [15:0] ch_0,
+    input wire [15:0] ch_1,
+    input wire [15:0] ch_2,
+    input wire [15:0] ch_3,
+    input wire [15:0] ch_4,
+    input wire [15:0] ch_5,
+    input wire [15:0] ch_6,
+    input wire [15:0] ch_7,
+    input rxclk,
+    input rxstrobe,
+    input clear_status,
+    input [6:0] serial_addr, input [31:0] serial_data, input serial_strobe,
+    output [15:0] debugbus
+    );
+
+   wire [15:0] fifodata, fifodata_8;
+   reg [15:0]  fifodata_16;
+   
+   wire [11:0] rxfifolevel;
+   wire rx_empty, rx_full;
+
+   wire bypass_hb, want_q;
+   wire [4:0] bitwidth;
+   wire [3:0] bitshift;
+   
+   setting_reg #(`FR_RX_FORMAT) sr_rxformat(.clock(rxclk),.reset(reset_regs),
+					    .strobe(serial_strobe),.addr(serial_addr),.in(serial_data),
+					    .out({bypass_hb,want_q,bitwidth,bitshift}));
+
+   // Receive FIFO (ADC --> USB)
+
+   // 257 Bug Fix
+   reg [8:0] read_count;
+   always @(negedge usbclk)
+     if(bus_reset)
+       read_count <= #1 9'd0;
+     else if(RD & ~read_count[8])
+       read_count <= #1 read_count + 9'd1;
+     else
+       read_count <= #1 RD ? read_count : 9'b0;
+   
+   // Detect overrun
+   always @(posedge rxclk)
+     if(reset)
+       rx_overrun <= 1'b0;
+     else if(rxstrobe & (store_next != 0))
+       rx_overrun <= 1'b1;
+     else if(clear_status)
+       rx_overrun <= 1'b0;
+
+   reg [3:0] store_next;
+   always @(posedge rxclk)
+     if(reset)
+       store_next <= #1 4'd0;
+     else if(rxstrobe & (store_next == 0))
+       store_next <= #1 4'd1;
+     else if(~rx_full & (store_next == channels))
+       store_next <= #1 4'd0;
+     else if(~rx_full & (bitwidth == 5'd8) & (store_next == (channels>>1)))
+       store_next <= #1 4'd0;
+     else if(~rx_full & (store_next != 0))
+       store_next <= #1 store_next + 4'd1;
+
+   assign    fifodata = (bitwidth == 5'd8) ? fifodata_8 : fifodata_16;
+
+   assign    fifodata_8 = {round_8(top),round_8(bottom)};
+   reg [15:0] top,bottom;
+
+   function [7:0] round_8;
+      input [15:0] in_val;
+
+      round_8 = in_val[15:8] + (in_val[15] & |in_val[7:0]);
+   endfunction // round_8
+      
+   always @*
+     case(store_next)
+       4'd1 : begin
+	  bottom = ch_0;
+	  top = ch_1;
+       end
+       4'd2 : begin
+	  bottom = ch_2;
+	  top = ch_3;
+       end
+       4'd3 : begin
+	  bottom = ch_4;
+	  top = ch_5;
+       end
+       4'd4 : begin
+	  bottom = ch_6;
+	  top = ch_7;
+       end
+       default : begin
+	  top = 16'hFFFF;
+	  bottom = 16'hFFFF;
+       end
+     endcase // case(store_next)
+   
+   always @*
+     case(store_next)
+       4'd1 : fifodata_16 = ch_0;
+       4'd2 : fifodata_16 = ch_1;
+       4'd3 : fifodata_16 = ch_2;
+       4'd4 : fifodata_16 = ch_3;
+       4'd5 : fifodata_16 = ch_4;
+       4'd6 : fifodata_16 = ch_5;
+       4'd7 : fifodata_16 = ch_6;
+       4'd8 : fifodata_16 = ch_7;
+       default : fifodata_16 = 16'hFFFF;
+     endcase // case(store_next)
+   
+   fifo_4k rxfifo 
+     ( .data ( fifodata ),
+       .wrreq (~rx_full & (store_next != 0)),
+       .wrclk ( rxclk ),
+
+       .q ( usbdata ),
+       .rdreq ( RD & ~read_count[8] ), 
+       .rdclk ( ~usbclk ),
+       
+       .aclr ( reset ),  // This one is asynchronous, so we can use either reset
+       
+       .rdempty ( rx_empty ),
+       .rdusedw ( rxfifolevel ),
+       .wrfull ( rx_full ),
+       .wrusedw (  )
+       );
+   
+   assign have_pkt_rdy = (rxfifolevel >= 256);
+
+   // Debugging Aids
+   assign debugbus[0] = RD;
+   assign debugbus[1] = rx_overrun;
+   assign debugbus[2] = read_count[8];
+   assign debugbus[3] = rx_full;
+   assign debugbus[4] = rxstrobe;
+   assign debugbus[5] = usbclk;
+   assign debugbus[6] = have_pkt_rdy;
+   assign debugbus[10:7] = store_next;
+   //assign debugbus[15:11] = rxfifolevel[4:0];
+   assign debugbus[15:11] = bitwidth;
+   
+endmodule // rx_buffer
+
diff --git a/usrp/fpga/sdr_lib/rx_chain.v b/usrp/fpga/sdr_lib/rx_chain.v
new file mode 100644
index 0000000000..4031e6bfbb
--- /dev/null
+++ b/usrp/fpga/sdr_lib/rx_chain.v
@@ -0,0 +1,105 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+// Following defines conditionally include RX path circuitry
+
+`include "usrp_std.vh"
+module rx_chain
+  (input clock,
+   input reset,
+   input enable,
+   input wire [7:0] decim_rate,
+   input sample_strobe,
+   input decimator_strobe,
+   output wire hb_strobe,
+   input [6:0] serial_addr, input [31:0] serial_data, input serial_strobe,
+   input wire [15:0] i_in,
+   input wire [15:0] q_in,
+   output wire [15:0] i_out,
+   output wire [15:0] q_out,
+   output wire [15:0] debugdata,output wire [15:0] debugctrl
+   );
+
+   parameter FREQADDR = 0;
+   parameter PHASEADDR = 0;
+   
+   wire [31:0] phase;
+   wire [15:0] bb_i, bb_q;
+   wire [15:0] hb_in_i, hb_in_q;
+   
+   assign      debugdata = hb_in_i;
+
+`ifdef RX_NCO_ON
+    phase_acc #(FREQADDR,PHASEADDR,32) rx_phase_acc
+     (.clk(clock),.reset(reset),.enable(enable),
+      .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe),
+      .strobe(sample_strobe),.phase(phase) );
+
+   cordic rx_cordic
+     ( .clock(clock),.reset(reset),.enable(enable), 
+       .xi(i_in),.yi(q_in),.zi(phase[31:16]),
+       .xo(bb_i),.yo(bb_q),.zo() );
+`else
+   assign bb_i = i_in;
+   assign bb_q = q_in;
+   assign sample_strobe = 1;
+`endif // !`ifdef RX_NCO_ON
+   
+`ifdef RX_CIC_ON
+   cic_decim cic_decim_i_0
+     ( .clock(clock),.reset(reset),.enable(enable),
+       .rate(decim_rate),.strobe_in(sample_strobe),.strobe_out(decimator_strobe),
+       .signal_in(bb_i),.signal_out(hb_in_i) );
+`else
+   assign hb_in_i = bb_i;
+   assign decimator_strobe = sample_strobe;
+`endif
+   
+`ifdef RX_HB_ON
+   halfband_decim hbd_i_0
+     ( .clock(clock),.reset(reset),.enable(enable),
+       .strobe_in(decimator_strobe),.strobe_out(hb_strobe),
+       .data_in(hb_in_i),.data_out(i_out),.debugctrl(debugctrl) );
+`else
+   assign i_out = hb_in_i;
+   assign hb_strobe = decimator_strobe;
+`endif
+   
+`ifdef RX_CIC_ON
+   cic_decim cic_decim_q_0
+     ( .clock(clock),.reset(reset),.enable(enable),
+       .rate(decim_rate),.strobe_in(sample_strobe),.strobe_out(decimator_strobe),
+       .signal_in(bb_q),.signal_out(hb_in_q) );
+`else
+   assign hb_in_q = bb_q;
+`endif
+
+`ifdef RX_HB_ON
+   halfband_decim hbd_q_0
+     ( .clock(clock),.reset(reset),.enable(enable),
+       .strobe_in(decimator_strobe),.strobe_out(),
+       .data_in(hb_in_q),.data_out(q_out) );   
+`else
+   assign q_out = hb_in_q;
+`endif
+
+
+endmodule // rx_chain
diff --git a/usrp/fpga/sdr_lib/rx_chain_dual.v b/usrp/fpga/sdr_lib/rx_chain_dual.v
new file mode 100644
index 0000000000..698859468d
--- /dev/null
+++ b/usrp/fpga/sdr_lib/rx_chain_dual.v
@@ -0,0 +1,103 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+module rx_chain_dual
+  (input clock,
+   input clock_2x,
+   input reset,
+   input enable,
+   input wire [7:0] decim_rate,
+   input sample_strobe,
+   input decimator_strobe,
+   input wire [31:0] freq0,
+   input wire [15:0] i_in0,
+   input wire [15:0] q_in0,
+   output wire [15:0] i_out0,
+   output wire [15:0] q_out0,
+   input wire [31:0] freq1,
+   input wire [15:0] i_in1,
+   input wire [15:0] q_in1,
+   output wire [15:0] i_out1,
+   output wire [15:0] q_out1
+   );
+
+   wire [15:0] phase;
+   wire [15:0] bb_i, bb_q;
+   wire [15:0] i_in, q_in;
+   
+   wire [31:0] phase0;
+   wire [31:0] phase1;
+   reg [15:0] bb_i0, bb_q0;
+   reg [15:0] bb_i1, bb_q1;
+
+   // We want to time-share the CORDIC by double-clocking it
+   
+   phase_acc rx_phase_acc_0
+     (.clk(clock),.reset(reset),.enable(enable),
+      .strobe(sample_strobe),.freq(freq0),.phase(phase0) );
+
+   phase_acc rx_phase_acc_1
+     (.clk(clock),.reset(reset),.enable(enable),
+      .strobe(sample_strobe),.freq(freq1),.phase(phase1) );
+   
+   assign phase = clock ? phase0[31:16] : phase1[31:16];
+   assign i_in = clock ? i_in0 : i_in1;
+   assign q_in = clock ? q_in0 : q_in1;
+
+// This appears reversed because of the number of CORDIC stages
+   always @(posedge clock_2x)
+     if(clock)
+       begin
+	  bb_i1 <= #1 bb_i;
+	  bb_q1 <= #1 bb_q;
+       end
+     else
+       begin
+	  bb_i0 <= #1 bb_i;
+	  bb_q0 <= #1 bb_q;
+       end
+	
+   cordic rx_cordic
+     ( .clock(clock_2x),.reset(reset),.enable(enable), 
+       .xi(i_in),.yi(q_in),.zi(phase),
+       .xo(bb_i),.yo(bb_q),.zo() );
+   
+   cic_decim cic_decim_i_0
+     ( .clock(clock),.reset(reset),.enable(enable),
+       .rate(decim_rate),.strobe_in(sample_strobe),.strobe_out(decimator_strobe),
+       .signal_in(bb_i0),.signal_out(i_out0) );
+
+   cic_decim cic_decim_q_0
+     ( .clock(clock),.reset(reset),.enable(enable),
+       .rate(decim_rate),.strobe_in(sample_strobe),.strobe_out(decimator_strobe),
+       .signal_in(bb_q0),.signal_out(q_out0) );
+
+   cic_decim cic_decim_i_1
+     ( .clock(clock),.reset(reset),.enable(enable),
+       .rate(decim_rate),.strobe_in(sample_strobe),.strobe_out(decimator_strobe),
+       .signal_in(bb_i1),.signal_out(i_out1) );
+
+   cic_decim cic_decim_q_1
+     ( .clock(clock),.reset(reset),.enable(enable),
+       .rate(decim_rate),.strobe_in(sample_strobe),.strobe_out(decimator_strobe),
+       .signal_in(bb_q1),.signal_out(q_out1) );
+
+endmodule // rx_chain
diff --git a/usrp/fpga/sdr_lib/rx_dcoffset.v b/usrp/fpga/sdr_lib/rx_dcoffset.v
new file mode 100644
index 0000000000..3be475ed60
--- /dev/null
+++ b/usrp/fpga/sdr_lib/rx_dcoffset.v
@@ -0,0 +1,22 @@
+
+
+module rx_dcoffset (input clock, input enable, input reset, 
+		    input signed [15:0] adc_in, output signed [15:0] adc_out,
+		    input wire [6:0] serial_addr, input wire [31:0] serial_data, input serial_strobe);
+   parameter 		  MYADDR = 0;
+   
+   reg signed [31:0] 		 integrator;
+   wire signed [15:0] 		 scaled_integrator = integrator[31:16] + (integrator[31] & |integrator[15:0]);
+   assign 			 adc_out = adc_in - scaled_integrator;
+
+   // FIXME do we need signed?
+   //FIXME  What do we do when clipping?
+   always @(posedge clock)
+     if(reset)
+       integrator <= #1 32'd0;
+     else if(serial_strobe & (MYADDR == serial_addr))
+       integrator <= #1 {serial_data[15:0],16'd0};
+     else if(enable)
+       integrator <= #1 integrator + adc_out;
+
+endmodule // rx_dcoffset
diff --git a/usrp/fpga/sdr_lib/serial_io.v b/usrp/fpga/sdr_lib/serial_io.v
new file mode 100644
index 0000000000..1fe43c9590
--- /dev/null
+++ b/usrp/fpga/sdr_lib/serial_io.v
@@ -0,0 +1,118 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003,2004 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+
+
+// Serial Control Bus from Cypress chip
+
+module serial_io
+  ( input master_clk,
+    input serial_clock,
+    input serial_data_in,
+    input enable,
+    input reset,
+    inout wire serial_data_out,
+    output reg [6:0] serial_addr,
+    output reg [31:0] serial_data,
+    output wire serial_strobe,
+    input wire [31:0] readback_0,
+    input wire [31:0] readback_1,
+    input wire [31:0] readback_2,
+    input wire [31:0] readback_3,
+    input wire [31:0] readback_4,
+    input wire [31:0] readback_5,
+    input wire [31:0] readback_6,
+    input wire [31:0] readback_7
+    );
+       
+   reg 	      is_read;
+   reg [7:0]  ser_ctr;
+   reg 	      write_done;
+
+   assign serial_data_out = is_read ? serial_data[31] : 1'bz;
+
+   always @(posedge serial_clock, posedge reset, negedge enable)
+     if(reset)
+       ser_ctr <= #1 8'd0;
+     else if(~enable)
+       ser_ctr <= #1 8'd0;
+     else if(ser_ctr == 39)
+       ser_ctr <= #1 8'd0;
+     else
+       ser_ctr <= #1 ser_ctr + 8'd1;
+
+   always @(posedge serial_clock, posedge reset, negedge enable)
+     if(reset)
+       is_read <= #1 1'b0;
+     else if(~enable)
+       is_read <= #1 1'b0;
+     else if((ser_ctr == 7)&&(serial_addr[6]==1))
+       is_read <= #1 1'b1;
+   
+   always @(posedge serial_clock, posedge reset)
+     if(reset)
+       begin
+	  serial_addr <= #1 7'b0;
+	  serial_data <= #1 32'b0;
+	  write_done <= #1 1'b0;
+       end
+     else if(~enable)
+       begin
+	  //serial_addr <= #1 7'b0;
+	  //serial_data <= #1 32'b0;
+	  write_done <= #1 1'b0;
+       end
+     else 
+       begin
+	  if(~is_read && (ser_ctr == 39))
+	    write_done <= #1 1'b1;
+	  else
+	    write_done <= #1 1'b0;
+	  if(is_read & (ser_ctr==8))
+	    case (serial_addr)
+	      7'd1: serial_data <= #1 readback_0;
+	      7'd2: serial_data <= #1 readback_1;
+	      7'd3: serial_data <= #1 readback_2;
+	      7'd4: serial_data <= #1 readback_3;
+	      7'd5: serial_data <= #1 readback_4;
+	      7'd6: serial_data <= #1 readback_5;
+	      7'd7: serial_data <= #1 readback_6;
+	      7'd8: serial_data <= #1 readback_7;
+	      default: serial_data <= #1 32'd0;
+	    endcase // case(serial_addr)
+	  else if(ser_ctr >= 8)
+	    serial_data <= #1 {serial_data[30:0],serial_data_in};
+	  else if(ser_ctr < 8)
+	    serial_addr <= #1 {serial_addr[5:0],serial_data_in};
+       end // else: !if(~enable)
+
+   reg enable_d1, enable_d2;
+   always @(posedge master_clk)
+     begin
+	enable_d1 <= #1 enable;
+	enable_d2 <= #1 enable_d1;
+     end
+
+   assign serial_strobe = enable_d2 & ~enable_d1;
+   
+endmodule // serial_io
+
+
diff --git a/usrp/fpga/sdr_lib/setting_reg.v b/usrp/fpga/sdr_lib/setting_reg.v
new file mode 100644
index 0000000000..3d31a9efb2
--- /dev/null
+++ b/usrp/fpga/sdr_lib/setting_reg.v
@@ -0,0 +1,23 @@
+
+
+module setting_reg
+  ( input clock, input reset, input strobe, input wire [6:0] addr,
+    input wire [31:0] in, output reg [31:0] out, output reg changed);
+   parameter my_addr = 0;
+   
+   always @(posedge clock)
+     if(reset)
+       begin
+	  out <= #1 32'd0;
+	  changed <= #1 1'b0;
+       end
+     else
+       if(strobe & (my_addr==addr))
+	 begin
+	    out <= #1 in;
+	    changed <= #1 1'b1;
+	 end
+       else
+	 changed <= #1 1'b0;
+   
+endmodule // setting_reg
diff --git a/usrp/fpga/sdr_lib/setting_reg_masked.v b/usrp/fpga/sdr_lib/setting_reg_masked.v
new file mode 100644
index 0000000000..72f7e21ebc
--- /dev/null
+++ b/usrp/fpga/sdr_lib/setting_reg_masked.v
@@ -0,0 +1,26 @@
+
+
+module setting_reg_masked
+  ( input clock, input reset, input strobe, input wire [6:0] addr,
+    input wire [31:0] in, output reg [31:0] out, output reg changed);
+/* upper 16 bits are mask, lower 16 bits are value 
+ * Note that you get a 16 bit register, not a 32 bit one */
+
+   parameter my_addr = 0;
+   
+   always @(posedge clock)
+     if(reset)
+       begin
+	  out <= #1 32'd0;
+	  changed <= #1 1'b0;
+       end
+     else
+       if(strobe & (my_addr==addr))
+	 begin
+	    out <= #1 (out & ~in[31:16]) | (in[15:0] & in[31:16] );
+	    changed <= #1 1'b1;
+	 end
+       else
+	 changed <= #1 1'b0;
+   
+endmodule // setting_reg_masked
diff --git a/usrp/fpga/sdr_lib/sign_extend.v b/usrp/fpga/sdr_lib/sign_extend.v
new file mode 100644
index 0000000000..2417909bd7
--- /dev/null
+++ b/usrp/fpga/sdr_lib/sign_extend.v
@@ -0,0 +1,35 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+
+// Sign extension "macro"
+// bits_out should be greater than bits_in
+
+module sign_extend (in,out);
+	parameter bits_in=0;  // FIXME Quartus insists on a default
+	parameter bits_out=0;
+	
+	input [bits_in-1:0] in;
+	output [bits_out-1:0] out;
+	
+	assign out = {{(bits_out-bits_in){in[bits_in-1]}},in};
+	
+endmodule
diff --git a/usrp/fpga/sdr_lib/strobe_gen.v b/usrp/fpga/sdr_lib/strobe_gen.v
new file mode 100644
index 0000000000..0511b6a1db
--- /dev/null
+++ b/usrp/fpga/sdr_lib/strobe_gen.v
@@ -0,0 +1,44 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+module strobe_gen 
+  ( input clock,
+    input reset,
+    input enable,
+    input [7:0] rate,
+    input strobe_in,
+    output wire strobe );
+   
+//   parameter width = 8;
+   
+   reg [7:0] counter;
+   assign strobe = ~|counter && enable && strobe_in;
+   
+   always @(posedge clock)
+     if(reset | ~enable)
+       counter <= #1 8'd0;
+     else if(strobe_in)
+       if(counter == 0)
+	 counter <= #1 rate;
+       else 
+	 counter <= #1 counter - 8'd1;
+   
+endmodule // strobe_gen
diff --git a/usrp/fpga/sdr_lib/tx_buffer.v b/usrp/fpga/sdr_lib/tx_buffer.v
new file mode 100644
index 0000000000..cae6607b30
--- /dev/null
+++ b/usrp/fpga/sdr_lib/tx_buffer.v
@@ -0,0 +1,138 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+// Interface to Cypress FX2 bus
+// A packet is 512 Bytes.  Each fifo line is 2 bytes
+// Fifo has 1024 or 2048 lines
+
+module tx_buffer
+  ( input usbclk,
+    input bus_reset,  // Used here for the 257-Hack to fix the FX2 bug
+    input reset,  // standard DSP-side reset
+    input [15:0] usbdata,
+    input wire WR,
+    output wire have_space,
+    output reg tx_underrun,
+    input wire [3:0] channels,
+    output reg [15:0] tx_i_0,
+    output reg [15:0] tx_q_0,
+    output reg [15:0] tx_i_1,
+    output reg [15:0] tx_q_1,
+    output reg [15:0] tx_i_2,
+    output reg [15:0] tx_q_2,
+    output reg [15:0] tx_i_3,
+    output reg [15:0] tx_q_3,
+    input txclk,
+    input txstrobe,
+    input clear_status,
+    output wire tx_empty,
+    output [11:0] debugbus
+    );
+   
+   wire [11:0] txfifolevel;
+   reg [8:0] write_count;
+   wire tx_full;
+   wire [15:0] fifodata;
+   wire rdreq;
+
+   reg [3:0] load_next;
+
+   // DAC Side of FIFO
+   assign    rdreq = ((load_next != channels) & !tx_empty);
+   
+   always @(posedge txclk)
+     if(reset)
+       begin
+	  {tx_i_0,tx_q_0,tx_i_1,tx_q_1,tx_i_2,tx_q_2,tx_i_3,tx_q_3}
+	    <= #1 128'h0;
+	  load_next <= #1 4'd0;
+       end
+     else
+       if((load_next != channels) & !tx_empty)
+	 begin
+	    load_next <= #1 load_next + 4'd1;
+	    case(load_next)
+	      4'd0 : tx_i_0 <= #1 fifodata;
+	      4'd1 : tx_q_0 <= #1 fifodata;
+	      4'd2 : tx_i_1 <= #1 fifodata;
+	      4'd3 : tx_q_1 <= #1 fifodata;
+	      4'd4 : tx_i_2 <= #1 fifodata;
+	      4'd5 : tx_q_2 <= #1 fifodata;
+	      4'd6 : tx_i_3 <= #1 fifodata;
+	      4'd7 : tx_q_3 <= #1 fifodata;
+	    endcase // case(load_next)
+	 end // if ((load_next != channels) & !tx_empty)
+       else if(txstrobe & (load_next == channels))
+	 begin
+	    load_next <= #1 4'd0;
+	 end
+
+   // USB Side of FIFO
+   assign have_space = (txfifolevel <= (4095-256));
+
+   always @(posedge usbclk)
+     if(bus_reset)        // Use bus reset because this is on usbclk
+       write_count <= #1 0;
+     else if(WR & ~write_count[8])
+       write_count <= #1 write_count + 9'd1;
+     else
+       write_count <= #1 WR ? write_count : 9'b0;
+
+   // Detect Underruns
+   always @(posedge txclk)
+     if(reset)
+       tx_underrun <= 1'b0;
+     else if(txstrobe & (load_next != channels))
+       tx_underrun <= 1'b1;
+     else if(clear_status)
+       tx_underrun <= 1'b0;
+
+   // FIFO
+   fifo_4k txfifo 
+     ( .data ( usbdata ),
+       .wrreq ( WR & ~write_count[8] ),
+       .wrclk ( usbclk ),
+       
+       .q ( fifodata ),			
+       .rdreq ( rdreq ),
+       .rdclk ( txclk ),
+       
+       .aclr ( reset ),  // asynch, so we can use either
+       
+       .rdempty ( tx_empty ),
+       .rdusedw (  ),
+       .wrfull ( tx_full ),
+       .wrusedw ( txfifolevel )
+       );
+   
+   // Debugging Aids
+   assign debugbus[0] = WR;
+   assign debugbus[1] = have_space;
+   assign debugbus[2] = tx_empty;
+   assign debugbus[3] = tx_full;
+   assign debugbus[4] = tx_underrun;
+   assign debugbus[5] = write_count[8];
+   assign debugbus[6] = txstrobe;
+   assign debugbus[7] = rdreq;
+   assign debugbus[11:8] = load_next;
+   
+endmodule // tx_buffer
+
diff --git a/usrp/fpga/sdr_lib/tx_chain.v b/usrp/fpga/sdr_lib/tx_chain.v
new file mode 100644
index 0000000000..8f0a17a52b
--- /dev/null
+++ b/usrp/fpga/sdr_lib/tx_chain.v
@@ -0,0 +1,65 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+module tx_chain
+  (input clock,
+   input reset,
+   input enable,
+   input wire [7:0] interp_rate,
+   input sample_strobe,
+   input interpolator_strobe,
+   input wire [31:0] freq,
+   input wire [15:0] i_in,
+   input wire [15:0] q_in,
+   output wire [15:0] i_out,
+   output wire [15:0] q_out
+   );
+
+   wire [15:0] bb_i, bb_q;
+
+   cic_interp cic_interp_i
+     ( .clock(clock),.reset(reset),.enable(enable),
+       .rate(interp_rate),.strobe_in(interpolator_strobe),.strobe_out(sample_strobe),
+       .signal_in(i_in),.signal_out(bb_i) );
+
+   cic_interp cic_interp_q
+     ( .clock(clock),.reset(reset),.enable(enable),
+       .rate(interp_rate),.strobe_in(interpolator_strobe),.strobe_out(sample_strobe),
+       .signal_in(q_in),.signal_out(bb_q) );
+   
+`define NOCORDIC_TX
+`ifdef NOCORDIC_TX
+   assign      i_out = bb_i;
+   assign      q_out = bb_q;
+`else
+   wire [31:0] phase;
+
+   phase_acc phase_acc_tx
+     (.clk(clock),.reset(reset),.enable(enable),
+      .strobe(sample_strobe),.freq(freq),.phase(phase) );
+   
+   cordic tx_cordic_0
+     ( .clock(clock),.reset(reset),.enable(sample_strobe), 
+       .xi(bb_i),.yi(bb_q),.zi(phase[31:16]),
+       .xo(i_out),.yo(q_out),.zo() );
+`endif
+
+endmodule // tx_chain
diff --git a/usrp/fpga/sdr_lib/tx_chain_hb.v b/usrp/fpga/sdr_lib/tx_chain_hb.v
new file mode 100644
index 0000000000..6cbe29c000
--- /dev/null
+++ b/usrp/fpga/sdr_lib/tx_chain_hb.v
@@ -0,0 +1,76 @@
+// -*- verilog -*-
+//
+//  USRP - Universal Software Radio Peripheral
+//
+//  Copyright (C) 2003 Matt Ettus
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+module tx_chain_hb
+  (input clock,
+   input reset,
+   input enable,
+   input wire [7:0] interp_rate,
+   input sample_strobe,
+   input interpolator_strobe,
+   input hb_strobe,
+   input wire [31:0] freq,
+   input wire [15:0] i_in,
+   input wire [15:0] q_in,
+   output wire [15:0] i_out,
+   output wire [15:0] q_out,
+output wire [15:0] debug, output [15:0] hb_i_out
+   );
+assign debug[15:13] = {sample_strobe,hb_strobe,interpolator_strobe};
+
+   wire [15:0] bb_i, bb_q;
+   wire [15:0] hb_i_out, hb_q_out;
+   
+   halfband_interp hb
+     (.clock(clock),.reset(reset),.enable(enable),
+      .strobe_in(interpolator_strobe),.strobe_out(hb_strobe),
+      .signal_in_i(i_in),.signal_in_q(q_in),
+      .signal_out_i(hb_i_out),.signal_out_q(hb_q_out),
+	.debug(debug[12:0]));
+      
+   cic_interp cic_interp_i
+     ( .clock(clock),.reset(reset),.enable(enable),
+       .rate(interp_rate),.strobe_in(hb_strobe),.strobe_out(sample_strobe),
+       .signal_in(hb_i_out),.signal_out(bb_i) );
+
+   cic_interp cic_interp_q
+     ( .clock(clock),.reset(reset),.enable(enable),
+       .rate(interp_rate),.strobe_in(hb_strobe),.strobe_out(sample_strobe),
+       .signal_in(hb_q_out),.signal_out(bb_q) );
+   
+`define NOCORDIC_TX
+`ifdef NOCORDIC_TX
+   assign      i_out = bb_i;
+   assign      q_out = bb_q;
+`else
+   wire [31:0] phase;
+
+   phase_acc phase_acc_tx
+     (.clk(clock),.reset(reset),.enable(enable),
+      .strobe(sample_strobe),.freq(freq),.phase(phase) );
+   
+   cordic tx_cordic_0
+     ( .clock(clock),.reset(reset),.enable(sample_strobe), 
+       .xi(bb_i),.yi(bb_q),.zi(phase[31:16]),
+       .xo(i_out),.yo(q_out),.zo() );
+`endif
+
+endmodule // tx_chain
-- 
cgit v1.2.3