From b774533c615ef34732d93c30a6df6fa4d702d90e Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Tue, 23 Feb 2010 08:27:29 -0800 Subject: Manually assign clk_fpga to BUFG to improve timing Starting Router Phase 1: 96908 unrouted; REAL time: 25 secs Phase 2: 85651 unrouted; REAL time: 35 secs Phase 3: 27099 unrouted; REAL time: 49 secs Phase 4: 27099 unrouted; (97405) REAL time: 49 secs Phase 5: 27259 unrouted; (5348) REAL time: 54 secs Phase 6: 27277 unrouted; (0) REAL time: 54 secs Phase 7: 0 unrouted; (0) REAL time: 1 mins 46 secs Phase 8: 0 unrouted; (0) REAL time: 1 mins 56 secs Phase 9: 0 unrouted; (0) REAL time: 2 mins 29 secs --- usrp2/top/u2_rev3/u2_rev3.v | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/usrp2/top/u2_rev3/u2_rev3.v b/usrp2/top/u2_rev3/u2_rev3.v index 23a825007..3c35743a3 100644 --- a/usrp2/top/u2_rev3/u2_rev3.v +++ b/usrp2/top/u2_rev3/u2_rev3.v @@ -171,7 +171,11 @@ 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 exp_pps_in; -- cgit v1.2.3 From c4a00173b2f3b0b4adb1bd003c4865e625d6da86 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Tue, 23 Feb 2010 09:03:58 -0800 Subject: Change bit width of CORDIC constants to remove meaningless warning --- usrp2/sdr_lib/cordic_z24.v | 48 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/usrp2/sdr_lib/cordic_z24.v b/usrp2/sdr_lib/cordic_z24.v index cf668d5ec..97b7beaf7 100644 --- a/usrp2/sdr_lib/cordic_z24.v +++ b/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) -- cgit v1.2.3 From 9519efb38f006e7c934a62f69d7366fe7cdd4410 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Tue, 23 Feb 2010 09:05:51 -0800 Subject: Fix missing item on sensitivity list --- usrp2/control_lib/nsgpio.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usrp2/control_lib/nsgpio.v b/usrp2/control_lib/nsgpio.v index 937ea7020..26130cc8e 100644 --- a/usrp2/control_lib/nsgpio.v +++ b/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]) ) -- cgit v1.2.3 From 4f66d0fbff3da2105018492d21ca64b96115aba3 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Tue, 23 Feb 2010 10:09:54 -0800 Subject: Remove some warnings in dsp_core_rx --- usrp2/sdr_lib/dsp_core_rx.v | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/usrp2/sdr_lib/dsp_core_rx.v b/usrp2/sdr_lib/dsp_core_rx.v index af4f0b9fb..aba18fccb 100644 --- a/usrp2/sdr_lib/dsp_core_rx.v +++ b/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(`DSP_CORE_RX_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(`DSP_CORE_RX_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(`DSP_CORE_RX_BASE+6)) 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(`DSP_CORE_RX_BASE+8)) 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(`DSP_CORE_RX_BASE+9)) 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. -- cgit v1.2.3 From 06ba14e55b200b9aa0314f63b38c08f30613859f Mon Sep 17 00:00:00 2001 From: Ian Buckley Date: Wed, 24 Feb 2010 10:54:54 -0800 Subject: Cut debug bus connection to etherenet MAC to make closing timing easier --- usrp2/top/u2_rev3/u2_rev3.v | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/usrp2/top/u2_rev3/u2_rev3.v b/usrp2/top/u2_rev3/u2_rev3.v index 3c35743a3..3a43e4ffe 100644 --- a/usrp2/top/u2_rev3/u2_rev3.v +++ b/usrp2/top/u2_rev3/u2_rev3.v @@ -177,6 +177,9 @@ module u2_rev3 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)); @@ -314,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; @@ -371,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), -- cgit v1.2.3 From 50b1ca13e651152a731d3fdf7a5f532b65e04e13 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Mon, 29 Mar 2010 15:35:06 -0700 Subject: Added timing constraint for Wishbone clock/dsp_clock skew --- usrp2/top/u2_rev3/u2_rev3.ucf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/usrp2/top/u2_rev3/u2_rev3.ucf b/usrp2/top/u2_rev3/u2_rev3.ucf index 255a298ac..6aa699d2a 100644 --- a/usrp2/top/u2_rev3/u2_rev3.ucf +++ b/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; -- cgit v1.2.3 From de21671b8dab89d6aaa3b6bbb99a4dc0d306121f Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Mon, 29 Mar 2010 17:14:24 -0700 Subject: Update config to all eight clock buffers to be used. --- usrp2/top/u2_rev3/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usrp2/top/u2_rev3/Makefile b/usrp2/top/u2_rev3/Makefile index 4358d7c56..81d787566 100644 --- a/usrp2/top/u2_rev3/Makefile +++ b/usrp2/top/u2_rev3/Makefile @@ -183,7 +183,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 \ -- cgit v1.2.3 From a7c230cb1f97b452da027d5baa71891f2066d430 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 28 Apr 2010 16:35:22 -0700 Subject: Added reload flag to the stream cmd. This reloads the last command to handle continuous streaming in hardware. Moved rx control register setup and stream command issuing to the host. --- firmware/microblaze/apps/txrx_uhd.c | 120 ----------------------------------- firmware/microblaze/lib/banal.c | 18 ------ firmware/microblaze/lib/banal.h | 3 - firmware/microblaze/lib/memory_map.h | 4 -- firmware/microblaze/lib/u2_init.c | 4 +- fpga/usrp2/vrt/vita_rx_control.v | 24 +++++-- host/lib/usrp/usrp2/dsp_impl.cpp | 3 - host/lib/usrp/usrp2/fw_common.h | 14 +--- host/lib/usrp/usrp2/io_impl.cpp | 22 +++++-- host/lib/usrp/usrp2/mboard_impl.cpp | 59 ++++++++--------- host/lib/usrp/usrp2/usrp2_regs.hpp | 21 ++++++ 11 files changed, 83 insertions(+), 209 deletions(-) diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 8ff3b8c58..d5b400e0c 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -126,14 +126,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 +147,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 +167,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)) @@ -303,72 +282,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 ******************************************************************/ @@ -463,25 +376,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 +448,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 } @@ -662,13 +549,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/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/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/u2_init.c b/firmware/microblaze/lib/u2_init.c index 399d834cb..40237ba87 100644 --- a/firmware/microblaze/lib/u2_init.c +++ b/firmware/microblaze/lib/u2_init.c @@ -50,8 +50,8 @@ u2_init(void) 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); + //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 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/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 84314a656..bd61ac376 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -77,9 +77,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..f28013cf6 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 @@ -70,9 +70,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', @@ -113,15 +110,6 @@ typedef struct{ _SINS_ uint8_t bytes; _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; diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 367a1d9fb..a2e99c824 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 #include #include //htonl and ntohl @@ -39,14 +40,23 @@ void usrp2_impl::io_init(void){ _rx_copy_buff = asio::buffer("", 0); //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(), data, sizeof(data)); + boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER); + memcpy(send_buff->cast(), &data, sizeof(data)); send_buff->done(sizeof(data)); + + //setup RX DSP regs + _iface->poke32(FR_RX_CTRL_NSAMPS_PER_PKT, _max_rx_samples_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); } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 36bef4f25..48aeb2a62 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -119,40 +119,31 @@ void usrp2_impl::set_time_spec(const time_spec_t &time_spec, bool now){ } 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 inst_t; + static const uhd::dict 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)? _max_rx_samples_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())); } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 0e2a18756..67a342217 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -207,4 +207,25 @@ #define FR_ATR_FULL_TXSIDE FR_ATR_BASE + 12 #define FR_ATR_FULL_RXSIDE FR_ATR_BASE + 14 +/////////////////////////////////////////////////// +// ATR Controller, Slave 11 +/////////////////////////////////////////////////// +// 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 */ -- cgit v1.2.3 From c79595e6cc0044d09432aab19b26c3ac4d256595 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 28 Apr 2010 17:23:55 -0700 Subject: removed some unused things like gpio from microblaze code --- firmware/microblaze/apps/txrx_uhd.c | 25 ------ firmware/microblaze/lib/Makefile.am | 1 - firmware/microblaze/lib/hal_io.c | 128 ------------------------------- firmware/microblaze/lib/hal_io.h | 58 -------------- firmware/microblaze/lib/print_fxpt.c | 83 -------------------- firmware/microblaze/lib/print_mac_addr.c | 10 +-- firmware/microblaze/lib/u2_init.c | 11 --- 7 files changed, 4 insertions(+), 312 deletions(-) delete mode 100644 firmware/microblaze/lib/print_fxpt.c diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index d5b400e0c..db830fa51 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 #include #include "u2_init.h" @@ -49,8 +47,6 @@ #include #include -#define LEDS_SW LED_A - /* * Full duplex Tx and Rx between ethernet and DSP pipelines * @@ -481,27 +477,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, 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/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 #include #include -//#include - -/* - * ======================================================================== - * 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/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 . - */ -#include - -/* - * 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 40237ba87..b4fbb9e88 100644 --- a/firmware/microblaze/lib/u2_init.c +++ b/firmware/microblaze/lib/u2_init.c @@ -46,13 +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(); @@ -71,10 +64,6 @@ u2_init(void) // 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); -- cgit v1.2.3 From 30bd666e306cb8f8c947c6ba99a76f7c49484597 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 28 Apr 2010 17:38:22 -0700 Subject: Moved some misc setting registers into host. --- firmware/microblaze/lib/u2_init.c | 10 ---------- host/lib/usrp/usrp2/mboard_impl.cpp | 13 ++++++++++--- host/lib/usrp/usrp2/usrp2_regs.hpp | 20 ++++++++++++++++++-- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/firmware/microblaze/lib/u2_init.c b/firmware/microblaze/lib/u2_init.c index b4fbb9e88..6809101c0 100644 --- a/firmware/microblaze/lib/u2_init.c +++ b/firmware/microblaze/lib/u2_init.c @@ -46,8 +46,6 @@ get_hw_rev(void) bool u2_init(void) { - 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 @@ -60,14 +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; - - // Set up serdes - output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN); - pic_init(); // progammable interrupt controller bp_init(); // buffer pool diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 48aeb2a62..2c8fd2df4 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -63,6 +63,13 @@ void usrp2_impl::mboard_init(void){ 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*/); } + + //enable ADCs + _iface->poke32(FR_MISC_CTRL_ADC, FRF_MISC_CTRL_ADC_ON); + + //set up serdes + _iface->poke32(FR_MISC_CTRL_SERDES, FRF_MISC_CTRL_SERDES_ENABLE | FRF_MISC_CTRL_SERDES_RXEN); + } void usrp2_impl::init_clock_config(void){ @@ -97,9 +104,9 @@ 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"); } diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 67a342217..feeccaa34 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) @@ -208,7 +224,7 @@ #define FR_ATR_FULL_RXSIDE FR_ATR_BASE + 14 /////////////////////////////////////////////////// -// ATR Controller, Slave 11 +// 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. -- cgit v1.2.3 From 9c7c178f70f8a78dc638d5f4301407893351b4fd Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 10 May 2010 14:17:25 -0700 Subject: added save state for ic regs map common --- host/lib/ic_reg_maps/common.py | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) 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 \#include +\#include +\#include -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 std::set get_changed_addrs(void){ + if (_state == NULL) throw std::runtime_error("no saved state"); + //check each register for changes + std::set 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 */ -- cgit v1.2.3 From bf7ef6aeb502839797894cac4d7518029a0d04c4 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 10 May 2010 15:14:48 -0700 Subject: Moved adc and dac control into codec control source file. The codec control powers down the chips on destruction. --- host/lib/usrp/usrp2/CMakeLists.txt | 3 +- host/lib/usrp/usrp2/clock_control.cpp | 157 ---------------------------------- host/lib/usrp/usrp2/clock_control.hpp | 60 ------------- host/lib/usrp/usrp2/clock_ctrl.cpp | 155 +++++++++++++++++++++++++++++++++ host/lib/usrp/usrp2/clock_ctrl.hpp | 60 +++++++++++++ host/lib/usrp/usrp2/codec_ctrl.cpp | 91 ++++++++++++++++++++ host/lib/usrp/usrp2/codec_ctrl.hpp | 38 ++++++++ host/lib/usrp/usrp2/dboard_iface.cpp | 18 ++-- host/lib/usrp/usrp2/dboard_impl.cpp | 2 +- host/lib/usrp/usrp2/mboard_impl.cpp | 32 +------ host/lib/usrp/usrp2/usrp2_impl.cpp | 2 + host/lib/usrp/usrp2/usrp2_impl.hpp | 8 +- 12 files changed, 364 insertions(+), 262 deletions(-) delete mode 100644 host/lib/usrp/usrp2/clock_control.cpp delete mode 100644 host/lib/usrp/usrp2/clock_control.hpp create mode 100644 host/lib/usrp/usrp2/clock_ctrl.cpp create mode 100644 host/lib/usrp/usrp2/clock_ctrl.hpp create mode 100644 host/lib/usrp/usrp2/codec_ctrl.cpp create mode 100644 host/lib/usrp/usrp2/codec_ctrl.hpp diff --git a/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt index f9907e21e..6c7881861 100644 --- a/host/lib/usrp/usrp2/CMakeLists.txt +++ b/host/lib/usrp/usrp2/CMakeLists.txt @@ -18,7 +18,8 @@ #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/codec_ctrl.cpp ${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 diff --git a/host/lib/usrp/usrp2/clock_control.cpp b/host/lib/usrp/usrp2/clock_control.cpp deleted file mode 100644 index 72f1f1c7a..000000000 --- a/host/lib/usrp/usrp2/clock_control.cpp +++ /dev/null @@ -1,157 +0,0 @@ -// -// 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 . -// - -#include "usrp2_impl.hpp" -#include "clock_control.hpp" -#include "ad9510_regs.hpp" -#include "usrp2_regs.hpp" //spi slave constants -#include - -using namespace uhd; -using namespace uhd::usrp; - -/*! - * A usrp2 clock control specific to the ad9510 ic. - */ -class clock_control_ad9510 : public clock_control{ -public: - clock_control_ad9510(usrp2_iface::sptr iface){ - _iface = iface; - - _ad9510_regs.cp_current_setting = ad9510_regs_t::CP_CURRENT_SETTING_3_0MA; - this->write_reg(0x09); - - // Setup the clock registers to 100MHz: - // This was already done by the firmware (or the host couldnt communicate). - // We could remove this part, and just leave it to the firmware. - // But why not leave it in for those who want to mess with clock settings? - // 100mhz = 10mhz/R * (P*B + A) - - _ad9510_regs.pll_power_down = ad9510_regs_t::PLL_POWER_DOWN_NORMAL; - _ad9510_regs.prescaler_value = ad9510_regs_t::PRESCALER_VALUE_DIV2; - this->write_reg(0x0A); - - _ad9510_regs.acounter = 0; - this->write_reg(0x04); - - _ad9510_regs.bcounter_msb = 0; - _ad9510_regs.bcounter_lsb = 5; - this->write_reg(0x05); - this->write_reg(0x06); - - _ad9510_regs.ref_counter_msb = 0; - _ad9510_regs.ref_counter_lsb = 1; // r divider = 1 - this->write_reg(0x0B); - this->write_reg(0x0C); - - /* regs will be updated in commands below */ - - this->enable_external_ref(false); - this->enable_rx_dboard_clock(false); - this->enable_tx_dboard_clock(false); - - /* private clock enables, must be set here */ - this->enable_dac_clock(true); - this->enable_adc_clock(true); - - } - - ~clock_control_ad9510(void){ - /* private clock enables, must be set here */ - this->enable_dac_clock(false); - this->enable_adc_clock(false); - } - - //uses output clock 7 (cmos) - void enable_rx_dboard_clock(bool enb){ - _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; - this->write_reg(0x43); - this->update_regs(); - } - - //uses output clock 6 (cmos) - void enable_tx_dboard_clock(bool enb){ - _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; - this->write_reg(0x42); - this->update_regs(); - } - - /*! - * If we are to use an external reference, enable the charge pump. - * \param enb true to enable the CP - */ - void enable_external_ref(bool enb){ - _ad9510_regs.charge_pump_mode = (enb)? - ad9510_regs_t::CHARGE_PUMP_MODE_NORMAL : - ad9510_regs_t::CHARGE_PUMP_MODE_3STATE ; - _ad9510_regs.pll_mux_control = ad9510_regs_t::PLL_MUX_CONTROL_DLD_HIGH; - _ad9510_regs.pfd_polarity = ad9510_regs_t::PFD_POLARITY_POS; - this->write_reg(0x08); - this->update_regs(); - } - -private: - /*! - * Write a single register to the spi regs. - * \param addr the address to write - */ - void write_reg(boost::uint8_t addr){ - boost::uint32_t data = _ad9510_regs.get_write_reg(addr); - _iface->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24, false /*no rb*/); - } - - /*! - * Tells the ad9510 to latch the settings into the operational registers. - */ - void update_regs(void){ - _ad9510_regs.update_registers = 1; - this->write_reg(0x5a); - } - - //uses output clock 3 (pecl) - void enable_dac_clock(bool enb){ - _ad9510_regs.power_down_lvpecl_out3 = (enb)? - 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; - this->write_reg(0x3F); - this->update_regs(); - } - - //uses output clock 4 (lvds) - void enable_adc_clock(bool enb){ - _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; - this->write_reg(0x40); - this->update_regs(); - } - - usrp2_iface::sptr _iface; - ad9510_regs_t _ad9510_regs; -}; - -/*********************************************************************** - * 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)); -} diff --git a/host/lib/usrp/usrp2/clock_control.hpp b/host/lib/usrp/usrp2/clock_control.hpp deleted file mode 100644 index b64a53196..000000000 --- a/host/lib/usrp/usrp2/clock_control.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// -// 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 . -// - -#ifndef INCLUDED_CLOCK_CONTROL_HPP -#define INCLUDED_CLOCK_CONTROL_HPP - -#include "usrp2_iface.hpp" -#include -#include - -class clock_control : boost::noncopyable{ -public: - typedef boost::shared_ptr 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); - - /*! - * Enable/disable the rx dboard clock. - * \param enb true to enable - */ - virtual void enable_rx_dboard_clock(bool enb) = 0; - - /*! - * Enable/disable the tx dboard clock. - * \param enb true to enable - */ - virtual void enable_tx_dboard_clock(bool enb) = 0; - - /*! - * Enable/disable external reference. - * \param enb true to enable - */ - virtual void enable_external_ref(bool enb) = 0; - - /*! - * TODO other clock control api here.... - */ - -}; - -#endif /* INCLUDED_CLOCK_CONTROL_HPP */ diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp new file mode 100644 index 000000000..db8d8a886 --- /dev/null +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -0,0 +1,155 @@ +// +// 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 . +// + +#include "clock_ctrl.hpp" +#include "ad9510_regs.hpp" +#include "usrp2_regs.hpp" //spi slave constants +#include + +using namespace uhd; + +/*! + * A usrp2 clock control specific to the ad9510 ic. + */ +class clock_ctrl_impl : public clock_ctrl{ +public: + clock_ctrl_impl(usrp2_iface::sptr iface){ + _iface = iface; + + _ad9510_regs.cp_current_setting = ad9510_regs_t::CP_CURRENT_SETTING_3_0MA; + this->write_reg(0x09); + + // Setup the clock registers to 100MHz: + // This was already done by the firmware (or the host couldnt communicate). + // We could remove this part, and just leave it to the firmware. + // But why not leave it in for those who want to mess with clock settings? + // 100mhz = 10mhz/R * (P*B + A) + + _ad9510_regs.pll_power_down = ad9510_regs_t::PLL_POWER_DOWN_NORMAL; + _ad9510_regs.prescaler_value = ad9510_regs_t::PRESCALER_VALUE_DIV2; + this->write_reg(0x0A); + + _ad9510_regs.acounter = 0; + this->write_reg(0x04); + + _ad9510_regs.bcounter_msb = 0; + _ad9510_regs.bcounter_lsb = 5; + this->write_reg(0x05); + this->write_reg(0x06); + + _ad9510_regs.ref_counter_msb = 0; + _ad9510_regs.ref_counter_lsb = 1; // r divider = 1 + this->write_reg(0x0B); + this->write_reg(0x0C); + + /* regs will be updated in commands below */ + + this->enable_external_ref(false); + this->enable_rx_dboard_clock(false); + this->enable_tx_dboard_clock(false); + + /* private clock enables, must be set here */ + this->enable_dac_clock(true); + this->enable_adc_clock(true); + + } + + ~clock_ctrl_impl(void){ + /* private clock enables, must be set here */ + this->enable_dac_clock(false); + this->enable_adc_clock(false); + } + + //uses output clock 7 (cmos) + void enable_rx_dboard_clock(bool enb){ + _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; + this->write_reg(0x43); + this->update_regs(); + } + + //uses output clock 6 (cmos) + void enable_tx_dboard_clock(bool enb){ + _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; + this->write_reg(0x42); + this->update_regs(); + } + + /*! + * If we are to use an external reference, enable the charge pump. + * \param enb true to enable the CP + */ + void enable_external_ref(bool enb){ + _ad9510_regs.charge_pump_mode = (enb)? + ad9510_regs_t::CHARGE_PUMP_MODE_NORMAL : + ad9510_regs_t::CHARGE_PUMP_MODE_3STATE ; + _ad9510_regs.pll_mux_control = ad9510_regs_t::PLL_MUX_CONTROL_DLD_HIGH; + _ad9510_regs.pfd_polarity = ad9510_regs_t::PFD_POLARITY_POS; + this->write_reg(0x08); + this->update_regs(); + } + +private: + /*! + * Write a single register to the spi regs. + * \param addr the address to write + */ + void write_reg(boost::uint8_t addr){ + boost::uint32_t data = _ad9510_regs.get_write_reg(addr); + _iface->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24, false /*no rb*/); + } + + /*! + * Tells the ad9510 to latch the settings into the operational registers. + */ + void update_regs(void){ + _ad9510_regs.update_registers = 1; + this->write_reg(0x5a); + } + + //uses output clock 3 (pecl) + void enable_dac_clock(bool enb){ + _ad9510_regs.power_down_lvpecl_out3 = (enb)? + 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; + this->write_reg(0x3F); + this->update_regs(); + } + + //uses output clock 4 (lvds) + void enable_adc_clock(bool enb){ + _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; + this->write_reg(0x40); + this->update_regs(); + } + + usrp2_iface::sptr _iface; + ad9510_regs_t _ad9510_regs; +}; + +/*********************************************************************** + * Public make function for the ad9510 clock control + **********************************************************************/ +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_ctrl.hpp b/host/lib/usrp/usrp2/clock_ctrl.hpp new file mode 100644 index 000000000..3208008a9 --- /dev/null +++ b/host/lib/usrp/usrp2/clock_ctrl.hpp @@ -0,0 +1,60 @@ +// +// 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 . +// + +#ifndef INCLUDED_CLOCK_CONTROL_HPP +#define INCLUDED_CLOCK_CONTROL_HPP + +#include "usrp2_iface.hpp" +#include +#include + +class clock_ctrl : boost::noncopyable{ +public: + typedef boost::shared_ptr 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(usrp2_iface::sptr iface); + + /*! + * Enable/disable the rx dboard clock. + * \param enb true to enable + */ + virtual void enable_rx_dboard_clock(bool enb) = 0; + + /*! + * Enable/disable the tx dboard clock. + * \param enb true to enable + */ + virtual void enable_tx_dboard_clock(bool enb) = 0; + + /*! + * Enable/disable external reference. + * \param enb true to enable + */ + virtual void enable_external_ref(bool enb) = 0; + + /*! + * TODO other clock control api here.... + */ + +}; + +#endif /* INCLUDED_CLOCK_CONTROL_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..452aa39b1 --- /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 . +// + +#include "codec_ctrl.hpp" +#include "ad9777_regs.hpp" +#include "usrp2_regs.hpp" +#include +#include +#include + +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_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++){ + 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; + 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, 6, 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..c34fb8159 --- /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 . +// + +#ifndef INCLUDED_CODEC_CONTROL_HPP +#define INCLUDED_CODEC_CONTROL_HPP + +#include "usrp2_iface.hpp" +#include +#include + +class codec_ctrl : boost::noncopyable{ +public: + typedef boost::shared_ptr 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_CONTROL_HPP */ diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index 372a5af07..d33a11fd6 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 #include @@ -33,7 +33,7 @@ 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); @@ -66,7 +66,7 @@ public: private: usrp2_iface::sptr _iface; - clock_control::sptr _clk_ctrl; + clock_ctrl::sptr _clock_ctrl; boost::uint32_t _ddr_shadow; uhd::dict _dac_regs; @@ -78,17 +78,17 @@ 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 @@ -123,8 +123,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; } } diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 403faf5cf..0f8a739f2 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -39,7 +39,7 @@ void usrp2_impl::dboard_init(void){ //create a new dboard interface and manager dboard_iface::sptr _dboard_iface( - make_usrp2_dboard_iface(_iface, _clk_ctrl) + make_usrp2_dboard_iface(_iface, _clock_ctrl) ); _dboard_manager = dboard_manager::make( _rx_db_eeprom.id, _tx_db_eeprom.id, _dboard_iface diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 2c8fd2df4..892e45f49 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -17,7 +17,6 @@ #include "usrp2_impl.hpp" #include "usrp2_regs.hpp" -#include "ad9777_regs.hpp" #include #include #include @@ -38,35 +37,6 @@ void usrp2_impl::mboard_init(void){ 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*/); - } - - //enable ADCs - _iface->poke32(FR_MISC_CTRL_ADC, FRF_MISC_CTRL_ADC_ON); - //set up serdes _iface->poke32(FR_MISC_CTRL_SERDES, FRF_MISC_CTRL_SERDES_ENABLE | FRF_MISC_CTRL_SERDES_RXEN); @@ -112,7 +82,7 @@ void usrp2_impl::update_clock_config(void){ //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){ diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 1dde8c054..ef7754c33 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -147,6 +147,8 @@ 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); //load the allowed decim/interp rates //_USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4) diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 1c9387744..871050356 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -19,7 +19,8 @@ #define INCLUDED_USRP2_IMPL_HPP #include "usrp2_iface.hpp" -#include "clock_control.hpp" +#include "clock_ctrl.hpp" +#include "codec_ctrl.hpp" #include #include #include @@ -40,7 +41,7 @@ */ uhd::usrp::dboard_iface::sptr make_usrp2_dboard_iface( usrp2_iface::sptr iface, - clock_control::sptr clk_ctrl + clock_ctrl::sptr clk_ctrl ); /*! @@ -114,7 +115,8 @@ private: void set(const wax::obj &, const wax::obj &); //interfaces - clock_control::sptr _clk_ctrl; + clock_ctrl::sptr _clock_ctrl; + codec_ctrl::sptr _codec_ctrl; usrp2_iface::sptr _iface; //the raw io interface (samples are in the usrp2 native format) -- cgit v1.2.3 From 7c7b0d0a0dc8dd0cb4f0229fbc55978d6f2e253c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 10 May 2010 16:37:12 -0700 Subject: Added a place for serdes control on the host. Fix bug in codec control. Comment out some clock control in fw code. --- firmware/microblaze/lib/clocks.c | 30 ++++++++++++------------ firmware/microblaze/lib/clocks.h | 10 ++++---- host/lib/usrp/usrp2/CMakeLists.txt | 1 + host/lib/usrp/usrp2/clock_ctrl.hpp | 6 ++--- host/lib/usrp/usrp2/codec_ctrl.cpp | 6 ++--- host/lib/usrp/usrp2/codec_ctrl.hpp | 6 ++--- host/lib/usrp/usrp2/mboard_impl.cpp | 4 ---- host/lib/usrp/usrp2/serdes_ctrl.cpp | 46 +++++++++++++++++++++++++++++++++++++ host/lib/usrp/usrp2/serdes_ctrl.hpp | 40 ++++++++++++++++++++++++++++++++ host/lib/usrp/usrp2/usrp2_impl.cpp | 1 + host/lib/usrp/usrp2/usrp2_impl.hpp | 4 +++- 11 files changed, 120 insertions(+), 34 deletions(-) create mode 100644 host/lib/usrp/usrp2/serdes_ctrl.cpp create mode 100644 host/lib/usrp/usrp2/serdes_ctrl.hpp 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/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt index 6c7881861..fee67dff9 100644 --- a/host/lib/usrp/usrp2/CMakeLists.txt +++ b/host/lib/usrp/usrp2/CMakeLists.txt @@ -25,6 +25,7 @@ LIBUHD_APPEND_SOURCES( ${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/usrp2_iface.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_impl.cpp ) diff --git a/host/lib/usrp/usrp2/clock_ctrl.hpp b/host/lib/usrp/usrp2/clock_ctrl.hpp index 3208008a9..706bf4246 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.hpp +++ b/host/lib/usrp/usrp2/clock_ctrl.hpp @@ -15,8 +15,8 @@ // along with this program. If not, see . // -#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 @@ -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 index 452aa39b1..d1e16881b 100644 --- a/host/lib/usrp/usrp2/codec_ctrl.cpp +++ b/host/lib/usrp/usrp2/codec_ctrl.cpp @@ -53,7 +53,7 @@ public: _ad9777_regs.qdac_offset_adjust_msb = 0; //write all regs for(boost::uint8_t addr = 0; addr <= 0xC; addr++){ - send_ad9777_reg(addr); + this->send_ad9777_reg(addr); } //power-up adc @@ -63,7 +63,7 @@ public: ~codec_ctrl_impl(void){ //power-down dac _ad9777_regs.power_down_mode = 1; - send_ad9777_reg(0); + this->send_ad9777_reg(0); //power-down adc _iface->poke32(FR_MISC_CTRL_ADC, FRF_MISC_CTRL_ADC_OFF); @@ -78,7 +78,7 @@ private: 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, 6, false /*no rb*/ + reg, 16, false /*no rb*/ ); } }; diff --git a/host/lib/usrp/usrp2/codec_ctrl.hpp b/host/lib/usrp/usrp2/codec_ctrl.hpp index c34fb8159..0ee52f476 100644 --- a/host/lib/usrp/usrp2/codec_ctrl.hpp +++ b/host/lib/usrp/usrp2/codec_ctrl.hpp @@ -15,8 +15,8 @@ // along with this program. If not, see . // -#ifndef INCLUDED_CODEC_CONTROL_HPP -#define INCLUDED_CODEC_CONTROL_HPP +#ifndef INCLUDED_CODEC_CTRL_HPP +#define INCLUDED_CODEC_CTRL_HPP #include "usrp2_iface.hpp" #include @@ -35,4 +35,4 @@ public: }; -#endif /* INCLUDED_CODEC_CONTROL_HPP */ +#endif /* INCLUDED_CODEC_CTRL_HPP */ diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 892e45f49..7e62bedf0 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -36,10 +36,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) ); - - //set up serdes - _iface->poke32(FR_MISC_CTRL_SERDES, FRF_MISC_CTRL_SERDES_ENABLE | FRF_MISC_CTRL_SERDES_RXEN); - } void usrp2_impl::init_clock_config(void){ 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 . +// + +#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 . +// + +#ifndef INCLUDED_SERDES_CTRL_HPP +#define INCLUDED_SERDES_CTRL_HPP + +#include "usrp2_iface.hpp" +#include +#include + +class serdes_ctrl : boost::noncopyable{ +public: + typedef boost::shared_ptr 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_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index ef7754c33..5c1d7f9e3 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -149,6 +149,7 @@ usrp2_impl::usrp2_impl( _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) diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 871050356..c5b6af810 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -21,6 +21,7 @@ #include "usrp2_iface.hpp" #include "clock_ctrl.hpp" #include "codec_ctrl.hpp" +#include "serdes_ctrl.hpp" #include #include #include @@ -115,9 +116,10 @@ private: void set(const wax::obj &, const wax::obj &); //interfaces + usrp2_iface::sptr _iface; clock_ctrl::sptr _clock_ctrl; codec_ctrl::sptr _codec_ctrl; - usrp2_iface::sptr _iface; + serdes_ctrl::sptr _serdes_ctrl; //the raw io interface (samples are in the usrp2 native format) void recv_raw(uhd::rx_metadata_t &); -- cgit v1.2.3 From 93185ca7719e8949e90b594676be6c3d2f709fb9 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 11 May 2010 15:48:47 -0700 Subject: allow settings bus to cross to a new clock domain, should help timing, but not attached yet --- usrp2/control_lib/settings_bus_crossclock.v | 20 +++ usrp2/coregen/fifo_xlnx_16x40_2clk.ngc | 3 + usrp2/coregen/fifo_xlnx_16x40_2clk.v | 165 +++++++++++++++++++++ usrp2/coregen/fifo_xlnx_16x40_2clk.veo | 51 +++++++ usrp2/coregen/fifo_xlnx_16x40_2clk.xco | 82 ++++++++++ ...x40_2clk_fifo_generator_v4_3_xst_1.ngc_xst.xrpt | 98 ++++++++++++ usrp2/coregen/fifo_xlnx_16x40_2clk_flist.txt | 8 + usrp2/coregen/fifo_xlnx_16x40_2clk_readme.txt | 39 +++++ usrp2/coregen/fifo_xlnx_16x40_2clk_xmdf.tcl | 68 +++++++++ 9 files changed, 534 insertions(+) create mode 100644 usrp2/control_lib/settings_bus_crossclock.v create mode 100644 usrp2/coregen/fifo_xlnx_16x40_2clk.ngc create mode 100644 usrp2/coregen/fifo_xlnx_16x40_2clk.v create mode 100644 usrp2/coregen/fifo_xlnx_16x40_2clk.veo create mode 100644 usrp2/coregen/fifo_xlnx_16x40_2clk.xco create mode 100644 usrp2/coregen/fifo_xlnx_16x40_2clk_fifo_generator_v4_3_xst_1.ngc_xst.xrpt create mode 100644 usrp2/coregen/fifo_xlnx_16x40_2clk_flist.txt create mode 100644 usrp2/coregen/fifo_xlnx_16x40_2clk_readme.txt create mode 100644 usrp2/coregen/fifo_xlnx_16x40_2clk_xmdf.tcl diff --git a/usrp2/control_lib/settings_bus_crossclock.v b/usrp2/control_lib/settings_bus_crossclock.v new file mode 100644 index 000000000..b043aa0ad --- /dev/null +++ b/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/usrp2/coregen/fifo_xlnx_16x40_2clk.ngc b/usrp2/coregen/fifo_xlnx_16x40_2clk.ngc new file mode 100644 index 000000000..f42663419 --- /dev/null +++ b/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;:HLSQQ2=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>:;ERQE4385KPSC00>@?0180JI=4FEA7?CBDM:1MH]:4FERF1>@fdzo:7J=4GOF2?L45A1168J467<2D:<<:4N0210>H68:>0B<>;4:L24020668J46?<2D:<4=4N037?K768=1E=459M54333G;::95A1057?K760=1E=<7<;O310>H6:9>0B<<>4:L26722568J442;2D:?>5A1518J4343G;=?6@>729M5=5H5=:1E>;=4N350?K4?;2D95>5A3118J6743G99?6@<329M7157<;O637>H39:1E8?=4N510?K23;2D?9?5A639M36=I?990B:?<;O507>H0=:1E;;<4N918J=243G2>?6@7629M<25H>8:1E5<=4N800?K?4;2D28>5A9418J<043G30\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:;?00]Qavsk|8997X> gsd-vc)`kq$h`fv Mymq[wbXxg~ySjmPxnp3454XZly~`y?<3:W3+bta&{l$knv!cmi{+H~hzV}yS}`{r^`jjZ~hz9:;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]dgZgtzlmThS7'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;TS7'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:;=!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}6920>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?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\Tn5Z0.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-NvdkXZHG99f: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?<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;>2f: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;2f: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-gkprXa5932e: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::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>?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[wusWhyyijS7'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:21S_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'8;ekm,42.?2nbb%?:)69gmk.6> =0hd`'16+4?aoi 82";6jfn)3:-3=cag"9%:5kio*14,1<'8;ekm,74.?2nbb%<<)69gmk.5< =0hd`'24+4?aoi ;<";6jfn)04-2=cag"94$94dhl+6'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<;?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,> 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,>:&8:flqq.4= 20hb{{(24*<>bh}}"8;$64dnww,6>.02ndyy&<9(58`jss =#<7iazt)7*3>bh}}"=%:5kotv+3,199gkpr;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;>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;169gkpr;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~64)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~6P2bnh[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-4311`9svjaXn|fgSyf}erj\j`af|l";%)028vaYci}kTob{at)0*55=ulVnjxlQlotlw,6/682xoSio{a^alqkr;87;97jPd`vb[firf}686=0:;sf\ak04ws]geqgXkfex%?&119tvZbf|hUhcx`{(3+24>quWmkmRm`uov+7,753~xThlzn_bmvjq:4294>7z|Peo48swYu{}wKL}7l3:BC|40<6;;h>5k4<16dek4293;0b?;=:59'61`=:=h0q^0<6;;h>5k4<16de?V2>2::26=4>33`6=c<491::7^5<6;;h>5k4<1922?a57;3:1=7?tS229756==3;8>o;6f;123c`<~]h?6=4>:08250}T;908<=4::011f0?a2:;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;07b5$c296c152g58jd`=>21d>n750;&a4?4a?2djj794;n0`k94n`d9<>=h:j=1<7*m0;0e3>hfn3307b5$c296c152g58jd`=m21d>n>50;&a4?4a?2djj7h4;n0ab?6=,k:1>k94n`d955=i5jj0;6)l?:3d4?kga28907b290/n=4=f69mec<6=21d>o650;&a4?4a?2djj7?9;:m1f2<72-h;6?h8;oce>41<3f8i:7>5$c296c15<#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<77`03gkm6k94n`d965=i5l80;6)l?:3d4?kga2;907bo>50;&a4?4a?2djj7<9;:m1ec<72-h;6?h8;oce>71<3`85$c296d052`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<75$c296d052`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<75$c296d05<#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<77g13gkm6<94;h051?6=,k:1>l84n`d95==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=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<77g13gkm6?94;h11f?6=3k8?;7>51;294~N55}O:=<0(o853g9l7`<722wi>:4?:9a9a=<69984Z3: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=>i48h0;66a<3g83>!d72:>;7coi:198k65b290/n=4<419mec<632e8?i4?:%`3>6273gkm6?54o21`>5<#j9088=5aag80?>i4:o0;6)l?:212?kga2910c>;:m06a<72-h;6>=>;oce>7=!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>7=>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=!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=!d72;l<7coi:b98k7e5290/n=4=f69mec7`03gkm6h54o3a3>5<#j909j:5aag8e?>i5jo0;6)l?:3d4?kga28:07bom50;&a4?4a?2djj7?<;:m1fd<72-h;6?h8;oce>42<3f8i57>5$c296c15<#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<77`03gkm6k94n`d95a=i5l=0;6)l?:3d4?kga2;:07bi?50;&a4?4a?2djj7<<;:m1g3<72-h;6?h8;oce>72<3f8in7>5$c296c1854o3`3>5<#j909j:5aag812>=h:hl1<7*m0;0e3>hfn38<76g<0g83>!d72:;;7coi:198m66b290/n=4<119mec<632c86773gkm6?54i22`>5<#j908==5aag80?>o5?o0;6)l?:3c5?kga2910e?9j:18'f5<5i?1emk4>;:k13a<72-h;6?o9;oce>7=!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=!d72;k=7coi:b98m716290/n=4=a79mec7g13gkm6h54i34e>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$c296d05<#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<77g13gkm6l84n`d95a=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$c296d0854i37e>5<#j909m;5aag812>=n:hfn38<76g=5483>>o4:=0;6)l?:206?kga2910e><<:18'f5<4:<1emk4>;:k067<72-h;6><:;oce>7=!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;4k50;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<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:17d5}#j?0846F=4b9K610<@;<0(9h53258 13=:2c957>5;h12>5<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>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<>{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<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>N5984$5796>o513:17d5}#j?08m6F=4b9K610<,=?1>6g=9;29?l4e2900e?j50;9j74<722ei>7>5;|`27g<72<0;6=u+b780e>N5984$5796>o513:17d5}#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>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>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>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>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>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>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>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>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>N55<>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<=7):::39j6<<722c9h7>5;h12>5<=7):::39j6<<722c9h7>5;h12>5<=7):::39j6<<722c9h7>5;h12>5<=7):::39j6<<722c9h7>5;h12>5<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;5+4g8072=#<<097d<6:188m7b=831b?<4?::ma6?6=3th:<<4?:583>5}#j?0856F=4b9K610<@;<0(9h53258 13=:2c957>5;h0g>5<>{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<=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>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<>{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<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<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<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<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<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<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<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<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<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<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<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<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<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<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<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<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<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<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<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<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<55;h10>5<1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn:18g>5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<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<55;h10>5<1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<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<55;h10>5<1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn<7=:18g>5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<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<55;h10>5<1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn<76:18g>5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<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<55;h10>5<1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn<7l:18g>5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<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<55;h10>5<1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<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<55;h10>5<1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<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<55;h10>5<1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<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<55;h10>5<1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<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<55;h10>5<1<75f3483>>o4>3:17d<;9;29?l43i3:17bl::188k64=831vn5<7s-h=6o=4H36`?M43>2c9>7>5;h00>5<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<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<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<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<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<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<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<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<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<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<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<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<5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8"3=380e?750;9j6g<722c9h7>5;h12>5<5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8"3=380e?750;9j6g<722c9h7>5;h12>5<5<2290;w)l9:2c8L72d3A8?:6*;5;08m7?=831b>o4?::k1`?6=3`9:6=44oc094?=zj8"3=380e?750;9j6g<722c9h7>5;h12>5<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<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<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<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<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<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>N5984$579e>o393:17d:=:188kdd=831vn<:l:180>5<7s-h=69l4H36`?M43>2.?97?9;h62>5<>{e9;31<7=50;2x g0=9m4H365?!2228<0e9?50;9j07<722ejn7>5;|``6?6=;3:1o393: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<=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>ifj3:17pl>1583>1<729q/n;4;c:J10f=O:=<0(9;51c9j04<722c?>7>5;h60>5<5<3290;w)l9:5a8L72d3A8?:6*;5;3:?l262900e9<50;9j06<722ejn7>5;|`26d<72=0;6=u+b787g>N5984$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>N5a: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<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:1o393: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>o3;3:17d:;:188kdd=831vn<<=:186>5<7s-h=69j4H36`?M43>2.?97?k;h62>5<>o3<3:17bom:188yg75;3:197>50z&a2?2c3A8?o6F=479'00<582c?=7>5;h61>5<>ifj3:17pl>1d83>6<729q/n;4;b:J10f=O:=<0(9;51d9j04<722c?>7>5;nca>5<55;294~"e>3>o7E<;c:J103=#<<08;6g;1;29?l252900e9=50;9j01<722ejn7>5;|`aa?6=<3:1o393:17d:=:188m15=831dmo4?::af=<72=0;6=u+b787g>N5984$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<>ifj3:17plm9;291?6=8r.i:7:k;I07g>N57:k75?6=3`>96=44i5194?=n<=0;66anb;29?xd6990;684?:1y'f3<3l2B98n5G2548 13=?2c?=7>5;h61>5<>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:15;n6;>5<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?[5412T8m6P=589]60>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<34;;n7<6;<33e?4>34;;57<6;<3334;;?7<6;<336?4>34;;=7<6;<334?4>34n>6?74=e696<=:l:09563k2;0:?876=38270?>2;0:?876138270?>8;0:?847038270f;0:?845i38270<=b;0:?845k38270<=d;0:?845m38270<=f;0:?847i382701;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~=34i<6?74=d796<=:m=09563j3;0:?8c52;301ij5289>`f<5127on7<6;7?<5oh1>452f`81=>;a138270h7:3;894g12;>270?60;07=>;61k0984521c3961?<58h86?:6;<3a2?43127:n94=489>5g3=:=301938?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: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~k;50;0xZ7eb34;3;7l=;|q1b1<72;qU>nj4=0:5>g452z\1gf=:91?1n?5rs3d1>5<5sW8hn63>858a6>{t:o;1<77}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~h:50;0xZ7dc34;<:7l=;|q1a6<72;qU>om4=056>g452z\1fd=:9>91n?5rs3g3>5<5sW8i563>738a6>{t:ml1<77}Y:k=01<9?:c08yv4cl3:1>vP=b79>53`=j;1v?jl:181[4e=27::h4m2:p6ad=838pR?l;;<35`?d53ty9hl4?:3y]6g5<58;6>h0i>6s|2gd94?4|V;n=70?7f;`1?xu5nl0;6?uQ2e7894>b2k80q~kl50;0xZ7b534;3n7l=;|q1bd<72;qU>i?4=0:b>g452z\1g3=:9>l1n?5rs3gg>5<5sW8in63>758a6>{t:l81<77}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>6752z\137=:9h>1?<5rs3;;>5<5sW8<=63>a2805>{t:0=1<77}Y:?l01: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>6752z\124=:9091?<5rs3:4>5<5sW8=<63>93805>{t:ho1<7939:7p}=ae83>7}Y:1>01vP=829>5g0=;81v?om:181[4?:27:n84<1:p6dg=838pR?6>;<3a0?563ty9m44?:3y]6=6<58h86>?4}r0b;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>1753z?17`<49279?n4=b:?17a>k50;0x975b2k801?:?:538yv4493:1?v3=33805>;5;80i>63=34876>{t::i1<7=t=31`>g4<5;9o6>?4=363>1454z?17g=83op1?=m:c08947d2k;01<=7:3f8945>2;n01<=n:3f8945e2;n01<=>:3f894572k;01<==:3f894542;n01;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<l4=d:?16g<5l279>n4=d:?16a<5l279>h4=d:?16c<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>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=;7b<5j31>i52c981`>;d?38o70k::3f89`2=:m16i>4=d:?f6?4c34no6?j4=ea96a=:lk09h63ka;0g?8`e2;n01ko52e9>b<<5l27m47576=ik1v7;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>dd57z?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<77=;;<3b7?5334;j97=;;<3b3?5334;jm7=;;<3b5<2s4;8m7=>;<306?d534;9m7:=;<31f?2334;9?7:<;|q273<72;ip1<=n:c0894g12:?01<7?:27894?e2:?01:27894d42:?01: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:?012:?01nu212`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;h01838?m63>9c810d=:9k;1>9o4=0`0>72f34;i:7<;a:?2f1<5j70?61;07e>;61=098l52180961g<58386?:n;<3:1?43i27:5;4=4`9>5038?m63>9`810d=:90i1>9o4=0;e>72f34;2h7<;a:?2=`<5525c894g62;>j70?n4;07e>;6i;098l521`1961g<58k>6?:n;<3b3?43i27:ml4=4`9>5d>=:=k01ab810d=:9hl1>9o4=0cg>72f34;ji7<;a:?2f5<5: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<=;1447>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}:952157906=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<4?:2y>g24;4:?204<3:2wx==950;7x9c6=;816==l5b39>fa<3:27ii7:=;<`e>14g4<588969<4=03f>1767<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>g452z?24=;g467<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<767<5oh1n?5rsg494?4|58:96>?4=gc9f7=z{o?1<767<5o31n?5rsg694?4|58:;6>?4=g:9f7=z{m;1<76s|d183>7}:lj08=63k4;`1?xudn3:1>v3kb;12?8b42k80q~mj:1818bf2:;01i<5b39~w`0=838p1i:5309>fd`6<4927in7om;|qf7=>;<``>dd52z?ee?5634i;6ll4}r33`?6=:r7m57=>;dd52z?ei: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>1553z?25<<4927:=54<1:?25gv3=09805>;61908>6s|1d294?4|5;:36o<4=04;>6752z?14<<4927:5o4<2:p5`d=838p1?>6:c08940>2:;0q~?le;296~;59=08=63>a7806>{t9o<1<7g4<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>6752z?16g<4927:n94<2:p655=838p1?e2:;0q~?kc;296~;5:j08=63>b4806>{t:9>1<7g4<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>6752z?16c<4927:5<4<2:p651=838p1?a2:;0q~?m9;296~;58h08=63>93806>{t9l;1<7g4<58?4}r3ae?6=:r79v3=0b805>;61=08>6s|1d194?4|5;:h6o<4=04`>6752z?14a<4927:584<2:p5`2=838p1?>k:c08940c2:;0q~?md;296~;58l08=63>97806>{t9l?1<7g4<58?4}r3aa?6=:r79v3=11805>;61108>6s|1d594?4|5;;;6o<4=053>6752z?154<4927:544<2:p5`>=838p1??>:c0894162:;0q~?l1;296~;59;08=63>9`806>{t9l31<7g4<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>6752z?153<4927:5h4<2:p5`b=838p1??9:c0894112:;0q~?l6;296~;59>08=63>9g806>{t9lo1<7g4<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:>6752z?15d<4927:m?4<2:p5c7=838p1??n:c08941f2:;0q~?la;296~;59k08=63>a2806>{t9o81<7g4<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>6752z?15`<4927:m:4<2:p5c3=838p1??j:c08941b2:;0q~?lf;296~;5:908=63>a9806>{t9o=1<7g4<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>677>52z?166<4927:mo4<2:p5cg=838p1?<<:c0894>42:;0q~?k3;296~;5:=08=63>ab806>{t9oh1<7g4<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>6752z?162<4927:mk4<2:p5cc=838p1?<8:c0894>02:;0q~?k7;296~;5:108=63>b1806>{t9ol1<7g4<58236>?4}r3g44<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=37}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>2252z\134=::>09;<5+257930=z{;3<6=4={_044>;5?38<<6*=44842>{t:0<1<7<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<<07}Y:??01?952778 72221:0q~<7b;296~X5>=16>:4=659'613=081v?6n:181[41;279;7<93:&1005750;0xZ705348<6?8=;%071?>43ty9454?:3y]637<5;=1>;?4$366>=252z\125=::>09:=5+2579<0=z{;kn6=4={_0;1>;5?38396*=448;2>{t:hn1<7vP=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><052z\1`5=::>09h=5+2579===z{;l=6=4={_0`b>;5?38hj6*=448:=>{t:o?1<7vP=cb9>62<5kj1/>9;59b9~w7`52909wS7ef3-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~:4=c29'613=i<1v?k6:181[4d:279;72wx>h650;0xZ7e6348<6?m>;%071?g03ty9i:4?:3y]6f6<5;=1>n>4$366>d>52z\1fc=::>09nk5+257916=z{;o>6=4={_0aa>;5?38ii6*=44860>{t:l>1<7vP=b`9>62<5jh1/>9;5569~w7c72909wS7d?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:4=b39'613=>91v?j7:181[4e9279;7kh50;0xZ7b1348<6?j9;%071?053ty9jh4?:3y]6a3<5;=1>i;4$366>3552z\1`1=::>09h95+257921=z{;lh6=4={_0g7>;5?38o?6*=44851>{t:oh1<7vP=c79>62<5k?1/>9;5689~w7cc2909wS7d73-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~N52we48m50;0xL7213td39i4?:3yK610i7>52zJ103=zf1?m6=4={I072>{i0?:1<780;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~N52we4;m50;0xL7213td3:i4?:3yK61052zJ103=zf1{i0>:1<70: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~N52we4:m50;0xL7213td3;i4?:3yK61052zJ103=zf1=m6=4={I072>{i01:1<7?: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~N52we45m50;0xL7213td34i4?:3yK61052zJ103=zf12m6=4={I072>{i00:1<7>: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~N52we44m50;0xL7213td35i4?:3yK61052zJ103=zf13m6=4={I072>{i0h:1<7f:3:1>vF=479~j=g42909wE<;6:m984}o:b2?6=:rB98;5rn9c4>5<5sA8?:6sa8`:94?4|@;>=7p`7a883>7}O:=<0qc6na;296~N52we4lm50;0xL7213td3mi4?:3yK61051zJ103=zf>3j6=4>{I072>{i?0h1<7?tH365?xh01j0;6l3: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~N52we;l950;3xL7213td51zJ103=zf>kj6=4>{I072>{i?hh1<7?tH365?xh0ij0;6984}o5a5?6=9rB98;5rn6`1>5<6sA8?:6sa7c194?7|@;>=7p`8b583>4}O:=<0qc9m5;295~N52we;o950;3xL7213td51zJ103=zf>hj6=4>{I072>{i?kh1<7?tH365?xh0jj0;6984}o5`5?6=9rB98;5rn6a1>5<6sA8?:6sa7b194?7|@;>=7p`8c583>4}O:=<0qc9l5;295~N52we;n950;3xL7213td51zJ103=zf>ij6=4>{I072>{i?jh1<7?tH365?xh0kj0;6984}o5g5?6=9rB98;5rn6f1>5<6sA8?:6sa7e194?7|@;>=7p`8d583>4}O:=<0qc9k5;295~N52we;i950;3xL7213td51zJ103=zf>nj6=4>{I072>{i?mh1<7?tH365?xh0lj0;6984}o5f5?6=9rB98;5rn6g1>5<6sA8?:6sa7d194?7|@;>=7p`8e583>4}O:=<0qc9j5;295~N52we;h950;3xL7213td51zJ103=zf>oj6=4>{I072>{i?lh1<7?tH365?xh0mj0;6984}o5e5?6=9rB98;5rn6d1>5<6sA8?:6sa7g194?7|@;>=7p`8f583>4}O:=<0qc9i5;295~N52we;k950;3xL7213td51zJ103=zf>lj6=4>{I072>{i?oh1<7?tH365?xh0nj0;6984}o:35?6=9rB98;5rn921>5<6sA8?:6sa81194?7|@;>=7p`70583>4}O:=<0qc6?5;295~N59:182M43>2we4=950;3xL7213td3<54?:0yK61051zJ103=zf1:j6=4>{I072>{i09h1<7?tH365?xh?8j0;67l3: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~N52we4<950;3xL7213td3=54?:0yK61051zJ103=zf1;j6=4>{I072>{i08h1<7?tH365?xh?9j0;66l3: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~N52we4?950;3xL7213td3>54?:0yK61051zJ103=zf18j6=4>{I072>{i0;h1<7?tH365?xh?:j0;65l3: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~N52we4>950;3xL7213td3?54?:0yK61051zJ103=zf19j6=4>{I072>{i0:h1<7?tH365?xh?;j0;64l3: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~N52we49950;3xL7213td3854?:0yK61051zJ103=zf1>j6=4>{I072>{i0=h1<7?tH365?xh?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~N52wvqpNOCz;`7?1fm?:m4pNOBz2~DEV|uIJ \ No newline at end of file diff --git a/usrp2/coregen/fifo_xlnx_16x40_2clk.v b/usrp2/coregen/fifo_xlnx_16x40_2clk.v new file mode 100644 index 000000000..8a08330d5 --- /dev/null +++ b/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/usrp2/coregen/fifo_xlnx_16x40_2clk.veo b/usrp2/coregen/fifo_xlnx_16x40_2clk.veo new file mode 100644 index 000000000..684078e58 --- /dev/null +++ b/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/usrp2/coregen/fifo_xlnx_16x40_2clk.xco b/usrp2/coregen/fifo_xlnx_16x40_2clk.xco new file mode 100644 index 000000000..d0da5a6e8 --- /dev/null +++ b/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/usrp2/coregen/fifo_xlnx_16x40_2clk_fifo_generator_v4_3_xst_1.ngc_xst.xrpt b/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/usrp2/coregen/fifo_xlnx_16x40_2clk_fifo_generator_v4_3_xst_1.ngc_xst.xrpt @@ -0,0 +1,98 @@ + + + + + + +
+ + + + + + + + + + + + + +
+
+ + + + + + + + + + + +
+
+ + + +
+
+
+
+
+
+
+
+ + + + +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
+
+
+ + + + + + + + +
+
+
+
+
+ + + +
+ + + diff --git a/usrp2/coregen/fifo_xlnx_16x40_2clk_flist.txt b/usrp2/coregen/fifo_xlnx_16x40_2clk_flist.txt new file mode 100644 index 000000000..c38f4e991 --- /dev/null +++ b/usrp2/coregen/fifo_xlnx_16x40_2clk_flist.txt @@ -0,0 +1,8 @@ +# Output products list for +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/usrp2/coregen/fifo_xlnx_16x40_2clk_readme.txt b/usrp2/coregen/fifo_xlnx_16x40_2clk_readme.txt new file mode 100644 index 000000000..bbcd4af79 --- /dev/null +++ b/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/usrp2/coregen/fifo_xlnx_16x40_2clk_xmdf.tcl b/usrp2/coregen/fifo_xlnx_16x40_2clk_xmdf.tcl new file mode 100644 index 000000000..2b4824831 --- /dev/null +++ b/usrp2/coregen/fifo_xlnx_16x40_2clk_xmdf.tcl @@ -0,0 +1,68 @@ +# The package naming convention is _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 _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: +# 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 -- cgit v1.2.3 From 9899b81f920b8dab0220e2e4b086bae0f24f6970 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 11 May 2010 15:49:48 -0700 Subject: cleaned up the logic, this is copied over from quad radio --- usrp2/control_lib/settings_bus.v | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/usrp2/control_lib/settings_bus.v b/usrp2/control_lib/settings_bus.v index d01a30ab4..aec179516 100644 --- a/usrp2/control_lib/settings_bus.v +++ b/usrp2/control_lib/settings_bus.v @@ -10,8 +10,7 @@ module settings_bus input wb_stb_i, input wb_we_i, output reg wb_ack_o, - input sys_clk, - output strobe, + output reg strobe, output reg [7:0] addr, output reg [31:0] data); @@ -20,18 +19,18 @@ module settings_bus always @(posedge wb_clk) if(wb_rst) begin - stb_int <= 1'b0; + strobe <= 1'b0; addr <= 8'd0; data <= 32'd0; end - else if(wb_we_i & wb_stb_i) + else if(wb_we_i & wb_stb_i & ~wb_ack_o) begin - stb_int <= 1'b1; + strobe <= 1'b1; addr <= wb_adr_i[9:2]; data <= wb_dat_i; end else - stb_int <= 1'b0; + strobe <= 1'b0; always @(posedge wb_clk) if(wb_rst) @@ -39,11 +38,4 @@ module settings_bus else wb_ack_o <= wb_stb_i & ~wb_ack_o; - always @(posedge wb_clk) - stb_int_d1 <= stb_int; - - //assign strobe = stb_int & ~stb_int_d1; - assign strobe = stb_int & wb_ack_o; - endmodule // settings_bus - -- cgit v1.2.3 From 9df5aa38bb1cd289e80ca817c4cd7412b1eb7e0c Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 11 May 2010 15:54:36 -0700 Subject: remove port which is no longer there --- usrp2/top/u2_core/u2_core.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usrp2/top/u2_core/u2_core.v b/usrp2/top/u2_core/u2_core.v index fd17a10a7..78922fb4f 100755 --- a/usrp2/top/u2_core/u2_core.v +++ b/usrp2/top/u2_core/u2_core.v @@ -431,7 +431,7 @@ 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; -- cgit v1.2.3 From 81f211c94f761c92baaf1a2997a7f9b9b7718182 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 11 May 2010 16:35:01 -0700 Subject: Moved usrp2 eeprom addr read/write to host control over i2c/eeprom interface calls. No longer part of the dude/bro protocol. Simplified the mac and ip addr read write code in mboard impl. Modified the mac addr type to take byte_vector_t from serial.hpp types. --- firmware/microblaze/apps/txrx_uhd.c | 23 +++-------------- host/include/uhd/types/mac_addr.hpp | 16 +++++------- host/include/uhd/utils/algorithm.hpp | 5 ++++ host/lib/types.cpp | 27 ++++++++++--------- host/lib/usrp/usrp2/fw_common.h | 10 ++------ host/lib/usrp/usrp2/mboard_impl.cpp | 50 +++++++++--------------------------- host/lib/usrp/usrp2/usrp2_iface.hpp | 7 +++++ host/lib/usrp/usrp2/usrp2_impl.cpp | 4 +-- 8 files changed, 53 insertions(+), 89 deletions(-) diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index db830fa51..7ad4ab110 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -185,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 @@ -209,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; + 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_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); - 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 ******************************************************************/ diff --git a/host/include/uhd/types/mac_addr.hpp b/host/include/uhd/types/mac_addr.hpp index 3cd1fe86b..034b6a348 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 -#include +#include #include 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 + byte_vector_t _bytes; //internal representation }; } //namespace uhd 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 inline + void copy(const RangeSrc &src, RangeDst &dst){ + std::copy(boost::begin(src), boost::end(src), boost::begin(dst)); + } + template 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/types.cpp b/host/lib/types.cpp index ec9c8ac01..33eb550a1 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -15,6 +15,7 @@ // along with this program. If not, see . // +#include #include #include #include @@ -164,17 +165,19 @@ 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){ + UHD_ASSERT_THROW(bytes.size() == 6); + _bytes = bytes; } -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 +192,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,19 +202,19 @@ 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; } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index f28013cf6..75f5b1779 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -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', @@ -96,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; diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 7e62bedf0..9ae68d158 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -19,10 +19,11 @@ #include "usrp2_regs.hpp" #include #include +#include #include #include #include -#include //htonl and ntohl +#include #include using namespace uhd; @@ -129,30 +130,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() == "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() == "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; } } @@ -223,27 +209,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() == "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::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()).to_bytes(); + _iface->write_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_MAC_ADDR, bytes); return; } if (key.as() == "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()).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()).to_bytes(), bytes); + _iface->write_eeprom(I2C_ADDR_MBOARD, EE_MBOARD_IP_ADDR, bytes); return; } } 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 5c1d7f9e3..2b7bdeea2 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; -- cgit v1.2.3 From fd4bdced70e5089434ec736b5938456219bda068 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 11 May 2010 17:20:06 -0700 Subject: reverting logic clean up which should have made timing better, but made it worse instead --- usrp2/control_lib/settings_bus.v | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/usrp2/control_lib/settings_bus.v b/usrp2/control_lib/settings_bus.v index aec179516..fc960e456 100644 --- a/usrp2/control_lib/settings_bus.v +++ b/usrp2/control_lib/settings_bus.v @@ -10,7 +10,7 @@ module settings_bus input wb_stb_i, input wb_we_i, output reg wb_ack_o, - output reg strobe, + output strobe, output reg [7:0] addr, output reg [31:0] data); @@ -19,18 +19,18 @@ module settings_bus always @(posedge wb_clk) if(wb_rst) begin - strobe <= 1'b0; + stb_int <= 1'b0; addr <= 8'd0; data <= 32'd0; end - else if(wb_we_i & wb_stb_i & ~wb_ack_o) + else if(wb_we_i & wb_stb_i) begin - strobe <= 1'b1; + stb_int <= 1'b1; addr <= wb_adr_i[9:2]; data <= wb_dat_i; end else - strobe <= 1'b0; + stb_int <= 1'b0; always @(posedge wb_clk) if(wb_rst) @@ -38,4 +38,11 @@ module settings_bus else wb_ack_o <= wb_stb_i & ~wb_ack_o; + always @(posedge wb_clk) + stb_int_d1 <= stb_int; + + //assign strobe = stb_int & ~stb_int_d1; + assign strobe = stb_int & wb_ack_o; + endmodule // settings_bus + -- cgit v1.2.3 From 4eef4015672ffafb56d66feb57848772f42b54e3 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 12 May 2010 16:10:08 -0700 Subject: move dsp settings regs to reclocked setting bus. Works, gets us to within 18ps of passing timing --- usrp2/top/u2_core/u2_core.v | 28 ++++++++++++++++------------ usrp2/top/u2_rev3/Makefile | 3 +++ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/usrp2/top/u2_core/u2_core.v b/usrp2/top/u2_core/u2_core.v index 2302f59ee..b57e4f127 100644 --- a/usrp2/top/u2_core/u2_core.v +++ b/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), @@ -480,6 +480,10 @@ module u2_core 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/usrp2/top/u2_rev3/Makefile b/usrp2/top/u2_rev3/Makefile index 867fb5cab..af93700c5 100644 --- a/usrp2/top/u2_rev3/Makefile +++ b/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 \ -- cgit v1.2.3 From 9fd30e928e3599b43b3d9bbd7be82793a62d7944 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 12 May 2010 18:59:15 -0700 Subject: Added card burner python app with gui and windows support. --- host/docs/usrp2.rst | 2 +- host/utils/CMakeLists.txt | 12 +- host/utils/usrp2_addr_burner.cpp | 90 +++++++++++++ host/utils/usrp2_burner.cpp | 90 ------------- host/utils/usrp2_card_burner.py | 285 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 384 insertions(+), 95 deletions(-) create mode 100644 host/utils/usrp2_addr_burner.cpp delete mode 100644 host/utils/usrp2_burner.cpp create mode 100755 host/utils/usrp2_card_burner.py diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index dfde06b27..c453354ca 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -103,7 +103,7 @@ Run the following commands: :: cd /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/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index 3c2236379..d28576e8c 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -19,12 +19,16 @@ ADD_EXECUTABLE(uhd_find_devices uhd_find_devices.cpp) TARGET_LINK_LIBRARIES(uhd_find_devices uhd) INSTALL(TARGETS uhd_find_devices RUNTIME DESTINATION ${RUNTIME_DIR}) -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 + DESTINATION ${PKG_DATA_DIR}/utils +) diff --git a/host/utils/usrp2_addr_burner.cpp b/host/utils/usrp2_addr_burner.cpp new file mode 100644 index 000000000..08fc1e218 --- /dev/null +++ b/host/utils/usrp2_addr_burner.cpp @@ -0,0 +1,90 @@ +// +// 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 . +// + +#include +#include +#include +#include +#include +#include + +namespace po = boost::program_options; + +int UHD_SAFE_MAIN(int argc, char *argv[]){ + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "help message") + ("addr", po::value(), "resolvable network address") + ("new-ip", po::value(), "new ip address (optional)") + ("new-mac", po::value(), "new mac address (optional)") + ; + + 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("USRP2 Address Burner %s") % desc << std::endl; + return ~0; + } + + //load the options into the address + uhd::device_addr_t device_addr; + if (vm.count("addr")){ + device_addr["addr"] = vm["addr"].as(); + } + else{ + std::cerr << "Error: missing addr option" << std::endl; + return ~0; + } + + //create a usrp2 device + uhd::device::sptr u2_dev = uhd::usrp::usrp2::make(device_addr); + //FIXME usees the default mboard for now (until the mimo link is supported) + wax::obj u2_mb = (*u2_dev)[uhd::usrp::DEVICE_PROP_MBOARD]; + std::cout << std::endl; + + //fetch and print current settings + std::cout << "Fetching current settings from usrp2 eeprom:" << std::endl; + std::string curr_ip = u2_mb[std::string("ip-addr")].as(); + std::cout << boost::format(" Current IP Address: %s") % curr_ip << std::endl; + std::string curr_mac = u2_mb[std::string("mac-addr")].as(); + std::cout << boost::format(" Current MAC Address: %s") % curr_mac << std::endl; + std::cout << " Done" << std::endl << std::endl; + + //try to set the new ip (if provided) + if (vm.count("new-ip")){ + std::cout << "Burning a new ip address into the usrp2 eeprom:" << std::endl; + std::string new_ip = vm["new-ip"].as(); + std::cout << boost::format(" New IP Address: %s") % new_ip << std::endl; + u2_mb[std::string("ip-addr")] = new_ip; + std::cout << " Done" << std::endl << std::endl; + } + + //try to set the new mac (if provided) + if (vm.count("new-mac")){ + std::cout << "Burning a new mac address into the usrp2 eeprom:" << std::endl; + std::string new_mac = vm["new-mac"].as(); + std::cout << boost::format(" New MAC Address: %s") % new_mac << std::endl; + u2_mb[std::string("mac-addr")] = new_mac; + std::cout << " Done" << std::endl << std::endl; + } + + std::cout << "Power-cycle the usrp2 for the changes to take effect." << std::endl; + return 0; +} diff --git a/host/utils/usrp2_burner.cpp b/host/utils/usrp2_burner.cpp deleted file mode 100644 index 9c1bf72fe..000000000 --- a/host/utils/usrp2_burner.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// 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 . -// - -#include -#include -#include -#include -#include -#include - -namespace po = boost::program_options; - -int UHD_SAFE_MAIN(int argc, char *argv[]){ - po::options_description desc("Allowed options"); - desc.add_options() - ("help", "help message") - ("addr", po::value(), "resolvable network address") - ("new-ip", po::value(), "new ip address (optional)") - ("new-mac", po::value(), "new mac address (optional)") - ; - - 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("USRP2 Burner %s") % desc << std::endl; - return ~0; - } - - //load the options into the address - uhd::device_addr_t device_addr; - if (vm.count("addr")){ - device_addr["addr"] = vm["addr"].as(); - } - else{ - std::cerr << "Error: missing addr option" << std::endl; - return ~0; - } - - //create a usrp2 device - uhd::device::sptr u2_dev = uhd::usrp::usrp2::make(device_addr); - //FIXME usees the default mboard for now (until the mimo link is supported) - wax::obj u2_mb = (*u2_dev)[uhd::usrp::DEVICE_PROP_MBOARD]; - std::cout << std::endl; - - //fetch and print current settings - std::cout << "Fetching current settings from usrp2 eeprom:" << std::endl; - std::string curr_ip = u2_mb[std::string("ip-addr")].as(); - std::cout << boost::format(" Current IP Address: %s") % curr_ip << std::endl; - std::string curr_mac = u2_mb[std::string("mac-addr")].as(); - std::cout << boost::format(" Current MAC Address: %s") % curr_mac << std::endl; - std::cout << " Done" << std::endl << std::endl; - - //try to set the new ip (if provided) - if (vm.count("new-ip")){ - std::cout << "Burning a new ip address into the usrp2 eeprom:" << std::endl; - std::string new_ip = vm["new-ip"].as(); - std::cout << boost::format(" New IP Address: %s") % new_ip << std::endl; - u2_mb[std::string("ip-addr")] = new_ip; - std::cout << " Done" << std::endl << std::endl; - } - - //try to set the new mac (if provided) - if (vm.count("new-mac")){ - std::cout << "Burning a new mac address into the usrp2 eeprom:" << std::endl; - std::string new_mac = vm["new-mac"].as(); - std::cout << boost::format(" New MAC Address: %s") % new_mac << std::endl; - u2_mb[std::string("mac-addr")] = new_mac; - std::cout << " Done" << std::endl << std::endl; - } - - std::cout << "Power-cycle the usrp2 for the changes to take effect." << 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..99cdcb626 --- /dev/null +++ b/host/utils/usrp2_card_burner.py @@ -0,0 +1,285 @@ +#!/usr/bin/env python + +######################################################################## +# Deal with raw devices +######################################################################## +import glob +import platform +import tempfile +import subprocess +import urllib + +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 + +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' + +def get_raw_device_hints(): + if platform.system() == 'Windows': + output = subprocess.Popen( + [get_dd_path(), '--list'],#, '--filter=removable'], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ).stdout.read() + volumes = list() + for info in output.replace('\r', '').split('\n\\\\'): + if 'removeable' not in info.lower(): continue + if 'link to' not in info: continue + if 'size is' in info: + size = info.split('size is')[-1].split()[0] + if int(size) > 2048e6: continue + if 'Mounted on' in info: + volumes.append(info.split('Mounted on')[-1].split()[0]) + continue + volumes.append(info.split('link to')[-1].split()[0]) + return volumes + if platform.system() == 'Linux': + return sorted(set(filter(lambda sd: not sd[-1].isdigit(), glob.glob("/dev/sd*")))) + return () + +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 + args = [ + get_dd_path(), + "of=%s"%tmp_file, + "if=%s"%device_file, + "skip=%d"%offset, + "bs=%d"%SECTOR_SIZE, + "count=%d"%(MAX_FILE_SIZE/SECTOR_SIZE), + ] + p = subprocess.Popen( + args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + ret = p.wait() + verbose = p.stdout.read() + if ret != 0: raise Exception, verbose + + #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): + args = [ + get_dd_path(), + "if=%s"%image_file, + "of=%s"%device_file, + "seek=%d"%offset, + "bs=%d"%SECTOR_SIZE, + ] + p = subprocess.Popen( + args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + ret = p.wait() + verbose = p.stdout.read() + + #get the verbose back to the caller + if ret != 0: raise Exception, verbose + 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 verbose:\n%s\n'%write_and_verify( + image_file=fw, device_file=dev, offset=FIRMWARE_OFFSET + ) + if fpga: verbose += 'Burn fpga image verbose:\n%s\n'%write_and_verify( + image_file=fpga, device_file=dev, offset=FPGA_OFFSET + ) + return verbose + +######################################################################## +# Graphical Tk stuff +######################################################################## +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) + + self._hints = Tkinter.Listbox(self) + self._hints.bind("<>", self._listbox_cb) + for hint in get_raw_device_hints(): + self._hints.insert(Tkinter.END, hint) + 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 _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.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 = burn_sd_card(dev=dev, fw=fw, fpga=fpga) + tkMessageBox.showinfo('Verbose:', verbose) + except Exception, e: + tkMessageBox.showerror('Verbose:', 'Error: %s'%str(e)) + +######################################################################## +# Main +######################################################################## +import optparse + +if __name__=='__main__': + parser = optparse.OptionParser() + parser.add_option("--gui", action="store_true", default=False, help="run in gui mode") + 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='') + (options, args) = parser.parse_args() + + if options.gui: + root = Tkinter.Tk() + root.title('USRP2 SD Card Burner') + USRP2CardBurnerApp(root, dev=options.dev, fw=options.fw, fpga=options.fpga).pack() + root.mainloop() + exit() + + if not options.dev: raise Exception, 'no raw device path specified' + print burn_sd_card(dev=options.dev, fw=options.fw, fpga=options.fpga) -- cgit v1.2.3 From 24fca6b58d37d390057f423ae4e6c3e5c9930d0a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 12 May 2010 19:08:03 -0700 Subject: notes on usrp2 card burner --- host/docs/usrp2.rst | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index c453354ca..e8901b839 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -45,22 +45,21 @@ 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 card burner tool (linux): :: - cd /firmware/microblaze - sudo ./u2_flash_tool --dev=/dev/sd -t fpga -w - -Load the firmware image: + cd /share/uhd/utils + sudo ./usrp2_card_burner.py --dev=/dev/sd --fpga= + sudo ./usrp2_card_burner.py --dev=/dev/sd --fw= +Use the card burner tool (windows): :: - cd /firmware/microblaze directory - sudo ./u2_flash_tool --dev=/dev/sd -t s/w -w + /share/uhd/utils/usrp2_card_burner.py --gui + ------------------------------------------------------------------------ Setup networking -- cgit v1.2.3 From 2e6123a7f8ddfe99d214b24fc07a2ef3354abfd1 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 13 May 2010 12:10:24 -0700 Subject: work on usrp2 card burner, uses blockdev and /proc/paritions to check for devices, windows tweaks as well --- host/utils/usrp2_card_burner.py | 120 +++++++++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 37 deletions(-) diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py index 99cdcb626..5f876c7bc 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -1,9 +1,24 @@ #!/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 . +# ######################################################################## # Deal with raw devices ######################################################################## -import glob import platform import tempfile import subprocess @@ -15,6 +30,19 @@ 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) + +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') @@ -26,26 +54,57 @@ def get_dd_path(): return 'dd' def get_raw_device_hints(): + #################################################################### + # Platform Windows: parse the output of dd.exe --list + #################################################################### if platform.system() == 'Windows': - output = subprocess.Popen( - [get_dd_path(), '--list'],#, '--filter=removable'], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ).stdout.read() volumes = list() + try: output = command(get_dd_path(), '--list') + except: return volumes + + #coagulate info for identical links + link_to_info = dict() for info in output.replace('\r', '').split('\n\\\\'): - if 'removeable' not in info.lower(): continue if 'link to' not in info: continue + link = info.split('link to')[-1].split()[0].strip() + if not link_to_info.has_key(link): link_to_info[link] = '\n\n' + link_to_info[link] += info + + #parse info only keeping viable volumes + for link, info in link_to_info.iteritems(): + if 'removable' not in info.lower(): continue if 'size is' in info: - size = info.split('size is')[-1].split()[0] - if int(size) > 2048e6: continue + size = info.split('size is')[-1].split()[0].strip() + if int(size) > MAX_SD_CARD_SIZE: continue if 'Mounted on' in info: volumes.append(info.split('Mounted on')[-1].split()[0]) continue - volumes.append(info.split('link to')[-1].split()[0]) - return volumes + volumes.append(link) + + return sorted(set(volumes)) + + #################################################################### + # Platform Linux: call blockdev on all the /dev/sd* devices + #################################################################### if platform.system() == 'Linux': - return sorted(set(filter(lambda sd: not sd[-1].isdigit(), glob.glob("/dev/sd*")))) + devs = list() + try: output = open('/proc/partitions', 'r').read() + except: return devs + for line in output.splitlines(): + try: + major, minor, blocks, name = line.split() + if name[-1].isdigit(): assert int(minor) == 0 + dev = os.path.join('/dev/', name) + size = int(command('blockdev', '--getsz', dev))*512 + assert size <= MAX_SD_CARD_SIZE + except: continue + devs.append(dev) + + return sorted(set(devs)) + + #################################################################### + # Platform Others: + #################################################################### return () def verify_image(image_file, device_file, offset): @@ -55,22 +114,14 @@ def verify_image(image_file, device_file, offset): tmp_file = tmp[1] #execute a dd subprocess - args = [ + verbose = command( get_dd_path(), "of=%s"%tmp_file, "if=%s"%device_file, "skip=%d"%offset, "bs=%d"%SECTOR_SIZE, "count=%d"%(MAX_FILE_SIZE/SECTOR_SIZE), - ] - p = subprocess.Popen( - args, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, ) - ret = p.wait() - verbose = p.stdout.read() - if ret != 0: raise Exception, verbose #read in the image and readback img_data = open(image_file, 'rb').read() @@ -81,24 +132,13 @@ def verify_image(image_file, device_file, offset): return 'Verification Passed:\n%s'%verbose def write_image(image_file, device_file, offset): - args = [ + return command( get_dd_path(), "if=%s"%image_file, "of=%s"%device_file, "seek=%d"%offset, "bs=%d"%SECTOR_SIZE, - ] - p = subprocess.Popen( - args, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, ) - ret = p.wait() - verbose = p.stdout.read() - - #get the verbose back to the caller - if ret != 0: raise Exception, verbose - return verbose def write_and_verify(image_file, device_file, offset): if os.path.getsize(image_file) > MAX_FILE_SIZE: @@ -117,10 +157,10 @@ def write_and_verify(image_file, device_file, offset): def burn_sd_card(dev, fw, fpga): verbose = '' - if fw: verbose += 'Burn firmware image verbose:\n%s\n'%write_and_verify( + 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 verbose:\n%s\n'%write_and_verify( + if fpga: verbose += 'Burn fpga image:\n%s\n'%write_and_verify( image_file=fpga, device_file=dev, offset=FPGA_OFFSET ) return verbose @@ -171,10 +211,11 @@ class DeviceEntryWidget(Tkinter.Frame): def __init__(self, root, text=''): Tkinter.Frame.__init__(self, root) + Tkinter.Button(self, text="Reload Possible Devices", command=self._reload_cb).pack() + self._hints = Tkinter.Listbox(self) self._hints.bind("<>", self._listbox_cb) - for hint in get_raw_device_hints(): - self._hints.insert(Tkinter.END, hint) + self._reload_cb() self._hints.pack(expand=Tkinter.YES, fill=Tkinter.X) frame = Tkinter.Frame(self) @@ -185,6 +226,11 @@ class DeviceEntryWidget(Tkinter.Frame): 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 get_raw_device_hints(): + self._hints.insert(Tkinter.END, hint) + def _listbox_cb(self, event): try: sel = self._hints.get(self._hints.curselection()[0]) -- cgit v1.2.3 From f85e6c6d2f8ed6224eac44ca22d2701600e8a36e Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 13 May 2010 13:37:39 -0700 Subject: revert commit 9899b81f920 which should have improved timing but didn't --- usrp2/control_lib/settings_bus.v | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/usrp2/control_lib/settings_bus.v b/usrp2/control_lib/settings_bus.v index aec179516..d01a30ab4 100644 --- a/usrp2/control_lib/settings_bus.v +++ b/usrp2/control_lib/settings_bus.v @@ -10,7 +10,8 @@ module settings_bus input wb_stb_i, input wb_we_i, output reg wb_ack_o, - output reg strobe, + input sys_clk, + output strobe, output reg [7:0] addr, output reg [31:0] data); @@ -19,18 +20,18 @@ module settings_bus always @(posedge wb_clk) if(wb_rst) begin - strobe <= 1'b0; + stb_int <= 1'b0; addr <= 8'd0; data <= 32'd0; end - else if(wb_we_i & wb_stb_i & ~wb_ack_o) + else if(wb_we_i & wb_stb_i) begin - strobe <= 1'b1; + stb_int <= 1'b1; addr <= wb_adr_i[9:2]; data <= wb_dat_i; end else - strobe <= 1'b0; + stb_int <= 1'b0; always @(posedge wb_clk) if(wb_rst) @@ -38,4 +39,11 @@ module settings_bus else wb_ack_o <= wb_stb_i & ~wb_ack_o; + always @(posedge wb_clk) + stb_int_d1 <= stb_int; + + //assign strobe = stb_int & ~stb_int_d1; + assign strobe = stb_int & wb_ack_o; + endmodule // settings_bus + -- cgit v1.2.3 From fbe639c25af74ee047d724dde0927cc96d343b0e Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 13 May 2010 13:48:30 -0700 Subject: remove files for old prototypes, they were confusing people --- usrp2/top/u2_rev1/.gitignore | 52 ----- usrp2/top/u2_rev1/Makefile | 129 ------------ usrp2/top/u2_rev1/u2_fpga.ise | Bin 477678 -> 0 bytes usrp2/top/u2_rev1/u2_fpga.ucf | 341 ------------------------------- usrp2/top/u2_rev1/u2_fpga_top.prj | 102 ---------- usrp2/top/u2_rev1/u2_fpga_top.v | 393 ----------------------------------- usrp2/top/u2_rev2/.gitignore | 57 ------ usrp2/top/u2_rev2/Makefile | 248 ----------------------- usrp2/top/u2_rev2/u2_rev2.ucf | 337 ------------------------------ usrp2/top/u2_rev2/u2_rev2.v | 417 -------------------------------------- 10 files changed, 2076 deletions(-) delete mode 100644 usrp2/top/u2_rev1/.gitignore delete mode 100644 usrp2/top/u2_rev1/Makefile delete mode 100644 usrp2/top/u2_rev1/u2_fpga.ise delete mode 100755 usrp2/top/u2_rev1/u2_fpga.ucf delete mode 100644 usrp2/top/u2_rev1/u2_fpga_top.prj delete mode 100644 usrp2/top/u2_rev1/u2_fpga_top.v delete mode 100644 usrp2/top/u2_rev2/.gitignore delete mode 100644 usrp2/top/u2_rev2/Makefile delete mode 100644 usrp2/top/u2_rev2/u2_rev2.ucf delete mode 100644 usrp2/top/u2_rev2/u2_rev2.v diff --git a/usrp2/top/u2_rev1/.gitignore b/usrp2/top/u2_rev1/.gitignore deleted file mode 100644 index de5b50277..000000000 --- a/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/usrp2/top/u2_rev1/Makefile b/usrp2/top/u2_rev1/Makefile deleted file mode 100644 index b3245d883..000000000 --- a/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/usrp2/top/u2_rev1/u2_fpga.ise b/usrp2/top/u2_rev1/u2_fpga.ise deleted file mode 100644 index f90caf024..000000000 Binary files a/usrp2/top/u2_rev1/u2_fpga.ise and /dev/null differ diff --git a/usrp2/top/u2_rev1/u2_fpga.ucf b/usrp2/top/u2_rev1/u2_fpga.ucf deleted file mode 100755 index 5d2124819..000000000 --- a/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/usrp2/top/u2_rev1/u2_fpga_top.prj b/usrp2/top/u2_rev1/u2_fpga_top.prj deleted file mode 100644 index 544415f4d..000000000 --- a/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/usrp2/top/u2_rev1/u2_fpga_top.v b/usrp2/top/u2_rev1/u2_fpga_top.v deleted file mode 100644 index 63798a0c8..000000000 --- a/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/usrp2/top/u2_rev2/.gitignore b/usrp2/top/u2_rev2/.gitignore deleted file mode 100644 index 432f8fd58..000000000 --- a/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/usrp2/top/u2_rev2/Makefile b/usrp2/top/u2_rev2/Makefile deleted file mode 100644 index 275c24b02..000000000 --- a/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/usrp2/top/u2_rev2/u2_rev2.ucf b/usrp2/top/u2_rev2/u2_rev2.ucf deleted file mode 100644 index e18dc6f17..000000000 --- a/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/usrp2/top/u2_rev2/u2_rev2.v b/usrp2/top/u2_rev2/u2_rev2.v deleted file mode 100644 index 517285e52..000000000 --- a/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 -- cgit v1.2.3 From 573872edd90207b2c73c7d028868d01afc8b8a5c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 13 May 2010 14:07:18 -0700 Subject: card burner: added --list option, added warning, added sync on linux --- host/utils/usrp2_card_burner.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py index 5f876c7bc..a1d4c5ed1 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -132,7 +132,7 @@ def verify_image(image_file, device_file, offset): return 'Verification Passed:\n%s'%verbose def write_image(image_file, device_file, offset): - return command( + verbose = command( get_dd_path(), "if=%s"%image_file, "of=%s"%device_file, @@ -140,6 +140,12 @@ def write_image(image_file, device_file, offset): "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 @@ -211,7 +217,7 @@ class DeviceEntryWidget(Tkinter.Frame): def __init__(self, root, text=''): Tkinter.Frame.__init__(self, root) - Tkinter.Button(self, text="Reload Possible Devices", command=self._reload_cb).pack() + Tkinter.Button(self, text="Rescan for Devices", command=self._reload_cb).pack() self._hints = Tkinter.Listbox(self) self._hints.bind("<>", self._listbox_cb) @@ -278,6 +284,7 @@ class USRP2CardBurnerApp(Tkinter.Frame): #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): @@ -314,12 +321,18 @@ import optparse if __name__=='__main__': parser = optparse.OptionParser() - parser.add_option("--gui", action="store_true", default=False, help="run in gui mode") - 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("--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) + parser.add_option("--gui", action="store_true", help="run in gui mode", default=False) (options, args) = parser.parse_args() + if options.list: + print 'Possible raw devices:' + print ' ' + '\n '.join(get_raw_device_hints()) + exit() + if options.gui: root = Tkinter.Tk() root.title('USRP2 SD Card Burner') -- cgit v1.2.3 From 11059ddbd6f5301f72299933321c35d00663dfe6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 13 May 2010 17:35:09 -0700 Subject: fix to ad9777 dac control --- host/lib/ic_reg_maps/gen_ad9777_regs.py | 2 +- host/lib/usrp/usrp2/codec_ctrl.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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/usrp/usrp2/codec_ctrl.cpp b/host/lib/usrp/usrp2/codec_ctrl.cpp index d1e16881b..d698216ba 100644 --- a/host/lib/usrp/usrp2/codec_ctrl.cpp +++ b/host/lib/usrp/usrp2/codec_ctrl.cpp @@ -39,8 +39,8 @@ public: _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; + _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; -- cgit v1.2.3 From abf2bc77f1880e34e206bd299fa0170f1bf9fe1d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 13 May 2010 18:23:19 -0700 Subject: memcpy data when in custom io type --- host/lib/transport/convert_types.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/host/lib/transport/convert_types.cpp b/host/lib/transport/convert_types.cpp index 8c3d6b17a..510d39454 100644 --- a/host/lib/transport/convert_types.cpp +++ b/host/lib/transport/convert_types.cpp @@ -115,10 +115,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 +138,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)); } -- cgit v1.2.3 From ce0a3da138f5de23f0647d991fd4a1dfaef17286 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 14 May 2010 12:32:40 -0700 Subject: card burner notes --- host/docs/usrp2.rst | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index e8901b839..4731b73cf 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -48,14 +48,26 @@ Load the images onto the SD card 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. -Use the card burner tool (linux): +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 not yet been implemented on macosx. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Use the card burner tool (unix) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: + sudo /share/uhd/utils/usrp2_card_burner.py --gui + + -- OR -- + cd /share/uhd/utils sudo ./usrp2_card_burner.py --dev=/dev/sd --fpga= sudo ./usrp2_card_burner.py --dev=/dev/sd --fw= -Use the card burner tool (windows): +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Use the card burner tool (windows) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: /share/uhd/utils/usrp2_card_burner.py --gui -- cgit v1.2.3 From 695dd535d5a7419f467598a90c51c7e0f3d611e5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 14 May 2010 13:02:04 -0700 Subject: added set freq with lo offset to simple usrp wrapper --- host/include/uhd/usrp/simple_usrp.hpp | 2 ++ host/lib/usrp/simple_usrp.cpp | 8 ++++++++ 2 files changed, 10 insertions(+) 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/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(); } @@ -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(); } -- cgit v1.2.3 From d20595a3fe9ba864d824c160c3db39fc7a3d1e7c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 17 May 2010 09:52:43 -0700 Subject: calculate max samples per packet using otw type --- host/lib/usrp/usrp2/io_impl.cpp | 23 +++++++++++++++-------- host/lib/usrp/usrp2/mboard_impl.cpp | 2 +- host/lib/usrp/usrp2/usrp2_impl.cpp | 4 ++-- host/lib/usrp/usrp2/usrp2_impl.hpp | 27 +++++++++++++++++++-------- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 7c9d003ce..de0c76eb1 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -31,10 +31,16 @@ 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; + + //setup tx otw type + _tx_otw_type.width = 16; + _tx_otw_type.shift = 0; + _tx_otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN; + //initially empty copy buffer _rx_copy_buff = asio::buffer("", 0); @@ -49,7 +55,8 @@ void usrp2_impl::io_init(void){ send_buff->done(sizeof(data)); //setup RX DSP regs - _iface->poke32(FR_RX_CTRL_NSAMPS_PER_PKT, _max_rx_samples_per_packet); + std::cout << "RX samples per packet: " << max_rx_samps_per_packet() << std::endl; + _iface->poke32(FR_RX_CTRL_NSAMPS_PER_PKT, max_rx_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 @@ -121,7 +128,7 @@ size_t usrp2_impl::send( boost::uint32_t *tx_mem = send_buff->cast(); size_t num_samps = std::min(std::min( asio::buffer_size(buff)/io_type.size, - size_t(_max_tx_samples_per_packet)), + size_t(max_tx_samps_per_packet())), send_buff->size()/io_type.size ); @@ -148,7 +155,7 @@ size_t usrp2_impl::send( //copy-convert the samples into the send buffer convert_io_type_to_otw_type( asio::buffer_cast(buff), io_type, - (void*)items, _otw_type, + (void*)items, _tx_otw_type, num_samps ); @@ -192,7 +199,7 @@ size_t usrp2_impl::recv( //copy-convert the samples from the recv buffer convert_otw_type_to_io_type( - (const void*)items, _otw_type, + (const void*)items, _rx_otw_type, asio::buffer_cast(buff), io_type, num_samps ); diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 9ae68d158..a10529102 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -111,7 +111,7 @@ void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ //issue the stream command _iface->poke32(FR_RX_CTRL_STREAM_CMD, FR_RX_CTRL_MAKE_CMD( - (inst_samps)? stream_cmd.num_samps : ((inst_chain)? _max_rx_samples_per_packet : 1), + (inst_samps)? stream_cmd.num_samps : ((inst_chain)? max_rx_samps_per_packet() : 1), (stream_cmd.stream_now)? 1 : 0, (inst_chain)? 1 : 0, (inst_reload)? 1 : 0 diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 2b7bdeea2..3b7156802 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -211,11 +211,11 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){ return; case DEVICE_PROP_MAX_RX_SAMPLES: - val = size_t(_max_rx_samples_per_packet); + val = max_rx_samps_per_packet(); return; case DEVICE_PROP_MAX_TX_SAMPLES: - val = size_t(_max_tx_samples_per_packet); + val = max_tx_samps_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 c5b6af810..e2d37e512 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -125,21 +125,32 @@ private: void recv_raw(uhd::rx_metadata_t &); uhd::dict _tx_stream_id_to_packet_seq; uhd::dict _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) ; + size_t max_rx_samps_per_packet(void){ + return _max_rx_bytes_per_packet/(_rx_otw_type.width*2/8); + } + size_t max_tx_samps_per_packet(void){ + return _max_tx_bytes_per_packet/(_tx_otw_type.width*2/8); + } + 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; + uhd::otw_type_t _rx_otw_type, _tx_otw_type; void io_init(void); //udp transports for control and data -- cgit v1.2.3 From 7823e08855f1fe48fbc014c37f822a9f22de19ef Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 17 May 2010 10:12:16 -0700 Subject: simplification of udp asio socket stuff --- host/include/uhd/transport/zero_copy.hpp | 12 ++--- host/lib/transport/udp_zero_copy_asio.cpp | 75 +++++++++++++++---------------- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp index 4fc1df9de..fdc5b141c 100644 --- a/host/include/uhd/transport/zero_copy.hpp +++ b/host/include/uhd/transport/zero_copy.hpp @@ -45,7 +45,7 @@ public: * 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 +53,7 @@ public: * Get a pointer to the underlying buffer. * \return a pointer into memory */ - template T cast(void){ + template T cast(void) const{ return boost::asio::buffer_cast(this->get()); } @@ -63,7 +63,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; }; /*! @@ -87,7 +87,7 @@ public: * 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 +95,7 @@ public: * Get a pointer to the underlying buffer. * \return a pointer into memory */ - template T cast(void){ + template T cast(void) const{ return boost::asio::buffer_cast(this->get()); } @@ -105,7 +105,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/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index ee44803f4..c26b39867 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -16,9 +16,9 @@ // #include +#include #include #include -#include #include #include @@ -26,65 +26,56 @@ using namespace uhd::transport; /*********************************************************************** * 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(); + /* NOP */ } void done(void){ - _done = true; - delete [] boost::asio::buffer_cast(_buff); + /* NOP */ } 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(_buff); - _socket->send(boost::asio::buffer(mem, num_bytes)); - delete [] mem; + _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; }; /*********************************************************************** @@ -94,6 +85,8 @@ private: * However, it is not a true zero copy implementation as each * send and recv requires a copy operation to/from userspace. **********************************************************************/ +static const size_t max_buff_size = 2000; //assume max size on send and recv + class udp_zero_copy_impl : public udp_zero_copy{ public: //structors @@ -121,6 +114,11 @@ public: 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[max_buff_size], _recv_mem[max_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 +129,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, max_buff_size), _socket + )); + + // set recv timeout + timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 100*1000; //100 ms + UHD_ASSERT_THROW(setsockopt( + _socket->native(), + SOL_SOCKET, SO_RCVTIMEO, + (timeval *)&tv, sizeof(timeval) + ) == 0); } udp_zero_copy_impl::~udp_zero_copy_impl(void){ @@ -142,31 +155,17 @@ 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)); - } - - //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, max_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; } /*********************************************************************** -- cgit v1.2.3 From 7facfba666046f305086f754c9cebe1406ea54ad Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 17 May 2010 10:22:14 -0700 Subject: windows fix for setsockopt --- host/lib/transport/udp_zero_copy_asio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index c26b39867..e97bbf31c 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -146,7 +146,7 @@ udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::strin UHD_ASSERT_THROW(setsockopt( _socket->native(), SOL_SOCKET, SO_RCVTIMEO, - (timeval *)&tv, sizeof(timeval) + (const char *)&tv, sizeof(timeval) ) == 0); } -- cgit v1.2.3 From a6f7b02ae69eb4b0755f2805922eeb06d977c1ee Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 17 May 2010 11:01:42 -0700 Subject: automatic resize for small udp buffers --- host/lib/transport/udp_zero_copy_asio.cpp | 61 ++++++++++++++++++------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index e97bbf31c..56ba391d3 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -89,6 +89,8 @@ static const size_t max_buff_size = 2000; //assume max size on send and recv class udp_zero_copy_impl : public udp_zero_copy{ public: + typedef boost::shared_ptr sptr; + //structors udp_zero_copy_impl(const std::string &addr, const std::string &port); ~udp_zero_copy_impl(void); @@ -97,18 +99,17 @@ 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 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 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(); } private: @@ -171,31 +172,39 @@ managed_send_buffer::sptr udp_zero_copy_impl::get_send_buff(void){ /*********************************************************************** * UDP zero copy make function **********************************************************************/ +template static inline void resize_buff_helper( + udp_zero_copy_impl::sptr udp_trans, + size_t target_size, + const std::string &name +){ + static const size_t min_buff_size = size_t(100e3); + + //resize the buffer if size was provided + if (target_size > 0){ + size_t actual_size = udp_trans->resize_buff(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() < min_buff_size){ + resize_buff_helper(udp_trans, min_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_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(udp_trans, recv_buff_size, "recv"); + resize_buff_helper (udp_trans, send_buff_size, "send"); return udp_trans; } -- cgit v1.2.3 From d9cc352ed14dbab04523f53e21f855b05c30eb3f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 17 May 2010 13:22:26 -0700 Subject: work on generic packet handler (got rx working) --- host/lib/transport/vrt_packet_handler.hpp | 161 ++++++++++++++++++++++++++++++ host/lib/usrp/usrp2/io_impl.cpp | 95 ++---------------- host/lib/usrp/usrp2/usrp2_impl.hpp | 8 +- 3 files changed, 169 insertions(+), 95 deletions(-) create mode 100644 host/lib/transport/vrt_packet_handler.hpp diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp new file mode 100644 index 000000000..a6161ef55 --- /dev/null +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -0,0 +1,161 @@ +// +// 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 . +// + +#ifndef INCLUDED_LIBUHD_TRANSPORT_VRT_PACKET_HANDLER_HPP +#define INCLUDED_LIBUHD_TRANSPORT_VRT_PACKET_HANDLER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 recv_cb_t; + + static inline void recv_cb_nop(uhd::transport::managed_recv_buffer::sptr){ + /* NOP */ + } + + static inline size_t recv( + recv_state &state, + const boost::asio::mutable_buffer &buff, + 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, + size_t vrt_header_offset_words32 = 0, + const recv_cb_t& recv_cb = &recv_cb_nop + ){ + //////////////////////////////////////////////////////////////// + // Perform the recv + //////////////////////////////////////////////////////////////// + { + //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); + } + //otherwise flag the metadata to show that is is a fragment + else{ + metadata = uhd::rx_metadata_t(); + goto vrt_recv_copy_convert; + } + } + + //////////////////////////////////////////////////////////////// + // Unpack the vrt header + //////////////////////////////////////////////////////////////// + { + 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); + goto vrt_recv_copy_convert; //must exit here after setting the buffer + } + const boost::uint32_t *vrt_hdr = state.managed_buff->cast() + 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) + ); + } + + //////////////////////////////////////////////////////////////// + // Perform copy-convert into buffer + //////////////////////////////////////////////////////////////// + vrt_recv_copy_convert:{ + size_t bytes_per_item = (otw_type.width * 2) / 8; + + //extract the number of samples available to copy + //and a pointer into the usrp2 received items memory + size_t bytes_available = boost::asio::buffer_size(state.copy_buff); + size_t num_samps = std::min( + boost::asio::buffer_size(buff)/io_type.size, + bytes_available/bytes_per_item + ); + + //setup the fragment flags and offset + metadata.more_fragments = boost::asio::buffer_size(buff)/io_type.size < num_samps; + metadata.fragment_offset = state.fragment_offset_in_samps; + state.fragment_offset_in_samps += num_samps; //set for next time + + //copy-convert the samples from the recv buffer + uhd::transport::convert_otw_type_to_io_type( + boost::asio::buffer_cast(state.copy_buff), otw_type, + boost::asio::buffer_cast(buff), 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(state.copy_buff) + bytes_copied, + bytes_available - bytes_copied + ); + + return num_samps; + } + } + +} //namespace vrt_packet_handler + +#endif /* INCLUDED_LIBUHD_TRANSPORT_VRT_PACKET_HANDLER_HPP */ diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index de0c76eb1..389460fe8 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -41,13 +41,6 @@ void usrp2_impl::io_init(void){ _tx_otw_type.shift = 0; _tx_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; - //send a small data packet so the usrp2 knows the udp source port managed_send_buffer::sptr send_buff = _data_transport->get_send_buff(); boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER); @@ -69,51 +62,6 @@ void usrp2_impl::io_init(void){ _iface->poke32(FR_RX_CTRL_VRT_TRAILER, 0); } -/*********************************************************************** - * 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(); - 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) - ); -} - /*********************************************************************** * Send Data **********************************************************************/ @@ -172,42 +120,11 @@ size_t usrp2_impl::recv( rx_metadata_t &metadata, const io_type_t &io_type ){ - //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) - ); - const boost::uint32_t *items = asio::buffer_cast(_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, _rx_otw_type, - asio::buffer_cast(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 vrt_packet_handler::recv( + _packet_handler_recv_state, //last state of the recv handler + buff, metadata, //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 ); - - return num_samps; } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index e2d37e512..6958fc8ea 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -33,6 +33,7 @@ #include #include #include +#include "../../transport/vrt_packet_handler.hpp" /*! * Make a usrp2 dboard interface. @@ -121,10 +122,7 @@ private: 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 _tx_stream_id_to_packet_seq; - uhd::dict _rx_stream_id_to_packet_seq; /******************************************************************* * Deal with the rx and tx packet sizes @@ -147,9 +145,7 @@ private: return _max_tx_bytes_per_packet/(_tx_otw_type.width*2/8); } - uhd::transport::managed_recv_buffer::sptr _rx_smart_buff; - boost::asio::const_buffer _rx_copy_buff; - size_t _fragment_offset_in_samps; + vrt_packet_handler::recv_state _packet_handler_recv_state; uhd::otw_type_t _rx_otw_type, _tx_otw_type; void io_init(void); -- cgit v1.2.3 From 101afd526de722b6d30381340a7ca8148aa9a6d7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 17 May 2010 18:47:33 -0700 Subject: Created inline send vrt packer function that also handles fragmentation. --- host/include/uhd/device.hpp | 11 +- host/include/uhd/types/otw_type.hpp | 6 + host/lib/transport/vrt_packet_handler.hpp | 280 ++++++++++++++++++++++-------- host/lib/types.cpp | 4 + host/lib/usrp/usrp2/io_impl.cpp | 48 +---- host/lib/usrp/usrp2/usrp2_impl.hpp | 7 +- 6 files changed, 232 insertions(+), 124 deletions(-) diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index ae75e6dc8..ecbe8c95c 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -80,12 +80,11 @@ public: * 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. * * This is a blocking call and will not return until the number * of samples returned have been read out of the buffer. 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/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index a6161ef55..cd0c89b05 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -57,6 +57,49 @@ namespace vrt_packet_handler{ /* NOP */ } + /******************************************************************* + * Unpack a received vrt header and set the copy buffer. + * - helper function for vrt_packet_handler::recv + ******************************************************************/ + static inline void _recv_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() + 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 vrt packets and copy convert the samples into the buffer. + ******************************************************************/ static inline size_t recv( recv_state &state, const boost::asio::mutable_buffer &buff, @@ -65,95 +108,184 @@ namespace vrt_packet_handler{ 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 ){ - //////////////////////////////////////////////////////////////// - // Perform the recv - //////////////////////////////////////////////////////////////// - { - //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); - } - //otherwise flag the metadata to show that is is a fragment - else{ - metadata = uhd::rx_metadata_t(); - goto vrt_recv_copy_convert; - } - } + metadata = uhd::rx_metadata_t(); //init the metadata - //////////////////////////////////////////////////////////////// - // Unpack the vrt header - //////////////////////////////////////////////////////////////// - { - 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); - goto vrt_recv_copy_convert; //must exit here after setting the buffer - } - const boost::uint32_t *vrt_hdr = state.managed_buff->cast() + 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 + //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 + _recv_helper( + state, metadata, tick_rate, vrt_header_offset_words32 ); + } - //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; + //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( + boost::asio::buffer_size(buff)/io_type.size, + bytes_available/bytes_per_item + ); - //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) - ); + //setup the fragment flags and offset + metadata.more_fragments = boost::asio::buffer_size(buff)/io_type.size < 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(state.copy_buff), otw_type, + boost::asio::buffer_cast(buff), 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(state.copy_buff) + bytes_copied, + bytes_available - bytes_copied + ); + + return num_samps; + } + +/*********************************************************************** + * 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; } + }; - //////////////////////////////////////////////////////////////// - // Perform copy-convert into buffer - //////////////////////////////////////////////////////////////// - vrt_recv_copy_convert:{ - size_t bytes_per_item = (otw_type.width * 2) / 8; - - //extract the number of samples available to copy - //and a pointer into the usrp2 received items memory - size_t bytes_available = boost::asio::buffer_size(state.copy_buff); - size_t num_samps = std::min( - boost::asio::buffer_size(buff)/io_type.size, - bytes_available/bytes_per_item - ); + typedef boost::function send_cb_t; - //setup the fragment flags and offset - metadata.more_fragments = boost::asio::buffer_size(buff)/io_type.size < num_samps; - metadata.fragment_offset = state.fragment_offset_in_samps; - state.fragment_offset_in_samps += num_samps; //set for next time + static inline void send_cb_nop(uhd::transport::managed_send_buffer::sptr){ + /* NOP */ + } - //copy-convert the samples from the recv buffer - uhd::transport::convert_otw_type_to_io_type( - boost::asio::buffer_cast(state.copy_buff), otw_type, - boost::asio::buffer_cast(buff), io_type, - num_samps - ); + /******************************************************************* + * Pack a vrt header, copy-convert the data, and send it. + * - helper function for vrt_packet_handler::send + ******************************************************************/ + static inline void _send_helper( + 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() + vrt_header_offset_words32; + + size_t num_header_words32, num_packet_words32; + size_t packet_count = state.next_packet_seq++; - //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(state.copy_buff) + bytes_copied, - bytes_available - bytes_copied + //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->done(num_packet_words32*sizeof(boost::uint32_t)); + } + + /******************************************************************* + * Send vrt packets and copy convert the samples into the buffer. + ******************************************************************/ + static inline size_t send( + send_state &state, + const boost::asio::const_buffer &buff, + 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 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 + ){ + + size_t total_num_samps = boost::asio::buffer_size(buff)/io_type.size; + + //special case: no fragmentation needed + if (total_num_samps <= max_samples_per_packet){ + _send_helper( + state, + boost::asio::buffer_cast(buff), + total_num_samps, + metadata, + io_type, otw_type, + tick_rate, + zc_iface, + vrt_header_offset_words32, + send_cb ); + return total_num_samps; + } - return num_samps; + //calculate constants for fragmentation + const size_t final_packet_samps = total_num_samps%max_samples_per_packet; + 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 = md.has_time_spec and (n == first_fragment_index); + md.start_of_burst = md.start_of_burst and (n == first_fragment_index); + md.end_of_burst = md.end_of_burst and (n == final_fragment_index); + + //send the fragment with the helper function + _send_helper( + state, + boost::asio::buffer_cast(buff) + (n*max_samples_per_packet*io_type.size), + (n == final_fragment_index)?final_packet_samps:max_samples_per_packet, + md, + io_type, otw_type, + tick_rate, + zc_iface, + vrt_header_offset_words32, + send_cb + ); } + + return total_num_samps; } } //namespace vrt_packet_handler diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 33eb550a1..87a2ad4ab 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -220,6 +220,10 @@ std::string mac_addr_t::to_string(void) const{ /*********************************************************************** * otw type **********************************************************************/ +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; diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 389460fe8..b26dbb8bd 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -67,49 +67,17 @@ void usrp2_impl::io_init(void){ **********************************************************************/ size_t usrp2_impl::send( const asio::const_buffer &buff, - const tx_metadata_t &metadata_, + const tx_metadata_t &metadata, const io_type_t &io_type ){ - 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(); - size_t num_samps = std::min(std::min( - asio::buffer_size(buff)/io_type.size, - size_t(max_tx_samps_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(buff), io_type, - (void*)items, _tx_otw_type, - num_samps + return vrt_packet_handler::send( + _packet_handler_send_state, //last state of the send handler + buff, metadata, //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 + max_tx_samps_per_packet() ); - - //send and return number of samples - send_buff->done(num_packet_words32*sizeof(boost::uint32_t)); - return num_samps; } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 6958fc8ea..f98aa1938 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -122,8 +122,6 @@ private: codec_ctrl::sptr _codec_ctrl; serdes_ctrl::sptr _serdes_ctrl; - uhd::dict _tx_stream_id_to_packet_seq; - /******************************************************************* * Deal with the rx and tx packet sizes ******************************************************************/ @@ -139,13 +137,14 @@ private: uhd::transport::vrt::max_header_words32*sizeof(boost::uint32_t) ; size_t max_rx_samps_per_packet(void){ - return _max_rx_bytes_per_packet/(_rx_otw_type.width*2/8); + return _max_rx_bytes_per_packet/_rx_otw_type.get_sample_size(); } size_t max_tx_samps_per_packet(void){ - return _max_tx_bytes_per_packet/(_tx_otw_type.width*2/8); + return _max_tx_bytes_per_packet/_tx_otw_type.get_sample_size(); } 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); -- cgit v1.2.3 From 18f3f257145c4dcd981182221779550a7474488a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 17 May 2010 22:24:14 -0700 Subject: Created config macro to force inline. --- host/CMakeLists.txt | 1 + host/include/uhd/config.hpp | 9 +++++++++ host/lib/transport/CMakeLists.txt | 1 + host/lib/transport/vrt_packet_handler.hpp | 13 +++++++------ 4 files changed, 18 insertions(+), 6 deletions(-) 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/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/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/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index cd0c89b05..f6353ef99 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -18,6 +18,7 @@ #ifndef INCLUDED_LIBUHD_TRANSPORT_VRT_PACKET_HANDLER_HPP #define INCLUDED_LIBUHD_TRANSPORT_VRT_PACKET_HANDLER_HPP +#include #include #include #include @@ -53,7 +54,7 @@ namespace vrt_packet_handler{ typedef boost::function recv_cb_t; - static inline void recv_cb_nop(uhd::transport::managed_recv_buffer::sptr){ + static UHD_INLINE void recv_cb_nop(uhd::transport::managed_recv_buffer::sptr){ /* NOP */ } @@ -61,7 +62,7 @@ namespace vrt_packet_handler{ * Unpack a received vrt header and set the copy buffer. * - helper function for vrt_packet_handler::recv ******************************************************************/ - static inline void _recv_helper( + static UHD_INLINE void _recv_helper( recv_state &state, uhd::rx_metadata_t &metadata, double tick_rate, @@ -100,7 +101,7 @@ namespace vrt_packet_handler{ /******************************************************************* * Recv vrt packets and copy convert the samples into the buffer. ******************************************************************/ - static inline size_t recv( + static UHD_INLINE size_t recv( recv_state &state, const boost::asio::mutable_buffer &buff, uhd::rx_metadata_t &metadata, @@ -168,7 +169,7 @@ namespace vrt_packet_handler{ typedef boost::function send_cb_t; - static inline void send_cb_nop(uhd::transport::managed_send_buffer::sptr){ + static UHD_INLINE void send_cb_nop(uhd::transport::managed_send_buffer::sptr){ /* NOP */ } @@ -176,7 +177,7 @@ namespace vrt_packet_handler{ * Pack a vrt header, copy-convert the data, and send it. * - helper function for vrt_packet_handler::send ******************************************************************/ - static inline void _send_helper( + static UHD_INLINE void _send_helper( send_state &state, const void *send_mem, size_t num_samps, @@ -222,7 +223,7 @@ namespace vrt_packet_handler{ /******************************************************************* * Send vrt packets and copy convert the samples into the buffer. ******************************************************************/ - static inline size_t send( + static UHD_INLINE size_t send( send_state &state, const boost::asio::const_buffer &buff, const uhd::tx_metadata_t &metadata, -- cgit v1.2.3 From 527630cc9d51b17c7cf5ab6ca257a78a28284f6d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 17 May 2010 23:23:58 -0700 Subject: use static init lists for the types, some speedup for the fast path related ones, other changes are pointless --- host/include/uhd/types/mac_addr.hpp | 2 +- host/lib/types.cpp | 115 +++++++++++++++++++++--------------- 2 files changed, 68 insertions(+), 49 deletions(-) diff --git a/host/include/uhd/types/mac_addr.hpp b/host/include/uhd/types/mac_addr.hpp index 034b6a348..0ced2e734 100644 --- a/host/include/uhd/types/mac_addr.hpp +++ b/host/include/uhd/types/mac_addr.hpp @@ -58,7 +58,7 @@ namespace uhd{ private: mac_addr_t(const byte_vector_t &bytes); //private constructor - byte_vector_t _bytes; //internal representation + const byte_vector_t _bytes; //internal representation }; } //namespace uhd diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 87a2ad4ab..daf3be7f7 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -42,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{ @@ -165,9 +181,8 @@ std::string device_addr_t::to_string(void) const{ /*********************************************************************** * mac addr **********************************************************************/ -mac_addr_t::mac_addr_t(const byte_vector_t &bytes){ - UHD_ASSERT_THROW(bytes.size() == 6); - _bytes = 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 byte_vector_t &bytes){ @@ -224,10 +239,12 @@ 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; +otw_type_t::otw_type_t(void): + width(0), + shift(0), + byteorder(BO_NATIVE) +{ + /* NOP */ } /*********************************************************************** @@ -255,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( -- cgit v1.2.3 From 7c98884eda041b676584059ca3a63b11f1bbd505 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 18 May 2010 10:28:37 -0700 Subject: burn sd card fix, units for seek and skip in blocks not bytes --- host/utils/usrp2_card_burner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py index a1d4c5ed1..dfdc663bc 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -118,7 +118,7 @@ def verify_image(image_file, device_file, offset): get_dd_path(), "of=%s"%tmp_file, "if=%s"%device_file, - "skip=%d"%offset, + "skip=%d"%(offset/SECTOR_SIZE), "bs=%d"%SECTOR_SIZE, "count=%d"%(MAX_FILE_SIZE/SECTOR_SIZE), ) @@ -136,7 +136,7 @@ def write_image(image_file, device_file, offset): get_dd_path(), "if=%s"%image_file, "of=%s"%device_file, - "seek=%d"%offset, + "seek=%d"%(offset/SECTOR_SIZE), "bs=%d"%SECTOR_SIZE, ) -- cgit v1.2.3 From eaa1508dcf6ff32496838f593ba4eb9eb1aee2ff Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 18 May 2010 12:34:04 -0700 Subject: Added send and recv modes to the device class and packet handler implementation. --- host/include/uhd/device.hpp | 33 +++++- host/lib/transport/vrt_packet_handler.hpp | 178 ++++++++++++++++++++---------- host/lib/usrp/usrp2/io_impl.cpp | 10 +- host/lib/usrp/usrp2/usrp2_impl.hpp | 14 ++- 4 files changed, 170 insertions(+), 65 deletions(-) diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index ecbe8c95c..a76b34ee2 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -76,6 +76,16 @@ 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 + }; + /*! * Send a buffer containing IF data with its metadata. * @@ -85,6 +95,7 @@ public: * 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. @@ -92,14 +103,26 @@ 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 = SEND_MODE_ONE_PACKET ) = 0; + /*! + * 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 + }; + /*! * Receive a buffer containing IF data and its metadata. * @@ -122,15 +145,21 @@ 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 = RECV_MODE_ONE_PACKET ) = 0; }; diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index f6353ef99..c857db1c4 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -19,6 +19,7 @@ #define INCLUDED_LIBUHD_TRANSPORT_VRT_PACKET_HANDLER_HPP #include +#include #include #include #include @@ -60,9 +61,9 @@ namespace vrt_packet_handler{ /******************************************************************* * Unpack a received vrt header and set the copy buffer. - * - helper function for vrt_packet_handler::recv + * - helper function for vrt_packet_handler::_recv1 ******************************************************************/ - static UHD_INLINE void _recv_helper( + static UHD_INLINE void _recv1_helper( recv_state &state, uhd::rx_metadata_t &metadata, double tick_rate, @@ -99,28 +100,28 @@ namespace vrt_packet_handler{ } /******************************************************************* - * Recv vrt packets and copy convert the samples into the buffer. + * Recv data, unpack a vrt header, and copy-convert the data. + * - helper function for vrt_packet_handler::recv ******************************************************************/ - static UHD_INLINE size_t recv( + static UHD_INLINE size_t _recv1( recv_state &state, - const boost::asio::mutable_buffer &buff, + 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 = 0, - const recv_cb_t& recv_cb = &recv_cb_nop + size_t vrt_header_offset_words32, + const recv_cb_t& recv_cb ){ - metadata = uhd::rx_metadata_t(); //init the metadata - //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 - _recv_helper( + _recv1_helper( state, metadata, tick_rate, vrt_header_offset_words32 ); } @@ -128,21 +129,17 @@ namespace vrt_packet_handler{ //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( - boost::asio::buffer_size(buff)/io_type.size, - bytes_available/bytes_per_item - ); + size_t num_samps = std::min(total_samps, bytes_available/bytes_per_item); //setup the fragment flags and offset - metadata.more_fragments = boost::asio::buffer_size(buff)/io_type.size < num_samps; + 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(state.copy_buff), otw_type, - boost::asio::buffer_cast(buff), io_type, - num_samps + recv_mem, io_type, num_samps ); //update the rx copy buffer to reflect the bytes copied @@ -155,6 +152,66 @@ namespace vrt_packet_handler{ 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(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 num_samps = 0; + uhd::rx_metadata_t tmp_md; + while(num_samps < total_num_samps){ + num_samps += _recv1( + state, + boost::asio::buffer_cast(buff) + (num_samps*io_type.size), + total_num_samps - num_samps, + (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 + ); + } + return total_num_samps; + } + }//switch(recv_mode) + } + /*********************************************************************** * vrt packet handler for send **********************************************************************/ @@ -177,7 +234,7 @@ namespace vrt_packet_handler{ * Pack a vrt header, copy-convert the data, and send it. * - helper function for vrt_packet_handler::send ******************************************************************/ - static UHD_INLINE void _send_helper( + static UHD_INLINE void _send1( send_state &state, const void *send_mem, size_t num_samps, @@ -227,6 +284,7 @@ namespace vrt_packet_handler{ 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, @@ -236,15 +294,17 @@ namespace vrt_packet_handler{ size_t vrt_header_offset_words32 = 0, const send_cb_t& send_cb = &send_cb_nop ){ - - size_t total_num_samps = boost::asio::buffer_size(buff)/io_type.size; - - //special case: no fragmentation needed - if (total_num_samps <= max_samples_per_packet){ - _send_helper( + const size_t total_num_samps = boost::asio::buffer_size(buff)/io_type.size; + 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(buff), - total_num_samps, + num_samps, metadata, io_type, otw_type, tick_rate, @@ -252,41 +312,45 @@ namespace vrt_packet_handler{ vrt_header_offset_words32, send_cb ); - return total_num_samps; + return num_samps; } - //calculate constants for fragmentation - const size_t final_packet_samps = total_num_samps%max_samples_per_packet; - 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 = md.has_time_spec and (n == first_fragment_index); - md.start_of_burst = md.start_of_burst and (n == first_fragment_index); - md.end_of_burst = md.end_of_burst and (n == final_fragment_index); - - //send the fragment with the helper function - _send_helper( - state, - boost::asio::buffer_cast(buff) + (n*max_samples_per_packet*io_type.size), - (n == final_fragment_index)?final_packet_samps:max_samples_per_packet, - md, - io_type, otw_type, - tick_rate, - zc_iface, - vrt_header_offset_words32, - send_cb - ); + //////////////////////////////////////////////////////////////// + case uhd::device::SEND_MODE_FULL_BUFF:{ + //////////////////////////////////////////////////////////////// + //calculate constants for fragmentation + const size_t final_packet_samps = total_num_samps%max_samples_per_packet; + 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 = md.has_time_spec and (n == first_fragment_index); + md.start_of_burst = md.start_of_burst and (n == first_fragment_index); + md.end_of_burst = md.end_of_burst and (n == final_fragment_index); + + //send the fragment with the helper function + _send1( + state, + boost::asio::buffer_cast(buff) + (n*max_samples_per_packet*io_type.size), + (n == final_fragment_index)?final_packet_samps:max_samples_per_packet, + md, + io_type, otw_type, + tick_rate, + zc_iface, + vrt_header_offset_words32, + send_cb + ); + } + return total_num_samps; } - - return total_num_samps; + }//switch(send_mode) } } //namespace vrt_packet_handler diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index b26dbb8bd..485cc2bd9 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -68,11 +68,12 @@ void usrp2_impl::io_init(void){ size_t usrp2_impl::send( const 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 ){ return vrt_packet_handler::send( _packet_handler_send_state, //last state of the send handler - buff, metadata, //buffer to empty and samples metadata + 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 @@ -86,11 +87,12 @@ 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 ){ return vrt_packet_handler::recv( _packet_handler_recv_state, //last state of the recv handler - buff, metadata, //buffer to fill and samples metadata + 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 diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index f98aa1938..ad674f594 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -104,8 +104,18 @@ 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 send( + const boost::asio::const_buffer &, + const uhd::tx_metadata_t &, + const uhd::io_type_t &, + uhd::device::send_mode_t + ); + 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){ -- cgit v1.2.3 From 17c494b79a99d947a150cdbc582ba331aeb57786 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 18 May 2010 14:26:43 -0700 Subject: Added tx timed samples example. Added called to device to get max samples per packet. Removed device props that gave max samples per packet. --- host/examples/CMakeLists.txt | 4 ++ host/examples/rx_timed_samples.cpp | 13 +++-- host/examples/tx_timed_samples.cpp | 92 ++++++++++++++++++++++++++++++++++ host/include/uhd/device.hpp | 33 ++++++++---- host/include/uhd/usrp/device_props.hpp | 4 +- host/lib/usrp/usrp2/io_impl.cpp | 6 +-- host/lib/usrp/usrp2/mboard_impl.cpp | 2 +- host/lib/usrp/usrp2/usrp2_impl.cpp | 8 --- host/lib/usrp/usrp2/usrp2_impl.hpp | 12 ++--- 9 files changed, 138 insertions(+), 36 deletions(-) create mode 100644 host/examples/tx_timed_samples.cpp 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..d2306c7c4 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(&seconds_in_future)->default_value(3), "number of seconds in the future to receive") ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to receive") ("rxrate", po::value(&rx_rate)->default_value(100e6/16), "rate of incoming samples") + ("freq", po::value(&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,10 +80,11 @@ 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 buff[1000]; + std::vector > 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) continue; //wait for packets with contents diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp new file mode 100644 index 000000000..6dee69cd5 --- /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 . +// + +#include +#include +#include +#include +#include +#include + +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(&args)->default_value(""), "simple uhd device address args") + ("secs", po::value(&seconds_in_future)->default_value(3), "number of seconds in the future to transmit") + ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to transmit") + ("txrate", po::value(&tx_rate)->default_value(100e6/16), "rate of outgoing samples") + ("freq", po::value(&freq)->default_value(0), "rf center frequency in Hz") + ("ampl", po::value(&l)->default_value(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 > buff(total_num_samps, std::complex(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/device.hpp b/host/include/uhd/device.hpp index a76b34ee2..27b461184 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -86,6 +86,16 @@ public: 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. * @@ -113,16 +123,6 @@ public: send_mode_t send_mode = SEND_MODE_ONE_PACKET ) = 0; - /*! - * 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 - }; - /*! * Receive a buffer containing IF data and its metadata. * @@ -161,6 +161,19 @@ public: const io_type_t &io_type, recv_mode_t recv_mode = RECV_MODE_ONE_PACKET ) = 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/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/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 485cc2bd9..b6ab919e7 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -48,8 +48,8 @@ void usrp2_impl::io_init(void){ send_buff->done(sizeof(data)); //setup RX DSP regs - std::cout << "RX samples per packet: " << max_rx_samps_per_packet() << std::endl; - _iface->poke32(FR_RX_CTRL_NSAMPS_PER_PKT, max_rx_samps_per_packet()); + 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 @@ -77,7 +77,7 @@ size_t usrp2_impl::send( io_type, _tx_otw_type, //input and output types to convert get_master_clock_freq(), //master clock tick rate _data_transport, //zero copy interface - max_tx_samps_per_packet() + get_max_send_samps_per_packet() ); } diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index a10529102..f17efd88e 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -111,7 +111,7 @@ void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ //issue the stream command _iface->poke32(FR_RX_CTRL_STREAM_CMD, FR_RX_CTRL_MAKE_CMD( - (inst_samps)? stream_cmd.num_samps : ((inst_chain)? max_rx_samps_per_packet() : 1), + (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 diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 3b7156802..af3ec216a 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -210,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 = max_rx_samps_per_packet(); - return; - - case DEVICE_PROP_MAX_TX_SAMPLES: - val = max_tx_samps_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 ad674f594..afea9683c 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -104,12 +104,18 @@ public: ~usrp2_impl(void); //the io interface + 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 &, @@ -146,12 +152,6 @@ private: _mtu - _hdrs - uhd::transport::vrt::max_header_words32*sizeof(boost::uint32_t) ; - size_t max_rx_samps_per_packet(void){ - return _max_rx_bytes_per_packet/_rx_otw_type.get_sample_size(); - } - size_t max_tx_samps_per_packet(void){ - return _max_tx_bytes_per_packet/_tx_otw_type.get_sample_size(); - } vrt_packet_handler::recv_state _packet_handler_recv_state; vrt_packet_handler::send_state _packet_handler_send_state; -- cgit v1.2.3 From 4ea8822a50073b01ede9e0b0f7c8c713767ea1b8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 18 May 2010 17:38:49 -0700 Subject: clock bypass divider fixes, forgot to move this part into the host --- host/lib/usrp/usrp2/clock_ctrl.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp index db8d8a886..4c5207203 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.cpp +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -79,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(); } @@ -88,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(); } @@ -130,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(); } @@ -139,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(); } -- cgit v1.2.3 From bea1c582491d71bf90e240be345a32ba77028460 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 18 May 2010 18:03:27 -0700 Subject: tweaks to remove warning is msvc --- host/examples/tx_timed_samples.cpp | 2 +- host/lib/transport/vrt_packet_handler.hpp | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index 6dee69cd5..e9e0c785e 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -41,7 +41,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to transmit") ("txrate", po::value(&tx_rate)->default_value(100e6/16), "rate of outgoing samples") ("freq", po::value(&freq)->default_value(0), "rf center frequency in Hz") - ("ampl", po::value(&l)->default_value(0.3), "amplitude of each sample") + ("ampl", po::value(&l)->default_value(float(0.3)), "amplitude of each sample") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index c857db1c4..5b73c82bf 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include namespace vrt_packet_handler{ @@ -209,6 +210,8 @@ namespace vrt_packet_handler{ } return total_num_samps; } + + default: throw std::runtime_error("unknown recv mode"); }//switch(recv_mode) } @@ -350,6 +353,8 @@ namespace vrt_packet_handler{ } return total_num_samps; } + + default: throw std::runtime_error("unknown send mode"); }//switch(send_mode) } -- cgit v1.2.3 From 5aac700bc675c913b75b5fd791d9cf92949ceeea Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 18 May 2010 18:27:49 -0700 Subject: init values in dboards to remove gcc warnings --- host/lib/usrp/dboard/db_rfx.cpp | 4 ++-- host/lib/usrp/dboard/db_wbx.cpp | 2 +- host/lib/usrp/usrp2/CMakeLists.txt | 6 ++++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index bbc9716b1..3b3b96fad 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -258,8 +258,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, diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index 2a8a3a9f2..81edf7a11 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -303,7 +303,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/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt index fee67dff9..99d0b8bdd 100644 --- a/host/lib/usrp/usrp2/CMakeLists.txt +++ b/host/lib/usrp/usrp2/CMakeLists.txt @@ -19,13 +19,19 @@ LIBUHD_APPEND_SOURCES( ${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 ) -- cgit v1.2.3 From dd3850559fcc4fd91d83c787b12b3428cca6e296 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 19 May 2010 11:46:02 -0700 Subject: dont default the mode parameter, that is only asking for trouble --- host/include/uhd/device.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 27b461184..d3e9015c4 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -120,7 +120,7 @@ public: const boost::asio::const_buffer &buff, const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode = SEND_MODE_ONE_PACKET + send_mode_t send_mode ) = 0; /*! @@ -159,7 +159,7 @@ public: const boost::asio::mutable_buffer &buff, rx_metadata_t &metadata, const io_type_t &io_type, - recv_mode_t recv_mode = RECV_MODE_ONE_PACKET + recv_mode_t recv_mode ) = 0; /*! -- cgit v1.2.3 From fd28cd7056867ec1ab81f7fb408c382e110ddaa1 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 19 May 2010 11:56:50 -0700 Subject: break recv loop on timeout --- host/lib/transport/vrt_packet_handler.hpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 5b73c82bf..ab1b7e16c 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -193,22 +193,24 @@ namespace vrt_packet_handler{ //////////////////////////////////////////////////////////////// case uhd::device::RECV_MODE_FULL_BUFF:{ //////////////////////////////////////////////////////////////// - size_t num_samps = 0; + size_t accum_num_samps = 0; uhd::rx_metadata_t tmp_md; - while(num_samps < total_num_samps){ - num_samps += _recv1( + while(accum_num_samps < total_num_samps){ + size_t num_samps = _recv1( state, boost::asio::buffer_cast(buff) + (num_samps*io_type.size), total_num_samps - num_samps, - (num_samps == 0)? metadata : tmp_md, //only the first metadata gets kept + (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 total_num_samps; + return accum_num_samps; } default: throw std::runtime_error("unknown recv mode"); -- cgit v1.2.3 From b46c5abe79dcd70cd21f7dce56f29e962237d6c9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 19 May 2010 15:09:31 -0700 Subject: Fixed some bugs in the send and recv full buffer modes. Dealing with samples counts, metadata flags, etc.. --- host/lib/transport/convert_types.cpp | 9 +++++---- host/lib/transport/vrt_packet_handler.hpp | 14 +++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/host/lib/transport/convert_types.cpp b/host/lib/transport/convert_types.cpp index 510d39454..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 . // +#include #include #include #include //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 diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index ab1b7e16c..2a7f995a1 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -198,8 +198,8 @@ namespace vrt_packet_handler{ while(accum_num_samps < total_num_samps){ size_t num_samps = _recv1( state, - boost::asio::buffer_cast(buff) + (num_samps*io_type.size), - total_num_samps - num_samps, + boost::asio::buffer_cast(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, @@ -300,6 +300,7 @@ namespace vrt_packet_handler{ 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){ //////////////////////////////////////////////////////////////// @@ -324,7 +325,6 @@ namespace vrt_packet_handler{ case uhd::device::SEND_MODE_FULL_BUFF:{ //////////////////////////////////////////////////////////////// //calculate constants for fragmentation - const size_t final_packet_samps = total_num_samps%max_samples_per_packet; 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; @@ -336,15 +336,15 @@ namespace vrt_packet_handler{ for (size_t n = first_fragment_index; n <= final_fragment_index; n++){ //calculate new flags for the fragments - md.has_time_spec = md.has_time_spec and (n == first_fragment_index); - md.start_of_burst = md.start_of_burst and (n == first_fragment_index); - md.end_of_burst = md.end_of_burst and (n == final_fragment_index); + 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(buff) + (n*max_samples_per_packet*io_type.size), - (n == final_fragment_index)?final_packet_samps:max_samples_per_packet, + (n == final_fragment_index)?(total_num_samps%max_samples_per_packet):max_samples_per_packet, md, io_type, otw_type, tick_rate, -- cgit v1.2.3 From fb000993e185a182386101a8bafd880d7c4b2bf0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 19 May 2010 16:23:31 -0700 Subject: rfx dboard code minor refactor to look more like xcvr2450 code --- host/lib/usrp/dboard/db_rfx.cpp | 116 +++++++++++++++++++++++++--------------- 1 file changed, 73 insertions(+), 43 deletions(-) diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 3b3b96fad..7bfd14943 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 . // -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 rfx_tx_gain_ranges; //empty + +static const uhd::dict 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); /*! @@ -189,19 +204,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 +220,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(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(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( @@ -364,12 +400,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 +420,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 +456,15 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ switch(key.as()){ case SUBDEV_PROP_FREQ: - set_rx_lo_freq(val.as()); + this->set_rx_lo_freq(val.as()); return; case SUBDEV_PROP_GAIN: - UHD_ASSERT_THROW(name == "PGA0"); - set_rx_pga0_gain(val.as()); + this->set_rx_gain(val.as(), name); return; case SUBDEV_PROP_ANTENNA: - set_rx_ant(val.as()); + this->set_rx_ant(val.as()); return; default: UHD_THROW_PROP_SET_ERROR(); @@ -456,15 +489,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 +511,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 +546,15 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ switch(key.as()){ case SUBDEV_PROP_FREQ: - set_tx_lo_freq(val.as()); + this->set_tx_lo_freq(val.as()); return; case SUBDEV_PROP_GAIN: - //no gains to set! + this->set_tx_gain(val.as(), name); return; case SUBDEV_PROP_ANTENNA: - //its always set to tx/rx, so we only allow this value - UHD_ASSERT_THROW(val.as() == "TX/RX"); + this->set_tx_ant(val.as()); return; default: UHD_THROW_PROP_SET_ERROR(); -- cgit v1.2.3 From a0bdd2d25aee9934c4457eb5f05341927438fb1e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 20 May 2010 14:39:55 -0700 Subject: split the card burner into two python apps, one command line app with implementation, and the other a gui only app, updated docs as well --- host/docs/usrp2.rst | 4 +- host/utils/CMakeLists.txt | 1 + host/utils/usrp2_card_burner.py | 181 +++++------------------------------- host/utils/usrp2_card_burner_gui.py | 169 +++++++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 160 deletions(-) create mode 100755 host/utils/usrp2_card_burner_gui.py diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index 4731b73cf..c4a7aa64f 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -57,7 +57,7 @@ Use the card burner tool (unix) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: - sudo /share/uhd/utils/usrp2_card_burner.py --gui + sudo /share/uhd/utils/usrp2_card_burner_gui.py -- OR -- @@ -70,7 +70,7 @@ Use the card burner tool (windows) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: - /share/uhd/utils/usrp2_card_burner.py --gui + /share/uhd/utils/usrp2_card_burner_gui.py ------------------------------------------------------------------------ diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index d28576e8c..69a013a28 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -30,5 +30,6 @@ INSTALL(TARGETS uhd_burn_db_eeprom RUNTIME 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_card_burner.py b/host/utils/usrp2_card_burner.py index dfdc663bc..59d0b3231 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -16,14 +16,16 @@ # along with this program. If not, see . # -######################################################################## -# Deal with raw devices -######################################################################## import platform import tempfile import subprocess import urllib +import optparse +import os +######################################################################## +# constants +######################################################################## SECTOR_SIZE = 512 # bytes MAX_FILE_SIZE = 1 * (2**20) # maximum number of bytes we'll burn to a slot @@ -32,6 +34,9 @@ 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, @@ -53,6 +58,9 @@ def get_dd_path(): return dd_path return 'dd' +######################################################################## +# list possible devices +######################################################################## def get_raw_device_hints(): #################################################################### # Platform Windows: parse the output of dd.exe --list @@ -84,7 +92,7 @@ def get_raw_device_hints(): return sorted(set(volumes)) #################################################################### - # Platform Linux: call blockdev on all the /dev/sd* devices + # Platform Linux: call blockdev on all the dev0 devices #################################################################### if platform.system() == 'Linux': devs = list() @@ -107,6 +115,9 @@ def get_raw_device_hints(): #################################################################### 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() @@ -172,160 +183,14 @@ def burn_sd_card(dev, fw, fpga): return verbose ######################################################################## -# Graphical Tk stuff +# command line options ######################################################################## -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("<>", 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 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 = burn_sd_card(dev=dev, fw=fw, fpga=fpga) - tkMessageBox.showinfo('Verbose:', verbose) - except Exception, e: - tkMessageBox.showerror('Verbose:', 'Error: %s'%str(e)) - -######################################################################## -# Main -######################################################################## -import optparse - -if __name__=='__main__': +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) - parser.add_option("--gui", action="store_true", help="run in gui mode", default=False) (options, args) = parser.parse_args() if options.list: @@ -333,12 +198,12 @@ if __name__=='__main__': print ' ' + '\n '.join(get_raw_device_hints()) exit() - if options.gui: - root = Tkinter.Tk() - root.title('USRP2 SD Card Burner') - USRP2CardBurnerApp(root, dev=options.dev, fw=options.fw, fpga=options.fpga).pack() - root.mainloop() - 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 . +# + +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("<>", 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() -- cgit v1.2.3 From af1231fddbb8bb24ef7cdd2612e4933f73f83a9f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 20 May 2010 14:44:46 -0700 Subject: some wbx series notes --- host/README | 1 + host/docs/dboards.rst | 11 +++++++++++ 2 files changed, 12 insertions(+) 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/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. -- cgit v1.2.3 From 221909b36b2a08a5817e75a3d13ebfe56716c7da Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 20 May 2010 17:08:53 -0700 Subject: use only procfs /proc/partitions for discovering raw devices on linux --- host/include/uhd/types/dict.hpp | 2 +- host/utils/usrp2_card_burner.py | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) 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 + template dict(InputIterator first, InputIterator last){ for(InputIterator it = first; it != last; it++){ _map.push_back(*it); diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py index 59d0b3231..c39fb9d19 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -92,7 +92,7 @@ def get_raw_device_hints(): return sorted(set(volumes)) #################################################################### - # Platform Linux: call blockdev on all the dev0 devices + # Platform Linux: parse procfs /proc/partitions #################################################################### if platform.system() == 'Linux': devs = list() @@ -101,12 +101,10 @@ def get_raw_device_hints(): for line in output.splitlines(): try: major, minor, blocks, name = line.split() - if name[-1].isdigit(): assert int(minor) == 0 - dev = os.path.join('/dev/', name) - size = int(command('blockdev', '--getsz', dev))*512 - assert size <= MAX_SD_CARD_SIZE + assert not name[-1].isdigit() or int(minor) == 0 + assert int(blocks)*1024 <= MAX_SD_CARD_SIZE except: continue - devs.append(dev) + devs.append(os.path.join('/dev', name)) return sorted(set(devs)) -- cgit v1.2.3 From 98bd3e1ddc0189f45f209c02b7dc7877ab377960 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 21 May 2010 15:06:54 -0700 Subject: clean up parsing of dd.exe --list for windows usrp2 card burner --- host/utils/usrp2_card_burner.py | 46 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py index c39fb9d19..60aca9133 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -66,30 +66,28 @@ def get_raw_device_hints(): # Platform Windows: parse the output of dd.exe --list #################################################################### if platform.system() == 'Windows': - volumes = list() - try: output = command(get_dd_path(), '--list') - except: return volumes - - #coagulate info for identical links - link_to_info = dict() - for info in output.replace('\r', '').split('\n\\\\'): - if 'link to' not in info: continue - link = info.split('link to')[-1].split()[0].strip() - if not link_to_info.has_key(link): link_to_info[link] = '\n\n' - link_to_info[link] += info - - #parse info only keeping viable volumes - for link, info in link_to_info.iteritems(): - if 'removable' not in info.lower(): continue - if 'size is' in info: - size = info.split('size is')[-1].split()[0].strip() - if int(size) > MAX_SD_CARD_SIZE: continue - if 'Mounted on' in info: - volumes.append(info.split('Mounted on')[-1].split()[0]) - continue - volumes.append(link) - - return sorted(set(volumes)) + 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 -- cgit v1.2.3 From 76ce1d824a41beacdb5bd603549c9b0e3f64d98f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 21 May 2010 17:30:05 -0700 Subject: mac os x card burner support and documentation notes --- host/docs/build.rst | 31 ++++++++++++++++++++++++++----- host/docs/usrp2.rst | 2 +- host/lib/transport/gen_vrt.py | 2 +- host/utils/usrp2_card_burner.py | 21 +++++++++++++++++++++ 4 files changed, 49 insertions(+), 7 deletions(-) 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= ../ +For a custom prefix, use: cmake -DCMAKE_INSTALL_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/usrp2.rst b/host/docs/usrp2.rst index c4a7aa64f..1bd95cefa 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -50,7 +50,7 @@ you could overwrite your hard drive. Make sure that --dev= specifies the SD card 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 not yet been implemented on macosx. +The list option has been implemented on Linux, Mac OS X, and Windows. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the card burner tool (unix) 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/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py index 60aca9133..d47a4f5f4 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -22,6 +22,7 @@ import subprocess import urllib import optparse import os +import re ######################################################################## # constants @@ -106,6 +107,26 @@ def get_raw_device_hints(): 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: #################################################################### -- cgit v1.2.3 From 830e34fe30737432a5bfa4b19cc4bad5b4e425ee Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 24 May 2010 11:47:53 -0700 Subject: fix for time64 register write order --- host/lib/usrp/usrp2/mboard_impl.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index f17efd88e..a2aeadf16 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -83,13 +83,15 @@ void usrp2_impl::update_clock_config(void){ } 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){ -- cgit v1.2.3 From 71169b8e030d984220eadde83c4b40481f97cf6b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 24 May 2010 14:38:25 -0700 Subject: Added timeout error message to timed samples example. Added try catch to recv helper because vrt unpack can throw. --- host/examples/rx_timed_samples.cpp | 4 ++++ host/lib/transport/vrt_packet_handler.hpp | 11 ++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index d2306c7c4..64da260d5 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -86,6 +86,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ 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/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 2a7f995a1..81420b39e 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -122,9 +122,14 @@ namespace vrt_packet_handler{ state.fragment_offset_in_samps = 0; state.managed_buff = zc_iface->get_recv_buff(); recv_cb(state.managed_buff); //callback before vrt unpack - _recv1_helper( - state, metadata, tick_rate, vrt_header_offset_words32 - ); + 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 -- cgit v1.2.3 From 39943a5b0c3c210babfd6e62711ea4bf3133866b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 24 May 2010 16:31:23 -0700 Subject: Added support to set GPIO pins from dboard interface: write gpio and set pin control (atr or gpio) Added property to get dboard interface from the dboard obj. --- host/include/uhd/usrp/dboard_iface.hpp | 22 ++++++++++++++++++++-- host/include/uhd/usrp/dboard_props.hpp | 3 ++- host/lib/usrp/dboard/db_rfx.cpp | 4 +++- host/lib/usrp/dboard/db_wbx.cpp | 4 +++- host/lib/usrp/dboard/db_xcvr2450.cpp | 4 +++- host/lib/usrp/dboard_manager.cpp | 3 ++- host/lib/usrp/usrp2/dboard_iface.cpp | 34 ++++++++++++++++++++++++++-------- host/lib/usrp/usrp2/dboard_impl.cpp | 12 +++++++++--- host/lib/usrp/usrp2/usrp2_impl.hpp | 1 + host/lib/usrp/usrp2/usrp2_regs.hpp | 2 +- 10 files changed, 70 insertions(+), 19 deletions(-) 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 @@ -67,23 +67,41 @@ 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; + /*! + * 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. * 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/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 7bfd14943..89e707718 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -176,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); diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index 81edf7a11..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( 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/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index d33a11fd6..0a2e4b550 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -39,8 +39,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 &); @@ -68,6 +70,7 @@ private: usrp2_iface::sptr _iface; clock_ctrl::sptr _clock_ctrl; boost::uint32_t _ddr_shadow; + boost::uint32_t _gpio_shadow; uhd::dict _dac_regs; void _write_aux_dac(unit_t); @@ -90,14 +93,7 @@ usrp2_dboard_iface::usrp2_dboard_iface(usrp2_iface::sptr iface, clock_ctrl::sptr _iface = iface; _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(); @@ -136,6 +132,21 @@ static const uhd::dict 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 0f8a739f2..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, _clock_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/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index afea9683c..7948a2069 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -169,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 feeccaa34..0f675357b 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -204,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 -- cgit v1.2.3 From 4eff47a4b66eff61feffe6498b9ecebef94dc6b9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 27 May 2010 14:10:50 -0700 Subject: Tweak with the udp and zero-copy transport. Eventually, the caller will hang onto a ring of managed buffers. --- host/include/uhd/transport/zero_copy.hpp | 5 ++-- host/lib/transport/udp_zero_copy_asio.cpp | 38 ++++++++++++++++--------------- host/lib/transport/vrt_packet_handler.hpp | 2 +- host/lib/usrp/usrp2/io_impl.cpp | 2 +- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp index fdc5b141c..52c6d4143 100644 --- a/host/include/uhd/transport/zero_copy.hpp +++ b/host/include/uhd/transport/zero_copy.hpp @@ -35,11 +35,12 @@ public: typedef boost::shared_ptr 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. @@ -81,7 +82,7 @@ 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. diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 56ba391d3..f8a222475 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -24,6 +24,13 @@ 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: **********************************************************************/ @@ -34,11 +41,7 @@ public: } ~managed_recv_buffer_impl(void){ - /* NOP */ - } - - void done(void){ - /* NOP */ + delete [] this->cast(); } private: @@ -65,7 +68,7 @@ public: /* NOP */ } - void done(size_t num_bytes){ + void commit(size_t num_bytes){ _socket->send(boost::asio::buffer(_buff, num_bytes)); } @@ -85,8 +88,6 @@ private: * However, it is not a true zero copy implementation as each * send and recv requires a copy operation to/from userspace. **********************************************************************/ -static const size_t max_buff_size = 2000; //assume max size on send and recv - class udp_zero_copy_impl : public udp_zero_copy{ public: typedef boost::shared_ptr sptr; @@ -117,7 +118,7 @@ private: boost::asio::io_service _io_service; //send and recv buffer memory (allocated once) - boost::uint8_t _send_mem[max_buff_size], _recv_mem[max_buff_size]; + boost::uint8_t _send_mem[MIN_SOCK_BUFF_SIZE]; managed_send_buffer::sptr _send_buff; }; @@ -137,13 +138,13 @@ udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::strin // create the managed send buff (just once) _send_buff = managed_send_buffer::sptr(new managed_send_buffer_impl( - boost::asio::buffer(_send_mem, max_buff_size), _socket + boost::asio::buffer(_send_mem, MIN_SOCK_BUFF_SIZE), _socket )); // set recv timeout timeval tv; tv.tv_sec = 0; - tv.tv_usec = 100*1000; //100 ms + tv.tv_usec = size_t(RECV_TIMEOUT*1e6); UHD_ASSERT_THROW(setsockopt( _socket->native(), SOL_SOCKET, SO_RCVTIMEO, @@ -156,17 +157,20 @@ udp_zero_copy_impl::~udp_zero_copy_impl(void){ } managed_recv_buffer::sptr udp_zero_copy_impl::get_recv_buff(void){ + //allocate memory + boost::uint8_t *recv_mem = new boost::uint8_t[MAX_DGRAM_SIZE]; + //call recv() with timeout option - size_t num_bytes = _socket->receive(boost::asio::buffer(_recv_mem, max_buff_size)); + 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(_recv_mem, num_bytes)) + new managed_recv_buffer_impl(boost::asio::buffer(recv_mem, num_bytes)) ); } managed_send_buffer::sptr udp_zero_copy_impl::get_send_buff(void){ - return _send_buff; + return _send_buff; //FIXME there is only ever one send buff, we assume that the caller doesnt hang onto these } /*********************************************************************** @@ -177,8 +181,6 @@ template static inline void resize_buff_helper( size_t target_size, const std::string &name ){ - static const size_t min_buff_size = size_t(100e3); - //resize the buffer if size was provided if (target_size > 0){ size_t actual_size = udp_trans->resize_buff(target_size); @@ -189,8 +191,8 @@ template static inline void resize_buff_helper( } //otherwise, ensure that the buffer is at least the minimum size - else if (udp_trans->get_buff_size() < min_buff_size){ - resize_buff_helper(udp_trans, min_buff_size, name); + else if (udp_trans->get_buff_size() < MIN_SOCK_BUFF_SIZE){ + resize_buff_helper(udp_trans, MIN_SOCK_BUFF_SIZE, name); } } diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 81420b39e..e64e3383d 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -284,7 +284,7 @@ namespace vrt_packet_handler{ send_cb(send_buff); //callback after memory filled //commit the samples to the zero-copy interface - send_buff->done(num_packet_words32*sizeof(boost::uint32_t)); + send_buff->commit(num_packet_words32*sizeof(boost::uint32_t)); } /******************************************************************* diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index b6ab919e7..79b18fb63 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -45,7 +45,7 @@ void usrp2_impl::io_init(void){ managed_send_buffer::sptr send_buff = _data_transport->get_send_buff(); boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER); memcpy(send_buff->cast(), &data, sizeof(data)); - send_buff->done(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; -- cgit v1.2.3