aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--firmware/microblaze/apps/txrx_uhd.c168
-rw-r--r--firmware/microblaze/lib/Makefile.am1
-rw-r--r--firmware/microblaze/lib/banal.c18
-rw-r--r--firmware/microblaze/lib/banal.h3
-rw-r--r--firmware/microblaze/lib/clocks.c30
-rw-r--r--firmware/microblaze/lib/clocks.h10
-rw-r--r--firmware/microblaze/lib/hal_io.c128
-rw-r--r--firmware/microblaze/lib/hal_io.h58
-rw-r--r--firmware/microblaze/lib/memory_map.h4
-rw-r--r--firmware/microblaze/lib/print_fxpt.c83
-rw-r--r--firmware/microblaze/lib/print_mac_addr.c10
-rw-r--r--firmware/microblaze/lib/u2_init.c21
-rw-r--r--fpga/usrp2/control_lib/nsgpio.v2
-rw-r--r--fpga/usrp2/control_lib/settings_bus.v1
-rw-r--r--fpga/usrp2/control_lib/settings_bus_crossclock.v20
-rw-r--r--fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.ngc3
-rw-r--r--fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.v165
-rw-r--r--fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.veo51
-rw-r--r--fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.xco82
-rw-r--r--fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_fifo_generator_v4_3_xst_1.ngc_xst.xrpt98
-rw-r--r--fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_flist.txt8
-rw-r--r--fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_readme.txt39
-rw-r--r--fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_xmdf.tcl68
-rw-r--r--fpga/usrp2/sdr_lib/cordic_z24.v48
-rw-r--r--fpga/usrp2/sdr_lib/dsp_core_rx.v10
-rw-r--r--fpga/usrp2/top/u2_core/u2_core.v30
-rw-r--r--fpga/usrp2/top/u2_rev1/.gitignore52
-rw-r--r--fpga/usrp2/top/u2_rev1/Makefile129
-rw-r--r--fpga/usrp2/top/u2_rev1/u2_fpga.isebin477678 -> 0 bytes
-rwxr-xr-xfpga/usrp2/top/u2_rev1/u2_fpga.ucf341
-rw-r--r--fpga/usrp2/top/u2_rev1/u2_fpga_top.prj102
-rw-r--r--fpga/usrp2/top/u2_rev1/u2_fpga_top.v393
-rw-r--r--fpga/usrp2/top/u2_rev2/.gitignore57
-rw-r--r--fpga/usrp2/top/u2_rev2/Makefile248
-rw-r--r--fpga/usrp2/top/u2_rev2/u2_rev2.ucf337
-rw-r--r--fpga/usrp2/top/u2_rev2/u2_rev2.v417
-rw-r--r--fpga/usrp2/top/u2_rev3/Makefile5
-rw-r--r--fpga/usrp2/top/u2_rev3/u2_rev3.ucf2
-rw-r--r--fpga/usrp2/top/u2_rev3/u2_rev3.v15
-rw-r--r--fpga/usrp2/vrt/vita_rx_control.v24
-rw-r--r--host/CMakeLists.txt1
-rw-r--r--host/README1
-rw-r--r--host/apps/omap_debug/usrp-e-led.c16
-rw-r--r--host/docs/build.rst31
-rw-r--r--host/docs/dboards.rst11
-rw-r--r--host/docs/usrp2.rst27
-rw-r--r--host/examples/CMakeLists.txt4
-rw-r--r--host/examples/rx_timed_samples.cpp17
-rw-r--r--host/examples/tx_timed_samples.cpp92
-rw-r--r--host/include/uhd/config.hpp9
-rw-r--r--host/include/uhd/device.hpp57
-rw-r--r--host/include/uhd/transport/zero_copy.hpp17
-rw-r--r--host/include/uhd/types/dict.hpp2
-rw-r--r--host/include/uhd/types/mac_addr.hpp16
-rw-r--r--host/include/uhd/types/otw_type.hpp6
-rw-r--r--host/include/uhd/usrp/dboard_iface.hpp22
-rw-r--r--host/include/uhd/usrp/dboard_props.hpp3
-rw-r--r--host/include/uhd/usrp/device_props.hpp4
-rw-r--r--host/include/uhd/usrp/simple_usrp.hpp2
-rw-r--r--host/include/uhd/utils/algorithm.hpp5
-rw-r--r--host/lib/ic_reg_maps/common.py41
-rwxr-xr-xhost/lib/ic_reg_maps/gen_ad9777_regs.py2
-rw-r--r--host/lib/transport/CMakeLists.txt1
-rw-r--r--host/lib/transport/convert_types.cpp23
-rwxr-xr-xhost/lib/transport/gen_vrt.py2
-rw-r--r--host/lib/transport/udp_zero_copy_asio.cpp144
-rw-r--r--host/lib/transport/vrt_packet_handler.hpp370
-rw-r--r--host/lib/types.cpp140
-rw-r--r--host/lib/usrp/dboard/db_rfx.cpp124
-rw-r--r--host/lib/usrp/dboard/db_wbx.cpp6
-rw-r--r--host/lib/usrp/dboard/db_xcvr2450.cpp4
-rw-r--r--host/lib/usrp/dboard_manager.cpp3
-rw-r--r--host/lib/usrp/simple_usrp.cpp8
-rw-r--r--host/lib/usrp/usrp2/CMakeLists.txt10
-rw-r--r--host/lib/usrp/usrp2/clock_ctrl.cpp (renamed from host/lib/usrp/usrp2/clock_control.cpp)22
-rw-r--r--host/lib/usrp/usrp2/clock_ctrl.hpp (renamed from host/lib/usrp/usrp2/clock_control.hpp)12
-rw-r--r--host/lib/usrp/usrp2/codec_ctrl.cpp91
-rw-r--r--host/lib/usrp/usrp2/codec_ctrl.hpp38
-rw-r--r--host/lib/usrp/usrp2/dboard_iface.cpp52
-rw-r--r--host/lib/usrp/usrp2/dboard_impl.cpp12
-rw-r--r--host/lib/usrp/usrp2/dsp_impl.cpp3
-rw-r--r--host/lib/usrp/usrp2/fw_common.h24
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp182
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp152
-rw-r--r--host/lib/usrp/usrp2/serdes_ctrl.cpp46
-rw-r--r--host/lib/usrp/usrp2/serdes_ctrl.hpp40
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.hpp7
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp15
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp61
-rw-r--r--host/lib/usrp/usrp2/usrp2_regs.hpp41
-rw-r--r--host/lib/usrp/usrp_e/dboard_iface.cpp50
-rw-r--r--host/lib/usrp/usrp_e/usrp_e_impl.cpp14
-rw-r--r--host/lib/usrp/usrp_e/usrp_e_impl.hpp6
-rw-r--r--host/lib/usrp/usrp_e/usrp_e_regs.hpp12
-rw-r--r--host/utils/CMakeLists.txt13
-rw-r--r--host/utils/usrp2_addr_burner.cpp (renamed from host/utils/usrp2_burner.cpp)2
-rwxr-xr-xhost/utils/usrp2_card_burner.py226
-rwxr-xr-xhost/utils/usrp2_card_burner_gui.py169
98 files changed, 2533 insertions, 3259 deletions
diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c
index 8ff3b8c58..7ad4ab110 100644
--- a/firmware/microblaze/apps/txrx_uhd.c
+++ b/firmware/microblaze/apps/txrx_uhd.c
@@ -22,8 +22,6 @@
#include "config.h"
#endif
-#define DEBUG_MODE 0 //0 for normal operation
-
#include <lwip/ip.h>
#include <lwip/udp.h>
#include "u2_init.h"
@@ -49,8 +47,6 @@
#include <ethertype.h>
#include <arp_cache.h>
-#define LEDS_SW LED_A
-
/*
* Full duplex Tx and Rx between ethernet and DSP pipelines
*
@@ -126,14 +122,7 @@ dbsm_t dsp_rx_sm; // the state machine
// The mac address of the host we're sending to.
eth_mac_addr_t host_mac_addr;
-//controls continuous streaming...
-static bool auto_reload_command = false;
-static size_t streaming_items_per_frame = 0;
-static int streaming_frame_count = 0;
-#define FRAMES_PER_CMD 2
-
static void setup_network(void);
-static void setup_vrt(void);
// ----------------------------------------------------------------
// the fast-path setup global variables
@@ -154,9 +143,6 @@ void handle_udp_data_packet(
struct socket_address src, struct socket_address dst,
unsigned char *payload, int payload_len
){
- //store the 2nd word as the following:
- streaming_items_per_frame = ((uint32_t *)payload)[1];
-
//its a tiny payload, load the fast-path variables
fp_mac_addr_src = *ethernet_mac_addr();
arp_cache_lookup_mac(&src.addr, &fp_mac_addr_dst);
@@ -177,23 +163,12 @@ void handle_udp_data_packet(
//setup network and vrt
setup_network();
- setup_vrt();
// kick off the state machine
dbsm_start(&dsp_rx_sm);
}
-static void inline issue_stream_command(size_t nsamps, bool now, bool chain, uint32_t secs, uint32_t ticks, bool start){
- //printf("Stream cmd: nsamps %d, now %d, chain %d, secs %u, ticks %u\n", (int)nsamps, now, chain, secs, ticks);
- sr_rx_ctrl->cmd = MK_RX_CMD(nsamps, now, chain);
-
- if (start) dbsm_start(&dsp_rx_sm);
-
- sr_rx_ctrl->time_secs = secs;
- sr_rx_ctrl->time_ticks = ticks; // enqueue command
-}
-
#define OTW_GPIO_BANK_TO_NUM(bank) \
(((bank) == USRP2_DIR_RX)? (GPIO_RX_BANK) : (GPIO_TX_BANK))
@@ -210,7 +185,7 @@ void handle_udp_ctrl_packet(
printf("!Error in control packet handler: Expected protocol version %d, but got %d\n",
USRP2_PROTO_VERSION, ctrl_data_in->proto_ver
);
- ctrl_data_in_id = USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO;
+ ctrl_data_in_id = USRP2_CTRL_ID_WAZZUP_BRO;
}
//ensure that this is not a short packet
@@ -234,28 +209,11 @@ void handle_udp_ctrl_packet(
/*******************************************************************
* Addressing
******************************************************************/
- case USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO:
- ctrl_data_out.id = USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE;
- memcpy(&ctrl_data_out.data.ip_addr, get_ip_addr(), sizeof(struct ip_addr));
- break;
-
- case USRP2_CTRL_ID_HERE_IS_A_NEW_IP_ADDR_BRO:
- ctrl_data_out.id = USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE;
- set_ip_addr((struct ip_addr *)&ctrl_data_in->data.ip_addr);
+ case USRP2_CTRL_ID_WAZZUP_BRO:
+ ctrl_data_out.id = USRP2_CTRL_ID_WAZZUP_DUDE;
memcpy(&ctrl_data_out.data.ip_addr, get_ip_addr(), sizeof(struct ip_addr));
break;
- case USRP2_CTRL_ID_GIVE_ME_YOUR_MAC_ADDR_BRO:
- ctrl_data_out.id = USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE;
- memcpy(&ctrl_data_out.data.mac_addr, ethernet_mac_addr(), sizeof(eth_mac_addr_t));
- break;
-
- case USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO:
- ctrl_data_out.id = USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE;
- ethernet_set_mac_addr((eth_mac_addr_t *)&ctrl_data_in->data.mac_addr);
- memcpy(&ctrl_data_out.data.mac_addr, ethernet_mac_addr(), sizeof(eth_mac_addr_t));
- break;
-
/*******************************************************************
* SPI
******************************************************************/
@@ -304,72 +262,6 @@ void handle_udp_ctrl_packet(
break;
/*******************************************************************
- * Streaming
- ******************************************************************/
- case USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO:{
-
- //issue two commands and set the auto-reload flag
- if (ctrl_data_in->data.stream_cmd.continuous){
- printf("Setting up continuous streaming...\n");
- printf("items per frame: %d\n", (int)streaming_items_per_frame);
- hal_set_leds(LED_A, LEDS_SW);
- auto_reload_command = true;
- streaming_frame_count = FRAMES_PER_CMD;
-
- issue_stream_command(
- streaming_items_per_frame * FRAMES_PER_CMD,
- (ctrl_data_in->data.stream_cmd.now == 0)? false : true, //now
- true, //chain
- ctrl_data_in->data.stream_cmd.secs,
- ctrl_data_in->data.stream_cmd.ticks,
- true //start
- );
-
- issue_stream_command(
- streaming_items_per_frame * FRAMES_PER_CMD,
- true, //now
- true, //chain
- 0, 0, //time does not matter
- false
- );
-
- }
-
- //issue regular stream commands (split commands if too large)
- else{
- hal_set_leds(0, LEDS_SW);
- auto_reload_command = false;
- size_t num_samps = ctrl_data_in->data.stream_cmd.num_samps;
- if (num_samps == 0) num_samps = 1; //FIXME hack, zero is used when stopping continuous streaming but it somehow makes it inifinite
-
- bool chain = num_samps > MAX_SAMPLES_PER_CMD;
- issue_stream_command(
- (chain)? streaming_items_per_frame : num_samps, //nsamps
- (ctrl_data_in->data.stream_cmd.now == 0)? false : true, //now
- (ctrl_data_in->data.stream_cmd.chain == 0)? chain : true, //chain
- ctrl_data_in->data.stream_cmd.secs,
- ctrl_data_in->data.stream_cmd.ticks,
- false
- );
-
- //handle rest of the samples that did not fit into one cmd
- while(chain){
- num_samps -= MAX_SAMPLES_PER_CMD;
- chain = num_samps > MAX_SAMPLES_PER_CMD;
- issue_stream_command(
- (chain)? streaming_items_per_frame : num_samps, //nsamps
- true, //now
- (ctrl_data_in->data.stream_cmd.chain == 0)? chain : true, //chain
- 0, 0, //time does not matter
- false
- );
- }
- }
- ctrl_data_out.id = USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE;
- break;
- }
-
- /*******************************************************************
* Peek and Poke Register
******************************************************************/
case USRP2_CTRL_ID_POKE_THIS_REGISTER_FOR_ME_BRO:
@@ -463,25 +355,6 @@ eth_pkt_inspector(dbsm_t *sm, int bufno)
//------------------------------------------------------------------
-static bool vrt_has_trailer(void){
- return USRP2_HOST_RX_VRT_TRAILER_WORDS32 > 0;
-}
-
-static void setup_vrt(void){
- // setup RX DSP regs
- sr_rx_ctrl->nsamples_per_pkt = streaming_items_per_frame;
- sr_rx_ctrl->nchannels = 1;
- sr_rx_ctrl->clear_overrun = 1; // reset
- sr_rx_ctrl->vrt_header = (0
- | VRTH_PT_IF_DATA_WITH_SID
- | (vrt_has_trailer()? VRTH_HAS_TRAILER : 0)
- | VRTH_TSI_OTHER
- | VRTH_TSF_SAMPLE_CNT
- );
- sr_rx_ctrl->vrt_stream_id = 0;
- sr_rx_ctrl->vrt_trailer = 0;
-}
-
/*
* 1's complement sum for IP and UDP headers
*
@@ -554,13 +427,6 @@ fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false
buff->control_word = MK_RX_CTRL_WORD(vrt_len);
buff->vrt_header[0] = (buff->vrt_header[0] & ~VRTH_PKT_SIZE_MASK) | (vrt_len & VRTH_PKT_SIZE_MASK);
- // queue up another rx command when required
- if (auto_reload_command && --streaming_frame_count == 0){
- streaming_frame_count = FRAMES_PER_CMD;
- sr_rx_ctrl->time_secs = 0;
- sr_rx_ctrl->time_ticks = 0; //enqueue last command
- }
-
return false; // we didn't handle the packet
}
@@ -594,27 +460,6 @@ main(void)
register_udp_listener(USRP2_UDP_CTRL_PORT, handle_udp_ctrl_packet);
register_udp_listener(USRP2_UDP_DATA_PORT, handle_udp_data_packet);
- hal_set_led_src(0, LEDS_SW);
-
-#if 0
- // make bit 15 of Tx gpio's be a s/w output
- hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
- hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
-#endif
-
-//set them all to the atr settings by default
-hal_gpio_set_sels(GPIO_TX_BANK, "aaaaaaaaaaaaaaaa");
-hal_gpio_set_sels(GPIO_RX_BANK, "aaaaaaaaaaaaaaaa");
-
- output_regs->debug_mux_ctrl = 1;
-#if DEBUG_MODE
- hal_gpio_set_sels(GPIO_TX_BANK, "0000000000000000");
- hal_gpio_set_sels(GPIO_RX_BANK, "0000000000000000");
- hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
- hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
-#endif
-
-
// initialize double buffering state machine for ethernet -> DSP Tx
dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
@@ -662,13 +507,6 @@ hal_gpio_set_sels(GPIO_RX_BANK, "aaaaaaaaaaaaaaaa");
// FIXME Figure out how to handle this robustly.
// Any buffers that are emptying should be allowed to drain...
- if (auto_reload_command){
- // restart_streaming();
- // FIXME report error
- }
- else {
- // FIXME report error
- }
putchar('O');
}
}
diff --git a/firmware/microblaze/lib/Makefile.am b/firmware/microblaze/lib/Makefile.am
index 783895850..b51d74463 100644
--- a/firmware/microblaze/lib/Makefile.am
+++ b/firmware/microblaze/lib/Makefile.am
@@ -44,7 +44,6 @@ libu2fw_a_SOURCES = \
pic.c \
print_mac_addr.c \
print_rmon_regs.c \
- print_fxpt.c \
print_buffer.c \
printf.c \
sd.c \
diff --git a/firmware/microblaze/lib/banal.c b/firmware/microblaze/lib/banal.c
index 23f5f3b8a..42937957f 100644
--- a/firmware/microblaze/lib/banal.c
+++ b/firmware/microblaze/lib/banal.c
@@ -29,21 +29,3 @@ get_uint64(const unsigned char *s)
{
return (((uint64_t)get_uint32(s)) << 32) | get_uint32(s+4);
}
-
-uint32_t
-divide_uint64(uint64_t dividend, uint32_t divisor)
-{
- uint32_t result = 0;
- uint64_t dividend_ = 0;
- for(int i = 31; i >= 0; i--){
- //approximate the divisor with the ith result bit set
- uint64_t tmp = dividend_;
- tmp += (uint64_t)divisor << i;
- //set the ith result bit if the approximation is less
- if (tmp <= dividend){
- dividend_ = tmp;
- result |= 1 << i;
- }
- }
- return result;
-}
diff --git a/firmware/microblaze/lib/banal.h b/firmware/microblaze/lib/banal.h
index 6d9420602..7b3c71a20 100644
--- a/firmware/microblaze/lib/banal.h
+++ b/firmware/microblaze/lib/banal.h
@@ -87,7 +87,4 @@ get_int64(const unsigned char *s)
void
print_ip(struct ip_addr ip);
-uint32_t
-divide_uint64(uint64_t dividend, uint32_t divisor);
-
#endif /* INCLUDED_BANAL_H */
diff --git a/firmware/microblaze/lib/clocks.c b/firmware/microblaze/lib/clocks.c
index d9d4fcd3c..ccc4a7cc7 100644
--- a/firmware/microblaze/lib/clocks.c
+++ b/firmware/microblaze/lib/clocks.c
@@ -48,14 +48,14 @@ clocks_init(void)
clocks_mimo_config(MC_WE_DONT_LOCK);
// Set up other clocks
- clocks_enable_test_clk(false, 0);
- clocks_enable_tx_dboard(false, 0);
- clocks_enable_rx_dboard(false, 0);
+ //clocks_enable_test_clk(false, 0);
+ //clocks_enable_tx_dboard(false, 0);
+ //clocks_enable_rx_dboard(false, 0);
clocks_enable_eth_phyclk(false, 0);
// Enable clock to ADCs and DACs
- clocks_enable_dac_clk(true, 1);
- clocks_enable_adc_clk(true, 1);
+ //clocks_enable_dac_clk(true, 1);
+ //clocks_enable_adc_clk(true, 1);
}
@@ -168,11 +168,11 @@ clocks_enable_XXX_clk(bool enable, int divisor, int reg_en, int reg_div, int mod
}
// Clock 0
-void
+/*void
clocks_enable_test_clk(bool enable, int divisor)
{
clocks_enable_XXX_clk(enable,divisor,0x3C,0x48,CLOCK_MODE_PECL);
-}
+}*/
// Clock 1
void
@@ -211,29 +211,29 @@ clocks_enable_eth_phyclk(bool enable, int divisor)
}
// Clock 3
-void
+/*void
clocks_enable_dac_clk(bool enable, int divisor)
{
clocks_enable_XXX_clk(enable,divisor,0x3F,0x4E,CLOCK_MODE_PECL);
-}
+}*/
// Clock 4
-void
+/*void
clocks_enable_adc_clk(bool enable, int divisor)
{
clocks_enable_XXX_clk(enable,divisor,0x40,0x50,CLOCK_MODE_LVDS);
-}
+}*/
// Clock 6
-void
+/*void
clocks_enable_tx_dboard(bool enable, int divisor)
{
clocks_enable_XXX_clk(enable,divisor,0x42,0x54,CLOCK_MODE_CMOS);
-}
+}*/
// Clock 7
-void
+/*void
clocks_enable_rx_dboard(bool enable, int divisor)
{
clocks_enable_XXX_clk(enable,divisor,0x43,0x56,CLOCK_MODE_CMOS);
-}
+}*/
diff --git a/firmware/microblaze/lib/clocks.h b/firmware/microblaze/lib/clocks.h
index 141fc61e0..43d5a05c2 100644
--- a/firmware/microblaze/lib/clocks.h
+++ b/firmware/microblaze/lib/clocks.h
@@ -53,7 +53,7 @@ bool clocks_lock_detect();
/*!
* \brief Enable or disable test clock (extra clock signal)
*/
-void clocks_enable_test_clk(bool enable, int divisor);
+//void clocks_enable_test_clk(bool enable, int divisor);
/*!
* \brief Enable or disable fpga clock. Disabling would wedge and require a power cycle.
@@ -73,23 +73,23 @@ void clocks_enable_eth_phyclk(bool enable, int divisor);
/*!
* \brief Enable or disable clock to DAC
*/
-void clocks_enable_dac_clk(bool enable, int divisor);
+//void clocks_enable_dac_clk(bool enable, int divisor);
/*!
* \brief Enable or disable clock to ADC
*/
-void clocks_enable_adc_clk(bool enable, int divisor);
+//void clocks_enable_adc_clk(bool enable, int divisor);
/*!
* \brief Enable or disable clock to Rx daughterboard
*/
-void clocks_enable_rx_dboard(bool enable, int divisor);
+//void clocks_enable_rx_dboard(bool enable, int divisor);
/*!
* \brief Enable or disable clock to Tx daughterboard
*/
-void clocks_enable_tx_dboard(bool enable, int divisor);
+//void clocks_enable_tx_dboard(bool enable, int divisor);
#endif /* INCLUDED_CLOCKS_H */
diff --git a/firmware/microblaze/lib/hal_io.c b/firmware/microblaze/lib/hal_io.c
index fdfa15000..0afd6a2cc 100644
--- a/firmware/microblaze/lib/hal_io.c
+++ b/firmware/microblaze/lib/hal_io.c
@@ -24,134 +24,6 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
-//#include <assert.h>
-
-/*
- * ========================================================================
- * GPIOS
- * ========================================================================
- */
-void
-hal_gpio_set_ddr(int bank, int value, int mask)
-{
- bank &= 0x1;
-
- if (bank == GPIO_TX_BANK){ // tx in top half
- value <<= 16;
- mask <<= 16;
- }
- else {
- value &= 0xffff;
- mask &= 0xffff;
- }
-
- int ei = hal_disable_ints();
- gpio_base->ddr = (gpio_base->ddr & ~mask) | (value & mask);
- hal_restore_ints(ei);
-}
-
-static bool
-code_to_int(char code, int *val)
-{
- switch(code){
- case 's': *val = GPIO_SEL_SW; return true;
- case 'a': *val = GPIO_SEL_ATR; return true;
- case '0': *val = GPIO_SEL_DEBUG_0; return true;
- case '1': *val = GPIO_SEL_DEBUG_1; return true;
- case '.':
- default:
- return false;
- }
-}
-
-void
-hal_gpio_set_sel(int bank, int bitno, char code)
-{
- bank &= 0x1;
- int t;
-
- if (!code_to_int(code, &t))
- return;
-
- int val = t << (2 * bitno);
- int mask = 0x3 << (2 * bitno);
-
- volatile uint32_t *sel = bank == GPIO_TX_BANK ? &gpio_base->tx_sel : &gpio_base->rx_sel;
- int ei = hal_disable_ints();
- int v = (*sel & ~mask) | (val & mask);
- *sel = v;
- hal_restore_ints(ei);
-
- if (0)
- printf("hal_gpio_set_sel(bank=%d, bitno=%d, code=%c) *sel = 0x%x\n",
- bank, bitno, code, v);
-}
-
-void
-hal_gpio_set_sels(int bank, char *codes)
-{
- //assert(strlen(codes) == 16);
-
- int val = 0;
- int mask = 0;
- int i;
-
- for (i = 15; i >= 0; i--){
- val <<= 2;
- mask <<= 2;
- int t;
- if (code_to_int(codes[i], &t)){
- val |= t;
- mask |= 0x3;
- }
- }
-
- volatile uint32_t *sel = bank == GPIO_TX_BANK ? &gpio_base->tx_sel : &gpio_base->rx_sel;
- int ei = hal_disable_ints();
- *sel = (*sel & ~mask) | (val & mask);
- hal_restore_ints(ei);
-}
-
-
-/*!
- * \brief write \p value to gpio pins specified by \p mask.
- */
-void
-hal_gpio_write(int bank, int value, int mask)
-{
- static uint32_t _gpio_io_shadow;
-
- bank &= 0x1;
-
- if (bank == GPIO_TX_BANK){ // tx in top half
- value <<= 16;
- mask <<= 16;
- }
- else {
- value &= 0xffff;
- mask &= 0xffff;
- }
-
- //int ei = hal_disable_ints();
- _gpio_io_shadow = (_gpio_io_shadow & ~mask) | (value & mask);
- gpio_base->io = _gpio_io_shadow;
- //hal_restore_ints(ei);
-}
-
-
-/*!
- * \brief read GPIO bits
- */
-int
-hal_gpio_read(int bank)
-{
- bank &= 0x1;
- int r = gpio_base->io;
- if (bank == GPIO_TX_BANK)
- r >>= 16;
-
- return r & 0xffff;
-}
/*
* ========================================================================
diff --git a/firmware/microblaze/lib/hal_io.h b/firmware/microblaze/lib/hal_io.h
index f8ec617f8..d8967f063 100644
--- a/firmware/microblaze/lib/hal_io.h
+++ b/firmware/microblaze/lib/hal_io.h
@@ -24,64 +24,6 @@
void hal_io_init(void);
void hal_finish();
-
-/*
- * ------------------------------------------------------------------------
- * The GPIO pins are organized into two banks of 16-bits.
- * Bank 0 goes to the Tx daughterboard, Bank 1 goes to the Rx daughterboard.
- *
- * Each pin may be configured as an input or an output from the FPGA.
- * For output pins, there are four signals which may be routed to the
- * pin. The four signals are the value written by s/w, the output of
- * the ATR controller, or two different sources of debug info from the
- * FPGA fabric.
- * ------------------------------------------------------------------------
- */
-
-#define GPIO_TX_BANK 0 // pins that connect to the Tx daughterboard
-#define GPIO_RX_BANK 1 // pins that connect to the Rx daughterboard
-
-
-/*!
- * \brief Set the data direction for GPIO pins
- *
- * If the bit is set, it's an output from the FPGA.
- * \param value is a 16-bit bitmask of values
- * \param mask is a 16-bit bitmask of which bits to effect.
- */
-void hal_gpio_set_ddr(int bank, int value, int mask);
-
-/*!
- * \brief Select the source of the signal for an output pin.
- *
- * \param code is is one of 's', 'a', '0', '1'
- * where 's' selects software output, 'a' selects ATR output, '0' selects
- * debug 0, '1' selects debug 1.
- */
-void hal_gpio_set_sel(int bank, int bitno, char code);
-
-/*!
- * \brief Select the source of the signal for the output pins.
- *
- * \param codes is is a string of 16 characters composed of '.', 's',
- * 'a', '0', or '1' where '.' means "don't change", 's' selects
- * software output, 'a' selects ATR output, '0' selects debug 0, '1'
- * selects debug 1.
- */
-void hal_gpio_set_sels(int bank, char *codes);
-
-
-/*!
- * \brief write \p value to gpio pins specified by \p mask.
- */
-void hal_gpio_write(int bank, int value, int mask);
-
-/*!
- * \brief read GPIO bits
- */
-int hal_gpio_read(int bank);
-
-
/*
* ------------------------------------------------------------------------
* control the leds
diff --git a/firmware/microblaze/lib/memory_map.h b/firmware/microblaze/lib/memory_map.h
index fed1e5259..cdf3dd338 100644
--- a/firmware/microblaze/lib/memory_map.h
+++ b/firmware/microblaze/lib/memory_map.h
@@ -525,10 +525,6 @@ typedef struct {
volatile uint32_t pad[7]; // Make each structure 16 elements long
} sr_rx_ctrl_t;
-#define MAX_SAMPLES_PER_CMD 0x3fffffff
-#define MK_RX_CMD(nsamples, now, chain) \
- ((((now) & 0x1) << 31) | (((chain) & 0x1) << 30) | ((nsamples) & 0x3fffffff))
-
#define sr_rx_ctrl ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL))
// --- dsp rx regs ---
diff --git a/firmware/microblaze/lib/print_fxpt.c b/firmware/microblaze/lib/print_fxpt.c
deleted file mode 100644
index 185bbc51b..000000000
--- a/firmware/microblaze/lib/print_fxpt.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * 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 3 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, see <http://www.gnu.org/licenses/>.
- */
-#include <nonstdio.h>
-
-/*
- * print uint64_t
- */
-void
-print_uint64(uint64_t u)
-{
- const char *_hex = "0123456789ABCDEF";
- if (u >= 10)
- print_uint64(u/10);
- putchar(_hex[u%10]);
-}
-
-static void
-print_thousandths(int thousandths)
-{
- putchar('.');
- if (thousandths < 100)
- putchar('0');
- if (thousandths < 10)
- putchar('0');
- printf("%d", thousandths);
-}
-
-
-void
-print_fxpt_freq(u2_fxpt_freq_t v)
-{
- if (v < 0){
- v = -v;
- putchar('-');
- }
-
- int64_t int_part = v >> 20;
- int32_t frac_part = v & ((1 << 20) - 1);
-
-#if 0
- // would work, if we had it
- printf("%lld.%03d", int_part, (frac_part * 1000) >> 20);
-#else
- print_uint64(int_part);
- print_thousandths((frac_part * 1000) >> 20);
-#endif
-}
-
-void
-print_fxpt_gain(u2_fxpt_gain_t v)
-{
- if (v < 0){
- v = -v;
- putchar('-');
- }
-
- int32_t int_part = v >> 7;
- int32_t frac_part = v & ((1 << 7) - 1);
-
-#if 0
- // would work, if we had it
- printf("%d.%03d", int_part, (frac_part * 1000) >> 7);
-#else
- printf("%d", int_part);
- print_thousandths((frac_part * 1000) >> 7);
-#endif
-}
-
diff --git a/firmware/microblaze/lib/print_mac_addr.c b/firmware/microblaze/lib/print_mac_addr.c
index 838fd614a..475082325 100644
--- a/firmware/microblaze/lib/print_mac_addr.c
+++ b/firmware/microblaze/lib/print_mac_addr.c
@@ -20,11 +20,9 @@
void
print_mac_addr(const unsigned char addr[6])
{
- puthex8(addr[0]); putchar(':');
- puthex8(addr[1]); putchar(':');
- puthex8(addr[2]); putchar(':');
- puthex8(addr[3]); putchar(':');
- puthex8(addr[4]); putchar(':');
- puthex8(addr[5]);
+ for(size_t i = 0; i < 6; i++){
+ if(i) putchar(':');
+ puthex8(addr[i]);
+ }
}
diff --git a/firmware/microblaze/lib/u2_init.c b/firmware/microblaze/lib/u2_init.c
index 399d834cb..6809101c0 100644
--- a/firmware/microblaze/lib/u2_init.c
+++ b/firmware/microblaze/lib/u2_init.c
@@ -46,15 +46,6 @@ get_hw_rev(void)
bool
u2_init(void)
{
- // Set GPIOs to inputs, disable GPIO streaming
- hal_gpio_set_ddr(GPIO_TX_BANK, 0x0000, 0xffff);
- hal_gpio_set_ddr(GPIO_RX_BANK, 0x0000, 0xffff);
-
- hal_gpio_write(GPIO_TX_BANK, 0x0000, 0xffff); // init s/w output value to zero
- hal_gpio_write(GPIO_RX_BANK, 0x0000, 0xffff);
-
- dsp_rx_regs->gpio_stream_enable = 0; // I, Q LSBs come from DSP
-
hal_io_init();
// init spi, so that we can switch over to the high-speed clock
@@ -67,18 +58,6 @@ u2_init(void)
// set up the default clocks
clocks_init();
- // clocks_enable_test_clk(true,1);
-
- // Enable ADCs
- output_regs->adc_ctrl = ADC_CTRL_ON;
-
- // Initial values for tx and rx mux registers
- dsp_tx_regs->tx_mux = 0x10;
- dsp_rx_regs->rx_mux = 0x44444444;
-
- // Set up serdes
- output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN);
-
pic_init(); // progammable interrupt controller
bp_init(); // buffer pool
diff --git a/fpga/usrp2/control_lib/nsgpio.v b/fpga/usrp2/control_lib/nsgpio.v
index 937ea7020..26130cc8e 100644
--- a/fpga/usrp2/control_lib/nsgpio.v
+++ b/fpga/usrp2/control_lib/nsgpio.v
@@ -95,7 +95,7 @@ module nsgpio
integer n;
reg [31:0] igpio; // temporary internal signal
- always @(ctrl or line or debug_1 or debug_0 or atr)
+ always @(ctrl or line or debug_1 or debug_0 or atr or ddr)
for(n=0;n<32;n=n+1)
igpio[n] <= ddr[n] ? (ctrl[2*n+1] ? (ctrl[2*n] ? debug_1[n] : debug_0[n]) :
(ctrl[2*n] ? atr[n] : line[n]) )
diff --git a/fpga/usrp2/control_lib/settings_bus.v b/fpga/usrp2/control_lib/settings_bus.v
index d01a30ab4..fc960e456 100644
--- a/fpga/usrp2/control_lib/settings_bus.v
+++ b/fpga/usrp2/control_lib/settings_bus.v
@@ -10,7 +10,6 @@ module settings_bus
input wb_stb_i,
input wb_we_i,
output reg wb_ack_o,
- input sys_clk,
output strobe,
output reg [7:0] addr,
output reg [31:0] data);
diff --git a/fpga/usrp2/control_lib/settings_bus_crossclock.v b/fpga/usrp2/control_lib/settings_bus_crossclock.v
new file mode 100644
index 000000000..b043aa0ad
--- /dev/null
+++ b/fpga/usrp2/control_lib/settings_bus_crossclock.v
@@ -0,0 +1,20 @@
+
+
+// This module takes the settings bus on one clock domain and crosses it over to another domain
+// Typically it will be used with the input settings bus on the wishbone clock, and either
+// the system or dsp clock on the output side
+
+module settings_bus_crossclock
+ (input clk_i, input rst_i, input set_stb_i, input [7:0] set_addr_i, input [31:0] set_data_i,
+ input clk_o, input rst_o, output set_stb_o, output [7:0] set_addr_o, output [31:0] set_data_o);
+
+ wire full, empty;
+
+ fifo_xlnx_16x40_2clk settings_fifo
+ (.rst(rst_i),
+ .wr_clk(clk_i), .din({set_addr_i,set_data_i}), .wr_en(set_stb_i & ~full), .full(full),
+ .rd_clk(clk_o), .dout({set_addr_o,set_data_o}), .rd_en(~empty), .empty(empty));
+
+ assign set_stb_o = ~empty;
+
+endmodule // settings_bus_crossclock
diff --git a/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.ngc b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.ngc
new file mode 100644
index 000000000..f42663419
--- /dev/null
+++ b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.ngc
@@ -0,0 +1,3 @@
+XILINX-XDB 0.1 STUB 0.1 ASCII
+XILINX-XDM V1.4e
+$2604g<,[o}e~g`n;"2*413&;$>"9 > %10?*nhel%fmyz cnpfc`h(|dz$Sni fhdl[}jipV;=t9>P2bnh*kah92:?7=>=10927>7)881986=<22087=b<;z8;<=hh444.14=39;1?<7GAPTV9`lh;;00;2<:4418LQQVR\3ndyy2<9;2=5`=32@D[YY4rne\ahvsqV~c~h}g<283:73<<3CE\XZ5psmd[`kw|pUdk|h^cpw`ts4:0;2?;44;KMTPR=x{elShctx]wlwct`Vdnklzj<283:4b<<3CE\XZ5psmd[cskdV~c~h}g<283:72<<3CE\XZ5psmd[cskdV~c~h}g_`qpawr;;3:5>95;:HLSQQ<wzfmTjxbc_ujqavnXflmjxh2<:1<2<>2=G\^[YY4kauc\gjsi|591<3?m;58LQQVR\3xoSio{a^alqkr;;3:5=o5;:NWWTPR={UomyoPcnwmp95=87;0:9599847?3?F9;1=O959CBA1?3C53>N?75:=109:0>?789>05=>62:;56>G7:2K:>6O=2:C0=>GTQGIT^HI<;CW1<>DR[VCEJB?4C59@E=G53JO:>6MGEBI\HLEBFZOTXT^J3:AOV<=DGDGBXYKK159@KWCXOLDN^LZFOO]JJCI03JXNMYKK1:F0?AVH=2N[^L>:;ERQE43<LYXJ>85KPSC00>@?0180JI=4FEA7?CBDM:1MH]:4FERF1>@fdzo:7J=4GOF2?L4<A980E<<4I308M6?<AGC__YO[E29JJS5<AFH97AA9;MMB@@B03EELENOC4:NVP72<D\^886BZT548HPR3WE?0A^I@Nb9Neoiu^lxxeb`l;LkmkwPbzzcdb>5A1168J467<2D:<<:4N0210>H68:>0B<>;4:L2402<F8:=86@>0668J46?<2D:<4=4N037?K768=1E=<?;;O3261=I989?7C?>459M54333G;::95A1057?K760=1E=<7<;O310>H6:9>0B<<>4:L2672<F88886@>2568J442;2D:?>5A1518J4343G;=?6@>729M5=5<F8387C<?3:L156=I:;90B?=<;O077>H5=:1E>;=4N350?K4?;2D95>5A3118J6743G99?6@<329M715<F:?87C=93:L036=I;190B>7<;O637>H39:1E8?=4N510?K23;2D?9?5A639M36=I?990B:?<;O507>H0=:1E;;<4N918J=243G2>?6@7629M<25<F1287C662:L:7>H>8:1E5<=4N800?K?4;2D28>5A9418J<043G3<?6@6829M=<`<FKUIY^^FN^RQKUU03GO_[B\D1:M1?JM63Y>0\L\[a:RJJZDR[@NSn6^FN^@VWKGJM:1[^H?4Q99QEH71P8N=7^AZRBG0?VVH<2^R\H=<;T2,cw`)zo%lou lljz,I}iuW{nT|cz}_ckm[}iu89:;S_k|umv276=R8&myj#|i/fa{*fjlp&GscQ}d^rmpwYeagUsc>?00]Qavsk|8987X> gsd-vc)`kq$h`fv Mymq[wbXxg~ySoga_ymq4565W[oxyaz>339V4*aun'xm#jmw.bnh|*Kg{UyhR~ats]dgZ~hz9:;<R\jstnw564<]9%l~k }f.e`|+ekcq%Ftb|Pre]sjqtXojUsc>?00]Qavsk|8997X> gsd-vc)`kq$h`fv Mymq[wbXxg~ySjmPxnp3454XZly~`y?<3:W3+bta&{l$knv!cmi{+H~hzV}yS}`{r^`jjZ~hz9:;<R\jstnw565<]9%l~k }f.e`|+ekcq%Ftb|Pws]sjqtXj`dTtb|?013\V`urd};8?6[?/fpe*w`(ojr%oaew/LzlvZquWyd~Rlfn^zlv567:VXnxb{1208Q5)`zo$yj"ilx/aoo})JpfxT{Qnup\cfYg{:;<=Q]erwop4553\:$kh!rg-dg}(ddbr$Aua}_vp\tkruWniTtb|?013\V`urd};8>6[?/fpe*w`(ojr%oaew/LzlvZquWyd~Ril_ymq4565W[oxyaz>209V4*aun'xm#jmw.bnh|*tcWyd~Rlfn=2=64=R8&myj#|i/fa{*fjlp&xoS}`{r^`jj979:81^<"i}f/pe+be&jf`t"|k_qlwvZdnf585><5Z0.eqb+ta'nis"nbdx.pg[uhszVhbb1=1219V4*aun'xm#jmw.bnh|*tcWyd~Rlfn^214>S7'nxm"h gbz-gim'{nT|cz}_ckm[4473\:$kh!rg-dg}(ddbr$~iQnup\flhX:;:0Y=!hrg,qb*adp'iggu!}d^rmpwYeagU8>;5Z0.eqb+ta'nis"nbdx.pg[uhszVhbbRv`r123470<]9%l~k }f.e`|+ekcq%yhR~ats]amkYg{:;<<<9;T2,cw`)zo%lou lljz,vaYwf}xTnd`Pxnp3454582_;#j|i.sd,cf~)keas#jPpovq[be;878;7X> gsd-vc)`kq$h`fv re]sjqtXoj6:2?>4U1-dvc(un&mht#mcky-q`Zvi|{Ulo1<1219V4*aun'xm#jmw.bnh|*tcWyd~Ril<2<2b>S7'nxm"h gbz-gim'{nT|cz}_fa\44`<]9%l~k }f.e`|+ekcq%yhR~ats]dgZ76n2_;#j|i.sd,cf~)keas#jPpovq[beX:8l0Y=!hrg,qb*adp'iggu!}d^rmpwY`kV99:6[?/fpe*w`(ojr%oaew/sf\tkruWniTm~|jg=2=63=R8&myj#|i/fa{*fjlp&xoS}`{r^e`[duumn6:2?84U1-dvc(un&mht#mcky-q`Zvi|{UloRo|rde?6;413\:$kh!rg-dg}(ddbr$~iQnup\cfYf{{ol0>0=5:W3+bta&{l$knv!cmi{+wbXxg~ySjmParpfcZ65=2_;#j|i.sd,cf~)keas#jPpovq[beXizxnkR?=5:W3+bta&{l$knv!cmi{+wbXxg~ySjmParpfcZ45=2_;#j|i.sd,cf~)keas#jPpovq[beXizxnkR==9:W3+bta&{l$knv!cmi{+wbXxg~ySjmParpfcZb6494956[?/fpe*w`(ojr%oaew/sf\tkruWniTm~|jg^f2848512_;#j|i.sd,cf~)keas#jPpovq[beXizxnkRj><3<1=>S7'nxm"h gbz-gim'{nT|cz}_fa\evtboVn:0>0=8:W3+bta&{l$knv!cmi{+wbXxg~ySjmParpfcZb6W9837X> gsd-vc)`kq$h`fv re]sjqtXojUjkh_e3\57><]9%l~k }f.e`|+ekcq%yhR~ats]dgZgtzlmTh<Q=299V4*aun'xm#jmw.bnh|*tcWyd~Ril_`qqabYc9V9996[?/fpe*w`(ojr%oaew/sf\tkruWniTtb|?01211>S7'nxm"h gbz-gim'{nT|cz}_fa\|jt789;996[?/fpe*w`(ojr%oaew/sf\tkruWniTtb|?01015>S7'nxm"h gbz-gim'~xT|cz}_ckm858592_;#j|i.sd,cf~)keas#z|Ppovq[goi4849=6[?/fpe*w`(ojr%oaew/vp\tkruWkce0?0=1:W3+bta&{l$knv!cmi{+rtXxg~ySoga<2<14>S7'nxm"h gbz-gim'~xT|cz}_ckm[5473\:$kh!rg-dg}(ddbr${Qnup\flhX9;:0Y=!hrg,qb*adp'iggu!xr^rmpwYeagU9>=5Z0.eqb+ta'nis"nbdx.uq[uhszVhbbR==6:W3+bta&{l$knv!cmi{+rtXxg~ySoga_ymq4567:?1^<"i}f/pe+be&jf`t"y}_qlwvZdnfVrd~=>?1348Q5)`zo$yj"ilx/aoo})pzVzexQmio]{kw678;8;7X> gsd-vc)`kq$h`fv ws]sjqtXoj6;2?>4U1-dvc(un&mht#mcky-tvZvi|{Ulo1?1219V4*aun'xm#jmw.bnh|*quWyd~Ril<3<14>S7'nxm"h gbz-gim'~xT|cz}_fa?7;7a3\:$kh!rg-dg}(ddbr${Qnup\cfY79o1^<"i}f/pe+be&jf`t"y}_qlwvZadW8;m7X> gsd-vc)`kq$h`fv ws]sjqtXojU9=k5Z0.eqb+ta'nis"nbdx.uq[uhszVmhS><9;T2,cw`)zo%lou lljz,swYwf}xTknQnssgd8585>2_;#j|i.sd,cf~)keas#z|Ppovq[beXizxnk1?1279V4*aun'xm#jmw.bnh|*quWyd~Ril_`qqab:56;<0Y=!hrg,qb*adp'iggu!xr^rmpwY`kVkx~hi33?06?P6(o{l%~k!hcy,`hn~({U{by|Pgb]bwwc`W98>7X> gsd-vc)`kq$h`fv ws]sjqtXojUjkh_006?P6(o{l%~k!hcy,`hn~({U{by|Pgb]bwwc`W;8>7X> gsd-vc)`kq$h`fv ws]sjqtXojUjkh_20:?P6(o{l%~k!hcy,`hn~({U{by|Pgb]bwwc`Wm;7<3<6;T2,cw`)zo%lou lljz,swYwf}xTknQnssgd[a7;97827X> gsd-vc)`kq$h`fv ws]sjqtXojUjkh_e3?6;4>3\:$kh!rg-dg}(ddbr${Qnup\cfYf{{olSi?33?0;?P6(o{l%~k!hcy,`hn~({U{by|Pgb]bwwc`Wm;T<?64U1-dvc(un&mht#mcky-tvZvi|{UloRo|rde\`4Y6:11^<"i}f/pe+be&jf`t"y}_qlwvZadWhyyijQk1^01<>S7'nxm"h gbz-gim'~xT|cz}_fa\evtboVn:S><:;T2,cw`)zo%lou lljz,swYwf}xTknQwos2345423\:$kh!rg-dg}(ddbr${Qnup\cfYg{:;<<<:;T2,cw`)zo%lou lljz,swYwf}xTknQwos23474f3\:$kh!rg-dh5(ul&my=#|iwgv,VDKXZMUNBRHXFU31g>S7'nxm"h gm2-va)`z8$yjzh{/SCN[WBXMGUM[KZ>_00:?P6(o{l%~k!hl1,q`*au9'xm{kz R@O\V@AH]]UNB<=<;T2,cw`)zo%l`= }d.eq5+tao~$ox|}_guepZusi}oTJ^CPFGf273=R8&myj#|i/fn3*wb(o{;%~kyit.avvwYao~Tyo{e^DPIZ@Al8'Bb>64U1-dvc(un&mg<#|k/fp2*w`pn}%hy|Pfvdw[vrf|lUM_@QIFe3.Mk76;:1^<"i}f/pe+bj7&{n$k?!rguep*erz{Um{kzPsucwaZ@TEVLMh?=9;T2,cw`)zo%l`= }d.eq5+tao~$ox|}_guepZusi}oTJ^CPFGf1)Lh402_;#j|i.sd,ci6)zm%l~< }fvdw+fsuzVl|jyQ|t`vf[CUJWOLo> Ga100;?P6(o{l%~k!hl1,q`*au9'xm{kz elrw}Z`pn}Umn?94U1-dvc(un&mg<#|k/fp2*w`pn}%na}zv_guepZo5m2_;#j|i.sd,ci6)zm%l~< }fvdw+`kw|pUm{kzPi^mq4567:o1^<"i}f/pe+bj7&{n$k?!rguep*cjx}sTjzh{_h]lv56788827X> gsd-vc)`d9$yh"i}ar,qwqu(zhgTi`~{y^da[l573\:$kh!rg-dh5(ul&mym~ }suq,vdkXmdzuRhm_h]lv5678:90Y=!hrg,qb*ak8'xo#j|ns/pppv)uidUna}zv_g`\mZiu89:;=<?<3:W3+bta&{l$ka>!re-dvdu)zz~x#ob_dosp|YajVcTc>?0132<65<]9%l~k }f.eo4+tc'nxj#||tr-qehYbey~rSklPi^mq45679=;8>6[?/fpe*w`(oe:%~i!hr`q-vvrt'{kfShctx]efZoXg{:;<=<9339V4*aun'xm#jb?.sf,cwgt&{y"|nm^gntqXnkUbSb|?0126764<]9%l~k }f.eo4+tc'nxj#||tr-qehYbey~rSklPi^mq45671:887X> gsd-vc)`d9$yh"|nup,Ifirf}Uhcx`{259V4*aun'xm#jb?.sf,vuhsz&Ghcx`{_bmvjq55<2_;#j|i.sd,ci6)zm%y|cz}/LalqkrXkfex;<;;T2,cw`)zo%l`= }d.psjqt(Eje~byQlotlw=64<]9%l~k }f.eo4+tc'{zex!BcnwmpZeh}g~Ttb|30?32[LHQW98h7X> gsd-vc)`d9$yh"|nup,Ifirf}Uhcx`{_ymq84869;i0Y=!hrg,qb*ak8'xo#~ats-Ngjsi|VidyczPxnp?6;76:j1^<"i}f/pe+bj7&{n$~}`{r.O`kphsWje~byQwos>0:476n2_;#j|i.sd,ci6)zm%y|cz}/bmvjq:768l0Y=!hrg,qb*ak8'xo#~ats-`kphs484:j6[?/fpe*w`(oe:%~i!}povq+firf}692<h4U1-dvc(un&mg<#|k/srmpw)dg|d0>0>e:W3+bta&{l$ka>!re-qtkru'je~byQ?1d9V4*aun'xm#jb?.sf,vuhsz&idyczP10g8Q5)`zo$yj"ic0/pg+wvi|{%hcx`{_33f?P6(o{l%~k!hl1,q`*twf}x$ob{at^116>S7'nxm"h gm2-va)uxg~y#naznu]g5969:;1^<"i}f/pe+bj7&{n$~}`{r.alqkrXl86:2?<4U1-dvc(un&mg<#|k/srmpw)dg|dSi?32?01?P6(o{l%~k!hl1,q`*twf}x$ob{at^f2868592_;#j|i.sd,ci6)zm%y|cz}/bmvjqYc9V:9=6[?/fpe*w`(oe:%~i!}povq+firf}Uo=R?=1:W3+bta&{l$ka>!re-qtkru'je~byQk1^015>S7'nxm"h gm2-va)uxg~y#naznu]g5Z55<2_;#j|i.sd,ci6)zm%y|cz}/bmvjqYig}:;<<<7;T2,cw`)zo%l`= xr.etev(p{}y$~lcPftno[cdXa;?0Y=!hrg,qb*ak8'}y#jyns/uppv)uidUmyabPi3a8Q5)`zo$yj"ic0/uq+bqf{'}xx~!}al]eqijXaVey<=>?2g9V4*aun'xm#jb?.vp,crgt&~y"|nm^dvhiYnWfx;<=>>1910?P6(o{l%~k!hl1,tv*apiz$|y} r`o\bpjkW`Ud~=>?003;[VQ7:o1^<"i}f/pe+bj7&~x$kzo|.vqww*tfeVl~`aQf_np34566<88n7X> gsd-vc)`d9$|~"ixar,twqu(zhgTjxbc_h]lv5678;<9i6[?/fpe*w`(oe:%{!hw`q-svrt'{kfSk{cl^k\kw6789?8>h5Z0.eqb+ta'nf;"z| gvcp*rus{&xjaRhzlm]j[jt789:2?<j4U1-dvc(un&mg<#y}/scn[rtXmgUb=?=4U1-dvc(un&mg<#y}/vrmpw)JkfexRm`uov10>S7'nxm"h gm2-sw)pxg~y#@m`uov\gjsi|:8?7X> gsd-vc)`d9$|~"ynup,Ifirf}Uhcx`{6368Q5)`zo$yj"ic0/uq+rvi|{%Fob{at^alqkr>;;1^<"i}f/pe+bj7&~x${}`{r.O`kphsWje~byQwos>3:47XAG\T<?m4U1-dvc(un&mg<#y}/vrmpw)JkfexRm`uov\|jt;97;:>n5Z0.eqb+ta'nf;"z| wqlwv*Kdg|dSnaznu]{kw:568;9o6[?/fpe*w`(oe:%{!xpovq+Heh}g~Tob{at^zlv95998;m7X> gsd-vc)`d9$|~"ynup,gjsi|5:5=k5Z0.eqb+ta'nf;"z| wqlwv*eh}g~7=3?i;T2,cw`)zo%l`= xr.usjqt(kfex1<11g9V4*aun'xm#jb?.vp,suhsz&idycz33?3f?P6(o{l%~k!hl1,tv*qwf}x$ob{at^22a>S7'nxm"h gm2-sw)pxg~y#naznu]25`=R8&myj#|i/fn3*rt(yd~"m`uov\64c<]9%l~k }f.eo4+qu'~zex!lotlw[6453\:$kh!rg-dh5(pz&}{by| cnwmpZb64949>6[?/fpe*w`(oe:%{!xpovq+firf}Uo=1?1239V4*aun'xm#jb?.vp,suhsz&idyczPd0>1:74<]9%l~k }f.eo4+qu'~zex!lotlw[a7;;78:7X> gsd-vc)`d9$|~"ynup,gjsi|Vn:S=<>;T2,cw`)zo%l`= xr.usjqt(kfexRj>_002?P6(o{l%~k!hl1,tv*qwf}x$ob{at^f2[7463\:$kh!rg-dh5(pz&}{by| cnwmpZb6W:897X> gsd-vc)`d9$|~"ynup,gjsi|Vn90=0=2:W3+bta&{l$ka>!ws-ttkru'je~byQk2=3=67=R8&myj#|i/fn3*rt(yd~"m`uov\`7:56;80Y=!hrg,qb*ak8'}y#z~ats-`kphsWm87?3<>;T2,cw`)zo%l`= xr.usjqt(kfexRj=_102?P6(o{l%~k!hl1,tv*qwf}x$ob{at^f1[4463\:$kh!rg-dh5(pz&}{by| cnwmpZb5W;8:7X> gsd-vc)`d9$|~"ynup,gjsi|Vn9S><;;T2,cw`)zo%l`= xr.usjqt(kfexR``t123540<]9%l~k }f.ofi*bh}}UbS=?9;T2,cw`)zo%fi`!kotv\mZ76?2_;#j|i.sd,i`k(lfSdQ>0058Q5)`zo$yj"cjm.flqqYnW8;:;6[?/fpe*w`(elg$hb{{_h]2641<]9%l~k }f.ofi*bh}}UbS<=>7:W3+bta&{l$ahc dnww[lY6<8=0Y=!hrg,qb*kbe&ndyyQf_0723>S7'nxm"h mdo,`jssW`U::<94U1-dvc(un&gna"j`uu]j[416?2_;#j|i.sd,i`k(lfSdQ>8058Q5)`zo$yj"cjm.flqqYnW83::6[?/fpe*w`(elg$hb{{_h]152=R8&myj#|i/lgn+air|VcT>=?8;T2,cw`)zo%fi`!kotv\mZ469>1^<"i}f/pe+hcj'me~xRgP2334?P6(o{l%~k!bel-gkprXaV88=:5Z0.eqb+ta'dof#iazt^k\61703\:$kh!rg-nah)cg|~TeR<:169V4*aun'xm#`kb/emvpZoX:?;<7X> gsd-vc)jmd%ocxzPi^0452=R8&myj#|i/lgn+air|VcT>5?8;T2,cw`)zo%fi`!kotv\mZ4>9?1^<"i}f/pe+hcj'me~xRgP3058Q5)`zo$yj"cjm.flqqYnW:::;6[?/fpe*w`(elg$hb{{_h]0541<]9%l~k }f.ofi*bh}}UbS><>7:W3+bta&{l$ahc dnww[lY4;8=0Y=!hrg,qb*kbe&ndyyQf_2623>S7'nxm"h mdo,`jssW`U89<94U1-dvc(un&gna"j`uu]j[606?2_;#j|i.sd,i`k(lfSdQ<7058Q5)`zo$yj"cjm.flqqYnW:2:;6[?/fpe*w`(elg$hb{{_h]0=40<]9%l~k }f.ofi*bh}}UbS9?9;T2,cw`)zo%fi`!kotv\mZ36>2_;#j|i.sd,i`k(lfSdQ9179V4*aun'xm#`kb/emvpZoX?8<0Y=!hrg,qb*kbe&ndyyQf_935?P6(o{l%~k!bel-gkprXaV3:i6[?/fpe*w`(elg$kic!dl-NvdkXZHG:=k5Z0.eqb+ta'dof#jjb.eo,IwgjW[KF==?i;T2,cw`)zo%fi`!hdl,gi*KuidUYM@?>1g9V4*aun'xm#`kb/ffn*ak(E{kfS_OB133e?P6(o{l%~k!bel-d`h(ce&Gym`Q]AL305c=R8&myj#|i/lgn+bbj&mg$Aob_SCN517a3\:$kh!rg-nah)`ld$oa"C}al]QEH729o1^<"i}f/pe+hcj'nnf"ic Mscn[WGJ9?;m7X> gsd-vc)jmd%lh` km.OqehYUID;<=k5Z0.eqb+ta'dof#jjb.eo,IwgjW[KF=5?i;T2,cw`)zo%fi`!hdl,gi*KuidUYM@?61d9V4*aun'xm#`kb/ffn*ak(E{kfS_OB20d8Q5)`zo$yj"cjm.egi+bj'DxjaR\NM322b>S7'nxm"h mdo,cak)ld%F~lcPR@O154`<]9%l~k }f.ofi*ace'nf#@|nm^PBI746n2_;#j|i.sd,i`k(omg%h`!Br`o\VDK5;8l0Y=!hrg,qb*kbe&moa#jb/LpbiZTFE;>:j6[?/fpe*w`(elg$kic!dl-NvdkXZHG99<h4U1-dvc(un&gna"ikm/fn+HtfeVXJA?8>f:W3+bta&{l$ahc geo-`h)JzhgT^LC=70d8Q5)`zo$yj"cjm.egi+bj'DxjaR\NM3:2b>S7'nxm"h mdo,cak)ld%F~lcPR@O1=4c<]9%l~k }f.ofi*ace'nf#@|nm^PBI67a3\:$kh!rg-nah)`ld$oa"C}al]QEH579o1^<"i}f/pe+hcj'nnf"ic Mscn[WGJ;8;m7X> gsd-vc)jmd%lh` km.OqehYUID99=k5Z0.eqb+ta'dof#jjb.eo,IwgjW[KF?>?i;T2,cw`)zo%fi`!hdl,gi*KuidUYM@=;1g9V4*aun'xm#`kb/ffn*ak(E{kfS_OB343e?P6(o{l%~k!bel-d`h(ce&Gym`Q]AL155c=R8&myj#|i/lgn+bbj&mg$Aob_SCN727a3\:$kh!rg-nah)`ld$oa"C}al]QEH5?9o1^<"i}f/pe+hcj'nnf"ic Mscn[WGJ;0;n7X> gsd-vc)jmd%lh` km.OqehYUID>:j6[?/fpe*w`(elg$kic!dl-NvdkXZHG?<<k4U1-dvc(un&gna"ikm/fn+HtfeVXJA8?j;T2,cw`)zo%fi`!hdl,gi*KuidUYM@8>e:W3+bta&{l$ahc geo-`h)JzhgT^LC81d9V4*aun'xm#`kb/ffn*ak(E{kfS_OB80g8Q5)`zo$yj"cjm.egi+bj'DxjaR\NM806?P6(o{l%~k!bel-d`h(ce&U}mgaddz3456;878=7X> gsd-vc)jmd%lh` km.]uewoillr;<=>311<12>S7'nxm"h mdo,cak)ld%Tzl|fneg{456748;5>;5Z0.eqb+ta'dof#jjb.eo,[sguagnnt=>?0=31:70<]9%l~k }f.ofi*ace'nf#Rxnrhlga}67896:?3<9;T2,cw`)zo%fi`!hdl,gi*Yqi{cehhv?012?5185>2_;#j|i.sd,i`k(omg%h`!Pv`pjjac89:;0<;1279V4*aun'xm#`kb/ffn*ak(Wkyecjjx12349716;<0Y=!hrg,qb*kbe&moa#jb/^tbvlhcmq:;<=2>7?05?P6(o{l%~k!bel-d`h(ce&U}mgaddz3456;9149:6[?/fpe*w`(elg$kic!dl-\rdtnfmos<=>?<0;=60=R8&myj#|i/lgn+bbj&mg$S{o}ioff|56785;5>;5Z0.eqb+ta'dof#jjb.eo,[sguagnnt=>?0=03:70<]9%l~k }f.ofi*ace'nf#Rxnrhlga}678969=3<9;T2,cw`)zo%fi`!hdl,gi*Yqi{cehhv?012?6785>2_;#j|i.sd,i`k(omg%h`!Pv`pjjac89:;0?=1279V4*aun'xm#`kb/ffn*ak(Wkyecjjx12349436;<0Y=!hrg,qb*kbe&moa#jb/^tbvlhcmq:;<=2=5?05?P6(o{l%~k!bel-d`h(ce&U}mgaddz3456;:?49:6[?/fpe*w`(elg$kic!dl-\rdtnfmos<=>?<35=63=R8&myj#|i/lgn+bbj&mg$S{o}ioff|56785832?84U1-dvc(un&gna"ikm/fn+Zpfz`doiu>?01>1=;423\:$kh!rg-nah)`ld$oa"Qyaskm``~789:7>3<9;T2,cw`)zo%fi`!hdl,gi*Yqi{cehhv?012?7585>2_;#j|i.sd,i`k(omg%h`!Pv`pjjac89:;0>?1279V4*aun'xm#`kb/ffn*ak(Wkyecjjx12349556;<0Y=!hrg,qb*kbe&moa#jb/^tbvlhcmq:;<=2<3?05?P6(o{l%~k!bel-d`h(ce&U}mgaddz3456;;=49:6[?/fpe*w`(elg$kic!dl-\rdtnfmos<=>?<27=63=R8&myj#|i/lgn+bbj&mg$S{o}ioff|567859=2?84U1-dvc(un&gna"ikm/fn+Zpfz`doiu>?01>03;413\:$kh!rg-nah)`ld$oa"Qyaskm``~789:7?50=6:W3+bta&{l$ahc geo-`h)X~hxbbikw012386?9:<1^<"i}f/pe+hcj'nnf"ic _wcqmkbbp9:;<1=1249V4*aun'xm#`kb/ffn*ak(Wkyecjjx1234929:<1^<"i}f/pe+hcj'nnf"ic _wcqmkbbp9:;<1;1249V4*aun'xm#`kb/ffn*ak(Wkyecjjx1234909:<1^<"i}f/pe+hcj'nnf"ic _wcqmkbbp9:;<191249V4*aun'xm#`kb/ffn*ak(Wkyecjjx12349>9:<1^<"i}f/pe+hcj'nnf"ic _wcqmkbbp9:;<1711d9V4*aun'xm#`kb/ffn*ak(lfSd2?>0d8Q5)`zo$yj"cjm.egi+bj'me~xRg311<2b>S7'nxm"h mdo,cak)ld%ocxzPi=32:4`<]9%l~k }f.ofi*ace'nf#iazt^k?5786n2_;#j|i.sd,i`k(omg%h`!kotv\m97468l0Y=!hrg,qb*kbe&moa#jb/emvpZo;9=4:j6[?/fpe*w`(elg$kic!dl-gkprXa5;>2<h4U1-dvc(un&gna"ikm/fn+air|Vc7=;0>f:W3+bta&{l$ahc geo-`h)cg|~Te1?8>0d8Q5)`zo$yj"cjm.egi+bj'me~xRg319<2b>S7'nxm"h mdo,cak)ld%ocxzPi=3::4c<]9%l~k }f.ofi*ace'nf#iazt^k?5;7a3\:$kh!rg-nah)`ld$oa"j`uu]j87699o1^<"i}f/pe+hcj'nnf"ic dnww[l:597;m7X> gsd-vc)jmd%lh` km.flqqYn4;85=k5Z0.eqb+ta'dof#jjb.eo,`jssW`69?3?i;T2,cw`)zo%fi`!hdl,gi*bh}}Ub0?:11g9V4*aun'xm#`kb/ffn*ak(lfSd2=5?3e?P6(o{l%~k!bel-d`h(ce&ndyyQf<34=5c=R8&myj#|i/lgn+bbj&mg$hb{{_h>13;7a3\:$kh!rg-nah)`ld$oa"j`uu]j87>99o1^<"i}f/pe+hcj'nnf"ic dnww[l:517;n7X> gsd-vc)jmd%lh` km.flqqYn4;4:j6[?/fpe*w`(elg$kic!dl-gkprXa59;2<h4U1-dvc(un&gna"ikm/fn+air|Vc7?<0>f:W3+bta&{l$ahc geo-`h)cg|~Te1==>0d8Q5)`zo$yj"cjm.egi+bj'me~xRg332<2b>S7'nxm"h mdo,cak)ld%ocxzPi=17:4`<]9%l~k }f.ofi*ace'nf#iazt^k?7086n2_;#j|i.sd,i`k(omg%h`!kotv\m95168l0Y=!hrg,qb*kbe&moa#jb/emvpZo;;>4:j6[?/fpe*w`(elg$kic!dl-gkprXa5932<h4U1-dvc(un&gna"ikm/fn+air|Vc7?40>e:W3+bta&{l$ahc geo-`h)cg|~Te1=11d9V4*aun'xm#`kb/ffn*ak(lfSd2;>0g8Q5)`zo$yj"cjm.egi+bj'me~xRg35?3f?P6(o{l%~k!bel-d`h(ce&ndyyQf<7<2a>S7'nxm"h mdo,cak)ld%ocxzPi=5=5`=R8&myj#|i/lgn+bbj&mg$hb{{_h>;:4c<]9%l~k }f.ofi*ace'nf#iazt^k?=;7c3\:$kh!rg-nah)`ld$oa"j`uu]j[57c3\:$kh!rg-nah)`ld$oa"j`uu]j[47b3\:$kh!rg-nah)`ld$oa"j`uu]j[466m2_;#j|i.sd,i`k(omg%h`!kotv\mZ769l1^<"i}f/pe+hcj'nnf"ic dnww[lY6:8o0Y=!hrg,qb*kbe&moa#jb/emvpZoX9:;n7X> gsd-vc)jmd%lh` km.flqqYnW8>:i6[?/fpe*w`(elg$kic!dl-gkprXaV;>=h5Z0.eqb+ta'dof#jjb.eo,`jssW`U::<k4U1-dvc(un&gna"ikm/fn+air|VcT=:?j;T2,cw`)zo%fi`!hdl,gi*bh}}UbS<6>e:W3+bta&{l$ahc geo-`h)cg|~TeR?61e9V4*aun'xm#`kb/ffn*ak(lfSdQ=1d9V4*aun'xm#`kb/ffn*ak(lfSdQ=00g8Q5)`zo$yj"cjm.egi+bj'me~xRgP203f?P6(o{l%~k!bel-d`h(ce&ndyyQf_302a>S7'nxm"h mdo,cak)ld%ocxzPi^005`=R8&myj#|i/lgn+bbj&mg$hb{{_h]104c<]9%l~k }f.ofi*ace'nf#iazt^k\607b3\:$kh!rg-nah)`ld$oa"j`uu]j[706m2_;#j|i.sd,i`k(omg%h`!kotv\mZ409l1^<"i}f/pe+hcj'nnf"ic dnww[lY508o0Y=!hrg,qb*kbe&moa#jb/emvpZoX:0;o7X> gsd-vc)jmd%lh` km.flqqYnW:;n7X> gsd-vc)jmd%lh` km.flqqYnW:::i6[?/fpe*w`(elg$kic!dl-gkprXaV9:=h5Z0.eqb+ta'dof#jjb.eo,`jssW`U8><k4U1-dvc(un&gna"ikm/fn+air|VcT?>?j;T2,cw`)zo%fi`!hdl,gi*bh}}UbS>:>e:W3+bta&{l$ahc geo-`h)cg|~TeR=:1d9V4*aun'xm#`kb/ffn*ak(lfSdQ<60g8Q5)`zo$yj"cjm.egi+bj'me~xRgP363f?P6(o{l%~k!bel-d`h(ce&ndyyQf_2:2a>S7'nxm"h mdo,cak)ld%ocxzPi^1:5a=R8&myj#|i/lgn+bbj&mg$hb{{_h]75a=R8&myj#|i/lgn+bbj&mg$hb{{_h]65a=R8&myj#|i/lgn+bbj&mg$hb{{_h]55a=R8&myj#|i/lgn+bbj&mg$hb{{_h]45a=R8&myj#|i/lgn+bbj&mg$hb{{_h];5a=R8&myj#|i/lgn+bbj&mg$hb{{_h]:52=R8&myj#|i/scn[wc`g|~Tic?k;T2,cw`)zo%yylck.pg[wusWhyyij<?;T2,cw`)zo%yylck.pg[wusWhyyijQk1328Q5)`zo$yj"||tcnh+wbXzz~Tm~|jg^f15f=R8&myj#|i/sqwfim(zmUyyQlol`2`>S7'nxm"h rrvahn)ulVxxxRm`mc32a>S7'nxm"h rrvahn)ulVxxxR|jg=2=5`=R8&myj#|i/sqwfim(zmUyyQ}ef>2:4c<]9%l~k }f.pppgjl'{nT~~zPrde?6;7c3\:$kh!rg-qwqdkc&xoS}{_sgd[57c3\:$kh!rg-qwqdkc&xoS}{_sgd[47c3\:$kh!rg-qwqdkc&xoS}{_sgd[77c3\:$kh!rg-qwqdkc&}yS}{_`qqab473\:$kh!rg-qwqdkc&}yS}{_`qqabYc9;:0Y=!hrg,qb*tt|kf`#z|Prrv\evtboVn9=n5Z0.eqb+ta'{ynae ws]qwqYdgdh:h6[?/fpe*w`(zz~i`f!xr^pppZehek;:i6[?/fpe*w`(zz~i`f!xr^pppZtbo5:5=h5Z0.eqb+ta'{ynae ws]qwqYumn6:2<j4U1-dvc(un&xxxobd/vp\vvrXzlmT<<j4U1-dvc(un&xxxobd/vp\vvrXzlmT=l5ZSDP\EIOF[j1^_H\PVHQJFIC43_IH56XFEV]W]UC33^IGG?5XE0f8\LJNFQ'SHO.?.0"PPPD'8';+M^MFI79[WQJNJ>1S_YQHNE`8\ZEHZLUBBKA9;Yfa[Lba3QncS]|fmWgqwlii991Sh`QBakmqR`ttafd:<6Vkm^OjjjtQm{ybccm4amolwqYbey~rn6ocmnqw[cskd?1imnezpe9aefmrxVgj~fk}3:aooa=ci}kTob{at)2*`>bf|hUhcx`{(0+g?agsiVidycz'2(f8`drfWje~by&<)g9geqgXkfex1=50?58`gosm{x=7iga(1+5?aoi 8#<7iga(02*3>bnf!;:%:5kio*26,1<l`d#=>'8;ekm,42.?2nbb%?:)69gmk.6> =0hd`'16+4?aoi 82";6jfn)3:-3=cag"9%:5kio*14,1<l`d#><'8;ekm,74.?2nbb%<<)69gmk.5< =0hd`'24+4?aoi ;<";6jfn)04-2=cag"94$94dhl+6</13mce$>'8;ekm,66.?2nbb%=>)69gmk.4: =0hd`'32+4?aoi :>";6jfn)16-2=cag"8:$94dhl+72/03mce$>6&7:fjj-5>!?1oec&;)79gmk.2!?1oec&9)79gmk.0!?1oec&7)79gmk.>!?1oec2?>69gmk:687=0hd`310<4?aoi4885;6jfn=30:2=cag6:8394dhl?50803mce0<817:fjj9706>1oec2>8?58`lh;904=7iga<0<4?aoi4;:5;6jfn=02:2=cag69>394dhl?66803mce0?:17:fjj9426>1oec2=6?58`lh;:>4<7iga<3:=3>bnf5822;5kio>1:2=cag68<394dhl?74803mce0><17:fjj9546>1oec2<4?58`lh;;<4<7iga<24=3>bnf59<2:5kio>0<;?<l`d7?44?>69gmk:417<0hd`33?48`lh;<7<0hd`35?48`lh;>7<0hd`37?48`lh;07<0hd`39?58`jss 9#<7iazt)3*<>bh}}":<$64dnww,47.02ndyy&>2(:8`jss 89"46j`uu*20,><lf$<;&8:flqq.6> 20hb{{(05*<>bh}}":4$64dnww,4?.?2ndyy&=)99gkpr/:9#37iazt)02-==cg|~#>?'7;emvp-44!11ocxz'25+;?air|!8>%55kotv+63/?3me~x%<8)99gkpr/:1#37iazt)0:-2=cg|~#?$64dnww,66.02ndyy&<1(:8`jss :8"46j`uu*07,><lf$>:&8:flqq.4= 20hb{{(24*<>bh}}"8;$64dnww,6>.02ndyy&<9(58`jss =#<7iazt)7*3>bh}}"=%:5kotv+3,1<lf$5'8;emvp-?.?2ndyy2?>99gkpr;99437iazt=32:==cg|~7=?07;emvp974611ocxz315<;?air|5;>255kotv?538?3me~x1?8>99gkpr;91437iazt=3::2=cg|~7=364dnww876902ndyy2=1?:8`jss4;8546j`uu>17;><lf0?:18:flqq:5=720hb{{<34=<>bh}}69;364dnww87>902ndyy2=9?58`jss4;437iazt=13:==cg|~7?<07;emvp955611ocxz332<;?air|59?255kotv?708?3me~x1=9>99gkpr;;>437iazt=1;:d=cg|~7?44?>99gkpr;;04<7iazt=1=3>bh}}6?2:5kotv?1;1<lf0;08;emvp919?2ndyy27>69gkpr;1720iigi2oeg1>cjx}s8>6hffn]dakcui}eyS{:P3-"[mioip)ID^H.Heogqeqiu(8:%=#><159emciXpedsS<8w41]1gim4:2lbjbQwloz\53~38V8h`f"iigm\c`hbzh~d~Rx;_2.MKKC+FFDN?oj4fhdl[}jipV;=t9>P2bnh(coagVmnbh|ntnp\r1Y4$riTdl}Piov\gim:8%iTdl}Pssqw95*dW{nTjk~=0.`[mgtW{nThlzn_bmvjq;7$jUoecQxievk916+kVbjRy}_ecweZeh}g~6<!mPftno[cjfozUyyQyam?2(fYneyfnah`{aukljZr~xl79 nQzsd]figccllnT~hi20-a\swYazl{6=!mPurg\`jssW{y1<"l_tlgaw`kg~Ugcz3?,b]kevYh~lxm`by20-a\twckghnT`lzjnb{>4)eXlfSzgkti?74)eXezmdbRxnl<3/gZtcWmo{xe3>6-a\lduX}gnn~kb`w<2/gZnf{Vkgab}{_gwoh86+kVbjR||t<3/gZbf|hUhcx`{_vkgpm;3$jUcm~Qxr^c`o86+kVxiRklc<2/gZehedeeSnb`cj?3(fYpzVkhgRb`w<2/gZtcWyd~Ryfduj>0)eX}zoTjzh{_ecweZeh}g~6<!mPh`q\eikh{}Una}zv=1.`[wbXlh~jSnaznu]tmaro5=&hSbxjrgnlsZjh4:'oRy}_qlwvZqnl}b68!mPpsmd[`kw|pUu}k20-a\swYci}kTob{at^uj`qn:<%iT|kco`f\v`at58&hSiazt^pppZpfd4:'oRfns^fbpdYdg|d1="l_qplcZ`rdeUdk|h^lfcdrbWkg1<:#c^uq[acw|a7::!mPpsmd[`kw|pUdk|h^lfcdrbWkg18"l_qplcZcjx}sTxe|jsi]bwvcu|V|j`0:#c^jbwZpfd`n6<!mPpsmd[cskdV~c~h}g_`qpawrX~hf6=8"lolrlj`hsWgkfi0hffn]{hk~X9?r?<R<llj.`[sgkamUgcz3?,b]svlkXn`ldSywe<726}15$jU{~biPftno[qwm4:'oRcjmnpz[qwm48'q?k4fhdl[}jipV;=t9>P2bnh[coagVmnbh|ntnp\r1Y4WqyS<:4ftno3>oi|Vigg55agb`vmib?3f|n~kb`w`9svjaXmdzu<:4psmd[`kw|pUdk|h)2*51=wzfmTi`~{y^vkv`uo 8#:86~}of]fiur~W}byi~f'2(37?uthoVof|ywPtipfwm.4!8<0|ah_dosp|Ys`{oxd1=50?3a?uthoVof|ywPtipfwmYf{zoyx%>&1c9svjaXmdzuRzgrdqk[dutm{~#=$?m;qplcZcjx}sTxe|jsi]bwvcu|!8"=o5rne\ahvsqV~c~h}g_`qpawr/; ;o7}|`g^gntqX|axneQnsrgqp95=87;i7}|`g^gntqX|axneQaefcwa-6.9k1{~biPelrw}ZrozlycSckhaug+5,7e3yxdkRkbpu{\pmtb{aUeijo{e)0*5g=wzfmTi`~{y^vkv`uoWgolmyk'3(3g?uthoVof|ywPtipfwmYimnki1=50?;8twi`Wog`<=4psmd[cskdV~c~h}g(1+27>vugnUmyabPtipfwm.6!890|ah_gwohZrozlyc$?'>3:rqkbYa}efTxe|jsi*0-43<x{elSk{cl^vkv`uo4:0;2<o4psmd[cskdV~c~h}g_`qpawr/8 ;j7}|`g^dvhiYs`{oxdRo|sdpw,4/6i2zycjQiumn\pmtb{aUj~k}t)0*5d=wzfmTjxbc_ujqavnXizyn~y&<)0a8twi`Wog`Rzgrdqk[dutm{~7?7>11`9svjaXn|fgSyf}erj\j`af|l";%<o4psmd[cskdV~c~h}g_ogdeqc/9 ;j7}|`g^dvhiYs`{oxdR`jg`vf,7/6i2zycjQiumn\pmtb{aUeijo{e)1*5f=wzfmTjxbc_ujqavnXflmjxh2<:1<5?wbXkea:<6|k_ecweZeh}g~#<$??;sf\`drfWje~by&>)028vaYci}kTob{at)0*55=ulVnjxlQlotlw,6/682xoSio{a^alqkr;87;97jPd`vb[firf}686=0:;sf\ak0<zmUyy=4rrv4?vdn|lxy86}}su68pwsb12ehh|ilnu6?sgkam<0{Qncj48swYddb;;7z|Pd`vb[firf}";%<>4ws]geqgXkfex%?&119tvZbf|hUhcx`{(3+24>quWmkmRm`uov+7,753~xThlzn_bmvjq:4294>7z|Peo48swYu{}wKL}7l3:BC|4<A2=0:w^=?:223>0<6;;h>5k4<16dek4293;0b?;=:59'61`=:=h0q^<j:223>0<6;;h>5k4<16de?V2>2::26=4>33`6=c<491::7^<j:22:>5<6;;h>5k4<1922?a57;3:1=7?tS229756==3;8>o;6f;123c`<~]h?6=4>:08250}T;908<=4::011f0?a2:;<jk5+25:90d=Q:<:1>v{:0;38q07=82w/mh46;c137?6==>08689tH365?_4?2;qh6o4r$c49755<,;>n6>>=;h106?6=3`9?=7>5;n133?6=3f9;=7>5;h10f?6=3`9887>5;n0g4?6=,k:1>k94n`d94>=h:jl1<7*m0;0e3>hfn3;07b<le;29 g6=:o=0blh52:9l6fb=83.i<7<i7:lbb?5<3f8ho7>5$c296c1<fhl1865`2b`94?"e838m;6`nf;78?j4di3:1(o>52g58jd`=>21d>n750;&a4?4a?2djj794;n0`<?6=,k:1>k94n`d9<>=h:j=1<7*m0;0e3>hfn3307b<l5;29 g6=:o=0blh5a:9l6f2=83.i<7<i7:lbb?d<3f8h?7>5$c296c1<fhl1o65`2b094?"e838m;6`nf;f8?j4d93:1(o>52g58jd`=m21d>n>50;&a4?4a?2djj7h4;n0ab?6=,k:1>k94n`d955=<g;hn6=4+b181b2=iio0:=65`2cf94?"e838m;6`nf;31?>i5jj0;6)l?:3d4?kga28907b<ma;29 g6=:o=0blh51598k7d>290/n=4=f69mec<6=21d>o650;&a4?4a?2djj7?9;:m1f2<72-h;6?h8;oce>41<3f8i:7>5$c296c1<fhl1=554o3`6>5<#j909j:5aag82=>=h:k>1<7*m0;0e3>hfn3;j76a=b283>!d72;l<7coi:0`8?j4e:3:1(o>52g58jd`=9j10c?l>:18'f5<5n>1emk4>d:9l6a0=83.i<7<i7:lbb?7b32e9h84?:%`3>7`03gkm6<h4;n0g0?6=,k:1>k94n`d965=<g;n86=4+b181b2=iio09=65`2e094?"e838m;6`nf;01?>i5l80;6)l?:3d4?kga2;907b<l6;29 g6=:o=0blh52598k7de290/n=4=f69mec<5=21d>o>50;&a4?4a?2djj7<9;:m1ec<72-h;6?h8;oce>71<3`8<j7>5$c296d0<fhl1<65f26g94?"e838j:6`nf;38?l40l3:1(o>52`48jd`=:21b>:m50;&a4?4f>2djj7=4;h04f?6=,k:1>l84n`d90>=n:>k1<7*m0;0b2>hfn3?07d<89;29 g6=:h<0blh56:9j62>=83.i<7<n6:lbb?1<3`8<;7>5$c296d0<fhl1465f26494?"e838j:6`nf;;8?l40<3:1(o>52`48jd`=i21b>:=50;&a4?4f>2djj7l4;h046?6=,k:1>l84n`d9g>=n:>;1<7*m0;0b2>hfn3n07d<80;29 g6=:h<0blh5e:9j63`=83.i<7<n6:lbb?`<3`8=i7>5$c296d0<fhl1==54i34g>5<#j909m;5aag825>=n:?i1<7*m0;0b2>hfn3;976g=6c83>!d72;k=7coi:018?l4113:1(o>52`48jd`=9=10e?87:18'f5<5i?1emk4>5:9j631=83.i<7<n6:lbb?7132c9:;4?:%`3>7g13gkm6<94;h051?6=,k:1>l84n`d95==<a;<?6=4+b181e3=iio0:565f27194?"e838j:6`nf;3b?>o5>;0;6)l?:3c5?kga28h07d<91;29 g6=:h<0blh51b98m707290/n=4=a79mec<6l21b>5;50;&a4?4f>2djj7?j;:k1<1<72-h;6?o9;oce>4`<3`83?7>5$c296d0<fhl1>=54i3:1>5<#j909m;5aag815>=n:1;1<7*m0;0b2>hfn38976g=8183>!d72;k=7coi:318?l40=3:1(o>52`48jd`=:=10e?8n:18'f5<5i?1emk4=5:9j60`=83.i<7<n6:lbb?4132c99h4?:%`3>7g13gkm6?94;h11f?6=3k8?;7>51;294~N5<?1/n;4=469lea<722wi?k4?:083>5}O:=<0(o853g9l7`<722wi>:4?:9a9a=<69<qC>984Z3:953}b28?1=94>2;30>46=k3n1n7?>:g827?722j0:87k5b;31>47=990m6i4r$c49750<,==1?i5+2b8041=#:o08<85+a88bg>o4;:0;66a<1c83>>o4;?0;66a=5283>>i4;00;66g=5783>>o49=0;6)l?:236?kga2910e>?<:18'f5<49<1emk4>;:k057<72-h;6>?:;oce>7=<a:;:6=4+b18050=iio0876g<3383>>i48h0;66a<3g83>!d72:>;7coi:198k65b290/n=4<419mec<632e8?i4?:%`3>6273gkm6?54o21`>5<#j9088=5aag80?>i4:o0;6)l?:212?kga2910c><j:18'f5<4;81emk4>;:m06a<72-h;6>=>;oce>7=<g:8h6=4+b18074=iio0876g<2883>!d72:8j7coi:198m64?290/n=4<2`9mec<632c8>:4?:%`3>64f3gkm6?54i205>5<#j908>l5aag80?>o4<80;66a=5c83>!d72;?h7coi:198k73f290/n=4=5b9mec<632e9944?:%`3>73d3gkm6?54o37;>5<#j9099n5aag80?>i48>0;66a<0083>>o49o0;6)l?:203?kga2910e>?j:18'f5<4:91emk4>;:k05a<72-h;6><?;oce>7=<a:;h6=4+b18065=iio0876g<3c83>>o4810;66g=5683>>o4<;0;66a<3483>>i4;h0;66a=5583>>i4;10;66g<3583>>i5l90;6)l?:3d4?kga2910c?mi:18'f5<5n>1emk4>;:m1g`<72-h;6?h8;oce>7=<g;io6=4+b181b2=iio0876a=cb83>!d72;l<7coi:598k7ee290/n=4=f69mec<232e9ol4?:%`3>7`03gkm6;54o3a:>5<#j909j:5aag84?>i5k10;6)l?:3d4?kga2110c?m8:18'f5<5n>1emk46;:m1g0<72-h;6?h8;oce>d=<g;i?6=4+b181b2=iio0i76a=c283>!d72;l<7coi:b98k7e5290/n=4=f69mec<c32e9o<4?:%`3>7`03gkm6h54o3a3>5<#j909j:5aag8e?>i5jo0;6)l?:3d4?kga28:07b<me;29 g6=:o=0blh51098k7dc290/n=4=f69mec<6:21d>om50;&a4?4a?2djj7?<;:m1fd<72-h;6?h8;oce>42<3f8i57>5$c296c1<fhl1=854o3`;>5<#j909j:5aag822>=h:k=1<7*m0;0e3>hfn3;<76a=b783>!d72;l<7coi:0:8?j4e=3:1(o>52g58jd`=9010c?l;:18'f5<5n>1emk4>a:9l6g5=83.i<7<i7:lbb?7e32e9n?4?:%`3>7`03gkm6<m4;n0a5?6=,k:1>k94n`d95a=<g;n=6=4+b181b2=iio0:i65`2e794?"e838m;6`nf;3e?>i5l=0;6)l?:3d4?kga2;:07b<k3;29 g6=:o=0blh52098k7b5290/n=4=f69mec<5:21d>i?50;&a4?4a?2djj7<<;:m1g3<72-h;6?h8;oce>72<3f8in7>5$c296c1<fhl1>854o3`3>5<#j909j:5aag812>=h:hl1<7*m0;0e3>hfn38<76g<0g83>!d72:;;7coi:198m66b290/n=4<119mec<632c8<i4?:%`3>6773gkm6?54i22`>5<#j908==5aag80?>o5?o0;6)l?:3c5?kga2910e?9j:18'f5<5i?1emk4>;:k13a<72-h;6?o9;oce>7=<a;=h6=4+b181e3=iio0876g=7c83>!d72;k=7coi:598m71f290/n=4=a79mec<232c9;44?:%`3>7g13gkm6;54i35;>5<#j909m;5aag84?>o5?>0;6)l?:3c5?kga2110e?99:18'f5<5i?1emk46;:k131<72-h;6?o9;oce>d=<a;=86=4+b181e3=iio0i76g=7383>!d72;k=7coi:b98m716290/n=4=a79mec<c32c9;=4?:%`3>7g13gkm6h54i34e>5<#j909m;5aag8e?>o5>l0;6)l?:3c5?kga28:07d<9d;29 g6=:h<0blh51098m70d290/n=4=a79mec<6:21b>;l50;&a4?4f>2djj7?<;:k12<<72-h;6?o9;oce>42<3`8=47>5$c296d0<fhl1=854i344>5<#j909m;5aag822>=n:?<1<7*m0;0b2>hfn3;<76g=6483>!d72;k=7coi:0:8?l41<3:1(o>52`48jd`=9010e?8<:18'f5<5i?1emk4>a:9j634=83.i<7<n6:lbb?7e32c9:<4?:%`3>7g13gkm6<m4;h054?6=,k:1>l84n`d95a=<a;2>6=4+b181e3=iio0:i65f29694?"e838j:6`nf;3e?>o50:0;6)l?:3c5?kga2;:07d<72;29 g6=:h<0blh52098m7>6290/n=4=a79mec<5:21b>5>50;&a4?4f>2djj7<<;:k130<72-h;6?o9;oce>72<3`8=m7>5$c296d0<fhl1>854i37e>5<#j909m;5aag812>=n:<o1<7*m0;0b2>hfn38<76g=5483>>o4:=0;6)l?:206?kga2910e><<:18'f5<4:<1emk4>;:k067<72-h;6><:;oce>7=<a:8:6=4+b18060=iio0876g<1883>!d72:;j7coi:198m67?290/n=4<1`9mec<632c8=:4?:%`3>67f3gkm6?54i235>5<#j908=l5aag80?>i48k0;66a=5e83>>o4:k0;66l=4e83>4<729q/n;4<f:J10f=O:=<0c>k50;9~f75429086=4?{%`5>6><@;>h7E<;6:J12>"3n398;6*;5;08m7?=831b?<4?::ma6?6=3th9?h4?:283>5}#j?0846F=4b9K610<@;<0(9h53258 13=:2c957>5;h12>5<<gk81<75rb311>5<4290;w)l9:2:8L72d3A8?:6F=6:&7b?54?2.?97<4i3;94?=n;80;66am2;29?xd5;j0;684?:1y'f3<4k2B98n5G2548L70<,=l1?>94$5796>o513:17d<m:188m67=831bn<4?::ma6?6=3th9?i4?:283>5}#j?0846F=4b9K610<@;<0(9h53258 13=:2c957>5;h12>5<<gk81<75rb312>5<2290;w)l9:2a8L72d3A8?:6F=6:&7b?54?2.?97<4i3;94?=n:k0;66g<1;29?ld62900co<50;9~f75e290?6=4?{%`5>6d<@;>h7E<;6:&71?4<a;31<75f3083>>oe93:17bl=:188yg44i3:187>50z&a2?5e3A8?o6F=479'00<53`826=44i2394?=nj80;66am2;29?xd5;00;694?:1y'f3<4j2B98n5G2548 13=:2c957>5;h12>5<<ak;1<75`b383>>{e:=>1<7:50;2x g0=;k1C>9m4H365?!222;1b>44?::k05?6=3`h:6=44oc094?=zj;>86=4;:183!d12:h0D?:l;I072>"3=380e?750;9j74<722ci=7>5;n`1>5<<uk;:o7>54;294~"e>39i7E<;c:J103=#<<0?7d<6:188m67=831bn<4?::ma6?6=3th:?54?:483>5}#j?08m6F=4b9K610<,=?1>6g=9;29?l4e2900e?j50;9j74<722ei>7>5;|`27<<72<0;6=u+b780e>N5<j1C>984$5796>o513:17d<m:188m7b=831b?<4?::ma6?6=3th:?l4?:483>5}#j?08m6F=4b9K610<,=?1>6g=9;29?l4e2900e?j50;9j74<722ei>7>5;|`27g<72<0;6=u+b780e>N5<j1C>984$5796>o513:17d<m:188m7b=831b?<4?::ma6?6=3th:?h4?:583>5}#j?08n6F=4b9K610<,=?1>6g=9;29?l562900eo?50;9lf7<722wi=>j50;694?6|,k<1?o5G25a8L7213->>6?5f2883>>o493:17dl>:188kg4=831vn<8<:186>5<7s-h=6>o4H36`?M43>2.?97<4i3;94?=n:k0;66g=d;29?l562900co<50;9~f403290>6=4?{%`5>6g<@;>h7E<;6:&71?4<a;31<75f2c83>>o5l3:17d=>:188kg4=831vn<8::186>5<7s-h=6>o4H36`?M43>2.?97<4i3;94?=n:k0;66g=d;29?l562900co<50;9~f401290>6=4?{%`5>6g<@;>h7E<;6:&71?4<a;31<75f2c83>>o5l3:17d=>:188kg4=831vn<;j:186>5<7s-h=6>o4H36`?M43>2.?97<4i3;94?=n:k0;66g=d;29?l562900co<50;9~f43c290>6=4?{%`5>6g<@;>h7E<;6:&71?4<a;31<75f2c83>>o5l3:17d=>:188kg4=831vn<;l:186>5<7s-h=6>o4H36`?M43>2.?97<4i3;94?=n:k0;66g=d;29?l562900co<50;9~f43e290>6=4?{%`5>6e<@;>h7E<;6:&71?2<a;31<75f2c83>>o493:17dl>:188kg4=831vn<;::186>5<7s-h=6>o4H36`?M43>2.?97<4i3;94?=n:k0;66g=d;29?l562900co<50;9~f434290>6=4?{%`5>6g<@;>h7E<;6:&71?4<a;31<75f2c83>>o5l3:17d=>:188kg4=831vn<;;:186>5<7s-h=6>m4H36`?M43>2.?97:4i3;94?=n:k0;66g<1;29?ld62900co<50;9~f431290>6=4?{%`5>6g<@;>h7E<;6:&71?4<a;31<75f2c83>>o5l3:17d=>:188kg4=831vn<=>:186>5<7s-h=6>o4H36`?M43>2.?97<4i3;94?=n:k0;66g=d;29?l562900co<50;9~f457290>6=4?{%`5>6e<@;>h7E<;6:&71?2<a;31<75f2c83>>o493:17dl>:188kg4=831vn<==:186>5<7s-h=6>o4H36`?M43>2.?97<4i3;94?=n:k0;66g=d;29?l562900co<50;9~f454290>6=4?{%`5>6g<@;>h7E<;6:&71?4<a;31<75f2c83>>o5l3:17d=>:188kg4=831vnno50;694?6|,k<1?45G25a8L7213->>6?5f2883>>o5l3:17d=>:188kg4=831vnn750;694?6|,k<1?45G25a8L7213->>6?5f2883>>o5l3:17d=>:188kg4=831vnn650;694?6|,k<1?45G25a8L7213->>6?5f2883>>o5l3:17d=>:188kg4=831vnn950;694?6|,k<1?45G25a8L7213->>6?5f2883>>o5l3:17d=>:188kg4=831vnk>50;694?6|,k<1?45G25a8L7213->>6?5f2883>>o5l3:17d=>:188kg4=831vnhh50;694?6|,k<1?45G25a8L7213->>6?5f2883>>o5l3:17d=>:188kg4=831vnhk50;694?6|,k<1?45G25a8L7213->>6?5f2883>>o5l3:17d=>:188kg4=831vnhj50;694?6|,k<1?45G25a8L7213->>6?5f2883>>o5l3:17d=>:188kg4=831vn<>m:187>5<7s-h=6>74H36`?M43>2.?97<4i3;94?=n:m0;66g<1;29?jd52900qo??a;290?6=8r.i:7=6;I07g>N5<?1/884=;h0:>5<<a;n1<75f3083>>ie:3:17pl>0883>1<729q/n;4<9:J10f=O:=<0(9;52:k1=?6=3`8o6=44i2394?=hj;0;66sm11:94?2=83:p(o85389K61e<@;>=7):::39j6<<722c9h7>5;h12>5<<gk81<75rbd794?2=83:p(o85389K61e<@;>=7):::39j6<<722c9h7>5;h12>5<<gk81<75rbd694?2=83:p(o85389K61e<@;>=7):::39j6<<722c9h7>5;h12>5<<gk81<75rbd194?2=83:p(o85389K61e<@;>=7):::39j6<<722c9h7>5;h12>5<<gk81<75rbd094?2=83:p(o85389K61e<@;>=7):::39j6<<722c9h7>5;h12>5<<gk81<75rb020>5<3290;w)l9:2;8L72d3A8?:6F=6:&7b?54?2.?97<4i3;94?=n:m0;66g<1;29?jd52900qo??2;290?6=8r.i:7=6;I07g>N5<?1C>;5+4g8072=#<<097d<6:188m7b=831b?<4?::ma6?6=3th:<<4?:583>5}#j?0856F=4b9K610<@;<0(9h53258 13=:2c957>5;h0g>5<<a:;1<75`b383>>{e99:1<7:50;2x g0=;01C>9m4H365?M413->m6>=8;%66>7=n:00;66g=d;29?l562900co<50;9~fab=83>1<7>t$c497<=O:=i0D?:9;I05?!2a2:9<7):::39j6<<722c9h7>5;h12>5<<gk81<75rbea94?2=83:p(o85389K61e<@;>=7E<9;%6e>6503->>6?5f2883>>o5l3:17d=>:188kg4=831vnil50;694?6|,k<1?45G25a8L7213A8=7):i:214?!222;1b>44?::k1`?6=3`9:6=44oc094?=zjmk1<7:50;2x g0=;01C>9m4H365?M413->m6>=8;%66>7=n:00;66g=d;29?l562900co<50;9~fa3=83>1<7>t$c497<=O:=i0D?:9;%66>7=n:00;66g=d;29?l562900co<50;9~fa2=83>1<7>t$c497<=O:=i0D?:9;%66>7=n:00;66g=d;29?l562900co<50;9~fa5=83>1<7>t$c497<=O:=i0D?:9;%66>7=n:00;66g=d;29?l562900co<50;9~fa4=83>1<7>t$c497<=O:=i0D?:9;%66>7=n:00;66g=d;29?l562900co<50;9~fcd=83>1<7>t$c497<=O:=i0D?:9;%66>7=n:00;66g=d;29?l562900co<50;9~fcg=83>1<7>t$c497<=O:=i0D?:9;%66>7=n:00;66g=d;29?l562900co<50;9~fc?=83>1<7>t$c497<=O:=i0D?:9;%66>7=n:00;66g=d;29?l562900co<50;9~fc>=83>1<7>t$c497<=O:=i0D?:9;%66>7=n:00;66g=d;29?l562900co<50;9~f472290?6=4?{%`5>6?<@;>h7E<;6:&71?4<a;31<75f2e83>>o493:17bl=:188yg76:3:187>50z&a2?5>3A8?o6F=479'00<53`826=44i3f94?=n;80;66am2;29?xd6900;694?:1y'f3<4j2B98n5G2548 13=<2c957>5;h12>5<<ak;1<75`b383>>{e9821<7:50;2x g0=;k1C>9m4H365?!222=1b>44?::k05?6=3`h:6=44oc094?=zj;:36=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb32:>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;;?6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb33e>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;8j6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb30a>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;8h6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb30g>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;8n6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb30e>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;:j6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb32a>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;:h6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb32g>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;:n6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb32e>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;;;6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb332>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;;96=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb330>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;;>6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb335>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;;<6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb33;>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;;26=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb33b>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;;i6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb33`>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;;o6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb33f>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;8;6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb302>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;896=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb300>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;8?6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb306>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;8=6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb304>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;836=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb30:>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8k=6=4k:183!d12k90D?:l;I072>o5:3:17d<<:188m72=831b>84?::k05?6=3`986=44i2694?=n;<0;66g<6;29?l4313:17d<;a;29?jd22900c><50;9~f4?7290o6=4?{%`5>g5<@;>h7E<;6:k16?6=3`886=44i3694?=n:<0;66g<1;29?l542900e>:50;9j70<722c8:7>5;h07=?6=3`8?m7>5;n`6>5<<g:81<75rb0;a>5<c290;w)l9:c18L72d3A8?:6g=2;29?l442900e?:50;9j60<722c8=7>5;h10>5<<a:>1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn<l>:18g>5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<<a;>1<75f2483>>o493:17d=<:188m62=831b?84?::k02?6=3`8?57>5;h07e?6=3fh>6=44o2094?=zj8h86=4k:183!d12k90D?:l;I072>o5:3:17d<<:188m72=831b>84?::k05?6=3`986=44i2694?=n;<0;66g<6;29?l4313:17d<;a;29?jd22900c><50;9~f4d1290o6=4?{%`5>g5<@;>h7E<;6:k16?6=3`886=44i3694?=n:<0;66g<1;29?l542900e>:50;9j70<722c8:7>5;h07=?6=3`8?m7>5;n`6>5<<g:81<75rb0`7>5<c290;w)l9:c18L72d3A8?:6g=2;29?l442900e?:50;9j60<722c8=7>5;h10>5<<a:>1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn<l::18g>5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<<a;>1<75f2483>>o493:17d=<:188m62=831b?84?::k02?6=3`8?57>5;h07e?6=3fh>6=44o2094?=zj8h<6=4k:183!d12k90D?:l;I072>o5:3:17d<<:188m72=831b>84?::k05?6=3`986=44i2694?=n;<0;66g<6;29?l4313:17d<;a;29?jd22900c><50;9~f4?6290o6=4?{%`5>g5<@;>h7E<;6:k16?6=3`886=44i3694?=n:<0;66g<1;29?l542900e>:50;9j70<722c8:7>5;h07=?6=3`8?m7>5;n`6>5<<g:81<75rb0;7>5<c290;w)l9:c18L72d3A8?:6g=2;29?l442900e?:50;9j60<722c8=7>5;h10>5<<a:>1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn<7=:18g>5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<<a;>1<75f2483>>o493:17d=<:188m62=831b?84?::k02?6=3`8?57>5;h07e?6=3fh>6=44o2094?=zj8386=4k:183!d12k90D?:l;I072>o5:3:17d<<:188m72=831b>84?::k05?6=3`986=44i2694?=n;<0;66g<6;29?l4313:17d<;a;29?jd22900c><50;9~f4?2290o6=4?{%`5>g5<@;>h7E<;6:k16?6=3`886=44i3694?=n:<0;66g<1;29?l542900e>:50;9j70<722c8:7>5;h07=?6=3`8?m7>5;n`6>5<<g:81<75rb0;5>5<c290;w)l9:c18L72d3A8?:6g=2;29?l442900e?:50;9j60<722c8=7>5;h10>5<<a:>1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn<76:18g>5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<<a;>1<75f2483>>o493:17d=<:188m62=831b?84?::k02?6=3`8?57>5;h07e?6=3fh>6=44o2094?=zj83<6=4k:183!d12k90D?:l;I072>o5:3:17d<<:188m72=831b>84?::k05?6=3`986=44i2694?=n;<0;66g<6;29?l4313:17d<;a;29?jd22900c><50;9~f4??290o6=4?{%`5>g5<@;>h7E<;6:k16?6=3`886=44i3694?=n:<0;66g<1;29?l542900e>:50;9j70<722c8:7>5;h07=?6=3`8?m7>5;n`6>5<<g:81<75rb0;b>5<c290;w)l9:c18L72d3A8?:6g=2;29?l442900e?:50;9j60<722c8=7>5;h10>5<<a:>1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn<7l:18g>5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<<a;>1<75f2483>>o493:17d=<:188m62=831b?84?::k02?6=3`8?57>5;h07e?6=3fh>6=44o2094?=zj83m6=4k:183!d12k90D?:l;I072>o5:3:17d<<:188m72=831b>84?::k05?6=3`986=44i2694?=n;<0;66g<6;29?l4313:17d<;a;29?jd22900c><50;9~f4?c290o6=4?{%`5>g5<@;>h7E<;6:k16?6=3`886=44i3694?=n:<0;66g<1;29?l542900e>:50;9j70<722c8:7>5;h07=?6=3`8?m7>5;n`6>5<<g:81<75rb0;f>5<c290;w)l9:c18L72d3A8?:6g=2;29?l442900e?:50;9j60<722c8=7>5;h10>5<<a:>1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn<o?:18g>5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<<a;>1<75f2483>>o493:17d=<:188m62=831b?84?::k02?6=3`8?57>5;h07e?6=3fh>6=44o2094?=zj8k:6=4k:183!d12k90D?:l;I072>o5:3:17d<<:188m72=831b>84?::k05?6=3`986=44i2694?=n;<0;66g<6;29?l4313:17d<;a;29?jd22900c><50;9~f4g3290o6=4?{%`5>g5<@;>h7E<;6:k16?6=3`886=44i3694?=n:<0;66g<1;29?l542900e>:50;9j70<722c8:7>5;h07=?6=3`8?m7>5;n`6>5<<g:81<75rb0c1>5<c290;w)l9:c18L72d3A8?:6g=2;29?l442900e?:50;9j60<722c8=7>5;h10>5<<a:>1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn<o<:18g>5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<<a;>1<75f2483>>o493:17d=<:188m62=831b?84?::k02?6=3`8?57>5;h07e?6=3fh>6=44o2094?=zj8k>6=4k:183!d12k90D?:l;I072>o5:3:17d<<:188m72=831b>84?::k05?6=3`986=44i2694?=n;<0;66g<6;29?l4313:17d<;a;29?jd22900c><50;9~f4g0290o6=4?{%`5>g5<@;>h7E<;6:k16?6=3`886=44i3694?=n:<0;66g<1;29?l542900e>:50;9j70<722c8:7>5;h07=?6=3`8?m7>5;n`6>5<<g:81<75rb0cb>5<c290;w)l9:c18L72d3A8?:6g=2;29?l442900e?:50;9j60<722c8=7>5;h10>5<<a:>1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn<o7:18g>5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<<a;>1<75f2483>>o493:17d=<:188m62=831b?84?::k02?6=3`8?57>5;h07e?6=3fh>6=44o2094?=zj8k26=4k:183!d12k90D?:l;I072>o5:3:17d<<:188m72=831b>84?::k05?6=3`986=44i2694?=n;<0;66g<6;29?l4313:17d<;a;29?jd22900c><50;9~f4ge290o6=4?{%`5>g5<@;>h7E<;6:k16?6=3`886=44i3694?=n:<0;66g<1;29?l542900e>:50;9j70<722c8:7>5;h07=?6=3`8?m7>5;n`6>5<<g:81<75rb0c`>5<c290;w)l9:c18L72d3A8?:6g=2;29?l442900e?:50;9j60<722c8=7>5;h10>5<<a:>1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn<oi:18g>5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<<a;>1<75f2483>>o493:17d=<:188m62=831b?84?::k02?6=3`8?57>5;h07e?6=3fh>6=44o2094?=zj8ko6=4k:183!d12k90D?:l;I072>o5:3:17d<<:188m72=831b>84?::k05?6=3`986=44i2694?=n;<0;66g<6;29?l4313:17d<;a;29?jd22900c><50;9~f4gb290o6=4?{%`5>g5<@;>h7E<;6:k16?6=3`886=44i3694?=n:<0;66g<1;29?l542900e>:50;9j70<722c8:7>5;h07=?6=3`8?m7>5;n`6>5<<g:81<75rb0`3>5<c290;w)l9:c18L72d3A8?:6g=2;29?l442900e?:50;9j60<722c8=7>5;h10>5<<a:>1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn<l=:18g>5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<<a;>1<75f2483>>o493:17d=<:188m62=831b?84?::k02?6=3`8?57>5;h07e?6=3fh>6=44o2094?=zj8226=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb0:;>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj82<6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb0:5>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj82>6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb0:7>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8286=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb0:1>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj82:6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb0:3>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8=n6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb05g>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8=h6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb05a>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8=j6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb05:>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8=36=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb054>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8==6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb056>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8=86=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb051>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8=:6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb053>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8<m6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb04f>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8<o6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb04`>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8<i6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb04b>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj82m6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb0:f>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj82o6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb0:`>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj82i6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb0:b>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8=m6=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb057>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8<26=4::183!d12:k0D?:l;I072>"3=380e?750;9j6g<722c9h7>5;h12>5<<gk81<75rb04;>5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj;>;6=4<:183!d12=h0D?:l;I072>"3=3k0e9?50;9j07<722ejn7>5;|`170<72:0;6=u+b787f>N5<j1C>984$579e>o393:17d:=:188kdd=831vn<:l:180>5<7s-h=69l4H36`?M43>2.?97?9;h62>5<<a=81<75`ac83>>{e9;31<7=50;2x g0=<k1C>9m4H365?!2228<0e9?50;9j07<722ejn7>5;|``6?6=;3:1<v*m6;6a?M43k2B98;5+44822>o393:17d:=:188kdd=831vnn?50;194?6|,k<18o5G25a8L7213->>6<84i5394?=n<;0;66anb;29?xdd83:1?7>50z&a2?2e3A8?o6F=479'00<6>2c?=7>5;h61>5<<ghh1<75rbca94?5=83:p(o854c9K61e<@;>=7):::048m17=831b8?4?::mbf?6=3thin7>53;294~"e>3>i7E<;c:J103=#<<0::6g;1;29?l252900cll50;9~fgg=8391<7>t$c490g=O:=i0D?:9;%66>40<a=;1<75f4383>>ifj3:17pl>1583>1<729q/n;4;c:J10f=O:=<0(9;51c9j04<722c?>7>5;h60>5<<ghh1<75rb06g>5<3290;w)l9:5a8L72d3A8?:6*;5;3:?l262900e9<50;9j06<722ejn7>5;|`26d<72=0;6=u+b787g>N5<j1C>984$5795<=n<80;66g;2;29?l242900cll50;9~f47e290>6=4?{%`5>1b<@;>h7E<;6:&71?4f3`>:6=44i5094?=n<:0;66g;4;29?jge2900qo?;e;291?6=8r.i:7:k;I07g>N5<?1/884>a:k75?6=3`>96=44i5194?=n<=0;66anb;29?xd6:k0;684?:1y'f3<3l2B98n5G2548 13=9h1b8<4?::k76?6=3`>86=44i5694?=hik0;66sm10594?3=83:p(o854e9K61e<@;>=7):::0:8m17=831b8?4?::k77?6=3`>?6=44o``94?=zj8;:6=4;:183!d12=i0D?:l;I072>"3=320e9?50;9j07<722c??7>5;nca>5<<uk;?:7>53;294~"e>3>i7E<;c:J103=#<<0=7d:>:188m14=831dmo4?::a55`=83?1<7>t$c490a=O:=i0D?:9;%66>2=n<80;66g;2;29?l242900e9:50;9leg<722wini4?:283>5}#j?0?n6F=4b9K610<,=?1=;5f4083>>o3:3:17bom:188ygd029086=4?{%`5>1d<@;>h7E<;6:&71?713`>:6=44i5094?=hik0;66sm15194?3=83:p(o854e9K61e<@;>=7):::328m17=831b8?4?::k77?6=3`>?6=44o``94?=zj8>?6=4::183!d12=n0D?:l;I072>"3=38;7d:>:188m14=831b8>4?::k70?6=3fki6=44}c371?6==3:1<v*m6;6g?M43k2B98;5+44814>o393:17d:=:188m15=831b894?::mbf?6=3th:8?4?:483>5}#j?0?h6F=4b9K610<,=?1?:5f4083>>o3:3:17d:<:188m12=831dmo4?::a577=83?1<7>t$c490a=O:=i0D?:9;%66>4b<a=;1<75f4383>>o3;3:17d:;:188kdd=831vn<<=:186>5<7s-h=69j4H36`?M43>2.?97?k;h62>5<<a=81<75f4283>>o3<3:17bom:188yg75;3:197>50z&a2?2c3A8?o6F=479'00<582c?=7>5;h61>5<<a=91<75f4583>>ifj3:17pl>1d83>6<729q/n;4;b:J10f=O:=<0(9;51d9j04<722c?>7>5;nca>5<<uk;9<7>55;294~"e>3>o7E<;c:J103=#<<08;6g;1;29?l252900e9=50;9j01<722ejn7>5;|`aa?6=<3:1<v*m6;6`?M43k2B98;5+44815>o393:17d:=:188m15=831dmo4?::af=<72=0;6=u+b787g>N5<j1C>984$57964=n<80;66g;2;29?l242900cll50;9~f426290?6=4?{%`5>1e<@;>h7E<;6:&71?7d3`>:6=44i5094?=n<:0;66anb;29?xden3:197>50z&a2?2c3A8?o6F=479'00<6?2c?=7>5;h61>5<<a=91<75f4583>>ifj3:17plm9;291?6=8r.i:7:k;I07g>N5<?1/884>7:k75?6=3`>96=44i5194?=n<=0;66anb;29?xd6990;684?:1y'f3<3l2B98n5G2548 13=?2c?=7>5;h61>5<<a=91<75f4583>>ifj3:17pl>4c83>7<729q/n;4;6:J10f=O:=<0e9>50;9leg<722wi=?650;094?6|,k<18;5G25a8L7213`>;6=44o``94?=zj8;m6=4::183!d12=o0D?:l;I072>"3=3;m7d:>:188m14=831b8>4?::k70?6=3f>36=44}c374?6==3:1<v*m6;6f?M43k2B98;5+4480?l262900e9<50;9j06<722c?87>5;n6;>5<<uz98>7>57z\077=:98>18>5210`901=:98=18952103904=:99l18<52102904=z{:9;6=4>ez\11a=Y:<>0R>=n;_10<>X5=:1U?>;4^22b?[5412T8<o5Q30`8Z73e3W8>m6P=589]60><V:9m7S=<e:\07a=Y;:i0R><i;_11a>X4:m1U??m4=36g>6c<5;9h6>?4=312>67<5;9i6>?4=31b>67<5;926>?4=367>67<5;>86>?4}r100?6=;rT8?95222a9f4=:::;1n<5rs222>5<5sW9;=63>188a6>{t;=;1<7=t^262?873>3>:70?;1;62?xu4:k0;6::t^20a?844;38270<<2;0:?844938270<<b;0:?844i38270<<9;0:?876k38270?<8;0:?874138270?<a;0:?874j38270?<1;0:?874838270?<2;0:?874;38270h?:3;89``=:016ih4=9:?f`?4>34;;n7<6;<33e?4>34;;57<6;<33<?4>34;;?7<6;<336?4>34;;=7<6;<334?4>34n>6?74=e696<=:l:09563k2;0:?876=38270?>2;0:?876138270?>8;0:?847038270<?9;0:?846<38270<>f;0:?845i38270<=b;0:?845k38270<=d;0:?845m38270<=f;0:?847i38270<?b;0:?847k38270<?d;0:?847m38270<?f;0:?846838270<>1;0:?846:38270<>3;0:?846=38270<>6;0:?846?38270<>8;0:?846138270<>a;0:?846j38270<>c;0:?846l38270<>e;0:?845838270<=1;0:?845:38270<=3;0:?845<38270<=5;0:?845>38270<=7;0:?845038270<=9;0:?87?138270?78;0:?87??38270?76;0:?87?=38270?74;0:?87?;38270?72;0:?87?938270?70;0:?870m38270?8d;0:?870k38270?8b;0:?870i38270?89;0:?870038270?87;0:?870>38270?85;0:?870;38270?82;0:?870938270?80;0:?871n38270?9e;0:?871l38270?9c;0:?871j38270?9a;0:?87?n38270?7e;0:?87?l38270?7c;0:?87?j38270?7a;0:?870n38270?84;0:?871138270?98;0:?xu48>0;6?uQ3158945b2k80q~=<b;290f}Y;:h01?=j:3;8975d2;301?=k:3;897232;301?:<:3;8945b2;301<=k:3;894042;301<8;:3;894022;301<89:3;8943b2;301<;k:3;8943d2;301<;m:3;894322;301<;<:3;894332;301<;9:3;89fg=:016o44=9:?`<?4>34i<6?74=d796<=:m=09563j3;0:?8c52;301ij5289>`f<5127on7<6;<fb>7?<5oh1>452f`81=>;a138270h7:3;894g12;>270?60;07=>;61k0984521c3961?<58h86?:6;<3a2?43127:n94=489>5g3=:=301<l8:36:?87>938?563>95810<=:9081>974=0;0>72>34;297<;9:?2=3<5<016=47525;894?02;>270?68;07=>;61h09845218a961?<583m6?:6;<3:`?43127:5h4=489>5d6=:=301<o>:36:?87f<38?563>a3810<=:9h91>974=0c6>72>34;j;7<;9:?2ed<5<016=l6525;894g>2;>270?nb;07=>;6ij0984521`d961?<58ko6?:6;<3ba?43127:n=4=489>5g4=:=30q~<i8;296~X5l916=575b39~w7`12909wS<lf:?2<=<e:2wx>k;50;0xZ7eb34;3;7l=;|q1b1<72;qU>nj4=0:5>g4<uz8m?7>52z\1gf=:91?1n?5rs3d1>5<5sW8hn63>858a6>{t:o;1<7<t^3ab?87?;3h97p}=f183>7}Y:j301<6=:c08yv4bn3:1>vP=c99>5=7=j;1v?kj:181[4d?27:4=4m2:p6`e=838pR?m:;<34a?d53ty9io4?:3y]6f2<58=o6o<4}r0fe?6=:rT9o>5216a9f7=z{;o26=4={_0`6>;6?k0i>6s|2d:94?4|V;i:70?8a;`1?xu5m>0;6?uQ2b28941>2k80q~<j6;296~X5jo16=:65b39~w7c22909wS<me:?232<e:2wx>h:50;0xZ7dc34;<:7l=;|q1a6<72;qU>om4=056>g4<uz8n=7>52z\1fd=:9>91n?5rs3g3>5<5sW8i563>738a6>{t:ml1<7<t^3`;?87093h97p}=dd83>7}Y:k=01<9?:c08yv4cl3:1>vP=b79>53`=j;1v?jl:181[4e=27::h4m2:p6ad=838pR?l;;<35`?d53ty9hl4?:3y]6g5<58<h6o<4}r0g=?6=:rT9n?5217`9f7=z{;n36=4={_0a5>;6>h0i>6s|2gd94?4|V;n=70?7f;`1?xu5nl0;6?uQ2e7894>b2k80q~<id;296~X5l=16=5j5b39~w7`d2909wS<k3:?2<f<e:2wx>kl50;0xZ7b534;3n7l=;|q1bd<72;qU>i?4=0:b>g4<uz8m57>52z\1g3=:9>l1n?5rs3gg>5<5sW8in63>758a6>{t:l81<7<t^3`3?87113h97p}=d683>7}Y:hl01<87:c08yv4f?3:1>vP=7g9>5g4=;81v?o::181[40m27:n=4<1:p6d2=838pR?9k;<3bb?563ty9m>4?:3y]62e<58kn6>?4}r0b6?6=:rT9;o521`f974=z{;k:6=4={_04e>;6ij08=6s|2`294?4|V;=270?nb;12?xu51o0;6?uQ26:894gf2:;0q~<6e;296~X5?>16=l75309~w7?c2909wS<86:?2e=<492wx>4l50;0xZ71334;j;7=>;|q1=d<72;qU>:=4=0c6>67<uz8257>52z\137=:9h>1?<5rs3;;>5<5sW8<=63>a2805>{t:0=1<7<t^353?87f:39:7p}=9783>7}Y:?l01<o>:238yv4>=3:1>vP=6d9>5d6=;81v?7;:181[41l27:5k4<1:p6<5=838pR?8l;<3:a?563ty95?4?:3y]63d<583o6>?4}r0:4?6=:rT9:45218a974=z{;2m6=4={_05<>;61h08=6s|29g94?4|V;<<70?69;12?xu50m0;6?uQ274894??2:;0q~<7c;296~X5><16=495309~w7>e2909wS<94:?2=3<492wx>5o50;0xZ70434;297=>;|q1<<<72;qU>;<4=0;7>67<uz8347>52z\124=:9091?<5rs3:4>5<5sW8=<63>93805>{t:ho1<7<t^3:6?87>939:7p}=ae83>7}Y:1>01<l8:238yv4fk3:1>vP=829>5g0=;81v?om:181[4?:27:n84<1:p6dg=838pR?6>;<3a0?563ty9m44?:3y]6=6<58h86>?4}r0b<?6=:rT9;8521c3974=z{;3h6=4={_05e>;6i?08=6s|28394?4|V;?m70?6b;12?xu50?0;6?uQ24g894?72:;0q~<<2;297~;5;:08=63=338a6>;5;809n6s|22194?4|5;986o<4=316>17<uz88h7>53z?17`<49279?n4=b:?17a<e:2wx>>k50;0x975b2k801?:?:538yv4493:1?v3=33805>;5;80i>63=34876>{t::i1<7=t=31`>g4<5;9o6>?4=363>14<uz8887>54z?17g<e9279?l4m1:?17<<e9279?84nb:p66>=83op1?=m:c08947d2k;01<=7:3f8945>2;n01<=n:3f8945e2;n01<=>:3f894572k;01<==:3f894542;n01<?::3f894752;n01<?6:c38947?2k;0q~<<7;2954}:::k1n?52f181`>;bn38o70kj:3f89`b=:m16==l52e9>55g=:m16==752e9>55>=:m16===52e9>554=:m16==?52e9>556=:m16h84=d:?g0?4c34n86?j4=e096a=z{;9=6=4:1z?17<<e:279<54=d:?14<<5l279=94=d:?15c<5l279>l4=d:?16g<5l279>n4=d:?16a<5l279>h4=d:?16c<5l279<l4=d:?14g<5l279<n4=d:?14a<5l279<h4=d:?14c<5l279==4=d:?154<5l279=?4=d:?156<5l279=84=d:?153<5l279=:4=d:?15=<5l279=44=d:?15d<5l279=o4=d:?15f<5l279=i4=d:?15`<5l279>=4=d:?164<5l279>?4=d:?166<5l279>94=d:?160<5l279>;4=d:?162<5l279>54=d:?16<<5l27:444=d:?2<=<5l27:4:4=d:?2<3<5l27:484=d:?2<1<5l27:4>4=d:?2<7<5l27:4<4=d:?2<5<5l27:;h4=d:?23a<5l27:;n4=d:?23g<5l27:;l4=d:?23<<5l27:;54=d:?232<5l27:;;4=d:?230<5l27:;>4=d:?237<5l27:;<4=d:?235<5l27::k4=d:?22`<5l27::i4=d:?22f<5l27::o4=d:?22d<5l27:4k4=d:?2<`<5l27:4i4=d:?2<f<5l27:4o4=d:?2<d<5l27:;k4=d:?231<5l27::44=d:?22=<5l2wx>>h50;1x97232k;01?:<:c3897272hh0q~<;2;29b~;5<=0i>63>3d8a5>;6;m0i=63>6281`>;6>=09h63>6481`>;6>?09h63>5d81`>;6=m09h63>5b81`>;6=k0i=63>5481`>;6=:09h63>558a5>;6=?09h6s|25394?76s48??7l=;<ab>7b<5j31>i52c981`>;d?38o70k::3f89`2=:m16i>4=d:?f6?4c34no6?j4=ea96a=:lk09h63ka;0g?8`e2;n01ko52e9>b<<5l27m47<k;|q25a<72;q6=<m5309>576=ik1v<?l:187876k3h970?>7;62?877n3>970?>0;61?xu68o0;6>?t=01;>7d<58926?l4=01b>7d<589i6?l4=012>7d<589;6?l4=011>7d<58986?l4=32;>7d<5;:26?l4=337>7d<5;;m6?l4=30b>7d<5;8i6?l4=30`>7d<5;8o6?l4=30f>7d<5;8m6?l4=32b>7d<5;:i6?l4=32`>7d<5;:o6?l4=32f>7d<5;:m6?l4=333>7d<5;;:6?l4=331>7d<5;;86?l4=336>7d<5;;=6?l4=334>7d<5;;36?l4=33:>7d<5;;j6?l4=33a>7d<5;;h6?l4=33g>7d<5;;n6?l4=303>7d<5;8:6?l4=301>7d<5;886?l4=307>7d<5;8>6?l4=305>7d<5;8<6?l4=30;>7d<5;826?l4=033>dd<uz;9o7>57z?27=<4927:?=4m2:?26<<3:27:>l4;3:?26g<3927:>54;0:?25c<3:2wx=>:50;0a87403h970?n6;10?87>839870?6b;10?87e939870?m3;10?87e>39870?m4;10?87e=39870?m7;10?87>939870?64;10?87>:39870?63;10?87>=39870?66;10?87>139870?67;10?87>039870?6a;10?87>k39870?6f;10?87>l39870?6e;10?87f839870?n1;10?87f<39870?n2;10?87f;39870?n5;10?87f?39870?na;10?87f039870?n9;10?87fj39870?nc;10?87fn39870?nd;10?87fm39870?m0;10?87e:39870ll:50894462=90q~?=d;292~;6;008=63>308a6>;6:00?=63>2`875>;6:k0??63>22875>{t9:?1<7<l{<30=?d534;j:7=;;<3:4?5334;2n7=;;<3a5?5334;i?7=;;<3a2?5334;i87=;;<3a1?5334;i;7=;;<3:5?5334;287=;;<3:6?5334;2?7=;;<3:1?5334;2:7=;;<3:=?5334;2;7=;;<3:<?5334;2m7=;;<3:g?5334;2j7=;;<3:`?5334;2i7=;;<3b4?5334;j=7=;;<3b0?5334;j>7=;;<3b7?5334;j97=;;<3b3?5334;jm7=;;<3b<?5334;j57=;;<3bf?5334;jo7=;;<3bb?5334;jh7=;;<3ba?5334;i<7=;;<3a6?5334hh69?4=c`907=:9;;1895rs00f>5<2s4;8m7=>;<306?d534;9m7:=;<31f?2334;9?7:<;|q273<72;ip1<=n:c0894g12:?01<7?:27894?e2:?01<l>:27894d42:?01<l9:27894d32:?01<l::27894d02:?01<7>:27894?32:?01<7=:27894?42:?01<7::27894?12:?01<76:27894?02:?01<77:27894?f2:?01<7l:27894?a2:?01<7k:27894?b2:?01<o?:27894g62:?01<o;:27894g52:?01<o<:27894g22:?01<o8:27894gf2:?01<o7:27894g>2:?01<om:27894gd2:?01<oi:27894gc2:?01<oj:27894d72:?01<l=:2789gd=<816nl4;2:?267<3;2wx=?h50;6x945e2:;01<=<:c08944e2=801<?j:508yv74?3:1>nu212`9f7=:l<08=63>a7802>;61908:63>9c802>;6j808:63>b2802>;6j?08:63>b5802>;6j<08:63>b6802>;61808:63>95802>;61;08:63>92802>;61<08:63>97802>;61008:63>96802>;61108:63>9`802>;61j08:63>9g802>;61m08:63>9d802>;6i908:63>a0802>;6i=08:63>a3802>;6i:08:63>a4802>;6i>08:63>a`802>;6i108:63>a8802>;6ik08:63>ab802>;6io08:63>ae802>;6il08:63>b1802>;6j;08:63ma;62?875:3>?7p}>3g83>6}:9:o1?<5212f974=:9=81mo5rs01g>5<4s4;8h7l=;<372?2534;?<7:=;|q222<72:?p1<8<:3`894032;h01<8::3`894012;h01<;j:3`8943c2;h01<;l:3`8943e2;h01<;::3`894342;h01<;;:3`894312;h01<o9:36b?87>838?m63>9c810d=:9k;1>9o4=0`0>72f34;i:7<;a:?2f1<5<h16=o;525c894d02;>j70?61;07e>;61=098l52180961g<58386?:n;<3:1?43i27:5;4=4`9>5<?=:=k01<78:36b?87>038?m63>9`810d=:90i1>9o4=0;e>72f34;2h7<;a:?2=`<5<h16=l>525c894g62;>j70?n4;07e>;6i;098l521`1961g<58k>6?:n;<3b3?43i27:ml4=4`9>5d>=:=k01<o6:36b?87fj38?m63>ab810d=:9hl1>9o4=0cg>72f34;ji7<;a:?2f5<5<h16=o<525c894212hh0q~?:7;297~;6>:08=63>5c8a6>;6<:0??6s|14d94?4fs4;=?7l=;<3b2?4534;2<7<=;<3:f?4534;i=7<=;<3a7?4534;i:7<=;<3a0?4534;i97<=;<3a3?4534;2=7<=;<3:0?4534;2>7<=;<3:7?4534;297<=;<3:2?4534;257<=;<3:3?4534;247<=;<3:e?4534;2o7<=;<3:b?4534;2h7<=;<3:a?4534;j<7<=;<3b5?4534;j87<=;<3b6?4534;j?7<=;<3b1?4534;j;7<=;<3be?4534;j47<=;<3b=?4534;jn7<=;<3bg?4534;jj7<=;<3b`?4534;ji7<=;<3a4?4534;i>7<=;<a1>14<uz;>47>53z?221<4927:9n4m2:?206<392wx=;>50;0a871<3h970?n6;00?87>838870?6b;00?87e938870?m3;00?87e>38870?m4;00?87e=38870?m7;00?87>938870?64;00?87>:38870?63;00?87>=38870?66;00?87>138870?67;00?87>038870?6a;00?87>k38870?6f;00?87>l38870?6e;00?87f838870?n1;00?87f<38870?n2;00?87f;38870?n5;00?87f?38870?na;00?87f038870?n9;00?87fj38870?nc;00?87fn38870?nd;00?87fm38870?m0;00?87e:38870m=:5389f7=<;1v<;6:180871=39:70?:d;`1?873<3>87p}>6083>7d|58<>6o<4=0c5>72<583;6?:4=0;a>72<58h:6?:4=0`0>72<58h=6?:4=0`7>72<58h>6?:4=0`4>72<583:6?:4=0;7>72<58396?:4=0;0>72<583>6?:4=0;5>72<58326?:4=0;4>72<58336?:4=0;b>72<583h6?:4=0;e>72<583o6?:4=0;f>72<58k;6?:4=0c2>72<58k?6?:4=0c1>72<58k86?:4=0c6>72<58k<6?:4=0cb>72<58k36?:4=0c:>72<58ki6?:4=0c`>72<58km6?:4=0cg>72<58kn6?:4=0`3>72<58h96?:4=b3904=:k90?>6s|14c94?5|58<=6>?4=07f>g4<58>?69?4}r356?6=:kq6=;85b39>bg<4927:m;4=5:?2=5<5=27:5o4=5:?2f4<5=27:n>4=5:?2f3<5=27:n94=5:?2f0<5=27:n:4=5:?2=4<5=27:594=5:?2=7<5=27:5>4=5:?2=0<5=27:5;4=5:?2=<<5=27:5:4=5:?2==<5=27:5l4=5:?2=f<5=27:5k4=5:?2=a<5=27:5h4=5:?2e5<5=27:m<4=5:?2e1<5=27:m?4=5:?2e6<5=27:m84=5:?2e2<5=27:ml4=5:?2e=<5=27:m44=5:?2eg<5=27:mn4=5:?2ec<5=27:mi4=5:?2e`<5=27:n=4=5:?2f7<5=27h<7:>;|q217<72=q6=8k5309>500=j;16=9k5439>513=<81v<;>:186872l39:70?:5;`1?873l3>970?;e;67?87383>:7p}>5183>3}:9<i1?<521469f7=:9=i18<5215f904=:9=o18>52157906=z{8>m6=48{<36f?5634;>?7l=;<37g?2534;?h7:<;<37a?2634;?=7:<;<37f?273ty:844?:3y>503=;816=9j5ac9~w4202909w0?:3;12?873j3ki7p}>4983>7}:9<>1?<5215a9eg=z{8>j6=4={<362?5634;?i7om;|q260<72;q6=>?5309>57?=ik1v<<;:181874839:70?=8;ca?xu6:?0;6?u2120974=:9;k1mo5rs004>5<5s4;8?7=>;<31f?ge3tyn=7>55z?`e?5634o>6o<4=c5907=:j10?>63m9;61?xud>3:1?v3la;`1?873<3>970?;5;61?xudj3:1>v3l9;12?8d02hh0q~m::1808e>2k801<:;:56894272=90q~ml:1818e?2:;01o65ac9~wf2=839p1n65b39>515=<;16=9;5459~wfb=838p1n95309>f<<fj2wxo>4?:2y>g2<e:27:8>4;4:?204<3:2wx==950;7x9c6=;816==l5b39>fa<3:27ii7:=;<`e>14<uzoh6=4<{<d3>g4<588969<4=03f>17<uzl:6=4={<ge>67<5kn1mo5rsd`94?5|5ll1n?52130904=:9;91895rsg094?4|5lo1?<52bd8bf>{tmh0;6>u2ed8a6>;6:80?>63>22876>{tn:0;6?u2ee805>;en3ki7p}j9;297~;bl3h970?=1;62?876n3>:7p}if;296~;68k08=63>028a6>{tnl0;6?u211c974=:9981n?5rs025>5<3s4;;m7l=;<`g>17<5ko18<52bg875>{tnm0;6?u211;974=:99;1n?5rs026>5<4s4;;57l=;<`f>15<5kl18>5rsga94?4|58:36>?4=023>g4<uz;;87>52z?24=<e:27ij7:;;|qg=?6=:r7n97=>;<fg>g4<uzn36=4={<g7>67<5mi1n?5rsd294?2|5l>1n?52b6875>;e03>:70l6:538yvb02909w0k<:2389ad=j;1vih50;1x9`5=j;16n54;3:?a=?243tyo:7>52z?f6?5634nj6o<4}rff>5<5s4o96o<4=c;901=z{o=1<7<t=020>67<5oh1n?5rsg494?4|58:96>?4=gc9f7=z{o?1<7<t=022>67<5o31n?5rsg694?4|58:;6>?4=g:9f7=z{m;1<7<t=ef974=:l<0i>6s|d183>7}:lj08=63k4;`1?xudn3:1>v3kb;12?8b42k80q~mj:1818bf2:;01i<5b39~w`0=838p1i:5309>fd<fj2wxi:4?:3y>`6<4927in7om;|qf<?6=:r7o>7=>;<``>dd<uz;;o7>52z?ee?5634i;6ll4}r33`?6=:r7m57=>;<a2>dd<uz;;i7>52z?e<?5634i96ll4}r322?6=:r7:=84<1:?252<fj2wx=<;50;5x94722k801<?;:508947e2=901<?8:51894762=901<>i:56894772=>0q~?>3;296~;69;08=63>158bf>{t9881<79t=031>g4<58;?69?4=03a>14<58;<69<4=032>14<58:m69=4=033>15<uz;:m7>53z?25<<4927:=54<1:?25g<fj2wx=<650;0x947?2k801<?m:538yv7e03:1>v3=09805>;61908>6s|1d294?4|5;:36o<4=04;>67<uz;h?7>52z?14<<4927:5o4<2:p5`d=838p1?>6:c08940>2:;0q~?le;296~;59=08=63>a7806>{t9o<1<7<t=337>g4<58=?6>?4}r3g=?6=:r79=k4<1:?2f4<4:2wx>=?50;0x977a2k801<9i:238yv7ci3:1>v3=2`805>;6j:08>6s|21094?4|5;8j6o<4=0:b>67<uz;on7>52z?16g<4927:n94<2:p655=838p1?<m:c0894>e2:;0q~?kc;296~;5:j08=63>b4806>{t:9>1<7<t=30`>g4<582h6>?4}r3g`?6=:r79>i4<1:?2f3<4:2wx>=;50;0x974c2k801<6k:238yv7cm3:1>v3=2d805>;6j>08>6s|21494?4|5;8n6o<4=0:f>67<uz;oj7>52z?16c<4927:5<4<2:p651=838p1?<i:c0894>a2:;0q~?m9;296~;58h08=63>93806>{t9l;1<7<t=32b>g4<58<j6>?4}r3ae?6=:r79<o4<1:?2=6<4:2wx=h<50;0x976e2k801<8m:238yv7ej3:1>v3=0b805>;61=08>6s|1d194?4|5;:h6o<4=04`>67<uz;io7>52z?14a<4927:584<2:p5`2=838p1?>k:c08940c2:;0q~?md;296~;58l08=63>97806>{t9l?1<7<t=32f>g4<58<n6>?4}r3aa?6=:r79<k4<1:?2=2<4:2wx=h850;0x976a2k801<8i:238yv7en3:1>v3=11805>;61108>6s|1d594?4|5;;;6o<4=053>67<uz;h<7>52z?154<4927:544<2:p5`>=838p1??>:c0894162:;0q~?l1;296~;59;08=63>9`806>{t9l31<7<t=331>g4<58=96>?4}r3`6?6=:r79=>4<1:?2=f<4:2wx=ho50;0x97742k801<9<:238yv7d<3:1>v3=14805>;61m08>6s|1da94?4|5;;>6o<4=056>67<uz;h97>52z?153<4927:5h4<2:p5`b=838p1??9:c0894112:;0q~?l6;296~;59>08=63>9g806>{t9lo1<7<t=334>g4<58=<6>?4}r3`3?6=:r79=54<1:?2e5<4:2wx=hh50;0x977?2k801<97:238yv7d03:1>v3=18805>;6i808>6s|1g294?4|5;;26o<4=05:>67<uz;h57>52z?15d<4927:m?4<2:p5c7=838p1??n:c08941f2:;0q~?la;296~;59k08=63>a2806>{t9o81<7<t=33a>g4<58=i6>?4}r3`f?6=:r79=n4<1:?2e1<4:2wx=k=50;0x977d2k801<9l:238yv7dk3:1>v3=1e805>;6i<08>6s|1g694?4|5;;o6o<4=05g>67<uz;hh7>52z?15`<4927:m:4<2:p5c3=838p1??j:c08941b2:;0q~?lf;296~;5:908=63>a9806>{t9o=1<7<t=303>g4<582;6>?4}r3g4?6=:r79><4<1:?2e<<4:2wx=k650;0x97462k801<6>:238yv7c93:1>v3=23805>;6ih08>6s|1g;94?4|5;896o<4=0:1>67<uz;o>7>52z?166<4927:mo4<2:p5cg=838p1?<<:c0894>42:;0q~?k3;296~;5:=08=63>ab806>{t9oh1<7<t=307>g4<582?6>?4}r3g0?6=:r79>84<1:?2ea<4:2wx=km50;0x97422k801<6::238yv7c=3:1>v3=27805>;6il08>6s|1gf94?4|5;8=6o<4=0:5>67<uz;o:7>52z?162<4927:mk4<2:p5cc=838p1?<8:c0894>02:;0q~?k7;296~;5:108=63>b1806>{t9ol1<7<t=30;>g4<58236>?4}r3g<?6=:r79>44<1:?2f7<4:2wx>=>50;0x974>2k801<66:238yv4483:1>4u219;96g=:9121>o5219596g=:91<1>o5219796g=:91>1>o5219196g=:9181>o5219396g=:91:1>o5216g96g=:9>n1>o5216a96g=:9>h1>o5216c96g=:9>31>o5216:96g=:9>=1>o5216496g=:9>?1>o5216196g=:9>81>o5216396g=:9>:1>o5217d96g=:9?o1>o5217f96g=:9?i1>o5217`96g=:9?k1>o5219d96g=:91o1>o5219f96g=:91i1>o5219`96g=:91k1>o5216d96g=:9>>1>o5217;96g=:9?21>o521039eg=z{89h6=4={<33b?ge34;:j7:<;|q206<72;q6=9=5ac9>514=<81v<:;:181873<3ki70?;2;61?xu6<<0;6?u21579eg=:9=818>5rs063>5<5s4;?>7:;;<374?2?3ty:><4?:3y>577=ik16=?>5409~w4452909w0?=2;ca?87583>97p}>2283>7}:9;91mo52132906=z{8;n6=4={<32a?ge34;:j7:;;|q25c<72;q6=?>5459>54`=<11v:850;0x94262hh01<:?:568yxu5i>0;6?uQ26d8971=:>l0(?:::828yv4f=3:1>vP=7d9>62<5?l1/>9;5909~w7g32909wS<8d:?13?40l2.988467:p6d5=838pR?9l;<04>71d3-8?977j;|q1e7<72;qU>:l4=35962d<,;>>68<4}r0b5?6=:rT9;l5226813d=#:=?19i5rs3c3>5<5sW8<563=7;04=>"5<<0=46s|28d94?4|V;=370<8:35;?!43=3<m7p}=9d83>7}Y:>=01?952658 7222>:0q~<6d;296~X5??16>:4=779'613=?81v?7m:181[40<279;7<84:&100<0:2wx>4o50;0xZ714348<6?9<;%071?143ty9544?:3y]624<5;=1>:<4$366>22<uz8247>52z\134=::>09;<5+257930=z{;3<6=4={_044>;5?38<<6*=44842>{t:0<1<7<t^34e?8402;<m7)<;5;54?xu51<0;6?uQ27g8971=:?o0(?:::6:8yv4><3:1>vP=6e9>62<5>m1/>9;5789~w7?42909wS<9c:?13?41k2.98848a:p6<4=838pR?8m;<04>70e3-8?979m;|q1=5<72;qU>;74=35963?<,;>>6:m4}r0;b?6=:rT9:55226812==#:=?1;i5rs3:f>5<5sW8=;63=7;053>"5<<0<i6s|29f94?4|V;<=70<8:345?!43=3=m7p}=8b83>7}Y:??01?952778 72221:0q~<7b;296~X5>=16>:4=659'613=081v?6n:181[41;279;7<93:&100<?:2wx>5750;0xZ705348<6?8=;%071?>43ty9454?:3y]637<5;=1>;?4$366>=2<uz83;7>52z\125=::>09:=5+2579<0=z{;kn6=4={_0;1>;5?38396*=448;2>{t:hn1<7<t^3:7?8402;2?7)<;5;:4?xu5ij0;6?uQ2918971=:190(?:::9:8yv4fj3:1>vP=839>62<50;1/>9;5889~w7gf2909wS<71:?13?4?92.98847a:p6d?=838pR?6?;<04>7>73-8?976m;|q1e=<72;qU>:;4=359623<,;>>65m4}r0:g?6=:rT9:l5226812d=#:=?14i5rs3;2>5<5sW8>j63=7;06b>"5<<03i6s|29494?4|V;?n70<8:37f?!43=32m7p}<2c83>7}Y;;h01?9533`8 7222080q~=<2;296~X4;;16>:4<339'613=1:1v>=;:181[54<279;7=<4:&100<><2wx?>l50;0xZ65e348<6>=m;%071??23ty88<4?:3y]717<5;=1?9?4$366><0<uz8m47>52z\1`5=::>09h=5+2579===z{;l=6=4={_0`b>;5?38hj6*=448:=>{t:o?1<7<t^3af?8402;in7)<;5;;b?xu5n=0;6?uQ2bf8971=:jn0(?:::8`8yv4a;3:1>vP=cb9>62<5kj1/>9;59b9~w7`52909wS<lb:?13?4dj2.98846d:p6c7=838pR?mn;<04>7ef3-8?977i;|q1b5<72;qU>n74=3596f?<,;>>6l>4}r0fb?6=:rT9o5522681g==#:=?1m<5rs3gf>5<5sW8h;63=7;0`3>"5<<0j>6s|2da94?4|V;i>70<8:3a6?!43=3k87p}=ec83>7}Y:j>01?952b68 7222h>0q~<ja;296~X5k:16>:4=c29'613=i<1v?k6:181[4d:279;7<l2:&100<f>2wx>h650;0xZ7e6348<6?m>;%071?g03ty9i:4?:3y]6f6<5;=1>n>4$366>d><uz8n:7>52z\1fc=::>09nk5+257916=z{;o>6=4={_0aa>;5?38ii6*=44860>{t:l>1<7<t^3`g?8402;ho7)<;5;76?xu5m:0;6?uQ2ca8971=:ki0(?:::448yv4b93:1>vP=b`9>62<5jh1/>9;5569~w7c72909wS<m9:?13?4e12.9884:8:p6a`=838pR?l7;<04>7d?3-8?97;6;|q1``<72;qU>o94=3596g1<,;>>68o4}r0g`?6=:rT9n;522681f3=#:=?19o5rs3f`>5<5sW8i963=7;0a1>"5<<0>o6s|2e`94?4|V;h?70<8:3`7?!43=3?n7p}=d`83>7}Y:k901?952c18 7222<l0q~<k9;296~X5j;16>:4=b39'613=>91v?j7:181[4e9279;7<m1:&100<192wx>kh50;0xZ7b1348<6?j9;%071?053ty9jh4?:3y]6a3<5;=1>i;4$366>35<uz8mh7>52z\1`1=::>09h95+257921=z{;lh6=4={_0g7>;5?38o?6*=44851>{t:oh1<7<t^3f1?8402;n97)<;5;45?xu5nh0;6?uQ2e38971=:m;0(?:::758yv4a13:1>vP=c79>62<5k?1/>9;5689~w7cc2909wS<mb:?13?4ej2.98849a:p6`4=838pR?l?;<04>7d73-8?978m;|q1`2<72;qU>lh4=3596d`<,;>>6;m4}r135?6=:rT8<<52268044=#:=?1:i5rs224>5<5sW9;;63=7;133>"5<<0=i6srn974>5<5sA8?:6sa84:94?4|@;>=7p`75883>7}O:=<0qc6:a;296~N5<?1vb5;m:181M43>2we48m50;0xL7213td39i4?:3yK610<ug2>i7>52zJ103=zf1?m6=4={I072>{i0?:1<7<tH365?xh?>80;6?uG2548yk>1:3:1>vF=479~j=042909wE<;6:m<32=838pD?:9;|l;20<72;qC>984}o:52?6=:rB98;5rn944>5<5sA8?:6sa87:94?4|@;>=7p`76883>7}O:=<0qc69a;296~N5<?1vb58m:181M43>2we4;m50;0xL7213td3:i4?:3yK610<ug2=i7>52zJ103=zf1<m6=4={I072>{i0>:1<7<tH365?xh??80;6?uG2548yk>0:3:1>vF=479~j=142909wE<;6:m<22=838pD?:9;|l;30<72;qC>984}o:42?6=:rB98;5rn954>5<5sA8?:6sa86:94?4|@;>=7p`77883>7}O:=<0qc68a;296~N5<?1vb59m:181M43>2we4:m50;0xL7213td3;i4?:3yK610<ug2<i7>52zJ103=zf1=m6=4={I072>{i01:1<7<tH365?xh?080;6?uG2548yk>?:3:1>vF=479~j=>42909wE<;6:m<=2=838pD?:9;|l;<0<72;qC>984}o:;2?6=:rB98;5rn9:4>5<5sA8?:6sa89:94?4|@;>=7p`78883>7}O:=<0qc67a;296~N5<?1vb56m:181M43>2we45m50;0xL7213td34i4?:3yK610<ug23i7>52zJ103=zf12m6=4={I072>{i00:1<7<tH365?xh?180;6?uG2548yk>>:3:1>vF=479~j=?42909wE<;6:m<<2=838pD?:9;|l;=0<72;qC>984}o::2?6=:rB98;5rn9;4>5<5sA8?:6sa88:94?4|@;>=7p`79883>7}O:=<0qc66a;296~N5<?1vb57m:181M43>2we44m50;0xL7213td35i4?:3yK610<ug22i7>52zJ103=zf13m6=4={I072>{i0h:1<7<tH365?xh?i80;6?uG2548yk>f:3:1>vF=479~j=g42909wE<;6:m<d2=838pD?:9;|l;e0<72;qC>984}o:b2?6=:rB98;5rn9c4>5<5sA8?:6sa8`:94?4|@;>=7p`7a883>7}O:=<0qc6na;296~N5<?1vb5om:181M43>2we4lm50;0xL7213td3mi4?:3yK610<ug=??7>51zJ103=zf>3j6=4>{I072>{i?0h1<7?tH365?xh01j0;6<uG2548yk1>l3:1=vF=479~j2?b290:wE<;6:m3<`=83;pD?:9;|l4e5<728qC>984}o5b5?6=9rB98;5rn6c1>5<6sA8?:6sa7`194?7|@;>=7p`8a583>4}O:=<0qc9n5;295~N5<?1vb:o9:182M43>2we;l950;3xL7213td<m54?:0yK610<ug=j57>51zJ103=zf>kj6=4>{I072>{i?hh1<7?tH365?xh0ij0;6<uG2548yk1fl3:1=vF=479~j2gb290:wE<;6:m3d`=83;pD?:9;|l4f5<728qC>984}o5a5?6=9rB98;5rn6`1>5<6sA8?:6sa7c194?7|@;>=7p`8b583>4}O:=<0qc9m5;295~N5<?1vb:l9:182M43>2we;o950;3xL7213td<n54?:0yK610<ug=i57>51zJ103=zf>hj6=4>{I072>{i?kh1<7?tH365?xh0jj0;6<uG2548yk1el3:1=vF=479~j2db290:wE<;6:m3g`=83;pD?:9;|l4g5<728qC>984}o5`5?6=9rB98;5rn6a1>5<6sA8?:6sa7b194?7|@;>=7p`8c583>4}O:=<0qc9l5;295~N5<?1vb:m9:182M43>2we;n950;3xL7213td<o54?:0yK610<ug=h57>51zJ103=zf>ij6=4>{I072>{i?jh1<7?tH365?xh0kj0;6<uG2548yk1dl3:1=vF=479~j2eb290:wE<;6:m3f`=83;pD?:9;|l4`5<728qC>984}o5g5?6=9rB98;5rn6f1>5<6sA8?:6sa7e194?7|@;>=7p`8d583>4}O:=<0qc9k5;295~N5<?1vb:j9:182M43>2we;i950;3xL7213td<h54?:0yK610<ug=o57>51zJ103=zf>nj6=4>{I072>{i?mh1<7?tH365?xh0lj0;6<uG2548yk1cl3:1=vF=479~j2bb290:wE<;6:m3a`=83;pD?:9;|l4a5<728qC>984}o5f5?6=9rB98;5rn6g1>5<6sA8?:6sa7d194?7|@;>=7p`8e583>4}O:=<0qc9j5;295~N5<?1vb:k9:182M43>2we;h950;3xL7213td<i54?:0yK610<ug=n57>51zJ103=zf>oj6=4>{I072>{i?lh1<7?tH365?xh0mj0;6<uG2548yk1bl3:1=vF=479~j2cb290:wE<;6:m3``=83;pD?:9;|l4b5<728qC>984}o5e5?6=9rB98;5rn6d1>5<6sA8?:6sa7g194?7|@;>=7p`8f583>4}O:=<0qc9i5;295~N5<?1vb:h9:182M43>2we;k950;3xL7213td<j54?:0yK610<ug=m57>51zJ103=zf>lj6=4>{I072>{i?oh1<7?tH365?xh0nj0;6<uG2548yk1al3:1=vF=479~j2`b290:wE<;6:m3c`=83;pD?:9;|l;45<728qC>984}o:35?6=9rB98;5rn921>5<6sA8?:6sa81194?7|@;>=7p`70583>4}O:=<0qc6?5;295~N5<?1vb5>9:182M43>2we4=950;3xL7213td3<54?:0yK610<ug2;57>51zJ103=zf1:j6=4>{I072>{i09h1<7?tH365?xh?8j0;6<uG2548yk>7l3:1=vF=479~j=6b290:wE<;6:m<5`=83;pD?:9;|l;55<728qC>984}o:25?6=9rB98;5rn931>5<6sA8?:6sa80194?7|@;>=7p`71583>4}O:=<0qc6>5;295~N5<?1vb5?9:182M43>2we4<950;3xL7213td3=54?:0yK610<ug2:57>51zJ103=zf1;j6=4>{I072>{i08h1<7?tH365?xh?9j0;6<uG2548yk>6l3:1=vF=479~j=7b290:wE<;6:m<4`=83;pD?:9;|l;65<728qC>984}o:15?6=9rB98;5rn901>5<6sA8?:6sa83194?7|@;>=7p`72583>4}O:=<0qc6=5;295~N5<?1vb5<9:182M43>2we4?950;3xL7213td3>54?:0yK610<ug2957>51zJ103=zf18j6=4>{I072>{i0;h1<7?tH365?xh?:j0;6<uG2548yk>5l3:1=vF=479~j=4b290:wE<;6:m<7`=83;pD?:9;|l;75<728qC>984}o:05?6=9rB98;5rn911>5<6sA8?:6sa82194?7|@;>=7p`73583>4}O:=<0qc6<5;295~N5<?1vb5=9:182M43>2we4>950;3xL7213td3?54?:0yK610<ug2857>51zJ103=zf19j6=4>{I072>{i0:h1<7?tH365?xh?;j0;6<uG2548yk>4l3:1=vF=479~j=5b290:wE<;6:m<6`=83;pD?:9;|l;05<728qC>984}o:75?6=9rB98;5rn961>5<6sA8?:6sa85194?7|@;>=7p`74583>4}O:=<0qc6;5;295~N5<?1vb5:9:182M43>2we49950;3xL7213td3854?:0yK610<ug2?57>51zJ103=zf1>j6=4>{I072>{i0=h1<7?tH365?xh?<j0;6<uG2548yk>3l3:1=vF=479~j=2b290:wE<;6:m<1`=83;pD?:9;|l;15<728qC>984}o:65?6=9rB98;5rn971>5<6sA8?:6sa84194?7|@;>=7p`75583>4}O:=<0qc6:5;295~N5<?1vb5;9:182M43>2wvqpNOCz;`7?1fm?:m4pNOBz2~DEV|uIJ \ No newline at end of file
diff --git a/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.v b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.v
new file mode 100644
index 000000000..8a08330d5
--- /dev/null
+++ b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.v
@@ -0,0 +1,165 @@
+/*******************************************************************************
+* This file is owned and controlled by Xilinx and must be used *
+* solely for design, simulation, implementation and creation of *
+* design files limited to Xilinx devices or technologies. Use *
+* with non-Xilinx devices or technologies is expressly prohibited *
+* and immediately terminates your license. *
+* *
+* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" *
+* SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR *
+* XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION *
+* AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION *
+* OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS *
+* IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, *
+* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE *
+* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY *
+* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE *
+* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR *
+* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF *
+* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
+* FOR A PARTICULAR PURPOSE. *
+* *
+* Xilinx products are not intended for use in life support *
+* appliances, devices, or systems. Use in such applications are *
+* expressly prohibited. *
+* *
+* (c) Copyright 1995-2007 Xilinx, Inc. *
+* All rights reserved. *
+*******************************************************************************/
+// The synthesis directives "translate_off/translate_on" specified below are
+// supported by Xilinx, Mentor Graphics and Synplicity synthesis
+// tools. Ensure they are correct for your synthesis tool(s).
+
+// You must compile the wrapper file fifo_xlnx_16x40_2clk.v when simulating
+// the core, fifo_xlnx_16x40_2clk. When compiling the wrapper file, be sure to
+// reference the XilinxCoreLib Verilog simulation library. For detailed
+// instructions, please refer to the "CORE Generator Help".
+
+`timescale 1ns/1ps
+
+module fifo_xlnx_16x40_2clk(
+ din,
+ rd_clk,
+ rd_en,
+ rst,
+ wr_clk,
+ wr_en,
+ dout,
+ empty,
+ full);
+
+
+input [39 : 0] din;
+input rd_clk;
+input rd_en;
+input rst;
+input wr_clk;
+input wr_en;
+output [39 : 0] dout;
+output empty;
+output full;
+
+// synthesis translate_off
+
+ FIFO_GENERATOR_V4_3 #(
+ .C_COMMON_CLOCK(0),
+ .C_COUNT_TYPE(0),
+ .C_DATA_COUNT_WIDTH(4),
+ .C_DEFAULT_VALUE("BlankString"),
+ .C_DIN_WIDTH(40),
+ .C_DOUT_RST_VAL("0"),
+ .C_DOUT_WIDTH(40),
+ .C_ENABLE_RLOCS(0),
+ .C_FAMILY("spartan3"),
+ .C_FULL_FLAGS_RST_VAL(1),
+ .C_HAS_ALMOST_EMPTY(0),
+ .C_HAS_ALMOST_FULL(0),
+ .C_HAS_BACKUP(0),
+ .C_HAS_DATA_COUNT(0),
+ .C_HAS_INT_CLK(0),
+ .C_HAS_MEMINIT_FILE(0),
+ .C_HAS_OVERFLOW(0),
+ .C_HAS_RD_DATA_COUNT(0),
+ .C_HAS_RD_RST(0),
+ .C_HAS_RST(1),
+ .C_HAS_SRST(0),
+ .C_HAS_UNDERFLOW(0),
+ .C_HAS_VALID(0),
+ .C_HAS_WR_ACK(0),
+ .C_HAS_WR_DATA_COUNT(0),
+ .C_HAS_WR_RST(0),
+ .C_IMPLEMENTATION_TYPE(2),
+ .C_INIT_WR_PNTR_VAL(0),
+ .C_MEMORY_TYPE(2),
+ .C_MIF_FILE_NAME("BlankString"),
+ .C_MSGON_VAL(1),
+ .C_OPTIMIZATION_MODE(0),
+ .C_OVERFLOW_LOW(0),
+ .C_PRELOAD_LATENCY(0),
+ .C_PRELOAD_REGS(1),
+ .C_PRIM_FIFO_TYPE("512x72"),
+ .C_PROG_EMPTY_THRESH_ASSERT_VAL(4),
+ .C_PROG_EMPTY_THRESH_NEGATE_VAL(5),
+ .C_PROG_EMPTY_TYPE(0),
+ .C_PROG_FULL_THRESH_ASSERT_VAL(15),
+ .C_PROG_FULL_THRESH_NEGATE_VAL(14),
+ .C_PROG_FULL_TYPE(0),
+ .C_RD_DATA_COUNT_WIDTH(4),
+ .C_RD_DEPTH(16),
+ .C_RD_FREQ(1),
+ .C_RD_PNTR_WIDTH(4),
+ .C_UNDERFLOW_LOW(0),
+ .C_USE_DOUT_RST(1),
+ .C_USE_ECC(0),
+ .C_USE_EMBEDDED_REG(0),
+ .C_USE_FIFO16_FLAGS(0),
+ .C_USE_FWFT_DATA_COUNT(0),
+ .C_VALID_LOW(0),
+ .C_WR_ACK_LOW(0),
+ .C_WR_DATA_COUNT_WIDTH(4),
+ .C_WR_DEPTH(16),
+ .C_WR_FREQ(1),
+ .C_WR_PNTR_WIDTH(4),
+ .C_WR_RESPONSE_LATENCY(1))
+ inst (
+ .DIN(din),
+ .RD_CLK(rd_clk),
+ .RD_EN(rd_en),
+ .RST(rst),
+ .WR_CLK(wr_clk),
+ .WR_EN(wr_en),
+ .DOUT(dout),
+ .EMPTY(empty),
+ .FULL(full),
+ .CLK(),
+ .INT_CLK(),
+ .BACKUP(),
+ .BACKUP_MARKER(),
+ .PROG_EMPTY_THRESH(),
+ .PROG_EMPTY_THRESH_ASSERT(),
+ .PROG_EMPTY_THRESH_NEGATE(),
+ .PROG_FULL_THRESH(),
+ .PROG_FULL_THRESH_ASSERT(),
+ .PROG_FULL_THRESH_NEGATE(),
+ .RD_RST(),
+ .SRST(),
+ .WR_RST(),
+ .ALMOST_EMPTY(),
+ .ALMOST_FULL(),
+ .DATA_COUNT(),
+ .OVERFLOW(),
+ .PROG_EMPTY(),
+ .PROG_FULL(),
+ .VALID(),
+ .RD_DATA_COUNT(),
+ .UNDERFLOW(),
+ .WR_ACK(),
+ .WR_DATA_COUNT(),
+ .SBITERR(),
+ .DBITERR());
+
+
+// synthesis translate_on
+
+endmodule
+
diff --git a/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.veo b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.veo
new file mode 100644
index 000000000..684078e58
--- /dev/null
+++ b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.veo
@@ -0,0 +1,51 @@
+/*******************************************************************************
+* This file is owned and controlled by Xilinx and must be used *
+* solely for design, simulation, implementation and creation of *
+* design files limited to Xilinx devices or technologies. Use *
+* with non-Xilinx devices or technologies is expressly prohibited *
+* and immediately terminates your license. *
+* *
+* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" *
+* SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR *
+* XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION *
+* AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION *
+* OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS *
+* IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, *
+* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE *
+* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY *
+* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE *
+* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR *
+* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF *
+* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
+* FOR A PARTICULAR PURPOSE. *
+* *
+* Xilinx products are not intended for use in life support *
+* appliances, devices, or systems. Use in such applications are *
+* expressly prohibited. *
+* *
+* (c) Copyright 1995-2007 Xilinx, Inc. *
+* All rights reserved. *
+*******************************************************************************/
+// The following must be inserted into your Verilog file for this
+// core to be instantiated. Change the instance name and port connections
+// (in parentheses) to your own signal names.
+
+//----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG
+fifo_xlnx_16x40_2clk YourInstanceName (
+ .din(din), // Bus [39 : 0]
+ .rd_clk(rd_clk),
+ .rd_en(rd_en),
+ .rst(rst),
+ .wr_clk(wr_clk),
+ .wr_en(wr_en),
+ .dout(dout), // Bus [39 : 0]
+ .empty(empty),
+ .full(full));
+
+// INST_TAG_END ------ End INSTANTIATION Template ---------
+
+// You must compile the wrapper file fifo_xlnx_16x40_2clk.v when simulating
+// the core, fifo_xlnx_16x40_2clk. When compiling the wrapper file, be sure to
+// reference the XilinxCoreLib Verilog simulation library. For detailed
+// instructions, please refer to the "CORE Generator Help".
+
diff --git a/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.xco b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.xco
new file mode 100644
index 000000000..d0da5a6e8
--- /dev/null
+++ b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk.xco
@@ -0,0 +1,82 @@
+##############################################################
+#
+# Xilinx Core Generator version K.39
+# Date: Tue May 11 20:27:53 2010
+#
+##############################################################
+#
+# This file contains the customisation parameters for a
+# Xilinx CORE Generator IP GUI. It is strongly recommended
+# that you do not manually alter this file as it may cause
+# unexpected and unsupported behavior.
+#
+##############################################################
+#
+# BEGIN Project Options
+SET addpads = False
+SET asysymbol = False
+SET busformat = BusFormatAngleBracketNotRipped
+SET createndf = False
+SET designentry = Verilog
+SET device = xc3s2000
+SET devicefamily = spartan3
+SET flowvendor = Other
+SET formalverification = False
+SET foundationsym = False
+SET implementationfiletype = Ngc
+SET package = fg456
+SET removerpms = False
+SET simulationfiles = Behavioral
+SET speedgrade = -5
+SET verilogsim = True
+SET vhdlsim = False
+# END Project Options
+# BEGIN Select
+SELECT Fifo_Generator family Xilinx,_Inc. 4.3
+# END Select
+# BEGIN Parameters
+CSET almost_empty_flag=false
+CSET almost_full_flag=false
+CSET component_name=fifo_xlnx_16x40_2clk
+CSET data_count=false
+CSET data_count_width=4
+CSET disable_timing_violations=false
+CSET dout_reset_value=0
+CSET empty_threshold_assert_value=4
+CSET empty_threshold_negate_value=5
+CSET enable_ecc=false
+CSET enable_int_clk=false
+CSET fifo_implementation=Independent_Clocks_Distributed_RAM
+CSET full_flags_reset_value=1
+CSET full_threshold_assert_value=15
+CSET full_threshold_negate_value=14
+CSET input_data_width=40
+CSET input_depth=16
+CSET output_data_width=40
+CSET output_depth=16
+CSET overflow_flag=false
+CSET overflow_sense=Active_High
+CSET performance_options=First_Word_Fall_Through
+CSET programmable_empty_type=No_Programmable_Empty_Threshold
+CSET programmable_full_type=No_Programmable_Full_Threshold
+CSET read_clock_frequency=1
+CSET read_data_count=false
+CSET read_data_count_width=4
+CSET reset_pin=true
+CSET reset_type=Asynchronous_Reset
+CSET underflow_flag=false
+CSET underflow_sense=Active_High
+CSET use_dout_reset=true
+CSET use_embedded_registers=false
+CSET use_extra_logic=false
+CSET valid_flag=false
+CSET valid_sense=Active_High
+CSET write_acknowledge_flag=false
+CSET write_acknowledge_sense=Active_High
+CSET write_clock_frequency=1
+CSET write_data_count=false
+CSET write_data_count_width=4
+# END Parameters
+GENERATE
+# CRC: 6bcb05e1
+
diff --git a/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_fifo_generator_v4_3_xst_1.ngc_xst.xrpt b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_fifo_generator_v4_3_xst_1.ngc_xst.xrpt
new file mode 100644
index 000000000..544bda31d
--- /dev/null
+++ b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_fifo_generator_v4_3_xst_1.ngc_xst.xrpt
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<document OS="lin64" product="ISE" version="10.1.03">
+
+ <!--The data in this file is primarily intended for consumption by Xilinx tools.
+ The structure and the elements are likely to change over the next few releases.
+ This means code written to parse this file will need to be revisited each subsequent release.-->
+
+ <application stringID="Xst" timeStamp="Tue May 11 13:27:35 2010">
+ <section stringID="XST_HDL_SYNTHESIS_REPORT">
+ <item dataType="int" stringID="XST_RAMS" value="1"></item>
+ <item dataType="int" stringID="XST_COUNTERS" value="2">
+ <item dataType="int" stringID="XST_4BIT_UP_COUNTER" value="2"/>
+ </item>
+ <item dataType="int" stringID="XST_REGISTERS" value="30">
+ <item dataType="int" stringID="XST_1BIT_REGISTER" value="15"/>
+ <item dataType="int" stringID="XST_2BIT_REGISTER" value="1"/>
+ <item dataType="int" stringID="XST_3BIT_REGISTER" value="1"/>
+ <item dataType="int" stringID="XST_4BIT_REGISTER" value="11"/>
+ </item>
+ <item dataType="int" stringID="XST_XORS" value="28">
+ <item dataType="int" stringID="XST_1BIT_XOR2" value="28"/>
+ </item>
+ </section>
+ <section stringID="XST_ADVANCED_HDL_SYNTHESIS_REPORT">
+ <item dataType="int" stringID="XST_FSMS" value="1"/>
+ <item dataType="int" stringID="XST_RAMS" value="1"></item>
+ <item dataType="int" stringID="XST_COUNTERS" value="2">
+ <item dataType="int" stringID="XST_4BIT_UP_COUNTER" value="2"/>
+ </item>
+ <item dataType="int" stringID="XST_REGISTERS" value="144">
+ <item dataType="int" stringID="XST_FLIPFLOPS" value="144"/>
+ </item>
+ <item dataType="int" stringID="XST_XORS" value="28">
+ <item dataType="int" stringID="XST_1BIT_XOR2" value="28"/>
+ </item>
+ </section>
+ <section stringID="XST_FINAL_REGISTER_REPORT">
+ <item dataType="int" stringID="XST_REGISTERS" value="150">
+ <item dataType="int" stringID="XST_FLIPFLOPS" value="150"/>
+ </item>
+ </section>
+ <section stringID="XST_PARTITION_REPORT">
+ <section stringID="XST_PARTITION_IMPLEMENTATION_STATUS">
+ <section stringID="XST_NO_PARTITIONS_WERE_FOUND_IN_THIS_DESIGN"/>
+ </section>
+ </section>
+ <section stringID="XST_FINAL_REPORT">
+ <section stringID="XST_FINAL_RESULTS">
+ <item stringID="XST_TOP_LEVEL_OUTPUT_FILE_NAME" value="/home/matt/coregen/tmp/_cg/fifo_xlnx_16x40_2clk_fifo_generator_v4_3_xst_1.ngc"/>
+ <item stringID="XST_OUTPUT_FORMAT" value="NGC"/>
+ <item stringID="XST_OPTIMIZATION_GOAL" value="SPEED"/>
+ <item stringID="XST_KEEP_HIERARCHY" value="no"/>
+ </section>
+ <section stringID="XST_DESIGN_STATISTICS">
+ <item stringID="XST_IOS" value="140"/>
+ </section>
+ <section stringID="XST_CELL_USAGE">
+ <item dataType="int" stringID="XST_BELS" value="42">
+ <item dataType="int" stringID="XST_GND" value="1"/>
+ <item dataType="int" stringID="XST_INV" value="2"/>
+ <item dataType="int" stringID="XST_LUT2" value="14"/>
+ <item dataType="int" stringID="XST_LUT3" value="7"/>
+ <item dataType="int" stringID="XST_LUT4" value="16"/>
+ <item dataType="int" stringID="XST_LUT4L" value="2"/>
+ </item>
+ <item dataType="int" stringID="XST_FLIPFLOPSLATCHES" value="150">
+ <item dataType="int" stringID="XST_FD" value="4"/>
+ <item dataType="int" stringID="XST_FDC" value="34"/>
+ <item dataType="int" stringID="XST_FDCE" value="97"/>
+ <item dataType="int" stringID="XST_FDP" value="10"/>
+ <item dataType="int" stringID="XST_FDPE" value="5"/>
+ </item>
+ <item dataType="int" stringID="XST_RAMS" value="40">
+ <item dataType="int" stringID="XST_RAM16X1D" value="40"/>
+ </item>
+ </section>
+ </section>
+ <section stringID="XST_DEVICE_UTILIZATION_SUMMARY">
+ <item stringID="XST_SELECTED_DEVICE" value="3s2000fg456-5"/>
+ <item AVAILABLE="20480" dataType="int" stringID="XST_NUMBER_OF_SLICES" value="127"/>
+ <item AVAILABLE="40960" dataType="int" stringID="XST_NUMBER_OF_SLICE_FLIP_FLOPS" value="150"/>
+ <item AVAILABLE="40960" dataType="int" stringID="XST_NUMBER_OF_4_INPUT_LUTS" value="121"/>
+ <item dataType="int" stringID="XST_NUMBER_USED_AS_LOGIC" value="41"/>
+ <item dataType="int" stringID="XST_NUMBER_USED_AS_RAMS" value="80"/>
+ <item dataType="int" stringID="XST_NUMBER_OF_IOS" value="140"/>
+ <item AVAILABLE="333" dataType="int" stringID="XST_NUMBER_OF_BONDED_IOBS" value="0"/>
+ </section>
+ <section stringID="XST_PARTITION_RESOURCE_SUMMARY">
+ <section stringID="XST_NO_PARTITIONS_WERE_FOUND_IN_THIS_DESIGN"/>
+ </section>
+ <section stringID="XST_ERRORS_STATISTICS">
+ <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_ERRORS" value="0"/>
+ <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_WARNINGS" value="74"/>
+ <item dataType="int" filtered="0" stringID="XST_NUMBER_OF_INFOS" value="9"/>
+ </section>
+ </application>
+
+</document>
diff --git a/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_flist.txt b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_flist.txt
new file mode 100644
index 000000000..c38f4e991
--- /dev/null
+++ b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_flist.txt
@@ -0,0 +1,8 @@
+# Output products list for <fifo_xlnx_16x40_2clk>
+fifo_xlnx_16x40_2clk.ngc
+fifo_xlnx_16x40_2clk.v
+fifo_xlnx_16x40_2clk.veo
+fifo_xlnx_16x40_2clk.xco
+fifo_xlnx_16x40_2clk_fifo_generator_v4_3_xst_1.ngc_xst.xrpt
+fifo_xlnx_16x40_2clk_flist.txt
+fifo_xlnx_16x40_2clk_xmdf.tcl
diff --git a/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_readme.txt b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_readme.txt
new file mode 100644
index 000000000..bbcd4af79
--- /dev/null
+++ b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_readme.txt
@@ -0,0 +1,39 @@
+The following files were generated for 'fifo_xlnx_16x40_2clk' in directory
+/home/matt/sourcerepo/fpga/usrp2/coregen/:
+
+fifo_xlnx_16x40_2clk.ngc:
+ Binary Xilinx implementation netlist file containing the information
+ required to implement the module in a Xilinx (R) FPGA.
+
+fifo_xlnx_16x40_2clk.v:
+ Verilog wrapper file provided to support functional simulation.
+ This file contains simulation model customization data that is
+ passed to a parameterized simulation model for the core.
+
+fifo_xlnx_16x40_2clk.veo:
+ VEO template file containing code that can be used as a model for
+ instantiating a CORE Generator module in a Verilog design.
+
+fifo_xlnx_16x40_2clk.xco:
+ CORE Generator input file containing the parameters used to
+ regenerate a core.
+
+fifo_xlnx_16x40_2clk_fifo_generator_v4_3_xst_1.ngc_xst.xrpt:
+ Please see the core data sheet.
+
+fifo_xlnx_16x40_2clk_flist.txt:
+ Text file listing all of the output files produced when a customized
+ core was generated in the CORE Generator.
+
+fifo_xlnx_16x40_2clk_readme.txt:
+ Text file indicating the files generated and how they are used.
+
+fifo_xlnx_16x40_2clk_xmdf.tcl:
+ ISE Project Navigator interface file. ISE uses this file to determine
+ how the files output by CORE Generator for the core can be integrated
+ into your ISE project.
+
+
+Please see the Xilinx CORE Generator online help for further details on
+generated files and how to use them.
+
diff --git a/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_xmdf.tcl b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_xmdf.tcl
new file mode 100644
index 000000000..2b4824831
--- /dev/null
+++ b/fpga/usrp2/coregen/fifo_xlnx_16x40_2clk_xmdf.tcl
@@ -0,0 +1,68 @@
+# The package naming convention is <core_name>_xmdf
+package provide fifo_xlnx_16x40_2clk_xmdf 1.0
+
+# This includes some utilities that support common XMDF operations
+package require utilities_xmdf
+
+# Define a namespace for this package. The name of the name space
+# is <core_name>_xmdf
+namespace eval ::fifo_xlnx_16x40_2clk_xmdf {
+# Use this to define any statics
+}
+
+# Function called by client to rebuild the params and port arrays
+# Optional when the use context does not require the param or ports
+# arrays to be available.
+proc ::fifo_xlnx_16x40_2clk_xmdf::xmdfInit { instance } {
+# Variable containg name of library into which module is compiled
+# Recommendation: <module_name>
+# Required
+utilities_xmdf::xmdfSetData $instance Module Attributes Name fifo_xlnx_16x40_2clk
+}
+# ::fifo_xlnx_16x40_2clk_xmdf::xmdfInit
+
+# Function called by client to fill in all the xmdf* data variables
+# based on the current settings of the parameters
+proc ::fifo_xlnx_16x40_2clk_xmdf::xmdfApplyParams { instance } {
+
+set fcount 0
+# Array containing libraries that are assumed to exist
+# Examples include unisim and xilinxcorelib
+# Optional
+# In this example, we assume that the unisim library will
+# be magically
+# available to the simulation and synthesis tool
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type logical_library
+utilities_xmdf::xmdfSetData $instance FileSet $fcount logical_library unisim
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path fifo_xlnx_16x40_2clk.ngc
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type ngc
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path fifo_xlnx_16x40_2clk.v
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type verilog
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path fifo_xlnx_16x40_2clk.veo
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type verilog_template
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path fifo_xlnx_16x40_2clk.xco
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type coregen_ip
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path fifo_xlnx_16x40_2clk_fifo_generator_v4_3_xst_1.ngc_xst.xrpt
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type AnyView
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount relative_path fifo_xlnx_16x40_2clk_xmdf.tcl
+utilities_xmdf::xmdfSetData $instance FileSet $fcount type AnyView
+incr fcount
+
+utilities_xmdf::xmdfSetData $instance FileSet $fcount associated_module fifo_xlnx_16x40_2clk
+incr fcount
+
+}
+
+# ::gen_comp_name_xmdf::xmdfApplyParams
diff --git a/fpga/usrp2/sdr_lib/cordic_z24.v b/fpga/usrp2/sdr_lib/cordic_z24.v
index cf668d5ec..97b7beaf7 100644
--- a/fpga/usrp2/sdr_lib/cordic_z24.v
+++ b/fpga/usrp2/sdr_lib/cordic_z24.v
@@ -45,30 +45,30 @@ module cordic_z24(clock, reset, enable, xi, yi, zi, xo, yo, zo );
// see gen_cordic_consts.py
// constants for 24 bit wide phase
- localparam c00 = 24'd2097152;
- localparam c01 = 24'd1238021;
- localparam c02 = 24'd654136;
- localparam c03 = 24'd332050;
- localparam c04 = 24'd166669;
- localparam c05 = 24'd83416;
- localparam c06 = 24'd41718;
- localparam c07 = 24'd20860;
- localparam c08 = 24'd10430;
- localparam c09 = 24'd5215;
- localparam c10 = 24'd2608;
- localparam c11 = 24'd1304;
- localparam c12 = 24'd652;
- localparam c13 = 24'd326;
- localparam c14 = 24'd163;
- localparam c15 = 24'd81;
- localparam c16 = 24'd41;
- localparam c17 = 24'd20;
- localparam c18 = 24'd10;
- localparam c19 = 24'd5;
- localparam c20 = 24'd3;
- localparam c21 = 24'd1;
- localparam c22 = 24'd1;
- localparam c23 = 24'd0;
+ localparam c00 = 23'd2097152;
+ localparam c01 = 23'd1238021;
+ localparam c02 = 23'd654136;
+ localparam c03 = 23'd332050;
+ localparam c04 = 23'd166669;
+ localparam c05 = 23'd83416;
+ localparam c06 = 23'd41718;
+ localparam c07 = 23'd20860;
+ localparam c08 = 23'd10430;
+ localparam c09 = 23'd5215;
+ localparam c10 = 23'd2608;
+ localparam c11 = 23'd1304;
+ localparam c12 = 23'd652;
+ localparam c13 = 23'd326;
+ localparam c14 = 23'd163;
+ localparam c15 = 23'd81;
+ localparam c16 = 23'd41;
+ localparam c17 = 23'd20;
+ localparam c18 = 23'd10;
+ localparam c19 = 23'd5;
+ localparam c20 = 23'd3;
+ localparam c21 = 23'd1;
+ localparam c22 = 23'd1;
+ localparam c23 = 23'd0;
always @(posedge clock)
if(reset)
diff --git a/fpga/usrp2/sdr_lib/dsp_core_rx.v b/fpga/usrp2/sdr_lib/dsp_core_rx.v
index 2ac429630..1e689fc7f 100644
--- a/fpga/usrp2/sdr_lib/dsp_core_rx.v
+++ b/fpga/usrp2/sdr_lib/dsp_core_rx.v
@@ -32,6 +32,10 @@ module dsp_core_rx
wire strobe_cic, strobe_hb1, strobe_hb2;
wire enable_hb1, enable_hb2;
wire [7:0] cic_decim_rate;
+
+ wire [31:10] UNUSED_1;
+ wire [31:4] UNUSED_2;
+ wire [31:2] UNUSED_3;
setting_reg #(.my_addr(BASE+0)) sr_0
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
@@ -43,7 +47,7 @@ module dsp_core_rx
setting_reg #(.my_addr(BASE+2)) sr_2
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
- .in(set_data),.out({enable_hb1, enable_hb2, cic_decim_rate}),.changed());
+ .in(set_data),.out({UNUSED_1, enable_hb1, enable_hb2, cic_decim_rate}),.changed());
rx_dcoffset #(.WIDTH(14),.ADDR(BASE+3)) rx_dcoffset_a
(.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
@@ -56,12 +60,12 @@ module dsp_core_rx
wire [3:0] muxctrl;
setting_reg #(.my_addr(BASE+5)) sr_8
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
- .in(set_data),.out(muxctrl),.changed());
+ .in(set_data),.out({UNUSED_2,muxctrl}),.changed());
wire [1:0] gpio_ena;
setting_reg #(.my_addr(BASE+6)) sr_9
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
- .in(set_data),.out(gpio_ena),.changed());
+ .in(set_data),.out({UNUSED_3,gpio_ena}),.changed());
// The TVRX connects to what is called adc_b, thus A and B are
// swapped throughout the design.
diff --git a/fpga/usrp2/top/u2_core/u2_core.v b/fpga/usrp2/top/u2_core/u2_core.v
index cd0199005..b57e4f127 100644
--- a/fpga/usrp2/top/u2_core/u2_core.v
+++ b/fpga/usrp2/top/u2_core/u2_core.v
@@ -154,9 +154,9 @@ module u2_core
localparam SERDES_TX_FIFOSIZE = 9;
localparam SERDES_RX_FIFOSIZE = 9; // RX currently doesn't use a fifo?
- wire [7:0] set_addr;
- wire [31:0] set_data;
- wire set_stb;
+ wire [7:0] set_addr, set_addr_dsp;
+ wire [31:0] set_data, set_data_dsp;
+ wire set_stb, set_stb_dsp;
wire ram_loader_done;
wire ram_loader_rst, wb_rst, dsp_rst;
@@ -359,7 +359,7 @@ module u2_core
.wb_dat_o(s1_dat_i),.wb_ack_o(s1_ack),.wb_err_o(),.wb_rty_o(),
.stream_clk(dsp_clk), .stream_rst(dsp_rst),
- .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
+ .set_stb(set_stb_dsp), .set_addr(set_addr_dsp), .set_data(set_data_dsp),
.status(status),.sys_int_o(buffer_int),
.s0(status_b0),.s1(status_b1),.s2(status_b2),.s3(status_b3),
@@ -454,7 +454,7 @@ module u2_core
udp_wrapper #(.BASE(SR_UDP_SM)) udp_wrapper
(.clk(dsp_clk), .reset(dsp_rst), .clear(0),
- .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
+ .set_stb(set_stb_dsp), .set_addr(set_addr_dsp), .set_data(set_data_dsp),
.rx_f19_data(rx_f19_data), .rx_f19_src_rdy_i(rx_f19_src_rdy), .rx_f19_dst_rdy_o(rx_f19_dst_rdy),
.tx_f19_data(tx_f19_data), .tx_f19_src_rdy_o(tx_f19_src_rdy), .tx_f19_dst_rdy_i(tx_f19_dst_rdy),
.rx_f36_data(udp_rx_data), .rx_f36_src_rdy_o(udp_rx_src_rdy), .rx_f36_dst_rdy_i(udp_rx_dst_rdy),
@@ -476,10 +476,14 @@ module u2_core
settings_bus settings_bus
(.wb_clk(wb_clk),.wb_rst(wb_rst),.wb_adr_i(s7_adr),.wb_dat_i(s7_dat_o),
.wb_stb_i(s7_stb),.wb_we_i(s7_we),.wb_ack_o(s7_ack),
- .sys_clk(dsp_clk),.strobe(set_stb),.addr(set_addr),.data(set_data));
+ .strobe(set_stb),.addr(set_addr),.data(set_data));
assign s7_dat_i = 32'd0;
+ settings_bus_crossclock settings_bus_crossclock
+ (.clk_i(wb_clk), .rst_i(wb_rst), .set_stb_i(set_stb), .set_addr_i(set_addr), .set_data_i(set_data),
+ .clk_o(dsp_clk), .rst_o(dsp_rst), .set_stb_o(set_stb_dsp), .set_addr_o(set_addr_dsp), .set_data_o(set_data_dsp));
+
// Output control lines
wire [7:0] clock_outs, serdes_outs, adc_outs;
assign {clock_ready, clk_en[1:0], clk_sel[1:0]} = clock_outs[4:0];
@@ -600,7 +604,7 @@ module u2_core
dsp_core_rx #(.BASE(SR_RX_DSP)) dsp_core_rx
(.clk(dsp_clk),.rst(dsp_rst),
- .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
+ .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
.adc_a(adc_a),.adc_ovf_a(adc_ovf_a),.adc_b(adc_b),.adc_ovf_b(adc_ovf_b),
.sample(sample_rx), .run(run_rx_d1), .strobe(strobe_rx),
.debug(debug_rx_dsp) );
@@ -609,7 +613,7 @@ module u2_core
vita_rx_control #(.BASE(SR_RX_CTRL), .WIDTH(32)) vita_rx_control
(.clk(dsp_clk), .reset(dsp_rst), .clear(0),
- .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
+ .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
.vita_time(vita_time), .overrun(overrun),
.sample(sample_rx), .run(run_rx), .strobe(strobe_rx),
.sample_fifo_o(rx_data), .sample_fifo_dst_rdy_i(rx_dst_rdy), .sample_fifo_src_rdy_o(rx_src_rdy),
@@ -619,7 +623,7 @@ module u2_core
vita_rx_framer #(.BASE(SR_RX_CTRL), .MAXCHAN(1)) vita_rx_framer
(.clk(dsp_clk), .reset(dsp_rst), .clear(0),
- .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
+ .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
.sample_fifo_i(rx_data), .sample_fifo_dst_rdy_o(rx_dst_rdy), .sample_fifo_src_rdy_i(rx_src_rdy),
.data_o(rx1_data), .dst_rdy_i(rx1_dst_rdy), .src_rdy_o(rx1_src_rdy),
.fifo_occupied(), .fifo_full(), .fifo_empty(),
@@ -646,14 +650,14 @@ module u2_core
vita_tx_deframer #(.BASE(SR_TX_CTRL), .MAXCHAN(1)) vita_tx_deframer
(.clk(dsp_clk), .reset(dsp_rst), .clear(0),
- .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
+ .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
.data_i(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy),
.sample_fifo_o(tx1_data), .sample_fifo_src_rdy_o(tx1_src_rdy), .sample_fifo_dst_rdy_i(tx1_dst_rdy),
.debug(debug_vtd) );
vita_tx_control #(.BASE(SR_TX_CTRL), .WIDTH(32)) vita_tx_control
(.clk(dsp_clk), .reset(dsp_rst), .clear(0),
- .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
+ .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
.vita_time(vita_time),.underrun(underrun),
.sample_fifo_i(tx1_data), .sample_fifo_src_rdy_i(tx1_src_rdy), .sample_fifo_dst_rdy_o(tx1_dst_rdy),
.sample(sample_tx), .run(run_tx), .strobe(strobe_tx),
@@ -663,7 +667,7 @@ module u2_core
dsp_core_tx #(.BASE(SR_TX_DSP)) dsp_core_tx
(.clk(dsp_clk),.rst(dsp_rst),
- .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
+ .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp),
.sample(sample_tx), .run(run_tx), .strobe(strobe_tx),
.dac_a(dac_a),.dac_b(dac_b),
.debug(debug_tx_dsp) );
@@ -720,7 +724,7 @@ module u2_core
// VITA Timing
time_64bit #(.TICKS_PER_SEC(32'd100000000),.BASE(SR_TIME64)) time_64bit
- (.clk(dsp_clk), .rst(dsp_rst), .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
+ (.clk(dsp_clk), .rst(dsp_rst), .set_stb(set_stb_dsp), .set_addr(set_addr_dsp), .set_data(set_data_dsp),
.pps(pps_in), .vita_time(vita_time), .pps_int(pps_int));
// /////////////////////////////////////////////////////////////////////////////////////////
diff --git a/fpga/usrp2/top/u2_rev1/.gitignore b/fpga/usrp2/top/u2_rev1/.gitignore
deleted file mode 100644
index de5b50277..000000000
--- a/fpga/usrp2/top/u2_rev1/.gitignore
+++ /dev/null
@@ -1,52 +0,0 @@
-/templates
-/netgen
-/_ngo
-/_xmsgs
-/_pace.ucf
-/*.cmd
-/*.ibs
-/*.lfp
-/*.mfp
-/*.bit
-/*.bin
-/*.stx
-/*.par
-/*.unroutes
-/*.ntrc_log
-/*.ngr
-/*.mrp
-/*.html
-/*.lso
-/*.twr
-/*.bld
-/*.ncd
-/*.txt
-/*.cmd_log
-/*.drc
-/*.map
-/*.twr
-/*.xml
-/*.syr
-/*.ngm
-/*.xst
-/*.csv
-/*.html
-/*.lock
-/*.ncd
-/*.twx
-/*.ise_ISE_Backup
-/*.xml
-/*.ut
-/*.xpi
-/*.ngd
-/*.ncd
-/*.pad
-/*.bgn
-/*.ngc
-/*.pcf
-/*.ngd
-/xst
-/*.log
-/*.rpt
-/*.cel
-/*.restore
diff --git a/fpga/usrp2/top/u2_rev1/Makefile b/fpga/usrp2/top/u2_rev1/Makefile
deleted file mode 100644
index b3245d883..000000000
--- a/fpga/usrp2/top/u2_rev1/Makefile
+++ /dev/null
@@ -1,129 +0,0 @@
-FILENAME=u2_fpga_top
-PARTNUM=xc3s1500-5fg456
-
-all: project command xst ngd ncd ncd2 bit
-
-xst:
- xst -ifn ${FILENAME}.cmd -ofn xst.log
-
-ngd:
- ngdbuild -nt timestamp -p ${PARTNUM} ${FILENAME}
-
-ncd:
- rm -rf ${FILENAME}.ncd
- map -detail -cm speed -k 8 -retiming on -equivalent_register_removal on -timing -ol high -pr b -p ${PARTNUM} ${FILENAME}.ngd -o ${FILENAME}.ncd ${FILENAME}.pcf
-
-# Place and route ncd file into new ncd file
-ncd2:
- par -ol high -xe n -w ${FILENAME}.ncd ${FILENAME} ${FILENAME}.pcf
-
-bit:
- bitgen -w ${FILENAME}.ncd -b ${FILENAME}.bit
-
-clean:
- @rm -rf ${FILENAME}.ngc *.lst *.bit *.lso *.xst *.stx *.syr \
- *.ngr *.cmd_log _ngc _xmsgs xst *.html *.srp \
- *.blc *.bld *.ise_ISE_Backup *~ \
- *.pad *.ngm *.ngd *.par *.pcf *.unroutes \
- *.xpi *.bgn *.drc *.bin *.mrp *.csv *.txt \
- *.rbt *.ncd ${FILENAME} *_cg templates/ tmp/ \
- output.dat coregen.log *.ngo *.log ${FILENAME}.map \
- ${FILENAME}_summary.xml ${FILENAME}_usage.xml ${FILENAME}.twr
-
-command:
- rm -rf ${FILENAME}.cmd
- @echo "identification" >> ${FILENAME}.cmd
- @echo "status" >> ${FILENAME}.cmd
- @echo "time short" >> ${FILENAME}.cmd
- @echo "memory on" >> ${FILENAME}.cmd
- @echo "run " >> ${FILENAME}.cmd
- @echo "-top ${FILENAME}" >> ${FILENAME}.cmd
- @echo "-ifn ${FILENAME}.prj" >> ${FILENAME}.cmd
- @echo "-ifmt Verilog " >> ${FILENAME}.cmd
- @echo "-ofn ${FILENAME} " >> ${FILENAME}.cmd
- @echo "-p ${PARTNUM}" >> ${FILENAME}.cmd
- @echo "-bufg 6" >> ${FILENAME}.cmd
- @echo "-vlgincdir { ../../opencores/i2c/rtl/verilog ../../eth/rtl/verilog/ ../../opencores/spi/rtl/verilog}" >> ${FILENAME}.cmd
-
-project:
- rm -f ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/TECH/duram.v" ' >> ${FILENAME}.prj
- @echo '`include "../../sdr_lib/sign_extend.v" ' >> ${FILENAME}.prj
- @echo '`include "../../sdr_lib/cordic_stage.v" ' >> ${FILENAME}.prj
- @echo '`include "../../sdr_lib/cic_int_shifter.v" ' >> ${FILENAME}.prj
- @echo '`include "../../sdr_lib/cic_dec_shifter.v" ' >> ${FILENAME}.prj
- @echo '`include "../../opencores/i2c/rtl/verilog/i2c_master_bit_ctrl.v" ' >> ${FILENAME}.prj
- @echo '`include "../../opencores/aemb/rtl/verilog/aeMB_regfile.v" ' >> ${FILENAME}.prj
- @echo '`include "../../opencores/aemb/rtl/verilog/aeMB_fetch.v" ' >> ${FILENAME}.prj
- @echo '`include "../../opencores/aemb/rtl/verilog/aeMB_decode.v" ' >> ${FILENAME}.prj
- @echo '`include "../../opencores/aemb/rtl/verilog/aeMB_control.v" ' >> ${FILENAME}.prj
- @echo '`include "../../opencores/aemb/rtl/verilog/aeMB_aslu.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/miim/eth_shiftreg.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/miim/eth_outputcontrol.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/miim/eth_clockgen.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/TECH/eth_clk_switch.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/TECH/eth_clk_div2.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/Reg_int.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/RMON/RMON_dpram.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/RMON/RMON_ctrl.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/RMON/RMON_addr_gen.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/MAC_tx/flow_ctrl.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/MAC_tx/Ramdon_gen.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/MAC_tx/MAC_tx_ctrl.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/MAC_tx/MAC_tx_addr_add.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/MAC_tx/MAC_tx_FF.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/MAC_tx/CRC_gen.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/MAC_rx/MAC_rx_ctrl.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/MAC_rx/MAC_rx_add_chk.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/MAC_rx/MAC_rx_FF.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/MAC_rx/CRC_chk.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/MAC_rx/Broadcast_filter.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/ram_2port.v" ' >> ${FILENAME}.prj
- @echo '`include "../../sdr_lib/cordic.v" ' >> ${FILENAME}.prj
- @echo '`include "../../sdr_lib/cic_interp.v" ' >> ${FILENAME}.prj
- @echo '`include "../../sdr_lib/cic_decim.v" ' >> ${FILENAME}.prj
- @echo '`include "../../opencores/spi/rtl/verilog/spi_shift.v" ' >> ${FILENAME}.prj
- @echo '`include "../../opencores/spi/rtl/verilog/spi_clgen.v" ' >> ${FILENAME}.prj
- @echo '`include "../../opencores/i2c/rtl/verilog/i2c_master_byte_ctrl.v" ' >> ${FILENAME}.prj
- @echo '`include "../../opencores/aemb/rtl/verilog/aeMB_core.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/eth_miim.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/RMON.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/Phy_int.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/MAC_tx.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/MAC_rx.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/Clk_ctrl.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/strobe_gen.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/ss_rcvr.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/shortfifo.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/setting_reg.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/mux8.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/mux4.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/longfifo.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/decoder_3_8.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/buffer_int.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/CRC16_D16.v" ' >> ${FILENAME}.prj
- @echo '`include "../../sdr_lib/tx_control.v" ' >> ${FILENAME}.prj
- @echo '`include "../../sdr_lib/rx_control.v" ' >> ${FILENAME}.prj
- @echo '`include "../../sdr_lib/dsp_core_tx.v" ' >> ${FILENAME}.prj
- @echo '`include "../../sdr_lib/dsp_core_rx.v" ' >> ${FILENAME}.prj
- @echo '`include "../../opencores/spi/rtl/verilog/spi_top.v" ' >> ${FILENAME}.prj
- @echo '`include "../../opencores/simple_pic/rtl/simple_pic.v" ' >> ${FILENAME}.prj
- @echo '`include "../../opencores/i2c/rtl/verilog/i2c_master_top.v" ' >> ${FILENAME}.prj
- @echo '`include "../../opencores/aemb/rtl/verilog/aeMB_core_BE.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/MAC_top.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/mac_txfifo_int.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/mac_rxfifo_int.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/wb_readback_mux.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/wb_1master.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/timer.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/system_control.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/settings_bus.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/serdes_tx.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/serdes_rx.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/ram_wb_harvard.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/ram_loader.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/nsgpio.v" ' >> ${FILENAME}.prj
- @echo '`include "../../control_lib/buffer_pool.v" ' >> ${FILENAME}.prj
- @echo '`include "../u2_basic/u2_basic.v" ' >> ${FILENAME}.prj
- @echo '`include "u2_fpga_top.v" ' >> ${FILENAME}.prj
- @echo '`include "../../eth/rtl/verilog/elastic_buffer.v" ' >> ${FILENAME}.prj
diff --git a/fpga/usrp2/top/u2_rev1/u2_fpga.ise b/fpga/usrp2/top/u2_rev1/u2_fpga.ise
deleted file mode 100644
index f90caf024..000000000
--- a/fpga/usrp2/top/u2_rev1/u2_fpga.ise
+++ /dev/null
Binary files differ
diff --git a/fpga/usrp2/top/u2_rev1/u2_fpga.ucf b/fpga/usrp2/top/u2_rev1/u2_fpga.ucf
deleted file mode 100755
index 5d2124819..000000000
--- a/fpga/usrp2/top/u2_rev1/u2_fpga.ucf
+++ /dev/null
@@ -1,341 +0,0 @@
-NET "adc_a[0]" LOC = "A14" ;
-NET "adc_a[10]" LOC = "D20" ;
-NET "adc_a[11]" LOC = "D19" ;
-NET "adc_a[12]" LOC = "D21" ;
-NET "adc_a[13]" LOC = "E18" ;
-NET "adc_a[1]" LOC = "B14" ;
-NET "adc_a[2]" LOC = "C13" ;
-NET "adc_a[3]" LOC = "D13" ;
-NET "adc_a[4]" LOC = "A13" ;
-NET "adc_a[5]" LOC = "B13" ;
-NET "adc_a[6]" LOC = "E12" ;
-NET "adc_a[7]" LOC = "C22" ;
-NET "adc_a[8]" LOC = "C20" ;
-NET "adc_a[9]" LOC = "C21" ;
-NET "adc_b[0]" LOC = "A12" ;
-NET "adc_b[10]" LOC = "D18" ;
-NET "adc_b[11]" LOC = "B18" ;
-NET "adc_b[12]" LOC = "D17" ;
-NET "adc_b[13]" LOC = "E17" ;
-NET "adc_b[1]" LOC = "E16" ;
-NET "adc_b[2]" LOC = "F12" ;
-NET "adc_b[3]" LOC = "F13" ;
-NET "adc_b[4]" LOC = "F16" ;
-NET "adc_b[5]" LOC = "F17" ;
-NET "adc_b[6]" LOC = "C19" ;
-NET "adc_b[7]" LOC = "B20" ;
-NET "adc_b[8]" LOC = "B19" ;
-NET "adc_b[9]" LOC = "C18" ;
-NET "clk_en[0]" LOC = "C4" ;
-NET "clk_en[1]" LOC = "D1" ;
-NET "clk_sel[0]" LOC = "C3" ;
-NET "clk_sel[1]" LOC = "C2" ;
-NET "dac_a[0]" LOC = "A5" ;
-NET "dac_a[10]" LOC = "L2" ;
-NET "dac_a[11]" LOC = "L4" ;
-NET "dac_a[12]" LOC = "L3" ;
-NET "dac_a[13]" LOC = "L6" ;
-NET "dac_a[14]" LOC = "L5" ;
-NET "dac_a[15]" LOC = "K2" ;
-NET "dac_a[1]" LOC = "B5" ;
-NET "dac_a[2]" LOC = "C5" ;
-NET "dac_a[3]" LOC = "D5" ;
-NET "dac_a[4]" LOC = "A4" ;
-NET "dac_a[5]" LOC = "B4" ;
-NET "dac_a[6]" LOC = "F6" ;
-NET "dac_a[7]" LOC = "D10" ;
-NET "dac_a[8]" LOC = "D9" ;
-NET "dac_a[9]" LOC = "A10" ;
-NET "dac_b[0]" LOC = "D11" ;
-NET "dac_b[10]" LOC = "F9" ;
-NET "dac_b[11]" LOC = "A8" ;
-NET "dac_b[12]" LOC = "B8" ;
-NET "dac_b[13]" LOC = "D7" ;
-NET "dac_b[14]" LOC = "E7" ;
-NET "dac_b[15]" LOC = "B6" ;
-NET "dac_b[1]" LOC = "E11" ;
-NET "dac_b[2]" LOC = "F11" ;
-NET "dac_b[3]" LOC = "B10" ;
-NET "dac_b[4]" LOC = "C10" ;
-NET "dac_b[5]" LOC = "E10" ;
-NET "dac_b[6]" LOC = "F10" ;
-NET "dac_b[7]" LOC = "A9" ;
-NET "dac_b[8]" LOC = "B9" ;
-NET "dac_b[9]" LOC = "E9" ;
-NET "debug[0]" LOC = "N5" ;
-NET "debug[10]" LOC = "R4" ;
-NET "debug[11]" LOC = "T3" ;
-NET "debug[12]" LOC = "U3" ;
-NET "debug[13]" LOC = "M2" ;
-NET "debug[14]" LOC = "M3" ;
-NET "debug[15]" LOC = "M4" ;
-NET "debug[16]" LOC = "M5" ;
-NET "debug[17]" LOC = "M6" ;
-NET "debug[18]" LOC = "N1" ;
-NET "debug[19]" LOC = "N2" ;
-NET "debug[1]" LOC = "N6" ;
-NET "debug[20]" LOC = "N3" ;
-NET "debug[21]" LOC = "T1" ;
-NET "debug[22]" LOC = "T2" ;
-NET "debug[23]" LOC = "U2" ;
-NET "debug[24]" LOC = "T4" ;
-NET "debug[25]" LOC = "U4" ;
-NET "debug[26]" LOC = "T5" ;
-NET "debug[27]" LOC = "T6" ;
-NET "debug[28]" LOC = "U5" ;
-NET "debug[29]" LOC = "V5" ;
-NET "debug[2]" LOC = "P1" ;
-NET "debug[30]" LOC = "W2" ;
-NET "debug[31]" LOC = "W3" ;
-NET "debug[3]" LOC = "P2" ;
-NET "debug[4]" LOC = "P4" ;
-NET "debug[5]" LOC = "P5" ;
-NET "debug[6]" LOC = "R1" ;
-NET "debug[7]" LOC = "R2" ;
-NET "debug[8]" LOC = "P6" ;
-NET "debug[9]" LOC = "R5" ;
-NET "debug_clk[0]" LOC = "N4" ;
-NET "debug_clk[1]" LOC = "M1" ;
-NET "GMII_RXD[0]" LOC = "AA15" ;
-NET "GMII_RXD[1]" LOC = "AB15" ;
-NET "GMII_RXD[2]" LOC = "U14" ;
-NET "GMII_RXD[3]" LOC = "V14" ;
-NET "GMII_RXD[4]" LOC = "U13" ;
-NET "GMII_RXD[5]" LOC = "V13" ;
-NET "GMII_RXD[6]" LOC = "Y13" ;
-NET "GMII_RXD[7]" LOC = "AA13" ;
-NET "GMII_TXD[0]" LOC = "W14" ;
-NET "GMII_TXD[1]" LOC = "AA20" ;
-NET "GMII_TXD[2]" LOC = "AB20" ;
-NET "GMII_TXD[3]" LOC = "Y18" ;
-NET "GMII_TXD[4]" LOC = "AA18" ;
-NET "GMII_TXD[5]" LOC = "AB18" ;
-NET "GMII_TXD[6]" LOC = "V17" ;
-NET "GMII_TXD[7]" LOC = "W17" ;
-NET "io_rx[0]" LOC = "L21" ;
-NET "io_rx[10]" LOC = "F21" ;
-NET "io_rx[11]" LOC = "F20" ;
-NET "io_rx[12]" LOC = "G19" ;
-NET "io_rx[13]" LOC = "G18" ;
-NET "io_rx[14]" LOC = "G17" ;
-NET "io_rx[15]" LOC = "E22" ;
-NET "io_rx[1]" LOC = "L20" ;
-NET "io_rx[2]" LOC = "L19" ;
-NET "io_rx[3]" LOC = "L18" ;
-NET "io_rx[4]" LOC = "L17" ;
-NET "io_rx[5]" LOC = "K22" ;
-NET "io_rx[6]" LOC = "K21" ;
-NET "io_rx[7]" LOC = "K20" ;
-NET "io_rx[8]" LOC = "G22" ;
-NET "io_rx[9]" LOC = "G21" ;
-NET "io_tx[0]" LOC = "K4" ;
-NET "io_tx[10]" LOC = "E1" ;
-NET "io_tx[11]" LOC = "E3" ;
-NET "io_tx[12]" LOC = "F4" ;
-NET "io_tx[13]" LOC = "D2" ;
-NET "io_tx[14]" LOC = "D4" ;
-NET "io_tx[15]" LOC = "E4" ;
-NET "io_tx[1]" LOC = "K3" ;
-NET "io_tx[2]" LOC = "G1" ;
-NET "io_tx[3]" LOC = "G5" ;
-NET "io_tx[4]" LOC = "H5" ;
-NET "io_tx[5]" LOC = "F3" ;
-NET "io_tx[6]" LOC = "F2" ;
-NET "io_tx[7]" LOC = "F5" ;
-NET "io_tx[8]" LOC = "G6" ;
-NET "io_tx[9]" LOC = "E2" ;
-NET "RAM_A[0]" LOC = "N22" ;
-NET "RAM_A[10]" LOC = "P18" ;
-NET "RAM_A[11]" LOC = "R19" ;
-NET "RAM_A[12]" LOC = "P19" ;
-NET "RAM_A[13]" LOC = "R21" ;
-NET "RAM_A[14]" LOC = "R22" ;
-NET "RAM_A[15]" LOC = "T19" ;
-NET "RAM_A[16]" LOC = "T20" ;
-NET "RAM_A[17]" LOC = "U20" ;
-NET "RAM_A[18]" LOC = "W19" ;
-NET "RAM_A[1]" LOC = "N20" ;
-NET "RAM_A[2]" LOC = "T21" ;
-NET "RAM_A[3]" LOC = "M22" ;
-NET "RAM_A[4]" LOC = "N19" ;
-NET "RAM_A[5]" LOC = "N17" ;
-NET "RAM_A[6]" LOC = "N18" ;
-NET "RAM_A[7]" LOC = "P21" ;
-NET "RAM_A[8]" LOC = "P22" ;
-NET "RAM_A[9]" LOC = "P17" ;
-NET "RAM_D[0]" LOC = "Y21" ;
-NET "RAM_D[10]" LOC = "V22" ;
-NET "RAM_D[11]" LOC = "V21" ;
-NET "RAM_D[12]" LOC = "T17" ;
-NET "RAM_D[13]" LOC = "U18" ;
-NET "RAM_D[14]" LOC = "U21" ;
-NET "RAM_D[15]" LOC = "R18" ;
-NET "RAM_D[16]" LOC = "T18" ;
-NET "RAM_D[17]" LOC = "T22" ;
-NET "RAM_D[1]" LOC = "Y20" ;
-NET "RAM_D[2]" LOC = "Y19" ;
-NET "RAM_D[3]" LOC = "W22" ;
-NET "RAM_D[4]" LOC = "Y22" ;
-NET "RAM_D[5]" LOC = "V19" ;
-NET "RAM_D[6]" LOC = "W21" ;
-NET "RAM_D[7]" LOC = "W20" ;
-NET "RAM_D[8]" LOC = "U19" ;
-NET "RAM_D[9]" LOC = "V20" ;
-NET "ser_r[0]" LOC = "AB10" ;
-NET "ser_r[10]" LOC = "W10" ;
-NET "ser_r[11]" LOC = "Y1" ;
-NET "ser_r[12]" LOC = "Y3" ;
-NET "ser_r[13]" LOC = "Y2" ;
-NET "ser_r[14]" LOC = "W4" ;
-NET "ser_r[15]" LOC = "W1" ;
-NET "ser_r[1]" LOC = "AA10" ;
-NET "ser_r[2]" LOC = "U9" ;
-NET "ser_r[3]" LOC = "U6" ;
-NET "ser_r[4]" LOC = "AB11" ;
-NET "ser_r[5]" LOC = "Y7" ;
-NET "ser_r[6]" LOC = "W7" ;
-NET "ser_r[7]" LOC = "AB7" ;
-NET "ser_r[8]" LOC = "AA7" ;
-NET "ser_r[9]" LOC = "W9" ;
-NET "ser_t[0]" LOC = "V7" ;
-NET "ser_t[10]" LOC = "AA6" ;
-NET "ser_t[11]" LOC = "Y6" ;
-NET "ser_t[12]" LOC = "W8" ;
-NET "ser_t[13]" LOC = "V8" ;
-NET "ser_t[14]" LOC = "AB8" ;
-NET "ser_t[15]" LOC = "AA8" ;
-NET "ser_t[1]" LOC = "V10" ;
-NET "ser_t[2]" LOC = "AB4" ;
-NET "ser_t[3]" LOC = "AA4" ;
-NET "ser_t[4]" LOC = "Y5" ;
-NET "ser_t[5]" LOC = "W5" ;
-NET "ser_t[6]" LOC = "AB5" ;
-NET "ser_t[7]" LOC = "AA5" ;
-NET "ser_t[8]" LOC = "W6" ;
-NET "ser_t[9]" LOC = "V6" ;
-NET "clk_muxed" TNM_NET = "clk_muxed";
-TIMESPEC "TS_clk_muxed" = PERIOD "clk_muxed" 10 ns HIGH 50 %;
-NET "clk_to_mac" TNM_NET = "clk_to_mac";
-TIMESPEC "TS_clk_to_mac" = PERIOD "clk_to_mac" 8 ns HIGH 50 %;
-NET "cpld_clk" TNM_NET = "cpld_clk";
-TIMESPEC "TS_cpld_clk" = PERIOD "cpld_clk" 40 ns HIGH 50 %;
-NET "GMII_RX_CLK" TNM_NET = "GMII_RX_CLK";
-TIMESPEC "TS_GMII_RX_CLK" = PERIOD "GMII_RX_CLK" 8 ns HIGH 50 %;
-NET "ser_rx_clk" TNM_NET = "ser_rx_clk";
-TIMESPEC "TS_ser_rx_clk" = PERIOD "ser_rx_clk" 10 ns HIGH 50 %;
-#PACE: Start of Constraints generated by PACE
-
-#PACE: Start of PACE I/O Pin Assignments
-NET "adc_oen_a" LOC = "E19" ;
-NET "adc_oen_b" LOC = "C17" ;
-NET "adc_ovf_a" LOC = "F18" ;
-NET "adc_ovf_b" LOC = "B17" ;
-NET "adc_pdn_a" LOC = "E20" ;
-NET "adc_pdn_b" LOC = "D15" ;
-NET "clk_fpga_n" LOC = "B11" ;
-NET "clk_fpga_p" LOC = "A11" ;
-NET "clk_func" LOC = "C12" ;
-NET "clk_status" LOC = "B12" ;
-NET "clk_to_mac" LOC = "AB12" ;
-NET "cpld_clk" LOC = "AB14" ;
-NET "cpld_din" LOC = "AA14" ;
-NET "cpld_done" LOC = "V12" ;
-NET "cpld_mode" LOC = "U12" ;
-NET "cpld_start" LOC = "AA9" ;
-NET "exp_pps_in_n" LOC = "V4" ;
-NET "exp_pps_in_p" LOC = "V3" ;
-NET "exp_pps_out_n" LOC = "V2" ;
-NET "exp_pps_out_p" LOC = "V1" ;
-NET "GMII_COL" LOC = "U16" ;
-NET "GMII_CRS" LOC = "U17" ;
-NET "GMII_GTX_CLK" LOC = "AA17" | IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "GMII_RX_CLK" LOC = "W16" ;
-NET "GMII_RX_DV" LOC = "AB16" ;
-NET "GMII_RX_ER" LOC = "AA16" ;
-NET "GMII_TX_CLK" LOC = "W13" ;
-NET "GMII_TX_EN" LOC = "Y17" | IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "GMII_TX_ER" LOC = "V16" | IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "GMII_TXD<0>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "GMII_TXD<1>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "GMII_TXD<2>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "GMII_TXD<3>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "GMII_TXD<4>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "GMII_TXD<5>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "GMII_TXD<6>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "GMII_TXD<7>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "led1" LOC = "V11" ;
-NET "led2" LOC = "Y12" ;
-NET "MDC" LOC = "V18" ;
-NET "MDIO" LOC = "Y16" | PULLUP ;
-NET "PHY_CLK" LOC = "V15" ;
-NET "PHY_INTn" LOC = "AB13" ;
-NET "PHY_RESETn" LOC = "AA19" ;
-NET "pps_in" LOC = "Y11" ;
-NET "RAM_CE1n" LOC = "N21" ;
-NET "RAM_CENn" LOC = "M18" ;
-NET "RAM_CLK" LOC = "M17" ;
-NET "RAM_LDn" LOC = "M21" ;
-NET "RAM_OEn" LOC = "M19" ;
-NET "RAM_WEn" LOC = "M20" ;
-NET "SCL" LOC = "A7" ;
-NET "SCL_force" LOC = "E8" ;
-NET "sclk" LOC = "K5" ;
-NET "sclk_rx_adc" LOC = "J17" ;
-NET "sclk_rx_dac" LOC = "J19" ;
-NET "sclk_rx_db" LOC = "F19" ;
-NET "sclk_tx_adc" LOC = "H1" ;
-NET "sclk_tx_dac" LOC = "J5" ;
-NET "sclk_tx_db" LOC = "D3" ;
-NET "SDA" LOC = "D8" ;
-NET "SDA_force" LOC = "C11" ;
-NET "sdi" LOC = "J1" ;
-NET "sdi_rx_adc" LOC = "H22" ;
-NET "sdi_rx_dac" LOC = "J21" ;
-NET "sdi_rx_db" LOC = "H19" ;
-NET "sdi_tx_adc" LOC = "J4" ;
-NET "sdi_tx_dac" LOC = "J6" ;
-NET "sdi_tx_db" LOC = "G4" ;
-NET "sdo" LOC = "J2" ;
-NET "sdo_rx_adc" LOC = "H21" ;
-NET "sdo_rx_db" LOC = "G20" ;
-NET "sdo_tx_adc" LOC = "H2" ;
-NET "sdo_tx_db" LOC = "G3" ;
-NET "sen_clk" LOC = "K6" ;
-NET "sen_dac" LOC = "L1" ;
-NET "sen_rx_adc" LOC = "H18" ;
-NET "sen_rx_dac" LOC = "J18" ;
-NET "sen_rx_db" LOC = "D22" ;
-NET "sen_tx_adc" LOC = "G2" ;
-NET "sen_tx_dac" LOC = "H4" ;
-NET "sen_tx_db" LOC = "C1" ;
-NET "ser_enable" LOC = "W11" ;
-NET "ser_loopen" LOC = "Y4" ;
-NET "ser_prbsen" LOC = "AA3" ;
-NET "ser_rklsb" LOC = "V9" ;
-NET "ser_rkmsb" LOC = "Y10" ;
-NET "ser_rx_clk" LOC = "AA11" ;
-NET "ser_rx_en" LOC = "AB9" ;
-NET "ser_tklsb" LOC = "U10" | IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_tkmsb" LOC = "U11" | IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_tx_clk" LOC = "U7" | IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<0>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<1>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<2>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<3>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<4>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<5>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<6>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<7>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<8>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<9>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<10>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<11>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<12>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<13>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<14>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-NET "ser_t<15>" IOSTANDARD = LVCMOS25 | DRIVE = 12 | SLEW = FAST ;
-#PACE: Start of PACE Area Constraints
-
-#PACE: Start of PACE Prohibit Constraints
-
-#PACE: End of Constraints generated by PACE
diff --git a/fpga/usrp2/top/u2_rev1/u2_fpga_top.prj b/fpga/usrp2/top/u2_rev1/u2_fpga_top.prj
deleted file mode 100644
index 544415f4d..000000000
--- a/fpga/usrp2/top/u2_rev1/u2_fpga_top.prj
+++ /dev/null
@@ -1,102 +0,0 @@
-verilog work "../../opencores/uart16550/rtl/verilog/raminfr.v"
-verilog work "../../control_lib/ram_2port.v"
-verilog work "../../opencores/uart16550/rtl/verilog/uart_tfifo.v"
-verilog work "../../opencores/uart16550/rtl/verilog/uart_rfifo.v"
-verilog work "../../coregen/fifo_generator_v4_1.v"
-verilog work "../../control_lib/shortfifo.v"
-verilog work "../../control_lib/longfifo.v"
-verilog work "../../sdr_lib/sign_extend.v"
-verilog work "../../sdr_lib/cordic_stage.v"
-verilog work "../../sdr_lib/cic_int_shifter.v"
-verilog work "../../sdr_lib/cic_dec_shifter.v"
-verilog work "../../opencores/uart16550/rtl/verilog/uart_transmitter.v"
-verilog work "../../opencores/uart16550/rtl/verilog/uart_sync_flops.v"
-verilog work "../../opencores/uart16550/rtl/verilog/uart_receiver.v"
-verilog work "../../opencores/i2c/rtl/verilog/i2c_master_bit_ctrl.v"
-verilog work "../../opencores/aemb/rtl/verilog/aeMB_xecu.v"
-verilog work "../../opencores/aemb/rtl/verilog/aeMB_regf.v"
-verilog work "../../opencores/aemb/rtl/verilog/aeMB_ibuf.v"
-verilog work "../../opencores/aemb/rtl/verilog/aeMB_ctrl.v"
-verilog work "../../opencores/aemb/rtl/verilog/aeMB_bpcu.v"
-verilog work "../../opencores/8b10b/encode_8b10b.v"
-verilog work "../../opencores/8b10b/decode_8b10b.v"
-verilog work "../../eth/rtl/verilog/miim/eth_shiftreg.v"
-verilog work "../../eth/rtl/verilog/miim/eth_outputcontrol.v"
-verilog work "../../eth/rtl/verilog/miim/eth_clockgen.v"
-verilog work "../../eth/rtl/verilog/Reg_int.v"
-verilog work "../../eth/rtl/verilog/RMON/RMON_ctrl.v"
-verilog work "../../eth/rtl/verilog/RMON/RMON_addr_gen.v"
-verilog work "../../eth/rtl/verilog/MAC_tx/Random_gen.v"
-verilog work "../../eth/rtl/verilog/MAC_tx/MAC_tx_ctrl.v"
-verilog work "../../eth/rtl/verilog/MAC_tx/MAC_tx_addr_add.v"
-verilog work "../../eth/rtl/verilog/MAC_tx/MAC_tx_FF.v"
-verilog work "../../eth/rtl/verilog/MAC_tx/CRC_gen.v"
-verilog work "../../eth/rtl/verilog/MAC_rx/MAC_rx_ctrl.v"
-verilog work "../../eth/rtl/verilog/MAC_rx/MAC_rx_add_chk.v"
-verilog work "../../eth/rtl/verilog/MAC_rx/MAC_rx_FF.v"
-verilog work "../../eth/rtl/verilog/MAC_rx/CRC_chk.v"
-verilog work "../../eth/rtl/verilog/MAC_rx/Broadcast_filter.v"
-verilog work "../../control_lib/ss_rcvr.v"
-verilog work "../../control_lib/cascadefifo2.v"
-verilog work "../../control_lib/CRC16_D16.v"
-verilog work "../../timing/time_sender.v"
-verilog work "../../timing/time_receiver.v"
-verilog work "../../serdes/serdes_tx.v"
-verilog work "../../serdes/serdes_rx.v"
-verilog work "../../serdes/serdes_fc_tx.v"
-verilog work "../../serdes/serdes_fc_rx.v"
-verilog work "../../sdr_lib/round.v"
-verilog work "../../sdr_lib/cordic.v"
-verilog work "../../sdr_lib/cic_interp.v"
-verilog work "../../sdr_lib/cic_decim.v"
-verilog work "../../opencores/uart16550/rtl/verilog/uart_wb.v"
-verilog work "../../opencores/uart16550/rtl/verilog/uart_regs.v"
-verilog work "../../opencores/uart16550/rtl/verilog/uart_debug_if.v"
-verilog work "../../opencores/spi/rtl/verilog/spi_shift.v"
-verilog work "../../opencores/spi/rtl/verilog/spi_clgen.v"
-verilog work "../../opencores/i2c/rtl/verilog/i2c_master_byte_ctrl.v"
-verilog work "../../opencores/aemb/rtl/verilog/aeMB_edk32.v"
-verilog work "../../eth/rtl/verilog/flow_ctrl_tx.v"
-verilog work "../../eth/rtl/verilog/flow_ctrl_rx.v"
-verilog work "../../eth/rtl/verilog/eth_miim.v"
-verilog work "../../eth/rtl/verilog/RMON.v"
-verilog work "../../eth/rtl/verilog/Phy_int.v"
-verilog work "../../eth/rtl/verilog/MAC_tx.v"
-verilog work "../../eth/rtl/verilog/MAC_rx.v"
-verilog work "../../eth/rtl/verilog/Clk_ctrl.v"
-verilog work "../../control_lib/strobe_gen.v"
-verilog work "../../control_lib/setting_reg.v"
-verilog work "../../control_lib/mux8.v"
-verilog work "../../control_lib/mux4.v"
-verilog work "../../control_lib/icache.v"
-verilog work "../../control_lib/dpram32.v"
-verilog work "../../control_lib/decoder_3_8.v"
-verilog work "../../control_lib/dcache.v"
-verilog work "../../control_lib/buffer_int.v"
-verilog work "../../timing/timer.v"
-verilog work "../../timing/time_sync.v"
-verilog work "../../serdes/serdes.v"
-verilog work "../../sdr_lib/tx_control.v"
-verilog work "../../sdr_lib/rx_control.v"
-verilog work "../../sdr_lib/dsp_core_tx.v"
-verilog work "../../sdr_lib/dsp_core_rx.v"
-verilog work "../../opencores/uart16550/rtl/verilog/uart_top.v"
-verilog work "../../opencores/spi/rtl/verilog/spi_top.v"
-verilog work "../../opencores/simple_pic/rtl/simple_pic.v"
-verilog work "../../opencores/i2c/rtl/verilog/i2c_master_top.v"
-verilog work "../../opencores/aemb/rtl/verilog/aeMB_core_BE.v"
-verilog work "../../eth/rtl/verilog/MAC_top.v"
-verilog work "../../eth/mac_txfifo_int.v"
-verilog work "../../eth/mac_rxfifo_int.v"
-verilog work "../../control_lib/wb_readback_mux.v"
-verilog work "../../control_lib/wb_1master.v"
-verilog work "../../control_lib/system_control.v"
-verilog work "../../control_lib/settings_bus.v"
-verilog work "../../control_lib/ram_loader.v"
-verilog work "../../control_lib/ram_harv_cache.v"
-verilog work "../../control_lib/nsgpio.v"
-verilog work "../../control_lib/extram_interface.v"
-verilog work "../../control_lib/buffer_pool.v"
-verilog work "../../control_lib/atr_controller.v"
-verilog work "../u2_basic/u2_basic.v"
-verilog work "u2_fpga_top.v"
diff --git a/fpga/usrp2/top/u2_rev1/u2_fpga_top.v b/fpga/usrp2/top/u2_rev1/u2_fpga_top.v
deleted file mode 100644
index 63798a0c8..000000000
--- a/fpga/usrp2/top/u2_rev1/u2_fpga_top.v
+++ /dev/null
@@ -1,393 +0,0 @@
-`timescale 1ns / 1ps
-//////////////////////////////////////////////////////////////////////////////////
-
-module u2_fpga_top
- (
- // Misc, debug
- output led1,
- output led2,
- output [31:0] debug,
- output [1:0] debug_clk,
-
- // Expansion
- input exp_pps_in_p, // Diff
- input exp_pps_in_n, // Diff
- output exp_pps_out_p, // Diff
- output exp_pps_out_n, // Diff
-
- // GMII
- // GMII-CTRL
- input GMII_COL,
- input GMII_CRS,
-
- // GMII-TX
- output reg [7:0] GMII_TXD,
- output reg GMII_TX_EN,
- output reg GMII_TX_ER,
- output GMII_GTX_CLK,
- input GMII_TX_CLK, // 100mbps clk
-
- // GMII-RX
- input [7:0] GMII_RXD,
- input GMII_RX_CLK,
- input GMII_RX_DV,
- input GMII_RX_ER,
-
- // GMII-Management
- inout MDIO,
- output MDC,
- input PHY_INTn, // open drain
- output PHY_RESETn,
- input PHY_CLK, // possibly use on-board osc
-
- // RAM
- inout [17:0] RAM_D,
- output [18:0] RAM_A,
- output RAM_CE1n,
- output RAM_CENn,
- output RAM_CLK,
- output RAM_WEn,
- output RAM_OEn,
- output RAM_LDn,
-
- // SERDES
- output ser_enable,
- output ser_prbsen,
- output ser_loopen,
- output ser_rx_en,
-
- output ser_tx_clk,
- output reg [15:0] ser_t,
- output reg ser_tklsb,
- output reg ser_tkmsb,
-
- input ser_rx_clk,
- input [15:0] ser_r,
- input ser_rklsb,
- input ser_rkmsb,
-
- // CPLD interface
- output cpld_start, // AA9
- output cpld_mode, // U12
- output cpld_done, // V12
- input cpld_din, // AA14 Now shared with CFG_Din
- input cpld_clk, // AB14 serial clock
-
- // ADC
- input [13:0] adc_a,
- input adc_ovf_a,
- output adc_oen_a,
- output adc_pdn_a,
-
- input [13:0] adc_b,
- input adc_ovf_b,
- output adc_oen_b,
- output adc_pdn_b,
-
- // DAC
- output [15:0] dac_a,
- output [15:0] dac_b,
-
- // I2C
- inout SCL,
- inout SDA,
- input SCL_force,
- input SDA_force,
-
- // Clock Gen Control
- output [1:0] clk_en,
- output [1:0] clk_sel,
- input clk_func, // FIXME is an input to control the 9510
- input clk_status,
-
- // Clocks
- input clk_fpga_p, // Diff
- input clk_fpga_n, // Diff
- input clk_to_mac,
- input pps_in,
-
- // Generic SPI
- output sclk,
- output sen_clk,
- output sen_dac,
- output sdi,
- input sdo,
-
- // TX DBoard
- output sen_tx_db,
- output sclk_tx_db,
- input sdo_tx_db,
- output sdi_tx_db,
-
- output sen_tx_adc,
- output sclk_tx_adc,
- input sdo_tx_adc,
- output sdi_tx_adc,
-
- output sen_tx_dac,
- output sclk_tx_dac,
- output sdi_tx_dac,
-
- inout [15:0] io_tx,
-
- // RX DBoard
- output sen_rx_db,
- output sclk_rx_db,
- input sdo_rx_db,
- output sdi_rx_db,
-
- output sen_rx_adc,
- output sclk_rx_adc,
- input sdo_rx_adc,
- output sdi_rx_adc,
-
- output sen_rx_dac,
- output sclk_rx_dac,
- output sdi_rx_dac,
-
- inout [15:0] io_rx
- );
-
- // FPGA-specific pins connections
- wire aux_clk = PHY_CLK;
- //wire cpld_detached = RAM_A[14]; // FIXME Hacked on with Blue Wire
- wire cpld_detached = SDA_force; // FIXME Hacked on with Blue Wire
-
- wire clk_fpga, dsp_clk, clk_div, dcm_out, wb_clk, clock_ready;
-
- IBUFGDS clk_fpga_pin (.O(clk_fpga),.I(clk_fpga_p),.IB(clk_fpga_n));
- defparam clk_fpga_pin.IOSTANDARD = "LVPECL_25";
-
- wire exp_pps_in;
- IBUFDS exp_pps_in_pin (.O(exp_pps_in),.I(exp_pps_in_p),.IB(exp_pps_in_n));
- defparam exp_pps_in_pin.IOSTANDARD = "LVDS_25";
-
- wire exp_pps_out;
- OBUFDS exp_pps_out_pin (.O(exp_pps_out_p),.OB(exp_pps_out_n),.I(exp_pps_out));
- defparam exp_pps_out_pin.IOSTANDARD = "LVDS_25";
-
- reg [5:0] clock_ready_d;
- always @(posedge aux_clk)
- clock_ready_d[5:0] <= {clock_ready_d[4:0],clock_ready};
-
- wire dcm_rst = ~&clock_ready_d & |clock_ready_d;
- wire clk_muxed = clock_ready ? clk_fpga : aux_clk;
-
- wire adc_on_a, adc_on_b, adc_oe_a, adc_oe_b;
- assign adc_oen_a = ~adc_oe_a;
- assign adc_oen_b = ~adc_oe_b;
- assign adc_pdn_a = ~adc_on_a;
- assign adc_pdn_b = ~adc_on_b;
-
- // Handle Clocks
- DCM DCM_INST (.CLKFB(dsp_clk),
- .CLKIN(clk_muxed),
- .DSSEN(0),
- .PSCLK(0),
- .PSEN(0),
- .PSINCDEC(0),
- .RST(dcm_rst),
- .CLKDV(clk_div),
- .CLKFX(),
- .CLKFX180(),
- .CLK0(dcm_out),
- .CLK2X(),
- .CLK2X180(),
- .CLK90(),
- .CLK180(),
- .CLK270(),
- .LOCKED(LOCKED_OUT),
- .PSDONE(),
- .STATUS());
- defparam DCM_INST.CLK_FEEDBACK = "1X";
- defparam DCM_INST.CLKDV_DIVIDE = 2.0;
- defparam DCM_INST.CLKFX_DIVIDE = 1;
- defparam DCM_INST.CLKFX_MULTIPLY = 4;
- defparam DCM_INST.CLKIN_DIVIDE_BY_2 = "FALSE";
- defparam DCM_INST.CLKIN_PERIOD = 10.000;
- defparam DCM_INST.CLKOUT_PHASE_SHIFT = "NONE";
- defparam DCM_INST.DESKEW_ADJUST = "SYSTEM_SYNCHRONOUS";
- defparam DCM_INST.DFS_FREQUENCY_MODE = "LOW";
- defparam DCM_INST.DLL_FREQUENCY_MODE = "LOW";
- defparam DCM_INST.DUTY_CYCLE_CORRECTION = "TRUE";
- defparam DCM_INST.FACTORY_JF = 16'h8080;
- defparam DCM_INST.PHASE_SHIFT = 0;
- defparam DCM_INST.STARTUP_WAIT = "FALSE";
-
- BUFG dspclk_BUFG (.I(dcm_out), .O(dsp_clk));
- BUFG wbclk_BUFG (.I(clk_div), .O(wb_clk));
-
- // I2C -- Don't use external transistors for open drain, the FPGA implements this
- IOBUF scl_pin(.O(scl_pad_i), .IO(SCL), .I(scl_pad_o), .T(scl_pad_oen_o));
- IOBUF sda_pin(.O(sda_pad_i), .IO(SDA), .I(sda_pad_o), .T(sda_pad_oen_o));
-
- // LEDs are active low outputs
- wire led1_int, led2_int;
- assign led1 = ~led1_int;
- assign led2 = ~led2_int;
-
- // SPI
- wire miso, mosi, sclk_int;
- assign {sclk,sdi} = (~sen_clk | ~sen_dac) ? {sclk_int,mosi} : 2'b0;
- assign {sclk_tx_db,sdi_tx_db} = ~sen_tx_db ? {sclk_int,mosi} : 2'b0;
- assign {sclk_tx_dac,sdi_tx_dac} = ~sen_tx_dac ? {sclk_int,mosi} : 2'b0;
- assign {sclk_tx_adc,sdi_tx_adc} = ~sen_tx_adc ? {sclk_int,mosi} : 2'b0;
- assign {sclk_rx_db,sdi_rx_db} = ~sen_rx_db ? {sclk_int,mosi} : 2'b0;
- assign {sclk_rx_dac,sdi_rx_dac} = ~sen_rx_dac ? {sclk_int,mosi} : 2'b0;
- assign {sclk_rx_adc,sdi_rx_adc} = ~sen_rx_adc ? {sclk_int,mosi} : 2'b0;
-
- assign miso = (~sen_clk & sdo) | (~sen_dac & sdo) |
- (~sen_tx_db & sdo_tx_db) | (~sen_tx_adc & sdo_tx_adc) |
- (~sen_rx_db & sdo_rx_db) | (~sen_rx_adc & sdo_rx_adc);
-
- wire GMII_TX_EN_unreg, GMII_TX_ER_unreg;
- wire [7:0] GMII_TXD_unreg;
- wire GMII_GTX_CLK_int;
-
- always @(posedge GMII_GTX_CLK_int)
- begin
- GMII_TX_EN <= GMII_TX_EN_unreg;
- GMII_TX_ER <= GMII_TX_ER_unreg;
- GMII_TXD <= GMII_TXD_unreg;
- end
-
- OFDDRRSE OFDDRRSE_gmii_inst
- (.Q(GMII_GTX_CLK), // Data output (connect directly to top-level port)
- .C0(GMII_GTX_CLK_int), // 0 degree clock input
- .C1(~GMII_GTX_CLK_int), // 180 degree clock input
- .CE(1), // Clock enable input
- .D0(0), // Posedge data input
- .D1(1), // Negedge data input
- .R(0), // Synchronous reset input
- .S(0) // Synchronous preset input
- );
-
- wire ser_tklsb_unreg, ser_tkmsb_unreg;
- wire [15:0] ser_t_unreg;
- wire ser_tx_clk_int;
-
- always @(posedge ser_tx_clk_int)
- begin
- ser_tklsb <= ser_tklsb_unreg;
- ser_tkmsb <= ser_tkmsb_unreg;
- ser_t <= ser_t_unreg;
- end
-
- assign ser_tx_clk = clk_fpga;
-
- reg [15:0] ser_r_int;
- reg ser_rklsb_int, ser_rkmsb_int;
-
- always @(posedge ser_rx_clk)
- begin
- ser_r_int <= ser_r;
- ser_rklsb_int <= ser_rklsb;
- ser_rkmsb_int <= ser_rkmsb;
- end
-
- /*
- OFDDRRSE OFDDRRSE_serdes_inst
- (.Q(ser_tx_clk), // Data output (connect directly to top-level port)
- .C0(ser_tx_clk_int), // 0 degree clock input
- .C1(~ser_tx_clk_int), // 180 degree clock input
- .CE(1), // Clock enable input
- .D0(0), // Posedge data input
- .D1(1), // Negedge data input
- .R(0), // Synchronous reset input
- .S(0) // Synchronous preset input
- );
- */
- u2_basic u2_basic(.dsp_clk (dsp_clk),
- .wb_clk (wb_clk),
- .clock_ready (clock_ready),
- .clk_to_mac (clk_to_mac),
- .pps_in (pps_in),
- .led1 (led1_int),
- .led2 (led2_int),
- .debug (debug[31:0]),
- .debug_clk (debug_clk[1:0]),
- .exp_pps_in (exp_pps_in),
- .exp_pps_out (exp_pps_out),
- .GMII_COL (GMII_COL),
- .GMII_CRS (GMII_CRS),
- .GMII_TXD (GMII_TXD_unreg[7:0]),
- .GMII_TX_EN (GMII_TX_EN_unreg),
- .GMII_TX_ER (GMII_TX_ER_unreg),
- .GMII_GTX_CLK (GMII_GTX_CLK_int),
- .GMII_TX_CLK (GMII_TX_CLK),
- .GMII_RXD (GMII_RXD[7:0]),
- .GMII_RX_CLK (GMII_RX_CLK),
- .GMII_RX_DV (GMII_RX_DV),
- .GMII_RX_ER (GMII_RX_ER),
- .MDIO (MDIO),
- .MDC (MDC),
- .PHY_INTn (PHY_INTn),
- .PHY_RESETn (PHY_RESETn),
- .PHY_CLK (PHY_CLK),
- .ser_enable (ser_enable),
- .ser_prbsen (ser_prbsen),
- .ser_loopen (ser_loopen),
- .ser_rx_en (ser_rx_en),
- .ser_tx_clk (ser_tx_clk_int),
- .ser_t (ser_t_unreg[15:0]),
- .ser_tklsb (ser_tklsb_unreg),
- .ser_tkmsb (ser_tkmsb_unreg),
- .ser_rx_clk (ser_rx_clk),
- .ser_r (ser_r_int[15:0]),
- .ser_rklsb (ser_rklsb_int),
- .ser_rkmsb (ser_rkmsb_int),
- .cpld_start (cpld_start),
- .cpld_mode (cpld_mode),
- .cpld_done (cpld_done),
- .cpld_din (cpld_din),
- .cpld_clk (cpld_clk),
- .cpld_detached (cpld_detached),
- .adc_a (adc_a[13:0]),
- .adc_ovf_a (adc_ovf_a),
- .adc_on_a (adc_on_a),
- .adc_oe_a (adc_oe_a),
- .adc_b (adc_b[13:0]),
- .adc_ovf_b (adc_ovf_b),
- .adc_on_b (adc_on_b),
- .adc_oe_b (adc_oe_b),
- .dac_a (dac_a[15:0]),
- .dac_b (dac_b[15:0]),
- .scl_pad_i (scl_pad_i),
- .scl_pad_o (scl_pad_o),
- .scl_pad_oen_o (scl_pad_oen_o),
- .sda_pad_i (sda_pad_i),
- .sda_pad_o (sda_pad_o),
- .sda_pad_oen_o (sda_pad_oen_o),
- .clk_en (clk_en[1:0]),
- .clk_sel (clk_sel[1:0]),
- .clk_func (clk_func),
- .clk_status (clk_status),
- .sclk (sclk_int),
- .mosi (mosi),
- .miso (miso),
- .sen_clk (sen_clk),
- .sen_dac (sen_dac),
- .sen_tx_db (sen_tx_db),
- .sen_tx_adc (sen_tx_adc),
- .sen_tx_dac (sen_tx_dac),
- .sen_rx_db (sen_rx_db),
- .sen_rx_adc (sen_rx_adc),
- .sen_rx_dac (sen_rx_dac),
- .io_tx (io_tx[15:0]),
- .io_rx (io_rx[15:0]),
- .RAM_D (RAM_D),
- .RAM_A (RAM_A),
- .RAM_CE1n (RAM_CE1n),
- .RAM_CENn (RAM_CENn),
- .RAM_CLK (RAM_CLK),
- .RAM_WEn (RAM_WEn),
- .RAM_OEn (RAM_OEn),
- .RAM_LDn (RAM_LDn),
- .uart_tx_o (),
- .uart_rx_i (),
- .uart_baud_o (),
- .sim_mode (1'b0),
- .clock_divider (2)
- );
-
-endmodule // u2_fpga_top
diff --git a/fpga/usrp2/top/u2_rev2/.gitignore b/fpga/usrp2/top/u2_rev2/.gitignore
deleted file mode 100644
index 432f8fd58..000000000
--- a/fpga/usrp2/top/u2_rev2/.gitignore
+++ /dev/null
@@ -1,57 +0,0 @@
-/*.ptwx
-/*.xrpt
-/*.zip
-/*_xdb
-/templates
-/netgen
-/_ngo
-/_xmsgs
-/_pace.ucf
-/*.cmd
-/*.ibs
-/*.lfp
-/*.mfp
-/*.bit
-/*.bin
-/*.stx
-/*.par
-/*.unroutes
-/*.ntrc_log
-/*.ngr
-/*.mrp
-/*.html
-/*.lso
-/*.twr
-/*.bld
-/*.ncd
-/*.txt
-/*.cmd_log
-/*.drc
-/*.map
-/*.twr
-/*.xml
-/*.syr
-/*.ngm
-/*.xst
-/*.csv
-/*.html
-/*.lock
-/*.ncd
-/*.twx
-/*.ise_ISE_Backup
-/*.xml
-/*.ut
-/*.xpi
-/*.ngd
-/*.ncd
-/*.pad
-/*.bgn
-/*.ngc
-/*.pcf
-/*.ngd
-/xst
-/*.log
-/*.rpt
-/*.cel
-/*.restore
-/build
diff --git a/fpga/usrp2/top/u2_rev2/Makefile b/fpga/usrp2/top/u2_rev2/Makefile
deleted file mode 100644
index 275c24b02..000000000
--- a/fpga/usrp2/top/u2_rev2/Makefile
+++ /dev/null
@@ -1,248 +0,0 @@
-#
-# Copyright 2008 Ettus Research LLC
-#
-# This file is part of GNU Radio
-#
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Radio; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-#
-
-##################################################
-# xtclsh Shell and tcl Script Path
-##################################################
-#XTCLSH := /opt/Xilinx/10.1/ISE/bin/lin/xtclsh
-XTCLSH := xtclsh
-ISE_HELPER := ../tcl/ise_helper.tcl
-
-##################################################
-# Project Setup
-##################################################
-BUILD_DIR := build/
-export TOP_MODULE := u2_rev2
-export PROJ_FILE := $(BUILD_DIR)$(TOP_MODULE).ise
-
-##################################################
-# Project Properties
-##################################################
-export PROJECT_PROPERTIES := \
-family Spartan3 \
-device xc3s2000 \
-package fg456 \
-speed -5 \
-top_level_module_type "HDL" \
-synthesis_tool "XST (VHDL/Verilog)" \
-simulator "ISE Simulator (VHDL/Verilog)" \
-"Preferred Language" "Verilog" \
-"Enable Message Filtering" FALSE \
-"Display Incremental Messages" FALSE
-
-##################################################
-# Sources
-##################################################
-export SOURCE_ROOT := ../../../
-export SOURCES := \
-control_lib/CRC16_D16.v \
-control_lib/atr_controller.v \
-control_lib/bin2gray.v \
-control_lib/buffer_int.v \
-control_lib/buffer_pool.v \
-control_lib/cascadefifo2.v \
-control_lib/dcache.v \
-control_lib/decoder_3_8.v \
-control_lib/dpram32.v \
-control_lib/fifo_2clock.v \
-control_lib/fifo_2clock_casc.v \
-control_lib/gray2bin.v \
-control_lib/gray_send.v \
-control_lib/icache.v \
-control_lib/longfifo.v \
-control_lib/mux4.v \
-control_lib/mux8.v \
-control_lib/nsgpio.v \
-control_lib/ram_2port.v \
-control_lib/ram_harv_cache.v \
-control_lib/ram_loader.v \
-control_lib/setting_reg.v \
-control_lib/settings_bus.v \
-control_lib/shortfifo.v \
-control_lib/medfifo.v \
-control_lib/srl.v \
-control_lib/system_control.v \
-control_lib/wb_1master.v \
-control_lib/wb_readback_mux.v \
-control_lib/simple_uart.v \
-control_lib/simple_uart_tx.v \
-control_lib/simple_uart_rx.v \
-control_lib/oneshot_2clk.v \
-control_lib/sd_spi.v \
-control_lib/sd_spi_wb.v \
-control_lib/wb_bridge_16_32.v \
-coregen/fifo_xlnx_2Kx36_2clk.v \
-coregen/fifo_xlnx_2Kx36_2clk.xco \
-coregen/fifo_xlnx_512x36_2clk.v \
-coregen/fifo_xlnx_512x36_2clk.xco \
-eth/mac_rxfifo_int.v \
-eth/mac_txfifo_int.v \
-eth/rtl/verilog/Clk_ctrl.v \
-eth/rtl/verilog/MAC_rx.v \
-eth/rtl/verilog/MAC_rx/Broadcast_filter.v \
-eth/rtl/verilog/MAC_rx/CRC_chk.v \
-eth/rtl/verilog/MAC_rx/MAC_rx_FF.v \
-eth/rtl/verilog/MAC_rx/MAC_rx_add_chk.v \
-eth/rtl/verilog/MAC_rx/MAC_rx_ctrl.v \
-eth/rtl/verilog/MAC_top.v \
-eth/rtl/verilog/MAC_tx.v \
-eth/rtl/verilog/MAC_tx/CRC_gen.v \
-eth/rtl/verilog/MAC_tx/MAC_tx_FF.v \
-eth/rtl/verilog/MAC_tx/MAC_tx_addr_add.v \
-eth/rtl/verilog/MAC_tx/MAC_tx_ctrl.v \
-eth/rtl/verilog/MAC_tx/Random_gen.v \
-eth/rtl/verilog/Phy_int.v \
-eth/rtl/verilog/RMON.v \
-eth/rtl/verilog/RMON/RMON_addr_gen.v \
-eth/rtl/verilog/RMON/RMON_ctrl.v \
-eth/rtl/verilog/Reg_int.v \
-eth/rtl/verilog/eth_miim.v \
-eth/rtl/verilog/flow_ctrl_rx.v \
-eth/rtl/verilog/flow_ctrl_tx.v \
-eth/rtl/verilog/miim/eth_clockgen.v \
-eth/rtl/verilog/miim/eth_outputcontrol.v \
-eth/rtl/verilog/miim/eth_shiftreg.v \
-extram/wb_zbt16_b.v \
-opencores/8b10b/decode_8b10b.v \
-opencores/8b10b/encode_8b10b.v \
-opencores/aemb/rtl/verilog/aeMB_bpcu.v \
-opencores/aemb/rtl/verilog/aeMB_core_BE.v \
-opencores/aemb/rtl/verilog/aeMB_ctrl.v \
-opencores/aemb/rtl/verilog/aeMB_edk32.v \
-opencores/aemb/rtl/verilog/aeMB_ibuf.v \
-opencores/aemb/rtl/verilog/aeMB_regf.v \
-opencores/aemb/rtl/verilog/aeMB_xecu.v \
-opencores/i2c/rtl/verilog/i2c_master_bit_ctrl.v \
-opencores/i2c/rtl/verilog/i2c_master_byte_ctrl.v \
-opencores/i2c/rtl/verilog/i2c_master_defines.v \
-opencores/i2c/rtl/verilog/i2c_master_top.v \
-opencores/i2c/rtl/verilog/timescale.v \
-opencores/simple_pic/rtl/simple_pic.v \
-opencores/spi/rtl/verilog/spi_clgen.v \
-opencores/spi/rtl/verilog/spi_defines.v \
-opencores/spi/rtl/verilog/spi_shift.v \
-opencores/spi/rtl/verilog/spi_top.v \
-opencores/spi/rtl/verilog/timescale.v \
-sdr_lib/acc.v \
-sdr_lib/add2.v \
-sdr_lib/add2_and_round.v \
-sdr_lib/add2_and_round_reg.v \
-sdr_lib/add2_reg.v \
-sdr_lib/cic_dec_shifter.v \
-sdr_lib/cic_decim.v \
-sdr_lib/cic_int_shifter.v \
-sdr_lib/cic_interp.v \
-sdr_lib/cic_strober.v \
-sdr_lib/clip.v \
-sdr_lib/clip_reg.v \
-sdr_lib/cordic.v \
-sdr_lib/cordic_z24.v \
-sdr_lib/cordic_stage.v \
-sdr_lib/dsp_core_rx.v \
-sdr_lib/dsp_core_tx.v \
-sdr_lib/hb_dec.v \
-sdr_lib/hb_interp.v \
-sdr_lib/round.v \
-sdr_lib/round_reg.v \
-sdr_lib/rx_control.v \
-sdr_lib/rx_dcoffset.v \
-sdr_lib/sign_extend.v \
-sdr_lib/small_hb_dec.v \
-sdr_lib/small_hb_int.v \
-sdr_lib/tx_control.v \
-serdes/serdes.v \
-serdes/serdes_fc_rx.v \
-serdes/serdes_fc_tx.v \
-serdes/serdes_rx.v \
-serdes/serdes_tx.v \
-timing/time_receiver.v \
-timing/time_sender.v \
-timing/time_sync.v \
-timing/timer.v \
-top/u2_core/u2_core.v \
-top/u2_rev2/u2_rev2.ucf \
-top/u2_rev2/u2_rev2.v
-
-##################################################
-# Process Properties
-##################################################
-export SYNTHESIZE_PROPERTIES := \
-"Number of Clock Buffers" 6 \
-"Pack I/O Registers into IOBs" Yes \
-"Optimization Effort" High \
-"Optimize Instantiated Primitives" TRUE \
-"Register Balancing" Yes \
-"Use Clock Enable" Auto \
-"Use Synchronous Reset" Auto \
-"Use Synchronous Set" Auto
-
-export TRANSLATE_PROPERTIES := \
-"Macro Search Path" "$(shell pwd)/../../coregen/"
-
-export MAP_PROPERTIES := \
-"Allow Logic Optimization Across Hierarchy" TRUE \
-"Map to Input Functions" 4 \
-"Optimization Strategy (Cover Mode)" Speed \
-"Pack I/O Registers/Latches into IOBs" "For Inputs and Outputs" \
-"Perform Timing-Driven Packing and Placement" TRUE \
-"Map Effort Level" High \
-"Extra Effort" Normal \
-"Combinatorial Logic Optimization" TRUE \
-"Register Duplication" TRUE
-
-export PLACE_ROUTE_PROPERTIES := \
-"Place & Route Effort Level (Overall)" High
-
-export STATIC_TIMING_PROPERTIES := \
-"Number of Paths in Error/Verbose Report" 10 \
-"Report Type" "Error Report"
-
-export GEN_PROG_FILE_PROPERTIES := \
-"Configuration Rate" 6 \
-"Create Binary Configuration File" TRUE \
-"Done (Output Events)" 5 \
-"Enable Bitstream Compression" TRUE \
-"Enable Outputs (Output Events)" 6
-
-export SIM_MODEL_PROPERTIES := ""
-
-##################################################
-# Make Options
-##################################################
-all:
- @echo make proj, check, synth, bin, or clean
-
-proj:
- PROCESS_RUN="" $(XTCLSH) $(ISE_HELPER)
-
-check:
- PROCESS_RUN="Check Syntax" $(XTCLSH) $(ISE_HELPER)
-
-synth:
- PROCESS_RUN="Synthesize - XST" $(XTCLSH) $(ISE_HELPER)
-
-bin:
- PROCESS_RUN="Generate Programming File" $(XTCLSH) $(ISE_HELPER)
-
-clean:
- rm -rf $(BUILD_DIR)
-
-
diff --git a/fpga/usrp2/top/u2_rev2/u2_rev2.ucf b/fpga/usrp2/top/u2_rev2/u2_rev2.ucf
deleted file mode 100644
index e18dc6f17..000000000
--- a/fpga/usrp2/top/u2_rev2/u2_rev2.ucf
+++ /dev/null
@@ -1,337 +0,0 @@
-NET "leds[0]" LOC = "F7" ;
-NET "leds[1]" LOC = "E5" ;
-NET "leds[2]" LOC = "B7" ;
-NET "leds[3]" LOC = "C11" ;
-NET "leds[4]" LOC = "AB19" ;
-NET "debug[0]" LOC = "N5" ;
-NET "debug[1]" LOC = "N6" ;
-NET "debug[2]" LOC = "P1" ;
-NET "debug[3]" LOC = "P2" ;
-NET "debug[4]" LOC = "P4" ;
-NET "debug[5]" LOC = "P5" ;
-NET "debug[6]" LOC = "R1" ;
-NET "debug[7]" LOC = "R2" ;
-NET "debug[8]" LOC = "P6" ;
-NET "debug[9]" LOC = "R5" ;
-NET "debug[10]" LOC = "R4" ;
-NET "debug[11]" LOC = "T3" ;
-NET "debug[12]" LOC = "U3" ;
-NET "debug[13]" LOC = "M2" ;
-NET "debug[14]" LOC = "M3" ;
-NET "debug[15]" LOC = "M4" ;
-NET "debug[16]" LOC = "M5" ;
-NET "debug[17]" LOC = "M6" ;
-NET "debug[18]" LOC = "N1" ;
-NET "debug[19]" LOC = "N2" ;
-NET "debug[20]" LOC = "N3" ;
-NET "debug[21]" LOC = "T1" ;
-NET "debug[22]" LOC = "T2" ;
-NET "debug[23]" LOC = "U2" ;
-NET "debug[24]" LOC = "T4" ;
-NET "debug[25]" LOC = "U4" ;
-NET "debug[26]" LOC = "T5" ;
-NET "debug[27]" LOC = "T6" ;
-NET "debug[28]" LOC = "U5" ;
-NET "debug[29]" LOC = "V5" ;
-NET "debug[30]" LOC = "W2" ;
-NET "debug[31]" LOC = "W3" ;
-NET "debug_clk[0]" LOC = "N4" ;
-NET "debug_clk[1]" LOC = "M1" ;
-NET "uart_tx_o" LOC = "C7" ;
-NET "uart_rx_i" LOC = "A3" ;
-NET "exp_pps_in_p" LOC = "V3" ;
-NET "exp_pps_in_n" LOC = "V4" ;
-NET "exp_pps_out_p" LOC = "V1" ;
-NET "exp_pps_out_n" LOC = "V2" ;
-NET "GMII_COL" LOC = "U16" ;
-NET "GMII_CRS" LOC = "U17" ;
-NET "GMII_TXD[0]" LOC = "W14" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "GMII_TXD[1]" LOC = "AA20" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "GMII_TXD[2]" LOC = "AB20" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "GMII_TXD[3]" LOC = "Y18" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "GMII_TXD[4]" LOC = "AA18" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "GMII_TXD[5]" LOC = "AB18" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "GMII_TXD[6]" LOC = "V17" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "GMII_TXD[7]" LOC = "W17" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "GMII_TX_EN" LOC = "Y17" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "GMII_TX_ER" LOC = "V16" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "GMII_GTX_CLK" LOC = "AA17" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "GMII_TX_CLK" LOC = "W13" ;
-NET "GMII_RXD[0]" LOC = "AA15" ;
-NET "GMII_RXD[1]" LOC = "AB15" ;
-NET "GMII_RXD[2]" LOC = "U14" ;
-NET "GMII_RXD[3]" LOC = "V14" ;
-NET "GMII_RXD[4]" LOC = "U13" ;
-NET "GMII_RXD[5]" LOC = "V13" ;
-NET "GMII_RXD[6]" LOC = "Y13" ;
-NET "GMII_RXD[7]" LOC = "AA13" ;
-NET "GMII_RX_CLK" LOC = "W16" ;
-NET "GMII_RX_DV" LOC = "AB16" ;
-NET "GMII_RX_ER" LOC = "AA16" ;
-NET "MDIO" LOC = "Y16" |PULLUP ;
-NET "MDC" LOC = "V18" ;
-NET "PHY_INTn" LOC = "AB13" ;
-NET "PHY_RESETn" LOC = "AA19" ;
-NET "PHY_CLK" LOC = "V15" ;
-NET "RAM_D[0]" LOC = "N20" ;
-NET "RAM_D[1]" LOC = "N21" ;
-NET "RAM_D[2]" LOC = "N22" ;
-NET "RAM_D[3]" LOC = "M17" ;
-NET "RAM_D[4]" LOC = "M18" ;
-NET "RAM_D[5]" LOC = "M19" ;
-NET "RAM_D[6]" LOC = "M20" ;
-NET "RAM_D[7]" LOC = "M21" ;
-NET "RAM_D[8]" LOC = "M22" ;
-NET "RAM_D[9]" LOC = "Y22" ;
-NET "RAM_D[10]" LOC = "Y21" ;
-NET "RAM_D[11]" LOC = "Y20" ;
-NET "RAM_D[12]" LOC = "Y19" ;
-NET "RAM_D[13]" LOC = "W22" ;
-NET "RAM_D[14]" LOC = "W21" ;
-NET "RAM_D[15]" LOC = "W20" ;
-NET "RAM_D[16]" LOC = "W19" ;
-NET "RAM_D[17]" LOC = "V22" ;
-NET "RAM_A[0]" LOC = "U21" ;
-NET "RAM_A[1]" LOC = "T19" ;
-NET "RAM_A[2]" LOC = "V21" ;
-NET "RAM_A[3]" LOC = "V20" ;
-NET "RAM_A[4]" LOC = "T20" ;
-NET "RAM_A[5]" LOC = "T21" ;
-NET "RAM_A[6]" LOC = "T22" ;
-NET "RAM_A[7]" LOC = "T18" ;
-NET "RAM_A[8]" LOC = "R18" ;
-NET "RAM_A[9]" LOC = "P19" ;
-NET "RAM_A[10]" LOC = "P21" ;
-NET "RAM_A[11]" LOC = "P22" ;
-NET "RAM_A[12]" LOC = "N19" ;
-NET "RAM_A[13]" LOC = "N17" ;
-NET "RAM_A[14]" LOC = "N18" ;
-NET "RAM_A[15]" LOC = "T17" ;
-NET "RAM_A[16]" LOC = "U19" ;
-NET "RAM_A[17]" LOC = "U18" ;
-NET "RAM_A[18]" LOC = "V19" ;
-NET "RAM_CE1n" LOC = "U20" ;
-NET "RAM_CENn" LOC = "P18" ;
-NET "RAM_CLK" LOC = "P17" ;
-NET "RAM_WEn" LOC = "R22" ;
-NET "RAM_OEn" LOC = "R21" ;
-NET "RAM_LDn" LOC = "R19" ;
-NET "ser_enable" LOC = "W11" ;
-NET "ser_prbsen" LOC = "AA3" ;
-NET "ser_loopen" LOC = "Y4" ;
-NET "ser_rx_en" LOC = "AB9" ;
-NET "ser_tx_clk" LOC = "U7" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[0]" LOC = "V7" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[1]" LOC = "V10" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[2]" LOC = "AB4" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[3]" LOC = "AA4" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[4]" LOC = "Y5" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[5]" LOC = "W5" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[6]" LOC = "AB5" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[7]" LOC = "AA5" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[8]" LOC = "W6" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[9]" LOC = "V6" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[10]" LOC = "AA6" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[11]" LOC = "Y6" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[12]" LOC = "W8" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[13]" LOC = "V8" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[14]" LOC = "AB8" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_t[15]" LOC = "AA8" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_tklsb" LOC = "U10" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_tkmsb" LOC = "U11" |IOSTANDARD = LVCMOS25 |DRIVE = 12 |SLEW = FAST ;
-NET "ser_rx_clk" LOC = "AA11" ;
-NET "ser_r[0]" LOC = "AB10" ;
-NET "ser_r[1]" LOC = "AA10" ;
-NET "ser_r[2]" LOC = "U9" ;
-NET "ser_r[3]" LOC = "U6" ;
-NET "ser_r[4]" LOC = "AB11" ;
-NET "ser_r[5]" LOC = "Y7" ;
-NET "ser_r[6]" LOC = "W7" ;
-NET "ser_r[7]" LOC = "AB7" ;
-NET "ser_r[8]" LOC = "AA7" ;
-NET "ser_r[9]" LOC = "W9" ;
-NET "ser_r[10]" LOC = "W10" ;
-NET "ser_r[11]" LOC = "Y1" ;
-NET "ser_r[12]" LOC = "Y3" ;
-NET "ser_r[13]" LOC = "Y2" ;
-NET "ser_r[14]" LOC = "W4" ;
-NET "ser_r[15]" LOC = "W1" ;
-NET "ser_rklsb" LOC = "V9" ;
-NET "ser_rkmsb" LOC = "Y10" ;
-NET "cpld_start" LOC = "AA9" ;
-NET "cpld_mode" LOC = "U12" ;
-NET "cpld_done" LOC = "V12" ;
-NET "cpld_din" LOC = "AA14" ;
-NET "cpld_clk" LOC = "AB14" ;
-NET "cpld_detached" LOC = "V11" ;
-NET "cpld_init_b" LOC = "W12" ;
-NET "cpld_misc" LOC = "Y12" ;
-NET "adc_a[0]" LOC = "A14" | IOBDELAY= "NONE" ;
-NET "adc_a[1]" LOC = "B14" | IOBDELAY= "NONE" ;
-NET "adc_a[2]" LOC = "C13" | IOBDELAY= "NONE" ;
-NET "adc_a[3]" LOC = "D13" | IOBDELAY= "NONE" ;
-NET "adc_a[4]" LOC = "A13" | IOBDELAY= "NONE" ;
-NET "adc_a[5]" LOC = "B13" | IOBDELAY= "NONE" ;
-NET "adc_a[6]" LOC = "E12" | IOBDELAY= "NONE" ;
-NET "adc_a[7]" LOC = "C22" | IOBDELAY= "NONE" ;
-NET "adc_a[8]" LOC = "C20" | IOBDELAY= "NONE" ;
-NET "adc_a[9]" LOC = "C21" | IOBDELAY= "NONE" ;
-NET "adc_a[10]" LOC = "D20" | IOBDELAY= "NONE" ;
-NET "adc_a[11]" LOC = "D19" | IOBDELAY= "NONE" ;
-NET "adc_a[12]" LOC = "D21" | IOBDELAY= "NONE" ;
-NET "adc_a[13]" LOC = "E18" | IOBDELAY= "NONE" ;
-NET "adc_ovf_a" LOC = "F18" ;
-NET "adc_oen_a" LOC = "E19" ;
-NET "adc_pdn_a" LOC = "E20" ;
-NET "adc_b[0]" LOC = "A12" | IOBDELAY= "NONE";
-NET "adc_b[1]" LOC = "E16" | IOBDELAY= "NONE" ;
-NET "adc_b[2]" LOC = "F12" | IOBDELAY= "NONE" ;
-NET "adc_b[3]" LOC = "F13" | IOBDELAY= "NONE" ;
-NET "adc_b[4]" LOC = "F16" | IOBDELAY= "NONE" ;
-NET "adc_b[5]" LOC = "F17" | IOBDELAY= "NONE" ;
-NET "adc_b[6]" LOC = "C19" | IOBDELAY= "NONE" ;
-NET "adc_b[7]" LOC = "B20" | IOBDELAY= "NONE" ;
-NET "adc_b[8]" LOC = "B19" | IOBDELAY= "NONE" ;
-NET "adc_b[9]" LOC = "C18" | IOBDELAY= "NONE" ;
-NET "adc_b[10]" LOC = "D18" | IOBDELAY= "NONE" ;
-NET "adc_b[11]" LOC = "B18" | IOBDELAY= "NONE" ;
-NET "adc_b[12]" LOC = "D17" | IOBDELAY= "NONE" ;
-NET "adc_b[13]" LOC = "E17" | IOBDELAY= "NONE" ;
-NET "adc_ovf_b" LOC = "B17" ;
-NET "adc_oen_b" LOC = "C17" ;
-NET "adc_pdn_b" LOC = "D15" ;
-NET "dac_a[0]" LOC = "A5" ;
-NET "dac_a[1]" LOC = "B5" ;
-NET "dac_a[2]" LOC = "C5" ;
-NET "dac_a[3]" LOC = "D5" ;
-NET "dac_a[4]" LOC = "A4" ;
-NET "dac_a[5]" LOC = "B4" ;
-NET "dac_a[6]" LOC = "F6" ;
-NET "dac_a[7]" LOC = "D10" ;
-NET "dac_a[8]" LOC = "D9" ;
-NET "dac_a[9]" LOC = "A10" ;
-NET "dac_a[10]" LOC = "L2" ;
-NET "dac_a[11]" LOC = "L4" ;
-NET "dac_a[12]" LOC = "L3" ;
-NET "dac_a[13]" LOC = "L6" ;
-NET "dac_a[14]" LOC = "L5" ;
-NET "dac_a[15]" LOC = "K2" ;
-NET "dac_b[0]" LOC = "D11" ;
-NET "dac_b[1]" LOC = "E11" ;
-NET "dac_b[2]" LOC = "F11" ;
-NET "dac_b[3]" LOC = "B10" ;
-NET "dac_b[4]" LOC = "C10" ;
-NET "dac_b[5]" LOC = "E10" ;
-NET "dac_b[6]" LOC = "F10" ;
-NET "dac_b[7]" LOC = "A9" ;
-NET "dac_b[8]" LOC = "B9" ;
-NET "dac_b[9]" LOC = "E9" ;
-NET "dac_b[10]" LOC = "F9" ;
-NET "dac_b[11]" LOC = "A8" ;
-NET "dac_b[12]" LOC = "B8" ;
-NET "dac_b[13]" LOC = "D7" ;
-NET "dac_b[14]" LOC = "E7" ;
-NET "dac_b[15]" LOC = "B6" ;
-NET "dac_lock" LOC = "D6" ;
-NET "SCL" LOC = "A7" ;
-NET "SDA" LOC = "D8" ;
-NET "clk_en[0]" LOC = "C4" ;
-NET "clk_en[1]" LOC = "D1" ;
-NET "clk_sel[0]" LOC = "C3" ;
-NET "clk_sel[1]" LOC = "C2" ;
-NET "clk_func" LOC = "C12" ;
-NET "clk_status" LOC = "B12" ;
-NET "clk_fpga_p" LOC = "A11" ;
-NET "clk_fpga_n" LOC = "B11" ;
-NET "clk_to_mac" LOC = "AB12" ;
-NET "pps_in" LOC = "Y11" ;
-NET "sclk" LOC = "K5" ;
-NET "sen_clk" LOC = "K6" ;
-NET "sen_dac" LOC = "L1" ;
-NET "sdi" LOC = "J1" ;
-NET "sdo" LOC = "J2" ;
-NET "sen_tx_db" LOC = "C1" ;
-NET "sclk_tx_db" LOC = "D3" ;
-NET "sdo_tx_db" LOC = "G3" ;
-NET "sdi_tx_db" LOC = "G4" ;
-NET "sen_tx_adc" LOC = "G2" ;
-NET "sclk_tx_adc" LOC = "H1" ;
-NET "sdo_tx_adc" LOC = "H2" ;
-NET "sdi_tx_adc" LOC = "J4" ;
-NET "sen_tx_dac" LOC = "H4" ;
-NET "sclk_tx_dac" LOC = "J5" ;
-NET "sdi_tx_dac" LOC = "J6" ;
-NET "io_tx[0]" LOC = "K4" ;
-NET "io_tx[1]" LOC = "K3" ;
-NET "io_tx[2]" LOC = "G1" ;
-NET "io_tx[3]" LOC = "G5" ;
-NET "io_tx[4]" LOC = "H5" ;
-NET "io_tx[5]" LOC = "F3" ;
-NET "io_tx[6]" LOC = "F2" ;
-NET "io_tx[7]" LOC = "F5" ;
-NET "io_tx[8]" LOC = "G6" ;
-NET "io_tx[9]" LOC = "E2" ;
-NET "io_tx[10]" LOC = "E1" ;
-NET "io_tx[11]" LOC = "E3" ;
-NET "io_tx[12]" LOC = "F4" ;
-NET "io_tx[13]" LOC = "D2" ;
-NET "io_tx[14]" LOC = "D4" ;
-NET "io_tx[15]" LOC = "E4" ;
-NET "sen_rx_db" LOC = "D22" ;
-NET "sclk_rx_db" LOC = "F19" ;
-NET "sdo_rx_db" LOC = "G20" ;
-NET "sdi_rx_db" LOC = "H19" ;
-NET "sen_rx_adc" LOC = "H18" ;
-NET "sclk_rx_adc" LOC = "J17" ;
-NET "sdo_rx_adc" LOC = "H21" ;
-NET "sdi_rx_adc" LOC = "H22" ;
-NET "sen_rx_dac" LOC = "J18" ;
-NET "sclk_rx_dac" LOC = "J19" ;
-NET "sdi_rx_dac" LOC = "J21" ;
-NET "io_rx[0]" LOC = "L21" ;
-NET "io_rx[1]" LOC = "L20" ;
-NET "io_rx[2]" LOC = "L19" ;
-NET "io_rx[3]" LOC = "L18" ;
-NET "io_rx[4]" LOC = "L17" ;
-NET "io_rx[5]" LOC = "K22" ;
-NET "io_rx[6]" LOC = "K21" ;
-NET "io_rx[7]" LOC = "K20" ;
-NET "io_rx[8]" LOC = "G22" ;
-NET "io_rx[9]" LOC = "G21" ;
-NET "io_rx[10]" LOC = "F21" ;
-NET "io_rx[11]" LOC = "F20" ;
-NET "io_rx[12]" LOC = "G19" ;
-NET "io_rx[13]" LOC = "G18" ;
-NET "io_rx[14]" LOC = "G17" ;
-NET "io_rx[15]" LOC = "E22" ;
-
-NET "clk_to_mac" TNM_NET = "clk_to_mac";
-TIMESPEC "TS_clk_to_mac" = PERIOD "clk_to_mac" 8 ns HIGH 50 %;
-
-#NET "dsp_clk" TNM_NET = "dsp_clk";
-#TIMESPEC "TS_dsp_clk" = PERIOD "dsp_clk" 10 ns HIGH 50 %;
-
-NET "clk_fpga_p" TNM_NET = "clk_fpga_p";
-TIMESPEC "TS_clk_fpga_p" = PERIOD "clk_fpga_p" 10 ns HIGH 50 %;
-
-NET "cpld_clk" TNM_NET = "cpld_clk";
-TIMESPEC "TS_cpld_clk" = PERIOD "cpld_clk" 40 ns HIGH 50 %;
-
-NET "GMII_RX_CLK" TNM_NET = "GMII_RX_CLK";
-TIMESPEC "TS_GMII_RX_CLK" = PERIOD "GMII_RX_CLK" 8 ns HIGH 50 %;
-
-NET "ser_rx_clk" TNM_NET = "ser_rx_clk";
-TIMESPEC "TS_ser_rx_clk" = PERIOD "ser_rx_clk" 10 ns HIGH 50 %;
-
-#NET "wb_clk" TNM_NET = "wb_clk";
-#TIMESPEC "TS_wb_clk" = PERIOD "wb_clk" 20 ns HIGH 50 %;
-
-NET "GMII_RX_CLK" CLOCK_DEDICATED_ROUTE = FALSE;
-NET "cpld_clk" CLOCK_DEDICATED_ROUTE = FALSE;
-
-#NET "adc_a<*>" TNM_NET = ADC_DATA_GRP;
-#NET "adc_b<*>" TNM_NET = ADC_DATA_GRP;
-#TIMEGRP "ADC_DATA_GRP" OFFSET = IN 1 ns VALID 5 ns BEFORE "clk_fpga_p" RISING;
-
-#NET "adc_a<*>" OFFSET = IN 1 ns VALID 5 ns BEFORE "clk_fpga_p" RISING;
-#NET "adc_b<*>" OFFSET = IN 1 ns VALID 5 ns BEFORE "clk_fpga_p" RISING;
diff --git a/fpga/usrp2/top/u2_rev2/u2_rev2.v b/fpga/usrp2/top/u2_rev2/u2_rev2.v
deleted file mode 100644
index 517285e52..000000000
--- a/fpga/usrp2/top/u2_rev2/u2_rev2.v
+++ /dev/null
@@ -1,417 +0,0 @@
-`timescale 1ns / 1ps
-//////////////////////////////////////////////////////////////////////////////////
-
-module u2_rev2
- (
- // Misc, debug
- output [4:0] leds,
- output [31:0] debug,
- output [1:0] debug_clk,
- output uart_tx_o,
- input uart_rx_i,
-
- // Expansion
- input exp_pps_in_p, // Diff
- input exp_pps_in_n, // Diff
- output exp_pps_out_p, // Diff
- output exp_pps_out_n, // Diff
-
- // GMII
- // GMII-CTRL
- input GMII_COL,
- input GMII_CRS,
-
- // GMII-TX
- output reg [7:0] GMII_TXD,
- output reg GMII_TX_EN,
- output reg GMII_TX_ER,
- output GMII_GTX_CLK,
- input GMII_TX_CLK, // 100mbps clk
-
- // GMII-RX
- input [7:0] GMII_RXD,
- input GMII_RX_CLK,
- input GMII_RX_DV,
- input GMII_RX_ER,
-
- // GMII-Management
- inout MDIO,
- output MDC,
- input PHY_INTn, // open drain
- output PHY_RESETn,
- input PHY_CLK, // possibly use on-board osc
-
- // RAM
- inout [17:0] RAM_D,
- output [18:0] RAM_A,
- output RAM_CE1n,
- output RAM_CENn,
- output RAM_CLK,
- output RAM_WEn,
- output RAM_OEn,
- output RAM_LDn,
-
- // SERDES
- output ser_enable,
- output ser_prbsen,
- output ser_loopen,
- output ser_rx_en,
-
- output ser_tx_clk,
- output reg [15:0] ser_t,
- output reg ser_tklsb,
- output reg ser_tkmsb,
-
- input ser_rx_clk,
- input [15:0] ser_r,
- input ser_rklsb,
- input ser_rkmsb,
-
- // CPLD interface
- output cpld_start, // AA9
- output cpld_mode, // U12
- output cpld_done, // V12
- input cpld_din, // AA14 Now shared with CFG_Din
- input cpld_clk, // AB14 serial clock
- input cpld_detached,// V11 unused
- output cpld_init_b, // W12 unused dual purpose
- output cpld_misc, // Y12
-
- // ADC
- input [13:0] adc_a,
- input adc_ovf_a,
- output adc_oen_a,
- output adc_pdn_a,
-
- input [13:0] adc_b,
- input adc_ovf_b,
- output adc_oen_b,
- output adc_pdn_b,
-
- // DAC
- output reg [15:0] dac_a,
- output reg [15:0] dac_b,
- input dac_lock, // unused for now
-
- // I2C
- inout SCL,
- inout SDA,
-
- // Clock Gen Control
- output [1:0] clk_en,
- output [1:0] clk_sel,
- input clk_func, // FIXME is an input to control the 9510
- input clk_status,
-
- // Clocks
- input clk_fpga_p, // Diff
- input clk_fpga_n, // Diff
- input clk_to_mac,
- input pps_in,
-
- // Generic SPI
- output sclk,
- output sen_clk,
- output sen_dac,
- output sdi,
- input sdo,
-
- // TX DBoard
- output sen_tx_db,
- output sclk_tx_db,
- input sdo_tx_db,
- output sdi_tx_db,
-
- output sen_tx_adc,
- output sclk_tx_adc,
- input sdo_tx_adc,
- output sdi_tx_adc,
-
- output sen_tx_dac,
- output sclk_tx_dac,
- output sdi_tx_dac,
-
- inout [15:0] io_tx,
-
- // RX DBoard
- output sen_rx_db,
- output sclk_rx_db,
- input sdo_rx_db,
- output sdi_rx_db,
-
- output sen_rx_adc,
- output sclk_rx_adc,
- input sdo_rx_adc,
- output sdi_rx_adc,
-
- output sen_rx_dac,
- output sclk_rx_dac,
- output sdi_rx_dac,
-
- inout [15:0] io_rx
- );
-
- assign cpld_init_b = 0;
- // FPGA-specific pins connections
- wire clk_fpga, dsp_clk, clk_div, dcm_out, wb_clk, clock_ready;
- wire clk90, clk180, clk270;
-
- IBUFGDS clk_fpga_pin (.O(clk_fpga),.I(clk_fpga_p),.IB(clk_fpga_n));
- defparam clk_fpga_pin.IOSTANDARD = "LVPECL_25";
-
- wire exp_pps_in;
- IBUFDS exp_pps_in_pin (.O(exp_pps_in),.I(exp_pps_in_p),.IB(exp_pps_in_n));
- defparam exp_pps_in_pin.IOSTANDARD = "LVDS_25";
-
- wire exp_pps_out;
- OBUFDS exp_pps_out_pin (.O(exp_pps_out_p),.OB(exp_pps_out_n),.I(exp_pps_out));
- defparam exp_pps_out_pin.IOSTANDARD = "LVDS_25";
-
- reg [5:0] clock_ready_d;
- always @(posedge clk_fpga)
- clock_ready_d[5:0] <= {clock_ready_d[4:0],clock_ready};
- wire dcm_rst = ~&clock_ready_d & |clock_ready_d;
-
- wire adc_on_a, adc_on_b, adc_oe_a, adc_oe_b;
- assign adc_oen_a = ~adc_oe_a;
- assign adc_oen_b = ~adc_oe_b;
- assign adc_pdn_a = ~adc_on_a;
- assign adc_pdn_b = ~adc_on_b;
-
- reg [13:0] adc_a_reg1, adc_b_reg1, adc_a_reg2, adc_b_reg2;
- reg adc_ovf_a_reg1, adc_ovf_a_reg2, adc_ovf_b_reg1, adc_ovf_b_reg2;
-
- always @(posedge dsp_clk)
- begin
- adc_a_reg1 <= adc_a;
- adc_b_reg1 <= adc_b;
- adc_ovf_a_reg1 <= adc_ovf_a;
- adc_ovf_b_reg1 <= adc_ovf_b;
- end
-
- always @(posedge dsp_clk)
- begin
- adc_a_reg2 <= adc_a_reg1;
- adc_b_reg2 <= adc_b_reg1;
- adc_ovf_a_reg2 <= adc_ovf_a_reg1;
- adc_ovf_b_reg2 <= adc_ovf_b_reg1;
- end // always @ (posedge dsp_clk)
-
- // Handle Clocks
- DCM DCM_INST (.CLKFB(dsp_clk),
- .CLKIN(clk_fpga),
- .DSSEN(0),
- .PSCLK(0),
- .PSEN(0),
- .PSINCDEC(0),
- .RST(dcm_rst),
- .CLKDV(clk_div),
- .CLKFX(),
- .CLKFX180(),
- .CLK0(dcm_out),
- .CLK2X(),
- .CLK2X180(),
- .CLK90(clk90),
- .CLK180(clk180),
- .CLK270(clk270),
- .LOCKED(LOCKED_OUT),
- .PSDONE(),
- .STATUS());
- defparam DCM_INST.CLK_FEEDBACK = "1X";
- defparam DCM_INST.CLKDV_DIVIDE = 2.0;
- defparam DCM_INST.CLKFX_DIVIDE = 1;
- defparam DCM_INST.CLKFX_MULTIPLY = 4;
- defparam DCM_INST.CLKIN_DIVIDE_BY_2 = "FALSE";
- defparam DCM_INST.CLKIN_PERIOD = 10.000;
- defparam DCM_INST.CLKOUT_PHASE_SHIFT = "NONE";
- defparam DCM_INST.DESKEW_ADJUST = "SYSTEM_SYNCHRONOUS";
- defparam DCM_INST.DFS_FREQUENCY_MODE = "LOW";
- defparam DCM_INST.DLL_FREQUENCY_MODE = "LOW";
- defparam DCM_INST.DUTY_CYCLE_CORRECTION = "TRUE";
- defparam DCM_INST.FACTORY_JF = 16'h8080;
- defparam DCM_INST.PHASE_SHIFT = 0;
- defparam DCM_INST.STARTUP_WAIT = "FALSE";
-
- BUFG dspclk_BUFG (.I(dcm_out), .O(dsp_clk));
- BUFG wbclk_BUFG (.I(clk_div), .O(wb_clk));
-
- // I2C -- Don't use external transistors for open drain, the FPGA implements this
- IOBUF scl_pin(.O(scl_pad_i), .IO(SCL), .I(scl_pad_o), .T(scl_pad_oen_o));
- IOBUF sda_pin(.O(sda_pad_i), .IO(SDA), .I(sda_pad_o), .T(sda_pad_oen_o));
-
- // LEDs are active low outputs
- wire [4:0] leds_int;
- assign leds = 5'b01111 ^ leds_int; // all except eth are active-low
-
- // SPI
- wire miso, mosi, sclk_int;
- assign {sclk,sdi} = (~sen_clk | ~sen_dac) ? {sclk_int,mosi} : 2'b0;
- assign {sclk_tx_db,sdi_tx_db} = ~sen_tx_db ? {sclk_int,mosi} : 2'b0;
- assign {sclk_tx_dac,sdi_tx_dac} = ~sen_tx_dac ? {sclk_int,mosi} : 2'b0;
- assign {sclk_tx_adc,sdi_tx_adc} = ~sen_tx_adc ? {sclk_int,mosi} : 2'b0;
- assign {sclk_rx_db,sdi_rx_db} = ~sen_rx_db ? {sclk_int,mosi} : 2'b0;
- assign {sclk_rx_dac,sdi_rx_dac} = ~sen_rx_dac ? {sclk_int,mosi} : 2'b0;
- assign {sclk_rx_adc,sdi_rx_adc} = ~sen_rx_adc ? {sclk_int,mosi} : 2'b0;
-
- assign miso = (~sen_clk & sdo) | (~sen_dac & sdo) |
- (~sen_tx_db & sdo_tx_db) | (~sen_tx_adc & sdo_tx_adc) |
- (~sen_rx_db & sdo_rx_db) | (~sen_rx_adc & sdo_rx_adc);
-
- wire GMII_TX_EN_unreg, GMII_TX_ER_unreg;
- wire [7:0] GMII_TXD_unreg;
- wire GMII_GTX_CLK_int;
-
- always @(posedge GMII_GTX_CLK_int)
- begin
- GMII_TX_EN <= GMII_TX_EN_unreg;
- GMII_TX_ER <= GMII_TX_ER_unreg;
- GMII_TXD <= GMII_TXD_unreg;
- end
-
- OFDDRRSE OFDDRRSE_gmii_inst
- (.Q(GMII_GTX_CLK), // Data output (connect directly to top-level port)
- .C0(GMII_GTX_CLK_int), // 0 degree clock input
- .C1(~GMII_GTX_CLK_int), // 180 degree clock input
- .CE(1), // Clock enable input
- .D0(0), // Posedge data input
- .D1(1), // Negedge data input
- .R(0), // Synchronous reset input
- .S(0) // Synchronous preset input
- );
-
- wire ser_tklsb_unreg, ser_tkmsb_unreg;
- wire [15:0] ser_t_unreg;
- wire ser_tx_clk_int;
-
- always @(posedge ser_tx_clk_int)
- begin
- ser_tklsb <= ser_tklsb_unreg;
- ser_tkmsb <= ser_tkmsb_unreg;
- ser_t <= ser_t_unreg;
- end
-
- assign ser_tx_clk = clk_fpga;
-
- reg [15:0] ser_r_int;
- reg ser_rklsb_int, ser_rkmsb_int;
-
- always @(posedge ser_rx_clk)
- begin
- ser_r_int <= ser_r;
- ser_rklsb_int <= ser_rklsb;
- ser_rkmsb_int <= ser_rkmsb;
- end
-
- wire [15:0] dac_a_int, dac_b_int;
- always @(negedge dsp_clk) dac_a <= dac_a_int;
- always @(negedge dsp_clk) dac_b <= dac_b_int;
-
- /*
- OFDDRRSE OFDDRRSE_serdes_inst
- (.Q(ser_tx_clk), // Data output (connect directly to top-level port)
- .C0(ser_tx_clk_int), // 0 degree clock input
- .C1(~ser_tx_clk_int), // 180 degree clock input
- .CE(1), // Clock enable input
- .D0(0), // Posedge data input
- .D1(1), // Negedge data input
- .R(0), // Synchronous reset input
- .S(0) // Synchronous preset input
- );
- */
- u2_core #(.RAM_SIZE(32768))
- u2_core(.dsp_clk (dsp_clk),
- .wb_clk (wb_clk),
- .clock_ready (clock_ready),
- .clk_to_mac (clk_to_mac),
- .pps_in (pps_in),
- .leds (leds_int),
- .debug (debug[31:0]),
- .debug_clk (debug_clk[1:0]),
- .exp_pps_in (exp_pps_in),
- .exp_pps_out (exp_pps_out),
- .GMII_COL (GMII_COL),
- .GMII_CRS (GMII_CRS),
- .GMII_TXD (GMII_TXD_unreg[7:0]),
- .GMII_TX_EN (GMII_TX_EN_unreg),
- .GMII_TX_ER (GMII_TX_ER_unreg),
- .GMII_GTX_CLK (GMII_GTX_CLK_int),
- .GMII_TX_CLK (GMII_TX_CLK),
- .GMII_RXD (GMII_RXD[7:0]),
- .GMII_RX_CLK (GMII_RX_CLK),
- .GMII_RX_DV (GMII_RX_DV),
- .GMII_RX_ER (GMII_RX_ER),
- .MDIO (MDIO),
- .MDC (MDC),
- .PHY_INTn (PHY_INTn),
- .PHY_RESETn (PHY_RESETn),
- .ser_enable (ser_enable),
- .ser_prbsen (ser_prbsen),
- .ser_loopen (ser_loopen),
- .ser_rx_en (ser_rx_en),
- .ser_tx_clk (ser_tx_clk_int),
- .ser_t (ser_t_unreg[15:0]),
- .ser_tklsb (ser_tklsb_unreg),
- .ser_tkmsb (ser_tkmsb_unreg),
- .ser_rx_clk (ser_rx_clk),
- .ser_r (ser_r_int[15:0]),
- .ser_rklsb (ser_rklsb_int),
- .ser_rkmsb (ser_rkmsb_int),
- .cpld_start (cpld_start),
- .cpld_mode (cpld_mode),
- .cpld_done (cpld_done),
- .cpld_din (cpld_din),
- .cpld_clk (cpld_clk),
- .cpld_detached (cpld_detached),
- .cpld_misc (cpld_misc),
- .cpld_init_b (cpld_init_b),
- .por (~POR),
- .config_success (config_success),
- .adc_a (adc_a_reg2),
- .adc_ovf_a (adc_ovf_a_reg2),
- .adc_on_a (adc_on_a),
- .adc_oe_a (adc_oe_a),
- .adc_b (adc_b_reg2),
- .adc_ovf_b (adc_ovf_b_reg2),
- .adc_on_b (adc_on_b),
- .adc_oe_b (adc_oe_b),
- .dac_a (dac_a_int),
- .dac_b (dac_b_int),
- .scl_pad_i (scl_pad_i),
- .scl_pad_o (scl_pad_o),
- .scl_pad_oen_o (scl_pad_oen_o),
- .sda_pad_i (sda_pad_i),
- .sda_pad_o (sda_pad_o),
- .sda_pad_oen_o (sda_pad_oen_o),
- .clk_en (clk_en[1:0]),
- .clk_sel (clk_sel[1:0]),
- .clk_func (clk_func),
- .clk_status (clk_status),
- .sclk (sclk_int),
- .mosi (mosi),
- .miso (miso),
- .sen_clk (sen_clk),
- .sen_dac (sen_dac),
- .sen_tx_db (sen_tx_db),
- .sen_tx_adc (sen_tx_adc),
- .sen_tx_dac (sen_tx_dac),
- .sen_rx_db (sen_rx_db),
- .sen_rx_adc (sen_rx_adc),
- .sen_rx_dac (sen_rx_dac),
- .io_tx (io_tx[15:0]),
- .io_rx (io_rx[15:0]),
- .RAM_D (RAM_D),
- .RAM_A (RAM_A),
- .RAM_CE1n (RAM_CE1n),
- .RAM_CENn (RAM_CENn),
- .RAM_CLK (RAM_CLK),
- .RAM_WEn (RAM_WEn),
- .RAM_OEn (RAM_OEn),
- .RAM_LDn (RAM_LDn),
- .uart_tx_o (uart_tx_o),
- .uart_rx_i (uart_rx_i),
- .uart_baud_o (),
- .sim_mode (1'b0),
- .clock_divider (2)
- );
-
-endmodule // u2_rev2
diff --git a/fpga/usrp2/top/u2_rev3/Makefile b/fpga/usrp2/top/u2_rev3/Makefile
index 1fd8638d9..af93700c5 100644
--- a/fpga/usrp2/top/u2_rev3/Makefile
+++ b/fpga/usrp2/top/u2_rev3/Makefile
@@ -70,6 +70,7 @@ control_lib/ram_harv_cache.v \
control_lib/ram_loader.v \
control_lib/setting_reg.v \
control_lib/settings_bus.v \
+control_lib/settings_bus_crossclock.v \
control_lib/srl.v \
control_lib/system_control.v \
control_lib/wb_1master.v \
@@ -134,6 +135,8 @@ coregen/fifo_xlnx_64x36_2clk.v \
coregen/fifo_xlnx_64x36_2clk.xco \
coregen/fifo_xlnx_16x19_2clk.v \
coregen/fifo_xlnx_16x19_2clk.xco \
+coregen/fifo_xlnx_16x40_2clk.v \
+coregen/fifo_xlnx_16x40_2clk.xco \
extram/wb_zbt16_b.v \
opencores/8b10b/decode_8b10b.v \
opencores/8b10b/encode_8b10b.v \
@@ -199,7 +202,7 @@ top/u2_rev3/u2_rev3.v
# Process Properties
##################################################
export SYNTHESIZE_PROPERTIES := \
-"Number of Clock Buffers" 6 \
+"Number of Clock Buffers" 8 \
"Pack I/O Registers into IOBs" Yes \
"Optimization Effort" High \
"Optimize Instantiated Primitives" TRUE \
diff --git a/fpga/usrp2/top/u2_rev3/u2_rev3.ucf b/fpga/usrp2/top/u2_rev3/u2_rev3.ucf
index 255a298ac..6aa699d2a 100644
--- a/fpga/usrp2/top/u2_rev3/u2_rev3.ucf
+++ b/fpga/usrp2/top/u2_rev3/u2_rev3.ucf
@@ -331,3 +331,5 @@ NET "cpld_clk" CLOCK_DEDICATED_ROUTE = FALSE;
#NET "adc_a<*>" OFFSET = IN 1 ns VALID 5 ns BEFORE "clk_fpga_p" RISING;
#NET "adc_b<*>" OFFSET = IN 1 ns VALID 5 ns BEFORE "clk_fpga_p" RISING;
+
+TIMESPEC "TS_clk_div_to_dsp_clk" = FROM "clk_div" TO "dcm_out" 10 ns;
diff --git a/fpga/usrp2/top/u2_rev3/u2_rev3.v b/fpga/usrp2/top/u2_rev3/u2_rev3.v
index 23a825007..3a43e4ffe 100644
--- a/fpga/usrp2/top/u2_rev3/u2_rev3.v
+++ b/fpga/usrp2/top/u2_rev3/u2_rev3.v
@@ -171,8 +171,15 @@ module u2_rev3
wd <= wd + 1;
assign WDI = wd[15];
- IBUFGDS clk_fpga_pin (.O(clk_fpga),.I(clk_fpga_p),.IB(clk_fpga_n));
+ wire clk_fpga_unbuf;
+
+ IBUFGDS clk_fpga_pin (.O(clk_fpga_unbuf),.I(clk_fpga_p),.IB(clk_fpga_n));
+ BUFG clk_fpga_BUF (.O(clk_fpga),.I(clk_fpga_unbuf));
+
defparam clk_fpga_pin.IOSTANDARD = "LVPECL_25";
+
+ wire cpld_clock_buf;
+ BUFG cpld_clock_BUF (.O(cpld_clock_buf),.I(cpld_clock));
wire exp_pps_in;
IBUFDS exp_pps_in_pin (.O(exp_pps_in),.I(exp_pps_in_p),.IB(exp_pps_in_n));
@@ -310,7 +317,9 @@ module u2_rev3
reg [15:0] ser_r_int;
reg ser_rklsb_int, ser_rkmsb_int;
- always @(posedge ser_rx_clk)
+ wire ser_rx_clk_buf;
+ BUFG ser_rx_clk_BUF (.O(ser_rx_clk_buf),.I(ser_rx_clk));
+ always @(posedge ser_rx_clk_buf)
begin
ser_r_int <= ser_r;
ser_rklsb_int <= ser_rklsb;
@@ -367,7 +376,7 @@ module u2_rev3
.ser_t (ser_t_unreg[15:0]),
.ser_tklsb (ser_tklsb_unreg),
.ser_tkmsb (ser_tkmsb_unreg),
- .ser_rx_clk (ser_rx_clk),
+ .ser_rx_clk (ser_rx_clk_buf),
.ser_r (ser_r_int[15:0]),
.ser_rklsb (ser_rklsb_int),
.ser_rkmsb (ser_rkmsb_int),
diff --git a/fpga/usrp2/vrt/vita_rx_control.v b/fpga/usrp2/vrt/vita_rx_control.v
index 669b8299d..742dd47e0 100644
--- a/fpga/usrp2/vrt/vita_rx_control.v
+++ b/fpga/usrp2/vrt/vita_rx_control.v
@@ -31,13 +31,13 @@ module vita_rx_control
wire [63:0] rcvtime_pre;
reg [63:0] rcvtime;
- wire [29:0] numlines_pre;
- wire send_imm_pre, chain_pre;
- reg send_imm, chain;
+ wire [28:0] numlines_pre;
+ wire send_imm_pre, chain_pre, reload_pre;
+ reg send_imm, chain, reload;
wire full_ctrl, read_ctrl, empty_ctrl, write_ctrl;
reg sc_pre2;
wire [33:0] fifo_line;
- reg [29:0] lines_left;
+ reg [28:0] lines_left, lines_total;
reg [2:0] ibs_state;
wire now, early, late;
wire sample_fifo_in_rdy;
@@ -67,7 +67,7 @@ module vita_rx_control
shortfifo #(.WIDTH(96)) commandfifo
(.clk(clk),.rst(reset),.clear(clear_int),
.datain({new_command,new_time}), .write(write_ctrl&~full_ctrl), .full(full_ctrl),
- .dataout({send_imm_pre,chain_pre,numlines_pre,rcvtime_pre}),
+ .dataout({send_imm_pre,chain_pre,reload_pre,numlines_pre,rcvtime_pre}),
.read(read_ctrl), .empty(empty_ctrl),
.occupied(command_queue_len), .space() );
@@ -98,7 +98,7 @@ module vita_rx_control
.src_rdy_o(sample_fifo_src_rdy_o), .dst_rdy_i(sample_fifo_dst_rdy_i),
.space(), .occupied() );
- // Inband Signalling State Machine
+ // Inband Signallling State Machine
time_compare
time_compare (.time_now(vita_time), .trigger_time(rcvtime), .now(now), .early(early), .late(late));
@@ -111,9 +111,11 @@ module vita_rx_control
begin
ibs_state <= IBS_IDLE;
lines_left <= 0;
+ lines_total <= 0;
rcvtime <= 0;
send_imm <= 0;
chain <= 0;
+ reload <= 0;
end
else
case(ibs_state)
@@ -121,10 +123,12 @@ module vita_rx_control
if(~empty_ctrl)
begin
lines_left <= numlines_pre;
+ lines_total <= numlines_pre;
rcvtime <= rcvtime_pre;
ibs_state <= IBS_WAITING;
send_imm <= send_imm_pre;
chain <= chain_pre;
+ reload <= reload_pre;
end
IBS_WAITING :
if(go_now)
@@ -141,14 +145,21 @@ module vita_rx_control
if(lines_left == 1)
if(~chain)
ibs_state <= IBS_IDLE;
+ else if(empty_ctrl & reload)
+ begin
+ ibs_state <= IBS_RUNNING;
+ lines_left <= lines_total;
+ end
else if(empty_ctrl)
ibs_state <= IBS_BROKENCHAIN;
else
begin
lines_left <= numlines_pre;
+ lines_total <= numlines_pre;
rcvtime <= rcvtime_pre;
send_imm <= send_imm_pre;
chain <= chain_pre;
+ reload <= reload_pre;
if(numlines_pre == 0) // If we are told to stop here
ibs_state <= IBS_IDLE;
else
@@ -178,3 +189,4 @@ module vita_rx_control
{ 2'b0, overrun, chain_pre, sample_fifo_in_rdy, attempt_sample_write, sample_fifo_src_rdy_o,sample_fifo_dst_rdy_i} };
endmodule // rx_control
+
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt
index f2725e4b3..0b2d3f012 100644
--- a/host/CMakeLists.txt
+++ b/host/CMakeLists.txt
@@ -62,6 +62,7 @@ IF(UNIX)
UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-ansi HAVE_ANSI)
#only export symbols that are declared to be part of the uhd api:
UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN)
+ UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-O3 HAVE_O3) #have some optimizations
ENDIF(UNIX)
IF(WIN32)
diff --git a/host/README b/host/README
index e67bb25f8..6eaf6bb42 100644
--- a/host/README
+++ b/host/README
@@ -17,6 +17,7 @@ LF RX
LF TX
RFX Series
XCVR 2450
+WBX Series
########################################################################
# Documentation
diff --git a/host/apps/omap_debug/usrp-e-led.c b/host/apps/omap_debug/usrp-e-led.c
index d1b6c8996..30fbb66e0 100644
--- a/host/apps/omap_debug/usrp-e-led.c
+++ b/host/apps/omap_debug/usrp-e-led.c
@@ -20,16 +20,16 @@ int main(int argc, char *argv[])
fp = open("/dev/usrp_e0", O_RDWR);
printf("fp = %d\n", fp);
- d.offset = UE_REG_MISC_BASE;
+ d.offset = UE_REG_MISC_BASE+14;
d.count = 1;
- while (1) {
- for (i=0; i<8; i++) {
- d.buf[0] = i;
- ret = ioctl(fp, USRP_E_WRITE_CTL16, &d);
- sleep(1);
- }
- }
+ d.buf[0] = 0x4020;
+ ret = ioctl(fp, USRP_E_WRITE_CTL16, &d);
+
+ sleep(10);
+
+ d.buf[0] = 0x0;
+ ret = ioctl(fp, USRP_E_WRITE_CTL16, &d);
return 0;
}
diff --git a/host/docs/build.rst b/host/docs/build.rst
index d28682764..f5a8dac8d 100644
--- a/host/docs/build.rst
+++ b/host/docs/build.rst
@@ -8,9 +8,14 @@ UHD - Build Guide
Build Dependencies
------------------------------------------------------------------------
-**Unix Notes:**
+**Linux Notes:**
The dependencies can be acquired through the package manager.
+**Mac OS X Notes:**
+Install the "Xcode Developer Tools" to get the build tools (gcc and make).
+Use MacPorts to get the Boost and Cheetah dependencies.
+Other dependencies can be downloaded as dmg installers from the web.
+
**Windows Notes:**
The dependencies can be acquired through installable exe files.
Usually, the windows installer can be found on the project's website.
@@ -27,12 +32,13 @@ or install msysgit from http://code.google.com/p/msysgit/downloads/list
^^^^^^^^^^^^^^^^
C++
^^^^^^^^^^^^^^^^
-On unix, this is GCC 4.0 and above. On windows, this is MSVC 2008.
+On Unix, this is GCC 4.0 and above. On Windows, this is MSVC 2008.
Other compilers have not been tested yet or confirmed working.
^^^^^^^^^^^^^^^^
CMake
^^^^^^^^^^^^^^^^
+* **Purpose:** generates project build files
* **Version:** at least 2.8
* **Required for:** build time
* **Download URL:** http://www.cmake.org/cmake/resources/software.html
@@ -40,6 +46,7 @@ CMake
^^^^^^^^^^^^^^^^
Boost
^^^^^^^^^^^^^^^^
+* **Purpose:** C++ library
* **Version:** at least 3.6 unix, at least 4.0 windows
* **Required for:** build time + run time
* **Download URL:** http://www.boost.org/users/download/
@@ -48,13 +55,15 @@ Boost
^^^^^^^^^^^^^^^^
Python
^^^^^^^^^^^^^^^^
+* **Purpose:** used by Cheetah and utility scripts
* **Version:** at least 2.6
-* **Required for:** build time
+* **Required for:** build time + run time utility scripts
* **Download URL:** http://www.python.org/download/
^^^^^^^^^^^^^^^^
Cheetah
^^^^^^^^^^^^^^^^
+* **Purpose:** source code generation
* **Version:** at least 2.0
* **Required for:** build time
* **Download URL:** http://www.cheetahtemplate.org/download.html
@@ -63,9 +72,17 @@ Cheetah
^^^^^^^^^^^^^^^^
Doxygen
^^^^^^^^^^^^^^^^
+* **Purpose:** generates html api documentation
* **Required for:** build time (optional)
* **Download URL:** http://www.stack.nl/~dimitri/doxygen/download.html#latestsrc
+^^^^^^^^^^^^^^^^
+Docutils
+^^^^^^^^^^^^^^^^
+* **Purpose:** generates html user manual
+* **Required for:** build time (optional)
+* **Download URL:** http://docutils.sourceforge.net/
+
------------------------------------------------------------------------
Build Instructions (Unix)
------------------------------------------------------------------------
@@ -80,7 +97,7 @@ Generate Makefiles with cmake
cd build
cmake ../
-For a custom prefix, use: cmake -DCMAKE_INSTALL_PREFIX=<myprefix> ../
+For a custom prefix, use: cmake -DCMAKE_INSTALL_PREFIX=<prefix> ../
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Build and install
@@ -92,11 +109,15 @@ Build and install
sudo make install
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Setup the library path
+Setup the library path (Linux)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Make sure that libuhd.so is in your LD_LIBRARY_PATH
or add it to /etc/ld.so.conf and make sure to run sudo ldconfig
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Setup the library path (Mac OS X)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Make sure that libuhd.dylib is in your DYLD_LIBRARY_PATH
------------------------------------------------------------------------
Build Instructions (Windows)
diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst
index d08b752a6..a320f86cb 100644
--- a/host/docs/dboards.rst
+++ b/host/docs/dboards.rst
@@ -62,3 +62,14 @@ not doing so will yeild undefined results.
The XCVR2450 uses a common LO for both receive and transmit.
Even though the API allows the RX and TX LOs to be individually set,
a change of one LO setting will be reflected in the other LO setting.
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+WBX Series
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Transmit Antennas: **TX/RX**
+
+Receive Antennas: **TX/RX** or **RX2**
+
+The user may set the receive antenna to be TX/RX or RX2.
+However, when using an RFX board in full-duplex mode,
+the receive antenna will always be set to RX2, regardless of the settings.
diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst
index dfde06b27..1bd95cefa 100644
--- a/host/docs/usrp2.rst
+++ b/host/docs/usrp2.rst
@@ -45,22 +45,33 @@ Run the following commands:
Load the images onto the SD card
------------------------------------------------------------------------
**Warning!**
-Use the u2_flash_tool with caution. If you specify the wrong device node,
+Use the usrp2_card_burner.py with caution. If you specify the wrong device node,
you could overwrite your hard drive. Make sure that --dev= specifies the SD card.
-Load the FPGA image:
+Use the *--list* option to get a list of possible raw devices.
+The list result will filter out disk partitions and devices too large to be the sd card.
+The list option has been implemented on Linux, Mac OS X, and Windows.
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Use the card burner tool (unix)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- cd <uhd-repo-path>/firmware/microblaze
- sudo ./u2_flash_tool --dev=/dev/sd<XXX> -t fpga -w <path_to_fpga_image>
+ sudo <prefix>/share/uhd/utils/usrp2_card_burner_gui.py
+
+ -- OR --
-Load the firmware image:
+ cd <prefix>/share/uhd/utils
+ sudo ./usrp2_card_burner.py --dev=/dev/sd<XXX> --fpga=<path_to_fpga_image>
+ sudo ./usrp2_card_burner.py --dev=/dev/sd<XXX> --fw=<path_to_firmware_image>
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Use the card burner tool (windows)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- cd <uhd-repo-path>/firmware/microblaze directory
- sudo ./u2_flash_tool --dev=/dev/sd<XXX> -t s/w -w <path_to_firmware_image>
+ <path_to_python.exe> <prefix>/share/uhd/utils/usrp2_card_burner_gui.py
+
------------------------------------------------------------------------
Setup networking
@@ -103,7 +114,7 @@ Run the following commands:
::
cd <prefix>/share/uhd/utils
- ./usrp_burner --addr=192.168.10.2 --new-ip=192.168.10.3
+ ./usrp_addr_burner --addr=192.168.10.2 --new-ip=192.168.10.3
**Method 2 (Linux Only):**
This method assumes that you do not know the IP address of your USRP2.
diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt
index 242857625..a537c0901 100644
--- a/host/examples/CMakeLists.txt
+++ b/host/examples/CMakeLists.txt
@@ -18,3 +18,7 @@
ADD_EXECUTABLE(rx_timed_samples rx_timed_samples.cpp)
TARGET_LINK_LIBRARIES(rx_timed_samples uhd)
INSTALL(TARGETS rx_timed_samples RUNTIME DESTINATION ${PKG_DATA_DIR}/examples)
+
+ADD_EXECUTABLE(tx_timed_samples tx_timed_samples.cpp)
+TARGET_LINK_LIBRARIES(tx_timed_samples uhd)
+INSTALL(TARGETS tx_timed_samples RUNTIME DESTINATION ${PKG_DATA_DIR}/examples)
diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp
index 4b8774036..64da260d5 100644
--- a/host/examples/rx_timed_samples.cpp
+++ b/host/examples/rx_timed_samples.cpp
@@ -29,7 +29,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::string args;
int seconds_in_future;
size_t total_num_samps;
- double rx_rate;
+ double rx_rate, freq;
//setup the program options
po::options_description desc("Allowed options");
@@ -39,10 +39,11 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
("secs", po::value<int>(&seconds_in_future)->default_value(3), "number of seconds in the future to receive")
("nsamps", po::value<size_t>(&total_num_samps)->default_value(1000), "total number of samples to receive")
("rxrate", po::value<double>(&rx_rate)->default_value(100e6/16), "rate of incoming samples")
+ ("freq", po::value<double>(&freq)->default_value(0), "rf center frequency in Hz")
;
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
- po::notify(vm);
+ po::notify(vm);
//print the help message
if (vm.count("help")){
@@ -62,6 +63,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
sdev->set_rx_rate(rx_rate);
std::cout << boost::format("Actual RX Rate: %f Msps...") % (sdev->get_rx_rate()/1e6) << std::endl;
std::cout << boost::format("Setting device timestamp to 0...") << std::endl;
+ sdev->set_rx_freq(freq);
sdev->set_time_now(uhd::time_spec_t(0));
//setup streaming
@@ -78,11 +80,16 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
size_t num_acc_samps = 0; //number of accumulated samples
while(num_acc_samps < total_num_samps){
uhd::rx_metadata_t md;
- std::complex<float> buff[1000];
+ std::vector<std::complex<float> > buff(dev->get_max_recv_samps_per_packet());
size_t num_rx_samps = dev->recv(
- boost::asio::buffer(buff, sizeof(buff)),
- md, uhd::io_type_t::COMPLEX_FLOAT32
+ boost::asio::buffer(buff),
+ md, uhd::io_type_t::COMPLEX_FLOAT32,
+ uhd::device::RECV_MODE_ONE_PACKET
);
+ if (num_rx_samps == 0 and num_acc_samps > 0){
+ std::cout << "Got timeout before all samples received, possible packet loss, exiting loop..." << std::endl;
+ break;
+ }
if (num_rx_samps == 0) continue; //wait for packets with contents
std::cout << boost::format("Got packet: %u samples, %u secs, %u nsecs")
diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp
new file mode 100644
index 000000000..e9e0c785e
--- /dev/null
+++ b/host/examples/tx_timed_samples.cpp
@@ -0,0 +1,92 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/safe_main.hpp>
+#include <uhd/usrp/simple_usrp.hpp>
+#include <boost/program_options.hpp>
+#include <boost/format.hpp>
+#include <iostream>
+#include <complex>
+
+namespace po = boost::program_options;
+
+int UHD_SAFE_MAIN(int argc, char *argv[]){
+ //variables to be set by po
+ std::string args;
+ int seconds_in_future;
+ size_t total_num_samps;
+ double tx_rate, freq;
+ float ampl;
+
+ //setup the program options
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "help message")
+ ("args", po::value<std::string>(&args)->default_value(""), "simple uhd device address args")
+ ("secs", po::value<int>(&seconds_in_future)->default_value(3), "number of seconds in the future to transmit")
+ ("nsamps", po::value<size_t>(&total_num_samps)->default_value(1000), "total number of samples to transmit")
+ ("txrate", po::value<double>(&tx_rate)->default_value(100e6/16), "rate of outgoing samples")
+ ("freq", po::value<double>(&freq)->default_value(0), "rf center frequency in Hz")
+ ("ampl", po::value<float>(&ampl)->default_value(float(0.3)), "amplitude of each sample")
+ ;
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //print the help message
+ if (vm.count("help")){
+ std::cout << boost::format("UHD TX Timed Samples %s") % desc << std::endl;
+ return ~0;
+ }
+
+ //create a usrp device
+ std::cout << std::endl;
+ std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
+ uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args);
+ uhd::device::sptr dev = sdev->get_device();
+ std::cout << boost::format("Using Device: %s") % sdev->get_name() << std::endl;
+
+ //set properties on the device
+ std::cout << boost::format("Setting TX Rate: %f Msps...") % (tx_rate/1e6) << std::endl;
+ sdev->set_tx_rate(tx_rate);
+ std::cout << boost::format("Actual TX Rate: %f Msps...") % (sdev->get_tx_rate()/1e6) << std::endl;
+ std::cout << boost::format("Setting device timestamp to 0...") << std::endl;
+ sdev->set_tx_freq(freq);
+ sdev->set_time_now(uhd::time_spec_t(0));
+
+ //data to send
+ std::vector<std::complex<float> > buff(total_num_samps, std::complex<float>(ampl, ampl));
+ uhd::tx_metadata_t md;
+ md.start_of_burst = true;
+ md.end_of_burst = true;
+ md.has_time_spec = true;
+ md.time_spec = uhd::time_spec_t(seconds_in_future);
+
+ //send the entire buffer, let the driver handle fragmentation
+ size_t num_tx_samps = dev->send(
+ boost::asio::buffer(buff),
+ md, uhd::io_type_t::COMPLEX_FLOAT32,
+ uhd::device::SEND_MODE_FULL_BUFF
+ );
+ std::cout << std::endl << boost::format("Sent %d samples") % num_tx_samps << std::endl;
+
+
+ //finished
+ std::cout << std::endl << "Done!" << std::endl << std::endl;
+
+ return 0;
+}
diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp
index 32eafc89b..fea95145c 100644
--- a/host/include/uhd/config.hpp
+++ b/host/include/uhd/config.hpp
@@ -76,4 +76,13 @@
#define UHD_LOCAL
#endif // UHD_DLL
+// Define force inline macro
+#ifdef BOOST_MSVC
+ #define UHD_INLINE __forceinline
+#elif defined(__GNUG__) && __GNUG__ >= 4
+ #define UHD_INLINE inline __attribute__((always_inline))
+#else
+ #define UHD_INLINE inline
+#endif
+
#endif /* INCLUDED_UHD_CONFIG_HPP */
diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp
index ae75e6dc8..d3e9015c4 100644
--- a/host/include/uhd/device.hpp
+++ b/host/include/uhd/device.hpp
@@ -77,15 +77,35 @@ public:
static sptr make(const device_addr_t &hint, size_t which = 0);
/*!
+ * Send modes for the device send routine.
+ */
+ enum send_mode_t{
+ //! Tells the send routine to send the entire buffer
+ SEND_MODE_FULL_BUFF = 0,
+ //! Tells the send routine to return after one packet
+ SEND_MODE_ONE_PACKET = 1
+ };
+
+ /*!
+ * Recv modes for the device recv routine.
+ */
+ enum recv_mode_t{
+ //! Tells the recv routine to recv the entire buffer
+ RECV_MODE_FULL_BUFF = 0,
+ //! Tells the recv routine to return after one packet
+ RECV_MODE_ONE_PACKET = 1
+ };
+
+ /*!
* Send a buffer containing IF data with its metadata.
*
* Send handles fragmentation as follows:
- * If the buffer has more samples than the maximum supported,
- * the send method will send the maximum number of samples
- * as supported by the transport and return the number sent.
- * In this case, the end of burst flag will be forced to false.
- * It is up to the caller to call send again on the un-sent
- * portions of the buffer, until the buffer is exhausted.
+ * If the buffer has more samples than the maximum per packet,
+ * the send method will fragment the samples across several packets.
+ * Send will respect the burst flags when fragmenting to ensure
+ * that start of burst can only be set on the first fragment and
+ * that end of burst can only be set on the final fragment.
+ * Fragmentation only applies in the full buffer send mode.
*
* This is a blocking call and will not return until the number
* of samples returned have been read out of the buffer.
@@ -93,12 +113,14 @@ public:
* \param buff a buffer pointing to some read-only memory
* \param metadata data describing the buffer's contents
* \param io_type the type of data loaded in the buffer
+ * \param send_mode tells send how to unload the buffer
* \return the number of samples sent
*/
virtual size_t send(
const boost::asio::const_buffer &buff,
const tx_metadata_t &metadata,
- const io_type_t &io_type
+ const io_type_t &io_type,
+ send_mode_t send_mode
) = 0;
/*!
@@ -123,16 +145,35 @@ public:
* immediately when no packets are available to the transport layer,
* and that the timeout duration is reasonably tuned for performance.
*
+ * When using the full buffer recv mode, the metadata only applies
+ * to the first packet received and written into the recv buffer.
+ * Use the one packet recv mode to get per packet metadata.
+ *
* \param buff the buffer to fill with IF data
* \param metadata data to fill describing the buffer
* \param io_type the type of data to fill into the buffer
+ * \param recv_mode tells recv how to load the buffer
* \return the number of samples received
*/
virtual size_t recv(
const boost::asio::mutable_buffer &buff,
rx_metadata_t &metadata,
- const io_type_t &io_type
+ const io_type_t &io_type,
+ recv_mode_t recv_mode
) = 0;
+
+ /*!
+ * Get the maximum number of samples per packet on send.
+ * \return the number of samples
+ */
+ virtual size_t get_max_send_samps_per_packet(void) const = 0;
+
+ /*!
+ * Get the maximum number of samples per packet on recv.
+ * \return the number of samples
+ */
+ virtual size_t get_max_recv_samps_per_packet(void) const = 0;
+
};
} //namespace uhd
diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp
index 4fc1df9de..52c6d4143 100644
--- a/host/include/uhd/transport/zero_copy.hpp
+++ b/host/include/uhd/transport/zero_copy.hpp
@@ -35,17 +35,18 @@ public:
typedef boost::shared_ptr<managed_recv_buffer> sptr;
/*!
+ * Managed recv buffer destructor:
* Signal to the transport that we are done with the buffer.
* This should be called to release the buffer to the transport.
* After calling, the referenced memory should be considered invalid.
*/
- virtual void done(void) = 0;
+ virtual ~managed_recv_buffer(void){};
/*!
* Get the size of the underlying buffer.
* \return the number of bytes
*/
- size_t size(void){
+ size_t size(void) const{
return boost::asio::buffer_size(this->get());
}
@@ -53,7 +54,7 @@ public:
* Get a pointer to the underlying buffer.
* \return a pointer into memory
*/
- template <class T> T cast(void){
+ template <class T> T cast(void) const{
return boost::asio::buffer_cast<T>(this->get());
}
@@ -63,7 +64,7 @@ private:
* The buffer has a reference to memory and a size.
* \return a boost asio const buffer
*/
- virtual const boost::asio::const_buffer &get(void) = 0;
+ virtual const boost::asio::const_buffer &get(void) const = 0;
};
/*!
@@ -81,13 +82,13 @@ public:
* After calling, the referenced memory should be considered invalid.
* \param num_bytes the number of bytes written into the buffer
*/
- virtual void done(size_t num_bytes) = 0;
+ virtual void commit(size_t num_bytes) = 0;
/*!
* Get the size of the underlying buffer.
* \return the number of bytes
*/
- size_t size(void){
+ size_t size(void) const{
return boost::asio::buffer_size(this->get());
}
@@ -95,7 +96,7 @@ public:
* Get a pointer to the underlying buffer.
* \return a pointer into memory
*/
- template <class T> T cast(void){
+ template <class T> T cast(void) const{
return boost::asio::buffer_cast<T>(this->get());
}
@@ -105,7 +106,7 @@ private:
* The buffer has a reference to memory and a size.
* \return a boost asio mutable buffer
*/
- virtual const boost::asio::mutable_buffer &get(void) = 0;
+ virtual const boost::asio::mutable_buffer &get(void) const = 0;
};
/*!
diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp
index b5fb11120..50a2b5c3b 100644
--- a/host/include/uhd/types/dict.hpp
+++ b/host/include/uhd/types/dict.hpp
@@ -46,7 +46,7 @@ namespace uhd{
* \param first the begin iterator
* \param last the end iterator
*/
- template <class InputIterator>
+ template <typename InputIterator>
dict(InputIterator first, InputIterator last){
for(InputIterator it = first; it != last; it++){
_map.push_back(*it);
diff --git a/host/include/uhd/types/mac_addr.hpp b/host/include/uhd/types/mac_addr.hpp
index 3cd1fe86b..0ced2e734 100644
--- a/host/include/uhd/types/mac_addr.hpp
+++ b/host/include/uhd/types/mac_addr.hpp
@@ -19,7 +19,7 @@
#define INCLUDED_UHD_TYPES_MAC_ADDR_HPP
#include <uhd/config.hpp>
-#include <boost/cstdint.hpp>
+#include <uhd/types/serial.hpp>
#include <string>
namespace uhd{
@@ -30,14 +30,12 @@ namespace uhd{
*/
class UHD_API mac_addr_t{
public:
- static const size_t hlen = 6;
-
/*!
* Create a mac address a byte array.
- * \param bytes a pointer for the byte array
+ * \param bytes a vector of bytes
* \return a new mac address
*/
- static mac_addr_t from_bytes(const boost::uint8_t *bytes);
+ static mac_addr_t from_bytes(const byte_vector_t &bytes);
/*!
* Create a mac address from a string.
@@ -48,9 +46,9 @@ namespace uhd{
/*!
* Get the byte representation of the mac address.
- * \return a pointer to the internal byte array
+ * \return a vector of bytes
*/
- const boost::uint8_t *to_bytes(void) const;
+ byte_vector_t to_bytes(void) const;
/*!
* Get the string representation of this mac address.
@@ -59,8 +57,8 @@ namespace uhd{
std::string to_string(void) const;
private:
- mac_addr_t(const boost::uint8_t *bytes); //private constructor
- boost::uint8_t _bytes[hlen]; //internal representation
+ mac_addr_t(const byte_vector_t &bytes); //private constructor
+ const byte_vector_t _bytes; //internal representation
};
} //namespace uhd
diff --git a/host/include/uhd/types/otw_type.hpp b/host/include/uhd/types/otw_type.hpp
index f10664584..8e3e65d78 100644
--- a/host/include/uhd/types/otw_type.hpp
+++ b/host/include/uhd/types/otw_type.hpp
@@ -55,6 +55,12 @@ namespace uhd{
BO_NOT_APPLICABLE = '|'
} byteorder;
+ /*!
+ * Get the sample size of this otw type.
+ * \return the size of a sample in bytes
+ */
+ size_t get_sample_size(void) const;
+
otw_type_t(void);
};
diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp
index 1214a1a2f..7ecfcd3c0 100644
--- a/host/include/uhd/usrp/dboard_iface.hpp
+++ b/host/include/uhd/usrp/dboard_iface.hpp
@@ -68,19 +68,29 @@ public:
virtual float read_aux_adc(unit_t unit, int which_adc) = 0;
/*!
+ * Set a daughterboard output pin control source.
+ * By default, the outputs are all GPIO controlled.
+ *
+ * \param unit which unit rx or tx
+ * \param value 16-bits, 0=GPIO controlled, 1=ATR controlled
+ */
+ virtual void set_pin_ctrl(unit_t unit, boost::uint16_t value) = 0;
+
+ /*!
* Set a daughterboard ATR register.
*
* \param unit which unit rx or tx
* \param reg which ATR register to set
- * \param value 16-bits, 0=FPGA output low, 1=FPGA output high
+ * \param value 16-bits, 0=ATR output low, 1=ATR output high
*/
virtual void set_atr_reg(unit_t unit, atr_reg_t reg, boost::uint16_t value) = 0;
/*!
* Set daughterboard GPIO data direction register.
+ * By default, the GPIO pins are all inputs.
*
* \param unit which unit rx or tx
- * \param value 16-bits, 0=FPGA input, 1=FPGA output
+ * \param value 16-bits, 0=GPIO input, 1=GPIO output
*/
virtual void set_gpio_ddr(unit_t unit, boost::uint16_t value) = 0;
@@ -88,6 +98,14 @@ public:
* Read daughterboard GPIO pin values.
*
* \param unit which unit rx or tx
+ * \param value 16-bits, 0=GPIO output low, 1=GPIO output high
+ */
+ virtual void write_gpio(unit_t unit, boost::uint16_t value) = 0;
+
+ /*!
+ * Read daughterboard GPIO pin values.
+ *
+ * \param unit which unit rx or tx
* \return the value of the gpio unit
*/
virtual boost::uint16_t read_gpio(unit_t unit) = 0;
diff --git a/host/include/uhd/usrp/dboard_props.hpp b/host/include/uhd/usrp/dboard_props.hpp
index 0208a6c2c..4d5c5efbd 100644
--- a/host/include/uhd/usrp/dboard_props.hpp
+++ b/host/include/uhd/usrp/dboard_props.hpp
@@ -30,7 +30,8 @@ namespace uhd{ namespace usrp{
DBOARD_PROP_SUBDEV = 's', //ro, wax::obj
DBOARD_PROP_SUBDEV_NAMES = 'S', //ro, prop_names_t
DBOARD_PROP_USED_SUBDEVS = 'u', //ro, prop_names_t
- DBOARD_PROP_DBOARD_ID = 'i' //rw, dboard_id_t
+ DBOARD_PROP_DBOARD_ID = 'i', //rw, dboard_id_t
+ DBOARD_PROP_DBOARD_IFACE = 'f' //ro, dboard_iface::sptr
//DBOARD_PROP_CODEC //ro, wax::obj //----> not sure, dont have to deal with yet
};
diff --git a/host/include/uhd/usrp/device_props.hpp b/host/include/uhd/usrp/device_props.hpp
index b8f6f5cd4..983bcb672 100644
--- a/host/include/uhd/usrp/device_props.hpp
+++ b/host/include/uhd/usrp/device_props.hpp
@@ -31,9 +31,7 @@ namespace uhd{ namespace usrp{
enum device_prop_t{
DEVICE_PROP_NAME = 'n', //ro, std::string
DEVICE_PROP_MBOARD = 'm', //ro, wax::obj
- DEVICE_PROP_MBOARD_NAMES = 'M', //ro, prop_names_t
- DEVICE_PROP_MAX_RX_SAMPLES = 'r', //ro, size_t
- DEVICE_PROP_MAX_TX_SAMPLES = 't' //ro, size_t
+ DEVICE_PROP_MBOARD_NAMES = 'M' //ro, prop_names_t
};
////////////////////////////////////////////////////////////////////////
diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp
index c4142b4e6..6ba1b90dd 100644
--- a/host/include/uhd/usrp/simple_usrp.hpp
+++ b/host/include/uhd/usrp/simple_usrp.hpp
@@ -112,6 +112,7 @@ public:
virtual double get_rx_rate(void) = 0;
virtual tune_result_t set_rx_freq(double freq) = 0;
+ virtual tune_result_t set_rx_freq(double freq, double lo_off) = 0;
virtual freq_range_t get_rx_freq_range(void) = 0;
virtual void set_rx_gain(float gain) = 0;
@@ -131,6 +132,7 @@ public:
virtual double get_tx_rate(void) = 0;
virtual tune_result_t set_tx_freq(double freq) = 0;
+ virtual tune_result_t set_tx_freq(double freq, double lo_off) = 0;
virtual freq_range_t get_tx_freq_range(void) = 0;
virtual void set_tx_gain(float gain) = 0;
diff --git a/host/include/uhd/utils/algorithm.hpp b/host/include/uhd/utils/algorithm.hpp
index 72b655745..146b56c63 100644
--- a/host/include/uhd/utils/algorithm.hpp
+++ b/host/include/uhd/utils/algorithm.hpp
@@ -26,6 +26,11 @@
*/
namespace std{
+ template<typename RangeSrc, typename RangeDst> inline
+ void copy(const RangeSrc &src, RangeDst &dst){
+ std::copy(boost::begin(src), boost::end(src), boost::begin(dst));
+ }
+
template<typename Range, typename T> inline
bool has(const Range &range, const T &value){
return boost::end(range) != std::find(boost::begin(range), boost::end(range), value);
diff --git a/host/lib/ic_reg_maps/common.py b/host/lib/ic_reg_maps/common.py
index 4aa1ef35e..e27c2816d 100644
--- a/host/lib/ic_reg_maps/common.py
+++ b/host/lib/ic_reg_maps/common.py
@@ -29,30 +29,59 @@ COMMON_TMPL = """\
\#ifndef INCLUDED_$(name.upper())_HPP
\#define INCLUDED_$(name.upper())_HPP
+\#include <uhd/config.hpp>
\#include <boost/cstdint.hpp>
+\#include <stdexcept>
+\#include <set>
-struct $(name)_t{
-
+class $(name)_t{
+public:
#for $reg in $regs
- #if $reg.get_enums()
+ #if $reg.get_enums()
enum $reg.get_type(){
#for $i, $enum in enumerate($reg.get_enums())
#set $end_comma = ',' if $i < len($reg.get_enums())-1 else ''
$(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma
#end for
};
- #end if
+ #end if
$reg.get_type() $reg.get_name();
#end for
$(name)_t(void){
- #for $reg in $regs
+ _state = NULL;
+ #for $reg in $regs
$reg.get_name() = $reg.get_default();
- #end for
+ #end for
+ }
+
+ ~$(name)_t(void){
+ delete _state;
}
$body
+ void save_state(void){
+ if (_state == NULL) _state = new $(name)_t();
+ #for $reg in $regs
+ _state->$reg.get_name() = this->$reg.get_name();
+ #end for
+ }
+
+ template<typename T> std::set<T> get_changed_addrs(void){
+ if (_state == NULL) throw std::runtime_error("no saved state");
+ //check each register for changes
+ std::set<T> addrs;
+ #for $reg in $regs
+ if(_state->$reg.get_name() != this->$reg.get_name()){
+ addrs.insert($reg.get_addr());
+ }
+ #end for
+ return addrs;
+ }
+
+private:
+ $(name)_t *_state;
};
\#endif /* INCLUDED_$(name.upper())_HPP */
diff --git a/host/lib/ic_reg_maps/gen_ad9777_regs.py b/host/lib/ic_reg_maps/gen_ad9777_regs.py
index abb839f0f..690b15e24 100755
--- a/host/lib/ic_reg_maps/gen_ad9777_regs.py
+++ b/host/lib/ic_reg_maps/gen_ad9777_regs.py
@@ -59,7 +59,7 @@ pll_divide_ratio 3[0:1] 0 div1, div2, div4, div8
## address 4
########################################################################
pll_state 4[7] 0 off, on
-auto_cp_control 4[6] 0 dis, enb
+auto_cp_control 4[6] 0 auto, manual
pll_cp_control 4[0:2] 0 50ua=0, 100ua=1, 200ua=2, 400ua=3, 800ua=7
########################################################################
## address 5 and 9
diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt
index a36f0fc03..ed8c35225 100644
--- a/host/lib/transport/CMakeLists.txt
+++ b/host/lib/transport/CMakeLists.txt
@@ -49,4 +49,5 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_SOURCE_DIR}/lib/transport/if_addrs.cpp
${CMAKE_SOURCE_DIR}/lib/transport/udp_simple.cpp
${CMAKE_SOURCE_DIR}/lib/transport/udp_zero_copy_asio.cpp
+ ${CMAKE_SOURCE_DIR}/lib/transport/vrt_packet_handler.hpp
)
diff --git a/host/lib/transport/convert_types.cpp b/host/lib/transport/convert_types.cpp
index 8c3d6b17a..43503025a 100644
--- a/host/lib/transport/convert_types.cpp
+++ b/host/lib/transport/convert_types.cpp
@@ -15,6 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
+#include <uhd/config.hpp>
#include <uhd/transport/convert_types.hpp>
#include <uhd/utils/assert.hpp>
#include <boost/asio.hpp> //endianness conversion
@@ -49,7 +50,7 @@ static const bool is_big_endian = true;
static const bool is_big_endian = false;
#endif
-static inline void host_floats_to_usrp2_items(
+static UHD_INLINE void host_floats_to_usrp2_items(
boost::uint32_t *usrp2_items,
const fc32_t *host_floats,
size_t num_samps
@@ -62,7 +63,7 @@ static inline void host_floats_to_usrp2_items(
unrolled_loop(host_floats_to_usrp2_items_i, num_samps);
}
-static inline void usrp2_items_to_host_floats(
+static UHD_INLINE void usrp2_items_to_host_floats(
fc32_t *host_floats,
const boost::uint32_t *usrp2_items,
size_t num_samps
@@ -76,7 +77,7 @@ static inline void usrp2_items_to_host_floats(
unrolled_loop(usrp2_items_to_host_floats_i, num_samps);
}
-static inline void host_items_to_usrp2_items(
+static UHD_INLINE void host_items_to_usrp2_items(
boost::uint32_t *usrp2_items,
const boost::uint32_t *host_items,
size_t num_samps
@@ -90,7 +91,7 @@ static inline void host_items_to_usrp2_items(
}
}
-static inline void usrp2_items_to_host_items(
+static UHD_INLINE void usrp2_items_to_host_items(
boost::uint32_t *host_items,
const boost::uint32_t *usrp2_items,
size_t num_samps
@@ -115,10 +116,13 @@ void transport::convert_io_type_to_otw_type(
switch(io_type.tid){
case io_type_t::COMPLEX_FLOAT32:
host_floats_to_usrp2_items((boost::uint32_t *)otw_buff, (const fc32_t*)io_buff, num_samps);
- break;
+ return;
case io_type_t::COMPLEX_INT16:
host_items_to_usrp2_items((boost::uint32_t *)otw_buff, (const boost::uint32_t*)io_buff, num_samps);
- break;
+ return;
+ case io_type_t::CUSTOM_TYPE:
+ std::memcpy(otw_buff, io_buff, num_samps*io_type.size);
+ return;
default:
throw std::runtime_error(str(boost::format("convert_types: cannot handle type \"%c\"") % io_type.tid));
}
@@ -135,10 +139,13 @@ void transport::convert_otw_type_to_io_type(
switch(io_type.tid){
case io_type_t::COMPLEX_FLOAT32:
usrp2_items_to_host_floats((fc32_t*)io_buff, (const boost::uint32_t *)otw_buff, num_samps);
- break;
+ return;
case io_type_t::COMPLEX_INT16:
usrp2_items_to_host_items((boost::uint32_t*)io_buff, (const boost::uint32_t *)otw_buff, num_samps);
- break;
+ return;
+ case io_type_t::CUSTOM_TYPE:
+ std::memcpy(io_buff, otw_buff, num_samps*io_type.size);
+ return;
default:
throw std::runtime_error(str(boost::format("convert_types: cannot handle type \"%c\"") % io_type.tid));
}
diff --git a/host/lib/transport/gen_vrt.py b/host/lib/transport/gen_vrt.py
index 9a57c83c3..c34ffb198 100755
--- a/host/lib/transport/gen_vrt.py
+++ b/host/lib/transport/gen_vrt.py
@@ -57,7 +57,7 @@ void vrt::pack(
size_t packet_count, //input
double tick_rate //input
){
- boost::uint32_t vrt_hdr_flags;
+ boost::uint32_t vrt_hdr_flags = 0;
boost::uint8_t pred = 0;
if (metadata.has_stream_id) pred |= $hex($sid_p);
diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp
index ee44803f4..f8a222475 100644
--- a/host/lib/transport/udp_zero_copy_asio.cpp
+++ b/host/lib/transport/udp_zero_copy_asio.cpp
@@ -16,75 +16,69 @@
//
#include <uhd/transport/udp_zero_copy.hpp>
+#include <uhd/utils/assert.hpp>
#include <boost/cstdint.hpp>
#include <boost/asio.hpp>
-#include <boost/thread.hpp>
#include <boost/format.hpp>
#include <iostream>
using namespace uhd::transport;
/***********************************************************************
+ * Constants
+ **********************************************************************/
+static const size_t MIN_SOCK_BUFF_SIZE = size_t(100e3);
+static const size_t MAX_DGRAM_SIZE = 2048; //assume max size on send and recv
+static const double RECV_TIMEOUT = 0.1; // 100 ms
+
+/***********************************************************************
* Managed receive buffer implementation for udp zero-copy asio:
- * Frees the memory held by the const buffer on done.
**********************************************************************/
class managed_recv_buffer_impl : public managed_recv_buffer{
public:
managed_recv_buffer_impl(const boost::asio::const_buffer &buff) : _buff(buff){
- _done = false;
+ /* NOP */
}
~managed_recv_buffer_impl(void){
- if (not _done) this->done();
- }
-
- void done(void){
- _done = true;
- delete [] boost::asio::buffer_cast<const boost::uint32_t *>(_buff);
+ delete [] this->cast<const boost::uint8_t *>();
}
private:
- const boost::asio::const_buffer &get(void){
+ const boost::asio::const_buffer &get(void) const{
return _buff;
}
const boost::asio::const_buffer _buff;
- bool _done;
};
/***********************************************************************
* Managed send buffer implementation for udp zero-copy asio:
- * Sends and frees the memory held by the mutable buffer on done.
**********************************************************************/
class managed_send_buffer_impl : public managed_send_buffer{
public:
managed_send_buffer_impl(
const boost::asio::mutable_buffer &buff,
boost::asio::ip::udp::socket *socket
- ) : _buff(buff){
- _done = false;
- _socket = socket;
+ ) : _buff(buff), _socket(socket){
+ /* NOP */
}
~managed_send_buffer_impl(void){
- if (not _done) this->done(0);
+ /* NOP */
}
- void done(size_t num_bytes){
- _done = true;
- boost::uint32_t *mem = boost::asio::buffer_cast<boost::uint32_t *>(_buff);
- _socket->send(boost::asio::buffer(mem, num_bytes));
- delete [] mem;
+ void commit(size_t num_bytes){
+ _socket->send(boost::asio::buffer(_buff, num_bytes));
}
private:
- const boost::asio::mutable_buffer &get(void){
+ const boost::asio::mutable_buffer &get(void) const{
return _buff;
}
const boost::asio::mutable_buffer _buff;
boost::asio::ip::udp::socket *_socket;
- bool _done;
};
/***********************************************************************
@@ -96,6 +90,8 @@ private:
**********************************************************************/
class udp_zero_copy_impl : public udp_zero_copy{
public:
+ typedef boost::shared_ptr<udp_zero_copy_impl> sptr;
+
//structors
udp_zero_copy_impl(const std::string &addr, const std::string &port);
~udp_zero_copy_impl(void);
@@ -104,23 +100,27 @@ public:
managed_recv_buffer::sptr get_recv_buff(void);
managed_send_buffer::sptr get_send_buff(void);
- //resize
- size_t resize_recv_buff(size_t num_bytes){
- boost::asio::socket_base::receive_buffer_size option(num_bytes);
- _socket->set_option(option);
+ //manage buffer
+ template <typename Opt> size_t get_buff_size(void){
+ Opt option;
_socket->get_option(option);
return option.value();
}
- size_t resize_send_buff(size_t num_bytes){
- boost::asio::socket_base::send_buffer_size option(num_bytes);
+
+ template <typename Opt> size_t resize_buff(size_t num_bytes){
+ Opt option(num_bytes);
_socket->set_option(option);
- _socket->get_option(option);
- return option.value();
+ return get_buff_size<Opt>();
}
private:
boost::asio::ip::udp::socket *_socket;
boost::asio::io_service _io_service;
+
+ //send and recv buffer memory (allocated once)
+ boost::uint8_t _send_mem[MIN_SOCK_BUFF_SIZE];
+
+ managed_send_buffer::sptr _send_buff;
};
udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::string &port){
@@ -131,10 +131,25 @@ udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::strin
boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port);
boost::asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query);
- // Create, open, and connect the socket
+ // create, open, and connect the socket
_socket = new boost::asio::ip::udp::socket(_io_service);
_socket->open(boost::asio::ip::udp::v4());
_socket->connect(receiver_endpoint);
+
+ // create the managed send buff (just once)
+ _send_buff = managed_send_buffer::sptr(new managed_send_buffer_impl(
+ boost::asio::buffer(_send_mem, MIN_SOCK_BUFF_SIZE), _socket
+ ));
+
+ // set recv timeout
+ timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = size_t(RECV_TIMEOUT*1e6);
+ UHD_ASSERT_THROW(setsockopt(
+ _socket->native(),
+ SOL_SOCKET, SO_RCVTIMEO,
+ (const char *)&tv, sizeof(timeval)
+ ) == 0);
}
udp_zero_copy_impl::~udp_zero_copy_impl(void){
@@ -142,61 +157,56 @@ udp_zero_copy_impl::~udp_zero_copy_impl(void){
}
managed_recv_buffer::sptr udp_zero_copy_impl::get_recv_buff(void){
- //implement timeout through polling and sleeping
- size_t available = 0;
- boost::asio::deadline_timer timer(_socket->get_io_service());
- timer.expires_from_now(boost::posix_time::milliseconds(100));
- while (not ((available = _socket->available()) or timer.expires_from_now().is_negative())){
- boost::this_thread::sleep(boost::posix_time::milliseconds(1));
- }
+ //allocate memory
+ boost::uint8_t *recv_mem = new boost::uint8_t[MAX_DGRAM_SIZE];
- //receive only if data is available
- boost::uint32_t *buff_mem = new boost::uint32_t[available/sizeof(boost::uint32_t)];
- if (available){
- available = _socket->receive(boost::asio::buffer(buff_mem, available));
- }
+ //call recv() with timeout option
+ size_t num_bytes = _socket->receive(boost::asio::buffer(recv_mem, MIN_SOCK_BUFF_SIZE));
//create a new managed buffer to house the data
return managed_recv_buffer::sptr(
- new managed_recv_buffer_impl(boost::asio::buffer(buff_mem, available))
+ new managed_recv_buffer_impl(boost::asio::buffer(recv_mem, num_bytes))
);
}
managed_send_buffer::sptr udp_zero_copy_impl::get_send_buff(void){
- boost::uint32_t *buff_mem = new boost::uint32_t[2000/sizeof(boost::uint32_t)];
- return managed_send_buffer::sptr(
- new managed_send_buffer_impl(boost::asio::buffer(buff_mem, 2000), _socket)
- );
+ return _send_buff; //FIXME there is only ever one send buff, we assume that the caller doesnt hang onto these
}
/***********************************************************************
* UDP zero copy make function
**********************************************************************/
+template<typename Opt> static inline void resize_buff_helper(
+ udp_zero_copy_impl::sptr udp_trans,
+ size_t target_size,
+ const std::string &name
+){
+ //resize the buffer if size was provided
+ if (target_size > 0){
+ size_t actual_size = udp_trans->resize_buff<Opt>(target_size);
+ if (target_size != actual_size) std::cout << boost::format(
+ "Target %s buffer size: %d\n"
+ "Actual %s byffer size: %d"
+ ) % name % target_size % name % actual_size << std::endl;
+ }
+
+ //otherwise, ensure that the buffer is at least the minimum size
+ else if (udp_trans->get_buff_size<Opt>() < MIN_SOCK_BUFF_SIZE){
+ resize_buff_helper<Opt>(udp_trans, MIN_SOCK_BUFF_SIZE, name);
+ }
+}
+
udp_zero_copy::sptr udp_zero_copy::make(
const std::string &addr,
const std::string &port,
size_t recv_buff_size,
size_t send_buff_size
){
- boost::shared_ptr<udp_zero_copy_impl> udp_trans(new udp_zero_copy_impl(addr, port));
-
- //resize the recv buffer if size was provided
- if (recv_buff_size > 0){
- size_t actual_bytes = udp_trans->resize_recv_buff(recv_buff_size);
- if (recv_buff_size != actual_bytes) std::cout << boost::format(
- "Target recv buffer size: %d\n"
- "Actual recv byffer size: %d"
- ) % recv_buff_size % actual_bytes << std::endl;
- }
+ udp_zero_copy_impl::sptr udp_trans(new udp_zero_copy_impl(addr, port));
- //resize the send buffer if size was provided
- if (send_buff_size > 0){
- size_t actual_bytes = udp_trans->resize_send_buff(send_buff_size);
- if (send_buff_size != actual_bytes) std::cout << boost::format(
- "Target send buffer size: %d\n"
- "Actual send byffer size: %d"
- ) % send_buff_size % actual_bytes << std::endl;
- }
+ //call the helper to resize send and recv buffers
+ resize_buff_helper<boost::asio::socket_base::receive_buffer_size>(udp_trans, recv_buff_size, "recv");
+ resize_buff_helper<boost::asio::socket_base::send_buffer_size> (udp_trans, send_buff_size, "send");
return udp_trans;
}
diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp
new file mode 100644
index 000000000..e64e3383d
--- /dev/null
+++ b/host/lib/transport/vrt_packet_handler.hpp
@@ -0,0 +1,370 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_LIBUHD_TRANSPORT_VRT_PACKET_HANDLER_HPP
+#define INCLUDED_LIBUHD_TRANSPORT_VRT_PACKET_HANDLER_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/device.hpp>
+#include <uhd/types/io_type.hpp>
+#include <uhd/types/otw_type.hpp>
+#include <uhd/types/metadata.hpp>
+#include <uhd/transport/vrt.hpp>
+#include <uhd/transport/convert_types.hpp>
+#include <uhd/transport/zero_copy.hpp>
+#include <boost/asio/buffer.hpp>
+#include <boost/function.hpp>
+#include <stdexcept>
+#include <iostream>
+
+namespace vrt_packet_handler{
+
+/***********************************************************************
+ * vrt packet handler for recv
+ **********************************************************************/
+ struct recv_state{
+ //init the expected seq number
+ size_t next_packet_seq;
+
+ //state variables to handle fragments
+ uhd::transport::managed_recv_buffer::sptr managed_buff;
+ boost::asio::const_buffer copy_buff;
+ size_t fragment_offset_in_samps;
+
+ recv_state(void){
+ //first expected seq is zero
+ next_packet_seq = 0;
+
+ //initially empty copy buffer
+ copy_buff = boost::asio::buffer("", 0);
+ }
+ };
+
+ typedef boost::function<void(uhd::transport::managed_recv_buffer::sptr)> recv_cb_t;
+
+ static UHD_INLINE void recv_cb_nop(uhd::transport::managed_recv_buffer::sptr){
+ /* NOP */
+ }
+
+ /*******************************************************************
+ * Unpack a received vrt header and set the copy buffer.
+ * - helper function for vrt_packet_handler::_recv1
+ ******************************************************************/
+ static UHD_INLINE void _recv1_helper(
+ recv_state &state,
+ uhd::rx_metadata_t &metadata,
+ double tick_rate,
+ size_t vrt_header_offset_words32
+ ){
+ size_t num_packet_words32 = state.managed_buff->size()/sizeof(boost::uint32_t);
+ if (num_packet_words32 <= vrt_header_offset_words32){
+ state.copy_buff = boost::asio::buffer("", 0);
+ return; //must exit here after setting the buffer
+ }
+ const boost::uint32_t *vrt_hdr = state.managed_buff->cast<const boost::uint32_t *>() + vrt_header_offset_words32;
+ size_t num_header_words32_out, num_payload_words32_out, packet_count_out;
+ uhd::transport::vrt::unpack(
+ metadata, //output
+ vrt_hdr, //input
+ num_header_words32_out, //output
+ num_payload_words32_out, //output
+ num_packet_words32, //input
+ packet_count_out, //output
+ tick_rate
+ );
+
+ //handle the packet count / sequence number
+ if (packet_count_out != state.next_packet_seq){
+ std::cerr << "S" << (packet_count_out - state.next_packet_seq)%16;
+ }
+ state.next_packet_seq = (packet_count_out+1)%16;
+
+ //setup the buffer to point to the data
+ state.copy_buff = boost::asio::buffer(
+ vrt_hdr + num_header_words32_out,
+ num_payload_words32_out*sizeof(boost::uint32_t)
+ );
+ }
+
+ /*******************************************************************
+ * Recv data, unpack a vrt header, and copy-convert the data.
+ * - helper function for vrt_packet_handler::recv
+ ******************************************************************/
+ static UHD_INLINE size_t _recv1(
+ recv_state &state,
+ void *recv_mem,
+ size_t total_samps,
+ uhd::rx_metadata_t &metadata,
+ const uhd::io_type_t &io_type,
+ const uhd::otw_type_t &otw_type,
+ double tick_rate,
+ uhd::transport::zero_copy_if::sptr zc_iface,
+ //use these two params to handle a layer above vrt
+ size_t vrt_header_offset_words32,
+ const recv_cb_t& recv_cb
+ ){
+ //perform a receive if no rx data is waiting to be copied
+ if (boost::asio::buffer_size(state.copy_buff) == 0){
+ state.fragment_offset_in_samps = 0;
+ state.managed_buff = zc_iface->get_recv_buff();
+ recv_cb(state.managed_buff); //callback before vrt unpack
+ try{
+ _recv1_helper(
+ state, metadata, tick_rate, vrt_header_offset_words32
+ );
+ }catch(const std::exception &e){
+ std::cerr << "Error (recv): " << e.what() << std::endl;
+ return 0;
+ }
+ }
+
+ //extract the number of samples available to copy
+ size_t bytes_per_item = otw_type.get_sample_size();
+ size_t bytes_available = boost::asio::buffer_size(state.copy_buff);
+ size_t num_samps = std::min(total_samps, bytes_available/bytes_per_item);
+
+ //setup the fragment flags and offset
+ metadata.more_fragments = total_samps < num_samps;
+ metadata.fragment_offset = state.fragment_offset_in_samps;
+ state.fragment_offset_in_samps += num_samps; //set for next call
+
+ //copy-convert the samples from the recv buffer
+ uhd::transport::convert_otw_type_to_io_type(
+ boost::asio::buffer_cast<const void*>(state.copy_buff), otw_type,
+ recv_mem, io_type, num_samps
+ );
+
+ //update the rx copy buffer to reflect the bytes copied
+ size_t bytes_copied = num_samps*bytes_per_item;
+ state.copy_buff = boost::asio::buffer(
+ boost::asio::buffer_cast<const boost::uint8_t*>(state.copy_buff) + bytes_copied,
+ bytes_available - bytes_copied
+ );
+
+ return num_samps;
+ }
+
+ /*******************************************************************
+ * Recv vrt packets and copy convert the samples into the buffer.
+ ******************************************************************/
+ static UHD_INLINE size_t recv(
+ recv_state &state,
+ const boost::asio::mutable_buffer &buff,
+ uhd::rx_metadata_t &metadata,
+ uhd::device::recv_mode_t recv_mode,
+ const uhd::io_type_t &io_type,
+ const uhd::otw_type_t &otw_type,
+ double tick_rate,
+ uhd::transport::zero_copy_if::sptr zc_iface,
+ //use these two params to handle a layer above vrt
+ size_t vrt_header_offset_words32 = 0,
+ const recv_cb_t& recv_cb = &recv_cb_nop
+ ){
+ metadata = uhd::rx_metadata_t(); //init the metadata
+ const size_t total_num_samps = boost::asio::buffer_size(buff)/io_type.size;
+
+ switch(recv_mode){
+
+ ////////////////////////////////////////////////////////////////
+ case uhd::device::RECV_MODE_ONE_PACKET:{
+ ////////////////////////////////////////////////////////////////
+ return _recv1(
+ state,
+ boost::asio::buffer_cast<void *>(buff),
+ total_num_samps,
+ metadata,
+ io_type, otw_type,
+ tick_rate,
+ zc_iface,
+ vrt_header_offset_words32,
+ recv_cb
+ );
+ }
+
+ ////////////////////////////////////////////////////////////////
+ case uhd::device::RECV_MODE_FULL_BUFF:{
+ ////////////////////////////////////////////////////////////////
+ size_t accum_num_samps = 0;
+ uhd::rx_metadata_t tmp_md;
+ while(accum_num_samps < total_num_samps){
+ size_t num_samps = _recv1(
+ state,
+ boost::asio::buffer_cast<boost::uint8_t *>(buff) + (accum_num_samps*io_type.size),
+ total_num_samps - accum_num_samps,
+ (accum_num_samps == 0)? metadata : tmp_md, //only the first metadata gets kept
+ io_type, otw_type,
+ tick_rate,
+ zc_iface,
+ vrt_header_offset_words32,
+ recv_cb
+ );
+ if (num_samps == 0) break; //had a recv timeout or error, break loop
+ accum_num_samps += num_samps;
+ }
+ return accum_num_samps;
+ }
+
+ default: throw std::runtime_error("unknown recv mode");
+ }//switch(recv_mode)
+ }
+
+/***********************************************************************
+ * vrt packet handler for send
+ **********************************************************************/
+ struct send_state{
+ //init the expected seq number
+ size_t next_packet_seq;
+
+ send_state(void){
+ next_packet_seq = 0;
+ }
+ };
+
+ typedef boost::function<void(uhd::transport::managed_send_buffer::sptr)> send_cb_t;
+
+ static UHD_INLINE void send_cb_nop(uhd::transport::managed_send_buffer::sptr){
+ /* NOP */
+ }
+
+ /*******************************************************************
+ * Pack a vrt header, copy-convert the data, and send it.
+ * - helper function for vrt_packet_handler::send
+ ******************************************************************/
+ static UHD_INLINE void _send1(
+ send_state &state,
+ const void *send_mem,
+ size_t num_samps,
+ const uhd::tx_metadata_t &metadata,
+ const uhd::io_type_t &io_type,
+ const uhd::otw_type_t &otw_type,
+ double tick_rate,
+ uhd::transport::zero_copy_if::sptr zc_iface,
+ size_t vrt_header_offset_words32,
+ const send_cb_t& send_cb
+ ){
+ //get a new managed send buffer
+ uhd::transport::managed_send_buffer::sptr send_buff = zc_iface->get_send_buff();
+ boost::uint32_t *tx_mem = send_buff->cast<boost::uint32_t *>() + vrt_header_offset_words32;
+
+ size_t num_header_words32, num_packet_words32;
+ size_t packet_count = state.next_packet_seq++;
+
+ //pack metadata into a vrt header
+ uhd::transport::vrt::pack(
+ metadata, //input
+ tx_mem, //output
+ num_header_words32, //output
+ num_samps, //input
+ num_packet_words32, //output
+ packet_count, //input
+ tick_rate
+ );
+
+ //copy-convert the samples into the send buffer
+ uhd::transport::convert_io_type_to_otw_type(
+ send_mem, io_type,
+ tx_mem + num_header_words32, otw_type,
+ num_samps
+ );
+
+ send_cb(send_buff); //callback after memory filled
+
+ //commit the samples to the zero-copy interface
+ send_buff->commit(num_packet_words32*sizeof(boost::uint32_t));
+ }
+
+ /*******************************************************************
+ * Send vrt packets and copy convert the samples into the buffer.
+ ******************************************************************/
+ static UHD_INLINE size_t send(
+ send_state &state,
+ const boost::asio::const_buffer &buff,
+ const uhd::tx_metadata_t &metadata,
+ uhd::device::send_mode_t send_mode,
+ const uhd::io_type_t &io_type,
+ const uhd::otw_type_t &otw_type,
+ double tick_rate,
+ uhd::transport::zero_copy_if::sptr zc_iface,
+ size_t max_samples_per_packet,
+ //use these two params to handle a layer above vrt
+ size_t vrt_header_offset_words32 = 0,
+ const send_cb_t& send_cb = &send_cb_nop
+ ){
+ const size_t total_num_samps = boost::asio::buffer_size(buff)/io_type.size;
+ if (total_num_samps <= max_samples_per_packet) send_mode = uhd::device::SEND_MODE_ONE_PACKET;
+ switch(send_mode){
+
+ ////////////////////////////////////////////////////////////////
+ case uhd::device::SEND_MODE_ONE_PACKET:{
+ ////////////////////////////////////////////////////////////////
+ size_t num_samps = std::min(total_num_samps, max_samples_per_packet);
+ _send1(
+ state,
+ boost::asio::buffer_cast<const void *>(buff),
+ num_samps,
+ metadata,
+ io_type, otw_type,
+ tick_rate,
+ zc_iface,
+ vrt_header_offset_words32,
+ send_cb
+ );
+ return num_samps;
+ }
+
+ ////////////////////////////////////////////////////////////////
+ case uhd::device::SEND_MODE_FULL_BUFF:{
+ ////////////////////////////////////////////////////////////////
+ //calculate constants for fragmentation
+ const size_t num_fragments = (total_num_samps+max_samples_per_packet-1)/max_samples_per_packet;
+ static const size_t first_fragment_index = 0;
+ const size_t final_fragment_index = num_fragments-1;
+
+ //make a rw copy of the metadata to re-flag below
+ uhd::tx_metadata_t md(metadata);
+
+ //loop through the following fragment indexes
+ for (size_t n = first_fragment_index; n <= final_fragment_index; n++){
+
+ //calculate new flags for the fragments
+ md.has_time_spec = metadata.has_time_spec and (n == first_fragment_index);
+ md.start_of_burst = metadata.start_of_burst and (n == first_fragment_index);
+ md.end_of_burst = metadata.end_of_burst and (n == final_fragment_index);
+
+ //send the fragment with the helper function
+ _send1(
+ state,
+ boost::asio::buffer_cast<const boost::uint8_t *>(buff) + (n*max_samples_per_packet*io_type.size),
+ (n == final_fragment_index)?(total_num_samps%max_samples_per_packet):max_samples_per_packet,
+ md,
+ io_type, otw_type,
+ tick_rate,
+ zc_iface,
+ vrt_header_offset_words32,
+ send_cb
+ );
+ }
+ return total_num_samps;
+ }
+
+ default: throw std::runtime_error("unknown send mode");
+ }//switch(send_mode)
+ }
+
+} //namespace vrt_packet_handler
+
+#endif /* INCLUDED_LIBUHD_TRANSPORT_VRT_PACKET_HANDLER_HPP */
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
index ec9c8ac01..daf3be7f7 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -15,6 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
+#include <uhd/utils/assert.hpp>
#include <uhd/types/ranges.hpp>
#include <uhd/types/tune_result.hpp>
#include <uhd/types/clock_config.hpp>
@@ -41,73 +42,89 @@ using namespace uhd;
/***********************************************************************
* ranges
**********************************************************************/
-gain_range_t::gain_range_t(float min_, float max_, float step_){
- min = min_;
- max = max_;
- step = step_;
+gain_range_t::gain_range_t(float min, float max, float step):
+ min(min),
+ max(max),
+ step(step)
+{
+ /* NOP */
}
-freq_range_t::freq_range_t(double min_, double max_){
- min = min_;
- max = max_;
+freq_range_t::freq_range_t(double min, double max):
+ min(min),
+ max(max)
+{
+ /* NOP */
}
/***********************************************************************
* tune result
**********************************************************************/
-tune_result_t::tune_result_t(void){
- target_inter_freq = 0.0;
- actual_inter_freq = 0.0;
- target_dsp_freq = 0.0;
- actual_dsp_freq = 0.0;
- spectrum_inverted = false;
+tune_result_t::tune_result_t(void):
+ target_inter_freq(0.0),
+ actual_inter_freq(0.0),
+ target_dsp_freq(0.0),
+ actual_dsp_freq(0.0),
+ spectrum_inverted(false)
+{
+ /* NOP */
}
/***********************************************************************
* clock config
**********************************************************************/
-clock_config_t::clock_config_t(void){
- ref_source = REF_INT,
- pps_source = PPS_INT,
- pps_polarity = PPS_NEG;
+clock_config_t::clock_config_t(void):
+ ref_source(REF_INT),
+ pps_source(PPS_INT),
+ pps_polarity(PPS_NEG)
+{
+ /* NOP */
}
/***********************************************************************
* stream command
**********************************************************************/
-stream_cmd_t::stream_cmd_t(const stream_mode_t &stream_mode_){
- stream_mode = stream_mode_;
- stream_now = true;
- num_samps = 0;
+stream_cmd_t::stream_cmd_t(const stream_mode_t &stream_mode):
+ stream_mode(stream_mode),
+ num_samps(0),
+ stream_now(true)
+{
+ /* NOP */
}
/***********************************************************************
* metadata
**********************************************************************/
-rx_metadata_t::rx_metadata_t(void){
- stream_id = 0;
- has_stream_id = false;
- time_spec = time_spec_t();
- has_time_spec = false;
- more_fragments = false;
- fragment_offset = 0;
+rx_metadata_t::rx_metadata_t(void):
+ has_stream_id(false),
+ stream_id(0),
+ has_time_spec(false),
+ time_spec(time_spec_t()),
+ more_fragments(false),
+ fragment_offset(0)
+{
+ /* NOP */
}
-tx_metadata_t::tx_metadata_t(void){
- stream_id = 0;
- has_stream_id = false;
- time_spec = time_spec_t();
- has_time_spec = false;
- start_of_burst = false;
- end_of_burst = false;
+tx_metadata_t::tx_metadata_t(void):
+ has_stream_id(false),
+ stream_id(0),
+ has_time_spec(false),
+ time_spec(time_spec_t()),
+ start_of_burst(false),
+ end_of_burst(false)
+{
+ /* NOP */
}
/***********************************************************************
* time spec
**********************************************************************/
-time_spec_t::time_spec_t(boost::uint32_t secs_, double nsecs_){
- secs = secs_;
- nsecs = nsecs_;
+time_spec_t::time_spec_t(boost::uint32_t secs, double nsecs):
+ secs(secs),
+ nsecs(nsecs)
+{
+ /* NOP */
}
boost::uint32_t time_spec_t::get_ticks(double tick_rate) const{
@@ -164,17 +181,18 @@ std::string device_addr_t::to_string(void) const{
/***********************************************************************
* mac addr
**********************************************************************/
-mac_addr_t::mac_addr_t(const boost::uint8_t *bytes){
- std::copy(bytes, bytes+hlen, _bytes);
+mac_addr_t::mac_addr_t(const byte_vector_t &bytes) : _bytes(bytes){
+ UHD_ASSERT_THROW(_bytes.size() == 6);
}
-mac_addr_t mac_addr_t::from_bytes(const boost::uint8_t *bytes){
+mac_addr_t mac_addr_t::from_bytes(const byte_vector_t &bytes){
return mac_addr_t(bytes);
}
mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){
- boost::uint8_t p[hlen] = {0x00, 0x50, 0xC2, 0x85, 0x30, 0x00}; // Matt's IAB
+ byte_vector_t bytes = boost::assign::list_of
+ (0x00)(0x50)(0xC2)(0x85)(0x30)(0x00); // Matt's IAB
try{
//only allow patterns of xx:xx or xx:xx:xx:xx:xx:xx
@@ -189,7 +207,7 @@ mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){
int hex_num;
std::istringstream iss(hex_strs[i]);
iss >> std::hex >> hex_num;
- p[i] = boost::uint8_t(hex_num);
+ bytes[i] = boost::uint8_t(hex_num);
}
}
@@ -199,28 +217,34 @@ mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){
));
}
- return from_bytes(p);
+ return mac_addr_t::from_bytes(bytes);
}
-const boost::uint8_t *mac_addr_t::to_bytes(void) const{
+byte_vector_t mac_addr_t::to_bytes(void) const{
return _bytes;
}
std::string mac_addr_t::to_string(void) const{
- return str(
- boost::format("%02x:%02x:%02x:%02x:%02x:%02x")
- % int(to_bytes()[0]) % int(to_bytes()[1]) % int(to_bytes()[2])
- % int(to_bytes()[3]) % int(to_bytes()[4]) % int(to_bytes()[5])
- );
+ std::string addr = "";
+ BOOST_FOREACH(boost::uint8_t byte, this->to_bytes()){
+ addr += str(boost::format("%s%02x") % ((addr == "")?"":":") % int(byte));
+ }
+ return addr;
}
/***********************************************************************
* otw type
**********************************************************************/
-otw_type_t::otw_type_t(void){
- width = 0;
- shift = 0;
- byteorder = BO_NATIVE;
+size_t otw_type_t::get_sample_size(void) const{
+ return (this->width * 2) / 8;
+}
+
+otw_type_t::otw_type_t(void):
+ width(0),
+ shift(0),
+ byteorder(BO_NATIVE)
+{
+ /* NOP */
}
/***********************************************************************
@@ -248,9 +272,11 @@ io_type_t::io_type_t(size_t size)
/***********************************************************************
* serial
**********************************************************************/
-spi_config_t::spi_config_t(edge_t edge){
- mosi_edge = edge;
- miso_edge = edge;
+spi_config_t::spi_config_t(edge_t edge):
+ mosi_edge(edge),
+ miso_edge(edge)
+{
+ /* NOP */
}
void i2c_iface::write_eeprom(
diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index bbc9716b1..89e707718 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -15,8 +15,6 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-static const bool rfx_debug = false;
-
// IO Pin functions
#define POWER_IO (1 << 7) // Low enables power supply
#define ANTSW_IO (1 << 6) // On TX DB, 0 = TX, 1 = RX, on RX DB 0 = main ant, 1 = RX2
@@ -56,10 +54,23 @@ using namespace uhd::usrp;
using namespace boost::assign;
/***********************************************************************
- * The RFX series of dboards
+ * The RFX Series constants
**********************************************************************/
-static const float _max_rx_pga0_gain = 45;
+static const bool rfx_debug = false;
+
+static const prop_names_t rfx_tx_antennas = list_of("TX/RX");
+
+static const prop_names_t rfx_rx_antennas = list_of("TX/RX")("RX2");
+static const uhd::dict<std::string, gain_range_t> rfx_tx_gain_ranges; //empty
+
+static const uhd::dict<std::string, gain_range_t> rfx_rx_gain_ranges = map_list_of
+ ("PGA0", gain_range_t(0, 45, float(0.022)))
+;
+
+/***********************************************************************
+ * The RFX series of dboards
+ **********************************************************************/
class rfx_xcvr : public xcvr_dboard_base{
public:
rfx_xcvr(
@@ -85,6 +96,10 @@ private:
void set_rx_lo_freq(double freq);
void set_tx_lo_freq(double freq);
void set_rx_ant(const std::string &ant);
+ void set_tx_ant(const std::string &ant);
+ void set_rx_gain(float gain, const std::string &name);
+ void set_tx_gain(float gain, const std::string &name);
+
void set_rx_pga0_gain(float gain);
/*!
@@ -161,8 +176,10 @@ rfx_xcvr::rfx_xcvr(
this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true);
this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true);
- //set the gpio directions
+ //set the gpio directions and atr controls (identically)
boost::uint16_t output_enables = POWER_IO | ANTSW_IO | MIXER_IO;
+ this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, output_enables);
+ this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, output_enables);
this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, output_enables);
this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, output_enables);
@@ -189,19 +206,11 @@ rfx_xcvr::~rfx_xcvr(void){
}
/***********************************************************************
- * Helper Methods
+ * Antenna Handling
**********************************************************************/
-void rfx_xcvr::set_rx_lo_freq(double freq){
- _rx_lo_freq = set_lo_freq(dboard_iface::UNIT_RX, freq);
-}
-
-void rfx_xcvr::set_tx_lo_freq(double freq){
- _tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, freq);
-}
-
void rfx_xcvr::set_rx_ant(const std::string &ant){
//validate input
- UHD_ASSERT_THROW(ant == "TX/RX" or ant == "RX2");
+ assert_has(rfx_rx_antennas, ant, "rfx rx antenna name");
//set the rx atr regs that change with antenna setting
this->get_iface()->set_atr_reg(
@@ -213,22 +222,51 @@ void rfx_xcvr::set_rx_ant(const std::string &ant){
_rx_ant = ant;
}
-void rfx_xcvr::set_rx_pga0_gain(float gain){
- //clip the input
- gain = std::clip<float>(gain, 0, _max_rx_pga0_gain);
+void rfx_xcvr::set_tx_ant(const std::string &ant){
+ assert_has(rfx_tx_antennas, ant, "rfx tx antenna name");
+ //only one antenna option, do nothing
+}
+
+/***********************************************************************
+ * Gain Handling
+ **********************************************************************/
+void rfx_xcvr::set_tx_gain(float, const std::string &name){
+ assert_has(rfx_tx_gain_ranges.keys(), name, "rfx tx gain name");
+ UHD_ASSERT_THROW(false); //no gains to set
+}
+
+void rfx_xcvr::set_rx_gain(float gain, const std::string &name){
+ assert_has(rfx_rx_gain_ranges.keys(), name, "rfx rx gain name");
+ if(name == "PGA0"){
+ this->set_rx_pga0_gain(gain);
+ }
+ else UHD_ASSERT_THROW(false);
+}
- //voltage level constants
+void rfx_xcvr::set_rx_pga0_gain(float gain){
+ //voltage level constants (negative slope)
static const float max_volts = float(.2), min_volts = float(1.2);
- static const float slope = (max_volts-min_volts)/_max_rx_pga0_gain;
+ static const float slope = (max_volts-min_volts)/45;
//calculate the voltage for the aux dac
- float dac_volts = gain*slope + min_volts;
+ float dac_volts = std::clip<float>(gain*slope + min_volts, max_volts, min_volts);
//write the new voltage to the aux dac
this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, 1, dac_volts);
- //shadow the setting (does not account for precision loss)
- _rx_pga0_gain = gain;
+ //shadow the actual gain setting
+ _rx_pga0_gain = (dac_volts - min_volts)/slope;
+}
+
+/***********************************************************************
+ * Tuning
+ **********************************************************************/
+void rfx_xcvr::set_rx_lo_freq(double freq){
+ _rx_lo_freq = set_lo_freq(dboard_iface::UNIT_RX, freq);
+}
+
+void rfx_xcvr::set_tx_lo_freq(double freq){
+ _tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, freq);
}
double rfx_xcvr::set_lo_freq(
@@ -258,8 +296,8 @@ double rfx_xcvr::set_lo_freq(
(8, adf4360_regs_t::BAND_SELECT_CLOCK_DIV_8)
;
- double actual_freq, ref_freq = this->get_iface()->get_clock_rate(unit);
- int R, BS, P, B, A;
+ double actual_freq=0, ref_freq = this->get_iface()->get_clock_rate(unit);
+ int R=0, BS=0, P=0, B=0, A=0;
/*
* The goal here to to loop though possible R dividers,
@@ -364,12 +402,12 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN_RANGE:
- UHD_ASSERT_THROW(name == "PGA0");
- val = gain_range_t(0, _max_rx_pga0_gain, float(0.022));
+ assert_has(rfx_rx_gain_ranges.keys(), name, "rfx rx gain name");
+ val = rfx_rx_gain_ranges[name];
return;
case SUBDEV_PROP_GAIN_NAMES:
- val = prop_names_t(1, "PGA0");
+ val = prop_names_t(rfx_rx_gain_ranges.keys());
return;
case SUBDEV_PROP_FREQ:
@@ -384,10 +422,8 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
val = _rx_ant;
return;
- case SUBDEV_PROP_ANTENNA_NAMES:{
- prop_names_t ants = list_of("TX/RX")("RX2");
- val = ants;
- }
+ case SUBDEV_PROP_ANTENNA_NAMES:
+ val = rfx_rx_antennas;
return;
case SUBDEV_PROP_QUADRATURE:
@@ -422,16 +458,15 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_FREQ:
- set_rx_lo_freq(val.as<double>());
+ this->set_rx_lo_freq(val.as<double>());
return;
case SUBDEV_PROP_GAIN:
- UHD_ASSERT_THROW(name == "PGA0");
- set_rx_pga0_gain(val.as<float>());
+ this->set_rx_gain(val.as<float>(), name);
return;
case SUBDEV_PROP_ANTENNA:
- set_rx_ant(val.as<std::string>());
+ this->set_rx_ant(val.as<std::string>());
return;
default: UHD_THROW_PROP_SET_ERROR();
@@ -456,15 +491,13 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- val = float(0);
- return;
-
case SUBDEV_PROP_GAIN_RANGE:
- val = gain_range_t(0, 0, 0);
+ assert_has(rfx_tx_gain_ranges.keys(), name, "rfx tx gain name");
+ //no controllable tx gains, will not get here
return;
case SUBDEV_PROP_GAIN_NAMES:
- val = prop_names_t(); //empty
+ val = prop_names_t(rfx_tx_gain_ranges.keys());
return;
case SUBDEV_PROP_FREQ:
@@ -480,7 +513,7 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_ANTENNA_NAMES:
- val = prop_names_t(1, "TX/RX");
+ val = rfx_tx_antennas;
return;
case SUBDEV_PROP_QUADRATURE:
@@ -515,16 +548,15 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_FREQ:
- set_tx_lo_freq(val.as<double>());
+ this->set_tx_lo_freq(val.as<double>());
return;
case SUBDEV_PROP_GAIN:
- //no gains to set!
+ this->set_tx_gain(val.as<float>(), name);
return;
case SUBDEV_PROP_ANTENNA:
- //its always set to tx/rx, so we only allow this value
- UHD_ASSERT_THROW(val.as<std::string>() == "TX/RX");
+ this->set_tx_ant(val.as<std::string>());
return;
default: UHD_THROW_PROP_SET_ERROR();
diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp
index 2a8a3a9f2..23654860f 100644
--- a/host/lib/usrp/dboard/db_wbx.cpp
+++ b/host/lib/usrp/dboard/db_wbx.cpp
@@ -164,7 +164,9 @@ wbx_xcvr::wbx_xcvr(
this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true);
this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true);
- //set the gpio directions
+ //set the gpio directions and atr controls (identically)
+ this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, TXIO_MASK);
+ this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXIO_MASK);
this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TXIO_MASK);
this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RXIO_MASK);
if (wbx_debug) std::cerr << boost::format(
@@ -303,7 +305,7 @@ double wbx_xcvr::set_lo_freq(
double actual_freq, pfd_freq;
double ref_freq = this->get_iface()->get_clock_rate(unit);
- int R, BS, N, FRAC, MOD;
+ int R=0, BS=0, N=0, FRAC=0, MOD=0;
int RFdiv = 1;
adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED;
adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED;
diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp
index 3472229f4..d4d5f184e 100644
--- a/host/lib/usrp/dboard/db_xcvr2450.cpp
+++ b/host/lib/usrp/dboard/db_xcvr2450.cpp
@@ -169,7 +169,9 @@ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){
//enable only the clocks we need
this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true);
- //set the gpio directions
+ //set the gpio directions and atr controls (identically)
+ this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, TXIO_MASK);
+ this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXIO_MASK);
this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TXIO_MASK);
this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RXIO_MASK);
diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp
index 8161727e5..01352039e 100644
--- a/host/lib/usrp/dboard_manager.cpp
+++ b/host/lib/usrp/dboard_manager.cpp
@@ -298,7 +298,8 @@ void dboard_manager_impl::set_nice_dboard_if(void){
//set nice settings on each unit
BOOST_FOREACH(dboard_iface::unit_t unit, units){
_iface->set_gpio_ddr(unit, 0x0000); //all inputs
- _iface->set_atr_reg(unit, dboard_iface::ATR_REG_IDLE, 0x0000); //all low
+ _iface->write_gpio(unit, 0x0000); //all low
+ _iface->set_pin_ctrl(unit, 0x0000); //all gpio
_iface->set_clock_enabled(unit, false); //clock off
}
}
diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp
index a8c104485..f4aa82669 100644
--- a/host/lib/usrp/simple_usrp.cpp
+++ b/host/lib/usrp/simple_usrp.cpp
@@ -121,6 +121,10 @@ public:
return tune_rx_subdev_and_ddc(_rx_subdev, _rx_dsp, target_freq);
}
+ tune_result_t set_rx_freq(double target_freq, double lo_off){
+ return tune_rx_subdev_and_ddc(_rx_subdev, _rx_dsp, target_freq, lo_off);
+ }
+
freq_range_t get_rx_freq_range(void){
return _rx_subdev[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>();
}
@@ -168,6 +172,10 @@ public:
return tune_tx_subdev_and_duc(_tx_subdev, _tx_dsp, target_freq);
}
+ tune_result_t set_tx_freq(double target_freq, double lo_off){
+ return tune_tx_subdev_and_duc(_tx_subdev, _tx_dsp, target_freq, lo_off);
+ }
+
freq_range_t get_tx_freq_range(void){
return _tx_subdev[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>();
}
diff --git a/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt
index f9907e21e..99d0b8bdd 100644
--- a/host/lib/usrp/usrp2/CMakeLists.txt
+++ b/host/lib/usrp/usrp2/CMakeLists.txt
@@ -18,12 +18,20 @@
#This file will be included by cmake, use absolute paths!
LIBUHD_APPEND_SOURCES(
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/clock_control.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/clock_ctrl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/clock_ctrl.hpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_ctrl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_ctrl.hpp
${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_impl.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_iface.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dsp_impl.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/io_impl.cpp
${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/mboard_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.hpp
${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_iface.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_iface.hpp
${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_impl.hpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_regs.hpp
)
diff --git a/host/lib/usrp/usrp2/clock_control.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp
index 72f1f1c7a..4c5207203 100644
--- a/host/lib/usrp/usrp2/clock_control.cpp
+++ b/host/lib/usrp/usrp2/clock_ctrl.cpp
@@ -15,21 +15,19 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include "usrp2_impl.hpp"
-#include "clock_control.hpp"
+#include "clock_ctrl.hpp"
#include "ad9510_regs.hpp"
#include "usrp2_regs.hpp" //spi slave constants
#include <boost/cstdint.hpp>
using namespace uhd;
-using namespace uhd::usrp;
/*!
* A usrp2 clock control specific to the ad9510 ic.
*/
-class clock_control_ad9510 : public clock_control{
+class clock_ctrl_impl : public clock_ctrl{
public:
- clock_control_ad9510(usrp2_iface::sptr iface){
+ clock_ctrl_impl(usrp2_iface::sptr iface){
_iface = iface;
_ad9510_regs.cp_current_setting = ad9510_regs_t::CP_CURRENT_SETTING_3_0MA;
@@ -70,7 +68,7 @@ public:
}
- ~clock_control_ad9510(void){
+ ~clock_ctrl_impl(void){
/* private clock enables, must be set here */
this->enable_dac_clock(false);
this->enable_adc_clock(false);
@@ -81,7 +79,9 @@ public:
_ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1;
_ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS;
_ad9510_regs.output_level_lvds_out7 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA;
+ _ad9510_regs.bypass_divider_out7 = 1;
this->write_reg(0x43);
+ this->write_reg(0x57);
this->update_regs();
}
@@ -90,7 +90,9 @@ public:
_ad9510_regs.power_down_lvds_cmos_out6 = enb? 0 : 1;
_ad9510_regs.lvds_cmos_select_out6 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_CMOS;
_ad9510_regs.output_level_lvds_out6 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA;
+ _ad9510_regs.bypass_divider_out6 = 1;
this->write_reg(0x42);
+ this->write_reg(0x55);
this->update_regs();
}
@@ -132,7 +134,9 @@ private:
ad9510_regs_t::POWER_DOWN_LVPECL_OUT3_NORMAL :
ad9510_regs_t::POWER_DOWN_LVPECL_OUT3_SAFE_PD;
_ad9510_regs.output_level_lvpecl_out3 = ad9510_regs_t::OUTPUT_LEVEL_LVPECL_OUT3_810MV;
+ _ad9510_regs.bypass_divider_out3 = 1;
this->write_reg(0x3F);
+ this->write_reg(0x4F);
this->update_regs();
}
@@ -141,7 +145,9 @@ private:
_ad9510_regs.power_down_lvds_cmos_out4 = enb? 0 : 1;
_ad9510_regs.lvds_cmos_select_out4 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT4_LVDS;
_ad9510_regs.output_level_lvds_out4 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT4_1_75MA;
+ _ad9510_regs.bypass_divider_out4 = 1;
this->write_reg(0x40);
+ this->write_reg(0x51);
this->update_regs();
}
@@ -152,6 +158,6 @@ private:
/***********************************************************************
* Public make function for the ad9510 clock control
**********************************************************************/
-clock_control::sptr clock_control::make_ad9510(usrp2_iface::sptr iface){
- return clock_control::sptr(new clock_control_ad9510(iface));
+clock_ctrl::sptr clock_ctrl::make(usrp2_iface::sptr iface){
+ return sptr(new clock_ctrl_impl(iface));
}
diff --git a/host/lib/usrp/usrp2/clock_control.hpp b/host/lib/usrp/usrp2/clock_ctrl.hpp
index b64a53196..706bf4246 100644
--- a/host/lib/usrp/usrp2/clock_control.hpp
+++ b/host/lib/usrp/usrp2/clock_ctrl.hpp
@@ -15,23 +15,23 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#ifndef INCLUDED_CLOCK_CONTROL_HPP
-#define INCLUDED_CLOCK_CONTROL_HPP
+#ifndef INCLUDED_CLOCK_CTRL_HPP
+#define INCLUDED_CLOCK_CTRL_HPP
#include "usrp2_iface.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
-class clock_control : boost::noncopyable{
+class clock_ctrl : boost::noncopyable{
public:
- typedef boost::shared_ptr<clock_control> sptr;
+ typedef boost::shared_ptr<clock_ctrl> sptr;
/*!
* Make a clock config for the ad9510 ic.
* \param _iface a pointer to the usrp2 interface object
* \return a new clock control object
*/
- static sptr make_ad9510(usrp2_iface::sptr iface);
+ static sptr make(usrp2_iface::sptr iface);
/*!
* Enable/disable the rx dboard clock.
@@ -57,4 +57,4 @@ public:
};
-#endif /* INCLUDED_CLOCK_CONTROL_HPP */
+#endif /* INCLUDED_CLOCK_CTRL_HPP */
diff --git a/host/lib/usrp/usrp2/codec_ctrl.cpp b/host/lib/usrp/usrp2/codec_ctrl.cpp
new file mode 100644
index 000000000..d698216ba
--- /dev/null
+++ b/host/lib/usrp/usrp2/codec_ctrl.cpp
@@ -0,0 +1,91 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "codec_ctrl.hpp"
+#include "ad9777_regs.hpp"
+#include "usrp2_regs.hpp"
+#include <boost/cstdint.hpp>
+#include <boost/foreach.hpp>
+#include <iostream>
+
+static const bool codec_ctrl_debug = false;
+
+using namespace uhd;
+
+/*!
+ * A usrp2 codec control specific to the ad9777 ic.
+ */
+class codec_ctrl_impl : public codec_ctrl{
+public:
+ codec_ctrl_impl(usrp2_iface::sptr iface){
+ _iface = iface;
+
+ //setup the ad9777 dac
+ _ad9777_regs.x_1r_2r_mode = ad9777_regs_t::X_1R_2R_MODE_1R;
+ _ad9777_regs.filter_interp_rate = ad9777_regs_t::FILTER_INTERP_RATE_4X;
+ _ad9777_regs.mix_mode = ad9777_regs_t::MIX_MODE_REAL;
+ _ad9777_regs.pll_divide_ratio = ad9777_regs_t::PLL_DIVIDE_RATIO_DIV1;
+ _ad9777_regs.pll_state = ad9777_regs_t::PLL_STATE_ON;
+ _ad9777_regs.auto_cp_control = ad9777_regs_t::AUTO_CP_CONTROL_AUTO;
+ //I dac values
+ _ad9777_regs.idac_fine_gain_adjust = 0;
+ _ad9777_regs.idac_coarse_gain_adjust = 0xf;
+ _ad9777_regs.idac_offset_adjust_lsb = 0;
+ _ad9777_regs.idac_offset_adjust_msb = 0;
+ //Q dac values
+ _ad9777_regs.qdac_fine_gain_adjust = 0;
+ _ad9777_regs.qdac_coarse_gain_adjust = 0xf;
+ _ad9777_regs.qdac_offset_adjust_lsb = 0;
+ _ad9777_regs.qdac_offset_adjust_msb = 0;
+ //write all regs
+ for(boost::uint8_t addr = 0; addr <= 0xC; addr++){
+ this->send_ad9777_reg(addr);
+ }
+
+ //power-up adc
+ _iface->poke32(FR_MISC_CTRL_ADC, FRF_MISC_CTRL_ADC_ON);
+ }
+
+ ~codec_ctrl_impl(void){
+ //power-down dac
+ _ad9777_regs.power_down_mode = 1;
+ this->send_ad9777_reg(0);
+
+ //power-down adc
+ _iface->poke32(FR_MISC_CTRL_ADC, FRF_MISC_CTRL_ADC_OFF);
+ }
+
+private:
+ ad9777_regs_t _ad9777_regs;
+ usrp2_iface::sptr _iface;
+
+ void send_ad9777_reg(boost::uint8_t addr){
+ boost::uint16_t reg = _ad9777_regs.get_write_reg(addr);
+ if (codec_ctrl_debug) std::cout << "send_ad9777_reg: " << std::hex << reg << std::endl;
+ _iface->transact_spi(
+ SPI_SS_AD9777, spi_config_t::EDGE_RISE,
+ reg, 16, false /*no rb*/
+ );
+ }
+};
+
+/***********************************************************************
+ * Public make function for the usrp2 codec control
+ **********************************************************************/
+codec_ctrl::sptr codec_ctrl::make(usrp2_iface::sptr iface){
+ return sptr(new codec_ctrl_impl(iface));
+}
diff --git a/host/lib/usrp/usrp2/codec_ctrl.hpp b/host/lib/usrp/usrp2/codec_ctrl.hpp
new file mode 100644
index 000000000..0ee52f476
--- /dev/null
+++ b/host/lib/usrp/usrp2/codec_ctrl.hpp
@@ -0,0 +1,38 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_CODEC_CTRL_HPP
+#define INCLUDED_CODEC_CTRL_HPP
+
+#include "usrp2_iface.hpp"
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+class codec_ctrl : boost::noncopyable{
+public:
+ typedef boost::shared_ptr<codec_ctrl> sptr;
+
+ /*!
+ * Make a codec control for the DAC and ADC.
+ * \param _iface a pointer to the usrp2 interface object
+ * \return a new codec control object
+ */
+ static sptr make(usrp2_iface::sptr iface);
+
+};
+
+#endif /* INCLUDED_CODEC_CTRL_HPP */
diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp
index 372a5af07..0a2e4b550 100644
--- a/host/lib/usrp/usrp2/dboard_iface.cpp
+++ b/host/lib/usrp/usrp2/dboard_iface.cpp
@@ -16,7 +16,7 @@
//
#include "usrp2_iface.hpp"
-#include "clock_control.hpp"
+#include "clock_ctrl.hpp"
#include "usrp2_regs.hpp" //wishbone address constants
#include <uhd/usrp/dboard_iface.hpp>
#include <uhd/types/dict.hpp>
@@ -33,14 +33,16 @@ using namespace boost::assign;
class usrp2_dboard_iface : public dboard_iface{
public:
- usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::sptr clk_ctrl);
+ usrp2_dboard_iface(usrp2_iface::sptr iface, clock_ctrl::sptr clock_ctrl);
~usrp2_dboard_iface(void);
void write_aux_dac(unit_t, int, float);
float read_aux_adc(unit_t, int);
+ void set_pin_ctrl(unit_t, boost::uint16_t);
void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);
void set_gpio_ddr(unit_t, boost::uint16_t);
+ void write_gpio(unit_t, boost::uint16_t);
boost::uint16_t read_gpio(unit_t);
void write_i2c(boost::uint8_t, const byte_vector_t &);
@@ -66,8 +68,9 @@ public:
private:
usrp2_iface::sptr _iface;
- clock_control::sptr _clk_ctrl;
+ clock_ctrl::sptr _clock_ctrl;
boost::uint32_t _ddr_shadow;
+ boost::uint32_t _gpio_shadow;
uhd::dict<unit_t, ad5624_regs_t> _dac_regs;
void _write_aux_dac(unit_t);
@@ -78,26 +81,19 @@ private:
**********************************************************************/
dboard_iface::sptr make_usrp2_dboard_iface(
usrp2_iface::sptr iface,
- clock_control::sptr clk_ctrl
+ clock_ctrl::sptr clock_ctrl
){
- return dboard_iface::sptr(new usrp2_dboard_iface(iface, clk_ctrl));
+ return dboard_iface::sptr(new usrp2_dboard_iface(iface, clock_ctrl));
}
/***********************************************************************
* Structors
**********************************************************************/
-usrp2_dboard_iface::usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::sptr clk_ctrl){
+usrp2_dboard_iface::usrp2_dboard_iface(usrp2_iface::sptr iface, clock_ctrl::sptr clock_ctrl){
_iface = iface;
- _clk_ctrl = clk_ctrl;
+ _clock_ctrl = clock_ctrl;
_ddr_shadow = 0;
-
- //set the selection mux to use atr
- boost::uint32_t new_sels = 0x0;
- for(size_t i = 0; i < 16; i++){
- new_sels |= FRF_GPIO_SEL_ATR << (i*2);
- }
- _iface->poke32(FR_GPIO_TX_SEL, new_sels);
- _iface->poke32(FR_GPIO_RX_SEL, new_sels);
+ _gpio_shadow = 0;
//reset the aux dacs
_dac_regs[UNIT_RX] = ad5624_regs_t();
@@ -123,8 +119,8 @@ double usrp2_dboard_iface::get_clock_rate(unit_t){
void usrp2_dboard_iface::set_clock_enabled(unit_t unit, bool enb){
switch(unit){
- case UNIT_RX: _clk_ctrl->enable_rx_dboard_clock(enb); return;
- case UNIT_TX: _clk_ctrl->enable_tx_dboard_clock(enb); return;
+ case UNIT_RX: _clock_ctrl->enable_rx_dboard_clock(enb); return;
+ case UNIT_TX: _clock_ctrl->enable_tx_dboard_clock(enb); return;
}
}
@@ -136,6 +132,21 @@ static const uhd::dict<dboard_iface::unit_t, int> unit_to_shift = map_list_of
(dboard_iface::UNIT_TX, 16)
;
+void usrp2_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint16_t value){
+ //calculate the new selection mux setting
+ boost::uint32_t new_sels = 0x0;
+ for(size_t i = 0; i < 16; i++){
+ bool is_bit_set = bool(value & (0x1 << i));
+ new_sels |= ((is_bit_set)? FRF_GPIO_SEL_ATR : FRF_GPIO_SEL_GPIO) << (i*2);
+ }
+
+ //write the selection mux value to register
+ switch(unit){
+ case UNIT_RX: _iface->poke32(FR_GPIO_RX_SEL, new_sels); return;
+ case UNIT_TX: _iface->poke32(FR_GPIO_TX_SEL, new_sels); return;
+ }
+}
+
void usrp2_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){
_ddr_shadow = \
(_ddr_shadow & ~(0xffff << unit_to_shift[unit])) |
@@ -143,6 +154,13 @@ void usrp2_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){
_iface->poke32(FR_GPIO_DDR, _ddr_shadow);
}
+void usrp2_dboard_iface::write_gpio(unit_t unit, boost::uint16_t value){
+ _gpio_shadow = \
+ (_gpio_shadow & ~(0xffff << unit_to_shift[unit])) |
+ (boost::uint32_t(value) << unit_to_shift[unit]);
+ _iface->poke32(FR_GPIO_IO, _gpio_shadow);
+}
+
boost::uint16_t usrp2_dboard_iface::read_gpio(unit_t unit){
return boost::uint16_t(_iface->peek32(FR_GPIO_IO) >> unit_to_shift[unit]);
}
diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp
index 403faf5cf..0ac39d2a3 100644
--- a/host/lib/usrp/usrp2/dboard_impl.cpp
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -38,9 +38,7 @@ void usrp2_impl::dboard_init(void){
_tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes()));
//create a new dboard interface and manager
- dboard_iface::sptr _dboard_iface(
- make_usrp2_dboard_iface(_iface, _clk_ctrl)
- );
+ _dboard_iface = make_usrp2_dboard_iface(_iface, _clock_ctrl);
_dboard_manager = dboard_manager::make(
_rx_db_eeprom.id, _tx_db_eeprom.id, _dboard_iface
);
@@ -123,6 +121,10 @@ void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){
val = _rx_db_eeprom.id;
return;
+ case DBOARD_PROP_DBOARD_IFACE:
+ val = _dboard_iface;
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -172,6 +174,10 @@ void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){
val = _tx_db_eeprom.id;
return;
+ case DBOARD_PROP_DBOARD_IFACE:
+ val = _dboard_iface;
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp
index fc4c5479e..195a9bc53 100644
--- a/host/lib/usrp/usrp2/dsp_impl.cpp
+++ b/host/lib/usrp/usrp2/dsp_impl.cpp
@@ -94,9 +94,6 @@ void usrp2_impl::init_ddc_config(void){
_ddc_decim = default_decim;
_ddc_freq = 0;
update_ddc_config();
-
- //initial command that kills streaming (in case if was left on)
- issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
}
void usrp2_impl::update_ddc_config(void){
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index e80001ff2..75f5b1779 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -34,7 +34,7 @@ extern "C" {
//defines the protocol version in this shared header
//increment this value when the protocol is changed
-#define USRP2_PROTO_VERSION 2
+#define USRP2_PROTO_VERSION 3
//used to differentiate control packets over data port
#define USRP2_INVALID_VRT_HEADER 0
@@ -53,13 +53,8 @@ typedef enum{
//USRP2_CTRL_ID_FOR_SURE, //TODO error condition enums
//USRP2_CTRL_ID_SUX_MAN,
- USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO = 'a',
- USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE = 'A',
- USRP2_CTRL_ID_HERE_IS_A_NEW_IP_ADDR_BRO = 'b',
-
- USRP2_CTRL_ID_GIVE_ME_YOUR_MAC_ADDR_BRO = 'm',
- USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE = 'M',
- USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO = 'n',
+ USRP2_CTRL_ID_WAZZUP_BRO = 'a',
+ USRP2_CTRL_ID_WAZZUP_DUDE = 'A',
USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO = 's',
USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE = 'S',
@@ -70,9 +65,6 @@ typedef enum{
USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO = 'h',
USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE = 'H',
- USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO = '{',
- USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE = '}',
-
USRP2_CTRL_ID_POKE_THIS_REGISTER_FOR_ME_BRO = 'p',
USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE = 'P',
@@ -99,7 +91,6 @@ typedef struct{
_SINS_ uint32_t seq;
union{
_SINS_ uint32_t ip_addr;
- _SINS_ uint8_t mac_addr[6];
struct {
_SINS_ uint8_t dev;
_SINS_ uint8_t miso_edge;
@@ -114,15 +105,6 @@ typedef struct{
_SINS_ uint8_t data[sizeof(_SINS_ uint32_t)];
} i2c_args;
struct {
- _SINS_ uint8_t now; //stream now?
- _SINS_ uint8_t continuous; //auto-reload commmands?
- _SINS_ uint8_t chain;
- _SINS_ uint8_t _pad[1];
- _SINS_ uint32_t secs;
- _SINS_ uint32_t ticks;
- _SINS_ uint32_t num_samps;
- } stream_cmd;
- struct {
_SINS_ uint32_t addr;
_SINS_ uint32_t data;
_SINS_ uint8_t num_bytes; //1, 2, 4
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index 2634e84aa..79b18fb63 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -16,6 +16,7 @@
//
#include "usrp2_impl.hpp"
+#include "usrp2_regs.hpp"
#include <uhd/transport/convert_types.hpp>
#include <boost/format.hpp>
#include <boost/asio.hpp> //htonl and ntohl
@@ -30,71 +31,35 @@ namespace asio = boost::asio;
* Helper Functions
**********************************************************************/
void usrp2_impl::io_init(void){
- //setup otw type
- _otw_type.width = 16;
- _otw_type.shift = 0;
- _otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN;
+ //setup rx otw type
+ _rx_otw_type.width = 16;
+ _rx_otw_type.shift = 0;
+ _rx_otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN;
- //initially empty copy buffer
- _rx_copy_buff = asio::buffer("", 0);
-
- //init the expected rx seq number
- _rx_stream_id_to_packet_seq[0] = 0;
+ //setup tx otw type
+ _tx_otw_type.width = 16;
+ _tx_otw_type.shift = 0;
+ _tx_otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN;
//send a small data packet so the usrp2 knows the udp source port
- //and the maximum number of lines (32 bit words) per packet
managed_send_buffer::sptr send_buff = _data_transport->get_send_buff();
- boost::uint32_t data[2] = {
- htonl(USRP2_INVALID_VRT_HEADER),
- htonl(_max_rx_samples_per_packet)
- };
- memcpy(send_buff->cast<void*>(), data, sizeof(data));
- send_buff->done(sizeof(data));
-}
-
-/***********************************************************************
- * Receive Raw Data
- **********************************************************************/
-void usrp2_impl::recv_raw(rx_metadata_t &metadata){
- //do a receive
- _rx_smart_buff = _data_transport->get_recv_buff();
-
- //unpack the vrt header
- size_t num_packet_words32 = _rx_smart_buff->size()/sizeof(boost::uint32_t);
- if (num_packet_words32 == 0){
- _rx_copy_buff = boost::asio::buffer("", 0);
- return; //must exit here after setting the buffer
- }
- const boost::uint32_t *vrt_hdr = _rx_smart_buff->cast<const boost::uint32_t *>();
- size_t num_header_words32_out, num_payload_words32_out, packet_count_out;
- try{
- vrt::unpack(
- metadata, //output
- vrt_hdr, //input
- num_header_words32_out, //output
- num_payload_words32_out, //output
- num_packet_words32, //input
- packet_count_out, //output
- get_master_clock_freq()
- );
- }catch(const std::exception &e){
- std::cerr << "bad vrt header: " << e.what() << std::endl;
- _rx_copy_buff = boost::asio::buffer("", 0);
- return; //must exit here after setting the buffer
- }
-
- //handle the packet count / sequence number
- size_t expected_packet_count = _rx_stream_id_to_packet_seq[metadata.stream_id];
- if (packet_count_out != expected_packet_count){
- std::cerr << "S" << (packet_count_out - expected_packet_count)%16;
- }
- _rx_stream_id_to_packet_seq[metadata.stream_id] = (packet_count_out+1)%16;
-
- //setup the rx buffer to point to the data
- _rx_copy_buff = asio::buffer(
- vrt_hdr + num_header_words32_out,
- num_payload_words32_out*sizeof(boost::uint32_t)
+ boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER);
+ memcpy(send_buff->cast<void*>(), &data, sizeof(data));
+ send_buff->commit(sizeof(data));
+
+ //setup RX DSP regs
+ std::cout << "RX samples per packet: " << get_max_recv_samps_per_packet() << std::endl;
+ _iface->poke32(FR_RX_CTRL_NSAMPS_PER_PKT, get_max_recv_samps_per_packet());
+ _iface->poke32(FR_RX_CTRL_NCHANNELS, 1);
+ _iface->poke32(FR_RX_CTRL_CLEAR_OVERRUN, 1); //reset
+ _iface->poke32(FR_RX_CTRL_VRT_HEADER, 0
+ | (0x1 << 28) //if data with stream id
+ | (0x1 << 26) //has trailer
+ | (0x3 << 22) //integer time other
+ | (0x1 << 20) //fractional time sample count
);
+ _iface->poke32(FR_RX_CTRL_VRT_STREAM_ID, 0);
+ _iface->poke32(FR_RX_CTRL_VRT_TRAILER, 0);
}
/***********************************************************************
@@ -102,49 +67,18 @@ void usrp2_impl::recv_raw(rx_metadata_t &metadata){
**********************************************************************/
size_t usrp2_impl::send(
const asio::const_buffer &buff,
- const tx_metadata_t &metadata_,
- const io_type_t &io_type
+ const tx_metadata_t &metadata,
+ const io_type_t &io_type,
+ send_mode_t send_mode
){
- tx_metadata_t metadata = metadata_; //rw copy to change later
-
- transport::managed_send_buffer::sptr send_buff = _data_transport->get_send_buff();
- boost::uint32_t *tx_mem = send_buff->cast<boost::uint32_t *>();
- size_t num_samps = std::min(std::min(
- asio::buffer_size(buff)/io_type.size,
- size_t(_max_tx_samples_per_packet)),
- send_buff->size()/io_type.size
- );
-
- //kill the end of burst flag if this is a fragment
- if (asio::buffer_size(buff)/io_type.size < num_samps)
- metadata.end_of_burst = false;
-
- size_t num_header_words32, num_packet_words32;
- size_t packet_count = _tx_stream_id_to_packet_seq[metadata.stream_id]++;
-
- //pack metadata into a vrt header
- vrt::pack(
- metadata, //input
- tx_mem, //output
- num_header_words32, //output
- num_samps, //input
- num_packet_words32, //output
- packet_count, //input
- get_master_clock_freq()
- );
-
- boost::uint32_t *items = tx_mem + num_header_words32; //offset for data
-
- //copy-convert the samples into the send buffer
- convert_io_type_to_otw_type(
- asio::buffer_cast<const void*>(buff), io_type,
- (void*)items, _otw_type,
- num_samps
+ return vrt_packet_handler::send(
+ _packet_handler_send_state, //last state of the send handler
+ buff, metadata, send_mode, //buffer to empty and samples metadata
+ io_type, _tx_otw_type, //input and output types to convert
+ get_master_clock_freq(), //master clock tick rate
+ _data_transport, //zero copy interface
+ get_max_send_samps_per_packet()
);
-
- //send and return number of samples
- send_buff->done(num_packet_words32*sizeof(boost::uint32_t));
- return num_samps;
}
/***********************************************************************
@@ -153,44 +87,14 @@ size_t usrp2_impl::send(
size_t usrp2_impl::recv(
const asio::mutable_buffer &buff,
rx_metadata_t &metadata,
- const io_type_t &io_type
+ const io_type_t &io_type,
+ recv_mode_t recv_mode
){
- //perform a receive if no rx data is waiting to be copied
- if (asio::buffer_size(_rx_copy_buff) == 0){
- _fragment_offset_in_samps = 0;
- recv_raw(metadata);
- }
- //otherwise flag the metadata to show that is is a fragment
- else{
- metadata = rx_metadata_t();
- }
-
- //extract the number of samples available to copy
- //and a pointer into the usrp2 received items memory
- size_t bytes_to_copy = asio::buffer_size(_rx_copy_buff);
- if (bytes_to_copy == 0) return 0; //nothing to receive
- size_t num_samps = std::min(
- asio::buffer_size(buff)/io_type.size,
- bytes_to_copy/sizeof(boost::uint32_t)
+ return vrt_packet_handler::recv(
+ _packet_handler_recv_state, //last state of the recv handler
+ buff, metadata, recv_mode, //buffer to fill and samples metadata
+ io_type, _rx_otw_type, //input and output types to convert
+ get_master_clock_freq(), //master clock tick rate
+ _data_transport //zero copy interface
);
- const boost::uint32_t *items = asio::buffer_cast<const boost::uint32_t*>(_rx_copy_buff);
-
- //setup the fragment flags and offset
- metadata.more_fragments = asio::buffer_size(buff)/io_type.size < num_samps;
- metadata.fragment_offset = _fragment_offset_in_samps;
- _fragment_offset_in_samps += num_samps; //set for next time
-
- //copy-convert the samples from the recv buffer
- convert_otw_type_to_io_type(
- (const void*)items, _otw_type,
- asio::buffer_cast<void*>(buff), io_type,
- num_samps
- );
-
- //update the rx copy buffer to reflect the bytes copied
- _rx_copy_buff = asio::buffer(
- items + num_samps, bytes_to_copy - num_samps*sizeof(boost::uint32_t)
- );
-
- return num_samps;
}
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 36bef4f25..a2aeadf16 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -17,13 +17,13 @@
#include "usrp2_impl.hpp"
#include "usrp2_regs.hpp"
-#include "ad9777_regs.hpp"
#include <uhd/usrp/mboard_props.hpp>
#include <uhd/utils/assert.hpp>
+#include <uhd/utils/algorithm.hpp>
#include <uhd/types/mac_addr.hpp>
#include <uhd/types/dict.hpp>
#include <boost/bind.hpp>
-#include <boost/asio.hpp> //htonl and ntohl
+#include <boost/asio/ip/address_v4.hpp>
#include <boost/assign/list_of.hpp>
using namespace uhd;
@@ -37,32 +37,6 @@ void usrp2_impl::mboard_init(void){
boost::bind(&usrp2_impl::mboard_get, this, _1, _2),
boost::bind(&usrp2_impl::mboard_set, this, _1, _2)
);
-
- _clk_ctrl = clock_control::make_ad9510(_iface);
-
- //setup the ad9777 dac
- ad9777_regs_t ad9777_regs;
- ad9777_regs.x_1r_2r_mode = ad9777_regs_t::X_1R_2R_MODE_1R;
- ad9777_regs.filter_interp_rate = ad9777_regs_t::FILTER_INTERP_RATE_4X;
- ad9777_regs.mix_mode = ad9777_regs_t::MIX_MODE_REAL;
- ad9777_regs.pll_divide_ratio = ad9777_regs_t::PLL_DIVIDE_RATIO_DIV1;
- ad9777_regs.pll_state = ad9777_regs_t::PLL_STATE_OFF;
- ad9777_regs.auto_cp_control = ad9777_regs_t::AUTO_CP_CONTROL_ENB;
- //I dac values
- ad9777_regs.idac_fine_gain_adjust = 0;
- ad9777_regs.idac_coarse_gain_adjust = 0xf;
- ad9777_regs.idac_offset_adjust_lsb = 0;
- ad9777_regs.idac_offset_adjust_msb = 0;
- //Q dac values
- ad9777_regs.qdac_fine_gain_adjust = 0;
- ad9777_regs.qdac_coarse_gain_adjust = 0xf;
- ad9777_regs.qdac_offset_adjust_lsb = 0;
- ad9777_regs.qdac_offset_adjust_msb = 0;
- //write all regs
- for(boost::uint8_t addr = 0; addr <= 0xC; addr++){
- boost::uint16_t data = ad9777_regs.get_write_reg(addr);
- _iface->transact_spi(SPI_SS_AD9777, spi_config_t::EDGE_RISE, data, 16, false /*no rb*/);
- }
}
void usrp2_impl::init_clock_config(void){
@@ -97,62 +71,55 @@ void usrp2_impl::update_clock_config(void){
//clock source ref 10mhz
switch(_clock_config.ref_source){
- case clock_config_t::REF_INT : _iface->poke32(FR_CLOCK_CONTROL, 0x10); break;
- case clock_config_t::REF_SMA : _iface->poke32(FR_CLOCK_CONTROL, 0x1C); break;
- case clock_config_t::REF_MIMO: _iface->poke32(FR_CLOCK_CONTROL, 0x15); break;
+ case clock_config_t::REF_INT : _iface->poke32(FR_MISC_CTRL_CLOCK, 0x10); break;
+ case clock_config_t::REF_SMA : _iface->poke32(FR_MISC_CTRL_CLOCK, 0x1C); break;
+ case clock_config_t::REF_MIMO: _iface->poke32(FR_MISC_CTRL_CLOCK, 0x15); break;
default: throw std::runtime_error("usrp2: unhandled clock configuration reference source");
}
//clock source ref 10mhz
bool use_external = _clock_config.ref_source != clock_config_t::REF_INT;
- _clk_ctrl->enable_external_ref(use_external);
+ _clock_ctrl->enable_external_ref(use_external);
}
void usrp2_impl::set_time_spec(const time_spec_t &time_spec, bool now){
- //set ticks and seconds
- _iface->poke32(FR_TIME64_SECS, time_spec.secs);
+ //set the ticks
_iface->poke32(FR_TIME64_TICKS, time_spec.get_ticks(get_master_clock_freq()));
- //set the register to latch it all in
+ //set the flags register
boost::uint32_t imm_flags = (now)? FRF_TIME64_LATCH_NOW : FRF_TIME64_LATCH_NEXT_PPS;
_iface->poke32(FR_TIME64_IMM, imm_flags);
+
+ //set the seconds (latches in all 3 registers)
+ _iface->poke32(FR_TIME64_SECS, time_spec.secs);
}
void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
- //setup the out data
- usrp2_ctrl_data_t out_data;
- out_data.id = htonl(USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO);
- out_data.data.stream_cmd.now = (stream_cmd.stream_now)? 1 : 0;
- out_data.data.stream_cmd.secs = htonl(stream_cmd.time_spec.secs);
- out_data.data.stream_cmd.ticks = htonl(stream_cmd.time_spec.get_ticks(get_master_clock_freq()));
-
- //set these to defaults, then change in the switch statement
- out_data.data.stream_cmd.continuous = 0;
- out_data.data.stream_cmd.chain = 0;
- out_data.data.stream_cmd.num_samps = htonl(stream_cmd.num_samps);
-
- //setup chain, num samps, and continuous below
- switch(stream_cmd.stream_mode){
- case stream_cmd_t::STREAM_MODE_START_CONTINUOUS:
- out_data.data.stream_cmd.continuous = 1;
- break;
-
- case stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS:
- out_data.data.stream_cmd.num_samps = htonl(0);
- break;
-
- case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE:
- //all set by defaults above
- break;
-
- case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE:
- out_data.data.stream_cmd.chain = 1;
- break;
- }
-
- //send and recv
- usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
- UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE);
+ UHD_ASSERT_THROW(stream_cmd.num_samps <= FR_RX_CTRL_MAX_SAMPS_PER_CMD);
+
+ //setup the mode to instruction flags
+ typedef boost::tuple<bool, bool, bool> inst_t;
+ static const uhd::dict<stream_cmd_t::stream_mode_t, inst_t> mode_to_inst = boost::assign::map_list_of
+ //reload, chain, samps
+ (stream_cmd_t::STREAM_MODE_START_CONTINUOUS, inst_t(true, true, false))
+ (stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS, inst_t(false, false, false))
+ (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE, inst_t(false, false, true))
+ (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE, inst_t(false, true, true))
+ ;
+
+ //setup the instruction flag values
+ bool inst_reload, inst_chain, inst_samps;
+ boost::tie(inst_reload, inst_chain, inst_samps) = mode_to_inst[stream_cmd.stream_mode];
+
+ //issue the stream command
+ _iface->poke32(FR_RX_CTRL_STREAM_CMD, FR_RX_CTRL_MAKE_CMD(
+ (inst_samps)? stream_cmd.num_samps : ((inst_chain)? get_max_recv_samps_per_packet() : 1),
+ (stream_cmd.stream_now)? 1 : 0,
+ (inst_chain)? 1 : 0,
+ (inst_reload)? 1 : 0
+ ));
+ _iface->poke32(FR_RX_CTRL_TIME_SECS, stream_cmd.time_spec.secs);
+ _iface->poke32(FR_RX_CTRL_TIME_TICKS, stream_cmd.time_spec.get_ticks(get_master_clock_freq()));
}
/***********************************************************************
@@ -165,30 +132,15 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){
//handle the other props
if (key.type() == typeid(std::string)){
if (key.as<std::string>() == "mac-addr"){
- //setup the out data
- usrp2_ctrl_data_t out_data;
- out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_MAC_ADDR_BRO);
-
- //send and recv
- usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
- UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE);
-
- //extract the address
- val = mac_addr_t::from_bytes(in_data.data.mac_addr).to_string();
+ byte_vector_t bytes = _iface->read_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_MAC_ADDR, 6);
+ val = mac_addr_t::from_bytes(bytes).to_string();
return;
}
if (key.as<std::string>() == "ip-addr"){
- //setup the out data
- usrp2_ctrl_data_t out_data;
- out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO);
-
- //send and recv
- usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
- UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE);
-
- //extract the address
- val = boost::asio::ip::address_v4(ntohl(in_data.data.ip_addr)).to_string();
+ boost::asio::ip::address_v4::bytes_type bytes;
+ std::copy(_iface->read_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_IP_ADDR, 4), bytes);
+ val = boost::asio::ip::address_v4(bytes).to_string();
return;
}
}
@@ -259,27 +211,15 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
//handle the other props
if (key.type() == typeid(std::string)){
if (key.as<std::string>() == "mac-addr"){
- //setup the out data
- usrp2_ctrl_data_t out_data;
- out_data.id = htonl(USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO);
- mac_addr_t mac_addr = mac_addr_t::from_string(val.as<std::string>());
- std::copy(mac_addr.to_bytes(), mac_addr.to_bytes()+mac_addr_t::hlen, out_data.data.mac_addr);
-
- //send and recv
- usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
- UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE);
+ byte_vector_t bytes = mac_addr_t::from_string(val.as<std::string>()).to_bytes();
+ _iface->write_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_MAC_ADDR, bytes);
return;
}
if (key.as<std::string>() == "ip-addr"){
- //setup the out data
- usrp2_ctrl_data_t out_data;
- out_data.id = htonl(USRP2_CTRL_ID_HERE_IS_A_NEW_IP_ADDR_BRO);
- out_data.data.ip_addr = htonl(boost::asio::ip::address_v4::from_string(val.as<std::string>()).to_ulong());
-
- //send and recv
- usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
- UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE);
+ byte_vector_t bytes(4);
+ std::copy(boost::asio::ip::address_v4::from_string(val.as<std::string>()).to_bytes(), bytes);
+ _iface->write_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_IP_ADDR, bytes);
return;
}
}
diff --git a/host/lib/usrp/usrp2/serdes_ctrl.cpp b/host/lib/usrp/usrp2/serdes_ctrl.cpp
new file mode 100644
index 000000000..dde22b499
--- /dev/null
+++ b/host/lib/usrp/usrp2/serdes_ctrl.cpp
@@ -0,0 +1,46 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "serdes_ctrl.hpp"
+#include "usrp2_regs.hpp"
+
+using namespace uhd;
+
+/*!
+ * A usrp2 serdes control implementation
+ */
+class serdes_ctrl_impl : public serdes_ctrl{
+public:
+ serdes_ctrl_impl(usrp2_iface::sptr iface){
+ _iface = iface;
+ _iface->poke32(FR_MISC_CTRL_SERDES, FRF_MISC_CTRL_SERDES_ENABLE | FRF_MISC_CTRL_SERDES_RXEN);
+ }
+
+ ~serdes_ctrl_impl(void){
+ _iface->poke32(FR_MISC_CTRL_SERDES, 0); //power-down
+ }
+
+private:
+ usrp2_iface::sptr _iface;
+};
+
+/***********************************************************************
+ * Public make function for the usrp2 serdes control
+ **********************************************************************/
+serdes_ctrl::sptr serdes_ctrl::make(usrp2_iface::sptr iface){
+ return sptr(new serdes_ctrl_impl(iface));
+}
diff --git a/host/lib/usrp/usrp2/serdes_ctrl.hpp b/host/lib/usrp/usrp2/serdes_ctrl.hpp
new file mode 100644
index 000000000..586238739
--- /dev/null
+++ b/host/lib/usrp/usrp2/serdes_ctrl.hpp
@@ -0,0 +1,40 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_SERDES_CTRL_HPP
+#define INCLUDED_SERDES_CTRL_HPP
+
+#include "usrp2_iface.hpp"
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+class serdes_ctrl : boost::noncopyable{
+public:
+ typedef boost::shared_ptr<serdes_ctrl> sptr;
+
+ /*!
+ * Make a serdes control object for the usrp2 serdes port.
+ * \param _iface a pointer to the usrp2 interface object
+ * \return a new serdes control object
+ */
+ static sptr make(usrp2_iface::sptr iface);
+
+ //TODO fill me in with virtual methods
+
+};
+
+#endif /* INCLUDED_SERDES_CTRL_HPP */
diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp
index 7158c58d0..caf6623e2 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.hpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.hpp
@@ -32,7 +32,14 @@
#define I2C_ADDR_MBOARD (I2C_DEV_EEPROM | 0x0)
#define I2C_ADDR_TX_DB (I2C_DEV_EEPROM | 0x4)
#define I2C_ADDR_RX_DB (I2C_DEV_EEPROM | 0x5)
+
+////////////////////////////////////////////////////////////////////////
+// EEPROM Layout
////////////////////////////////////////////////////////////////////////
+#define EE_MBOARD_REV_LSB 0x00 //1 byte
+#define EE_MBOARD_REV_MSB 0x01 //1 byte
+#define EE_MBOARD_MAC_ADDR 0x02 //6 bytes
+#define EE_MBOARD_IP_ADDR 0x0C //uint32, big-endian
/*!
* The usrp2 interface class:
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index 1dde8c054..af3ec216a 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -72,7 +72,7 @@ uhd::device_addrs_t usrp2::find(const device_addr_t &hint){
//send a hello control packet
usrp2_ctrl_data_t ctrl_data_out;
ctrl_data_out.proto_ver = htonl(USRP2_PROTO_VERSION);
- ctrl_data_out.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO);
+ ctrl_data_out.id = htonl(USRP2_CTRL_ID_WAZZUP_BRO);
udp_transport->send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out)));
//loop and recieve until the timeout
@@ -83,7 +83,7 @@ uhd::device_addrs_t usrp2::find(const device_addr_t &hint){
if (len >= sizeof(usrp2_ctrl_data_t)){
//handle the received data
switch(ntohl(ctrl_data_in.id)){
- case USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE:
+ case USRP2_CTRL_ID_WAZZUP_DUDE:
//make a boost asio ipv4 with the raw addr in host byte order
boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in.data.ip_addr));
device_addr_t new_addr;
@@ -147,6 +147,9 @@ usrp2_impl::usrp2_impl(
//make a new interface for usrp2 stuff
_iface = usrp2_iface::make(ctrl_transport);
+ _clock_ctrl = clock_ctrl::make(_iface);
+ _codec_ctrl = codec_ctrl::make(_iface);
+ _serdes_ctrl = serdes_ctrl::make(_iface);
//load the allowed decim/interp rates
//_USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4)
@@ -207,14 +210,6 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){
val = prop_names_t(1, "");
return;
- case DEVICE_PROP_MAX_RX_SAMPLES:
- val = size_t(_max_rx_samples_per_packet);
- return;
-
- case DEVICE_PROP_MAX_TX_SAMPLES:
- val = size_t(_max_tx_samples_per_packet);
- return;
-
default: UHD_THROW_PROP_GET_ERROR();
}
}
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index 1c9387744..7948a2069 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -19,7 +19,9 @@
#define INCLUDED_USRP2_IMPL_HPP
#include "usrp2_iface.hpp"
-#include "clock_control.hpp"
+#include "clock_ctrl.hpp"
+#include "codec_ctrl.hpp"
+#include "serdes_ctrl.hpp"
#include <uhd/usrp/usrp2.hpp>
#include <uhd/types/dict.hpp>
#include <uhd/types/otw_type.hpp>
@@ -31,6 +33,7 @@
#include <uhd/transport/vrt.hpp>
#include <uhd/transport/udp_zero_copy.hpp>
#include <uhd/usrp/dboard_manager.hpp>
+#include "../../transport/vrt_packet_handler.hpp"
/*!
* Make a usrp2 dboard interface.
@@ -40,7 +43,7 @@
*/
uhd::usrp::dboard_iface::sptr make_usrp2_dboard_iface(
usrp2_iface::sptr iface,
- clock_control::sptr clk_ctrl
+ clock_ctrl::sptr clk_ctrl
);
/*!
@@ -101,8 +104,24 @@ public:
~usrp2_impl(void);
//the io interface
- size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const uhd::io_type_t &);
- size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &);
+ size_t get_max_send_samps_per_packet(void) const{
+ return _max_tx_bytes_per_packet/_tx_otw_type.get_sample_size();
+ }
+ size_t send(
+ const boost::asio::const_buffer &,
+ const uhd::tx_metadata_t &,
+ const uhd::io_type_t &,
+ uhd::device::send_mode_t
+ );
+ size_t get_max_recv_samps_per_packet(void) const{
+ return _max_rx_bytes_per_packet/_rx_otw_type.get_sample_size();
+ }
+ size_t recv(
+ const boost::asio::mutable_buffer &,
+ uhd::rx_metadata_t &,
+ const uhd::io_type_t &,
+ uhd::device::recv_mode_t
+ );
private:
double get_master_clock_freq(void){
@@ -114,28 +133,29 @@ private:
void set(const wax::obj &, const wax::obj &);
//interfaces
- clock_control::sptr _clk_ctrl;
usrp2_iface::sptr _iface;
+ clock_ctrl::sptr _clock_ctrl;
+ codec_ctrl::sptr _codec_ctrl;
+ serdes_ctrl::sptr _serdes_ctrl;
- //the raw io interface (samples are in the usrp2 native format)
- void recv_raw(uhd::rx_metadata_t &);
- uhd::dict<boost::uint32_t, size_t> _tx_stream_id_to_packet_seq;
- uhd::dict<boost::uint32_t, size_t> _rx_stream_id_to_packet_seq;
+ /*******************************************************************
+ * Deal with the rx and tx packet sizes
+ ******************************************************************/
static const size_t _mtu = 1500; //FIXME we have no idea
static const size_t _hdrs = (2 + 14 + 20 + 8); //size of headers (pad, eth, ip, udp)
- static const size_t _max_rx_samples_per_packet =
- (_mtu - _hdrs)/sizeof(boost::uint32_t) -
- USRP2_HOST_RX_VRT_HEADER_WORDS32 -
- USRP2_HOST_RX_VRT_TRAILER_WORDS32
+ static const size_t _max_rx_bytes_per_packet =
+ _mtu - _hdrs -
+ USRP2_HOST_RX_VRT_HEADER_WORDS32*sizeof(boost::uint32_t) -
+ USRP2_HOST_RX_VRT_TRAILER_WORDS32*sizeof(boost::uint32_t)
;
- static const size_t _max_tx_samples_per_packet =
- (_mtu - _hdrs)/sizeof(boost::uint32_t) -
- uhd::transport::vrt::max_header_words32
+ static const size_t _max_tx_bytes_per_packet =
+ _mtu - _hdrs -
+ uhd::transport::vrt::max_header_words32*sizeof(boost::uint32_t)
;
- uhd::transport::managed_recv_buffer::sptr _rx_smart_buff;
- boost::asio::const_buffer _rx_copy_buff;
- size_t _fragment_offset_in_samps;
- uhd::otw_type_t _otw_type;
+
+ vrt_packet_handler::recv_state _packet_handler_recv_state;
+ vrt_packet_handler::send_state _packet_handler_send_state;
+ uhd::otw_type_t _rx_otw_type, _tx_otw_type;
void io_init(void);
//udp transports for control and data
@@ -149,6 +169,7 @@ private:
//rx and tx dboard methods and objects
uhd::usrp::dboard_manager::sptr _dboard_manager;
+ uhd::usrp::dboard_iface::sptr _dboard_iface;
void dboard_init(void);
//properties for the mboard
diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp
index 0e2a18756..0f675357b 100644
--- a/host/lib/usrp/usrp2/usrp2_regs.hpp
+++ b/host/lib/usrp/usrp2/usrp2_regs.hpp
@@ -64,7 +64,23 @@
/////////////////////////////////////////////////
// Misc Control
////////////////////////////////////////////////
-#define FR_CLOCK_CONTROL _SR_ADDR(0)
+#define FR_MISC_CTRL_CLOCK _SR_ADDR(0)
+#define FR_MISC_CTRL_SERDES _SR_ADDR(1)
+#define FR_MISC_CTRL_ADC _SR_ADDR(2)
+#define FR_MISC_CTRL_LEDS _SR_ADDR(3)
+#define FR_MISC_CTRL_PHY _SR_ADDR(4) // LSB is reset line to eth phy
+#define FR_MISC_CTRL_DBG_MUX _SR_ADDR(5)
+#define FR_MISC_CTRL_RAM_PAGE _SR_ADDR(6) // FIXME should go somewhere else...
+#define FR_MISC_CTRL_FLUSH_ICACHE _SR_ADDR(7) // Flush the icache
+#define FR_MISC_CTRL_LED_SRC _SR_ADDR(8) // HW or SW control for LEDs
+
+#define FRF_MISC_CTRL_SERDES_ENABLE 8
+#define FRF_MISC_CTRL_SERDES_PRBSEN 4
+#define FRF_MISC_CTRL_SERDES_LOOPEN 2
+#define FRF_MISC_CTRL_SERDES_RXEN 1
+
+#define FRF_MISC_CTRL_ADC_ON 0x0F
+#define FRF_MISC_CTRL_ADC_OFF 0x00
/////////////////////////////////////////////////
// VITA49 64 bit time (write only)
@@ -188,7 +204,7 @@
#define FR_GPIO_RX_SEL FR_GPIO_BASE + 12 // 16 2-bit fields select which source goes to RX DB
// each 2-bit sel field is layed out this way
-#define FRF_GPIO_SEL_SW 0 // if pin is an output, set by software in the io reg
+#define FRF_GPIO_SEL_GPIO 0 // if pin is an output, set by GPIO register
#define FRF_GPIO_SEL_ATR 1 // if pin is an output, set by ATR logic
#define FRF_GPIO_SEL_DEBUG_0 2 // if pin is an output, debug lines from FPGA fabric
#define FRF_GPIO_SEL_DEBUG_1 3 // if pin is an output, debug lines from FPGA fabric
@@ -207,4 +223,25 @@
#define FR_ATR_FULL_TXSIDE FR_ATR_BASE + 12
#define FR_ATR_FULL_RXSIDE FR_ATR_BASE + 14
+///////////////////////////////////////////////////
+// VITA RX CTRL regs
+///////////////////////////////////////////////////
+// The following 3 are logically a single command register.
+// They are clocked into the underlying fifo when time_ticks is written.
+#define FR_RX_CTRL_STREAM_CMD _SR_ADDR(SR_RX_CTRL + 0) // {now, chain, num_samples(30)
+#define FR_RX_CTRL_TIME_SECS _SR_ADDR(SR_RX_CTRL + 1)
+#define FR_RX_CTRL_TIME_TICKS _SR_ADDR(SR_RX_CTRL + 2)
+
+#define FR_RX_CTRL_CLEAR_OVERRUN _SR_ADDR(SR_RX_CTRL + 3) // write anything to clear overrun
+#define FR_RX_CTRL_VRT_HEADER _SR_ADDR(SR_RX_CTRL + 4) // word 0 of packet. FPGA fills in packet counter
+#define FR_RX_CTRL_VRT_STREAM_ID _SR_ADDR(SR_RX_CTRL + 5) // word 1 of packet.
+#define FR_RX_CTRL_VRT_TRAILER _SR_ADDR(SR_RX_CTRL + 6)
+#define FR_RX_CTRL_NSAMPS_PER_PKT _SR_ADDR(SR_RX_CTRL + 7)
+#define FR_RX_CTRL_NCHANNELS _SR_ADDR(SR_RX_CTRL + 8) // 1 in basic case, up to 4 for vector sources
+
+//helpful macros for dealing with stream cmd
+#define FR_RX_CTRL_MAX_SAMPS_PER_CMD 0x1fffffff
+#define FR_RX_CTRL_MAKE_CMD(nsamples, now, chain, reload) \
+ ((((now) & 0x1) << 31) | (((chain) & 0x1) << 30) | (((reload) & 0x1) << 29) | ((nsamples) & 0x1fffffff))
+
#endif /* INCLUDED_USRP2_REGS_HPP */
diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp
index e70934b8c..23255b58c 100644
--- a/host/lib/usrp/usrp_e/dboard_iface.cpp
+++ b/host/lib/usrp/usrp_e/dboard_iface.cpp
@@ -49,8 +49,10 @@ public:
void write_aux_dac(unit_t, int, float);
float read_aux_adc(unit_t, int);
+ void set_pin_ctrl(unit_t, boost::uint16_t);
void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);
void set_gpio_ddr(unit_t, boost::uint16_t);
+ void write_gpio(unit_t, boost::uint16_t);
boost::uint16_t read_gpio(unit_t);
void write_i2c(boost::uint8_t, const byte_vector_t &);
@@ -111,29 +113,41 @@ void usrp_e_dboard_iface::set_clock_enabled(unit_t unit, bool enb){
/***********************************************************************
* GPIO
**********************************************************************/
-void usrp_e_dboard_iface::set_gpio_ddr(unit_t bank, boost::uint16_t value){
- //define mapping of gpio bank to register address
- static const uhd::dict<unit_t, boost::uint32_t> bank_to_addr = map_list_of
- (UNIT_RX, UE_REG_GPIO_RX_DDR)
- (UNIT_TX, UE_REG_GPIO_TX_DDR)
- ;
- _iface->poke16(bank_to_addr[bank], value);
+void usrp_e_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint16_t value){
+ UHD_ASSERT_THROW(GPIO_SEL_ATR == 1); //make this assumption
+ switch(unit){
+ case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_SEL, value); return;
+ case UNIT_TX: _iface->poke16(UE_REG_GPIO_TX_SEL, value); return;
+ }
}
-boost::uint16_t usrp_e_dboard_iface::read_gpio(unit_t bank){
- //define mapping of gpio bank to register address
- static const uhd::dict<unit_t, boost::uint32_t> bank_to_addr = map_list_of
- (UNIT_RX, UE_REG_GPIO_RX_IO)
- (UNIT_TX, UE_REG_GPIO_TX_IO)
- ;
- return _iface->peek16(bank_to_addr[bank]);
+void usrp_e_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){
+ switch(unit){
+ case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_DDR, value); return;
+ case UNIT_TX: _iface->poke16(UE_REG_GPIO_TX_DDR, value); return;
+ }
+}
+
+void usrp_e_dboard_iface::write_gpio(unit_t unit, boost::uint16_t value){
+ switch(unit){
+ case UNIT_RX: _iface->poke16(UE_REG_GPIO_RX_IO, value); return;
+ case UNIT_TX: _iface->poke16(UE_REG_GPIO_TX_IO, value); return;
+ }
+}
+
+boost::uint16_t usrp_e_dboard_iface::read_gpio(unit_t unit){
+ switch(unit){
+ case UNIT_RX: return _iface->peek16(UE_REG_GPIO_RX_IO);
+ case UNIT_TX: return _iface->peek16(UE_REG_GPIO_TX_IO);
+ }
+ UHD_ASSERT_THROW(false);
}
-void usrp_e_dboard_iface::set_atr_reg(unit_t bank, atr_reg_t atr, boost::uint16_t value){
- //define mapping of bank to atr regs to register address
+void usrp_e_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){
+ //define mapping of unit to atr regs to register address
static const uhd::dict<
unit_t, uhd::dict<atr_reg_t, boost::uint32_t>
- > bank_to_atr_to_addr = map_list_of
+ > unit_to_atr_to_addr = map_list_of
(UNIT_RX, map_list_of
(ATR_REG_IDLE, UE_REG_ATR_IDLE_RXSIDE)
(ATR_REG_TX_ONLY, UE_REG_ATR_INTX_RXSIDE)
@@ -147,7 +161,7 @@ void usrp_e_dboard_iface::set_atr_reg(unit_t bank, atr_reg_t atr, boost::uint16_
(ATR_REG_FULL_DUPLEX, UE_REG_ATR_FULL_TXSIDE)
)
;
- _iface->poke16(bank_to_atr_to_addr[bank][atr], value);
+ _iface->poke16(unit_to_atr_to_addr[unit][atr], value);
}
/***********************************************************************
diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp
index 4f7361eca..4a398e21c 100644
--- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp
+++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp
@@ -117,14 +117,6 @@ void usrp_e_impl::get(const wax::obj &key_, wax::obj &val){
val = prop_names_t(1, ""); //vector of size 1 with empty string
return;
- case DEVICE_PROP_MAX_RX_SAMPLES:
- val = size_t(_max_num_samples);
- return;
-
- case DEVICE_PROP_MAX_TX_SAMPLES:
- val = size_t(_max_num_samples);
- return;
-
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -142,7 +134,8 @@ void usrp_e_impl::set(const wax::obj &, const wax::obj &){
size_t usrp_e_impl::send(
const boost::asio::const_buffer &,
const uhd::tx_metadata_t &,
- const io_type_t &
+ const io_type_t &,
+ send_mode_t
){
if (true){
throw std::runtime_error(str(boost::format("usrp-e send: cannot handle type \"%s\"") % ""));
@@ -153,7 +146,8 @@ size_t usrp_e_impl::send(
size_t usrp_e_impl::recv(
const boost::asio::mutable_buffer &,
uhd::rx_metadata_t &,
- const io_type_t &
+ const io_type_t &,
+ recv_mode_t
){
if (true){
throw std::runtime_error(str(boost::format("usrp-e recv: cannot handle type \"%s\"") % ""));
diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp
index 59f80c70c..a2cdbc31e 100644
--- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp
+++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp
@@ -89,8 +89,10 @@ public:
~usrp_e_impl(void);
//the io interface
- size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const uhd::io_type_t &);
- size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &);
+ size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t);
+ size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t);
+ size_t get_max_send_samps_per_packet(void) const{return _max_num_samples;}
+ size_t get_max_recv_samps_per_packet(void) const{return _max_num_samples;}
private:
static const size_t _max_num_samples = 2048/sizeof(boost::uint32_t);
diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp
index 7f35212f4..51a47f061 100644
--- a/host/lib/usrp/usrp_e/usrp_e_regs.hpp
+++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp
@@ -78,11 +78,13 @@
#define UE_REG_GPIO_RX_DBG UE_REG_GPIO_BASE + 12
#define UE_REG_GPIO_TX_DBG UE_REG_GPIO_BASE + 14
-// each 2-bit sel field is layed out this way
-#define GPIO_SEL_SW 0 // if pin is an output, set by software in the io reg
-#define GPIO_SEL_ATR 1 // if pin is an output, set by ATR logic
-#define GPIO_SEL_DEBUG_0 0 // if pin is an output, debug lines from FPGA fabric
-#define GPIO_SEL_DEBUG_1 1 // if pin is an output, debug lines from FPGA fabric
+//possible bit values for sel when dbg is 0:
+#define GPIO_SEL_SW 0 // if pin is an output, set by software in the io reg
+#define GPIO_SEL_ATR 1 // if pin is an output, set by ATR logic
+
+//possible bit values for sel when dbg is 1:
+#define GPIO_SEL_DEBUG_0 0 // if pin is an output, debug lines from FPGA fabric
+#define GPIO_SEL_DEBUG_1 1 // if pin is an output, debug lines from FPGA fabric
////////////////////////////////////////////////////
diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt
index 78970ad0e..2cb95e66f 100644
--- a/host/utils/CMakeLists.txt
+++ b/host/utils/CMakeLists.txt
@@ -23,12 +23,17 @@ ADD_EXECUTABLE(usrp_e_load_fpga usrp_e_load_fpga.cpp)
TARGET_LINK_LIBRARIES(usrp_e_load_fpga uhd)
INSTALL(TARGETS usrp_e_load_fpga RUNTIME DESTINATION ${PKG_DATA_DIR}/utils)
-ADD_EXECUTABLE(usrp2_burner usrp2_burner.cpp)
-TARGET_LINK_LIBRARIES(usrp2_burner uhd)
-INSTALL(TARGETS usrp2_burner RUNTIME DESTINATION ${PKG_DATA_DIR}/utils)
+ADD_EXECUTABLE(usrp2_addr_burner usrp2_addr_burner.cpp)
+TARGET_LINK_LIBRARIES(usrp2_addr_burner uhd)
+INSTALL(TARGETS usrp2_addr_burner RUNTIME DESTINATION ${PKG_DATA_DIR}/utils)
ADD_EXECUTABLE(uhd_burn_db_eeprom uhd_burn_db_eeprom.cpp)
TARGET_LINK_LIBRARIES(uhd_burn_db_eeprom uhd)
INSTALL(TARGETS uhd_burn_db_eeprom RUNTIME DESTINATION ${PKG_DATA_DIR}/utils)
-INSTALL(PROGRAMS usrp2_recovery.py DESTINATION ${PKG_DATA_DIR}/utils)
+INSTALL(PROGRAMS
+ usrp2_recovery.py
+ usrp2_card_burner.py
+ usrp2_card_burner_gui.py
+ DESTINATION ${PKG_DATA_DIR}/utils
+)
diff --git a/host/utils/usrp2_burner.cpp b/host/utils/usrp2_addr_burner.cpp
index 9c1bf72fe..08fc1e218 100644
--- a/host/utils/usrp2_burner.cpp
+++ b/host/utils/usrp2_addr_burner.cpp
@@ -39,7 +39,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//print the help message
if (vm.count("help")){
- std::cout << boost::format("USRP2 Burner %s") % desc << std::endl;
+ std::cout << boost::format("USRP2 Address Burner %s") % desc << std::endl;
return ~0;
}
diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py
new file mode 100755
index 000000000..d47a4f5f4
--- /dev/null
+++ b/host/utils/usrp2_card_burner.py
@@ -0,0 +1,226 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+import platform
+import tempfile
+import subprocess
+import urllib
+import optparse
+import os
+import re
+
+########################################################################
+# constants
+########################################################################
+SECTOR_SIZE = 512 # bytes
+MAX_FILE_SIZE = 1 * (2**20) # maximum number of bytes we'll burn to a slot
+
+FPGA_OFFSET = 0 # offset in flash to fpga image
+FIRMWARE_OFFSET = 1 * (2**20) # offset in flash to firmware image
+
+MAX_SD_CARD_SIZE = 2048e6 # bytes (any bigger is sdhc)
+
+########################################################################
+# helper functions
+########################################################################
+def command(*args):
+ p = subprocess.Popen(
+ args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
+ ret = p.wait()
+ verbose = p.stdout.read()
+ if ret != 0: raise Exception, verbose
+ return verbose
+
+def get_dd_path():
+ if platform.system() == 'Windows':
+ dd_path = os.path.join(tempfile.gettempdir(), 'dd.exe')
+ if not os.path.exists(dd_path):
+ print 'Downloading dd.exe to %s'%dd_path
+ dd_bin = urllib.urlopen('http://www.ettus.com/downloads/dd.exe').read()
+ open(dd_path, 'wb').write(dd_bin)
+ return dd_path
+ return 'dd'
+
+########################################################################
+# list possible devices
+########################################################################
+def get_raw_device_hints():
+ ####################################################################
+ # Platform Windows: parse the output of dd.exe --list
+ ####################################################################
+ if platform.system() == 'Windows':
+ def extract_info_value(info, key):
+ return info.split(key)[-1].split()[0]
+ def get_info_list(output):
+ in_info = False
+ for line in output.splitlines():
+ if line.startswith('\\\\'): in_info = True; info = ''
+ elif in_info and not line.strip(): in_info = False; yield info
+ if in_info: info += '\n'+line.strip()
+ def is_info_valid(info):
+ try:
+ assert 'link to' in info
+ #handles two spellings of remov(e)able:
+ assert 'remov' in info.lower()
+ if 'size is' in info: assert int(extract_info_value(info, 'size is')) <= MAX_SD_CARD_SIZE
+ return True
+ except: return False
+ def extract_info_name(info):
+ for key in ('Mounted on', 'link to'):
+ if key in info: return extract_info_value(info, key)
+ return info.splitlines()[0].strip()
+
+ return sorted(set(map(extract_info_name, filter(is_info_valid, get_info_list(command(get_dd_path(), '--list'))))))
+
+ ####################################################################
+ # Platform Linux: parse procfs /proc/partitions
+ ####################################################################
+ if platform.system() == 'Linux':
+ devs = list()
+ try: output = open('/proc/partitions', 'r').read()
+ except: return devs
+ for line in output.splitlines():
+ try:
+ major, minor, blocks, name = line.split()
+ assert not name[-1].isdigit() or int(minor) == 0
+ assert int(blocks)*1024 <= MAX_SD_CARD_SIZE
+ except: continue
+ devs.append(os.path.join('/dev', name))
+
+ return sorted(set(devs))
+
+ ####################################################################
+ # Platform Mac OS X: parse diskutil list and info commands
+ ####################################################################
+ if platform.system() == 'Darwin':
+ devs = map(lambda d: d.split()[0], filter(lambda l: l.startswith('/dev'), command('diskutil', 'list').splitlines()))
+ def output_to_info(output):
+ return dict([map(str.strip, pair.lower().split(':')) for pair in filter(lambda l: ':' in l, output.splitlines())])
+ def is_dev_valid(dev):
+ info = output_to_info(command('diskutil', 'info', dev))
+ try:
+ if info.has_key('internal'): assert info['internal'] == 'no'
+ if info.has_key('ejectable'): assert info['ejectable'] == 'yes'
+ if info.has_key('total size'):
+ size_match = re.match('^.*\((\d+)\s*bytes\).*$', info['total size'])
+ if size_match: assert int(size_match.groups()[0]) <= MAX_SD_CARD_SIZE
+ return True
+ except: return False
+
+ return sorted(set(filter(is_dev_valid, devs)))
+
+ ####################################################################
+ # Platform Others:
+ ####################################################################
+ return ()
+
+########################################################################
+# write and verify with dd
+########################################################################
+def verify_image(image_file, device_file, offset):
+ #create a temporary file to store the readback
+ tmp = tempfile.mkstemp()
+ os.close(tmp[0])
+ tmp_file = tmp[1]
+
+ #execute a dd subprocess
+ verbose = command(
+ get_dd_path(),
+ "of=%s"%tmp_file,
+ "if=%s"%device_file,
+ "skip=%d"%(offset/SECTOR_SIZE),
+ "bs=%d"%SECTOR_SIZE,
+ "count=%d"%(MAX_FILE_SIZE/SECTOR_SIZE),
+ )
+
+ #read in the image and readback
+ img_data = open(image_file, 'rb').read()
+ tmp_data = open(tmp_file, 'rb').read(len(img_data))
+
+ #verfy the data
+ if img_data != tmp_data: return 'Verification Failed:\n%s'%verbose
+ return 'Verification Passed:\n%s'%verbose
+
+def write_image(image_file, device_file, offset):
+ verbose = command(
+ get_dd_path(),
+ "if=%s"%image_file,
+ "of=%s"%device_file,
+ "seek=%d"%(offset/SECTOR_SIZE),
+ "bs=%d"%SECTOR_SIZE,
+ )
+
+ try: #exec the sync command (only works on linux)
+ if platform.system() == 'Linux': command('sync')
+ except: pass
+
+ return verbose
+
+def write_and_verify(image_file, device_file, offset):
+ if os.path.getsize(image_file) > MAX_FILE_SIZE:
+ raise Exception, 'Image file larger than %d bytes!'%MAX_FILE_SIZE
+ return '%s\n%s'%(
+ write_image(
+ image_file=image_file,
+ device_file=device_file,
+ offset=offset,
+ ), verify_image(
+ image_file=image_file,
+ device_file=device_file,
+ offset=offset,
+ ),
+ )
+
+def burn_sd_card(dev, fw, fpga):
+ verbose = ''
+ if fw: verbose += 'Burn firmware image:\n%s\n'%write_and_verify(
+ image_file=fw, device_file=dev, offset=FIRMWARE_OFFSET
+ )
+ if fpga: verbose += 'Burn fpga image:\n%s\n'%write_and_verify(
+ image_file=fpga, device_file=dev, offset=FPGA_OFFSET
+ )
+ return verbose
+
+########################################################################
+# command line options
+########################################################################
+def get_options():
+ parser = optparse.OptionParser()
+ parser.add_option("--dev", type="string", help="raw device path", default='')
+ parser.add_option("--fw", type="string", help="firmware image path (optional)", default='')
+ parser.add_option("--fpga", type="string", help="fpga image path (optional)", default='')
+ parser.add_option("--list", action="store_true", help="list possible raw devices", default=False)
+ (options, args) = parser.parse_args()
+
+ if options.list:
+ print 'Possible raw devices:'
+ print ' ' + '\n '.join(get_raw_device_hints())
+ exit()
+
+ return options
+
+########################################################################
+# main
+########################################################################
+if __name__=='__main__':
+ options = get_options()
+ if not options.dev: raise Exception, 'no raw device path specified'
+ print burn_sd_card(dev=options.dev, fw=options.fw, fpga=options.fpga)
diff --git a/host/utils/usrp2_card_burner_gui.py b/host/utils/usrp2_card_burner_gui.py
new file mode 100755
index 000000000..61fbadbe3
--- /dev/null
+++ b/host/utils/usrp2_card_burner_gui.py
@@ -0,0 +1,169 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+import usrp2_card_burner #import implementation
+import Tkinter, Tkconstants, tkFileDialog, tkFont, tkMessageBox
+import os
+
+class BinFileEntry(Tkinter.Frame):
+ """
+ Simple file entry widget for getting the file path of bin files.
+ Combines a label, entry, and button with file dialog callback.
+ """
+
+ def __init__(self, root, what, def_path=''):
+ self._what = what
+ Tkinter.Frame.__init__(self, root)
+ Tkinter.Label(self, text=what+":").pack(side=Tkinter.LEFT)
+ self._entry = Tkinter.Entry(self, width=50)
+ self._entry.insert(Tkinter.END, def_path)
+ self._entry.pack(side=Tkinter.LEFT)
+ Tkinter.Button(self, text="...", command=self._button_cb).pack(side=Tkinter.LEFT)
+
+ def _button_cb(self):
+ filename = tkFileDialog.askopenfilename(
+ parent=self,
+ filetypes=[('bin files', '*.bin'), ('all files', '*.*')],
+ title="Select bin file for %s"%self._what,
+ initialdir=os.path.dirname(self.get_filename()),
+ )
+
+ # open file on your own
+ if filename:
+ self._entry.delete(0, Tkinter.END)
+ self._entry.insert(0, filename)
+
+ def get_filename(self):
+ return self._entry.get()
+
+class DeviceEntryWidget(Tkinter.Frame):
+ """
+ Simple entry widget for getting the raw device name.
+ Combines a label, entry, and helpful text box with hints.
+ """
+
+ def __init__(self, root, text=''):
+ Tkinter.Frame.__init__(self, root)
+
+ Tkinter.Button(self, text="Rescan for Devices", command=self._reload_cb).pack()
+
+ self._hints = Tkinter.Listbox(self)
+ self._hints.bind("<<ListboxSelect>>", self._listbox_cb)
+ self._reload_cb()
+ self._hints.pack(expand=Tkinter.YES, fill=Tkinter.X)
+
+ frame = Tkinter.Frame(self)
+ frame.pack()
+
+ Tkinter.Label(frame, text="Raw Device:").pack(side=Tkinter.LEFT)
+ self._entry = Tkinter.Entry(frame, width=50)
+ self._entry.insert(Tkinter.END, text)
+ self._entry.pack(side=Tkinter.LEFT)
+
+ def _reload_cb(self):
+ self._hints.delete(0, Tkinter.END)
+ for hint in usrp2_card_burner.get_raw_device_hints():
+ self._hints.insert(Tkinter.END, hint)
+
+ def _listbox_cb(self, event):
+ try:
+ sel = self._hints.get(self._hints.curselection()[0])
+ self._entry.delete(0, Tkinter.END)
+ self._entry.insert(0, sel)
+ except Exception, e: print e
+
+ def get_devname(self):
+ return self._entry.get()
+
+class SectionLabel(Tkinter.Label):
+ """
+ Make a text label with bold font.
+ """
+
+ def __init__(self, root, text):
+ Tkinter.Label.__init__(self, root, text=text)
+
+ #set the font bold
+ f = tkFont.Font(font=self['font'])
+ f['weight'] = 'bold'
+ self['font'] = f.name
+
+class USRP2CardBurnerApp(Tkinter.Frame):
+ """
+ The top level gui application for the usrp2 sd card burner.
+ Creates entry widgets and button with callback to write images.
+ """
+
+ def __init__(self, root, dev, fw, fpga):
+
+ Tkinter.Frame.__init__(self, root)
+
+ #pack the file entry widgets
+ SectionLabel(self, text="Select Images").pack(pady=5)
+ self._fw_img_entry = BinFileEntry(self, "Firmware Image", def_path=fw)
+ self._fw_img_entry.pack()
+ self._fpga_img_entry = BinFileEntry(self, "FPGA Image", def_path=fpga)
+ self._fpga_img_entry.pack()
+
+ #pack the destination entry widget
+ SectionLabel(self, text="Select Device").pack(pady=5)
+ self._raw_dev_entry = DeviceEntryWidget(self, text=dev)
+ self._raw_dev_entry.pack()
+
+ #the do it button
+ SectionLabel(self, text="").pack(pady=5)
+ Tkinter.Label(self, text="Warning! This tool can overwrite your hard drive. Use with caution.").pack()
+ Tkinter.Button(self, text="Burn SD Card", command=self._burn).pack()
+
+ def _burn(self):
+ #grab strings from the gui
+ fw = self._fw_img_entry.get_filename()
+ fpga = self._fpga_img_entry.get_filename()
+ dev = self._raw_dev_entry.get_devname()
+
+ #check input
+ if not dev:
+ tkMessageBox.showerror('Error:', 'No device specified!')
+ return
+ if not fw and not fpga:
+ tkMessageBox.showerror('Error:', 'No images specified!')
+ return
+ if fw and not os.path.exists(fw):
+ tkMessageBox.showerror('Error:', 'Firmware image not found!')
+ return
+ if fpga and not os.path.exists(fpga):
+ tkMessageBox.showerror('Error:', 'FPGA image not found!')
+ return
+
+ #burn the sd card
+ try:
+ verbose = usrp2_card_burner.burn_sd_card(dev=dev, fw=fw, fpga=fpga)
+ tkMessageBox.showinfo('Verbose:', verbose)
+ except Exception, e:
+ tkMessageBox.showerror('Verbose:', 'Error: %s'%str(e))
+
+########################################################################
+# main
+########################################################################
+if __name__=='__main__':
+ options = usrp2_card_burner.get_options()
+ root = Tkinter.Tk()
+ root.title('USRP2 SD Card Burner')
+ USRP2CardBurnerApp(root, dev=options.dev, fw=options.fw, fpga=options.fpga).pack()
+ root.mainloop()
+ exit()