From 2faaa1e36257c9909415f142e165e5ad74495a4e Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 9 Feb 2010 18:26:47 -0800 Subject: skeletons that don't work yet --- usrp2/top/safe_u1e/Makefile | 245 ++++++++++++++++++++++++++++ usrp2/top/safe_u1e/safe_u1e.v | 362 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 607 insertions(+) create mode 100644 usrp2/top/safe_u1e/Makefile create mode 100644 usrp2/top/safe_u1e/safe_u1e.v diff --git a/usrp2/top/safe_u1e/Makefile b/usrp2/top/safe_u1e/Makefile new file mode 100644 index 000000000..8fe77d554 --- /dev/null +++ b/usrp2/top/safe_u1e/Makefile @@ -0,0 +1,245 @@ +# +# 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 := safe_u1e +export PROJ_FILE := $(BUILD_DIR)$(TOP_MODULE).ise + +################################################## +# Project Properties +################################################## +export PROJECT_PROPERTIES := \ +family "Spartan-3A DSP" \ +device xc3sd1800a \ +package cs484 \ +speed -4 \ +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/dcache.v \ +control_lib/decoder_3_8.v \ +control_lib/dpram32.v \ +control_lib/gray2bin.v \ +control_lib/gray_send.v \ +control_lib/icache.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/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 \ +control_lib/reset_sync.v \ +simple_gemac/simple_gemac_wrapper.v \ +simple_gemac/simple_gemac.v \ +simple_gemac/simple_gemac_wb.v \ +simple_gemac/simple_gemac_tx.v \ +simple_gemac/simple_gemac_rx.v \ +simple_gemac/crc.v \ +simple_gemac/delay_line.v \ +simple_gemac/flow_ctrl_tx.v \ +simple_gemac/flow_ctrl_rx.v \ +simple_gemac/address_filter.v \ +simple_gemac/ll8_to_txmac.v \ +simple_gemac/rxmac_to_ll8.v \ +simple_gemac/miim/eth_miim.v \ +simple_gemac/miim/eth_clockgen.v \ +simple_gemac/miim/eth_outputcontrol.v \ +simple_gemac/miim/eth_shiftreg.v \ +control_lib/newfifo/buffer_int.v \ +control_lib/newfifo/buffer_pool.v \ +control_lib/newfifo/fifo_2clock.v \ +control_lib/newfifo/fifo_2clock_cascade.v \ +control_lib/newfifo/ll8_shortfifo.v \ +control_lib/newfifo/ll8_to_fifo36.v \ +control_lib/newfifo/fifo_short.v \ +control_lib/newfifo/fifo_long.v \ +control_lib/newfifo/fifo_cascade.v \ +control_lib/newfifo/fifo36_to_ll8.v \ +control_lib/longfifo.v \ +control_lib/shortfifo.v \ +control_lib/medfifo.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 \ +coregen/fifo_xlnx_64x36_2clk.v \ +coregen/fifo_xlnx_64x36_2clk.xco \ +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/safe_u1e/u1e.ucf \ +top/safe_u1e/safe_u1e.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/safe_u1e/safe_u1e.v b/usrp2/top/safe_u1e/safe_u1e.v new file mode 100644 index 000000000..c880a9e55 --- /dev/null +++ b/usrp2/top/safe_u1e/safe_u1e.v @@ -0,0 +1,362 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// + +module safe_u1e + ( + input CLK_FPGA_P, input CLK_FPGA_N, // Diff + + // ADC + //input ADC_clkout_p, //input ADC_clkout_n, + //input ADCA_12_p, //input ADCA_12_n, + //input ADCA_10_p, //input ADCA_10_n, + //input ADCA_8_p, //input ADCA_8_n, + //input ADCA_6_p, //input ADCA_6_n, + //input ADCA_4_p, //input ADCA_4_n, + //input ADCA_2_p, //input ADCA_2_n, + //input ADCA_0_p, //input ADCA_0_n, + //input ADCB_12_p, //input ADCB_12_n, + //input ADCB_10_p, //input ADCB_10_n, + //input ADCB_8_p, //input ADCB_8_n, + //input ADCB_6_p, //input ADCB_6_n, + //input ADCB_4_p, //input ADCB_4_n, + //input ADCB_2_p, //input ADCB_2_n, + //input ADCB_0_p, //input ADCB_0_n, + + // DAC + //output [15:0] DACA, + //output [15:0] DACB, + //input DAC_LOCK, // unused for now + + // DB IO Pins + //inout [15:0] io_tx, + //inout [15:0] io_rx, + + // Misc, debug + output [5:1] leds, // LED4 is shared w/INIT_B + //input FPGA_RESET, + //output [1:0] debug_clk, + //output [31:0] debug, + //output [3:1] TXD, //input [3:1] RXD, // UARTs + ////input [3:0] dipsw, // Forgot DIP Switches... + + // 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, + + //inout SCL, //inout SDA, // I2C + + // PPS + //input PPS_IN, //input PPS2_IN, + + // SPI + //output SEN_CLK, //output SCLK_CLK, //output MOSI_CLK, //input MISO_CLK, + //output SEN_DAC, //output SCLK_DAC, //output MOSI_DAC, //input MISO_DAC, + //output SEN_ADC, //output SCLK_ADC, //output MOSI_ADC, + //output SEN_TX_DB, //output SCLK_TX_DB, //output MOSI_TX_DB, //input MISO_TX_DB, + //output SEN_TX_DAC, //output SCLK_TX_DAC, //output MOSI_TX_DAC, + //output SEN_TX_ADC, //output SCLK_TX_ADC, //output MOSI_TX_ADC, //input MISO_TX_ADC, + //output SEN_RX_DB, //output SCLK_RX_DB, //output MOSI_RX_DB, //input MISO_RX_DB, + //output SEN_RX_DAC, //output SCLK_RX_DAC, //output MOSI_RX_DAC, + //output SEN_RX_ADC, //output SCLK_RX_ADC, //output MOSI_RX_ADC, //input MISO_RX_ADC, + + // GigE PHY + //input CLK_TO_MAC, + + //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 + + //input GMII_RX_CLK, + //input [7:0] GMII_RXD, + //input GMII_RX_DV, + //input GMII_RX_ER, + //input GMII_COL, + //input GMII_CRS, + + //input PHY_INTn, // open drain + //inout MDIO, + //output MDC, + //output PHY_RESETn, + output ETH_LED + + //input POR, + + // Expansion + //input exp_time_in_p, //input exp_time_in_n, // Diff + //output exp_time_out_p, //output exp_time_out_n, // Diff + //input exp_user_in_p, //input exp_user_in_n, // Diff + //output exp_user_out_p, //output exp_user_out_n, // Diff + + // 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, + + // SRAM + //inout [35:0] RAM_D, + //output [20:0] RAM_A, + //output [3:0] RAM_BWn, + //output RAM_ZZ, + //output RAM_LDn, + //output RAM_OEn, + //output RAM_WEn, + //output RAM_CENn, + //output RAM_CLK, + + // SPI Flash + //output flash_cs, + //output flash_clk, + //output flash_mosi, + //input flash_miso + ); + + // FPGA-specific pins connections + 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"; + + reg [31:0] ctr; + + always @(posedge clk_fpga) + ctr <= ctr + 1; + + assign {leds,ETH_LED} = ~ctr[29:24]; + + +/* + wire exp_time_in; + IBUFDS exp_time_in_pin (.O(exp_time_in),.I(exp_time_in_p),.IB(exp_time_in_n)); + defparam exp_time_in_pin.IOSTANDARD = "LVDS_25"; + + wire exp_time_out; + OBUFDS exp_time_out_pin (.O(exp_time_out_p),.OB(exp_time_out_n),.I(exp_time_out)); + defparam exp_time_out_pin.IOSTANDARD = "LVDS_25"; + + wire dcm_rst = 0; + + wire [13:0] adc_a, adc_b; + + capture_ddrlvds #(.WIDTH(14)) capture_ddrlvds + (.clk(dsp_clk), .ssclk_p(ADC_clkout_p), .ssclk_n(ADC_clkout_n), + .in_p({{ADCA_12_p, ADCA_10_p, ADCA_8_p, ADCA_6_p, ADCA_4_p, ADCA_2_p, ADCA_0_p}, + {ADCB_12_p, ADCB_10_p, ADCB_8_p, ADCB_6_p, ADCB_4_p, ADCB_2_p, ADCB_0_p}}), + .in_n({{ADCA_12_n, ADCA_10_n, ADCA_8_n, ADCA_6_n, ADCA_4_n, ADCA_2_n, ADCA_0_n}, + {ADCB_12_n, ADCB_10_n, ADCB_8_n, ADCB_6_n, ADCB_4_n, ADCB_2_n, ADCB_0_n}}), + .out({adc_a,adc_b})); + + // 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(), + .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 [4:0] leds_int; + assign leds = ~leds_int; // drive low to turn on leds + + // SPI + wire miso, mosi, sclk; + + assign {SCLK_CLK,MOSI_CLK} = ~SEN_CLK ? {sclk,mosi} : 2'B0; + assign {SCLK_DAC,MOSI_DAC} = ~SEN_DAC ? {sclk,mosi} : 2'B0; + assign {SCLK_ADC,MOSI_ADC} = ~SEN_ADC ? {sclk,mosi} : 2'B0; + assign {SCLK_TX_DB,MOSI_TX_DB} = ~SEN_TX_DB ? {sclk,mosi} : 2'B0; + assign {SCLK_TX_DAC,MOSI_TX_DAC} = ~SEN_TX_DAC ? {sclk,mosi} : 2'B0; + assign {SCLK_TX_ADC,MOSI_TX_ADC} = ~SEN_TX_ADC ? {sclk,mosi} : 2'B0; + assign {SCLK_RX_DB,MOSI_RX_DB} = ~SEN_RX_DB ? {sclk,mosi} : 2'B0; + assign {SCLK_RX_DAC,MOSI_RX_DAC} = ~SEN_RX_DAC ? {sclk,mosi} : 2'B0; + assign {SCLK_RX_ADC,MOSI_RX_ADC} = ~SEN_RX_ADC ? {sclk,mosi} : 2'B0; + + assign miso = (~SEN_CLK & MISO_CLK) | (~SEN_DAC & MISO_DAC) | + (~SEN_TX_DB & MISO_TX_DB) | (~SEN_TX_ADC & MISO_TX_ADC) | + (~SEN_RX_DB & MISO_RX_DB) | (~SEN_RX_ADC & MISO_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 + + u2_core 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_time_in), + .exp_pps_out (exp_time_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), + .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 (DACA[15:0]), + .dac_b (DACB[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_tx_o), + .uart_rx_i (uart_rx_i), + .uart_baud_o (), + .sim_mode (1'b0), + .clock_divider (2) + ); +*/ +endmodule // safe_u2plus -- cgit v1.2.3 From 3f2e589f639c6ec16e62b337568ebca96e241ae2 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 9 Feb 2010 18:41:22 -0800 Subject: first cut at blinking leds --- usrp2/top/safe_u1e/.gitignore | 2 + usrp2/top/safe_u1e/Makefile | 2 +- usrp2/top/safe_u1e/safe_u1e.ucf | 228 ++++++++++++++++++++++++++ usrp2/top/safe_u1e/safe_u1e.v | 350 +--------------------------------------- 4 files changed, 237 insertions(+), 345 deletions(-) create mode 100644 usrp2/top/safe_u1e/.gitignore create mode 100644 usrp2/top/safe_u1e/safe_u1e.ucf diff --git a/usrp2/top/safe_u1e/.gitignore b/usrp2/top/safe_u1e/.gitignore new file mode 100644 index 000000000..bdc5af040 --- /dev/null +++ b/usrp2/top/safe_u1e/.gitignore @@ -0,0 +1,2 @@ +*~ +build diff --git a/usrp2/top/safe_u1e/Makefile b/usrp2/top/safe_u1e/Makefile index 8fe77d554..664835187 100644 --- a/usrp2/top/safe_u1e/Makefile +++ b/usrp2/top/safe_u1e/Makefile @@ -175,7 +175,7 @@ timing/time_sender.v \ timing/time_sync.v \ timing/timer.v \ top/u2_core/u2_core.v \ -top/safe_u1e/u1e.ucf \ +top/safe_u1e/safe_u1e.ucf \ top/safe_u1e/safe_u1e.v ################################################## diff --git a/usrp2/top/safe_u1e/safe_u1e.ucf b/usrp2/top/safe_u1e/safe_u1e.ucf new file mode 100644 index 000000000..83dbeca54 --- /dev/null +++ b/usrp2/top/safe_u1e/safe_u1e.ucf @@ -0,0 +1,228 @@ +#NET "EM_CLK" LOC = "F11" ; +#NET "overo_gpio23" LOC = "B3" ; +#NET "overo_gpio22" LOC = "A3" ; +#NET "overo_gpio21" LOC = "D5" ; +#NET "overo_gpio14" LOC = "C4" ; +#NET "overo_gpio176" LOC = "B4" ; +#NET "overo_gpio64" LOC = "A4" ; +#NET "overo_gpio65" LOC = "F8" ; +#NET "overo_gpio170" LOC = "E8" ; +#NET "overo_gpio145" LOC = "C7" ; +#NET "overo_gpio163" LOC = "D7" ; +#NET "overo_gpio146" LOC = "A6" ; +#NET "overo_gpio144" LOC = "A5" ; +#NET "overo_gpio147" LOC = "B6" ; +#NET "overo_gpio128" LOC = "G8" ; +#NET "overo_gpio0" LOC = "F9" ; +#NET "overo_gpio127" LOC = "C8" ; +#NET "overo_txd1" LOC = "C6" ; +#NET "overo_rxd1" LOC = "D6" ; +#NET "EM_WAIT0" LOC = "F14" ; +#NET "EM_NWP" LOC = "F13" ; +#NET "EM_NBE1" LOC = "D14" ; +#NET "EM_NBE0" LOC = "A13" ; +#NET "EM_NWE" LOC = "B13" ; +#NET "EM_NOE" LOC = "A14" ; +#NET "EM_NADV_ALE" LOC = "B15" ; +#NET "EM_D15" LOC = "D13" ; +#NET "EM_D14" LOC = "D15" ; +#NET "EM_D13" LOC = "C16" ; +#NET "EM_D12" LOC = "B20" ; +#NET "EM_D11" LOC = "A19" ; +#NET "EM_D10" LOC = "A17" ; +#NET "EM_D9" LOC = "E15" ; +#NET "EM_D8" LOC = "F15" ; +#NET "EM_D7" LOC = "E16" ; +#NET "EM_D6" LOC = "F16" ; +#NET "EM_D5" LOC = "B17" ; +#NET "EM_D4" LOC = "C17" ; +#NET "EM_D3" LOC = "B19" ; +#NET "EM_D2" LOC = "D19" ; +#NET "EM_D1" LOC = "C19" ; +#NET "EM_D0" LOC = "A20" ; +#NET "SYSEN" LOC = "C11" ; +#NET "EM_NCS6" LOC = "E17" ; +#NET "EM_NCS5" LOC = "E10" ; +#NET "EM_NCS4" LOC = "E6" ; +#NET "EM_NCS1" LOC = "D18" ; +#NET "EM_NCS0" LOC = "D17" ; +#NET "EM_A10" LOC = "C14" ; +#NET "EM_A9" LOC = "C10" ; +#NET "EM_A8" LOC = "C5" ; +#NET "EM_A7" LOC = "A18" ; +#NET "EM_A6" LOC = "A15" ; +#NET "EM_A5" LOC = "A12" ; +#NET "EM_A4" LOC = "A10" ; +#NET "EM_A3" LOC = "E7" ; +#NET "EM_A2" LOC = "A7" ; +#NET "EM_A1" LOC = "C15" ; +#NET "db_scl" LOC = "U4" ; +#NET "db_sda" LOC = "U5" ; +#NET "db_sclk_rx" LOC = "W3" ; +#NET "db_miso_rx" LOC = "W2" ; +#NET "db_mosi_rx" LOC = "V4" ; +#NET "db_sen_rx" LOC = "V3" ; +#NET "db_sclk_tx" LOC = "Y1" ; +#NET "db_miso_tx" LOC = "W1" ; +#NET "db_mosi_tx" LOC = "R3" ; +#NET "db_sen_tx" LOC = "T4" ; +#NET "cgen_miso" LOC = "U2" ; +#NET "cgen_mosi" LOC = "V1" ; +#NET "cgen_sclk" LOC = "R5" ; +#NET "cgen_sen_b" LOC = "T1" ; +#NET "FPGA_TXD" LOC = "U1" ; +#NET "FPGA_RXD" LOC = "T6" ; +#NET "debug_00" LOC = "P6" ; +#NET "debug_01" LOC = "R6" ; +#NET "debug_02" LOC = "P1" ; +#NET "debug_03" LOC = "P2" ; +#NET "debug_04" LOC = "N6" ; +#NET "debug_05" LOC = "N5" ; +#NET "debug_06" LOC = "N1" ; +#NET "debug_07" LOC = "K2" ; +#NET "debug_08" LOC = "K3" ; +#NET "debug_09" LOC = "K6" ; +#NET "debug_10" LOC = "L5" ; +#NET "debug_11" LOC = "H2" ; +#NET "debug_12" LOC = "K4" ; +#NET "debug_13" LOC = "K5" ; +#NET "debug_14" LOC = "G1" ; +#NET "debug_15" LOC = "H1" ; +#NET "debug_16" LOC = "H5" ; +#NET "debug_17" LOC = "H6" ; +#NET "debug_18" LOC = "E3" ; +#NET "debug_19" LOC = "E4" ; +#NET "debug_20" LOC = "G5" ; +#NET "debug_21" LOC = "G6" ; +#NET "debug_22" LOC = "F2" ; +#NET "debug_23" LOC = "F1" ; +#NET "debug_24" LOC = "H3" ; +#NET "debug_25" LOC = "H4" ; +#NET "debug_26" LOC = "F4" ; +#NET "debug_27" LOC = "F5" ; +#NET "debug_28" LOC = "C2" ; +#NET "debug_29" LOC = "C1" ; +#NET "debug_30" LOC = "F3" ; +#NET "debug_31" LOC = "G3" ; +#NET "debug_pb2" LOC = "Y2" ; +#NET "debug_pb1" LOC = "AA1" ; +#NET "debug_pb0" LOC = "N3" ; +#NET "dip_sw_7" LOC = "T3" ; +#NET "dip_sw_6" LOC = "U3" ; +#NET "dip_sw_5" LOC = "M3" ; +#NET "dip_sw_4" LOC = "N4" ; +#NET "dip_sw_3" LOC = "J3" ; +#NET "dip_sw_2" LOC = "J4" ; +#NET "dip_sw_1" LOC = "J6" ; +#NET "dip_sw_0" LOC = "J7" ; +#NET "cgen_st_status" LOC = "D4" ; +#NET "cgen_st_ld" LOC = "D1" ; +#NET "cgen_st_refmon" LOC = "E1" ; +#NET "cgen_sync_b" LOC = "M1" ; +#NET "cgen_ref_sel" LOC = "J1" ; +#NET "debug_clk0" LOC = "L6" ; +#NET "debug_clk1" LOC = "M5" ; +#NET "unnamed_net37" LOC = "B1" ; +#NET "unnamed_net36" LOC = "B22" ; +#NET "unnamed_net35" LOC = "D2" ; +#NET "unnamed_net34" LOC = "A21" ; +#NET "GND" LOC = "V19" ; +#NET "fpga_cfg_prog_b" LOC = "A2" ; +#NET "fpga_cfg_done" LOC = "AB21" ; +#NET "unnamed_net45" LOC = "F7" ; +#NET "fpga_cfg_din" LOC = "W17" ; +#NET "fpga_cfg_cclk" LOC = "V17" ; +#NET "fpga_cfg_init_b" LOC = "W15" ; +#NET "unnamed_net44" LOC = "V6" ; +#NET "unnamed_net43" LOC = "AA3" ; +#NET "unnamed_net42" LOC = "AB3" ; +#NET "aux_sdi_codec" LOC = "F19" ; +#NET "aux_sdo_codec" LOC = "F18" ; +#NET "aux_sclk_codec" LOC = "D21" ; +#NET "reset_codec" LOC = "D22" ; +#NET "sen_codec" LOC = "D20" ; +#NET "mosi_codec" LOC = "E19" ; +#NET "miso_codec" LOC = "F21" ; +#NET "sclk_codec" LOC = "E20" ; +#NET "RXSYNC" LOC = "F22" ; +#NET "DB11" LOC = "E22" ; +#NET "DB10" LOC = "J19" ; +#NET "DB09" LOC = "H20" ; +#NET "DB08" LOC = "G19" ; +#NET "DB07" LOC = "F20" ; +#NET "DB06" LOC = "K16" ; +#NET "DB05" LOC = "J17" ; +#NET "DB04" LOC = "H22" ; +#NET "DB03" LOC = "G22" ; +#NET "DB02" LOC = "H17" ; +#NET "DB01" LOC = "H18" ; +#NET "DB00" LOC = "K20" ; +#NET "DA11" LOC = "J20" ; +#NET "DA10" LOC = "K19" ; +#NET "DA09" LOC = "K18" ; +#NET "DA08" LOC = "L22" ; +#NET "DA07" LOC = "K22" ; +#NET "DA06" LOC = "N22" ; +#NET "DA05" LOC = "M22" ; +#NET "DA04" LOC = "N20" ; +#NET "DA03" LOC = "N19" ; +#NET "DA02" LOC = "R22" ; +#NET "DA01" LOC = "P22" ; +#NET "DA00" LOC = "N17" ; +#NET "TX13" LOC = "P19" ; +#NET "TX12" LOC = "R18" ; +#NET "TX11" LOC = "U20" ; +#NET "TX10" LOC = "T20" ; +#NET "TX09" LOC = "R19" ; +#NET "TX08" LOC = "R20" ; +#NET "TX07" LOC = "W22" ; +#NET "TX06" LOC = "Y22" ; +#NET "TX05" LOC = "T18" ; +#NET "TX04" LOC = "T17" ; +#NET "TX03" LOC = "W19" ; +#NET "TX02" LOC = "V20" ; +#NET "TX01" LOC = "Y21" ; +#NET "TX00" LOC = "AA22" ; +#NET "TXSYNC" LOC = "U18" ; +#NET "TXBLANK" LOC = "U19" ; +#NET "PPS_IN" LOC = "M17" ; +#NET "io_tx_00" LOC = "AB20" ; +#NET "io_tx_01" LOC = "Y17" ; +#NET "io_tx_02" LOC = "Y16" ; +#NET "io_tx_03" LOC = "U16" ; +#NET "io_tx_04" LOC = "V16" ; +#NET "io_tx_05" LOC = "AB19" ; +#NET "io_tx_06" LOC = "AA19" ; +#NET "io_tx_07" LOC = "U14" ; +#NET "io_tx_08" LOC = "U15" ; +#NET "io_tx_09" LOC = "AB17" ; +#NET "io_tx_10" LOC = "AB18" ; +#NET "io_tx_11" LOC = "Y13" ; +#NET "io_tx_12" LOC = "W14" ; +#NET "io_tx_13" LOC = "U13" ; +#NET "io_tx_14" LOC = "AA15" ; +#NET "io_tx_15" LOC = "AB14" ; +#NET "io_rx_00" LOC = "Y8" ; +#NET "io_rx_01" LOC = "Y9" ; +#NET "io_rx_02" LOC = "V7" ; +#NET "io_rx_03" LOC = "U8" ; +#NET "io_rx_04" LOC = "V10" ; +#NET "io_rx_05" LOC = "U9" ; +#NET "io_rx_06" LOC = "AB7" ; +#NET "io_rx_07" LOC = "AA8" ; +#NET "io_rx_08" LOC = "W8" ; +#NET "io_rx_09" LOC = "V8" ; +#NET "io_rx_10" LOC = "AB5" ; +#NET "io_rx_11" LOC = "AB6" ; +#NET "io_rx_12" LOC = "AB4" ; +#NET "io_rx_13" LOC = "AA4" ; +#NET "io_rx_14" LOC = "W5" ; +#NET "io_rx_15" LOC = "Y4" ; +#NET "CLKOUT2_CODEC" LOC = "U12" ; +#NET "CLKOUT1_CODEC" LOC = "V12" ; + +NET "CLK_FPGA_P" LOC = "Y11" ; +NET "CLK_FPGA_N" LOC = "Y10" ; +NET "debug_led<2>" LOC = "T5" ; +NET "debug_led<1>" LOC = "R2" ; +NET "debug_led<0>" LOC = "R1" ; diff --git a/usrp2/top/safe_u1e/safe_u1e.v b/usrp2/top/safe_u1e/safe_u1e.v index c880a9e55..79aaac6cd 100644 --- a/usrp2/top/safe_u1e/safe_u1e.v +++ b/usrp2/top/safe_u1e/safe_u1e.v @@ -4,131 +4,14 @@ module safe_u1e ( input CLK_FPGA_P, input CLK_FPGA_N, // Diff - - // ADC - //input ADC_clkout_p, //input ADC_clkout_n, - //input ADCA_12_p, //input ADCA_12_n, - //input ADCA_10_p, //input ADCA_10_n, - //input ADCA_8_p, //input ADCA_8_n, - //input ADCA_6_p, //input ADCA_6_n, - //input ADCA_4_p, //input ADCA_4_n, - //input ADCA_2_p, //input ADCA_2_n, - //input ADCA_0_p, //input ADCA_0_n, - //input ADCB_12_p, //input ADCB_12_n, - //input ADCB_10_p, //input ADCB_10_n, - //input ADCB_8_p, //input ADCB_8_n, - //input ADCB_6_p, //input ADCB_6_n, - //input ADCB_4_p, //input ADCB_4_n, - //input ADCB_2_p, //input ADCB_2_n, - //input ADCB_0_p, //input ADCB_0_n, - - // DAC - //output [15:0] DACA, - //output [15:0] DACB, - //input DAC_LOCK, // unused for now - - // DB IO Pins - //inout [15:0] io_tx, - //inout [15:0] io_rx, - - // Misc, debug - output [5:1] leds, // LED4 is shared w/INIT_B - //input FPGA_RESET, - //output [1:0] debug_clk, - //output [31:0] debug, - //output [3:1] TXD, //input [3:1] RXD, // UARTs - ////input [3:0] dipsw, // Forgot DIP Switches... - - // 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, - - //inout SCL, //inout SDA, // I2C - - // PPS - //input PPS_IN, //input PPS2_IN, - - // SPI - //output SEN_CLK, //output SCLK_CLK, //output MOSI_CLK, //input MISO_CLK, - //output SEN_DAC, //output SCLK_DAC, //output MOSI_DAC, //input MISO_DAC, - //output SEN_ADC, //output SCLK_ADC, //output MOSI_ADC, - //output SEN_TX_DB, //output SCLK_TX_DB, //output MOSI_TX_DB, //input MISO_TX_DB, - //output SEN_TX_DAC, //output SCLK_TX_DAC, //output MOSI_TX_DAC, - //output SEN_TX_ADC, //output SCLK_TX_ADC, //output MOSI_TX_ADC, //input MISO_TX_ADC, - //output SEN_RX_DB, //output SCLK_RX_DB, //output MOSI_RX_DB, //input MISO_RX_DB, - //output SEN_RX_DAC, //output SCLK_RX_DAC, //output MOSI_RX_DAC, - //output SEN_RX_ADC, //output SCLK_RX_ADC, //output MOSI_RX_ADC, //input MISO_RX_ADC, - - // GigE PHY - //input CLK_TO_MAC, - - //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 - - //input GMII_RX_CLK, - //input [7:0] GMII_RXD, - //input GMII_RX_DV, - //input GMII_RX_ER, - //input GMII_COL, - //input GMII_CRS, - - //input PHY_INTn, // open drain - //inout MDIO, - //output MDC, - //output PHY_RESETn, - output ETH_LED - - //input POR, - - // Expansion - //input exp_time_in_p, //input exp_time_in_n, // Diff - //output exp_time_out_p, //output exp_time_out_n, // Diff - //input exp_user_in_p, //input exp_user_in_n, // Diff - //output exp_user_out_p, //output exp_user_out_n, // Diff - - // 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, - - // SRAM - //inout [35:0] RAM_D, - //output [20:0] RAM_A, - //output [3:0] RAM_BWn, - //output RAM_ZZ, - //output RAM_LDn, - //output RAM_OEn, - //output RAM_WEn, - //output RAM_CENn, - //output RAM_CLK, - - // SPI Flash - //output flash_cs, - //output flash_clk, - //output flash_mosi, - //input flash_miso + output [2:0] debug_led ); // FPGA-specific pins connections - 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)); + wire clk_fpga; + + IBUFGDS #(.IOSTANDARD("LVDS_33"), .DIFF_TERM("TRUE")) + clk_fpga_pin (.O(clk_fpga),.I(CLK_FPGA_P),.IB(CLK_FPGA_N)); defparam clk_fpga_pin.IOSTANDARD = "LVPECL_25"; reg [31:0] ctr; @@ -136,227 +19,6 @@ module safe_u1e always @(posedge clk_fpga) ctr <= ctr + 1; - assign {leds,ETH_LED} = ~ctr[29:24]; - - -/* - wire exp_time_in; - IBUFDS exp_time_in_pin (.O(exp_time_in),.I(exp_time_in_p),.IB(exp_time_in_n)); - defparam exp_time_in_pin.IOSTANDARD = "LVDS_25"; - - wire exp_time_out; - OBUFDS exp_time_out_pin (.O(exp_time_out_p),.OB(exp_time_out_n),.I(exp_time_out)); - defparam exp_time_out_pin.IOSTANDARD = "LVDS_25"; - - wire dcm_rst = 0; - - wire [13:0] adc_a, adc_b; - - capture_ddrlvds #(.WIDTH(14)) capture_ddrlvds - (.clk(dsp_clk), .ssclk_p(ADC_clkout_p), .ssclk_n(ADC_clkout_n), - .in_p({{ADCA_12_p, ADCA_10_p, ADCA_8_p, ADCA_6_p, ADCA_4_p, ADCA_2_p, ADCA_0_p}, - {ADCB_12_p, ADCB_10_p, ADCB_8_p, ADCB_6_p, ADCB_4_p, ADCB_2_p, ADCB_0_p}}), - .in_n({{ADCA_12_n, ADCA_10_n, ADCA_8_n, ADCA_6_n, ADCA_4_n, ADCA_2_n, ADCA_0_n}, - {ADCB_12_n, ADCB_10_n, ADCB_8_n, ADCB_6_n, ADCB_4_n, ADCB_2_n, ADCB_0_n}}), - .out({adc_a,adc_b})); - - // 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(), - .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 [4:0] leds_int; - assign leds = ~leds_int; // drive low to turn on leds - - // SPI - wire miso, mosi, sclk; + assign debug_led = ctr[27:25]; - assign {SCLK_CLK,MOSI_CLK} = ~SEN_CLK ? {sclk,mosi} : 2'B0; - assign {SCLK_DAC,MOSI_DAC} = ~SEN_DAC ? {sclk,mosi} : 2'B0; - assign {SCLK_ADC,MOSI_ADC} = ~SEN_ADC ? {sclk,mosi} : 2'B0; - assign {SCLK_TX_DB,MOSI_TX_DB} = ~SEN_TX_DB ? {sclk,mosi} : 2'B0; - assign {SCLK_TX_DAC,MOSI_TX_DAC} = ~SEN_TX_DAC ? {sclk,mosi} : 2'B0; - assign {SCLK_TX_ADC,MOSI_TX_ADC} = ~SEN_TX_ADC ? {sclk,mosi} : 2'B0; - assign {SCLK_RX_DB,MOSI_RX_DB} = ~SEN_RX_DB ? {sclk,mosi} : 2'B0; - assign {SCLK_RX_DAC,MOSI_RX_DAC} = ~SEN_RX_DAC ? {sclk,mosi} : 2'B0; - assign {SCLK_RX_ADC,MOSI_RX_ADC} = ~SEN_RX_ADC ? {sclk,mosi} : 2'B0; - - assign miso = (~SEN_CLK & MISO_CLK) | (~SEN_DAC & MISO_DAC) | - (~SEN_TX_DB & MISO_TX_DB) | (~SEN_TX_ADC & MISO_TX_ADC) | - (~SEN_RX_DB & MISO_RX_DB) | (~SEN_RX_ADC & MISO_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 - - u2_core 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_time_in), - .exp_pps_out (exp_time_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), - .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 (DACA[15:0]), - .dac_b (DACB[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_tx_o), - .uart_rx_i (uart_rx_i), - .uart_baud_o (), - .sim_mode (1'b0), - .clock_divider (2) - ); -*/ endmodule // safe_u2plus -- cgit v1.2.3 From 36138857e9d64a129840814aed79c00cc6f505e9 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 9 Feb 2010 19:04:26 -0800 Subject: builds a successful led blinker --- usrp2/top/safe_u1e/.gitignore | 2 ++ usrp2/top/safe_u1e/Makefile | 3 ++- usrp2/top/safe_u1e/safe_u1e.v | 1 - 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/usrp2/top/safe_u1e/.gitignore b/usrp2/top/safe_u1e/.gitignore index bdc5af040..f8b57ea21 100644 --- a/usrp2/top/safe_u1e/.gitignore +++ b/usrp2/top/safe_u1e/.gitignore @@ -1,2 +1,4 @@ *~ build +*.log +*.cmd diff --git a/usrp2/top/safe_u1e/Makefile b/usrp2/top/safe_u1e/Makefile index 664835187..d28cc2b89 100644 --- a/usrp2/top/safe_u1e/Makefile +++ b/usrp2/top/safe_u1e/Makefile @@ -217,7 +217,8 @@ export GEN_PROG_FILE_PROPERTIES := \ "Create Binary Configuration File" TRUE \ "Done (Output Events)" 5 \ "Enable Bitstream Compression" TRUE \ -"Enable Outputs (Output Events)" 6 +"Enable Outputs (Output Events)" 6 \ +"Unused IOB Pins" "Pull Up" export SIM_MODEL_PROPERTIES := "" diff --git a/usrp2/top/safe_u1e/safe_u1e.v b/usrp2/top/safe_u1e/safe_u1e.v index 79aaac6cd..1b81bab5a 100644 --- a/usrp2/top/safe_u1e/safe_u1e.v +++ b/usrp2/top/safe_u1e/safe_u1e.v @@ -12,7 +12,6 @@ module safe_u1e IBUFGDS #(.IOSTANDARD("LVDS_33"), .DIFF_TERM("TRUE")) clk_fpga_pin (.O(clk_fpga),.I(CLK_FPGA_P),.IB(CLK_FPGA_N)); - defparam clk_fpga_pin.IOSTANDARD = "LVPECL_25"; reg [31:0] ctr; -- cgit v1.2.3 From 44d8aeb6bdbe598d6d453c4530015892959cb765 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 9 Feb 2010 21:09:56 -0800 Subject: organized the pins in the ucf by function --- usrp2/top/safe_u1e/safe_u1e.ucf | 128 ++++++++++++++++++++++------------------ 1 file changed, 72 insertions(+), 56 deletions(-) diff --git a/usrp2/top/safe_u1e/safe_u1e.ucf b/usrp2/top/safe_u1e/safe_u1e.ucf index 83dbeca54..16265c203 100644 --- a/usrp2/top/safe_u1e/safe_u1e.ucf +++ b/usrp2/top/safe_u1e/safe_u1e.ucf @@ -1,3 +1,8 @@ + +NET "CLK_FPGA_P" LOC = "Y11" ; +NET "CLK_FPGA_N" LOC = "Y10" ; + +## GPMC #NET "EM_CLK" LOC = "F11" ; #NET "overo_gpio23" LOC = "B3" ; #NET "overo_gpio22" LOC = "A3" ; @@ -56,6 +61,7 @@ #NET "EM_A3" LOC = "E7" ; #NET "EM_A2" LOC = "A7" ; #NET "EM_A1" LOC = "C15" ; + #NET "db_scl" LOC = "U4" ; #NET "db_sda" LOC = "U5" ; #NET "db_sclk_rx" LOC = "W3" ; @@ -72,49 +78,57 @@ #NET "cgen_sen_b" LOC = "T1" ; #NET "FPGA_TXD" LOC = "U1" ; #NET "FPGA_RXD" LOC = "T6" ; -#NET "debug_00" LOC = "P6" ; -#NET "debug_01" LOC = "R6" ; -#NET "debug_02" LOC = "P1" ; -#NET "debug_03" LOC = "P2" ; -#NET "debug_04" LOC = "N6" ; -#NET "debug_05" LOC = "N5" ; -#NET "debug_06" LOC = "N1" ; -#NET "debug_07" LOC = "K2" ; -#NET "debug_08" LOC = "K3" ; -#NET "debug_09" LOC = "K6" ; -#NET "debug_10" LOC = "L5" ; -#NET "debug_11" LOC = "H2" ; -#NET "debug_12" LOC = "K4" ; -#NET "debug_13" LOC = "K5" ; -#NET "debug_14" LOC = "G1" ; -#NET "debug_15" LOC = "H1" ; -#NET "debug_16" LOC = "H5" ; -#NET "debug_17" LOC = "H6" ; -#NET "debug_18" LOC = "E3" ; -#NET "debug_19" LOC = "E4" ; -#NET "debug_20" LOC = "G5" ; -#NET "debug_21" LOC = "G6" ; -#NET "debug_22" LOC = "F2" ; -#NET "debug_23" LOC = "F1" ; -#NET "debug_24" LOC = "H3" ; -#NET "debug_25" LOC = "H4" ; -#NET "debug_26" LOC = "F4" ; -#NET "debug_27" LOC = "F5" ; -#NET "debug_28" LOC = "C2" ; -#NET "debug_29" LOC = "C1" ; -#NET "debug_30" LOC = "F3" ; -#NET "debug_31" LOC = "G3" ; -#NET "debug_pb2" LOC = "Y2" ; -#NET "debug_pb1" LOC = "AA1" ; -#NET "debug_pb0" LOC = "N3" ; -#NET "dip_sw_7" LOC = "T3" ; -#NET "dip_sw_6" LOC = "U3" ; -#NET "dip_sw_5" LOC = "M3" ; -#NET "dip_sw_4" LOC = "N4" ; -#NET "dip_sw_3" LOC = "J3" ; -#NET "dip_sw_2" LOC = "J4" ; -#NET "dip_sw_1" LOC = "J6" ; -#NET "dip_sw_0" LOC = "J7" ; + +## Debug pins +NET "debug_led<2>" LOC = "T5" ; +NET "debug_led<1>" LOC = "R2" ; +NET "debug_led<0>" LOC = "R1" ; +#NET "debug<0>" LOC = "P6" ; +#NET "debug<1>" LOC = "R6" ; +#NET "debug<2>" LOC = "P1" ; +#NET "debug<3>" LOC = "P2" ; +#NET "debug<4>" LOC = "N6" ; +#NET "debug<5>" LOC = "N5" ; +#NET "debug<6>" LOC = "N1" ; +#NET "debug<7>" LOC = "K2" ; +#NET "debug<8>" LOC = "K3" ; +#NET "debug<9>" LOC = "K6" ; +#NET "debug<10>" LOC = "L5" ; +#NET "debug<11>" LOC = "H2" ; +#NET "debug<12>" LOC = "K4" ; +#NET "debug<13>" LOC = "K5" ; +#NET "debug<14>" LOC = "G1" ; +#NET "debug<15>" LOC = "H1" ; +#NET "debug<16>" LOC = "H5" ; +#NET "debug<17>" LOC = "H6" ; +#NET "debug<18>" LOC = "E3" ; +#NET "debug<19>" LOC = "E4" ; +#NET "debug<20>" LOC = "G5" ; +#NET "debug<21>" LOC = "G6" ; +#NET "debug<22>" LOC = "F2" ; +#NET "debug<23>" LOC = "F1" ; +#NET "debug<24>" LOC = "H3" ; +#NET "debug<25>" LOC = "H4" ; +#NET "debug<26>" LOC = "F4" ; +#NET "debug<27>" LOC = "F5" ; +#NET "debug<28>" LOC = "C2" ; +#NET "debug<29>" LOC = "C1" ; +#NET "debug<30>" LOC = "F3" ; +#NET "debug<31>" LOC = "G3" ; + +#NET "debug_pb<2>" LOC = "Y2" ; +#NET "debug_pb<1>" LOC = "AA1" ; +#NET "debug_pb<0>" LOC = "N3" ; + +#NET "dip_sw<7>" LOC = "T3" ; +#NET "dip_sw<6>" LOC = "U3" ; +#NET "dip_sw<5>" LOC = "M3" ; +#NET "dip_sw<4>" LOC = "N4" ; +#NET "dip_sw<3>" LOC = "J3" ; +#NET "dip_sw<2>" LOC = "J4" ; +#NET "dip_sw<1>" LOC = "J6" ; +#NET "dip_sw<0>" LOC = "J7" ; + #NET "cgen_st_status" LOC = "D4" ; #NET "cgen_st_ld" LOC = "D1" ; #NET "cgen_st_refmon" LOC = "E1" ; @@ -122,20 +136,12 @@ #NET "cgen_ref_sel" LOC = "J1" ; #NET "debug_clk0" LOC = "L6" ; #NET "debug_clk1" LOC = "M5" ; -#NET "unnamed_net37" LOC = "B1" ; -#NET "unnamed_net36" LOC = "B22" ; -#NET "unnamed_net35" LOC = "D2" ; -#NET "unnamed_net34" LOC = "A21" ; #NET "GND" LOC = "V19" ; #NET "fpga_cfg_prog_b" LOC = "A2" ; #NET "fpga_cfg_done" LOC = "AB21" ; -#NET "unnamed_net45" LOC = "F7" ; #NET "fpga_cfg_din" LOC = "W17" ; #NET "fpga_cfg_cclk" LOC = "V17" ; #NET "fpga_cfg_init_b" LOC = "W15" ; -#NET "unnamed_net44" LOC = "V6" ; -#NET "unnamed_net43" LOC = "AA3" ; -#NET "unnamed_net42" LOC = "AB3" ; #NET "aux_sdi_codec" LOC = "F19" ; #NET "aux_sdo_codec" LOC = "F18" ; #NET "aux_sclk_codec" LOC = "D21" ; @@ -144,7 +150,9 @@ #NET "mosi_codec" LOC = "E19" ; #NET "miso_codec" LOC = "F21" ; #NET "sclk_codec" LOC = "E20" ; + #NET "RXSYNC" LOC = "F22" ; + #NET "DB11" LOC = "E22" ; #NET "DB10" LOC = "J19" ; #NET "DB09" LOC = "H20" ; @@ -169,6 +177,7 @@ #NET "DA02" LOC = "R22" ; #NET "DA01" LOC = "P22" ; #NET "DA00" LOC = "N17" ; + #NET "TX13" LOC = "P19" ; #NET "TX12" LOC = "R18" ; #NET "TX11" LOC = "U20" ; @@ -185,7 +194,9 @@ #NET "TX00" LOC = "AA22" ; #NET "TXSYNC" LOC = "U18" ; #NET "TXBLANK" LOC = "U19" ; + #NET "PPS_IN" LOC = "M17" ; + #NET "io_tx_00" LOC = "AB20" ; #NET "io_tx_01" LOC = "Y17" ; #NET "io_tx_02" LOC = "Y16" ; @@ -218,11 +229,16 @@ #NET "io_rx_13" LOC = "AA4" ; #NET "io_rx_14" LOC = "W5" ; #NET "io_rx_15" LOC = "Y4" ; + #NET "CLKOUT2_CODEC" LOC = "U12" ; #NET "CLKOUT1_CODEC" LOC = "V12" ; -NET "CLK_FPGA_P" LOC = "Y11" ; -NET "CLK_FPGA_N" LOC = "Y10" ; -NET "debug_led<2>" LOC = "T5" ; -NET "debug_led<1>" LOC = "R2" ; -NET "debug_led<0>" LOC = "R1" ; +## Unnamed, need to figure out what they do +#NET "unnamed_net37" LOC = "B1" ; +#NET "unnamed_net36" LOC = "B22" ; +#NET "unnamed_net35" LOC = "D2" ; +#NET "unnamed_net34" LOC = "A21" ; +#NET "unnamed_net45" LOC = "F7" ; +#NET "unnamed_net44" LOC = "V6" ; +#NET "unnamed_net43" LOC = "AA3" ; +#NET "unnamed_net42" LOC = "AB3" ; -- cgit v1.2.3 From a6872631b33fca08bb39fd8b1329146470369b19 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Sun, 14 Feb 2010 17:07:24 -0800 Subject: connect GPMC pins to debug bus --- usrp2/top/safe_u1e/safe_u1e.ucf | 156 +++++++++++++++++++++------------------- usrp2/top/safe_u1e/safe_u1e.v | 14 +++- 2 files changed, 94 insertions(+), 76 deletions(-) diff --git a/usrp2/top/safe_u1e/safe_u1e.ucf b/usrp2/top/safe_u1e/safe_u1e.ucf index 16265c203..14389f299 100644 --- a/usrp2/top/safe_u1e/safe_u1e.ucf +++ b/usrp2/top/safe_u1e/safe_u1e.ucf @@ -3,7 +3,52 @@ NET "CLK_FPGA_P" LOC = "Y11" ; NET "CLK_FPGA_N" LOC = "Y10" ; ## GPMC -#NET "EM_CLK" LOC = "F11" ; +NET "EM_CLK" LOC = "F11" ; + +NET "EM_D<15>" LOC = "D13" ; +NET "EM_D<14>" LOC = "D15" ; +NET "EM_D<13>" LOC = "C16" ; +NET "EM_D<12>" LOC = "B20" ; +NET "EM_D<11>" LOC = "A19" ; +NET "EM_D<10>" LOC = "A17" ; +NET "EM_D<9>" LOC = "E15" ; +NET "EM_D<8>" LOC = "F15" ; +NET "EM_D<7>" LOC = "E16" ; +NET "EM_D<6>" LOC = "F16" ; +NET "EM_D<5>" LOC = "B17" ; +NET "EM_D<4>" LOC = "C17" ; +NET "EM_D<3>" LOC = "B19" ; +NET "EM_D<2>" LOC = "D19" ; +NET "EM_D<1>" LOC = "C19" ; +NET "EM_D<0>" LOC = "A20" ; + +NET "EM_A<10>" LOC = "C14" ; +NET "EM_A<9>" LOC = "C10" ; +NET "EM_A<8>" LOC = "C5" ; +NET "EM_A<7>" LOC = "A18" ; +NET "EM_A<6>" LOC = "A15" ; +NET "EM_A<5>" LOC = "A12" ; +NET "EM_A<4>" LOC = "A10" ; +NET "EM_A<3>" LOC = "E7" ; +NET "EM_A<2>" LOC = "A7" ; +NET "EM_A<1>" LOC = "C15" ; + +#NET "EM_NCS6" LOC = "E17" ; +#NET "EM_NCS5" LOC = "E10" ; +NET "EM_NCS4" LOC = "E6" ; +#NET "EM_NCS1" LOC = "D18" ; +#NET "EM_NCS0" LOC = "D17" ; + +NET "EM_WAIT0" LOC = "F14" ; +#NET "EM_NBE1" LOC = "D14" ; +#NET "EM_NBE0" LOC = "A13" ; +NET "EM_NWP" LOC = "F13" ; +NET "EM_NWE" LOC = "B13" ; +NET "EM_NOE" LOC = "A14" ; +NET "EM_NADV_ALE" LOC = "B15" ; + + +## Overo GPIO #NET "overo_gpio23" LOC = "B3" ; #NET "overo_gpio22" LOC = "A3" ; #NET "overo_gpio21" LOC = "D5" ; @@ -20,47 +65,12 @@ NET "CLK_FPGA_N" LOC = "Y10" ; #NET "overo_gpio128" LOC = "G8" ; #NET "overo_gpio0" LOC = "F9" ; #NET "overo_gpio127" LOC = "C8" ; + +## Overo UART #NET "overo_txd1" LOC = "C6" ; #NET "overo_rxd1" LOC = "D6" ; -#NET "EM_WAIT0" LOC = "F14" ; -#NET "EM_NWP" LOC = "F13" ; -#NET "EM_NBE1" LOC = "D14" ; -#NET "EM_NBE0" LOC = "A13" ; -#NET "EM_NWE" LOC = "B13" ; -#NET "EM_NOE" LOC = "A14" ; -#NET "EM_NADV_ALE" LOC = "B15" ; -#NET "EM_D15" LOC = "D13" ; -#NET "EM_D14" LOC = "D15" ; -#NET "EM_D13" LOC = "C16" ; -#NET "EM_D12" LOC = "B20" ; -#NET "EM_D11" LOC = "A19" ; -#NET "EM_D10" LOC = "A17" ; -#NET "EM_D9" LOC = "E15" ; -#NET "EM_D8" LOC = "F15" ; -#NET "EM_D7" LOC = "E16" ; -#NET "EM_D6" LOC = "F16" ; -#NET "EM_D5" LOC = "B17" ; -#NET "EM_D4" LOC = "C17" ; -#NET "EM_D3" LOC = "B19" ; -#NET "EM_D2" LOC = "D19" ; -#NET "EM_D1" LOC = "C19" ; -#NET "EM_D0" LOC = "A20" ; + #NET "SYSEN" LOC = "C11" ; -#NET "EM_NCS6" LOC = "E17" ; -#NET "EM_NCS5" LOC = "E10" ; -#NET "EM_NCS4" LOC = "E6" ; -#NET "EM_NCS1" LOC = "D18" ; -#NET "EM_NCS0" LOC = "D17" ; -#NET "EM_A10" LOC = "C14" ; -#NET "EM_A9" LOC = "C10" ; -#NET "EM_A8" LOC = "C5" ; -#NET "EM_A7" LOC = "A18" ; -#NET "EM_A6" LOC = "A15" ; -#NET "EM_A5" LOC = "A12" ; -#NET "EM_A4" LOC = "A10" ; -#NET "EM_A3" LOC = "E7" ; -#NET "EM_A2" LOC = "A7" ; -#NET "EM_A1" LOC = "C15" ; #NET "db_scl" LOC = "U4" ; #NET "db_sda" LOC = "U5" ; @@ -83,38 +93,40 @@ NET "CLK_FPGA_N" LOC = "Y10" ; NET "debug_led<2>" LOC = "T5" ; NET "debug_led<1>" LOC = "R2" ; NET "debug_led<0>" LOC = "R1" ; -#NET "debug<0>" LOC = "P6" ; -#NET "debug<1>" LOC = "R6" ; -#NET "debug<2>" LOC = "P1" ; -#NET "debug<3>" LOC = "P2" ; -#NET "debug<4>" LOC = "N6" ; -#NET "debug<5>" LOC = "N5" ; -#NET "debug<6>" LOC = "N1" ; -#NET "debug<7>" LOC = "K2" ; -#NET "debug<8>" LOC = "K3" ; -#NET "debug<9>" LOC = "K6" ; -#NET "debug<10>" LOC = "L5" ; -#NET "debug<11>" LOC = "H2" ; -#NET "debug<12>" LOC = "K4" ; -#NET "debug<13>" LOC = "K5" ; -#NET "debug<14>" LOC = "G1" ; -#NET "debug<15>" LOC = "H1" ; -#NET "debug<16>" LOC = "H5" ; -#NET "debug<17>" LOC = "H6" ; -#NET "debug<18>" LOC = "E3" ; -#NET "debug<19>" LOC = "E4" ; -#NET "debug<20>" LOC = "G5" ; -#NET "debug<21>" LOC = "G6" ; -#NET "debug<22>" LOC = "F2" ; -#NET "debug<23>" LOC = "F1" ; -#NET "debug<24>" LOC = "H3" ; -#NET "debug<25>" LOC = "H4" ; -#NET "debug<26>" LOC = "F4" ; -#NET "debug<27>" LOC = "F5" ; -#NET "debug<28>" LOC = "C2" ; -#NET "debug<29>" LOC = "C1" ; -#NET "debug<30>" LOC = "F3" ; -#NET "debug<31>" LOC = "G3" ; +NET "debug<0>" LOC = "P6" ; +NET "debug<1>" LOC = "R6" ; +NET "debug<2>" LOC = "P1" ; +NET "debug<3>" LOC = "P2" ; +NET "debug<4>" LOC = "N6" ; +NET "debug<5>" LOC = "N5" ; +NET "debug<6>" LOC = "N1" ; +NET "debug<7>" LOC = "K2" ; +NET "debug<8>" LOC = "K3" ; +NET "debug<9>" LOC = "K6" ; +NET "debug<10>" LOC = "L5" ; +NET "debug<11>" LOC = "H2" ; +NET "debug<12>" LOC = "K4" ; +NET "debug<13>" LOC = "K5" ; +NET "debug<14>" LOC = "G1" ; +NET "debug<15>" LOC = "H1" ; +NET "debug<16>" LOC = "H5" ; +NET "debug<17>" LOC = "H6" ; +NET "debug<18>" LOC = "E3" ; +NET "debug<19>" LOC = "E4" ; +NET "debug<20>" LOC = "G5" ; +NET "debug<21>" LOC = "G6" ; +NET "debug<22>" LOC = "F2" ; +NET "debug<23>" LOC = "F1" ; +NET "debug<24>" LOC = "H3" ; +NET "debug<25>" LOC = "H4" ; +NET "debug<26>" LOC = "F4" ; +NET "debug<27>" LOC = "F5" ; +NET "debug<28>" LOC = "C2" ; +NET "debug<29>" LOC = "C1" ; +NET "debug<30>" LOC = "F3" ; +NET "debug<31>" LOC = "G3" ; +NET "debug_clk<0>" LOC = "L6" ; +NET "debug_clk<1>" LOC = "M5" ; #NET "debug_pb<2>" LOC = "Y2" ; #NET "debug_pb<1>" LOC = "AA1" ; @@ -134,8 +146,6 @@ NET "debug_led<0>" LOC = "R1" ; #NET "cgen_st_refmon" LOC = "E1" ; #NET "cgen_sync_b" LOC = "M1" ; #NET "cgen_ref_sel" LOC = "J1" ; -#NET "debug_clk0" LOC = "L6" ; -#NET "debug_clk1" LOC = "M5" ; #NET "GND" LOC = "V19" ; #NET "fpga_cfg_prog_b" LOC = "A2" ; #NET "fpga_cfg_done" LOC = "AB21" ; diff --git a/usrp2/top/safe_u1e/safe_u1e.v b/usrp2/top/safe_u1e/safe_u1e.v index 1b81bab5a..3f16d941c 100644 --- a/usrp2/top/safe_u1e/safe_u1e.v +++ b/usrp2/top/safe_u1e/safe_u1e.v @@ -4,7 +4,11 @@ module safe_u1e ( input CLK_FPGA_P, input CLK_FPGA_N, // Diff - output [2:0] debug_led + output [2:0] debug_led, output [31:0] debug, output [1:0] debug_clk, + + // GPMC + input EM_CLK, input [15:0] EM_D, input [10:1] EM_A, + input EM_WAIT0, input EM_NCS4, input EM_NWP, input EM_NWE, input EM_NOE, input EM_NADV_ALE ); // FPGA-specific pins connections @@ -13,11 +17,15 @@ module safe_u1e IBUFGDS #(.IOSTANDARD("LVDS_33"), .DIFF_TERM("TRUE")) clk_fpga_pin (.O(clk_fpga),.I(CLK_FPGA_P),.IB(CLK_FPGA_N)); + // Debug circuitry reg [31:0] ctr; - always @(posedge clk_fpga) ctr <= ctr + 1; + assign debug_led = ctr[27:25]; - + assign debug_clk = { EM_CLK, clk_fpga }; + assign debug = { { EM_WAIT0, EM_NADV_ALE, EM_NWP, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, + { EM_D } }; + endmodule // safe_u2plus -- cgit v1.2.3 From e091b4812ff4f7e6f959aabf48ac65bac5be86b7 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Sun, 14 Feb 2010 17:23:43 -0800 Subject: reorg pin defs --- usrp2/top/safe_u1e/safe_u1e.ucf | 196 +++++++++++++++++++++------------------- 1 file changed, 102 insertions(+), 94 deletions(-) diff --git a/usrp2/top/safe_u1e/safe_u1e.ucf b/usrp2/top/safe_u1e/safe_u1e.ucf index 14389f299..cb6d6372e 100644 --- a/usrp2/top/safe_u1e/safe_u1e.ucf +++ b/usrp2/top/safe_u1e/safe_u1e.ucf @@ -49,27 +49,30 @@ NET "EM_NADV_ALE" LOC = "B15" ; ## Overo GPIO -#NET "overo_gpio23" LOC = "B3" ; -#NET "overo_gpio22" LOC = "A3" ; -#NET "overo_gpio21" LOC = "D5" ; +#NET "overo_gpio0" LOC = "F9" ; #NET "overo_gpio14" LOC = "C4" ; -#NET "overo_gpio176" LOC = "B4" ; +#NET "overo_gpio21" LOC = "D5" ; +#NET "overo_gpio22" LOC = "A3" ; +#NET "overo_gpio23" LOC = "B3" ; #NET "overo_gpio64" LOC = "A4" ; #NET "overo_gpio65" LOC = "F8" ; -#NET "overo_gpio170" LOC = "E8" ; +#NET "overo_gpio127" LOC = "C8" ; +#NET "overo_gpio128" LOC = "G8" ; +#NET "overo_gpio144" LOC = "A5" ; #NET "overo_gpio145" LOC = "C7" ; -#NET "overo_gpio163" LOC = "D7" ; #NET "overo_gpio146" LOC = "A6" ; -#NET "overo_gpio144" LOC = "A5" ; #NET "overo_gpio147" LOC = "B6" ; -#NET "overo_gpio128" LOC = "G8" ; -#NET "overo_gpio0" LOC = "F9" ; -#NET "overo_gpio127" LOC = "C8" ; +#NET "overo_gpio163" LOC = "D7" ; +#NET "overo_gpio170" LOC = "E8" ; +#NET "overo_gpio176" LOC = "B4" ; ## Overo UART #NET "overo_txd1" LOC = "C6" ; #NET "overo_rxd1" LOC = "D6" ; +#NET "FPGA_TXD" LOC = "U1" ; +#NET "FPGA_RXD" LOC = "T6" ; + #NET "SYSEN" LOC = "C11" ; #NET "db_scl" LOC = "U4" ; @@ -82,12 +85,17 @@ NET "EM_NADV_ALE" LOC = "B15" ; #NET "db_miso_tx" LOC = "W1" ; #NET "db_mosi_tx" LOC = "R3" ; #NET "db_sen_tx" LOC = "T4" ; + +## Clock Gen #NET "cgen_miso" LOC = "U2" ; #NET "cgen_mosi" LOC = "V1" ; #NET "cgen_sclk" LOC = "R5" ; #NET "cgen_sen_b" LOC = "T1" ; -#NET "FPGA_TXD" LOC = "U1" ; -#NET "FPGA_RXD" LOC = "T6" ; +#NET "cgen_st_status" LOC = "D4" ; +#NET "cgen_st_ld" LOC = "D1" ; +#NET "cgen_st_refmon" LOC = "E1" ; +#NET "cgen_sync_b" LOC = "M1" ; +#NET "cgen_ref_sel" LOC = "J1" ; ## Debug pins NET "debug_led<2>" LOC = "T5" ; @@ -141,17 +149,7 @@ NET "debug_clk<1>" LOC = "M5" ; #NET "dip_sw<1>" LOC = "J6" ; #NET "dip_sw<0>" LOC = "J7" ; -#NET "cgen_st_status" LOC = "D4" ; -#NET "cgen_st_ld" LOC = "D1" ; -#NET "cgen_st_refmon" LOC = "E1" ; -#NET "cgen_sync_b" LOC = "M1" ; -#NET "cgen_ref_sel" LOC = "J1" ; -#NET "GND" LOC = "V19" ; -#NET "fpga_cfg_prog_b" LOC = "A2" ; -#NET "fpga_cfg_done" LOC = "AB21" ; -#NET "fpga_cfg_din" LOC = "W17" ; -#NET "fpga_cfg_cclk" LOC = "V17" ; -#NET "fpga_cfg_init_b" LOC = "W15" ; +## AD9862 Interface #NET "aux_sdi_codec" LOC = "F19" ; #NET "aux_sdo_codec" LOC = "F18" ; #NET "aux_sclk_codec" LOC = "D21" ; @@ -163,86 +161,94 @@ NET "debug_clk<1>" LOC = "M5" ; #NET "RXSYNC" LOC = "F22" ; -#NET "DB11" LOC = "E22" ; -#NET "DB10" LOC = "J19" ; -#NET "DB09" LOC = "H20" ; -#NET "DB08" LOC = "G19" ; -#NET "DB07" LOC = "F20" ; -#NET "DB06" LOC = "K16" ; -#NET "DB05" LOC = "J17" ; -#NET "DB04" LOC = "H22" ; -#NET "DB03" LOC = "G22" ; -#NET "DB02" LOC = "H17" ; -#NET "DB01" LOC = "H18" ; -#NET "DB00" LOC = "K20" ; -#NET "DA11" LOC = "J20" ; -#NET "DA10" LOC = "K19" ; -#NET "DA09" LOC = "K18" ; -#NET "DA08" LOC = "L22" ; -#NET "DA07" LOC = "K22" ; -#NET "DA06" LOC = "N22" ; -#NET "DA05" LOC = "M22" ; -#NET "DA04" LOC = "N20" ; -#NET "DA03" LOC = "N19" ; -#NET "DA02" LOC = "R22" ; -#NET "DA01" LOC = "P22" ; -#NET "DA00" LOC = "N17" ; - -#NET "TX13" LOC = "P19" ; -#NET "TX12" LOC = "R18" ; -#NET "TX11" LOC = "U20" ; -#NET "TX10" LOC = "T20" ; -#NET "TX09" LOC = "R19" ; -#NET "TX08" LOC = "R20" ; -#NET "TX07" LOC = "W22" ; -#NET "TX06" LOC = "Y22" ; -#NET "TX05" LOC = "T18" ; -#NET "TX04" LOC = "T17" ; -#NET "TX03" LOC = "W19" ; -#NET "TX02" LOC = "V20" ; -#NET "TX01" LOC = "Y21" ; -#NET "TX00" LOC = "AA22" ; +#NET "DB<11>" LOC = "E22" ; +#NET "DB<10>" LOC = "J19" ; +#NET "DB<9>" LOC = "H20" ; +#NET "DB<8>" LOC = "G19" ; +#NET "DB<7>" LOC = "F20" ; +#NET "DB<6>" LOC = "K16" ; +#NET "DB<5>" LOC = "J17" ; +#NET "DB<4>" LOC = "H22" ; +#NET "DB<3>" LOC = "G22" ; +#NET "DB<2>" LOC = "H17" ; +#NET "DB<1>" LOC = "H18" ; +#NET "DB<0>" LOC = "K20" ; +#NET "DA<11>" LOC = "J20" ; +#NET "DA<10>" LOC = "K19" ; +#NET "DA<9>" LOC = "K18" ; +#NET "DA<8>" LOC = "L22" ; +#NET "DA<7>" LOC = "K22" ; +#NET "DA<6>" LOC = "N22" ; +#NET "DA<5>" LOC = "M22" ; +#NET "DA<4>" LOC = "N20" ; +#NET "DA<3>" LOC = "N19" ; +#NET "DA<2>" LOC = "R22" ; +#NET "DA<1>" LOC = "P22" ; +#NET "DA<0>" LOC = "N17" ; + +#NET "TX<13>" LOC = "P19" ; +#NET "TX<12>" LOC = "R18" ; +#NET "TX<11>" LOC = "U20" ; +#NET "TX<10>" LOC = "T20" ; +#NET "TX<9>" LOC = "R19" ; +#NET "TX<8>" LOC = "R20" ; +#NET "TX<7>" LOC = "W22" ; +#NET "TX<6>" LOC = "Y22" ; +#NET "TX<5>" LOC = "T18" ; +#NET "TX<4>" LOC = "T17" ; +#NET "TX<3>" LOC = "W19" ; +#NET "TX<2>" LOC = "V20" ; +#NET "TX<1>" LOC = "Y21" ; +#NET "TX<0>" LOC = "AA22" ; #NET "TXSYNC" LOC = "U18" ; #NET "TXBLANK" LOC = "U19" ; #NET "PPS_IN" LOC = "M17" ; -#NET "io_tx_00" LOC = "AB20" ; -#NET "io_tx_01" LOC = "Y17" ; -#NET "io_tx_02" LOC = "Y16" ; -#NET "io_tx_03" LOC = "U16" ; -#NET "io_tx_04" LOC = "V16" ; -#NET "io_tx_05" LOC = "AB19" ; -#NET "io_tx_06" LOC = "AA19" ; -#NET "io_tx_07" LOC = "U14" ; -#NET "io_tx_08" LOC = "U15" ; -#NET "io_tx_09" LOC = "AB17" ; -#NET "io_tx_10" LOC = "AB18" ; -#NET "io_tx_11" LOC = "Y13" ; -#NET "io_tx_12" LOC = "W14" ; -#NET "io_tx_13" LOC = "U13" ; -#NET "io_tx_14" LOC = "AA15" ; -#NET "io_tx_15" LOC = "AB14" ; -#NET "io_rx_00" LOC = "Y8" ; -#NET "io_rx_01" LOC = "Y9" ; -#NET "io_rx_02" LOC = "V7" ; -#NET "io_rx_03" LOC = "U8" ; -#NET "io_rx_04" LOC = "V10" ; -#NET "io_rx_05" LOC = "U9" ; -#NET "io_rx_06" LOC = "AB7" ; -#NET "io_rx_07" LOC = "AA8" ; -#NET "io_rx_08" LOC = "W8" ; -#NET "io_rx_09" LOC = "V8" ; -#NET "io_rx_10" LOC = "AB5" ; -#NET "io_rx_11" LOC = "AB6" ; -#NET "io_rx_12" LOC = "AB4" ; -#NET "io_rx_13" LOC = "AA4" ; -#NET "io_rx_14" LOC = "W5" ; -#NET "io_rx_15" LOC = "Y4" ; +#NET "io_tx<0>" LOC = "AB20" ; +#NET "io_tx<1>" LOC = "Y17" ; +#NET "io_tx<2>" LOC = "Y16" ; +#NET "io_tx<3>" LOC = "U16" ; +#NET "io_tx<4>" LOC = "V16" ; +#NET "io_tx<5>" LOC = "AB19" ; +#NET "io_tx<6>" LOC = "AA19" ; +#NET "io_tx<7>" LOC = "U14" ; +#NET "io_tx<8>" LOC = "U15" ; +#NET "io_tx<9>" LOC = "AB17" ; +#NET "io_tx<10>" LOC = "AB18" ; +#NET "io_tx<11>" LOC = "Y13" ; +#NET "io_tx<12>" LOC = "W14" ; +#NET "io_tx<13>" LOC = "U13" ; +#NET "io_tx<14>" LOC = "AA15" ; +#NET "io_tx<15>" LOC = "AB14" ; + +#NET "io_rx<0>" LOC = "Y8" ; +#NET "io_rx<1>" LOC = "Y9" ; +#NET "io_rx<2>" LOC = "V7" ; +#NET "io_rx<3>" LOC = "U8" ; +#NET "io_rx<4>" LOC = "V10" ; +#NET "io_rx<5>" LOC = "U9" ; +#NET "io_rx<6>" LOC = "AB7" ; +#NET "io_rx<7>" LOC = "AA8" ; +#NET "io_rx<8>" LOC = "W8" ; +#NET "io_rx<9>" LOC = "V8" ; +#NET "io_rx<10>" LOC = "AB5" ; +#NET "io_rx<11>" LOC = "AB6" ; +#NET "io_rx<12>" LOC = "AB4" ; +#NET "io_rx<13>" LOC = "AA4" ; +#NET "io_rx<14>" LOC = "W5" ; +#NET "io_rx<15>" LOC = "Y4" ; #NET "CLKOUT2_CODEC" LOC = "U12" ; #NET "CLKOUT1_CODEC" LOC = "V12" ; +## FPGA Config Pins +#NET "fpga_cfg_prog_b" LOC = "A2" ; +#NET "fpga_cfg_done" LOC = "AB21" ; +#NET "fpga_cfg_din" LOC = "W17" ; +#NET "fpga_cfg_cclk" LOC = "V17" ; +#NET "fpga_cfg_init_b" LOC = "W15" ; + ## Unnamed, need to figure out what they do #NET "unnamed_net37" LOC = "B1" ; #NET "unnamed_net36" LOC = "B22" ; @@ -252,3 +258,5 @@ NET "debug_clk<1>" LOC = "M5" ; #NET "unnamed_net44" LOC = "V6" ; #NET "unnamed_net43" LOC = "AA3" ; #NET "unnamed_net42" LOC = "AB3" ; + +#NET "GND" LOC = "V19" ; -- cgit v1.2.3 From 034eeacfe8d35b0e9733dd9183f1a9dbed78f347 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 16 Feb 2010 10:24:18 -0800 Subject: basic read support for the GPMC, responds with 16'hBEEF --- usrp2/top/safe_u1e/safe_u1e.v | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/usrp2/top/safe_u1e/safe_u1e.v b/usrp2/top/safe_u1e/safe_u1e.v index 3f16d941c..ddd203cf9 100644 --- a/usrp2/top/safe_u1e/safe_u1e.v +++ b/usrp2/top/safe_u1e/safe_u1e.v @@ -7,7 +7,7 @@ module safe_u1e output [2:0] debug_led, output [31:0] debug, output [1:0] debug_clk, // GPMC - input EM_CLK, input [15:0] EM_D, input [10:1] EM_A, + input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input EM_WAIT0, input EM_NCS4, input EM_NWP, input EM_NWE, input EM_NOE, input EM_NADV_ALE ); @@ -27,5 +27,11 @@ module safe_u1e assign debug_clk = { EM_CLK, clk_fpga }; assign debug = { { EM_WAIT0, EM_NADV_ALE, EM_NWP, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, { EM_D } }; - + + wire EM_output_enable = (~EM_NOE & ~EM_NCS4); + wire [15:0] EM_D_out = 16'hBEEF; + wire [15:0] EM_D_in = EM_D; + + assign EM_D = EM_output_enable ? EM_D_out : 16'bz; + endmodule // safe_u2plus -- cgit v1.2.3 From 8e76952016272c9898776b6beb7a69f476d4707e Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 16 Feb 2010 16:21:00 -0800 Subject: block ram interface to GPMC --- usrp2/top/safe_u1e/safe_u1e.v | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/usrp2/top/safe_u1e/safe_u1e.v b/usrp2/top/safe_u1e/safe_u1e.v index ddd203cf9..dee9c6067 100644 --- a/usrp2/top/safe_u1e/safe_u1e.v +++ b/usrp2/top/safe_u1e/safe_u1e.v @@ -29,9 +29,13 @@ module safe_u1e { EM_D } }; wire EM_output_enable = (~EM_NOE & ~EM_NCS4); - wire [15:0] EM_D_out = 16'hBEEF; - wire [15:0] EM_D_in = EM_D; + wire [15:0] EM_D_out; assign EM_D = EM_output_enable ? EM_D_out : 16'bz; + + ram_2port #(.DWIDTH(16), .AWIDTH(10)) ram_2port + (.clka(clk_fpga), .ena(~EM_NCS4), .wea(~EM_NWE), .addra(EM_A), .dia(EM_D), .doa(EM_D_out), + .clkb(clk_fpga), .enb(0), .web(0), .addrb(0), .dib(0), .dob()); + endmodule // safe_u2plus -- cgit v1.2.3 From c1ddc5c082c053eaa46c8bc87064d3e3e56b0d9e Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 16 Feb 2010 16:29:44 -0800 Subject: copied over from safe_u1e --- usrp2/top/u1e/.gitignore | 4 + usrp2/top/u1e/Makefile | 246 ++++++++++++++++++++++++++++++++++++++++++++ usrp2/top/u1e/u1e.ucf | 262 +++++++++++++++++++++++++++++++++++++++++++++++ usrp2/top/u1e/u1e.v | 41 ++++++++ 4 files changed, 553 insertions(+) create mode 100644 usrp2/top/u1e/.gitignore create mode 100644 usrp2/top/u1e/Makefile create mode 100644 usrp2/top/u1e/u1e.ucf create mode 100644 usrp2/top/u1e/u1e.v diff --git a/usrp2/top/u1e/.gitignore b/usrp2/top/u1e/.gitignore new file mode 100644 index 000000000..f8b57ea21 --- /dev/null +++ b/usrp2/top/u1e/.gitignore @@ -0,0 +1,4 @@ +*~ +build +*.log +*.cmd diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile new file mode 100644 index 000000000..e9c101226 --- /dev/null +++ b/usrp2/top/u1e/Makefile @@ -0,0 +1,246 @@ +# +# 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 := u1e +export PROJ_FILE := $(BUILD_DIR)$(TOP_MODULE).ise + +################################################## +# Project Properties +################################################## +export PROJECT_PROPERTIES := \ +family "Spartan-3A DSP" \ +device xc3sd1800a \ +package cs484 \ +speed -4 \ +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/dcache.v \ +control_lib/decoder_3_8.v \ +control_lib/dpram32.v \ +control_lib/gray2bin.v \ +control_lib/gray_send.v \ +control_lib/icache.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/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 \ +control_lib/reset_sync.v \ +simple_gemac/simple_gemac_wrapper.v \ +simple_gemac/simple_gemac.v \ +simple_gemac/simple_gemac_wb.v \ +simple_gemac/simple_gemac_tx.v \ +simple_gemac/simple_gemac_rx.v \ +simple_gemac/crc.v \ +simple_gemac/delay_line.v \ +simple_gemac/flow_ctrl_tx.v \ +simple_gemac/flow_ctrl_rx.v \ +simple_gemac/address_filter.v \ +simple_gemac/ll8_to_txmac.v \ +simple_gemac/rxmac_to_ll8.v \ +simple_gemac/miim/eth_miim.v \ +simple_gemac/miim/eth_clockgen.v \ +simple_gemac/miim/eth_outputcontrol.v \ +simple_gemac/miim/eth_shiftreg.v \ +control_lib/newfifo/buffer_int.v \ +control_lib/newfifo/buffer_pool.v \ +control_lib/newfifo/fifo_2clock.v \ +control_lib/newfifo/fifo_2clock_cascade.v \ +control_lib/newfifo/ll8_shortfifo.v \ +control_lib/newfifo/ll8_to_fifo36.v \ +control_lib/newfifo/fifo_short.v \ +control_lib/newfifo/fifo_long.v \ +control_lib/newfifo/fifo_cascade.v \ +control_lib/newfifo/fifo36_to_ll8.v \ +control_lib/longfifo.v \ +control_lib/shortfifo.v \ +control_lib/medfifo.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 \ +coregen/fifo_xlnx_64x36_2clk.v \ +coregen/fifo_xlnx_64x36_2clk.xco \ +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/u1e/u1e.ucf \ +top/u1e/u1e.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 \ +"Unused IOB Pins" "Pull Up" + +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/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf new file mode 100644 index 000000000..cb6d6372e --- /dev/null +++ b/usrp2/top/u1e/u1e.ucf @@ -0,0 +1,262 @@ + +NET "CLK_FPGA_P" LOC = "Y11" ; +NET "CLK_FPGA_N" LOC = "Y10" ; + +## GPMC +NET "EM_CLK" LOC = "F11" ; + +NET "EM_D<15>" LOC = "D13" ; +NET "EM_D<14>" LOC = "D15" ; +NET "EM_D<13>" LOC = "C16" ; +NET "EM_D<12>" LOC = "B20" ; +NET "EM_D<11>" LOC = "A19" ; +NET "EM_D<10>" LOC = "A17" ; +NET "EM_D<9>" LOC = "E15" ; +NET "EM_D<8>" LOC = "F15" ; +NET "EM_D<7>" LOC = "E16" ; +NET "EM_D<6>" LOC = "F16" ; +NET "EM_D<5>" LOC = "B17" ; +NET "EM_D<4>" LOC = "C17" ; +NET "EM_D<3>" LOC = "B19" ; +NET "EM_D<2>" LOC = "D19" ; +NET "EM_D<1>" LOC = "C19" ; +NET "EM_D<0>" LOC = "A20" ; + +NET "EM_A<10>" LOC = "C14" ; +NET "EM_A<9>" LOC = "C10" ; +NET "EM_A<8>" LOC = "C5" ; +NET "EM_A<7>" LOC = "A18" ; +NET "EM_A<6>" LOC = "A15" ; +NET "EM_A<5>" LOC = "A12" ; +NET "EM_A<4>" LOC = "A10" ; +NET "EM_A<3>" LOC = "E7" ; +NET "EM_A<2>" LOC = "A7" ; +NET "EM_A<1>" LOC = "C15" ; + +#NET "EM_NCS6" LOC = "E17" ; +#NET "EM_NCS5" LOC = "E10" ; +NET "EM_NCS4" LOC = "E6" ; +#NET "EM_NCS1" LOC = "D18" ; +#NET "EM_NCS0" LOC = "D17" ; + +NET "EM_WAIT0" LOC = "F14" ; +#NET "EM_NBE1" LOC = "D14" ; +#NET "EM_NBE0" LOC = "A13" ; +NET "EM_NWP" LOC = "F13" ; +NET "EM_NWE" LOC = "B13" ; +NET "EM_NOE" LOC = "A14" ; +NET "EM_NADV_ALE" LOC = "B15" ; + + +## Overo GPIO +#NET "overo_gpio0" LOC = "F9" ; +#NET "overo_gpio14" LOC = "C4" ; +#NET "overo_gpio21" LOC = "D5" ; +#NET "overo_gpio22" LOC = "A3" ; +#NET "overo_gpio23" LOC = "B3" ; +#NET "overo_gpio64" LOC = "A4" ; +#NET "overo_gpio65" LOC = "F8" ; +#NET "overo_gpio127" LOC = "C8" ; +#NET "overo_gpio128" LOC = "G8" ; +#NET "overo_gpio144" LOC = "A5" ; +#NET "overo_gpio145" LOC = "C7" ; +#NET "overo_gpio146" LOC = "A6" ; +#NET "overo_gpio147" LOC = "B6" ; +#NET "overo_gpio163" LOC = "D7" ; +#NET "overo_gpio170" LOC = "E8" ; +#NET "overo_gpio176" LOC = "B4" ; + +## Overo UART +#NET "overo_txd1" LOC = "C6" ; +#NET "overo_rxd1" LOC = "D6" ; + +#NET "FPGA_TXD" LOC = "U1" ; +#NET "FPGA_RXD" LOC = "T6" ; + +#NET "SYSEN" LOC = "C11" ; + +#NET "db_scl" LOC = "U4" ; +#NET "db_sda" LOC = "U5" ; +#NET "db_sclk_rx" LOC = "W3" ; +#NET "db_miso_rx" LOC = "W2" ; +#NET "db_mosi_rx" LOC = "V4" ; +#NET "db_sen_rx" LOC = "V3" ; +#NET "db_sclk_tx" LOC = "Y1" ; +#NET "db_miso_tx" LOC = "W1" ; +#NET "db_mosi_tx" LOC = "R3" ; +#NET "db_sen_tx" LOC = "T4" ; + +## Clock Gen +#NET "cgen_miso" LOC = "U2" ; +#NET "cgen_mosi" LOC = "V1" ; +#NET "cgen_sclk" LOC = "R5" ; +#NET "cgen_sen_b" LOC = "T1" ; +#NET "cgen_st_status" LOC = "D4" ; +#NET "cgen_st_ld" LOC = "D1" ; +#NET "cgen_st_refmon" LOC = "E1" ; +#NET "cgen_sync_b" LOC = "M1" ; +#NET "cgen_ref_sel" LOC = "J1" ; + +## Debug pins +NET "debug_led<2>" LOC = "T5" ; +NET "debug_led<1>" LOC = "R2" ; +NET "debug_led<0>" LOC = "R1" ; +NET "debug<0>" LOC = "P6" ; +NET "debug<1>" LOC = "R6" ; +NET "debug<2>" LOC = "P1" ; +NET "debug<3>" LOC = "P2" ; +NET "debug<4>" LOC = "N6" ; +NET "debug<5>" LOC = "N5" ; +NET "debug<6>" LOC = "N1" ; +NET "debug<7>" LOC = "K2" ; +NET "debug<8>" LOC = "K3" ; +NET "debug<9>" LOC = "K6" ; +NET "debug<10>" LOC = "L5" ; +NET "debug<11>" LOC = "H2" ; +NET "debug<12>" LOC = "K4" ; +NET "debug<13>" LOC = "K5" ; +NET "debug<14>" LOC = "G1" ; +NET "debug<15>" LOC = "H1" ; +NET "debug<16>" LOC = "H5" ; +NET "debug<17>" LOC = "H6" ; +NET "debug<18>" LOC = "E3" ; +NET "debug<19>" LOC = "E4" ; +NET "debug<20>" LOC = "G5" ; +NET "debug<21>" LOC = "G6" ; +NET "debug<22>" LOC = "F2" ; +NET "debug<23>" LOC = "F1" ; +NET "debug<24>" LOC = "H3" ; +NET "debug<25>" LOC = "H4" ; +NET "debug<26>" LOC = "F4" ; +NET "debug<27>" LOC = "F5" ; +NET "debug<28>" LOC = "C2" ; +NET "debug<29>" LOC = "C1" ; +NET "debug<30>" LOC = "F3" ; +NET "debug<31>" LOC = "G3" ; +NET "debug_clk<0>" LOC = "L6" ; +NET "debug_clk<1>" LOC = "M5" ; + +#NET "debug_pb<2>" LOC = "Y2" ; +#NET "debug_pb<1>" LOC = "AA1" ; +#NET "debug_pb<0>" LOC = "N3" ; + +#NET "dip_sw<7>" LOC = "T3" ; +#NET "dip_sw<6>" LOC = "U3" ; +#NET "dip_sw<5>" LOC = "M3" ; +#NET "dip_sw<4>" LOC = "N4" ; +#NET "dip_sw<3>" LOC = "J3" ; +#NET "dip_sw<2>" LOC = "J4" ; +#NET "dip_sw<1>" LOC = "J6" ; +#NET "dip_sw<0>" LOC = "J7" ; + +## AD9862 Interface +#NET "aux_sdi_codec" LOC = "F19" ; +#NET "aux_sdo_codec" LOC = "F18" ; +#NET "aux_sclk_codec" LOC = "D21" ; +#NET "reset_codec" LOC = "D22" ; +#NET "sen_codec" LOC = "D20" ; +#NET "mosi_codec" LOC = "E19" ; +#NET "miso_codec" LOC = "F21" ; +#NET "sclk_codec" LOC = "E20" ; + +#NET "RXSYNC" LOC = "F22" ; + +#NET "DB<11>" LOC = "E22" ; +#NET "DB<10>" LOC = "J19" ; +#NET "DB<9>" LOC = "H20" ; +#NET "DB<8>" LOC = "G19" ; +#NET "DB<7>" LOC = "F20" ; +#NET "DB<6>" LOC = "K16" ; +#NET "DB<5>" LOC = "J17" ; +#NET "DB<4>" LOC = "H22" ; +#NET "DB<3>" LOC = "G22" ; +#NET "DB<2>" LOC = "H17" ; +#NET "DB<1>" LOC = "H18" ; +#NET "DB<0>" LOC = "K20" ; +#NET "DA<11>" LOC = "J20" ; +#NET "DA<10>" LOC = "K19" ; +#NET "DA<9>" LOC = "K18" ; +#NET "DA<8>" LOC = "L22" ; +#NET "DA<7>" LOC = "K22" ; +#NET "DA<6>" LOC = "N22" ; +#NET "DA<5>" LOC = "M22" ; +#NET "DA<4>" LOC = "N20" ; +#NET "DA<3>" LOC = "N19" ; +#NET "DA<2>" LOC = "R22" ; +#NET "DA<1>" LOC = "P22" ; +#NET "DA<0>" LOC = "N17" ; + +#NET "TX<13>" LOC = "P19" ; +#NET "TX<12>" LOC = "R18" ; +#NET "TX<11>" LOC = "U20" ; +#NET "TX<10>" LOC = "T20" ; +#NET "TX<9>" LOC = "R19" ; +#NET "TX<8>" LOC = "R20" ; +#NET "TX<7>" LOC = "W22" ; +#NET "TX<6>" LOC = "Y22" ; +#NET "TX<5>" LOC = "T18" ; +#NET "TX<4>" LOC = "T17" ; +#NET "TX<3>" LOC = "W19" ; +#NET "TX<2>" LOC = "V20" ; +#NET "TX<1>" LOC = "Y21" ; +#NET "TX<0>" LOC = "AA22" ; +#NET "TXSYNC" LOC = "U18" ; +#NET "TXBLANK" LOC = "U19" ; + +#NET "PPS_IN" LOC = "M17" ; + +#NET "io_tx<0>" LOC = "AB20" ; +#NET "io_tx<1>" LOC = "Y17" ; +#NET "io_tx<2>" LOC = "Y16" ; +#NET "io_tx<3>" LOC = "U16" ; +#NET "io_tx<4>" LOC = "V16" ; +#NET "io_tx<5>" LOC = "AB19" ; +#NET "io_tx<6>" LOC = "AA19" ; +#NET "io_tx<7>" LOC = "U14" ; +#NET "io_tx<8>" LOC = "U15" ; +#NET "io_tx<9>" LOC = "AB17" ; +#NET "io_tx<10>" LOC = "AB18" ; +#NET "io_tx<11>" LOC = "Y13" ; +#NET "io_tx<12>" LOC = "W14" ; +#NET "io_tx<13>" LOC = "U13" ; +#NET "io_tx<14>" LOC = "AA15" ; +#NET "io_tx<15>" LOC = "AB14" ; + +#NET "io_rx<0>" LOC = "Y8" ; +#NET "io_rx<1>" LOC = "Y9" ; +#NET "io_rx<2>" LOC = "V7" ; +#NET "io_rx<3>" LOC = "U8" ; +#NET "io_rx<4>" LOC = "V10" ; +#NET "io_rx<5>" LOC = "U9" ; +#NET "io_rx<6>" LOC = "AB7" ; +#NET "io_rx<7>" LOC = "AA8" ; +#NET "io_rx<8>" LOC = "W8" ; +#NET "io_rx<9>" LOC = "V8" ; +#NET "io_rx<10>" LOC = "AB5" ; +#NET "io_rx<11>" LOC = "AB6" ; +#NET "io_rx<12>" LOC = "AB4" ; +#NET "io_rx<13>" LOC = "AA4" ; +#NET "io_rx<14>" LOC = "W5" ; +#NET "io_rx<15>" LOC = "Y4" ; + +#NET "CLKOUT2_CODEC" LOC = "U12" ; +#NET "CLKOUT1_CODEC" LOC = "V12" ; + +## FPGA Config Pins +#NET "fpga_cfg_prog_b" LOC = "A2" ; +#NET "fpga_cfg_done" LOC = "AB21" ; +#NET "fpga_cfg_din" LOC = "W17" ; +#NET "fpga_cfg_cclk" LOC = "V17" ; +#NET "fpga_cfg_init_b" LOC = "W15" ; + +## Unnamed, need to figure out what they do +#NET "unnamed_net37" LOC = "B1" ; +#NET "unnamed_net36" LOC = "B22" ; +#NET "unnamed_net35" LOC = "D2" ; +#NET "unnamed_net34" LOC = "A21" ; +#NET "unnamed_net45" LOC = "F7" ; +#NET "unnamed_net44" LOC = "V6" ; +#NET "unnamed_net43" LOC = "AA3" ; +#NET "unnamed_net42" LOC = "AB3" ; + +#NET "GND" LOC = "V19" ; diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v new file mode 100644 index 000000000..e28a6a582 --- /dev/null +++ b/usrp2/top/u1e/u1e.v @@ -0,0 +1,41 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// + +module u1e + ( + input CLK_FPGA_P, input CLK_FPGA_N, // Diff + output [2:0] debug_led, output [31:0] debug, output [1:0] debug_clk, + + // GPMC + input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, + input EM_WAIT0, input EM_NCS4, input EM_NWP, input EM_NWE, input EM_NOE, input EM_NADV_ALE + ); + + // FPGA-specific pins connections + wire clk_fpga; + + IBUFGDS #(.IOSTANDARD("LVDS_33"), .DIFF_TERM("TRUE")) + clk_fpga_pin (.O(clk_fpga),.I(CLK_FPGA_P),.IB(CLK_FPGA_N)); + + // Debug circuitry + reg [31:0] ctr; + always @(posedge clk_fpga) + ctr <= ctr + 1; + + + assign debug_led = ctr[27:25]; + assign debug_clk = { EM_CLK, clk_fpga }; + assign debug = { { EM_WAIT0, EM_NADV_ALE, EM_NWP, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, + { EM_D } }; + + wire EM_output_enable = (~EM_NOE & ~EM_NCS4); + wire [15:0] EM_D_out; + + assign EM_D = EM_output_enable ? EM_D_out : 16'bz; + + ram_2port #(.DWIDTH(16), .AWIDTH(10)) ram_2port + (.clka(clk_fpga), .ena(~EM_NCS4), .wea(~EM_NWE), .addra(EM_A), .dia(EM_D), .doa(EM_D_out), + .clkb(clk_fpga), .enb(0), .web(0), .addrb(0), .dib(0), .dob()); + + +endmodule // u2plus -- cgit v1.2.3 From b115e4d7661d64c6d20f0421908622b56a91e950 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 16 Feb 2010 18:47:22 -0800 Subject: first cut at gpmc <-> wb bridge, split u1e into core, top, and tb --- .gitignore | 1 + usrp2/gpmc/gpmc.v | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ usrp2/top/u1e/Makefile | 3 ++- usrp2/top/u1e/tb_u1e.v | 25 ++++++++++++++++++ usrp2/top/u1e/u1e.ucf | 14 +++++----- usrp2/top/u1e/u1e.v | 33 ++++++------------------ usrp2/top/u1e/u1e_core.v | 52 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 160 insertions(+), 34 deletions(-) create mode 100644 .gitignore create mode 100644 usrp2/gpmc/gpmc.v create mode 100644 usrp2/top/u1e/tb_u1e.v create mode 100644 usrp2/top/u1e/u1e_core.v diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..b25c15b81 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/usrp2/gpmc/gpmc.v b/usrp2/gpmc/gpmc.v new file mode 100644 index 000000000..96ee139fd --- /dev/null +++ b/usrp2/gpmc/gpmc.v @@ -0,0 +1,66 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// + +module gpmc + (input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, + input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, + + input wb_clk, input wb_rst, + output reg [10:0] wb_adr_o, output reg [15:0] wb_dat_mosi, input [15:0] wb_dat_miso, + output reg [1:0] wb_sel_o, output wb_cyc_o, output reg wb_stb_o, output reg wb_we_o, input wb_ack_i + ); + + wire EM_output_enable = (~EM_NOE & (~EM_NCS4 | ~EM_NCS6)); + wire [15:0] EM_D_ram; + reg [15:0] EM_D_wb; + + assign EM_D = ~EM_output_enable ? 16'bz : ~EM_NCS4 ? EM_D_ram : EM_D_wb; + + // CS4 is RAM_2PORT for high-speed data + ram_2port #(.DWIDTH(16), .AWIDTH(10)) ram_2port + (.clka(clk_fpga), .ena(~EM_NCS4), .wea(~EM_NWE), .addra(EM_A), .dia(EM_D), .doa(EM_D_ram), + .clkb(clk_fpga), .enb(0), .web(0), .addrb(0), .dib(0), .dob()); + + // CS6 is Control, Wishbone bus bridge (wb master) + // Sync version + reg [1:0] cs_del, we_del, oe_del; + + // Synchronize the async control signals + always @(posedge wb_clk) + begin + cs_del <= { cs_del[0], EM_NCS6 }; + we_del <= { we_del[0], EM_NWE }; + oe_del <= { oe_del[0], EM_NOE }; + end + + always @(posedge wb_clk) + if(cs_del == 2'b10) // Falling Edge + wb_adr_o <= { EM_A, 1'b0 }; + + always @(posedge wb_clk) + if(we_del == 2'b10) // Falling Edge + begin + wb_dat_mosi <= EM_D; + wb_sel_o <= ~EM_NBE; + end + + always @(posedge wb_clk) + if(wb_ack_i) + EM_D_wb <= wb_dat_miso; + + // stb, oe_del, we_del + assign wb_cyc_o = wb_stb_o; + + always @(posedge wb_clk) + if( ~cs_del[0] & (we_del == 2'b10) ) + wb_we_o <= 1; + else if(wb_ack_i) // Turn off we when done. Could also use we_del[0], others... + wb_we_o <= 0; + + always @(posedge wb_clk) + if( ~cs_del[0] & ((we_del == 2'b10) | (oe_del == 2'b10))) + wb_stb_o <= 1; + else if(wb_ack_i) + wb_stb_o <= 0; + +endmodule // gpmc diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index e9c101226..cdbdf995e 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -174,7 +174,8 @@ timing/time_receiver.v \ timing/time_sender.v \ timing/time_sync.v \ timing/timer.v \ -top/u2_core/u2_core.v \ +gpmc/gpmc.v \ +top/u1e/u1e_core.v \ top/u1e/u1e.ucf \ top/u1e/u1e.v diff --git a/usrp2/top/u1e/tb_u1e.v b/usrp2/top/u1e/tb_u1e.v new file mode 100644 index 000000000..6e0c60e17 --- /dev/null +++ b/usrp2/top/u1e/tb_u1e.v @@ -0,0 +1,25 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// + +module tb_u1e(); + + wire [2:0] debug_led; + wire [31:0] debug; + wire [1:0] debug_clk; + + + // GPMC + wire EM_CLK, EM_WAIT0, EM_NCS4, EM_NCS6, EM_NWE, EM_NOE; + wire [15:0] EM_D; + wire [10:1] EM_A; + wire [1:0] EM_NBE; + + reg clk_fpga = 0; + always #100 clk_fpga = ~clk_fpga; + + u1e_core u1e_core(.clk_fpga(clk_fpga), .debug_led(debug_led), .debug(debug), .debug_clk(debug_clk), + .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), + .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), + .EM_NWE(EM_NWE), .EM_NOE(EM_NOE) ); + +endmodule // u1e diff --git a/usrp2/top/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf index cb6d6372e..3b524a6ea 100644 --- a/usrp2/top/u1e/u1e.ucf +++ b/usrp2/top/u1e/u1e.ucf @@ -3,8 +3,6 @@ NET "CLK_FPGA_P" LOC = "Y11" ; NET "CLK_FPGA_N" LOC = "Y10" ; ## GPMC -NET "EM_CLK" LOC = "F11" ; - NET "EM_D<15>" LOC = "D13" ; NET "EM_D<14>" LOC = "D15" ; NET "EM_D<13>" LOC = "C16" ; @@ -33,20 +31,20 @@ NET "EM_A<3>" LOC = "E7" ; NET "EM_A<2>" LOC = "A7" ; NET "EM_A<1>" LOC = "C15" ; -#NET "EM_NCS6" LOC = "E17" ; +NET "EM_NCS6" LOC = "E17" ; #NET "EM_NCS5" LOC = "E10" ; NET "EM_NCS4" LOC = "E6" ; #NET "EM_NCS1" LOC = "D18" ; #NET "EM_NCS0" LOC = "D17" ; +NET "EM_CLK" LOC = "F11" ; NET "EM_WAIT0" LOC = "F14" ; -#NET "EM_NBE1" LOC = "D14" ; -#NET "EM_NBE0" LOC = "A13" ; -NET "EM_NWP" LOC = "F13" ; +NET "EM_NBE<1>" LOC = "D14" ; +NET "EM_NBE<0>" LOC = "A13" ; NET "EM_NWE" LOC = "B13" ; NET "EM_NOE" LOC = "A14" ; -NET "EM_NADV_ALE" LOC = "B15" ; - +#NET "EM_NADV_ALE" LOC = "B15" ; +#NET "EM_NWP" LOC = "F13" ; ## Overo GPIO #NET "overo_gpio0" LOC = "F9" ; diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index e28a6a582..8832d6e11 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -2,13 +2,12 @@ ////////////////////////////////////////////////////////////////////////////////// module u1e - ( - input CLK_FPGA_P, input CLK_FPGA_N, // Diff + (input CLK_FPGA_P, input CLK_FPGA_N, // Diff output [2:0] debug_led, output [31:0] debug, output [1:0] debug_clk, // GPMC - input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, - input EM_WAIT0, input EM_NCS4, input EM_NWP, input EM_NWE, input EM_NOE, input EM_NADV_ALE + input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, + input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE ); // FPGA-specific pins connections @@ -17,25 +16,9 @@ module u1e IBUFGDS #(.IOSTANDARD("LVDS_33"), .DIFF_TERM("TRUE")) clk_fpga_pin (.O(clk_fpga),.I(CLK_FPGA_P),.IB(CLK_FPGA_N)); - // Debug circuitry - reg [31:0] ctr; - always @(posedge clk_fpga) - ctr <= ctr + 1; - - - assign debug_led = ctr[27:25]; - assign debug_clk = { EM_CLK, clk_fpga }; - assign debug = { { EM_WAIT0, EM_NADV_ALE, EM_NWP, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, - { EM_D } }; - - wire EM_output_enable = (~EM_NOE & ~EM_NCS4); - wire [15:0] EM_D_out; - - assign EM_D = EM_output_enable ? EM_D_out : 16'bz; - - ram_2port #(.DWIDTH(16), .AWIDTH(10)) ram_2port - (.clka(clk_fpga), .ena(~EM_NCS4), .wea(~EM_NWE), .addra(EM_A), .dia(EM_D), .doa(EM_D_out), - .clkb(clk_fpga), .enb(0), .web(0), .addrb(0), .dib(0), .dob()); + u1e_core u1e_core(.clk_fpga(clk_fpga), .debug_led(debug_led), .debug(debug), .debug_clk(debug_clk), + .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), + .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), + .EM_NWE(EM_NWE), .EM_NOE(EM_NOE) ); - -endmodule // u2plus +endmodule // u1e diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v new file mode 100644 index 000000000..2481549b2 --- /dev/null +++ b/usrp2/top/u1e/u1e_core.v @@ -0,0 +1,52 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// + +module u1e_core + (input clk_fpga, output [2:0] debug_led, output [31:0] debug, output [1:0] debug_clk, + + // GPMC + input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, + input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE + ); + + // Debug circuitry + reg [31:0] ctr; + always @(posedge clk_fpga) + ctr <= ctr + 1; + + assign debug_led = ctr[27:25]; + assign debug_clk = { EM_CLK, clk_fpga }; + assign debug = { { 1'b0, EM_WAIT0, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, + { EM_D } }; + + wire wb_clk, wb_rst; + wire wb_cyc, wb_stb, wb_we, wb_ack; + wire [1:0] wb_sel; + wire [10:0] wb_adr; + wire [15:0] wb_dat_mosi, wb_dat_miso; + + gpmc gpmc (.EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), + .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), + .EM_NOE(EM_NOE), + + .wb_clk(wb_clk), .wb_rst(wb_rst), + .wb_adr_o(wb_adr), .wb_dat_mosi(wb_dat_mosi), .wb_dat_miso(wb_dat_miso), + .wb_sel_o(wb_sel), .wb_cyc_o(wb_cyc), .wb_stb_o(wb_stb), .wb_we_o(wb_we), + .wb_ack_i(wb_ack)); + + assign wb_clk = clk_fpga; + reg [15:0] reg_fast, reg_slow; + + localparam [10:0] WB_ADR_REG_FAST = 36; + localparam [10:0] WB_ADR_REG_SLOW = 38; + + always @(posedge wb_clk) + if(wb_cyc & wb_stb & wb_we & (wb_adr == WB_ADR_REG_FAST)) + reg_fast <= wb_dat_mosi; + + assign wb_dat_miso = (wb_adr == WB_ADR_REG_FAST) ? reg_fast : 16'bx; + + assign wb_ack = wb_stb & wb_cyc; + + +endmodule // u2plus -- cgit v1.2.3 From d4649caee02a1c76802dc4f8d7d76bb31b14ce09 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 16 Feb 2010 22:49:02 -0800 Subject: wishbone bridge now with minimal functionality. Need to check timing and handle wait states. --- usrp2/gpmc/gpmc.v | 4 +-- usrp2/models/gpmc_model.v | 70 +++++++++++++++++++++++++++++++++++++++++++++++ usrp2/top/u1e/.gitignore | 2 ++ usrp2/top/u1e/README | 4 +++ usrp2/top/u1e/cmdfile | 19 +++++++++++++ usrp2/top/u1e/make.sim | 7 +++++ usrp2/top/u1e/tb_u1e.v | 17 +++++++++--- usrp2/top/u1e/u1e_core.v | 9 +++--- 8 files changed, 121 insertions(+), 11 deletions(-) create mode 100644 usrp2/models/gpmc_model.v create mode 100644 usrp2/top/u1e/README create mode 100644 usrp2/top/u1e/cmdfile create mode 100644 usrp2/top/u1e/make.sim diff --git a/usrp2/gpmc/gpmc.v b/usrp2/gpmc/gpmc.v index 96ee139fd..1963af6e6 100644 --- a/usrp2/gpmc/gpmc.v +++ b/usrp2/gpmc/gpmc.v @@ -18,8 +18,8 @@ module gpmc // CS4 is RAM_2PORT for high-speed data ram_2port #(.DWIDTH(16), .AWIDTH(10)) ram_2port - (.clka(clk_fpga), .ena(~EM_NCS4), .wea(~EM_NWE), .addra(EM_A), .dia(EM_D), .doa(EM_D_ram), - .clkb(clk_fpga), .enb(0), .web(0), .addrb(0), .dib(0), .dob()); + (.clka(wb_clk), .ena(~EM_NCS4), .wea(~EM_NWE), .addra(EM_A), .dia(EM_D), .doa(EM_D_ram), + .clkb(wb_clk), .enb(0), .web(0), .addrb(0), .dib(0), .dob()); // CS6 is Control, Wishbone bus bridge (wb master) // Sync version diff --git a/usrp2/models/gpmc_model.v b/usrp2/models/gpmc_model.v new file mode 100644 index 000000000..ce3acaacf --- /dev/null +++ b/usrp2/models/gpmc_model.v @@ -0,0 +1,70 @@ + + +module gpmc_model + (output EM_CLK, inout [15:0] EM_D, output reg [10:1] EM_A, output reg [1:0] EM_NBE, + output reg EM_WAIT0, output reg EM_NCS4, output reg EM_NCS6, + output reg EM_NWE, output reg EM_NOE ); + + assign EM_CLK = 0; + reg [15:0] EM_D_int; + assign EM_D = EM_D_int; + + initial + begin + EM_A <= 10'bz; + EM_NBE <= 2'b11; + EM_NWE <= 1; + EM_NOE <= 1; + EM_NCS4 <= 1; + EM_NCS6 <= 1; + EM_D_int <= 16'bz; + EM_WAIT0 <= 0; // FIXME this is actually an input + end + + task GPMC_Write; + input [10:0] addr; + input [15:0] data; + begin + #2; + EM_A <= addr[10:1]; + EM_D_int <= data; + #4; + EM_NCS6 <= 0; + #5; + EM_NWE <= 0; + #41; + EM_NWE <= 1; + EM_NCS6 <= 1; + EM_A <= 10'bz; + EM_D_int <= 16'bz; + end + endtask // GPMC_Write + + task GPMC_Read; + input [10:0] addr; + begin + #2; + EM_A <= addr[10:1]; + #4; + EM_NCS6 <= 0; + #5; + EM_NOE <= 0; + #41; + EM_NOE <= 1; + EM_NCS6 <= 1; + EM_A <= 10'bz; + $display("Data Read from GPMC: %X",EM_D); + end + endtask // GPMC_Read + + initial + begin + #1000; + GPMC_Write(36,16'hBEEF); + #1000; + GPMC_Read(36); + #1000; + $finish; + end + +endmodule // gpmc_model diff --git a/usrp2/top/u1e/.gitignore b/usrp2/top/u1e/.gitignore index f8b57ea21..8d872713e 100644 --- a/usrp2/top/u1e/.gitignore +++ b/usrp2/top/u1e/.gitignore @@ -2,3 +2,5 @@ build *.log *.cmd +tb_u1e +*.lxt diff --git a/usrp2/top/u1e/README b/usrp2/top/u1e/README new file mode 100644 index 000000000..14c7a4955 --- /dev/null +++ b/usrp2/top/u1e/README @@ -0,0 +1,4 @@ + +make clean +make sim +./tb_u1e -lxt2 diff --git a/usrp2/top/u1e/cmdfile b/usrp2/top/u1e/cmdfile new file mode 100644 index 000000000..5e4db5c65 --- /dev/null +++ b/usrp2/top/u1e/cmdfile @@ -0,0 +1,19 @@ + +# My stuff +-y . +-y ../../control_lib +-y ../../control_lib/newfifo +-y ../../sdr_lib +-y ../../timing +-y ../../coregen +-y ../../gpmc + +# Models +-y ../../models + +# Open Cores +-y ../opencores/spi/rtl/verilog ++incdir+../opencores/spi/rtl/verilog +-y ../opencores/i2c/rtl/verilog ++incdir+../opencores/i2c/rtl/verilog + diff --git a/usrp2/top/u1e/make.sim b/usrp2/top/u1e/make.sim new file mode 100644 index 000000000..1c163884c --- /dev/null +++ b/usrp2/top/u1e/make.sim @@ -0,0 +1,7 @@ +all: sim + +sim: + iverilog -Wimplicit -Wportbind -c cmdfile tb_u1e.v -o tb_u1e + +clean: + rm -f tb_u1e *.vcd *.lxt a.out diff --git a/usrp2/top/u1e/tb_u1e.v b/usrp2/top/u1e/tb_u1e.v index 6e0c60e17..85d2b49f0 100644 --- a/usrp2/top/u1e/tb_u1e.v +++ b/usrp2/top/u1e/tb_u1e.v @@ -6,8 +6,12 @@ module tb_u1e(); wire [2:0] debug_led; wire [31:0] debug; wire [1:0] debug_clk; - - + + initial begin + $dumpfile("tb_u1e.lxt"); + $dumpvars(0,tb_u1e); + end + // GPMC wire EM_CLK, EM_WAIT0, EM_NCS4, EM_NCS6, EM_NWE, EM_NOE; wire [15:0] EM_D; @@ -15,11 +19,16 @@ module tb_u1e(); wire [1:0] EM_NBE; reg clk_fpga = 0; - always #100 clk_fpga = ~clk_fpga; + always #15.625 clk_fpga = ~clk_fpga; u1e_core u1e_core(.clk_fpga(clk_fpga), .debug_led(debug_led), .debug(debug), .debug_clk(debug_clk), .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE) ); + + gpmc_model gpmc_model + (.EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), + .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), + .EM_NWE(EM_NWE), .EM_NOE(EM_NOE) ); -endmodule // u1e +endmodule // tb_u1e diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 2481549b2..b0edbb9b6 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -10,7 +10,7 @@ module u1e_core ); // Debug circuitry - reg [31:0] ctr; + reg [31:0] ctr=0; always @(posedge clk_fpga) ctr <= ctr + 1; @@ -37,7 +37,7 @@ module u1e_core assign wb_clk = clk_fpga; reg [15:0] reg_fast, reg_slow; - localparam [10:0] WB_ADR_REG_FAST = 36; + localparam [10:0] WB_ADR_REG_FAST = 11'd36; localparam [10:0] WB_ADR_REG_SLOW = 38; always @(posedge wb_clk) @@ -47,6 +47,5 @@ module u1e_core assign wb_dat_miso = (wb_adr == WB_ADR_REG_FAST) ? reg_fast : 16'bx; assign wb_ack = wb_stb & wb_cyc; - - -endmodule // u2plus + +endmodule // u1e_core -- cgit v1.2.3 From 1912ff60acd490a24204a7596e373e9aef9276cd Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 17 Feb 2010 15:00:41 -0800 Subject: speed up the presentation of registered wb data to the gpmc --- usrp2/gpmc/gpmc.v | 7 +++++-- usrp2/models/gpmc_model.v | 26 +++++++++++++++----------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/usrp2/gpmc/gpmc.v b/usrp2/gpmc/gpmc.v index 1963af6e6..56f879abc 100644 --- a/usrp2/gpmc/gpmc.v +++ b/usrp2/gpmc/gpmc.v @@ -12,7 +12,7 @@ module gpmc wire EM_output_enable = (~EM_NOE & (~EM_NCS4 | ~EM_NCS6)); wire [15:0] EM_D_ram; - reg [15:0] EM_D_wb; + wire [15:0] EM_D_wb; assign EM_D = ~EM_output_enable ? 16'bz : ~EM_NCS4 ? EM_D_ram : EM_D_wb; @@ -44,10 +44,13 @@ module gpmc wb_sel_o <= ~EM_NBE; end + reg [15:0] EM_D_wb_reg; always @(posedge wb_clk) if(wb_ack_i) - EM_D_wb <= wb_dat_miso; + EM_D_wb_reg <= wb_dat_miso; + assign EM_D_wb = wb_ack_i ? wb_dat_miso : EM_D_wb_reg; + // stb, oe_del, we_del assign wb_cyc_o = wb_stb_o; diff --git a/usrp2/models/gpmc_model.v b/usrp2/models/gpmc_model.v index ce3acaacf..38dde1fa5 100644 --- a/usrp2/models/gpmc_model.v +++ b/usrp2/models/gpmc_model.v @@ -25,16 +25,18 @@ module gpmc_model input [10:0] addr; input [15:0] data; begin - #2; + #2.3; EM_A <= addr[10:1]; EM_D_int <= data; - #4; + #2.01; EM_NCS6 <= 0; - #5; + #14; EM_NWE <= 0; - #41; - EM_NWE <= 1; + #77.5; EM_NCS6 <= 1; + //#1.5; + EM_NWE <= 1; + #6; EM_A <= 10'bz; EM_D_int <= 16'bz; end @@ -43,17 +45,19 @@ module gpmc_model task GPMC_Read; input [10:0] addr; begin - #2; + #1.3; EM_A <= addr[10:1]; - #4; + #3; EM_NCS6 <= 0; - #5; + #14; EM_NOE <= 0; - #41; - EM_NOE <= 1; + #77.5; EM_NCS6 <= 1; - EM_A <= 10'bz; + //#1.5; $display("Data Read from GPMC: %X",EM_D); + EM_NOE <= 1; + #254; + EM_A <= 10'bz; end endtask // GPMC_Read -- cgit v1.2.3 From e56b4767451dcdca41512faba634b812e44d2e1d Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 18 Feb 2010 18:03:26 -0800 Subject: Fixed paths to help icarus find opencores and xilinx models. Added Xilinx global set and reset module. --- usrp2/top/u1e/cmdfile | 9 +++++---- usrp2/top/u1e/tb_u1e.v | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/usrp2/top/u1e/cmdfile b/usrp2/top/u1e/cmdfile index 5e4db5c65..291c723b8 100644 --- a/usrp2/top/u1e/cmdfile +++ b/usrp2/top/u1e/cmdfile @@ -10,10 +10,11 @@ # Models -y ../../models +-y /opt/Xilinx/10.1/ISE/verilog/src/unisims # Open Cores --y ../opencores/spi/rtl/verilog -+incdir+../opencores/spi/rtl/verilog --y ../opencores/i2c/rtl/verilog -+incdir+../opencores/i2c/rtl/verilog +-y ../../opencores/spi/rtl/verilog ++incdir+../../opencores/spi/rtl/verilog +-y ../../opencores/i2c/rtl/verilog ++incdir+../../opencores/i2c/rtl/verilog diff --git a/usrp2/top/u1e/tb_u1e.v b/usrp2/top/u1e/tb_u1e.v index 85d2b49f0..319645af6 100644 --- a/usrp2/top/u1e/tb_u1e.v +++ b/usrp2/top/u1e/tb_u1e.v @@ -7,6 +7,8 @@ module tb_u1e(); wire [31:0] debug; wire [1:0] debug_clk; + xlnx_glbl glbl (.GSR(),.GTS()); + initial begin $dumpfile("tb_u1e.lxt"); $dumpvars(0,tb_u1e); -- cgit v1.2.3 From 7c31f8d25d563b9f2795914f8ea0f3e49b214c56 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 18 Feb 2010 18:04:24 -0800 Subject: allow default uart clock divider --- usrp2/control_lib/simple_uart.v | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/usrp2/control_lib/simple_uart.v b/usrp2/control_lib/simple_uart.v index 22f0e70a2..0dd58b5f5 100644 --- a/usrp2/control_lib/simple_uart.v +++ b/usrp2/control_lib/simple_uart.v @@ -1,11 +1,12 @@ module simple_uart #(parameter TXDEPTH = 1, - parameter RXDEPTH = 1) - (input clk_i, input rst_i, - input we_i, input stb_i, input cyc_i, output reg ack_o, - input [2:0] adr_i, input [31:0] dat_i, output reg [31:0] dat_o, - output rx_int_o, output tx_int_o, output tx_o, input rx_i, output baud_o); + parameter RXDEPTH = 1, + parameter CLKDIV_DEFAULT = 16'd0) + (input clk_i, input rst_i, + input we_i, input stb_i, input cyc_i, output reg ack_o, + input [2:0] adr_i, input [31:0] dat_i, output reg [31:0] dat_o, + output rx_int_o, output tx_int_o, output tx_o, input rx_i, output baud_o); // Register Map localparam SUART_CLKDIV = 0; @@ -30,7 +31,7 @@ module simple_uart always @(posedge clk_i) if (rst_i) - clkdiv <= 0; + clkdiv <= CLKDIV_DEFAULT; else if (wb_wr) case(adr_i) SUART_CLKDIV : clkdiv <= dat_i[15:0]; -- cgit v1.2.3 From f3c61700fbeba30f420ef939a1cabdc42bd15fb7 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 18 Feb 2010 18:05:42 -0800 Subject: Added I2C, UART, debug pins, misc wishbone stuff --- usrp2/top/u1e/u1e.ucf | 38 +++++----- usrp2/top/u1e/u1e.v | 12 ++- usrp2/top/u1e/u1e_core.v | 185 ++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 187 insertions(+), 48 deletions(-) diff --git a/usrp2/top/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf index 3b524a6ea..40d458034 100644 --- a/usrp2/top/u1e/u1e.ucf +++ b/usrp2/top/u1e/u1e.ucf @@ -56,10 +56,10 @@ NET "EM_NOE" LOC = "A14" ; #NET "overo_gpio65" LOC = "F8" ; #NET "overo_gpio127" LOC = "C8" ; #NET "overo_gpio128" LOC = "G8" ; -#NET "overo_gpio144" LOC = "A5" ; -#NET "overo_gpio145" LOC = "C7" ; -#NET "overo_gpio146" LOC = "A6" ; -#NET "overo_gpio147" LOC = "B6" ; +NET "overo_gpio144" LOC = "A5" ; # tx_have_space +NET "overo_gpio145" LOC = "C7" ; # tx_underrun +NET "overo_gpio146" LOC = "A6" ; # rx_have_data +NET "overo_gpio147" LOC = "B6" ; # rx_overrun #NET "overo_gpio163" LOC = "D7" ; #NET "overo_gpio170" LOC = "E8" ; #NET "overo_gpio176" LOC = "B4" ; @@ -68,13 +68,13 @@ NET "EM_NOE" LOC = "A14" ; #NET "overo_txd1" LOC = "C6" ; #NET "overo_rxd1" LOC = "D6" ; -#NET "FPGA_TXD" LOC = "U1" ; -#NET "FPGA_RXD" LOC = "T6" ; +NET "FPGA_TXD" LOC = "U1" ; +NET "FPGA_RXD" LOC = "T6" ; #NET "SYSEN" LOC = "C11" ; -#NET "db_scl" LOC = "U4" ; -#NET "db_sda" LOC = "U5" ; +NET "db_scl" LOC = "U4" ; +NET "db_sda" LOC = "U5" ; #NET "db_sclk_rx" LOC = "W3" ; #NET "db_miso_rx" LOC = "W2" ; #NET "db_mosi_rx" LOC = "V4" ; @@ -134,18 +134,18 @@ NET "debug<31>" LOC = "G3" ; NET "debug_clk<0>" LOC = "L6" ; NET "debug_clk<1>" LOC = "M5" ; -#NET "debug_pb<2>" LOC = "Y2" ; -#NET "debug_pb<1>" LOC = "AA1" ; -#NET "debug_pb<0>" LOC = "N3" ; +NET "debug_pb<2>" LOC = "Y2" ; +NET "debug_pb<1>" LOC = "AA1" ; +NET "debug_pb<0>" LOC = "N3" ; -#NET "dip_sw<7>" LOC = "T3" ; -#NET "dip_sw<6>" LOC = "U3" ; -#NET "dip_sw<5>" LOC = "M3" ; -#NET "dip_sw<4>" LOC = "N4" ; -#NET "dip_sw<3>" LOC = "J3" ; -#NET "dip_sw<2>" LOC = "J4" ; -#NET "dip_sw<1>" LOC = "J6" ; -#NET "dip_sw<0>" LOC = "J7" ; +NET "dip_sw<7>" LOC = "T3" ; +NET "dip_sw<6>" LOC = "U3" ; +NET "dip_sw<5>" LOC = "M3" ; +NET "dip_sw<4>" LOC = "N4" ; +NET "dip_sw<3>" LOC = "J3" ; +NET "dip_sw<2>" LOC = "J4" ; +NET "dip_sw<1>" LOC = "J6" ; +NET "dip_sw<0>" LOC = "J7" ; ## AD9862 Interface #NET "aux_sdi_codec" LOC = "F19" ; diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index 8832d6e11..4ca9b5580 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -4,10 +4,14 @@ module u1e (input CLK_FPGA_P, input CLK_FPGA_N, // Diff output [2:0] debug_led, output [31:0] debug, output [1:0] debug_clk, + input [2:0] debug_pb, input [7:0] dip_sw, output FPGA_TXD, input FPGA_RXD, // GPMC input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, - input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE + input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, + + inout db_sda, inout db_scl, // I2C + output overo_gpio144, output overo_gpio145, output overo_gpio146, output overo_gpio147 // Fifo controls ); // FPGA-specific pins connections @@ -17,8 +21,12 @@ module u1e clk_fpga_pin (.O(clk_fpga),.I(CLK_FPGA_P),.IB(CLK_FPGA_N)); u1e_core u1e_core(.clk_fpga(clk_fpga), .debug_led(debug_led), .debug(debug), .debug_clk(debug_clk), + .debug_pb(debug_pb), .dip_sw(dip_sw), .debug_txd(FPGA_TXD), .debug_rxd(FPGA_RXD), .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), - .EM_NWE(EM_NWE), .EM_NOE(EM_NOE) ); + .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), + .db_sda(db_sda), .db_scl(db_scl), + .tx_have_space(overo_gpio144), .tx_underrun(overo_gpio145), + .rx_have_data(overo_gpio_146), .rx_overrun(overo_gpio147) ); endmodule // u1e diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index b0edbb9b6..cad697858 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -3,49 +3,180 @@ module u1e_core (input clk_fpga, output [2:0] debug_led, output [31:0] debug, output [1:0] debug_clk, - + input [2:0] debug_pb, input [7:0] dip_sw, output debug_txd, input debug_rxd, + // GPMC input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, - input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE - ); - - // Debug circuitry - reg [31:0] ctr=0; - always @(posedge clk_fpga) - ctr <= ctr + 1; + input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, - assign debug_led = ctr[27:25]; - assign debug_clk = { EM_CLK, clk_fpga }; - assign debug = { { 1'b0, EM_WAIT0, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, - { EM_D } }; + inout db_sda, inout db_scl, + output tx_have_space, output tx_underrun, output rx_have_data, output rx_overrun + ); wire wb_clk, wb_rst; - wire wb_cyc, wb_stb, wb_we, wb_ack; - wire [1:0] wb_sel; - wire [10:0] wb_adr; - wire [15:0] wb_dat_mosi, wb_dat_miso; + + assign tx_have_space = 0; + assign tx_underrun = 0; + assign rx_have_data = 0; + assign rx_overrun = 0; + + // ///////////////////////////////////////////////////////////////////////////////////// + // GPMC Slave to Wishbone Master + localparam dw = 16; + localparam aw = 11; + localparam sw = 2; + + wire [dw-1:0] m0_dat_mosi, m0_dat_miso; + wire [aw-1:0] m0_adr; + wire [sw-1:0] m0_sel; + wire m0_cyc, m0_stb, m0_we, m0_ack, m0_err, m0_rty; gpmc gpmc (.EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), .wb_clk(wb_clk), .wb_rst(wb_rst), - .wb_adr_o(wb_adr), .wb_dat_mosi(wb_dat_mosi), .wb_dat_miso(wb_dat_miso), - .wb_sel_o(wb_sel), .wb_cyc_o(wb_cyc), .wb_stb_o(wb_stb), .wb_we_o(wb_we), - .wb_ack_i(wb_ack)); + .wb_adr_o(m0_adr), .wb_dat_mosi(m0_dat_mosi), .wb_dat_miso(m0_dat_miso), + .wb_sel_o(m0_sel), .wb_cyc_o(m0_cyc), .wb_stb_o(m0_stb), .wb_we_o(m0_we), + .wb_ack_i(m0_ack)); assign wb_clk = clk_fpga; - reg [15:0] reg_fast, reg_slow; - localparam [10:0] WB_ADR_REG_FAST = 11'd36; - localparam [10:0] WB_ADR_REG_SLOW = 38; + // ///////////////////////////////////////////////////////////////////////////////////// + // Wishbone Intercon, single master + wire [dw-1:0] s0_dat_mosi, s1_dat_mosi, s0_dat_miso, s1_dat_miso, s2_dat_mosi, s3_dat_mosi, s2_dat_miso, s3_dat_miso, + s4_dat_mosi, s5_dat_mosi, s4_dat_miso, s5_dat_miso, s6_dat_mosi, s7_dat_mosi, s6_dat_miso, s7_dat_miso, + s8_dat_mosi, s9_dat_mosi, s8_dat_miso, s9_dat_miso, sa_dat_mosi, sb_dat_mosi, sa_dat_miso, sb_dat_miso, + sc_dat_mosi, sd_dat_mosi, sc_dat_miso, sd_dat_miso, se_dat_mosi, sf_dat_mosi, se_dat_miso, sf_dat_miso; + wire [aw-1:0] s0_adr,s1_adr,s2_adr,s3_adr,s4_adr,s5_adr,s6_adr,s7_adr; + wire [aw-1:0] s8_adr,s9_adr,sa_adr,sb_adr,sc_adr, sd_adr, se_adr, sf_adr; + wire [sw-1:0] s0_sel,s1_sel,s2_sel,s3_sel,s4_sel,s5_sel,s6_sel,s7_sel; + wire [sw-1:0] s8_sel,s9_sel,sa_sel,sb_sel,sc_sel, sd_sel, se_sel, sf_sel; + wire s0_ack,s1_ack,s2_ack,s3_ack,s4_ack,s5_ack,s6_ack,s7_ack; + wire s8_ack,s9_ack,sa_ack,sb_ack,sc_ack, sd_ack, se_ack, sf_ack; + wire s0_stb,s1_stb,s2_stb,s3_stb,s4_stb,s5_stb,s6_stb,s7_stb; + wire s8_stb,s9_stb,sa_stb,sb_stb,sc_stb, sd_stb, se_stb, sf_stb; + wire s0_cyc,s1_cyc,s2_cyc,s3_cyc,s4_cyc,s5_cyc,s6_cyc,s7_cyc; + wire s8_cyc,s9_cyc,sa_cyc,sb_cyc,sc_cyc, sd_cyc, se_cyc, sf_cyc; + wire s0_we,s1_we,s2_we,s3_we,s4_we,s5_we,s6_we,s7_we; + wire s8_we,s9_we,sa_we,sb_we,sc_we,sd_we, se_we, sf_we; + + wb_1master #(.dw(dw), .aw(aw), .sw(sw), .decode_w(4), + .s0_addr(4'h0), .s0_mask(4'hF), .s1_addr(4'h1), .s1_mask(4'hF), + .s2_addr(4'h2), .s2_mask(4'hF), .s3_addr(4'h3), .s3_mask(4'hF), + .s4_addr(4'h4), .s4_mask(4'hF), .s5_addr(4'h5), .s5_mask(4'hF), + .s6_addr(4'h6), .s6_mask(4'hF), .s7_addr(4'h7), .s7_mask(4'hF), + .s8_addr(4'h8), .s8_mask(4'hF), .s9_addr(4'h9), .s9_mask(4'hF), + .sa_addr(4'ha), .sa_mask(4'hF), .sb_addr(4'hb), .sb_mask(4'hF), + .sc_addr(4'hc), .sc_mask(4'hF), .sd_addr(4'hd), .sd_mask(4'hF), + .se_addr(4'he), .se_mask(4'hF), .sf_addr(4'hf), .sf_mask(4'hF)) + wb_1master + (.clk_i(wb_clk),.rst_i(wb_rst), + .m0_dat_o(m0_dat_miso),.m0_ack_o(m0_ack),.m0_err_o(m0_err),.m0_rty_o(m0_rty),.m0_dat_i(m0_dat_mosi), + .m0_adr_i(m0_adr),.m0_sel_i(m0_sel),.m0_we_i(m0_we),.m0_cyc_i(m0_cyc),.m0_stb_i(m0_stb), + .s0_dat_o(s0_dat_mosi),.s0_adr_o(s0_adr),.s0_sel_o(s0_sel),.s0_we_o(s0_we),.s0_cyc_o(s0_cyc),.s0_stb_o(s0_stb), + .s0_dat_i(s0_dat_miso),.s0_ack_i(s0_ack),.s0_err_i(0),.s0_rty_i(0), + .s1_dat_o(s1_dat_mosi),.s1_adr_o(s1_adr),.s1_sel_o(s1_sel),.s1_we_o(s1_we),.s1_cyc_o(s1_cyc),.s1_stb_o(s1_stb), + .s1_dat_i(s1_dat_miso),.s1_ack_i(s1_ack),.s1_err_i(0),.s1_rty_i(0), + .s2_dat_o(s2_dat_mosi),.s2_adr_o(s2_adr),.s2_sel_o(s2_sel),.s2_we_o(s2_we),.s2_cyc_o(s2_cyc),.s2_stb_o(s2_stb), + .s2_dat_i(s2_dat_miso),.s2_ack_i(s2_ack),.s2_err_i(0),.s2_rty_i(0), + .s3_dat_o(s3_dat_mosi),.s3_adr_o(s3_adr),.s3_sel_o(s3_sel),.s3_we_o(s3_we),.s3_cyc_o(s3_cyc),.s3_stb_o(s3_stb), + .s3_dat_i(s3_dat_miso),.s3_ack_i(s3_ack),.s3_err_i(0),.s3_rty_i(0), + .s4_dat_o(s4_dat_mosi),.s4_adr_o(s4_adr),.s4_sel_o(s4_sel),.s4_we_o(s4_we),.s4_cyc_o(s4_cyc),.s4_stb_o(s4_stb), + .s4_dat_i(s4_dat_miso),.s4_ack_i(s4_ack),.s4_err_i(0),.s4_rty_i(0), + .s5_dat_o(s5_dat_mosi),.s5_adr_o(s5_adr),.s5_sel_o(s5_sel),.s5_we_o(s5_we),.s5_cyc_o(s5_cyc),.s5_stb_o(s5_stb), + .s5_dat_i(s5_dat_miso),.s5_ack_i(s5_ack),.s5_err_i(0),.s5_rty_i(0), + .s6_dat_o(s6_dat_mosi),.s6_adr_o(s6_adr),.s6_sel_o(s6_sel),.s6_we_o(s6_we),.s6_cyc_o(s6_cyc),.s6_stb_o(s6_stb), + .s6_dat_i(s6_dat_miso),.s6_ack_i(s6_ack),.s6_err_i(0),.s6_rty_i(0), + .s7_dat_o(s7_dat_mosi),.s7_adr_o(s7_adr),.s7_sel_o(s7_sel),.s7_we_o(s7_we),.s7_cyc_o(s7_cyc),.s7_stb_o(s7_stb), + .s7_dat_i(s7_dat_miso),.s7_ack_i(s7_ack),.s7_err_i(0),.s7_rty_i(0), + .s8_dat_o(s8_dat_mosi),.s8_adr_o(s8_adr),.s8_sel_o(s8_sel),.s8_we_o(s8_we),.s8_cyc_o(s8_cyc),.s8_stb_o(s8_stb), + .s8_dat_i(s8_dat_miso),.s8_ack_i(s8_ack),.s8_err_i(0),.s8_rty_i(0), + .s9_dat_o(s9_dat_mosi),.s9_adr_o(s9_adr),.s9_sel_o(s9_sel),.s9_we_o(s9_we),.s9_cyc_o(s9_cyc),.s9_stb_o(s9_stb), + .s9_dat_i(s9_dat_miso),.s9_ack_i(s9_ack),.s9_err_i(0),.s9_rty_i(0), + .sa_dat_o(sa_dat_mosi),.sa_adr_o(sa_adr),.sa_sel_o(sa_sel),.sa_we_o(sa_we),.sa_cyc_o(sa_cyc),.sa_stb_o(sa_stb), + .sa_dat_i(sa_dat_miso),.sa_ack_i(sa_ack),.sa_err_i(0),.sa_rty_i(0), + .sb_dat_o(sb_dat_mosi),.sb_adr_o(sb_adr),.sb_sel_o(sb_sel),.sb_we_o(sb_we),.sb_cyc_o(sb_cyc),.sb_stb_o(sb_stb), + .sb_dat_i(sb_dat_miso),.sb_ack_i(sb_ack),.sb_err_i(0),.sb_rty_i(0), + .sc_dat_o(sc_dat_mosi),.sc_adr_o(sc_adr),.sc_sel_o(sc_sel),.sc_we_o(sc_we),.sc_cyc_o(sc_cyc),.sc_stb_o(sc_stb), + .sc_dat_i(sc_dat_miso),.sc_ack_i(sc_ack),.sc_err_i(0),.sc_rty_i(0), + .sd_dat_o(sd_dat_mosi),.sd_adr_o(sd_adr),.sd_sel_o(sd_sel),.sd_we_o(sd_we),.sd_cyc_o(sd_cyc),.sd_stb_o(sd_stb), + .sd_dat_i(sd_dat_miso),.sd_ack_i(sd_ack),.sd_err_i(0),.sd_rty_i(0), + .se_dat_o(se_dat_mosi),.se_adr_o(se_adr),.se_sel_o(se_sel),.se_we_o(se_we),.se_cyc_o(se_cyc),.se_stb_o(se_stb), + .se_dat_i(se_dat_miso),.se_ack_i(se_ack),.se_err_i(0),.se_rty_i(0), + .sf_dat_o(sf_dat_mosi),.sf_adr_o(sf_adr),.sf_sel_o(sf_sel),.sf_we_o(sf_we),.sf_cyc_o(sf_cyc),.sf_stb_o(sf_stb), + .sf_dat_i(sf_dat_miso),.sf_ack_i(sf_ack),.sf_err_i(0),.sf_rty_i(0) ); + + assign s4_ack = 0; assign s5_ack = 0; assign s6_ack = 0; assign s7_ack = 0; + assign s8_ack = 0; assign s9_ack = 0; assign sa_ack = 0; assign sb_ack = 0; + assign sc_ack = 0; assign sd_ack = 0; assign se_ack = 0; assign sf_ack = 0; + + // ///////////////////////////////////////////////////////////////////////////////////// + // Slave 0, LEDs and Switches + + reg [15:0] reg_fast, reg_slow; + localparam REG_FAST = 7'd4; + localparam REG_SWITCHES = 7'd5; always @(posedge wb_clk) - if(wb_cyc & wb_stb & wb_we & (wb_adr == WB_ADR_REG_FAST)) - reg_fast <= wb_dat_mosi; + if(s0_cyc & s0_stb & s0_we & (s0_adr[6:0] == REG_FAST)) + reg_fast <= s0_dat_mosi; - assign wb_dat_miso = (wb_adr == WB_ADR_REG_FAST) ? reg_fast : 16'bx; + assign s0_dat_miso = (s0_adr[6:0] == REG_FAST) ? reg_fast : + (s0_adr[6:0] == REG_SWITCHES) ? {5'b0,debug_pb[2:0],dip_sw[7:0]} : + 16'hBEEF; + assign s0_ack = s0_stb & s0_cyc; - assign wb_ack = wb_stb & wb_cyc; - + + // ///////////////////////////////////////////////////////////////////////////////////// + // Slave 1, UART + // depth of 3 is 128 entries, clkdiv of 278 gives 230.4k with a 64 MHz system clock + + simple_uart #(.TXDEPTH(3),.RXDEPTH(3), .CLKDIV_DEFAULT(278)) uart + (.clk_i(wb_clk),.rst_i(wb_rst), + .we_i(s1_we),.stb_i(s1_stb),.cyc_i(s1_cyc),.ack_o(s1_ack), + .adr_i(s1_adr[4:2]),.dat_i({16'd0,s1_dat_mosi}),.dat_o(s1_dat_miso), + .rx_int_o(),.tx_int_o(), + .tx_o(debug_txd),.rx_i(debug_rxd),.baud_o()); + + // ///////////////////////////////////////////////////////////////////////////////////// + // Slave 2, SPI + + /* + spi_top shared_spi + (.wb_clk_i(wb_clk),.wb_rst_i(wb_rst),.wb_adr_i(s2_adr[4:0]),.wb_dat_i(s2_dat_o), + .wb_dat_o(s2_dat_i),.wb_sel_i(s2_sel),.wb_we_i(s2_we),.wb_stb_i(s2_stb), + .wb_cyc_i(s2_cyc),.wb_ack_o(s2_ack),.wb_err_o(),.wb_int_o(spi_int), + .ss_pad_o({sen_tx_db,sen_tx_adc,sen_tx_dac,sen_rx_db,sen_rx_adc,sen_rx_dac,sen_dac,sen_clk}), + .sclk_pad_o(sclk),.mosi_pad_o(mosi),.miso_pad_i(miso) ); + */ + + // ///////////////////////////////////////////////////////////////////////// + // Slave 3, I2C + + wire scl_pad_i, scl_pad_o, scl_pad_oen_o, sda_pad_i, sda_pad_o, sda_pad_oen_o; + i2c_master_top #(.ARST_LVL(1)) i2c + (.wb_clk_i(wb_clk),.wb_rst_i(wb_rst),.arst_i(1'b0), + .wb_adr_i(s3_adr[4:2]),.wb_dat_i(s3_dat_mosi[7:0]),.wb_dat_o(s3_dat_miso[7:0]), + .wb_we_i(s3_we),.wb_stb_i(s3_stb),.wb_cyc_i(s3_cyc), + .wb_ack_o(s3_ack),.wb_inta_o(), + .scl_pad_i(scl_pad_i),.scl_pad_o(scl_pad_o),.scl_padoen_o(scl_pad_oen_o), + .sda_pad_i(sda_pad_i),.sda_pad_o(sda_pad_o),.sda_padoen_o(sda_pad_oen_o) ); + + assign s3_dat_miso[15:8] = 8'd0; + + // I2C -- Don't use external transistors for open drain, the FPGA implements this + IOBUF scl_pin(.O(scl_pad_i), .IO(db_scl), .I(scl_pad_o), .T(scl_pad_oen_o)); + IOBUF sda_pin(.O(sda_pad_i), .IO(db_sda), .I(sda_pad_o), .T(sda_pad_oen_o)); + + // ///////////////////////////////////////////////////////////////////////////////////// + // Debug Pins + + // Debug circuitry + assign debug_clk = { EM_CLK, clk_fpga }; + assign debug = { { 1'b0, EM_WAIT0, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, + { EM_D } }; + + assign { debug_led[2],debug_led[0],debug_led[1] } = reg_fast; // LEDs are arranged funny on board + endmodule // u1e_core -- cgit v1.2.3 From bc3c1fb34afba5fb4358f1b7eaaf3832360cc375 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 18 Feb 2010 19:13:10 -0800 Subject: added gpio control to the wishbone --- usrp2/top/u1e/u1e.v | 2 +- usrp2/top/u1e/u1e_core.v | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index 4ca9b5580..326476b21 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -27,6 +27,6 @@ module u1e .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), .db_sda(db_sda), .db_scl(db_scl), .tx_have_space(overo_gpio144), .tx_underrun(overo_gpio145), - .rx_have_data(overo_gpio_146), .rx_overrun(overo_gpio147) ); + .rx_have_data(overo_gpio146), .rx_overrun(overo_gpio147) ); endmodule // u1e diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index cad697858..257156d4b 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -12,20 +12,15 @@ module u1e_core inout db_sda, inout db_scl, output tx_have_space, output tx_underrun, output rx_have_data, output rx_overrun ); - - wire wb_clk, wb_rst; - - assign tx_have_space = 0; - assign tx_underrun = 0; - assign rx_have_data = 0; - assign rx_overrun = 0; + + wire wb_clk, wb_rst; // ///////////////////////////////////////////////////////////////////////////////////// // GPMC Slave to Wishbone Master localparam dw = 16; localparam aw = 11; localparam sw = 2; - + wire [dw-1:0] m0_dat_mosi, m0_dat_miso; wire [aw-1:0] m0_adr; wire [sw-1:0] m0_sel; @@ -114,19 +109,27 @@ module u1e_core // ///////////////////////////////////////////////////////////////////////////////////// // Slave 0, LEDs and Switches - reg [15:0] reg_fast, reg_slow; + reg [15:0] reg_fast, reg_slow; localparam REG_FAST = 7'd4; - localparam REG_SWITCHES = 7'd5; + localparam REG_SWITCHES = 7'd6; + localparam REG_GPIOS = 7'd8; + + reg [3:0] reg_gpios; always @(posedge wb_clk) if(s0_cyc & s0_stb & s0_we & (s0_adr[6:0] == REG_FAST)) reg_fast <= s0_dat_mosi; + always @(posedge wb_clk) + if(s0_cyc & s0_stb & s0_we & (s0_adr[6:0] == REG_GPIOS)) + reg_gpios <= s0_dat_mosi; + assign s0_dat_miso = (s0_adr[6:0] == REG_FAST) ? reg_fast : (s0_adr[6:0] == REG_SWITCHES) ? {5'b0,debug_pb[2:0],dip_sw[7:0]} : 16'hBEEF; assign s0_ack = s0_stb & s0_cyc; + assign { rx_overrun, rx_have_data, tx_underrun, tx_have_space } = reg_gpios; // ///////////////////////////////////////////////////////////////////////////////////// // Slave 1, UART -- cgit v1.2.3 From 2e4d962021334109b268c9080e5a5903b99be217 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 22 Feb 2010 12:30:22 -0800 Subject: GPIOs now on the wishbone interface --- usrp2/top/u1e/Makefile | 2 +- usrp2/top/u1e/u1e.ucf | 64 ++++++++++++++++++++++++------------------------ usrp2/top/u1e/u1e.v | 6 +++-- usrp2/top/u1e/u1e_core.v | 19 ++++++++++++-- 4 files changed, 54 insertions(+), 37 deletions(-) diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index cdbdf995e..9381789a7 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -64,7 +64,7 @@ control_lib/gray_send.v \ control_lib/icache.v \ control_lib/mux4.v \ control_lib/mux8.v \ -control_lib/nsgpio.v \ +control_lib/nsgpio16LE.v \ control_lib/ram_2port.v \ control_lib/ram_harv_cache.v \ control_lib/ram_loader.v \ diff --git a/usrp2/top/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf index 40d458034..f237eb60c 100644 --- a/usrp2/top/u1e/u1e.ucf +++ b/usrp2/top/u1e/u1e.ucf @@ -203,39 +203,39 @@ NET "dip_sw<0>" LOC = "J7" ; #NET "PPS_IN" LOC = "M17" ; -#NET "io_tx<0>" LOC = "AB20" ; -#NET "io_tx<1>" LOC = "Y17" ; -#NET "io_tx<2>" LOC = "Y16" ; -#NET "io_tx<3>" LOC = "U16" ; -#NET "io_tx<4>" LOC = "V16" ; -#NET "io_tx<5>" LOC = "AB19" ; -#NET "io_tx<6>" LOC = "AA19" ; -#NET "io_tx<7>" LOC = "U14" ; -#NET "io_tx<8>" LOC = "U15" ; -#NET "io_tx<9>" LOC = "AB17" ; -#NET "io_tx<10>" LOC = "AB18" ; -#NET "io_tx<11>" LOC = "Y13" ; -#NET "io_tx<12>" LOC = "W14" ; -#NET "io_tx<13>" LOC = "U13" ; -#NET "io_tx<14>" LOC = "AA15" ; -#NET "io_tx<15>" LOC = "AB14" ; +NET "io_tx<0>" LOC = "AB20" ; +NET "io_tx<1>" LOC = "Y17" ; +NET "io_tx<2>" LOC = "Y16" ; +NET "io_tx<3>" LOC = "U16" ; +NET "io_tx<4>" LOC = "V16" ; +NET "io_tx<5>" LOC = "AB19" ; +NET "io_tx<6>" LOC = "AA19" ; +NET "io_tx<7>" LOC = "U14" ; +NET "io_tx<8>" LOC = "U15" ; +NET "io_tx<9>" LOC = "AB17" ; +NET "io_tx<10>" LOC = "AB18" ; +NET "io_tx<11>" LOC = "Y13" ; +NET "io_tx<12>" LOC = "W14" ; +NET "io_tx<13>" LOC = "U13" ; +NET "io_tx<14>" LOC = "AA15" ; +NET "io_tx<15>" LOC = "AB14" ; -#NET "io_rx<0>" LOC = "Y8" ; -#NET "io_rx<1>" LOC = "Y9" ; -#NET "io_rx<2>" LOC = "V7" ; -#NET "io_rx<3>" LOC = "U8" ; -#NET "io_rx<4>" LOC = "V10" ; -#NET "io_rx<5>" LOC = "U9" ; -#NET "io_rx<6>" LOC = "AB7" ; -#NET "io_rx<7>" LOC = "AA8" ; -#NET "io_rx<8>" LOC = "W8" ; -#NET "io_rx<9>" LOC = "V8" ; -#NET "io_rx<10>" LOC = "AB5" ; -#NET "io_rx<11>" LOC = "AB6" ; -#NET "io_rx<12>" LOC = "AB4" ; -#NET "io_rx<13>" LOC = "AA4" ; -#NET "io_rx<14>" LOC = "W5" ; -#NET "io_rx<15>" LOC = "Y4" ; +NET "io_rx<0>" LOC = "Y8" ; +NET "io_rx<1>" LOC = "Y9" ; +NET "io_rx<2>" LOC = "V7" ; +NET "io_rx<3>" LOC = "U8" ; +NET "io_rx<4>" LOC = "V10" ; +NET "io_rx<5>" LOC = "U9" ; +NET "io_rx<6>" LOC = "AB7" ; +NET "io_rx<7>" LOC = "AA8" ; +NET "io_rx<8>" LOC = "W8" ; +NET "io_rx<9>" LOC = "V8" ; +NET "io_rx<10>" LOC = "AB5" ; +NET "io_rx<11>" LOC = "AB6" ; +NET "io_rx<12>" LOC = "AB4" ; +NET "io_rx<13>" LOC = "AA4" ; +NET "io_rx<14>" LOC = "W5" ; +NET "io_rx<15>" LOC = "Y4" ; #NET "CLKOUT2_CODEC" LOC = "U12" ; #NET "CLKOUT1_CODEC" LOC = "V12" ; diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index 326476b21..667372434 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -11,7 +11,8 @@ module u1e input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, inout db_sda, inout db_scl, // I2C - output overo_gpio144, output overo_gpio145, output overo_gpio146, output overo_gpio147 // Fifo controls + output overo_gpio144, output overo_gpio145, output overo_gpio146, output overo_gpio147, // Fifo controls + inout [15:0] io_tx, inout [15:0] io_rx ); // FPGA-specific pins connections @@ -27,6 +28,7 @@ module u1e .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), .db_sda(db_sda), .db_scl(db_scl), .tx_have_space(overo_gpio144), .tx_underrun(overo_gpio145), - .rx_have_data(overo_gpio146), .rx_overrun(overo_gpio147) ); + .rx_have_data(overo_gpio146), .rx_overrun(overo_gpio147), + .io_tx(io_tx), .io_rx(io_rx) ); endmodule // u1e diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 257156d4b..ad3234b56 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -10,7 +10,8 @@ module u1e_core input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, inout db_sda, inout db_scl, - output tx_have_space, output tx_underrun, output rx_have_data, output rx_overrun + output tx_have_space, output tx_underrun, output rx_have_data, output rx_overrun, + inout [15:0] io_tx, inout [15:0] io_rx ); wire wb_clk, wb_rst; @@ -102,7 +103,7 @@ module u1e_core .sf_dat_o(sf_dat_mosi),.sf_adr_o(sf_adr),.sf_sel_o(sf_sel),.sf_we_o(sf_we),.sf_cyc_o(sf_cyc),.sf_stb_o(sf_stb), .sf_dat_i(sf_dat_miso),.sf_ack_i(sf_ack),.sf_err_i(0),.sf_rty_i(0) ); - assign s4_ack = 0; assign s5_ack = 0; assign s6_ack = 0; assign s7_ack = 0; + assign s5_ack = 0; assign s6_ack = 0; assign s7_ack = 0; assign s8_ack = 0; assign s9_ack = 0; assign sa_ack = 0; assign sb_ack = 0; assign sc_ack = 0; assign sd_ack = 0; assign se_ack = 0; assign sf_ack = 0; @@ -172,6 +173,20 @@ module u1e_core IOBUF scl_pin(.O(scl_pad_i), .IO(db_scl), .I(scl_pad_o), .T(scl_pad_oen_o)); IOBUF sda_pin(.O(sda_pad_i), .IO(db_sda), .I(sda_pad_o), .T(sda_pad_oen_o)); + // ///////////////////////////////////////////////////////////////////////// + // GPIOs -- Slave #4 + + wire [31:0] atr_lines; + wire [31:0] debug_gpio_0, debug_gpio_1; + + nsgpio16LE + nsgpio16LE(.clk_i(wb_clk),.rst_i(wb_rst), + .cyc_i(s4_cyc),.stb_i(s4_stb),.adr_i(s4_adr[3:0]),.we_i(s4_we), + .dat_i(s4_dat_o),.dat_o(s4_dat_i),.ack_o(s4_ack), + .atr(atr_lines),.debug_0(debug_gpio_0),.debug_1(debug_gpio_1), + .gpio( {io_tx,io_rx} ) ); + + // ///////////////////////////////////////////////////////////////////////////////////// // Debug Pins -- cgit v1.2.3 From 7043c21bcef95879c58c9101f8bd16f216aa277a Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 22 Feb 2010 12:30:55 -0800 Subject: Modified nsgpio.v to support 16 bit little endian bus interface. --- usrp2/control_lib/nsgpio16LE.v | 124 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 usrp2/control_lib/nsgpio16LE.v diff --git a/usrp2/control_lib/nsgpio16LE.v b/usrp2/control_lib/nsgpio16LE.v new file mode 100644 index 000000000..6847bb4a9 --- /dev/null +++ b/usrp2/control_lib/nsgpio16LE.v @@ -0,0 +1,124 @@ +// Modified from code originally by Richard Herveille, his copyright is below + +///////////////////////////////////////////////////////////////////// +//// //// +//// OpenCores Simple General Purpose IO core //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2002 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + + +module nsgpio16LE + (input clk_i, input rst_i, + input cyc_i, input stb_i, input [3:0] adr_i, input we_i, input [15:0] dat_i, + output reg [15:0] dat_o, output reg ack_o, + input [31:0] atr, input [31:0] debug_0, input [31:0] debug_1, + inout [31:0] gpio + ); + + reg [63:0] ctrl; + reg [31:0] line; + reg [31:0] lgpio; // LatchedGPIO pins + reg [31:0] ddr; + + wire wb_acc = cyc_i & stb_i; // WISHBONE access + wire wb_wr = wb_acc & we_i; // WISHBONE write access + + always @(posedge clk_i or posedge rst_i) + if (rst_i) + begin + ctrl <= 64'h0; + line <= 0; + end + else if (wb_wr) + case( adr_i[3:1] ) + 3'b000 : + line[15:0] <= dat_i; + 3'b001 : + line[31:16] <= dat_i; + 3'b010 : + ddr[15:0] <= dat_i; + 3'b011 : + ddr[31:16] <= dat_i; + 3'b100 : + ctrl[15:0] <= dat_i; + 3'b101 : + ctrl[31:16] <= dat_i; + 3'b110 : + ctrl[47:32] <= dat_i; + 3'b111 : + ctrl[63:48] <= dat_i; + endcase // case ( adr_i[3:1] ) + + always @(posedge clk_i) + case (adr_i[3:1]) + 3'b000 : + dat_o <= lgpio[15:0]; + 3'b001 : + dat_o <= lgpio[31:16]; + 3'b010 : + dat_o <= ddr[15:0]; + 3'b011 : + dat_o <= ddr[31:16]; + 3'b100 : + dat_o <= ctrl[15:0]; + 3'b101 : + dat_o <= ctrl[31:16]; + 3'b110 : + dat_o <= ctrl[47:32]; + 3'b111 : + dat_o <= ctrl[63:48]; + endcase // case (adr_i[3:1]) + + + always @(posedge clk_i or posedge rst_i) + if (rst_i) + ack_o <= 1'b0; + else + ack_o <= wb_acc & !ack_o; + + // latch GPIO input pins + always @(posedge clk_i) + lgpio <= gpio; + + // assign GPIO outputs + integer n; + reg [31:0] igpio; // temporary internal signal + + always @(ctrl or line or debug_1 or debug_0 or atr) + 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]) ) + : 1'bz; + + assign gpio = igpio; + +endmodule + -- cgit v1.2.3 From ba97786f44d66c634f289e9a23021e8e13548326 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 22 Feb 2010 12:33:13 -0800 Subject: remove the #1 delay in all the regs. They just slow down sims. --- usrp2/opencores/spi/rtl/verilog/spi_clgen.v | 20 +++--- usrp2/opencores/spi/rtl/verilog/spi_defines.v | 8 +-- usrp2/opencores/spi/rtl/verilog/spi_shift.v | 90 +++++++++++++-------------- usrp2/opencores/spi/rtl/verilog/spi_top.v | 68 ++++++++++---------- 4 files changed, 90 insertions(+), 96 deletions(-) diff --git a/usrp2/opencores/spi/rtl/verilog/spi_clgen.v b/usrp2/opencores/spi/rtl/verilog/spi_clgen.v index 7bc4f6e5e..3f29f6d7f 100644 --- a/usrp2/opencores/spi/rtl/verilog/spi_clgen.v +++ b/usrp2/opencores/spi/rtl/verilog/spi_clgen.v @@ -43,8 +43,6 @@ module spi_clgen (clk_in, rst, go, enable, last_clk, divider, clk_out, pos_edge, neg_edge); - parameter Tp = 1; - input clk_in; // input clock (system clock) input rst; // reset input enable; // clock enable @@ -71,13 +69,13 @@ module spi_clgen (clk_in, rst, go, enable, last_clk, divider, clk_out, pos_edge, always @(posedge clk_in or posedge rst) begin if(rst) - cnt <= #Tp {`SPI_DIVIDER_LEN{1'b1}}; + cnt <= {`SPI_DIVIDER_LEN{1'b1}}; else begin if(!enable || cnt_zero) - cnt <= #Tp divider; + cnt <= divider; else - cnt <= #Tp cnt - {{`SPI_DIVIDER_LEN-1{1'b0}}, 1'b1}; + cnt <= cnt - {{`SPI_DIVIDER_LEN-1{1'b0}}, 1'b1}; end end @@ -85,9 +83,9 @@ module spi_clgen (clk_in, rst, go, enable, last_clk, divider, clk_out, pos_edge, always @(posedge clk_in or posedge rst) begin if(rst) - clk_out <= #Tp 1'b0; + clk_out <= 1'b0; else - clk_out <= #Tp (enable && cnt_zero && (!last_clk || clk_out)) ? ~clk_out : clk_out; + clk_out <= (enable && cnt_zero && (!last_clk || clk_out)) ? ~clk_out : clk_out; end // Pos and neg edge signals @@ -95,13 +93,13 @@ module spi_clgen (clk_in, rst, go, enable, last_clk, divider, clk_out, pos_edge, begin if(rst) begin - pos_edge <= #Tp 1'b0; - neg_edge <= #Tp 1'b0; + pos_edge <= 1'b0; + neg_edge <= 1'b0; end else begin - pos_edge <= #Tp (enable && !clk_out && cnt_one) || (!(|divider) && clk_out) || (!(|divider) && go && !enable); - neg_edge <= #Tp (enable && clk_out && cnt_one) || (!(|divider) && !clk_out && enable); + pos_edge <= (enable && !clk_out && cnt_one) || (!(|divider) && clk_out) || (!(|divider) && go && !enable); + neg_edge <= (enable && clk_out && cnt_one) || (!(|divider) && !clk_out && enable); end end endmodule diff --git a/usrp2/opencores/spi/rtl/verilog/spi_defines.v b/usrp2/opencores/spi/rtl/verilog/spi_defines.v index a6925918e..01de2584d 100644 --- a/usrp2/opencores/spi/rtl/verilog/spi_defines.v +++ b/usrp2/opencores/spi/rtl/verilog/spi_defines.v @@ -43,8 +43,8 @@ // low frequency of system clock this can be reduced. // Use SPI_DIVIDER_LEN for fine tuning theexact number. // -//`define SPI_DIVIDER_LEN_8 -`define SPI_DIVIDER_LEN_16 +`define SPI_DIVIDER_LEN_8 +//`define SPI_DIVIDER_LEN_16 //`define SPI_DIVIDER_LEN_24 //`define SPI_DIVIDER_LEN_32 @@ -66,9 +66,9 @@ // Use SPI_MAX_CHAR for fine tuning the exact number, when using // SPI_MAX_CHAR_32, SPI_MAX_CHAR_24, SPI_MAX_CHAR_16, SPI_MAX_CHAR_8. // -`define SPI_MAX_CHAR_128 +//`define SPI_MAX_CHAR_128 //`define SPI_MAX_CHAR_64 -//`define SPI_MAX_CHAR_32 +`define SPI_MAX_CHAR_32 //`define SPI_MAX_CHAR_24 //`define SPI_MAX_CHAR_16 //`define SPI_MAX_CHAR_8 diff --git a/usrp2/opencores/spi/rtl/verilog/spi_shift.v b/usrp2/opencores/spi/rtl/verilog/spi_shift.v index b17ac8b1f..c8c73706b 100644 --- a/usrp2/opencores/spi/rtl/verilog/spi_shift.v +++ b/usrp2/opencores/spi/rtl/verilog/spi_shift.v @@ -46,8 +46,6 @@ module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, tip, last, p_in, p_out, s_clk, s_in, s_out); - parameter Tp = 1; - input clk; // system clock input rst; // reset input [3:0] latch; // latch signal for storing the data in shift register @@ -92,13 +90,13 @@ module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, always @(posedge clk or posedge rst) begin if(rst) - cnt <= #Tp {`SPI_CHAR_LEN_BITS+1{1'b0}}; + cnt <= {`SPI_CHAR_LEN_BITS+1{1'b0}}; else begin if(tip) - cnt <= #Tp pos_edge ? (cnt - {{`SPI_CHAR_LEN_BITS{1'b0}}, 1'b1}) : cnt; + cnt <= pos_edge ? (cnt - {{`SPI_CHAR_LEN_BITS{1'b0}}, 1'b1}) : cnt; else - cnt <= #Tp !(|len) ? {1'b1, {`SPI_CHAR_LEN_BITS{1'b0}}} : {1'b0, len}; + cnt <= !(|len) ? {1'b1, {`SPI_CHAR_LEN_BITS{1'b0}}} : {1'b0, len}; end end @@ -106,132 +104,132 @@ module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, always @(posedge clk or posedge rst) begin if(rst) - tip <= #Tp 1'b0; + tip <= 1'b0; else if(go && ~tip) - tip <= #Tp 1'b1; + tip <= 1'b1; else if(tip && last && pos_edge) - tip <= #Tp 1'b0; + tip <= 1'b0; end // Sending bits to the line always @(posedge clk or posedge rst) begin if (rst) - s_out <= #Tp 1'b0; + s_out <= 1'b0; else - s_out <= #Tp (tx_clk || !tip) ? data[tx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] : s_out; + s_out <= (tx_clk || !tip) ? data[tx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] : s_out; end // Receiving bits from the line always @(posedge clk or posedge rst) begin if (rst) - data <= #Tp {`SPI_MAX_CHAR{1'b0}}; + data <= {`SPI_MAX_CHAR{1'b0}}; `ifdef SPI_MAX_CHAR_128 else if (latch[0] && !tip) begin if (byte_sel[3]) - data[31:24] <= #Tp p_in[31:24]; + data[31:24] <= p_in[31:24]; if (byte_sel[2]) - data[23:16] <= #Tp p_in[23:16]; + data[23:16] <= p_in[23:16]; if (byte_sel[1]) - data[15:8] <= #Tp p_in[15:8]; + data[15:8] <= p_in[15:8]; if (byte_sel[0]) - data[7:0] <= #Tp p_in[7:0]; + data[7:0] <= p_in[7:0]; end else if (latch[1] && !tip) begin if (byte_sel[3]) - data[63:56] <= #Tp p_in[31:24]; + data[63:56] <= p_in[31:24]; if (byte_sel[2]) - data[55:48] <= #Tp p_in[23:16]; + data[55:48] <= p_in[23:16]; if (byte_sel[1]) - data[47:40] <= #Tp p_in[15:8]; + data[47:40] <= p_in[15:8]; if (byte_sel[0]) - data[39:32] <= #Tp p_in[7:0]; + data[39:32] <= p_in[7:0]; end else if (latch[2] && !tip) begin if (byte_sel[3]) - data[95:88] <= #Tp p_in[31:24]; + data[95:88] <= p_in[31:24]; if (byte_sel[2]) - data[87:80] <= #Tp p_in[23:16]; + data[87:80] <= p_in[23:16]; if (byte_sel[1]) - data[79:72] <= #Tp p_in[15:8]; + data[79:72] <= p_in[15:8]; if (byte_sel[0]) - data[71:64] <= #Tp p_in[7:0]; + data[71:64] <= p_in[7:0]; end else if (latch[3] && !tip) begin if (byte_sel[3]) - data[127:120] <= #Tp p_in[31:24]; + data[127:120] <= p_in[31:24]; if (byte_sel[2]) - data[119:112] <= #Tp p_in[23:16]; + data[119:112] <= p_in[23:16]; if (byte_sel[1]) - data[111:104] <= #Tp p_in[15:8]; + data[111:104] <= p_in[15:8]; if (byte_sel[0]) - data[103:96] <= #Tp p_in[7:0]; + data[103:96] <= p_in[7:0]; end `else `ifdef SPI_MAX_CHAR_64 else if (latch[0] && !tip) begin if (byte_sel[3]) - data[31:24] <= #Tp p_in[31:24]; + data[31:24] <= p_in[31:24]; if (byte_sel[2]) - data[23:16] <= #Tp p_in[23:16]; + data[23:16] <= p_in[23:16]; if (byte_sel[1]) - data[15:8] <= #Tp p_in[15:8]; + data[15:8] <= p_in[15:8]; if (byte_sel[0]) - data[7:0] <= #Tp p_in[7:0]; + data[7:0] <= p_in[7:0]; end else if (latch[1] && !tip) begin if (byte_sel[3]) - data[63:56] <= #Tp p_in[31:24]; + data[63:56] <= p_in[31:24]; if (byte_sel[2]) - data[55:48] <= #Tp p_in[23:16]; + data[55:48] <= p_in[23:16]; if (byte_sel[1]) - data[47:40] <= #Tp p_in[15:8]; + data[47:40] <= p_in[15:8]; if (byte_sel[0]) - data[39:32] <= #Tp p_in[7:0]; + data[39:32] <= p_in[7:0]; end `else else if (latch[0] && !tip) begin `ifdef SPI_MAX_CHAR_8 if (byte_sel[0]) - data[`SPI_MAX_CHAR-1:0] <= #Tp p_in[`SPI_MAX_CHAR-1:0]; + data[`SPI_MAX_CHAR-1:0] <= p_in[`SPI_MAX_CHAR-1:0]; `endif `ifdef SPI_MAX_CHAR_16 if (byte_sel[0]) - data[7:0] <= #Tp p_in[7:0]; + data[7:0] <= p_in[7:0]; if (byte_sel[1]) - data[`SPI_MAX_CHAR-1:8] <= #Tp p_in[`SPI_MAX_CHAR-1:8]; + data[`SPI_MAX_CHAR-1:8] <= p_in[`SPI_MAX_CHAR-1:8]; `endif `ifdef SPI_MAX_CHAR_24 if (byte_sel[0]) - data[7:0] <= #Tp p_in[7:0]; + data[7:0] <= p_in[7:0]; if (byte_sel[1]) - data[15:8] <= #Tp p_in[15:8]; + data[15:8] <= p_in[15:8]; if (byte_sel[2]) - data[`SPI_MAX_CHAR-1:16] <= #Tp p_in[`SPI_MAX_CHAR-1:16]; + data[`SPI_MAX_CHAR-1:16] <= p_in[`SPI_MAX_CHAR-1:16]; `endif `ifdef SPI_MAX_CHAR_32 if (byte_sel[0]) - data[7:0] <= #Tp p_in[7:0]; + data[7:0] <= p_in[7:0]; if (byte_sel[1]) - data[15:8] <= #Tp p_in[15:8]; + data[15:8] <= p_in[15:8]; if (byte_sel[2]) - data[23:16] <= #Tp p_in[23:16]; + data[23:16] <= p_in[23:16]; if (byte_sel[3]) - data[`SPI_MAX_CHAR-1:24] <= #Tp p_in[`SPI_MAX_CHAR-1:24]; + data[`SPI_MAX_CHAR-1:24] <= p_in[`SPI_MAX_CHAR-1:24]; `endif end `endif `endif else - data[rx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] <= #Tp rx_clk ? s_in : data[rx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]]; + data[rx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] <= rx_clk ? s_in : data[rx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]]; end endmodule diff --git a/usrp2/opencores/spi/rtl/verilog/spi_top.v b/usrp2/opencores/spi/rtl/verilog/spi_top.v index 09b2e50e1..071aeefca 100644 --- a/usrp2/opencores/spi/rtl/verilog/spi_top.v +++ b/usrp2/opencores/spi/rtl/verilog/spi_top.v @@ -52,8 +52,6 @@ module spi_top ss_pad_o, sclk_pad_o, mosi_pad_o, miso_pad_i ); - parameter Tp = 1; - // Wishbone signals input wb_clk_i; // master clock input input wb_rst_i; // synchronous active high reset @@ -142,18 +140,18 @@ module spi_top always @(posedge wb_clk_i or posedge wb_rst_i) begin if (wb_rst_i) - wb_dat_o <= #Tp 32'b0; + wb_dat_o <= 32'b0; else - wb_dat_o <= #Tp wb_dat; + wb_dat_o <= wb_dat; end // Wb acknowledge always @(posedge wb_clk_i or posedge wb_rst_i) begin if (wb_rst_i) - wb_ack_o <= #Tp 1'b0; + wb_ack_o <= 1'b0; else - wb_ack_o <= #Tp wb_cyc_i & wb_stb_i & ~wb_ack_o; + wb_ack_o <= wb_cyc_i & wb_stb_i & ~wb_ack_o; end // Wb error @@ -163,47 +161,47 @@ module spi_top always @(posedge wb_clk_i or posedge wb_rst_i) begin if (wb_rst_i) - wb_int_o <= #Tp 1'b0; + wb_int_o <= 1'b0; else if (ie && tip && last_bit && pos_edge) - wb_int_o <= #Tp 1'b1; + wb_int_o <= 1'b1; else if (wb_ack_o) - wb_int_o <= #Tp 1'b0; + wb_int_o <= 1'b0; end // Divider register always @(posedge wb_clk_i or posedge wb_rst_i) begin if (wb_rst_i) - divider <= #Tp {`SPI_DIVIDER_LEN{1'b0}}; + divider <= {`SPI_DIVIDER_LEN{1'b0}}; else if (spi_divider_sel && wb_we_i && !tip) begin `ifdef SPI_DIVIDER_LEN_8 if (wb_sel_i[0]) - divider <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:0]; + divider <= wb_dat_i[`SPI_DIVIDER_LEN-1:0]; `endif `ifdef SPI_DIVIDER_LEN_16 if (wb_sel_i[0]) - divider[7:0] <= #Tp wb_dat_i[7:0]; + divider[7:0] <= wb_dat_i[7:0]; if (wb_sel_i[1]) - divider[`SPI_DIVIDER_LEN-1:8] <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:8]; + divider[`SPI_DIVIDER_LEN-1:8] <= wb_dat_i[`SPI_DIVIDER_LEN-1:8]; `endif `ifdef SPI_DIVIDER_LEN_24 if (wb_sel_i[0]) - divider[7:0] <= #Tp wb_dat_i[7:0]; + divider[7:0] <= wb_dat_i[7:0]; if (wb_sel_i[1]) - divider[15:8] <= #Tp wb_dat_i[15:8]; + divider[15:8] <= wb_dat_i[15:8]; if (wb_sel_i[2]) - divider[`SPI_DIVIDER_LEN-1:16] <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:16]; + divider[`SPI_DIVIDER_LEN-1:16] <= wb_dat_i[`SPI_DIVIDER_LEN-1:16]; `endif `ifdef SPI_DIVIDER_LEN_32 if (wb_sel_i[0]) - divider[7:0] <= #Tp wb_dat_i[7:0]; + divider[7:0] <= wb_dat_i[7:0]; if (wb_sel_i[1]) - divider[15:8] <= #Tp wb_dat_i[15:8]; + divider[15:8] <= wb_dat_i[15:8]; if (wb_sel_i[2]) - divider[23:16] <= #Tp wb_dat_i[23:16]; + divider[23:16] <= wb_dat_i[23:16]; if (wb_sel_i[3]) - divider[`SPI_DIVIDER_LEN-1:24] <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:24]; + divider[`SPI_DIVIDER_LEN-1:24] <= wb_dat_i[`SPI_DIVIDER_LEN-1:24]; `endif end end @@ -212,16 +210,16 @@ module spi_top always @(posedge wb_clk_i or posedge wb_rst_i) begin if (wb_rst_i) - ctrl <= #Tp {`SPI_CTRL_BIT_NB{1'b0}}; + ctrl <= {`SPI_CTRL_BIT_NB{1'b0}}; else if(spi_ctrl_sel && wb_we_i && !tip) begin if (wb_sel_i[0]) - ctrl[7:0] <= #Tp wb_dat_i[7:0] | {7'b0, ctrl[0]}; + ctrl[7:0] <= wb_dat_i[7:0] | {7'b0, ctrl[0]}; if (wb_sel_i[1]) - ctrl[`SPI_CTRL_BIT_NB-1:8] <= #Tp wb_dat_i[`SPI_CTRL_BIT_NB-1:8]; + ctrl[`SPI_CTRL_BIT_NB-1:8] <= wb_dat_i[`SPI_CTRL_BIT_NB-1:8]; end else if(tip && last_bit && pos_edge) - ctrl[`SPI_CTRL_GO] <= #Tp 1'b0; + ctrl[`SPI_CTRL_GO] <= 1'b0; end assign rx_negedge = ctrl[`SPI_CTRL_RX_NEGEDGE]; @@ -236,36 +234,36 @@ module spi_top always @(posedge wb_clk_i or posedge wb_rst_i) begin if (wb_rst_i) - ss <= #Tp {`SPI_SS_NB{1'b0}}; + ss <= {`SPI_SS_NB{1'b0}}; else if(spi_ss_sel && wb_we_i && !tip) begin `ifdef SPI_SS_NB_8 if (wb_sel_i[0]) - ss <= #Tp wb_dat_i[`SPI_SS_NB-1:0]; + ss <= wb_dat_i[`SPI_SS_NB-1:0]; `endif `ifdef SPI_SS_NB_16 if (wb_sel_i[0]) - ss[7:0] <= #Tp wb_dat_i[7:0]; + ss[7:0] <= wb_dat_i[7:0]; if (wb_sel_i[1]) - ss[`SPI_SS_NB-1:8] <= #Tp wb_dat_i[`SPI_SS_NB-1:8]; + ss[`SPI_SS_NB-1:8] <= wb_dat_i[`SPI_SS_NB-1:8]; `endif `ifdef SPI_SS_NB_24 if (wb_sel_i[0]) - ss[7:0] <= #Tp wb_dat_i[7:0]; + ss[7:0] <= wb_dat_i[7:0]; if (wb_sel_i[1]) - ss[15:8] <= #Tp wb_dat_i[15:8]; + ss[15:8] <= wb_dat_i[15:8]; if (wb_sel_i[2]) - ss[`SPI_SS_NB-1:16] <= #Tp wb_dat_i[`SPI_SS_NB-1:16]; + ss[`SPI_SS_NB-1:16] <= wb_dat_i[`SPI_SS_NB-1:16]; `endif `ifdef SPI_SS_NB_32 if (wb_sel_i[0]) - ss[7:0] <= #Tp wb_dat_i[7:0]; + ss[7:0] <= wb_dat_i[7:0]; if (wb_sel_i[1]) - ss[15:8] <= #Tp wb_dat_i[15:8]; + ss[15:8] <= wb_dat_i[15:8]; if (wb_sel_i[2]) - ss[23:16] <= #Tp wb_dat_i[23:16]; + ss[23:16] <= wb_dat_i[23:16]; if (wb_sel_i[3]) - ss[`SPI_SS_NB-1:24] <= #Tp wb_dat_i[`SPI_SS_NB-1:24]; + ss[`SPI_SS_NB-1:24] <= wb_dat_i[`SPI_SS_NB-1:24]; `endif end end -- cgit v1.2.3 From 035440ab7dce5c13655539db606de531606bad59 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 22 Feb 2010 15:39:53 -0800 Subject: settings bus with 16 bit wishbone interface, put on the main wishbone in u1e --- usrp2/control_lib/settings_bus_16LE.v | 54 +++++++++++++++++++++++++++++++++++ usrp2/top/u1e/Makefile | 2 +- usrp2/top/u1e/u1e_core.v | 15 ++++++++-- 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 usrp2/control_lib/settings_bus_16LE.v diff --git a/usrp2/control_lib/settings_bus_16LE.v b/usrp2/control_lib/settings_bus_16LE.v new file mode 100644 index 000000000..fbef9b1c9 --- /dev/null +++ b/usrp2/control_lib/settings_bus_16LE.v @@ -0,0 +1,54 @@ + +// Grab settings off the wishbone bus, send them out to settings bus +// 16 bits little endian, but all registers need to be written 32 bits at a time. +// This means that you write the low 16 bits first and then the high 16 bits. +// The setting regs are strobed when the high 16 bits are written + +module settings_bus_16LE + #(parameter AWIDTH=16) + (input wb_clk, + input wb_rst, + input [AWIDTH-1:0] wb_adr_i, + input [15:0] wb_dat_i, + input wb_stb_i, + input wb_we_i, + output reg wb_ack_o, + output strobe, + output reg [7:0] addr, + output reg [31:0] data); + + reg stb_int; + + always @(posedge wb_clk) + if(wb_rst) + begin + stb_int <= 1'b0; + addr <= 8'd0; + data <= 32'd0; + end + else if(wb_we_i & wb_stb_i) + begin + addr <= wb_adr_i[9:2]; + if(wb_adr_i[1]) + begin + stb_int <= 1'b1; // We now have both halves + data[31:16] <= wb_dat_i; + end + else + begin + stb_int <= 1'b0; // Don't strobe, we need other half + data[15:0] <= wb_dat_i; + end + end + else + stb_int <= 1'b0; + + always @(posedge wb_clk) + if(wb_rst) + wb_ack_o <= 0; + else + wb_ack_o <= wb_stb_i & ~wb_ack_o; + + assign strobe = stb_int & wb_ack_o; + +endmodule // settings_bus_16LE diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index 9381789a7..bcd80df6a 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -69,7 +69,7 @@ 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/settings_bus_16LE.v \ control_lib/srl.v \ control_lib/system_control.v \ control_lib/wb_1master.v \ diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index ad3234b56..7ac4c8f86 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -103,7 +103,7 @@ module u1e_core .sf_dat_o(sf_dat_mosi),.sf_adr_o(sf_adr),.sf_sel_o(sf_sel),.sf_we_o(sf_we),.sf_cyc_o(sf_cyc),.sf_stb_o(sf_stb), .sf_dat_i(sf_dat_miso),.sf_ack_i(sf_ack),.sf_err_i(0),.sf_rty_i(0) ); - assign s5_ack = 0; assign s6_ack = 0; assign s7_ack = 0; + assign s6_ack = 0; assign s7_ack = 0; assign s8_ack = 0; assign s9_ack = 0; assign sa_ack = 0; assign sb_ack = 0; assign sc_ack = 0; assign sd_ack = 0; assign se_ack = 0; assign sf_ack = 0; @@ -182,10 +182,21 @@ module u1e_core nsgpio16LE nsgpio16LE(.clk_i(wb_clk),.rst_i(wb_rst), .cyc_i(s4_cyc),.stb_i(s4_stb),.adr_i(s4_adr[3:0]),.we_i(s4_we), - .dat_i(s4_dat_o),.dat_o(s4_dat_i),.ack_o(s4_ack), + .dat_i(s4_dat_mosi),.dat_o(s4_dat_miso),.ack_o(s4_ack), .atr(atr_lines),.debug_0(debug_gpio_0),.debug_1(debug_gpio_1), .gpio( {io_tx,io_rx} ) ); + // ///////////////////////////////////////////////////////////////////////// + // Settings Bus -- Slave #5 + + wire [7:0] set_addr; + wire [31:0] set_data; + wire set_stb; + + settings_bus_16LE settings_bus_16LE + (.wb_clk(wb_clk),.wb_rst(wb_rst),.wb_adr_i(s5_adr),.wb_dat_i(s5_dat_mosi), + .wb_stb_i(s5_stb),.wb_we_i(s5_we),.wb_ack_o(s5_ack), + .strobe(set_stb),.addr(set_addr),.data(set_data) ); // ///////////////////////////////////////////////////////////////////////////////////// // Debug Pins -- cgit v1.2.3 From 89fc3946d6fa590dd8047984ed8718a6ffa4ab77 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 23 Feb 2010 16:35:06 -0800 Subject: use our fancy new debug ports --- usrp2/top/u1e/u1e_core.v | 3 +++ 1 file changed, 3 insertions(+) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 7ac4c8f86..12c566b6c 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -206,6 +206,9 @@ module u1e_core assign debug = { { 1'b0, EM_WAIT0, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, { EM_D } }; + assign debug_gpio_0 = { m0_we, m0_stb, m0_ack, s1_stb, s0_stb, m0_adr[10:0], m0_dat_mosi[15:0] }; + assign debug_gpio_1 = { debug_txd, debug_rxd }; + assign { debug_led[2],debug_led[0],debug_led[1] } = reg_fast; // LEDs are arranged funny on board endmodule // u1e_core -- cgit v1.2.3 From 702c87c3bae259f038d2c10fe32903f391e95de1 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 23 Feb 2010 19:54:54 -0800 Subject: first cut at making a bidirectional 2 port ram for the gpmc data interface ISE chokes on the unequal size ram --- usrp2/control_lib/ram_2port_mixed_width.v | 44 +++++++++++++++++++++++++++++++ usrp2/gpmc/gpmc.v | 24 ++++++++++++----- usrp2/top/u1e/Makefile | 1 + 3 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 usrp2/control_lib/ram_2port_mixed_width.v diff --git a/usrp2/control_lib/ram_2port_mixed_width.v b/usrp2/control_lib/ram_2port_mixed_width.v new file mode 100644 index 000000000..3fa43114f --- /dev/null +++ b/usrp2/control_lib/ram_2port_mixed_width.v @@ -0,0 +1,44 @@ + + +module ram_2port_mixed_width + #(parameter AWIDTH=9) + (input clk16, + input en16, + input we16, + input [10:0] addr16, + input [15:0] di16, + output reg [15:0] do16, + + input clk32, + input en32, + input we32, + input [9:0] addr32, + input [31:0] di32, + output reg [31:0] do32); + + reg [31:0] ram [(1< Date: Thu, 25 Feb 2010 16:50:09 -0800 Subject: First cut at passing data buffers around on GPMC bus --- usrp2/gpmc/dbsm.v | 88 +++++++++++++++++++++++++++++++++++++++++++++++ usrp2/gpmc/gpmc.v | 45 ++++++++++++++++++------ usrp2/models/gpmc_model.v | 23 ++++++++++--- usrp2/top/u1e/tb_u1e.v | 11 ++++-- usrp2/top/u1e/u1e.v | 3 +- usrp2/top/u1e/u1e_core.v | 20 +++++++---- 6 files changed, 165 insertions(+), 25 deletions(-) create mode 100644 usrp2/gpmc/dbsm.v diff --git a/usrp2/gpmc/dbsm.v b/usrp2/gpmc/dbsm.v new file mode 100644 index 000000000..0f27be46a --- /dev/null +++ b/usrp2/gpmc/dbsm.v @@ -0,0 +1,88 @@ + +module bsm + (input clk, input reset, input clear, + input write_done, + input read_done, + output readable, + output writeable); + + reg state; + localparam ST_WRITEABLE = 0; + localparam ST_READABLE = 1; + + always @(posedge clk) + if(reset | clear) + state <= ST_WRITEABLE; + else + case(state) + ST_WRITEABLE : + if(write_done) + state <= ST_READABLE; + ST_READABLE : + if(read_done) + state <= ST_WRITEABLE; + endcase // case (state) + + assign readable = (state == ST_READABLE); + assign writeable = (state == ST_WRITEABLE); + +endmodule // bsm + +module dbsm + (input clk, input reset, input clear, + output reg read_sel, output read_ready, input read_done, + output reg write_sel, output write_ready, input write_done); + + localparam NUM_BUFS = 2; + + wire [NUM_BUFS-1:0] readable, writeable, read_done_buf, write_done_buf; + + // Two of these buffer state machines + genvar i; + for(i=0;i Date: Thu, 25 Feb 2010 16:50:29 -0800 Subject: ISE chokes on the pure verilog version so we use the macro --- usrp2/control_lib/ram_2port_mixed_width.v | 53 ++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/usrp2/control_lib/ram_2port_mixed_width.v b/usrp2/control_lib/ram_2port_mixed_width.v index 3fa43114f..e10321959 100644 --- a/usrp2/control_lib/ram_2port_mixed_width.v +++ b/usrp2/control_lib/ram_2port_mixed_width.v @@ -1,5 +1,3 @@ - - module ram_2port_mixed_width #(parameter AWIDTH=9) (input clk16, @@ -7,14 +5,58 @@ module ram_2port_mixed_width input we16, input [10:0] addr16, input [15:0] di16, - output reg [15:0] do16, + output [15:0] do16, input clk32, input en32, input we32, input [9:0] addr32, input [31:0] di32, - output reg [31:0] do32); + output [31:0] do32); + + RAMB16BWER #(.DATA_WIDTH_A(18), // Valid values are 0, 1, 2, 4, 9, 18, or 36 + .DATA_WIDTH_B(36), // Valid values are 0, 1, 2, 4, 9, 18, or 36 + .DOA_REG(0), // Specifies to enable=1/disable=0 port A output registers + .DOB_REG(0), // Specifies to enable=1/disable=0 port B output registers + .INIT_A(36'h000000000), // Initial values on A output port + .INIT_B(36'h000000000), // Initial values on B output port + .RSTTYPE("SYNC"), // Specifes reset type to be "SYNC" or "ASYNC" + .SIM_COLLISION_CHECK("ALL"), // Collision check enable "ALL", "WARNING_ONLY", + // "GENERATE_X_ONLY" or "NONE" + .SRVAL_A(36'h000000000), // Set/Reset value for A port output + .SRVAL_B(36'h000000000), // Set/Reset value for B port output + .WRITE_MODE_A("WRITE_FIRST"), // "WRITE_FIRST", "READ_FIRST", or "NO_CHANGE" + .WRITE_MODE_B("WRITE_FIRST")) // "WRITE_FIRST", "READ_FIRST", or "NO_CHANGE" + RAMB16BWER_inst (.DOA(do16), // 32-bit A port data output + .DOB(do32), // 32-bit B port data output + .DOPA(), // 4-bit A port parity data output + .DOPB(), // 4-bit B port parity data output + .ADDRA(addr16), // 14-bit A port address input + .ADDRB(addr32), // 14-bit B port address input + .CLKA(clk16), // 1-bit A port clock input + .CLKB(clk32), // 1-bit B port clock input + .DIA(di16), // 32-bit A port data input + .DIB(di32), // 32-bit B port data input + .DIPA(0), // 4-bit A port parity data input + .DIPB(0), // 4-bit B port parity data input + .ENA(en16), // 1-bit A port enable input + .ENB(en32), // 1-bit B port enable input + .REGCEA(0), // 1-bit A port output register enable input + .REGCEB(0), // 1-bit B port output register enable input + .RSTA(0), // 1-bit A port reset input + .RSTB(0), // 1-bit B port reset input + .WEA({2{we16}}), // 4-bit A port write enable input + .WEB({4{we32}}) // 4-bit B port write enable input + ); + +endmodule // ram_2port_mixed_width + + + + +// ISE 10.1.03 chokes on the following + +/* reg [31:0] ram [(1< Date: Thu, 25 Feb 2010 18:37:25 -0800 Subject: Switched xilinx primitives because they order the bits funny in the other one --- usrp2/control_lib/ram_2port_mixed_width.v | 127 +++++++++++++++++++----------- 1 file changed, 79 insertions(+), 48 deletions(-) diff --git a/usrp2/control_lib/ram_2port_mixed_width.v b/usrp2/control_lib/ram_2port_mixed_width.v index e10321959..e84b0da02 100644 --- a/usrp2/control_lib/ram_2port_mixed_width.v +++ b/usrp2/control_lib/ram_2port_mixed_width.v @@ -1,54 +1,85 @@ + module ram_2port_mixed_width - #(parameter AWIDTH=9) - (input clk16, - input en16, - input we16, - input [10:0] addr16, - input [15:0] di16, - output [15:0] do16, - - input clk32, - input en32, - input we32, - input [9:0] addr32, - input [31:0] di32, - output [31:0] do32); + (input clk16, + input en16, + input we16, + input [10:0] addr16, + input [15:0] di16, + output [15:0] do16, + input clk32, + input en32, + input we32, + input [9:0] addr32, + input [31:0] di32, + output [31:0] do32); + + wire en32a = en32 & ~addr32[9]; + wire en32b = en32 & addr32[9]; + wire en16a = en16 & ~addr16[9]; + wire en16b = en16 & addr16[9]; - RAMB16BWER #(.DATA_WIDTH_A(18), // Valid values are 0, 1, 2, 4, 9, 18, or 36 - .DATA_WIDTH_B(36), // Valid values are 0, 1, 2, 4, 9, 18, or 36 - .DOA_REG(0), // Specifies to enable=1/disable=0 port A output registers - .DOB_REG(0), // Specifies to enable=1/disable=0 port B output registers - .INIT_A(36'h000000000), // Initial values on A output port - .INIT_B(36'h000000000), // Initial values on B output port - .RSTTYPE("SYNC"), // Specifes reset type to be "SYNC" or "ASYNC" - .SIM_COLLISION_CHECK("ALL"), // Collision check enable "ALL", "WARNING_ONLY", - // "GENERATE_X_ONLY" or "NONE" - .SRVAL_A(36'h000000000), // Set/Reset value for A port output - .SRVAL_B(36'h000000000), // Set/Reset value for B port output - .WRITE_MODE_A("WRITE_FIRST"), // "WRITE_FIRST", "READ_FIRST", or "NO_CHANGE" - .WRITE_MODE_B("WRITE_FIRST")) // "WRITE_FIRST", "READ_FIRST", or "NO_CHANGE" - RAMB16BWER_inst (.DOA(do16), // 32-bit A port data output - .DOB(do32), // 32-bit B port data output - .DOPA(), // 4-bit A port parity data output - .DOPB(), // 4-bit B port parity data output - .ADDRA(addr16), // 14-bit A port address input - .ADDRB(addr32), // 14-bit B port address input - .CLKA(clk16), // 1-bit A port clock input - .CLKB(clk32), // 1-bit B port clock input - .DIA(di16), // 32-bit A port data input - .DIB(di32), // 32-bit B port data input - .DIPA(0), // 4-bit A port parity data input - .DIPB(0), // 4-bit B port parity data input - .ENA(en16), // 1-bit A port enable input - .ENB(en32), // 1-bit B port enable input - .REGCEA(0), // 1-bit A port output register enable input - .REGCEB(0), // 1-bit B port output register enable input - .RSTA(0), // 1-bit A port reset input - .RSTB(0), // 1-bit B port reset input - .WEA({2{we16}}), // 4-bit A port write enable input - .WEB({4{we32}}) // 4-bit B port write enable input - ); + wire [31:0] do32a, do32b; + wire [15:0] do16a, do16b; + + assign do32 = addr32[9] ? do32b : do32a; + assign do16 = addr16[10] ? do16b : do16a; + RAMB16BWE_S36_S18 #(.INIT_A(36'h000000000), + .INIT_B(18'h00000), + .SIM_COLLISION_CHECK("ALL"), // "NONE", "WARNING_ONLY", "GENERATE_X_ONLY", "ALL" + .SRVAL_A(36'h000000000), // Port A output value upon SSR assertion + .SRVAL_B(18'h00000), // Port B output value upon SSR assertion + .WRITE_MODE_A("WRITE_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE + .WRITE_MODE_B("WRITE_FIRST") // WRITE_FIRST, READ_FIRST or NO_CHANGE + ) + RAMB16BWE_S36_S18_0 (.DOA(do32a), // Port A 32-bit Data Output + .DOB(do16a), // Port B 16-bit Data Output + .DOPA(), // Port A 4-bit Parity Output + .DOPB(), // Port B 2-bit Parity Output + .ADDRA(addr32[8:0]), // Port A 9-bit Address Input + .ADDRB(addr16[9:0]), // Port B 10-bit Address Input + .CLKA(clk32), // Port A 1-bit Clock + .CLKB(clk16), // Port B 1-bit Clock + .DIA(di32), // Port A 32-bit Data Input + .DIB(di16), // Port B 16-bit Data Input + .DIPA(0), // Port A 4-bit parity Input + .DIPB(0), // Port-B 2-bit parity Input + .ENA(en32a), // Port A 1-bit RAM Enable Input + .ENB(en16a), // Port B 1-bit RAM Enable Input + .SSRA(0), // Port A 1-bit Synchronous Set/Reset Input + .SSRB(0), // Port B 1-bit Synchronous Set/Reset Input + .WEA({4{we32}}), // Port A 4-bit Write Enable Input + .WEB({2{we16}}) // Port B 2-bit Write Enable Input + ); + + RAMB16BWE_S36_S18 #(.INIT_A(36'h000000000), + .INIT_B(18'h00000), + .SIM_COLLISION_CHECK("ALL"), // "NONE", "WARNING_ONLY", "GENERATE_X_ONLY", "ALL" + .SRVAL_A(36'h000000000), // Port A output value upon SSR assertion + .SRVAL_B(18'h00000), // Port B output value upon SSR assertion + .WRITE_MODE_A("WRITE_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE + .WRITE_MODE_B("WRITE_FIRST") // WRITE_FIRST, READ_FIRST or NO_CHANGE + ) + RAMB16BWE_S36_S18_1 (.DOA(do32b), // Port A 32-bit Data Output + .DOB(do16b), // Port B 16-bit Data Output + .DOPA(), // Port A 4-bit Parity Output + .DOPB(), // Port B 2-bit Parity Output + .ADDRA(addr32[8:0]), // Port A 9-bit Address Input + .ADDRB(addr16[9:0]), // Port B 10-bit Address Input + .CLKA(clk32), // Port A 1-bit Clock + .CLKB(clk16), // Port B 1-bit Clock + .DIA(di32), // Port A 32-bit Data Input + .DIB(di16), // Port B 16-bit Data Input + .DIPA(0), // Port A 4-bit parity Input + .DIPB(0), // Port-B 2-bit parity Input + .ENA(en32b), // Port A 1-bit RAM Enable Input + .ENB(en16b), // Port B 1-bit RAM Enable Input + .SSRA(0), // Port A 1-bit Synchronous Set/Reset Input + .SSRB(0), // Port B 1-bit Synchronous Set/Reset Input + .WEA({4{we32}}), // Port A 4-bit Write Enable Input + .WEB({2{we16}}) // Port B 2-bit Write Enable Input + ); + endmodule // ram_2port_mixed_width -- cgit v1.2.3 From 2f9b93f32ed8e561a0e92e2e32af03707475011c Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 25 Feb 2010 18:38:07 -0800 Subject: edge sync on done signals so we only fill/empty one buffer --- usrp2/gpmc/edge_sync.v | 22 ++++++++++++++++++++++ usrp2/gpmc/gpmc.v | 12 ++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 usrp2/gpmc/edge_sync.v diff --git a/usrp2/gpmc/edge_sync.v b/usrp2/gpmc/edge_sync.v new file mode 100644 index 000000000..5d9417c08 --- /dev/null +++ b/usrp2/gpmc/edge_sync.v @@ -0,0 +1,22 @@ + + +module edge_sync + #(parameter POSEDGE = 1) + (input clk, + input rst, + input sig, + output trig); + + reg [1:0] delay; + + always @(posedge clk) + if(rst) + delay <= 2'b00; + else + delay <= {delay[0],sig}; + + assign trig = POSEDGE ? (delay==2'b01) : (delay==2'b10); + +endmodule // edge_sync + + diff --git a/usrp2/gpmc/gpmc.v b/usrp2/gpmc/gpmc.v index 91d02bfec..831df3b4c 100644 --- a/usrp2/gpmc/gpmc.v +++ b/usrp2/gpmc/gpmc.v @@ -32,7 +32,11 @@ module gpmc // //////////////////////////////////////////// // Write path wire read_sel_in, write_sel_in, clear_in; - wire write_done_in = ~EM_NCS4 & ~EM_NWE & (EM_A == 10'h3FF); + wire write_done_in; + + edge_sync #(.POSEDGE(0)) + edge_sync_wdi(.clk(wb_clk), .rst(wb_rst), + .sig(~EM_NCS4 & ~EM_NWE & (EM_A == 10'h3FF)), .trig(write_done_in)); ram_2port_mixed_width buffer_in (.clk16(wb_clk), .en16(~EM_NCS4), .we16(~EM_NWE), .addr16({write_sel_in,EM_A}), .di16(EM_D), .do16(), @@ -47,7 +51,11 @@ module gpmc // //////////////////////////////////////////// // Read path wire read_sel_out, write_sel_out, clear_out; - wire read_done_out = ~EM_NCS4 & ~EM_NOE & (EM_A == 10'h3FF); + wire read_done_out; + + edge_sync #(.POSEDGE(0)) + edge_sync_rdo(.clk(wb_clk), .rst(wb_rst), + .sig(~EM_NCS4 & ~EM_NOE & (EM_A == 10'h3FF)), .trig(read_done_out)); ram_2port_mixed_width buffer_out (.clk16(wb_clk), .en16(~EM_NCS4), .we16(0), .addr16({read_sel_out,EM_A}), .di16(0), .do16(EM_D_ram), -- cgit v1.2.3 From d808829fee0c93f22c2ff3b34d0772d7cb91df5c Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 25 Feb 2010 18:38:35 -0800 Subject: corrected logic --- usrp2/gpmc/dbsm.v | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/usrp2/gpmc/dbsm.v b/usrp2/gpmc/dbsm.v index 0f27be46a..ff61859ec 100644 --- a/usrp2/gpmc/dbsm.v +++ b/usrp2/gpmc/dbsm.v @@ -56,28 +56,18 @@ module dbsm full <= 0; end else - if(write_done) - if(writeable[write_sel]==(NUM_BUFS-1)) - begin - write_sel <= 0; - if(read_sel == 0) - full <= 1; - end + if(write_done & writeable[write_sel]) + if(write_sel ==(NUM_BUFS-1)) + write_sel <= 0; else - begin - write_sel <= write_sel + 1; - if(read_sel == write_sel + 1) - full <= 1; - end // else: !if(writeable[write_sel]==(NUM_BUFS-1)) - else if(read_done) - full <= 0; - + write_sel <= write_sel + 1; + always @(posedge clk) if(reset | clear) read_sel <= 0; else - if(read_done) - if(readable[read_sel]==(NUM_BUFS-1)) + if(read_done & readable[read_sel]) + if(read_sel==(NUM_BUFS-1)) read_sel <= 0; else read_sel <= read_sel + 1; -- cgit v1.2.3 From c8e869b2e685cb8a5c012498b7f47aaadf39698a Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 25 Feb 2010 18:38:48 -0800 Subject: loopback and test --- usrp2/models/gpmc_model.v | 11 ++++++----- usrp2/top/u1e/u1e_core.v | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/usrp2/models/gpmc_model.v b/usrp2/models/gpmc_model.v index 1e7dcdde5..3424671bd 100644 --- a/usrp2/models/gpmc_model.v +++ b/usrp2/models/gpmc_model.v @@ -78,11 +78,12 @@ module gpmc_model #1000; GPMC_Read(1,36); #1000; - GPMC_Write(0,36,16'hF00D); - GPMC_Write(0,38,16'hF00D); - GPMC_Write(0,40,16'hF00D); - GPMC_Write(0,11'h7FFE,16'hF00D); - #1000; + GPMC_Write(0,36,16'h1234); + GPMC_Write(0,38,16'h5678); + GPMC_Write(0,40,16'h9abc); + GPMC_Write(0,11'h2F4,16'hF00D); + GPMC_Write(0,11'h7FE,16'hF00D); + #100000; $finish; end diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 7feafeda8..e14152f33 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -26,6 +26,13 @@ module u1e_core wire [aw-1:0] m0_adr; wire [sw-1:0] m0_sel; wire m0_cyc, m0_stb, m0_we, m0_ack, m0_err, m0_rty; + + // FIFO buffers + wire [31:0] read_data, write_data; + wire [8:0] read_addr, write_addr; + reg [8:0] addr; + + wire read_done, write_done, read_en, write_en, read_ready, write_ready; gpmc gpmc (.EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), @@ -43,9 +50,32 @@ module u1e_core .read_ready(read_ready), .read_done(read_done), .write_en(write_en), .write_addr(write_addr), .write_data(write_data), .write_ready(write_ready), .write_done(write_done) ); + + // Loopback + assign write_data = read_data; + + reg [10:0] counter; + assign write_addr = counter[10:2]; + assign read_addr = counter[10:2]; - assign wb_clk = clk_fpga; - + assign read_done = (counter == 11'h7FF); + assign write_done = (counter == 11'h7FF); + + always @(posedge wb_clk) + if(wb_rst) + counter <= 0; + else + if(counter == 0) + counter <= write_ready & read_ready; + else if(counter == 11'h7FF) + counter <= 0; + else + counter <= counter + 1; + + assign read_en = (counter[1:0] == 1); + assign write_en = (counter[1:0] == 2); + + // ///////////////////////////////////////////////////////////////////////////////////// // Wishbone Intercon, single master wire [dw-1:0] s0_dat_mosi, s1_dat_mosi, s0_dat_miso, s1_dat_miso, s2_dat_mosi, s3_dat_mosi, s2_dat_miso, s3_dat_miso, -- cgit v1.2.3 From bcf582bab2544a1d519f84c659322c4c4adc59a1 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 25 Feb 2010 18:48:51 -0800 Subject: fix syntax error which icarus allowed (filed a bug with them) --- usrp2/gpmc/dbsm.v | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/usrp2/gpmc/dbsm.v b/usrp2/gpmc/dbsm.v index ff61859ec..530af7205 100644 --- a/usrp2/gpmc/dbsm.v +++ b/usrp2/gpmc/dbsm.v @@ -39,13 +39,15 @@ module dbsm // Two of these buffer state machines genvar i; - for(i=0;i Date: Thu, 25 Feb 2010 18:49:20 -0800 Subject: point to the new files --- usrp2/top/u1e/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index 306ab5bae..3412e227d 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -176,6 +176,8 @@ timing/time_sender.v \ timing/time_sync.v \ timing/timer.v \ gpmc/gpmc.v \ +gpmc/edge_sync.v \ +gpmc/dbsm.v \ top/u1e/u1e_core.v \ top/u1e/u1e.ucf \ top/u1e/u1e.v -- cgit v1.2.3 From 67dd6732b70c1cd35a7134f4830b09b893255935 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 25 Feb 2010 19:43:01 -0800 Subject: gpmc debug pins --- usrp2/gpmc/gpmc.v | 9 ++++++++- usrp2/top/u1e/u1e_core.v | 9 ++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/usrp2/gpmc/gpmc.v b/usrp2/gpmc/gpmc.v index 831df3b4c..cf1357232 100644 --- a/usrp2/gpmc/gpmc.v +++ b/usrp2/gpmc/gpmc.v @@ -16,7 +16,8 @@ module gpmc // RAM Interface signals input ram_clk, input read_en, input [8:0] read_addr, output [31:0] read_data, output read_ready, input read_done, - input write_en, input [8:0] write_addr, input [31:0] write_data, output write_ready, input write_done + input write_en, input [8:0] write_addr, input [31:0] write_data, output write_ready, input write_done, + output [31:0] debug ); wire EM_output_enable = (~EM_NOE & (~EM_NCS4 | ~EM_NCS6)); @@ -65,6 +66,12 @@ module gpmc .read_sel(read_sel_out), .read_ready(rx_have_data), .read_done(read_done_out), .write_sel(write_sel_out), .write_ready(write_ready), .write_done(write_done)); + + assign debug = { { 2'b00, write_done_in, write_sel_in, read_en, read_sel_in, read_ready, read_done}, + { 2'b00, read_sel_out, write_en, write_sel_out, read_done_out, write_ready, write_done }, + { 8'd0 }, + { 8'd0 } }; + // CS6 is Control, Wishbone bus bridge (wb master) // Sync version reg [1:0] cs_del, we_del, oe_del; diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index e14152f33..6706d4aac 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -33,6 +33,8 @@ module u1e_core reg [8:0] addr; wire read_done, write_done, read_en, write_en, read_ready, write_ready; + + wire [31:0] debug_gpmc; gpmc gpmc (.EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), @@ -49,7 +51,8 @@ module u1e_core .read_en(read_en), .read_addr(read_addr), .read_data(read_data), .read_ready(read_ready), .read_done(read_done), .write_en(write_en), .write_addr(write_addr), .write_data(write_data), - .write_ready(write_ready), .write_done(write_done) ); + .write_ready(write_ready), .write_done(write_done), + .debug(debug_gpmc)); // Loopback assign write_data = read_data; @@ -241,10 +244,10 @@ module u1e_core // Debug circuitry assign debug_clk = { EM_CLK, clk_fpga }; - assign debug = { { 1'b0, EM_WAIT0, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, + assign debug = { { rx_have_data, tx_have_space, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, { EM_D } }; - assign debug_gpio_0 = { m0_we, m0_stb, m0_ack, s1_stb, s0_stb, m0_adr[10:0], m0_dat_mosi[15:0] }; + assign debug_gpio_0 = { debug_gpmc }; assign debug_gpio_1 = { debug_txd, debug_rxd }; assign { debug_led[2],debug_led[0],debug_led[1] } = reg_fast; // LEDs are arranged funny on board -- cgit v1.2.3 From e775ce6c17d1e43865cdd3f9472157d0d2d26b92 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 25 Feb 2010 21:09:34 -0800 Subject: invert the pushbuttons since they are active low --- usrp2/top/u1e/u1e.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index 066d02ca4..329d61aa9 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -21,9 +21,9 @@ module u1e IBUFGDS #(.IOSTANDARD("LVDS_33"), .DIFF_TERM("TRUE")) clk_fpga_pin (.O(clk_fpga),.I(CLK_FPGA_P),.IB(CLK_FPGA_N)); - u1e_core u1e_core(.clk_fpga(clk_fpga), .rst_fpga(debug_pb[2]), + u1e_core u1e_core(.clk_fpga(clk_fpga), .rst_fpga(~debug_pb[2]), .debug_led(debug_led), .debug(debug), .debug_clk(debug_clk), - .debug_pb(debug_pb), .dip_sw(dip_sw), .debug_txd(FPGA_TXD), .debug_rxd(FPGA_RXD), + .debug_pb(~debug_pb), .dip_sw(dip_sw), .debug_txd(FPGA_TXD), .debug_rxd(FPGA_RXD), .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), -- cgit v1.2.3 From db60b00d7a1bafe4f3f49e1ec2367897fc8c71ab Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 25 Feb 2010 21:10:26 -0800 Subject: enable was on the wrong address pin, needs to be the highest order one --- usrp2/control_lib/ram_2port_mixed_width.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usrp2/control_lib/ram_2port_mixed_width.v b/usrp2/control_lib/ram_2port_mixed_width.v index e84b0da02..fae7d8de3 100644 --- a/usrp2/control_lib/ram_2port_mixed_width.v +++ b/usrp2/control_lib/ram_2port_mixed_width.v @@ -15,8 +15,8 @@ module ram_2port_mixed_width wire en32a = en32 & ~addr32[9]; wire en32b = en32 & addr32[9]; - wire en16a = en16 & ~addr16[9]; - wire en16b = en16 & addr16[9]; + wire en16a = en16 & ~addr16[10]; + wire en16b = en16 & addr16[10]; wire [31:0] do32a, do32b; wire [15:0] do16a, do16b; -- cgit v1.2.3 From 4288c956b45143f3cab7b798758ff41ffb43aa4a Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 25 Feb 2010 21:55:13 -0800 Subject: debug pins --- usrp2/top/u1e/u1e_core.v | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 6706d4aac..2645225a0 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -216,7 +216,7 @@ module u1e_core // ///////////////////////////////////////////////////////////////////////// // GPIOs -- Slave #4 - +/* wire [31:0] atr_lines; wire [31:0] debug_gpio_0, debug_gpio_1; @@ -226,7 +226,7 @@ module u1e_core .dat_i(s4_dat_mosi),.dat_o(s4_dat_miso),.ack_o(s4_ack), .atr(atr_lines),.debug_0(debug_gpio_0),.debug_1(debug_gpio_1), .gpio( {io_tx,io_rx} ) ); - +*/ // ///////////////////////////////////////////////////////////////////////// // Settings Bus -- Slave #5 @@ -247,6 +247,7 @@ module u1e_core assign debug = { { rx_have_data, tx_have_space, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, { EM_D } }; + assign {io_tx,io_rx} = debug_gpmc; assign debug_gpio_0 = { debug_gpmc }; assign debug_gpio_1 = { debug_txd, debug_rxd }; -- cgit v1.2.3 From b74388567c0ed3048e45158ac077e31def59fea1 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 25 Mar 2010 15:49:23 -0700 Subject: connected spi pins, but the spi core still needs to be redone for 16 bit interfaces Also reconnected GPIOs so you'll need to send commands in order to get debug pins on the GPIOs --- usrp2/top/u1e/u1e.ucf | 72 ++++++++++++++++++++++++++---------------------- usrp2/top/u1e/u1e.v | 16 +++++++++++ usrp2/top/u1e/u1e_core.v | 12 ++++---- 3 files changed, 60 insertions(+), 40 deletions(-) diff --git a/usrp2/top/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf index f237eb60c..27f507c6b 100644 --- a/usrp2/top/u1e/u1e.ucf +++ b/usrp2/top/u1e/u1e.ucf @@ -68,27 +68,43 @@ NET "overo_gpio147" LOC = "B6" ; # rx_overrun #NET "overo_txd1" LOC = "C6" ; #NET "overo_rxd1" LOC = "D6" ; +## FTDI UART to USB converter NET "FPGA_TXD" LOC = "U1" ; NET "FPGA_RXD" LOC = "T6" ; #NET "SYSEN" LOC = "C11" ; +## I2C NET "db_scl" LOC = "U4" ; NET "db_sda" LOC = "U5" ; -#NET "db_sclk_rx" LOC = "W3" ; -#NET "db_miso_rx" LOC = "W2" ; -#NET "db_mosi_rx" LOC = "V4" ; -#NET "db_sen_rx" LOC = "V3" ; -#NET "db_sclk_tx" LOC = "Y1" ; -#NET "db_miso_tx" LOC = "W1" ; -#NET "db_mosi_tx" LOC = "R3" ; -#NET "db_sen_tx" LOC = "T4" ; -## Clock Gen -#NET "cgen_miso" LOC = "U2" ; -#NET "cgen_mosi" LOC = "V1" ; -#NET "cgen_sclk" LOC = "R5" ; -#NET "cgen_sen_b" LOC = "T1" ; +## SPI +### DBoard SPI +NET "db_sclk_rx" LOC = "W3" ; +NET "db_miso_rx" LOC = "W2" ; +NET "db_mosi_rx" LOC = "V4" ; +NET "db_sen_rx" LOC = "V3" ; +NET "db_sclk_tx" LOC = "Y1" ; +NET "db_miso_tx" LOC = "W1" ; +NET "db_mosi_tx" LOC = "R3" ; +NET "db_sen_tx" LOC = "T4" ; + +### AD9862 SPI and aux SPI Interfaces +#NET "aux_sdi_codec" LOC = "F19" ; +#NET "aux_sdo_codec" LOC = "F18" ; +#NET "aux_sclk_codec" LOC = "D21" ; +NET "sen_codec" LOC = "D20" ; +NET "mosi_codec" LOC = "E19" ; +NET "miso_codec" LOC = "F21" ; +NET "sclk_codec" LOC = "E20" ; + +### Clock Gen SPI +NET "cgen_miso" LOC = "U2" ; +NET "cgen_mosi" LOC = "V1" ; +NET "cgen_sclk" LOC = "R5" ; +NET "cgen_sen_b" LOC = "T1" ; + +## Clock gen control #NET "cgen_st_status" LOC = "D4" ; #NET "cgen_st_ld" LOC = "D1" ; #NET "cgen_st_refmon" LOC = "E1" ; @@ -147,17 +163,8 @@ NET "dip_sw<2>" LOC = "J4" ; NET "dip_sw<1>" LOC = "J6" ; NET "dip_sw<0>" LOC = "J7" ; -## AD9862 Interface -#NET "aux_sdi_codec" LOC = "F19" ; -#NET "aux_sdo_codec" LOC = "F18" ; -#NET "aux_sclk_codec" LOC = "D21" ; -#NET "reset_codec" LOC = "D22" ; -#NET "sen_codec" LOC = "D20" ; -#NET "mosi_codec" LOC = "E19" ; -#NET "miso_codec" LOC = "F21" ; -#NET "sclk_codec" LOC = "E20" ; - #NET "RXSYNC" LOC = "F22" ; +#NET "reset_codec" LOC = "D22" ; #NET "DB<11>" LOC = "E22" ; #NET "DB<10>" LOC = "J19" ; @@ -248,13 +255,12 @@ NET "io_rx<15>" LOC = "Y4" ; #NET "fpga_cfg_init_b" LOC = "W15" ; ## Unnamed, need to figure out what they do -#NET "unnamed_net37" LOC = "B1" ; -#NET "unnamed_net36" LOC = "B22" ; -#NET "unnamed_net35" LOC = "D2" ; -#NET "unnamed_net34" LOC = "A21" ; -#NET "unnamed_net45" LOC = "F7" ; -#NET "unnamed_net44" LOC = "V6" ; -#NET "unnamed_net43" LOC = "AA3" ; -#NET "unnamed_net42" LOC = "AB3" ; - -#NET "GND" LOC = "V19" ; +#NET "unnamed_net37" LOC = "B1" ; # TMS +#NET "unnamed_net36" LOC = "B22" ; # TDO +#NET "unnamed_net35" LOC = "D2" ; # TDI +#NET "unnamed_net34" LOC = "A21" ; # TCK +#NET "unnamed_net45" LOC = "F7" ; # PUDC_B +#NET "unnamed_net44" LOC = "V6" ; # M2 +#NET "unnamed_net43" LOC = "AA3" ; # M1 +#NET "unnamed_net42" LOC = "AB3" ; # M0 +#NET "GND" LOC = "V19" ; # Suspend, unused diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index 329d61aa9..f1f491a97 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -11,6 +11,12 @@ module u1e input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, inout db_sda, inout db_scl, // I2C + + output db_sclk_tx, output db_sen_tx, output db_mosi_tx, input db_miso_tx, // DB TX SPI + output db_sclk_rx, output db_sen_rx, output db_mosi_rx, input db_miso_rx, // DB TX SPI + output sclk_codec, output sen_codec, output mosi_codec, input miso_codec, // AD9862 main SPI + output cgen_sclk, output cgen_sen_b, output cgen_mosi, input cgen_miso, // Clock gen SPI + output overo_gpio144, output overo_gpio145, output overo_gpio146, output overo_gpio147, // Fifo controls inout [15:0] io_tx, inout [15:0] io_rx ); @@ -21,6 +27,15 @@ module u1e IBUFGDS #(.IOSTANDARD("LVDS_33"), .DIFF_TERM("TRUE")) clk_fpga_pin (.O(clk_fpga),.I(CLK_FPGA_P),.IB(CLK_FPGA_N)); + // SPI pins + wire mosi, sclk, miso; + assign { db_sclk_tx, db_mosi_tx } = ~db_sen_tx ? {sclk,mosi} : 2'b0; + assign { db_sclk_rx, db_mosi_rx } = ~db_sen_rx ? {sclk,mosi} : 2'b0; + assign { sclk_codec, mosi_codec } = ~sen_codec ? {sclk,mosi} : 2'b0; + assign { cgen_sclk, cgen_mosi } = ~cgen_sen_b ? {sclk,mosi} : 2'b0; + assign miso = (~db_sen_tx & db_miso_tx) | (~db_sen_rx & db_miso_rx) | + (~sen_codec & miso_codec) | (~cgen_sen_b & cgen_miso); + u1e_core u1e_core(.clk_fpga(clk_fpga), .rst_fpga(~debug_pb[2]), .debug_led(debug_led), .debug(debug), .debug_clk(debug_clk), .debug_pb(~debug_pb), .dip_sw(dip_sw), .debug_txd(FPGA_TXD), .debug_rxd(FPGA_RXD), @@ -28,6 +43,7 @@ module u1e .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), .db_sda(db_sda), .db_scl(db_scl), + .sclk(sclk), .sen({cgen_sen_b,sen_codec,db_sen_tx,db_sen_rx}), .mosi(mosi), .miso(miso), .tx_have_space(overo_gpio144), .tx_underrun(overo_gpio145), .rx_have_data(overo_gpio146), .rx_overrun(overo_gpio147), .io_tx(io_tx), .io_rx(io_rx) ); diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 2645225a0..c74d385ee 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -9,6 +9,8 @@ module u1e_core input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, inout db_sda, inout db_scl, + output sclk, output [7:0] sen, output mosi, input miso, + output tx_have_space, output tx_underrun, output rx_have_data, output rx_overrun, inout [15:0] io_tx, inout [15:0] io_rx ); @@ -187,14 +189,11 @@ module u1e_core // ///////////////////////////////////////////////////////////////////////////////////// // Slave 2, SPI - /* spi_top shared_spi (.wb_clk_i(wb_clk),.wb_rst_i(wb_rst),.wb_adr_i(s2_adr[4:0]),.wb_dat_i(s2_dat_o), .wb_dat_o(s2_dat_i),.wb_sel_i(s2_sel),.wb_we_i(s2_we),.wb_stb_i(s2_stb), .wb_cyc_i(s2_cyc),.wb_ack_o(s2_ack),.wb_err_o(),.wb_int_o(spi_int), - .ss_pad_o({sen_tx_db,sen_tx_adc,sen_tx_dac,sen_rx_db,sen_rx_adc,sen_rx_dac,sen_dac,sen_clk}), - .sclk_pad_o(sclk),.mosi_pad_o(mosi),.miso_pad_i(miso) ); - */ + .ss_pad_o(sen), .sclk_pad_o(sclk), .mosi_pad_o(mosi), .miso_pad_i(miso) ); // ///////////////////////////////////////////////////////////////////////// // Slave 3, I2C @@ -216,7 +215,7 @@ module u1e_core // ///////////////////////////////////////////////////////////////////////// // GPIOs -- Slave #4 -/* + wire [31:0] atr_lines; wire [31:0] debug_gpio_0, debug_gpio_1; @@ -226,7 +225,7 @@ module u1e_core .dat_i(s4_dat_mosi),.dat_o(s4_dat_miso),.ack_o(s4_ack), .atr(atr_lines),.debug_0(debug_gpio_0),.debug_1(debug_gpio_1), .gpio( {io_tx,io_rx} ) ); -*/ + // ///////////////////////////////////////////////////////////////////////// // Settings Bus -- Slave #5 @@ -247,7 +246,6 @@ module u1e_core assign debug = { { rx_have_data, tx_have_space, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, { EM_D } }; - assign {io_tx,io_rx} = debug_gpmc; assign debug_gpio_0 = { debug_gpmc }; assign debug_gpio_1 = { debug_txd, debug_rxd }; -- cgit v1.2.3 From 7a3064b67172aea1be00d188bdd79185a7df2ecf Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Fri, 26 Mar 2010 11:30:13 -0700 Subject: connect 2 clock gen controls and 3 status pins to the wishbone so they can be read/controlled from SW --- usrp2/top/u1e/u1e.ucf | 10 +++++----- usrp2/top/u1e/u1e.v | 4 ++++ usrp2/top/u1e/u1e_core.v | 20 +++++++++++++++++--- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/usrp2/top/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf index 27f507c6b..c39759d0b 100644 --- a/usrp2/top/u1e/u1e.ucf +++ b/usrp2/top/u1e/u1e.ucf @@ -105,11 +105,11 @@ NET "cgen_sclk" LOC = "R5" ; NET "cgen_sen_b" LOC = "T1" ; ## Clock gen control -#NET "cgen_st_status" LOC = "D4" ; -#NET "cgen_st_ld" LOC = "D1" ; -#NET "cgen_st_refmon" LOC = "E1" ; -#NET "cgen_sync_b" LOC = "M1" ; -#NET "cgen_ref_sel" LOC = "J1" ; +NET "cgen_st_status" LOC = "D4" ; +NET "cgen_st_ld" LOC = "D1" ; +NET "cgen_st_refmon" LOC = "E1" ; +NET "cgen_sync_b" LOC = "M1" ; +NET "cgen_ref_sel" LOC = "J1" ; ## Debug pins NET "debug_led<2>" LOC = "T5" ; diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index f1f491a97..ab270879c 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -16,6 +16,8 @@ module u1e output db_sclk_rx, output db_sen_rx, output db_mosi_rx, input db_miso_rx, // DB TX SPI output sclk_codec, output sen_codec, output mosi_codec, input miso_codec, // AD9862 main SPI output cgen_sclk, output cgen_sen_b, output cgen_mosi, input cgen_miso, // Clock gen SPI + + input cgen_st_status, input cgen_st_ld, input cgen_st_refmon, output cgen_sync_b, output cgen_ref_sel, output overo_gpio144, output overo_gpio145, output overo_gpio146, output overo_gpio147, // Fifo controls inout [15:0] io_tx, inout [15:0] io_rx @@ -44,6 +46,8 @@ module u1e .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), .db_sda(db_sda), .db_scl(db_scl), .sclk(sclk), .sen({cgen_sen_b,sen_codec,db_sen_tx,db_sen_rx}), .mosi(mosi), .miso(miso), + .cgen_st_status(cgen_st_status), .cgen_st_ld(cgen_st_ld),.cgen_st_refmon(cgen_st_refmon), + .cgen_sync_b(cgen_sync_b), .cgen_ref_sel(cgen_ref_sel), .tx_have_space(overo_gpio144), .tx_underrun(overo_gpio145), .rx_have_data(overo_gpio146), .rx_overrun(overo_gpio147), .io_tx(io_tx), .io_rx(io_rx) ); diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index c74d385ee..4f0227dfd 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -10,7 +10,8 @@ module u1e_core inout db_sda, inout db_scl, output sclk, output [7:0] sen, output mosi, input miso, - + + input cgen_st_status, input cgen_st_ld, input cgen_st_refmon, output cgen_sync_b, output cgen_ref_sel, output tx_have_space, output tx_underrun, output rx_have_data, output rx_overrun, inout [15:0] io_tx, inout [15:0] io_rx ); @@ -151,13 +152,15 @@ module u1e_core assign sc_ack = 0; assign sd_ack = 0; assign se_ack = 0; assign sf_ack = 0; // ///////////////////////////////////////////////////////////////////////////////////// - // Slave 0, LEDs and Switches + // Slave 0, Misc LEDs, Switches, controls reg [15:0] reg_fast, reg_slow; localparam REG_FAST = 7'd4; localparam REG_SWITCHES = 7'd6; localparam REG_GPIOS = 7'd8; - + localparam REG_CGEN_ST = 7'd9; + localparam REG_CGEN_CTRL = 7'd10; + reg [3:0] reg_gpios; always @(posedge wb_clk) @@ -168,8 +171,19 @@ module u1e_core if(s0_cyc & s0_stb & s0_we & (s0_adr[6:0] == REG_GPIOS)) reg_gpios <= s0_dat_mosi; + reg [1:0] reg_cgen_ctrls; + + always @(posedge wb_clk) + if(wb_rst) + reg_cgen_ctrls <= 2'b11; + else if(s0_cyc & s0_stb & s0_we & (s0_adr[6:0] == REG_CGEN_CTRL)) + reg_cgen_ctrls <= s0_dat_mosi; + + assign {cgen_sync_b, cgen_ref_sel} = reg_cgen_ctrls; + assign s0_dat_miso = (s0_adr[6:0] == REG_FAST) ? reg_fast : (s0_adr[6:0] == REG_SWITCHES) ? {5'b0,debug_pb[2:0],dip_sw[7:0]} : + (s0_adr[6:0] == REG_CGEN_ST) ? {13'b0,cgen_st_status,cgen_st_ld,cgen_st_refmon} : 16'hBEEF; assign s0_ack = s0_stb & s0_cyc; -- cgit v1.2.3 From 806a2de4cdd9794f6fba915e32534fd2a0f31cb5 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Fri, 26 Mar 2010 14:04:22 -0700 Subject: remove timescale junk get rid of asynchronous resets fix spelling error corrected comment --- usrp2/opencores/spi/rtl/verilog/spi_clgen.v | 7 +++---- usrp2/opencores/spi/rtl/verilog/spi_defines.v | 2 +- usrp2/opencores/spi/rtl/verilog/spi_shift.v | 9 ++++----- usrp2/opencores/spi/rtl/verilog/spi_top.v | 20 +++++++++++--------- usrp2/opencores/spi/rtl/verilog/timescale.v | 2 -- 5 files changed, 19 insertions(+), 21 deletions(-) delete mode 100644 usrp2/opencores/spi/rtl/verilog/timescale.v diff --git a/usrp2/opencores/spi/rtl/verilog/spi_clgen.v b/usrp2/opencores/spi/rtl/verilog/spi_clgen.v index 3f29f6d7f..2d9c34f40 100644 --- a/usrp2/opencores/spi/rtl/verilog/spi_clgen.v +++ b/usrp2/opencores/spi/rtl/verilog/spi_clgen.v @@ -39,7 +39,6 @@ ////////////////////////////////////////////////////////////////////// `include "spi_defines.v" -`include "timescale.v" module spi_clgen (clk_in, rst, go, enable, last_clk, divider, clk_out, pos_edge, neg_edge); @@ -66,7 +65,7 @@ module spi_clgen (clk_in, rst, go, enable, last_clk, divider, clk_out, pos_edge, assign cnt_one = cnt == {{`SPI_DIVIDER_LEN-1{1'b0}}, 1'b1}; // Counter counts half period - always @(posedge clk_in or posedge rst) + always @(posedge clk_in) begin if(rst) cnt <= {`SPI_DIVIDER_LEN{1'b1}}; @@ -80,7 +79,7 @@ module spi_clgen (clk_in, rst, go, enable, last_clk, divider, clk_out, pos_edge, end // clk_out is asserted every other half period - always @(posedge clk_in or posedge rst) + always @(posedge clk_in) begin if(rst) clk_out <= 1'b0; @@ -89,7 +88,7 @@ module spi_clgen (clk_in, rst, go, enable, last_clk, divider, clk_out, pos_edge, end // Pos and neg edge signals - always @(posedge clk_in or posedge rst) + always @(posedge clk_in) begin if(rst) begin diff --git a/usrp2/opencores/spi/rtl/verilog/spi_defines.v b/usrp2/opencores/spi/rtl/verilog/spi_defines.v index 01de2584d..963a680a8 100644 --- a/usrp2/opencores/spi/rtl/verilog/spi_defines.v +++ b/usrp2/opencores/spi/rtl/verilog/spi_defines.v @@ -137,7 +137,7 @@ `define SPI_TX_2 2 `define SPI_TX_3 3 `define SPI_CTRL 4 -`define SPI_DEVIDE 5 +`define SPI_DIVIDE 5 `define SPI_SS 6 // diff --git a/usrp2/opencores/spi/rtl/verilog/spi_shift.v b/usrp2/opencores/spi/rtl/verilog/spi_shift.v index c8c73706b..ac3bb3f48 100644 --- a/usrp2/opencores/spi/rtl/verilog/spi_shift.v +++ b/usrp2/opencores/spi/rtl/verilog/spi_shift.v @@ -39,7 +39,6 @@ ////////////////////////////////////////////////////////////////////// `include "spi_defines.v" -`include "timescale.v" module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, pos_edge, neg_edge, rx_negedge, tx_negedge, @@ -87,7 +86,7 @@ module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, assign tx_clk = (tx_negedge ? neg_edge : pos_edge) && !last; // Character bit counter - always @(posedge clk or posedge rst) + always @(posedge clk) begin if(rst) cnt <= {`SPI_CHAR_LEN_BITS+1{1'b0}}; @@ -101,7 +100,7 @@ module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, end // Transfer in progress - always @(posedge clk or posedge rst) + always @(posedge clk) begin if(rst) tip <= 1'b0; @@ -112,7 +111,7 @@ module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, end // Sending bits to the line - always @(posedge clk or posedge rst) + always @(posedge clk) begin if (rst) s_out <= 1'b0; @@ -121,7 +120,7 @@ module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, end // Receiving bits from the line - always @(posedge clk or posedge rst) + always @(posedge clk) begin if (rst) data <= {`SPI_MAX_CHAR{1'b0}}; diff --git a/usrp2/opencores/spi/rtl/verilog/spi_top.v b/usrp2/opencores/spi/rtl/verilog/spi_top.v index 071aeefca..8289449a9 100644 --- a/usrp2/opencores/spi/rtl/verilog/spi_top.v +++ b/usrp2/opencores/spi/rtl/verilog/spi_top.v @@ -1,3 +1,6 @@ + +// Modified 2010 by Matt Ettus to remove old verilog style + ////////////////////////////////////////////////////////////////////// //// //// //// spi_top.v //// @@ -40,7 +43,6 @@ `include "spi_defines.v" -`include "timescale.v" module spi_top ( @@ -99,7 +101,7 @@ module spi_top wire last_bit; // marks last character bit // Address decoder - assign spi_divider_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_DEVIDE); + assign spi_divider_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_DIVIDE); assign spi_ctrl_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_CTRL); assign spi_tx_sel[0] = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX_0); assign spi_tx_sel[1] = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX_1); @@ -130,14 +132,14 @@ module spi_top `endif `endif `SPI_CTRL: wb_dat = {{32-`SPI_CTRL_BIT_NB{1'b0}}, ctrl}; - `SPI_DEVIDE: wb_dat = {{32-`SPI_DIVIDER_LEN{1'b0}}, divider}; + `SPI_DIVIDE: wb_dat = {{32-`SPI_DIVIDER_LEN{1'b0}}, divider}; `SPI_SS: wb_dat = {{32-`SPI_SS_NB{1'b0}}, ss}; default: wb_dat = 32'bx; endcase end // Wb data out - always @(posedge wb_clk_i or posedge wb_rst_i) + always @(posedge wb_clk_i) begin if (wb_rst_i) wb_dat_o <= 32'b0; @@ -146,7 +148,7 @@ module spi_top end // Wb acknowledge - always @(posedge wb_clk_i or posedge wb_rst_i) + always @(posedge wb_clk_i) begin if (wb_rst_i) wb_ack_o <= 1'b0; @@ -158,7 +160,7 @@ module spi_top assign wb_err_o = 1'b0; // Interrupt - always @(posedge wb_clk_i or posedge wb_rst_i) + always @(posedge wb_clk_i) begin if (wb_rst_i) wb_int_o <= 1'b0; @@ -169,7 +171,7 @@ module spi_top end // Divider register - always @(posedge wb_clk_i or posedge wb_rst_i) + always @(posedge wb_clk_i) begin if (wb_rst_i) divider <= {`SPI_DIVIDER_LEN{1'b0}}; @@ -207,7 +209,7 @@ module spi_top end // Ctrl register - always @(posedge wb_clk_i or posedge wb_rst_i) + always @(posedge wb_clk_i) begin if (wb_rst_i) ctrl <= {`SPI_CTRL_BIT_NB{1'b0}}; @@ -231,7 +233,7 @@ module spi_top assign ass = ctrl[`SPI_CTRL_ASS]; // Slave select register - always @(posedge wb_clk_i or posedge wb_rst_i) + always @(posedge wb_clk_i) begin if (wb_rst_i) ss <= {`SPI_SS_NB{1'b0}}; diff --git a/usrp2/opencores/spi/rtl/verilog/timescale.v b/usrp2/opencores/spi/rtl/verilog/timescale.v deleted file mode 100644 index 60d4ecbd1..000000000 --- a/usrp2/opencores/spi/rtl/verilog/timescale.v +++ /dev/null @@ -1,2 +0,0 @@ -`timescale 1ns / 10ps - -- cgit v1.2.3 From b9e715983eaa625f65f1ac4d18c7fbc9e5ace4cd Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Fri, 26 Mar 2010 17:12:07 -0700 Subject: connect up the 16 bit spi core --- usrp2/top/u1e/Makefile | 3 +-- usrp2/top/u1e/u1e_core.v | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index 3412e227d..2b78b21bd 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -137,8 +137,7 @@ 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 \ +opencores/spi/rtl/verilog/spi_top16.v \ sdr_lib/acc.v \ sdr_lib/add2.v \ sdr_lib/add2_and_round.v \ diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 4f0227dfd..f2415d7e1 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -203,9 +203,9 @@ module u1e_core // ///////////////////////////////////////////////////////////////////////////////////// // Slave 2, SPI - spi_top shared_spi - (.wb_clk_i(wb_clk),.wb_rst_i(wb_rst),.wb_adr_i(s2_adr[4:0]),.wb_dat_i(s2_dat_o), - .wb_dat_o(s2_dat_i),.wb_sel_i(s2_sel),.wb_we_i(s2_we),.wb_stb_i(s2_stb), + spi_top16 shared_spi + (.wb_clk_i(wb_clk),.wb_rst_i(wb_rst),.wb_adr_i(s2_adr[4:0]),.wb_dat_i(s2_dat_mosi), + .wb_dat_o(s2_dat_miso),.wb_sel_i(s2_sel),.wb_we_i(s2_we),.wb_stb_i(s2_stb), .wb_cyc_i(s2_cyc),.wb_ack_o(s2_ack),.wb_err_o(),.wb_int_o(spi_int), .ss_pad_o(sen), .sclk_pad_o(sclk), .mosi_pad_o(mosi), .miso_pad_i(miso) ); -- cgit v1.2.3 From cce4104964c1e1930f85dbb0bb8b8f33086bd75e Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Sat, 27 Mar 2010 09:20:50 -0700 Subject: 16 bit wide spi core --- usrp2/opencores/spi/rtl/verilog/spi_top16.v | 182 ++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 usrp2/opencores/spi/rtl/verilog/spi_top16.v diff --git a/usrp2/opencores/spi/rtl/verilog/spi_top16.v b/usrp2/opencores/spi/rtl/verilog/spi_top16.v new file mode 100644 index 000000000..ee808a8ab --- /dev/null +++ b/usrp2/opencores/spi/rtl/verilog/spi_top16.v @@ -0,0 +1,182 @@ + +// Modified 2010 by Matt Ettus to remove old verilog style and +// allow 16-bit operation + +////////////////////////////////////////////////////////////////////// +//// //// +//// spi_top.v //// +//// //// +//// This file is part of the SPI IP core project //// +//// http://www.opencores.org/projects/spi/ //// +//// //// +//// Author(s): //// +//// - Simon Srot (simons@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + + +`include "spi_defines.v" + +module spi_top16 + (input wb_clk_i, input wb_rst_i, + input [4:0] wb_adr_i, + input [15:0] wb_dat_i, + output reg [15:0] wb_dat_o, + input [1:0] wb_sel_i, + input wb_we_i, input wb_stb_i, input wb_cyc_i, + output reg wb_ack_o, output wb_err_o, output reg wb_int_o, + + // SPI signals + output [15:0] ss_pad_o, output sclk_pad_o, output mosi_pad_o, input miso_pad_i); + + // Internal signals + reg [15:0] divider; // Divider register + reg [`SPI_CTRL_BIT_NB-1:0] ctrl; // Control and status register + reg [15:0] ss; // Slave select register + reg [31:0] wb_dat; // wb data out + wire [31:0] rx; // Rx register + wire rx_negedge; // miso is sampled on negative edge + wire tx_negedge; // mosi is driven on negative edge + wire [`SPI_CHAR_LEN_BITS-1:0] char_len; // char len + wire go; // go + wire lsb; // lsb first on line + wire ie; // interrupt enable + wire ass; // automatic slave select + wire spi_divider_sel; // divider register select + wire spi_ctrl_sel; // ctrl register select + wire [3:0] spi_tx_sel; // tx_l register select + wire spi_ss_sel; // ss register select + wire tip; // transfer in progress + wire pos_edge; // recognize posedge of sclk + wire neg_edge; // recognize negedge of sclk + wire last_bit; // marks last character bit + + // Address decoder + assign spi_divider_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[4:2] == `SPI_DIVIDE); + assign spi_ctrl_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[4:2] == `SPI_CTRL); + assign spi_tx_sel[0] = wb_cyc_i & wb_stb_i & (wb_adr_i[4:2] == `SPI_TX_0); + assign spi_tx_sel[1] = wb_cyc_i & wb_stb_i & (wb_adr_i[4:2] == `SPI_TX_1); + assign spi_tx_sel[2] = wb_cyc_i & wb_stb_i & (wb_adr_i[4:2] == `SPI_TX_2); + assign spi_tx_sel[3] = wb_cyc_i & wb_stb_i & (wb_adr_i[4:2] == `SPI_TX_3); + assign spi_ss_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[4:2] == `SPI_SS); + + always @(wb_adr_i or rx or ctrl or divider or ss) + case (wb_adr_i[4:2]) + `SPI_RX_0: wb_dat = rx[31:0]; + `SPI_CTRL: wb_dat = {{32-`SPI_CTRL_BIT_NB{1'b0}}, ctrl}; + `SPI_DIVIDE: wb_dat = {16'b0, divider}; + `SPI_SS: wb_dat = {16'b0, ss}; + default : wb_dat = 32'd0; + endcase // case (wb_adr_i[4:2]) + + always @(posedge wb_clk_i) + if (wb_rst_i) + wb_dat_o <= 32'b0; + else + wb_dat_o <= wb_adr_i[1] ? wb_dat[31:16] : wb_dat[15:0]; + + always @(posedge wb_clk_i) + if (wb_rst_i) + wb_ack_o <= 1'b0; + else + wb_ack_o <= wb_cyc_i & wb_stb_i & ~wb_ack_o; + + assign wb_err_o = 1'b0; + + // Interrupt + always @(posedge wb_clk_i) + if (wb_rst_i) + wb_int_o <= 1'b0; + else if (ie && tip && last_bit && pos_edge) + wb_int_o <= 1'b1; + else if (wb_ack_o) + wb_int_o <= 1'b0; + + // Divider register + always @(posedge wb_clk_i) + if (wb_rst_i) + divider <= 16'b0; + else if (spi_divider_sel && wb_we_i && !tip && ~wb_adr_i[1]) + divider <= wb_dat_i; + + // Ctrl register + always @(posedge wb_clk_i) + if (wb_rst_i) + ctrl <= {`SPI_CTRL_BIT_NB{1'b0}}; + else if(spi_ctrl_sel && wb_we_i && !tip && ~wb_adr_i[1]) + begin + if (wb_sel_i[0]) + ctrl[7:0] <= wb_dat_i[7:0] | {7'b0, ctrl[0]}; + if (wb_sel_i[1]) + ctrl[`SPI_CTRL_BIT_NB-1:8] <= wb_dat_i[`SPI_CTRL_BIT_NB-1:8]; + end + else if(tip && last_bit && pos_edge) + ctrl[`SPI_CTRL_GO] <= 1'b0; + + assign rx_negedge = ctrl[`SPI_CTRL_RX_NEGEDGE]; + assign tx_negedge = ctrl[`SPI_CTRL_TX_NEGEDGE]; + assign go = ctrl[`SPI_CTRL_GO]; + assign char_len = ctrl[`SPI_CTRL_CHAR_LEN]; + assign lsb = ctrl[`SPI_CTRL_LSB]; + assign ie = ctrl[`SPI_CTRL_IE]; + assign ass = ctrl[`SPI_CTRL_ASS]; + + // Slave select register + always @(posedge wb_clk_i) + if (wb_rst_i) + ss <= 16'b0; + else if(spi_ss_sel && wb_we_i && !tip & ~wb_adr_i[1]) + begin + if (wb_sel_i[0]) + ss[7:0] <= wb_dat_i[7:0]; + if (wb_sel_i[1]) + ss[15:8] <= wb_dat_i[15:8]; + end + + assign ss_pad_o = ~((ss & {16{tip & ass}}) | (ss & {16{!ass}})); + + spi_clgen clgen (.clk_in(wb_clk_i), .rst(wb_rst_i), .go(go), .enable(tip), .last_clk(last_bit), + .divider(divider[`SPI_DIVIDER_LEN-1:0]), .clk_out(sclk_pad_o), .pos_edge(pos_edge), + .neg_edge(neg_edge)); + + wire [3:0] new_sels = { (wb_adr_i[1] & wb_sel_i[1]), (wb_adr_i[1] & wb_sel_i[0]), + (~wb_adr_i[1] & wb_sel_i[1]), (~wb_adr_i[1] & wb_sel_i[0]) }; + + + spi_shift shift (.clk(wb_clk_i), .rst(wb_rst_i), .len(char_len[`SPI_CHAR_LEN_BITS-1:0]), + .latch(spi_tx_sel[3:0] & {4{wb_we_i}}), .byte_sel(new_sels), .lsb(lsb), + .go(go), .pos_edge(pos_edge), .neg_edge(neg_edge), + .rx_negedge(rx_negedge), .tx_negedge(tx_negedge), + .tip(tip), .last(last_bit), + .p_in({wb_dat_i,wb_dat_i}), .p_out(rx), + .s_clk(sclk_pad_o), .s_in(miso_pad_i), .s_out(mosi_pad_o)); + +endmodule // spi_top16 -- cgit v1.2.3 From 52c8d239ac4b2c448a15b7cc2e2cadf6f296c3e0 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 1 Apr 2010 17:05:50 -0700 Subject: added 16-bit wide atr controller settings_bus_16 now handles variable address window sizes split ctrl of nsgpio into ctrl (selector) and debug bits --- usrp2/control_lib/atr_controller16.v | 60 ++++++++++++++++++++++++++++ usrp2/control_lib/nsgpio16LE.v | 23 +++++------ usrp2/control_lib/settings_bus_16LE.v | 4 +- usrp2/top/u1e/Makefile | 2 +- usrp2/top/u1e/u1e_core.v | 75 ++++++++++++++++++++--------------- 5 files changed, 117 insertions(+), 47 deletions(-) create mode 100644 usrp2/control_lib/atr_controller16.v diff --git a/usrp2/control_lib/atr_controller16.v b/usrp2/control_lib/atr_controller16.v new file mode 100644 index 000000000..3d8b5b1e9 --- /dev/null +++ b/usrp2/control_lib/atr_controller16.v @@ -0,0 +1,60 @@ + +// Automatic transmit/receive switching of control pins to daughterboards +// Store everything in registers for now, but could use a RAM for more +// complex state machines in the future + +module atr_controller16 + (input clk_i, input rst_i, + input [5:0] adr_i, input [1:0] sel_i, input [15:0] dat_i, output reg [15:0] dat_o, + input we_i, input stb_i, input cyc_i, output reg ack_o, + input run_rx, input run_tx, input [31:0] master_time, + output [31:0] ctrl_lines); + + reg [3:0] state; + reg [31:0] atr_ram [0:15]; // DP distributed RAM + + wire [3:0] sel_int = { (sel_i[1] & adr_i[1]), (sel_i[0] & adr_i[1]), + (sel_i[1] & ~adr_i[1]), (sel_i[0] & ~adr_i[1]) }; + + // WB Interface + always @(posedge clk_i) + if(we_i & stb_i & cyc_i) + begin + if(sel_int[3]) + atr_ram[adr_i[5:2]][31:24] <= dat_i[15:8]; + if(sel_int[2]) + atr_ram[adr_i[5:2]][23:16] <= dat_i[7:0]; + if(sel_int[1]) + atr_ram[adr_i[5:2]][15:8] <= dat_i[15:8]; + if(sel_int[0]) + atr_ram[adr_i[5:2]][7:0] <= dat_i[7:0]; + end // if (we_i & stb_i & cyc_i) + + always @(posedge clk_i) + dat_o <= adr_i[1] ? atr_ram[adr_i[5:2]][31:16] : atr_ram[adr_i[5:2]][15:0]; + + always @(posedge clk_i) + ack_o <= stb_i & cyc_i & ~ack_o; + + // Control side of DP RAM + assign ctrl_lines = atr_ram[state]; + + // Put a more complex state machine with time delays and multiple states here + // if daughterboard requires more complex sequencing + localparam ATR_IDLE = 4'd0; + localparam ATR_TX = 4'd1; + localparam ATR_RX = 4'd2; + localparam ATR_FULL_DUPLEX = 4'd3; + + always @(posedge clk_i) + if(rst_i) + state <= ATR_IDLE; + else + case ({run_rx,run_tx}) + 2'b00 : state <= ATR_IDLE; + 2'b01 : state <= ATR_TX; + 2'b10 : state <= ATR_RX; + 2'b11 : state <= ATR_FULL_DUPLEX; + endcase // case({run_rx,run_tx}) + +endmodule // atr_controller16 diff --git a/usrp2/control_lib/nsgpio16LE.v b/usrp2/control_lib/nsgpio16LE.v index 6847bb4a9..d6d7dcf56 100644 --- a/usrp2/control_lib/nsgpio16LE.v +++ b/usrp2/control_lib/nsgpio16LE.v @@ -43,10 +43,7 @@ module nsgpio16LE inout [31:0] gpio ); - reg [63:0] ctrl; - reg [31:0] line; - reg [31:0] lgpio; // LatchedGPIO pins - reg [31:0] ddr; + reg [31:0] ctrl, line, ddr, dbg, lgpio; wire wb_acc = cyc_i & stb_i; // WISHBONE access wire wb_wr = wb_acc & we_i; // WISHBONE write access @@ -54,8 +51,10 @@ module nsgpio16LE always @(posedge clk_i or posedge rst_i) if (rst_i) begin - ctrl <= 64'h0; - line <= 0; + ctrl <= 32'h0; + line <= 32'h0; + ddr <= 32'h0; + dbg <= 32'h0; end else if (wb_wr) case( adr_i[3:1] ) @@ -72,9 +71,9 @@ module nsgpio16LE 3'b101 : ctrl[31:16] <= dat_i; 3'b110 : - ctrl[47:32] <= dat_i; + dbg[15:0] <= dat_i; 3'b111 : - ctrl[63:48] <= dat_i; + dbg[31:16] <= dat_i; endcase // case ( adr_i[3:1] ) always @(posedge clk_i) @@ -92,9 +91,9 @@ module nsgpio16LE 3'b101 : dat_o <= ctrl[31:16]; 3'b110 : - dat_o <= ctrl[47:32]; + dat_o <= dbg[15:0]; 3'b111 : - dat_o <= ctrl[63:48]; + dat_o <= dbg[31:16]; endcase // case (adr_i[3:1]) @@ -114,8 +113,8 @@ module nsgpio16LE always @(ctrl or line or debug_1 or debug_0 or atr) 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]) ) + igpio[n] <= ddr[n] ? (dbg[n] ? (ctrl[n] ? debug_1[n] : debug_0[n]) : + (ctrl[n] ? atr[n] : line[n]) ) : 1'bz; assign gpio = igpio; diff --git a/usrp2/control_lib/settings_bus_16LE.v b/usrp2/control_lib/settings_bus_16LE.v index fbef9b1c9..76061e9e0 100644 --- a/usrp2/control_lib/settings_bus_16LE.v +++ b/usrp2/control_lib/settings_bus_16LE.v @@ -5,7 +5,7 @@ // The setting regs are strobed when the high 16 bits are written module settings_bus_16LE - #(parameter AWIDTH=16) + #(parameter AWIDTH=16, RWIDTH=8) (input wb_clk, input wb_rst, input [AWIDTH-1:0] wb_adr_i, @@ -28,7 +28,7 @@ module settings_bus_16LE end else if(wb_we_i & wb_stb_i) begin - addr <= wb_adr_i[9:2]; + addr <= wb_adr_i[RWIDTH+1:2]; // Zero pad high bits if(wb_adr_i[1]) begin stb_int <= 1'b1; // We now have both halves diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index 2b78b21bd..a0f921485 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -54,7 +54,7 @@ simulator "ISE Simulator (VHDL/Verilog)" \ export SOURCE_ROOT := ../../../ export SOURCES := \ control_lib/CRC16_D16.v \ -control_lib/atr_controller.v \ +control_lib/atr_controller16.v \ control_lib/bin2gray.v \ control_lib/dcache.v \ control_lib/decoder_3_8.v \ diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index f2415d7e1..e692cbc3d 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -147,48 +147,52 @@ module u1e_core .sf_dat_o(sf_dat_mosi),.sf_adr_o(sf_adr),.sf_sel_o(sf_sel),.sf_we_o(sf_we),.sf_cyc_o(sf_cyc),.sf_stb_o(sf_stb), .sf_dat_i(sf_dat_miso),.sf_ack_i(sf_ack),.sf_err_i(0),.sf_rty_i(0) ); - assign s6_ack = 0; assign s7_ack = 0; + assign s7_ack = 0; assign s8_ack = 0; assign s9_ack = 0; assign sa_ack = 0; assign sb_ack = 0; assign sc_ack = 0; assign sd_ack = 0; assign se_ack = 0; assign sf_ack = 0; // ///////////////////////////////////////////////////////////////////////////////////// // Slave 0, Misc LEDs, Switches, controls - reg [15:0] reg_fast, reg_slow; - localparam REG_FAST = 7'd4; - localparam REG_SWITCHES = 7'd6; - localparam REG_GPIOS = 7'd8; - localparam REG_CGEN_ST = 7'd9; - localparam REG_CGEN_CTRL = 7'd10; + reg [15:0] reg_leds, reg_cgen_ctrl, reg_test; - reg [3:0] reg_gpios; - - always @(posedge wb_clk) - if(s0_cyc & s0_stb & s0_we & (s0_adr[6:0] == REG_FAST)) - reg_fast <= s0_dat_mosi; - - always @(posedge wb_clk) - if(s0_cyc & s0_stb & s0_we & (s0_adr[6:0] == REG_GPIOS)) - reg_gpios <= s0_dat_mosi; - - reg [1:0] reg_cgen_ctrls; + localparam REG_LEDS = 7'd0; // out + localparam REG_SWITCHES = 7'd2; // in + localparam REG_CGEN_CTRL = 7'd4; // out + localparam REG_CGEN_ST = 7'd6; // in + localparam REG_TEST = 7'd8; // out always @(posedge wb_clk) if(wb_rst) - reg_cgen_ctrls <= 2'b11; - else if(s0_cyc & s0_stb & s0_we & (s0_adr[6:0] == REG_CGEN_CTRL)) - reg_cgen_ctrls <= s0_dat_mosi; + begin + reg_leds <= 0; + reg_cgen_ctrl <= 2'b11; + reg_test <= 0; + end + else + if(s0_cyc & s0_stb & s0_we) + case(s0_adr[6:0]) + REG_LEDS : + reg_leds <= s0_dat_mosi; + REG_CGEN_CTRL : + reg_cgen_ctrl <= s0_dat_mosi; + REG_TEST : + reg_test <= s0_dat_mosi; + endcase // case (s0_adr[6:0]) - assign {cgen_sync_b, cgen_ref_sel} = reg_cgen_ctrls; + assign { debug_led[2],debug_led[0],debug_led[1] } = reg_leds; // LEDs are arranged funny on board + assign { cgen_sync_b, cgen_ref_sel } = reg_cgen_ctrl; + assign { rx_overrun, tx_undderun } = reg_test; - assign s0_dat_miso = (s0_adr[6:0] == REG_FAST) ? reg_fast : + assign s0_dat_miso = (s0_adr[6:0] == REG_LEDS) ? reg_leds : (s0_adr[6:0] == REG_SWITCHES) ? {5'b0,debug_pb[2:0],dip_sw[7:0]} : + (s0_adr[6:0] == REG_CGEN_CTRL) ? reg_cgen_ctrl : (s0_adr[6:0] == REG_CGEN_ST) ? {13'b0,cgen_st_status,cgen_st_ld,cgen_st_refmon} : + (s0_adr[6:0] == REG_TEST) ? reg_test : 16'hBEEF; + assign s0_ack = s0_stb & s0_cyc; - assign { rx_overrun, tx_underrun } = reg_gpios; - // ///////////////////////////////////////////////////////////////////////////////////// // Slave 1, UART // depth of 3 is 128 entries, clkdiv of 278 gives 230.4k with a 64 MHz system clock @@ -196,7 +200,7 @@ module u1e_core simple_uart #(.TXDEPTH(3),.RXDEPTH(3), .CLKDIV_DEFAULT(278)) uart (.clk_i(wb_clk),.rst_i(wb_rst), .we_i(s1_we),.stb_i(s1_stb),.cyc_i(s1_cyc),.ack_o(s1_ack), - .adr_i(s1_adr[4:2]),.dat_i({16'd0,s1_dat_mosi}),.dat_o(s1_dat_miso), + .adr_i(s1_adr[3:1]),.dat_i({16'd0,s1_dat_mosi}),.dat_o(s1_dat_miso), .rx_int_o(),.tx_int_o(), .tx_o(debug_txd),.rx_i(debug_rxd),.baud_o()); @@ -246,16 +250,25 @@ module u1e_core wire [7:0] set_addr; wire [31:0] set_data; wire set_stb; - - settings_bus_16LE settings_bus_16LE + + // only have 32 regs, 32 bits each with current setup... + settings_bus_16LE #(.AWIDTH(11),.RWIDTH(11-4-2)) settings_bus_16LE (.wb_clk(wb_clk),.wb_rst(wb_rst),.wb_adr_i(s5_adr),.wb_dat_i(s5_dat_mosi), .wb_stb_i(s5_stb),.wb_we_i(s5_we),.wb_ack_o(s5_ack), .strobe(set_stb),.addr(set_addr),.data(set_data) ); - // ///////////////////////////////////////////////////////////////////////////////////// - // Debug Pins + // ///////////////////////////////////////////////////////////////////////// + // ATR Controller -- Slave #6 + + atr_controller16 atr_controller16 + (.clk_i(wb_clk), .rst_i(wb_rst), + .adr_i(s6_adr), .sel_i(s6_sel), .dat_i(s6_dat_mosi), .dat_o(s6_dat_miso), + .we_i(s6_we), .stb_i(s6_stb), .cyc_i(s6_cyc), .ack_o(s6_ack), + .run_rx(), .run_tx(), .master_time(0), .ctrl_lines(atr_lines)); + // ///////////////////////////////////////////////////////////////////////////////////// // Debug circuitry + assign debug_clk = { EM_CLK, clk_fpga }; assign debug = { { rx_have_data, tx_have_space, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, { EM_D } }; @@ -263,6 +276,4 @@ module u1e_core assign debug_gpio_0 = { debug_gpmc }; assign debug_gpio_1 = { debug_txd, debug_rxd }; - assign { debug_led[2],debug_led[0],debug_led[1] } = reg_fast; // LEDs are arranged funny on board - endmodule // u1e_core -- cgit v1.2.3 From 4aca5e04d026977272e35db4e0c1ccaac5da555f Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 12 Apr 2010 19:06:04 -0700 Subject: split out gpmc to wishbone interface to make gpmc top level cleaner --- usrp2/gpmc/gpmc_wb.v | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 usrp2/gpmc/gpmc_wb.v diff --git a/usrp2/gpmc/gpmc_wb.v b/usrp2/gpmc/gpmc_wb.v new file mode 100644 index 000000000..64f6a1c00 --- /dev/null +++ b/usrp2/gpmc/gpmc_wb.v @@ -0,0 +1,57 @@ + + +module gpmc_wb + (input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, + input EM_NCS, input EM_NWE, input EM_NOE, + + input wb_clk, input wb_rst, + output reg [10:0] wb_adr_o, output reg [15:0] wb_dat_mosi, input [15:0] wb_dat_miso, + output reg [1:0] wb_sel_o, output wb_cyc_o, output reg wb_stb_o, output reg wb_we_o, input wb_ack_i); + + // //////////////////////////////////////////// + // Control Path, Wishbone bus bridge (wb master) + reg [1:0] cs_del, we_del, oe_del; + + // Synchronize the async control signals + always @(posedge wb_clk) + begin + cs_del <= { cs_del[0], EM_NCS }; + we_del <= { we_del[0], EM_NWE }; + oe_del <= { oe_del[0], EM_NOE }; + end + + always @(posedge wb_clk) + if(cs_del == 2'b10) // Falling Edge + wb_adr_o <= { EM_A, 1'b0 }; + + always @(posedge wb_clk) + if(we_del == 2'b10) // Falling Edge + begin + wb_dat_mosi <= EM_D; + wb_sel_o <= ~EM_NBE; + end + + reg [15:0] EM_D_hold; + + always @(posedge wb_clk) + if(wb_ack_i) + EM_D_hold <= wb_dat_miso; + + assign EM_D = wb_ack_i ? wb_dat_miso : EM_D_hold; + + assign wb_cyc_o = wb_stb_o; + + always @(posedge wb_clk) + if(~cs_del[0] & (we_del == 2'b10) ) + wb_we_o <= 1; + else if(wb_ack_i) // Turn off we when done. Could also use we_del[0], others... + wb_we_o <= 0; + + // FIXME should this look at cs_del[1]? + always @(posedge wb_clk) + if(~cs_del[0] & ((we_del == 2'b10) | (oe_del == 2'b10))) + wb_stb_o <= 1; + else if(wb_ack_i) + wb_stb_o <= 0; + +endmodule // gpmc_wb -- cgit v1.2.3 From 45b9ec4c39a2f4a3087b2f637f70818fd0efb94e Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 12 Apr 2010 19:06:49 -0700 Subject: replaced ram interface with a fifo interface. still need to do rx side --- usrp2/gpmc/gpmc.v | 133 ++++++++++++++++++---------------------------- usrp2/gpmc/gpmc_to_fifo.v | 58 ++++++++++++++++++++ usrp2/top/u1e/u1e_core.v | 46 +++------------- 3 files changed, 117 insertions(+), 120 deletions(-) create mode 100644 usrp2/gpmc/gpmc_to_fifo.v diff --git a/usrp2/gpmc/gpmc.v b/usrp2/gpmc/gpmc.v index cf1357232..2715414b3 100644 --- a/usrp2/gpmc/gpmc.v +++ b/usrp2/gpmc/gpmc.v @@ -10,13 +10,14 @@ module gpmc // Wishbone signals input wb_clk, input wb_rst, - output reg [10:0] wb_adr_o, output reg [15:0] wb_dat_mosi, input [15:0] wb_dat_miso, - output reg [1:0] wb_sel_o, output wb_cyc_o, output reg wb_stb_o, output reg wb_we_o, input wb_ack_i, + output [10:0] wb_adr_o, output [15:0] wb_dat_mosi, input [15:0] wb_dat_miso, + output [1:0] wb_sel_o, output wb_cyc_o, output wb_stb_o, output wb_we_o, input wb_ack_i, - // RAM Interface signals - input ram_clk, - input read_en, input [8:0] read_addr, output [31:0] read_data, output read_ready, input read_done, - input write_en, input [8:0] write_addr, input [31:0] write_data, output write_ready, input write_done, + // FIFO interface + input fifo_clk, input fifo_rst, + output [35:0] tx_data_o, output tx_src_rdy_o, input tx_dst_rdy_i, + input [35:0] rx_data_i, input rx_src_rdy_i, output rx_dst_rdy_o, + output [31:0] debug ); @@ -26,94 +27,64 @@ module gpmc assign EM_D = ~EM_output_enable ? 16'bz : ~EM_NCS4 ? EM_D_ram : EM_D_wb; - // CS4 is RAM_2PORT for high-speed data - // Writes go into one RAM, reads come from the other - + // CS4 is RAM_2PORT for DATA PATH (high-speed data) + // Writes go into one RAM, reads come from the other + // CS6 is for CONTROL PATH (wishbone) // //////////////////////////////////////////// - // Write path - wire read_sel_in, write_sel_in, clear_in; - wire write_done_in; - - edge_sync #(.POSEDGE(0)) - edge_sync_wdi(.clk(wb_clk), .rst(wb_rst), - .sig(~EM_NCS4 & ~EM_NWE & (EM_A == 10'h3FF)), .trig(write_done_in)); - - ram_2port_mixed_width buffer_in - (.clk16(wb_clk), .en16(~EM_NCS4), .we16(~EM_NWE), .addr16({write_sel_in,EM_A}), .di16(EM_D), .do16(), - .clk32(ram_clk), .en32(read_en), .we32(0), .addr32({read_sel_in,read_addr}), .di32(0), .do32(read_data)); + // TX Data Path - dbsm dbsm_in(.clk(wb_clk), .reset(wb_rst), .clear(clear_in), - .read_sel(read_sel_in), .read_ready(read_ready), .read_done(read_done), - .write_sel(write_sel_in), .write_ready(tx_have_space), .write_done(write_done_in)); + wire [17:0] tx18_data, tx18b_data; + wire tx18_src_rdy, tx18_dst_rdy, tx18b_src_rdy, tx18b_dst_rdy; + wire [15:0] tx_fifo_space, tx_frame_len; + assign tx_frame_len = 10; + + gpmc_to_fifo gpmc_to_fifo + (.EM_CLK(EM_CLK), .EM_D(EM_D), .EM_NBE(EM_NBE), .EM_NCS(EM_NCS4), .EM_NWE(EM_NWE), + .fifo_clk(fifo_clk), .fifo_rst(fifo_rst), + .data_o(tx18_data), .src_rdy_o(tx18_src_rdy), .dst_rdy_i(tx18_dst_rdy), + .frame_len(tx_frame_len), .fifo_space(tx_fifo_space), .fifo_ready(tx_have_space)); + fifo_cascade #(.WIDTH(18), .SIZE(10)) tx_fifo + (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + .datain(tx18_data), .src_rdy_i(tx18_src_rdy), .dst_rdy_o(tx18_dst_rdy), .space(tx_fifo_space), + .dataout(tx18b_data), .src_rdy_o(tx18b_src_rdy), .dst_rdy_i(tx18b_dst_rdy)); + + fifo19_to_fifo36 f19_to_f36 + (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + .f19_datain({1'b0,tx18b_data}), .f19_src_rdy_i(tx18b_src_rdy), .f19_dst_rdy_o(tx18b_dst_rdy), + .f36_dataout(tx_data_o), .f36_src_rdy_o(tx_src_rdy_o), .f36_dst_rdy_i(tx_dst_rdy_i)); + // //////////////////////////////////////////// - // Read path - wire read_sel_out, write_sel_out, clear_out; - wire read_done_out; + // RX Data Path + wire read_sel_rx, write_sel_rx, clear_rx; + wire read_done_rx; edge_sync #(.POSEDGE(0)) - edge_sync_rdo(.clk(wb_clk), .rst(wb_rst), - .sig(~EM_NCS4 & ~EM_NOE & (EM_A == 10'h3FF)), .trig(read_done_out)); + edge_sync_rx(.clk(wb_clk), .rst(wb_rst), + .sig(~EM_NCS4 & ~EM_NOE & (EM_A == 10'h3FF)), .trig(read_done_rx)); - ram_2port_mixed_width buffer_out - (.clk16(wb_clk), .en16(~EM_NCS4), .we16(0), .addr16({read_sel_out,EM_A}), .di16(0), .do16(EM_D_ram), - .clk32(ram_clk), .en32(write_en), .we32(write_en), .addr32({write_sel_out,write_addr}), .di32(write_data), .do32()); - - dbsm dbsm_out(.clk(wb_clk), .reset(wb_rst), .clear(clear_out), - .read_sel(read_sel_out), .read_ready(rx_have_data), .read_done(read_done_out), - .write_sel(write_sel_out), .write_ready(write_ready), .write_done(write_done)); + ram_2port_mixed_width buffer_rx + (.clk16(wb_clk), .en16(~EM_NCS4), .we16(0), .addr16({read_sel_rx,EM_A}), .di16(0), .do16(EM_D_ram), + .clk32(ram_clk), .en32(write_en), .we32(write_en), .addr32({write_sel_rx,write_addr}), .di32(write_data), .do32()); + dbsm dbsm_rx(.clk(wb_clk), .reset(wb_rst), .clear(clear_rx), + .read_sel(read_sel_rx), .read_ready(rx_have_data), .read_done(read_done_rx), + .write_sel(write_sel_rx), .write_ready(write_ready), .write_done(write_done)); - assign debug = { { 2'b00, write_done_in, write_sel_in, read_en, read_sel_in, read_ready, read_done}, - { 2'b00, read_sel_out, write_en, write_sel_out, read_done_out, write_ready, write_done }, - { 8'd0 }, - { 8'd0 } }; + // //////////////////////////////////////////// + // Control path on CS6 - // CS6 is Control, Wishbone bus bridge (wb master) - // Sync version - reg [1:0] cs_del, we_del, oe_del; - - // Synchronize the async control signals - always @(posedge wb_clk) - begin - cs_del <= { cs_del[0], EM_NCS6 }; - we_del <= { we_del[0], EM_NWE }; - oe_del <= { oe_del[0], EM_NOE }; - end - - always @(posedge wb_clk) - if(cs_del == 2'b10) // Falling Edge - wb_adr_o <= { EM_A, 1'b0 }; - - always @(posedge wb_clk) - if(we_del == 2'b10) // Falling Edge - begin - wb_dat_mosi <= EM_D; - wb_sel_o <= ~EM_NBE; - end - - reg [15:0] EM_D_wb_reg; - always @(posedge wb_clk) - if(wb_ack_i) - EM_D_wb_reg <= wb_dat_miso; - - assign EM_D_wb = wb_ack_i ? wb_dat_miso : EM_D_wb_reg; + gpmc_wb gpmc_wb + (.EM_CLK(EM_CLK), .EM_D(EM_D_wb), .EM_A(EM_A), .EM_NBE(EM_NBE), + .EM_NCS(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), + .wb_clk(wb_clk), .wb_rst(wb_rst), + .wb_adr_o(wb_adr_o), .wb_dat_mosi(wb_dat_mosi), .wb_dat_miso(wb_dat_miso), + .wb_sel_o(wb_sel_o), .wb_cyc_o(wb_cyc_o), .wb_stb_o(wb_stb_o), .wb_we_o(wb_we_o), + .wb_ack_i(wb_ack_i) ); - assign wb_cyc_o = wb_stb_o; - - always @(posedge wb_clk) - if(~cs_del[0] & (we_del == 2'b10) ) - wb_we_o <= 1; - else if(wb_ack_i) // Turn off we when done. Could also use we_del[0], others... - wb_we_o <= 0; - - always @(posedge wb_clk) - if(~cs_del[0] & ((we_del == 2'b10) | (oe_del == 2'b10))) - wb_stb_o <= 1; - else if(wb_ack_i) - wb_stb_o <= 0; + assign debug = 0; endmodule // gpmc diff --git a/usrp2/gpmc/gpmc_to_fifo.v b/usrp2/gpmc/gpmc_to_fifo.v new file mode 100644 index 000000000..5d499494f --- /dev/null +++ b/usrp2/gpmc/gpmc_to_fifo.v @@ -0,0 +1,58 @@ + +module gpmc_to_fifo + (input EM_CLK, input [15:0] EM_D, input [1:0] EM_NBE, + input EM_NCS, input EM_NWE, + + input fifo_clk, input fifo_rst, + output reg [17:0] data_o, output reg src_rdy_o, input dst_rdy_i, + + input [15:0] frame_len, input [15:0] fifo_space, output fifo_ready); + + // Synchronize the async control signals + reg [1:0] cs_del, we_del; + always @(posedge fifo_clk) + if(fifo_rst) + begin + cs_del <= 2'b11; + we_del <= 2'b11; + end + else + begin + cs_del <= { cs_del[0], EM_NCS }; + we_del <= { we_del[0], EM_NWE }; + end + + wire do_write = (~cs_del[0] & (we_del == 2'b10)); + wire first_write = (counter == 0); + wire last_write = ((counter+1) == frame_len); + + always @(posedge fifo_clk) + if(do_write) + begin + data_o[15:0] <= EM_D; + data_o[16] <= first_write; + data_o[17] <= last_write; + // no byte writes data_o[18] <= |EM_NBE; // mark half full if either is not enabled FIXME + end + + always @(posedge fifo_clk) + if(fifo_rst) + src_rdy_o <= 0; + else if(do_write) + src_rdy_o <= 1; + else + src_rdy_o <= 0; // Assume it was taken + + reg [10:0] counter; + always @(posedge fifo_clk) + if(fifo_rst) + counter <= 0; + else if(do_write) + if(last_write) + counter <= 0; + else + counter <= counter + 1; + + assign fifo_ready = first_write & (fifo_space > frame_len); + +endmodule // gpmc_to_fifo diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index e692cbc3d..e5e5285bd 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -30,15 +30,8 @@ module u1e_core wire [sw-1:0] m0_sel; wire m0_cyc, m0_stb, m0_we, m0_ack, m0_err, m0_rty; - // FIFO buffers - wire [31:0] read_data, write_data; - wire [8:0] read_addr, write_addr; - reg [8:0] addr; - - wire read_done, write_done, read_en, write_en, read_ready, write_ready; - wire [31:0] debug_gpmc; - + gpmc gpmc (.EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), @@ -50,37 +43,12 @@ module u1e_core .wb_sel_o(m0_sel), .wb_cyc_o(m0_cyc), .wb_stb_o(m0_stb), .wb_we_o(m0_we), .wb_ack_i(m0_ack), - .ram_clk(wb_clk), - .read_en(read_en), .read_addr(read_addr), .read_data(read_data), - .read_ready(read_ready), .read_done(read_done), - .write_en(write_en), .write_addr(write_addr), .write_data(write_data), - .write_ready(write_ready), .write_done(write_done), + .fifo_clk(wb_clk), .fifo_rst(wb_rst), + .tx_data_o(), .tx_src_rdy_o(), .tx_dst_rdy_i(0), + .rx_data_i(0), .rx_src_rdy_i(0), .rx_dst_rdy_o(), + .debug(debug_gpmc)); - // Loopback - assign write_data = read_data; - - reg [10:0] counter; - assign write_addr = counter[10:2]; - assign read_addr = counter[10:2]; - - assign read_done = (counter == 11'h7FF); - assign write_done = (counter == 11'h7FF); - - always @(posedge wb_clk) - if(wb_rst) - counter <= 0; - else - if(counter == 0) - counter <= write_ready & read_ready; - else if(counter == 11'h7FF) - counter <= 0; - else - counter <= counter + 1; - - assign read_en = (counter[1:0] == 1); - assign write_en = (counter[1:0] == 2); - // ///////////////////////////////////////////////////////////////////////////////////// // Wishbone Intercon, single master @@ -182,7 +150,7 @@ module u1e_core assign { debug_led[2],debug_led[0],debug_led[1] } = reg_leds; // LEDs are arranged funny on board assign { cgen_sync_b, cgen_ref_sel } = reg_cgen_ctrl; - assign { rx_overrun, tx_undderun } = reg_test; + assign { rx_overrun, tx_underrun } = reg_test; assign s0_dat_miso = (s0_adr[6:0] == REG_LEDS) ? reg_leds : (s0_adr[6:0] == REG_SWITCHES) ? {5'b0,debug_pb[2:0],dip_sw[7:0]} : @@ -210,7 +178,7 @@ module u1e_core spi_top16 shared_spi (.wb_clk_i(wb_clk),.wb_rst_i(wb_rst),.wb_adr_i(s2_adr[4:0]),.wb_dat_i(s2_dat_mosi), .wb_dat_o(s2_dat_miso),.wb_sel_i(s2_sel),.wb_we_i(s2_we),.wb_stb_i(s2_stb), - .wb_cyc_i(s2_cyc),.wb_ack_o(s2_ack),.wb_err_o(),.wb_int_o(spi_int), + .wb_cyc_i(s2_cyc),.wb_ack_o(s2_ack),.wb_err_o(),.wb_int_o(), .ss_pad_o(sen), .sclk_pad_o(sclk), .mosi_pad_o(mosi), .miso_pad_i(miso) ); // ///////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From f95bf4d8d94511d26a5bb1f52823f8ffd5f637fe Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 12 Apr 2010 19:20:22 -0700 Subject: lengthened delay between cycles, added more transactions on the data bus --- usrp2/models/gpmc_model.v | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/usrp2/models/gpmc_model.v b/usrp2/models/gpmc_model.v index 3424671bd..6066ede6e 100644 --- a/usrp2/models/gpmc_model.v +++ b/usrp2/models/gpmc_model.v @@ -41,7 +41,7 @@ module gpmc_model EM_NCS6 <= 1; //#1.5; EM_NWE <= 1; - #6; + #60; EM_A <= 10'bz; EM_D_int <= 16'bz; end @@ -82,7 +82,12 @@ module gpmc_model GPMC_Write(0,38,16'h5678); GPMC_Write(0,40,16'h9abc); GPMC_Write(0,11'h2F4,16'hF00D); - GPMC_Write(0,11'h7FE,16'hF00D); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); #100000; $finish; end -- cgit v1.2.3 From 19d476df81cdf7a51b871154510be8f7c575ffde Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 13 Apr 2010 17:33:16 -0700 Subject: minor changes to get it to synthesize --- usrp2/gpmc/gpmc_to_fifo.v | 2 +- usrp2/top/u1e/Makefile | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/usrp2/gpmc/gpmc_to_fifo.v b/usrp2/gpmc/gpmc_to_fifo.v index 5d499494f..267804469 100644 --- a/usrp2/gpmc/gpmc_to_fifo.v +++ b/usrp2/gpmc/gpmc_to_fifo.v @@ -8,6 +8,7 @@ module gpmc_to_fifo input [15:0] frame_len, input [15:0] fifo_space, output fifo_ready); + reg [10:0] counter; // Synchronize the async control signals reg [1:0] cs_del, we_del; always @(posedge fifo_clk) @@ -43,7 +44,6 @@ module gpmc_to_fifo else src_rdy_o <= 0; // Assume it was taken - reg [10:0] counter; always @(posedge fifo_clk) if(fifo_rst) counter <= 0; diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index a0f921485..1cb56d7a9 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -109,6 +109,7 @@ control_lib/newfifo/fifo_short.v \ control_lib/newfifo/fifo_long.v \ control_lib/newfifo/fifo_cascade.v \ control_lib/newfifo/fifo36_to_ll8.v \ +control_lib/newfifo/fifo19_to_fifo36.v \ control_lib/longfifo.v \ control_lib/shortfifo.v \ control_lib/medfifo.v \ @@ -177,6 +178,8 @@ timing/timer.v \ gpmc/gpmc.v \ gpmc/edge_sync.v \ gpmc/dbsm.v \ +gpmc/gpmc_to_fifo.v \ +gpmc/gpmc_wb.v \ top/u1e/u1e_core.v \ top/u1e/u1e.ucf \ top/u1e/u1e.v -- cgit v1.2.3 From 8cef80c8ebb9b59f1fe65971c9066fd832ab2504 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 14 Apr 2010 18:01:28 -0700 Subject: probably won't be using this, and it hasn't been tested --- usrp2/gpmc/ram_to_fifo.v | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 usrp2/gpmc/ram_to_fifo.v diff --git a/usrp2/gpmc/ram_to_fifo.v b/usrp2/gpmc/ram_to_fifo.v new file mode 100644 index 000000000..8549dcc35 --- /dev/null +++ b/usrp2/gpmc/ram_to_fifo.v @@ -0,0 +1,46 @@ + + +module ram_to_fifo + (input clk, input reset, + input [10:0] read_length, // From the dbsm (?) + output read_en, output reg [8:0] read_addr, input [31:0] read_data, input read_ready, output read_done, + output [35:0] data_o, output src_rdy_o, input dst_rdy_i); + + // read_length/2 = number of 32 bit lines, numbered 0 through read_length/2-1 + wire [8:0] last_line = (read_length[10:1]-1); + + reg read_phase, sop; + + assign read_en = (read_phase == 0) | dst_rdy_i; + assign src_rdy_o = (read_phase == 1); + + always @(posedge clk) + if(reset) + begin + read_addr <= 0; + read_phase <= 0; + sop <= 1; + end + else + if(read_phase == 0) + begin + read_addr <= read_ready; + read_phase <= read_ready; + end + else if(dst_rdy_i) + begin + sop <= 0; + if(read_addr == last_line) + begin + read_addr <= 0; + read_phase <= 0; + end + else + read_addr <= read_addr + 1; + end + + assign read_done = (read_phase == 1) & (read_addr == last_line) & dst_rdy_i; + wire eop = (read_addr == last_line); + assign data_o = { 2'b00, eop, sop, read_data }; + +endmodule // ram_to_fifo -- cgit v1.2.3 From 17fc80cb82309879dd2b1dc03681058dd432327b Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 14 Apr 2010 18:02:29 -0700 Subject: added in a loopback fifo --- usrp2/top/u1e/u1e_core.v | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index e5e5285bd..7df7b0a48 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -32,6 +32,9 @@ module u1e_core wire [31:0] debug_gpmc; + wire [35:0] tx_data, rx_data; + wire tx_src_rdy, tx_dst_rdy, rx_src_rdy, rx_dst_rdy; + gpmc gpmc (.EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), @@ -44,12 +47,16 @@ module u1e_core .wb_ack_i(m0_ack), .fifo_clk(wb_clk), .fifo_rst(wb_rst), - .tx_data_o(), .tx_src_rdy_o(), .tx_dst_rdy_i(0), - .rx_data_i(0), .rx_src_rdy_i(0), .rx_dst_rdy_o(), + .tx_data_o(tx_data), .tx_src_rdy_o(tx_src_rdy), .tx_dst_rdy_i(tx_dst_rdy), + .rx_data_i(rx_data), .rx_src_rdy_i(rx_src_rdy), .rx_dst_rdy_o(rx_dst_rdy), .debug(debug_gpmc)); - - + + fifo_cascade #(.WIDTH(36), .SIZE(9)) loopback_fifo + (.clk(wb_clk), .reset(wb_rst), .clear(0), + .datain(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy), + .dataout(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); + // ///////////////////////////////////////////////////////////////////////////////////// // Wishbone Intercon, single master wire [dw-1:0] s0_dat_mosi, s1_dat_mosi, s0_dat_miso, s1_dat_miso, s2_dat_mosi, s3_dat_mosi, s2_dat_miso, s3_dat_miso, -- cgit v1.2.3 From fc54a55f97171f5714c370d566f31429ce112e89 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 14 Apr 2010 18:07:00 -0700 Subject: make timing diagrams for bus transactions. Still need to do reads --- usrp2/gpmc/.gitignore | 2 ++ usrp2/gpmc/burst_data_write.txt | 16 ++++++++++++++++ usrp2/gpmc/make_timing_diag | 6 ++++++ usrp2/gpmc/single_data_read.txt | 12 ++++++++++++ usrp2/gpmc/single_data_write.txt | 10 ++++++++++ 5 files changed, 46 insertions(+) create mode 100644 usrp2/gpmc/.gitignore create mode 100644 usrp2/gpmc/burst_data_write.txt create mode 100755 usrp2/gpmc/make_timing_diag create mode 100644 usrp2/gpmc/single_data_read.txt create mode 100644 usrp2/gpmc/single_data_write.txt diff --git a/usrp2/gpmc/.gitignore b/usrp2/gpmc/.gitignore new file mode 100644 index 000000000..3e14fa4f7 --- /dev/null +++ b/usrp2/gpmc/.gitignore @@ -0,0 +1,2 @@ +*.gif + diff --git a/usrp2/gpmc/burst_data_write.txt b/usrp2/gpmc/burst_data_write.txt new file mode 100644 index 000000000..3b5dfc785 --- /dev/null +++ b/usrp2/gpmc/burst_data_write.txt @@ -0,0 +1,16 @@ +# OMAP burst writes to FPGA + +CLK=0,nWE=1,nCS=1,nOE=1,DATA=Z. +CLK=1. +CLK=0,nWE=0,nCS=0,DATA=WR_DATA1. +CLK=1. +CLK=0,nWE=0,nCS=0,DATA=WR_DATA2. +CLK=1. +CLK=0,nWE=0,nCS=0,DATA=WR_DATA3. +CLK=1. +CLK=0,nWE=0,nCS=0,DATA=WR_DATA4. +CLK=1. +CLK=0,nWE=1,nCS=1,DATA=Z. +CLK=1. + + diff --git a/usrp2/gpmc/make_timing_diag b/usrp2/gpmc/make_timing_diag new file mode 100755 index 000000000..03166ad35 --- /dev/null +++ b/usrp2/gpmc/make_timing_diag @@ -0,0 +1,6 @@ +#!/bin/sh +drawtiming -o single_data_write.gif single_data_write.txt +drawtiming -o single_data_read.gif single_data_read.txt +drawtiming -o burst_data_write.gif burst_data_write.txt +#drawtiming -o burst_data_read.gif burst_data_read.txt + diff --git a/usrp2/gpmc/single_data_read.txt b/usrp2/gpmc/single_data_read.txt new file mode 100644 index 000000000..1dc0e3a78 --- /dev/null +++ b/usrp2/gpmc/single_data_read.txt @@ -0,0 +1,12 @@ +# OMAP writes to FPGA +# initialize the signals +CLK=0,nWE=1,nCS=1,nOE=1,DATA=Z. +CLK=1. +CLK=0,nOE=0,nCS=0,DATA=RD_DATA. +CLK=1. +CLK=0. +CLK=1. +CLK=0,nOE=1,nCS=1,DATA=Z. +CLK=1. + + diff --git a/usrp2/gpmc/single_data_write.txt b/usrp2/gpmc/single_data_write.txt new file mode 100644 index 000000000..287e3e2c1 --- /dev/null +++ b/usrp2/gpmc/single_data_write.txt @@ -0,0 +1,10 @@ +# OMAP writes to FPGA +# initialize the signals +CLK=0,nWE=1,nCS=1,nOE=1,DATA=Z. +CLK=1. +CLK=0,nWE=0,nCS=0,DATA=WR_DATA. +CLK=1. +CLK=0,nWE=1,nCS=1,DATA=Z. +CLK=1. + + -- cgit v1.2.3 From 204c591cd478958b4e2ddea4c61d3908d9520bbe Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 14 Apr 2010 18:13:49 -0700 Subject: renamed to async. Will be building a sync version for GPMC_CLK --- usrp2/gpmc/gpmc_to_fifo.v | 58 ----------------------------------------- usrp2/gpmc/gpmc_to_fifo_async.v | 58 +++++++++++++++++++++++++++++++++++++++++ usrp2/top/u1e/Makefile | 2 +- 3 files changed, 59 insertions(+), 59 deletions(-) delete mode 100644 usrp2/gpmc/gpmc_to_fifo.v create mode 100644 usrp2/gpmc/gpmc_to_fifo_async.v diff --git a/usrp2/gpmc/gpmc_to_fifo.v b/usrp2/gpmc/gpmc_to_fifo.v deleted file mode 100644 index 267804469..000000000 --- a/usrp2/gpmc/gpmc_to_fifo.v +++ /dev/null @@ -1,58 +0,0 @@ - -module gpmc_to_fifo - (input EM_CLK, input [15:0] EM_D, input [1:0] EM_NBE, - input EM_NCS, input EM_NWE, - - input fifo_clk, input fifo_rst, - output reg [17:0] data_o, output reg src_rdy_o, input dst_rdy_i, - - input [15:0] frame_len, input [15:0] fifo_space, output fifo_ready); - - reg [10:0] counter; - // Synchronize the async control signals - reg [1:0] cs_del, we_del; - always @(posedge fifo_clk) - if(fifo_rst) - begin - cs_del <= 2'b11; - we_del <= 2'b11; - end - else - begin - cs_del <= { cs_del[0], EM_NCS }; - we_del <= { we_del[0], EM_NWE }; - end - - wire do_write = (~cs_del[0] & (we_del == 2'b10)); - wire first_write = (counter == 0); - wire last_write = ((counter+1) == frame_len); - - always @(posedge fifo_clk) - if(do_write) - begin - data_o[15:0] <= EM_D; - data_o[16] <= first_write; - data_o[17] <= last_write; - // no byte writes data_o[18] <= |EM_NBE; // mark half full if either is not enabled FIXME - end - - always @(posedge fifo_clk) - if(fifo_rst) - src_rdy_o <= 0; - else if(do_write) - src_rdy_o <= 1; - else - src_rdy_o <= 0; // Assume it was taken - - always @(posedge fifo_clk) - if(fifo_rst) - counter <= 0; - else if(do_write) - if(last_write) - counter <= 0; - else - counter <= counter + 1; - - assign fifo_ready = first_write & (fifo_space > frame_len); - -endmodule // gpmc_to_fifo diff --git a/usrp2/gpmc/gpmc_to_fifo_async.v b/usrp2/gpmc/gpmc_to_fifo_async.v new file mode 100644 index 000000000..c47d69d7d --- /dev/null +++ b/usrp2/gpmc/gpmc_to_fifo_async.v @@ -0,0 +1,58 @@ + +module gpmc_to_fifo_async + (input EM_CLK, input [15:0] EM_D, input [1:0] EM_NBE, + input EM_NCS, input EM_NWE, + + input fifo_clk, input fifo_rst, + output reg [17:0] data_o, output reg src_rdy_o, input dst_rdy_i, + + input [15:0] frame_len, input [15:0] fifo_space, output fifo_ready); + + reg [10:0] counter; + // Synchronize the async control signals + reg [1:0] cs_del, we_del; + always @(posedge fifo_clk) + if(fifo_rst) + begin + cs_del <= 2'b11; + we_del <= 2'b11; + end + else + begin + cs_del <= { cs_del[0], EM_NCS }; + we_del <= { we_del[0], EM_NWE }; + end + + wire do_write = (~cs_del[0] & (we_del == 2'b10)); + wire first_write = (counter == 0); + wire last_write = ((counter+1) == frame_len); + + always @(posedge fifo_clk) + if(do_write) + begin + data_o[15:0] <= EM_D; + data_o[16] <= first_write; + data_o[17] <= last_write; + // no byte writes data_o[18] <= |EM_NBE; // mark half full if either is not enabled FIXME + end + + always @(posedge fifo_clk) + if(fifo_rst) + src_rdy_o <= 0; + else if(do_write) + src_rdy_o <= 1; + else + src_rdy_o <= 0; // Assume it was taken + + always @(posedge fifo_clk) + if(fifo_rst) + counter <= 0; + else if(do_write) + if(last_write) + counter <= 0; + else + counter <= counter + 1; + + assign fifo_ready = first_write & (fifo_space > frame_len); + +endmodule // gpmc_to_fifo_async diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index 1cb56d7a9..ca4d9ce89 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -178,7 +178,7 @@ timing/timer.v \ gpmc/gpmc.v \ gpmc/edge_sync.v \ gpmc/dbsm.v \ -gpmc/gpmc_to_fifo.v \ +gpmc/gpmc_to_fifo_async.v \ gpmc/gpmc_wb.v \ top/u1e/u1e_core.v \ top/u1e/u1e.ucf \ -- cgit v1.2.3 From 108109e649397147ecf6f5d6b82bdb3d5b852539 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 14 Apr 2010 19:14:46 -0700 Subject: more progress on synchronous interface --- usrp2/gpmc/gpmc.v | 61 ++++++++++++++++++++++++----------------- usrp2/gpmc/gpmc_to_fifo_async.v | 2 +- usrp2/gpmc/gpmc_to_fifo_sync.v | 57 ++++++++++++++++++++++++++++++++++++++ usrp2/top/u1e/Makefile | 1 + 4 files changed, 95 insertions(+), 26 deletions(-) create mode 100644 usrp2/gpmc/gpmc_to_fifo_sync.v diff --git a/usrp2/gpmc/gpmc.v b/usrp2/gpmc/gpmc.v index 2715414b3..d6a685bba 100644 --- a/usrp2/gpmc/gpmc.v +++ b/usrp2/gpmc/gpmc.v @@ -4,7 +4,8 @@ module gpmc (// GPMC signals input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, - + output bus_error, + // GPIOs for FIFO signalling output rx_have_data, output tx_have_space, @@ -17,15 +18,15 @@ module gpmc input fifo_clk, input fifo_rst, output [35:0] tx_data_o, output tx_src_rdy_o, input tx_dst_rdy_i, input [35:0] rx_data_i, input rx_src_rdy_i, output rx_dst_rdy_o, - + output [31:0] debug ); wire EM_output_enable = (~EM_NOE & (~EM_NCS4 | ~EM_NCS6)); - wire [15:0] EM_D_ram; + wire [15:0] EM_D_fifo; wire [15:0] EM_D_wb; - assign EM_D = ~EM_output_enable ? 16'bz : ~EM_NCS4 ? EM_D_ram : EM_D_wb; + assign EM_D = ~EM_output_enable ? 16'bz : ~EM_NCS4 ? EM_D_fifo : EM_D_wb; // CS4 is RAM_2PORT for DATA PATH (high-speed data) // Writes go into one RAM, reads come from the other @@ -37,19 +38,22 @@ module gpmc wire [17:0] tx18_data, tx18b_data; wire tx18_src_rdy, tx18_dst_rdy, tx18b_src_rdy, tx18b_dst_rdy; wire [15:0] tx_fifo_space, tx_frame_len; - + assign tx_frame_len = 10; + wire arst; - gpmc_to_fifo gpmc_to_fifo - (.EM_CLK(EM_CLK), .EM_D(EM_D), .EM_NBE(EM_NBE), .EM_NCS(EM_NCS4), .EM_NWE(EM_NWE), - .fifo_clk(fifo_clk), .fifo_rst(fifo_rst), + gpmc_to_fifo_sync gpmc_to_fifo_sync + (.arst(arst), + .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_NBE(EM_NBE), .EM_NCS(EM_NCS4), .EM_NWE(EM_NWE), .data_o(tx18_data), .src_rdy_o(tx18_src_rdy), .dst_rdy_i(tx18_dst_rdy), - .frame_len(tx_frame_len), .fifo_space(tx_fifo_space), .fifo_ready(tx_have_space)); + .frame_len(tx_frame_len), .fifo_space(tx_fifo_space), .fifo_ready(tx_have_space), + .bus_error(bus_error) ); - fifo_cascade #(.WIDTH(18), .SIZE(10)) tx_fifo - (.clk(fifo_clk), .reset(fifo_rst), .clear(0), - .datain(tx18_data), .src_rdy_i(tx18_src_rdy), .dst_rdy_o(tx18_dst_rdy), .space(tx_fifo_space), - .dataout(tx18b_data), .src_rdy_o(tx18b_src_rdy), .dst_rdy_i(tx18b_dst_rdy)); + fifo_2clock_cascade #(.WIDTH(18), .SIZE(10)) tx_fifo + (.wclk(EM_CLK), .datain(tx18_data), + .src_rdy_i(tx18_src_rdy), .dst_rdy_o(tx18_dst_rdy), .space(tx_fifo_space), + .rclk(fifo_clk), .dataout(tx18b_data), + .src_rdy_o(tx18b_src_rdy), .dst_rdy_i(tx18b_dst_rdy), .occupied(), .arst(arst)); fifo19_to_fifo36 f19_to_f36 (.clk(fifo_clk), .reset(fifo_rst), .clear(0), @@ -59,21 +63,28 @@ module gpmc // //////////////////////////////////////////// // RX Data Path - wire read_sel_rx, write_sel_rx, clear_rx; - wire read_done_rx; - - edge_sync #(.POSEDGE(0)) - edge_sync_rx(.clk(wb_clk), .rst(wb_rst), - .sig(~EM_NCS4 & ~EM_NOE & (EM_A == 10'h3FF)), .trig(read_done_rx)); + + wire [17:0] rx18_data, rx18b_data; + wire rx18_src_rdy, rx18_dst_rdy, rx18b_src_rdy, rx18b_dst_rdy; + wire [15:0] rx_fifo_space, rx_frame_len; - ram_2port_mixed_width buffer_rx - (.clk16(wb_clk), .en16(~EM_NCS4), .we16(0), .addr16({read_sel_rx,EM_A}), .di16(0), .do16(EM_D_ram), - .clk32(ram_clk), .en32(write_en), .we32(write_en), .addr32({write_sel_rx,write_addr}), .di32(write_data), .do32()); + fifo36_to_fifo18 f18_to_f36 + (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + .f36_datain(rx_data_i), .f36_src_rdy_i(rx_src_rdy_i), .f36_dst_rdy_o(rx_dst_rdy_o), + .f18_dataout(rx18_data), .f18_src_rdy_o(rx18_src_rdy), .f18_dst_rdy_i(rx18_dst_rdy) ); - dbsm dbsm_rx(.clk(wb_clk), .reset(wb_rst), .clear(clear_rx), - .read_sel(read_sel_rx), .read_ready(rx_have_data), .read_done(read_done_rx), - .write_sel(write_sel_rx), .write_ready(write_ready), .write_done(write_done)); + fifo_2clock_cascade #(.WIDTH(18), .SIZE(10)) rx_fifo + (.wclk(fifo_clk), .datain(rx18_data), + .src_rdy_i(rx18_src_rdy), .dst_rdy_o(rx18_dst_rdy), .space(rx_fifo_space), + .rclk(EM_CLK), .dataout(rx18b_data), + .src_rdy_o(tx18b_src_rdy), .dst_rdy_i(tx18b_dst_rdy), .occupied(), .arst(arst)); + fifo_to_gpmc_sync fifo_to_gpmc_sync + (.arst(arst), + .data_i(tx18b_data), .src_rdy_i(tx18b_src_rdy), .dst_rdy_o(tx18b_dst_rdy), + .EM_CLK(EM_CLK), .EM_D(EM_D_fifo), .EM_NCS(EM_NCS4), .EM_NOE(EM_NOE), + .fifo_ready(rx_have_data) ); + // //////////////////////////////////////////// // Control path on CS6 diff --git a/usrp2/gpmc/gpmc_to_fifo_async.v b/usrp2/gpmc/gpmc_to_fifo_async.v index c47d69d7d..a8068022f 100644 --- a/usrp2/gpmc/gpmc_to_fifo_async.v +++ b/usrp2/gpmc/gpmc_to_fifo_async.v @@ -1,6 +1,6 @@ module gpmc_to_fifo_async - (input EM_CLK, input [15:0] EM_D, input [1:0] EM_NBE, + (input [15:0] EM_D, input [1:0] EM_NBE, input EM_NCS, input EM_NWE, input fifo_clk, input fifo_rst, diff --git a/usrp2/gpmc/gpmc_to_fifo_sync.v b/usrp2/gpmc/gpmc_to_fifo_sync.v new file mode 100644 index 000000000..688de0e17 --- /dev/null +++ b/usrp2/gpmc/gpmc_to_fifo_sync.v @@ -0,0 +1,57 @@ + +// Assumes a GPMC cycle with GPMC clock, as in the timing diagrams +// If a packet bigger or smaller than we are told is sent, behavior is undefined. +// If dst_rdy_i is low when we get data, behavior is undefined and we signal bus error. +// If there is a bus error, we should be reset + +module gpmc_to_fifo_sync + (input arst, + input EM_CLK, input [15:0] EM_D, input [1:0] EM_NBE, + input EM_NCS, input EM_NWE, + output reg [17:0] data_o, output reg src_rdy_o, input dst_rdy_i, + input [15:0] frame_len, input [15:0] fifo_space, output fifo_ready, + output reg bus_error); + + reg [10:0] counter; + wire first_write = (counter == 0); + wire last_write = ((counter+1) == frame_len); + wire do_write = ~EM_NCS & ~EM_NWE; + + always @(posedge EM_CLK or posedge arst) + if(arst) + data_o <= 0; + else if(do_write) + begin + data_o[15:0] <= EM_D; + data_o[16] <= first_write; + data_o[17] <= last_write; + // no byte writes data_o[18] <= |EM_NBE; // mark half full if either is not enabled FIXME + end + + always @(posedge EM_CLK or posedge arst) + if(arst) + src_rdy_o <= 0; + else if(do_write & ~bus_error) // Don't put junk in if there is a bus error + src_rdy_o <= 1; + else + src_rdy_o <= 0; // Assume it was taken, ignore dst_rdy_i + + always @(posedge EM_CLK or posedge arst) + if(arst) + counter <= 0; + else if(do_write) + if(last_write) + counter <= 0; + else + counter <= counter + 1; + + assign fifo_ready = first_write & (fifo_space > frame_len); + + always @(posedge EM_CLK or posedge arst) + if(arst) + bus_error <= 0; + else if(src_rdy_o & ~dst_rdy_i) + bus_error <= 1; + // must be reset to make the error go away + +endmodule // gpmc_to_fifo_sync diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index ca4d9ce89..057de64cf 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -179,6 +179,7 @@ gpmc/gpmc.v \ gpmc/edge_sync.v \ gpmc/dbsm.v \ gpmc/gpmc_to_fifo_async.v \ +gpmc/gpmc_to_fifo_sync.v \ gpmc/gpmc_wb.v \ top/u1e/u1e_core.v \ top/u1e/u1e.ucf \ -- cgit v1.2.3 From f89ed91930f5933c827726d17b8c5b0313b6c297 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 14 Apr 2010 19:16:47 -0700 Subject: more sync progress. This is just a skeleton for now, with junk content --- usrp2/gpmc/fifo_to_gpmc_sync.v | 56 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 usrp2/gpmc/fifo_to_gpmc_sync.v diff --git a/usrp2/gpmc/fifo_to_gpmc_sync.v b/usrp2/gpmc/fifo_to_gpmc_sync.v new file mode 100644 index 000000000..647a507b4 --- /dev/null +++ b/usrp2/gpmc/fifo_to_gpmc_sync.v @@ -0,0 +1,56 @@ + +// Assumes a GPMC cycle with GPMC clock, as in the timing diagrams +// If a packet bigger or smaller than we are told is sent, behavior is undefined. +// If dst_rdy_i is low when we get data, behavior is undefined and we signal bus error. +// If there is a bus error, we should be reset + +module fifo_to_gpmc_sync + (input arst, + input [17:0] data_i, input src_rdy_i, output reg dst_rdy_o, + input EM_CLK, inout [15:0] EM_D, input EM_NCS, input EM_NOE, + output fifo_ready, + output reg bus_error); + + reg [10:0] counter; + wire first_write = (counter == 0); + wire last_write = ((counter+1) == frame_len); + wire do_write = ~EM_NCS & ~EM_NWE; + + always @(posedge EM_CLK or posedge arst) + if(arst) + data_o <= 0; + else if(do_write) + begin + data_o[15:0] <= EM_D; + data_o[16] <= first_write; + data_o[17] <= last_write; + // no byte writes data_o[18] <= |EM_NBE; // mark half full if either is not enabled FIXME + end + + always @(posedge EM_CLK or posedge arst) + if(arst) + src_rdy_o <= 0; + else if(do_write & ~bus_error) // Don't put junk in if there is a bus error + src_rdy_o <= 1; + else + src_rdy_o <= 0; // Assume it was taken, ignore dst_rdy_i + + always @(posedge EM_CLK or posedge arst) + if(arst) + counter <= 0; + else if(do_write) + if(last_write) + counter <= 0; + else + counter <= counter + 1; + + assign fifo_ready = first_write & (fifo_space > frame_len); + + always @(posedge EM_CLK or posedge arst) + if(arst) + bus_error <= 0; + else if(src_rdy_o & ~dst_rdy_i) + bus_error <= 1; + // must be reset to make the error go away + +endmodule // fifo_to_gpmc_sync -- cgit v1.2.3 From 7d00d3a7b93d53b2f60107f0e43645d35788cf2f Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 15 Apr 2010 12:52:18 -0700 Subject: handle all tri-state in the top level of gpmc --- usrp2/gpmc/gpmc.v | 6 +++--- usrp2/gpmc/gpmc_wb.v | 6 +++--- usrp2/top/u1e/Makefile | 2 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/usrp2/gpmc/gpmc.v b/usrp2/gpmc/gpmc.v index d6a685bba..93308a2d2 100644 --- a/usrp2/gpmc/gpmc.v +++ b/usrp2/gpmc/gpmc.v @@ -77,11 +77,11 @@ module gpmc (.wclk(fifo_clk), .datain(rx18_data), .src_rdy_i(rx18_src_rdy), .dst_rdy_o(rx18_dst_rdy), .space(rx_fifo_space), .rclk(EM_CLK), .dataout(rx18b_data), - .src_rdy_o(tx18b_src_rdy), .dst_rdy_i(tx18b_dst_rdy), .occupied(), .arst(arst)); + .src_rdy_o(rx18b_src_rdy), .dst_rdy_i(rx18b_dst_rdy), .occupied(), .arst(arst)); fifo_to_gpmc_sync fifo_to_gpmc_sync (.arst(arst), - .data_i(tx18b_data), .src_rdy_i(tx18b_src_rdy), .dst_rdy_o(tx18b_dst_rdy), + .data_i(rx18b_data), .src_rdy_i(rx18b_src_rdy), .dst_rdy_o(rx18b_dst_rdy), .EM_CLK(EM_CLK), .EM_D(EM_D_fifo), .EM_NCS(EM_NCS4), .EM_NOE(EM_NOE), .fifo_ready(rx_have_data) ); @@ -89,7 +89,7 @@ module gpmc // Control path on CS6 gpmc_wb gpmc_wb - (.EM_CLK(EM_CLK), .EM_D(EM_D_wb), .EM_A(EM_A), .EM_NBE(EM_NBE), + (.EM_CLK(EM_CLK), .EM_D_in(EM_D), .EM_D_out(EM_D_wb), .EM_A(EM_A), .EM_NBE(EM_NBE), .EM_NCS(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), .wb_clk(wb_clk), .wb_rst(wb_rst), .wb_adr_o(wb_adr_o), .wb_dat_mosi(wb_dat_mosi), .wb_dat_miso(wb_dat_miso), diff --git a/usrp2/gpmc/gpmc_wb.v b/usrp2/gpmc/gpmc_wb.v index 64f6a1c00..db6fbc6e9 100644 --- a/usrp2/gpmc/gpmc_wb.v +++ b/usrp2/gpmc/gpmc_wb.v @@ -1,7 +1,7 @@ module gpmc_wb - (input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, + (input EM_CLK, input [15:0] EM_D_in, output [15:0] EM_D_out, input [10:1] EM_A, input [1:0] EM_NBE, input EM_NCS, input EM_NWE, input EM_NOE, input wb_clk, input wb_rst, @@ -27,7 +27,7 @@ module gpmc_wb always @(posedge wb_clk) if(we_del == 2'b10) // Falling Edge begin - wb_dat_mosi <= EM_D; + wb_dat_mosi <= EM_D_in; wb_sel_o <= ~EM_NBE; end @@ -37,7 +37,7 @@ module gpmc_wb if(wb_ack_i) EM_D_hold <= wb_dat_miso; - assign EM_D = wb_ack_i ? wb_dat_miso : EM_D_hold; + assign EM_D_out = wb_ack_i ? wb_dat_miso : EM_D_hold; assign wb_cyc_o = wb_stb_o; diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index 057de64cf..160e67894 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -109,6 +109,7 @@ control_lib/newfifo/fifo_short.v \ control_lib/newfifo/fifo_long.v \ control_lib/newfifo/fifo_cascade.v \ control_lib/newfifo/fifo36_to_ll8.v \ +control_lib/newfifo/fifo36_to_fifo18.v \ control_lib/newfifo/fifo19_to_fifo36.v \ control_lib/longfifo.v \ control_lib/shortfifo.v \ @@ -180,6 +181,7 @@ gpmc/edge_sync.v \ gpmc/dbsm.v \ gpmc/gpmc_to_fifo_async.v \ gpmc/gpmc_to_fifo_sync.v \ +gpmc/fifo_to_gpmc_sync.v \ gpmc/gpmc_wb.v \ top/u1e/u1e_core.v \ top/u1e/u1e.ucf \ -- cgit v1.2.3 From d7342b46abac60bf4e2811ac4798dc4e06b5844f Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 15 Apr 2010 14:51:41 -0700 Subject: synchronous and asynchronous gpmc models --- usrp2/models/gpmc_model.v | 95 ---------------------------------------- usrp2/models/gpmc_model_async.v | 95 ++++++++++++++++++++++++++++++++++++++++ usrp2/models/gpmc_model_sync.v | 97 +++++++++++++++++++++++++++++++++++++++++ usrp2/top/u1e/tb_u1e.v | 2 +- 4 files changed, 193 insertions(+), 96 deletions(-) delete mode 100644 usrp2/models/gpmc_model.v create mode 100644 usrp2/models/gpmc_model_async.v create mode 100644 usrp2/models/gpmc_model_sync.v diff --git a/usrp2/models/gpmc_model.v b/usrp2/models/gpmc_model.v deleted file mode 100644 index 6066ede6e..000000000 --- a/usrp2/models/gpmc_model.v +++ /dev/null @@ -1,95 +0,0 @@ - - -module gpmc_model - (output EM_CLK, inout [15:0] EM_D, output reg [10:1] EM_A, output reg [1:0] EM_NBE, - output reg EM_WAIT0, output reg EM_NCS4, output reg EM_NCS6, - output reg EM_NWE, output reg EM_NOE ); - - assign EM_CLK = 0; - reg [15:0] EM_D_int; - assign EM_D = EM_D_int; - - initial - begin - EM_A <= 10'bz; - EM_NBE <= 2'b11; - EM_NWE <= 1; - EM_NOE <= 1; - EM_NCS4 <= 1; - EM_NCS6 <= 1; - EM_D_int <= 16'bz; - EM_WAIT0 <= 0; // FIXME this is actually an input - end - - task GPMC_Write; - input ctrl; - input [10:0] addr; - input [15:0] data; - begin - #2.3; - EM_A <= addr[10:1]; - EM_D_int <= data; - #2.01; - if(ctrl) - EM_NCS6 <= 0; - else - EM_NCS4 <= 0; - #14; - EM_NWE <= 0; - #77.5; - EM_NCS4 <= 1; - EM_NCS6 <= 1; - //#1.5; - EM_NWE <= 1; - #60; - EM_A <= 10'bz; - EM_D_int <= 16'bz; - end - endtask // GPMC_Write - - task GPMC_Read; - input ctrl; - input [10:0] addr; - begin - #1.3; - EM_A <= addr[10:1]; - #3; - if(ctrl) - EM_NCS6 <= 0; - else - EM_NCS4 <= 0; - #14; - EM_NOE <= 0; - #77.5; - EM_NCS4 <= 1; - EM_NCS6 <= 1; - //#1.5; - $display("Data Read from GPMC: %X",EM_D); - EM_NOE <= 1; - #254; - EM_A <= 10'bz; - end - endtask // GPMC_Read - - initial - begin - #1000; - GPMC_Write(1,36,16'hF00D); - #1000; - GPMC_Read(1,36); - #1000; - GPMC_Write(0,36,16'h1234); - GPMC_Write(0,38,16'h5678); - GPMC_Write(0,40,16'h9abc); - GPMC_Write(0,11'h2F4,16'hF00D); - GPMC_Write(0,11'h7FE,16'hDEAD); - GPMC_Write(0,11'h7FE,16'hDEAD); - GPMC_Write(0,11'h7FE,16'hDEAD); - GPMC_Write(0,11'h7FE,16'hDEAD); - GPMC_Write(0,11'h7FE,16'hDEAD); - GPMC_Write(0,11'h7FE,16'hDEAD); - #100000; - $finish; - end - -endmodule // gpmc_model diff --git a/usrp2/models/gpmc_model_async.v b/usrp2/models/gpmc_model_async.v new file mode 100644 index 000000000..a63a5a8fd --- /dev/null +++ b/usrp2/models/gpmc_model_async.v @@ -0,0 +1,95 @@ + + +module gpmc_model_async + (output EM_CLK, inout [15:0] EM_D, output reg [10:1] EM_A, output reg [1:0] EM_NBE, + output reg EM_WAIT0, output reg EM_NCS4, output reg EM_NCS6, + output reg EM_NWE, output reg EM_NOE ); + + assign EM_CLK = 0; + reg [15:0] EM_D_int; + assign EM_D = EM_D_int; + + initial + begin + EM_A <= 10'bz; + EM_NBE <= 2'b11; + EM_NWE <= 1; + EM_NOE <= 1; + EM_NCS4 <= 1; + EM_NCS6 <= 1; + EM_D_int <= 16'bz; + EM_WAIT0 <= 0; // FIXME this is actually an input + end + + task GPMC_Write; + input ctrl; + input [10:0] addr; + input [15:0] data; + begin + #2.3; + EM_A <= addr[10:1]; + EM_D_int <= data; + #2.01; + if(ctrl) + EM_NCS6 <= 0; + else + EM_NCS4 <= 0; + #14; + EM_NWE <= 0; + #77.5; + EM_NCS4 <= 1; + EM_NCS6 <= 1; + //#1.5; + EM_NWE <= 1; + #60; + EM_A <= 10'bz; + EM_D_int <= 16'bz; + end + endtask // GPMC_Write + + task GPMC_Read; + input ctrl; + input [10:0] addr; + begin + #1.3; + EM_A <= addr[10:1]; + #3; + if(ctrl) + EM_NCS6 <= 0; + else + EM_NCS4 <= 0; + #14; + EM_NOE <= 0; + #77.5; + EM_NCS4 <= 1; + EM_NCS6 <= 1; + //#1.5; + $display("Data Read from GPMC: %X",EM_D); + EM_NOE <= 1; + #254; + EM_A <= 10'bz; + end + endtask // GPMC_Read + + initial + begin + #1000; + GPMC_Write(1,36,16'hF00D); + #1000; + GPMC_Read(1,36); + #1000; + GPMC_Write(0,36,16'h1234); + GPMC_Write(0,38,16'h5678); + GPMC_Write(0,40,16'h9abc); + GPMC_Write(0,11'h2F4,16'hF00D); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + #100000; + $finish; + end + +endmodule // gpmc_model_async diff --git a/usrp2/models/gpmc_model_sync.v b/usrp2/models/gpmc_model_sync.v new file mode 100644 index 000000000..641720c15 --- /dev/null +++ b/usrp2/models/gpmc_model_sync.v @@ -0,0 +1,97 @@ + + +module gpmc_model_sync + (output reg EM_CLK, inout [15:0] EM_D, output reg [10:1] EM_A, output reg [1:0] EM_NBE, + output reg EM_WAIT0, output reg EM_NCS4, output reg EM_NCS6, + output reg EM_NWE, output reg EM_NOE ); + + reg [15:0] EM_D_int; + assign EM_D = EM_D_int; + + initial + begin + EM_CLK <= 0; + EM_A <= 10'bz; + EM_NBE <= 2'b11; + EM_NWE <= 1; + EM_NOE <= 1; + EM_NCS4 <= 1; + EM_NCS6 <= 1; + EM_D_int <= 16'bz; + EM_WAIT0 <= 0; // FIXME this is actually an input + end + + task GPMC_Write; + input ctrl; + input [10:0] addr; + input [15:0] data; + begin + EM_CLK <= 1; + #10; + EM_CLK <= 0; + EM_NWE <= 0; + if(ctrl) + EM_NCS6 <= 0; + else + EM_NCS4 <= 0; + EM_A <= addr[10:1]; + EM_D_int <= data; + #10; + EM_CLK <= 1; + #10; + EM_CLK <= 0; + EM_NWE <= 1; + EM_NCS4 <= 1; + EM_NCS6 <= 1; + EM_A <= 10'bz; + EM_D_int <= 16'bz; + #100; + end + endtask // GPMC_Write + + task GPMC_Read; + input ctrl; + input [10:0] addr; + begin + #1.3; + EM_A <= addr[10:1]; + #3; + if(ctrl) + EM_NCS6 <= 0; + else + EM_NCS4 <= 0; + #14; + EM_NOE <= 0; + #77.5; + EM_NCS4 <= 1; + EM_NCS6 <= 1; + //#1.5; + $display("Data Read from GPMC: %X",EM_D); + EM_NOE <= 1; + #254; + EM_A <= 10'bz; + end + endtask // GPMC_Read + + initial + begin + #1000; + GPMC_Write(1,36,16'hF00D); + #1000; + GPMC_Read(1,36); + #1000; + GPMC_Write(0,36,16'h1234); + GPMC_Write(0,38,16'h5678); + GPMC_Write(0,40,16'h9abc); + GPMC_Write(0,11'h2F4,16'hF00D); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + #100000; + $finish; + end + +endmodule // gpmc_model diff --git a/usrp2/top/u1e/tb_u1e.v b/usrp2/top/u1e/tb_u1e.v index 3cae74c8a..31e4fcb69 100644 --- a/usrp2/top/u1e/tb_u1e.v +++ b/usrp2/top/u1e/tb_u1e.v @@ -33,7 +33,7 @@ module tb_u1e(); .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE) ); - gpmc_model gpmc_model + gpmc_model_async gpmc_model_async (.EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE) ); -- cgit v1.2.3 From 6dd46af16008e46ee8830748194bbc2a1df9fdf3 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 15 Apr 2010 14:56:19 -0700 Subject: progress on synchronous gpmc, but it may not be possible due to the limited number of clock edges --- usrp2/gpmc/fifo_to_gpmc_sync.v | 44 +++-------------- usrp2/gpmc/fifo_watcher.v | 26 ++++++++++ usrp2/gpmc/gpmc.v | 101 -------------------------------------- usrp2/gpmc/gpmc_sync.v | 107 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+), 138 deletions(-) create mode 100644 usrp2/gpmc/fifo_watcher.v delete mode 100644 usrp2/gpmc/gpmc.v create mode 100644 usrp2/gpmc/gpmc_sync.v diff --git a/usrp2/gpmc/fifo_to_gpmc_sync.v b/usrp2/gpmc/fifo_to_gpmc_sync.v index 647a507b4..ef59d7137 100644 --- a/usrp2/gpmc/fifo_to_gpmc_sync.v +++ b/usrp2/gpmc/fifo_to_gpmc_sync.v @@ -6,51 +6,21 @@ module fifo_to_gpmc_sync (input arst, - input [17:0] data_i, input src_rdy_i, output reg dst_rdy_o, - input EM_CLK, inout [15:0] EM_D, input EM_NCS, input EM_NOE, + input [17:0] data_i, input src_rdy_i, output dst_rdy_o, + input EM_CLK, output [15:0] EM_D, input EM_NCS, input EM_NOE, output fifo_ready, output reg bus_error); - - reg [10:0] counter; - wire first_write = (counter == 0); - wire last_write = ((counter+1) == frame_len); - wire do_write = ~EM_NCS & ~EM_NWE; - - always @(posedge EM_CLK or posedge arst) - if(arst) - data_o <= 0; - else if(do_write) - begin - data_o[15:0] <= EM_D; - data_o[16] <= first_write; - data_o[17] <= last_write; - // no byte writes data_o[18] <= |EM_NBE; // mark half full if either is not enabled FIXME - end - always @(posedge EM_CLK or posedge arst) - if(arst) - src_rdy_o <= 0; - else if(do_write & ~bus_error) // Don't put junk in if there is a bus error - src_rdy_o <= 1; - else - src_rdy_o <= 0; // Assume it was taken, ignore dst_rdy_i + assign EM_D = data_i[15:0]; + wire read_access = ~EM_NCS & ~EM_NOE; - always @(posedge EM_CLK or posedge arst) - if(arst) - counter <= 0; - else if(do_write) - if(last_write) - counter <= 0; - else - counter <= counter + 1; + assign dst_rdy_o = read_access; - assign fifo_ready = first_write & (fifo_space > frame_len); - always @(posedge EM_CLK or posedge arst) if(arst) bus_error <= 0; - else if(src_rdy_o & ~dst_rdy_i) + else if(dst_rdy_o & ~src_rdy_i) bus_error <= 1; - // must be reset to make the error go away + endmodule // fifo_to_gpmc_sync diff --git a/usrp2/gpmc/fifo_watcher.v b/usrp2/gpmc/fifo_watcher.v new file mode 100644 index 000000000..8b8f1abfb --- /dev/null +++ b/usrp2/gpmc/fifo_watcher.v @@ -0,0 +1,26 @@ + + +module fifo_watcher + (input clk, input reset, input clear, + input src_rdy, input dst_rdy, input sof, input eof, + output have_packet, output [15:0] length, input next); + + wire write = src_rdy & dst_rdy & eof; + + fifo_short #(.WIDTH(16)) frame_lengths + (.clk(clk), .reset(reset), .clear(clear), + .datain(counter), .src_rdy_i(write), .dst_rdy_o(), + .dataout(length), .src_rdy_o(have_packet), .dst_rdy_i(next) ); + + reg [15:0] counter; + always @(posedge clk) + if(reset | clear) + counter <= 1; // Start at 1 + else if(src_rdy & dst_rdy) + if(eof) + counter <= 1; + else + counter <= counter + 1; + + +endmodule // fifo_watcher diff --git a/usrp2/gpmc/gpmc.v b/usrp2/gpmc/gpmc.v deleted file mode 100644 index 93308a2d2..000000000 --- a/usrp2/gpmc/gpmc.v +++ /dev/null @@ -1,101 +0,0 @@ -////////////////////////////////////////////////////////////////////////////////// - -module gpmc - (// GPMC signals - input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, - input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, - output bus_error, - - // GPIOs for FIFO signalling - output rx_have_data, output tx_have_space, - - // Wishbone signals - input wb_clk, input wb_rst, - output [10:0] wb_adr_o, output [15:0] wb_dat_mosi, input [15:0] wb_dat_miso, - output [1:0] wb_sel_o, output wb_cyc_o, output wb_stb_o, output wb_we_o, input wb_ack_i, - - // FIFO interface - input fifo_clk, input fifo_rst, - output [35:0] tx_data_o, output tx_src_rdy_o, input tx_dst_rdy_i, - input [35:0] rx_data_i, input rx_src_rdy_i, output rx_dst_rdy_o, - - output [31:0] debug - ); - - wire EM_output_enable = (~EM_NOE & (~EM_NCS4 | ~EM_NCS6)); - wire [15:0] EM_D_fifo; - wire [15:0] EM_D_wb; - - assign EM_D = ~EM_output_enable ? 16'bz : ~EM_NCS4 ? EM_D_fifo : EM_D_wb; - - // CS4 is RAM_2PORT for DATA PATH (high-speed data) - // Writes go into one RAM, reads come from the other - // CS6 is for CONTROL PATH (wishbone) - - // //////////////////////////////////////////// - // TX Data Path - - wire [17:0] tx18_data, tx18b_data; - wire tx18_src_rdy, tx18_dst_rdy, tx18b_src_rdy, tx18b_dst_rdy; - wire [15:0] tx_fifo_space, tx_frame_len; - - assign tx_frame_len = 10; - wire arst; - - gpmc_to_fifo_sync gpmc_to_fifo_sync - (.arst(arst), - .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_NBE(EM_NBE), .EM_NCS(EM_NCS4), .EM_NWE(EM_NWE), - .data_o(tx18_data), .src_rdy_o(tx18_src_rdy), .dst_rdy_i(tx18_dst_rdy), - .frame_len(tx_frame_len), .fifo_space(tx_fifo_space), .fifo_ready(tx_have_space), - .bus_error(bus_error) ); - - fifo_2clock_cascade #(.WIDTH(18), .SIZE(10)) tx_fifo - (.wclk(EM_CLK), .datain(tx18_data), - .src_rdy_i(tx18_src_rdy), .dst_rdy_o(tx18_dst_rdy), .space(tx_fifo_space), - .rclk(fifo_clk), .dataout(tx18b_data), - .src_rdy_o(tx18b_src_rdy), .dst_rdy_i(tx18b_dst_rdy), .occupied(), .arst(arst)); - - fifo19_to_fifo36 f19_to_f36 - (.clk(fifo_clk), .reset(fifo_rst), .clear(0), - .f19_datain({1'b0,tx18b_data}), .f19_src_rdy_i(tx18b_src_rdy), .f19_dst_rdy_o(tx18b_dst_rdy), - .f36_dataout(tx_data_o), .f36_src_rdy_o(tx_src_rdy_o), .f36_dst_rdy_i(tx_dst_rdy_i)); - - - // //////////////////////////////////////////// - // RX Data Path - - wire [17:0] rx18_data, rx18b_data; - wire rx18_src_rdy, rx18_dst_rdy, rx18b_src_rdy, rx18b_dst_rdy; - wire [15:0] rx_fifo_space, rx_frame_len; - - fifo36_to_fifo18 f18_to_f36 - (.clk(fifo_clk), .reset(fifo_rst), .clear(0), - .f36_datain(rx_data_i), .f36_src_rdy_i(rx_src_rdy_i), .f36_dst_rdy_o(rx_dst_rdy_o), - .f18_dataout(rx18_data), .f18_src_rdy_o(rx18_src_rdy), .f18_dst_rdy_i(rx18_dst_rdy) ); - - fifo_2clock_cascade #(.WIDTH(18), .SIZE(10)) rx_fifo - (.wclk(fifo_clk), .datain(rx18_data), - .src_rdy_i(rx18_src_rdy), .dst_rdy_o(rx18_dst_rdy), .space(rx_fifo_space), - .rclk(EM_CLK), .dataout(rx18b_data), - .src_rdy_o(rx18b_src_rdy), .dst_rdy_i(rx18b_dst_rdy), .occupied(), .arst(arst)); - - fifo_to_gpmc_sync fifo_to_gpmc_sync - (.arst(arst), - .data_i(rx18b_data), .src_rdy_i(rx18b_src_rdy), .dst_rdy_o(rx18b_dst_rdy), - .EM_CLK(EM_CLK), .EM_D(EM_D_fifo), .EM_NCS(EM_NCS4), .EM_NOE(EM_NOE), - .fifo_ready(rx_have_data) ); - - // //////////////////////////////////////////// - // Control path on CS6 - - gpmc_wb gpmc_wb - (.EM_CLK(EM_CLK), .EM_D_in(EM_D), .EM_D_out(EM_D_wb), .EM_A(EM_A), .EM_NBE(EM_NBE), - .EM_NCS(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), - .wb_clk(wb_clk), .wb_rst(wb_rst), - .wb_adr_o(wb_adr_o), .wb_dat_mosi(wb_dat_mosi), .wb_dat_miso(wb_dat_miso), - .wb_sel_o(wb_sel_o), .wb_cyc_o(wb_cyc_o), .wb_stb_o(wb_stb_o), .wb_we_o(wb_we_o), - .wb_ack_i(wb_ack_i) ); - - assign debug = 0; - -endmodule // gpmc diff --git a/usrp2/gpmc/gpmc_sync.v b/usrp2/gpmc/gpmc_sync.v new file mode 100644 index 000000000..41dfeb49e --- /dev/null +++ b/usrp2/gpmc/gpmc_sync.v @@ -0,0 +1,107 @@ +////////////////////////////////////////////////////////////////////////////////// + +module gpmc + (// GPMC signals + input arst, + input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, + input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, + + // GPIOs for FIFO signalling + output rx_have_data, output tx_have_space, output bus_error, input bus_reset, + + // Wishbone signals + input wb_clk, input wb_rst, + output [10:0] wb_adr_o, output [15:0] wb_dat_mosi, input [15:0] wb_dat_miso, + output [1:0] wb_sel_o, output wb_cyc_o, output wb_stb_o, output wb_we_o, input wb_ack_i, + + // FIFO interface + input fifo_clk, input fifo_rst, + output [35:0] tx_data_o, output tx_src_rdy_o, input tx_dst_rdy_i, + input [35:0] rx_data_i, input rx_src_rdy_i, output rx_dst_rdy_o, + + output [31:0] debug + ); + + wire EM_output_enable = (~EM_NOE & (~EM_NCS4 | ~EM_NCS6)); + wire [15:0] EM_D_fifo; + wire [15:0] EM_D_wb; + + assign EM_D = ~EM_output_enable ? 16'bz : ~EM_NCS4 ? EM_D_fifo : EM_D_wb; + + wire bus_error_tx, bus_error_rx; + assign bus_error = bus_error_tx | bus_error_rx; + + // CS4 is RAM_2PORT for DATA PATH (high-speed data) + // Writes go into one RAM, reads come from the other + // CS6 is for CONTROL PATH (wishbone) + + // //////////////////////////////////////////// + // TX Data Path + + wire [17:0] tx18_data, tx18b_data; + wire tx18_src_rdy, tx18_dst_rdy, tx18b_src_rdy, tx18b_dst_rdy; + wire [15:0] tx_fifo_space, tx_frame_len; + + assign tx_frame_len = 10; + + gpmc_to_fifo_sync gpmc_to_fifo_sync + (.arst(arst), + .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_NBE(EM_NBE), .EM_NCS(EM_NCS4), .EM_NWE(EM_NWE), + .data_o(tx18_data), .src_rdy_o(tx18_src_rdy), .dst_rdy_i(tx18_dst_rdy), + .frame_len(tx_frame_len), .fifo_space(tx_fifo_space), .fifo_ready(tx_have_space), + .bus_error(bus_error_tx) ); + + fifo_2clock_cascade #(.WIDTH(18), .SIZE(4)) tx_fifo + (.wclk(EM_CLK), .datain(tx18_data), + .src_rdy_i(tx18_src_rdy), .dst_rdy_o(tx18_dst_rdy), .space(tx_fifo_space), + .rclk(fifo_clk), .dataout(tx18b_data), + .src_rdy_o(tx18b_src_rdy), .dst_rdy_i(tx18b_dst_rdy), .occupied(), .arst(arst)); + + fifo19_to_fifo36 f19_to_f36 + (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + .f19_datain({1'b0,tx18b_data}), .f19_src_rdy_i(tx18b_src_rdy), .f19_dst_rdy_o(tx18b_dst_rdy), + .f36_dataout(tx_data_o), .f36_src_rdy_o(tx_src_rdy_o), .f36_dst_rdy_i(tx_dst_rdy_i)); + + // //////////////////////////////////////////// + // RX Data Path + + wire [17:0] rx18_data, rx18b_data; + wire rx18_src_rdy, rx18_dst_rdy, rx18b_src_rdy, rx18b_dst_rdy; + wire [15:0] rx_fifo_space, rx_frame_len; + + fifo36_to_fifo18 f18_to_f36 + (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + .f36_datain(rx_data_i), .f36_src_rdy_i(rx_src_rdy_i), .f36_dst_rdy_o(rx_dst_rdy_o), + .f18_dataout(rx18_data), .f18_src_rdy_o(rx18_src_rdy), .f18_dst_rdy_i(rx18_dst_rdy) ); + + fifo_2clock_cascade #(.WIDTH(18), .SIZE(10)) rx_fifo + (.wclk(fifo_clk), .datain(rx18_data), + .src_rdy_i(rx18_src_rdy), .dst_rdy_o(rx18_dst_rdy), .space(rx_fifo_space), + .rclk(EM_CLK), .dataout(rx18b_data), + .src_rdy_o(rx18b_src_rdy), .dst_rdy_i(rx18b_dst_rdy), .occupied(), .arst(arst)); + + fifo_to_gpmc_sync fifo_to_gpmc_sync + (.arst(arst), + .data_i(rx18b_data), .src_rdy_i(rx18b_src_rdy), .dst_rdy_o(rx18b_dst_rdy), + .EM_CLK(EM_CLK), .EM_D(EM_D_fifo), .EM_NCS(EM_NCS4), .EM_NOE(EM_NOE), + .fifo_ready(rx_have_data) ); + + fifo_watcher fifo_watcher + (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + .src_rdy(rx18_src_rdy), .dst_rdy(rx18_dst_rdy), .sof(rx18_data[16]), .eof(rx18_data[17]), + .have_packet(), .length(), .next() ); + + // //////////////////////////////////////////// + // Control path on CS6 + + gpmc_wb gpmc_wb + (.EM_CLK(EM_CLK), .EM_D_in(EM_D), .EM_D_out(EM_D_wb), .EM_A(EM_A), .EM_NBE(EM_NBE), + .EM_NCS(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), + .wb_clk(wb_clk), .wb_rst(wb_rst), + .wb_adr_o(wb_adr_o), .wb_dat_mosi(wb_dat_mosi), .wb_dat_miso(wb_dat_miso), + .wb_sel_o(wb_sel_o), .wb_cyc_o(wb_cyc_o), .wb_stb_o(wb_stb_o), .wb_we_o(wb_we_o), + .wb_ack_i(wb_ack_i) ); + + assign debug = 0; + +endmodule // gpmc -- cgit v1.2.3 From 8f6ddf93ef81deb73a8b84496e115be299769951 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 15 Apr 2010 16:13:42 -0700 Subject: correct name of module --- usrp2/gpmc/gpmc_sync.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usrp2/gpmc/gpmc_sync.v b/usrp2/gpmc/gpmc_sync.v index 41dfeb49e..825d131d8 100644 --- a/usrp2/gpmc/gpmc_sync.v +++ b/usrp2/gpmc/gpmc_sync.v @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////////// -module gpmc +module gpmc_sync (// GPMC signals input arst, input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, @@ -104,4 +104,4 @@ module gpmc assign debug = 0; -endmodule // gpmc +endmodule // gpmc_sync -- cgit v1.2.3 From 883c60cad6756042b5e90785668be3dd98e920bf Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 15 Apr 2010 16:14:24 -0700 Subject: add bus error reporting --- usrp2/gpmc/gpmc_to_fifo_async.v | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/usrp2/gpmc/gpmc_to_fifo_async.v b/usrp2/gpmc/gpmc_to_fifo_async.v index a8068022f..1df93f910 100644 --- a/usrp2/gpmc/gpmc_to_fifo_async.v +++ b/usrp2/gpmc/gpmc_to_fifo_async.v @@ -1,12 +1,12 @@ module gpmc_to_fifo_async - (input [15:0] EM_D, input [1:0] EM_NBE, - input EM_NCS, input EM_NWE, + (input [15:0] EM_D, input [1:0] EM_NBE, input EM_NCS, input EM_NWE, input fifo_clk, input fifo_rst, output reg [17:0] data_o, output reg src_rdy_o, input dst_rdy_i, - input [15:0] frame_len, input [15:0] fifo_space, output fifo_ready); + input [15:0] frame_len, input [15:0] fifo_space, output fifo_ready, + output reg bus_error ); reg [10:0] counter; // Synchronize the async control signals @@ -54,5 +54,11 @@ module gpmc_to_fifo_async counter <= counter + 1; assign fifo_ready = first_write & (fifo_space > frame_len); + + always @(posedge fifo_clk) + if(fifo_rst) + bus_error <= 0; + else if(src_rdy_o & ~dst_rdy_i) + bus_error <= 1; endmodule // gpmc_to_fifo_async -- cgit v1.2.3 From 2e6079841b7509f08a54c67db2ec19e07329e0d9 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 15 Apr 2010 16:14:57 -0700 Subject: change time parameters because Xilinx IP has a 1ps timescale --- usrp2/models/gpmc_model_async.v | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/usrp2/models/gpmc_model_async.v b/usrp2/models/gpmc_model_async.v index a63a5a8fd..64b596284 100644 --- a/usrp2/models/gpmc_model_async.v +++ b/usrp2/models/gpmc_model_async.v @@ -1,4 +1,4 @@ - +`timescale 1ps/1ps module gpmc_model_async (output EM_CLK, inout [15:0] EM_D, output reg [10:1] EM_A, output reg [1:0] EM_NBE, @@ -26,22 +26,22 @@ module gpmc_model_async input [10:0] addr; input [15:0] data; begin - #2.3; + #23000; EM_A <= addr[10:1]; EM_D_int <= data; - #2.01; + #20100; if(ctrl) EM_NCS6 <= 0; else EM_NCS4 <= 0; - #14; + #14000; EM_NWE <= 0; - #77.5; + #77500; EM_NCS4 <= 1; EM_NCS6 <= 1; //#1.5; EM_NWE <= 1; - #60; + #60000; EM_A <= 10'bz; EM_D_int <= 16'bz; end @@ -51,33 +51,33 @@ module gpmc_model_async input ctrl; input [10:0] addr; begin - #1.3; + #13000; EM_A <= addr[10:1]; - #3; + #3000; if(ctrl) EM_NCS6 <= 0; else EM_NCS4 <= 0; - #14; + #14000; EM_NOE <= 0; - #77.5; + #77500; EM_NCS4 <= 1; EM_NCS6 <= 1; //#1.5; $display("Data Read from GPMC: %X",EM_D); EM_NOE <= 1; - #254; + #254000; EM_A <= 10'bz; end endtask // GPMC_Read initial begin - #1000; + #1000000; GPMC_Write(1,36,16'hF00D); - #1000; + #1000000; GPMC_Read(1,36); - #1000; + #1000000; GPMC_Write(0,36,16'h1234); GPMC_Write(0,38,16'h5678); GPMC_Write(0,40,16'h9abc); @@ -89,6 +89,19 @@ module gpmc_model_async GPMC_Write(0,11'h7FE,16'hDEAD); GPMC_Write(0,11'h7FE,16'hDEAD); #100000; + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + #100000; + GPMC_Read(0,0); + #100000000; $finish; end -- cgit v1.2.3 From 449a420f4024004abc49f3a17d224910710def92 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 15 Apr 2010 16:16:31 -0700 Subject: async gpmc progress --- usrp2/gpmc/fifo_to_gpmc_async.v | 45 +++++++++++++++++ usrp2/gpmc/gpmc_async.v | 108 ++++++++++++++++++++++++++++++++++++++++ usrp2/top/u1e/tb_u1e.v | 4 +- usrp2/top/u1e/u1e_core.v | 34 +++++++------ 4 files changed, 173 insertions(+), 18 deletions(-) create mode 100644 usrp2/gpmc/fifo_to_gpmc_async.v create mode 100644 usrp2/gpmc/gpmc_async.v diff --git a/usrp2/gpmc/fifo_to_gpmc_async.v b/usrp2/gpmc/fifo_to_gpmc_async.v new file mode 100644 index 000000000..4f253e1b5 --- /dev/null +++ b/usrp2/gpmc/fifo_to_gpmc_async.v @@ -0,0 +1,45 @@ + +// Assumes an asynchronous GPMC cycle +// If a packet bigger or smaller than we are told is sent, behavior is undefined. +// If dst_rdy_i is low when we get data, behavior is undefined and we signal bus error. +// If there is a bus error, we should be reset + +module fifo_to_gpmc_async + (input clk, input reset, input clear, + input [17:0] data_i, input src_rdy_i, output dst_rdy_o, + output [15:0] EM_D, input EM_NCS, input EM_NOE, + input [15:0] frame_len, output reg bus_error); + + // Synchronize the async control signals + reg [1:0] cs_del, oe_del; + reg [15:0] counter; + + always @(posedge clk) + if(reset) + begin + cs_del <= 2'b11; + oe_del <= 2'b11; + end + else + begin + cs_del <= { cs_del[0], EM_NCS }; + oe_del <= { oe_del[0], EM_NOE }; + end + + //wire do_read = (~cs_del[0] & (oe_del == 2'b10)); + wire do_read = (~cs_del[1] & (oe_del == 2'b01)); // change output on trailing edge + wire first_read = (counter == 0); + wire last_read = ((counter+1) == frame_len); + + assign EM_D = data_i[15:0]; + + assign dst_rdy_o = do_read; + + always @(posedge clk) + if(reset) + bus_error <= 0; + else if(dst_rdy_o & ~src_rdy_i) + bus_error <= 1; + + +endmodule // fifo_to_gpmc_async diff --git a/usrp2/gpmc/gpmc_async.v b/usrp2/gpmc/gpmc_async.v new file mode 100644 index 000000000..c4cf0ef89 --- /dev/null +++ b/usrp2/gpmc/gpmc_async.v @@ -0,0 +1,108 @@ +////////////////////////////////////////////////////////////////////////////////// + +module gpmc_async + (// GPMC signals + input arst, + input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, + input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, + + // GPIOs for FIFO signalling + output rx_have_data, output tx_have_space, output bus_error, input bus_reset, + + // Wishbone signals + input wb_clk, input wb_rst, + output [10:0] wb_adr_o, output [15:0] wb_dat_mosi, input [15:0] wb_dat_miso, + output [1:0] wb_sel_o, output wb_cyc_o, output wb_stb_o, output wb_we_o, input wb_ack_i, + + // FIFO interface + input fifo_clk, input fifo_rst, + output [35:0] tx_data_o, output tx_src_rdy_o, input tx_dst_rdy_i, + input [35:0] rx_data_i, input rx_src_rdy_i, output rx_dst_rdy_o, + + output [31:0] debug + ); + + wire EM_output_enable = (~EM_NOE & (~EM_NCS4 | ~EM_NCS6)); + wire [15:0] EM_D_fifo; + wire [15:0] EM_D_wb; + + assign EM_D = ~EM_output_enable ? 16'bz : ~EM_NCS4 ? EM_D_fifo : EM_D_wb; + + wire bus_error_tx, bus_error_rx; + assign bus_error = bus_error_tx | bus_error_rx; + + // CS4 is RAM_2PORT for DATA PATH (high-speed data) + // Writes go into one RAM, reads come from the other + // CS6 is for CONTROL PATH (wishbone) + + // //////////////////////////////////////////// + // TX Data Path + + wire [17:0] tx18_data, tx18b_data; + wire tx18_src_rdy, tx18_dst_rdy, tx18b_src_rdy, tx18b_dst_rdy; + wire [15:0] tx_fifo_space, tx_frame_len; + + assign tx_frame_len = 10; + + gpmc_to_fifo_async gpmc_to_fifo_async + (.EM_D(EM_D), .EM_NBE(EM_NBE), .EM_NCS(EM_NCS4), .EM_NWE(EM_NWE), + .fifo_clk(fifo_clk), .fifo_rst(fifo_rst), + .data_o(tx18_data), .src_rdy_o(tx18_src_rdy), .dst_rdy_i(tx18_dst_rdy), + .frame_len(tx_frame_len), .fifo_space(tx_fifo_space), .fifo_ready(tx_have_space), + .bus_error(bus_error_tx) ); + + fifo_cascade #(.WIDTH(18), .SIZE(10)) tx_fifo + (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + .datain(tx18_data), .src_rdy_i(tx18_src_rdy), .dst_rdy_o(tx18_dst_rdy), .space(tx_fifo_space), + .dataout(tx18b_data), .src_rdy_o(tx18b_src_rdy), .dst_rdy_i(tx18b_dst_rdy), .occupied()); + + fifo19_to_fifo36 f19_to_f36 + (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + .f19_datain({1'b0,tx18b_data}), .f19_src_rdy_i(tx18b_src_rdy), .f19_dst_rdy_o(tx18b_dst_rdy), + .f36_dataout(tx_data_o), .f36_src_rdy_o(tx_src_rdy_o), .f36_dst_rdy_i(tx_dst_rdy_i)); + + // //////////////////////////////////////////// + // RX Data Path + + wire [17:0] rx18_data, rx18b_data; + wire rx18_src_rdy, rx18_dst_rdy, rx18b_src_rdy, rx18b_dst_rdy; + wire [15:0] rx_fifo_space, rx_frame_len; + assign rx_frame_len = tx_frame_len; + + fifo36_to_fifo18 f18_to_f36 + (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + .f36_datain(rx_data_i), .f36_src_rdy_i(rx_src_rdy_i), .f36_dst_rdy_o(rx_dst_rdy_o), + .f18_dataout(rx18_data), .f18_src_rdy_o(rx18_src_rdy), .f18_dst_rdy_i(rx18_dst_rdy) ); + + fifo_cascade #(.WIDTH(18), .SIZE(10)) rx_fifo + (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + .datain(rx18_data), .src_rdy_i(rx18_src_rdy), .dst_rdy_o(rx18_dst_rdy), .space(rx_fifo_space), + .dataout(rx18b_data), .src_rdy_o(rx18b_src_rdy), .dst_rdy_i(rx18b_dst_rdy), .occupied()); + + fifo_to_gpmc_async fifo_to_gpmc_async + (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + .data_i(rx18b_data), .src_rdy_i(rx18b_src_rdy), .dst_rdy_o(rx18b_dst_rdy), + .EM_D(EM_D_fifo), .EM_NCS(EM_NCS4), .EM_NOE(EM_NOE), + .frame_len(rx_frame_len), .bus_error(bus_error_rx) ); + + fifo_watcher fifo_watcher + (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + .src_rdy(rx18_src_rdy), .dst_rdy(rx18_dst_rdy), .sof(rx18_data[16]), .eof(rx18_data[17]), + .have_packet(), .length(), .next() ); + + assign rx_have_data = 0; + + // //////////////////////////////////////////// + // Control path on CS6 + + gpmc_wb gpmc_wb + (.EM_CLK(EM_CLK), .EM_D_in(EM_D), .EM_D_out(EM_D_wb), .EM_A(EM_A), .EM_NBE(EM_NBE), + .EM_NCS(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), + .wb_clk(wb_clk), .wb_rst(wb_rst), + .wb_adr_o(wb_adr_o), .wb_dat_mosi(wb_dat_mosi), .wb_dat_miso(wb_dat_miso), + .wb_sel_o(wb_sel_o), .wb_cyc_o(wb_cyc_o), .wb_stb_o(wb_stb_o), .wb_we_o(wb_we_o), + .wb_ack_i(wb_ack_i) ); + + assign debug = 0; + +endmodule // gpmc_async diff --git a/usrp2/top/u1e/tb_u1e.v b/usrp2/top/u1e/tb_u1e.v index 31e4fcb69..5fc8134fb 100644 --- a/usrp2/top/u1e/tb_u1e.v +++ b/usrp2/top/u1e/tb_u1e.v @@ -21,9 +21,9 @@ module tb_u1e(); wire [1:0] EM_NBE; reg clk_fpga = 0, rst_fpga = 1; - always #15.625 clk_fpga = ~clk_fpga; + always #15625 clk_fpga = ~clk_fpga; - initial #200 + initial #200000 @(posedge clk_fpga) rst_fpga <= 0; diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 7df7b0a48..40950bf82 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -35,22 +35,24 @@ module u1e_core wire [35:0] tx_data, rx_data; wire tx_src_rdy, tx_dst_rdy, rx_src_rdy, rx_dst_rdy; - gpmc gpmc (.EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), - .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), - .EM_NOE(EM_NOE), - - .rx_have_data(rx_have_data), .tx_have_space(tx_have_space), - - .wb_clk(wb_clk), .wb_rst(wb_rst), - .wb_adr_o(m0_adr), .wb_dat_mosi(m0_dat_mosi), .wb_dat_miso(m0_dat_miso), - .wb_sel_o(m0_sel), .wb_cyc_o(m0_cyc), .wb_stb_o(m0_stb), .wb_we_o(m0_we), - .wb_ack_i(m0_ack), - - .fifo_clk(wb_clk), .fifo_rst(wb_rst), - .tx_data_o(tx_data), .tx_src_rdy_o(tx_src_rdy), .tx_dst_rdy_i(tx_dst_rdy), - .rx_data_i(rx_data), .rx_src_rdy_i(rx_src_rdy), .rx_dst_rdy_o(rx_dst_rdy), - - .debug(debug_gpmc)); + gpmc_async gpmc (.arst(wb_rst), + .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), + .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), + .EM_NOE(EM_NOE), + + .rx_have_data(rx_have_data), .tx_have_space(tx_have_space), + .bus_error(), .bus_reset(0), + + .wb_clk(wb_clk), .wb_rst(wb_rst), + .wb_adr_o(m0_adr), .wb_dat_mosi(m0_dat_mosi), .wb_dat_miso(m0_dat_miso), + .wb_sel_o(m0_sel), .wb_cyc_o(m0_cyc), .wb_stb_o(m0_stb), .wb_we_o(m0_we), + .wb_ack_i(m0_ack), + + .fifo_clk(wb_clk), .fifo_rst(wb_rst), + .tx_data_o(tx_data), .tx_src_rdy_o(tx_src_rdy), .tx_dst_rdy_i(tx_dst_rdy), + .rx_data_i(rx_data), .rx_src_rdy_i(rx_src_rdy), .rx_dst_rdy_o(rx_dst_rdy), + + .debug(debug_gpmc)); fifo_cascade #(.WIDTH(36), .SIZE(9)) loopback_fifo (.clk(wb_clk), .reset(wb_rst), .clear(0), -- cgit v1.2.3 From beccd823da07b7c8b8d95b4688c6e05732f66165 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 15 Apr 2010 17:55:22 -0700 Subject: async seems to work with packet lengths now. Still need to do wishbone regs for gpmc --- usrp2/gpmc/fifo_to_gpmc_async.v | 9 +------- usrp2/gpmc/fifo_watcher.v | 38 +++++++++++++++++++++++++++------- usrp2/gpmc/gpmc_async.v | 10 ++++----- usrp2/models/gpmc_model_async.v | 46 ++++++++++++++++++++++++++++++----------- usrp2/top/u1e/Makefile | 6 +++--- 5 files changed, 72 insertions(+), 37 deletions(-) diff --git a/usrp2/gpmc/fifo_to_gpmc_async.v b/usrp2/gpmc/fifo_to_gpmc_async.v index 4f253e1b5..5ac8b19bd 100644 --- a/usrp2/gpmc/fifo_to_gpmc_async.v +++ b/usrp2/gpmc/fifo_to_gpmc_async.v @@ -8,7 +8,7 @@ module fifo_to_gpmc_async (input clk, input reset, input clear, input [17:0] data_i, input src_rdy_i, output dst_rdy_o, output [15:0] EM_D, input EM_NCS, input EM_NOE, - input [15:0] frame_len, output reg bus_error); + input [15:0] frame_len); // Synchronize the async control signals reg [1:0] cs_del, oe_del; @@ -35,11 +35,4 @@ module fifo_to_gpmc_async assign dst_rdy_o = do_read; - always @(posedge clk) - if(reset) - bus_error <= 0; - else if(dst_rdy_o & ~src_rdy_i) - bus_error <= 1; - - endmodule // fifo_to_gpmc_async diff --git a/usrp2/gpmc/fifo_watcher.v b/usrp2/gpmc/fifo_watcher.v index 8b8f1abfb..da2051b04 100644 --- a/usrp2/gpmc/fifo_watcher.v +++ b/usrp2/gpmc/fifo_watcher.v @@ -2,25 +2,47 @@ module fifo_watcher (input clk, input reset, input clear, - input src_rdy, input dst_rdy, input sof, input eof, - output have_packet, output [15:0] length, input next); + input src_rdy1, input dst_rdy1, input sof1, input eof1, + input src_rdy2, input dst_rdy2, input sof2, input eof2, + output have_packet, output [15:0] length, output reg bus_error); - wire write = src_rdy & dst_rdy & eof; + wire write = src_rdy1 & dst_rdy1 & eof1; + wire read = src_rdy2 & dst_rdy2 & eof2; + wire have_packet_int; + reg [15:0] counter; fifo_short #(.WIDTH(16)) frame_lengths (.clk(clk), .reset(reset), .clear(clear), .datain(counter), .src_rdy_i(write), .dst_rdy_o(), - .dataout(length), .src_rdy_o(have_packet), .dst_rdy_i(next) ); + .dataout(length), .src_rdy_o(have_packet_int), .dst_rdy_i(read) ); - reg [15:0] counter; always @(posedge clk) if(reset | clear) counter <= 1; // Start at 1 - else if(src_rdy & dst_rdy) - if(eof) + else if(src_rdy1 & dst_rdy1) + if(eof1) counter <= 1; else counter <= counter + 1; - + always @(posedge clk) + if(reset | clear) + bus_error <= 0; + else if(dst_rdy2 & ~src_rdy2) + bus_error <= 1; + else if(read & ~have_packet_int) + bus_error <= 1; + + reg in_packet; + assign have_packet = have_packet_int & ~in_packet; + + always @(posedge clk) + if(reset | clear) + in_packet <= 0; + else if(src_rdy2 & dst_rdy2) + if(eof2) + in_packet <= 0; + else + in_packet <= 1; + endmodule // fifo_watcher diff --git a/usrp2/gpmc/gpmc_async.v b/usrp2/gpmc/gpmc_async.v index c4cf0ef89..22e56cc89 100644 --- a/usrp2/gpmc/gpmc_async.v +++ b/usrp2/gpmc/gpmc_async.v @@ -67,7 +67,6 @@ module gpmc_async wire [17:0] rx18_data, rx18b_data; wire rx18_src_rdy, rx18_dst_rdy, rx18b_src_rdy, rx18b_dst_rdy; wire [15:0] rx_fifo_space, rx_frame_len; - assign rx_frame_len = tx_frame_len; fifo36_to_fifo18 f18_to_f36 (.clk(fifo_clk), .reset(fifo_rst), .clear(0), @@ -83,15 +82,14 @@ module gpmc_async (.clk(fifo_clk), .reset(fifo_rst), .clear(0), .data_i(rx18b_data), .src_rdy_i(rx18b_src_rdy), .dst_rdy_o(rx18b_dst_rdy), .EM_D(EM_D_fifo), .EM_NCS(EM_NCS4), .EM_NOE(EM_NOE), - .frame_len(rx_frame_len), .bus_error(bus_error_rx) ); + .frame_len(rx_frame_len) ); fifo_watcher fifo_watcher (.clk(fifo_clk), .reset(fifo_rst), .clear(0), - .src_rdy(rx18_src_rdy), .dst_rdy(rx18_dst_rdy), .sof(rx18_data[16]), .eof(rx18_data[17]), - .have_packet(), .length(), .next() ); + .src_rdy1(rx18_src_rdy), .dst_rdy1(rx18_dst_rdy), .sof1(rx18_data[16]), .eof1(rx18_data[17]), + .src_rdy2(rx18b_src_rdy), .dst_rdy2(rx18b_dst_rdy), .sof2(rx18b_data[16]), .eof2(rx18b_data[17]), + .have_packet(rx_have_data), .length(rx_frame_len), .bus_error(bus_error_rx) ); - assign rx_have_data = 0; - // //////////////////////////////////////////// // Control path on CS6 diff --git a/usrp2/models/gpmc_model_async.v b/usrp2/models/gpmc_model_async.v index 64b596284..beeaee028 100644 --- a/usrp2/models/gpmc_model_async.v +++ b/usrp2/models/gpmc_model_async.v @@ -78,28 +78,50 @@ module gpmc_model_async #1000000; GPMC_Read(1,36); #1000000; - GPMC_Write(0,36,16'h1234); - GPMC_Write(0,38,16'h5678); - GPMC_Write(0,40,16'h9abc); - GPMC_Write(0,11'h2F4,16'hF00D); - GPMC_Write(0,11'h7FE,16'hDEAD); - GPMC_Write(0,11'h7FE,16'hDEAD); - GPMC_Write(0,11'h7FE,16'hDEAD); - GPMC_Write(0,11'h7FE,16'hDEAD); - GPMC_Write(0,11'h7FE,16'hDEAD); - GPMC_Write(0,11'h7FE,16'hDEAD); - #100000; + GPMC_Write(0,0,16'h1234); + GPMC_Write(0,0,16'h5678); + GPMC_Write(0,0,16'h9abc); + GPMC_Write(0,0,16'hF00D); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + #1000000; + GPMC_Write(0,0,16'h1234); + GPMC_Write(0,0,16'h5678); + GPMC_Write(0,0,16'h9abc); + GPMC_Write(0,0,16'hF00D); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'h9876); + #1000000; + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); GPMC_Read(0,0); GPMC_Read(0,0); GPMC_Read(0,0); GPMC_Read(0,0); GPMC_Read(0,0); + #1000000; + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); GPMC_Read(0,0); GPMC_Read(0,0); GPMC_Read(0,0); GPMC_Read(0,0); GPMC_Read(0,0); - #100000; + GPMC_Read(0,0); + GPMC_Read(0,0); + #1000000; GPMC_Read(0,0); #100000000; $finish; diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index 160e67894..e15a49e10 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -176,12 +176,12 @@ timing/time_receiver.v \ timing/time_sender.v \ timing/time_sync.v \ timing/timer.v \ -gpmc/gpmc.v \ +gpmc/gpmc_async.v \ gpmc/edge_sync.v \ gpmc/dbsm.v \ gpmc/gpmc_to_fifo_async.v \ -gpmc/gpmc_to_fifo_sync.v \ -gpmc/fifo_to_gpmc_sync.v \ +gpmc/fifo_to_gpmc_async.v \ +gpmc/fifo_watcher.v \ gpmc/gpmc_wb.v \ top/u1e/u1e_core.v \ top/u1e/u1e.ucf \ -- cgit v1.2.3 From d94a0fbea165463a132006a15eb8548cde79a4d2 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 15 Apr 2010 18:55:20 -0700 Subject: access frame length regs from wishbone --- usrp2/gpmc/gpmc_async.v | 8 ++++---- usrp2/top/u1e/u1e_core.v | 20 ++++++++++++++------ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/usrp2/gpmc/gpmc_async.v b/usrp2/gpmc/gpmc_async.v index 22e56cc89..b1a545907 100644 --- a/usrp2/gpmc/gpmc_async.v +++ b/usrp2/gpmc/gpmc_async.v @@ -19,6 +19,8 @@ module gpmc_async output [35:0] tx_data_o, output tx_src_rdy_o, input tx_dst_rdy_i, input [35:0] rx_data_i, input rx_src_rdy_i, output rx_dst_rdy_o, + input [15:0] tx_frame_len, output [15:0] rx_frame_len, + output [31:0] debug ); @@ -40,9 +42,7 @@ module gpmc_async wire [17:0] tx18_data, tx18b_data; wire tx18_src_rdy, tx18_dst_rdy, tx18b_src_rdy, tx18b_dst_rdy; - wire [15:0] tx_fifo_space, tx_frame_len; - - assign tx_frame_len = 10; + wire [15:0] tx_fifo_space; gpmc_to_fifo_async gpmc_to_fifo_async (.EM_D(EM_D), .EM_NBE(EM_NBE), .EM_NCS(EM_NCS4), .EM_NWE(EM_NWE), @@ -66,7 +66,7 @@ module gpmc_async wire [17:0] rx18_data, rx18b_data; wire rx18_src_rdy, rx18_dst_rdy, rx18b_src_rdy, rx18b_dst_rdy; - wire [15:0] rx_fifo_space, rx_frame_len; + wire [15:0] rx_fifo_space; fifo36_to_fifo18 f18_to_f36 (.clk(fifo_clk), .reset(fifo_rst), .clear(0), diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 40950bf82..30396de3a 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -34,6 +34,8 @@ module u1e_core wire [35:0] tx_data, rx_data; wire tx_src_rdy, tx_dst_rdy, rx_src_rdy, rx_dst_rdy; + reg [15:0] tx_frame_len; + wire [15:0] rx_frame_len; gpmc_async gpmc (.arst(wb_rst), .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), @@ -51,7 +53,8 @@ module u1e_core .fifo_clk(wb_clk), .fifo_rst(wb_rst), .tx_data_o(tx_data), .tx_src_rdy_o(tx_src_rdy), .tx_dst_rdy_i(tx_dst_rdy), .rx_data_i(rx_data), .rx_src_rdy_i(rx_src_rdy), .rx_dst_rdy_o(rx_dst_rdy), - + + .tx_frame_len(tx_frame_len), .rx_frame_len(rx_frame_len), .debug(debug_gpmc)); fifo_cascade #(.WIDTH(36), .SIZE(9)) loopback_fifo @@ -133,11 +136,13 @@ module u1e_core reg [15:0] reg_leds, reg_cgen_ctrl, reg_test; - localparam REG_LEDS = 7'd0; // out - localparam REG_SWITCHES = 7'd2; // in - localparam REG_CGEN_CTRL = 7'd4; // out - localparam REG_CGEN_ST = 7'd6; // in - localparam REG_TEST = 7'd8; // out + localparam REG_LEDS = 7'd0; // out + localparam REG_SWITCHES = 7'd2; // in + localparam REG_CGEN_CTRL = 7'd4; // out + localparam REG_CGEN_ST = 7'd6; // in + localparam REG_TEST = 7'd8; // out + localparam REG_RX_FRAMELEN = 7'd10; // out + localparam REG_TX_FRAMELEN = 7'd12; // in always @(posedge wb_clk) if(wb_rst) @@ -155,6 +160,8 @@ module u1e_core reg_cgen_ctrl <= s0_dat_mosi; REG_TEST : reg_test <= s0_dat_mosi; + REG_TX_FRAMELEN : + tx_frame_len <= s0_dat_mosi; endcase // case (s0_adr[6:0]) assign { debug_led[2],debug_led[0],debug_led[1] } = reg_leds; // LEDs are arranged funny on board @@ -166,6 +173,7 @@ module u1e_core (s0_adr[6:0] == REG_CGEN_CTRL) ? reg_cgen_ctrl : (s0_adr[6:0] == REG_CGEN_ST) ? {13'b0,cgen_st_status,cgen_st_ld,cgen_st_refmon} : (s0_adr[6:0] == REG_TEST) ? reg_test : + (s0_adr[6:0] == REG_RX_FRAMELEN) ? rx_frame_len : 16'hBEEF; assign s0_ack = s0_stb & s0_cyc; -- cgit v1.2.3 From 23316f1ac73c917757a70980c3a9f251852ee426 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 15 Apr 2010 21:27:03 -0700 Subject: added pps and time capability --- usrp2/top/u1e/u1e.ucf | 2 +- usrp2/top/u1e/u1e.v | 6 ++++-- usrp2/top/u1e/u1e_core.v | 18 ++++++++++++++++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/usrp2/top/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf index c39759d0b..1c8dfc197 100644 --- a/usrp2/top/u1e/u1e.ucf +++ b/usrp2/top/u1e/u1e.ucf @@ -208,7 +208,7 @@ NET "dip_sw<0>" LOC = "J7" ; #NET "TXSYNC" LOC = "U18" ; #NET "TXBLANK" LOC = "U19" ; -#NET "PPS_IN" LOC = "M17" ; +NET "PPS_IN" LOC = "M17" ; NET "io_tx<0>" LOC = "AB20" ; NET "io_tx<1>" LOC = "Y17" ; diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index ab270879c..b8f716d26 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -20,7 +20,8 @@ module u1e input cgen_st_status, input cgen_st_ld, input cgen_st_refmon, output cgen_sync_b, output cgen_ref_sel, output overo_gpio144, output overo_gpio145, output overo_gpio146, output overo_gpio147, // Fifo controls - inout [15:0] io_tx, inout [15:0] io_rx + inout [15:0] io_tx, inout [15:0] io_rx, + input PPS_IN ); // FPGA-specific pins connections @@ -50,6 +51,7 @@ module u1e .cgen_sync_b(cgen_sync_b), .cgen_ref_sel(cgen_ref_sel), .tx_have_space(overo_gpio144), .tx_underrun(overo_gpio145), .rx_have_data(overo_gpio146), .rx_overrun(overo_gpio147), - .io_tx(io_tx), .io_rx(io_rx) ); + .io_tx(io_tx), .io_rx(io_rx), + .pps_in(PPS_IN) ); endmodule // u1e diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 30396de3a..9e65faeed 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -13,7 +13,9 @@ module u1e_core input cgen_st_status, input cgen_st_ld, input cgen_st_refmon, output cgen_sync_b, output cgen_ref_sel, output tx_have_space, output tx_underrun, output rx_have_data, output rx_overrun, - inout [15:0] io_tx, inout [15:0] io_rx + inout [15:0] io_tx, inout [15:0] io_rx, + + input pps_in ); wire wb_clk = clk_fpga; @@ -249,7 +251,19 @@ module u1e_core (.clk_i(wb_clk), .rst_i(wb_rst), .adr_i(s6_adr), .sel_i(s6_sel), .dat_i(s6_dat_mosi), .dat_o(s6_dat_miso), .we_i(s6_we), .stb_i(s6_stb), .cyc_i(s6_cyc), .ack_o(s6_ack), - .run_rx(), .run_tx(), .master_time(0), .ctrl_lines(atr_lines)); + .run_rx(0), .run_tx(0), .ctrl_lines(atr_lines)); + + + // ///////////////////////////////////////////////////////////////////////// + // VITA Timing + + localparam SR_TIME64 = 0; + wire pps_int; + wire [63:0] vita_time; + + time_64bit #(.TICKS_PER_SEC(32'd64000000),.BASE(SR_TIME64)) time_64bit + (.clk(wb_clk), .rst(wb_rst), .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), + .pps(pps_in), .vita_time(vita_time), .pps_int(pps_int)); // ///////////////////////////////////////////////////////////////////////////////////// // Debug circuitry -- cgit v1.2.3 From 21ceee337d61ccb2f31edaefd5c7418e8025b4b1 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 20 Apr 2010 10:51:23 -0700 Subject: find time_64bit --- usrp2/top/u1e/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index e15a49e10..5f712b046 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -176,6 +176,7 @@ timing/time_receiver.v \ timing/time_sender.v \ timing/time_sync.v \ timing/timer.v \ +timing/time_64bit.v \ gpmc/gpmc_async.v \ gpmc/edge_sync.v \ gpmc/dbsm.v \ -- cgit v1.2.3 From 5de2543e9cee644009d9ec15c19c70986df89594 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Fri, 23 Apr 2010 14:43:29 -0700 Subject: Register outputs to omap to prevent runt pulses from falsely triggering interrupts --- usrp2/gpmc/fifo_watcher.v | 8 ++++++-- usrp2/gpmc/gpmc_async.v | 9 +++++++-- usrp2/gpmc/gpmc_to_fifo_async.v | 10 +++++++--- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/usrp2/gpmc/fifo_watcher.v b/usrp2/gpmc/fifo_watcher.v index da2051b04..7a3f00483 100644 --- a/usrp2/gpmc/fifo_watcher.v +++ b/usrp2/gpmc/fifo_watcher.v @@ -4,7 +4,7 @@ module fifo_watcher (input clk, input reset, input clear, input src_rdy1, input dst_rdy1, input sof1, input eof1, input src_rdy2, input dst_rdy2, input sof2, input eof2, - output have_packet, output [15:0] length, output reg bus_error); + output reg have_packet, output [15:0] length, output reg bus_error); wire write = src_rdy1 & dst_rdy1 & eof1; wire read = src_rdy2 & dst_rdy2 & eof2; @@ -34,7 +34,11 @@ module fifo_watcher bus_error <= 1; reg in_packet; - assign have_packet = have_packet_int & ~in_packet; + always @(posedge clk) + if(reset | clear) + have_packet <= 0; + else + have_packet <= have_packet_int & ~in_packet; always @(posedge clk) if(reset | clear) diff --git a/usrp2/gpmc/gpmc_async.v b/usrp2/gpmc/gpmc_async.v index b1a545907..02a00ce57 100644 --- a/usrp2/gpmc/gpmc_async.v +++ b/usrp2/gpmc/gpmc_async.v @@ -7,7 +7,7 @@ module gpmc_async input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, // GPIOs for FIFO signalling - output rx_have_data, output tx_have_space, output bus_error, input bus_reset, + output rx_have_data, output tx_have_space, output reg bus_error, input bus_reset, // Wishbone signals input wb_clk, input wb_rst, @@ -31,7 +31,12 @@ module gpmc_async assign EM_D = ~EM_output_enable ? 16'bz : ~EM_NCS4 ? EM_D_fifo : EM_D_wb; wire bus_error_tx, bus_error_rx; - assign bus_error = bus_error_tx | bus_error_rx; + + always @(posedge fifo_clk) + if(fifo_rst) + bus_error <= 0; + else + bus_error <= bus_error_tx | bus_error_rx; // CS4 is RAM_2PORT for DATA PATH (high-speed data) // Writes go into one RAM, reads come from the other diff --git a/usrp2/gpmc/gpmc_to_fifo_async.v b/usrp2/gpmc/gpmc_to_fifo_async.v index 1df93f910..38f1165fc 100644 --- a/usrp2/gpmc/gpmc_to_fifo_async.v +++ b/usrp2/gpmc/gpmc_to_fifo_async.v @@ -5,10 +5,10 @@ module gpmc_to_fifo_async input fifo_clk, input fifo_rst, output reg [17:0] data_o, output reg src_rdy_o, input dst_rdy_i, - input [15:0] frame_len, input [15:0] fifo_space, output fifo_ready, + input [15:0] frame_len, input [15:0] fifo_space, output reg fifo_ready, output reg bus_error ); - reg [10:0] counter; + reg [15:0] counter; // Synchronize the async control signals reg [1:0] cs_del, we_del; always @(posedge fifo_clk) @@ -53,7 +53,11 @@ module gpmc_to_fifo_async else counter <= counter + 1; - assign fifo_ready = first_write & (fifo_space > frame_len); + always @(posedge fifo_clk) + if(fifo_rst) + fifo_ready <= 0; + else + fifo_ready <= first_write & (fifo_space > frame_len); always @(posedge fifo_clk) if(fifo_rst) -- cgit v1.2.3 From aeed16ec6e220f99df41534febe85336e5b384e6 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Fri, 23 Apr 2010 18:06:28 -0700 Subject: Only allow new packets if we can fit the largest possible packet (2KB) --- usrp2/gpmc/gpmc_to_fifo_async.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usrp2/gpmc/gpmc_to_fifo_async.v b/usrp2/gpmc/gpmc_to_fifo_async.v index 38f1165fc..6232244d4 100644 --- a/usrp2/gpmc/gpmc_to_fifo_async.v +++ b/usrp2/gpmc/gpmc_to_fifo_async.v @@ -57,7 +57,7 @@ module gpmc_to_fifo_async if(fifo_rst) fifo_ready <= 0; else - fifo_ready <= first_write & (fifo_space > frame_len); + fifo_ready <= first_write & (fifo_space > 16'd1023); always @(posedge fifo_clk) if(fifo_rst) -- cgit v1.2.3 From ae4b885e3533a73f0781e2fdb892f5d505081240 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Sat, 24 Apr 2010 22:58:06 -0700 Subject: Pass previously unused GPIOs to debug pins to help debug interrupts --- usrp2/top/u1e/u1e.ucf | 24 ++++++++++++------------ usrp2/top/u1e/u1e.v | 7 +++++++ usrp2/top/u1e/u1e_core.v | 6 ++---- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/usrp2/top/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf index 1c8dfc197..9c42b00ac 100644 --- a/usrp2/top/u1e/u1e.ucf +++ b/usrp2/top/u1e/u1e.ucf @@ -47,22 +47,22 @@ NET "EM_NOE" LOC = "A14" ; #NET "EM_NWP" LOC = "F13" ; ## Overo GPIO -#NET "overo_gpio0" LOC = "F9" ; -#NET "overo_gpio14" LOC = "C4" ; -#NET "overo_gpio21" LOC = "D5" ; -#NET "overo_gpio22" LOC = "A3" ; -#NET "overo_gpio23" LOC = "B3" ; -#NET "overo_gpio64" LOC = "A4" ; -#NET "overo_gpio65" LOC = "F8" ; -#NET "overo_gpio127" LOC = "C8" ; -#NET "overo_gpio128" LOC = "G8" ; +NET "overo_gpio0" LOC = "F9" ; # MISC GPIO for debug +NET "overo_gpio14" LOC = "C4" ; # MISC GPIO for debug +NET "overo_gpio21" LOC = "D5" ; # MISC GPIO for debug +NET "overo_gpio22" LOC = "A3" ; # MISC GPIO for debug +NET "overo_gpio23" LOC = "B3" ; # MISC GPIO for debug +NET "overo_gpio64" LOC = "A4" ; # MISC GPIO for debug +NET "overo_gpio65" LOC = "F8" ; # MISC GPIO for debug +NET "overo_gpio127" LOC = "C8" ; # MISC GPIO for debug +NET "overo_gpio128" LOC = "G8" ; # MISC GPIO for debug NET "overo_gpio144" LOC = "A5" ; # tx_have_space NET "overo_gpio145" LOC = "C7" ; # tx_underrun NET "overo_gpio146" LOC = "A6" ; # rx_have_data NET "overo_gpio147" LOC = "B6" ; # rx_overrun -#NET "overo_gpio163" LOC = "D7" ; -#NET "overo_gpio170" LOC = "E8" ; -#NET "overo_gpio176" LOC = "B4" ; +NET "overo_gpio163" LOC = "D7" ; # MISC GPIO for debug +NET "overo_gpio170" LOC = "E8" ; # MISC GPIO for debug +NET "overo_gpio176" LOC = "B4" ; # MISC GPIO for debug ## Overo UART #NET "overo_txd1" LOC = "C6" ; diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index b8f716d26..2ed6b71c8 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -20,6 +20,10 @@ module u1e input cgen_st_status, input cgen_st_ld, input cgen_st_refmon, output cgen_sync_b, output cgen_ref_sel, output overo_gpio144, output overo_gpio145, output overo_gpio146, output overo_gpio147, // Fifo controls + input overo_gpio0, input overo_gpio14, input overo_gpio21, input overo_gpio22, // Misc GPIO + input overo_gpio23, input overo_gpio64, input overo_gpio65, input overo_gpio127, // Misc GPIO + input overo_gpio128, input overo_gpio163, input overo_gpio170, input overo_gpio176, // Misc GPIO + inout [15:0] io_tx, inout [15:0] io_rx, input PPS_IN ); @@ -52,6 +56,9 @@ module u1e .tx_have_space(overo_gpio144), .tx_underrun(overo_gpio145), .rx_have_data(overo_gpio146), .rx_overrun(overo_gpio147), .io_tx(io_tx), .io_rx(io_rx), + .misc_gpio( {{overo_gpio128,overo_gpio163,overo_gpio170,overo_gpio176}, + {overo_gpio0,overo_gpio14,overo_gpio21,overo_gpio22}, + {overo_gpio23,overo_gpio64,overo_gpio65,overo_gpio127}}), .pps_in(PPS_IN) ); endmodule // u1e diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 9e65faeed..e67b1b158 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -13,9 +13,7 @@ module u1e_core input cgen_st_status, input cgen_st_ld, input cgen_st_refmon, output cgen_sync_b, output cgen_ref_sel, output tx_have_space, output tx_underrun, output rx_have_data, output rx_overrun, - inout [15:0] io_tx, inout [15:0] io_rx, - - input pps_in + inout [15:0] io_tx, inout [15:0] io_rx, input [11:0] misc_gpio, input pps_in ); wire wb_clk = clk_fpga; @@ -273,6 +271,6 @@ module u1e_core { EM_D } }; assign debug_gpio_0 = { debug_gpmc }; - assign debug_gpio_1 = { debug_txd, debug_rxd }; + assign debug_gpio_1 = { misc_gpio }; endmodule // u1e_core -- cgit v1.2.3 From 97af4bd12673fbb8d68dd087690dabb3e9488c4d Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 26 Apr 2010 17:15:53 -0700 Subject: send bus error to debug pins --- usrp2/top/u1e/u1e_core.v | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index e67b1b158..f231791da 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -36,6 +36,8 @@ module u1e_core wire tx_src_rdy, tx_dst_rdy, rx_src_rdy, rx_dst_rdy; reg [15:0] tx_frame_len; wire [15:0] rx_frame_len; + + wire bus_error; gpmc_async gpmc (.arst(wb_rst), .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), @@ -43,7 +45,7 @@ module u1e_core .EM_NOE(EM_NOE), .rx_have_data(rx_have_data), .tx_have_space(tx_have_space), - .bus_error(), .bus_reset(0), + .bus_error(bus_error), .bus_reset(0), .wb_clk(wb_clk), .wb_rst(wb_rst), .wb_adr_o(m0_adr), .wb_dat_mosi(m0_dat_mosi), .wb_dat_miso(m0_dat_miso), @@ -271,6 +273,6 @@ module u1e_core { EM_D } }; assign debug_gpio_0 = { debug_gpmc }; - assign debug_gpio_1 = { misc_gpio }; + assign debug_gpio_1 = { bus_error, misc_gpio[11:0] }; endmodule // u1e_core -- cgit v1.2.3 From eb5bfb963459dbb3e51df49b5aa22fcbda1627d5 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 28 Apr 2010 17:03:14 -0700 Subject: separate timed tx and rx instead of loopback --- usrp2/top/u1e/u1e_core.v | 54 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index f231791da..d5a3ddf68 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -58,12 +58,48 @@ module u1e_core .tx_frame_len(tx_frame_len), .rx_frame_len(rx_frame_len), .debug(debug_gpmc)); - +/* fifo_cascade #(.WIDTH(36), .SIZE(9)) loopback_fifo (.clk(wb_clk), .reset(wb_rst), .clear(0), .datain(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy), .dataout(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); +*/ + wire tx_strobe, rx_strobe, tx_enable, rx_enable; + wire [7:0] rate; + wire tx_fifo_rdy, rx_fifo_rdy; + + cic_strober tx_strober (.clock(wb_clk), .reset(wb_rst), .enable(tx_enable), + .rate(rate), .strobe_fast(1), .strobe_slow(tx_strobe)); + + fifo_cascade #(.WIDTH(36), .SIZE(11)) tx_fifo + (.clk(wb_clk), .reset(wb_rst), .clear(0), + .datain(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy), + .dataout(), .src_rdy_o(tx_fifo_rdy), .dst_rdy_i(tx_strobe)); + + + reg [15:0] ctr; + wire [15:0] rx_pkt_len = 480; + wire rx_eof = (ctr == rx_pkt_len); + wire rx_sof = (ctr == 0); + + cic_strober rx_strober (.clock(wb_clk), .reset(wb_rst), .enable(rx_enable), + .rate(rate), .strobe_fast(1), .strobe_slow(rx_strobe)); + + fifo_cascade #(.WIDTH(36), .SIZE(11)) rx_fifo + (.clk(wb_clk), .reset(wb_rst), .clear(0), + .datain({2'b00,rx_eof,rx_sof,16'd0,ctr}), .src_rdy_i(rx_strobe), .dst_rdy_o(rx_fifo_rdy), + .dataout(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); + always @(posedge wb_clk) + if(wb_rst) + ctr <= 0; + else if(rx_strobe & rx_fifo_rdy) + if(ctr == rx_pkt_len) + ctr <= 0; + else + ctr <= ctr + 1; + + // ///////////////////////////////////////////////////////////////////////////////////// // Wishbone Intercon, single master wire [dw-1:0] s0_dat_mosi, s1_dat_mosi, s0_dat_miso, s1_dat_miso, s2_dat_mosi, s3_dat_mosi, s2_dat_miso, s3_dat_miso, @@ -136,7 +172,7 @@ module u1e_core // ///////////////////////////////////////////////////////////////////////////////////// // Slave 0, Misc LEDs, Switches, controls - reg [15:0] reg_leds, reg_cgen_ctrl, reg_test; + reg [15:0] reg_leds, reg_cgen_ctrl, reg_test, xfer_rate; localparam REG_LEDS = 7'd0; // out localparam REG_SWITCHES = 7'd2; // in @@ -145,6 +181,7 @@ module u1e_core localparam REG_TEST = 7'd8; // out localparam REG_RX_FRAMELEN = 7'd10; // out localparam REG_TX_FRAMELEN = 7'd12; // in + localparam REG_XFER_RATE = 7'd14; // in always @(posedge wb_clk) if(wb_rst) @@ -152,6 +189,8 @@ module u1e_core reg_leds <= 0; reg_cgen_ctrl <= 2'b11; reg_test <= 0; + tx_frame_len <= 0; + xfer_rate <= 0; end else if(s0_cyc & s0_stb & s0_we) @@ -164,7 +203,13 @@ module u1e_core reg_test <= s0_dat_mosi; REG_TX_FRAMELEN : tx_frame_len <= s0_dat_mosi; + REG_XFER_RATE : + xfer_rate <= s0_dat_mosi; endcase // case (s0_adr[6:0]) + + assign tx_enable = xfer_rate[15]; + assign rx_enable = xfer_rate[14]; + assign rate = xfer_rate[7:0]; assign { debug_led[2],debug_led[0],debug_led[1] } = reg_leds; // LEDs are arranged funny on board assign { cgen_sync_b, cgen_ref_sel } = reg_cgen_ctrl; @@ -273,6 +318,9 @@ module u1e_core { EM_D } }; assign debug_gpio_0 = { debug_gpmc }; - assign debug_gpio_1 = { bus_error, misc_gpio[11:0] }; + assign debug_gpio_1 = { {rx_enable, rx_strobe, rx_fifo_rdy, rx_strobe & ~rx_fifo_rdy}, + {tx_enable, tx_strobe, tx_fifo_rdy, tx_strobe & ~tx_fifo_rdy}, + {rx_sof, rx_eof, rx_src_rdy, rx_dst_rdy, rx_data[33:32],2'b0}, + {3'b0, bus_error, misc_gpio[11:0]} }; endmodule // u1e_core -- cgit v1.2.3 From b30cbe85e8537de6a94e481a57033b5e57a73e12 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 3 May 2010 12:34:45 -0700 Subject: have_space and have_packet now stay high even while busy, as long as there really is more data/space. This should allow bursting without having additional interrupts. Also lenghten RX FIFO --- usrp2/gpmc/fifo_watcher.v | 6 ++++-- usrp2/gpmc/gpmc_async.v | 2 +- usrp2/gpmc/gpmc_to_fifo_async.v | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/usrp2/gpmc/fifo_watcher.v b/usrp2/gpmc/fifo_watcher.v index 7a3f00483..4bba142b0 100644 --- a/usrp2/gpmc/fifo_watcher.v +++ b/usrp2/gpmc/fifo_watcher.v @@ -10,11 +10,13 @@ module fifo_watcher wire read = src_rdy2 & dst_rdy2 & eof2; wire have_packet_int; reg [15:0] counter; + wire [4:0] pkt_count; fifo_short #(.WIDTH(16)) frame_lengths (.clk(clk), .reset(reset), .clear(clear), .datain(counter), .src_rdy_i(write), .dst_rdy_o(), - .dataout(length), .src_rdy_o(have_packet_int), .dst_rdy_i(read) ); + .dataout(length), .src_rdy_o(have_packet_int), .dst_rdy_i(read), + .occupied(pkt_count), .space()); always @(posedge clk) if(reset | clear) @@ -38,7 +40,7 @@ module fifo_watcher if(reset | clear) have_packet <= 0; else - have_packet <= have_packet_int & ~in_packet; + have_packet <= (have_packet_int & ~in_packet) | (pkt_count>1) ; always @(posedge clk) if(reset | clear) diff --git a/usrp2/gpmc/gpmc_async.v b/usrp2/gpmc/gpmc_async.v index 02a00ce57..dd06478b3 100644 --- a/usrp2/gpmc/gpmc_async.v +++ b/usrp2/gpmc/gpmc_async.v @@ -78,7 +78,7 @@ module gpmc_async .f36_datain(rx_data_i), .f36_src_rdy_i(rx_src_rdy_i), .f36_dst_rdy_o(rx_dst_rdy_o), .f18_dataout(rx18_data), .f18_src_rdy_o(rx18_src_rdy), .f18_dst_rdy_i(rx18_dst_rdy) ); - fifo_cascade #(.WIDTH(18), .SIZE(10)) rx_fifo + fifo_cascade #(.WIDTH(18), .SIZE(12)) rx_fifo (.clk(fifo_clk), .reset(fifo_rst), .clear(0), .datain(rx18_data), .src_rdy_i(rx18_src_rdy), .dst_rdy_o(rx18_dst_rdy), .space(rx_fifo_space), .dataout(rx18b_data), .src_rdy_o(rx18b_src_rdy), .dst_rdy_i(rx18b_dst_rdy), .occupied()); diff --git a/usrp2/gpmc/gpmc_to_fifo_async.v b/usrp2/gpmc/gpmc_to_fifo_async.v index 6232244d4..3d29745a2 100644 --- a/usrp2/gpmc/gpmc_to_fifo_async.v +++ b/usrp2/gpmc/gpmc_to_fifo_async.v @@ -57,7 +57,7 @@ module gpmc_to_fifo_async if(fifo_rst) fifo_ready <= 0; else - fifo_ready <= first_write & (fifo_space > 16'd1023); + fifo_ready <= /* first_write & */ (fifo_space > 16'd1023); always @(posedge fifo_clk) if(fifo_rst) -- cgit v1.2.3 From c4698bb0a42b60dea924a83d18b27131a15958a2 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 4 May 2010 09:44:28 -0700 Subject: changed comment --- usrp2/top/u1e/u1e.ucf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usrp2/top/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf index 9c42b00ac..055a1ef17 100644 --- a/usrp2/top/u1e/u1e.ucf +++ b/usrp2/top/u1e/u1e.ucf @@ -254,7 +254,7 @@ NET "io_rx<15>" LOC = "Y4" ; #NET "fpga_cfg_cclk" LOC = "V17" ; #NET "fpga_cfg_init_b" LOC = "W15" ; -## Unnamed, need to figure out what they do +## Unused #NET "unnamed_net37" LOC = "B1" ; # TMS #NET "unnamed_net36" LOC = "B22" ; # TDO #NET "unnamed_net35" LOC = "D2" ; # TDI -- cgit v1.2.3 From 031becd1f05f0fbcab6a4f2be353292cd667a88f Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 4 May 2010 12:30:56 -0700 Subject: add timing constraints. Just have main clock signal at 64 MHz for now. --- usrp2/top/u1e/Makefile | 1 + usrp2/top/u1e/timing.ucf | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 usrp2/top/u1e/timing.ucf diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index 5f712b046..2aebb33f9 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -186,6 +186,7 @@ gpmc/fifo_watcher.v \ gpmc/gpmc_wb.v \ top/u1e/u1e_core.v \ top/u1e/u1e.ucf \ +top/u1e/timing.ucf \ top/u1e/u1e.v ################################################## diff --git a/usrp2/top/u1e/timing.ucf b/usrp2/top/u1e/timing.ucf new file mode 100644 index 000000000..8df28c9d3 --- /dev/null +++ b/usrp2/top/u1e/timing.ucf @@ -0,0 +1,13 @@ + +NET "CLK_FPGA_P" TNM_NET = "CLK_FPGA_P"; +TIMESPEC "TS_clk_fpga_p" = PERIOD "CLK_FPGA_P" 15625 ps HIGH 50 %; + + + + +#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; -- cgit v1.2.3 From 2ddaba2d8bdcdda07b949f007d2555cf57c7c8d7 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 4 May 2010 15:06:03 -0700 Subject: added DAC output pins, and a sine wave generator to test them --- usrp2/top/u1e/u1e.ucf | 32 ++++++++++++++++---------------- usrp2/top/u1e/u1e.v | 4 ++++ usrp2/top/u1e/u1e_core.v | 45 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 63 insertions(+), 18 deletions(-) diff --git a/usrp2/top/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf index 055a1ef17..a73ebceb8 100644 --- a/usrp2/top/u1e/u1e.ucf +++ b/usrp2/top/u1e/u1e.ucf @@ -191,22 +191,22 @@ NET "dip_sw<0>" LOC = "J7" ; #NET "DA<1>" LOC = "P22" ; #NET "DA<0>" LOC = "N17" ; -#NET "TX<13>" LOC = "P19" ; -#NET "TX<12>" LOC = "R18" ; -#NET "TX<11>" LOC = "U20" ; -#NET "TX<10>" LOC = "T20" ; -#NET "TX<9>" LOC = "R19" ; -#NET "TX<8>" LOC = "R20" ; -#NET "TX<7>" LOC = "W22" ; -#NET "TX<6>" LOC = "Y22" ; -#NET "TX<5>" LOC = "T18" ; -#NET "TX<4>" LOC = "T17" ; -#NET "TX<3>" LOC = "W19" ; -#NET "TX<2>" LOC = "V20" ; -#NET "TX<1>" LOC = "Y21" ; -#NET "TX<0>" LOC = "AA22" ; -#NET "TXSYNC" LOC = "U18" ; -#NET "TXBLANK" LOC = "U19" ; +NET "TX<13>" LOC = "P19" ; +NET "TX<12>" LOC = "R18" ; +NET "TX<11>" LOC = "U20" ; +NET "TX<10>" LOC = "T20" ; +NET "TX<9>" LOC = "R19" ; +NET "TX<8>" LOC = "R20" ; +NET "TX<7>" LOC = "W22" ; +NET "TX<6>" LOC = "Y22" ; +NET "TX<5>" LOC = "T18" ; +NET "TX<4>" LOC = "T17" ; +NET "TX<3>" LOC = "W19" ; +NET "TX<2>" LOC = "V20" ; +NET "TX<1>" LOC = "Y21" ; +NET "TX<0>" LOC = "AA22" ; +NET "TXSYNC" LOC = "U18" ; +NET "TXBLANK" LOC = "U19" ; NET "PPS_IN" LOC = "M17" ; diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index 2ed6b71c8..35818e8c8 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -25,6 +25,9 @@ module u1e input overo_gpio128, input overo_gpio163, input overo_gpio170, input overo_gpio176, // Misc GPIO inout [15:0] io_tx, inout [15:0] io_rx, + + output [13:0] TX, output TXSYNC, output TXBLANK, + input PPS_IN ); @@ -56,6 +59,7 @@ module u1e .tx_have_space(overo_gpio144), .tx_underrun(overo_gpio145), .rx_have_data(overo_gpio146), .rx_overrun(overo_gpio147), .io_tx(io_tx), .io_rx(io_rx), + .tx(TX), .txsync(TXSYNC), .txblank(TXBLANK), .misc_gpio( {{overo_gpio128,overo_gpio163,overo_gpio170,overo_gpio176}, {overo_gpio0,overo_gpio14,overo_gpio21,overo_gpio22}, {overo_gpio23,overo_gpio64,overo_gpio65,overo_gpio127}}), diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index d5a3ddf68..74ffc4657 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -13,7 +13,10 @@ module u1e_core input cgen_st_status, input cgen_st_ld, input cgen_st_refmon, output cgen_sync_b, output cgen_ref_sel, output tx_have_space, output tx_underrun, output rx_have_data, output rx_overrun, - inout [15:0] io_tx, inout [15:0] io_rx, input [11:0] misc_gpio, input pps_in + inout [15:0] io_tx, inout [15:0] io_rx, + output reg [13:0] tx, output reg txsync, output txblank, + + input [11:0] misc_gpio, input pps_in ); wire wb_clk = clk_fpga; @@ -213,7 +216,7 @@ module u1e_core assign { debug_led[2],debug_led[0],debug_led[1] } = reg_leds; // LEDs are arranged funny on board assign { cgen_sync_b, cgen_ref_sel } = reg_cgen_ctrl; - assign { rx_overrun, tx_underrun } = reg_test; + assign { rx_overrun, tx_underrun } = 0; // reg_test; assign s0_dat_miso = (s0_adr[6:0] == REG_LEDS) ? reg_leds : (s0_adr[6:0] == REG_SWITCHES) ? {5'b0,debug_pb[2:0],dip_sw[7:0]} : @@ -309,6 +312,44 @@ module u1e_core time_64bit #(.TICKS_PER_SEC(32'd64000000),.BASE(SR_TIME64)) time_64bit (.clk(wb_clk), .rst(wb_rst), .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), .pps(pps_in), .vita_time(vita_time), .pps_int(pps_int)); + + + // ///////////////////////////////////////////////////////////////////////// + // TX + + assign txblank = 0; + + wire [23:0] freq = {reg_test,8'd0}; + + reg [23:0] tx_q_hold; + wire [23:0] tx_i, tx_q; + + reg tx_stb; + always @(posedge wb_clk) + tx_stb <= ~tx_stb; + + always @(posedge wb_clk) + if(tx_stb) + tx <= tx_i[23:10]; + else + tx <= tx_q_hold[23:10]; + + always @(posedge wb_clk) + if(tx_stb) + tx_q_hold <= tx_q; + + always @(posedge wb_clk) + txsync <= ~tx_stb; // TX Sync low indicates first data item + // We invert here if we don't use inv_txsync in the 9862 + + reg [23:0] phase; + always @(posedge wb_clk) + if(tx_stb) + phase <= phase + freq; + + cordic_z24 #(.bitwidth(24)) tx_cordic + (.clock(wb_clk), .reset(wb_rst), .enable(1), + .xi(24'd15000), .yi(24'd0), .zi(phase), .xo(tx_i), .yo(tx_q), .zo()); // ///////////////////////////////////////////////////////////////////////////////////// // Debug circuitry -- cgit v1.2.3 From 45d92a0610582672cea4f1d97d116af00eac7bef Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Fri, 7 May 2010 10:27:33 -0700 Subject: SPI passthru for programming clock gen chip on brand new boards --- usrp2/top/u1e_passthru/Makefile | 107 +++++++++++++++ usrp2/top/u1e_passthru/passthru.ucf | 266 ++++++++++++++++++++++++++++++++++++ usrp2/top/u1e_passthru/passthru.v | 18 +++ 3 files changed, 391 insertions(+) create mode 100644 usrp2/top/u1e_passthru/Makefile create mode 100644 usrp2/top/u1e_passthru/passthru.ucf create mode 100644 usrp2/top/u1e_passthru/passthru.v diff --git a/usrp2/top/u1e_passthru/Makefile b/usrp2/top/u1e_passthru/Makefile new file mode 100644 index 000000000..62923f87f --- /dev/null +++ b/usrp2/top/u1e_passthru/Makefile @@ -0,0 +1,107 @@ +# +# Copyright 2008 Ettus Research LLC +# + +################################################## +# 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 := passthru +export PROJ_FILE := $(BUILD_DIR)$(TOP_MODULE).ise + +################################################## +# Project Properties +################################################## +export PROJECT_PROPERTIES := \ +family "Spartan-3A DSP" \ +device xc3sd1800a \ +package cs484 \ +speed -4 \ +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 := \ +top/u1e_passthru/passthru.ucf \ +top/u1e_passthru/passthru.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 \ +"Unused IOB Pins" "Pull Up" + +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/u1e_passthru/passthru.ucf b/usrp2/top/u1e_passthru/passthru.ucf new file mode 100644 index 000000000..1672132a2 --- /dev/null +++ b/usrp2/top/u1e_passthru/passthru.ucf @@ -0,0 +1,266 @@ + +#NET "CLK_FPGA_P" LOC = "Y11" ; +#NET "CLK_FPGA_N" LOC = "Y10" ; + +## GPMC +#NET "EM_D<15>" LOC = "D13" ; +#NET "EM_D<14>" LOC = "D15" ; +#NET "EM_D<13>" LOC = "C16" ; +#NET "EM_D<12>" LOC = "B20" ; +#NET "EM_D<11>" LOC = "A19" ; +#NET "EM_D<10>" LOC = "A17" ; +#NET "EM_D<9>" LOC = "E15" ; +#NET "EM_D<8>" LOC = "F15" ; +#NET "EM_D<7>" LOC = "E16" ; +#NET "EM_D<6>" LOC = "F16" ; +#NET "EM_D<5>" LOC = "B17" ; +#NET "EM_D<4>" LOC = "C17" ; +#NET "EM_D<3>" LOC = "B19" ; +#NET "EM_D<2>" LOC = "D19" ; +#NET "EM_D<1>" LOC = "C19" ; +#NET "EM_D<0>" LOC = "A20" ; + +#NET "EM_A<10>" LOC = "C14" ; +#NET "EM_A<9>" LOC = "C10" ; +#NET "EM_A<8>" LOC = "C5" ; +#NET "EM_A<7>" LOC = "A18" ; +#NET "EM_A<6>" LOC = "A15" ; +#NET "EM_A<5>" LOC = "A12" ; +#NET "EM_A<4>" LOC = "A10" ; +#NET "EM_A<3>" LOC = "E7" ; +#NET "EM_A<2>" LOC = "A7" ; +#NET "EM_A<1>" LOC = "C15" ; + +#NET "EM_NCS6" LOC = "E17" ; +##NET "EM_NCS5" LOC = "E10" ; +#NET "EM_NCS4" LOC = "E6" ; +##NET "EM_NCS1" LOC = "D18" ; +##NET "EM_NCS0" LOC = "D17" ; + +#NET "EM_CLK" LOC = "F11" ; +#NET "EM_WAIT0" LOC = "F14" ; +#NET "EM_NBE<1>" LOC = "D14" ; +#NET "EM_NBE<0>" LOC = "A13" ; +#NET "EM_NWE" LOC = "B13" ; +#NET "EM_NOE" LOC = "A14" ; +##NET "EM_NADV_ALE" LOC = "B15" ; +##NET "EM_NWP" LOC = "F13" ; + +## Overo GPIO +NET "overo_gpio0" LOC = "F9" ; # MISC GPIO for debug +#NET "overo_gpio14" LOC = "C4" ; # MISC GPIO for debug +#NET "overo_gpio21" LOC = "D5" ; # MISC GPIO for debug +#NET "overo_gpio22" LOC = "A3" ; # MISC GPIO for debug +#NET "overo_gpio23" LOC = "B3" ; # MISC GPIO for debug +#NET "overo_gpio64" LOC = "A4" ; # MISC GPIO for debug +#NET "overo_gpio65" LOC = "F8" ; # MISC GPIO for debug +#NET "overo_gpio127" LOC = "C8" ; # MISC GPIO for debug +#NET "overo_gpio128" LOC = "G8" ; # MISC GPIO for debug +#NET "overo_gpio144" LOC = "A5" ; # tx_have_space +#NET "overo_gpio145" LOC = "C7" ; # tx_underrun +#NET "overo_gpio146" LOC = "A6" ; # rx_have_data +#NET "overo_gpio147" LOC = "B6" ; # rx_overrun +#NET "overo_gpio163" LOC = "D7" ; # MISC GPIO for debug +#NET "overo_gpio170" LOC = "E8" ; # MISC GPIO for debug +#NET "overo_gpio176" LOC = "B4" ; # MISC GPIO for debug + +## Overo UART +##NET "overo_txd1" LOC = "C6" ; +##NET "overo_rxd1" LOC = "D6" ; + +## FTDI UART to USB converter +#NET "FPGA_TXD" LOC = "U1" ; +#NET "FPGA_RXD" LOC = "T6" ; + +##NET "SYSEN" LOC = "C11" ; + +## I2C +#NET "db_scl" LOC = "U4" ; +#NET "db_sda" LOC = "U5" ; + +## SPI +### DBoard SPI +#NET "db_sclk_rx" LOC = "W3" ; +#NET "db_miso_rx" LOC = "W2" ; +#NET "db_mosi_rx" LOC = "V4" ; +#NET "db_sen_rx" LOC = "V3" ; +#NET "db_sclk_tx" LOC = "Y1" ; +#NET "db_miso_tx" LOC = "W1" ; +#NET "db_mosi_tx" LOC = "R3" ; +#NET "db_sen_tx" LOC = "T4" ; + +### AD9862 SPI and aux SPI Interfaces +##NET "aux_sdi_codec" LOC = "F19" ; +##NET "aux_sdo_codec" LOC = "F18" ; +##NET "aux_sclk_codec" LOC = "D21" ; +#NET "sen_codec" LOC = "D20" ; +#NET "mosi_codec" LOC = "E19" ; +#NET "miso_codec" LOC = "F21" ; +#NET "sclk_codec" LOC = "E20" ; + +### Clock Gen SPI +#NET "cgen_miso" LOC = "U2" ; +NET "cgen_mosi" LOC = "V1" ; +NET "cgen_sclk" LOC = "R5" ; +NET "cgen_sen_b" LOC = "T1" ; + +## Clock gen control +#NET "cgen_st_status" LOC = "D4" ; +#NET "cgen_st_ld" LOC = "D1" ; +#NET "cgen_st_refmon" LOC = "E1" ; +#NET "cgen_sync_b" LOC = "M1" ; +#NET "cgen_ref_sel" LOC = "J1" ; + +## Debug pins +#NET "debug_led<2>" LOC = "T5" ; +#NET "debug_led<1>" LOC = "R2" ; +#NET "debug_led<0>" LOC = "R1" ; +#NET "debug<0>" LOC = "P6" ; +#NET "debug<1>" LOC = "R6" ; +#NET "debug<2>" LOC = "P1" ; +#NET "debug<3>" LOC = "P2" ; +#NET "debug<4>" LOC = "N6" ; +#NET "debug<5>" LOC = "N5" ; +#NET "debug<6>" LOC = "N1" ; +#NET "debug<7>" LOC = "K2" ; +#NET "debug<8>" LOC = "K3" ; +#NET "debug<9>" LOC = "K6" ; +#NET "debug<10>" LOC = "L5" ; +#NET "debug<11>" LOC = "H2" ; +#NET "debug<12>" LOC = "K4" ; +#NET "debug<13>" LOC = "K5" ; +#NET "debug<14>" LOC = "G1" ; +#NET "debug<15>" LOC = "H1" ; +#NET "debug<16>" LOC = "H5" ; +#NET "debug<17>" LOC = "H6" ; +#NET "debug<18>" LOC = "E3" ; +#NET "debug<19>" LOC = "E4" ; +#NET "debug<20>" LOC = "G5" ; +#NET "debug<21>" LOC = "G6" ; +#NET "debug<22>" LOC = "F2" ; +#NET "debug<23>" LOC = "F1" ; +#NET "debug<24>" LOC = "H3" ; +#NET "debug<25>" LOC = "H4" ; +#NET "debug<26>" LOC = "F4" ; +#NET "debug<27>" LOC = "F5" ; +#NET "debug<28>" LOC = "C2" ; +#NET "debug<29>" LOC = "C1" ; +#NET "debug<30>" LOC = "F3" ; +#NET "debug<31>" LOC = "G3" ; +#NET "debug_clk<0>" LOC = "L6" ; +#NET "debug_clk<1>" LOC = "M5" ; + +#NET "debug_pb<2>" LOC = "Y2" ; +#NET "debug_pb<1>" LOC = "AA1" ; +#NET "debug_pb<0>" LOC = "N3" ; + +#NET "dip_sw<7>" LOC = "T3" ; +#NET "dip_sw<6>" LOC = "U3" ; +#NET "dip_sw<5>" LOC = "M3" ; +#NET "dip_sw<4>" LOC = "N4" ; +#NET "dip_sw<3>" LOC = "J3" ; +#NET "dip_sw<2>" LOC = "J4" ; +#NET "dip_sw<1>" LOC = "J6" ; +#NET "dip_sw<0>" LOC = "J7" ; + +##NET "RXSYNC" LOC = "F22" ; +##NET "reset_codec" LOC = "D22" ; + +##NET "DB<11>" LOC = "E22" ; +##NET "DB<10>" LOC = "J19" ; +##NET "DB<9>" LOC = "H20" ; +##NET "DB<8>" LOC = "G19" ; +##NET "DB<7>" LOC = "F20" ; +##NET "DB<6>" LOC = "K16" ; +##NET "DB<5>" LOC = "J17" ; +##NET "DB<4>" LOC = "H22" ; +##NET "DB<3>" LOC = "G22" ; +##NET "DB<2>" LOC = "H17" ; +##NET "DB<1>" LOC = "H18" ; +##NET "DB<0>" LOC = "K20" ; +##NET "DA<11>" LOC = "J20" ; +##NET "DA<10>" LOC = "K19" ; +##NET "DA<9>" LOC = "K18" ; +##NET "DA<8>" LOC = "L22" ; +##NET "DA<7>" LOC = "K22" ; +##NET "DA<6>" LOC = "N22" ; +##NET "DA<5>" LOC = "M22" ; +##NET "DA<4>" LOC = "N20" ; +##NET "DA<3>" LOC = "N19" ; +##NET "DA<2>" LOC = "R22" ; +##NET "DA<1>" LOC = "P22" ; +##NET "DA<0>" LOC = "N17" ; + +#NET "TX<13>" LOC = "P19" ; +#NET "TX<12>" LOC = "R18" ; +#NET "TX<11>" LOC = "U20" ; +#NET "TX<10>" LOC = "T20" ; +#NET "TX<9>" LOC = "R19" ; +#NET "TX<8>" LOC = "R20" ; +#NET "TX<7>" LOC = "W22" ; +#NET "TX<6>" LOC = "Y22" ; +#NET "TX<5>" LOC = "T18" ; +#NET "TX<4>" LOC = "T17" ; +#NET "TX<3>" LOC = "W19" ; +#NET "TX<2>" LOC = "V20" ; +#NET "TX<1>" LOC = "Y21" ; +#NET "TX<0>" LOC = "AA22" ; +#NET "TXSYNC" LOC = "U18" ; +#NET "TXBLANK" LOC = "U19" ; + +#NET "PPS_IN" LOC = "M17" ; + +#NET "io_tx<0>" LOC = "AB20" ; +#NET "io_tx<1>" LOC = "Y17" ; +#NET "io_tx<2>" LOC = "Y16" ; +#NET "io_tx<3>" LOC = "U16" ; +#NET "io_tx<4>" LOC = "V16" ; +#NET "io_tx<5>" LOC = "AB19" ; +#NET "io_tx<6>" LOC = "AA19" ; +#NET "io_tx<7>" LOC = "U14" ; +#NET "io_tx<8>" LOC = "U15" ; +#NET "io_tx<9>" LOC = "AB17" ; +#NET "io_tx<10>" LOC = "AB18" ; +#NET "io_tx<11>" LOC = "Y13" ; +#NET "io_tx<12>" LOC = "W14" ; +#NET "io_tx<13>" LOC = "U13" ; +#NET "io_tx<14>" LOC = "AA15" ; +#NET "io_tx<15>" LOC = "AB14" ; + +#NET "io_rx<0>" LOC = "Y8" ; +#NET "io_rx<1>" LOC = "Y9" ; +#NET "io_rx<2>" LOC = "V7" ; +#NET "io_rx<3>" LOC = "U8" ; +#NET "io_rx<4>" LOC = "V10" ; +#NET "io_rx<5>" LOC = "U9" ; +#NET "io_rx<6>" LOC = "AB7" ; +#NET "io_rx<7>" LOC = "AA8" ; +#NET "io_rx<8>" LOC = "W8" ; +#NET "io_rx<9>" LOC = "V8" ; +#NET "io_rx<10>" LOC = "AB5" ; +#NET "io_rx<11>" LOC = "AB6" ; +#NET "io_rx<12>" LOC = "AB4" ; +#NET "io_rx<13>" LOC = "AA4" ; +#NET "io_rx<14>" LOC = "W5" ; +#NET "io_rx<15>" LOC = "Y4" ; + +##NET "CLKOUT2_CODEC" LOC = "U12" ; +##NET "CLKOUT1_CODEC" LOC = "V12" ; + +## FPGA Config Pins +##NET "fpga_cfg_prog_b" LOC = "A2" ; +##NET "fpga_cfg_done" LOC = "AB21" ; +NET "fpga_cfg_din" LOC = "W17" ; +NET "fpga_cfg_cclk" LOC = "V17" ; +##NET "fpga_cfg_init_b" LOC = "W15" ; + +## Unused +##NET "unnamed_net37" LOC = "B1" ; # TMS +##NET "unnamed_net36" LOC = "B22" ; # TDO +##NET "unnamed_net35" LOC = "D2" ; # TDI +##NET "unnamed_net34" LOC = "A21" ; # TCK +##NET "unnamed_net45" LOC = "F7" ; # PUDC_B +##NET "unnamed_net44" LOC = "V6" ; # M2 +##NET "unnamed_net43" LOC = "AA3" ; # M1 +##NET "unnamed_net42" LOC = "AB3" ; # M0 +##NET "GND" LOC = "V19" ; # Suspend, unused diff --git a/usrp2/top/u1e_passthru/passthru.v b/usrp2/top/u1e_passthru/passthru.v new file mode 100644 index 000000000..459c226ee --- /dev/null +++ b/usrp2/top/u1e_passthru/passthru.v @@ -0,0 +1,18 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// + +module passthru + (input overo_gpio0, + output cgen_sclk, + output cgen_sen_b, + output cgen_mosi, + input fpga_cfg_din, + input fpga_cfg_cclk + ); + + assign cgen_sclk = fpga_cfg_cclk; + assign cgen_sen_b = overo_gpio0; + assign cgen_mosi = fpga_cfg_din; + + +endmodule // passthru -- cgit v1.2.3 From 4a573b5dcc78f9a13162efce09f0bc31f298a818 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 10 May 2010 13:23:48 -0700 Subject: proper signal level for 24 bit data --- usrp2/top/u1e/u1e_core.v | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 74ffc4657..a262184a8 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -349,15 +349,20 @@ module u1e_core cordic_z24 #(.bitwidth(24)) tx_cordic (.clock(wb_clk), .reset(wb_rst), .enable(1), - .xi(24'd15000), .yi(24'd0), .zi(phase), .xo(tx_i), .yo(tx_q), .zo()); + .xi(24'd2500000), .yi(24'd0), .zi(phase), .xo(tx_i), .yo(tx_q), .zo()); // ///////////////////////////////////////////////////////////////////////////////////// // Debug circuitry assign debug_clk = { EM_CLK, clk_fpga }; - assign debug = { { rx_have_data, tx_have_space, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, +/* + assign debug = { { rx_have_data, tx_have_space, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, { EM_D } }; +*/ + assign debug = { phase[23:8], txsync, txblank, tx }; + + assign debug_gpio_0 = { debug_gpmc }; assign debug_gpio_1 = { {rx_enable, rx_strobe, rx_fifo_rdy, rx_strobe & ~rx_fifo_rdy}, {tx_enable, tx_strobe, tx_fifo_rdy, tx_strobe & ~tx_fifo_rdy}, -- cgit v1.2.3 From 57114cf6579a0c6f8fc4626d4c20e8fc09cddb72 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 10 May 2010 14:56:14 -0700 Subject: switched passthru of cgen_sen_b to gpio127, made a note of it. No more safe_u1e necessary. --- usrp2/top/safe_u1e/.gitignore | 4 - usrp2/top/safe_u1e/Makefile | 246 --------------------------------- usrp2/top/safe_u1e/safe_u1e.ucf | 262 ------------------------------------ usrp2/top/safe_u1e/safe_u1e.v | 41 ------ usrp2/top/u1e/u1e.ucf | 2 +- usrp2/top/u1e_passthru/.gitignore | 1 + usrp2/top/u1e_passthru/passthru.ucf | 4 +- usrp2/top/u1e_passthru/passthru.v | 10 +- 8 files changed, 9 insertions(+), 561 deletions(-) delete mode 100644 usrp2/top/safe_u1e/.gitignore delete mode 100644 usrp2/top/safe_u1e/Makefile delete mode 100644 usrp2/top/safe_u1e/safe_u1e.ucf delete mode 100644 usrp2/top/safe_u1e/safe_u1e.v create mode 100644 usrp2/top/u1e_passthru/.gitignore diff --git a/usrp2/top/safe_u1e/.gitignore b/usrp2/top/safe_u1e/.gitignore deleted file mode 100644 index f8b57ea21..000000000 --- a/usrp2/top/safe_u1e/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*~ -build -*.log -*.cmd diff --git a/usrp2/top/safe_u1e/Makefile b/usrp2/top/safe_u1e/Makefile deleted file mode 100644 index d28cc2b89..000000000 --- a/usrp2/top/safe_u1e/Makefile +++ /dev/null @@ -1,246 +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 := safe_u1e -export PROJ_FILE := $(BUILD_DIR)$(TOP_MODULE).ise - -################################################## -# Project Properties -################################################## -export PROJECT_PROPERTIES := \ -family "Spartan-3A DSP" \ -device xc3sd1800a \ -package cs484 \ -speed -4 \ -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/dcache.v \ -control_lib/decoder_3_8.v \ -control_lib/dpram32.v \ -control_lib/gray2bin.v \ -control_lib/gray_send.v \ -control_lib/icache.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/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 \ -control_lib/reset_sync.v \ -simple_gemac/simple_gemac_wrapper.v \ -simple_gemac/simple_gemac.v \ -simple_gemac/simple_gemac_wb.v \ -simple_gemac/simple_gemac_tx.v \ -simple_gemac/simple_gemac_rx.v \ -simple_gemac/crc.v \ -simple_gemac/delay_line.v \ -simple_gemac/flow_ctrl_tx.v \ -simple_gemac/flow_ctrl_rx.v \ -simple_gemac/address_filter.v \ -simple_gemac/ll8_to_txmac.v \ -simple_gemac/rxmac_to_ll8.v \ -simple_gemac/miim/eth_miim.v \ -simple_gemac/miim/eth_clockgen.v \ -simple_gemac/miim/eth_outputcontrol.v \ -simple_gemac/miim/eth_shiftreg.v \ -control_lib/newfifo/buffer_int.v \ -control_lib/newfifo/buffer_pool.v \ -control_lib/newfifo/fifo_2clock.v \ -control_lib/newfifo/fifo_2clock_cascade.v \ -control_lib/newfifo/ll8_shortfifo.v \ -control_lib/newfifo/ll8_to_fifo36.v \ -control_lib/newfifo/fifo_short.v \ -control_lib/newfifo/fifo_long.v \ -control_lib/newfifo/fifo_cascade.v \ -control_lib/newfifo/fifo36_to_ll8.v \ -control_lib/longfifo.v \ -control_lib/shortfifo.v \ -control_lib/medfifo.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 \ -coregen/fifo_xlnx_64x36_2clk.v \ -coregen/fifo_xlnx_64x36_2clk.xco \ -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/safe_u1e/safe_u1e.ucf \ -top/safe_u1e/safe_u1e.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 \ -"Unused IOB Pins" "Pull Up" - -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/safe_u1e/safe_u1e.ucf b/usrp2/top/safe_u1e/safe_u1e.ucf deleted file mode 100644 index cb6d6372e..000000000 --- a/usrp2/top/safe_u1e/safe_u1e.ucf +++ /dev/null @@ -1,262 +0,0 @@ - -NET "CLK_FPGA_P" LOC = "Y11" ; -NET "CLK_FPGA_N" LOC = "Y10" ; - -## GPMC -NET "EM_CLK" LOC = "F11" ; - -NET "EM_D<15>" LOC = "D13" ; -NET "EM_D<14>" LOC = "D15" ; -NET "EM_D<13>" LOC = "C16" ; -NET "EM_D<12>" LOC = "B20" ; -NET "EM_D<11>" LOC = "A19" ; -NET "EM_D<10>" LOC = "A17" ; -NET "EM_D<9>" LOC = "E15" ; -NET "EM_D<8>" LOC = "F15" ; -NET "EM_D<7>" LOC = "E16" ; -NET "EM_D<6>" LOC = "F16" ; -NET "EM_D<5>" LOC = "B17" ; -NET "EM_D<4>" LOC = "C17" ; -NET "EM_D<3>" LOC = "B19" ; -NET "EM_D<2>" LOC = "D19" ; -NET "EM_D<1>" LOC = "C19" ; -NET "EM_D<0>" LOC = "A20" ; - -NET "EM_A<10>" LOC = "C14" ; -NET "EM_A<9>" LOC = "C10" ; -NET "EM_A<8>" LOC = "C5" ; -NET "EM_A<7>" LOC = "A18" ; -NET "EM_A<6>" LOC = "A15" ; -NET "EM_A<5>" LOC = "A12" ; -NET "EM_A<4>" LOC = "A10" ; -NET "EM_A<3>" LOC = "E7" ; -NET "EM_A<2>" LOC = "A7" ; -NET "EM_A<1>" LOC = "C15" ; - -#NET "EM_NCS6" LOC = "E17" ; -#NET "EM_NCS5" LOC = "E10" ; -NET "EM_NCS4" LOC = "E6" ; -#NET "EM_NCS1" LOC = "D18" ; -#NET "EM_NCS0" LOC = "D17" ; - -NET "EM_WAIT0" LOC = "F14" ; -#NET "EM_NBE1" LOC = "D14" ; -#NET "EM_NBE0" LOC = "A13" ; -NET "EM_NWP" LOC = "F13" ; -NET "EM_NWE" LOC = "B13" ; -NET "EM_NOE" LOC = "A14" ; -NET "EM_NADV_ALE" LOC = "B15" ; - - -## Overo GPIO -#NET "overo_gpio0" LOC = "F9" ; -#NET "overo_gpio14" LOC = "C4" ; -#NET "overo_gpio21" LOC = "D5" ; -#NET "overo_gpio22" LOC = "A3" ; -#NET "overo_gpio23" LOC = "B3" ; -#NET "overo_gpio64" LOC = "A4" ; -#NET "overo_gpio65" LOC = "F8" ; -#NET "overo_gpio127" LOC = "C8" ; -#NET "overo_gpio128" LOC = "G8" ; -#NET "overo_gpio144" LOC = "A5" ; -#NET "overo_gpio145" LOC = "C7" ; -#NET "overo_gpio146" LOC = "A6" ; -#NET "overo_gpio147" LOC = "B6" ; -#NET "overo_gpio163" LOC = "D7" ; -#NET "overo_gpio170" LOC = "E8" ; -#NET "overo_gpio176" LOC = "B4" ; - -## Overo UART -#NET "overo_txd1" LOC = "C6" ; -#NET "overo_rxd1" LOC = "D6" ; - -#NET "FPGA_TXD" LOC = "U1" ; -#NET "FPGA_RXD" LOC = "T6" ; - -#NET "SYSEN" LOC = "C11" ; - -#NET "db_scl" LOC = "U4" ; -#NET "db_sda" LOC = "U5" ; -#NET "db_sclk_rx" LOC = "W3" ; -#NET "db_miso_rx" LOC = "W2" ; -#NET "db_mosi_rx" LOC = "V4" ; -#NET "db_sen_rx" LOC = "V3" ; -#NET "db_sclk_tx" LOC = "Y1" ; -#NET "db_miso_tx" LOC = "W1" ; -#NET "db_mosi_tx" LOC = "R3" ; -#NET "db_sen_tx" LOC = "T4" ; - -## Clock Gen -#NET "cgen_miso" LOC = "U2" ; -#NET "cgen_mosi" LOC = "V1" ; -#NET "cgen_sclk" LOC = "R5" ; -#NET "cgen_sen_b" LOC = "T1" ; -#NET "cgen_st_status" LOC = "D4" ; -#NET "cgen_st_ld" LOC = "D1" ; -#NET "cgen_st_refmon" LOC = "E1" ; -#NET "cgen_sync_b" LOC = "M1" ; -#NET "cgen_ref_sel" LOC = "J1" ; - -## Debug pins -NET "debug_led<2>" LOC = "T5" ; -NET "debug_led<1>" LOC = "R2" ; -NET "debug_led<0>" LOC = "R1" ; -NET "debug<0>" LOC = "P6" ; -NET "debug<1>" LOC = "R6" ; -NET "debug<2>" LOC = "P1" ; -NET "debug<3>" LOC = "P2" ; -NET "debug<4>" LOC = "N6" ; -NET "debug<5>" LOC = "N5" ; -NET "debug<6>" LOC = "N1" ; -NET "debug<7>" LOC = "K2" ; -NET "debug<8>" LOC = "K3" ; -NET "debug<9>" LOC = "K6" ; -NET "debug<10>" LOC = "L5" ; -NET "debug<11>" LOC = "H2" ; -NET "debug<12>" LOC = "K4" ; -NET "debug<13>" LOC = "K5" ; -NET "debug<14>" LOC = "G1" ; -NET "debug<15>" LOC = "H1" ; -NET "debug<16>" LOC = "H5" ; -NET "debug<17>" LOC = "H6" ; -NET "debug<18>" LOC = "E3" ; -NET "debug<19>" LOC = "E4" ; -NET "debug<20>" LOC = "G5" ; -NET "debug<21>" LOC = "G6" ; -NET "debug<22>" LOC = "F2" ; -NET "debug<23>" LOC = "F1" ; -NET "debug<24>" LOC = "H3" ; -NET "debug<25>" LOC = "H4" ; -NET "debug<26>" LOC = "F4" ; -NET "debug<27>" LOC = "F5" ; -NET "debug<28>" LOC = "C2" ; -NET "debug<29>" LOC = "C1" ; -NET "debug<30>" LOC = "F3" ; -NET "debug<31>" LOC = "G3" ; -NET "debug_clk<0>" LOC = "L6" ; -NET "debug_clk<1>" LOC = "M5" ; - -#NET "debug_pb<2>" LOC = "Y2" ; -#NET "debug_pb<1>" LOC = "AA1" ; -#NET "debug_pb<0>" LOC = "N3" ; - -#NET "dip_sw<7>" LOC = "T3" ; -#NET "dip_sw<6>" LOC = "U3" ; -#NET "dip_sw<5>" LOC = "M3" ; -#NET "dip_sw<4>" LOC = "N4" ; -#NET "dip_sw<3>" LOC = "J3" ; -#NET "dip_sw<2>" LOC = "J4" ; -#NET "dip_sw<1>" LOC = "J6" ; -#NET "dip_sw<0>" LOC = "J7" ; - -## AD9862 Interface -#NET "aux_sdi_codec" LOC = "F19" ; -#NET "aux_sdo_codec" LOC = "F18" ; -#NET "aux_sclk_codec" LOC = "D21" ; -#NET "reset_codec" LOC = "D22" ; -#NET "sen_codec" LOC = "D20" ; -#NET "mosi_codec" LOC = "E19" ; -#NET "miso_codec" LOC = "F21" ; -#NET "sclk_codec" LOC = "E20" ; - -#NET "RXSYNC" LOC = "F22" ; - -#NET "DB<11>" LOC = "E22" ; -#NET "DB<10>" LOC = "J19" ; -#NET "DB<9>" LOC = "H20" ; -#NET "DB<8>" LOC = "G19" ; -#NET "DB<7>" LOC = "F20" ; -#NET "DB<6>" LOC = "K16" ; -#NET "DB<5>" LOC = "J17" ; -#NET "DB<4>" LOC = "H22" ; -#NET "DB<3>" LOC = "G22" ; -#NET "DB<2>" LOC = "H17" ; -#NET "DB<1>" LOC = "H18" ; -#NET "DB<0>" LOC = "K20" ; -#NET "DA<11>" LOC = "J20" ; -#NET "DA<10>" LOC = "K19" ; -#NET "DA<9>" LOC = "K18" ; -#NET "DA<8>" LOC = "L22" ; -#NET "DA<7>" LOC = "K22" ; -#NET "DA<6>" LOC = "N22" ; -#NET "DA<5>" LOC = "M22" ; -#NET "DA<4>" LOC = "N20" ; -#NET "DA<3>" LOC = "N19" ; -#NET "DA<2>" LOC = "R22" ; -#NET "DA<1>" LOC = "P22" ; -#NET "DA<0>" LOC = "N17" ; - -#NET "TX<13>" LOC = "P19" ; -#NET "TX<12>" LOC = "R18" ; -#NET "TX<11>" LOC = "U20" ; -#NET "TX<10>" LOC = "T20" ; -#NET "TX<9>" LOC = "R19" ; -#NET "TX<8>" LOC = "R20" ; -#NET "TX<7>" LOC = "W22" ; -#NET "TX<6>" LOC = "Y22" ; -#NET "TX<5>" LOC = "T18" ; -#NET "TX<4>" LOC = "T17" ; -#NET "TX<3>" LOC = "W19" ; -#NET "TX<2>" LOC = "V20" ; -#NET "TX<1>" LOC = "Y21" ; -#NET "TX<0>" LOC = "AA22" ; -#NET "TXSYNC" LOC = "U18" ; -#NET "TXBLANK" LOC = "U19" ; - -#NET "PPS_IN" LOC = "M17" ; - -#NET "io_tx<0>" LOC = "AB20" ; -#NET "io_tx<1>" LOC = "Y17" ; -#NET "io_tx<2>" LOC = "Y16" ; -#NET "io_tx<3>" LOC = "U16" ; -#NET "io_tx<4>" LOC = "V16" ; -#NET "io_tx<5>" LOC = "AB19" ; -#NET "io_tx<6>" LOC = "AA19" ; -#NET "io_tx<7>" LOC = "U14" ; -#NET "io_tx<8>" LOC = "U15" ; -#NET "io_tx<9>" LOC = "AB17" ; -#NET "io_tx<10>" LOC = "AB18" ; -#NET "io_tx<11>" LOC = "Y13" ; -#NET "io_tx<12>" LOC = "W14" ; -#NET "io_tx<13>" LOC = "U13" ; -#NET "io_tx<14>" LOC = "AA15" ; -#NET "io_tx<15>" LOC = "AB14" ; - -#NET "io_rx<0>" LOC = "Y8" ; -#NET "io_rx<1>" LOC = "Y9" ; -#NET "io_rx<2>" LOC = "V7" ; -#NET "io_rx<3>" LOC = "U8" ; -#NET "io_rx<4>" LOC = "V10" ; -#NET "io_rx<5>" LOC = "U9" ; -#NET "io_rx<6>" LOC = "AB7" ; -#NET "io_rx<7>" LOC = "AA8" ; -#NET "io_rx<8>" LOC = "W8" ; -#NET "io_rx<9>" LOC = "V8" ; -#NET "io_rx<10>" LOC = "AB5" ; -#NET "io_rx<11>" LOC = "AB6" ; -#NET "io_rx<12>" LOC = "AB4" ; -#NET "io_rx<13>" LOC = "AA4" ; -#NET "io_rx<14>" LOC = "W5" ; -#NET "io_rx<15>" LOC = "Y4" ; - -#NET "CLKOUT2_CODEC" LOC = "U12" ; -#NET "CLKOUT1_CODEC" LOC = "V12" ; - -## FPGA Config Pins -#NET "fpga_cfg_prog_b" LOC = "A2" ; -#NET "fpga_cfg_done" LOC = "AB21" ; -#NET "fpga_cfg_din" LOC = "W17" ; -#NET "fpga_cfg_cclk" LOC = "V17" ; -#NET "fpga_cfg_init_b" LOC = "W15" ; - -## Unnamed, need to figure out what they do -#NET "unnamed_net37" LOC = "B1" ; -#NET "unnamed_net36" LOC = "B22" ; -#NET "unnamed_net35" LOC = "D2" ; -#NET "unnamed_net34" LOC = "A21" ; -#NET "unnamed_net45" LOC = "F7" ; -#NET "unnamed_net44" LOC = "V6" ; -#NET "unnamed_net43" LOC = "AA3" ; -#NET "unnamed_net42" LOC = "AB3" ; - -#NET "GND" LOC = "V19" ; diff --git a/usrp2/top/safe_u1e/safe_u1e.v b/usrp2/top/safe_u1e/safe_u1e.v deleted file mode 100644 index dee9c6067..000000000 --- a/usrp2/top/safe_u1e/safe_u1e.v +++ /dev/null @@ -1,41 +0,0 @@ -`timescale 1ns / 1ps -////////////////////////////////////////////////////////////////////////////////// - -module safe_u1e - ( - input CLK_FPGA_P, input CLK_FPGA_N, // Diff - output [2:0] debug_led, output [31:0] debug, output [1:0] debug_clk, - - // GPMC - input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, - input EM_WAIT0, input EM_NCS4, input EM_NWP, input EM_NWE, input EM_NOE, input EM_NADV_ALE - ); - - // FPGA-specific pins connections - wire clk_fpga; - - IBUFGDS #(.IOSTANDARD("LVDS_33"), .DIFF_TERM("TRUE")) - clk_fpga_pin (.O(clk_fpga),.I(CLK_FPGA_P),.IB(CLK_FPGA_N)); - - // Debug circuitry - reg [31:0] ctr; - always @(posedge clk_fpga) - ctr <= ctr + 1; - - - assign debug_led = ctr[27:25]; - assign debug_clk = { EM_CLK, clk_fpga }; - assign debug = { { EM_WAIT0, EM_NADV_ALE, EM_NWP, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, - { EM_D } }; - - wire EM_output_enable = (~EM_NOE & ~EM_NCS4); - wire [15:0] EM_D_out; - - assign EM_D = EM_output_enable ? EM_D_out : 16'bz; - - ram_2port #(.DWIDTH(16), .AWIDTH(10)) ram_2port - (.clka(clk_fpga), .ena(~EM_NCS4), .wea(~EM_NWE), .addra(EM_A), .dia(EM_D), .doa(EM_D_out), - .clkb(clk_fpga), .enb(0), .web(0), .addrb(0), .dib(0), .dob()); - - -endmodule // safe_u2plus diff --git a/usrp2/top/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf index a73ebceb8..2caa46639 100644 --- a/usrp2/top/u1e/u1e.ucf +++ b/usrp2/top/u1e/u1e.ucf @@ -54,7 +54,7 @@ NET "overo_gpio22" LOC = "A3" ; # MISC GPIO for debug NET "overo_gpio23" LOC = "B3" ; # MISC GPIO for debug NET "overo_gpio64" LOC = "A4" ; # MISC GPIO for debug NET "overo_gpio65" LOC = "F8" ; # MISC GPIO for debug -NET "overo_gpio127" LOC = "C8" ; # MISC GPIO for debug +NET "overo_gpio127" LOC = "C8" ; # MISC GPIO for debug, also used on the passthru image as the cgen_sen_b pin NET "overo_gpio128" LOC = "G8" ; # MISC GPIO for debug NET "overo_gpio144" LOC = "A5" ; # tx_have_space NET "overo_gpio145" LOC = "C7" ; # tx_underrun diff --git a/usrp2/top/u1e_passthru/.gitignore b/usrp2/top/u1e_passthru/.gitignore new file mode 100644 index 000000000..1b2211df0 --- /dev/null +++ b/usrp2/top/u1e_passthru/.gitignore @@ -0,0 +1 @@ +build* diff --git a/usrp2/top/u1e_passthru/passthru.ucf b/usrp2/top/u1e_passthru/passthru.ucf index 1672132a2..3ffe33882 100644 --- a/usrp2/top/u1e_passthru/passthru.ucf +++ b/usrp2/top/u1e_passthru/passthru.ucf @@ -47,14 +47,14 @@ ##NET "EM_NWP" LOC = "F13" ; ## Overo GPIO -NET "overo_gpio0" LOC = "F9" ; # MISC GPIO for debug +#NET "overo_gpio0" LOC = "F9" ; # MISC GPIO for debug #NET "overo_gpio14" LOC = "C4" ; # MISC GPIO for debug #NET "overo_gpio21" LOC = "D5" ; # MISC GPIO for debug #NET "overo_gpio22" LOC = "A3" ; # MISC GPIO for debug #NET "overo_gpio23" LOC = "B3" ; # MISC GPIO for debug #NET "overo_gpio64" LOC = "A4" ; # MISC GPIO for debug #NET "overo_gpio65" LOC = "F8" ; # MISC GPIO for debug -#NET "overo_gpio127" LOC = "C8" ; # MISC GPIO for debug +NET "overo_gpio127" LOC = "C8" ; # passed through as cgen_sen_b #NET "overo_gpio128" LOC = "G8" ; # MISC GPIO for debug #NET "overo_gpio144" LOC = "A5" ; # tx_have_space #NET "overo_gpio145" LOC = "C7" ; # tx_underrun diff --git a/usrp2/top/u1e_passthru/passthru.v b/usrp2/top/u1e_passthru/passthru.v index 459c226ee..d846f2cf6 100644 --- a/usrp2/top/u1e_passthru/passthru.v +++ b/usrp2/top/u1e_passthru/passthru.v @@ -2,16 +2,16 @@ ////////////////////////////////////////////////////////////////////////////////// module passthru - (input overo_gpio0, - output cgen_sclk, - output cgen_sen_b, - output cgen_mosi, + (input overo_gpio127, + output cgen_sclk, + output cgen_sen_b, + output cgen_mosi, input fpga_cfg_din, input fpga_cfg_cclk ); assign cgen_sclk = fpga_cfg_cclk; - assign cgen_sen_b = overo_gpio0; + assign cgen_sen_b = overo_gpio127; assign cgen_mosi = fpga_cfg_din; -- cgit v1.2.3 From 247e36dcbace9ef06763c2c537b44c8225a9d6a7 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 12 May 2010 16:12:00 -0700 Subject: packet generator and verifier, to test gpmc and other data transfer stuff --- usrp2/control_lib/newfifo/.gitignore | 2 + usrp2/control_lib/newfifo/packet_generator.v | 59 ++++++++++++++++++++++++++ usrp2/control_lib/newfifo/packet_tb.v | 29 +++++++++++++ usrp2/control_lib/newfifo/packet_verifier.v | 63 ++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+) create mode 100644 usrp2/control_lib/newfifo/packet_generator.v create mode 100644 usrp2/control_lib/newfifo/packet_tb.v create mode 100644 usrp2/control_lib/newfifo/packet_verifier.v diff --git a/usrp2/control_lib/newfifo/.gitignore b/usrp2/control_lib/newfifo/.gitignore index cba7efc8e..866f1faad 100644 --- a/usrp2/control_lib/newfifo/.gitignore +++ b/usrp2/control_lib/newfifo/.gitignore @@ -1 +1,3 @@ +*.vcd +*.lxt a.out diff --git a/usrp2/control_lib/newfifo/packet_generator.v b/usrp2/control_lib/newfifo/packet_generator.v new file mode 100644 index 000000000..e5bfe5b26 --- /dev/null +++ b/usrp2/control_lib/newfifo/packet_generator.v @@ -0,0 +1,59 @@ + + +module packet_generator + (input clk, input reset, input clear, + output reg [7:0] data_o, output sof_o, output eof_o, + output src_rdy_o, input dst_rdy_i); + + localparam len = 32'd100; + + reg [31:0] state; + reg [31:0] seq; + wire [31:0] crc_out; + wire calc_crc = src_rdy_o & dst_rdy_i & ~(state[31:2] == 30'h3FFF_FFFF); + + + always @(posedge clk) + if(reset | clear) + seq <= 0; + else + if(eof_o & src_rdy_o & dst_rdy_i) + seq <= seq + 1; + + always @(posedge clk) + if(reset | clear) + state <= 0; + else + if(src_rdy_o & dst_rdy_i) + if(state == (len - 1)) + state <= 32'hFFFF_FFFC; + else + state <= state + 1; + + always @* + case(state) + 0 : data_o <= len[7:0]; + 1 : data_o <= len[15:8]; + 2 : data_o <= len[23:16]; + 3 : data_o <= len[31:24]; + 4 : data_o <= seq[7:0]; + 5 : data_o <= seq[15:8]; + 6 : data_o <= seq[23:16]; + 7 : data_o <= seq[31:24]; + 32'hFFFF_FFFC : data_o <= crc_out[31:24]; + 32'hFFFF_FFFD : data_o <= crc_out[23:16]; + 32'hFFFF_FFFE : data_o <= crc_out[15:8]; + 32'hFFFF_FFFF : data_o <= crc_out[7:0]; + default : data_o <= state[7:0]; + endcase // case (state) + + assign src_rdy_o = 1; + assign sof_o = (state == 0); + assign eof_o = (state == 32'hFFFF_FFFF); + + wire clear_crc = eof_o & src_rdy_o & dst_rdy_i; + + crc crc(.clk(clk), .reset(reset), .clear(clear_crc), .data(data_o), + .calc(calc_crc), .crc_out(crc_out), .match()); + +endmodule // packet_generator diff --git a/usrp2/control_lib/newfifo/packet_tb.v b/usrp2/control_lib/newfifo/packet_tb.v new file mode 100644 index 000000000..3c423d2ba --- /dev/null +++ b/usrp2/control_lib/newfifo/packet_tb.v @@ -0,0 +1,29 @@ + + +module packet_tb(); + + wire [7:0] data; + wire sof, eof, src_rdy, dst_rdy; + + wire clear = 0; + reg clk = 0; + reg reset = 1; + + always #10 clk <= ~clk; + initial #1000 reset <= 0; + + initial $dumpfile("packet_tb.vcd"); + initial $dumpvars(0,packet_tb); + + wire [31:0] total, crc_err, seq_err, len_err; + + packet_generator pkt_gen (.clk(clk), .reset(reset), .clear(clear), + .data_o(data), .sof_o(sof), .eof_o(eof), + .src_rdy_o(src_rdy), .dst_rdy_i(dst_rdy)); + + packet_verifier pkt_ver (.clk(clk), .reset(reset), .clear(clear), + .data_i(data), .sof_i(sof), .eof_i(eof), + .src_rdy_i(src_rdy), .dst_rdy_o(dst_rdy), + .total(total), .crc_err(crc_err), .seq_err(seq_err), .len_err(len_err)); + +endmodule // packet_tb diff --git a/usrp2/control_lib/newfifo/packet_verifier.v b/usrp2/control_lib/newfifo/packet_verifier.v new file mode 100644 index 000000000..22c924198 --- /dev/null +++ b/usrp2/control_lib/newfifo/packet_verifier.v @@ -0,0 +1,63 @@ + + +// Packet format -- +// Line 1 -- Length, 32 bits +// Line 2 -- Sequence number, 32 bits +// Last line -- CRC, 32 bits + +module packet_verifier + (input clk, input reset, input clear, + input [7:0] data_i, input sof_i, output eof_i, input src_rdy_i, output dst_rdy_o, + + output reg [31:0] total, + output reg [31:0] crc_err, + output reg [31:0] seq_err, + output reg [31:0] len_err); + + assign dst_rdy_o = ~last_byte_d1; + + reg [31:0] seq_num; + reg [31:0] length; + + wire calc_crc = src_rdy_i & dst_rdy_o; + + crc crc(.clk(clk), .reset(reset), .clear(last_byte_d1), .data(data_i), + .calc(calc_crc), .crc_out(), .match(match_crc)); + + wire first_byte, last_byte; + reg second_byte, last_byte_d1; + + assign first_byte = src_rdy_i & dst_rdy_o & sof_i; + assign last_byte = src_rdy_i & dst_rdy_o & eof_i; + + // stubs for now + wire match_seq = 1; + wire match_len = 1; + + always @(posedge clk) + if(reset | clear) + last_byte_d1 <= 0; + else + last_byte_d1 <= last_byte; + + always @(posedge clk) + if(reset | clear) + begin + total <= 0; + crc_err <= 0; + seq_err <= 0; + len_err <= 0; + end + else + if(last_byte_d1) + begin + total <= total + 1; + if(~match_crc) + crc_err <= crc_err + 1; + else if(~match_seq) + seq_err <= seq_err + 1; + else if(~match_len) + seq_err <= len_err + 1; + end + +endmodule // packet_verifier -- cgit v1.2.3 From ed48630974fb8cbdc3b863b13d4e7d7e8fe31434 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 12 May 2010 16:16:18 -0700 Subject: add missing signal from sensitivity list --- usrp2/control_lib/nsgpio16LE.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usrp2/control_lib/nsgpio16LE.v b/usrp2/control_lib/nsgpio16LE.v index d6d7dcf56..514b003ce 100644 --- a/usrp2/control_lib/nsgpio16LE.v +++ b/usrp2/control_lib/nsgpio16LE.v @@ -111,7 +111,7 @@ module nsgpio16LE 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] ? (dbg[n] ? (ctrl[n] ? debug_1[n] : debug_0[n]) : (ctrl[n] ? atr[n] : line[n]) ) -- cgit v1.2.3 From b04a1beaab300000ce2d8a5814bd2e37af48286c Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 12 May 2010 18:51:33 -0700 Subject: moved fifos into gpmc_async, reorganized top level a bit, added in crc packet gen and test --- usrp2/control_lib/newfifo/packet_generator32.v | 21 ++++++ usrp2/control_lib/newfifo/packet_verifier.v | 10 ++- usrp2/control_lib/newfifo/packet_verifier32.v | 23 +++++++ usrp2/gpmc/gpmc_async.v | 91 +++++++++++++++----------- usrp2/top/u1e/Makefile | 4 ++ usrp2/top/u1e/u1e_core.v | 61 ++++++++++------- 6 files changed, 144 insertions(+), 66 deletions(-) create mode 100644 usrp2/control_lib/newfifo/packet_generator32.v create mode 100644 usrp2/control_lib/newfifo/packet_verifier32.v diff --git a/usrp2/control_lib/newfifo/packet_generator32.v b/usrp2/control_lib/newfifo/packet_generator32.v new file mode 100644 index 000000000..6f8004964 --- /dev/null +++ b/usrp2/control_lib/newfifo/packet_generator32.v @@ -0,0 +1,21 @@ + + +module packet_generator32 + (input clk, input reset, input clear, + output [35:0] data_o, output src_rdy_o, input dst_rdy_i); + + wire [7:0] ll_data; + wire ll_sof, ll_eof, ll_src_rdy, ll_dst_rdy_n; + + packet_generator pkt_gen + (.clk(clk), .reset(reset), .clear(clear), + .data_o(ll_data), .sof_o(ll_sof), .eof_o(ll_eof), + .src_rdy_o(ll_src_rdy), .dst_rdy_i(~ll_dst_rdy_n)); + + ll8_to_fifo36 ll8_to_f36 + (.clk(clk), .reset(reset), .clear(clear), + .ll_data(ll_data), .ll_sof_n(~ll_sof), .ll_eof_n(~ll_eof), + .ll_src_rdy_n(~ll_src_rdy), .ll_dst_rdy_n(ll_dst_rdy_n), + .f36_data(data_o), .f36_src_rdy_o(src_rdy_o), .f36_dst_rdy_i(dst_rdy_i)); + +endmodule // packet_generator32 diff --git a/usrp2/control_lib/newfifo/packet_verifier.v b/usrp2/control_lib/newfifo/packet_verifier.v index 22c924198..b49ad1bbb 100644 --- a/usrp2/control_lib/newfifo/packet_verifier.v +++ b/usrp2/control_lib/newfifo/packet_verifier.v @@ -7,28 +7,26 @@ module packet_verifier (input clk, input reset, input clear, - input [7:0] data_i, input sof_i, output eof_i, input src_rdy_i, output dst_rdy_o, + input [7:0] data_i, input sof_i, input eof_i, input src_rdy_i, output dst_rdy_o, output reg [31:0] total, output reg [31:0] crc_err, output reg [31:0] seq_err, output reg [31:0] len_err); - assign dst_rdy_o = ~last_byte_d1; - reg [31:0] seq_num; reg [31:0] length; + wire first_byte, last_byte; + reg second_byte, last_byte_d1; wire calc_crc = src_rdy_i & dst_rdy_o; crc crc(.clk(clk), .reset(reset), .clear(last_byte_d1), .data(data_i), .calc(calc_crc), .crc_out(), .match(match_crc)); - wire first_byte, last_byte; - reg second_byte, last_byte_d1; - assign first_byte = src_rdy_i & dst_rdy_o & sof_i; assign last_byte = src_rdy_i & dst_rdy_o & eof_i; + assign dst_rdy_o = ~last_byte_d1; // stubs for now wire match_seq = 1; diff --git a/usrp2/control_lib/newfifo/packet_verifier32.v b/usrp2/control_lib/newfifo/packet_verifier32.v new file mode 100644 index 000000000..065607b6c --- /dev/null +++ b/usrp2/control_lib/newfifo/packet_verifier32.v @@ -0,0 +1,23 @@ + + +module packet_verifier32 + (input clk, input reset, input clear, + input [35:0] data_i, input src_rdy_i, output dst_rdy_o, + output [31:0] total, output [31:0] crc_err, output [31:0] seq_err, output [31:0] len_err); + + wire [7:0] ll_data; + wire ll_sof_n, ll_eof_n, ll_src_rdy_n, ll_dst_rdy; + + fifo36_to_ll8 f36_to_ll8 + (.clk(clk), .reset(reset), .clear(clear), + .f36_data(data_i), .f36_src_rdy_i(src_rdy_i), .f36_dst_rdy_o(dst_rdy_o), + .ll_data(ll_data), .ll_sof_n(ll_sof_n), .ll_eof_n(ll_eof_n), + .ll_src_rdy_n(ll_src_rdy_n), .ll_dst_rdy_n(~ll_dst_rdy)); + + packet_verifier pkt_ver + (.clk(clk), .reset(reset), .clear(clear), + .data_i(ll_data), .sof_i(~ll_sof_n), .eof_i(~ll_eof_n), + .src_rdy_i(~ll_src_rdy_n), .dst_rdy_o(ll_dst_rdy), + .total(total), .crc_err(crc_err), .seq_err(seq_err), .len_err(len_err)); + +endmodule // packet_verifier32 diff --git a/usrp2/gpmc/gpmc_async.v b/usrp2/gpmc/gpmc_async.v index dd06478b3..380689c62 100644 --- a/usrp2/gpmc/gpmc_async.v +++ b/usrp2/gpmc/gpmc_async.v @@ -1,37 +1,38 @@ ////////////////////////////////////////////////////////////////////////////////// module gpmc_async - (// GPMC signals - input arst, - input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, - input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, - - // GPIOs for FIFO signalling - output rx_have_data, output tx_have_space, output reg bus_error, input bus_reset, - - // Wishbone signals - input wb_clk, input wb_rst, - output [10:0] wb_adr_o, output [15:0] wb_dat_mosi, input [15:0] wb_dat_miso, - output [1:0] wb_sel_o, output wb_cyc_o, output wb_stb_o, output wb_we_o, input wb_ack_i, + #(parameter TXFIFOSIZE = 11, parameter RXFIFOSIZE = 11) + (// GPMC signals + input arst, + input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, + input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, + + // GPIOs for FIFO signalling + output rx_have_data, output tx_have_space, output reg bus_error, input bus_reset, + + // Wishbone signals + input wb_clk, input wb_rst, + output [10:0] wb_adr_o, output [15:0] wb_dat_mosi, input [15:0] wb_dat_miso, + output [1:0] wb_sel_o, output wb_cyc_o, output wb_stb_o, output wb_we_o, input wb_ack_i, + + // FIFO interface + input fifo_clk, input fifo_rst, + output [35:0] tx_data_o, output tx_src_rdy_o, input tx_dst_rdy_i, + input [35:0] rx_data_i, input rx_src_rdy_i, output rx_dst_rdy_o, + + input [15:0] tx_frame_len, output [15:0] rx_frame_len, + + output [31:0] debug + ); - // FIFO interface - input fifo_clk, input fifo_rst, - output [35:0] tx_data_o, output tx_src_rdy_o, input tx_dst_rdy_i, - input [35:0] rx_data_i, input rx_src_rdy_i, output rx_dst_rdy_o, - - input [15:0] tx_frame_len, output [15:0] rx_frame_len, + wire EM_output_enable = (~EM_NOE & (~EM_NCS4 | ~EM_NCS6)); + wire [15:0] EM_D_fifo; + wire [15:0] EM_D_wb; - output [31:0] debug - ); - - wire EM_output_enable = (~EM_NOE & (~EM_NCS4 | ~EM_NCS6)); - wire [15:0] EM_D_fifo; - wire [15:0] EM_D_wb; - assign EM_D = ~EM_output_enable ? 16'bz : ~EM_NCS4 ? EM_D_fifo : EM_D_wb; - - wire bus_error_tx, bus_error_rx; - + + wire bus_error_tx, bus_error_rx; + always @(posedge fifo_clk) if(fifo_rst) bus_error <= 0; @@ -45,9 +46,11 @@ module gpmc_async // //////////////////////////////////////////// // TX Data Path - wire [17:0] tx18_data, tx18b_data; - wire tx18_src_rdy, tx18_dst_rdy, tx18b_src_rdy, tx18b_dst_rdy; - wire [15:0] tx_fifo_space; + wire [17:0] tx18_data, tx18b_data; + wire tx18_src_rdy, tx18_dst_rdy, tx18b_src_rdy, tx18b_dst_rdy; + wire [15:0] tx_fifo_space; + wire [35:0] tx36_data; + wire tx36_src_rdy, tx36_dst_rdy; gpmc_to_fifo_async gpmc_to_fifo_async (.EM_D(EM_D), .EM_NBE(EM_NBE), .EM_NCS(EM_NCS4), .EM_NWE(EM_NWE), @@ -64,18 +67,30 @@ module gpmc_async fifo19_to_fifo36 f19_to_f36 (.clk(fifo_clk), .reset(fifo_rst), .clear(0), .f19_datain({1'b0,tx18b_data}), .f19_src_rdy_i(tx18b_src_rdy), .f19_dst_rdy_o(tx18b_dst_rdy), - .f36_dataout(tx_data_o), .f36_src_rdy_o(tx_src_rdy_o), .f36_dst_rdy_i(tx_dst_rdy_i)); + .f36_dataout(tx36_data), .f36_src_rdy_o(tx36_src_rdy), .f36_dst_rdy_i(tx36_dst_rdy)); + fifo_cascade #(.WIDTH(36), .SIZE(TXFIFOSIZE)) tx_fifo36 + (.clk(wb_clk), .reset(wb_rst), .clear(0), + .datain(tx36_data), .src_rdy_i(tx36_src_rdy), .dst_rdy_o(tx36_dst_rdy), + .dataout(tx_data_o), .src_rdy_o(tx_src_rdy_o), .dst_rdy_i(tx_dst_rdy_i)); + // //////////////////////////////////////////// // RX Data Path - - wire [17:0] rx18_data, rx18b_data; - wire rx18_src_rdy, rx18_dst_rdy, rx18b_src_rdy, rx18b_dst_rdy; - wire [15:0] rx_fifo_space; + wire [17:0] rx18_data, rx18b_data; + wire rx18_src_rdy, rx18_dst_rdy, rx18b_src_rdy, rx18b_dst_rdy; + wire [15:0] rx_fifo_space; + wire [35:0] rx36_data; + wire rx36_src_rdy, rx36_dst_rdy; + + fifo_cascade #(.WIDTH(36), .SIZE(RXFIFOSIZE)) rx_fifo36 + (.clk(wb_clk), .reset(wb_rst), .clear(0), + .datain(rx_data_i), .src_rdy_i(rx_src_rdy_i), .dst_rdy_o(rx_dst_rdy_o), + .dataout(rx36_data), .src_rdy_o(rx36_src_rdy), .dst_rdy_i(rx36_dst_rdy)); + fifo36_to_fifo18 f18_to_f36 (.clk(fifo_clk), .reset(fifo_rst), .clear(0), - .f36_datain(rx_data_i), .f36_src_rdy_i(rx_src_rdy_i), .f36_dst_rdy_o(rx_dst_rdy_o), + .f36_datain(rx36_data), .f36_src_rdy_i(rx36_src_rdy), .f36_dst_rdy_o(rx36_dst_rdy), .f18_dataout(rx18_data), .f18_src_rdy_o(rx18_src_rdy), .f18_dst_rdy_i(rx18_dst_rdy) ); fifo_cascade #(.WIDTH(18), .SIZE(12)) rx_fifo @@ -106,6 +121,6 @@ module gpmc_async .wb_sel_o(wb_sel_o), .wb_cyc_o(wb_cyc_o), .wb_stb_o(wb_stb_o), .wb_we_o(wb_we_o), .wb_ack_i(wb_ack_i) ); - assign debug = 0; + assign debug = 0; endmodule // gpmc_async diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index 2aebb33f9..8622b8480 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -111,6 +111,10 @@ control_lib/newfifo/fifo_cascade.v \ control_lib/newfifo/fifo36_to_ll8.v \ control_lib/newfifo/fifo36_to_fifo18.v \ control_lib/newfifo/fifo19_to_fifo36.v \ +control_lib/newfifo/packet_generator.v \ +control_lib/newfifo/packet_verifier.v \ +control_lib/newfifo/packet_generator32.v \ +control_lib/newfifo/packet_verifier32.v \ control_lib/longfifo.v \ control_lib/shortfifo.v \ control_lib/medfifo.v \ diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index a262184a8..903121832 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -1,4 +1,9 @@ + +//`define LOOPBACK 1 +//`define TIMED 1 +`define CRC 1 + module u1e_core (input clk_fpga, input rst_fpga, output [2:0] debug_led, output [31:0] debug, output [1:0] debug_clk, @@ -61,47 +66,59 @@ module u1e_core .tx_frame_len(tx_frame_len), .rx_frame_len(rx_frame_len), .debug(debug_gpmc)); -/* + +`ifdef LOOPBACK fifo_cascade #(.WIDTH(36), .SIZE(9)) loopback_fifo (.clk(wb_clk), .reset(wb_rst), .clear(0), .datain(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy), .dataout(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); -*/ - wire tx_strobe, rx_strobe, tx_enable, rx_enable; + wire rx_sof = rx_data[32]; + wire rx_eof = rx_data[33]; +`endif // LOOPBACK + +`ifdef TIMED wire [7:0] rate; - wire tx_fifo_rdy, rx_fifo_rdy; - + + // TX side + wire tx_enable; cic_strober tx_strober (.clock(wb_clk), .reset(wb_rst), .enable(tx_enable), - .rate(rate), .strobe_fast(1), .strobe_slow(tx_strobe)); - - fifo_cascade #(.WIDTH(36), .SIZE(11)) tx_fifo - (.clk(wb_clk), .reset(wb_rst), .clear(0), - .datain(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy), - .dataout(), .src_rdy_o(tx_fifo_rdy), .dst_rdy_i(tx_strobe)); + .rate(rate), .strobe_fast(1), .strobe_slow(tx_dst_rdy)); - + // RX side + wire rx_enable; reg [15:0] ctr; wire [15:0] rx_pkt_len = 480; wire rx_eof = (ctr == rx_pkt_len); wire rx_sof = (ctr == 0); cic_strober rx_strober (.clock(wb_clk), .reset(wb_rst), .enable(rx_enable), - .rate(rate), .strobe_fast(1), .strobe_slow(rx_strobe)); + .rate(rate), .strobe_fast(1), .strobe_slow(rx_src_rdy)); - fifo_cascade #(.WIDTH(36), .SIZE(11)) rx_fifo - (.clk(wb_clk), .reset(wb_rst), .clear(0), - .datain({2'b00,rx_eof,rx_sof,16'd0,ctr}), .src_rdy_i(rx_strobe), .dst_rdy_o(rx_fifo_rdy), - .dataout(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); - always @(posedge wb_clk) if(wb_rst) ctr <= 0; - else if(rx_strobe & rx_fifo_rdy) + else if(rx_dst_rdy & rx_src_rdy) if(ctr == rx_pkt_len) ctr <= 0; else ctr <= ctr + 1; - + + assign rx_data = {2'b00,rx_eof,rx_sof,~ctr,ctr}; +`endif // TIMED + +`ifdef CRC + packet_generator32 pktgen32 + (.clk(wb_clk), .reset(wb_rst), .clear(clear), + .data_o(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); + + packet_verifier32 pktver32 + (.clk(wb_clk), .reset(wb_rst), .clear(clear), + .data_i(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy), + .total(total), .crc_err(crc_err), .seq_err(seq_err), .len_err(len_err)); + + wire rx_sof = rx_data[32]; + wire rx_eof = rx_data[33]; +`endif // CRC // ///////////////////////////////////////////////////////////////////////////////////// // Wishbone Intercon, single master @@ -364,8 +381,8 @@ module u1e_core assign debug_gpio_0 = { debug_gpmc }; - assign debug_gpio_1 = { {rx_enable, rx_strobe, rx_fifo_rdy, rx_strobe & ~rx_fifo_rdy}, - {tx_enable, tx_strobe, tx_fifo_rdy, tx_strobe & ~tx_fifo_rdy}, + assign debug_gpio_1 = { {rx_enable, rx_src_rdy, rx_dst_rdy, rx_src_rdy & ~rx_dst_rdy}, + {tx_enable, tx_src_rdy, tx_dst_rdy, tx_dst_rdy & ~tx_src_rdy}, {rx_sof, rx_eof, rx_src_rdy, rx_dst_rdy, rx_data[33:32],2'b0}, {3'b0, bus_error, misc_gpio[11:0]} }; -- cgit v1.2.3 From 47230fadfbbde3b45fbf57e8ff506f4fac812ca2 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 17 May 2010 20:59:55 -0700 Subject: better debug pins --- usrp2/top/u1e/u1e_core.v | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 903121832..4637df0cc 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -1,8 +1,8 @@ -//`define LOOPBACK 1 +`define LOOPBACK 1 //`define TIMED 1 -`define CRC 1 +//`define CRC 1 module u1e_core (input clk_fpga, input rst_fpga, @@ -372,12 +372,10 @@ module u1e_core // Debug circuitry assign debug_clk = { EM_CLK, clk_fpga }; -/* - assign debug = { { rx_have_data, tx_have_space, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, + assign debug = { { rx_have_data, tx_have_space, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, { EM_D } }; -*/ - assign debug = { phase[23:8], txsync, txblank, tx }; + //assign debug = { phase[23:8], txsync, txblank, tx }; assign debug_gpio_0 = { debug_gpmc }; -- cgit v1.2.3 From c94256034819feb26d739e57e8cf7d3f60539e9c Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 20 May 2010 00:30:49 -0700 Subject: combined timed and crc cases. fifo pacer produces/consumes at a fixed rate --- usrp2/control_lib/newfifo/fifo_pacer.v | 24 ++++++++++++++ usrp2/top/u1e/Makefile | 1 + usrp2/top/u1e/u1e_core.v | 57 ++++++++++++++-------------------- 3 files changed, 48 insertions(+), 34 deletions(-) create mode 100644 usrp2/control_lib/newfifo/fifo_pacer.v diff --git a/usrp2/control_lib/newfifo/fifo_pacer.v b/usrp2/control_lib/newfifo/fifo_pacer.v new file mode 100644 index 000000000..1bf03ab6e --- /dev/null +++ b/usrp2/control_lib/newfifo/fifo_pacer.v @@ -0,0 +1,24 @@ + + +module fifo_pacer + (input clk, + input reset, + input [7:0] rate, + input enable, + input src1_rdy_i, output dst1_rdy_o, + output src2_rdy_o, input dst2_rdy_i, + output underrun, overrun); + + wire strobe; + + cic_strober strober (.clock(clk), .reset(reset), .enable(enable), + .rate(rate), .strobe_fast(1), .strobe_slow(strobe)); + + wire all_ready = src1_rdy_i & dst2_rdy_i; + assign dst1_rdy_o = all_ready & strobe; + assign src2_rdy_o = dst1_rdy_o; + + assign underrun = strobe & ~src1_rdy_i; + assign overrun = strobe & ~dst2_rdy_i; + +endmodule // fifo_pacer diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index 8622b8480..0277ef4f2 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -115,6 +115,7 @@ control_lib/newfifo/packet_generator.v \ control_lib/newfifo/packet_verifier.v \ control_lib/newfifo/packet_generator32.v \ control_lib/newfifo/packet_verifier32.v \ +control_lib/newfifo/fifo_pacer.v \ control_lib/longfifo.v \ control_lib/shortfifo.v \ control_lib/medfifo.v \ diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 903121832..21ac97dbd 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -1,8 +1,7 @@ //`define LOOPBACK 1 -//`define TIMED 1 -`define CRC 1 +`define TIMED 1 module u1e_core (input clk_fpga, input rst_fpga, @@ -80,45 +79,35 @@ module u1e_core wire [7:0] rate; // TX side - wire tx_enable; - cic_strober tx_strober (.clock(wb_clk), .reset(wb_rst), .enable(tx_enable), - .rate(rate), .strobe_fast(1), .strobe_slow(tx_dst_rdy)); - - // RX side - wire rx_enable; - reg [15:0] ctr; - wire [15:0] rx_pkt_len = 480; - wire rx_eof = (ctr == rx_pkt_len); - wire rx_sof = (ctr == 0); + wire tx_enable, tx_src_rdy_int, tx_dst_rdy_int; - cic_strober rx_strober (.clock(wb_clk), .reset(wb_rst), .enable(rx_enable), - .rate(rate), .strobe_fast(1), .strobe_slow(rx_src_rdy)); + fifo_pacer tx_pacer + (.clk(wb_clk), .reset(wb_rst), .rate(rate), .enable(tx_enable), + .src1_rdy_i(tx_src_rdy), .dst1_rdy_o(tx_dst_rdy), + .src2_rdy_o(tx_src_rdy_int), .dst2_rdy_i(tx_dst_rdy_int), + .underrun(tx_underrun), .overrun()); - always @(posedge wb_clk) - if(wb_rst) - ctr <= 0; - else if(rx_dst_rdy & rx_src_rdy) - if(ctr == rx_pkt_len) - ctr <= 0; - else - ctr <= ctr + 1; - - assign rx_data = {2'b00,rx_eof,rx_sof,~ctr,ctr}; -`endif // TIMED - -`ifdef CRC - packet_generator32 pktgen32 - (.clk(wb_clk), .reset(wb_rst), .clear(clear), - .data_o(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); - packet_verifier32 pktver32 (.clk(wb_clk), .reset(wb_rst), .clear(clear), - .data_i(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy), + .data_i(tx_data), .src_rdy_i(tx_src_rdy_int), .dst_rdy_o(tx_dst_rdy_int), .total(total), .crc_err(crc_err), .seq_err(seq_err), .len_err(len_err)); + // RX side + wire rx_enable, rx_src_rdy_int, rx_dst_rdy_int; wire rx_sof = rx_data[32]; wire rx_eof = rx_data[33]; -`endif // CRC + + packet_generator32 pktgen32 + (.clk(wb_clk), .reset(wb_rst), .clear(clear), + .data_o(rx_data), .src_rdy_o(rx_src_rdy_int), .dst_rdy_i(rx_dst_rdy_int)); + + fifo_pacer rx_pacer + (.clk(wb_clk), .reset(wb_rst), .rate(rate), .enable(rx_enable), + .src1_rdy_i(rx_src_rdy_int), .dst1_rdy_o(rx_dst_rdy_int), + .src2_rdy_o(rx_src_rdy), .dst2_rdy_i(rx_dst_rdy), + .underrun(), .overrun(rx_overrun)); + +`endif // `ifdef TIMED // ///////////////////////////////////////////////////////////////////////////////////// // Wishbone Intercon, single master @@ -233,7 +222,7 @@ module u1e_core assign { debug_led[2],debug_led[0],debug_led[1] } = reg_leds; // LEDs are arranged funny on board assign { cgen_sync_b, cgen_ref_sel } = reg_cgen_ctrl; - assign { rx_overrun, tx_underrun } = 0; // reg_test; + //assign { rx_overrun, tx_underrun } = 0; // reg_test; assign s0_dat_miso = (s0_adr[6:0] == REG_LEDS) ? reg_leds : (s0_adr[6:0] == REG_SWITCHES) ? {5'b0,debug_pb[2:0],dip_sw[7:0]} : -- cgit v1.2.3 From 3b96b1f0f443acb9412b40592de5dc13e1f840d6 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 20 May 2010 00:34:35 -0700 Subject: put over/underrun on debug bus, remove high order address bits --- usrp2/top/u1e/u1e_core.v | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 71b9b8712..48b5bd010 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -361,7 +361,8 @@ module u1e_core // Debug circuitry assign debug_clk = { EM_CLK, clk_fpga }; - assign debug = { { rx_have_data, tx_have_space, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, EM_A[10:1] }, + assign debug = { { rx_have_data, tx_have_space, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, rx_overrun, tx_underrun }, + { EM_A[8:1] }, { EM_D } }; //assign debug = { phase[23:8], txsync, txblank, tx }; -- cgit v1.2.3 From c6e8d0658dc66e9a24a87d4574c649b77ec4075d Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 20 May 2010 13:43:13 -0700 Subject: removes the icache and pipelines the reads --- usrp2/control_lib/ram_harvard.v | 71 +++++++++++++++++++++++++ usrp2/opencores/aemb/rtl/verilog/aeMB_bpcu.v | 5 +- usrp2/opencores/aemb/rtl/verilog/aeMB_core_BE.v | 27 ++++++---- usrp2/top/u2_core/u2_core.v | 10 ++-- usrp2/top/u2_rev3/Makefile | 1 + 5 files changed, 98 insertions(+), 16 deletions(-) create mode 100644 usrp2/control_lib/ram_harvard.v diff --git a/usrp2/control_lib/ram_harvard.v b/usrp2/control_lib/ram_harvard.v new file mode 100644 index 000000000..6711da366 --- /dev/null +++ b/usrp2/control_lib/ram_harvard.v @@ -0,0 +1,71 @@ + + +// Dual ported, Harvard architecture, cached ram + +module ram_harvard + #(parameter AWIDTH=15, + parameter RAM_SIZE=16384, + parameter ICWIDTH=6, + parameter DCWIDTH=6) + + (input wb_clk_i, + input wb_rst_i, + // Firmware download port. + input [AWIDTH-1:0] ram_loader_adr_i, + input [31:0] ram_loader_dat_i, + input ram_loader_stb_i, + input [3:0] ram_loader_sel_i, + input ram_loader_we_i, + output ram_loader_ack_o, + input ram_loader_done_i, + // Instruction fetch port. + input [AWIDTH-1:0] if_adr, + output [31:0] if_data, + // Data access port. + input [AWIDTH-1:0] dwb_adr_i, + input [31:0] dwb_dat_i, + output [31:0] dwb_dat_o, + input dwb_we_i, + output dwb_ack_o, + input dwb_stb_i, + input [3:0] dwb_sel_i, + + input flush_icache ); + + reg ack_d1; + reg stb_d1; + + + dpram32 #(.AWIDTH(AWIDTH),.RAM_SIZE(RAM_SIZE)) + sys_ram + (.clk(wb_clk_i), + .adr1_i(ram_loader_done_i ? if_adr : ram_loader_adr_i), + .dat1_i(ram_loader_dat_i), + .dat1_o(if_data), + .we1_i(ram_loader_done_i ? 1'b0 : ram_loader_we_i), + .en1_i(ram_loader_done_i ? 1'b1 : ram_loader_stb_i), + .sel1_i(ram_loader_done_i ? 4'hF : ram_loader_sel_i), + .adr2_i(dwb_adr_i), + .dat2_i(dwb_dat_i), + .dat2_o(dwb_dat_o), + .we2_i(dwb_we_i), + .en2_i(dwb_stb_i), + .sel2_i(dwb_sel_i) + ); + + assign dwb_ack_o = dwb_stb_i & (dwb_we_i | (stb_d1 & ~ack_d1)); + + always @(posedge wb_clk_i) + if(wb_rst_i) + ack_d1 <= 1'b0; + else + ack_d1 <= dwb_ack_o; + + always @(posedge wb_clk_i) + if(wb_rst_i) + stb_d1 <= 0; + else + stb_d1 <= dwb_stb_i; + + +endmodule // ram_harv_cache diff --git a/usrp2/opencores/aemb/rtl/verilog/aeMB_bpcu.v b/usrp2/opencores/aemb/rtl/verilog/aeMB_bpcu.v index a7c686e7e..81587e25c 100644 --- a/usrp2/opencores/aemb/rtl/verilog/aeMB_bpcu.v +++ b/usrp2/opencores/aemb/rtl/verilog/aeMB_bpcu.v @@ -125,7 +125,7 @@ module aeMB_bpcu (/*AUTOARG*/ reg [31:2] rPC, xPC; reg [31:2] rPCLNK, xPCLNK; - assign iwb_adr_o = rIPC[IW-1:2]; + assign iwb_adr_o = gena ? xIPC[IW-1:2] : rIPC[IW-1:2]; //IJB always @(/*AUTOSENSE*/rBRA or rIPC or rPC or rRESULT) begin //xPCLNK <= (^rATOM) ? rPC : rPC; @@ -168,7 +168,8 @@ module aeMB_bpcu (/*AUTOARG*/ rATOM <= 2'h0; rBRA <= 1'h0; rDLY <= 1'h0; - rIPC <= 30'h0; +// rIPC <= 30'h0; + rIPC <= 30'h3fffffff; // DWORD aligned address rPC <= 30'h0; rPCLNK <= 30'h0; // End of automatics diff --git a/usrp2/opencores/aemb/rtl/verilog/aeMB_core_BE.v b/usrp2/opencores/aemb/rtl/verilog/aeMB_core_BE.v index 9ffa20ff2..38ca3a023 100644 --- a/usrp2/opencores/aemb/rtl/verilog/aeMB_core_BE.v +++ b/usrp2/opencores/aemb/rtl/verilog/aeMB_core_BE.v @@ -10,12 +10,10 @@ module aeMB_core_BE parameter MUL=0, parameter BSF=0) (input sys_clk_i, input sys_rst_i, - - output iwb_stb_o, - output [ISIZ-1:0] iwb_adr_o, - input [31:0] iwb_dat_i, - input iwb_ack_i, - + // Instruction port + output [14:0] if_adr, + input [31:0] if_dat, + // Data port output dwb_we_o, output dwb_stb_o, output [DSIZ-1:0] dwb_adr_o, @@ -28,17 +26,28 @@ module aeMB_core_BE input sys_int_i, input sys_exc_i); - assign dwb_cyc_o = dwb_stb_o; + wire [ISIZ-1:0] iwb_adr_o; + wire [31:0] iwb_dat_i; + wire iwb_ack_i; + wire iwb_stb_o; + + assign dwb_cyc_o = dwb_stb_o; + assign iwb_ack_i = 1'b1; + assign if_adr = iwb_adr_o[14:0]; + assign iwb_dat_i = if_dat; + + // Note some "wishbone" instruction fetch signals pruned on external interface + // but not propogated change deep into aeMB. aeMB_edk32 #(.IW(ISIZ),.DW(DSIZ),.MUL(MUL),.BSF(BSF)) aeMB_edk32 (.sys_clk_i(sys_clk_i), .sys_rst_i(sys_rst_i), - + // Instruction Port .iwb_stb_o(iwb_stb_o), .iwb_adr_o(iwb_adr_o[ISIZ-1:2]), .iwb_ack_i(iwb_ack_i), .iwb_dat_i(iwb_dat_i), - + // Data port .dwb_wre_o(dwb_we_o), .dwb_stb_o(dwb_stb_o), .dwb_adr_o(dwb_adr_o[DSIZ-1:2]), diff --git a/usrp2/top/u2_core/u2_core.v b/usrp2/top/u2_core/u2_core.v index df74c7dba..5e0b569cc 100755 --- a/usrp2/top/u2_core/u2_core.v +++ b/usrp2/top/u2_core/u2_core.v @@ -284,8 +284,8 @@ module u2_core aeMB_core_BE #(.ISIZ(16),.DSIZ(16),.MUL(0),.BSF(1)) aeMB (.sys_clk_i(wb_clk), .sys_rst_i(wb_rst), // Instruction Wishbone bus to I-RAM - .iwb_stb_o(iwb_stb),.iwb_adr_o(iwb_adr), - .iwb_dat_i(iwb_dat),.iwb_ack_i(iwb_ack), + .if_adr(if_adr), + .if_dat(if_dat), // Data Wishbone bus to system bus fabric .dwb_we_o(m0_we),.dwb_stb_o(m0_stb),.dwb_dat_o(m0_dat_i),.dwb_adr_o(m0_adr), .dwb_dat_i(m0_dat_o),.dwb_ack_i(m0_ack),.dwb_sel_o(m0_sel),.dwb_cyc_o(m0_cyc), @@ -299,7 +299,7 @@ module u2_core // I-port connects directly to processor and ram loader wire flush_icache; - ram_harv_cache #(.AWIDTH(15),.RAM_SIZE(RAM_SIZE),.ICWIDTH(7),.DCWIDTH(6)) + ram_harvard #(.AWIDTH(15),.RAM_SIZE(RAM_SIZE),.ICWIDTH(7),.DCWIDTH(6)) sys_ram(.wb_clk_i(wb_clk),.wb_rst_i(wb_rst), .ram_loader_adr_i(ram_loader_adr[14:0]), .ram_loader_dat_i(ram_loader_dat), @@ -307,8 +307,8 @@ module u2_core .ram_loader_we_i(ram_loader_we), .ram_loader_ack_o(ram_loader_ack), .ram_loader_done_i(ram_loader_done), - .iwb_adr_i(iwb_adr[14:0]), .iwb_stb_i(iwb_stb), - .iwb_dat_o(iwb_dat), .iwb_ack_o(iwb_ack), + .if_adr(if_adr), + .if_data(if_dat), .dwb_adr_i(s0_adr[14:0]), .dwb_dat_i(s0_dat_o), .dwb_dat_o(s0_dat_i), .dwb_we_i(s0_we), .dwb_ack_o(s0_ack), .dwb_stb_i(s0_stb), .dwb_sel_i(s0_sel), diff --git a/usrp2/top/u2_rev3/Makefile b/usrp2/top/u2_rev3/Makefile index 80d09acb7..bfebcac8b 100644 --- a/usrp2/top/u2_rev3/Makefile +++ b/usrp2/top/u2_rev3/Makefile @@ -66,6 +66,7 @@ control_lib/mux4.v \ control_lib/mux8.v \ control_lib/nsgpio.v \ control_lib/ram_2port.v \ +control_lib/ram_harvard.v \ control_lib/ram_harv_cache.v \ control_lib/ram_loader.v \ control_lib/setting_reg.v \ -- cgit v1.2.3 From 1d38c098122746ff34c0c1f16668b44d7337175d Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 20 May 2010 16:48:59 -0700 Subject: send bigger packets to reduce cpu load --- usrp2/control_lib/newfifo/packet_generator.v | 2 +- usrp2/top/u1e/u1e_core.v | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/usrp2/control_lib/newfifo/packet_generator.v b/usrp2/control_lib/newfifo/packet_generator.v index e5bfe5b26..6e8b45ccd 100644 --- a/usrp2/control_lib/newfifo/packet_generator.v +++ b/usrp2/control_lib/newfifo/packet_generator.v @@ -5,7 +5,7 @@ module packet_generator output reg [7:0] data_o, output sof_o, output eof_o, output src_rdy_o, input dst_rdy_i); - localparam len = 32'd100; + localparam len = 32'd2000; reg [31:0] state; reg [31:0] seq; diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 48b5bd010..ee193ffb9 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -43,6 +43,7 @@ module u1e_core wire tx_src_rdy, tx_dst_rdy, rx_src_rdy, rx_dst_rdy; reg [15:0] tx_frame_len; wire [15:0] rx_frame_len; + wire [7:0] rate; wire bus_error; @@ -76,7 +77,6 @@ module u1e_core `endif // LOOPBACK `ifdef TIMED - wire [7:0] rate; // TX side wire tx_enable, tx_src_rdy_int, tx_dst_rdy_int; @@ -362,7 +362,7 @@ module u1e_core assign debug_clk = { EM_CLK, clk_fpga }; assign debug = { { rx_have_data, tx_have_space, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, rx_overrun, tx_underrun }, - { EM_A[8:1] }, + { tx_src_rdy, tx_src_rdy_int, tx_dst_rdy, tx_dst_rdy_int, rx_src_rdy, rx_src_rdy_int, rx_dst_rdy, rx_dst_rdy_int }, { EM_D } }; //assign debug = { phase[23:8], txsync, txblank, tx }; -- cgit v1.2.3 From 268324b62898a916c0ef01e9336c34cd4ae1ff93 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Fri, 21 May 2010 15:56:01 -0700 Subject: fix double declaration --- usrp2/control_lib/newfifo/fifo36_to_ll8.v | 1 - 1 file changed, 1 deletion(-) diff --git a/usrp2/control_lib/newfifo/fifo36_to_ll8.v b/usrp2/control_lib/newfifo/fifo36_to_ll8.v index 0dee1dfc6..9604d0e38 100644 --- a/usrp2/control_lib/newfifo/fifo36_to_ll8.v +++ b/usrp2/control_lib/newfifo/fifo36_to_ll8.v @@ -55,6 +55,5 @@ module fifo36_to_ll8 assign advance = ll_src_rdy & ll_dst_rdy; assign f36_dst_rdy_o = advance & ((state==3)|ll_eof); - assign debug = state; endmodule // ll8_to_fifo36 -- cgit v1.2.3 From d3e6f630945076cc9d5fb91e86e1caf0b554ac89 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Fri, 21 May 2010 15:56:18 -0700 Subject: fifo36_to_ll8 and fifo pacer need a real fifo between them or they deadlock (by design) --- usrp2/control_lib/newfifo/packet_verifier32.v | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/usrp2/control_lib/newfifo/packet_verifier32.v b/usrp2/control_lib/newfifo/packet_verifier32.v index 065607b6c..06a13d242 100644 --- a/usrp2/control_lib/newfifo/packet_verifier32.v +++ b/usrp2/control_lib/newfifo/packet_verifier32.v @@ -7,10 +7,17 @@ module packet_verifier32 wire [7:0] ll_data; wire ll_sof_n, ll_eof_n, ll_src_rdy_n, ll_dst_rdy; + wire [35:0] data_int; + wire src_rdy_int, dst_rdy_int; + + fifo_short #(.WIDTH(36)) fifo_short + (.clk(clk), .reset(reset), .clear(clear), + .datain(data_i), .src_rdy_i(src_rdy_i), .dst_rdy_o(dst_rdy_o), + .dataout(data_int), .src_rdy_o(src_rdy_int), .dst_rdy_i(dst_rdy_int)); fifo36_to_ll8 f36_to_ll8 (.clk(clk), .reset(reset), .clear(clear), - .f36_data(data_i), .f36_src_rdy_i(src_rdy_i), .f36_dst_rdy_o(dst_rdy_o), + .f36_data(data_int), .f36_src_rdy_i(src_rdy_int), .f36_dst_rdy_o(dst_rdy_int), .ll_data(ll_data), .ll_sof_n(ll_sof_n), .ll_eof_n(ll_eof_n), .ll_src_rdy_n(ll_src_rdy_n), .ll_dst_rdy_n(~ll_dst_rdy)); -- cgit v1.2.3 From 6f63773d7425dd952c5ca24da618c22c486ae294 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 24 May 2010 11:34:42 -0700 Subject: test full width packets --- usrp2/control_lib/newfifo/packet32_tb.v | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 usrp2/control_lib/newfifo/packet32_tb.v diff --git a/usrp2/control_lib/newfifo/packet32_tb.v b/usrp2/control_lib/newfifo/packet32_tb.v new file mode 100644 index 000000000..82bb09c29 --- /dev/null +++ b/usrp2/control_lib/newfifo/packet32_tb.v @@ -0,0 +1,27 @@ + + +module packet32_tb(); + + wire [35:0] data; + wire src_rdy, dst_rdy; + + wire clear = 0; + reg clk = 0; + reg reset = 1; + + always #10 clk <= ~clk; + initial #1000 reset <= 0; + + initial $dumpfile("packet32_tb.vcd"); + initial $dumpvars(0,packet32_tb); + + wire [31:0] total, crc_err, seq_err, len_err; + + packet_generator32 pkt_gen (.clk(clk), .reset(reset), .clear(clear), + .data_o(data), .src_rdy_o(src_rdy), .dst_rdy_i(dst_rdy)); + + packet_verifier32 pkt_ver (.clk(clk), .reset(reset), .clear(clear), + .data_i(data), .src_rdy_i(src_rdy), .dst_rdy_o(dst_rdy), + .total(total), .crc_err(crc_err), .seq_err(seq_err), .len_err(len_err)); + +endmodule // packet32_tb -- cgit v1.2.3 From d32cedbf00eb342d999832737f9f1ba2109ef2ad Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 24 May 2010 14:21:03 -0700 Subject: fixes from IJB from 5/24. Basically connect unconnected wires. --- usrp2/control_lib/ram_harvard.v | 2 ++ usrp2/top/u2_core/u2_core.v | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/usrp2/control_lib/ram_harvard.v b/usrp2/control_lib/ram_harvard.v index 6711da366..3c00f87c7 100644 --- a/usrp2/control_lib/ram_harvard.v +++ b/usrp2/control_lib/ram_harvard.v @@ -36,6 +36,8 @@ module ram_harvard reg stb_d1; + assign ram_loader_ack_o = ram_loader_stb_i; + dpram32 #(.AWIDTH(AWIDTH),.RAM_SIZE(RAM_SIZE)) sys_ram (.clk(wb_clk_i), diff --git a/usrp2/top/u2_core/u2_core.v b/usrp2/top/u2_core/u2_core.v index 5e0b569cc..600bd7f3f 100755 --- a/usrp2/top/u2_core/u2_core.v +++ b/usrp2/top/u2_core/u2_core.v @@ -259,8 +259,9 @@ module u2_core // /////////////////////////////////////////////////////////////////// // RAM Loader - wire [31:0] ram_loader_dat, iwb_dat; - wire [15:0] ram_loader_adr, iwb_adr; + wire [31:0] ram_loader_dat, if_dat; + wire [15:0] ram_loader_adr; + wire [14:0] if_adr; wire [3:0] ram_loader_sel; wire ram_loader_stb, ram_loader_we, ram_loader_ack; wire iwb_ack, iwb_stb; -- cgit v1.2.3 From a1284e5d02fbb9e0b7cf541a9ffe501707d37c8c Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 26 May 2010 18:45:01 -0700 Subject: experimental mods to make ram loader fully synchronous. Based on IJB's work --- usrp2/control_lib/ram_harvard.v | 12 +- usrp2/control_lib/ram_loader.v | 460 ++++++++++++++++++++++------------------ usrp2/top/u2_core/u2_core.v | 29 ++- 3 files changed, 266 insertions(+), 235 deletions(-) diff --git a/usrp2/control_lib/ram_harvard.v b/usrp2/control_lib/ram_harvard.v index 3c00f87c7..948f9b36f 100644 --- a/usrp2/control_lib/ram_harvard.v +++ b/usrp2/control_lib/ram_harvard.v @@ -13,10 +13,9 @@ module ram_harvard // Firmware download port. input [AWIDTH-1:0] ram_loader_adr_i, input [31:0] ram_loader_dat_i, - input ram_loader_stb_i, input [3:0] ram_loader_sel_i, + input ram_loader_stb_i, input ram_loader_we_i, - output ram_loader_ack_o, input ram_loader_done_i, // Instruction fetch port. input [AWIDTH-1:0] if_adr, @@ -35,9 +34,6 @@ module ram_harvard reg ack_d1; reg stb_d1; - - assign ram_loader_ack_o = ram_loader_stb_i; - dpram32 #(.AWIDTH(AWIDTH),.RAM_SIZE(RAM_SIZE)) sys_ram (.clk(wb_clk_i), @@ -46,7 +42,8 @@ module ram_harvard .dat1_o(if_data), .we1_i(ram_loader_done_i ? 1'b0 : ram_loader_we_i), .en1_i(ram_loader_done_i ? 1'b1 : ram_loader_stb_i), - .sel1_i(ram_loader_done_i ? 4'hF : ram_loader_sel_i), + //.sel1_i(ram_loader_done_i ? 4'hF : ram_loader_sel_i), + .sel1_i(ram_loader_sel_i), // Sel is only for writes anyway .adr2_i(dwb_adr_i), .dat2_i(dwb_dat_i), .dat2_o(dwb_dat_o), @@ -68,6 +65,5 @@ module ram_harvard stb_d1 <= 0; else stb_d1 <= dwb_stb_i; - -endmodule // ram_harv_cache +endmodule // ram_harvard diff --git a/usrp2/control_lib/ram_loader.v b/usrp2/control_lib/ram_loader.v index cb67de739..c53ea7aa7 100644 --- a/usrp2/control_lib/ram_loader.v +++ b/usrp2/control_lib/ram_loader.v @@ -1,225 +1,261 @@ +module ram_loader + #(parameter AWIDTH=16, RAM_SIZE=16384) + ( + // Wishbone I/F and clock domain + input wb_clk, + input dsp_clk, + input ram_loader_rst, + output wire [31:0] wb_dat, + output wire [AWIDTH-1:0] wb_adr, + output wb_stb, + output reg [3:0] wb_sel, + output wb_we, + output reg ram_loader_done, + // CPLD signals and clock domain + input cpld_clk, + input cpld_din, + output reg cpld_start, + output reg cpld_mode, + output reg cpld_done, + input cpld_detached + ); -// Adapted from VHDL code in spi_boot by Arnim Legauer -// Added a full wishbone master interface (32-bit) - -module ram_loader #(parameter AWIDTH=16, RAM_SIZE=16384) - (input clk_i, input rst_i, - // CPLD Interface - input cfg_clk_i, input cfg_data_i, - output start_o, output mode_o, output done_o, - input detached_i, - // Wishbone interface - output wire [31:0] wb_dat_o, - output reg [AWIDTH-1:0] wb_adr_o, - output wb_stb_o, - output wb_cyc_o, - output reg [3:0] wb_sel_o, - output reg wb_we_o, - input wb_ack_i, - output ram_loader_done_o); + localparam S0 = 0; + localparam S1 = 1; + localparam S2 = 2; + localparam S3 = 3; + localparam S4 = 4; + localparam S5 = 5; + localparam S6 = 6; + localparam RESET = 7; - // FSM to control start signal, clocked on main clock - localparam FSM1_WAIT_DETACH = 2'b00; - localparam FSM1_CHECK_NO_DONE = 2'b01; - localparam FSM1_WAIT_DONE = 2'b10; - - reg [1:0] start_fsm_q, start_fsm_s; - reg start_q, enable_q, start_s, enable_s; - reg done_q, done_s; + localparam WB_IDLE = 0; + localparam WB_WRITE = 1; + + + reg [AWIDTH+2:0] count; // 3 LSB's count bits in, the MSB's generate the Wishbone address + reg [6:0] shift_reg; + reg [7:0] data_reg; + reg sampled_clk; + reg sampled_clk_meta; + reg sampled_din; + reg inc_count; + reg load_data_reg; + reg shift; + reg wb_state, wb_next_state; + reg [2:0] state, next_state; + + // + // CPLD clock doesn't free run and is approximately 12.5MHz. + // Use 50MHz Wishbone clock to sample it as a signal and avoid having + // an extra clock domain for no reason. + // + + always @(posedge dsp_clk or posedge ram_loader_rst) + if (ram_loader_rst) + begin + sampled_clk_meta <= 1'b0; + sampled_clk <= 1'b0; + sampled_din <= 1'b0; + count <= 'h7FFF8; // Initialize so that address will be 0 when first byte fully received. + data_reg <= 0; + shift_reg <= 0; + end + else + begin + sampled_clk_meta <= cpld_clk; + sampled_clk <= sampled_clk_meta; + sampled_din <= cpld_din; + if (inc_count) + count <= count + 1'b1; + if (load_data_reg) + data_reg <= {shift_reg,sampled_din}; + if (shift) + shift_reg <= {shift_reg[5:0],sampled_din}; + end // else: !if(ram_loader_rst) - always @(posedge clk_i or posedge rst_i) - if(rst_i) - begin - start_fsm_q <= FSM1_WAIT_DETACH; - start_q <= 1'b0; - enable_q <= 1'b0; - end + + always @(posedge dsp_clk or posedge ram_loader_rst) + if (ram_loader_rst) + state <= RESET; else - begin - start_fsm_q <= start_fsm_s; - enable_q <= enable_s; - start_q <= start_s; - end // else: !if(rst_i) - + state <= next_state; + + always @* - case(start_fsm_q) - FSM1_WAIT_DETACH: - if(detached_i == 1'b1) - begin - start_fsm_s <= FSM1_CHECK_NO_DONE; - enable_s <= 1'b1; - start_s <= 1'b1; - end - else - begin - start_fsm_s <= FSM1_WAIT_DETACH; - enable_s <= enable_q; - start_s <= start_q; - end // else: !if(detached_i == 1'b1) - FSM1_CHECK_NO_DONE: - if(~done_q) - begin - start_fsm_s <= FSM1_WAIT_DONE; - enable_s <= enable_q; - start_s <= start_q; - end - else - begin - start_fsm_s <= FSM1_CHECK_NO_DONE; - enable_s <= enable_q; - start_s <= start_q; - end // else: !if(~done_q) - FSM1_WAIT_DONE: - if(done_q) - begin - start_fsm_s <= FSM1_WAIT_DETACH; - enable_s <= 1'b0; - start_s <= 1'b0; - end - else - begin - start_fsm_s <= FSM1_WAIT_DONE; - enable_s <= enable_q; - start_s <= start_q; - end // else: !if(done_q) - default: - begin - start_fsm_s <= FSM1_WAIT_DETACH; - enable_s <= enable_q; - start_s <= start_q; - end // else: !if(done_q) - endcase // case(start_fsm_q) - - // FSM running on data clock - - localparam FSM2_IDLE = 3'b000; - localparam FSM2_WE_ON = 3'b001; - localparam FSM2_WE_OFF = 3'b010; - localparam FSM2_INC_ADDR1 = 3'b011; - localparam FSM2_INC_ADDR2 = 3'b100; - localparam FSM2_FINISHED = 3'b101; - - reg [AWIDTH-1:0] addr_q; - reg [7:0] shift_dat_q, ser_dat_q; - reg [2:0] bit_q, fsm_q, fsm_s; - reg bit_ovfl_q, ram_we_s, ram_we_q, mode_q, mode_s, inc_addr_s; - - always @(posedge cfg_clk_i or posedge rst_i) - if(rst_i) - begin - addr_q <= 0; - shift_dat_q <= 8'd0; - ser_dat_q <= 8'd0; - bit_q <= 3'd0; - bit_ovfl_q <= 1'b0; - fsm_q <= FSM2_IDLE; - ram_we_q <= 1'b0; - done_q <= 1'b0; - mode_q <= 1'b0; - end + begin + // Defaults + next_state = state; + cpld_start = 1'b0; + shift = 1'b0; + inc_count = 0; + load_data_reg = 1'b0; + ram_loader_done = 1'b0; + cpld_mode = 1'b0; + cpld_done = 1'b1; + + + + case (state) //synthesis parallel_case full_case + // After reset wait until CPLD indicates its detached. + RESET: begin + if (cpld_detached) + next_state = S0; + else + next_state = RESET; + end + + // Assert cpld_start to signal the CPLD its to start sending serial clock and data. + // Assume cpld_clk is low as we transition into search for first rising edge + S0: begin + cpld_start = 1'b1; + cpld_done = 1'b0; + if (~cpld_detached) + next_state = S2; + else + next_state = S0; + end + + // + S1: begin + cpld_start = 1'b1; + cpld_done = 1'b0; + if (sampled_clk) + begin + // Found rising edge on cpld_clk. + if (count[2:0] == 3'b111) + // Its the last bit of a byte, send it out to the Wishbone bus. + begin + load_data_reg = 1'b1; + inc_count = 1'b1; + end + else + // Shift databit into LSB of shift register and increment count + begin + shift = 1'b1; + inc_count = 1'b1; + end // else: !if(count[2:0] == 3'b111) + next_state = S2; + end // if (sampled_clk) + else + next_state = S1; + end // case: S1 + + // + S2: begin + cpld_start = 1'b1; + cpld_done = 1'b0; + if (~sampled_clk) + // Found negative edge of clock + if (count[AWIDTH+2:3] == RAM_SIZE-1) // NOTE need to change this constant + // All firmware now downloaded + next_state = S3; + else + next_state = S1; + else + next_state = S2; + end // case: S2 + + // Now that terminal count is reached and all firmware is downloaded signal CPLD that download is done + // and that mode is now SPI mode. + S3: begin + if (sampled_clk) + begin + cpld_mode = 1'b1; + cpld_done = 1'b1; + next_state = S4; + end + else + next_state = S3; + end + + // Search for negedge of cpld_clk whilst keeping done sequence asserted. + // Keep done assserted + S4: begin + cpld_mode = 1'b1; + cpld_done = 1'b1; + if (~sampled_clk) + next_state = S5; + else + next_state = S4; + end + + // Search for posedge of cpld_clk whilst keeping done sequence asserted. + S5: begin + cpld_mode = 1'b1; + cpld_done = 1'b1; + if (sampled_clk) + next_state = S6; + else + next_state = S5; + end + + // Stay in this state until reset/power down + S6: begin + ram_loader_done = 1'b1; + cpld_done = 1'b1; + cpld_mode = 1'b1; + next_state = S6; + end + + endcase // case(state) + end + + always @(posedge dsp_clk or posedge ram_loader_rst) + if (ram_loader_rst) + wb_state <= WB_IDLE; else - begin - if(inc_addr_s) - addr_q <= addr_q + 1; - if(enable_q) - begin - bit_q <= bit_q + 1; - bit_ovfl_q <= (bit_q == 3'd7); - shift_dat_q[0] <= cfg_data_i; - shift_dat_q[7:1] <= shift_dat_q[6:0]; - end - if(bit_ovfl_q) - ser_dat_q <= shift_dat_q; - - fsm_q <= fsm_s; - - ram_we_q <= ram_we_s; - - if(done_s) - done_q <= 1'b1; - mode_q <= mode_s; - end // else: !if(rst_i) + wb_state <= wb_next_state; + reg do_write; + wire empty, full; + always @* begin - inc_addr_s <= 1'b0; - ram_we_s <= 1'b0; - done_s <= 1'b0; - fsm_s <= FSM2_IDLE; - mode_s <= 1'b0; - - case(fsm_q) - FSM2_IDLE : - if(start_q) - if(bit_ovfl_q) - fsm_s <= FSM2_WE_ON; - FSM2_WE_ON: - begin - ram_we_s <= 1'b1; - fsm_s <= FSM2_WE_OFF; - end - FSM2_WE_OFF: - begin - ram_we_s <= 1'b1; - fsm_s <= FSM2_INC_ADDR1; - end - FSM2_INC_ADDR1: - fsm_s <= FSM2_INC_ADDR2; - FSM2_INC_ADDR2: - if(addr_q == (RAM_SIZE-1)) - //if(&addr_q) - begin - fsm_s <= FSM2_FINISHED; - done_s <= 1'b1; - mode_s <= 1'b1; - end - else - begin - inc_addr_s <= 1'b1; - fsm_s <= FSM2_IDLE; - end // else: !if(&addr_q) - FSM2_FINISHED: - begin - fsm_s <= FSM2_FINISHED; - mode_s <= 1'b1; - end - endcase // case(fsm_q) + wb_next_state = wb_state; + do_write = 1'b0; + + case (wb_state) //synthesis full_case parallel_case + // + WB_IDLE: begin + if (load_data_reg) + // Data reg will load ready to write wishbone @ next clock edge + wb_next_state = WB_WRITE; + else + wb_next_state = WB_IDLE; + end + + // Drive address and data onto wishbone. + WB_WRITE: begin + do_write = 1'b1; + if (~full) + wb_next_state = WB_IDLE; + else + wb_next_state = WB_WRITE; + end + + endcase // case(wb_state) end // always @ * - assign start_o = start_q; - assign mode_o = mode_q; - assign done_o = start_q ? done_q : 1'b1; - wire [AWIDTH-1:0] ram_addr = addr_q; - wire [7:0] ram_data = ser_dat_q; - assign ram_loader_done_o = (fsm_q == FSM2_FINISHED); - - // wishbone master, only writes - reg [7:0] dat_holder; - assign wb_dat_o = {4{dat_holder}}; - assign wb_stb_o = wb_we_o; - assign wb_cyc_o = wb_we_o; + wire [1:0] count_out; + wire [7:0] data_out; + + fifo_xlnx_16x40_2clk crossclk + (.rst(ram_loader_rst), + .wr_clk(dsp_clk), .din({count[4:3],count[AWIDTH+2:3],data_reg}), .wr_en(do_write), .full(full), + .rd_clk(wb_clk), .dout({count_out,wb_adr,data_out}), .rd_en(~empty), .empty(empty)); + + assign wb_dat = {4{data_out}}; + + always @* + case(count_out[1:0]) //synthesis parallel_case full_case + 2'b00 : wb_sel = 4'b1000; + 2'b01 : wb_sel = 4'b0100; + 2'b10 : wb_sel = 4'b0010; + 2'b11 : wb_sel = 4'b0001; + endcase + + assign wb_we = ~empty; + assign wb_stb = ~empty; - always @(posedge clk_i or posedge rst_i) - if(rst_i) - begin - dat_holder <= 8'd0; - wb_adr_o <= 0; - wb_sel_o <= 4'b0000; - wb_we_o <= 1'b0; - end - else if(ram_we_q) - begin - dat_holder <= ram_data; - wb_adr_o <= ram_addr; - wb_we_o <= 1'b1; - case(ram_addr[1:0]) // Big Endian - 2'b00 : wb_sel_o <= 4'b1000; - 2'b01 : wb_sel_o <= 4'b0100; - 2'b10 : wb_sel_o <= 4'b0010; - 2'b11 : wb_sel_o <= 4'b0001; - endcase // case(ram_addr[1:0]) - end // if (ram_we_q) - else if(wb_ack_i) - wb_we_o <= 1'b0; - endmodule // ram_loader diff --git a/usrp2/top/u2_core/u2_core.v b/usrp2/top/u2_core/u2_core.v index 600bd7f3f..a90e2ced6 100755 --- a/usrp2/top/u2_core/u2_core.v +++ b/usrp2/top/u2_core/u2_core.v @@ -263,23 +263,22 @@ module u2_core wire [15:0] ram_loader_adr; wire [14:0] if_adr; wire [3:0] ram_loader_sel; - wire ram_loader_stb, ram_loader_we, ram_loader_ack; + wire ram_loader_stb, ram_loader_we; wire iwb_ack, iwb_stb; ram_loader #(.AWIDTH(16),.RAM_SIZE(RAM_SIZE)) - ram_loader (.clk_i(wb_clk),.rst_i(ram_loader_rst), + ram_loader (.wb_clk(wb_clk),.dsp_clk(dsp_clk),.ram_loader_rst(ram_loader_rst), + .wb_dat(ram_loader_dat),.wb_adr(ram_loader_adr), + .wb_stb(ram_loader_stb),.wb_sel(ram_loader_sel), + .wb_we(ram_loader_we), + .ram_loader_done(ram_loader_done), // CPLD Interface - .cfg_clk_i(cpld_clk), - .cfg_data_i(cpld_din), - .start_o(cpld_start_int), - .mode_o(cpld_mode_int), - .done_o(cpld_done_int), - .detached_i(cpld_detached), - // Wishbone Interface - .wb_dat_o(ram_loader_dat),.wb_adr_o(ram_loader_adr), - .wb_stb_o(ram_loader_stb),.wb_cyc_o(),.wb_sel_o(ram_loader_sel), - .wb_we_o(ram_loader_we),.wb_ack_i(ram_loader_ack), - .ram_loader_done_o(ram_loader_done)); - + .cpld_clk(cpld_clk), + .cpld_din(cpld_din), + .cpld_start(cpld_start_int), + .cpld_mode(cpld_mode_int), + .cpld_done(cpld_done_int), + .cpld_detached(cpld_detached)); + // ///////////////////////////////////////////////////////////////////////// // Processor aeMB_core_BE #(.ISIZ(16),.DSIZ(16),.MUL(0),.BSF(1)) @@ -305,7 +304,7 @@ module u2_core .ram_loader_adr_i(ram_loader_adr[14:0]), .ram_loader_dat_i(ram_loader_dat), .ram_loader_stb_i(ram_loader_stb), .ram_loader_sel_i(ram_loader_sel), - .ram_loader_we_i(ram_loader_we), .ram_loader_ack_o(ram_loader_ack), + .ram_loader_we_i(ram_loader_we), .ram_loader_done_i(ram_loader_done), .if_adr(if_adr), -- cgit v1.2.3 From 1c8fc02f8787b8f809335d18a6691c2d7510be9a Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 26 May 2010 18:45:46 -0700 Subject: change the debug pins, which makes it more reliable. This is unnerving. --- usrp2/top/u2_core/u2_core.v | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/usrp2/top/u2_core/u2_core.v b/usrp2/top/u2_core/u2_core.v index 600bd7f3f..fc2e10d52 100755 --- a/usrp2/top/u2_core/u2_core.v +++ b/usrp2/top/u2_core/u2_core.v @@ -683,7 +683,8 @@ module u2_core { wr2_flags, rd2_flags }, { GMII_TX_EN,3'd0, wr2_ready_i, wr2_ready_o, rd2_ready_i, rd2_ready_o } }; - assign debug_gpio_0 = debug_mac; //eth_mac_debug; + assign debug_gpio_0 = 0; + //debug_mac; //eth_mac_debug; assign debug_gpio_1 = 0; endmodule // u2_core -- cgit v1.2.3 From 2d45c8537171f8a82baf13674fbe9ccefa2cc0c0 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 1 Jun 2010 10:18:13 -0700 Subject: zero out debug pins. helps timing a little bit. --- usrp2/top/u2_core/u2_core_udp.v | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/usrp2/top/u2_core/u2_core_udp.v b/usrp2/top/u2_core/u2_core_udp.v index 1fe3aafd8..d2e842b1c 100644 --- a/usrp2/top/u2_core/u2_core_udp.v +++ b/usrp2/top/u2_core/u2_core_udp.v @@ -729,7 +729,15 @@ module u2_core // ///////////////////////////////////////////////////////////////////////////////////////// // Debug Pins + + assign debug_clk[1:0] = 2'b00; + assign debug = 32'd0; + assign debug_gpio_0 = 32'd0; + assign debug_gpio_1 = 32'd0; +endmodule // u2_core + + /* // FIFO Level Debugging reg [31:0] host_to_dsp_fifo,dsp_to_host_fifo,eth_mac_debug,serdes_to_dsp_fifo,dsp_to_serdes_fifo; @@ -756,15 +764,12 @@ module u2_core assign debug_clk[0] = GMII_RX_CLK; // wb_clk; assign debug_clk[1] = dsp_clk; -/* - wire mdio_cpy = MDIO; assign debug = { { 1'b0, s6_stb, s6_ack, s6_we, s6_sel[3:0] }, { s6_adr[15:8] }, { s6_adr[7:0] }, { 6'd0, mdio_cpy, MDC } }; -*/ -/* + assign debug = { { GMII_TXD }, { 5'd0, GMII_TX_EN, GMII_TX_ER, GMII_GTX_CLK }, { wr2_flags, rd2_flags }, @@ -773,9 +778,8 @@ module u2_core { 5'd0, GMII_RX_DV, GMII_RX_ER, GMII_RX_CLK }, { wr2_flags, rd2_flags }, { GMII_TX_EN,3'd0, wr2_ready_i, wr2_ready_o, rd2_ready_i, rd2_ready_o } }; - */ -// assign debug = debug_udp; + assign debug = debug_udp; assign debug = vrc_debug; assign debug_gpio_0 = { {pps_in, pps_int, 2'd0, vita_state}, {2'd0, rx_dst_rdy, rx_src_rdy, rx_data[99:96]}, @@ -784,14 +788,12 @@ module u2_core assign debug_gpio_1 = {vita_time[63:32] }; -/* - assign debug_gpio_1 = { { tx_f19_data[15:8] }, + assign debug_gpio_1 = { { tx_f19_data[15:8] }, { tx_f19_data[7:0] }, { 3'd0, tx_f19_src_rdy, tx_f19_dst_rdy, tx_f19_data[18:16] }, { 2'b0, rd2_ready_i, rd2_ready_o, rd2_flags } }; */ -endmodule // u2_core // wire debug_mux; // setting_reg #(.my_addr(5)) sr_debug (.clk(wb_clk),.rst(wb_rst),.strobe(set_stb),.addr(set_addr), -- cgit v1.2.3 From e5bc7a493252753ad9ddf6799e986fa19841221a Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 1 Jun 2010 15:50:06 -0700 Subject: vita49 tx and rx added in, all sample rates now at main system clock rate. --- usrp2/top/u1e/Makefile | 5 ++ usrp2/top/u1e/u1e.ucf | 50 ++++++------ usrp2/top/u1e/u1e.v | 68 ++++++++++++++-- usrp2/top/u1e/u1e_core.v | 204 ++++++++++++++++++++++++++++++----------------- 4 files changed, 220 insertions(+), 107 deletions(-) diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index 0277ef4f2..7f5085275 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -189,6 +189,11 @@ gpmc/gpmc_to_fifo_async.v \ gpmc/fifo_to_gpmc_async.v \ gpmc/fifo_watcher.v \ gpmc/gpmc_wb.v \ +vrt/vita_rx_control.v \ +vrt/vita_rx_framer.v \ +vrt/vita_tx_control.v \ +vrt/vita_tx_deframer.v \ +timing/time_compare.v \ top/u1e/u1e_core.v \ top/u1e/u1e.ucf \ top/u1e/timing.ucf \ diff --git a/usrp2/top/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf index 2caa46639..659a9dce5 100644 --- a/usrp2/top/u1e/u1e.ucf +++ b/usrp2/top/u1e/u1e.ucf @@ -163,33 +163,33 @@ NET "dip_sw<2>" LOC = "J4" ; NET "dip_sw<1>" LOC = "J6" ; NET "dip_sw<0>" LOC = "J7" ; -#NET "RXSYNC" LOC = "F22" ; #NET "reset_codec" LOC = "D22" ; -#NET "DB<11>" LOC = "E22" ; -#NET "DB<10>" LOC = "J19" ; -#NET "DB<9>" LOC = "H20" ; -#NET "DB<8>" LOC = "G19" ; -#NET "DB<7>" LOC = "F20" ; -#NET "DB<6>" LOC = "K16" ; -#NET "DB<5>" LOC = "J17" ; -#NET "DB<4>" LOC = "H22" ; -#NET "DB<3>" LOC = "G22" ; -#NET "DB<2>" LOC = "H17" ; -#NET "DB<1>" LOC = "H18" ; -#NET "DB<0>" LOC = "K20" ; -#NET "DA<11>" LOC = "J20" ; -#NET "DA<10>" LOC = "K19" ; -#NET "DA<9>" LOC = "K18" ; -#NET "DA<8>" LOC = "L22" ; -#NET "DA<7>" LOC = "K22" ; -#NET "DA<6>" LOC = "N22" ; -#NET "DA<5>" LOC = "M22" ; -#NET "DA<4>" LOC = "N20" ; -#NET "DA<3>" LOC = "N19" ; -#NET "DA<2>" LOC = "R22" ; -#NET "DA<1>" LOC = "P22" ; -#NET "DA<0>" LOC = "N17" ; +NET "RXSYNC" LOC = "F22" ; +NET "DB<11>" LOC = "E22" ; +NET "DB<10>" LOC = "J19" ; +NET "DB<9>" LOC = "H20" ; +NET "DB<8>" LOC = "G19" ; +NET "DB<7>" LOC = "F20" ; +NET "DB<6>" LOC = "K16" ; +NET "DB<5>" LOC = "J17" ; +NET "DB<4>" LOC = "H22" ; +NET "DB<3>" LOC = "G22" ; +NET "DB<2>" LOC = "H17" ; +NET "DB<1>" LOC = "H18" ; +NET "DB<0>" LOC = "K20" ; +NET "DA<11>" LOC = "J20" ; +NET "DA<10>" LOC = "K19" ; +NET "DA<9>" LOC = "K18" ; +NET "DA<8>" LOC = "L22" ; +NET "DA<7>" LOC = "K22" ; +NET "DA<6>" LOC = "N22" ; +NET "DA<5>" LOC = "M22" ; +NET "DA<4>" LOC = "N20" ; +NET "DA<3>" LOC = "N19" ; +NET "DA<2>" LOC = "R22" ; +NET "DA<1>" LOC = "P22" ; +NET "DA<0>" LOC = "N17" ; NET "TX<13>" LOC = "P19" ; NET "TX<12>" LOC = "R18" ; diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index 35818e8c8..3018ff100 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -26,18 +26,46 @@ module u1e inout [15:0] io_tx, inout [15:0] io_rx, - output [13:0] TX, output TXSYNC, output TXBLANK, - + output reg [13:0] TX, output reg TXSYNC, output TXBLANK, + input [11:0] DA, input [11:0] DB, input RXSYNC, + input PPS_IN ); - // FPGA-specific pins connections - wire clk_fpga; + // ///////////////////////////////////////////////////////////////////////// + // Clocking + wire clk_fpga, clk_fpga_in, clk_2x, dcm_rst, dcm_locked; IBUFGDS #(.IOSTANDARD("LVDS_33"), .DIFF_TERM("TRUE")) - clk_fpga_pin (.O(clk_fpga),.I(CLK_FPGA_P),.IB(CLK_FPGA_N)); + clk_fpga_pin (.O(clk_fpga_in),.I(CLK_FPGA_P),.IB(CLK_FPGA_N)); + + DCM #(.CLK_FEEDBACK ( "1X" ), + .CLKDV_DIVIDE ( 2.0 ), + .CLKFX_DIVIDE ( 1 ), + .CLKFX_MULTIPLY ( 2 ), + .CLKIN_DIVIDE_BY_2 ( "FALSE" ), + .CLKIN_PERIOD ( 15.625 ), + .CLKOUT_PHASE_SHIFT ( "NONE" ), + .DESKEW_ADJUST ( "SYSTEM_SYNCHRONOUS" ), + .DFS_FREQUENCY_MODE ( "LOW" ), + .DLL_FREQUENCY_MODE ( "LOW" ), + .DUTY_CYCLE_CORRECTION ( "TRUE" ), + .FACTORY_JF ( 16'h8080 ), + .PHASE_SHIFT ( 0 ), + .STARTUP_WAIT ( "FALSE" )) + clk_doubler (.CLKFB(clk_fpga), .CLKIN(clk_fpga_in), .RST(dcm_rst), + .DSSEN(0), .PSCLK(0), .PSEN(0), .PSINCDEC(0), .PSDONE(), + .CLKDV(), .CLKFX(), .CLKFX180(), + .CLK2X(clk_2x), .CLK2X180(), + .CLK0(clk_fpga), .CLK90(), .CLK180(), .CLK270(), + .LOCKED(dcm_locked), .STATUS()); + + //BUFG dspclk_BUFG (.I(dcm_out), .O(dsp_clk)); + //BUFG wbclk_BUFG (.I(clk_div), .O(wb_clk)); + - // SPI pins + // ///////////////////////////////////////////////////////////////////////// + // SPI wire mosi, sclk, miso; assign { db_sclk_tx, db_mosi_tx } = ~db_sen_tx ? {sclk,mosi} : 2'b0; assign { db_sclk_rx, db_mosi_rx } = ~db_sen_rx ? {sclk,mosi} : 2'b0; @@ -45,7 +73,27 @@ module u1e assign { cgen_sclk, cgen_mosi } = ~cgen_sen_b ? {sclk,mosi} : 2'b0; assign miso = (~db_sen_tx & db_miso_tx) | (~db_sen_rx & db_miso_rx) | (~sen_codec & miso_codec) | (~cgen_sen_b & cgen_miso); + + // ///////////////////////////////////////////////////////////////////////// + // TX DAC -- handle the interleaved data bus to DAC, with clock doubling DLL + + assign TXBLANK = 0; + wire [13:0] tx_i, tx_q; + always @(posedge clk_2x) + if(clk_fpga) + begin + TX <= tx_i; + TXSYNC <= 0; // Low indicates first data item + end + else + begin + TX <= tx_q; + TXSYNC <= 1; + end + + // ///////////////////////////////////////////////////////////////////////// + // Main U1E Core u1e_core u1e_core(.clk_fpga(clk_fpga), .rst_fpga(~debug_pb[2]), .debug_led(debug_led), .debug(debug), .debug_clk(debug_clk), .debug_pb(~debug_pb), .dip_sw(dip_sw), .debug_txd(FPGA_TXD), .debug_rxd(FPGA_RXD), @@ -59,10 +107,16 @@ module u1e .tx_have_space(overo_gpio144), .tx_underrun(overo_gpio145), .rx_have_data(overo_gpio146), .rx_overrun(overo_gpio147), .io_tx(io_tx), .io_rx(io_rx), - .tx(TX), .txsync(TXSYNC), .txblank(TXBLANK), + .tx_i(tx_i), .tx_q(tx_q), + .rx_i(DA), .rx_q(DB), .misc_gpio( {{overo_gpio128,overo_gpio163,overo_gpio170,overo_gpio176}, {overo_gpio0,overo_gpio14,overo_gpio21,overo_gpio22}, {overo_gpio23,overo_gpio64,overo_gpio65,overo_gpio127}}), .pps_in(PPS_IN) ); + + // ///////////////////////////////////////////////////////////////////////// + // Local Debug + // assign debug_clk = {clk_fpga, clk_2x }; + // assign debug = { TXSYNC, TXBLANK, TX }; endmodule // u1e diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index ee193ffb9..002b28f7a 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -1,7 +1,8 @@ //`define LOOPBACK 1 -`define TIMED 1 +//`define TIMED 1 +`define DSP 1 module u1e_core (input clk_fpga, input rst_fpga, @@ -18,14 +19,31 @@ module u1e_core input cgen_st_status, input cgen_st_ld, input cgen_st_refmon, output cgen_sync_b, output cgen_ref_sel, output tx_have_space, output tx_underrun, output rx_have_data, output rx_overrun, inout [15:0] io_tx, inout [15:0] io_rx, - output reg [13:0] tx, output reg txsync, output txblank, + output [13:0] tx_i, output [13:0] tx_q, + input [11:0] rx_i, input [11:0] rx_q, input [11:0] misc_gpio, input pps_in ); - + + localparam TXFIFOSIZE = 11; + localparam RXFIFOSIZE = 11; + localparam SR_TIME64 = 0; + localparam SR_RX_DSP = 0; + localparam SR_RX_CTRL = 0; + localparam SR_TX_DSP = 0; + localparam SR_TX_CTRL = 0; + wire wb_clk = clk_fpga; wire wb_rst = rst_fpga; + wire pps_int; + wire [63:0] vita_time; + reg [15:0] reg_leds, reg_cgen_ctrl, reg_test, xfer_rate; + + wire [7:0] set_addr; + wire [31:0] set_data; + wire set_stb; + // ///////////////////////////////////////////////////////////////////////////////////// // GPMC Slave to Wishbone Master localparam dw = 16; @@ -47,33 +65,36 @@ module u1e_core wire bus_error; - gpmc_async gpmc (.arst(wb_rst), - .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), - .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), - .EM_NOE(EM_NOE), - - .rx_have_data(rx_have_data), .tx_have_space(tx_have_space), - .bus_error(bus_error), .bus_reset(0), - - .wb_clk(wb_clk), .wb_rst(wb_rst), - .wb_adr_o(m0_adr), .wb_dat_mosi(m0_dat_mosi), .wb_dat_miso(m0_dat_miso), - .wb_sel_o(m0_sel), .wb_cyc_o(m0_cyc), .wb_stb_o(m0_stb), .wb_we_o(m0_we), - .wb_ack_i(m0_ack), - - .fifo_clk(wb_clk), .fifo_rst(wb_rst), - .tx_data_o(tx_data), .tx_src_rdy_o(tx_src_rdy), .tx_dst_rdy_i(tx_dst_rdy), - .rx_data_i(rx_data), .rx_src_rdy_i(rx_src_rdy), .rx_dst_rdy_o(rx_dst_rdy), - - .tx_frame_len(tx_frame_len), .rx_frame_len(rx_frame_len), - .debug(debug_gpmc)); + gpmc_async #(.TXFIFOSIZE(TXFIFOSIZE), .RXFIFOSIZE(RXFIFOSIZE)) + gpmc (.arst(wb_rst), + .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), + .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), + .EM_NOE(EM_NOE), + + .rx_have_data(rx_have_data), .tx_have_space(tx_have_space), + .bus_error(bus_error), .bus_reset(0), + + .wb_clk(wb_clk), .wb_rst(wb_rst), + .wb_adr_o(m0_adr), .wb_dat_mosi(m0_dat_mosi), .wb_dat_miso(m0_dat_miso), + .wb_sel_o(m0_sel), .wb_cyc_o(m0_cyc), .wb_stb_o(m0_stb), .wb_we_o(m0_we), + .wb_ack_i(m0_ack), + + .fifo_clk(wb_clk), .fifo_rst(wb_rst), + .tx_data_o(tx_data), .tx_src_rdy_o(tx_src_rdy), .tx_dst_rdy_i(tx_dst_rdy), + .rx_data_i(rx_data), .rx_src_rdy_i(rx_src_rdy), .rx_dst_rdy_o(rx_dst_rdy), + + .tx_frame_len(tx_frame_len), .rx_frame_len(rx_frame_len), + .debug(debug_gpmc)); + wire rx_sof = rx_data[32]; + wire rx_eof = rx_data[33]; + wire rx_src_rdy_int, rx_dst_rdy_int, tx_src_rdy_int, tx_dst_rdy_int; + `ifdef LOOPBACK fifo_cascade #(.WIDTH(36), .SIZE(9)) loopback_fifo (.clk(wb_clk), .reset(wb_rst), .clear(0), .datain(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy), .dataout(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); - wire rx_sof = rx_data[32]; - wire rx_eof = rx_data[33]; `endif // LOOPBACK `ifdef TIMED @@ -93,9 +114,7 @@ module u1e_core .total(total), .crc_err(crc_err), .seq_err(seq_err), .len_err(len_err)); // RX side - wire rx_enable, rx_src_rdy_int, rx_dst_rdy_int; - wire rx_sof = rx_data[32]; - wire rx_eof = rx_data[33]; + wire rx_enable; packet_generator32 pktgen32 (.clk(wb_clk), .reset(wb_rst), .clear(clear), @@ -108,7 +127,90 @@ module u1e_core .underrun(), .overrun(rx_overrun)); `endif // `ifdef TIMED + +`ifdef DSP + wire [31:0] debug_rx_dsp, vrc_debug, vrf_debug; + + // ///////////////////////////////////////////////////////////////////////// + // DSP RX + wire [31:0] sample_rx, sample_tx; + wire strobe_rx, strobe_tx; + wire rx1_dst_rdy, rx1_src_rdy; + wire [99:0] rx1_data; + + dsp_core_rx #(.BASE(SR_RX_DSP)) dsp_core_rx + (.clk(wb_clk),.rst(wb_rst), + .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .adc_a({rx_i,2'b0}),.adc_ovf_a(0),.adc_b({rx_q,2'b0}),.adc_ovf_b(0), + .sample(sample_rx), .run(run_rx_d1), .strobe(strobe_rx), + .debug(debug_rx_dsp) ); + + vita_rx_control #(.BASE(SR_RX_CTRL), .WIDTH(32)) vita_rx_control + (.clk(wb_clk), .reset(wb_rst), .clear(0), + .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .vita_time(vita_time), .overrun(overrun), + .sample(sample_rx), .run(run_rx), .strobe(strobe_rx), + .sample_fifo_o(rx1_data), .sample_fifo_dst_rdy_i(rx1_dst_rdy), .sample_fifo_src_rdy_o(rx1_src_rdy), + .debug_rx(vrc_debug)); + + vita_rx_framer #(.BASE(SR_RX_CTRL), .MAXCHAN(1)) vita_rx_framer + (.clk(wb_clk), .reset(wb_rst), .clear(0), + .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .sample_fifo_i(rx1_data), .sample_fifo_dst_rdy_o(rx1_dst_rdy), .sample_fifo_src_rdy_i(rx1_src_rdy), + .data_o(rx_data), .dst_rdy_i(rx_dst_rdy), .src_rdy_o(rx_src_rdy), + .fifo_occupied(), .fifo_full(), .fifo_empty(), + .debug_rx(vrf_debug) ); + + // /////////////////////////////////////////////////////////////////////////////////// + // DSP TX + + wire [99:0] tx1_data; + wire tx1_src_rdy, tx1_dst_rdy; + wire [15:0] tx_i_int, tx_q_int; + wire [31:0] debug_vtc, debug_vtd, debug_vt; + + vita_tx_deframer #(.BASE(SR_TX_CTRL), .MAXCHAN(1)) vita_tx_deframer + (.clk(wb_clk), .reset(wb_rst), .clear(0), + .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .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(wb_clk), .reset(wb_rst), .clear(0), + .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .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), + .debug(debug_vtc) ); + + dsp_core_tx #(.BASE(SR_TX_DSP)) dsp_core_tx + (.clk(wb_clk),.rst(wb_rst), + .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .sample(sample_tx), .run(run_tx), .strobe(strobe_tx), + .dac_a(tx_i_int),.dac_b(tx_q_int), + .debug(debug_tx_dsp) ); + + assign tx_i = tx_i_int[15:2]; + assign tx_q = tx_q_int[15:2]; + +`else // !`ifdef DSP + // Dummy DSP signal generator for test purposes + wire [23:0] tx_i_int, tx_q_int; + wire [23:0] freq = {reg_test,8'd0}; + reg [23:0] phase; + + always @(posedge wb_clk) + phase <= phase + freq; + cordic_z24 #(.bitwidth(24)) tx_cordic + (.clock(wb_clk), .reset(wb_rst), .enable(1), + .xi(24'd2500000), .yi(24'd0), .zi(phase), .xo(tx_i_int), .yo(tx_q_int), .zo()); + + assign tx_i = tx_i_int[23:10]; + assign tx_q = tx_q_int[23:10]; +`endif // !`ifdef DSP + // ///////////////////////////////////////////////////////////////////////////////////// // Wishbone Intercon, single master wire [dw-1:0] s0_dat_mosi, s1_dat_mosi, s0_dat_miso, s1_dat_miso, s2_dat_mosi, s3_dat_mosi, s2_dat_miso, s3_dat_miso, @@ -181,8 +283,6 @@ module u1e_core // ///////////////////////////////////////////////////////////////////////////////////// // Slave 0, Misc LEDs, Switches, controls - reg [15:0] reg_leds, reg_cgen_ctrl, reg_test, xfer_rate; - localparam REG_LEDS = 7'd0; // out localparam REG_SWITCHES = 7'd2; // in localparam REG_CGEN_CTRL = 7'd4; // out @@ -288,10 +388,6 @@ module u1e_core // ///////////////////////////////////////////////////////////////////////// // Settings Bus -- Slave #5 - wire [7:0] set_addr; - wire [31:0] set_data; - wire set_stb; - // only have 32 regs, 32 bits each with current setup... settings_bus_16LE #(.AWIDTH(11),.RWIDTH(11-4-2)) settings_bus_16LE (.wb_clk(wb_clk),.wb_rst(wb_rst),.wb_adr_i(s5_adr),.wb_dat_i(s5_dat_mosi), @@ -311,51 +407,9 @@ module u1e_core // ///////////////////////////////////////////////////////////////////////// // VITA Timing - localparam SR_TIME64 = 0; - wire pps_int; - wire [63:0] vita_time; - time_64bit #(.TICKS_PER_SEC(32'd64000000),.BASE(SR_TIME64)) time_64bit (.clk(wb_clk), .rst(wb_rst), .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), .pps(pps_in), .vita_time(vita_time), .pps_int(pps_int)); - - - // ///////////////////////////////////////////////////////////////////////// - // TX - - assign txblank = 0; - - wire [23:0] freq = {reg_test,8'd0}; - - reg [23:0] tx_q_hold; - wire [23:0] tx_i, tx_q; - - reg tx_stb; - always @(posedge wb_clk) - tx_stb <= ~tx_stb; - - always @(posedge wb_clk) - if(tx_stb) - tx <= tx_i[23:10]; - else - tx <= tx_q_hold[23:10]; - - always @(posedge wb_clk) - if(tx_stb) - tx_q_hold <= tx_q; - - always @(posedge wb_clk) - txsync <= ~tx_stb; // TX Sync low indicates first data item - // We invert here if we don't use inv_txsync in the 9862 - - reg [23:0] phase; - always @(posedge wb_clk) - if(tx_stb) - phase <= phase + freq; - - cordic_z24 #(.bitwidth(24)) tx_cordic - (.clock(wb_clk), .reset(wb_rst), .enable(1), - .xi(24'd2500000), .yi(24'd0), .zi(phase), .xo(tx_i), .yo(tx_q), .zo()); // ///////////////////////////////////////////////////////////////////////////////////// // Debug circuitry -- cgit v1.2.3 From 552c3477734c6c302c53fe039d6e85134fcf210c Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 1 Jun 2010 16:20:24 -0700 Subject: assign addresses for the settings regs --- usrp2/top/u1e/u1e_core.v | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 002b28f7a..ed4176ca5 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -27,11 +27,12 @@ module u1e_core localparam TXFIFOSIZE = 11; localparam RXFIFOSIZE = 11; - localparam SR_TIME64 = 0; - localparam SR_RX_DSP = 0; - localparam SR_RX_CTRL = 0; - localparam SR_TX_DSP = 0; - localparam SR_TX_CTRL = 0; + + localparam SR_RX_DSP = 0; // 7 regs + localparam SR_RX_CTRL = 8; // 9 regs + localparam SR_TX_DSP = 17; // 5 regs + localparam SR_TX_CTRL = 24; // 2 regs + localparam SR_TIME64 = 28; // 4 regs wire wb_clk = clk_fpga; wire wb_rst = rst_fpga; -- cgit v1.2.3 From 7a776f9fce357b298566d0a417a1417c4484723c Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 1 Jun 2010 18:23:09 -0700 Subject: use DDR regs instead of a 2nd clock --- usrp2/top/u1e/u1e.v | 54 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index 3018ff100..523aae1b9 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -1,6 +1,8 @@ `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// +//`define DCM 1 + module u1e (input CLK_FPGA_P, input CLK_FPGA_N, // Diff output [2:0] debug_led, output [31:0] debug, output [1:0] debug_clk, @@ -26,7 +28,7 @@ module u1e inout [15:0] io_tx, inout [15:0] io_rx, - output reg [13:0] TX, output reg TXSYNC, output TXBLANK, + output [13:0] TX, output TXSYNC, output TXBLANK, input [11:0] DA, input [11:0] DB, input RXSYNC, input PPS_IN @@ -34,11 +36,13 @@ module u1e // ///////////////////////////////////////////////////////////////////////// // Clocking - wire clk_fpga, clk_fpga_in, clk_2x, dcm_rst, dcm_locked; + wire clk_fpga, clk_fpga_in; IBUFGDS #(.IOSTANDARD("LVDS_33"), .DIFF_TERM("TRUE")) clk_fpga_pin (.O(clk_fpga_in),.I(CLK_FPGA_P),.IB(CLK_FPGA_N)); +`ifdef DCM + wire clk_2x, dcm_rst, dcm_locked; DCM #(.CLK_FEEDBACK ( "1X" ), .CLKDV_DIVIDE ( 2.0 ), .CLKFX_DIVIDE ( 1 ), @@ -59,11 +63,10 @@ module u1e .CLK2X(clk_2x), .CLK2X180(), .CLK0(clk_fpga), .CLK90(), .CLK180(), .CLK270(), .LOCKED(dcm_locked), .STATUS()); - - //BUFG dspclk_BUFG (.I(dcm_out), .O(dsp_clk)); - //BUFG wbclk_BUFG (.I(clk_div), .O(wb_clk)); - - +`else // !`ifdef DCM + BUFG clk_fpga_BUFG (.I(clk_fpga_in), .O(clk_fpga)); +`endif // !`ifdef DCM + // ///////////////////////////////////////////////////////////////////////// // SPI wire mosi, sclk, miso; @@ -79,6 +82,10 @@ module u1e assign TXBLANK = 0; wire [13:0] tx_i, tx_q; + +`ifdef DCM + reg [13:0] TX; + reg TXSYNC; always @(posedge clk_2x) if(clk_fpga) @@ -91,7 +98,38 @@ module u1e TX <= tx_q; TXSYNC <= 1; end - +`else // !`ifdef DCM + genvar i; + generate + for(i=0;i<14;i=i+1) + begin : gen_dacout + ODDR2 #(.DDR_ALIGNMENT("NONE"), // Sets output alignment to "NONE", "C0" or "C1" + .INIT(1'b0), // Sets initial state of the Q output to 1'b0 or 1'b1 + .SRTYPE("SYNC")) // Specifies "SYNC" or "ASYNC" set/reset + ODDR2_inst (.Q(TX[i]), // 1-bit DDR output data + .C0(clk_fpga), // 1-bit clock input + .C1(~clk_fpga), // 1-bit clock input + .CE(1'b1), // 1-bit clock enable input + .D0(tx_i[i]), // 1-bit data input (associated with C0) + .D1(tx_q[i]), // 1-bit data input (associated with C1) + .R(1'b0), // 1-bit reset input + .S(1'b0)); // 1-bit set input + end // block: gen_dacout + endgenerate + ODDR2 #(.DDR_ALIGNMENT("NONE"), // Sets output alignment to "NONE", "C0" or "C1" + .INIT(1'b0), // Sets initial state of the Q output to 1'b0 or 1'b1 + .SRTYPE("SYNC")) // Specifies "SYNC" or "ASYNC" set/reset + ODDR2_txsnc (.Q(TXSYNC), // 1-bit DDR output data + .C0(clk_fpga), // 1-bit clock input + .C1(~clk_fpga), // 1-bit clock input + .CE(1'b1), // 1-bit clock enable input + .D0(1'b0), // 1-bit data input (associated with C0) + .D1(1'b1), // 1-bit data input (associated with C1) + .R(1'b0), // 1-bit reset input + .S(1'b0)); // 1-bit set input + +`endif // !`ifdef DCM + // ///////////////////////////////////////////////////////////////////////// // Main U1E Core u1e_core u1e_core(.clk_fpga(clk_fpga), .rst_fpga(~debug_pb[2]), -- cgit v1.2.3 From b96282d6d9d7aad94d82f2ac6487460f4850a55c Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 1 Jun 2010 18:23:35 -0700 Subject: connect the rx run lines so it doesn't get optimized out --- usrp2/top/u1e/u1e_core.v | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index ed4176ca5..7307a0299 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -138,12 +138,14 @@ module u1e_core wire strobe_rx, strobe_tx; wire rx1_dst_rdy, rx1_src_rdy; wire [99:0] rx1_data; + wire run_rx; + dsp_core_rx #(.BASE(SR_RX_DSP)) dsp_core_rx (.clk(wb_clk),.rst(wb_rst), .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), .adc_a({rx_i,2'b0}),.adc_ovf_a(0),.adc_b({rx_q,2'b0}),.adc_ovf_b(0), - .sample(sample_rx), .run(run_rx_d1), .strobe(strobe_rx), + .sample(sample_rx), .run(run_rx), .strobe(strobe_rx), .debug(debug_rx_dsp) ); vita_rx_control #(.BASE(SR_RX_CTRL), .WIDTH(32)) vita_rx_control @@ -169,6 +171,7 @@ module u1e_core wire tx1_src_rdy, tx1_dst_rdy; wire [15:0] tx_i_int, tx_q_int; wire [31:0] debug_vtc, debug_vtd, debug_vt; + wire run_tx; vita_tx_deframer #(.BASE(SR_TX_CTRL), .MAXCHAN(1)) vita_tx_deframer (.clk(wb_clk), .reset(wb_rst), .clear(0), -- cgit v1.2.3 From d2163a256d55692c19b0a717e382850a6546f80f Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 1 Jun 2010 18:56:44 -0700 Subject: use same version as usrp2-udp, so regs are same place in memory map --- usrp2/top/u1e/Makefile | 2 +- usrp2/top/u1e/u1e_core.v | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index 7f5085275..edfc47c53 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -160,7 +160,7 @@ 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_rx_udp.v \ sdr_lib/dsp_core_tx.v \ sdr_lib/hb_dec.v \ sdr_lib/hb_interp.v \ diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 7307a0299..12ce41c23 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -28,7 +28,7 @@ module u1e_core localparam TXFIFOSIZE = 11; localparam RXFIFOSIZE = 11; - localparam SR_RX_DSP = 0; // 7 regs + localparam SR_RX_DSP = 0; // 5 regs localparam SR_RX_CTRL = 8; // 9 regs localparam SR_TX_DSP = 17; // 5 regs localparam SR_TX_CTRL = 24; // 2 regs -- cgit v1.2.3 From 4f1b2441c0250a61f691c038f8bd9cfb229bd103 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 3 Jun 2010 08:44:13 -0700 Subject: Phil wants gpio #145 --- usrp2/top/u1e_passthru/passthru.ucf | 4 ++-- usrp2/top/u1e_passthru/passthru.v | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/usrp2/top/u1e_passthru/passthru.ucf b/usrp2/top/u1e_passthru/passthru.ucf index 3ffe33882..fcfce61b2 100644 --- a/usrp2/top/u1e_passthru/passthru.ucf +++ b/usrp2/top/u1e_passthru/passthru.ucf @@ -54,10 +54,10 @@ #NET "overo_gpio23" LOC = "B3" ; # MISC GPIO for debug #NET "overo_gpio64" LOC = "A4" ; # MISC GPIO for debug #NET "overo_gpio65" LOC = "F8" ; # MISC GPIO for debug -NET "overo_gpio127" LOC = "C8" ; # passed through as cgen_sen_b +#NET "overo_gpio127" LOC = "C8" ; # passed through as cgen_sen_b #NET "overo_gpio128" LOC = "G8" ; # MISC GPIO for debug #NET "overo_gpio144" LOC = "A5" ; # tx_have_space -#NET "overo_gpio145" LOC = "C7" ; # tx_underrun +NET "overo_gpio145" LOC = "C7" ; # tx_underrun #NET "overo_gpio146" LOC = "A6" ; # rx_have_data #NET "overo_gpio147" LOC = "B6" ; # rx_overrun #NET "overo_gpio163" LOC = "D7" ; # MISC GPIO for debug diff --git a/usrp2/top/u1e_passthru/passthru.v b/usrp2/top/u1e_passthru/passthru.v index d846f2cf6..12e4db017 100644 --- a/usrp2/top/u1e_passthru/passthru.v +++ b/usrp2/top/u1e_passthru/passthru.v @@ -2,7 +2,7 @@ ////////////////////////////////////////////////////////////////////////////////// module passthru - (input overo_gpio127, + (input overo_gpio145, output cgen_sclk, output cgen_sen_b, output cgen_mosi, @@ -11,7 +11,7 @@ module passthru ); assign cgen_sclk = fpga_cfg_cclk; - assign cgen_sen_b = overo_gpio127; + assign cgen_sen_b = overo_gpio145; assign cgen_mosi = fpga_cfg_din; -- cgit v1.2.3 From 761e22013c6715987c411216d012098e60684836 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Sun, 6 Jun 2010 02:26:48 -0700 Subject: get rid of redundant fifo18, since we can just use fifo19 and ignore the occ bit --- usrp2/control_lib/newfifo/fifo36_to_fifo18.v | 40 ---------------------------- usrp2/gpmc/gpmc_async.v | 5 ++-- usrp2/gpmc/gpmc_sync.v | 5 ++-- 3 files changed, 6 insertions(+), 44 deletions(-) delete mode 100644 usrp2/control_lib/newfifo/fifo36_to_fifo18.v diff --git a/usrp2/control_lib/newfifo/fifo36_to_fifo18.v b/usrp2/control_lib/newfifo/fifo36_to_fifo18.v deleted file mode 100644 index b636ab9ca..000000000 --- a/usrp2/control_lib/newfifo/fifo36_to_fifo18.v +++ /dev/null @@ -1,40 +0,0 @@ - -module fifo36_to_fifo18 - (input clk, input reset, input clear, - input [35:0] f36_datain, - input f36_src_rdy_i, - output f36_dst_rdy_o, - - output [17:0] f18_dataout, - output f18_src_rdy_o, - input f18_dst_rdy_i ); - - wire f36_sof = f36_datain[32]; - wire f36_eof = f36_datain[33]; - wire f36_occ = f36_datain[35:34]; - - reg phase; - - wire half_line = f36_eof & ((f36_occ==1)|(f36_occ==2)); - - assign f18_dataout[15:0] = phase ? f36_datain[15:0] : f36_datain[31:16]; - assign f18_dataout[16] = phase ? 0 : f36_sof; - assign f18_dataout[17] = phase ? f36_eof : half_line; - - assign f18_src_rdy_o = f36_src_rdy_i; - assign f36_dst_rdy_o = (phase | half_line) & f18_dst_rdy_i; - - wire f18_xfer = f18_src_rdy_o & f18_dst_rdy_i; - wire f36_xfer = f36_src_rdy_i & f36_dst_rdy_o; - - always @(posedge clk) - if(reset) - phase <= 0; - else if(f36_xfer) - phase <= 0; - else if(f18_xfer) - phase <= 1; - - -endmodule // fifo36_to_fifo18 - diff --git a/usrp2/gpmc/gpmc_async.v b/usrp2/gpmc/gpmc_async.v index 380689c62..f42b835ed 100644 --- a/usrp2/gpmc/gpmc_async.v +++ b/usrp2/gpmc/gpmc_async.v @@ -82,16 +82,17 @@ module gpmc_async wire [15:0] rx_fifo_space; wire [35:0] rx36_data; wire rx36_src_rdy, rx36_dst_rdy; + wire dummy; fifo_cascade #(.WIDTH(36), .SIZE(RXFIFOSIZE)) rx_fifo36 (.clk(wb_clk), .reset(wb_rst), .clear(0), .datain(rx_data_i), .src_rdy_i(rx_src_rdy_i), .dst_rdy_o(rx_dst_rdy_o), .dataout(rx36_data), .src_rdy_o(rx36_src_rdy), .dst_rdy_i(rx36_dst_rdy)); - fifo36_to_fifo18 f18_to_f36 + fifo36_to_fifo19 f36_to_f19 (.clk(fifo_clk), .reset(fifo_rst), .clear(0), .f36_datain(rx36_data), .f36_src_rdy_i(rx36_src_rdy), .f36_dst_rdy_o(rx36_dst_rdy), - .f18_dataout(rx18_data), .f18_src_rdy_o(rx18_src_rdy), .f18_dst_rdy_i(rx18_dst_rdy) ); + .f19_dataout({dummy,rx18_data}), .f19_src_rdy_o(rx18_src_rdy), .f19_dst_rdy_i(rx18_dst_rdy) ); fifo_cascade #(.WIDTH(18), .SIZE(12)) rx_fifo (.clk(fifo_clk), .reset(fifo_rst), .clear(0), diff --git a/usrp2/gpmc/gpmc_sync.v b/usrp2/gpmc/gpmc_sync.v index 825d131d8..bac489ca0 100644 --- a/usrp2/gpmc/gpmc_sync.v +++ b/usrp2/gpmc/gpmc_sync.v @@ -68,11 +68,12 @@ module gpmc_sync wire [17:0] rx18_data, rx18b_data; wire rx18_src_rdy, rx18_dst_rdy, rx18b_src_rdy, rx18b_dst_rdy; wire [15:0] rx_fifo_space, rx_frame_len; + wire dummy; - fifo36_to_fifo18 f18_to_f36 + fifo36_to_fifo19 f36_to_f19 (.clk(fifo_clk), .reset(fifo_rst), .clear(0), .f36_datain(rx_data_i), .f36_src_rdy_i(rx_src_rdy_i), .f36_dst_rdy_o(rx_dst_rdy_o), - .f18_dataout(rx18_data), .f18_src_rdy_o(rx18_src_rdy), .f18_dst_rdy_i(rx18_dst_rdy) ); + .f19_dataout({dummy,rx18_data}), .f19_src_rdy_o(rx18_src_rdy), .f19_dst_rdy_i(rx18_dst_rdy) ); fifo_2clock_cascade #(.WIDTH(18), .SIZE(10)) rx_fifo (.wclk(fifo_clk), .datain(rx18_data), -- cgit v1.2.3 From 3122c8c3d9740a2fd5e68b99df627bc632d764da Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Sun, 6 Jun 2010 02:50:18 -0700 Subject: added little endian capability for gpmc to fifo and fifo to gpmc, since ARM is LE. --- usrp2/control_lib/newfifo/fifo19_to_fifo36.v | 40 ++++++++++++++----------- usrp2/control_lib/newfifo/fifo36_to_fifo19.v | 44 +++++++++++++++------------- usrp2/gpmc/gpmc_async.v | 4 +-- usrp2/gpmc/gpmc_sync.v | 4 +-- 4 files changed, 51 insertions(+), 41 deletions(-) diff --git a/usrp2/control_lib/newfifo/fifo19_to_fifo36.v b/usrp2/control_lib/newfifo/fifo19_to_fifo36.v index 5f9aeff9b..0e6bcea68 100644 --- a/usrp2/control_lib/newfifo/fifo19_to_fifo36.v +++ b/usrp2/control_lib/newfifo/fifo19_to_fifo36.v @@ -1,26 +1,31 @@ +// Parameter LE tells us if we are little-endian. +// Little-endian means send lower 16 bits first. +// Default is big endian (network order), send upper bits first. + module fifo19_to_fifo36 - (input clk, input reset, input clear, - input [18:0] f19_datain, - input f19_src_rdy_i, - output f19_dst_rdy_o, + #(parameter LE=0) + (input clk, input reset, input clear, + input [18:0] f19_datain, + input f19_src_rdy_i, + output f19_dst_rdy_o, - output [35:0] f36_dataout, - output f36_src_rdy_o, - input f36_dst_rdy_i, - output [31:0] debug - ); + output [35:0] f36_dataout, + output f36_src_rdy_o, + input f36_dst_rdy_i, + output [31:0] debug + ); - reg f36_sof, f36_eof, f36_occ; + reg f36_sof, f36_eof, f36_occ; - reg [1:0] state; - reg [15:0] dat0, dat1; + reg [1:0] state; + reg [15:0] dat0, dat1; - wire f19_sof = f19_datain[16]; - wire f19_eof = f19_datain[17]; - wire f19_occ = f19_datain[18]; + wire f19_sof = f19_datain[16]; + wire f19_eof = f19_datain[17]; + wire f19_occ = f19_datain[18]; - wire xfer_out = f36_src_rdy_o & f36_dst_rdy_i; + wire xfer_out = f36_src_rdy_o & f36_dst_rdy_i; always @(posedge clk) if(f19_src_rdy_i & ((state==0)|xfer_out)) @@ -68,7 +73,8 @@ module fifo19_to_fifo36 dat0 <= f19_datain; assign f19_dst_rdy_o = xfer_out | (state != 2); - assign f36_dataout = {f36_occ,f36_eof,f36_sof,dat0,dat1}; + assign f36_dataout = LE ? {f36_occ,f36_eof,f36_sof,dat1,dat0} : + {f36_occ,f36_eof,f36_sof,dat0,dat1}; assign f36_src_rdy_o = (state == 2); assign debug = state; diff --git a/usrp2/control_lib/newfifo/fifo36_to_fifo19.v b/usrp2/control_lib/newfifo/fifo36_to_fifo19.v index de249aaeb..517a2a476 100644 --- a/usrp2/control_lib/newfifo/fifo36_to_fifo19.v +++ b/usrp2/control_lib/newfifo/fifo36_to_fifo19.v @@ -1,33 +1,38 @@ -module fifo36_to_fifo19 - (input clk, input reset, input clear, - input [35:0] f36_datain, - input f36_src_rdy_i, - output f36_dst_rdy_o, - - output [18:0] f19_dataout, - output f19_src_rdy_o, - input f19_dst_rdy_i ); +// Parameter LE tells us if we are little-endian. +// Little-endian means send lower 16 bits first. +// Default is big endian (network order), send upper bits first. +module fifo36_to_fifo19 + #(parameter LE=0) + (input clk, input reset, input clear, + input [35:0] f36_datain, + input f36_src_rdy_i, + output f36_dst_rdy_o, + + output [18:0] f19_dataout, + output f19_src_rdy_o, + input f19_dst_rdy_i ); + wire f36_sof = f36_datain[32]; wire f36_eof = f36_datain[33]; wire f36_occ = f36_datain[35:34]; - - reg phase; - - wire half_line = f36_eof & ((f36_occ==1)|(f36_occ==2)); - assign f19_dataout[15:0] = phase ? f36_datain[15:0] : f36_datain[31:16]; + reg phase; + + wire half_line = f36_eof & ((f36_occ==1)|(f36_occ==2)); + + assign f19_dataout[15:0] = (LE ^ phase) ? f36_datain[15:0] : f36_datain[31:16]; assign f19_dataout[16] = phase ? 0 : f36_sof; assign f19_dataout[17] = phase ? f36_eof : half_line; assign f19_dataout[18] = f19_dataout[17] & ((f36_occ==1)|(f36_occ==3)); assign f19_src_rdy_o = f36_src_rdy_i; assign f36_dst_rdy_o = (phase | half_line) & f19_dst_rdy_i; - - wire f19_xfer = f19_src_rdy_o & f19_dst_rdy_i; - wire f36_xfer = f36_src_rdy_i & f36_dst_rdy_o; - + + wire f19_xfer = f19_src_rdy_o & f19_dst_rdy_i; + wire f36_xfer = f36_src_rdy_i & f36_dst_rdy_o; + always @(posedge clk) if(reset) phase <= 0; @@ -36,6 +41,5 @@ module fifo36_to_fifo19 else if(f19_xfer) phase <= 1; - + endmodule // fifo36_to_fifo19 - diff --git a/usrp2/gpmc/gpmc_async.v b/usrp2/gpmc/gpmc_async.v index f42b835ed..1050cef7d 100644 --- a/usrp2/gpmc/gpmc_async.v +++ b/usrp2/gpmc/gpmc_async.v @@ -64,7 +64,7 @@ module gpmc_async .datain(tx18_data), .src_rdy_i(tx18_src_rdy), .dst_rdy_o(tx18_dst_rdy), .space(tx_fifo_space), .dataout(tx18b_data), .src_rdy_o(tx18b_src_rdy), .dst_rdy_i(tx18b_dst_rdy), .occupied()); - fifo19_to_fifo36 f19_to_f36 + fifo19_to_fifo36 #(.LE(1)) f19_to_f36 // Little endian because ARM is LE (.clk(fifo_clk), .reset(fifo_rst), .clear(0), .f19_datain({1'b0,tx18b_data}), .f19_src_rdy_i(tx18b_src_rdy), .f19_dst_rdy_o(tx18b_dst_rdy), .f36_dataout(tx36_data), .f36_src_rdy_o(tx36_src_rdy), .f36_dst_rdy_i(tx36_dst_rdy)); @@ -89,7 +89,7 @@ module gpmc_async .datain(rx_data_i), .src_rdy_i(rx_src_rdy_i), .dst_rdy_o(rx_dst_rdy_o), .dataout(rx36_data), .src_rdy_o(rx36_src_rdy), .dst_rdy_i(rx36_dst_rdy)); - fifo36_to_fifo19 f36_to_f19 + fifo36_to_fifo19 #(.LE(1)) f36_to_f19 // Little endian because ARM is LE (.clk(fifo_clk), .reset(fifo_rst), .clear(0), .f36_datain(rx36_data), .f36_src_rdy_i(rx36_src_rdy), .f36_dst_rdy_o(rx36_dst_rdy), .f19_dataout({dummy,rx18_data}), .f19_src_rdy_o(rx18_src_rdy), .f19_dst_rdy_i(rx18_dst_rdy) ); diff --git a/usrp2/gpmc/gpmc_sync.v b/usrp2/gpmc/gpmc_sync.v index bac489ca0..61c54a793 100644 --- a/usrp2/gpmc/gpmc_sync.v +++ b/usrp2/gpmc/gpmc_sync.v @@ -57,7 +57,7 @@ module gpmc_sync .rclk(fifo_clk), .dataout(tx18b_data), .src_rdy_o(tx18b_src_rdy), .dst_rdy_i(tx18b_dst_rdy), .occupied(), .arst(arst)); - fifo19_to_fifo36 f19_to_f36 + fifo19_to_fifo36 #(.LE(1)) f19_to_f36 // Little endian because ARM is LE (.clk(fifo_clk), .reset(fifo_rst), .clear(0), .f19_datain({1'b0,tx18b_data}), .f19_src_rdy_i(tx18b_src_rdy), .f19_dst_rdy_o(tx18b_dst_rdy), .f36_dataout(tx_data_o), .f36_src_rdy_o(tx_src_rdy_o), .f36_dst_rdy_i(tx_dst_rdy_i)); @@ -70,7 +70,7 @@ module gpmc_sync wire [15:0] rx_fifo_space, rx_frame_len; wire dummy; - fifo36_to_fifo19 f36_to_f19 + fifo36_to_fifo19 #(.LE(1)) f36_to_f19 // Little endian because ARM is LE (.clk(fifo_clk), .reset(fifo_rst), .clear(0), .f36_datain(rx_data_i), .f36_src_rdy_i(rx_src_rdy_i), .f36_dst_rdy_o(rx_dst_rdy_o), .f19_dataout({dummy,rx18_data}), .f19_src_rdy_o(rx18_src_rdy), .f19_dst_rdy_i(rx18_dst_rdy) ); -- cgit v1.2.3 From 2f92808d27efae16368d6dddfbcc74ca181f4d7c Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Sun, 6 Jun 2010 03:18:39 -0700 Subject: use fifo19 not fifo18 in makefile --- usrp2/top/u1e/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index edfc47c53..cfef1378f 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -109,7 +109,7 @@ control_lib/newfifo/fifo_short.v \ control_lib/newfifo/fifo_long.v \ control_lib/newfifo/fifo_cascade.v \ control_lib/newfifo/fifo36_to_ll8.v \ -control_lib/newfifo/fifo36_to_fifo18.v \ +control_lib/newfifo/fifo36_to_fifo19.v \ control_lib/newfifo/fifo19_to_fifo36.v \ control_lib/newfifo/packet_generator.v \ control_lib/newfifo/packet_verifier.v \ -- cgit v1.2.3 From 552b06b5b281e0953b0268a22357c5f43bd9657c Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Sun, 6 Jun 2010 09:53:42 -0700 Subject: remove double declaration --- usrp2/top/u1e/u1e_core.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 12ce41c23..6dae653ce 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -101,7 +101,7 @@ module u1e_core `ifdef TIMED // TX side - wire tx_enable, tx_src_rdy_int, tx_dst_rdy_int; + wire tx_enable; fifo_pacer tx_pacer (.clk(wb_clk), .reset(wb_rst), .rate(rate), .enable(tx_enable), -- cgit v1.2.3 From 724af67a222aca01207cda9e0e4a8ce33217b7b8 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 8 Jun 2010 14:16:22 -0700 Subject: debug pins --- usrp2/gpmc/fifo_watcher.v | 4 +++- usrp2/gpmc/gpmc_async.v | 7 +++++-- usrp2/top/u1e/u1e_core.v | 3 ++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/usrp2/gpmc/fifo_watcher.v b/usrp2/gpmc/fifo_watcher.v index 4bba142b0..fe4e35de3 100644 --- a/usrp2/gpmc/fifo_watcher.v +++ b/usrp2/gpmc/fifo_watcher.v @@ -4,13 +4,15 @@ module fifo_watcher (input clk, input reset, input clear, input src_rdy1, input dst_rdy1, input sof1, input eof1, input src_rdy2, input dst_rdy2, input sof2, input eof2, - output reg have_packet, output [15:0] length, output reg bus_error); + output reg have_packet, output [15:0] length, output reg bus_error, + output [31:0] debug); wire write = src_rdy1 & dst_rdy1 & eof1; wire read = src_rdy2 & dst_rdy2 & eof2; wire have_packet_int; reg [15:0] counter; wire [4:0] pkt_count; + assign debug = pkt_count; fifo_short #(.WIDTH(16)) frame_lengths (.clk(clk), .reset(reset), .clear(clear), diff --git a/usrp2/gpmc/gpmc_async.v b/usrp2/gpmc/gpmc_async.v index 1050cef7d..9f7b6dc4c 100644 --- a/usrp2/gpmc/gpmc_async.v +++ b/usrp2/gpmc/gpmc_async.v @@ -105,11 +105,14 @@ module gpmc_async .EM_D(EM_D_fifo), .EM_NCS(EM_NCS4), .EM_NOE(EM_NOE), .frame_len(rx_frame_len) ); + wire [31:0] pkt_count; + fifo_watcher fifo_watcher (.clk(fifo_clk), .reset(fifo_rst), .clear(0), .src_rdy1(rx18_src_rdy), .dst_rdy1(rx18_dst_rdy), .sof1(rx18_data[16]), .eof1(rx18_data[17]), .src_rdy2(rx18b_src_rdy), .dst_rdy2(rx18b_dst_rdy), .sof2(rx18b_data[16]), .eof2(rx18b_data[17]), - .have_packet(rx_have_data), .length(rx_frame_len), .bus_error(bus_error_rx) ); + .have_packet(rx_have_data), .length(rx_frame_len), .bus_error(bus_error_rx), + .debug(pkt_count)); // //////////////////////////////////////////// // Control path on CS6 @@ -122,6 +125,6 @@ module gpmc_async .wb_sel_o(wb_sel_o), .wb_cyc_o(wb_cyc_o), .wb_stb_o(wb_stb_o), .wb_we_o(wb_we_o), .wb_ack_i(wb_ack_i) ); - assign debug = 0; + assign debug = pkt_count; endmodule // gpmc_async diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 6dae653ce..dde81df6b 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -430,6 +430,7 @@ module u1e_core assign debug_gpio_1 = { {rx_enable, rx_src_rdy, rx_dst_rdy, rx_src_rdy & ~rx_dst_rdy}, {tx_enable, tx_src_rdy, tx_dst_rdy, tx_dst_rdy & ~tx_src_rdy}, {rx_sof, rx_eof, rx_src_rdy, rx_dst_rdy, rx_data[33:32],2'b0}, - {3'b0, bus_error, misc_gpio[11:0]} }; + {2'b0, bus_error, debug_gpmc[4:0] }, + {misc_gpio[7:0]} }; endmodule // u1e_core -- cgit v1.2.3 From c28838a4ecfc1b3051bb46cf28114eb85a8845c7 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 8 Jun 2010 14:18:27 -0700 Subject: ignores --- usrp2/top/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/usrp2/top/.gitignore b/usrp2/top/.gitignore index bf1b77066..0d90f1698 100644 --- a/usrp2/top/.gitignore +++ b/usrp2/top/.gitignore @@ -1 +1,2 @@ /*.sav +build* -- cgit v1.2.3 From aefcb65e7788a9fbb50b443dbd3f248e2d462107 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 10 Jun 2010 12:03:45 -0700 Subject: proper overrun, underrun connections, debug pins. --- usrp2/top/u1e/u1e_core.v | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index dde81df6b..a6654906b 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -96,6 +96,9 @@ module u1e_core (.clk(wb_clk), .reset(wb_rst), .clear(0), .datain(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy), .dataout(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); + + assign tx_underrun = 0; + assign rx_overrun = 0; `endif // LOOPBACK `ifdef TIMED @@ -151,7 +154,7 @@ module u1e_core vita_rx_control #(.BASE(SR_RX_CTRL), .WIDTH(32)) vita_rx_control (.clk(wb_clk), .reset(wb_rst), .clear(0), .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), - .vita_time(vita_time), .overrun(overrun), + .vita_time(vita_time), .overrun(rx_overrun), .sample(sample_rx), .run(run_rx), .strobe(strobe_rx), .sample_fifo_o(rx1_data), .sample_fifo_dst_rdy_i(rx1_dst_rdy), .sample_fifo_src_rdy_o(rx1_src_rdy), .debug_rx(vrc_debug)); @@ -183,7 +186,7 @@ module u1e_core vita_tx_control #(.BASE(SR_TX_CTRL), .WIDTH(32)) vita_tx_control (.clk(wb_clk), .reset(wb_rst), .clear(0), .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), - .vita_time(vita_time),.underrun(underrun), + .vita_time(vita_time),.underrun(tx_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), .debug(debug_vtc) ); @@ -326,7 +329,6 @@ module u1e_core assign { debug_led[2],debug_led[0],debug_led[1] } = reg_leds; // LEDs are arranged funny on board assign { cgen_sync_b, cgen_ref_sel } = reg_cgen_ctrl; - //assign { rx_overrun, tx_underrun } = 0; // reg_test; assign s0_dat_miso = (s0_adr[6:0] == REG_LEDS) ? reg_leds : (s0_adr[6:0] == REG_SWITCHES) ? {5'b0,debug_pb[2:0],dip_sw[7:0]} : @@ -426,7 +428,9 @@ module u1e_core //assign debug = { phase[23:8], txsync, txblank, tx }; - assign debug_gpio_0 = { debug_gpmc }; + assign debug_gpio_0 = { {run_tx, strobe_tx, run_rx, strobe_rx, rx_i[11:0]}, + {rx1_src_rdy, rx1_dst_rdy, rx_src_rdy, rx_dst_rdy, rx_q[11:0]} }; + assign debug_gpio_1 = { {rx_enable, rx_src_rdy, rx_dst_rdy, rx_src_rdy & ~rx_dst_rdy}, {tx_enable, tx_src_rdy, tx_dst_rdy, tx_dst_rdy & ~tx_src_rdy}, {rx_sof, rx_eof, rx_src_rdy, rx_dst_rdy, rx_data[33:32],2'b0}, -- cgit v1.2.3 From 7d067d0109d4ee484a65caabcaf173082719f0d4 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 10 Jun 2010 12:19:41 -0700 Subject: left something out of the sensitivity list. --- usrp2/control_lib/nsgpio16LE.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usrp2/control_lib/nsgpio16LE.v b/usrp2/control_lib/nsgpio16LE.v index 514b003ce..8aef0c7ae 100644 --- a/usrp2/control_lib/nsgpio16LE.v +++ b/usrp2/control_lib/nsgpio16LE.v @@ -111,7 +111,7 @@ module nsgpio16LE integer n; reg [31:0] igpio; // temporary internal signal - always @(ctrl or line or debug_1 or debug_0 or atr or ddr) + always @(ctrl or line or debug_1 or debug_0 or atr or ddr or dbg) for(n=0;n<32;n=n+1) igpio[n] <= ddr[n] ? (dbg[n] ? (ctrl[n] ? debug_1[n] : debug_0[n]) : (ctrl[n] ? atr[n] : line[n]) ) -- cgit v1.2.3 From b38a1db20233e6d23ffce831c38d67a500e87b51 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 10 Jun 2010 14:50:32 -0700 Subject: much bigger fifos --- usrp2/top/u1e/u1e_core.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index a6654906b..8db995b17 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -25,8 +25,8 @@ module u1e_core input [11:0] misc_gpio, input pps_in ); - localparam TXFIFOSIZE = 11; - localparam RXFIFOSIZE = 11; + localparam TXFIFOSIZE = 13; + localparam RXFIFOSIZE = 13; localparam SR_RX_DSP = 0; // 5 regs localparam SR_RX_CTRL = 8; // 9 regs -- cgit v1.2.3 From a4b11332ab4f6a24bf4645c0b2770f9578a36f45 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 10 Jun 2010 15:45:58 -0700 Subject: debug pins --- usrp2/top/u1e/u1e_core.v | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 8db995b17..64173ef2d 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -428,13 +428,16 @@ module u1e_core //assign debug = { phase[23:8], txsync, txblank, tx }; - assign debug_gpio_0 = { {run_tx, strobe_tx, run_rx, strobe_rx, rx_i[11:0]}, - {rx1_src_rdy, rx1_dst_rdy, rx_src_rdy, rx_dst_rdy, rx_q[11:0]} }; + assign debug_gpio_0 = { {run_tx, strobe_tx, run_rx, strobe_rx, tx_i[11:0]}, + {tx1_src_rdy, tx1_dst_rdy, tx_src_rdy, tx_dst_rdy, tx_q[11:0]} }; + + assign debug_gpio_1 = debug_vtd | debug_vtc; +/* assign debug_gpio_1 = { {rx_enable, rx_src_rdy, rx_dst_rdy, rx_src_rdy & ~rx_dst_rdy}, {tx_enable, tx_src_rdy, tx_dst_rdy, tx_dst_rdy & ~tx_src_rdy}, {rx_sof, rx_eof, rx_src_rdy, rx_dst_rdy, rx_data[33:32],2'b0}, {2'b0, bus_error, debug_gpmc[4:0] }, {misc_gpio[7:0]} }; - + */ endmodule // u1e_core -- cgit v1.2.3 From 55e0d893e8a596e18c9eeb34e6f518e03c26dd80 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 17 Jun 2010 13:59:51 -0700 Subject: added ability to clear out fifos of tx and rx. --- usrp2/gpmc/gpmc_async.v | 22 +++++++++++----------- usrp2/gpmc/gpmc_to_fifo_async.v | 10 +++++----- usrp2/top/u1e/u1e_core.v | 33 +++++++++++++++++++++------------ 3 files changed, 37 insertions(+), 28 deletions(-) diff --git a/usrp2/gpmc/gpmc_async.v b/usrp2/gpmc/gpmc_async.v index 9f7b6dc4c..23bad56ae 100644 --- a/usrp2/gpmc/gpmc_async.v +++ b/usrp2/gpmc/gpmc_async.v @@ -16,7 +16,7 @@ module gpmc_async output [1:0] wb_sel_o, output wb_cyc_o, output wb_stb_o, output wb_we_o, input wb_ack_i, // FIFO interface - input fifo_clk, input fifo_rst, + input fifo_clk, input fifo_rst, input clear_tx, input clear_rx, output [35:0] tx_data_o, output tx_src_rdy_o, input tx_dst_rdy_i, input [35:0] rx_data_i, input rx_src_rdy_i, output rx_dst_rdy_o, @@ -34,7 +34,7 @@ module gpmc_async wire bus_error_tx, bus_error_rx; always @(posedge fifo_clk) - if(fifo_rst) + if(fifo_rst | clear_tx | clear_rx) bus_error <= 0; else bus_error <= bus_error_tx | bus_error_rx; @@ -54,23 +54,23 @@ module gpmc_async gpmc_to_fifo_async gpmc_to_fifo_async (.EM_D(EM_D), .EM_NBE(EM_NBE), .EM_NCS(EM_NCS4), .EM_NWE(EM_NWE), - .fifo_clk(fifo_clk), .fifo_rst(fifo_rst), + .fifo_clk(fifo_clk), .fifo_rst(fifo_rst), .clear(clear_tx), .data_o(tx18_data), .src_rdy_o(tx18_src_rdy), .dst_rdy_i(tx18_dst_rdy), .frame_len(tx_frame_len), .fifo_space(tx_fifo_space), .fifo_ready(tx_have_space), .bus_error(bus_error_tx) ); fifo_cascade #(.WIDTH(18), .SIZE(10)) tx_fifo - (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_tx), .datain(tx18_data), .src_rdy_i(tx18_src_rdy), .dst_rdy_o(tx18_dst_rdy), .space(tx_fifo_space), .dataout(tx18b_data), .src_rdy_o(tx18b_src_rdy), .dst_rdy_i(tx18b_dst_rdy), .occupied()); fifo19_to_fifo36 #(.LE(1)) f19_to_f36 // Little endian because ARM is LE - (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_tx), .f19_datain({1'b0,tx18b_data}), .f19_src_rdy_i(tx18b_src_rdy), .f19_dst_rdy_o(tx18b_dst_rdy), .f36_dataout(tx36_data), .f36_src_rdy_o(tx36_src_rdy), .f36_dst_rdy_i(tx36_dst_rdy)); fifo_cascade #(.WIDTH(36), .SIZE(TXFIFOSIZE)) tx_fifo36 - (.clk(wb_clk), .reset(wb_rst), .clear(0), + (.clk(wb_clk), .reset(wb_rst), .clear(clear_tx), .datain(tx36_data), .src_rdy_i(tx36_src_rdy), .dst_rdy_o(tx36_dst_rdy), .dataout(tx_data_o), .src_rdy_o(tx_src_rdy_o), .dst_rdy_i(tx_dst_rdy_i)); @@ -85,22 +85,22 @@ module gpmc_async wire dummy; fifo_cascade #(.WIDTH(36), .SIZE(RXFIFOSIZE)) rx_fifo36 - (.clk(wb_clk), .reset(wb_rst), .clear(0), + (.clk(wb_clk), .reset(wb_rst), .clear(clear_rx), .datain(rx_data_i), .src_rdy_i(rx_src_rdy_i), .dst_rdy_o(rx_dst_rdy_o), .dataout(rx36_data), .src_rdy_o(rx36_src_rdy), .dst_rdy_i(rx36_dst_rdy)); fifo36_to_fifo19 #(.LE(1)) f36_to_f19 // Little endian because ARM is LE - (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx), .f36_datain(rx36_data), .f36_src_rdy_i(rx36_src_rdy), .f36_dst_rdy_o(rx36_dst_rdy), .f19_dataout({dummy,rx18_data}), .f19_src_rdy_o(rx18_src_rdy), .f19_dst_rdy_i(rx18_dst_rdy) ); fifo_cascade #(.WIDTH(18), .SIZE(12)) rx_fifo - (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx), .datain(rx18_data), .src_rdy_i(rx18_src_rdy), .dst_rdy_o(rx18_dst_rdy), .space(rx_fifo_space), .dataout(rx18b_data), .src_rdy_o(rx18b_src_rdy), .dst_rdy_i(rx18b_dst_rdy), .occupied()); fifo_to_gpmc_async fifo_to_gpmc_async - (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx), .data_i(rx18b_data), .src_rdy_i(rx18b_src_rdy), .dst_rdy_o(rx18b_dst_rdy), .EM_D(EM_D_fifo), .EM_NCS(EM_NCS4), .EM_NOE(EM_NOE), .frame_len(rx_frame_len) ); @@ -108,7 +108,7 @@ module gpmc_async wire [31:0] pkt_count; fifo_watcher fifo_watcher - (.clk(fifo_clk), .reset(fifo_rst), .clear(0), + (.clk(fifo_clk), .reset(fifo_rst), .clear(clear_rx), .src_rdy1(rx18_src_rdy), .dst_rdy1(rx18_dst_rdy), .sof1(rx18_data[16]), .eof1(rx18_data[17]), .src_rdy2(rx18b_src_rdy), .dst_rdy2(rx18b_dst_rdy), .sof2(rx18b_data[16]), .eof2(rx18b_data[17]), .have_packet(rx_have_data), .length(rx_frame_len), .bus_error(bus_error_rx), diff --git a/usrp2/gpmc/gpmc_to_fifo_async.v b/usrp2/gpmc/gpmc_to_fifo_async.v index 3d29745a2..55c0cef50 100644 --- a/usrp2/gpmc/gpmc_to_fifo_async.v +++ b/usrp2/gpmc/gpmc_to_fifo_async.v @@ -2,7 +2,7 @@ module gpmc_to_fifo_async (input [15:0] EM_D, input [1:0] EM_NBE, input EM_NCS, input EM_NWE, - input fifo_clk, input fifo_rst, + input fifo_clk, input fifo_rst, input clear, output reg [17:0] data_o, output reg src_rdy_o, input dst_rdy_i, input [15:0] frame_len, input [15:0] fifo_space, output reg fifo_ready, @@ -37,7 +37,7 @@ module gpmc_to_fifo_async end always @(posedge fifo_clk) - if(fifo_rst) + if(fifo_rst | clear) src_rdy_o <= 0; else if(do_write) src_rdy_o <= 1; @@ -45,7 +45,7 @@ module gpmc_to_fifo_async src_rdy_o <= 0; // Assume it was taken always @(posedge fifo_clk) - if(fifo_rst) + if(fifo_rst | clear) counter <= 0; else if(do_write) if(last_write) @@ -54,13 +54,13 @@ module gpmc_to_fifo_async counter <= counter + 1; always @(posedge fifo_clk) - if(fifo_rst) + if(fifo_rst | clear) fifo_ready <= 0; else fifo_ready <= /* first_write & */ (fifo_space > 16'd1023); always @(posedge fifo_clk) - if(fifo_rst) + if(fifo_rst | clear) bus_error <= 0; else if(src_rdy_o & ~dst_rdy_i) bus_error <= 1; diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 64173ef2d..787bf016c 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -28,10 +28,11 @@ module u1e_core localparam TXFIFOSIZE = 13; localparam RXFIFOSIZE = 13; - localparam SR_RX_DSP = 0; // 5 regs - localparam SR_RX_CTRL = 8; // 9 regs - localparam SR_TX_DSP = 17; // 5 regs - localparam SR_TX_CTRL = 24; // 2 regs + localparam SR_RX_DSP = 0; // 5 regs + localparam SR_CLEAR_FIFO = 6; // 1 reg + localparam SR_RX_CTRL = 8; // 9 regs + localparam SR_TX_DSP = 17; // 5 regs + localparam SR_TX_CTRL = 24; // 2 regs localparam SR_TIME64 = 28; // 4 regs wire wb_clk = clk_fpga; @@ -65,6 +66,14 @@ module u1e_core wire [7:0] rate; wire bus_error; + + wire clear_rx_int, clear_tx_int, clear_tx, clear_rx, do_clear; + + setting_reg #(.my_addr(SR_CLEAR_FIFO), .width(2)) sr_clear + (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out({clear_tx_int,clear_rx_int}),.changed(do_clear)); + assign clear_tx = clear_tx_int & do_clear; + assign clear_rx = clear_rx_int & do_clear; gpmc_async #(.TXFIFOSIZE(TXFIFOSIZE), .RXFIFOSIZE(RXFIFOSIZE)) gpmc (.arst(wb_rst), @@ -80,7 +89,7 @@ module u1e_core .wb_sel_o(m0_sel), .wb_cyc_o(m0_cyc), .wb_stb_o(m0_stb), .wb_we_o(m0_we), .wb_ack_i(m0_ack), - .fifo_clk(wb_clk), .fifo_rst(wb_rst), + .fifo_clk(wb_clk), .fifo_rst(wb_rst), .clear_tx(clear_tx), .clear_rx(clear_rx), .tx_data_o(tx_data), .tx_src_rdy_o(tx_src_rdy), .tx_dst_rdy_i(tx_dst_rdy), .rx_data_i(rx_data), .rx_src_rdy_i(rx_src_rdy), .rx_dst_rdy_o(rx_dst_rdy), @@ -93,7 +102,7 @@ module u1e_core `ifdef LOOPBACK fifo_cascade #(.WIDTH(36), .SIZE(9)) loopback_fifo - (.clk(wb_clk), .reset(wb_rst), .clear(0), + (.clk(wb_clk), .reset(wb_rst), .clear(clear_tx | clear_rx), .datain(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy), .dataout(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); @@ -113,7 +122,7 @@ module u1e_core .underrun(tx_underrun), .overrun()); packet_verifier32 pktver32 - (.clk(wb_clk), .reset(wb_rst), .clear(clear), + (.clk(wb_clk), .reset(wb_rst), .clear(clear_tx), .data_i(tx_data), .src_rdy_i(tx_src_rdy_int), .dst_rdy_o(tx_dst_rdy_int), .total(total), .crc_err(crc_err), .seq_err(seq_err), .len_err(len_err)); @@ -121,7 +130,7 @@ module u1e_core wire rx_enable; packet_generator32 pktgen32 - (.clk(wb_clk), .reset(wb_rst), .clear(clear), + (.clk(wb_clk), .reset(wb_rst), .clear(clear_rx), .data_o(rx_data), .src_rdy_o(rx_src_rdy_int), .dst_rdy_i(rx_dst_rdy_int)); fifo_pacer rx_pacer @@ -152,7 +161,7 @@ module u1e_core .debug(debug_rx_dsp) ); vita_rx_control #(.BASE(SR_RX_CTRL), .WIDTH(32)) vita_rx_control - (.clk(wb_clk), .reset(wb_rst), .clear(0), + (.clk(wb_clk), .reset(wb_rst), .clear(clear_rx), .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), .vita_time(vita_time), .overrun(rx_overrun), .sample(sample_rx), .run(run_rx), .strobe(strobe_rx), @@ -160,7 +169,7 @@ module u1e_core .debug_rx(vrc_debug)); vita_rx_framer #(.BASE(SR_RX_CTRL), .MAXCHAN(1)) vita_rx_framer - (.clk(wb_clk), .reset(wb_rst), .clear(0), + (.clk(wb_clk), .reset(wb_rst), .clear(clear_rx), .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), .sample_fifo_i(rx1_data), .sample_fifo_dst_rdy_o(rx1_dst_rdy), .sample_fifo_src_rdy_i(rx1_src_rdy), .data_o(rx_data), .dst_rdy_i(rx_dst_rdy), .src_rdy_o(rx_src_rdy), @@ -177,14 +186,14 @@ module u1e_core wire run_tx; vita_tx_deframer #(.BASE(SR_TX_CTRL), .MAXCHAN(1)) vita_tx_deframer - (.clk(wb_clk), .reset(wb_rst), .clear(0), + (.clk(wb_clk), .reset(wb_rst), .clear(clear_tx), .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), .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(wb_clk), .reset(wb_rst), .clear(0), + (.clk(wb_clk), .reset(wb_rst), .clear(clear_tx), .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), .vita_time(vita_time),.underrun(tx_underrun), .sample_fifo_i(tx1_data), .sample_fifo_src_rdy_i(tx1_src_rdy), .sample_fifo_dst_rdy_o(tx1_dst_rdy), -- cgit v1.2.3 From c3ef4c04fd8d887a733fa9a8ed5b6702cf453a01 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Fri, 9 Jul 2010 14:20:30 -0700 Subject: point to new location for fifos --- usrp2/vrt/vita_rx.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usrp2/vrt/vita_rx.build b/usrp2/vrt/vita_rx.build index f6d2d75a3..010d1be6e 100755 --- a/usrp2/vrt/vita_rx.build +++ b/usrp2/vrt/vita_rx.build @@ -1 +1 @@ -iverilog -Wimplict -Wportbind -y ../models -y . -y ../control_lib/ -y ../control_lib/newfifo -y ../coregen -y /opt/Xilinx/10.1/ISE/verilog/src/XilinxCoreLib -y /opt/Xilinx/10.1/ISE/verilog/src/unisims/ -y ../timing -o vita_rx_tb vita_rx_tb.v +iverilog -Wimplict -Wportbind -y ../models -y . -y ../control_lib/ -y ../fifo -y ../coregen -y /opt/Xilinx/10.1/ISE/verilog/src/XilinxCoreLib -y /opt/Xilinx/10.1/ISE/verilog/src/unisims/ -y ../timing -o vita_rx_tb vita_rx_tb.v -- cgit v1.2.3 From 5922f348e19fd477c311c0cadef4eb5d3a17d4c6 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 14 Jul 2010 19:37:45 -0700 Subject: make loopback compile --- usrp2/top/u1e/u1e_core.v | 3 +++ 1 file changed, 3 insertions(+) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 787bf016c..5b60578ce 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -108,6 +108,9 @@ module u1e_core assign tx_underrun = 0; assign rx_overrun = 0; + + wire run_tx, run_rx, strobe_tx, strobe_rx, tx1_src_rdy, tx1_dst_rdy; + wire [31:0] debug_vtd, debug_vtc; `endif // LOOPBACK `ifdef TIMED -- cgit v1.2.3 From 19974fa00b04280e52d3d644e8e12953c570c06d Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 10 Aug 2010 09:59:33 -0700 Subject: enlarge loopback fifo --- usrp2/top/u1e/u1e_core.v | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 5b60578ce..516a5cf96 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -101,7 +101,7 @@ module u1e_core wire rx_src_rdy_int, rx_dst_rdy_int, tx_src_rdy_int, tx_dst_rdy_int; `ifdef LOOPBACK - fifo_cascade #(.WIDTH(36), .SIZE(9)) loopback_fifo + fifo_cascade #(.WIDTH(36), .SIZE(12)) loopback_fifo (.clk(wb_clk), .reset(wb_rst), .clear(clear_tx | clear_rx), .datain(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy), .dataout(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); @@ -437,9 +437,6 @@ module u1e_core { tx_src_rdy, tx_src_rdy_int, tx_dst_rdy, tx_dst_rdy_int, rx_src_rdy, rx_src_rdy_int, rx_dst_rdy, rx_dst_rdy_int }, { EM_D } }; - //assign debug = { phase[23:8], txsync, txblank, tx }; - - assign debug_gpio_0 = { {run_tx, strobe_tx, run_rx, strobe_rx, tx_i[11:0]}, {tx1_src_rdy, tx1_dst_rdy, tx_src_rdy, tx_dst_rdy, tx_q[11:0]} }; -- cgit v1.2.3 From 9e97e773b9952ec3212e6c818bb40d785016afa4 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Wed, 11 Aug 2010 16:26:58 -0700 Subject: connect the setting reg to the real clock and reset --- usrp2/top/u1e/u1e_core.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 516a5cf96..4561df173 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -70,7 +70,7 @@ module u1e_core wire clear_rx_int, clear_tx_int, clear_tx, clear_rx, do_clear; setting_reg #(.my_addr(SR_CLEAR_FIFO), .width(2)) sr_clear - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), + (.clk(wb_clk),.rst(wb_rst),.strobe(set_stb),.addr(set_addr), .in(set_data),.out({clear_tx_int,clear_rx_int}),.changed(do_clear)); assign clear_tx = clear_tx_int & do_clear; assign clear_rx = clear_rx_int & do_clear; -- cgit v1.2.3 From 3091759d3f6a69bc0c56f2101b7b775de443212a Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Fri, 13 Aug 2010 11:49:36 -0700 Subject: this is necessary for some reason --- usrp2/top/u1e/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/usrp2/top/u1e/Makefile b/usrp2/top/u1e/Makefile index f4a643176..3cb9fd8f3 100644 --- a/usrp2/top/u1e/Makefile +++ b/usrp2/top/u1e/Makefile @@ -95,6 +95,7 @@ GEN_PROG_FILE_PROPERTIES = \ "Create Binary Configuration File" TRUE \ "Done (Output Events)" 5 \ "Enable Bitstream Compression" TRUE \ -"Enable Outputs (Output Events)" 6 +"Enable Outputs (Output Events)" 6 \ +"Unused IOB Pins" "Pull Up" SIM_MODEL_PROPERTIES = "" -- cgit v1.2.3 From 1d9d3dcc7b460e25881d182e74429f91cef31a50 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 17 Aug 2010 15:50:27 -0700 Subject: delay the q channel to make the channels line up on the AD9862 --- usrp2/top/u1e/u1e.v | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index 523aae1b9..9536b5ced 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -99,6 +99,11 @@ module u1e TXSYNC <= 1; end `else // !`ifdef DCM + + reg[13:0] delay_q; + always @(posedge clk_fpga) + delay_q <= tx_q; + genvar i; generate for(i=0;i<14;i=i+1) @@ -111,7 +116,7 @@ module u1e .C1(~clk_fpga), // 1-bit clock input .CE(1'b1), // 1-bit clock enable input .D0(tx_i[i]), // 1-bit data input (associated with C0) - .D1(tx_q[i]), // 1-bit data input (associated with C1) + .D1(delay_q[i]), // 1-bit data input (associated with C1) .R(1'b0), // 1-bit reset input .S(1'b0)); // 1-bit set input end // block: gen_dacout -- cgit v1.2.3 From 746f94409d12b6ab2a0e99260655b5a0460ba220 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 17 Aug 2010 16:37:55 -0700 Subject: connect atr --- usrp2/top/u1e/u1e_core.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 4561df173..13e6f4b68 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -419,7 +419,7 @@ module u1e_core (.clk_i(wb_clk), .rst_i(wb_rst), .adr_i(s6_adr), .sel_i(s6_sel), .dat_i(s6_dat_mosi), .dat_o(s6_dat_miso), .we_i(s6_we), .stb_i(s6_stb), .cyc_i(s6_cyc), .ack_o(s6_ack), - .run_rx(0), .run_tx(0), .ctrl_lines(atr_lines)); + .run_rx(run_rx), .run_tx(run_tx), .ctrl_lines(atr_lines)); // ///////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 02c2a3fd08b1ae1a306fa45d89b55dafeaffb508 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 17 Aug 2010 17:11:43 -0700 Subject: attach run_tx and run_rx to leds --- usrp2/top/u1e/u1e_core.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 13e6f4b68..63488f549 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -339,7 +339,7 @@ module u1e_core assign rx_enable = xfer_rate[14]; assign rate = xfer_rate[7:0]; - assign { debug_led[2],debug_led[0],debug_led[1] } = reg_leds; // LEDs are arranged funny on board + assign { debug_led[2],debug_led[0],debug_led[1] } = {run_rx,run_tx,reg_leds[0]}; // LEDs are arranged funny on board assign { cgen_sync_b, cgen_ref_sel } = reg_cgen_ctrl; assign s0_dat_miso = (s0_adr[6:0] == REG_LEDS) ? reg_leds : -- cgit v1.2.3 From 50a2ccee65677ed855c1798185d963fde1607324 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 19 Aug 2010 13:08:04 -0700 Subject: catch up with tx_policy --- usrp2/fifo/fifo36_mux.v | 2 +- usrp2/fifo/fifo_new_tb.vcd | 5506 --------------------------------------- usrp2/fifo/fifo_tb.v | 25 +- usrp2/top/Makefile.common | 2 +- usrp2/top/u2_rev3/u2_core_udp.v | 56 +- usrp2/vrt/Makefile.srcs | 2 + usrp2/vrt/gen_context_pkt.v | 72 + usrp2/vrt/vita_rx_framer.v | 2 +- usrp2/vrt/vita_tx_chain.v | 71 + usrp2/vrt/vita_tx_control.v | 115 +- usrp2/vrt/vita_tx_deframer.v | 30 +- 11 files changed, 311 insertions(+), 5572 deletions(-) delete mode 100644 usrp2/fifo/fifo_new_tb.vcd create mode 100644 usrp2/vrt/gen_context_pkt.v create mode 100644 usrp2/vrt/vita_tx_chain.v diff --git a/usrp2/fifo/fifo36_mux.v b/usrp2/fifo/fifo36_mux.v index 04ec5abe8..92bf13ff9 100644 --- a/usrp2/fifo/fifo36_mux.v +++ b/usrp2/fifo/fifo36_mux.v @@ -52,6 +52,6 @@ module fifo36_mux assign dst0_rdy_o = (state==MUX_DATA0) ? dst_rdy_i : 0; assign dst1_rdy_o = (state==MUX_DATA1) ? dst_rdy_i : 0; assign src_rdy_o = (state==MUX_DATA0) ? src0_rdy_i : (state==MUX_DATA1) ? src1_rdy_i : 0; - assign data_0 = (state==MUX_DATA0) ? data0_i : data1_i; + assign data_o = (state==MUX_DATA0) ? data0_i : data1_i; endmodule // fifo36_demux diff --git a/usrp2/fifo/fifo_new_tb.vcd b/usrp2/fifo/fifo_new_tb.vcd deleted file mode 100644 index 796889e7d..000000000 --- a/usrp2/fifo/fifo_new_tb.vcd +++ /dev/null @@ -1,5506 +0,0 @@ -$date - Thu Mar 19 17:21:11 2009 -$end -$version - Icarus Verilog -$end -$timescale - 1ps -$end -$scope module fifo_new_tb $end -$var wire 1 ! dst_rdy_f36i $end -$var wire 36 " f36_in [35:0] $end -$var wire 36 # i1 [35:0] $end -$var wire 1 $ i1_dr $end -$var wire 1 % i1_sr $end -$var wire 19 & i2 [18:0] $end -$var wire 1 ' i2_dr $end -$var wire 1 ( i2_sr $end -$var wire 19 ) i3 [18:0] $end -$var wire 1 * i3_dr $end -$var wire 1 + i3_sr $end -$var wire 36 , i4 [35:0] $end -$var wire 1 - i4_sr $end -$var wire 8 . ll_data [7:0] $end -$var wire 1 / ll_dst_rdy_n $end -$var wire 1 0 ll_eof_n $end -$var wire 1 1 ll_sof_n $end -$var wire 1 2 ll_src_rdy_n $end -$var reg 1 3 clear $end -$var reg 1 4 clk $end -$var reg 16 5 count [15:0] $end -$var reg 1 6 dst_rdy_f36o $end -$var reg 32 7 f36_data [31:0] $end -$var reg 1 8 f36_eof $end -$var reg 2 9 f36_occ [1:0] $end -$var reg 1 : f36_sof $end -$var reg 1 ; i4_dr $end -$var reg 1 < rst $end -$var reg 1 = src_rdy_f36i $end -$scope module fifo_short1 $end -$var wire 1 > clear $end -$var wire 1 ? clk $end -$var wire 36 @ datain [35:0] $end -$var wire 36 A dataout [35:0] $end -$var wire 1 $ dst_rdy_i $end -$var wire 1 ! dst_rdy_o $end -$var wire 1 B read $end -$var wire 1 C reset $end -$var wire 1 D src_rdy_i $end -$var wire 1 % src_rdy_o $end -$var wire 1 E write $end -$var reg 4 F a [3:0] $end -$var reg 1 G empty $end -$var reg 1 H full $end -$var reg 5 I occupied [4:0] $end -$var reg 5 J space [4:0] $end -$scope begin gen_srl16[0] $end -$scope module srl16e $end -$var wire 1 K A0 $end -$var wire 1 L A1 $end -$var wire 1 M A2 $end -$var wire 1 N A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 O D $end -$var wire 1 P Q $end -$var reg 16 Q data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[1] $end -$scope module srl16e $end -$var wire 1 R A0 $end -$var wire 1 S A1 $end -$var wire 1 T A2 $end -$var wire 1 U A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 V D $end -$var wire 1 W Q $end -$var reg 16 X data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[2] $end -$scope module srl16e $end -$var wire 1 Y A0 $end -$var wire 1 Z A1 $end -$var wire 1 [ A2 $end -$var wire 1 \ A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 ] D $end -$var wire 1 ^ Q $end -$var reg 16 _ data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[3] $end -$scope module srl16e $end -$var wire 1 ` A0 $end -$var wire 1 a A1 $end -$var wire 1 b A2 $end -$var wire 1 c A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 d D $end -$var wire 1 e Q $end -$var reg 16 f data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[4] $end -$scope module srl16e $end -$var wire 1 g A0 $end -$var wire 1 h A1 $end -$var wire 1 i A2 $end -$var wire 1 j A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 k D $end -$var wire 1 l Q $end -$var reg 16 m data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[5] $end -$scope module srl16e $end -$var wire 1 n A0 $end -$var wire 1 o A1 $end -$var wire 1 p A2 $end -$var wire 1 q A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 r D $end -$var wire 1 s Q $end -$var reg 16 t data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[6] $end -$scope module srl16e $end -$var wire 1 u A0 $end -$var wire 1 v A1 $end -$var wire 1 w A2 $end -$var wire 1 x A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 y D $end -$var wire 1 z Q $end -$var reg 16 { data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[7] $end -$scope module srl16e $end -$var wire 1 | A0 $end -$var wire 1 } A1 $end -$var wire 1 ~ A2 $end -$var wire 1 !" A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 "" D $end -$var wire 1 #" Q $end -$var reg 16 $" data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[8] $end -$scope module srl16e $end -$var wire 1 %" A0 $end -$var wire 1 &" A1 $end -$var wire 1 '" A2 $end -$var wire 1 (" A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 )" D $end -$var wire 1 *" Q $end -$var reg 16 +" data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[9] $end -$scope module srl16e $end -$var wire 1 ," A0 $end -$var wire 1 -" A1 $end -$var wire 1 ." A2 $end -$var wire 1 /" A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 0" D $end -$var wire 1 1" Q $end -$var reg 16 2" data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[10] $end -$scope module srl16e $end -$var wire 1 3" A0 $end -$var wire 1 4" A1 $end -$var wire 1 5" A2 $end -$var wire 1 6" A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 7" D $end -$var wire 1 8" Q $end -$var reg 16 9" data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[11] $end -$scope module srl16e $end -$var wire 1 :" A0 $end -$var wire 1 ;" A1 $end -$var wire 1 <" A2 $end -$var wire 1 =" A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 >" D $end -$var wire 1 ?" Q $end -$var reg 16 @" data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[12] $end -$scope module srl16e $end -$var wire 1 A" A0 $end -$var wire 1 B" A1 $end -$var wire 1 C" A2 $end -$var wire 1 D" A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 E" D $end -$var wire 1 F" Q $end -$var reg 16 G" data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[13] $end -$scope module srl16e $end -$var wire 1 H" A0 $end -$var wire 1 I" A1 $end -$var wire 1 J" A2 $end -$var wire 1 K" A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 L" D $end -$var wire 1 M" Q $end -$var reg 16 N" data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[14] $end -$scope module srl16e $end -$var wire 1 O" A0 $end -$var wire 1 P" A1 $end -$var wire 1 Q" A2 $end -$var wire 1 R" A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 S" D $end -$var wire 1 T" Q $end -$var reg 16 U" data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[15] $end -$scope module srl16e $end -$var wire 1 V" A0 $end -$var wire 1 W" A1 $end -$var wire 1 X" A2 $end -$var wire 1 Y" A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 Z" D $end -$var wire 1 [" Q $end -$var reg 16 \" data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[16] $end -$scope module srl16e $end -$var wire 1 ]" A0 $end -$var wire 1 ^" A1 $end -$var wire 1 _" A2 $end -$var wire 1 `" A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 a" D $end -$var wire 1 b" Q $end -$var reg 16 c" data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[17] $end -$scope module srl16e $end -$var wire 1 d" A0 $end -$var wire 1 e" A1 $end -$var wire 1 f" A2 $end -$var wire 1 g" A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 h" D $end -$var wire 1 i" Q $end -$var reg 16 j" data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[18] $end -$scope module srl16e $end -$var wire 1 k" A0 $end -$var wire 1 l" A1 $end -$var wire 1 m" A2 $end -$var wire 1 n" A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 o" D $end -$var wire 1 p" Q $end -$var reg 16 q" data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[19] $end -$scope module srl16e $end -$var wire 1 r" A0 $end -$var wire 1 s" A1 $end -$var wire 1 t" A2 $end -$var wire 1 u" A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 v" D $end -$var wire 1 w" Q $end -$var reg 16 x" data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[20] $end -$scope module srl16e $end -$var wire 1 y" A0 $end -$var wire 1 z" A1 $end -$var wire 1 {" A2 $end -$var wire 1 |" A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 }" D $end -$var wire 1 ~" Q $end -$var reg 16 !# data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[21] $end -$scope module srl16e $end -$var wire 1 "# A0 $end -$var wire 1 ## A1 $end -$var wire 1 $# A2 $end -$var wire 1 %# A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 &# D $end -$var wire 1 '# Q $end -$var reg 16 (# data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[22] $end -$scope module srl16e $end -$var wire 1 )# A0 $end -$var wire 1 *# A1 $end -$var wire 1 +# A2 $end -$var wire 1 ,# A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 -# D $end -$var wire 1 .# Q $end -$var reg 16 /# data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[23] $end -$scope module srl16e $end -$var wire 1 0# A0 $end -$var wire 1 1# A1 $end -$var wire 1 2# A2 $end -$var wire 1 3# A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 4# D $end -$var wire 1 5# Q $end -$var reg 16 6# data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[24] $end -$scope module srl16e $end -$var wire 1 7# A0 $end -$var wire 1 8# A1 $end -$var wire 1 9# A2 $end -$var wire 1 :# A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 ;# D $end -$var wire 1 <# Q $end -$var reg 16 =# data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[25] $end -$scope module srl16e $end -$var wire 1 ># A0 $end -$var wire 1 ?# A1 $end -$var wire 1 @# A2 $end -$var wire 1 A# A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 B# D $end -$var wire 1 C# Q $end -$var reg 16 D# data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[26] $end -$scope module srl16e $end -$var wire 1 E# A0 $end -$var wire 1 F# A1 $end -$var wire 1 G# A2 $end -$var wire 1 H# A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 I# D $end -$var wire 1 J# Q $end -$var reg 16 K# data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[27] $end -$scope module srl16e $end -$var wire 1 L# A0 $end -$var wire 1 M# A1 $end -$var wire 1 N# A2 $end -$var wire 1 O# A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 P# D $end -$var wire 1 Q# Q $end -$var reg 16 R# data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[28] $end -$scope module srl16e $end -$var wire 1 S# A0 $end -$var wire 1 T# A1 $end -$var wire 1 U# A2 $end -$var wire 1 V# A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 W# D $end -$var wire 1 X# Q $end -$var reg 16 Y# data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[29] $end -$scope module srl16e $end -$var wire 1 Z# A0 $end -$var wire 1 [# A1 $end -$var wire 1 \# A2 $end -$var wire 1 ]# A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 ^# D $end -$var wire 1 _# Q $end -$var reg 16 `# data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[30] $end -$scope module srl16e $end -$var wire 1 a# A0 $end -$var wire 1 b# A1 $end -$var wire 1 c# A2 $end -$var wire 1 d# A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 e# D $end -$var wire 1 f# Q $end -$var reg 16 g# data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[31] $end -$scope module srl16e $end -$var wire 1 h# A0 $end -$var wire 1 i# A1 $end -$var wire 1 j# A2 $end -$var wire 1 k# A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 l# D $end -$var wire 1 m# Q $end -$var reg 16 n# data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[32] $end -$scope module srl16e $end -$var wire 1 o# A0 $end -$var wire 1 p# A1 $end -$var wire 1 q# A2 $end -$var wire 1 r# A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 s# D $end -$var wire 1 t# Q $end -$var reg 16 u# data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[33] $end -$scope module srl16e $end -$var wire 1 v# A0 $end -$var wire 1 w# A1 $end -$var wire 1 x# A2 $end -$var wire 1 y# A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 z# D $end -$var wire 1 {# Q $end -$var reg 16 |# data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[34] $end -$scope module srl16e $end -$var wire 1 }# A0 $end -$var wire 1 ~# A1 $end -$var wire 1 !$ A2 $end -$var wire 1 "$ A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 #$ D $end -$var wire 1 $$ Q $end -$var reg 16 %$ data [15:0] $end -$upscope $end -$upscope $end -$scope begin gen_srl16[35] $end -$scope module srl16e $end -$var wire 1 &$ A0 $end -$var wire 1 '$ A1 $end -$var wire 1 ($ A2 $end -$var wire 1 )$ A3 $end -$var wire 1 E CE $end -$var wire 1 ? CLK $end -$var wire 1 *$ D $end -$var wire 1 +$ Q $end -$var reg 16 ,$ data [15:0] $end -$upscope $end -$upscope $end -$upscope $end -$scope module fifo36_to_fifo19 $end -$var wire 1 > clear $end -$var wire 1 ? clk $end -$var wire 19 -$ f19_dataout [18:0] $end -$var wire 1 ' f19_dst_rdy_i $end -$var wire 1 ( f19_src_rdy_o $end -$var wire 1 .$ f19_xfer $end -$var wire 36 /$ f36_datain [35:0] $end -$var wire 1 $ f36_dst_rdy_o $end -$var wire 1 0$ f36_eof $end -$var wire 1 1$ f36_occ $end -$var wire 1 2$ f36_sof $end -$var wire 1 % f36_src_rdy_i $end -$var wire 1 3$ f36_xfer $end -$var wire 1 4$ half_line $end -$var wire 1 C reset $end -$var reg 1 5$ phase $end -$upscope $end -$scope module fifo19_to_ll8 $end -$var wire 1 6$ advance $end -$var wire 1 > clear $end -$var wire 1 ? clk $end -$var wire 19 7$ f19_data [18:0] $end -$var wire 1 ' f19_dst_rdy_o $end -$var wire 1 8$ f19_eof $end -$var wire 1 9$ f19_occ $end -$var wire 1 :$ f19_sof $end -$var wire 1 ( f19_src_rdy_i $end -$var wire 1 ;$ ll_dst_rdy $end -$var wire 1 / ll_dst_rdy_n $end -$var wire 1 <$ ll_eof $end -$var wire 1 0 ll_eof_n $end -$var wire 1 =$ ll_sof $end -$var wire 1 1 ll_sof_n $end -$var wire 1 >$ ll_src_rdy $end -$var wire 1 2 ll_src_rdy_n $end -$var wire 1 C reset $end -$var reg 8 ?$ ll_data [7:0] $end -$var reg 1 @$ state $end -$upscope $end -$scope module ll8_to_fifo19 $end -$var wire 1 > clear $end -$var wire 1 ? clk $end -$var wire 19 A$ f19_data [18:0] $end -$var wire 1 * f19_dst_rdy_i $end -$var wire 1 + f19_src_rdy_o $end -$var wire 8 B$ ll_data [7:0] $end -$var wire 1 C$ ll_dst_rdy $end -$var wire 1 / ll_dst_rdy_n $end -$var wire 1 D$ ll_eof $end -$var wire 1 0 ll_eof_n $end -$var wire 1 E$ ll_sof $end -$var wire 1 1 ll_sof_n $end -$var wire 1 F$ ll_src_rdy $end -$var wire 1 2 ll_src_rdy_n $end -$var wire 1 C reset $end -$var wire 1 G$ xfer_out $end -$var reg 8 H$ dat0 [7:0] $end -$var reg 8 I$ dat1 [7:0] $end -$var reg 1 J$ f19_eof $end -$var reg 1 K$ f19_occ $end -$var reg 1 L$ f19_sof $end -$var reg 2 M$ state [1:0] $end -$upscope $end -$scope module fifo19_to_fifo36 $end -$var wire 1 > clear $end -$var wire 1 ? clk $end -$var wire 19 N$ f19_datain [18:0] $end -$var wire 1 * f19_dst_rdy_o $end -$var wire 1 O$ f19_eof $end -$var wire 1 P$ f19_occ $end -$var wire 1 Q$ f19_sof $end -$var wire 1 + f19_src_rdy_i $end -$var wire 36 R$ f36_dataout [35:0] $end -$var wire 1 S$ f36_dst_rdy_i $end -$var wire 1 - f36_src_rdy_o $end -$var wire 1 C reset $end -$var wire 1 T$ xfer_out $end -$var reg 16 U$ dat0 [15:0] $end -$var reg 16 V$ dat1 [15:0] $end -$var reg 1 W$ f36_eof $end -$var reg 1 X$ f36_occ $end -$var reg 1 Y$ f36_sof $end -$var reg 2 Z$ state [1:0] $end -$upscope $end -$scope task PutPacketInFIFO36 $end -$var reg 32 [$ data_len [31:0] $end -$var reg 32 \$ data_start [31:0] $end -$upscope $end -$scope task ReadFromFIFO36 $end -$upscope $end -$upscope $end -$enddefinitions $end -#0 -$dumpvars -bx \$ -bx [$ -bx Z$ -xY$ -xX$ -xW$ -bx V$ -bx U$ -0T$ -0S$ -b0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx R$ -xQ$ -xP$ -xO$ -bx N$ -bx M$ -xL$ -xK$ -xJ$ -bx I$ -bx H$ -xG$ -xF$ -xE$ -xD$ -xC$ -bx B$ -bx A$ -x@$ -bx ?$ -x>$ -x=$ -x<$ -x;$ -x:$ -x9$ -x8$ -bx 7$ -x6$ -x5$ -x4$ -x3$ -x2$ -x1$ -x0$ -bx /$ -x.$ -bx -$ -b0 ,$ -x+$ -0*$ -x)$ -x($ -x'$ -x&$ -b0 %$ -x$$ -0#$ -x"$ -x!$ -x~# -x}# -b0 |# -x{# -0z# -xy# -xx# -xw# -xv# -b0 u# -xt# -0s# -xr# -xq# -xp# -xo# -b0 n# -xm# -0l# -xk# -xj# -xi# -xh# -b0 g# -xf# -0e# -xd# -xc# -xb# -xa# -b0 `# -x_# -0^# -x]# -x\# -x[# -xZ# -b0 Y# -xX# -0W# -xV# -xU# -xT# -xS# -b0 R# -xQ# -0P# -xO# -xN# -xM# -xL# -b0 K# -xJ# -0I# -xH# -xG# -xF# -xE# -b0 D# -xC# -0B# -xA# -x@# -x?# -x># -b0 =# -x<# -0;# -x:# -x9# -x8# -x7# -b0 6# -x5# -04# -x3# -x2# -x1# -x0# -b0 /# -x.# -0-# -x,# -x+# -x*# -x)# -b0 (# -x'# -0&# -x%# -x$# -x## -x"# -b0 !# -x~" -0}" -x|" -x{" -xz" -xy" -b0 x" -xw" -0v" -xu" -xt" -xs" -xr" -b0 q" -xp" -0o" -xn" -xm" -xl" -xk" -b0 j" -xi" -0h" -xg" -xf" -xe" -xd" -b0 c" -xb" -0a" -x`" -x_" -x^" -x]" -b0 \" -x[" -0Z" -xY" -xX" -xW" -xV" -b0 U" -xT" -0S" -xR" -xQ" -xP" -xO" -b0 N" -xM" -0L" -xK" -xJ" -xI" -xH" -b0 G" -xF" -0E" -xD" -xC" -xB" -xA" -b0 @" -x?" -0>" -x=" -x<" -x;" -x:" -b0 9" -x8" -07" -x6" -x5" -x4" -x3" -b0 2" -x1" -00" -x/" -x." -x-" -x," -b0 +" -x*" -0)" -x(" -x'" -x&" -x%" -b0 $" -x#" -0"" -x!" -x~ -x} -x| -b0 { -xz -0y -xx -xw -xv -xu -b0 t -xs -0r -xq -xp -xo -xn -b0 m -xl -0k -xj -xi -xh -xg -b0 f -xe -0d -xc -xb -xa -x` -b0 _ -x^ -0] -x\ -x[ -xZ -xY -b0 X -xW -0V -xU -xT -xS -xR -b0 Q -xP -0O -xN -xM -xL -xK -bx J -bx I -xH -xG -bx F -0E -0D -1C -xB -bx A -b0 @ -0? -0> -0= -1< -0; -0: -b0 9 -08 -b0 7 -06 -bx 5 -04 -03 -x2 -x1 -x0 -x/ -bx . -x- -b0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx , -x+ -x* -bx ) -x( -x' -bx & -x% -x$ -bx # -b0 " -x! -$end -#50000000000000 -0D$ -10 -0E$ -0<$ -11 -08$ -09$ -0=$ -0$ -b0 ?$ -b0 . -b0 B$ -0:$ -0' -0F$ -04$ -01$ -b0 & -b0 -$ -b0 7$ -1;$ -0.$ -06$ -12 -03$ -0B -02$ -00$ -0/ -1! -0>$ -0( -0% -0K -0P -0L -0M -0N -0R -0W -0S -0T -0U -0Y -0^ -0Z -0[ -0\ -0` -0e -0a -0b -0c -0g -0l -0h -0i -0j -0n -0s -0o -0p -0q -0u -0z -0v -0w -0x -0| -0#" -0} -0~ -0!" -0%" -0*" -0&" -0'" -0(" -0," -01" -0-" -0." -0/" -03" -08" -04" -05" -06" -0:" -0?" -0;" -0<" -0=" -0A" -0F" -0B" -0C" -0D" -0H" -0M" -0I" -0J" -0K" -0O" -0T" -0P" -0Q" -0R" -0V" -0[" -0W" -0X" -0Y" -0]" -0b" -0^" -0_" -0`" -0d" -0i" -0e" -0f" -0g" -0k" -0p" -0l" -0m" -0n" -0r" -0w" -0s" -0t" -0u" -0y" -0~" -0z" -0{" -0|" -0"# -0'# -0## -0$# -0%# -0)# -0.# -0*# -0+# -0,# -00# -05# -01# -02# -03# -07# -0<# -08# -09# -0:# -0># -0C# -0?# -0@# -0A# -0E# -0J# -0F# -0G# -0H# -0L# -0Q# -0M# -0N# -0O# -0S# -0X# -0T# -0U# -0V# -0Z# -0_# -0[# -0\# -0]# -0a# -0f# -0b# -0c# -0d# -0h# -0m# -0i# -0j# -0k# -0o# -0t# -0p# -0q# -0r# -0v# -0{# -0w# -0x# -0y# -0}# -0$$ -0~# -0!$ -0"$ -0&$ -0+$ -b0 # -b0 A -b0 /$ -0'$ -0($ -0)$ -0P$ -1C$ -0G$ -1* -0H -1G -b0 F -b10000 J -b0 I -05$ -0@$ -0K$ -b0xxxxxxxxxxxxxxxxxx ) -b0xxxxxxxxxxxxxxxxxx A$ -b0xxxxxxxxxxxxxxxxxx N$ -b0 M$ -0+ -0X$ -b0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx , -b0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx R$ -b0 Z$ -0- -14 -1? -#100000000000000 -04 -0? -#150000000000000 -14 -1? -#200000000000000 -04 -0? -#250000000000000 -14 -1? -#300000000000000 -04 -0? -#350000000000000 -14 -1? -#400000000000000 -04 -0? -#450000000000000 -14 -1? -#500000000000000 -04 -0? -#550000000000000 -14 -1? -#600000000000000 -04 -0? -#650000000000000 -14 -1? -#700000000000000 -04 -0? -#750000000000000 -14 -1? -#800000000000000 -04 -0? -#850000000000000 -14 -1? -#900000000000000 -04 -0? -#950000000000000 -14 -1? -#1000000000000000 -04 -0? -0< -0C -#1050000000000000 -14 -1? -#1100000000000000 -04 -0? -#1150000000000000 -1k -1y -1"" -1S" -1Z" -1}" -1&# -14# -1^# -1l# -1s# -1E -1: -b10100000101100001100000011010000 7 -b110100000101100001100000011010000 " -b110100000101100001100000011010000 @ -1= -1D -b100 5 -b1100 [$ -b10100000101100001100000011010000 \$ -14 -1? -#1200000000000000 -04 -0? -#1250000000000000 -1F$ -16$ -02 -1>$ -1( -1% -1O -1)" -1a" -1;# -0s# -0G -b1111 J -b1 I -b1000 5 -b10100001101100011100000111010001 7 -0: -b10100001101100011100000111010001 " -b10100001101100011100000111010001 @ -14 -1? -#1250000000000100 -1E$ -01 -1=$ -b10100000 ?$ -b10100000 . -b10100000 B$ -1:$ -b11010000010110000 & -b11010000010110000 -$ -b11010000010110000 7$ -12$ -b1 m -1l -b1 { -1z -b1 $" -1#" -b1 U" -1T" -b1 \" -1[" -b1 !# -1~" -b1 (# -1'# -b1 6# -15# -b1 `# -1_# -b1 n# -1m# -b1 u# -1t# -b110100000101100001100000011010000 # -b110100000101100001100000011010000 A -b110100000101100001100000011010000 /$ -#1300000000000000 -04 -0? -#1350000000000000 -0E$ -0:$ -1.$ -11 -b0 & -b0 -$ -b0 7$ -1' -0=$ -02$ -0O -1V -0)" -10" -0a" -1h" -0;# -1B# -1z# -1Q$ -0O$ -b0 ?$ -b0 . -b0 B$ -1K -1R -1Y -1` -1g -0l -1n -1u -0z -1| -0#" -1%" -1," -13" -1:" -1A" -1H" -1O" -0T" -1V" -0[" -1]" -1d" -1k" -1r" -1y" -0~" -1"# -0'# -1)# -10# -05# -17# -1># -1E# -1L# -1S# -1Z# -0_# -1a# -1h# -0m# -1o# -0t# -b0 # -b0 A -b0 /$ -1v# -1}# -1&$ -18 -b10100010101100101100001011010010 7 -b1010100010101100101100001011010010 " -b1010100010101100101100001011010010 @ -b10100000 H$ -b1 M$ -0J$ -1L$ -b110100000xxxxxxxx ) -b110100000xxxxxxxx A$ -b110100000xxxxxxxx N$ -1@$ -b10 I -b1110 J -b1 F -14 -1? -#1350000000000100 -b10110000 ?$ -b10110000 . -b10110000 B$ -1:$ -b11010000010110000 & -b11010000010110000 -$ -b11010000010110000 7$ -12$ -b10 u# -1t# -b11 n# -1m# -b11 `# -1_# -b1 =# -b11 6# -15# -b11 (# -1'# -b11 !# -1~" -b1 c" -b11 \" -1[" -b11 U" -1T" -b1 +" -b11 $" -1#" -b11 { -1z -b11 m -1l -b110100000101100001100000011010000 # -b110100000101100001100000011010000 A -b110100000101100001100000011010000 /$ -b1 Q -#1351000000000000 -1; -1S$ -#1400000000000000 -04 -0? -#1450000000000000 -0E$ -0.$ -11 -02$ -0:$ -0' -0=$ -0K -1L -0R -1S -0Y -1Z -0` -1a -0g -1h -0l -0n -1o -0u -1v -0z -0| -1} -0#" -0%" -1&" -0," -1-" -03" -14" -0:" -1;" -0A" -1B" -0H" -1I" -0O" -1P" -0T" -0V" -1W" -0[" -0]" -1^" -0d" -1e" -0k" -1l" -0r" -1s" -0y" -1z" -0~" -0"# -1## -0'# -0)# -1*# -00# -11# -05# -07# -18# -0># -1?# -0E# -1F# -0L# -1M# -0S# -1T# -0Z# -1[# -0_# -0a# -1b# -0h# -1i# -0m# -0o# -1p# -0t# -b0 # -b0 A -b0 /$ -0v# -1w# -0}# -1~# -0&$ -1'$ -b0 & -b0 -$ -b0 7$ -b0 ?$ -b0 . -b0 B$ -1G$ -0E -0V -0k -0y -0"" -00" -0S" -0Z" -0h" -0}" -0&# -04# -0B# -0^# -0l# -0z# -b10 F -b1101 J -b11 I -15$ -0@$ -b10 M$ -1+ -b10110000 I$ -b11010000010110000 ) -b11010000010110000 A$ -b11010000010110000 N$ -0= -0D -b0 7 -08 -b0 " -b0 @ -14 -1? -#1450000000000100 -b11000000 ?$ -b11000000 . -b11000000 B$ -b1100000011010000 & -b1100000011010000 -$ -b1100000011010000 7$ -12$ -b10 Q -b1 X -b111 m -1l -b111 { -1z -b111 $" -1#" -b10 +" -b1 2" -b111 U" -1T" -b111 \" -1[" -b10 c" -b1 j" -b111 !# -1~" -b111 (# -1'# -b111 6# -15# -b10 =# -b1 D# -b111 `# -1_# -b111 n# -1m# -b100 u# -1t# -b110100000101100001100000011010000 # -b110100000101100001100000011010000 A -b110100000101100001100000011010000 /$ -b1 |# -#1500000000000000 -04 -0? -#1550000000000000 -13$ -1B -1.$ -1$ -1' -0G$ -0Q$ -b11010000 ?$ -b11010000 . -b11010000 B$ -b1010000010110000 U$ -b1 Z$ -0W$ -1Y$ -b11010000010110000xxxxxxxxxxxxxxxx , -b11010000010110000xxxxxxxxxxxxxxxx R$ -b11000000 H$ -b1 M$ -0+ -0L$ -b1100000010110000 ) -b1100000010110000 A$ -b1100000010110000 N$ -1@$ -14 -1? -#1600000000000000 -04 -0? -#1650000000000000 -0E$ -11 -0=$ -03$ -0B -0.$ -02$ -0:$ -0$ -0' -1K -1P -0L -1R -0S -0W -1Y -0Z -1` -0a -1g -0h -1n -0o -1u -0v -1| -0} -1%" -1*" -0&" -1," -0-" -01" -13" -04" -1:" -0;" -1A" -0B" -1H" -0I" -1O" -0P" -1V" -0W" -1]" -1b" -0^" -1d" -0e" -0i" -1k" -0l" -1r" -0s" -1y" -0z" -1"# -0## -1)# -0*# -10# -01# -17# -1<# -08# -1># -0?# -0C# -1E# -0F# -1L# -0M# -1S# -0T# -1Z# -0[# -1a# -0b# -1h# -0i# -1o# -0p# -0t# -1v# -0w# -0{# -b10100001101100011100000111010001 # -b10100001101100011100000111010001 A -b10100001101100011100000111010001 /$ -1}# -0~# -1&$ -0'$ -b1010000110110001 & -b1010000110110001 -$ -b1010000110110001 7$ -b10100001 ?$ -b10100001 . -b10100001 B$ -1G$ -b1 F -b1110 J -b10 I -05$ -0@$ -b10 M$ -1+ -b11010000 I$ -b1100000011010000 ) -b1100000011010000 A$ -b1100000011010000 N$ -14 -1? -#1700000000000000 -04 -0? -#1750000000000000 -1.$ -1' -1T$ -0G$ -b10110001 ?$ -b10110001 . -b10110001 B$ -b1100000011010000 V$ -b110100000101100001100000011010000 , -b110100000101100001100000011010000 R$ -b10 Z$ -1- -b10100001 H$ -b1010000111010000 ) -b1010000111010000 A$ -b1010000111010000 N$ -b1 M$ -0+ -1@$ -14 -1? -#1800000000000000 -04 -0? -#1850000000000000 -0.$ -0' -b1100000111010001 & -b1100000111010001 -$ -b1100000111010001 7$ -b11000001 ?$ -b11000001 . -b11000001 B$ -1G$ -0T$ -15$ -0@$ -b10 M$ -1+ -b10110001 I$ -b1010000110110001 ) -b1010000110110001 A$ -b1010000110110001 N$ -b0 Z$ -0- -14 -1? -#1900000000000000 -04 -0? -#1950000000000000 -13$ -1B -1.$ -1$ -1' -0G$ -b11010001 ?$ -b11010001 . -b11010001 B$ -b1010000110110001 U$ -b1 Z$ -0Y$ -b10100001101100011100000011010000 , -b10100001101100011100000011010000 R$ -b11000001 H$ -b1100000110110001 ) -b1100000110110001 A$ -b1100000110110001 N$ -b1 M$ -0+ -1@$ -14 -1? -#2000000000000000 -04 -0? -#2050000000000000 -03$ -0B -0.$ -10$ -0$ -0' -0K -0P -0R -1W -0Y -0` -0g -0n -0u -0| -0%" -0*" -0," -11" -03" -0:" -0A" -0H" -0O" -0V" -0]" -0b" -0d" -1i" -0k" -0r" -0y" -0"# -0)# -00# -07# -0<# -0># -1C# -0E# -0L# -0S# -0Z# -0a# -0h# -0o# -0v# -1{# -b1010100010101100101100001011010010 # -b1010100010101100101100001011010010 A -b1010100010101100101100001011010010 /$ -0}# -0&$ -b1010001010110010 & -b1010001010110010 -$ -b1010001010110010 7$ -b10100010 ?$ -b10100010 . -b10100010 B$ -1G$ -b0 F -b1111 J -b1 I -05$ -0@$ -b10 M$ -1+ -b11010001 I$ -b1100000111010001 ) -b1100000111010001 A$ -b1100000111010001 N$ -14 -1? -#2100000000000000 -04 -0? -#2150000000000000 -1.$ -1' -1T$ -0G$ -b10110010 ?$ -b10110010 . -b10110010 B$ -b1100000111010001 V$ -b10100001101100011100000111010001 , -b10100001101100011100000111010001 R$ -b10 Z$ -1- -b10100010 H$ -b1010001011010001 ) -b1010001011010001 A$ -b1010001011010001 N$ -b1 M$ -0+ -1@$ -14 -1? -#2200000000000000 -04 -0? -#2250000000000000 -0.$ -18$ -0' -b101100001011010010 & -b101100001011010010 -$ -b101100001011010010 7$ -b11000010 ?$ -b11000010 . -b11000010 B$ -1G$ -0T$ -15$ -0@$ -b10 M$ -1+ -b10110010 I$ -b1010001010110010 ) -b1010001010110010 A$ -b1010001010110010 N$ -b0 Z$ -0- -14 -1? -#2300000000000000 -04 -0? -#2350000000000000 -1D$ -13$ -1B -00 -1.$ -1$ -1<$ -1' -0G$ -b11010010 ?$ -b11010010 . -b11010010 B$ -b1010001010110010 U$ -b10100010101100101100000111010001 , -b10100010101100101100000111010001 R$ -b1 Z$ -b11000010 H$ -b1100001010110010 ) -b1100001010110010 A$ -b1100001010110010 N$ -b1 M$ -0+ -1@$ -14 -1? -#2400000000000000 -04 -0? -#2450000000000000 -0D$ -0' -0F$ -10 -0.$ -06$ -12 -03$ -0B -08$ -0$ -0<$ -0>$ -0( -0% -b1010001010110010 & -b1010001010110010 -$ -b1010001010110010 7$ -b10100010 ?$ -b10100010 . -b10100010 B$ -1G$ -1O$ -1G -b10000 J -b0 I -05$ -0@$ -1J$ -b10 M$ -1+ -b11010010 I$ -b101100001011010010 ) -b101100001011010010 A$ -b101100001011010010 N$ -14 -1? -#2500000000000000 -04 -0? -#2550000000000000 -1T$ -0G$ -b1100001011010010 V$ -b10 Z$ -1- -1W$ -b1010100010101100101100001011010010 , -b1010100010101100101100001011010010 R$ -b0 M$ -0+ -14 -1? -#2600000000000000 -04 -0? -#2650000000000000 -0T$ -b0 Z$ -0- -14 -1? -#2700000000000000 -04 -0? -#2750000000000000 -14 -1? -#2800000000000000 -04 -0? -#2850000000000000 -14 -1? -#2900000000000000 -04 -0? -#2950000000000000 -14 -1? -#3000000000000000 -04 -0? -#3050000000000000 -14 -1? -#3100000000000000 -04 -0? -#3150000000000000 -14 -1? -#3200000000000000 -04 -0? -#3250000000000000 -14 -1? -#3300000000000000 -04 -0? -#3350000000000000 -14 -1? -#3400000000000000 -04 -0? -#3450000000000000 -14 -1? -#3500000000000000 -04 -0? -#3550000000000000 -14 -1? -#3600000000000000 -04 -0? -#3650000000000000 -14 -1? -#3700000000000000 -04 -0? -#3750000000000000 -14 -1? -#3800000000000000 -04 -0? -#3850000000000000 -14 -1? -#3900000000000000 -04 -0? -#3950000000000000 -14 -1? -#4000000000000000 -04 -0? -#4050000000000000 -14 -1? -#4100000000000000 -04 -0? -#4150000000000000 -14 -1? -#4200000000000000 -04 -0? -#4250000000000000 -14 -1? -#4300000000000000 -04 -0? -#4350000000000000 -14 -1? -#4400000000000000 -04 -0? -#4450000000000000 -14 -1? -#4500000000000000 -04 -0? -#4550000000000000 -14 -1? -#4600000000000000 -04 -0? -#4650000000000000 -14 -1? -#4700000000000000 -04 -0? -#4750000000000000 -14 -1? -#4800000000000000 -04 -0? -#4850000000000000 -14 -1? -#4900000000000000 -04 -0? -#4950000000000000 -14 -1? -#5000000000000000 -04 -0? -#5050000000000000 -14 -1? -#5100000000000000 -04 -0? -#5150000000000000 -14 -1? -#5200000000000000 -04 -0? -#5250000000000000 -14 -1? -#5300000000000000 -04 -0? -#5350000000000000 -14 -1? -#5400000000000000 -04 -0? -#5450000000000000 -14 -1? -#5500000000000000 -04 -0? -#5550000000000000 -14 -1? -#5600000000000000 -04 -0? -#5650000000000000 -14 -1? -#5700000000000000 -04 -0? -#5750000000000000 -14 -1? -#5800000000000000 -04 -0? -#5850000000000000 -14 -1? -#5900000000000000 -04 -0? -#5950000000000000 -14 -1? -#6000000000000000 -04 -0? -#6050000000000000 -14 -1? -#6100000000000000 -04 -0? -#6150000000000000 -14 -1? -#6200000000000000 -04 -0? -#6250000000000000 -14 -1? -#6300000000000000 -04 -0? -#6350000000000000 -14 -1? -#6400000000000000 -04 -0? -#6450000000000000 -14 -1? -#6500000000000000 -04 -0? -#6550000000000000 -14 -1? -#6600000000000000 -04 -0? -#6650000000000000 -14 -1? -#6700000000000000 -04 -0? -#6750000000000000 -14 -1? -#6800000000000000 -04 -0? -#6850000000000000 -14 -1? -#6900000000000000 -04 -0? -#6950000000000000 -14 -1? -#7000000000000000 -04 -0? -#7050000000000000 -14 -1? -#7100000000000000 -04 -0? -#7150000000000000 -14 -1? -#7200000000000000 -04 -0? -#7250000000000000 -14 -1? -#7300000000000000 -04 -0? -#7350000000000000 -14 -1? -#7400000000000000 -04 -0? -#7450000000000000 -14 -1? -#7500000000000000 -04 -0? -#7550000000000000 -14 -1? -#7600000000000000 -04 -0? -#7650000000000000 -14 -1? -#7700000000000000 -04 -0? -#7750000000000000 -14 -1? -#7800000000000000 -04 -0? -#7850000000000000 -14 -1? -#7900000000000000 -04 -0? -#7950000000000000 -14 -1? -#8000000000000000 -04 -0? -#8050000000000000 -14 -1? -#8100000000000000 -04 -0? -#8150000000000000 -14 -1? -#8200000000000000 -04 -0? -#8250000000000000 -14 -1? -#8300000000000000 -04 -0? -#8350000000000000 -14 -1? -#8400000000000000 -04 -0? -#8450000000000000 -14 -1? -#8500000000000000 -04 -0? -#8550000000000000 -14 -1? -#8600000000000000 -04 -0? -#8650000000000000 -14 -1? -#8700000000000000 -04 -0? -#8750000000000000 -14 -1? -#8800000000000000 -04 -0? -#8850000000000000 -14 -1? -#8900000000000000 -04 -0? -#8950000000000000 -14 -1? -#9000000000000000 -04 -0? -#9050000000000000 -14 -1? -#9100000000000000 -04 -0? -#9150000000000000 -14 -1? -#9200000000000000 -04 -0? -#9250000000000000 -14 -1? -#9300000000000000 -04 -0? -#9350000000000000 -14 -1? -#9400000000000000 -04 -0? -#9450000000000000 -14 -1? -#9500000000000000 -04 -0? -#9550000000000000 -14 -1? -#9600000000000000 -04 -0? -#9650000000000000 -14 -1? -#9700000000000000 -04 -0? -#9750000000000000 -14 -1? -#9800000000000000 -04 -0? -#9850000000000000 -14 -1? -#9900000000000000 -04 -0? -#9950000000000000 -14 -1? -#10000000000000000 -04 -0? -#10050000000000000 -14 -1? -#10100000000000000 -04 -0? -#10150000000000000 -14 -1? -#10200000000000000 -04 -0? -#10250000000000000 -14 -1? -#10300000000000000 -04 -0? -#10350000000000000 -14 -1? -#10400000000000000 -04 -0? -#10450000000000000 -14 -1? -#10500000000000000 -04 -0? -#10550000000000000 -14 -1? -#10600000000000000 -04 -0? -#10650000000000000 -14 -1? -#10700000000000000 -04 -0? -#10750000000000000 -14 -1? -#10800000000000000 -04 -0? -#10850000000000000 -14 -1? -#10900000000000000 -04 -0? -#10950000000000000 -14 -1? -#11000000000000000 -04 -0? -#11050000000000000 -14 -1? -#11100000000000000 -04 -0? -#11150000000000000 -14 -1? -#11200000000000000 -04 -0? -#11250000000000000 -14 -1? -#11300000000000000 -04 -0? -#11350000000000000 -14 -1? -#11400000000000000 -04 -0? -#11450000000000000 -14 -1? -#11500000000000000 -04 -0? -#11550000000000000 -14 -1? -#11600000000000000 -04 -0? -#11650000000000000 -1k -1r -1"" -1L" -1Z" -1}" -1&# -1-# -14# -1^# -1e# -1l# -1s# -1E -1: -b11100000111100001010000010110000 7 -b111100000111100001010000010110000 " -b111100000111100001010000010110000 @ -1= -1D -b100 5 -b100100 [$ -b11100000111100001010000010110000 \$ -14 -1? -#11700000000000000 -04 -0? -#11750000000000000 -1F$ -16$ -02 -1>$ -1( -1% -1O -1)" -1a" -1;# -0s# -b1 I -b1111 J -0G -b1000 5 -b11100001111100011010000110110001 7 -0: -b11100001111100011010000110110001 " -b11100001111100011010000110110001 @ -14 -1? -#11750000000000100 -1E$ -01 -1=$ -b11100000 ?$ -b11100000 . -b11100000 B$ -1:$ -b11110000011110000 & -b11110000011110000 -$ -b11110000011110000 7$ -12$ -00$ -b10 |# -0{# -b1001 u# -1t# -b1111 n# -b1 g# -1f# -b1111 `# -b10 D# -0C# -b100 =# -b1111 6# -b1 /# -1.# -b1111 (# -b1111 !# -b10 j" -0i" -b100 c" -b1111 \" -b1110 U" -0T" -b1 N" -1M" -b10 2" -01" -b100 +" -b1111 $" -b1110 { -0z -b1 t -1s -b1111 m -b10 X -0W -b111100000111100001010000010110000 # -b111100000111100001010000010110000 A -b111100000111100001010000010110000 /$ -b100 Q -#11800000000000000 -04 -0? -#11850000000000000 -0:$ -0E$ -b1010001010110010 & -b1010001010110010 -$ -b1010001010110010 7$ -1.$ -11 -02$ -10$ -1' -0=$ -0O -1V -0)" -10" -0a" -1h" -0;# -1B# -1K -1R -1W -1Y -1` -1g -1n -0s -1u -1z -1| -1%" -1," -11" -13" -1:" -1A" -1H" -0M" -1O" -1T" -1V" -1]" -1d" -1i" -1k" -1r" -1y" -1"# -1)# -0.# -10# -17# -1># -1C# -1E# -1L# -1S# -1Z# -1a# -0f# -1h# -1o# -0t# -1v# -1{# -b1010100010101100101100001011010010 # -b1010100010101100101100001011010010 A -b1010100010101100101100001011010010 /$ -1}# -1&$ -b10110010 ?$ -b10110010 . -b10110010 B$ -1Q$ -0O$ -b1100 5 -b11100010111100101010001010110010 7 -b11100010111100101010001010110010 " -b11100010111100101010001010110010 @ -b1 F -b1110 J -b10 I -1@$ -1L$ -0J$ -b1 M$ -b11100000 H$ -b11110000011010010 ) -b11110000011010010 A$ -b11110000011010010 N$ -14 -1? -#11850000000000100 -b11110000 ?$ -b11110000 . -b11110000 B$ -1:$ -b11110000011110000 & -b11110000011110000 -$ -b11110000011110000 7$ -12$ -00$ -b1001 Q -b100 X -0W -b11111 m -b11 t -1s -b11100 { -0z -b11111 $" -b1001 +" -b100 2" -01" -b11 N" -1M" -b11100 U" -0T" -b11111 \" -b1001 c" -b100 j" -0i" -b11111 !# -b11111 (# -b11 /# -1.# -b11111 6# -b1001 =# -b100 D# -0C# -b11111 `# -b11 g# -1f# -b11111 n# -b10010 u# -1t# -b100 |# -0{# -b111100000111100001010000010110000 # -b111100000111100001010000010110000 A -b111100000111100001010000010110000 /$ -#11900000000000000 -04 -0? -#11950000000000000 -18$ -0.$ -03$ -0B -0' -0:$ -0$ -02$ -10$ -1G$ -b11000010 ?$ -b11000010 . -b11000010 B$ -b101100001011010010 & -b101100001011010010 -$ -b101100001011010010 7$ -0K -1L -0P -0R -1W -1S -0Y -1Z -0` -1a -0g -1h -0n -1o -0s -0u -1v -1z -0| -1} -0%" -1&" -0*" -0," -11" -1-" -03" -14" -0:" -1;" -0A" -1B" -0H" -1I" -0M" -0O" -1P" -1T" -0V" -1W" -0]" -1^" -0b" -0d" -1i" -1e" -0k" -1l" -0r" -1s" -0y" -1z" -0"# -1## -0)# -1*# -0.# -00# -11# -07# -18# -0<# -0># -1C# -1?# -0E# -1F# -0L# -1M# -0S# -1T# -0Z# -1[# -0a# -1b# -0f# -0h# -1i# -0o# -1p# -0t# -0v# -1{# -b1010100010101100101100001011010010 # -b1010100010101100101100001011010010 A -b1010100010101100101100001011010010 /$ -1w# -0}# -1~# -0&$ -1'$ -1O -1)" -1a" -1;# -b11110000 I$ -b11110000011110000 ) -b11110000011110000 A$ -b11110000011110000 N$ -b10 M$ -1+ -0@$ -15$ -b11 I -b1101 J -b10 F -b10000 5 -b11100011111100111010001110110011 7 -b11100011111100111010001110110011 " -b11100011111100111010001110110011 @ -14 -1? -#11950000000000100 -b10100000 ?$ -b10100000 . -b10100000 B$ -08$ -b1010000010110000 & -b1010000010110000 -$ -b1010000010110000 7$ -12$ -00$ -b1000 |# -0{# -b100100 u# -1t# -b111111 n# -b111 g# -1f# -b111111 `# -b1001 D# -0C# -b10010 =# -b111111 6# -b111 /# -1.# -b111111 (# -b111111 !# -b1001 j" -0i" -b10010 c" -b111111 \" -b111000 U" -0T" -b111 N" -1M" -b1001 2" -01" -b10010 +" -b111111 $" -b111000 { -0z -b111 t -1s -b111111 m -b1001 X -0W -b111100000111100001010000010110000 # -b111100000111100001010000010110000 A -b111100000111100001010000010110000 /$ -b10010 Q -#12000000000000000 -04 -0? -#12050000000000000 -1D$ -00 -1<$ -18$ -13$ -1B -b101100001011010010 & -b101100001011010010 -$ -b101100001011010010 7$ -1.$ -1$ -02$ -10$ -1' -0O -0V -1] -0)" -00" -17" -0a" -0h" -1o" -0;# -0B# -1I# -1K -1R -1W -1Y -1` -1g -1n -0s -1u -1z -1| -1%" -1," -11" -13" -1:" -1A" -1H" -0M" -1O" -1T" -1V" -1]" -1d" -1i" -1k" -1r" -1y" -1"# -1)# -0.# -10# -17# -1># -1C# -1E# -1L# -1S# -1Z# -1a# -0f# -1h# -1o# -0t# -1v# -1{# -b1010100010101100101100001011010010 # -b1010100010101100101100001011010010 A -b1010100010101100101100001011010010 /$ -1}# -1&$ -b11010010 ?$ -b11010010 . -b11010010 B$ -0G$ -0Q$ -b10100 5 -b11100100111101001010010010110100 7 -b11100100111101001010010010110100 " -b11100100111101001010010010110100 @ -b11 F -b1100 J -b100 I -1@$ -0L$ -b1 M$ -0+ -b10100000 H$ -b1010000011110000 ) -b1010000011110000 A$ -b1010000011110000 N$ -1Y$ -0W$ -b1 Z$ -b1110000011110000 U$ -b111100000111100001100001011010010 , -b111100000111100001100001011010010 R$ -14 -1? -#12050000000000100 -0D$ -10 -0<$ -b10110000 ?$ -b10110000 . -b10110000 B$ -08$ -b1010000010110000 & -b1010000010110000 -$ -b1010000010110000 7$ -12$ -00$ -b100101 Q -b10011 X -0W -b1111111 m -b1111 t -1s -b1110000 { -0z -b1111111 $" -b100101 +" -b10011 2" -01" -b1111 N" -1M" -b1110000 U" -0T" -b1111111 \" -b100101 c" -b10011 j" -0i" -b1111111 !# -b1111111 (# -b1111 /# -1.# -b1111111 6# -b100101 =# -b10011 D# -0C# -b1111111 `# -b1111 g# -1f# -b1111111 n# -b1001000 u# -1t# -b10000 |# -0{# -b111100000111100001010000010110000 # -b111100000111100001010000010110000 A -b111100000111100001010000010110000 /$ -#12100000000000000 -04 -0? -#12150000000000000 -1E$ -0.$ -01 -03$ -0B -0' -1=$ -1:$ -0$ -1G$ -b11100000 ?$ -b11100000 . -b11100000 B$ -b11110000011110000 & -b11110000011110000 -$ -b11110000011110000 7$ -1O -1)" -1a" -1;# -b10110000 I$ -b1010000010110000 ) -b1010000010110000 A$ -b1010000010110000 N$ -b10 M$ -1+ -0@$ -05$ -b11000 5 -b11100101111101011010010110110101 7 -b11100101111101011010010110110101 " -b11100101111101011010010110110101 @ -14 -1? -#12150000000000100 -0E$ -11 -0=$ -b11100001 ?$ -b11100001 . -b11100001 B$ -0:$ -b1110000111110001 & -b1110000111110001 -$ -b1110000111110001 7$ -02$ -b100000 |# -b10010000 u# -0t# -b11111111 n# -b11111 g# -b11111111 `# -b1 K# -b100110 D# -b1001010 =# -1<# -b11111111 6# -b11111 /# -b11111111 (# -b11111111 !# -b1 q" -b100110 j" -b1001010 c" -1b" -b11111111 \" -b11100000 U" -b11111 N" -b1 9" -b100110 2" -b1001010 +" -1*" -b11111111 $" -b11100000 { -b11111 t -b11111111 m -b1 _ -b100110 X -b1001010 Q -1P -b11100001111100011010000110110001 # -b11100001111100011010000110110001 A -b11100001111100011010000110110001 /$ -#12200000000000000 -04 -0? -#12250000000000000 -1:$ -b11110000011110000 & -b11110000011110000 -$ -b11110000011110000 7$ -1.$ -12$ -1' -0O -1V -0)" -10" -0a" -1h" -0;# -1B# -0K -0L -1M -0P -0R -0S -0W -1T -0Y -0Z -1[ -0` -0a -1b -0g -0h -1i -0n -0o -1p -1s -0u -0v -1w -0z -0| -0} -1~ -0%" -0&" -1'" -0*" -0," -0-" -01" -1." -03" -04" -15" -0:" -0;" -1<" -0A" -0B" -1C" -0H" -0I" -1J" -1M" -0O" -0P" -1Q" -0T" -0V" -0W" -1X" -0]" -0^" -1_" -0b" -0d" -0e" -0i" -1f" -0k" -0l" -1m" -0r" -0s" -1t" -0y" -0z" -1{" -0"# -0## -1$# -0)# -0*# -1+# -1.# -00# -01# -12# -07# -08# -19# -0<# -0># -0?# -0C# -1@# -0E# -0F# -1G# -0L# -0M# -1N# -0S# -0T# -1U# -0Z# -0[# -1\# -0a# -0b# -1c# -1f# -0h# -0i# -1j# -0o# -0p# -1q# -1t# -0v# -0w# -0{# -b111100000111100001010000010110000 # -b111100000111100001010000010110000 A -b111100000111100001010000010110000 /$ -1x# -0}# -0~# -1!$ -0&$ -0'$ -1($ -b11110000 ?$ -b11110000 . -b11110000 B$ -0G$ -1T$ -b11100 5 -b11100110111101101010011010110110 7 -b11100110111101101010011010110110 " -b11100110111101101010011010110110 @ -b100 F -b1011 J -b101 I -1@$ -b1 M$ -0+ -b11100001 H$ -b1110000110110000 ) -b1110000110110000 A$ -b1110000110110000 N$ -b10 Z$ -1- -b1010000010110000 V$ -b111100000111100001010000010110000 , -b111100000111100001010000010110000 R$ -14 -1? -#12250000000000100 -b11110001 ?$ -b11110001 . -b11110001 B$ -0:$ -b1110000111110001 & -b1110000111110001 -$ -b1110000111110001 7$ -02$ -b10010101 Q -1P -b1001100 X -b11 _ -b111111111 m -b111111 t -b111000000 { -b111111111 $" -b10010101 +" -1*" -b1001100 2" -b11 9" -b111111 N" -b111000000 U" -b111111111 \" -b10010101 c" -1b" -b1001100 j" -b11 q" -b111111111 !# -b111111111 (# -b111111 /# -b111111111 6# -b10010101 =# -1<# -b1001100 D# -b11 K# -b111111111 `# -b111111 g# -b111111111 n# -b100100000 u# -0t# -b11100001111100011010000110110001 # -b11100001111100011010000110110001 A -b11100001111100011010000110110001 /$ -b1000000 |# -#12300000000000000 -04 -0? -#12350000000000000 -0.$ -03$ -0B -0' -0$ -12$ -0T$ -1G$ -b10100000 ?$ -b10100000 . -b10100000 B$ -b1010000010110000 & -b1010000010110000 -$ -b1010000010110000 7$ -1K -0P -1R -1Y -1` -1g -1n -1u -1| -1%" -0*" -1," -13" -1:" -1A" -1H" -1O" -1V" -1]" -0b" -1d" -1k" -1r" -1y" -1"# -1)# -10# -17# -0<# -1># -1E# -1L# -1S# -1Z# -1a# -1h# -1o# -1t# -b111100000111100001010000010110000 # -b111100000111100001010000010110000 A -b111100000111100001010000010110000 /$ -1v# -1}# -1&$ -1O -1)" -1a" -1;# -b0 Z$ -0- -b11110001 I$ -b1110000111110001 ) -b1110000111110001 A$ -b1110000111110001 N$ -b10 M$ -1+ -0@$ -15$ -b110 I -b1010 J -b101 F -b100000 5 -b11100111111101111010011110110111 7 -b11100111111101111010011110110111 " -b11100111111101111010011110110111 @ -14 -1? -#12350000000000100 -b10100001 ?$ -b10100001 . -b10100001 B$ -b1010000110110001 & -b1010000110110001 -$ -b1010000110110001 7$ -02$ -b10000000 |# -b1001000000 u# -0t# -b1111111111 n# -b1111111 g# -b1111111111 `# -b111 K# -b10011001 D# -b100101010 =# -1<# -b1111111111 6# -b1111111 /# -b1111111111 (# -b1111111111 !# -b111 q" -b10011001 j" -b100101010 c" -1b" -b1111111111 \" -b1110000000 U" -b1111111 N" -b111 9" -b10011001 2" -b100101010 +" -1*" -b1111111111 $" -b1110000000 { -b1111111 t -b1111111111 m -b111 _ -b10011001 X -b100101010 Q -1P -b11100001111100011010000110110001 # -b11100001111100011010000110110001 A -b11100001111100011010000110110001 /$ -#12400000000000000 -04 -0? -#12450000000000000 -13$ -1B -b1010000010110000 & -b1010000010110000 -$ -b1010000010110000 7$ -1.$ -1$ -12$ -1' -0O -0V -0] -1d -0)" -00" -07" -1>" -0a" -0h" -0o" -1v" -0;# -0B# -0I# -1P# -1z# -0K -1L -0P -0R -1S -0W -0Y -1Z -0` -1a -0g -1h -0n -1o -1s -0u -1v -0z -0| -1} -0%" -1&" -0*" -0," -1-" -01" -03" -14" -0:" -1;" -0A" -1B" -0H" -1I" -1M" -0O" -1P" -0T" -0V" -1W" -0]" -1^" -0b" -0d" -1e" -0i" -0k" -1l" -0r" -1s" -0y" -1z" -0"# -1## -0)# -1*# -1.# -00# -11# -07# -18# -0<# -0># -1?# -0C# -0E# -1F# -0L# -1M# -0S# -1T# -0Z# -1[# -0a# -1b# -1f# -0h# -1i# -0o# -1t# -1p# -0v# -1w# -0{# -b111100000111100001010000010110000 # -b111100000111100001010000010110000 A -b111100000111100001010000010110000 /$ -0}# -1~# -0&$ -1'$ -b10110000 ?$ -b10110000 . -b10110000 B$ -0G$ -18 -b11101000111110001010100010111000 7 -b1011101000111110001010100010111000 " -b1011101000111110001010100010111000 @ -b110 F -b1001 J -b111 I -1@$ -b1 M$ -0+ -b10100001 H$ -b1010000111110001 ) -b1010000111110001 A$ -b1010000111110001 N$ -0Y$ -b1 Z$ -b1110000111110001 U$ -b11100001111100011010000010110000 , -b11100001111100011010000010110000 R$ -14 -1? -#12450000000000100 -b10110001 ?$ -b10110001 . -b10110001 B$ -b1010000110110001 & -b1010000110110001 -$ -b1010000110110001 7$ -02$ -b1001010101 Q -1P -b100110011 X -b1111 _ -b11111111111 m -b11111111 t -b11100000000 { -b11111111111 $" -b1001010101 +" -1*" -b100110011 2" -b1111 9" -b11111111 N" -b11100000000 U" -b11111111111 \" -b1001010101 c" -1b" -b100110011 j" -b1111 q" -b11111111111 !# -b11111111111 (# -b11111111 /# -b11111111111 6# -b1001010101 =# -1<# -b100110011 D# -b1111 K# -b11111111111 `# -b11111111 g# -b11111111111 n# -b10010000000 u# -0t# -b11100001111100011010000110110001 # -b11100001111100011010000110110001 A -b11100001111100011010000110110001 /$ -b100000000 |# -#12500000000000000 -04 -0? -#12550000000000000 -0.$ -03$ -0B -0' -0$ -1G$ -b11100001 ?$ -b11100001 . -b11100001 B$ -b1110000111110001 & -b1110000111110001 -$ -b1110000111110001 7$ -0E -0d -0k -0r -0"" -0>" -0L" -0Z" -0v" -0}" -0&# -0-# -04# -0P# -0^# -0e# -0l# -0z# -b10110001 I$ -b1010000110110001 ) -b1010000110110001 A$ -b1010000110110001 N$ -b10 M$ -1+ -0@$ -05$ -0= -0D -b0 7 -08 -b0 " -b0 @ -14 -1? -#12550000000000100 -b11100010 ?$ -b11100010 . -b11100010 B$ -b1110001011110010 & -b1110001011110010 -$ -b1110001011110010 7$ -b1000000001 |# -b100100000000 u# -b111111111111 n# -b111111111 g# -b111111111111 `# -b1 R# -b11110 K# -b1001100110 D# -1C# -b10010101010 =# -0<# -b111111111111 6# -b111111111 /# -b111111111111 (# -b111111111111 !# -b1 x" -b11110 q" -b1001100110 j" -1i" -b10010101010 c" -0b" -b111111111111 \" -b111000000000 U" -b111111111 N" -b1 @" -b11110 9" -b1001100110 2" -11" -b10010101010 +" -0*" -b111111111111 $" -b111000000000 { -b111111111 t -b111111111111 m -b1 f -b11110 _ -b1001100110 X -1W -b10010101010 Q -0P -b11100010111100101010001010110010 # -b11100010111100101010001010110010 A -b11100010111100101010001010110010 /$ -#12600000000000000 -04 -0? -#12650000000000000 -1.$ -1' -b11110010 ?$ -b11110010 . -b11110010 B$ -0G$ -1T$ -1@$ -b1 M$ -0+ -b11100010 H$ -b1110001010110001 ) -b1110001010110001 A$ -b1110001010110001 N$ -b10 Z$ -1- -b1010000110110001 V$ -b11100001111100011010000110110001 , -b11100001111100011010000110110001 R$ -14 -1? -#12700000000000000 -04 -0? -#12750000000000000 -0.$ -03$ -0B -0' -0$ -0T$ -1G$ -b10100010 ?$ -b10100010 . -b10100010 B$ -b1010001010110010 & -b1010001010110010 -$ -b1010001010110010 7$ -b0 Z$ -0- -b11110010 I$ -b1110001011110010 ) -b1110001011110010 A$ -b1110001011110010 N$ -b10 M$ -1+ -0@$ -15$ -14 -1? -#12800000000000000 -04 -0? -#12850000000000000 -13$ -1B -1.$ -1$ -1' -b10110010 ?$ -b10110010 . -b10110010 B$ -0G$ -1@$ -b1 M$ -0+ -b10100010 H$ -b1010001011110010 ) -b1010001011110010 A$ -b1010001011110010 N$ -b1 Z$ -b1110001011110010 U$ -b11100010111100101010000110110001 , -b11100010111100101010000110110001 R$ -14 -1? -#12900000000000000 -04 -0? -#12950000000000000 -0.$ -03$ -0B -0' -0$ -1G$ -b11100011 ?$ -b11100011 . -b11100011 B$ -b1110001111110011 & -b1110001111110011 -$ -b1110001111110011 7$ -1K -1P -0L -1R -0S -1W -1Y -0Z -0^ -1` -0a -1g -0h -1n -0o -1u -0v -1| -0} -1%" -1*" -0&" -1," -0-" -11" -13" -04" -08" -1:" -0;" -1A" -0B" -1H" -0I" -1O" -0P" -1V" -0W" -1]" -1b" -0^" -1d" -0e" -1i" -1k" -0l" -0p" -1r" -0s" -1y" -0z" -1"# -0## -1)# -0*# -10# -01# -17# -1<# -08# -1># -0?# -1C# -1E# -0F# -0J# -b11100011111100111010001110110011 # -b11100011111100111010001110110011 A -b11100011111100111010001110110011 /$ -1L# -0M# -1S# -0T# -1Z# -0[# -1a# -0b# -1h# -0i# -1o# -0p# -1v# -0w# -1}# -0~# -1&$ -0'$ -b10110010 I$ -b1010001010110010 ) -b1010001010110010 A$ -b1010001010110010 N$ -b10 M$ -1+ -0@$ -05$ -b110 I -b1010 J -b101 F -14 -1? -#13000000000000000 -04 -0? -#13050000000000000 -1.$ -1' -b11110011 ?$ -b11110011 . -b11110011 B$ -0G$ -1T$ -1@$ -b1 M$ -0+ -b11100011 H$ -b1110001110110010 ) -b1110001110110010 A$ -b1110001110110010 N$ -b10 Z$ -1- -b1010001010110010 V$ -b11100010111100101010001010110010 , -b11100010111100101010001010110010 R$ -14 -1? -#13100000000000000 -04 -0? -#13150000000000000 -0.$ -03$ -0B -0' -0$ -0T$ -1G$ -b10100011 ?$ -b10100011 . -b10100011 B$ -b1010001110110011 & -b1010001110110011 -$ -b1010001110110011 7$ -b0 Z$ -0- -b11110011 I$ -b1110001111110011 ) -b1110001111110011 A$ -b1110001111110011 N$ -b10 M$ -1+ -0@$ -15$ -14 -1? -#13200000000000000 -04 -0? -#13250000000000000 -13$ -1B -1.$ -1$ -1' -b10110011 ?$ -b10110011 . -b10110011 B$ -0G$ -1@$ -b1 M$ -0+ -b10100011 H$ -b1010001111110011 ) -b1010001111110011 A$ -b1010001111110011 N$ -b1 Z$ -b1110001111110011 U$ -b11100011111100111010001010110010 , -b11100011111100111010001010110010 R$ -14 -1? -#13300000000000000 -04 -0? -#13350000000000000 -0.$ -03$ -0B -0' -0$ -1G$ -b11100100 ?$ -b11100100 . -b11100100 B$ -b1110010011110100 & -b1110010011110100 -$ -b1110010011110100 7$ -0K -0P -0R -0W -0Y -1^ -0` -0g -0n -0u -0| -0%" -0*" -0," -01" -03" -18" -0:" -0A" -0H" -0O" -0V" -0]" -0b" -0d" -0i" -0k" -1p" -0r" -0y" -0"# -0)# -00# -07# -0<# -0># -0C# -0E# -1J# -b11100100111101001010010010110100 # -b11100100111101001010010010110100 A -b11100100111101001010010010110100 /$ -0L# -0S# -0Z# -0a# -0h# -0o# -0v# -0}# -0&$ -b10110011 I$ -b1010001110110011 ) -b1010001110110011 A$ -b1010001110110011 N$ -b10 M$ -1+ -0@$ -05$ -b101 I -b1011 J -b100 F -14 -1? -#13400000000000000 -04 -0? -#13450000000000000 -1.$ -1' -b11110100 ?$ -b11110100 . -b11110100 B$ -0G$ -1T$ -1@$ -b1 M$ -0+ -b11100100 H$ -b1110010010110011 ) -b1110010010110011 A$ -b1110010010110011 N$ -b10 Z$ -1- -b1010001110110011 V$ -b11100011111100111010001110110011 , -b11100011111100111010001110110011 R$ -14 -1? -#13500000000000000 -04 -0? -#13550000000000000 -0.$ -03$ -0B -0' -0$ -0T$ -1G$ -b10100100 ?$ -b10100100 . -b10100100 B$ -b1010010010110100 & -b1010010010110100 -$ -b1010010010110100 7$ -b0 Z$ -0- -b11110100 I$ -b1110010011110100 ) -b1110010011110100 A$ -b1110010011110100 N$ -b10 M$ -1+ -0@$ -15$ -14 -1? -#13600000000000000 -04 -0? -#13650000000000000 -13$ -1B -1.$ -1$ -1' -b10110100 ?$ -b10110100 . -b10110100 B$ -0G$ -1@$ -b1 M$ -0+ -b10100100 H$ -b1010010011110100 ) -b1010010011110100 A$ -b1010010011110100 N$ -b1 Z$ -b1110010011110100 U$ -b11100100111101001010001110110011 , -b11100100111101001010001110110011 R$ -14 -1? -#13700000000000000 -04 -0? -#13750000000000000 -0.$ -03$ -0B -0' -0$ -1G$ -b11100101 ?$ -b11100101 . -b11100101 B$ -b1110010111110101 & -b1110010111110101 -$ -b1110010111110101 7$ -1K -1P -1L -0M -1R -1S -0W -0T -1Y -1Z -0[ -1^ -1` -1a -0b -0e -1g -1h -0i -1n -1o -0p -1u -1v -0w -1| -1} -0~ -1%" -1*" -1&" -0'" -1," -1-" -01" -0." -13" -14" -05" -18" -1:" -1;" -0<" -0?" -1A" -1B" -0C" -1H" -1I" -0J" -1O" -1P" -0Q" -1V" -1W" -0X" -1]" -1b" -1^" -0_" -1d" -1e" -0i" -0f" -1k" -1l" -0m" -1p" -1r" -1s" -0t" -0w" -1y" -1z" -0{" -1"# -1## -0$# -1)# -1*# -0+# -10# -11# -02# -17# -1<# -18# -09# -1># -1?# -0C# -0@# -1E# -1F# -0G# -1J# -1L# -1M# -0N# -0Q# -1S# -1T# -0U# -1Z# -1[# -0\# -1a# -1b# -0c# -1h# -1i# -0j# -1o# -1p# -0q# -1v# -1w# -0x# -0{# -b11100101111101011010010110110101 # -b11100101111101011010010110110101 A -b11100101111101011010010110110101 /$ -1}# -1~# -0!$ -1&$ -1'$ -0($ -b10110100 I$ -b1010010010110100 ) -b1010010010110100 A$ -b1010010010110100 N$ -b10 M$ -1+ -0@$ -05$ -b100 I -b1100 J -b11 F -14 -1? -#13800000000000000 -04 -0? -#13850000000000000 -1.$ -1' -b11110101 ?$ -b11110101 . -b11110101 B$ -0G$ -1T$ -1@$ -b1 M$ -0+ -b11100101 H$ -b1110010110110100 ) -b1110010110110100 A$ -b1110010110110100 N$ -b10 Z$ -1- -b1010010010110100 V$ -b11100100111101001010010010110100 , -b11100100111101001010010010110100 R$ -14 -1? -#13900000000000000 -04 -0? -#13950000000000000 -0.$ -03$ -0B -0' -0$ -0T$ -1G$ -b10100101 ?$ -b10100101 . -b10100101 B$ -b1010010110110101 & -b1010010110110101 -$ -b1010010110110101 7$ -b0 Z$ -0- -b11110101 I$ -b1110010111110101 ) -b1110010111110101 A$ -b1110010111110101 N$ -b10 M$ -1+ -0@$ -15$ -14 -1? -#14000000000000000 -04 -0? -#14050000000000000 -13$ -1B -1.$ -1$ -1' -b10110101 ?$ -b10110101 . -b10110101 B$ -0G$ -1@$ -b1 M$ -0+ -b10100101 H$ -b1010010111110101 ) -b1010010111110101 A$ -b1010010111110101 N$ -b1 Z$ -b1110010111110101 U$ -b11100101111101011010010010110100 , -b11100101111101011010010010110100 R$ -14 -1? -#14100000000000000 -04 -0? -#14150000000000000 -0.$ -03$ -0B -0' -0$ -1G$ -b11100110 ?$ -b11100110 . -b11100110 B$ -b1110011011110110 & -b1110011011110110 -$ -b1110011011110110 7$ -0K -0P -0R -1W -0Y -0` -0g -0n -0u -0| -0%" -0*" -0," -11" -03" -0:" -0A" -0H" -0O" -0V" -0]" -0b" -0d" -1i" -0k" -0r" -0y" -0"# -0)# -00# -07# -0<# -0># -1C# -b11100110111101101010011010110110 # -b11100110111101101010011010110110 A -b11100110111101101010011010110110 /$ -0E# -0L# -0S# -0Z# -0a# -0h# -0o# -0v# -0}# -0&$ -b10110101 I$ -b1010010110110101 ) -b1010010110110101 A$ -b1010010110110101 N$ -b10 M$ -1+ -0@$ -05$ -b11 I -b1101 J -b10 F -14 -1? -#14200000000000000 -04 -0? -#14250000000000000 -1.$ -1' -b11110110 ?$ -b11110110 . -b11110110 B$ -0G$ -1T$ -1@$ -b1 M$ -0+ -b11100110 H$ -b1110011010110101 ) -b1110011010110101 A$ -b1110011010110101 N$ -b10 Z$ -1- -b1010010110110101 V$ -b11100101111101011010010110110101 , -b11100101111101011010010110110101 R$ -14 -1? -#14300000000000000 -04 -0? -#14350000000000000 -0.$ -03$ -0B -0' -0$ -0T$ -1G$ -b10100110 ?$ -b10100110 . -b10100110 B$ -b1010011010110110 & -b1010011010110110 -$ -b1010011010110110 7$ -b0 Z$ -0- -b11110110 I$ -b1110011011110110 ) -b1110011011110110 A$ -b1110011011110110 N$ -b10 M$ -1+ -0@$ -15$ -14 -1? -#14400000000000000 -04 -0? -#14450000000000000 -13$ -1B -1.$ -1$ -1' -b10110110 ?$ -b10110110 . -b10110110 B$ -0G$ -1@$ -b1 M$ -0+ -b10100110 H$ -b1010011011110110 ) -b1010011011110110 A$ -b1010011011110110 N$ -b1 Z$ -b1110011011110110 U$ -b11100110111101101010010110110101 , -b11100110111101101010010110110101 R$ -14 -1? -#14500000000000000 -04 -0? -#14550000000000000 -0.$ -03$ -0B -0' -0$ -1G$ -b11100111 ?$ -b11100111 . -b11100111 B$ -b1110011111110111 & -b1110011111110111 -$ -b1110011111110111 7$ -1K -1P -0L -1R -0S -1W -1Y -0Z -1^ -1` -0a -0e -1g -0h -1n -0o -1u -0v -1| -0} -1%" -1*" -0&" -1," -0-" -11" -13" -04" -18" -1:" -0;" -0?" -1A" -0B" -1H" -0I" -1O" -0P" -1V" -0W" -1]" -1b" -0^" -1d" -0e" -1i" -1k" -0l" -1p" -1r" -0s" -0w" -1y" -0z" -1"# -0## -1)# -0*# -10# -01# -17# -1<# -08# -1># -0?# -1C# -1E# -0F# -1J# -1L# -0M# -0Q# -1S# -0T# -1Z# -0[# -1a# -0b# -1h# -0i# -1o# -0p# -1v# -0w# -0{# -b11100111111101111010011110110111 # -b11100111111101111010011110110111 A -b11100111111101111010011110110111 /$ -1}# -0~# -1&$ -0'$ -b10110110 I$ -b1010011010110110 ) -b1010011010110110 A$ -b1010011010110110 N$ -b10 M$ -1+ -0@$ -05$ -b10 I -b1110 J -b1 F -14 -1? -#14600000000000000 -04 -0? -#14650000000000000 -1.$ -1' -b11110111 ?$ -b11110111 . -b11110111 B$ -0G$ -1T$ -1@$ -b1 M$ -0+ -b11100111 H$ -b1110011110110110 ) -b1110011110110110 A$ -b1110011110110110 N$ -b10 Z$ -1- -b1010011010110110 V$ -b11100110111101101010011010110110 , -b11100110111101101010011010110110 R$ -14 -1? -#14700000000000000 -04 -0? -#14750000000000000 -0.$ -03$ -0B -0' -0$ -0T$ -1G$ -b10100111 ?$ -b10100111 . -b10100111 B$ -b1010011110110111 & -b1010011110110111 -$ -b1010011110110111 7$ -b0 Z$ -0- -b11110111 I$ -b1110011111110111 ) -b1110011111110111 A$ -b1110011111110111 N$ -b10 M$ -1+ -0@$ -15$ -14 -1? -#14800000000000000 -04 -0? -#14850000000000000 -13$ -1B -1.$ -1$ -1' -b10110111 ?$ -b10110111 . -b10110111 B$ -0G$ -1@$ -b1 M$ -0+ -b10100111 H$ -b1010011111110111 ) -b1010011111110111 A$ -b1010011111110111 N$ -b1 Z$ -b1110011111110111 U$ -b11100111111101111010011010110110 , -b11100111111101111010011010110110 R$ -14 -1? -#14900000000000000 -04 -0? -#14950000000000000 -0.$ -03$ -0B -0' -0$ -10$ -1G$ -b11101000 ?$ -b11101000 . -b11101000 B$ -b1110100011111000 & -b1110100011111000 -$ -b1110100011111000 7$ -0K -0P -0R -0W -0Y -0^ -0` -1e -0g -0n -0u -0| -0%" -0*" -0," -01" -03" -08" -0:" -1?" -0A" -0H" -0O" -0V" -0]" -0b" -0d" -0i" -0k" -0p" -0r" -1w" -0y" -0"# -0)# -00# -07# -0<# -0># -0C# -0E# -0J# -0L# -1Q# -0S# -0Z# -0a# -0h# -0o# -0v# -1{# -b1011101000111110001010100010111000 # -b1011101000111110001010100010111000 A -b1011101000111110001010100010111000 /$ -0}# -0&$ -b10110111 I$ -b1010011110110111 ) -b1010011110110111 A$ -b1010011110110111 N$ -b10 M$ -1+ -0@$ -05$ -b1 I -b1111 J -b0 F -14 -1? -#15000000000000000 -04 -0? -#15050000000000000 -1.$ -1' -b11111000 ?$ -b11111000 . -b11111000 B$ -0G$ -1T$ -1@$ -b1 M$ -0+ -b11101000 H$ -b1110100010110111 ) -b1110100010110111 A$ -b1110100010110111 N$ -b10 Z$ -1- -b1010011110110111 V$ -b11100111111101111010011110110111 , -b11100111111101111010011110110111 R$ -14 -1? -#15100000000000000 -04 -0? -#15150000000000000 -0.$ -03$ -0B -0' -18$ -0$ -0T$ -1G$ -b10101000 ?$ -b10101000 . -b10101000 B$ -b101010100010111000 & -b101010100010111000 -$ -b101010100010111000 7$ -b0 Z$ -0- -b11111000 I$ -b1110100011111000 ) -b1110100011111000 A$ -b1110100011111000 N$ -b10 M$ -1+ -0@$ -15$ -14 -1? -#15200000000000000 -04 -0? -#15250000000000000 -1D$ -13$ -1B -00 -1.$ -1$ -1<$ -1' -b10111000 ?$ -b10111000 . -b10111000 B$ -0G$ -1@$ -b1 M$ -0+ -b10101000 H$ -b1010100011111000 ) -b1010100011111000 A$ -b1010100011111000 N$ -b1 Z$ -b1110100011111000 U$ -b11101000111110001010011110110111 , -b11101000111110001010011110110111 R$ -14 -1? -#15300000000000000 -04 -0? -#15350000000000000 -0D$ -10 -0' -0F$ -0<$ -08$ -0$ -0.$ -06$ -12 -03$ -0B -1G$ -1O$ -b11101000 ?$ -b11101000 . -b11101000 B$ -b1110100011111000 & -b1110100011111000 -$ -b1110100011111000 7$ -0>$ -0( -0% -b10111000 I$ -b10 M$ -1+ -1J$ -b101010100010111000 ) -b101010100010111000 A$ -b101010100010111000 N$ -0@$ -05$ -b0 I -b10000 J -1G -14 -1? -#15400000000000000 -04 -0? -#15450000000000000 -0G$ -1T$ -b0 M$ -0+ -1W$ -b10 Z$ -1- -b1010100010111000 V$ -b1011101000111110001010100010111000 , -b1011101000111110001010100010111000 R$ -14 -1? -#15500000000000000 -04 -0? -#15550000000000000 -0T$ -b0 Z$ -0- -14 -1? -#15600000000000000 -04 -0? -#15650000000000000 -14 -1? -#15700000000000000 -04 -0? -#15750000000000000 -14 -1? -#15800000000000000 -04 -0? -#15850000000000000 -14 -1? -#15900000000000000 -04 -0? -#15950000000000000 -14 -1? -#16000000000000000 -04 -0? -#16050000000000000 -14 -1? -#16100000000000000 -04 -0? -#16150000000000000 -14 -1? -#16200000000000000 -04 -0? -#16250000000000000 -14 -1? -#16300000000000000 -04 -0? -#16350000000000000 -14 -1? -#16400000000000000 -04 -0? -#16450000000000000 -14 -1? -#16500000000000000 -04 -0? -#16550000000000000 -14 -1? -#16600000000000000 -04 -0? -#16650000000000000 -14 -1? -#16700000000000000 -04 -0? -#16750000000000000 -14 -1? -#16800000000000000 -04 -0? -#16850000000000000 -14 -1? -#16900000000000000 -04 -0? -#16950000000000000 -14 -1? -#17000000000000000 -04 -0? -#17050000000000000 -14 -1? -#17100000000000000 -04 -0? -#17150000000000000 -14 -1? -#17200000000000000 -04 -0? -#17250000000000000 -14 -1? -#17300000000000000 -04 -0? -#17350000000000000 -14 -1? -#17400000000000000 -04 -0? -#17450000000000000 -14 -1? -#17500000000000000 -04 -0? -#17550000000000000 -14 -1? -#17600000000000000 -04 -0? -#17650000000000000 -14 -1? -#17700000000000000 -04 -0? -#17750000000000000 -14 -1? -#17800000000000000 -04 -0? -#17850000000000000 -14 -1? -#17900000000000000 -04 -0? -#17950000000000000 -14 -1? -#18000000000000000 -04 -0? -#18050000000000000 -14 -1? -#18100000000000000 -04 -0? -#18150000000000000 -14 -1? -#18200000000000000 -04 -0? -#18250000000000000 -14 -1? -#18300000000000000 -04 -0? -#18350000000000000 -14 -1? -#18400000000000000 -04 -0? -#18450000000000000 -14 -1? -#18500000000000000 -04 -0? -#18550000000000000 -14 -1? -#18600000000000000 -04 -0? -#18650000000000000 -14 -1? -#18700000000000000 -04 -0? -#18750000000000000 -14 -1? -#18800000000000000 -04 -0? -#18850000000000000 -14 -1? -#18900000000000000 -04 -0? -#18950000000000000 -14 -1? -#19000000000000000 -04 -0? -#19050000000000000 -14 -1? -#19100000000000000 -04 -0? -#19150000000000000 -14 -1? -#19200000000000000 -04 -0? -#19250000000000000 -14 -1? -#19300000000000000 -04 -0? -#19350000000000000 -14 -1? -#19400000000000000 -04 -0? -#19450000000000000 -14 -1? -#19500000000000000 -04 -0? -#19550000000000000 -14 -1? -#19600000000000000 -04 -0? -#19650000000000000 -14 -1? -#19700000000000000 -04 -0? -#19750000000000000 -14 -1? -#19800000000000000 -04 -0? -#19850000000000000 -14 -1? -#19900000000000000 -04 -0? -#19950000000000000 -14 -1? -#20000000000000000 -04 -0? diff --git a/usrp2/fifo/fifo_tb.v b/usrp2/fifo/fifo_tb.v index f561df7fa..327da4700 100644 --- a/usrp2/fifo/fifo_tb.v +++ b/usrp2/fifo/fifo_tb.v @@ -24,20 +24,39 @@ module fifo_new_tb(); wire i1_sr, i1_dr; wire i2_sr, i2_dr; wire i3_sr, i3_dr; + wire i7_sr, i7_dr; + reg i4_dr = 0; wire i4_sr; - wire [35:0] i1, i4; + wire [35:0] i1, i4, i7; wire [18:0] i2, i3; wire [7:0] ll_data; wire ll_src_rdy_n, ll_dst_rdy_n, ll_sof_n, ll_eof_n; + wire [35:0] err_dat; + wire err_src_rdy, err_dst_rdy; + + reg trigger = 0; + initial #10000 trigger = 1; fifo_short #(.WIDTH(36)) fifo_short1 (.clk(clk),.reset(rst),.clear(clear), .datain(f36_in),.src_rdy_i(src_rdy_f36i),.dst_rdy_o(dst_rdy_f36i), - .dataout(i1),.src_rdy_o(i1_sr),.dst_rdy_i(i1_dr) ); + .dataout(i7),.src_rdy_o(i7_sr),.dst_rdy_i(i7_dr) ); + gen_context_pkt #(.PROT_ENG_FLAGS(1)) gcp + (.clk(clk),.reset(rst),.clear(clear), + .trigger(trigger), .sent(), + .streamid(32'hDEAD_F00D), .vita_time(64'h01234567_89ABCDEF), .message(32'hBEEF_2940), + .data_o(err_dat), .src_rdy_o(err_src_rdy), .dst_rdy_i(err_dst_rdy)); + + fifo36_mux #(.prio(0)) fifo36_mux + (.clk(clk), .reset(rst), .clear(clear), + .data0_i(i7), .src0_rdy_i(i7_sr), .dst0_rdy_o(i7_dr), + .data1_i(err_dat), .src1_rdy_i(err_src_rdy), .dst1_rdy_o(err_dst_rdy), + .data_o(i1), .src_rdy_o(i1_sr), .dst_rdy_i(i1_dr)); + fifo36_to_fifo19 fifo36_to_fifo19 (.clk(clk),.reset(rst),.clear(clear), .f36_datain(i1),.f36_src_rdy_i(i1_sr),.f36_dst_rdy_o(i1_dr), @@ -59,7 +78,7 @@ module fifo_new_tb(); (.clk(clk),.reset(rst),.clear(clear), .f19_datain(i3),.f19_src_rdy_i(i3_sr),.f19_dst_rdy_o(i3_dr), .f36_dataout(i4),.f36_src_rdy_o(i4_sr),.f36_dst_rdy_i(i4_dr) ); - + task ReadFromFIFO36; begin $display("Read from FIFO36"); diff --git a/usrp2/top/Makefile.common b/usrp2/top/Makefile.common index d0435fa1e..4da64ac28 100644 --- a/usrp2/top/Makefile.common +++ b/usrp2/top/Makefile.common @@ -47,7 +47,7 @@ $(ISE_FILE): $$(SOURCES) $$(MAKEFILE_LIST) @echo $@ $(ISE_HELPER) "" -$(BIN_FILE): $(ISE_FILE) +$(BIN_FILE): $(ISE_FILE) $$(SOURCES) $$(MAKEFILE_LIST) @echo $@ $(ISE_HELPER) "Generate Programming File" touch $@ diff --git a/usrp2/top/u2_rev3/u2_core_udp.v b/usrp2/top/u2_rev3/u2_core_udp.v index b034791a7..124930c23 100644 --- a/usrp2/top/u2_rev3/u2_core_udp.v +++ b/usrp2/top/u2_rev3/u2_core_udp.v @@ -423,7 +423,10 @@ module u2_core cycle_count <= 0; else cycle_count <= cycle_count + 1; - + + //compatibility number -> increment when the fpga has been sufficiently altered + localparam compat_num = 32'd1; + wb_readback_mux buff_pool_status (.wb_clk_i(wb_clk), .wb_rst_i(wb_rst), .wb_stb_i(s5_stb), .wb_adr_i(s5_adr), .wb_dat_o(s5_dat_i), .wb_ack_o(s5_ack), @@ -431,7 +434,7 @@ module u2_core .word00(status_b0),.word01(status_b1),.word02(status_b2),.word03(status_b3), .word04(status_b4),.word05(status_b5),.word06(status_b6),.word07(status_b7), .word08(status),.word09({sim_mode,27'b0,clock_divider[3:0]}),.word10(vita_time[63:32]), - .word11(vita_time[31:0]),.word12(32'b0),.word13(irq),.word14(status_enc),.word15(cycle_count) + .word11(vita_time[31:0]),.word12(compat_num),.word13(irq),.word14(status_enc),.word15(cycle_count) ); // ///////////////////////////////////////////////////////////////////////// @@ -466,11 +469,20 @@ module u2_core .tx_f36_data(udp_tx_data), .tx_f36_src_rdy_i(udp_tx_src_rdy), .tx_f36_dst_rdy_o(udp_tx_dst_rdy), .debug(debug_udp) ); + wire [35:0] tx_err_data, udp1_tx_data; + wire tx_err_src_rdy, tx_err_dst_rdy, udp1_tx_src_rdy, udp1_tx_dst_rdy; + fifo_cascade #(.WIDTH(36), .SIZE(ETH_TX_FIFOSIZE)) tx_eth_fifo (.clk(dsp_clk), .reset(dsp_rst), .clear(0), .datain({rd2_flags,rd2_dat}), .src_rdy_i(rd2_ready_o), .dst_rdy_o(rd2_ready_i), - .dataout(udp_tx_data), .src_rdy_o(udp_tx_src_rdy), .dst_rdy_i(udp_tx_dst_rdy)); + .dataout(udp1_tx_data), .src_rdy_o(udp1_tx_src_rdy), .dst_rdy_i(udp1_tx_dst_rdy)); + fifo36_mux #(.prio(0)) mux_err_stream + (.clk(dsp_clk), .reset(dsp_reset), .clear(0), + .data0_i(udp1_tx_data), .src0_rdy_i(udp1_tx_src_rdy), .dst0_rdy_o(udp1_tx_dst_rdy), + .data1_i(tx_err_data), .src1_rdy_i(tx_err_src_rdy), .dst1_rdy_o(tx_err_dst_rdy), + .data_o(udp_tx_data), .src_rdy_o(udp_tx_src_rdy), .dst_rdy_i(udp_tx_dst_rdy)); + fifo_cascade #(.WIDTH(36), .SIZE(ETH_RX_FIFOSIZE)) rx_eth_fifo (.clk(dsp_clk), .reset(dsp_rst), .clear(0), .datain(udp_rx_data), .src_rdy_i(udp_rx_src_rdy), .dst_rdy_o(udp_rx_dst_rdy), @@ -639,40 +651,26 @@ module u2_core // DSP TX wire [35:0] tx_data; - wire [99:0] tx1_data; - wire tx_src_rdy, tx_dst_rdy, tx1_src_rdy, tx1_dst_rdy; - - wire [31:0] debug_vtc, debug_vtd, debug_vt; + wire tx_src_rdy, tx_dst_rdy; + wire [31:0] debug_vt; fifo_cascade #(.WIDTH(36), .SIZE(DSP_TX_FIFOSIZE)) tx_fifo_cascade (.clk(dsp_clk), .reset(dsp_rst), .clear(0), .datain({rd1_flags,rd1_dat}), .src_rdy_i(rd1_ready_o), .dst_rdy_o(rd1_ready_i), .dataout(tx_data), .src_rdy_o(tx_src_rdy), .dst_rdy_i(tx_dst_rdy) ); - vita_tx_deframer #(.BASE(SR_TX_CTRL), .MAXCHAN(1)) vita_tx_deframer - (.clk(dsp_clk), .reset(dsp_rst), .clear(0), - .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_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), - .debug(debug_vtc) ); - - assign debug_vt = debug_vtc | debug_vtd; - - dsp_core_tx #(.BASE(SR_TX_DSP)) dsp_core_tx - (.clk(dsp_clk),.rst(dsp_rst), + vita_tx_chain #(.BASE_CTRL(SR_TX_CTRL), .BASE_DSP(SR_TX_DSP), + .REPORT_ERROR(1), .PROT_ENG_FLAGS(1)) + vita_tx_chain + (.clk(dsp_clk), .reset(dsp_rst), .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp), - .sample(sample_tx), .run(run_tx), .strobe(strobe_tx), + .vita_time(vita_time), + .tx_data_i(tx_data), .tx_src_rdy_i(tx_src_rdy), .tx_dst_rdy_o(tx_dst_rdy), + .err_data_o(tx_err_data), .err_src_rdy_o(tx_err_src_rdy), .err_dst_rdy_i(tx_err_dst_rdy), .dac_a(dac_a),.dac_b(dac_b), - .debug(debug_tx_dsp) ); - + .underrun(underrun), .run(run_tx), + .debug(debug_vt)); + assign dsp_rst = wb_rst; // /////////////////////////////////////////////////////////////////////////////////// diff --git a/usrp2/vrt/Makefile.srcs b/usrp2/vrt/Makefile.srcs index 07c62224b..dc4bd8c96 100644 --- a/usrp2/vrt/Makefile.srcs +++ b/usrp2/vrt/Makefile.srcs @@ -10,4 +10,6 @@ vita_rx_control.v \ vita_rx_framer.v \ vita_tx_control.v \ vita_tx_deframer.v \ +vita_tx_chain.v \ +gen_context_pkt.v \ )) diff --git a/usrp2/vrt/gen_context_pkt.v b/usrp2/vrt/gen_context_pkt.v new file mode 100644 index 000000000..780a027ba --- /dev/null +++ b/usrp2/vrt/gen_context_pkt.v @@ -0,0 +1,72 @@ + + +module gen_context_pkt + #(parameter PROT_ENG_FLAGS=1) + (input clk, input reset, input clear, + input trigger, output sent, + input [31:0] streamid, + input [63:0] vita_time, + input [31:0] message, + output [35:0] data_o, output src_rdy_o, input dst_rdy_i); + + localparam CTXT_IDLE = 0; + localparam CTXT_PROT_ENG = 1; + localparam CTXT_HEADER = 2; + localparam CTXT_STREAMID = 3; + localparam CTXT_SECS = 4; + localparam CTXT_TICS = 5; + localparam CTXT_TICS2 = 6; + localparam CTXT_MESSAGE = 7; + localparam CTXT_DONE = 8; + + reg [33:0] data_int; + wire src_rdy_int, dst_rdy_int; + wire [3:0] seqno = 0; + reg [3:0] ctxt_state; + reg [63:0] err_time; + + always @(posedge clk) + if(reset | clear) + ctxt_state <= CTXT_IDLE; + else + case(ctxt_state) + CTXT_IDLE : + if(trigger) + begin + err_time <= vita_time; + if(PROT_ENG_FLAGS) + ctxt_state <= CTXT_PROT_ENG; + else + ctxt_state <= CTXT_HEADER; + end + + CTXT_DONE : + if(~trigger) + ctxt_state <= CTXT_IDLE; + + default : + if(dst_rdy_int) + ctxt_state <= ctxt_state + 1; + endcase // case (ctxt_state) + + assign src_rdy_int = ~( (ctxt_state == CTXT_IDLE) | (ctxt_state == CTXT_DONE) ); + + always @* + case(ctxt_state) + CTXT_PROT_ENG : data_int <= { 2'b01, 16'd1, 16'd24 }; + CTXT_HEADER : data_int <= { 1'b0, (PROT_ENG_FLAGS ? 1'b0 : 1'b1), 12'b010100001101, seqno, 16'd6 }; + CTXT_STREAMID : data_int <= { 2'b00, streamid }; + CTXT_SECS : data_int <= { 2'b00, err_time[63:32] }; + CTXT_TICS : data_int <= { 2'b00, 32'd0 }; + CTXT_TICS2 : data_int <= { 2'b00, err_time[31:0] }; + CTXT_MESSAGE : data_int <= { 2'b10, message }; + default : data_int <= {2'b00, 32'b00}; + endcase // case (ctxt_state) + + fifo_short #(.WIDTH(34)) ctxt_fifo + (.clk(clk), .reset(reset), .clear(clear), + .datain(data_int), .src_rdy_i(src_rdy_int), .dst_rdy_o(dst_rdy_int), + .dataout(data_o[33:0]), .src_rdy_o(src_rdy_o), .dst_rdy_i(dst_rdy_i)); + assign data_o[35:34] = 2'b00; + +endmodule // gen_context_pkt diff --git a/usrp2/vrt/vita_rx_framer.v b/usrp2/vrt/vita_rx_framer.v index fd82263d0..235817941 100644 --- a/usrp2/vrt/vita_rx_framer.v +++ b/usrp2/vrt/vita_rx_framer.v @@ -128,7 +128,7 @@ module vita_rx_framer VITA_ERR_SECS : pkt_fifo_line <= {2'b00,vita_time_fifo_o[63:32]}; VITA_ERR_TICS : pkt_fifo_line <= {2'b00,32'd0}; VITA_ERR_TICS2 : pkt_fifo_line <= {2'b00,vita_time_fifo_o[31:0]}; - VITA_ERR_PAYLOAD : pkt_fifo_line <= {2'b11,28'd0,flags_fifo_o}; + VITA_ERR_PAYLOAD : pkt_fifo_line <= {2'b10,28'd0,flags_fifo_o}; //VITA_ERR_TRAILER : pkt_fifo_line <= {2'b11,vita_trailer}; default : pkt_fifo_line <= 34'h0_FFFF_FFFF; diff --git a/usrp2/vrt/vita_tx_chain.v b/usrp2/vrt/vita_tx_chain.v new file mode 100644 index 000000000..662cdca62 --- /dev/null +++ b/usrp2/vrt/vita_tx_chain.v @@ -0,0 +1,71 @@ + +module vita_tx_chain + #(parameter BASE_CTRL=0, + parameter BASE_DSP=0, + parameter REPORT_ERROR=0, + parameter PROT_ENG_FLAGS=0) + (input clk, input reset, + input set_stb, input [7:0] set_addr, input [31:0] set_data, + input [63:0] vita_time, + input [35:0] tx_data_i, input tx_src_rdy_i, output tx_dst_rdy_o, + output [35:0] err_data_o, output err_src_rdy_o, input err_dst_rdy_i, + output [15:0] dac_a, output [15:0] dac_b, + output underrun, output run, + output [31:0] debug); + + localparam MAXCHAN = 1; + localparam FIFOWIDTH = 5+64+16+(32*MAXCHAN); + + wire [FIFOWIDTH-1:0] tx1_data; + wire tx1_src_rdy, tx1_dst_rdy; + wire clear_vita; + wire [31:0] sample_tx; + wire [31:0] streamid, message; + wire trigger, sent; + wire [31:0] debug_vtc, debug_vtd, debug_tx_dsp; + + wire error; + wire [31:0] error_code; + wire clear_seqnum; + + assign underrun = error; + assign message = error_code; + + setting_reg #(.my_addr(BASE_CTRL+2), .at_reset(0)) sr_streamid + (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out(streamid),.changed(clear_seqnum)); + + vita_tx_deframer #(.BASE(BASE_CTRL), .MAXCHAN(MAXCHAN)) vita_tx_deframer + (.clk(clk), .reset(reset), .clear(clear_vita), .clear_seqnum(clear_seqnum), + .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .data_i(tx_data_i), .src_rdy_i(tx_src_rdy_i), .dst_rdy_o(tx_dst_rdy_o), + .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(BASE_CTRL), .WIDTH(32*MAXCHAN)) vita_tx_control + (.clk(clk), .reset(reset), .clear(clear_vita), + .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .vita_time(vita_time),.error(error),.error_code(error_code), + .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), .strobe(strobe_tx), + .debug(debug_vtc) ); + + dsp_core_tx #(.BASE(BASE_DSP)) dsp_core_tx + (.clk(clk),.rst(reset), + .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .sample(sample_tx), .run(run), .strobe(strobe_tx), + .dac_a(dac_a),.dac_b(dac_b), + .debug(debug_tx_dsp) ); + + generate + if(REPORT_ERROR==1) + gen_context_pkt #(.PROT_ENG_FLAGS(PROT_ENG_FLAGS)) gen_tx_err_pkt + (.clk(clk), .reset(reset), .clear(clear_vita), + .trigger(error), .sent(), + .streamid(streamid), .vita_time(vita_time), .message(message), + .data_o(err_data_o), .src_rdy_o(err_src_rdy_o), .dst_rdy_i(err_dst_rdy_i)); + endgenerate + + assign debug = debug_vtc | debug_vtd; + +endmodule // vita_tx_chain diff --git a/usrp2/vrt/vita_tx_control.v b/usrp2/vrt/vita_tx_control.v index bffc64e52..d0516bec8 100644 --- a/usrp2/vrt/vita_tx_control.v +++ b/usrp2/vrt/vita_tx_control.v @@ -6,10 +6,11 @@ module vita_tx_control input set_stb, input [7:0] set_addr, input [31:0] set_data, input [63:0] vita_time, - output underrun, + output error, + output reg [31:0] error_code, // From vita_tx_deframer - input [4+64+WIDTH-1:0] sample_fifo_i, + input [5+64+16+WIDTH-1:0] sample_fifo_i, input sample_fifo_src_rdy_i, output sample_fifo_dst_rdy_o, @@ -20,14 +21,17 @@ module vita_tx_control output [31:0] debug ); - - assign sample = sample_fifo_i[4+64+WIDTH-1:4+64]; + + assign sample = sample_fifo_i[5+64+16+WIDTH-1:5+64+16]; wire [63:0] send_time = sample_fifo_i[63:0]; - wire eop = sample_fifo_i[64]; - wire eob = sample_fifo_i[65]; - wire sob = sample_fifo_i[66]; - wire send_at = sample_fifo_i[67]; + wire [15:0] seqnum = sample_fifo_i[79:64]; + wire eop = sample_fifo_i[80]; + wire eob = sample_fifo_i[81]; + wire sob = sample_fifo_i[82]; + wire send_at = sample_fifo_i[83]; + wire seqnum_err = sample_fifo_i[84]; + wire now, early, late, too_early; // FIXME ignore too_early for now for timing reasons @@ -40,8 +44,15 @@ module vita_tx_control localparam IBS_IDLE = 0; localparam IBS_RUN = 1; // FIXME do we need this? localparam IBS_CONT_BURST = 2; - localparam IBS_UNDERRUN = 3; - localparam IBS_UNDERRUN_DONE = 4; + localparam IBS_ERROR = 3; + localparam IBS_ERROR_DONE = 4; + localparam IBS_ERROR_WAIT = 5; + + wire [31:0] CODE_UNDERRUN = {seqnum,16'd2}; + wire [31:0] CODE_SEQ_ERROR = {seqnum,16'd4}; + wire [31:0] CODE_TIME_ERROR = {seqnum,16'd8}; + wire [31:0] CODE_UNDERRUN_MIDPKT = {seqnum,16'd16}; + wire [31:0] CODE_SEQ_ERROR_MIDBURST = {seqnum,16'd32}; reg [2:0] ibs_state; @@ -50,22 +61,49 @@ module vita_tx_control (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), .in(set_data),.out(),.changed(clear_state)); + wire [31:0] error_policy; + setting_reg #(.my_addr(BASE+3)) sr_error_policy + (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out(error_policy),.changed()); + + wire policy_wait = error_policy[0]; + wire policy_next_packet = error_policy[1]; + wire policy_next_burst = error_policy[2]; + reg send_error; + always @(posedge clk) if(reset | clear_state) - ibs_state <= 0; + begin + ibs_state <= IBS_IDLE; + send_error <= 0; + end else case(ibs_state) IBS_IDLE : if(sample_fifo_src_rdy_i) - if(~send_at | now) + if(seqnum_err) + begin + ibs_state <= IBS_ERROR; + error_code <= CODE_SEQ_ERROR; + send_error <= 1; + end + else if(~send_at | now) ibs_state <= IBS_RUN; else if(late | too_early) - ibs_state <= IBS_UNDERRUN; + begin + ibs_state <= IBS_ERROR; + error_code <= CODE_TIME_ERROR; + send_error <= 1; + end IBS_RUN : if(strobe) if(~sample_fifo_src_rdy_i) - ibs_state <= IBS_UNDERRUN; + begin + ibs_state <= IBS_ERROR; + error_code <= CODE_UNDERRUN_MIDPKT; + send_error <= 1; + end else if(eop) if(eob) ibs_state <= IBS_IDLE; @@ -74,24 +112,53 @@ module vita_tx_control IBS_CONT_BURST : if(strobe) - ibs_state <= IBS_UNDERRUN_DONE; + begin + if(policy_next_packet) + ibs_state <= IBS_ERROR_DONE; + else if(policy_wait) + ibs_state <= IBS_ERROR_WAIT; + else + ibs_state <= IBS_ERROR; + error_code <= CODE_UNDERRUN; + send_error <= 1; + end else if(sample_fifo_src_rdy_i) - ibs_state <= IBS_RUN; + if(seqnum_err) + begin + ibs_state <= IBS_ERROR; + error_code <= CODE_SEQ_ERROR_MIDBURST; + send_error <= 1; + end + else + ibs_state <= IBS_RUN; - IBS_UNDERRUN : - if(sample_fifo_src_rdy_i & eop) - ibs_state <= IBS_UNDERRUN_DONE; + IBS_ERROR : + begin + send_error <= 0; + if(sample_fifo_src_rdy_i & eop) + if(policy_next_packet | (policy_next_burst & eob)) + ibs_state <= IBS_IDLE; + else if(policy_wait) + ibs_state <= IBS_ERROR_WAIT; + end - IBS_UNDERRUN_DONE : - ; + IBS_ERROR_DONE : + begin + send_error <= 0; + ibs_state <= IBS_IDLE; + end + + IBS_ERROR_WAIT : + send_error <= 0; endcase // case (ibs_state) - assign sample_fifo_dst_rdy_o = (ibs_state == IBS_UNDERRUN) | (strobe & (ibs_state == IBS_RUN)); // FIXME also cleanout + assign sample_fifo_dst_rdy_o = (ibs_state == IBS_ERROR) | (strobe & (ibs_state == IBS_RUN)); // FIXME also cleanout assign run = (ibs_state == IBS_RUN) | (ibs_state == IBS_CONT_BURST); - assign underrun = (ibs_state == IBS_UNDERRUN_DONE); + //assign error = (ibs_state == IBS_ERROR_DONE); + assign error = send_error; assign debug = { { now,early,late,too_early,eop,eob,sob,send_at }, - { sample_fifo_src_rdy_i, sample_fifo_dst_rdy_o, strobe, run, underrun, ibs_state[2:0] }, + { sample_fifo_src_rdy_i, sample_fifo_dst_rdy_o, strobe, run, error, ibs_state[2:0] }, { 8'b0 }, { 8'b0 } }; diff --git a/usrp2/vrt/vita_tx_deframer.v b/usrp2/vrt/vita_tx_deframer.v index 3b95f5902..f9cd7d00d 100644 --- a/usrp2/vrt/vita_tx_deframer.v +++ b/usrp2/vrt/vita_tx_deframer.v @@ -2,7 +2,7 @@ module vita_tx_deframer #(parameter BASE=0, parameter MAXCHAN=1) - (input clk, input reset, input clear, + (input clk, input reset, input clear, input clear_seqnum, input set_stb, input [7:0] set_addr, input [31:0] set_data, // To FIFO interface of Buffer Pool @@ -10,7 +10,7 @@ module vita_tx_deframer input src_rdy_i, output dst_rdy_o, - output [4+64+(32*MAXCHAN)-1:0] sample_fifo_o, + output [5+64+16+(32*MAXCHAN)-1:0] sample_fifo_o, output sample_fifo_src_rdy_o, input sample_fifo_dst_rdy_i, @@ -21,6 +21,8 @@ module vita_tx_deframer output [31:0] debug ); + localparam FIFOWIDTH = 5+64+16+(32*MAXCHAN); + wire [1:0] numchan; setting_reg #(.my_addr(BASE), .at_reset(0), .width(2)) sr_numchan (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), @@ -36,14 +38,18 @@ module vita_tx_deframer assign is_sob = data_i[25]; assign is_eob = data_i[24]; wire eof = data_i[33]; - reg has_streamid_reg, has_classid_reg, has_secs_reg, has_tics_reg; reg has_trailer_reg, is_sob_reg, is_eob_reg; - + reg [15:0] pkt_len; reg [1:0] vector_phase; wire line_done; + reg seqnum_err; + reg [3:0] seqnum_reg; + wire [3:0] seqnum = data_i[19:16]; + wire [3:0] next_seqnum = seqnum_reg + 4'd1; + // Output FIFO for packetized data localparam VITA_HEADER = 0; localparam VITA_STREAMID = 1; @@ -61,6 +67,13 @@ module vita_tx_deframer wire eop = eof | (pkt_len==hdr_len); // FIXME would ignoring eof allow larger VITA packets? wire fifo_space; + + always @(posedge clk) + if(reset | clear_seqnum) + seqnum_reg <= 4'hF; + else + if((vita_state==VITA_HEADER) & src_rdy_i) + seqnum_reg <= seqnum; always @(posedge clk) if(reset | clear) @@ -68,6 +81,7 @@ module vita_tx_deframer vita_state <= VITA_HEADER; {has_streamid_reg, has_classid_reg, has_secs_reg, has_tics_reg, has_trailer_reg, is_sob_reg, is_eob_reg} <= 0; + seqnum_err <= 0; end else if((vita_state == VITA_STORE) & fifo_space) @@ -99,6 +113,7 @@ module vita_tx_deframer vita_state <= VITA_TICS; else vita_state <= VITA_PAYLOAD; + seqnum_err <= ~(seqnum == next_seqnum); end // case: VITA_HEADER VITA_STREAMID : if(has_classid_reg) @@ -145,7 +160,7 @@ module vita_tx_deframer assign line_done = (vector_phase == numchan); - wire [4+64+32*MAXCHAN-1:0] fifo_i; + wire [FIFOWIDTH-1:0] fifo_i; reg [63:0] send_time; reg [31:0] sample_a, sample_b, sample_c, sample_d; @@ -169,13 +184,14 @@ module vita_tx_deframer endcase // case (vector_phase) wire store = (vita_state == VITA_STORE); - fifo_short #(.WIDTH(4+64+32*MAXCHAN)) short_tx_q + fifo_short #(.WIDTH(FIFOWIDTH)) short_tx_q (.clk(clk), .reset(reset), .clear(clear), .datain(fifo_i), .src_rdy_i(store), .dst_rdy_o(fifo_space), .dataout(sample_fifo_o), .src_rdy_o(sample_fifo_src_rdy_o), .dst_rdy_i(sample_fifo_dst_rdy_i) ); // sob, eob, has_secs (send_at) ignored on all lines except first - assign fifo_i = {sample_d,sample_c,sample_b,sample_a,has_secs_reg,is_sob_reg,is_eob_reg,eop,send_time}; + assign fifo_i = {sample_d,sample_c,sample_b,sample_a,seqnum_err,has_secs_reg,is_sob_reg,is_eob_reg,eop, + 12'd0,seqnum_reg,send_time}; assign dst_rdy_o = ~(vita_state == VITA_PAYLOAD) & ~((vita_state==VITA_STORE)& ~fifo_space) ; -- cgit v1.2.3 From 7d602e283bc30669df6c155f1abe5196a272b9b4 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 19 Aug 2010 13:08:23 -0700 Subject: properly integrate the new tx chain --- usrp2/top/u1e/u1e_core.v | 58 ++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 63488f549..33020ad5a 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -59,8 +59,9 @@ module u1e_core wire [31:0] debug_gpmc; - wire [35:0] tx_data, rx_data; - wire tx_src_rdy, tx_dst_rdy, rx_src_rdy, rx_dst_rdy; + wire [35:0] tx_data, rx_data, tx_err_data; + wire tx_src_rdy, tx_dst_rdy, rx_src_rdy, rx_dst_rdy, + tx_err_src_rdy, tx_err_dst_rdy; reg [15:0] tx_frame_len; wire [15:0] rx_frame_len; wire [7:0] rate; @@ -109,7 +110,7 @@ module u1e_core assign tx_underrun = 0; assign rx_overrun = 0; - wire run_tx, run_rx, strobe_tx, strobe_rx, tx1_src_rdy, tx1_dst_rdy; + wire run_tx, run_rx, strobe_tx, strobe_rx; wire [31:0] debug_vtd, debug_vtc; `endif // LOOPBACK @@ -154,8 +155,9 @@ module u1e_core wire rx1_dst_rdy, rx1_src_rdy; wire [99:0] rx1_data; wire run_rx; - - + wire [35:0] vita_rx_data; + wire vita_rx_src_rdy, vita_rx_dst_rdy; + dsp_core_rx #(.BASE(SR_RX_DSP)) dsp_core_rx (.clk(wb_clk),.rst(wb_rst), .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), @@ -175,41 +177,35 @@ module u1e_core (.clk(wb_clk), .reset(wb_rst), .clear(clear_rx), .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), .sample_fifo_i(rx1_data), .sample_fifo_dst_rdy_o(rx1_dst_rdy), .sample_fifo_src_rdy_i(rx1_src_rdy), - .data_o(rx_data), .dst_rdy_i(rx_dst_rdy), .src_rdy_o(rx_src_rdy), + .data_o(vita_rx_data), .dst_rdy_i(vita_rx_dst_rdy), .src_rdy_o(vita_rx_src_rdy), .fifo_occupied(), .fifo_full(), .fifo_empty(), .debug_rx(vrf_debug) ); - + + fifo36_mux #(.prio(0)) mux_err_stream + (.clk(dsp_clk), .reset(dsp_reset), .clear(0), + .data0_i(vita_rx_data), .src0_rdy_i(vita_rx_src_rdy), .dst0_rdy_o(vita_rx_dst_rdy), + .data1_i(tx_err_data), .src1_rdy_i(tx_err_src_rdy), .dst1_rdy_o(tx_err_dst_rdy), + .data_o(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); + // /////////////////////////////////////////////////////////////////////////////////// // DSP TX - wire [99:0] tx1_data; - wire tx1_src_rdy, tx1_dst_rdy; wire [15:0] tx_i_int, tx_q_int; wire [31:0] debug_vtc, debug_vtd, debug_vt; wire run_tx; - vita_tx_deframer #(.BASE(SR_TX_CTRL), .MAXCHAN(1)) vita_tx_deframer - (.clk(wb_clk), .reset(wb_rst), .clear(clear_tx), - .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), - .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(wb_clk), .reset(wb_rst), .clear(clear_tx), - .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), - .vita_time(vita_time),.underrun(tx_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), - .debug(debug_vtc) ); - - dsp_core_tx #(.BASE(SR_TX_DSP)) dsp_core_tx - (.clk(wb_clk),.rst(wb_rst), - .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), - .sample(sample_tx), .run(run_tx), .strobe(strobe_tx), + vita_tx_chain #(.BASE_CTRL(SR_TX_CTRL), .BASE_DSP(SR_TX_DSP), + .REPORT_ERROR(1), .PROT_ENG_FLAGS(1)) + vita_tx_chain + (.clk(dsp_clk), .reset(dsp_rst), + .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp), + .vita_time(vita_time), + .tx_data_i(tx_data), .tx_src_rdy_i(tx_src_rdy), .tx_dst_rdy_o(tx_dst_rdy), + .err_data_o(tx_err_data), .err_src_rdy_o(tx_err_src_rdy), .err_dst_rdy_i(tx_err_dst_rdy), .dac_a(tx_i_int),.dac_b(tx_q_int), - .debug(debug_tx_dsp) ); - + .underrun(underrun), .run(run_tx), + .debug(debug_vt)); + assign tx_i = tx_i_int[15:2]; assign tx_q = tx_q_int[15:2]; @@ -438,7 +434,7 @@ module u1e_core { EM_D } }; assign debug_gpio_0 = { {run_tx, strobe_tx, run_rx, strobe_rx, tx_i[11:0]}, - {tx1_src_rdy, tx1_dst_rdy, tx_src_rdy, tx_dst_rdy, tx_q[11:0]} }; + {2'b00, tx_src_rdy, tx_dst_rdy, tx_q[11:0]} }; assign debug_gpio_1 = debug_vtd | debug_vtc; -- cgit v1.2.3 From 105efcdfc21f760e9615e9a3221ef6ae13b01f1c Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 23 Aug 2010 17:12:43 -0700 Subject: debug pins cleanup --- usrp2/top/u1e/u1e_core.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 33020ad5a..ff9a846b5 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -111,7 +111,6 @@ module u1e_core assign rx_overrun = 0; wire run_tx, run_rx, strobe_tx, strobe_rx; - wire [31:0] debug_vtd, debug_vtc; `endif // LOOPBACK `ifdef TIMED @@ -191,7 +190,7 @@ module u1e_core // DSP TX wire [15:0] tx_i_int, tx_q_int; - wire [31:0] debug_vtc, debug_vtd, debug_vt; + wire [31:0] debug_vt; wire run_tx; vita_tx_chain #(.BASE_CTRL(SR_TX_CTRL), .BASE_DSP(SR_TX_DSP), @@ -429,6 +428,7 @@ module u1e_core // Debug circuitry assign debug_clk = { EM_CLK, clk_fpga }; + assign debug = { { rx_have_data, tx_have_space, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, rx_overrun, tx_underrun }, { tx_src_rdy, tx_src_rdy_int, tx_dst_rdy, tx_dst_rdy_int, rx_src_rdy, rx_src_rdy_int, rx_dst_rdy, rx_dst_rdy_int }, { EM_D } }; @@ -436,7 +436,7 @@ module u1e_core assign debug_gpio_0 = { {run_tx, strobe_tx, run_rx, strobe_rx, tx_i[11:0]}, {2'b00, tx_src_rdy, tx_dst_rdy, tx_q[11:0]} }; - assign debug_gpio_1 = debug_vtd | debug_vtc; + assign debug_gpio_1 = debug_vt; /* assign debug_gpio_1 = { {rx_enable, rx_src_rdy, rx_dst_rdy, rx_src_rdy & ~rx_dst_rdy}, -- cgit v1.2.3 From 87a64f5979e712fd0fa30cf0676f3c395599ff69 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 23 Aug 2010 19:20:02 -0700 Subject: match the signal names in this design --- usrp2/top/u1e/u1e_core.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index ff9a846b5..eda4e463d 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -181,7 +181,7 @@ module u1e_core .debug_rx(vrf_debug) ); fifo36_mux #(.prio(0)) mux_err_stream - (.clk(dsp_clk), .reset(dsp_reset), .clear(0), + (.clk(wb_clk), .reset(wb_rst), .clear(0), .data0_i(vita_rx_data), .src0_rdy_i(vita_rx_src_rdy), .dst0_rdy_o(vita_rx_dst_rdy), .data1_i(tx_err_data), .src1_rdy_i(tx_err_src_rdy), .dst1_rdy_o(tx_err_dst_rdy), .data_o(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy)); @@ -196,8 +196,8 @@ module u1e_core vita_tx_chain #(.BASE_CTRL(SR_TX_CTRL), .BASE_DSP(SR_TX_DSP), .REPORT_ERROR(1), .PROT_ENG_FLAGS(1)) vita_tx_chain - (.clk(dsp_clk), .reset(dsp_rst), - .set_stb(set_stb_dsp),.set_addr(set_addr_dsp),.set_data(set_data_dsp), + (.clk(wb_clk), .reset(wb_rst), + .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), .vita_time(vita_time), .tx_data_i(tx_data), .tx_src_rdy_i(tx_src_rdy), .tx_dst_rdy_o(tx_dst_rdy), .err_data_o(tx_err_data), .err_src_rdy_o(tx_err_src_rdy), .err_dst_rdy_i(tx_err_dst_rdy), -- cgit v1.2.3 From 743ea16da4eef07cf9956f4098fc4b959e689c00 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 24 Aug 2010 12:08:22 -0700 Subject: no need for protocol headers since we're not doing ethernet --- usrp2/top/u1e/u1e_core.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index eda4e463d..d7c4ff509 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -194,7 +194,7 @@ module u1e_core wire run_tx; vita_tx_chain #(.BASE_CTRL(SR_TX_CTRL), .BASE_DSP(SR_TX_DSP), - .REPORT_ERROR(1), .PROT_ENG_FLAGS(1)) + .REPORT_ERROR(1), .PROT_ENG_FLAGS(0)) vita_tx_chain (.clk(wb_clk), .reset(wb_rst), .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -- cgit v1.2.3 From 94e9baee9598f304b0e6918894876b16ffc8b2d7 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Fri, 27 Aug 2010 14:59:33 -0700 Subject: move declaration to make loopback compile --- usrp2/top/u1e/u1e_core.v | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index d7c4ff509..4a80fe916 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -46,6 +46,8 @@ module u1e_core wire [31:0] set_data; wire set_stb; + wire [31:0] debug_vt; + // ///////////////////////////////////////////////////////////////////////////////////// // GPMC Slave to Wishbone Master localparam dw = 16; @@ -190,7 +192,6 @@ module u1e_core // DSP TX wire [15:0] tx_i_int, tx_q_int; - wire [31:0] debug_vt; wire run_tx; vita_tx_chain #(.BASE_CTRL(SR_TX_CTRL), .BASE_DSP(SR_TX_DSP), -- cgit v1.2.3 From c3cd5ccbf38294a3dd4ae1e386ddefb2071f59b6 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Mon, 30 Aug 2010 15:11:05 -0700 Subject: add register to tell host about compatibility level and which image we are using --- usrp2/top/u1e/u1e_core.v | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 4a80fe916..5c4b6de6c 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -34,7 +34,9 @@ module u1e_core localparam SR_TX_DSP = 17; // 5 regs localparam SR_TX_CTRL = 24; // 2 regs localparam SR_TIME64 = 28; // 4 regs - + + wire COMPAT_NUM = 8'd2; + wire wb_clk = clk_fpga; wire wb_rst = rst_fpga; @@ -104,6 +106,8 @@ module u1e_core wire rx_src_rdy_int, rx_dst_rdy_int, tx_src_rdy_int, tx_dst_rdy_int; `ifdef LOOPBACK + wire [7:0] WHOAMI = 1; + fifo_cascade #(.WIDTH(36), .SIZE(12)) loopback_fifo (.clk(wb_clk), .reset(wb_rst), .clear(clear_tx | clear_rx), .datain(tx_data), .src_rdy_i(tx_src_rdy), .dst_rdy_o(tx_dst_rdy), @@ -116,7 +120,8 @@ module u1e_core `endif // LOOPBACK `ifdef TIMED - + wire [7:0] WHOAMI = 2; + // TX side wire tx_enable; @@ -147,6 +152,8 @@ module u1e_core `endif // `ifdef TIMED `ifdef DSP + wire [7:0] WHOAMI = 0; + wire [31:0] debug_rx_dsp, vrc_debug, vrf_debug; // ///////////////////////////////////////////////////////////////////////// @@ -303,9 +310,10 @@ module u1e_core localparam REG_CGEN_CTRL = 7'd4; // out localparam REG_CGEN_ST = 7'd6; // in localparam REG_TEST = 7'd8; // out - localparam REG_RX_FRAMELEN = 7'd10; // out - localparam REG_TX_FRAMELEN = 7'd12; // in - localparam REG_XFER_RATE = 7'd14; // in + localparam REG_RX_FRAMELEN = 7'd10; // in + localparam REG_TX_FRAMELEN = 7'd12; // out + localparam REG_XFER_RATE = 7'd14; // out + localparam REG_COMPAT = 7'd16; // in always @(posedge wb_clk) if(wb_rst) @@ -344,6 +352,7 @@ module u1e_core (s0_adr[6:0] == REG_CGEN_ST) ? {13'b0,cgen_st_status,cgen_st_ld,cgen_st_refmon} : (s0_adr[6:0] == REG_TEST) ? reg_test : (s0_adr[6:0] == REG_RX_FRAMELEN) ? rx_frame_len : + (s0_adr[6:0] == REG_COMPAT) ? { WHOAMI, COMPAT_NUM } : 16'hBEEF; assign s0_ack = s0_stb & s0_cyc; -- cgit v1.2.3 From 709d93fd675298c7d6fb3e97c60ae7258496efc4 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 7 Sep 2010 19:07:34 -0700 Subject: fixed makefile to compile with our new system --- usrp2/top/u1e_passthru/Makefile | 80 +++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 44 deletions(-) diff --git a/usrp2/top/u1e_passthru/Makefile b/usrp2/top/u1e_passthru/Makefile index 62923f87f..d1950629b 100644 --- a/usrp2/top/u1e_passthru/Makefile +++ b/usrp2/top/u1e_passthru/Makefile @@ -1,20 +1,30 @@ # # Copyright 2008 Ettus Research LLC -# +# ################################################## -# xtclsh Shell and tcl Script Path +# Project Setup ################################################## -#XTCLSH := /opt/Xilinx/10.1/ISE/bin/lin/xtclsh -XTCLSH := xtclsh -ISE_HELPER := ../tcl/ise_helper.tcl +TOP_MODULE = passthru +BUILD_DIR = $(abspath build$(ISE)) ################################################## -# Project Setup +# Include other makefiles ################################################## -BUILD_DIR := build/ -export TOP_MODULE := passthru -export PROJ_FILE := $(BUILD_DIR)$(TOP_MODULE).ise + +include ../Makefile.common +include ../../fifo/Makefile.srcs +include ../../control_lib/Makefile.srcs +include ../../sdr_lib/Makefile.srcs +include ../../serdes/Makefile.srcs +include ../../simple_gemac/Makefile.srcs +include ../../timing/Makefile.srcs +include ../../opencores/Makefile.srcs +include ../../vrt/Makefile.srcs +include ../../udp/Makefile.srcs +include ../../coregen/Makefile.srcs +include ../../extram/Makefile.srcs +include ../../gpmc/Makefile.srcs ################################################## # Project Properties @@ -34,16 +44,21 @@ simulator "ISE Simulator (VHDL/Verilog)" \ ################################################## # Sources ################################################## -export SOURCE_ROOT := ../../../ -export SOURCES := \ -top/u1e_passthru/passthru.ucf \ -top/u1e_passthru/passthru.v +TOP_SRCS = \ +passthru.v \ +passthru.ucf + +SOURCES = $(abspath $(TOP_SRCS)) $(FIFO_SRCS) \ +$(CONTROL_LIB_SRCS) $(SDR_LIB_SRCS) $(SERDES_SRCS) \ +$(SIMPLE_GEMAC_SRCS) $(TIMING_SRCS) $(OPENCORES_SRCS) \ +$(VRT_SRCS) $(UDP_SRCS) $(COREGEN_SRCS) $(EXTRAM_SRCS) \ +$(GPMC_SRCS) ################################################## # Process Properties ################################################## -export SYNTHESIZE_PROPERTIES := \ -"Number of Clock Buffers" 6 \ +SYNTHESIZE_PROPERTIES = \ +"Number of Clock Buffers" 8 \ "Pack I/O Registers into IOBs" Yes \ "Optimization Effort" High \ "Optimize Instantiated Primitives" TRUE \ @@ -52,10 +67,10 @@ export SYNTHESIZE_PROPERTIES := \ "Use Synchronous Reset" Auto \ "Use Synchronous Set" Auto -export TRANSLATE_PROPERTIES := \ +TRANSLATE_PROPERTIES = \ "Macro Search Path" "$(shell pwd)/../../coregen/" -export MAP_PROPERTIES := \ +MAP_PROPERTIES = \ "Allow Logic Optimization Across Hierarchy" TRUE \ "Map to Input Functions" 4 \ "Optimization Strategy (Cover Mode)" Speed \ @@ -66,14 +81,14 @@ export MAP_PROPERTIES := \ "Combinatorial Logic Optimization" TRUE \ "Register Duplication" TRUE -export PLACE_ROUTE_PROPERTIES := \ +PLACE_ROUTE_PROPERTIES = \ "Place & Route Effort Level (Overall)" High -export STATIC_TIMING_PROPERTIES := \ +STATIC_TIMING_PROPERTIES = \ "Number of Paths in Error/Verbose Report" 10 \ "Report Type" "Error Report" -export GEN_PROG_FILE_PROPERTIES := \ +GEN_PROG_FILE_PROPERTIES = \ "Configuration Rate" 6 \ "Create Binary Configuration File" TRUE \ "Done (Output Events)" 5 \ @@ -81,27 +96,4 @@ export GEN_PROG_FILE_PROPERTIES := \ "Enable Outputs (Output Events)" 6 \ "Unused IOB Pins" "Pull Up" -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) - - +SIM_MODEL_PROPERTIES = "" -- cgit v1.2.3 From 8db1a3901972745dfab310be77c409a82b63e941 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 9 Sep 2010 11:24:58 -0700 Subject: pins are different on rev2 --- usrp2/top/u1e_passthru/passthru.ucf | 268 +----------------------------------- 1 file changed, 4 insertions(+), 264 deletions(-) diff --git a/usrp2/top/u1e_passthru/passthru.ucf b/usrp2/top/u1e_passthru/passthru.ucf index fcfce61b2..64e6f0440 100644 --- a/usrp2/top/u1e_passthru/passthru.ucf +++ b/usrp2/top/u1e_passthru/passthru.ucf @@ -1,266 +1,6 @@ - -#NET "CLK_FPGA_P" LOC = "Y11" ; -#NET "CLK_FPGA_N" LOC = "Y10" ; - -## GPMC -#NET "EM_D<15>" LOC = "D13" ; -#NET "EM_D<14>" LOC = "D15" ; -#NET "EM_D<13>" LOC = "C16" ; -#NET "EM_D<12>" LOC = "B20" ; -#NET "EM_D<11>" LOC = "A19" ; -#NET "EM_D<10>" LOC = "A17" ; -#NET "EM_D<9>" LOC = "E15" ; -#NET "EM_D<8>" LOC = "F15" ; -#NET "EM_D<7>" LOC = "E16" ; -#NET "EM_D<6>" LOC = "F16" ; -#NET "EM_D<5>" LOC = "B17" ; -#NET "EM_D<4>" LOC = "C17" ; -#NET "EM_D<3>" LOC = "B19" ; -#NET "EM_D<2>" LOC = "D19" ; -#NET "EM_D<1>" LOC = "C19" ; -#NET "EM_D<0>" LOC = "A20" ; - -#NET "EM_A<10>" LOC = "C14" ; -#NET "EM_A<9>" LOC = "C10" ; -#NET "EM_A<8>" LOC = "C5" ; -#NET "EM_A<7>" LOC = "A18" ; -#NET "EM_A<6>" LOC = "A15" ; -#NET "EM_A<5>" LOC = "A12" ; -#NET "EM_A<4>" LOC = "A10" ; -#NET "EM_A<3>" LOC = "E7" ; -#NET "EM_A<2>" LOC = "A7" ; -#NET "EM_A<1>" LOC = "C15" ; - -#NET "EM_NCS6" LOC = "E17" ; -##NET "EM_NCS5" LOC = "E10" ; -#NET "EM_NCS4" LOC = "E6" ; -##NET "EM_NCS1" LOC = "D18" ; -##NET "EM_NCS0" LOC = "D17" ; - -#NET "EM_CLK" LOC = "F11" ; -#NET "EM_WAIT0" LOC = "F14" ; -#NET "EM_NBE<1>" LOC = "D14" ; -#NET "EM_NBE<0>" LOC = "A13" ; -#NET "EM_NWE" LOC = "B13" ; -#NET "EM_NOE" LOC = "A14" ; -##NET "EM_NADV_ALE" LOC = "B15" ; -##NET "EM_NWP" LOC = "F13" ; - -## Overo GPIO -#NET "overo_gpio0" LOC = "F9" ; # MISC GPIO for debug -#NET "overo_gpio14" LOC = "C4" ; # MISC GPIO for debug -#NET "overo_gpio21" LOC = "D5" ; # MISC GPIO for debug -#NET "overo_gpio22" LOC = "A3" ; # MISC GPIO for debug -#NET "overo_gpio23" LOC = "B3" ; # MISC GPIO for debug -#NET "overo_gpio64" LOC = "A4" ; # MISC GPIO for debug -#NET "overo_gpio65" LOC = "F8" ; # MISC GPIO for debug -#NET "overo_gpio127" LOC = "C8" ; # passed through as cgen_sen_b -#NET "overo_gpio128" LOC = "G8" ; # MISC GPIO for debug -#NET "overo_gpio144" LOC = "A5" ; # tx_have_space -NET "overo_gpio145" LOC = "C7" ; # tx_underrun -#NET "overo_gpio146" LOC = "A6" ; # rx_have_data -#NET "overo_gpio147" LOC = "B6" ; # rx_overrun -#NET "overo_gpio163" LOC = "D7" ; # MISC GPIO for debug -#NET "overo_gpio170" LOC = "E8" ; # MISC GPIO for debug -#NET "overo_gpio176" LOC = "B4" ; # MISC GPIO for debug - -## Overo UART -##NET "overo_txd1" LOC = "C6" ; -##NET "overo_rxd1" LOC = "D6" ; - -## FTDI UART to USB converter -#NET "FPGA_TXD" LOC = "U1" ; -#NET "FPGA_RXD" LOC = "T6" ; - -##NET "SYSEN" LOC = "C11" ; - -## I2C -#NET "db_scl" LOC = "U4" ; -#NET "db_sda" LOC = "U5" ; - -## SPI -### DBoard SPI -#NET "db_sclk_rx" LOC = "W3" ; -#NET "db_miso_rx" LOC = "W2" ; -#NET "db_mosi_rx" LOC = "V4" ; -#NET "db_sen_rx" LOC = "V3" ; -#NET "db_sclk_tx" LOC = "Y1" ; -#NET "db_miso_tx" LOC = "W1" ; -#NET "db_mosi_tx" LOC = "R3" ; -#NET "db_sen_tx" LOC = "T4" ; - -### AD9862 SPI and aux SPI Interfaces -##NET "aux_sdi_codec" LOC = "F19" ; -##NET "aux_sdo_codec" LOC = "F18" ; -##NET "aux_sclk_codec" LOC = "D21" ; -#NET "sen_codec" LOC = "D20" ; -#NET "mosi_codec" LOC = "E19" ; -#NET "miso_codec" LOC = "F21" ; -#NET "sclk_codec" LOC = "E20" ; - -### Clock Gen SPI -#NET "cgen_miso" LOC = "U2" ; -NET "cgen_mosi" LOC = "V1" ; -NET "cgen_sclk" LOC = "R5" ; -NET "cgen_sen_b" LOC = "T1" ; - -## Clock gen control -#NET "cgen_st_status" LOC = "D4" ; -#NET "cgen_st_ld" LOC = "D1" ; -#NET "cgen_st_refmon" LOC = "E1" ; -#NET "cgen_sync_b" LOC = "M1" ; -#NET "cgen_ref_sel" LOC = "J1" ; - -## Debug pins -#NET "debug_led<2>" LOC = "T5" ; -#NET "debug_led<1>" LOC = "R2" ; -#NET "debug_led<0>" LOC = "R1" ; -#NET "debug<0>" LOC = "P6" ; -#NET "debug<1>" LOC = "R6" ; -#NET "debug<2>" LOC = "P1" ; -#NET "debug<3>" LOC = "P2" ; -#NET "debug<4>" LOC = "N6" ; -#NET "debug<5>" LOC = "N5" ; -#NET "debug<6>" LOC = "N1" ; -#NET "debug<7>" LOC = "K2" ; -#NET "debug<8>" LOC = "K3" ; -#NET "debug<9>" LOC = "K6" ; -#NET "debug<10>" LOC = "L5" ; -#NET "debug<11>" LOC = "H2" ; -#NET "debug<12>" LOC = "K4" ; -#NET "debug<13>" LOC = "K5" ; -#NET "debug<14>" LOC = "G1" ; -#NET "debug<15>" LOC = "H1" ; -#NET "debug<16>" LOC = "H5" ; -#NET "debug<17>" LOC = "H6" ; -#NET "debug<18>" LOC = "E3" ; -#NET "debug<19>" LOC = "E4" ; -#NET "debug<20>" LOC = "G5" ; -#NET "debug<21>" LOC = "G6" ; -#NET "debug<22>" LOC = "F2" ; -#NET "debug<23>" LOC = "F1" ; -#NET "debug<24>" LOC = "H3" ; -#NET "debug<25>" LOC = "H4" ; -#NET "debug<26>" LOC = "F4" ; -#NET "debug<27>" LOC = "F5" ; -#NET "debug<28>" LOC = "C2" ; -#NET "debug<29>" LOC = "C1" ; -#NET "debug<30>" LOC = "F3" ; -#NET "debug<31>" LOC = "G3" ; -#NET "debug_clk<0>" LOC = "L6" ; -#NET "debug_clk<1>" LOC = "M5" ; - -#NET "debug_pb<2>" LOC = "Y2" ; -#NET "debug_pb<1>" LOC = "AA1" ; -#NET "debug_pb<0>" LOC = "N3" ; - -#NET "dip_sw<7>" LOC = "T3" ; -#NET "dip_sw<6>" LOC = "U3" ; -#NET "dip_sw<5>" LOC = "M3" ; -#NET "dip_sw<4>" LOC = "N4" ; -#NET "dip_sw<3>" LOC = "J3" ; -#NET "dip_sw<2>" LOC = "J4" ; -#NET "dip_sw<1>" LOC = "J6" ; -#NET "dip_sw<0>" LOC = "J7" ; - -##NET "RXSYNC" LOC = "F22" ; -##NET "reset_codec" LOC = "D22" ; - -##NET "DB<11>" LOC = "E22" ; -##NET "DB<10>" LOC = "J19" ; -##NET "DB<9>" LOC = "H20" ; -##NET "DB<8>" LOC = "G19" ; -##NET "DB<7>" LOC = "F20" ; -##NET "DB<6>" LOC = "K16" ; -##NET "DB<5>" LOC = "J17" ; -##NET "DB<4>" LOC = "H22" ; -##NET "DB<3>" LOC = "G22" ; -##NET "DB<2>" LOC = "H17" ; -##NET "DB<1>" LOC = "H18" ; -##NET "DB<0>" LOC = "K20" ; -##NET "DA<11>" LOC = "J20" ; -##NET "DA<10>" LOC = "K19" ; -##NET "DA<9>" LOC = "K18" ; -##NET "DA<8>" LOC = "L22" ; -##NET "DA<7>" LOC = "K22" ; -##NET "DA<6>" LOC = "N22" ; -##NET "DA<5>" LOC = "M22" ; -##NET "DA<4>" LOC = "N20" ; -##NET "DA<3>" LOC = "N19" ; -##NET "DA<2>" LOC = "R22" ; -##NET "DA<1>" LOC = "P22" ; -##NET "DA<0>" LOC = "N17" ; - -#NET "TX<13>" LOC = "P19" ; -#NET "TX<12>" LOC = "R18" ; -#NET "TX<11>" LOC = "U20" ; -#NET "TX<10>" LOC = "T20" ; -#NET "TX<9>" LOC = "R19" ; -#NET "TX<8>" LOC = "R20" ; -#NET "TX<7>" LOC = "W22" ; -#NET "TX<6>" LOC = "Y22" ; -#NET "TX<5>" LOC = "T18" ; -#NET "TX<4>" LOC = "T17" ; -#NET "TX<3>" LOC = "W19" ; -#NET "TX<2>" LOC = "V20" ; -#NET "TX<1>" LOC = "Y21" ; -#NET "TX<0>" LOC = "AA22" ; -#NET "TXSYNC" LOC = "U18" ; -#NET "TXBLANK" LOC = "U19" ; - -#NET "PPS_IN" LOC = "M17" ; - -#NET "io_tx<0>" LOC = "AB20" ; -#NET "io_tx<1>" LOC = "Y17" ; -#NET "io_tx<2>" LOC = "Y16" ; -#NET "io_tx<3>" LOC = "U16" ; -#NET "io_tx<4>" LOC = "V16" ; -#NET "io_tx<5>" LOC = "AB19" ; -#NET "io_tx<6>" LOC = "AA19" ; -#NET "io_tx<7>" LOC = "U14" ; -#NET "io_tx<8>" LOC = "U15" ; -#NET "io_tx<9>" LOC = "AB17" ; -#NET "io_tx<10>" LOC = "AB18" ; -#NET "io_tx<11>" LOC = "Y13" ; -#NET "io_tx<12>" LOC = "W14" ; -#NET "io_tx<13>" LOC = "U13" ; -#NET "io_tx<14>" LOC = "AA15" ; -#NET "io_tx<15>" LOC = "AB14" ; - -#NET "io_rx<0>" LOC = "Y8" ; -#NET "io_rx<1>" LOC = "Y9" ; -#NET "io_rx<2>" LOC = "V7" ; -#NET "io_rx<3>" LOC = "U8" ; -#NET "io_rx<4>" LOC = "V10" ; -#NET "io_rx<5>" LOC = "U9" ; -#NET "io_rx<6>" LOC = "AB7" ; -#NET "io_rx<7>" LOC = "AA8" ; -#NET "io_rx<8>" LOC = "W8" ; -#NET "io_rx<9>" LOC = "V8" ; -#NET "io_rx<10>" LOC = "AB5" ; -#NET "io_rx<11>" LOC = "AB6" ; -#NET "io_rx<12>" LOC = "AB4" ; -#NET "io_rx<13>" LOC = "AA4" ; -#NET "io_rx<14>" LOC = "W5" ; -#NET "io_rx<15>" LOC = "Y4" ; - -##NET "CLKOUT2_CODEC" LOC = "U12" ; -##NET "CLKOUT1_CODEC" LOC = "V12" ; - -## FPGA Config Pins -##NET "fpga_cfg_prog_b" LOC = "A2" ; -##NET "fpga_cfg_done" LOC = "AB21" ; +NET "overo_gpio145" LOC = "C7" ; +NET "cgen_mosi" LOC = "E22" ; +NET "cgen_sclk" LOC = "J19" ; +NET "cgen_sen_b" LOC = "H20" ; NET "fpga_cfg_din" LOC = "W17" ; NET "fpga_cfg_cclk" LOC = "V17" ; -##NET "fpga_cfg_init_b" LOC = "W15" ; - -## Unused -##NET "unnamed_net37" LOC = "B1" ; # TMS -##NET "unnamed_net36" LOC = "B22" ; # TDO -##NET "unnamed_net35" LOC = "D2" ; # TDI -##NET "unnamed_net34" LOC = "A21" ; # TCK -##NET "unnamed_net45" LOC = "F7" ; # PUDC_B -##NET "unnamed_net44" LOC = "V6" ; # M2 -##NET "unnamed_net43" LOC = "AA3" ; # M1 -##NET "unnamed_net42" LOC = "AB3" ; # M0 -##NET "GND" LOC = "V19" ; # Suspend, unused -- cgit v1.2.3 From 08eb9d2937c28edfb6d1fe7fb168ef77727406d5 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 9 Sep 2010 14:19:14 -0700 Subject: updated pins to match rev2, removed dip switch, etc. seems to compile ok. --- usrp2/top/u1e/u1e.ucf | 251 +++++++++++++++++++++++------------------------ usrp2/top/u1e/u1e.v | 8 +- usrp2/top/u1e/u1e_core.v | 8 +- 3 files changed, 130 insertions(+), 137 deletions(-) diff --git a/usrp2/top/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf index 659a9dce5..51968d24a 100644 --- a/usrp2/top/u1e/u1e.ucf +++ b/usrp2/top/u1e/u1e.ucf @@ -54,8 +54,10 @@ NET "overo_gpio22" LOC = "A3" ; # MISC GPIO for debug NET "overo_gpio23" LOC = "B3" ; # MISC GPIO for debug NET "overo_gpio64" LOC = "A4" ; # MISC GPIO for debug NET "overo_gpio65" LOC = "F8" ; # MISC GPIO for debug -NET "overo_gpio127" LOC = "C8" ; # MISC GPIO for debug, also used on the passthru image as the cgen_sen_b pin -NET "overo_gpio128" LOC = "G8" ; # MISC GPIO for debug + +NET "overo_gpio127" LOC = "C8" ; # Changed name to gpio10 +NET "overo_gpio128" LOC = "G8" ; # Changed name to gpio186 + NET "overo_gpio144" LOC = "A5" ; # tx_have_space NET "overo_gpio145" LOC = "C7" ; # tx_underrun NET "overo_gpio146" LOC = "A6" ; # rx_have_data @@ -69,146 +71,137 @@ NET "overo_gpio176" LOC = "B4" ; # MISC GPIO for debug #NET "overo_rxd1" LOC = "D6" ; ## FTDI UART to USB converter -NET "FPGA_TXD" LOC = "U1" ; -NET "FPGA_RXD" LOC = "T6" ; +NET "FPGA_TXD" LOC = "G19" ; +NET "FPGA_RXD" LOC = "F20" ; #NET "SYSEN" LOC = "C11" ; ## I2C -NET "db_scl" LOC = "U4" ; -NET "db_sda" LOC = "U5" ; +NET "db_scl" LOC = "F19" ; +NET "db_sda" LOC = "F18" ; ## SPI ### DBoard SPI -NET "db_sclk_rx" LOC = "W3" ; -NET "db_miso_rx" LOC = "W2" ; -NET "db_mosi_rx" LOC = "V4" ; -NET "db_sen_rx" LOC = "V3" ; -NET "db_sclk_tx" LOC = "Y1" ; -NET "db_miso_tx" LOC = "W1" ; -NET "db_mosi_tx" LOC = "R3" ; -NET "db_sen_tx" LOC = "T4" ; +NET "db_sclk_rx" LOC = "D21" ; +NET "db_miso_rx" LOC = "D22" ; +NET "db_mosi_rx" LOC = "D20" ; +NET "db_sen_rx" LOC = "E19" ; +NET "db_sclk_tx" LOC = "F21" ; +NET "db_miso_tx" LOC = "E20" ; +NET "db_mosi_tx" LOC = "G17" ; +NET "db_sen_tx" LOC = "G18" ; ### AD9862 SPI and aux SPI Interfaces -#NET "aux_sdi_codec" LOC = "F19" ; -#NET "aux_sdo_codec" LOC = "F18" ; -#NET "aux_sclk_codec" LOC = "D21" ; -NET "sen_codec" LOC = "D20" ; -NET "mosi_codec" LOC = "E19" ; -NET "miso_codec" LOC = "F21" ; -NET "sclk_codec" LOC = "E20" ; +#NET "aux_sdi_codec" LOC = "G3" ; +#NET "aux_sdo_codec" LOC = "F3" ; +#NET "aux_sclk_codec" LOC = "C1" ; +NET "sen_codec" LOC = "F5" ; +NET "mosi_codec" LOC = "F4" ; +NET "miso_codec" LOC = "H4" ; +NET "sclk_codec" LOC = "H3" ; ### Clock Gen SPI -NET "cgen_miso" LOC = "U2" ; -NET "cgen_mosi" LOC = "V1" ; -NET "cgen_sclk" LOC = "R5" ; -NET "cgen_sen_b" LOC = "T1" ; +NET "cgen_miso" LOC = "F22" ; +NET "cgen_mosi" LOC = "E22" ; +NET "cgen_sclk" LOC = "J19" ; +NET "cgen_sen_b" LOC = "H20" ; ## Clock gen control -NET "cgen_st_status" LOC = "D4" ; -NET "cgen_st_ld" LOC = "D1" ; -NET "cgen_st_refmon" LOC = "E1" ; -NET "cgen_sync_b" LOC = "M1" ; -NET "cgen_ref_sel" LOC = "J1" ; +NET "cgen_st_status" LOC = "P20" ; +NET "cgen_st_ld" LOC = "R17" ; +NET "cgen_st_refmon" LOC = "P17" ; +NET "cgen_sync_b" LOC = "U18" ; +NET "cgen_ref_sel" LOC = "U19" ; ## Debug pins -NET "debug_led<2>" LOC = "T5" ; -NET "debug_led<1>" LOC = "R2" ; -NET "debug_led<0>" LOC = "R1" ; -NET "debug<0>" LOC = "P6" ; -NET "debug<1>" LOC = "R6" ; -NET "debug<2>" LOC = "P1" ; -NET "debug<3>" LOC = "P2" ; -NET "debug<4>" LOC = "N6" ; -NET "debug<5>" LOC = "N5" ; -NET "debug<6>" LOC = "N1" ; -NET "debug<7>" LOC = "K2" ; -NET "debug<8>" LOC = "K3" ; -NET "debug<9>" LOC = "K6" ; -NET "debug<10>" LOC = "L5" ; -NET "debug<11>" LOC = "H2" ; -NET "debug<12>" LOC = "K4" ; -NET "debug<13>" LOC = "K5" ; -NET "debug<14>" LOC = "G1" ; -NET "debug<15>" LOC = "H1" ; -NET "debug<16>" LOC = "H5" ; -NET "debug<17>" LOC = "H6" ; -NET "debug<18>" LOC = "E3" ; -NET "debug<19>" LOC = "E4" ; -NET "debug<20>" LOC = "G5" ; -NET "debug<21>" LOC = "G6" ; -NET "debug<22>" LOC = "F2" ; -NET "debug<23>" LOC = "F1" ; -NET "debug<24>" LOC = "H3" ; -NET "debug<25>" LOC = "H4" ; -NET "debug<26>" LOC = "F4" ; -NET "debug<27>" LOC = "F5" ; -NET "debug<28>" LOC = "C2" ; -NET "debug<29>" LOC = "C1" ; -NET "debug<30>" LOC = "F3" ; -NET "debug<31>" LOC = "G3" ; -NET "debug_clk<0>" LOC = "L6" ; -NET "debug_clk<1>" LOC = "M5" ; +NET "debug_led<3>" LOC = "Y15" ; +NET "debug_led<2>" LOC = "K16" ; +NET "debug_led<1>" LOC = "J17" ; +NET "debug_led<0>" LOC = "H22" ; +NET "debug<0>" LOC = "G22" ; +NET "debug<1>" LOC = "H17" ; +NET "debug<2>" LOC = "H18" ; +NET "debug<3>" LOC = "K20" ; +NET "debug<4>" LOC = "J20" ; +NET "debug<5>" LOC = "K19" ; +NET "debug<6>" LOC = "K18" ; +NET "debug<7>" LOC = "L22" ; +NET "debug<8>" LOC = "K22" ; +NET "debug<9>" LOC = "N22" ; +NET "debug<10>" LOC = "M22" ; +NET "debug<11>" LOC = "N20" ; +NET "debug<12>" LOC = "N19" ; +NET "debug<13>" LOC = "R22" ; +NET "debug<14>" LOC = "P22" ; +NET "debug<15>" LOC = "N17" ; +NET "debug<16>" LOC = "P16" ; +NET "debug<17>" LOC = "U22" ; +NET "debug<18>" LOC = "P19" ; +NET "debug<19>" LOC = "R18" ; +NET "debug<20>" LOC = "U20" ; +NET "debug<21>" LOC = "T20" ; +NET "debug<22>" LOC = "R19" ; +NET "debug<23>" LOC = "R20" ; +NET "debug<24>" LOC = "W22" ; +NET "debug<25>" LOC = "Y22" ; +NET "debug<26>" LOC = "T18" ; +NET "debug<27>" LOC = "T17" ; +NET "debug<28>" LOC = "W19" ; +NET "debug<29>" LOC = "V20" ; +NET "debug<30>" LOC = "Y21" ; +NET "debug<31>" LOC = "AA22" ; +NET "debug_clk<0>" LOC = "N18" ; +NET "debug_clk<1>" LOC = "M17" ; -NET "debug_pb<2>" LOC = "Y2" ; -NET "debug_pb<1>" LOC = "AA1" ; -NET "debug_pb<0>" LOC = "N3" ; +NET "debug_pb" LOC = "C22" ; -NET "dip_sw<7>" LOC = "T3" ; -NET "dip_sw<6>" LOC = "U3" ; -NET "dip_sw<5>" LOC = "M3" ; -NET "dip_sw<4>" LOC = "N4" ; -NET "dip_sw<3>" LOC = "J3" ; -NET "dip_sw<2>" LOC = "J4" ; -NET "dip_sw<1>" LOC = "J6" ; -NET "dip_sw<0>" LOC = "J7" ; +#NET "reset_codec" LOC = "C2" ; -#NET "reset_codec" LOC = "D22" ; +NET "RXSYNC" LOC = "F2" ; +NET "DB<11>" LOC = "G6" ; +NET "DB<10>" LOC = "G5" ; +NET "DB<9>" LOC = "E4" ; +NET "DB<8>" LOC = "E3" ; +NET "DB<7>" LOC = "H6" ; +NET "DB<6>" LOC = "H5" ; +NET "DB<5>" LOC = "H1" ; +NET "DB<4>" LOC = "G1" ; +NET "DB<3>" LOC = "K5" ; +NET "DB<2>" LOC = "K4" ; +NET "DB<1>" LOC = "H2" ; +NET "DB<0>" LOC = "L5" ; -NET "RXSYNC" LOC = "F22" ; -NET "DB<11>" LOC = "E22" ; -NET "DB<10>" LOC = "J19" ; -NET "DB<9>" LOC = "H20" ; -NET "DB<8>" LOC = "G19" ; -NET "DB<7>" LOC = "F20" ; -NET "DB<6>" LOC = "K16" ; -NET "DB<5>" LOC = "J17" ; -NET "DB<4>" LOC = "H22" ; -NET "DB<3>" LOC = "G22" ; -NET "DB<2>" LOC = "H17" ; -NET "DB<1>" LOC = "H18" ; -NET "DB<0>" LOC = "K20" ; -NET "DA<11>" LOC = "J20" ; -NET "DA<10>" LOC = "K19" ; -NET "DA<9>" LOC = "K18" ; -NET "DA<8>" LOC = "L22" ; -NET "DA<7>" LOC = "K22" ; -NET "DA<6>" LOC = "N22" ; -NET "DA<5>" LOC = "M22" ; -NET "DA<4>" LOC = "N20" ; -NET "DA<3>" LOC = "N19" ; -NET "DA<2>" LOC = "R22" ; -NET "DA<1>" LOC = "P22" ; -NET "DA<0>" LOC = "N17" ; +NET "DA<11>" LOC = "K6" ; +NET "DA<10>" LOC = "K3" ; +NET "DA<9>" LOC = "K2" ; +NET "DA<8>" LOC = "N1" ; +NET "DA<7>" LOC = "N5" ; +NET "DA<6>" LOC = "N6" ; +NET "DA<5>" LOC = "P2" ; +NET "DA<4>" LOC = "P1" ; +NET "DA<3>" LOC = "R6" ; +NET "DA<2>" LOC = "P6" ; +NET "DA<1>" LOC = "R1" ; +NET "DA<0>" LOC = "R2" ; -NET "TX<13>" LOC = "P19" ; -NET "TX<12>" LOC = "R18" ; -NET "TX<11>" LOC = "U20" ; -NET "TX<10>" LOC = "T20" ; -NET "TX<9>" LOC = "R19" ; -NET "TX<8>" LOC = "R20" ; -NET "TX<7>" LOC = "W22" ; -NET "TX<6>" LOC = "Y22" ; -NET "TX<5>" LOC = "T18" ; -NET "TX<4>" LOC = "T17" ; -NET "TX<3>" LOC = "W19" ; -NET "TX<2>" LOC = "V20" ; -NET "TX<1>" LOC = "Y21" ; -NET "TX<0>" LOC = "AA22" ; -NET "TXSYNC" LOC = "U18" ; -NET "TXBLANK" LOC = "U19" ; +NET "TX<13>" LOC = "T6" ; +NET "TX<12>" LOC = "U1" ; +NET "TX<11>" LOC = "T1" ; +NET "TX<10>" LOC = "R5" ; +NET "TX<9>" LOC = "V1" ; +NET "TX<8>" LOC = "U2" ; +NET "TX<7>" LOC = "T4" ; +NET "TX<6>" LOC = "R3" ; +NET "TX<5>" LOC = "W1" ; +NET "TX<4>" LOC = "Y1" ; +NET "TX<3>" LOC = "V3" ; +NET "TX<2>" LOC = "V4" ; +NET "TX<1>" LOC = "W2" ; +NET "TX<0>" LOC = "W3" ; +NET "TXSYNC" LOC = "U5" ; +NET "TXBLANK" LOC = "U4" ; -NET "PPS_IN" LOC = "M17" ; +NET "PPS_IN" LOC = "M5" ; NET "io_tx<0>" LOC = "AB20" ; NET "io_tx<1>" LOC = "Y17" ; @@ -255,12 +248,12 @@ NET "io_rx<15>" LOC = "Y4" ; #NET "fpga_cfg_init_b" LOC = "W15" ; ## Unused -#NET "unnamed_net37" LOC = "B1" ; # TMS -#NET "unnamed_net36" LOC = "B22" ; # TDO -#NET "unnamed_net35" LOC = "D2" ; # TDI -#NET "unnamed_net34" LOC = "A21" ; # TCK -#NET "unnamed_net45" LOC = "F7" ; # PUDC_B -#NET "unnamed_net44" LOC = "V6" ; # M2 -#NET "unnamed_net43" LOC = "AA3" ; # M1 -#NET "unnamed_net42" LOC = "AB3" ; # M0 +#NET "unnamed_net53" LOC = "B1" ; # TMS +#NET "unnamed_net52" LOC = "B22" ; # TDO +#NET "unnamed_net51" LOC = "D2" ; # TDI +#NET "unnamed_net50" LOC = "A21" ; # TCK +#NET "unnamed_net59" LOC = "F7" ; # PUDC_B +#NET "unnamed_net58" LOC = "V6" ; # M2 +#NET "unnamed_net57" LOC = "AA3" ; # M1 +#NET "unnamed_net56" LOC = "AB3" ; # M0 #NET "GND" LOC = "V19" ; # Suspend, unused diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index 9536b5ced..7ddbfd537 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -5,8 +5,8 @@ module u1e (input CLK_FPGA_P, input CLK_FPGA_N, // Diff - output [2:0] debug_led, output [31:0] debug, output [1:0] debug_clk, - input [2:0] debug_pb, input [7:0] dip_sw, output FPGA_TXD, input FPGA_RXD, + output [3:0] debug_led, output [31:0] debug, output [1:0] debug_clk, + input debug_pb, output FPGA_TXD, input FPGA_RXD, // GPMC input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, @@ -137,9 +137,9 @@ module u1e // ///////////////////////////////////////////////////////////////////////// // Main U1E Core - u1e_core u1e_core(.clk_fpga(clk_fpga), .rst_fpga(~debug_pb[2]), + u1e_core u1e_core(.clk_fpga(clk_fpga), .rst_fpga(~debug_pb), .debug_led(debug_led), .debug(debug), .debug_clk(debug_clk), - .debug_pb(~debug_pb), .dip_sw(dip_sw), .debug_txd(FPGA_TXD), .debug_rxd(FPGA_RXD), + .debug_txd(FPGA_TXD), .debug_rxd(FPGA_RXD), .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 5c4b6de6c..42333a722 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -6,8 +6,8 @@ module u1e_core (input clk_fpga, input rst_fpga, - output [2:0] debug_led, output [31:0] debug, output [1:0] debug_clk, - input [2:0] debug_pb, input [7:0] dip_sw, output debug_txd, input debug_rxd, + output [3:0] debug_led, output [31:0] debug, output [1:0] debug_clk, + output debug_txd, input debug_rxd, // GPMC input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, @@ -343,11 +343,11 @@ module u1e_core assign rx_enable = xfer_rate[14]; assign rate = xfer_rate[7:0]; - assign { debug_led[2],debug_led[0],debug_led[1] } = {run_rx,run_tx,reg_leds[0]}; // LEDs are arranged funny on board + assign { debug_led[3:0] } = {run_rx,run_tx,reg_leds[1:0]}; assign { cgen_sync_b, cgen_ref_sel } = reg_cgen_ctrl; assign s0_dat_miso = (s0_adr[6:0] == REG_LEDS) ? reg_leds : - (s0_adr[6:0] == REG_SWITCHES) ? {5'b0,debug_pb[2:0],dip_sw[7:0]} : + (s0_adr[6:0] == REG_SWITCHES) ? { 16'd0 } : (s0_adr[6:0] == REG_CGEN_CTRL) ? reg_cgen_ctrl : (s0_adr[6:0] == REG_CGEN_ST) ? {13'b0,cgen_st_status,cgen_st_ld,cgen_st_refmon} : (s0_adr[6:0] == REG_TEST) ? reg_test : -- cgit v1.2.3 From f177ce94fb4d4d2bdb19339c24bf5dc6035f1411 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 16 Sep 2010 14:01:43 -0700 Subject: send all gpmc signals to mictor --- usrp2/top/u1e_ethdebug/.gitignore | 6 +++ usrp2/top/u1e_ethdebug/Makefile | 83 +++++++++++++++++++++++++++++++++++++ usrp2/top/u1e_ethdebug/u1e.ucf | 86 +++++++++++++++++++++++++++++++++++++++ usrp2/top/u1e_ethdebug/u1e.v | 26 ++++++++++++ 4 files changed, 201 insertions(+) create mode 100644 usrp2/top/u1e_ethdebug/.gitignore create mode 100644 usrp2/top/u1e_ethdebug/Makefile create mode 100644 usrp2/top/u1e_ethdebug/u1e.ucf create mode 100644 usrp2/top/u1e_ethdebug/u1e.v diff --git a/usrp2/top/u1e_ethdebug/.gitignore b/usrp2/top/u1e_ethdebug/.gitignore new file mode 100644 index 000000000..8d872713e --- /dev/null +++ b/usrp2/top/u1e_ethdebug/.gitignore @@ -0,0 +1,6 @@ +*~ +build +*.log +*.cmd +tb_u1e +*.lxt diff --git a/usrp2/top/u1e_ethdebug/Makefile b/usrp2/top/u1e_ethdebug/Makefile new file mode 100644 index 000000000..751b52970 --- /dev/null +++ b/usrp2/top/u1e_ethdebug/Makefile @@ -0,0 +1,83 @@ +# +# Copyright 2008 Ettus Research LLC +# + +################################################## +# Project Setup +################################################## +TOP_MODULE = u1e +BUILD_DIR = $(abspath build$(ISE)) + +################################################## +# Include other makefiles +################################################## + +include ../Makefile.common + +################################################## +# Project Properties +################################################## +export PROJECT_PROPERTIES := \ +family "Spartan-3A DSP" \ +device xc3sd1800a \ +package cs484 \ +speed -4 \ +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 +################################################## +TOP_SRCS = \ +u1e.v \ +u1e.ucf + +SOURCES = $(abspath $(TOP_SRCS)) + +################################################## +# Process Properties +################################################## +SYNTHESIZE_PROPERTIES = \ +"Number of Clock Buffers" 8 \ +"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 + +TRANSLATE_PROPERTIES = \ +"Macro Search Path" "$(shell pwd)/../../coregen/" + +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 + +PLACE_ROUTE_PROPERTIES = \ +"Place & Route Effort Level (Overall)" High + +STATIC_TIMING_PROPERTIES = \ +"Number of Paths in Error/Verbose Report" 10 \ +"Report Type" "Error Report" + +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 \ +"Unused IOB Pins" "Pull Up" + +SIM_MODEL_PROPERTIES = "" diff --git a/usrp2/top/u1e_ethdebug/u1e.ucf b/usrp2/top/u1e_ethdebug/u1e.ucf new file mode 100644 index 000000000..0d4384a2a --- /dev/null +++ b/usrp2/top/u1e_ethdebug/u1e.ucf @@ -0,0 +1,86 @@ + +## GPMC +NET "EM_D<15>" LOC = "D13" ; +NET "EM_D<14>" LOC = "D15" ; +NET "EM_D<13>" LOC = "C16" ; +NET "EM_D<12>" LOC = "B20" ; +NET "EM_D<11>" LOC = "A19" ; +NET "EM_D<10>" LOC = "A17" ; +NET "EM_D<9>" LOC = "E15" ; +NET "EM_D<8>" LOC = "F15" ; +NET "EM_D<7>" LOC = "E16" ; +NET "EM_D<6>" LOC = "F16" ; +NET "EM_D<5>" LOC = "B17" ; +NET "EM_D<4>" LOC = "C17" ; +NET "EM_D<3>" LOC = "B19" ; +NET "EM_D<2>" LOC = "D19" ; +NET "EM_D<1>" LOC = "C19" ; +NET "EM_D<0>" LOC = "A20" ; + +NET "EM_A<10>" LOC = "C14" ; +NET "EM_A<9>" LOC = "C10" ; +NET "EM_A<8>" LOC = "C5" ; +NET "EM_A<7>" LOC = "A18" ; +NET "EM_A<6>" LOC = "A15" ; +NET "EM_A<5>" LOC = "A12" ; +NET "EM_A<4>" LOC = "A10" ; +NET "EM_A<3>" LOC = "E7" ; +NET "EM_A<2>" LOC = "A7" ; +NET "EM_A<1>" LOC = "C15" ; + +NET "EM_NCS6" LOC = "E17" ; +NET "EM_NCS5" LOC = "E10" ; +NET "EM_NCS4" LOC = "E6" ; +#NET "EM_NCS1" LOC = "D18" ; +#NET "EM_NCS0" LOC = "D17" ; + +NET "EM_CLK" LOC = "F11" ; +NET "EM_WAIT0" LOC = "F14" ; +NET "EM_NBE<1>" LOC = "D14" ; +NET "EM_NBE<0>" LOC = "A13" ; +NET "EM_NWE" LOC = "B13" ; +NET "EM_NOE" LOC = "A14" ; +NET "EM_NADV_ALE" LOC = "B15" ; +NET "EM_NWP" LOC = "F13" ; + +## Debug pins +NET "debug_led<3>" LOC = "Y15" ; +NET "debug_led<2>" LOC = "K16" ; +NET "debug_led<1>" LOC = "J17" ; +NET "debug_led<0>" LOC = "H22" ; +NET "debug<0>" LOC = "G22" ; +NET "debug<1>" LOC = "H17" ; +NET "debug<2>" LOC = "H18" ; +NET "debug<3>" LOC = "K20" ; +NET "debug<4>" LOC = "J20" ; +NET "debug<5>" LOC = "K19" ; +NET "debug<6>" LOC = "K18" ; +NET "debug<7>" LOC = "L22" ; +NET "debug<8>" LOC = "K22" ; +NET "debug<9>" LOC = "N22" ; +NET "debug<10>" LOC = "M22" ; +NET "debug<11>" LOC = "N20" ; +NET "debug<12>" LOC = "N19" ; +NET "debug<13>" LOC = "R22" ; +NET "debug<14>" LOC = "P22" ; +NET "debug<15>" LOC = "N17" ; +NET "debug<16>" LOC = "P16" ; +NET "debug<17>" LOC = "U22" ; +NET "debug<18>" LOC = "P19" ; +NET "debug<19>" LOC = "R18" ; +NET "debug<20>" LOC = "U20" ; +NET "debug<21>" LOC = "T20" ; +NET "debug<22>" LOC = "R19" ; +NET "debug<23>" LOC = "R20" ; +NET "debug<24>" LOC = "W22" ; +NET "debug<25>" LOC = "Y22" ; +NET "debug<26>" LOC = "T18" ; +NET "debug<27>" LOC = "T17" ; +NET "debug<28>" LOC = "W19" ; +NET "debug<29>" LOC = "V20" ; +NET "debug<30>" LOC = "Y21" ; +NET "debug<31>" LOC = "AA22" ; +NET "debug_clk<0>" LOC = "N18" ; +NET "debug_clk<1>" LOC = "M17" ; + +NET "debug_pb" LOC = "C22" ; diff --git a/usrp2/top/u1e_ethdebug/u1e.v b/usrp2/top/u1e_ethdebug/u1e.v new file mode 100644 index 000000000..c4740b941 --- /dev/null +++ b/usrp2/top/u1e_ethdebug/u1e.v @@ -0,0 +1,26 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// + +//`define DCM 1 + +module u1e + (output [3:0] debug_led, output [31:0] debug, output [1:0] debug_clk, + input debug_pb, + + // GPMC + input EM_CLK, input [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, + input EM_WAIT0, input EM_NCS4, input EM_NCS5, input EM_NCS6, input EM_NWE, input EM_NOE, + input EM_NADV_ALE, input EM_NWP + ); + + assign debug_clk = {EM_CLK, EM_NADV_ALE}; + + assign debug_led = {EM_NWP, EM_A[9], EM_A[8], debug_pb}; + + assign debug = { { EM_NBE[1:0], EM_WAIT0, EM_NCS4, EM_NCS5, EM_NCS6, EM_NWE, EM_NOE }, + { EM_A[10], EM_A[7:1] }, + { EM_D[15:8] }, + { EM_D[7:0] } }; + + +endmodule // u1e -- cgit v1.2.3 From ba658f4d2cac9fb0f9d22060da989c9078cc4d1e Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 21 Sep 2010 10:41:05 -0700 Subject: added db_tvrx, regmap gen_dtt75403_regs.py --- host/lib/ic_reg_maps/CMakeLists.txt | 5 + host/lib/ic_reg_maps/gen_dtt75403_regs.py | 85 ++++++++ host/lib/ic_reg_maps/gen_max2118_regs.py | 0 host/lib/usrp/dboard/db_tvrx.cpp | 316 ++++++++++++++++++++++++++++++ 4 files changed, 406 insertions(+) create mode 100755 host/lib/ic_reg_maps/gen_dtt75403_regs.py mode change 100644 => 100755 host/lib/ic_reg_maps/gen_max2118_regs.py create mode 100644 host/lib/usrp/dboard/db_tvrx.cpp diff --git a/host/lib/ic_reg_maps/CMakeLists.txt b/host/lib/ic_reg_maps/CMakeLists.txt index f8e15c13d..b396db4ca 100644 --- a/host/lib/ic_reg_maps/CMakeLists.txt +++ b/host/lib/ic_reg_maps/CMakeLists.txt @@ -68,3 +68,8 @@ LIBUHD_PYTHON_GEN_SOURCE( ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_ad9522_regs.py ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/ad9522_regs.hpp ) + +LIBUHD_PYTHON_GEN_SOURCE( + ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_dtt75403_regs.py + ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/dtt75403_regs.py +) diff --git a/host/lib/ic_reg_maps/gen_dtt75403_regs.py b/host/lib/ic_reg_maps/gen_dtt75403_regs.py new file mode 100755 index 000000000..fe64bd92a --- /dev/null +++ b/host/lib/ic_reg_maps/gen_dtt75403_regs.py @@ -0,0 +1,85 @@ +#!/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 . +# + +######################################################################## +# Template for raw text data describing registers +# name addr[bit range inclusive] default optional enums +######################################################################## +REGS_TMPL="""\ +######################################################################## +## Note: offsets given from perspective of data bits (excludes address) +######################################################################## +## +######################################################################## +## Address byte +######################################################################## +adb 0[1:2] 0 +######################################################################## +## Divider byte 1 +######################################################################## +db1 1[0:6] 0x00 +######################################################################## +## Divider byte 2 +######################################################################## +db2 2[0:7] 0x00 +######################################################################## +## Control byte 1 +######################################################################## +atp 3[3:5] 0 112, 109, 106, 103, 100, 94, 94, disable +refdiv 3[0:2] 0 166.667khz, 142.857khz, 80khz, 62.5khz, 31.25khz, 50khz +######################################################################## +## Band switch byte +######################################################################## +cpsel 4[6:7] 0 +filterbw 4[4] 0 8mhz, 7mhz +bandsel 4[0:3] 0 +######################################################################## +## Control byte 2 +######################################################################## +atc 5[5] 0 low, high +stby 5[4] 0 standby, on +xto 5[0] 0 disable, enable +""" + +######################################################################## +# Template for methods in the body of the struct +######################################################################## +BODY_TMPL="""\ +boost::uint8_t get_reg(boost::uint8_t addr){ + boost::uint8_t reg = 0; + switch(addr){ + #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs))) + case $addr: + #for $reg in filter(lambda r: r.get_addr() == addr, $regs) + reg |= (boost::uint8_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); + #end for + break; + #end for + } + return boost::uint8_t(reg); +} + +""" + +if __name__ == '__main__': + import common; common.generate( + name='dtt75403_regs', + regs_tmpl=REGS_TMPL, + body_tmpl=BODY_TMPL, + file=__file__, + ) diff --git a/host/lib/ic_reg_maps/gen_max2118_regs.py b/host/lib/ic_reg_maps/gen_max2118_regs.py old mode 100644 new mode 100755 diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp new file mode 100644 index 000000000..5582dbe33 --- /dev/null +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -0,0 +1,316 @@ +// +// 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 . +// + +// No RX IO Pins Used + +// RX IO Functions + +//ADC/DAC functions: +//DAC 1: RF AGC +//DAC 2: IF AGC + +//min freq: 50e6 +//max freq: 860e6 +//gain range: [0:1dB:115dB] + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + +/*********************************************************************** + * The tvrx constants + **********************************************************************/ +static const bool tvrx_debug = true; + +static const freq_range_t tvrx_freq_range(50e6, 860e6); + +static const prop_names_t tvrx_antennas = ""; //only got one + +static const uhd::dict tvrx_gain_ranges = map_list_of + ("RF", gain_range_t(0, 60, float(60.0/4096))) //both gains are analog and controlled by DAC + ("IF", gain_range_t(0, 35, float(35.0/4096))) //the old driver used 1dB for both; i don't think that's right? +; + +static const uhd::dict tvrx_freq_ranges = map_list_of + ("VHFLO", freq_range_t(50e6, 158e6)) //this isn't used outside this driver. just for us. + ("VHFHI", freq_range_t(158e6, 454e6)) + ("UHF" , freq_range_t(454e6, 860e6)) +; + +//we might need to spec the various bands for band selection. + +static const double tvrx_lo_freq = 36e6; //LO freq of TVRX module + +/*********************************************************************** + * The tvrx dboard class + **********************************************************************/ +class tvrx : public rx_dboard_base{ +public: + tvrx(ctor_args_t args); + ~tvrx(void); + + void rx_get(const wax::obj &key, wax::obj &val); + void rx_set(const wax::obj &key, const wax::obj &val); + +private: + uhd::dict _gains; + dtt75403_regs_t _dtt75403_regs; + boost::uint8_t _dtt75403_addr(void){ + return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x60 : 0x61; //ok really? we could rename that call + }; + + void set_gain(float gain, const std::string &name); + + void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ + //why is this an inline anyway? bring this out + start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0x5)); + stop_reg = boost::uint8_t(std::clip(int(stop_reg), 0x0, 0x5)); + + for(boost::uint8_t start_addr=start_reg; start_addr <= stop_reg; start_addr += sizeof(boost::uint32_t) - 1){ + int num_bytes = int(stop_reg - start_addr + 1) > int(sizeof(boost::uint32_t)) - 1 ? sizeof(boost::uint32_t) - 1 : stop_reg - start_addr + 1; + + //create buffer for register data (+1 for start address) + byte_vector_t regs_vector(num_bytes + 1); + + //first byte is the address of first register + regs_vector[0] = start_addr; + + //get the register data + for(int i=0; iget_iface()->write_i2c( + _max2118_addr(), regs_vector + ); + } + } + +}; + +/*********************************************************************** + * Register the tvrx dboard + **********************************************************************/ +static dboard_base::sptr make_tvrx(dboard_base::ctor_args_t args){ + return dboard_base::sptr(new tvrx(args)); +} + +UHD_STATIC_BLOCK(reg_tvrx_dboard){ + //register the factory function for the rx dbid + dboard_manager::register_dboard(0x0003, &make_tvrx, "tvrx"); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){ + //enable only the clocks we need + + //TODO: YOU GOT SOME CLOCK SETUP TO DO HERE, DOGGGG + + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + + //set the gpio directions and atr controls (identically) + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0); // All unused in atr + if (this->get_iface()->get_special_props().soft_clock_divider){ + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x1); // GPIO0 is clock + } + else{ + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs + } + + //send initial register settings + //HAAAAY GUYYYYYSSS + + //set default gains + BOOST_FOREACH(const std::string &name, tvrx_gain_ranges.keys()){ + set_gain(tvrx_gain_ranges[name].min, name); + } +} + +tvrx::~tvrx(void){ +} + +/*********************************************************************** + * Gain Handling + **********************************************************************/ +/*! + * Convert a requested gain for the GC2 vga into the integer register value. + * The gain passed into the function will be set to the actual value. + * \param gain the requested gain in dB + * \return 5 bit the register value + */ + +//yo this should look the same as the below one for the IF, dogg +static int gain_to_gc2_vga_reg(float &gain){ + int reg = 0; + gain = std::clip(float(boost::math::iround(gain)), tvrx_gain_ranges["GC2"].min, tvrx_gain_ranges["GC2"].max); + + // Half dB steps from 0-5dB, 1dB steps from 5-24dB + if (gain < 5) { + reg = boost::math::iround(31.0 - gain/0.5); + gain = float(boost::math::iround(gain) * 0.5); + } else { + reg = boost::math::iround(22.0 - (gain - 4.0)); + gain = float(boost::math::iround(gain)); + } + + if (tvrx_debug) std::cerr << boost::format( + "tvrx GC2 Gain: %f dB, reg: %d" + ) % gain % reg << std::endl; + + return reg; +} + +/*! + * Convert a requested gain for the RF gain into the dac_volts value. + * The gain passed into the function will be set to the actual value. + * \param gain the requested gain in dB + * \return dac voltage value + */ + +//yo what about the 1.22 opamp gain of the USRP1 -- is this replicated on U2? +static float gain_to_rfgain_dac(float &gain){ + //clip the input + gain = std::clip(gain, tvrx_gain_ranges["RF"].min, tvrx_gain_ranges["RF"].max); + + //voltage level constants + static const float max_volts = float(0), min_volts = float(3.3); + static const float slope = (max_volts-min_volts)/tvrx_gain_ranges["RF"].max; + + //calculate the voltage for the aux dac + float dac_volts = gain*slope + min_volts; + + if (tvrx_debug) std::cerr << boost::format( + "tvrx RFAGC Gain: %f dB, dac_volts: %f V" + ) % gain % dac_volts << std::endl; + + //the actual gain setting + gain = (dac_volts - min_volts)/slope; + + return dac_volts; +} + +void tvrx::set_gain(float gain, const std::string &name){ + assert_has(tvrx_gain_ranges.keys(), name, "tvrx gain name"); + if (name == "RF"){ +//should look the same as below + } + else if(name == "IF"){ + //write the new voltage to the aux dac CHECK THIS + this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, gain_to_gc1_rfvga_dac(gain)); + } + else UHD_THROW_INVALID_CODE_PATH(); + _gains[name] = gain; +} + +/*********************************************************************** + * RX Get and Set + **********************************************************************/ +void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_NAME: + val = get_rx_id().to_pp_string(); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + assert_has(_gains.keys(), key.name, "tvrx gain name"); + val = _gains[key.name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(tvrx_gain_ranges.keys(), key.name, "tvrx gain name"); + val = tvrx_gain_ranges[key.name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(tvrx_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = tvrx_lo_freq; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = tvrx_freq_range; + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string(tvrx_antennas); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = tvrx_antennas; + return; + + case SUBDEV_PROP_CONNECTION: + val = SUBDEV_CONN_COMPLEX_IQ; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = false; + return; + + case SUBDEV_PROP_LO_LOCKED: + val = true; + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +//for smaaht kids to use to set advanced props +void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_GAIN: + this->set_gain(val.as(), key.name); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } +} + -- cgit v1.2.3 From d78fd935865e3ebece9163a85b4b8043beef4eee Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Tue, 21 Sep 2010 17:00:44 -0700 Subject: fix timing issue on DAC outputs with rev 2. This puts the whole system on a 90 degree phase shift --- usrp2/top/u1e/u1e.ucf | 38 +++++++++++++++++++------------------- usrp2/top/u1e/u1e.v | 37 ++++++------------------------------- 2 files changed, 25 insertions(+), 50 deletions(-) diff --git a/usrp2/top/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf index 51968d24a..5581b1dbd 100644 --- a/usrp2/top/u1e/u1e.ucf +++ b/usrp2/top/u1e/u1e.ucf @@ -95,10 +95,10 @@ NET "db_sen_tx" LOC = "G18" ; #NET "aux_sdi_codec" LOC = "G3" ; #NET "aux_sdo_codec" LOC = "F3" ; #NET "aux_sclk_codec" LOC = "C1" ; -NET "sen_codec" LOC = "F5" ; -NET "mosi_codec" LOC = "F4" ; +NET "sen_codec" LOC = "F5" |IOSTANDARD = LVCMOS33; +NET "mosi_codec" LOC = "F4" |IOSTANDARD = LVCMOS33; NET "miso_codec" LOC = "H4" ; -NET "sclk_codec" LOC = "H3" ; +NET "sclk_codec" LOC = "H3" |IOSTANDARD = LVCMOS33; ### Clock Gen SPI NET "cgen_miso" LOC = "F22" ; @@ -184,22 +184,22 @@ NET "DA<2>" LOC = "P6" ; NET "DA<1>" LOC = "R1" ; NET "DA<0>" LOC = "R2" ; -NET "TX<13>" LOC = "T6" ; -NET "TX<12>" LOC = "U1" ; -NET "TX<11>" LOC = "T1" ; -NET "TX<10>" LOC = "R5" ; -NET "TX<9>" LOC = "V1" ; -NET "TX<8>" LOC = "U2" ; -NET "TX<7>" LOC = "T4" ; -NET "TX<6>" LOC = "R3" ; -NET "TX<5>" LOC = "W1" ; -NET "TX<4>" LOC = "Y1" ; -NET "TX<3>" LOC = "V3" ; -NET "TX<2>" LOC = "V4" ; -NET "TX<1>" LOC = "W2" ; -NET "TX<0>" LOC = "W3" ; -NET "TXSYNC" LOC = "U5" ; -NET "TXBLANK" LOC = "U4" ; +NET "TX<13>" LOC = "T6" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TX<12>" LOC = "U1" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TX<11>" LOC = "T1" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TX<10>" LOC = "R5" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TX<9>" LOC = "V1" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TX<8>" LOC = "U2" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TX<7>" LOC = "T4" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TX<6>" LOC = "R3" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TX<5>" LOC = "W1" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TX<4>" LOC = "Y1" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TX<3>" LOC = "V3" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TX<2>" LOC = "V4" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TX<1>" LOC = "W2" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TX<0>" LOC = "W3" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TXSYNC" LOC = "U5" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; +NET "TXBLANK" LOC = "U4" |IOSTANDARD = LVCMOS33 |DRIVE = 12 |SLEW = FAST ; NET "PPS_IN" LOC = "M5" ; diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index 7ddbfd537..ee087e59d 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -1,8 +1,6 @@ `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// -//`define DCM 1 - module u1e (input CLK_FPGA_P, input CLK_FPGA_N, // Diff output [3:0] debug_led, output [31:0] debug, output [1:0] debug_clk, @@ -41,11 +39,10 @@ module u1e IBUFGDS #(.IOSTANDARD("LVDS_33"), .DIFF_TERM("TRUE")) clk_fpga_pin (.O(clk_fpga_in),.I(CLK_FPGA_P),.IB(CLK_FPGA_N)); -`ifdef DCM - wire clk_2x, dcm_rst, dcm_locked; + wire clk_2x, dcm_rst, dcm_locked, clk_fb; DCM #(.CLK_FEEDBACK ( "1X" ), - .CLKDV_DIVIDE ( 2.0 ), - .CLKFX_DIVIDE ( 1 ), + .CLKDV_DIVIDE ( 2 ), + .CLKFX_DIVIDE ( 2 ), .CLKFX_MULTIPLY ( 2 ), .CLKIN_DIVIDE_BY_2 ( "FALSE" ), .CLKIN_PERIOD ( 15.625 ), @@ -57,15 +54,12 @@ module u1e .FACTORY_JF ( 16'h8080 ), .PHASE_SHIFT ( 0 ), .STARTUP_WAIT ( "FALSE" )) - clk_doubler (.CLKFB(clk_fpga), .CLKIN(clk_fpga_in), .RST(dcm_rst), + clk_doubler (.CLKFB(clk_fb), .CLKIN(clk_fpga_in), .RST(dcm_rst), .DSSEN(0), .PSCLK(0), .PSEN(0), .PSINCDEC(0), .PSDONE(), .CLKDV(), .CLKFX(), .CLKFX180(), - .CLK2X(clk_2x), .CLK2X180(), - .CLK0(clk_fpga), .CLK90(), .CLK180(), .CLK270(), + .CLK2X(), .CLK2X180(), + .CLK0(clk_fb), .CLK90(clk_fpga), .CLK180(), .CLK270(), .LOCKED(dcm_locked), .STATUS()); -`else // !`ifdef DCM - BUFG clk_fpga_BUFG (.I(clk_fpga_in), .O(clk_fpga)); -`endif // !`ifdef DCM // ///////////////////////////////////////////////////////////////////////// // SPI @@ -83,23 +77,6 @@ module u1e assign TXBLANK = 0; wire [13:0] tx_i, tx_q; -`ifdef DCM - reg [13:0] TX; - reg TXSYNC; - - always @(posedge clk_2x) - if(clk_fpga) - begin - TX <= tx_i; - TXSYNC <= 0; // Low indicates first data item - end - else - begin - TX <= tx_q; - TXSYNC <= 1; - end -`else // !`ifdef DCM - reg[13:0] delay_q; always @(posedge clk_fpga) delay_q <= tx_q; @@ -133,8 +110,6 @@ module u1e .R(1'b0), // 1-bit reset input .S(1'b0)); // 1-bit set input -`endif // !`ifdef DCM - // ///////////////////////////////////////////////////////////////////////// // Main U1E Core u1e_core u1e_core(.clk_fpga(clk_fpga), .rst_fpga(~debug_pb), -- cgit v1.2.3 From 27eb894c397f758528f59bc24f2ac645f0fccc4b Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 23 Sep 2010 11:40:19 -0700 Subject: watch the ethernet chip select on our debug bus --- usrp2/top/u1e/u1e.ucf | 2 +- usrp2/top/u1e/u1e.v | 7 ++++--- usrp2/top/u1e/u1e_core.v | 5 +++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/usrp2/top/u1e/u1e.ucf b/usrp2/top/u1e/u1e.ucf index 5581b1dbd..0c487a601 100644 --- a/usrp2/top/u1e/u1e.ucf +++ b/usrp2/top/u1e/u1e.ucf @@ -32,7 +32,7 @@ NET "EM_A<2>" LOC = "A7" ; NET "EM_A<1>" LOC = "C15" ; NET "EM_NCS6" LOC = "E17" ; -#NET "EM_NCS5" LOC = "E10" ; +NET "EM_NCS5" LOC = "E10" ; NET "EM_NCS4" LOC = "E6" ; #NET "EM_NCS1" LOC = "D18" ; #NET "EM_NCS0" LOC = "D17" ; diff --git a/usrp2/top/u1e/u1e.v b/usrp2/top/u1e/u1e.v index ee087e59d..445b14a03 100644 --- a/usrp2/top/u1e/u1e.v +++ b/usrp2/top/u1e/u1e.v @@ -8,7 +8,8 @@ module u1e // GPMC input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, - input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, + input EM_WAIT0, input EM_NCS4, input EM_NCS5, input EM_NCS6, + input EM_NWE, input EM_NOE, inout db_sda, inout db_scl, // I2C @@ -116,8 +117,8 @@ module u1e .debug_led(debug_led), .debug(debug), .debug_clk(debug_clk), .debug_txd(FPGA_TXD), .debug_rxd(FPGA_RXD), .EM_CLK(EM_CLK), .EM_D(EM_D), .EM_A(EM_A), .EM_NBE(EM_NBE), - .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS6(EM_NCS6), - .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), + .EM_WAIT0(EM_WAIT0), .EM_NCS4(EM_NCS4), .EM_NCS5(EM_NCS5), + .EM_NCS6(EM_NCS6), .EM_NWE(EM_NWE), .EM_NOE(EM_NOE), .db_sda(db_sda), .db_scl(db_scl), .sclk(sclk), .sen({cgen_sen_b,sen_codec,db_sen_tx,db_sen_rx}), .mosi(mosi), .miso(miso), .cgen_st_status(cgen_st_status), .cgen_st_ld(cgen_st_ld),.cgen_st_refmon(cgen_st_refmon), diff --git a/usrp2/top/u1e/u1e_core.v b/usrp2/top/u1e/u1e_core.v index 42333a722..619e44b8a 100644 --- a/usrp2/top/u1e/u1e_core.v +++ b/usrp2/top/u1e/u1e_core.v @@ -11,7 +11,8 @@ module u1e_core // GPMC input EM_CLK, inout [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, - input EM_WAIT0, input EM_NCS4, input EM_NCS6, input EM_NWE, input EM_NOE, + input EM_WAIT0, input EM_NCS4, input EM_NCS5, input EM_NCS6, + input EM_NWE, input EM_NOE, inout db_sda, inout db_scl, output sclk, output [7:0] sen, output mosi, input miso, @@ -439,7 +440,7 @@ module u1e_core assign debug_clk = { EM_CLK, clk_fpga }; - assign debug = { { rx_have_data, tx_have_space, EM_NCS6, EM_NCS4, EM_NWE, EM_NOE, rx_overrun, tx_underrun }, + assign debug = { { rx_have_data, tx_have_space, EM_NCS6, EM_NCS5, EM_NCS4, EM_NWE, EM_NOE, rx_overrun }, { tx_src_rdy, tx_src_rdy_int, tx_dst_rdy, tx_dst_rdy_int, rx_src_rdy, rx_src_rdy_int, rx_dst_rdy, rx_dst_rdy_int }, { EM_D } }; -- cgit v1.2.3 From 69992b4133145cd92629a0d15354b5d33f0c4973 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 23 Sep 2010 17:15:14 -0700 Subject: better debug pins --- usrp2/top/u1e_ethdebug/u1e.ucf | 8 +++++--- usrp2/top/u1e_ethdebug/u1e.v | 10 ++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/usrp2/top/u1e_ethdebug/u1e.ucf b/usrp2/top/u1e_ethdebug/u1e.ucf index 0d4384a2a..d6a2ea4ed 100644 --- a/usrp2/top/u1e_ethdebug/u1e.ucf +++ b/usrp2/top/u1e_ethdebug/u1e.ucf @@ -36,12 +36,14 @@ NET "EM_NCS4" LOC = "E6" ; NET "EM_CLK" LOC = "F11" ; NET "EM_WAIT0" LOC = "F14" ; -NET "EM_NBE<1>" LOC = "D14" ; -NET "EM_NBE<0>" LOC = "A13" ; +#NET "EM_NBE<1>" LOC = "D14" ; +#NET "EM_NBE<0>" LOC = "A13" ; NET "EM_NWE" LOC = "B13" ; NET "EM_NOE" LOC = "A14" ; NET "EM_NADV_ALE" LOC = "B15" ; -NET "EM_NWP" LOC = "F13" ; +#NET "EM_NWP" LOC = "F13" ; +NET "overo_gpio64" LOC = "A4" ; # nRESET +NET "overo_gpio176" LOC = "B4" ; # IRQ ## Debug pins NET "debug_led<3>" LOC = "Y15" ; diff --git a/usrp2/top/u1e_ethdebug/u1e.v b/usrp2/top/u1e_ethdebug/u1e.v index c4740b941..2a543a313 100644 --- a/usrp2/top/u1e_ethdebug/u1e.v +++ b/usrp2/top/u1e_ethdebug/u1e.v @@ -8,16 +8,18 @@ module u1e input debug_pb, // GPMC - input EM_CLK, input [15:0] EM_D, input [10:1] EM_A, input [1:0] EM_NBE, + input EM_CLK, input [15:0] EM_D, input [10:1] EM_A, input EM_WAIT0, input EM_NCS4, input EM_NCS5, input EM_NCS6, input EM_NWE, input EM_NOE, - input EM_NADV_ALE, input EM_NWP + input EM_NADV_ALE, + + input overo_gpio64, input overo_gpio176 ); assign debug_clk = {EM_CLK, EM_NADV_ALE}; - assign debug_led = {EM_NWP, EM_A[9], EM_A[8], debug_pb}; + assign debug_led = {1'b0, EM_A[9], EM_A[8], debug_pb}; - assign debug = { { EM_NBE[1:0], EM_WAIT0, EM_NCS4, EM_NCS5, EM_NCS6, EM_NWE, EM_NOE }, + assign debug = { {overo_gpio64, overo_gpio176, EM_WAIT0, EM_NCS4, EM_NCS5, EM_NCS6, EM_NWE, EM_NOE }, { EM_A[10], EM_A[7:1] }, { EM_D[15:8] }, { EM_D[7:0] } }; -- cgit v1.2.3 From f2f4840ff9e15ed21344a5a19d676d548b542e91 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 24 Sep 2010 11:07:14 -0700 Subject: usb: moved msvc stdint file and changed cmake conditional for msvc --- host/lib/transport/CMakeLists.txt | 6 +++--- host/lib/transport/include/stdint.h | 35 ----------------------------------- host/lib/transport/msvc/stdint.h | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 38 deletions(-) delete mode 100644 host/lib/transport/include/stdint.h create mode 100644 host/lib/transport/msvc/stdint.h diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index 92c9f3181..48b6e9677 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -33,9 +33,9 @@ IF(LIBUSB_FOUND) ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.hpp ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_device_handle.cpp ) - IF(WIN32) #include our custom stdint for libusb - INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/transport/include) - ENDIF(WIN32) + IF(MSVC) #include our custom stdint for libusb + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/transport/msvc) + ENDIF(MSVC) SET(HAVE_USB_SUPPORT TRUE) ENDIF(LIBUSB_FOUND) diff --git a/host/lib/transport/include/stdint.h b/host/lib/transport/include/stdint.h deleted file mode 100644 index b3eb61aae..000000000 --- a/host/lib/transport/include/stdint.h +++ /dev/null @@ -1,35 +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_LIBUHD_TRANSPORT_STDINT_H -#define INCLUDED_LIBUHD_TRANSPORT_STDINT_H - -#include - -//provide a stdint implementation for libusb - -typedef boost::uint64_t uint64_t; -typedef boost::uint32_t uint32_t; -typedef boost::uint16_t uint16_t; -typedef boost::uint8_t uint8_t; - -typedef boost::int64_t int64_t; -typedef boost::int32_t int32_t; -typedef boost::int16_t int16_t; -typedef boost::int8_t int8_t; - -#endif /* INCLUDED_LIBUHD_TRANSPORT_STDINT_H */ diff --git a/host/lib/transport/msvc/stdint.h b/host/lib/transport/msvc/stdint.h new file mode 100644 index 000000000..b3eb61aae --- /dev/null +++ b/host/lib/transport/msvc/stdint.h @@ -0,0 +1,35 @@ +// +// 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_STDINT_H +#define INCLUDED_LIBUHD_TRANSPORT_STDINT_H + +#include + +//provide a stdint implementation for libusb + +typedef boost::uint64_t uint64_t; +typedef boost::uint32_t uint32_t; +typedef boost::uint16_t uint16_t; +typedef boost::uint8_t uint8_t; + +typedef boost::int64_t int64_t; +typedef boost::int32_t int32_t; +typedef boost::int16_t int16_t; +typedef boost::int8_t int8_t; + +#endif /* INCLUDED_LIBUHD_TRANSPORT_STDINT_H */ -- cgit v1.2.3 From 1f77494788fa4fa8450aaf170055553bd0e5fe8e Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Fri, 24 Sep 2010 14:37:15 -0700 Subject: allow for CS to rise before, at the same time, or after OE --- usrp2/gpmc/fifo_to_gpmc_async.v | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/usrp2/gpmc/fifo_to_gpmc_async.v b/usrp2/gpmc/fifo_to_gpmc_async.v index 5ac8b19bd..cf8b6e861 100644 --- a/usrp2/gpmc/fifo_to_gpmc_async.v +++ b/usrp2/gpmc/fifo_to_gpmc_async.v @@ -11,23 +11,22 @@ module fifo_to_gpmc_async input [15:0] frame_len); // Synchronize the async control signals - reg [1:0] cs_del, oe_del; + reg [2:0] cs_del, oe_del; reg [15:0] counter; always @(posedge clk) if(reset) begin - cs_del <= 2'b11; - oe_del <= 2'b11; + cs_del <= 3'b11; + oe_del <= 3'b11; end else begin - cs_del <= { cs_del[0], EM_NCS }; - oe_del <= { oe_del[0], EM_NOE }; + cs_del <= { cs_del[1:0], EM_NCS }; + oe_del <= { oe_del[1:0], EM_NOE }; end - //wire do_read = (~cs_del[0] & (oe_del == 2'b10)); - wire do_read = (~cs_del[1] & (oe_del == 2'b01)); // change output on trailing edge + wire do_read = ( (~cs_del[1] | ~cs_del[2]) & (oe_del[1:0] == 2'b01)); // change output on trailing edge wire first_read = (counter == 0); wire last_read = ((counter+1) == frame_len); -- cgit v1.2.3 From 1dffd5bb5fe16cd35ba54e44e927888e0192e905 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 24 Sep 2010 18:14:32 -0700 Subject: usb: tweaks to usb code to cleanup properly and/or in error conditions --- host/lib/transport/libusb1_base.cpp | 17 +++++++---------- host/lib/transport/libusb1_control.cpp | 1 + host/lib/transport/libusb1_device_handle.cpp | 9 +++++---- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index 1f816c6e2..cd3e4adcf 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -30,9 +30,7 @@ using namespace uhd::transport; **********************************************************/ void libusb::init(libusb_context **ctx, int debug_level) { - if (libusb_init(ctx) < 0) - std::cerr << "error: libusb_init" << std::endl; - + UHD_ASSERT_THROW(libusb_init(ctx) == 0); libusb_set_debug(*ctx, debug_level); } @@ -48,14 +46,13 @@ libusb_device_handle *libusb::open_device(libusb_context *ctx, libusb_device *dev = libusb_dev_list[i]; if (compare_device(dev, handle)) { - libusb_open(dev, &dev_handle); - libusb_unref_device(dev); - break; + if (libusb_open(dev, &dev_handle) == 0) break; } - - libusb_unref_device(dev); } + libusb_free_device_list(libusb_dev_list, true); + if(dev_handle == NULL) + throw std::runtime_error("USB: cannot open device handle"); return dev_handle; } @@ -70,12 +67,12 @@ bool libusb::compare_device(libusb_device *dev, boost::uint16_t device_addr = handle->get_device_addr(); libusb_device_descriptor libusb_desc; - if (libusb_get_device_descriptor(dev, &libusb_desc) < 0) + if (libusb_get_device_descriptor(dev, &libusb_desc) != 0) return false; if (vendor_id != libusb_desc.idVendor) return false; if (product_id != libusb_desc.idProduct) - return false; + return false; if (serial != get_serial(dev)) return false; if (device_addr != libusb_get_device_address(dev)) diff --git a/host/lib/transport/libusb1_control.cpp b/host/lib/transport/libusb1_control.cpp index 3531128b2..be9b51111 100644 --- a/host/lib/transport/libusb1_control.cpp +++ b/host/lib/transport/libusb1_control.cpp @@ -46,6 +46,7 @@ private: libusb_control_impl::libusb_control_impl(usb_device_handle::sptr handle) { + _ctx = NULL; libusb::init(&_ctx, libusb_debug_level); // Find and open the libusb_device corresponding to the diff --git a/host/lib/transport/libusb1_device_handle.cpp b/host/lib/transport/libusb1_device_handle.cpp index 7efddd410..6bef37ed2 100644 --- a/host/lib/transport/libusb1_device_handle.cpp +++ b/host/lib/transport/libusb1_device_handle.cpp @@ -77,7 +77,7 @@ usb_device_handle::sptr make_usb_device_handle(libusb_device *dev) libusb_device_descriptor desc; if (libusb_get_device_descriptor(dev, &desc) < 0) { - UHD_ASSERT_THROW("USB: failed to get device descriptor"); + throw std::runtime_error("USB: failed to get device descriptor"); } std::string serial = libusb::get_serial(dev); @@ -104,14 +104,15 @@ std::vector usb_device_handle::get_device_list(boost::u size_t dev_size = libusb_get_device_list(ctx, &libusb_device_list); for (size_t i = 0; i < dev_size; i++) { libusb_device *dev = libusb_device_list[i]; - if(libusb_get_device_descriptor(dev, &desc) < 0) { - UHD_ASSERT_THROW("USB: failed to get device descriptor"); + if(libusb_get_device_descriptor(dev, &desc) != 0) { + continue; //just try the next device, do not throw } if(desc.idVendor == vid && desc.idProduct == pid) { - device_handle_list.push_back(make_usb_device_handle(dev)); + device_handle_list.push_back(make_usb_device_handle(dev)); } } + libusb_free_device_list(libusb_device_list, true); libusb_exit(ctx); return device_handle_list; } -- cgit v1.2.3 From dc8bcfde805228ed5d00334ce44c6c0684dcfe2c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 25 Sep 2010 21:07:15 -0700 Subject: usb: work on libusb code to use a single context across all calls libusb allocation stuff had been moved inside of smart pointer classes to handle automatic cleanup the public device handle implementation now holds an actual libusb device inside of it needs testing - all platforms --- host/include/uhd/transport/usb_device_handle.hpp | 6 - host/lib/transport/CMakeLists.txt | 1 - host/lib/transport/libusb1_base.cpp | 289 +++++++++++++++++------ host/lib/transport/libusb1_base.hpp | 162 ++++++++----- host/lib/transport/libusb1_control.cpp | 74 ++---- host/lib/transport/libusb1_device_handle.cpp | 118 --------- host/lib/transport/libusb1_zero_copy.cpp | 83 +++---- 7 files changed, 367 insertions(+), 366 deletions(-) delete mode 100644 host/lib/transport/libusb1_device_handle.cpp diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp index 735a3acbe..9bb7db9c4 100644 --- a/host/include/uhd/transport/usb_device_handle.hpp +++ b/host/include/uhd/transport/usb_device_handle.hpp @@ -60,12 +60,6 @@ public: */ virtual boost::uint16_t get_product_id() const = 0; - /*! - * Return the device's USB address - * \return a Product ID - */ - virtual boost::uint16_t get_device_addr() const = 0; - /*! * Return a vector of USB devices on this host * \return a vector of USB device handles that match vid and pid diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index 48b6e9677..61616d077 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -31,7 +31,6 @@ IF(LIBUSB_FOUND) ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_zero_copy.cpp ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.cpp ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.hpp - ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_device_handle.cpp ) IF(MSVC) #include our custom stdint for libusb INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/transport/msvc) diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index cd3e4adcf..5ff996642 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -17,107 +17,242 @@ #include "libusb1_base.hpp" #include +#include +#include +#include #include using namespace uhd::transport; -/********************************************************** - * Helper Methods - **********************************************************/ - -/********************************************************** - * libusb namespace - **********************************************************/ -void libusb::init(libusb_context **ctx, int debug_level) -{ - UHD_ASSERT_THROW(libusb_init(ctx) == 0); - libusb_set_debug(*ctx, debug_level); +/*********************************************************************** + * libusb session + **********************************************************************/ +class libusb_session_impl : public libusb::session{ +public: + libusb_session_impl(void){ + UHD_ASSERT_THROW(libusb_init(&_context) == 0); + libusb_set_debug(_context, debug_level); + } + + ~libusb_session_impl(void){ + libusb_exit(_context); + } + + libusb_context *get_context(void) const{ + return _context; + } + +private: + libusb_context *_context; +}; + +libusb::session::sptr libusb::session::get_global_session(void){ + static boost::weak_ptr global_session; + + //not expired -> get existing session + if (not global_session.expired()) return global_session.lock(); + + //create a new global session + sptr new_global_session(new libusb_session_impl()); + global_session = new_global_session; + return new_global_session; } -libusb_device_handle *libusb::open_device(libusb_context *ctx, - usb_device_handle::sptr handle) -{ - libusb_device_handle *dev_handle = NULL; - libusb_device **libusb_dev_list; - size_t dev_cnt = libusb_get_device_list(ctx, &libusb_dev_list); +/*********************************************************************** + * libusb device + **********************************************************************/ +class libusb_device_impl : public libusb::device{ +public: + libusb_device_impl(libusb_device *dev){ + _session = libusb::session::get_global_session(); + _dev = dev; + } - //find and open the USB device - for (size_t i = 0; i < dev_cnt; i++) { - libusb_device *dev = libusb_dev_list[i]; + ~libusb_device_impl(void){ + libusb_unref_device(this->get()); + } - if (compare_device(dev, handle)) { - if (libusb_open(dev, &dev_handle) == 0) break; - } + libusb_device *get(void) const{ + return _dev; } - libusb_free_device_list(libusb_dev_list, true); - if(dev_handle == NULL) - throw std::runtime_error("USB: cannot open device handle"); - return dev_handle; -} +private: + libusb::session::sptr _session; //always keep a reference to session + libusb_device *_dev; +}; + +/*********************************************************************** + * libusb device list + **********************************************************************/ +class libusb_device_list_impl : public libusb::device_list{ +public: + libusb_device_list_impl(void){ + libusb::session::sptr sess = libusb::session::get_global_session(); -//note: changed order of checks so it only tries to get_serial and get_device_address if vid and pid match -//doing this so it doesn't try to open the device if it's not ours -bool libusb::compare_device(libusb_device *dev, - usb_device_handle::sptr handle) -{ - std::string serial = handle->get_serial(); - boost::uint16_t vendor_id = handle->get_vendor_id(); - boost::uint16_t product_id = handle->get_product_id(); - boost::uint16_t device_addr = handle->get_device_addr(); - - libusb_device_descriptor libusb_desc; - if (libusb_get_device_descriptor(dev, &libusb_desc) != 0) - return false; - if (vendor_id != libusb_desc.idVendor) - return false; - if (product_id != libusb_desc.idProduct) - return false; - if (serial != get_serial(dev)) - return false; - if (device_addr != libusb_get_device_address(dev)) - return false; - - return true; + //allocate a new list of devices + libusb_device** dev_list; + ssize_t ret = libusb_get_device_list(sess->get_context(), &dev_list); + if (ret < 0) throw std::runtime_error("cannot enumerate usb devices"); + + //fill the vector of device references + for (size_t i = 0; i < size_t(ret); i++) _devs.push_back( + libusb::device::sptr(new libusb_device_impl(dev_list[i])) + ); + + //free the device list but dont unref (done in ~device) + libusb_free_device_list(dev_list, false/*dont unref*/); + } + + size_t size(void) const{ + return _devs.size(); + } + + libusb::device::sptr at(size_t i) const{ + return _devs.at(i); + } + +private: + std::vector _devs; +}; + +libusb::device_list::sptr libusb::device_list::make(void){ + return sptr(new libusb_device_list_impl()); } +/*********************************************************************** + * libusb device descriptor + **********************************************************************/ +class libusb_device_descriptor_impl : public libusb::device_descriptor{ +public: + libusb_device_descriptor_impl(libusb::device::sptr dev){ + _dev = dev; + UHD_ASSERT_THROW(libusb_get_device_descriptor(_dev->get(), &_desc) == 0); + } -bool libusb::open_interface(libusb_device_handle *dev_handle, - int interface) -{ - int ret = libusb_claim_interface(dev_handle, interface); - if (ret < 0) { - std::cerr << "error: libusb_claim_interface() " << ret << std::endl; - return false; + const libusb_device_descriptor &get(void) const{ + return _desc; } - else { - return true; + + std::string get_ascii_serial(void) const{ + if (this->get().iSerialNumber == 0) return ""; + + libusb::device_handle::sptr handle( + libusb::device_handle::get_cached_handle(_dev) + ); + + unsigned char buff[512]; + ssize_t ret = libusb_get_string_descriptor_ascii( + handle->get(), this->get().iSerialNumber, buff, sizeof(buff) + ); + if (ret < 0) return ""; //on error, just return empty string + + return std::string((char *)buff, ret); } + +private: + libusb::device::sptr _dev; //always keep a reference to device + libusb_device_descriptor _desc; +}; + +libusb::device_descriptor::sptr libusb::device_descriptor::make(device::sptr dev){ + return sptr(new libusb_device_descriptor_impl(dev)); } +/*********************************************************************** + * libusb device handle + **********************************************************************/ +class libusb_device_handle_impl : public libusb::device_handle{ +public: + libusb_device_handle_impl(libusb::device::sptr dev){ + _dev = dev; + UHD_ASSERT_THROW(libusb_open(_dev->get(), &_handle) == 0); + } + + ~libusb_device_handle_impl(void){ + //release all claimed interfaces + for (size_t i = 0; i < _claimed.size(); i++){ + libusb_release_interface(this->get(), _claimed[i]); + } + libusb_close(_handle); + } + + libusb_device_handle *get(void) const{ + return _handle; + } -std::string libusb::get_serial(libusb_device *dev) -{ - unsigned char buff[32]; + void claim_interface(int interface){ + UHD_ASSERT_THROW(libusb_claim_interface(this->get(), interface) == 0); + _claimed.push_back(interface); + } - libusb_device_descriptor desc; - if (libusb_get_device_descriptor(dev, &desc) < 0) - return ""; +private: + libusb::device::sptr _dev; //always keep a reference to device + libusb_device_handle *_handle; + std::vector _claimed; +}; - if (desc.iSerialNumber == 0) - return ""; +libusb::device_handle::sptr libusb::device_handle::get_cached_handle(device::sptr dev){ + static uhd::dict > handles; - //open the device because we have to - libusb_device_handle *dev_handle; - if (libusb_open(dev, &dev_handle) < 0) - return ""; + //not expired -> get existing session + if (handles.has_key(dev->get()) and not handles[dev->get()].expired()){ + return handles[dev->get()].lock(); + } - if (libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber, - buff, sizeof(buff)) < 0) { - return ""; + //create a new global session + sptr new_handle(new libusb_device_handle_impl(dev)); + handles[dev->get()] = new_handle; + return new_handle; +} + +/*********************************************************************** + * libusb special handle + **********************************************************************/ +class libusb_special_handle_impl : public libusb::special_handle{ +public: + libusb_special_handle_impl(libusb::device::sptr dev){ + _dev = dev; } - libusb_close(dev_handle); + libusb::device::sptr get_device(void) const{ + return _dev; + } + + std::string get_serial(void) const{ + return libusb::device_descriptor::make(this->get_device())->get_ascii_serial(); + } + + boost::uint16_t get_vendor_id(void) const{ + return libusb::device_descriptor::make(this->get_device())->get().idVendor; + } + + boost::uint16_t get_product_id(void) const{ + return libusb::device_descriptor::make(this->get_device())->get().idProduct; + } + +private: + libusb::device::sptr _dev; //always keep a reference to device +}; + +libusb::special_handle::sptr libusb::special_handle::make(device::sptr dev){ + return sptr(new libusb_special_handle_impl(dev)); +} + +/*********************************************************************** + * list device handles implementations + **********************************************************************/ +std::vector usb_device_handle::get_device_list( + boost::uint16_t vid, boost::uint16_t pid +){ + std::vector handles; + + libusb::device_list::sptr dev_list = libusb::device_list::make(); + for (size_t i = 0; i < dev_list->size(); i++){ + usb_device_handle::sptr handle = libusb::special_handle::make(dev_list->at(i)); + if (handle->get_vendor_id() == vid and handle->get_product_id() == pid){ + handles.push_back(handle); + } + } - return (char*) buff; + return handles; } diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp index 484bcf3d9..47d078cde 100644 --- a/host/lib/transport/libusb1_base.hpp +++ b/host/lib/transport/libusb1_base.hpp @@ -19,74 +19,122 @@ #define INCLUDED_LIBUHD_TRANSPORT_LIBUSB_HPP #include +#include +#include #include #include namespace uhd { namespace transport { namespace libusb { - /* - * Initialize libusb and set debug level - * Takes a pointer to context pointer because that's - * how libusb rolls. Debug levels. - * - * Level 0: no messages ever printed by the library (default) - * Level 1: error messages are printed to stderr - * Level 2: warning and error messages are printed to stderr - * Level 3: informational messages are printed to stdout, warning - * and error messages are printed to stderr - * - * \param ctx pointer to context pointer - * \param debug_level + + /*! + * This session class holds a global libusb context for this process. + * The get global session call will create a new context if none exists. + * When all references to session are destroyed, the context will be freed. */ - void init(libusb_context **ctx, int debug_level); - - /* - * Open the device specified by a generic handle - * Find the libusb_device cooresponding to the generic handle - * and open it for I/O, which returns a libusb_device_handle - * ready for an interface - * \param ctx the libusb context used for init - * \return a libusb_device_handle ready for action + class session : boost::noncopyable { + public: + typedef boost::shared_ptr sptr; + + /*! + * Level 0: no messages ever printed by the library (default) + * Level 1: error messages are printed to stderr + * Level 2: warning and error messages are printed to stderr + * Level 3: informational messages are printed to stdout, warning + * and error messages are printed to stderr + */ + static const int debug_level = 0; + + //! get a shared pointer to the global session + static sptr get_global_session(void); + + //! get the underlying libusb context pointer + virtual libusb_context *get_context(void) const = 0; + }; + + /*! + * Holds a device pointer with a reference to the session. */ - libusb_device_handle *open_device(libusb_context *ctx, - usb_device_handle::sptr handle); - - /* - * Compare a libusb device with a generic handle - * Check the descriptors and open the device to check the - * serial number string. Compare values against the given - * handle. The libusb context is already implied in the - * libusb_device. - * \param dev a libusb_device pointer - * \param handle a generic handle specifier - * \return true if handle and device match, false otherwise + class device : boost::noncopyable { + public: + typedef boost::shared_ptr sptr; + + //! get the underlying device pointer + virtual libusb_device *get(void) const = 0; + }; + + /*! + * This device list class holds a device list that will be + * automatically freed when the last reference is destroyed. */ - bool compare_device(libusb_device *dev, usb_device_handle::sptr handle); - - /* - * Open an interface to the device - * This is a logical operation for operating system housekeeping as - * nothing is sent over the bus. The interface much correspond - * to the USB device descriptors. - * \param dev_handle libusb handle to an opened device - * \param interface integer of the interface to use - * \return true on success, false on error + class device_list : boost::noncopyable { + public: + typedef boost::shared_ptr sptr; + + //! make a new device list + static sptr make(void); + + //! the number of devices in this list + virtual size_t size() const = 0; + + //! get the device pointer at a particular index + virtual device::sptr at(size_t index) const = 0; + }; + + /*! + * Holds a device descriptor and a reference to the device. */ - bool open_interface(libusb_device_handle *dev_handle, int interface); - - /* - * Get serial number - * The standard USB device descriptor contains an index to an - * actual serial number string descriptor. The index is readily - * readble, but the string descriptor requires probing the device. - * Because this call attempts to open the device, it may not - * succeed because not all USB devices are readily opened. - * The default language is used for the request (English). - * \param dev a libusb_device pointer - * \return string serial number or 0 on error or unavailablity + class device_descriptor : boost::noncopyable { + public: + typedef boost::shared_ptr sptr; + + //! make a new descriptor from a device reference + static sptr make(device::sptr); + + //! get the underlying device descriptor + virtual const libusb_device_descriptor &get(void) const = 0; + + virtual std::string get_ascii_serial(void) const = 0; + }; + + /*! + * Holds a device handle and a reference to the device. */ - std::string get_serial(libusb_device *dev); + class device_handle : boost::noncopyable { + public: + typedef boost::shared_ptr sptr; + + //! get a cached handle or make a new one given the device + static sptr get_cached_handle(device::sptr); + + //! get the underlying device handle + virtual libusb_device_handle *get(void) const = 0; + + /*! + * Open USB interfaces for control using magic value + * IN interface: 2 + * OUT interface: 1 + * Control interface: 0 + */ + virtual void claim_interface(int) = 0; + }; + + /*! + * The special handle is our internal implementation of the + * usb device handle which is used publicly to identify a device. + */ + class special_handle : public usb_device_handle { + public: + typedef boost::shared_ptr sptr; + + //! make a new special handle from device + static sptr make(device::sptr); + + //! get the underlying device reference + virtual device::sptr get_device(void) const = 0; + }; + } }} //namespace diff --git a/host/lib/transport/libusb1_control.cpp b/host/lib/transport/libusb1_control.cpp index be9b51111..c989a788c 100644 --- a/host/lib/transport/libusb1_control.cpp +++ b/host/lib/transport/libusb1_control.cpp @@ -20,7 +20,6 @@ using namespace uhd::transport; -const int libusb_debug_level = 0; const int libusb_timeout = 0; /*********************************************************************** @@ -28,69 +27,38 @@ const int libusb_timeout = 0; **********************************************************************/ class libusb_control_impl : public usb_control { public: - libusb_control_impl(usb_device_handle::sptr handle); - ~libusb_control_impl(); + libusb_control_impl(libusb::device_handle::sptr handle): + _handle(handle) + { + _handle->claim_interface(0 /* control interface */); + } size_t submit(boost::uint8_t request_type, boost::uint8_t request, boost::uint16_t value, boost::uint16_t index, unsigned char *buff, - boost::uint16_t length); + boost::uint16_t length + ){ + return libusb_control_transfer(_handle->get(), + request_type, + request, + value, + index, + buff, + length, + libusb_timeout); + } private: - libusb_context *_ctx; - libusb_device_handle *_dev_handle; + libusb::device_handle::sptr _handle; }; - -libusb_control_impl::libusb_control_impl(usb_device_handle::sptr handle) -{ - _ctx = NULL; - libusb::init(&_ctx, libusb_debug_level); - - // Find and open the libusb_device corresponding to the - // given handle and return the libusb_device_handle - // that can be used for I/O purposes. - _dev_handle = libusb::open_device(_ctx, handle); - - // Open USB interfaces for control using magic value - // IN interface: 2 - // OUT interface: 1 - // Control interface: 0 - libusb::open_interface(_dev_handle, 0); -} - - -libusb_control_impl::~libusb_control_impl() -{ - libusb_close(_dev_handle); - libusb_exit(_ctx); -} - - -size_t libusb_control_impl::submit(boost::uint8_t request_type, - boost::uint8_t request, - boost::uint16_t value, - boost::uint16_t index, - unsigned char *buff, - boost::uint16_t length) -{ - return libusb_control_transfer(_dev_handle, - request_type, - request, - value, - index, - buff, - length, - libusb_timeout); -} - - /*********************************************************************** * USB control public make functions **********************************************************************/ -usb_control::sptr usb_control::make(usb_device_handle::sptr handle) -{ - return sptr(new libusb_control_impl(handle)); +usb_control::sptr usb_control::make(usb_device_handle::sptr handle){ + return sptr(new libusb_control_impl(libusb::device_handle::get_cached_handle( + boost::static_pointer_cast(handle)->get_device() + ))); } diff --git a/host/lib/transport/libusb1_device_handle.cpp b/host/lib/transport/libusb1_device_handle.cpp deleted file mode 100644 index 6bef37ed2..000000000 --- a/host/lib/transport/libusb1_device_handle.cpp +++ /dev/null @@ -1,118 +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 "libusb1_base.hpp" -#include -#include - -using namespace uhd::transport; - -const int libusb_debug_level = 0; - -/**************************************************************** - * libusb USB device handle implementation class - ***************************************************************/ -class libusb1_device_handle_impl : public usb_device_handle { -public: - libusb1_device_handle_impl(std::string serial, - boost::uint16_t product_id, - boost::uint16_t vendor_id, - boost::uint16_t device_addr) - : _serial(serial), _product_id(product_id), - _vendor_id(vendor_id), _device_addr(device_addr) - { - /* NOP */ - } - - ~libusb1_device_handle_impl() - { - /* NOP */ - } - - std::string get_serial() const - { - return _serial; - } - - boost::uint16_t get_vendor_id() const - { - return _vendor_id; - } - - - boost::uint16_t get_product_id() const - { - return _product_id; - } - - boost::uint16_t get_device_addr() const - { - return _device_addr; - } - -private: - std::string _serial; - boost::uint16_t _product_id; - boost::uint16_t _vendor_id; - boost::uint16_t _device_addr; -}; - - -usb_device_handle::sptr make_usb_device_handle(libusb_device *dev) -{ - libusb_device_descriptor desc; - - if (libusb_get_device_descriptor(dev, &desc) < 0) { - throw std::runtime_error("USB: failed to get device descriptor"); - } - - std::string serial = libusb::get_serial(dev); - boost::uint16_t product_id = desc.idProduct; - boost::uint16_t vendor_id = desc.idVendor; - boost::uint16_t device_addr = libusb_get_device_address(dev); - - return usb_device_handle::sptr(new libusb1_device_handle_impl( - serial, - product_id, - vendor_id, - device_addr)); -} - -std::vector usb_device_handle::get_device_list(boost::uint16_t vid, boost::uint16_t pid) -{ - libusb_context *ctx = NULL; - libusb_device** libusb_device_list; - std::vector device_handle_list; - libusb_device_descriptor desc; - - libusb::init(&ctx, libusb_debug_level); - - size_t dev_size = libusb_get_device_list(ctx, &libusb_device_list); - for (size_t i = 0; i < dev_size; i++) { - libusb_device *dev = libusb_device_list[i]; - if(libusb_get_device_descriptor(dev, &desc) != 0) { - continue; //just try the next device, do not throw - } - if(desc.idVendor == vid && desc.idProduct == pid) { - device_handle_list.push_back(make_usb_device_handle(dev)); - } - } - - libusb_free_device_list(libusb_device_list, true); - libusb_exit(ctx); - return device_handle_list; -} diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index b3a160462..41cd4b3fc 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -24,7 +24,6 @@ using namespace uhd::transport; -const int libusb_debug_level = 0; const int libusb_timeout = 0; /*********************************************************************** @@ -57,8 +56,8 @@ void pp_transfer(libusb_transfer *lut) **********************************************************************/ class usb_endpoint { private: - libusb_device_handle *_dev_handle; - libusb_context *_ctx; + libusb::device_handle::sptr _handle; + libusb::session::sptr _session; int _endpoint; bool _input; @@ -90,9 +89,8 @@ private: void print_transfer_status(libusb_transfer *lut); public: - usb_endpoint(libusb_device_handle *dev_handle, - libusb_context *ctx, int endpoint, bool input, - size_t transfer_size, size_t num_transfers); + usb_endpoint(libusb::device_handle::sptr handle, libusb::session::sptr sess, + int endpoint, bool input, size_t transfer_size, size_t num_transfers); ~usb_endpoint(); @@ -143,11 +141,11 @@ void usb_endpoint::callback_handle_transfer(libusb_transfer *lut) * submit the transfers so that they're ready to return when * data is available. */ -usb_endpoint::usb_endpoint(libusb_device_handle *dev_handle, - libusb_context *ctx, int endpoint, bool input, - size_t transfer_size, size_t num_transfers) - : _dev_handle(dev_handle), - _ctx(ctx), _endpoint(endpoint), _input(input), +usb_endpoint::usb_endpoint( + libusb::device_handle::sptr handle, libusb::session::sptr sess, + int endpoint, bool input, size_t transfer_size, size_t num_transfers) + : _handle(handle), _session(sess), + _endpoint(endpoint), _input(input), _transfer_size(transfer_size), _num_transfers(num_transfers) { unsigned int i; @@ -203,7 +201,7 @@ libusb_transfer *usb_endpoint::allocate_transfer(int buff_len) unsigned int endpoint = ((_endpoint & 0x7f) | (_input ? 0x80 : 0)); libusb_fill_bulk_transfer(lut, // transfer - _dev_handle, // dev_handle + _handle->get(), // dev_handle endpoint, // endpoint buff, // buffer buff_len, // length @@ -356,7 +354,7 @@ bool usb_endpoint::reap_pending_list() { int retval; - if ((retval = libusb_handle_events(_ctx)) < 0) { + if ((retval = libusb_handle_events(_session->get_context())) < 0) { std::cerr << "error: libusb_handle_events: " << retval << std::endl; return false; } @@ -383,7 +381,7 @@ bool usb_endpoint::reap_pending_list_timeout() size_t pending_list_size = _pending_list.size(); - if ((retval = libusb_handle_events_timeout(_ctx, &tv)) < 0) { + if ((retval = libusb_handle_events_timeout(_session->get_context(), &tv)) < 0) { std::cerr << "error: libusb_handle_events: " << retval << std::endl; return false; } @@ -613,11 +611,8 @@ private: usb_endpoint *_rx_ep; usb_endpoint *_tx_ep; - // Maintain libusb values - libusb_context *_rx_ctx; - libusb_context *_tx_ctx; - libusb_device_handle *_rx_dev_handle; - libusb_device_handle *_tx_dev_handle; + libusb::device_handle::sptr _handle; + libusb::session::sptr _session; size_t _recv_buff_size; size_t _send_buff_size; @@ -626,7 +621,7 @@ private: public: typedef boost::shared_ptr sptr; - libusb_zero_copy_impl(usb_device_handle::sptr handle, + libusb_zero_copy_impl(libusb::device_handle::sptr handle, unsigned int rx_endpoint, unsigned int tx_endpoint, size_t recv_buff_size, @@ -646,44 +641,27 @@ public: * Initializes libusb, opens devices, and sets up interfaces for I/O. * Finally, creates endpoints for asynchronous I/O. */ -libusb_zero_copy_impl::libusb_zero_copy_impl(usb_device_handle::sptr handle, +libusb_zero_copy_impl::libusb_zero_copy_impl(libusb::device_handle::sptr handle, unsigned int rx_endpoint, unsigned int tx_endpoint, size_t buff_size, size_t block_size) - : _rx_ctx(NULL), _tx_ctx(NULL), _rx_dev_handle(NULL), _tx_dev_handle(NULL), + : _handle(handle), _session(libusb::session::get_global_session()), _recv_buff_size(block_size), _send_buff_size(block_size), _num_frames(buff_size / block_size) { - // Initialize libusb with separate contexts to allow - // thread safe operation of transmit and receive - libusb::init(&_rx_ctx, libusb_debug_level); - libusb::init(&_tx_ctx, libusb_debug_level); - - UHD_ASSERT_THROW((_rx_ctx != NULL) && (_tx_ctx != NULL)); - - // Find and open the libusb_device corresponding to the - // given handle and return the libusb_device_handle - // that can be used for I/O purposes. - _rx_dev_handle = libusb::open_device(_rx_ctx, handle); - _tx_dev_handle = libusb::open_device(_tx_ctx, handle); - - // Open USB interfaces for tx/rx using magic values. - // IN interface: 2 - // OUT interface: 1 - // Control interface: 0 - libusb::open_interface(_rx_dev_handle, 2); - libusb::open_interface(_tx_dev_handle, 1); - - _rx_ep = new usb_endpoint(_rx_dev_handle, // libusb device_handle - _rx_ctx, // libusb context + _handle->claim_interface(2 /*in interface*/); + _handle->claim_interface(1 /*out interface*/); + + _rx_ep = new usb_endpoint(_handle, // libusb device_handle + _session, // libusb session w/ context rx_endpoint, // USB endpoint number true, // IN endpoint _recv_buff_size, // buffer size per transfer _num_frames); // number of libusb transfers - _tx_ep = new usb_endpoint(_tx_dev_handle, // libusb device_handle - _tx_ctx, // libusb context + _tx_ep = new usb_endpoint(_handle, // libusb device_handle + _session, // libusb session w/ context tx_endpoint, // USB endpoint number false, // OUT endpoint _send_buff_size, // buffer size per transfer @@ -694,13 +672,7 @@ libusb_zero_copy_impl::libusb_zero_copy_impl(usb_device_handle::sptr handle, libusb_zero_copy_impl::~libusb_zero_copy_impl() { delete _rx_ep; - delete _tx_ep; - - libusb_close(_rx_dev_handle); - libusb_close(_tx_dev_handle); - - libusb_exit(_rx_ctx); - libusb_exit(_tx_ctx); + delete _tx_ep; } @@ -755,7 +727,10 @@ usb_zero_copy::sptr usb_zero_copy::make(usb_device_handle::sptr handle, size_t block_size) { - return sptr(new libusb_zero_copy_impl(handle, + libusb::device_handle::sptr dev_handle(libusb::device_handle::get_cached_handle( + boost::static_pointer_cast(handle)->get_device() + )); + return sptr(new libusb_zero_copy_impl(dev_handle, rx_endpoint, tx_endpoint, buff_size, -- cgit v1.2.3 From 0816925695aa69a1ae344863fef47d239b3ec8af Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 26 Sep 2010 20:23:23 -0700 Subject: usb: zero copy work, multiple endpoints with single context, async io Heavy work on the zero copy interface and endpoint wrappers to properly use the async io. The global libusb session starts a thread to run the event handler, the async callbacks push completed transfers onto a thread-safe bounded buffer. The managed buffer creation routines use the bounded buffer to efficiently pop off completed transfers. works on linux, throws a weird exception on cleanup --- host/lib/transport/libusb1_base.cpp | 16 ++ host/lib/transport/libusb1_zero_copy.cpp | 474 ++++++++----------------------- 2 files changed, 134 insertions(+), 356 deletions(-) diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index 5ff996642..26e864459 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include using namespace uhd::transport; @@ -32,9 +33,12 @@ public: libusb_session_impl(void){ UHD_ASSERT_THROW(libusb_init(&_context) == 0); libusb_set_debug(_context, debug_level); + _thread_group.create_thread(boost::bind(&libusb_session_impl::run_event_loop, this)); } ~libusb_session_impl(void){ + _running = false; + _thread_group.join_all(); libusb_exit(_context); } @@ -44,6 +48,18 @@ public: private: libusb_context *_context; + boost::thread_group _thread_group; + bool _running; + + void run_event_loop(void){ + _running = true; + timeval tv; + while(_running){ + tv.tv_sec = 0; + tv.tv_usec = 100000; //100ms + libusb_handle_events_timeout(this->get_context(), &tv); + } + } }; libusb::session::sptr libusb::session::get_global_session(void){ diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index 41cd4b3fc..e84793e88 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -17,8 +17,11 @@ #include "libusb1_base.hpp" #include +#include #include -#include +#include +#include +#include #include #include @@ -55,52 +58,57 @@ void pp_transfer(libusb_transfer *lut) * interface provided by the kernel. **********************************************************************/ class usb_endpoint { +public: + typedef boost::shared_ptr sptr; + + usb_endpoint( + libusb::device_handle::sptr handle, + int endpoint, + bool input, + size_t transfer_size, + size_t num_transfers + ); + + ~usb_endpoint(void); + + // Exposed interface for submitting / retrieving transfer buffers + + //! Submit a new transfer that was presumably just filled or emptied. + void submit(libusb_transfer *lut); + + /*! + * Get an available transfer: + * For inputs, this is a just filled transfer. + * For outputs, this is a just emptied transfer. + * \param timeout_ms the timeout to wait for a lut + * \return the transfer pointer or NULL if timeout + */ + libusb_transfer *get_lut_with_wait(size_t timeout_ms = 100); + + //Callback use only + void callback_handle_transfer(libusb_transfer *lut); + private: libusb::device_handle::sptr _handle; - libusb::session::sptr _session; int _endpoint; bool _input; size_t _transfer_size; size_t _num_transfers; - // Transfer state lists (transfers are free, pending, or completed) - std::list _free_list; - std::list _pending_list; - std::list _completed_list; + //! hold a bounded buffer of completed transfers + typedef bounded_buffer lut_buff_type; + lut_buff_type::sptr _completed_list; + + //! a list of all transfer structs we allocated + std::vector _all_luts; + + //! a list of shared arrays for the transfer buffers + std::vector > _buffers; // Calls for processing asynchronous I/O libusb_transfer *allocate_transfer(int buff_len); - bool cancel(libusb_transfer *lut); - bool cancel_all(); - bool reap_pending_list(); - bool reap_pending_list_timeout(); - bool reap_completed_list(); - - // Transfer state manipulators - void free_list_add(libusb_transfer *lut); - void pending_list_add(libusb_transfer *lut); - void completed_list_add(libusb_transfer *lut); - libusb_transfer *free_list_get(); - libusb_transfer *completed_list_get(); - bool pending_list_remove(libusb_transfer *lut); - - // Debug use void print_transfer_status(libusb_transfer *lut); - -public: - usb_endpoint(libusb::device_handle::sptr handle, libusb::session::sptr sess, - int endpoint, bool input, size_t transfer_size, size_t num_transfers); - - ~usb_endpoint(); - - // Exposed interface for submitting / retrieving transfer buffers - bool submit(libusb_transfer *lut); - libusb_transfer *get_completed_transfer(); - libusb_transfer *get_free_transfer(); - - //Callback use only - void callback_handle_transfer(libusb_transfer *lut); }; @@ -113,9 +121,8 @@ public: * it from the pending to completed status list. * \param lut pointer to libusb_transfer */ -static void callback(libusb_transfer *lut) -{ - usb_endpoint *endpoint = (usb_endpoint *) lut->user_data; +static void callback(libusb_transfer *lut){ + usb_endpoint *endpoint = (usb_endpoint *) lut->user_data; endpoint->callback_handle_transfer(lut); } @@ -124,14 +131,8 @@ static void callback(libusb_transfer *lut) * Accessor call to allow list access from callback space * \param pointer to libusb_transfer */ -void usb_endpoint::callback_handle_transfer(libusb_transfer *lut) -{ - if (!pending_list_remove(lut)) { - std::cerr << "USB: pending remove failed" << std::endl; - return; - } - - completed_list_add(lut); +void usb_endpoint::callback_handle_transfer(libusb_transfer *lut){ + _completed_list->push_with_wait(lut); } @@ -142,18 +143,27 @@ void usb_endpoint::callback_handle_transfer(libusb_transfer *lut) * data is available. */ usb_endpoint::usb_endpoint( - libusb::device_handle::sptr handle, libusb::session::sptr sess, - int endpoint, bool input, size_t transfer_size, size_t num_transfers) - : _handle(handle), _session(sess), - _endpoint(endpoint), _input(input), - _transfer_size(transfer_size), _num_transfers(num_transfers) + libusb::device_handle::sptr handle, + int endpoint, + bool input, + size_t transfer_size, + size_t num_transfers +): + _handle(handle), + _endpoint(endpoint), + _input(input), + _transfer_size(transfer_size), + _num_transfers(num_transfers) { - unsigned int i; - for (i = 0; i < _num_transfers; i++) { - free_list_add(allocate_transfer(_transfer_size)); + _completed_list = lut_buff_type::make(num_transfers); - if (_input) - submit(free_list_get()); + for (size_t i = 0; i < _num_transfers; i++){ + _all_luts.push_back(allocate_transfer(_transfer_size)); + + //input luts are immediately submitted to be filled + //output luts go into the completed list as free buffers + if (_input) this->submit(_all_luts.back()); + else _completed_list->push_with_wait(_all_luts.back()); } } @@ -165,22 +175,21 @@ usb_endpoint::usb_endpoint( * the transfers. Libusb will deallocate the data buffer held by * each transfer. */ -usb_endpoint::~usb_endpoint() -{ - cancel_all(); - - while (!_pending_list.empty()) { - if (!reap_pending_list()) - std::cerr << "error: destructor failed to reap" << std::endl; +usb_endpoint::~usb_endpoint(void){ + //cancel all transfers + BOOST_FOREACH(libusb_transfer *lut, _all_luts){ + libusb_cancel_transfer(lut); } - while (!_completed_list.empty()) { - if (!reap_completed_list()) - std::cerr << "error: destructor failed to reap" << std::endl; - } + //collect canceled transfers (drain the queue) + libusb_transfer *lut; + while(_completed_list->pop_with_timed_wait( + lut, boost::posix_time::milliseconds(100) + )); - while (!_free_list.empty()) { - libusb_free_transfer(free_list_get()); + //free all transfers + BOOST_FOREACH(libusb_transfer *lut, _all_luts){ + libusb_free_transfer(lut); } } @@ -192,20 +201,21 @@ usb_endpoint::~usb_endpoint() * \param buff_len size of the individual buffer held by each transfer * \return pointer to an allocated libusb_transfer */ -libusb_transfer *usb_endpoint::allocate_transfer(int buff_len) -{ +libusb_transfer *usb_endpoint::allocate_transfer(int buff_len){ libusb_transfer *lut = libusb_alloc_transfer(0); - unsigned char *buff = new unsigned char[buff_len]; + boost::shared_array buff(new boost::uint8_t[buff_len]); + _buffers.push_back(buff); //store a reference to this shared array unsigned int endpoint = ((_endpoint & 0x7f) | (_input ? 0x80 : 0)); + libusb_transfer_cb_fn lut_callback = libusb_transfer_cb_fn(&callback); libusb_fill_bulk_transfer(lut, // transfer _handle->get(), // dev_handle endpoint, // endpoint - buff, // buffer + buff.get(), // buffer buff_len, // length - libusb_transfer_cb_fn(callback), // callback + lut_callback, // callback this, // user_data 0); // timeout return lut; @@ -218,95 +228,15 @@ libusb_transfer *usb_endpoint::allocate_transfer(int buff_len) * \param lut pointer to libusb_transfer * \return true on success or false on error */ -bool usb_endpoint::submit(libusb_transfer *lut) -{ - int retval; - if ((retval = libusb_submit_transfer(lut)) < 0) { - std::cerr << "error: libusb_submit_transfer: " << retval << std::endl; - return false; - } - - pending_list_add(lut); - return true; -} - - -/* - * Cancel a pending transfer - * Search the pending list for the transfer and cancel if found. - * \param lut pointer to libusb_transfer to cancel - * \return true on success or false if transfer is not found - * - * Note: success only indicates submission of cancelation request. - * Sucessful cancelation is not known until the callback occurs. - */ -bool usb_endpoint::cancel(libusb_transfer *lut) -{ - std::list::iterator iter; - for (iter = _pending_list.begin(); iter != _pending_list.end(); iter++) { - if (*iter == lut) { - libusb_cancel_transfer(lut); - return true; - } - } - return false; -} - - -/* - * Cancel all pending transfers - * \return bool true if cancelation request is submitted - * - * Note: success only indicates submission of cancelation request. - * Sucessful cancelation is not known until the callback occurs. - */ -bool usb_endpoint::cancel_all() -{ - std::list::iterator iter; - - for (iter = _pending_list.begin(); iter != _pending_list.end(); iter++) { - if (libusb_cancel_transfer(*iter) < 0) { - std::cerr << "error: libusb_cancal_transfer() failed" << std::endl; - return false; - } - } - - return true; -} - - -/* - * Reap completed transfers - * return true if at least one transfer was reaped, false otherwise. - * Check completed transfers for errors and mark as free. This is a - * blocking call. - * \return bool true if a libusb transfer is reaped, false otherwise - */ -bool usb_endpoint::reap_completed_list() -{ - libusb_transfer *lut; - - if (_completed_list.empty()) { - if (!reap_pending_list_timeout()) - return false; - } - - while (!_completed_list.empty()) { - lut = completed_list_get(); - print_transfer_status(lut); - free_list_add(lut); - } - - return true; +void usb_endpoint::submit(libusb_transfer *lut){ + UHD_ASSERT_THROW(libusb_submit_transfer(lut) == 0); } - /* * Print status errors of a completed transfer * \param lut pointer to an libusb_transfer */ -void usb_endpoint::print_transfer_status(libusb_transfer *lut) -{ +void usb_endpoint::print_transfer_status(libusb_transfer *lut){ switch (lut->status) { case LIBUSB_TRANSFER_COMPLETED: if (lut->actual_length < lut->length) { @@ -342,166 +272,14 @@ void usb_endpoint::print_transfer_status(libusb_transfer *lut) } } - -/* - * Reap pending transfers without timeout - * This is a blocking call. Reaping submitted transfers is - * handled by libusb and the assigned callback function. - * Block until at least one transfer is reaped. - * \return true true if a transfer was reaped or false otherwise - */ -bool usb_endpoint::reap_pending_list() -{ - int retval; - - if ((retval = libusb_handle_events(_session->get_context())) < 0) { - std::cerr << "error: libusb_handle_events: " << retval << std::endl; - return false; - } - - return true; -} - - -/* - * Reap pending transfers with timeout - * This call blocks until a transfer is reaped or timeout. - * Reaping submitted transfers is handled by libusb and the - * assigned callback function. Block until at least one - * transfer is reaped or timeout occurs. - * \return true if a transfer was reaped or false otherwise - */ -bool usb_endpoint::reap_pending_list_timeout() -{ - int retval; - timeval tv; - - tv.tv_sec = 0; - tv.tv_usec = 100000; //100ms - - size_t pending_list_size = _pending_list.size(); - - if ((retval = libusb_handle_events_timeout(_session->get_context(), &tv)) < 0) { - std::cerr << "error: libusb_handle_events: " << retval << std::endl; - return false; - } - - if (_pending_list.size() < pending_list_size) { - return true; - } - else { - return false; - } -} - - -/* - * Get a free transfer - * The transfer has an empty data bufer for OUT requests - * \return pointer to a libusb_transfer - */ -libusb_transfer *usb_endpoint::get_free_transfer() -{ - if (_free_list.empty()) { - if (!reap_completed_list()) - return NULL; - } - - return free_list_get(); -} - - -/* - * Get a completed transfer - * The transfer has a full data buffer for IN requests - * \return pointer to libusb_transfer - */ -libusb_transfer *usb_endpoint::get_completed_transfer() -{ - if (_completed_list.empty()) { - if (!reap_pending_list_timeout()) - return NULL; - } - - return completed_list_get(); -} - -/* - * List operations - */ -void usb_endpoint::free_list_add(libusb_transfer *lut) -{ - _free_list.push_back(lut); -} - -void usb_endpoint::pending_list_add(libusb_transfer *lut) -{ - _pending_list.push_back(lut); -} - -void usb_endpoint::completed_list_add(libusb_transfer *lut) -{ - _completed_list.push_back(lut); -} - - -/* - * Free and completed lists don't have ordered content - * Pop transfers from the front as needed - */ -libusb_transfer *usb_endpoint::free_list_get() -{ - libusb_transfer *lut; - - if (_free_list.size() == 0) { - return NULL; - } - else { - lut = _free_list.front(); - _free_list.pop_front(); - return lut; - } -} - - -/* - * Free and completed lists don't have ordered content - * Pop transfers from the front as needed - */ -libusb_transfer *usb_endpoint::completed_list_get() -{ +libusb_transfer *usb_endpoint::get_lut_with_wait(size_t timeout_ms){ libusb_transfer *lut; - - if (_completed_list.empty()) { - return NULL; - } - else { - lut = _completed_list.front(); - _completed_list.pop_front(); - return lut; - } + if (_completed_list->pop_with_timed_wait( + lut, boost::posix_time::milliseconds(timeout_ms) + )) return lut; + return NULL; } - -/* - * Search and remove transfer from pending list - * Assuming that the callbacks occur in order, the front element - * should yield the correct transfer. If not, then something else - * is going on. If no transfers match, then something went wrong. - */ -bool usb_endpoint::pending_list_remove(libusb_transfer *lut) -{ - std::list::iterator iter; - for (iter = _pending_list.begin(); iter != _pending_list.end(); iter++) { - if (*iter == lut) { - _pending_list.erase(iter); - return true; - } - } - return false; -} - - /*********************************************************************** * Managed buffers **********************************************************************/ @@ -515,17 +293,15 @@ bool usb_endpoint::pending_list_remove(libusb_transfer *lut) class libusb_managed_recv_buffer_impl : public managed_recv_buffer { public: libusb_managed_recv_buffer_impl(libusb_transfer *lut, - usb_endpoint *endpoint) + usb_endpoint::sptr endpoint) : _buff(lut->buffer, lut->length) { _lut = lut; _endpoint = endpoint; } - ~libusb_managed_recv_buffer_impl() - { - if (!_endpoint->submit(_lut)) - std::cerr << "USB: failed to submit IN transfer" << std::endl; + ~libusb_managed_recv_buffer_impl(void){ + _endpoint->submit(_lut); } private: @@ -535,7 +311,7 @@ private: } libusb_transfer *_lut; - usb_endpoint *_endpoint; + usb_endpoint::sptr _endpoint; const boost::asio::const_buffer _buff; }; @@ -551,7 +327,7 @@ private: class libusb_managed_send_buffer_impl : public managed_send_buffer { public: libusb_managed_send_buffer_impl(libusb_transfer *lut, - usb_endpoint *endpoint, + usb_endpoint::sptr endpoint, size_t buff_size) : _buff(lut->buffer, buff_size), _committed(false) { @@ -559,8 +335,7 @@ public: _endpoint = endpoint; } - ~libusb_managed_send_buffer_impl() - { + ~libusb_managed_send_buffer_impl(void){ if (!_committed) { _lut->length = 0; _lut->actual_length = 0; @@ -580,12 +355,14 @@ public: _lut->length = num_bytes; _lut->actual_length = 0; - if (_endpoint->submit(_lut)) { + try{ + _endpoint->submit(_lut); _committed = true; return num_bytes; } - else { - return 0; + catch(const std::exception &e){ + std::cerr << "Error in commit: " << e.what() << std::endl; + return -1; } } @@ -596,7 +373,7 @@ private: } libusb_transfer *_lut; - usb_endpoint *_endpoint; + usb_endpoint::sptr _endpoint; const boost::asio::mutable_buffer _buff; bool _committed; }; @@ -608,11 +385,9 @@ private: class libusb_zero_copy_impl : public usb_zero_copy { private: - usb_endpoint *_rx_ep; - usb_endpoint *_tx_ep; + usb_endpoint::sptr _rx_ep, _tx_ep; libusb::device_handle::sptr _handle; - libusb::session::sptr _session; size_t _recv_buff_size; size_t _send_buff_size; @@ -626,8 +401,6 @@ public: unsigned int tx_endpoint, size_t recv_buff_size, size_t send_buff_size); - - ~libusb_zero_copy_impl(); managed_recv_buffer::sptr get_recv_buff(void); managed_send_buffer::sptr get_send_buff(void); @@ -646,45 +419,38 @@ libusb_zero_copy_impl::libusb_zero_copy_impl(libusb::device_handle::sptr handle, unsigned int tx_endpoint, size_t buff_size, size_t block_size) - : _handle(handle), _session(libusb::session::get_global_session()), + : _handle(handle), _recv_buff_size(block_size), _send_buff_size(block_size), _num_frames(buff_size / block_size) { _handle->claim_interface(2 /*in interface*/); _handle->claim_interface(1 /*out interface*/); - _rx_ep = new usb_endpoint(_handle, // libusb device_handle - _session, // libusb session w/ context + _rx_ep = usb_endpoint::sptr(new usb_endpoint( + _handle, // libusb device_handle rx_endpoint, // USB endpoint number true, // IN endpoint _recv_buff_size, // buffer size per transfer - _num_frames); // number of libusb transfers + _num_frames // number of libusb transfers + )); - _tx_ep = new usb_endpoint(_handle, // libusb device_handle - _session, // libusb session w/ context + _tx_ep = usb_endpoint::sptr(new usb_endpoint( + _handle, // libusb device_handle tx_endpoint, // USB endpoint number false, // OUT endpoint _send_buff_size, // buffer size per transfer - _num_frames); // number of libusb transfers -} - - -libusb_zero_copy_impl::~libusb_zero_copy_impl() -{ - delete _rx_ep; - delete _tx_ep; + _num_frames // number of libusb transfers + )); } - /* * Construct a managed receive buffer from a completed libusb transfer * (happy with buffer full of data) obtained from the receive endpoint. * Return empty pointer if no transfer is available (timeout or error). * \return pointer to a managed receive buffer */ -managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff() -{ - libusb_transfer *lut = _rx_ep->get_completed_transfer(); +managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(void){ + libusb_transfer *lut = _rx_ep->get_lut_with_wait(/* TODO timeout API */); if (lut == NULL) { return managed_recv_buffer::sptr(); } @@ -702,9 +468,8 @@ managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff() * (timeout or error). * \return pointer to a managed send buffer */ -managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff() -{ - libusb_transfer *lut = _tx_ep->get_free_transfer(); +managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(void){ + libusb_transfer *lut = _tx_ep->get_lut_with_wait(/* TODO timeout API */); if (lut == NULL) { return managed_send_buffer::sptr(); } @@ -736,6 +501,3 @@ usb_zero_copy::sptr usb_zero_copy::make(usb_device_handle::sptr handle, buff_size, block_size)); } - - - -- cgit v1.2.3 From 86213f8de2cc4ca671f9afbcf475c744fe7aebcb Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 26 Sep 2010 20:54:58 -0700 Subject: usb: disable thread interruption on wait calls --- host/lib/transport/libusb1_zero_copy.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index e84793e88..d3888240b 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -132,6 +133,7 @@ static void callback(libusb_transfer *lut){ * \param pointer to libusb_transfer */ void usb_endpoint::callback_handle_transfer(libusb_transfer *lut){ + boost::this_thread::disable_interruption di; //disable because the wait can throw _completed_list->push_with_wait(lut); } @@ -182,10 +184,7 @@ usb_endpoint::~usb_endpoint(void){ } //collect canceled transfers (drain the queue) - libusb_transfer *lut; - while(_completed_list->pop_with_timed_wait( - lut, boost::posix_time::milliseconds(100) - )); + while (this->get_lut_with_wait() != NULL); //free all transfers BOOST_FOREACH(libusb_transfer *lut, _all_luts){ @@ -273,6 +272,7 @@ void usb_endpoint::print_transfer_status(libusb_transfer *lut){ } libusb_transfer *usb_endpoint::get_lut_with_wait(size_t timeout_ms){ + boost::this_thread::disable_interruption di; //disable because the wait can throw libusb_transfer *lut; if (_completed_list->pop_with_timed_wait( lut, boost::posix_time::milliseconds(timeout_ms) -- cgit v1.2.3 From 017e7202468a8800335c05afd4a85cb52c6171e6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 26 Sep 2010 21:07:43 -0700 Subject: usrp1: add print out messages when loading images --- host/lib/usrp/usrp1/usrp1_ctrl.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp index 1dc6e6e25..76e8ce368 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp @@ -38,6 +38,8 @@ enum firmware_code { #define FX2_FIRMWARE_LOAD 0xa0 +static const bool load_img_msg = true; + /*********************************************************************** * Helper Functions **********************************************************************/ @@ -178,6 +180,7 @@ public: unsigned char reset_n = 0; //hit the reset line + if (load_img_msg) std::cout << "Loading firmware image " << filestring << "..." << std::flush; usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_y, 1); @@ -213,7 +216,7 @@ public: //wait for things to settle boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); - + if (load_img_msg) std::cout << " done" << std::endl; return USRP_FIRMWARE_LOAD_SUCCESS; } //type anything else is unhandled @@ -249,6 +252,7 @@ public: unsigned char buf[ep0_size]; int ret; + if (load_img_msg) std::cout << "Loading FPGA image: " << filestring << "..." << std::flush; std::ifstream file; file.open(filename, std::ios::in | std::ios::binary); if (not file.good()) { @@ -282,6 +286,7 @@ public: usrp_set_fpga_hash(hash); file.close(); + if (load_img_msg) std::cout << " done" << std::endl; return 0; } -- cgit v1.2.3 From 1180615fe2ee1e976aeb9139eb1378fb93befb0f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 26 Sep 2010 22:45:56 -0700 Subject: usb: added some documentation to wrapper base --- host/lib/transport/libusb1_base.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp index 47d078cde..64a1442d1 100644 --- a/host/lib/transport/libusb1_base.hpp +++ b/host/lib/transport/libusb1_base.hpp @@ -24,6 +24,13 @@ #include #include +/*********************************************************************** + * Libusb object oriented smart pointer wrappers: + * The following wrappers provide allocation and automatic deallocation + * for various libusb data types and handles. The construction routines + * also store tables of already allocated structures to avoid multiple + * occurrences of opened handles (for example). + **********************************************************************/ namespace uhd { namespace transport { namespace libusb { -- cgit v1.2.3 From 694404694515e293da6b8949e74af5f469a2e1e5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 27 Sep 2010 00:32:46 -0700 Subject: usb: use the proper libusb include (in path set by pkgconfig) --- host/lib/transport/libusb1_base.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp index 64a1442d1..04c1d6574 100644 --- a/host/lib/transport/libusb1_base.hpp +++ b/host/lib/transport/libusb1_base.hpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include /*********************************************************************** * Libusb object oriented smart pointer wrappers: -- cgit v1.2.3 From 2f62c39b7135728ed06faa06db46004323b1c70f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 27 Sep 2010 11:35:28 -0700 Subject: uhd: fix warning by adding brackets for while(cond){}; --- host/examples/test_async_messages.cpp | 2 +- host/lib/transport/libusb1_zero_copy.cpp | 2 +- host/lib/usrp/usrp2/io_impl.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/host/examples/test_async_messages.cpp b/host/examples/test_async_messages.cpp index 4c9d18121..0a5c076ea 100644 --- a/host/examples/test_async_messages.cpp +++ b/host/examples/test_async_messages.cpp @@ -58,7 +58,7 @@ void test_no_async_message(uhd::usrp::single_usrp::sptr sdev){ " Got unexpected event code 0x%x.\n" ) % async_md.event_code << std::endl; //clear the async messages - while (dev->recv_async_msg(async_md, 0)); + while (dev->recv_async_msg(async_md, 0)){}; } else{ std::cout << boost::format( diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index d3888240b..b089d11e0 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -184,7 +184,7 @@ usb_endpoint::~usb_endpoint(void){ } //collect canceled transfers (drain the queue) - while (this->get_lut_with_wait() != NULL); + while (this->get_lut_with_wait() != NULL){}; //free all transfers BOOST_FOREACH(libusb_transfer *lut, _all_luts){ diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 91a1b2344..65411801d 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -150,7 +150,7 @@ void usrp2_impl::io_init(void){ std::memcpy(send_buff->cast(), &data, sizeof(data)); send_buff->commit(sizeof(data)); //drain the recv buffers (may have junk) - while (data_transport->get_recv_buff().get()); + while (data_transport->get_recv_buff().get()){}; } //the number of recv frames is the number for the first transport -- cgit v1.2.3 From fd15965442d5a8805a4730022f8d500841f8448d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 27 Sep 2010 16:04:04 -0700 Subject: usrp1: filter the discovery routine on the serial --- host/lib/usrp/usrp1/usrp1_impl.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 627180b11..80ea49e9d 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -96,7 +96,10 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) device_addr_t new_addr; new_addr["type"] = "usrp1"; new_addr["serial"] = handle->get_serial(); - usrp1_addrs.push_back(new_addr); + //this is a found usrp1 when a hint serial is not specified or it matches + if (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]){ + usrp1_addrs.push_back(new_addr); + } } return usrp1_addrs; -- cgit v1.2.3 From cd83b1664dc68666d182f771452819d2b0c60ea6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 27 Sep 2010 16:15:43 -0700 Subject: usrp2: application notes for the LEDs --- host/docs/usrp2.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index 4c95fb24c..72a919d1a 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -210,6 +210,20 @@ Example, set the args string to the following: Hardware setup notes ------------------------------------------------------------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Front panel LEDs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The LEDs on the front panel can be useful in debugging hardware and software issues. +The LEDs reveal the following about the state of the device: + +* **LED A:** transmitting +* **LED B:** undocumented +* **LED C:** receiving +* **LED D:** firmware loaded +* **LED E:** undocumented +* **LED F:** FPGA loaded + + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Ref Clock - 10MHz ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From a6f60ab4911fa756656a62ebe3a1093d52836a6e Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Mon, 27 Sep 2010 19:19:55 -0700 Subject: TVRX: not done yet but getting there. gain linearization framework in place. --- host/lib/ic_reg_maps/CMakeLists.txt | 4 +- host/lib/ic_reg_maps/gen_dtt75403_regs.py | 85 ---------- host/lib/ic_reg_maps/gen_tuner_4937di5_regs.py | 75 +++++++++ host/lib/usrp/dboard/db_tvrx.cpp | 218 +++++++++++++++++-------- 4 files changed, 225 insertions(+), 157 deletions(-) delete mode 100755 host/lib/ic_reg_maps/gen_dtt75403_regs.py create mode 100644 host/lib/ic_reg_maps/gen_tuner_4937di5_regs.py diff --git a/host/lib/ic_reg_maps/CMakeLists.txt b/host/lib/ic_reg_maps/CMakeLists.txt index b396db4ca..25f34a280 100644 --- a/host/lib/ic_reg_maps/CMakeLists.txt +++ b/host/lib/ic_reg_maps/CMakeLists.txt @@ -70,6 +70,6 @@ LIBUHD_PYTHON_GEN_SOURCE( ) LIBUHD_PYTHON_GEN_SOURCE( - ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_dtt75403_regs.py - ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/dtt75403_regs.py + ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_tuner_4937di5_regs.py + ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/tuner_4937di5_regs.hpp ) diff --git a/host/lib/ic_reg_maps/gen_dtt75403_regs.py b/host/lib/ic_reg_maps/gen_dtt75403_regs.py deleted file mode 100755 index fe64bd92a..000000000 --- a/host/lib/ic_reg_maps/gen_dtt75403_regs.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/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 . -# - -######################################################################## -# Template for raw text data describing registers -# name addr[bit range inclusive] default optional enums -######################################################################## -REGS_TMPL="""\ -######################################################################## -## Note: offsets given from perspective of data bits (excludes address) -######################################################################## -## -######################################################################## -## Address byte -######################################################################## -adb 0[1:2] 0 -######################################################################## -## Divider byte 1 -######################################################################## -db1 1[0:6] 0x00 -######################################################################## -## Divider byte 2 -######################################################################## -db2 2[0:7] 0x00 -######################################################################## -## Control byte 1 -######################################################################## -atp 3[3:5] 0 112, 109, 106, 103, 100, 94, 94, disable -refdiv 3[0:2] 0 166.667khz, 142.857khz, 80khz, 62.5khz, 31.25khz, 50khz -######################################################################## -## Band switch byte -######################################################################## -cpsel 4[6:7] 0 -filterbw 4[4] 0 8mhz, 7mhz -bandsel 4[0:3] 0 -######################################################################## -## Control byte 2 -######################################################################## -atc 5[5] 0 low, high -stby 5[4] 0 standby, on -xto 5[0] 0 disable, enable -""" - -######################################################################## -# Template for methods in the body of the struct -######################################################################## -BODY_TMPL="""\ -boost::uint8_t get_reg(boost::uint8_t addr){ - boost::uint8_t reg = 0; - switch(addr){ - #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs))) - case $addr: - #for $reg in filter(lambda r: r.get_addr() == addr, $regs) - reg |= (boost::uint8_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); - #end for - break; - #end for - } - return boost::uint8_t(reg); -} - -""" - -if __name__ == '__main__': - import common; common.generate( - name='dtt75403_regs', - regs_tmpl=REGS_TMPL, - body_tmpl=BODY_TMPL, - file=__file__, - ) diff --git a/host/lib/ic_reg_maps/gen_tuner_4937di5_regs.py b/host/lib/ic_reg_maps/gen_tuner_4937di5_regs.py new file mode 100644 index 000000000..73f7aa3db --- /dev/null +++ b/host/lib/ic_reg_maps/gen_tuner_4937di5_regs.py @@ -0,0 +1,75 @@ +#!/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 . +# + +######################################################################## +# Template for raw text data describing registers +# name addr[bit range inclusive] default optional enums +######################################################################## +REGS_TMPL="""\ +######################################################################## +## Note: offsets given from perspective of data bits (excludes address) +######################################################################## +## Divider byte 1 +######################################################################## +db1 0[0:6] 0x00 +######################################################################## +## Divider byte 2 +######################################################################## +db2 1[0:7] 0x00 +######################################################################## +## Control byte 1 +######################################################################## +cb7 2[7] 0x01 +cp 2[6] 0x00 low,high +os 2[0] 0x00 on,off +rs 2[1:2] 0x00 d512=3,d640=0,d1024=1 +test 2[3:5] 0x01 normal=0x01,cpoff=0x02,cpsink=0x06,cpsrc=0x07,cptest1=0x04,cptest2=0x05 +######################################################################## +## Control byte 2 +######################################################################## +bandsel 3[4:7] 0x03 uhf=0x03,vhfhi=0x09,vhflo=0x0a +power 3[3] 0x00 on,off +""" + +######################################################################## +# Template for methods in the body of the struct +######################################################################## +BODY_TMPL="""\ +boost::uint8_t get_reg(boost::uint8_t addr){ + boost::uint8_t reg = 0; + switch(addr){ + #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs))) + case $addr: + #for $reg in filter(lambda r: r.get_addr() == addr, $regs) + reg |= (boost::uint8_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); + #end for + break; + #end for + } + return boost::uint8_t(reg); +} + +""" + +if __name__ == '__main__': + import common; common.generate( + name='tuner_4937di5_regs', + regs_tmpl=REGS_TMPL, + body_tmpl=BODY_TMPL, + file=__file__, + ) diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 5582dbe33..ed6025433 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -42,6 +42,7 @@ #include #include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -57,19 +58,73 @@ static const freq_range_t tvrx_freq_range(50e6, 860e6); static const prop_names_t tvrx_antennas = ""; //only got one static const uhd::dict tvrx_gain_ranges = map_list_of - ("RF", gain_range_t(0, 60, float(60.0/4096))) //both gains are analog and controlled by DAC - ("IF", gain_range_t(0, 35, float(35.0/4096))) //the old driver used 1dB for both; i don't think that's right? + ("RF", gain_range_t(-13.3, 50.3, float(50.3/4096))) //both gains are analog and controlled by DAC + ("IF", gain_range_t(-1.5, 32.5, float(32.5/4096))) //the old driver used 1dB for both; i don't think that's right? ; static const uhd::dict tvrx_freq_ranges = map_list_of - ("VHFLO", freq_range_t(50e6, 158e6)) //this isn't used outside this driver. just for us. + ("VHFLO", freq_range_t(50e6, 158e6)) ("VHFHI", freq_range_t(158e6, 454e6)) ("UHF" , freq_range_t(454e6, 860e6)) ; -//we might need to spec the various bands for band selection. +//gain linearization data +//this is from the datasheet and is dB vs. volts (below) +//i tried to curve fit this, but it's really just so nonlinear that you'd +//need dang near as many coefficients as to just map it like this and interp. +//these numbers are culled from the 4937DI5 datasheet and are probably totally inaccurate +//but if it's better than the old linear fit i'm happy +static const uhd::dict > tvrx_rf_gains_db = map_list_of + ("VHFLO", std::vector(-6.00000, -6.00000, -6.00000, -4.00000, 0.00000, + 5.00000, 10.00000, 17.40000, 26.30000, 36.00000, + 43.00000, 48.00000, 49.50000, 50.10000, 50.30000, + 50.30000, 50.30000)) + ("VHFHI", std::vector(-13.3000, -13.3000, -13.3000, -1.0000, 7.7000, + 11.0000, 14.7000, 19.3000, 26.1000, 36.0000, + 42.7000, 46.0000, 47.0000, 47.8000, 48.2000, + 48.2000, 48.2000)) + ("UHF" , std::vector(-8.0000, -8.0000, -7.0000, 4.0000, 10.2000, + 14.5000, 17.5000, 20.0000, 24.5000, 30.8000, + 37.0000, 39.8000, 40.7000, 41.6000, 42.6000, + 43.2000, 43.8000)) +; + +static const std::vector tvrx_if_gains_db = + std::vector(-1.50000, -1.50000, -1.50000, -1.00000, 0.20000, + 2.10000, 4.30000, 6.40000, 9.00000, 12.00000, + 14.80000, 18.20000, 26.10000, 32.50000, 32.50000, + 32.50000, 32.50000) +; + +//sample voltages for the above points +static const std::vector tvrx_rf_gains_volts = + std::vector(0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0); -static const double tvrx_lo_freq = 36e6; //LO freq of TVRX module + +/*! + * Execute a linear interpolation to find the voltage corresponding to a desired gain + * \param gain the desired gain in dB + * \param db_vector the vector of dB readings + * \param volts_vector the corresponding vector of voltages db_vector was sampled at + * \return a voltage to feed the TVRX analog gain + */ + +static float gain_interp(float gain, std::vector db_vector, std::vector volts_vector) { + float volts; + gain = std::clip(gain, db_vector.front(), db_vector.back()); //let's not get carried away here + + boost::uint8_t gain_step = 0; + for(int i = 0; i < db_vector.size()-1; i++) { + if(gain > db_vector[i] && gain < db_vector.[i+1]) gain_step = i; + } + + + return volts; +} + +static const double opamp_gain = 1.22; //onboard DAC opamp gain +static const double tvrx_lo_freq = 43.75e6; //LO freq of TVRX module +static const boost::uint16_t reference_divider = 640; //clock reference divider to use /*********************************************************************** * The tvrx dboard class @@ -84,40 +139,28 @@ public: private: uhd::dict _gains; - dtt75403_regs_t _dtt75403_regs; - boost::uint8_t _dtt75403_addr(void){ + tuner_4937di5_regs_t _tuner_4937di5_regs; + boost::uint8_t _tuner_4937di5_addr(void){ return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x60 : 0x61; //ok really? we could rename that call }; void set_gain(float gain, const std::string &name); - void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ - //why is this an inline anyway? bring this out - start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0x5)); - stop_reg = boost::uint8_t(std::clip(int(stop_reg), 0x0, 0x5)); - - for(boost::uint8_t start_addr=start_reg; start_addr <= stop_reg; start_addr += sizeof(boost::uint32_t) - 1){ - int num_bytes = int(stop_reg - start_addr + 1) > int(sizeof(boost::uint32_t)) - 1 ? sizeof(boost::uint32_t) - 1 : stop_reg - start_addr + 1; - - //create buffer for register data (+1 for start address) - byte_vector_t regs_vector(num_bytes + 1); + void update_regs(void){ + byte_vector_t regs_vector(4); - //first byte is the address of first register - regs_vector[0] = start_addr; - - //get the register data - for(int i=0; iget_iface()->write_i2c( - _max2118_addr(), regs_vector - ); + //get the register data + for(int i=0; i<4; i++){ + regs_vector[i] = _tuner_4937di5_regs.get_reg(i); + if(tvrx_debug) std::cerr << boost::format( + "tvrx: send reg 0x%02x, value 0x%04x" + ) % int(i) % int(regs_vector[i]) << std::endl; } + + //send the data + this->get_iface()->write_i2c( + _tuner_4937di5_addr(), regs_vector + ); } }; @@ -138,10 +181,6 @@ UHD_STATIC_BLOCK(reg_tvrx_dboard){ * Structors **********************************************************************/ tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){ - //enable only the clocks we need - - //TODO: YOU GOT SOME CLOCK SETUP TO DO HERE, DOGGGG - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); //set the gpio directions and atr controls (identically) @@ -165,77 +204,114 @@ tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){ tvrx::~tvrx(void){ } +/*! Return a string corresponding to the relevant band + * \param freq the frequency of interest + * \return a string corresponding to the band + */ + +static std::string get_band(double freq) { + BOOST_FOREACH(const std::string &band, tvrx_freq_ranges.keys()) { + if(freq >= tvrx_freq_ranges[band].min && freq <= tvrx_freq_ranges[band].max) + return name; + } + UHD_THROW_INVALID_CODE_PATH(); +} + /*********************************************************************** * Gain Handling **********************************************************************/ +/* + * Gain accuracy on this thing is basically a crap shoot. In other words, there is none. + * The old driver basically picked a linear approximation of the median gain, but the actual + * gain slope is heavily nonlinear and varies both with gain and with frequency. + * It also probably varies markedly over temperature, but there's only so much we can do. + * The best approximation to the RF gain data is fifth-order. If we ignore the curve portions + * below 0dB (yes, it's a pad below a certain gain value) and if we ignore the curve portions + * near the max-gain asymptotes, it looks pretty close to third-order. This is less insane to + * approximate. + */ + /*! - * Convert a requested gain for the GC2 vga into the integer register value. + * Convert a requested gain for the RF gain into a DAC voltage. * The gain passed into the function will be set to the actual value. * \param gain the requested gain in dB - * \return 5 bit the register value + * \return dac voltage value */ -//yo this should look the same as the below one for the IF, dogg -static int gain_to_gc2_vga_reg(float &gain){ - int reg = 0; - gain = std::clip(float(boost::math::iround(gain)), tvrx_gain_ranges["GC2"].min, tvrx_gain_ranges["GC2"].max); - - // Half dB steps from 0-5dB, 1dB steps from 5-24dB - if (gain < 5) { - reg = boost::math::iround(31.0 - gain/0.5); - gain = float(boost::math::iround(gain) * 0.5); - } else { - reg = boost::math::iround(22.0 - (gain - 4.0)); - gain = float(boost::math::iround(gain)); - } +static float rf_gain_to_voltage(float &gain){ + //clip the input + gain = std::clip(gain, tvrx_gain_ranges["RF"].min, tvrx_gain_ranges["RF"].max); + + //voltage level constants + static const float max_volts = float(4.0), min_volts = float(0.6); + static const float slope = (max_volts-min_volts)/tvrx_gain_ranges["RF"].max; + + //this is the voltage at the TVRX gain input + float gain_volts = gain*slope + min_volts + //this is the voltage at the USRP DAC output + float dac_volts = gain_volts / opamp_gain; + + //the actual gain setting + gain = (dac_volts - min_volts)/slope; if (tvrx_debug) std::cerr << boost::format( - "tvrx GC2 Gain: %f dB, reg: %d" - ) % gain % reg << std::endl; + "tvrx RF AGC gain: %f dB, dac_volts: %f V" + ) % gain % dac_volts << std::endl; - return reg; + return dac_volts; } /*! - * Convert a requested gain for the RF gain into the dac_volts value. + * Convert a requested gain for the IF gain into a DAC voltage. * The gain passed into the function will be set to the actual value. * \param gain the requested gain in dB * \return dac voltage value */ -//yo what about the 1.22 opamp gain of the USRP1 -- is this replicated on U2? -static float gain_to_rfgain_dac(float &gain){ +static float if_gain_to_voltage(float &gain){ //clip the input - gain = std::clip(gain, tvrx_gain_ranges["RF"].min, tvrx_gain_ranges["RF"].max); + gain = std::clip(gain, tvrx_gain_ranges["IF"].min, tvrx_gain_ranges["IF"].max); //voltage level constants - static const float max_volts = float(0), min_volts = float(3.3); - static const float slope = (max_volts-min_volts)/tvrx_gain_ranges["RF"].max; + static const float max_volts = float(4.0), min_volts = float(0.0); + static const float slope = (max_volts-min_volts)/tvrx_gain_ranges["IF"].max; - //calculate the voltage for the aux dac - float dac_volts = gain*slope + min_volts; - - if (tvrx_debug) std::cerr << boost::format( - "tvrx RFAGC Gain: %f dB, dac_volts: %f V" - ) % gain % dac_volts << std::endl; + //this is the voltage at the TVRX gain input + float gain_volts = gain*slope + 1.25; + //this is the voltage at the USRP DAC output + float dac_volts = gain_volts / opamp_gain; //the actual gain setting gain = (dac_volts - min_volts)/slope; + if (tvrx_debug) std::cerr << boost::format( + "tvrx IF AGC gain: %f dB, dac_volts: %f V" + ) % gain % dac_volts << std::endl; + return dac_volts; } void tvrx::set_gain(float gain, const std::string &name){ assert_has(tvrx_gain_ranges.keys(), name, "tvrx gain name"); if (name == "RF"){ -//should look the same as below + this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, rf_gain_to_voltage(gain)); } else if(name == "IF"){ - //write the new voltage to the aux dac CHECK THIS - this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, gain_to_gc1_rfvga_dac(gain)); + this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_B, if_gain_to_voltage(gain)); } else UHD_THROW_INVALID_CODE_PATH(); _gains[name] = gain; +} + +/*! + * Set the tuner to center the desired frequency at 43.75MHz + * \param freq the requested frequency + */ + +void tvrx::set_freq(double freq) { + + + } /*********************************************************************** @@ -300,7 +376,6 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ } } -//for smaaht kids to use to set advanced props void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); @@ -309,6 +384,9 @@ void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_GAIN: this->set_gain(val.as(), key.name); return; + case SUBDEV_PROP_FREQ: + this->set_freq(val.as()); + return; default: UHD_THROW_PROP_SET_ERROR(); } -- cgit v1.2.3 From 852f5c5f7b31bfb2e7561a86ca9f5380bd53d130 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 28 Sep 2010 10:21:11 -0700 Subject: dboard: better warnings for invalid IDs and invalid ID combinations --- host/lib/usrp/dboard_manager.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index ab80875f5..181f843a0 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -18,6 +18,7 @@ #include "dboard_ctor_args.hpp" #include #include +#include #include #include #include @@ -176,10 +177,6 @@ static args_t get_dboard_args( ){ //special case, the none id was provided, use the following ids if (dboard_id == dboard_id_t::none() or force_to_unknown){ - std::cerr << boost::format( - "Warning: unknown dboard-id or dboard-id combination: %s\n" - " -> defaulting to the unknown board type" - ) % dboard_id.to_pp_string() << std::endl; UHD_ASSERT_THROW(get_id_to_args_map().has_key(0xfff1)); UHD_ASSERT_THROW(get_id_to_args_map().has_key(0xfff0)); switch(unit){ @@ -191,6 +188,9 @@ static args_t get_dboard_args( //verify that there is a registered constructor for this id if (not get_id_to_args_map().has_key(dboard_id)){ + uhd::print_warning(str(boost::format( + "Unknown dboard ID: %s.\n" + ) % dboard_id.to_pp_string())); return get_dboard_args(unit, dboard_id, true); } @@ -214,12 +214,25 @@ dboard_manager_impl::dboard_manager_impl( (get_xcvr_id_to_id_map()[tx_dboard_id] == rx_dboard_id) ); + //warn for invalid dboard id xcvr combinations + if (rx_dboard_is_xcvr != this_dboard_is_xcvr or tx_dboard_is_xcvr != this_dboard_is_xcvr){ + uhd::print_warning(str(boost::format( + "Unknown transceiver board ID combination...\n" + "RX dboard ID: %s\n" + "TX dboard ID: %s\n" + ) % rx_dboard_id.to_pp_string() % tx_dboard_id.to_pp_string())); + } + //extract dboard constructor and settings (force to unknown for messed up xcvr status) dboard_ctor_t rx_dboard_ctor; std::string rx_name; prop_names_t rx_subdevs; - boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_dboard_args(dboard_iface::UNIT_RX, rx_dboard_id, rx_dboard_is_xcvr != this_dboard_is_xcvr); + boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_dboard_args( + dboard_iface::UNIT_RX, rx_dboard_id, rx_dboard_is_xcvr != this_dboard_is_xcvr + ); dboard_ctor_t tx_dboard_ctor; std::string tx_name; prop_names_t tx_subdevs; - boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_dboard_args(dboard_iface::UNIT_TX, tx_dboard_id, tx_dboard_is_xcvr != this_dboard_is_xcvr); + boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_dboard_args( + dboard_iface::UNIT_TX, tx_dboard_id, tx_dboard_is_xcvr != this_dboard_is_xcvr + ); //initialize the gpio pins before creating subdevs set_nice_dboard_if(); -- cgit v1.2.3 From 137aa0ab1ed0b8f7f31a6c484fcf5a845682db80 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 28 Sep 2010 10:24:53 -0700 Subject: usrp1: modify fpga file load to use read (readsome seems to not work here in windows land) --- host/lib/usrp/usrp1/usrp1_ctrl.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp index 76e8ce368..2e1bd85cd 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp @@ -267,8 +267,9 @@ public: return -1; } - ssize_t n; - while ((n = file.readsome((char *)buf, sizeof(buf))) > 0) { + while (not file.eof()) { + file.read((char *)buf, sizeof(buf)); + size_t n = file.gcount(); ret = usrp_control_write(VRQ_FPGA_LOAD, 0, FL_XFER, buf, n); if (ret != n) { -- cgit v1.2.3 From f5bdb7ccb39ef23d4b2c0872fe410e9d5d031958 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 28 Sep 2010 11:08:41 -0700 Subject: usrp1: move the get handles call into the for loop scope to facilitate decontruction --- host/lib/usrp/usrp1/usrp1_impl.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 627180b11..a56649305 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -74,14 +74,14 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) boost::uint16_t vid = hint.has_key("uninit") ? FX2_VENDOR_ID : USRP1_VENDOR_ID; boost::uint16_t pid = hint.has_key("uninit") ? FX2_PRODUCT_ID : USRP1_PRODUCT_ID; - //see what we got on the USB bus - std::vector device_list = - usb_device_handle::get_device_list(vid, pid); - - if(device_list.size() == 0) return usrp1_addrs; //return nothing if no USRPs found + // Important note: + // The get device list calls are nested inside the for loop. + // This allows the usb guts to decontruct when not in use, + // so that re-enumeration after fw load can occur successfully. + // This requirement is a courtesy of libusb1.0 on windows. //find the usrps and load firmware - BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { + BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid, pid)) { usb_control::sptr ctrl_transport = usb_control::make(handle); usrp_ctrl::sptr usrp_ctrl = usrp_ctrl::make(ctrl_transport); usrp_ctrl->usrp_load_firmware(usrp1_fw_image); @@ -90,9 +90,8 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) //get descriptors again with serial number, but using the initialized VID/PID now since we have firmware vid = USRP1_VENDOR_ID; pid = USRP1_PRODUCT_ID; - device_list = usb_device_handle::get_device_list(vid, pid); - BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { + BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid, pid)) { device_addr_t new_addr; new_addr["type"] = "usrp1"; new_addr["serial"] = handle->get_serial(); -- cgit v1.2.3 From 15eacbd920a0527ec16c24baeb1d6b87f29d9110 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 28 Sep 2010 13:52:09 -0700 Subject: TVRX: Don't have mboard impl modified for ADC buffer disable. The rest of TVRX should be in there. Not debugged. --- host/lib/usrp/dboard/CMakeLists.txt | 1 + host/lib/usrp/dboard/db_tvrx.cpp | 219 +++++++++++++++++++++--------------- host/lib/usrp/usrp1/codec_ctrl.cpp | 13 +++ host/lib/usrp/usrp1/codec_ctrl.hpp | 3 + 4 files changed, 147 insertions(+), 89 deletions(-) diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index 3e995009e..8d3d11530 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -24,5 +24,6 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_wbx.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_dbsrx.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_unknown.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_tvrx.cpp ) diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index ed6025433..2988367e2 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -39,9 +39,11 @@ #include #include #include +#include #include #include #include +#include #include using namespace uhd; @@ -55,12 +57,11 @@ static const bool tvrx_debug = true; static const freq_range_t tvrx_freq_range(50e6, 860e6); -static const prop_names_t tvrx_antennas = ""; //only got one +static const std::string tvrx_antennas = std::string(""); //only got one -static const uhd::dict tvrx_gain_ranges = map_list_of - ("RF", gain_range_t(-13.3, 50.3, float(50.3/4096))) //both gains are analog and controlled by DAC - ("IF", gain_range_t(-1.5, 32.5, float(32.5/4096))) //the old driver used 1dB for both; i don't think that's right? -; +//a note on these: the gain of the TVRX varies over frequency. the gain ranges +//below correspond to the maximum and minimum gains over the entire frequency range. +//specifying a gain higher or lower than the TVRX can accomplish will of course just clip. static const uhd::dict tvrx_freq_ranges = map_list_of ("VHFLO", freq_range_t(50e6, 158e6)) @@ -68,63 +69,68 @@ static const uhd::dict tvrx_freq_ranges = map_list_of ("UHF" , freq_range_t(454e6, 860e6)) ; +static const boost::array vhflo_gains_db = + {{-6.00000, -6.00000, -6.00000, -4.00000, 0.00000, + 5.00000, 10.00000, 17.40000, 26.30000, 36.00000, + 43.00000, 48.00000, 49.50000, 50.10000, 50.30000, + 50.30000, 50.30000}}; + +static const boost::array vhfhi_gains_db = + {{13.3000, -13.3000, -13.3000, -1.0000, 7.7000, + 11.0000, 14.7000, 19.3000, 26.1000, 36.0000, + 42.7000, 46.0000, 47.0000, 47.8000, 48.2000, + 48.2000, 48.2000}}; + +static const boost::array uhf_gains_db = + {{-8.0000, -8.0000, -7.0000, 4.0000, 10.2000, + 14.5000, 17.5000, 20.0000, 24.5000, 30.8000, + 37.0000, 39.8000, 40.7000, 41.6000, 42.6000, + 43.2000, 43.8000}}; + +static const boost::array tvrx_if_gains_db = + {{-1.50000, -1.50000, -1.50000, -1.00000, 0.20000, + 2.10000, 4.30000, 6.40000, 9.00000, 12.00000, + 14.80000, 18.20000, 26.10000, 32.50000, 32.50000, + 32.50000, 32.50000}}; + //gain linearization data //this is from the datasheet and is dB vs. volts (below) //i tried to curve fit this, but it's really just so nonlinear that you'd //need dang near as many coefficients as to just map it like this and interp. //these numbers are culled from the 4937DI5 datasheet and are probably totally inaccurate //but if it's better than the old linear fit i'm happy -static const uhd::dict > tvrx_rf_gains_db = map_list_of - ("VHFLO", std::vector(-6.00000, -6.00000, -6.00000, -4.00000, 0.00000, - 5.00000, 10.00000, 17.40000, 26.30000, 36.00000, - 43.00000, 48.00000, 49.50000, 50.10000, 50.30000, - 50.30000, 50.30000)) - ("VHFHI", std::vector(-13.3000, -13.3000, -13.3000, -1.0000, 7.7000, - 11.0000, 14.7000, 19.3000, 26.1000, 36.0000, - 42.7000, 46.0000, 47.0000, 47.8000, 48.2000, - 48.2000, 48.2000)) - ("UHF" , std::vector(-8.0000, -8.0000, -7.0000, 4.0000, 10.2000, - 14.5000, 17.5000, 20.0000, 24.5000, 30.8000, - 37.0000, 39.8000, 40.7000, 41.6000, 42.6000, - 43.2000, 43.8000)) -; - -static const std::vector tvrx_if_gains_db = - std::vector(-1.50000, -1.50000, -1.50000, -1.00000, 0.20000, - 2.10000, 4.30000, 6.40000, 9.00000, 12.00000, - 14.80000, 18.20000, 26.10000, 32.50000, 32.50000, - 32.50000, 32.50000) +static const uhd::dict > tvrx_rf_gains_db = map_list_of + ("VHFLO", vhflo_gains_db) + ("VHFHI", vhfhi_gains_db) + ("UHF" , uhf_gains_db) ; //sample voltages for the above points -static const std::vector tvrx_rf_gains_volts = - std::vector(0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0); - - -/*! - * Execute a linear interpolation to find the voltage corresponding to a desired gain - * \param gain the desired gain in dB - * \param db_vector the vector of dB readings - * \param volts_vector the corresponding vector of voltages db_vector was sampled at - * \return a voltage to feed the TVRX analog gain - */ - -static float gain_interp(float gain, std::vector db_vector, std::vector volts_vector) { - float volts; - gain = std::clip(gain, db_vector.front(), db_vector.back()); //let's not get carried away here - - boost::uint8_t gain_step = 0; - for(int i = 0; i < db_vector.size()-1; i++) { - if(gain > db_vector[i] && gain < db_vector.[i+1]) gain_step = i; +static const boost::array tvrx_gains_volts = + {{0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0}}; + +static uhd::dict get_tvrx_gain_ranges(void) { + float rfmax = 0.0, rfmin = FLT_MAX; + BOOST_FOREACH(const std::string range, tvrx_rf_gains_db.keys()) { + float my_max = tvrx_rf_gains_db[range].back(); //we're assuming it's monotonic + float my_min = tvrx_rf_gains_db[range].front(); //if it's not this is wrong wrong wrong + if(my_max > rfmax) rfmax = my_max; + if(my_min < rfmin) rfmin = my_min; } - - return volts; + float ifmin = tvrx_if_gains_db.front(); + float ifmax = tvrx_if_gains_db.back(); + + return map_list_of + ("RF", gain_range_t(rfmin, rfmax, (rfmax-rfmin)/4096.0)) + ("IF", gain_range_t(ifmin, ifmax, (ifmax-ifmin)/4096.0)) + ; } static const double opamp_gain = 1.22; //onboard DAC opamp gain -static const double tvrx_lo_freq = 43.75e6; //LO freq of TVRX module +static const double tvrx_if_freq = 43.75e6; //IF freq of TVRX module static const boost::uint16_t reference_divider = 640; //clock reference divider to use +static const double reference_freq = 4.0e6; /*********************************************************************** * The tvrx dboard class @@ -139,12 +145,14 @@ public: private: uhd::dict _gains; + double _lo_freq; tuner_4937di5_regs_t _tuner_4937di5_regs; boost::uint8_t _tuner_4937di5_addr(void){ return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x60 : 0x61; //ok really? we could rename that call }; void set_gain(float gain, const std::string &name); + void set_freq(double freq); void update_regs(void){ byte_vector_t regs_vector(4); @@ -192,12 +200,14 @@ tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){ this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs } - //send initial register settings - //HAAAAY GUYYYYYSSS + //send initial register settings if necessary + + //set default freq + set_freq(tvrx_freq_range.min); //set default gains - BOOST_FOREACH(const std::string &name, tvrx_gain_ranges.keys()){ - set_gain(tvrx_gain_ranges[name].min, name); + BOOST_FOREACH(const std::string &name, get_tvrx_gain_ranges().keys()){ + set_gain(get_tvrx_gain_ranges()[name].min, name); } } @@ -212,7 +222,7 @@ tvrx::~tvrx(void){ static std::string get_band(double freq) { BOOST_FOREACH(const std::string &band, tvrx_freq_ranges.keys()) { if(freq >= tvrx_freq_ranges[band].min && freq <= tvrx_freq_ranges[band].max) - return name; + return band; } UHD_THROW_INVALID_CODE_PATH(); } @@ -220,17 +230,34 @@ static std::string get_band(double freq) { /*********************************************************************** * Gain Handling **********************************************************************/ -/* - * Gain accuracy on this thing is basically a crap shoot. In other words, there is none. - * The old driver basically picked a linear approximation of the median gain, but the actual - * gain slope is heavily nonlinear and varies both with gain and with frequency. - * It also probably varies markedly over temperature, but there's only so much we can do. - * The best approximation to the RF gain data is fifth-order. If we ignore the curve portions - * below 0dB (yes, it's a pad below a certain gain value) and if we ignore the curve portions - * near the max-gain asymptotes, it looks pretty close to third-order. This is less insane to - * approximate. +/*! + * Execute a linear interpolation to find the voltage corresponding to a desired gain + * \param gain the desired gain in dB + * \param db_vector the vector of dB readings + * \param volts_vector the corresponding vector of voltages db_vector was sampled at + * \return a voltage to feed the TVRX analog gain */ +static float gain_interp(float gain, boost::array db_vector, boost::array volts_vector) { + float volts; + gain = std::clip(gain, db_vector.front(), db_vector.back()); //let's not get carried away here + + boost::uint8_t gain_step = 0; + //find which bin we're in + for(size_t i = 0; i < db_vector.size()-1; i++) { + if(gain > db_vector[i] && gain < db_vector[i+1]) gain_step = i; + } + + //find the current slope for linear interpolation + float slope = (volts_vector[gain_step + 1] - volts_vector[gain_step]) + / (db_vector[gain_step + 1] - db_vector[gain_step]); + + //use the volts per dB slope to find the final interpolated voltage + volts = volts_vector[gain_step] + (slope * (gain - db_vector[gain_step])); + + return volts; +} + /*! * Convert a requested gain for the RF gain into a DAC voltage. * The gain passed into the function will be set to the actual value. @@ -238,22 +265,18 @@ static std::string get_band(double freq) { * \return dac voltage value */ -static float rf_gain_to_voltage(float &gain){ +static float rf_gain_to_voltage(float gain, double lo_freq){ //clip the input - gain = std::clip(gain, tvrx_gain_ranges["RF"].min, tvrx_gain_ranges["RF"].max); + gain = std::clip(gain, get_tvrx_gain_ranges()["RF"].min, get_tvrx_gain_ranges()["RF"].max); - //voltage level constants - static const float max_volts = float(4.0), min_volts = float(0.6); - static const float slope = (max_volts-min_volts)/tvrx_gain_ranges["RF"].max; + //first we need to find out what band we're in, because gains are different across different bands + std::string band = get_band(lo_freq + tvrx_if_freq); //this is the voltage at the TVRX gain input - float gain_volts = gain*slope + min_volts + float gain_volts = gain_interp(gain, tvrx_rf_gains_db[band], tvrx_gains_volts); //this is the voltage at the USRP DAC output float dac_volts = gain_volts / opamp_gain; - //the actual gain setting - gain = (dac_volts - min_volts)/slope; - if (tvrx_debug) std::cerr << boost::format( "tvrx RF AGC gain: %f dB, dac_volts: %f V" ) % gain % dac_volts << std::endl; @@ -268,22 +291,13 @@ static float rf_gain_to_voltage(float &gain){ * \return dac voltage value */ -static float if_gain_to_voltage(float &gain){ +static float if_gain_to_voltage(float gain){ //clip the input - gain = std::clip(gain, tvrx_gain_ranges["IF"].min, tvrx_gain_ranges["IF"].max); - - //voltage level constants - static const float max_volts = float(4.0), min_volts = float(0.0); - static const float slope = (max_volts-min_volts)/tvrx_gain_ranges["IF"].max; - - //this is the voltage at the TVRX gain input - float gain_volts = gain*slope + 1.25; - //this is the voltage at the USRP DAC output + gain = std::clip(gain, get_tvrx_gain_ranges()["IF"].min, get_tvrx_gain_ranges()["IF"].max); + + float gain_volts = gain_interp(gain, tvrx_if_gains_db, tvrx_gains_volts); float dac_volts = gain_volts / opamp_gain; - //the actual gain setting - gain = (dac_volts - min_volts)/slope; - if (tvrx_debug) std::cerr << boost::format( "tvrx IF AGC gain: %f dB, dac_volts: %f V" ) % gain % dac_volts << std::endl; @@ -292,9 +306,9 @@ static float if_gain_to_voltage(float &gain){ } void tvrx::set_gain(float gain, const std::string &name){ - assert_has(tvrx_gain_ranges.keys(), name, "tvrx gain name"); + assert_has(get_tvrx_gain_ranges().keys(), name, "tvrx gain name"); if (name == "RF"){ - this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, rf_gain_to_voltage(gain)); + this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, rf_gain_to_voltage(gain, _lo_freq)); } else if(name == "IF"){ this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_B, if_gain_to_voltage(gain)); @@ -309,9 +323,36 @@ void tvrx::set_gain(float gain, const std::string &name){ */ void tvrx::set_freq(double freq) { + freq = std::clip(freq, tvrx_freq_range.min, tvrx_freq_range.max); + std::string prev_band = get_band(_lo_freq + tvrx_if_freq); + std::string new_band = get_band(freq); + double lo_freq = freq + tvrx_if_freq; //the desired LO freq for high-side mixing + double f_ref = reference_freq / double(reference_divider); //your tuning step size + int divisor = int(lo_freq + (f_ref * 4.0)) / (f_ref * 8); //the divisor we'll use + double actual_lo_freq = (f_ref * 8 * divisor); //the LO freq we'll actually get + + if((divisor & ~0x7fff)) UHD_THROW_INVALID_CODE_PATH(); + + //now we update the registers + _tuner_4937di5_regs.db1 = (divisor >> 8) & 0xff; + _tuner_4937di5_regs.db2 = divisor & 0xff; + + if(new_band == "VHFLO") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_VHFLO; + else if(new_band == "VHFHI") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_VHFHI; + else if(new_band == "UHF") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_UHF; + else UHD_THROW_INVALID_CODE_PATH(); + + _tuner_4937di5_regs.power = tuner_4937di5_regs_t::POWER_ON; + update_regs(); + + //ok don't forget to reset RF gain here if the new band != the old band + //we do this because the gains are different for different band settings + //not FAR off, but we do this to be consistent + if(prev_band != new_band) set_gain(_gains["RF"], "RF"); + _lo_freq = actual_lo_freq; //for rx props } /*********************************************************************** @@ -336,16 +377,16 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_GAIN_RANGE: - assert_has(tvrx_gain_ranges.keys(), key.name, "tvrx gain name"); - val = tvrx_gain_ranges[key.name]; + assert_has(get_tvrx_gain_ranges().keys(), key.name, "tvrx gain name"); + val = get_tvrx_gain_ranges()[key.name]; return; case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(tvrx_gain_ranges.keys()); + val = prop_names_t(get_tvrx_gain_ranges().keys()); return; case SUBDEV_PROP_FREQ: - val = tvrx_lo_freq; + val = _lo_freq - tvrx_if_freq; return; case SUBDEV_PROP_FREQ_RANGE: diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp index 08f2d2a8e..3ab02eeeb 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.cpp +++ b/host/lib/usrp/usrp1/codec_ctrl.cpp @@ -61,6 +61,9 @@ public: float get_tx_pga_gain(void); void set_rx_pga_gain(float, char); float get_rx_pga_gain(char); + + //rx adc buffer control + void bypass_adc_buffers(bool bypass); private: usrp1_iface::sptr _iface; @@ -418,6 +421,16 @@ void usrp1_codec_ctrl_impl::set_duc_freq(double freq) this->send_reg(23); } +/*********************************************************************** + * Codec Control ADC buffer bypass + * Enable this for DC-coupled daughterboards (TVRX) + **********************************************************************/ +void usrp1_codec_ctrl_impl::bypass_adc_buffers(bool bypass) { + _ad9862_regs.byp_buffer_a = bypass; + _ad9862_regs.byp_buffer_b = bypass; + this->send_reg(2); +} + /*********************************************************************** * Codec Control Make **********************************************************************/ diff --git a/host/lib/usrp/usrp1/codec_ctrl.hpp b/host/lib/usrp/usrp1/codec_ctrl.hpp index 259d10ef4..e2e8a010d 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.hpp +++ b/host/lib/usrp/usrp1/codec_ctrl.hpp @@ -92,6 +92,9 @@ public: //! Set the TX modulator frequency virtual void set_duc_freq(double freq) = 0; + + //! Enable or disable ADC buffer bypass + virtual void bypass_adc_buffers(bool bypass) = 0; }; #endif /* INCLUDED_USRP1_CODEC_CTRL_HPP */ -- cgit v1.2.3 From b70d4430d4a898fe99b54740a1c4821ed9a1077b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 28 Sep 2010 15:31:38 -0700 Subject: wbx: fix for id swap typo --- host/lib/usrp/dboard/db_wbx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index ccd897674..e473ce41e 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -154,7 +154,7 @@ static dboard_base::sptr make_wbx(dboard_base::ctor_args_t args){ } UHD_STATIC_BLOCK(reg_wbx_dboards){ - dboard_manager::register_dboard(0x0052, 0x0053, &make_wbx, "WBX"); + dboard_manager::register_dboard(0x0053, 0x0052, &make_wbx, "WBX"); } /*********************************************************************** -- cgit v1.2.3 From e4c6f42ff30aeaedf2d1eb426a221b85236fb74e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 28 Sep 2010 16:53:52 -0700 Subject: usb: submit should return ssize_t, usrp1: set hash before reset after fw load --- host/include/uhd/transport/usb_control.hpp | 4 ++-- host/lib/transport/libusb1_control.cpp | 2 +- host/lib/usrp/usrp1/usrp1_ctrl.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/host/include/uhd/transport/usb_control.hpp b/host/include/uhd/transport/usb_control.hpp index 6137ecf84..f9829c3ec 100644 --- a/host/include/uhd/transport/usb_control.hpp +++ b/host/include/uhd/transport/usb_control.hpp @@ -50,9 +50,9 @@ public: * \param index 2-byte (wIndex) * \param buff buffer to hold send or receive data * \param length 2-byte (wLength) - * \return number of bytes submitted + * \return number of bytes submitted or error code */ - virtual size_t submit(boost::uint8_t request_type, + virtual ssize_t submit(boost::uint8_t request_type, boost::uint8_t request, boost::uint16_t value, boost::uint16_t index, diff --git a/host/lib/transport/libusb1_control.cpp b/host/lib/transport/libusb1_control.cpp index c989a788c..f903907d0 100644 --- a/host/lib/transport/libusb1_control.cpp +++ b/host/lib/transport/libusb1_control.cpp @@ -33,7 +33,7 @@ public: _handle->claim_interface(0 /* control interface */); } - size_t submit(boost::uint8_t request_type, + ssize_t submit(boost::uint8_t request_type, boost::uint8_t request, boost::uint16_t value, boost::uint16_t index, diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp index 2e1bd85cd..5d73e6dd9 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp @@ -209,9 +209,9 @@ public: } //type 0x01 is end else if (type == 0x01) { + usrp_set_firmware_hash(hash); //set hash before reset usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_n, 1); - usrp_set_firmware_hash(hash); file.close(); //wait for things to settle -- cgit v1.2.3 From 7cb95203f8d7173e3d7070d24f68358be67d0b29 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 28 Sep 2010 17:45:07 -0700 Subject: TVRX: First version that works. The gain linearity is still borked. I'll probably give up on the complicated linearizing stuff and just use the values from the old driver. The tuner's gain-vs-voltage is nothing like the datasheet. --- host/lib/usrp/dboard/db_tvrx.cpp | 44 ++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 2988367e2..f5b544c18 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include using namespace uhd; @@ -59,10 +60,6 @@ static const freq_range_t tvrx_freq_range(50e6, 860e6); static const std::string tvrx_antennas = std::string(""); //only got one -//a note on these: the gain of the TVRX varies over frequency. the gain ranges -//below correspond to the maximum and minimum gains over the entire frequency range. -//specifying a gain higher or lower than the TVRX can accomplish will of course just clip. - static const uhd::dict tvrx_freq_ranges = map_list_of ("VHFLO", freq_range_t(50e6, 158e6)) ("VHFHI", freq_range_t(158e6, 454e6)) @@ -148,7 +145,7 @@ private: double _lo_freq; tuner_4937di5_regs_t _tuner_4937di5_regs; boost::uint8_t _tuner_4937di5_addr(void){ - return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x60 : 0x61; //ok really? we could rename that call + return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x61 : 0x60; //ok really? we could rename that call }; void set_gain(float gain, const std::string &name); @@ -182,7 +179,7 @@ static dboard_base::sptr make_tvrx(dboard_base::ctor_args_t args){ UHD_STATIC_BLOCK(reg_tvrx_dboard){ //register the factory function for the rx dbid - dboard_manager::register_dboard(0x0003, &make_tvrx, "tvrx"); + dboard_manager::register_dboard(0x0040, &make_tvrx, "tvrx"); } /*********************************************************************** @@ -203,6 +200,7 @@ tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){ //send initial register settings if necessary //set default freq + _lo_freq = tvrx_freq_range.min + tvrx_if_freq; //init _lo_freq to a sane default set_freq(tvrx_freq_range.min); //set default gains @@ -220,9 +218,12 @@ tvrx::~tvrx(void){ */ static std::string get_band(double freq) { + std::cout << "get_band called with freq " << freq << std::endl; BOOST_FOREACH(const std::string &band, tvrx_freq_ranges.keys()) { - if(freq >= tvrx_freq_ranges[band].min && freq <= tvrx_freq_ranges[band].max) + if(freq >= tvrx_freq_ranges[band].min && freq <= tvrx_freq_ranges[band].max){ + std::cout << "Holy poop you're in band " << band << std::endl; return band; + } } UHD_THROW_INVALID_CODE_PATH(); } @@ -245,15 +246,25 @@ static float gain_interp(float gain, boost::array db_vector, boost::a boost::uint8_t gain_step = 0; //find which bin we're in for(size_t i = 0; i < db_vector.size()-1; i++) { - if(gain > db_vector[i] && gain < db_vector[i+1]) gain_step = i; + if(gain >= db_vector[i] && gain <= db_vector[i+1]) gain_step = i; } //find the current slope for linear interpolation float slope = (volts_vector[gain_step + 1] - volts_vector[gain_step]) / (db_vector[gain_step + 1] - db_vector[gain_step]); + + //the problem here is that for gains approaching the maximum, the voltage slope becomes infinite + //i.e., a small change in gain requires an infinite change in voltage + //to cope, we limit the slope + + if(slope == std::numeric_limits::infinity()) + return volts_vector[gain_step]; //use the volts per dB slope to find the final interpolated voltage volts = volts_vector[gain_step] + (slope * (gain - db_vector[gain_step])); + + if(tvrx_debug) + std::cout << "Gain interp: gain: " << gain << ", gain_step: " << int(gain_step) << ", slope: " << slope << ", volts: " << volts << std::endl; return volts; } @@ -276,6 +287,8 @@ static float rf_gain_to_voltage(float gain, double lo_freq){ float gain_volts = gain_interp(gain, tvrx_rf_gains_db[band], tvrx_gains_volts); //this is the voltage at the USRP DAC output float dac_volts = gain_volts / opamp_gain; + + dac_volts = std::clip(dac_volts, 0.0, 3.3); if (tvrx_debug) std::cerr << boost::format( "tvrx RF AGC gain: %f dB, dac_volts: %f V" @@ -297,6 +310,8 @@ static float if_gain_to_voltage(float gain){ float gain_volts = gain_interp(gain, tvrx_if_gains_db, tvrx_gains_volts); float dac_volts = gain_volts / opamp_gain; + + dac_volts = std::clip(dac_volts, 0.0, 3.3); if (tvrx_debug) std::cerr << boost::format( "tvrx IF AGC gain: %f dB, dac_volts: %f V" @@ -324,13 +339,13 @@ void tvrx::set_gain(float gain, const std::string &name){ void tvrx::set_freq(double freq) { freq = std::clip(freq, tvrx_freq_range.min, tvrx_freq_range.max); - std::string prev_band = get_band(_lo_freq + tvrx_if_freq); + std::string prev_band = get_band(_lo_freq - tvrx_if_freq); std::string new_band = get_band(freq); - double lo_freq = freq + tvrx_if_freq; //the desired LO freq for high-side mixing + double target_lo_freq = freq + tvrx_if_freq; //the desired LO freq for high-side mixing double f_ref = reference_freq / double(reference_divider); //your tuning step size - int divisor = int(lo_freq + (f_ref * 4.0)) / (f_ref * 8); //the divisor we'll use + int divisor = int((target_lo_freq + (f_ref * 4.0)) / (f_ref * 8)); //the divisor we'll use double actual_lo_freq = (f_ref * 8 * divisor); //the LO freq we'll actually get if((divisor & ~0x7fff)) UHD_THROW_INVALID_CODE_PATH(); @@ -344,7 +359,7 @@ void tvrx::set_freq(double freq) { else if(new_band == "UHF") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_UHF; else UHD_THROW_INVALID_CODE_PATH(); - _tuner_4937di5_regs.power = tuner_4937di5_regs_t::POWER_ON; + _tuner_4937di5_regs.power = tuner_4937di5_regs_t::POWER_OFF; update_regs(); //ok don't forget to reset RF gain here if the new band != the old band @@ -352,6 +367,9 @@ void tvrx::set_freq(double freq) { //not FAR off, but we do this to be consistent if(prev_band != new_band) set_gain(_gains["RF"], "RF"); + if(tvrx_debug) + std::cout << boost::format("set_freq: target LO: %f f_ref: %f divisor: %i actual LO: %f") % target_lo_freq % f_ref % divisor % actual_lo_freq << std::endl; + _lo_freq = actual_lo_freq; //for rx props } @@ -386,7 +404,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_FREQ: - val = _lo_freq - tvrx_if_freq; + val = _lo_freq - 2*tvrx_if_freq; return; case SUBDEV_PROP_FREQ_RANGE: -- cgit v1.2.3 From 560cbf9a2900a02391f025a3fd50a1616893c8c7 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 28 Sep 2010 18:04:35 -0700 Subject: TVRX: Fixed spectrum inversion (derp derp derp). Removed debug printing. --- host/lib/usrp/dboard/db_tvrx.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index f5b544c18..83a638810 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -54,7 +54,7 @@ using namespace boost::assign; /*********************************************************************** * The tvrx constants **********************************************************************/ -static const bool tvrx_debug = true; +static const bool tvrx_debug = false; static const freq_range_t tvrx_freq_range(50e6, 860e6); @@ -218,10 +218,9 @@ tvrx::~tvrx(void){ */ static std::string get_band(double freq) { - std::cout << "get_band called with freq " << freq << std::endl; BOOST_FOREACH(const std::string &band, tvrx_freq_ranges.keys()) { if(freq >= tvrx_freq_ranges[band].min && freq <= tvrx_freq_ranges[band].max){ - std::cout << "Holy poop you're in band " << band << std::endl; + if(tvrx_debug) std::cout << "Band: " << band << std::endl; return band; } } @@ -404,7 +403,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_FREQ: - val = _lo_freq - 2*tvrx_if_freq; + val = _lo_freq; return; case SUBDEV_PROP_FREQ_RANGE: -- cgit v1.2.3 From 6fe533e19a29ea6cd241b70c38081499a8f3ba55 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 28 Sep 2010 18:09:04 -0700 Subject: TVRX: Mixed up DAC channels. Gain is much more linear now. --- host/lib/usrp/dboard/db_tvrx.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 83a638810..71aff1680 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -322,10 +322,10 @@ static float if_gain_to_voltage(float gain){ void tvrx::set_gain(float gain, const std::string &name){ assert_has(get_tvrx_gain_ranges().keys(), name, "tvrx gain name"); if (name == "RF"){ - this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, rf_gain_to_voltage(gain, _lo_freq)); + this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_B, rf_gain_to_voltage(gain, _lo_freq)); } else if(name == "IF"){ - this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_B, if_gain_to_voltage(gain)); + this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, if_gain_to_voltage(gain)); } else UHD_THROW_INVALID_CODE_PATH(); _gains[name] = gain; -- cgit v1.2.3 From 302078474312ad87db69a9c06b63e3f8a0c19cd5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 29 Sep 2010 09:51:41 -0700 Subject: usrp1: fixed compile time warning, tweaked fw load message --- host/lib/usrp/usrp1/usrp1_ctrl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp index 5d73e6dd9..5043aed7d 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp @@ -180,7 +180,7 @@ public: unsigned char reset_n = 0; //hit the reset line - if (load_img_msg) std::cout << "Loading firmware image " << filestring << "..." << std::flush; + if (load_img_msg) std::cout << "Loading firmware image: " << filestring << "..." << std::flush; usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_y, 1); @@ -272,7 +272,7 @@ public: size_t n = file.gcount(); ret = usrp_control_write(VRQ_FPGA_LOAD, 0, FL_XFER, buf, n); - if (ret != n) { + if (ret < 0 or size_t(ret) != n) { std::cerr << "fpga load error " << ret << std::endl; file.close(); return -1; -- cgit v1.2.3 From 543a63648f11d0e502e897f3cd98667005580c9e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 29 Sep 2010 15:35:54 -0700 Subject: usrp: transfer resize options and documentation --- host/docs/usrp1.rst | 27 ++++++ host/include/uhd/transport/usb_zero_copy.hpp | 24 +++-- host/lib/transport/libusb1_zero_copy.cpp | 140 ++++++++++++++------------- host/lib/usrp/usrp1/usrp1_impl.cpp | 26 +++-- 4 files changed, 137 insertions(+), 80 deletions(-) diff --git a/host/docs/usrp1.rst b/host/docs/usrp1.rst index 3c1431d30..7cf447719 100644 --- a/host/docs/usrp1.rst +++ b/host/docs/usrp1.rst @@ -95,6 +95,27 @@ Notice that the subdevice name is always specified in the 3 possible cases. B:B + +------------------------------------------------------------------------ +Change USB transfer parameters +------------------------------------------------------------------------ +The advanced user may manipulate parameters of the usb bulk transfers +for various reasons, such as lowering latency or increasing buffer size. +By default, the UHD will use values for these parameters +that are known to perform well on a variety of systems. + +The following device address can be used to manipulate USB bulk transfers: + +* **recv_xfer_size:** the size of each receive bulk transfer in bytes +* **recv_num_xfers:** the number of simultaneous receive bulk transfers +* **send_xfer_size:** the size of each send bulk transfer in bytes +* **send_num_xfers:** the number of simultaneous send bulk transfers + +Example, set the args string to the following: +:: + + serial=12345678, recv_num_xfers=16 + ------------------------------------------------------------------------ OS Specific Notes ------------------------------------------------------------------------ @@ -113,3 +134,9 @@ so that non-root users may access the device: sudo mv tmpfile /etc/udev/rules.d/10-usrp.rules sudo udevadm control --reload-rules +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Install libusb driver on Windows +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +On Windows, a driver must be installed the first time the USRP1 is attached to the host computer. +A download link for this driver can be found on the Ettus Research UHD wiki page. +Download and unpack the driver, and direct the Windows driver install wizard to the *.inf file. diff --git a/host/include/uhd/transport/usb_zero_copy.hpp b/host/include/uhd/transport/usb_zero_copy.hpp index 75232c22a..61bf380ba 100644 --- a/host/include/uhd/transport/usb_zero_copy.hpp +++ b/host/include/uhd/transport/usb_zero_copy.hpp @@ -45,16 +45,22 @@ public: * The underlying implementation may be platform specific. * * \param handle a device handle that uniquely identifying the device - * \param rx_endpoint an integer specifiying an IN endpoint number - * \param tx_endpoint an integer specifiying an OUT endpoint number - * \param buff_size total number of bytes of buffer space to allocate - * \param block_size number of bytes allocated for each I/O transaction + * \param recv_endpoint an integer specifiying an IN endpoint number + * \param send_endpoint an integer specifiying an OUT endpoint number + * \param recv_xfer_size the number of bytes for each receive transfer + * \param recv_num_xfers the number of simultaneous receive transfers + * \param send_xfer_size the number of bytes for each send transfer + * \param send_num_xfers the number of simultaneous send transfers */ - static sptr make(usb_device_handle::sptr handle, - unsigned int rx_endpoint, - unsigned int tx_endpoint, - size_t buff_size = 0, - size_t block_size = 0); + static sptr make( + usb_device_handle::sptr handle, + unsigned int recv_endpoint, + unsigned int send_endpoint, + size_t recv_xfer_size = 0, + size_t recv_num_xfers = 0, + size_t send_xfer_size = 0, + size_t send_num_xfers = 0 + ); }; }} //namespace diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index b089d11e0..f2dcff6b5 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -30,6 +30,9 @@ using namespace uhd::transport; const int libusb_timeout = 0; +static const size_t DEFAULT_NUM_XFERS = 16; //num xfers +static const size_t DEFAULT_XFER_SIZE = 32*512; //bytes + /*********************************************************************** * Helper functions ***********************************************************************/ @@ -56,7 +59,7 @@ void pp_transfer(libusb_transfer *lut) * create a bidirectional interface. It is a zero copy implementation * with respect to libusb, however, each send and recv requires a copy * operation from kernel to userspace; this is due to the usbfs - * interface provided by the kernel. + * interface provided by the kernel. **********************************************************************/ class usb_endpoint { public: @@ -107,7 +110,7 @@ private: //! a list of shared arrays for the transfer buffers std::vector > _buffers; - // Calls for processing asynchronous I/O + // Calls for processing asynchronous I/O libusb_transfer *allocate_transfer(int buff_len); void print_transfer_status(libusb_transfer *lut); }; @@ -142,7 +145,7 @@ void usb_endpoint::callback_handle_transfer(libusb_transfer *lut){ * Constructor * Allocate libusb transfers and mark as free. For IN endpoints, * submit the transfers so that they're ready to return when - * data is available. + * data is available. */ usb_endpoint::usb_endpoint( libusb::device_handle::sptr handle, @@ -194,7 +197,7 @@ usb_endpoint::~usb_endpoint(void){ /* - * Allocate a libusb transfer + * Allocate a libusb transfer * The allocated transfer - and buffer it contains - is repeatedly * submitted, reaped, and reused and should not be freed until shutdown. * \param buff_len size of the individual buffer held by each transfer @@ -225,7 +228,7 @@ libusb_transfer *usb_endpoint::allocate_transfer(int buff_len){ * Asynchonous transfer submission * Submit a libusb transfer to libusb add pending status * \param lut pointer to libusb_transfer - * \return true on success or false on error + * \return true on success or false on error */ void usb_endpoint::submit(libusb_transfer *lut){ UHD_ASSERT_THROW(libusb_submit_transfer(lut) == 0); @@ -281,14 +284,14 @@ libusb_transfer *usb_endpoint::get_lut_with_wait(size_t timeout_ms){ } /*********************************************************************** - * Managed buffers + * Managed buffers **********************************************************************/ /* * Libusb managed receive buffer * Construct a recv buffer from a libusb transfer. The memory held by * the libusb transfer is exposed through the managed buffer interface. * Upon destruction, the transfer and buffer are resubmitted to the - * endpoint for further use. + * endpoint for further use. */ class libusb_managed_recv_buffer_impl : public managed_recv_buffer { public: @@ -307,7 +310,7 @@ public: private: const boost::asio::const_buffer &get() const { - return _buff; + return _buff; } libusb_transfer *_lut; @@ -327,9 +330,8 @@ private: class libusb_managed_send_buffer_impl : public managed_send_buffer { public: libusb_managed_send_buffer_impl(libusb_transfer *lut, - usb_endpoint::sptr endpoint, - size_t buff_size) - : _buff(lut->buffer, buff_size), _committed(false) + usb_endpoint::sptr endpoint) + : _buff(lut->buffer, lut->length), _committed(false) { _lut = lut; _endpoint = endpoint; @@ -349,7 +351,7 @@ public: std::cerr << "UHD: send buffer already committed" << std::endl; return 0; } - + UHD_ASSERT_THROW(num_bytes <= boost::asio::buffer_size(_buff)); _lut->length = num_bytes; @@ -369,7 +371,7 @@ public: private: const boost::asio::mutable_buffer &get() const { - return _buff; + return _buff; } libusb_transfer *_lut; @@ -385,61 +387,71 @@ private: class libusb_zero_copy_impl : public usb_zero_copy { private: - usb_endpoint::sptr _rx_ep, _tx_ep; - libusb::device_handle::sptr _handle; - - size_t _recv_buff_size; - size_t _send_buff_size; - size_t _num_frames; + size_t _recv_num_frames, _send_num_frames; + usb_endpoint::sptr _recv_ep, _send_ep; public: typedef boost::shared_ptr sptr; - libusb_zero_copy_impl(libusb::device_handle::sptr handle, - unsigned int rx_endpoint, - unsigned int tx_endpoint, - size_t recv_buff_size, - size_t send_buff_size); + libusb_zero_copy_impl( + libusb::device_handle::sptr handle, + unsigned int recv_endpoint, unsigned int send_endpoint, + size_t recv_xfer_size, size_t recv_num_xfers, + size_t send_xfer_size, size_t send_num_xfers + ); managed_recv_buffer::sptr get_recv_buff(void); managed_send_buffer::sptr get_send_buff(void); - size_t get_num_recv_frames(void) const { return _num_frames; } - size_t get_num_send_frames(void) const { return _num_frames; } + size_t get_num_recv_frames(void) const { return _recv_num_frames; } + size_t get_num_send_frames(void) const { return _send_num_frames; } }; /* * Constructor * Initializes libusb, opens devices, and sets up interfaces for I/O. - * Finally, creates endpoints for asynchronous I/O. + * Finally, creates endpoints for asynchronous I/O. */ -libusb_zero_copy_impl::libusb_zero_copy_impl(libusb::device_handle::sptr handle, - unsigned int rx_endpoint, - unsigned int tx_endpoint, - size_t buff_size, - size_t block_size) - : _handle(handle), - _recv_buff_size(block_size), _send_buff_size(block_size), - _num_frames(buff_size / block_size) -{ - _handle->claim_interface(2 /*in interface*/); +libusb_zero_copy_impl::libusb_zero_copy_impl( + libusb::device_handle::sptr handle, + unsigned int recv_endpoint, unsigned int send_endpoint, + size_t recv_xfer_size, size_t recv_num_xfers, + size_t send_xfer_size, size_t send_num_xfers +){ + _handle = handle; + + //if the sizes are left at 0 (automatic) -> use the defaults + if (recv_xfer_size == 0) recv_xfer_size = DEFAULT_XFER_SIZE; + if (recv_num_xfers == 0) recv_num_xfers = DEFAULT_NUM_XFERS; + if (send_xfer_size == 0) send_xfer_size = DEFAULT_XFER_SIZE; + if (send_num_xfers == 0) send_num_xfers = DEFAULT_NUM_XFERS; + + //sanity check the transfer sizes + UHD_ASSERT_THROW(recv_xfer_size % 512 == 0); + UHD_ASSERT_THROW(send_xfer_size % 512 == 0); + + //store the num xfers for the num frames count + _recv_num_frames = recv_num_xfers; + _send_num_frames = send_num_xfers; + + _handle->claim_interface(2 /*in interface*/); _handle->claim_interface(1 /*out interface*/); - _rx_ep = usb_endpoint::sptr(new usb_endpoint( + _recv_ep = usb_endpoint::sptr(new usb_endpoint( _handle, // libusb device_handle - rx_endpoint, // USB endpoint number + recv_endpoint, // USB endpoint number true, // IN endpoint - _recv_buff_size, // buffer size per transfer - _num_frames // number of libusb transfers + recv_xfer_size, // buffer size per transfer + recv_num_xfers // number of libusb transfers )); - _tx_ep = usb_endpoint::sptr(new usb_endpoint( + _send_ep = usb_endpoint::sptr(new usb_endpoint( _handle, // libusb device_handle - tx_endpoint, // USB endpoint number + send_endpoint, // USB endpoint number false, // OUT endpoint - _send_buff_size, // buffer size per transfer - _num_frames // number of libusb transfers + send_xfer_size, // buffer size per transfer + send_num_xfers // number of libusb transfers )); } @@ -447,17 +459,17 @@ libusb_zero_copy_impl::libusb_zero_copy_impl(libusb::device_handle::sptr handle, * Construct a managed receive buffer from a completed libusb transfer * (happy with buffer full of data) obtained from the receive endpoint. * Return empty pointer if no transfer is available (timeout or error). - * \return pointer to a managed receive buffer + * \return pointer to a managed receive buffer */ managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(void){ - libusb_transfer *lut = _rx_ep->get_lut_with_wait(/* TODO timeout API */); + libusb_transfer *lut = _recv_ep->get_lut_with_wait(/* TODO timeout API */); if (lut == NULL) { return managed_recv_buffer::sptr(); } else { return managed_recv_buffer::sptr( new libusb_managed_recv_buffer_impl(lut, - _rx_ep)); + _recv_ep)); } } @@ -466,38 +478,36 @@ managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(void){ * Construct a managed send buffer from a free libusb transfer (with * empty buffer). Return empty pointer of no transfer is available * (timeout or error). - * \return pointer to a managed send buffer + * \return pointer to a managed send buffer */ managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(void){ - libusb_transfer *lut = _tx_ep->get_lut_with_wait(/* TODO timeout API */); + libusb_transfer *lut = _send_ep->get_lut_with_wait(/* TODO timeout API */); if (lut == NULL) { return managed_send_buffer::sptr(); } else { return managed_send_buffer::sptr( new libusb_managed_send_buffer_impl(lut, - _tx_ep, - _send_buff_size)); + _send_ep)); } } - /*********************************************************************** * USB zero_copy make functions **********************************************************************/ -usb_zero_copy::sptr usb_zero_copy::make(usb_device_handle::sptr handle, - unsigned int rx_endpoint, - unsigned int tx_endpoint, - size_t buff_size, - size_t block_size) - -{ +usb_zero_copy::sptr usb_zero_copy::make( + usb_device_handle::sptr handle, + unsigned int recv_endpoint, unsigned int send_endpoint, + size_t recv_xfer_size, size_t recv_num_xfers, + size_t send_xfer_size, size_t send_num_xfers +){ libusb::device_handle::sptr dev_handle(libusb::device_handle::get_cached_handle( boost::static_pointer_cast(handle)->get_device() )); - return sptr(new libusb_zero_copy_impl(dev_handle, - rx_endpoint, - tx_endpoint, - buff_size, - block_size)); + return sptr(new libusb_zero_copy_impl( + dev_handle, + recv_endpoint, send_endpoint, + recv_xfer_size, recv_num_xfers, + send_xfer_size, send_num_xfers + )); } diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index b4c23bf12..793e3027d 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include using namespace uhd; @@ -107,6 +108,15 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) /*********************************************************************** * Make **********************************************************************/ +template static output_type cast_from_dev_addr( + const device_addr_t &device_addr, + const std::string &key, + output_type def_val +){ + return (device_addr.has_key(key))? + boost::lexical_cast(device_addr[key]) : def_val; +} + static device::sptr usrp1_make(const device_addr_t &device_addr) { //extract the FPGA path for the USRP1 @@ -130,11 +140,15 @@ static device::sptr usrp1_make(const device_addr_t &device_addr) usrp_ctrl = usrp_ctrl::make(ctrl_transport); usrp_ctrl->usrp_load_fpga(usrp1_fpga_image); - data_transport = usb_zero_copy::make(handle, // identifier - 6, // IN endpoint - 2, // OUT endpoint - 2 * (1 << 20), // buffer size - 16384); // transfer size + data_transport = usb_zero_copy::make( + handle, // identifier + 6, // IN endpoint + 2, // OUT endpoint + size_t(cast_from_dev_addr(device_addr, "recv_xfer_size", 0)), + size_t(cast_from_dev_addr(device_addr, "recv_num_xfers", 0)), + size_t(cast_from_dev_addr(device_addr, "send_xfer_size", 0)), + size_t(cast_from_dev_addr(device_addr, "send_num_xfers", 0)) + ); break; } } @@ -173,7 +187,7 @@ usrp1_impl::usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport, //initialize the mboard mboard_init(); - //initialize the dboards + //initialize the dboards dboard_init(); //initialize the dsps -- cgit v1.2.3 From b8e62bb9bf86d4804defe738b2a7140cd9417a6f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 29 Sep 2010 16:32:11 -0700 Subject: usb: added libusb docs to build guide, usrp1: moved transfer param docs --- host/docs/build.rst | 21 +++++++++++++++++++- host/docs/usrp1.rst | 56 +++++++++++++++++++++++++++-------------------------- host/docs/usrp2.rst | 2 +- 3 files changed, 50 insertions(+), 29 deletions(-) diff --git a/host/docs/build.rst b/host/docs/build.rst index f37b5dce7..9cf37db4a 100644 --- a/host/docs/build.rst +++ b/host/docs/build.rst @@ -58,7 +58,8 @@ LibUSB * **Purpose:** USB-based hardware support * **Version:** at least 1.0 * **Usage:** build time + run time (optional) -* **Download URL:** http://www.libusb.org/ +* **Download URL:** http://sourceforge.net/projects/libusb/files/libusb-1.0/ +* **Download URL (windows binaries):** http://www.libusb.org/wiki/windows_backend#LatestBinarySnapshots ^^^^^^^^^^^^^^^^ Python @@ -151,6 +152,19 @@ Generate the project with cmake * Set the build variables and click configure again. * Click generate and a project file will be created in the build directory. +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LibUSB cmake notes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +On Windows, cmake does not have the advantage of pkg-config, +so we must manually tell cmake how to locate the LibUSB header and lib. + +From the cmake gui, select "Advanded View": + +* Set LIBUSB_INCLUDE_DIR to the directory with "libusb.h". +* Set LIBUSB_LIBRARIES to the full path for "libusb-1.0.lib". + +Then check the boxes to enable USRP1 support, click configure and generate. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Build the project in MSVC ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,3 +191,8 @@ Setup the PATH environment variable ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Add the boost library path to %PATH% (usually c:\\program files\\boost\\\\lib) * Add the uhd library path to %PATH% (usually c:\\program files\\uhd\\lib) +* Add the libusb library to %PATH% (if using usb support) + +**Note:** +The interface for editing environment variable paths in Windows is very poor. +I recommend using "Rapid Environment Editor" (http://www.rapidee.com) over the default editor. diff --git a/host/docs/usrp1.rst b/host/docs/usrp1.rst index 7cf447719..0baa93a45 100644 --- a/host/docs/usrp1.rst +++ b/host/docs/usrp1.rst @@ -60,6 +60,29 @@ Example device address string representations to specify non-standard firmware a fpga=usrp1_fpga_4rx.rbf, fw=usrp1_fw_custom.ihx +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Change USB transfer parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The advanced user may manipulate parameters of the usb bulk transfers +for various reasons, such as lowering latency or increasing buffer size. +By default, the UHD will use values for these parameters +that are known to perform well on a variety of systems. +The following device address parameters can be used to manipulate USB bulk transfers: + +* **recv_xfer_size:** the size of each receive bulk transfer in bytes +* **recv_num_xfers:** the number of simultaneous receive bulk transfers +* **send_xfer_size:** the size of each send bulk transfer in bytes +* **send_num_xfers:** the number of simultaneous send bulk transfers + +Example usage, set the device address markup string to the following: +:: + + serial=12345678, recv_num_xfers=16 + + -- OR -- + + serial=12345678, recv_xfer_size=2048, recv_num_xfers=16 + ------------------------------------------------------------------------ Specifying the subdevice to use ------------------------------------------------------------------------ @@ -95,36 +118,15 @@ Notice that the subdevice name is always specified in the 3 possible cases. B:B - ------------------------------------------------------------------------- -Change USB transfer parameters ------------------------------------------------------------------------- -The advanced user may manipulate parameters of the usb bulk transfers -for various reasons, such as lowering latency or increasing buffer size. -By default, the UHD will use values for these parameters -that are known to perform well on a variety of systems. - -The following device address can be used to manipulate USB bulk transfers: - -* **recv_xfer_size:** the size of each receive bulk transfer in bytes -* **recv_num_xfers:** the number of simultaneous receive bulk transfers -* **send_xfer_size:** the size of each send bulk transfer in bytes -* **send_num_xfers:** the number of simultaneous send bulk transfers - -Example, set the args string to the following: -:: - - serial=12345678, recv_num_xfers=16 - ------------------------------------------------------------------------ OS Specific Notes ------------------------------------------------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Setup Udev on Linux +Linux - setup udev ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -On Linux, Udev handles USB plug and unplug events. -The following command creates a Udev rule for the USRP1 +On Linux, udev handles USB plug and unplug events. +The following commands create a udev rule for the USRP1 so that non-root users may access the device: :: @@ -135,8 +137,8 @@ so that non-root users may access the device: sudo udevadm control --reload-rules ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Install libusb driver on Windows +Windows - install driver ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ On Windows, a driver must be installed the first time the USRP1 is attached to the host computer. -A download link for this driver can be found on the Ettus Research UHD wiki page. -Download and unpack the driver, and direct the Windows driver install wizard to the *.inf file. +A download link for this driver can be found on the UHD wiki page. +Download and unpack the driver, and direct the Windows driver install wizard to the .inf file. diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index 72a919d1a..70e5ea28b 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -201,7 +201,7 @@ Each parameter will accept a numeric value for the number of bytes. * recv_buff_size * send_buff_size -Example, set the args string to the following: +Example usage, set the device address markup string to the following: :: addr=192.168.10.2, recv_buff_size=100e6 -- cgit v1.2.3 From 83596f1feb73a15a1ef8741c1c520e8cae46c2a6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 29 Sep 2010 17:43:26 -0700 Subject: usrp: added get codec rate to dboard iface --- host/include/uhd/usrp/dboard_iface.hpp | 9 +++++++++ host/lib/usrp/usrp1/dboard_iface.cpp | 5 +++++ host/lib/usrp/usrp2/dboard_iface.cpp | 4 ++++ 3 files changed, 18 insertions(+) diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp index c7db244f2..c430ecd3f 100644 --- a/host/include/uhd/usrp/dboard_iface.hpp +++ b/host/include/uhd/usrp/dboard_iface.hpp @@ -242,6 +242,15 @@ public: * \param enb true for enabled */ virtual void set_clock_enabled(unit_t unit, bool enb) = 0; + + /*! + * Get the rate of the codec. + * For rx, this is the rate the ADC feeds the DSP. + * For tx, this is the rate the DSP feeds the DAC. + * \param unit which unit rx or tx + * \return the codec rate in Hz + */ + virtual double get_codec_rate(unit_t unit) = 0; }; }} //namespace diff --git a/host/lib/usrp/usrp1/dboard_iface.cpp b/host/lib/usrp/usrp1/dboard_iface.cpp index 4791b55ce..4f0549a37 100644 --- a/host/lib/usrp/usrp1/dboard_iface.cpp +++ b/host/lib/usrp/usrp1/dboard_iface.cpp @@ -93,6 +93,7 @@ public: std::vector get_clock_rates(unit_t); double get_clock_rate(unit_t); void set_clock_enabled(unit_t, bool); + double get_codec_rate(unit_t); private: usrp1_iface::sptr _iface; @@ -170,6 +171,10 @@ void usrp1_dboard_iface::set_clock_enabled(unit_t, bool) //TODO we can only enable for special case anyway... } +double usrp1_dboard_iface::get_codec_rate(unit_t){ + return _clock->get_master_clock_freq(); +} + /*********************************************************************** * GPIO **********************************************************************/ diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index f6d2b718a..fdfbf0d17 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -61,6 +61,7 @@ public: double get_clock_rate(unit_t); std::vector get_clock_rates(unit_t); void set_clock_enabled(unit_t, bool); + double get_codec_rate(unit_t); void write_spi( unit_t unit, @@ -158,6 +159,9 @@ void usrp2_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ } } +double usrp2_dboard_iface::get_codec_rate(unit_t){ + return _clock_ctrl->get_master_clock_rate(); +} /*********************************************************************** * GPIO **********************************************************************/ -- cgit v1.2.3 From 56751efbe6e0751a2b8cd0f7a31d5dfd07fec5dd Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Wed, 29 Sep 2010 18:27:08 -0700 Subject: TVRX: works for USRP and USRP2. --- host/lib/usrp/dboard/db_tvrx.cpp | 11 ++++++++++- host/lib/usrp/usrp1/codec_ctrl.cpp | 3 ++- host/lib/usrp/usrp1/dboard_iface.cpp | 6 ++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 71aff1680..6b71a3c6e 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -377,6 +377,7 @@ void tvrx::set_freq(double freq) { **********************************************************************/ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); + int codec_rate; //handle the get request conditioned on the key switch(key.as()){ @@ -403,7 +404,15 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_FREQ: - val = _lo_freq; + /* + * so here we have to do some magic. because the TVRX uses a relatively high IF, + * we have to watch the sample rate to see if the IF will be aliased + * or if it will fall within Nyquist. + */ + codec_rate = this->get_iface()->get_codec_rate(dboard_iface::UNIT_RX); + if(codec_rate/2 > tvrx_if_freq) val = _lo_freq; + //ok take a deep breath i am positive there is an easier way to get this number + else val = _lo_freq - tvrx_if_freq - (tvrx_if_freq-codec_rate)*int(tvrx_if_freq / (codec_rate/2)); return; case SUBDEV_PROP_FREQ_RANGE: diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp index 33b18b196..4aa730573 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.cpp +++ b/host/lib/usrp/usrp1/codec_ctrl.cpp @@ -423,7 +423,8 @@ void usrp1_codec_ctrl_impl::set_duc_freq(double freq) /*********************************************************************** * Codec Control ADC buffer bypass - * Enable this for DC-coupled daughterboards (TVRX) + * Disable this for AC-coupled daughterboards (TVRX) + * By default it is initialized TRUE. **********************************************************************/ void usrp1_codec_ctrl_impl::bypass_adc_buffers(bool bypass) { _ad9862_regs.byp_buffer_a = bypass; diff --git a/host/lib/usrp/usrp1/dboard_iface.cpp b/host/lib/usrp/usrp1/dboard_iface.cpp index 4f0549a37..1ac15a46a 100644 --- a/host/lib/usrp/usrp1/dboard_iface.cpp +++ b/host/lib/usrp/usrp1/dboard_iface.cpp @@ -32,6 +32,8 @@ using namespace uhd; using namespace uhd::usrp; using namespace boost::assign; +static const dboard_id_t tvrx_id(0x0040); + class usrp1_dboard_iface : public dboard_iface { public: @@ -51,6 +53,10 @@ public: //init the clock rate shadows this->set_clock_rate(UNIT_RX, this->get_clock_rates(UNIT_RX).front()); this->set_clock_rate(UNIT_TX, this->get_clock_rates(UNIT_TX).front()); + + //yes this is evil but it's necessary for TVRX to work on USRP1 + if(_rx_dboard_id == tvrx_id) _codec->bypass_adc_buffers(false); + //else _codec->bypass_adc_buffers(false); //don't think this is necessary } ~usrp1_dboard_iface() -- cgit v1.2.3 From 04c74a3c74907e55e339f1568a1d5b4cdf190daf Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 30 Sep 2010 10:07:13 -0700 Subject: usrp1: replace byteswap with htonx (it was wrong to just swap) also removed unused poke and peek 16 bit calls --- host/lib/usrp/usrp1/usrp1_iface.cpp | 16 ++-------------- host/lib/usrp/usrp1/usrp1_iface.hpp | 14 -------------- 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/host/lib/usrp/usrp1/usrp1_iface.cpp b/host/lib/usrp/usrp1/usrp1_iface.cpp index 5fd3987d5..64ced2905 100644 --- a/host/lib/usrp/usrp1/usrp1_iface.cpp +++ b/host/lib/usrp/usrp1/usrp1_iface.cpp @@ -49,7 +49,7 @@ public: ******************************************************************/ void poke32(boost::uint32_t addr, boost::uint32_t value) { - boost::uint32_t swapped = byteswap(value); + boost::uint32_t swapped = uhd::htonx(value); if (iface_debug) { std::cout.fill('0'); @@ -72,12 +72,6 @@ public: std::cerr << "USRP: failed memory write: " << ret << std::endl; } - void poke16(boost::uint32_t, boost::uint16_t) - { - //fpga only handles 32 bit writes - std::cerr << "USRP: unsupported operation: poke16()" << std::endl; - } - boost::uint32_t peek32(boost::uint32_t addr) { boost::uint32_t value_out; @@ -95,13 +89,7 @@ public: if (ret < 0) std::cerr << "USRP: failed memory read: " << ret << std::endl; - return byteswap(value_out); - } - - boost::uint16_t peek16(boost::uint32_t addr) - { - boost::uint32_t val = peek32(addr); - return boost::uint16_t(val & 0xff); + return uhd::ntohx(value_out); } /******************************************************************* diff --git a/host/lib/usrp/usrp1/usrp1_iface.hpp b/host/lib/usrp/usrp1/usrp1_iface.hpp index 9a3fdd6bc..3f608584a 100644 --- a/host/lib/usrp/usrp1/usrp1_iface.hpp +++ b/host/lib/usrp/usrp1/usrp1_iface.hpp @@ -53,20 +53,6 @@ public: */ virtual boost::uint32_t peek32(boost::uint32_t addr) = 0; - /*! - * Write a register (16 bits) - * \param addr the address - * \param data the 16bit data - */ - virtual void poke16(boost::uint32_t addr, boost::uint16_t data) = 0; - - /*! - * read a register (16 bits) - * \param addr the address - * \return the 16bit data - */ - virtual boost::uint16_t peek16(boost::uint32_t addr) = 0; - /*! * Perform an spi transaction. * \param which_slave the slave device number -- cgit v1.2.3 From a4f8ad59b2abc6d4b1a6c65aa2652083486e3065 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 30 Sep 2010 11:05:33 -0700 Subject: usrp: added subdev enabled property the dboard manager will disable all subdevs at startup and shutdown setting the subdev spec will enable only the subdevs in use all dboards are currently implemented as always enabled nothing tested --- host/include/uhd/usrp/subdev_props.hpp | 1 + host/include/uhd/usrp/subdev_spec.hpp | 6 +++++- host/lib/usrp/dboard/db_basic_and_lf.cpp | 14 ++++++++++++++ host/lib/usrp/dboard/db_dbsrx.cpp | 7 +++++++ host/lib/usrp/dboard/db_rfx.cpp | 14 ++++++++++++++ host/lib/usrp/dboard/db_unknown.cpp | 14 ++++++++++++++ host/lib/usrp/dboard/db_wbx.cpp | 14 ++++++++++++++ host/lib/usrp/dboard/db_xcvr2450.cpp | 14 ++++++++++++++ host/lib/usrp/dboard_manager.cpp | 12 +++++++++++- host/lib/usrp/misc_utils.cpp | 17 +++++++++++++++++ host/lib/usrp/subdev_spec.cpp | 4 ++++ 11 files changed, 115 insertions(+), 2 deletions(-) diff --git a/host/include/uhd/usrp/subdev_props.hpp b/host/include/uhd/usrp/subdev_props.hpp index cd07cb7a8..8f096ffe4 100644 --- a/host/include/uhd/usrp/subdev_props.hpp +++ b/host/include/uhd/usrp/subdev_props.hpp @@ -53,6 +53,7 @@ namespace uhd{ namespace usrp{ SUBDEV_PROP_ANTENNA_NAMES = 'A', //ro, prop_names_t SUBDEV_PROP_LO_LOCKED = 'L', //ro, bool SUBDEV_PROP_CONNECTION = 'c', //ro, subdev_conn_t + SUBDEV_PROP_ENABLED = 'e', //rw, bool SUBDEV_PROP_USE_LO_OFFSET = 'l', //ro, bool SUBDEV_PROP_RSSI = 'R', //ro, float SUBDEV_PROP_BANDWIDTH = 'B' //rw, double diff --git a/host/include/uhd/usrp/subdev_spec.hpp b/host/include/uhd/usrp/subdev_spec.hpp index 2f32509b9..5de3bb3b8 100644 --- a/host/include/uhd/usrp/subdev_spec.hpp +++ b/host/include/uhd/usrp/subdev_spec.hpp @@ -19,6 +19,7 @@ #define INCLUDED_UHD_USRP_SUBDEV_SPEC_HPP #include +#include #include #include @@ -27,7 +28,7 @@ namespace uhd{ namespace usrp{ /*! * A subdevice specification (daughterboard, subdevice) name pairing. */ - struct UHD_API subdev_spec_pair_t{ + struct UHD_API subdev_spec_pair_t : boost::equality_comparable{ //! The daughterboard name std::string db_name; @@ -45,6 +46,9 @@ namespace uhd{ namespace usrp{ ); }; + //! overloaded comparison operator for subdev_spec_pair_t + UHD_API bool operator==(const subdev_spec_pair_t &, const subdev_spec_pair_t &); + /*! * A list of (daughterboard name, subdevice name) pairs: * diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 4b0d8bf27..41f6f8002 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -149,6 +149,10 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ val = sd_name_to_conn[get_subdev_name()]; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -178,6 +182,9 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -241,6 +248,10 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ val = sd_name_to_conn[get_subdev_name()]; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -270,6 +281,9 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 81434f054..23cafea53 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -551,6 +551,10 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -587,6 +591,9 @@ void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_gain(val.as(), key.name); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + case SUBDEV_PROP_BANDWIDTH: this->set_bandwidth(val.as()); return; diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index c3ab96e59..cfc34381e 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -444,6 +444,10 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_QI; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -474,6 +478,9 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_rx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -524,6 +531,10 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = true; return; @@ -554,6 +565,9 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ this->set_tx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp index f6f4f4a61..ec7ab440b 100644 --- a/host/lib/usrp/dboard/db_unknown.cpp +++ b/host/lib/usrp/dboard/db_unknown.cpp @@ -122,6 +122,10 @@ void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -151,6 +155,9 @@ void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -211,6 +218,10 @@ void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -240,6 +251,9 @@ void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index e473ce41e..907268aac 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -513,6 +513,10 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -543,6 +547,9 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_rx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -597,6 +604,10 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -627,6 +638,9 @@ void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ this->set_tx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 798ff74a3..0ee133f3d 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -484,6 +484,10 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -518,6 +522,9 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_rx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -572,6 +579,10 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_QI; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -602,6 +613,9 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ this->set_tx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 181f843a0..78daa1b4d 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -86,7 +86,7 @@ std::string dboard_id_t::to_pp_string(void) const{ } /*********************************************************************** - * internal helper classe + * internal helper classes **********************************************************************/ /*! * A special wax proxy object that forwards calls to a subdev. @@ -330,4 +330,14 @@ void dboard_manager_impl::set_nice_dboard_if(void){ _iface->set_pin_ctrl(unit, 0x0000); //all gpio _iface->set_clock_enabled(unit, false); //clock off } + + //disable all rx subdevices + BOOST_FOREACH(const std::string &sd_name, this->get_rx_subdev_names()){ + this->get_rx_subdev(sd_name)[SUBDEV_PROP_ENABLED] = false; + } + + //disable all tx subdevices + BOOST_FOREACH(const std::string &sd_name, this->get_tx_subdev_names()){ + this->get_tx_subdev(sd_name)[SUBDEV_PROP_ENABLED] = false; + } } diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp index 5cfcdc8d3..05308baba 100644 --- a/host/lib/usrp/misc_utils.cpp +++ b/host/lib/usrp/misc_utils.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -186,6 +187,22 @@ static void verify_xx_subdev_spec( "Validate %s subdev spec failed: %s\n %s" ) % xx_type % subdev_spec.to_string() % e.what())); } + + //now use the subdev spec to enable the subdevices in use and vice-versa + BOOST_FOREACH(const std::string &db_name, mboard[dboard_names_prop].as()){ + wax::obj dboard = mboard[named_prop_t(dboard_prop, db_name)]; + BOOST_FOREACH(const std::string &sd_name, dboard[DBOARD_PROP_SUBDEV_NAMES].as()){ + try{ + bool enable = std::has(subdev_spec, subdev_spec_pair_t(db_name, sd_name)); + dboard[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)][SUBDEV_PROP_ENABLED] = enable; + } + catch(const std::exception &e){ + throw std::runtime_error(str(boost::format( + "Cannot set enabled property on subdevice %s:%s\n %s" + ) % db_name % sd_name % e.what())); + } + } + } } void usrp::verify_rx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard){ diff --git a/host/lib/usrp/subdev_spec.cpp b/host/lib/usrp/subdev_spec.cpp index 7a3e72867..95d2cbb12 100644 --- a/host/lib/usrp/subdev_spec.cpp +++ b/host/lib/usrp/subdev_spec.cpp @@ -34,6 +34,10 @@ subdev_spec_pair_t::subdev_spec_pair_t( /* NOP */ } +bool usrp::operator==(const subdev_spec_pair_t &lhs, const subdev_spec_pair_t &rhs){ + return (lhs.db_name == rhs.db_name) and (lhs.sd_name == rhs.sd_name); +} + subdev_spec_t::subdev_spec_t(const std::string &markup){ BOOST_FOREACH(const std::string &pair, std::split_string(markup)){ if (pair == "") continue; -- cgit v1.2.3 From dd9f9c340a8def560235d737df446454ea75dadc Mon Sep 17 00:00:00 2001 From: root Date: Thu, 30 Sep 2010 18:25:24 +0000 Subject: Ignore direction for GPIO 114 since it is always an input. --- host/apps/omap_debug/fpga-downloader.cc | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/host/apps/omap_debug/fpga-downloader.cc b/host/apps/omap_debug/fpga-downloader.cc index fb96b64a3..4e475b5c1 100644 --- a/host/apps/omap_debug/fpga-downloader.cc +++ b/host/apps/omap_debug/fpga-downloader.cc @@ -97,15 +97,17 @@ gpio::gpio(unsigned int gpio_num, gpio_direction pin_direction) std::fstream direction_file; std::string direction_file_name; - direction_file_name = base_path.str() + "/direction"; - - direction_file.open(direction_file_name.c_str()); - if (!direction_file.is_open()) - std::cout << "Failed to open direction file." << std::endl; - if (pin_direction == OUT) - direction_file << "out" << std::endl; - else - direction_file << "in" << std::endl; + if (gpio_num != 114) { + direction_file_name = base_path.str() + "/direction"; + + direction_file.open(direction_file_name.c_str()); + if (!direction_file.is_open()) + std::cout << "Failed to open direction file." << std::endl; + if (pin_direction == OUT) + direction_file << "out" << std::endl; + else + direction_file << "in" << std::endl; + } std::string value_file_name; -- cgit v1.2.3 From e4fffed05dda57bb37d693a3a26ea6a903c925f7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 30 Sep 2010 11:32:21 -0700 Subject: usb: set rt thread priority for the libusb event loop --- host/lib/transport/libusb1_base.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index 26e864459..49f524a32 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -16,6 +16,7 @@ // #include "libusb1_base.hpp" +#include #include #include #include @@ -23,6 +24,7 @@ #include #include +using namespace uhd; using namespace uhd::transport; /*********************************************************************** @@ -52,6 +54,7 @@ private: bool _running; void run_event_loop(void){ + set_thread_priority_safe(); _running = true; timeval tv; while(_running){ -- cgit v1.2.3 From 046d8a9a5a5b0addb7e6c8bfde7973f3051d48b1 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Thu, 30 Sep 2010 11:57:40 -0700 Subject: TVRX: Fixed to properly calculate alias frequencies. --- host/lib/usrp/dboard/db_tvrx.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 6b71a3c6e..1cb74c5ae 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -372,12 +372,30 @@ void tvrx::set_freq(double freq) { _lo_freq = actual_lo_freq; //for rx props } +/*********************************************************************** + * Get the alias frequency of frequency freq when sampled at fs. + * \param freq the frequency of interest + * \param fs the sample rate + * \return the alias frequency + **********************************************************************/ + +static double get_alias(double freq, double fs) { + double alias; + freq = fmod(freq, fs); + if(freq >= (fs/2)) { + alias = fs - freq; + } else { + alias = freq; + } + return alias; +} + /*********************************************************************** * RX Get and Set **********************************************************************/ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); - int codec_rate; + double codec_rate; //handle the get request conditioned on the key switch(key.as()){ @@ -410,9 +428,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ * or if it will fall within Nyquist. */ codec_rate = this->get_iface()->get_codec_rate(dboard_iface::UNIT_RX); - if(codec_rate/2 > tvrx_if_freq) val = _lo_freq; - //ok take a deep breath i am positive there is an easier way to get this number - else val = _lo_freq - tvrx_if_freq - (tvrx_if_freq-codec_rate)*int(tvrx_if_freq / (codec_rate/2)); + val = (_lo_freq - tvrx_if_freq) + get_alias(tvrx_if_freq, codec_rate); return; case SUBDEV_PROP_FREQ_RANGE: -- cgit v1.2.3 From 2c8a7c7debf19d92065661cc1d258f97bd38e224 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 30 Sep 2010 14:36:24 -0700 Subject: uhd: implemented recv timeout for zero copy interface --- host/include/uhd/transport/zero_copy.hpp | 11 +++++--- host/lib/transport/libusb1_zero_copy.cpp | 42 +++++++++++++++---------------- host/lib/transport/udp_zero_copy_asio.cpp | 5 ++-- host/lib/transport/zero_copy.cpp | 4 +-- host/lib/usrp/usrp1/io_impl.cpp | 8 +++--- host/lib/usrp/usrp2/io_impl.cpp | 5 ++-- 6 files changed, 39 insertions(+), 36 deletions(-) diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp index 513291b63..8ecafd3fb 100644 --- a/host/include/uhd/transport/zero_copy.hpp +++ b/host/include/uhd/transport/zero_copy.hpp @@ -122,9 +122,10 @@ namespace uhd{ namespace transport{ /*! * Get a new receive buffer from this transport object. + * \param timeout_ms the timeout to get the buffer in ms * \return a managed buffer, or null sptr on timeout/error */ - virtual managed_recv_buffer::sptr get_recv_buff(void) = 0; + virtual managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms) = 0; /*! * Get the maximum number of receive frames: @@ -171,16 +172,19 @@ namespace uhd{ namespace transport{ /*! * Get a new receive buffer from this transport object. + * \param timeout_ms the timeout to get the buffer in ms + * \return a managed buffer, or null sptr on timeout/error */ - managed_recv_buffer::sptr get_recv_buff(void); + managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms); private: /*! * Perform a private copying recv. * \param buff the buffer to write data into + * \param timeout_ms the timeout to get the buffer in ms * \return the number of bytes written to buff, 0 for timeout, negative for error */ - virtual ssize_t recv(const boost::asio::mutable_buffer &buff) = 0; + virtual ssize_t recv(const boost::asio::mutable_buffer &buff, size_t timeout_ms) = 0; UHD_PIMPL_DECL(impl) _impl; }; @@ -204,6 +208,7 @@ namespace uhd{ namespace transport{ /*! * Get a new send buffer from this transport object. + * \return a managed buffer, or null sptr on timeout/error */ managed_send_buffer::sptr get_send_buff(void); diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index f2dcff6b5..f9beb0b4c 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -308,8 +308,7 @@ public: } private: - const boost::asio::const_buffer &get() const - { + const boost::asio::const_buffer &get(void) const{ return _buff; } @@ -369,8 +368,7 @@ public: } private: - const boost::asio::mutable_buffer &get() const - { + const boost::asio::mutable_buffer &get(void) const{ return _buff; } @@ -395,13 +393,13 @@ public: typedef boost::shared_ptr sptr; libusb_zero_copy_impl( - libusb::device_handle::sptr handle, - unsigned int recv_endpoint, unsigned int send_endpoint, - size_t recv_xfer_size, size_t recv_num_xfers, - size_t send_xfer_size, size_t send_num_xfers - ); + libusb::device_handle::sptr handle, + unsigned int recv_endpoint, unsigned int send_endpoint, + size_t recv_xfer_size, size_t recv_num_xfers, + size_t send_xfer_size, size_t send_num_xfers + ); - managed_recv_buffer::sptr get_recv_buff(void); + managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms); managed_send_buffer::sptr get_send_buff(void); size_t get_num_recv_frames(void) const { return _recv_num_frames; } @@ -419,23 +417,23 @@ libusb_zero_copy_impl::libusb_zero_copy_impl( size_t recv_xfer_size, size_t recv_num_xfers, size_t send_xfer_size, size_t send_num_xfers ){ - _handle = handle; + _handle = handle; - //if the sizes are left at 0 (automatic) -> use the defaults - if (recv_xfer_size == 0) recv_xfer_size = DEFAULT_XFER_SIZE; - if (recv_num_xfers == 0) recv_num_xfers = DEFAULT_NUM_XFERS; - if (send_xfer_size == 0) send_xfer_size = DEFAULT_XFER_SIZE; - if (send_num_xfers == 0) send_num_xfers = DEFAULT_NUM_XFERS; + //if the sizes are left at 0 (automatic) -> use the defaults + if (recv_xfer_size == 0) recv_xfer_size = DEFAULT_XFER_SIZE; + if (recv_num_xfers == 0) recv_num_xfers = DEFAULT_NUM_XFERS; + if (send_xfer_size == 0) send_xfer_size = DEFAULT_XFER_SIZE; + if (send_num_xfers == 0) send_num_xfers = DEFAULT_NUM_XFERS; //sanity check the transfer sizes UHD_ASSERT_THROW(recv_xfer_size % 512 == 0); UHD_ASSERT_THROW(send_xfer_size % 512 == 0); - //store the num xfers for the num frames count - _recv_num_frames = recv_num_xfers; - _send_num_frames = send_num_xfers; + //store the num xfers for the num frames count + _recv_num_frames = recv_num_xfers; + _send_num_frames = send_num_xfers; - _handle->claim_interface(2 /*in interface*/); + _handle->claim_interface(2 /*in interface*/); _handle->claim_interface(1 /*out interface*/); _recv_ep = usb_endpoint::sptr(new usb_endpoint( @@ -461,8 +459,8 @@ libusb_zero_copy_impl::libusb_zero_copy_impl( * Return empty pointer if no transfer is available (timeout or error). * \return pointer to a managed receive buffer */ -managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(void){ - libusb_transfer *lut = _recv_ep->get_lut_with_wait(/* TODO timeout API */); +managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(size_t timeout_ms){ + libusb_transfer *lut = _recv_ep->get_lut_with_wait(timeout_ms); if (lut == NULL) { return managed_recv_buffer::sptr(); } diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index ee989ee2b..0a6c9f2af 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -35,7 +35,6 @@ static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(sizeof(boost::uint32_t) * 2 //Perhaps this is due to the kernel scheduling, //but may change with host-based flow control. static const size_t MIN_SEND_SOCK_BUFF_SIZE = size_t(10e3); -static const double RECV_TIMEOUT = 0.1; //100 ms /*********************************************************************** * Zero Copy UDP implementation with ASIO: @@ -110,11 +109,11 @@ private: boost::asio::io_service _io_service; int _sock_fd; - ssize_t recv(const boost::asio::mutable_buffer &buff){ + ssize_t recv(const boost::asio::mutable_buffer &buff, size_t timeout_ms){ //setup timeval for timeout timeval tv; tv.tv_sec = 0; - tv.tv_usec = int(RECV_TIMEOUT*1e6); + tv.tv_usec = timeout_ms*1000; //setup rset for timeout fd_set rset; diff --git a/host/lib/transport/zero_copy.cpp b/host/lib/transport/zero_copy.cpp index 8a1cde694..1fcf846a0 100644 --- a/host/lib/transport/zero_copy.cpp +++ b/host/lib/transport/zero_copy.cpp @@ -68,12 +68,12 @@ phony_zero_copy_recv_if::~phony_zero_copy_recv_if(void){ /* NOP */ } -managed_recv_buffer::sptr phony_zero_copy_recv_if::get_recv_buff(void){ +managed_recv_buffer::sptr phony_zero_copy_recv_if::get_recv_buff(size_t timeout_ms){ //allocate memory boost::uint8_t *recv_mem = new boost::uint8_t[_impl->max_buff_size]; //call recv() with timeout option - ssize_t num_bytes = this->recv(boost::asio::buffer(recv_mem, _impl->max_buff_size)); + ssize_t num_bytes = this->recv(boost::asio::buffer(recv_mem, _impl->max_buff_size), timeout_ms); if (num_bytes <= 0) return managed_recv_buffer::sptr(); //NULL sptr diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 73974f2d6..aee760a83 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -272,18 +272,18 @@ static void usrp1_bs_vrt_unpacker( } static bool get_recv_buffs( - zero_copy_if::sptr zc_if, + zero_copy_if::sptr zc_if, size_t timeout_ms, vrt_packet_handler::managed_recv_buffs_t &buffs ){ UHD_ASSERT_THROW(buffs.size() == 1); - buffs[0] = zc_if->get_recv_buff(); + buffs[0] = zc_if->get_recv_buff(timeout_ms); return buffs[0].get() != NULL; } size_t usrp1_impl::recv( const std::vector &buffs, size_t num_samps, rx_metadata_t &metadata, const io_type_t &io_type, - recv_mode_t recv_mode, size_t /*timeout_ms TODO*/ + recv_mode_t recv_mode, size_t timeout_ms ){ size_t num_samps_recvd = vrt_packet_handler::recv( _io_impl->packet_handler_recv_state, //last state of the recv handler @@ -292,7 +292,7 @@ size_t usrp1_impl::recv( io_type, _rx_otw_type, //input and output types to convert _clock_ctrl->get_master_clock_freq(), //master clock tick rate &usrp1_bs_vrt_unpacker, - boost::bind(&get_recv_buffs, _data_transport, _1), + boost::bind(&get_recv_buffs, _data_transport, timeout_ms, _1), &vrt_packet_handler::handle_overflow_nop, 0, //vrt header offset _rx_subdev_spec.size() //num channels diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 65411801d..3395f94e2 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -33,6 +33,7 @@ using namespace uhd::transport; namespace asio = boost::asio; static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; +static const double RECV_TIMEOUT_MS = 100; /*********************************************************************** * io impl details (internal to this file) @@ -90,7 +91,7 @@ void usrp2_impl::io_impl::recv_pirate_loop( size_t next_packet_seq = 0; while(recv_pirate_crew_raiding){ - managed_recv_buffer::sptr buff = zc_if->get_recv_buff(); + managed_recv_buffer::sptr buff = zc_if->get_recv_buff(RECV_TIMEOUT_MS); if (not buff.get()) continue; //ignore timeout/error buffers try{ @@ -150,7 +151,7 @@ void usrp2_impl::io_init(void){ std::memcpy(send_buff->cast(), &data, sizeof(data)); send_buff->commit(sizeof(data)); //drain the recv buffers (may have junk) - while (data_transport->get_recv_buff().get()){}; + while (data_transport->get_recv_buff(RECV_TIMEOUT_MS).get()){}; } //the number of recv frames is the number for the first transport -- cgit v1.2.3 From 790a5ac665144180cde712d46b799a115bb74e46 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 30 Sep 2010 14:59:13 -0700 Subject: uhd: updated AUTHORS and README for tvrx and usrp1 --- host/AUTHORS | 3 ++- host/README | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/host/AUTHORS b/host/AUTHORS index e0775f3a1..512d4752e 100644 --- a/host/AUTHORS +++ b/host/AUTHORS @@ -24,6 +24,7 @@ Tom Tsou - ttsou@vt.edu USRP1 host code USRP1 firmware -Nick Foster - nick@nerdnetworks.org +Nick Foster - nick@ettus.com LIBUSB host code USRP1 host code + TVRX host code diff --git a/host/README b/host/README index 5018ef541..cab1e0b10 100644 --- a/host/README +++ b/host/README @@ -6,7 +6,8 @@ The hardware driver for Ettus Research products. ######################################################################## # Supported USRP Motherboards ######################################################################## -USRP2 - udp over gigabit ethernet +USRP1 +USRP2 ######################################################################## # Supported USRP Daughterboards @@ -19,6 +20,7 @@ RFX Series XCVR 2450 WBX Series DBSRX +TVRX ######################################################################## # Documentation -- cgit v1.2.3 From cc97c6ee0b3dbc8e0ed6bfae01505fcb209d13cb Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 30 Sep 2010 15:12:30 -0700 Subject: usrp-e: update to build with the master --- host/lib/usrp/usrp_e/dboard_iface.cpp | 5 +++++ host/lib/usrp/usrp_e/io_impl.cpp | 18 +++++------------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/host/lib/usrp/usrp_e/dboard_iface.cpp b/host/lib/usrp/usrp_e/dboard_iface.cpp index 1bd177f60..6898df8df 100644 --- a/host/lib/usrp/usrp_e/dboard_iface.cpp +++ b/host/lib/usrp/usrp_e/dboard_iface.cpp @@ -91,6 +91,7 @@ public: std::vector get_clock_rates(unit_t); double get_clock_rate(unit_t); void set_clock_enabled(unit_t, bool); + double get_codec_rate(unit_t); private: usrp_e_iface::sptr _iface; @@ -140,6 +141,10 @@ void usrp_e_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ } } +double usrp_e_dboard_iface::get_codec_rate(unit_t){ + return _clock->get_fpga_clock_rate(); +} + /*********************************************************************** * GPIO **********************************************************************/ diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 31ea4c6c0..e57d6ce35 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -39,6 +39,7 @@ static const size_t MAX_BUFF_SIZE = 2048; static const bool usrp_e_io_impl_verbose = false; static const size_t tx_async_report_sid = 1; static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; +static const double recv_timeout_ms = 100; /*********************************************************************** * Data Transport (phony zero-copy with read/write) @@ -74,7 +75,7 @@ private: boost::asio::buffer_size(buff) ); } - ssize_t recv(const boost::asio::mutable_buffer &buff){ + ssize_t recv(const boost::asio::mutable_buffer &buff, size_t to_ms){ //std::cout << boost::format( // "calling read on fd %d, buff size is %d" //) % _fd % boost::asio::buffer_size(buff) << std::endl; @@ -84,7 +85,7 @@ private: pollfd pfd; pfd.fd = _fd; pfd.events = POLLIN; - ssize_t poll_ret = poll(&pfd, 1, 100/*ms*/); + ssize_t poll_ret = poll(&pfd, 1, to_ms); if (poll_ret <= 0){ if (usrp_e_io_impl_verbose) std::cerr << boost::format( "usrp-e io impl recv(): poll() returned non-positive value: %d\n" @@ -170,7 +171,7 @@ void usrp_e_impl::io_impl::recv_pirate_loop( //size_t next_packet_seq = 0; while(recv_pirate_crew_raiding){ - managed_recv_buffer::sptr buff = this->transport.get_recv_buff(); + managed_recv_buffer::sptr buff = this->transport.get_recv_buff(recv_timeout_ms); if (not buff.get()) continue; //ignore timeout/error buffers try{ @@ -262,7 +263,7 @@ bool get_send_buffs( ){ UHD_ASSERT_THROW(buffs.size() == 1); buffs[0] = trans->get_send_buff(); - return buffs[0].get(); + return buffs[0].get() != NULL; } size_t usrp_e_impl::send( @@ -292,15 +293,6 @@ size_t usrp_e_impl::send( /*********************************************************************** * Data Recv **********************************************************************/ -bool get_recv_buffs( - data_transport *trans, - vrt_packet_handler::managed_recv_buffs_t &buffs -){ - UHD_ASSERT_THROW(buffs.size() == 1); - buffs[0] = trans->get_recv_buff(); - return buffs[0].get(); -} - size_t usrp_e_impl::recv( const std::vector &buffs, size_t num_samps, -- cgit v1.2.3 From b079d9d1751415139518f34d792200b041aff10b Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Thu, 30 Sep 2010 16:23:21 -0700 Subject: Made usb_device_handle UHD_API. --- host/include/uhd/transport/usb_device_handle.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp index 9bb7db9c4..6f8d868be 100644 --- a/host/include/uhd/transport/usb_device_handle.hpp +++ b/host/include/uhd/transport/usb_device_handle.hpp @@ -38,7 +38,7 @@ namespace uhd { namespace transport { * a true descriptor serial number string. This interface returns the * actual string descriptor. */ -class usb_device_handle : boost::noncopyable { +class UHD_API usb_device_handle : boost::noncopyable { public: typedef boost::shared_ptr sptr; -- cgit v1.2.3 From 46d2fc423d2fdcf32454621c6f41e555d2496702 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 30 Sep 2010 17:56:36 -0700 Subject: usrp-e: untested attempt at zero copy iface for mmap --- host/lib/usrp/usrp_e/CMakeLists.txt | 1 + host/lib/usrp/usrp_e/io_impl.cpp | 97 ++---------- host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp | 201 +++++++++++++++++++++++++ 3 files changed, 212 insertions(+), 87 deletions(-) create mode 100644 host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp diff --git a/host/lib/usrp/usrp_e/CMakeLists.txt b/host/lib/usrp/usrp_e/CMakeLists.txt index da759d931..bab868f90 100644 --- a/host/lib/usrp/usrp_e/CMakeLists.txt +++ b/host/lib/usrp/usrp_e/CMakeLists.txt @@ -54,6 +54,7 @@ IF(ENABLE_USRP_E) ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_impl.hpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_iface.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_iface.hpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/usrp_e_regs.hpp ) ELSE(ENABLE_USRP_E) diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index e57d6ce35..0b5fa054b 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -22,8 +22,6 @@ #include #include "../../transport/vrt_packet_handler.hpp" #include -#include //read, write -#include #include #include #include @@ -32,90 +30,15 @@ using namespace uhd; using namespace uhd::usrp; using namespace uhd::transport; +zero_copy_if::sptr usrp_e_make_mmap_zero_copy(usrp_e_iface::sptr iface); + /*********************************************************************** * Constants **********************************************************************/ -static const size_t MAX_BUFF_SIZE = 2048; -static const bool usrp_e_io_impl_verbose = false; static const size_t tx_async_report_sid = 1; static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; static const double recv_timeout_ms = 100; -/*********************************************************************** - * Data Transport (phony zero-copy with read/write) - **********************************************************************/ -class data_transport: - public transport::phony_zero_copy_recv_if, - public transport::phony_zero_copy_send_if -{ -public: - data_transport(int fd): - transport::phony_zero_copy_recv_if(MAX_BUFF_SIZE), - transport::phony_zero_copy_send_if(MAX_BUFF_SIZE), - _fd(fd) - { - /* NOP */ - } - - size_t get_num_recv_frames(void) const{ - return 100; //FIXME no idea! - //this will be an important number when packet ring gets implemented - } - - size_t get_num_send_frames(void) const{ - return 100; //FIXME no idea! - //this will be an important number when packet ring gets implemented - } - -private: - int _fd; - ssize_t send(const boost::asio::const_buffer &buff){ - return write(_fd, - boost::asio::buffer_cast(buff), - boost::asio::buffer_size(buff) - ); - } - ssize_t recv(const boost::asio::mutable_buffer &buff, size_t to_ms){ - //std::cout << boost::format( - // "calling read on fd %d, buff size is %d" - //) % _fd % boost::asio::buffer_size(buff) << std::endl; - - //setup and call poll on the file descriptor - //return 0 and do not read when poll times out - pollfd pfd; - pfd.fd = _fd; - pfd.events = POLLIN; - ssize_t poll_ret = poll(&pfd, 1, to_ms); - if (poll_ret <= 0){ - if (usrp_e_io_impl_verbose) std::cerr << boost::format( - "usrp-e io impl recv(): poll() returned non-positive value: %d\n" - " -> return 0 for timeout" - ) % poll_ret << std::endl; - return 0; //timeout - } - - //perform the blocking read(...) - ssize_t read_ret = read(_fd, - boost::asio::buffer_cast(buff), - boost::asio::buffer_size(buff) - ); - if (read_ret < 0){ - if (usrp_e_io_impl_verbose) std::cerr << boost::format( - "usrp-e io impl recv(): read() returned small value: %d\n" - " -> return -1 for error" - ) % read_ret << std::endl; - return -1; - } - - //std::cout << "len " << int(read_ret) << std::endl; - //for (size_t i = 0; i < 9; i++){ - // std::cout << boost::format(" 0x%08x") % boost::asio::buffer_cast(buff)[i] << std::endl; - //} - - return read_ret; - } -}; - /*********************************************************************** * io impl details (internal to this file) * - pirate crew of 1 @@ -127,11 +50,11 @@ struct usrp_e_impl::io_impl{ //state management for the vrt packet handler code vrt_packet_handler::recv_state packet_handler_recv_state; vrt_packet_handler::send_state packet_handler_send_state; - data_transport transport; + zero_copy_if::sptr data_xport; bool continuous_streaming; - io_impl(int fd): - transport(fd), - recv_pirate_booty(recv_booty_type::make(transport.get_num_recv_frames())), + io_impl(usrp_e_iface::sptr iface): + data_xport(usrp_e_make_mmap_zero_copy(iface)), + recv_pirate_booty(recv_booty_type::make(data_xport->get_num_recv_frames())), async_msg_fifo(bounded_buffer::make(100/*messages deep*/)) { /* NOP */ @@ -171,7 +94,7 @@ void usrp_e_impl::io_impl::recv_pirate_loop( //size_t next_packet_seq = 0; while(recv_pirate_crew_raiding){ - managed_recv_buffer::sptr buff = this->transport.get_recv_buff(recv_timeout_ms); + managed_recv_buffer::sptr buff = this->data_xport->get_recv_buff(recv_timeout_ms); if (not buff.get()) continue; //ignore timeout/error buffers try{ @@ -229,7 +152,7 @@ void usrp_e_impl::io_init(void){ _iface->poke32(UE_REG_CTRL_TX_REPORT_SID, tx_async_report_sid); _iface->poke32(UE_REG_CTRL_TX_POLICY, UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET); - _io_impl = UHD_PIMPL_MAKE(io_impl, (_iface->get_file_descriptor())); + _io_impl = UHD_PIMPL_MAKE(io_impl, (_iface)); //spawn a pirate, yarrr! _io_impl->recv_pirate_crew.create_thread(boost::bind( @@ -258,7 +181,7 @@ void usrp_e_impl::handle_overrun(size_t){ * Data Send **********************************************************************/ bool get_send_buffs( - data_transport *trans, + zero_copy_if::sptr trans, vrt_packet_handler::managed_send_buffs_t &buffs ){ UHD_ASSERT_THROW(buffs.size() == 1); @@ -285,7 +208,7 @@ size_t usrp_e_impl::send( io_type, send_otw_type, //input and output types to convert MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_pack_le, - boost::bind(&get_send_buffs, &_io_impl->transport, _1), + boost::bind(&get_send_buffs, _io_impl->data_xport, _1), get_max_send_samps_per_packet() ); } diff --git a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp new file mode 100644 index 000000000..0910caa6f --- /dev/null +++ b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp @@ -0,0 +1,201 @@ +// +// 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 //mmap +#include //getpagesize +#include //poll +#include +#include "usrp_e_iface.hpp" + +using namespace uhd; +using namespace uhd::transport; + +static const bool debug_verbose = false; + +/*********************************************************************** + * The managed receive buffer implementation + **********************************************************************/ +class usrp_e_mmap_managed_recv_buffer : public managed_recv_buffer{ +public: + usrp_e_mmap_managed_recv_buffer( + const void *mem, size_t len, ring_buffer_info *info + ): + _buff(mem, len), _info(info) + { + /* NOP */ + } + + ~usrp_e_mmap_managed_recv_buffer(void){ + _info->flags = RB_KERNEL; + } + +private: + const boost::asio::const_buffer &get(void) const{ + return _buff; + } + + const boost::asio::const_buffer _buff; + ring_buffer_info *_info; +}; + +/*********************************************************************** + * The managed send buffer implementation + **********************************************************************/ +class usrp_e_mmap_managed_send_buffer : public managed_send_buffer{ +public: + usrp_e_mmap_managed_send_buffer( + void *mem, size_t len, ring_buffer_info *info, int fd + ): + _buff(mem, len), _info(info), _fd(fd), _commited(false) + { + /* NOP */ + } + + ~usrp_e_mmap_managed_send_buffer(void){ + if (not _commited) this->commit(0); + } + + ssize_t commit(size_t num_bytes){ + _commited = true; + _info->len = num_bytes; + _info->flags = RB_USER; + ssize_t ret = ::write(_fd, NULL, 0); + return (ret < 0)? ret : num_bytes; + } + +private: + const boost::asio::mutable_buffer &get(void) const{ + return _buff; + } + + const boost::asio::mutable_buffer _buff; + ring_buffer_info *_info; + int _fd; + bool _commited; +}; + +/*********************************************************************** + * The zero copy interface implementation + **********************************************************************/ +class usrp_e_mmap_zero_copy_impl : public zero_copy_if{ +public: + usrp_e_mmap_zero_copy_impl(usrp_e_iface::sptr iface): + _fd(iface->get_file_descriptor()), _recv_index(0), _send_index(0) + { + //get system sizes + iface->ioctl(USRP_E_GET_RB_INFO, &_rb_size); + size_t page_size = getpagesize(); + _frame_size = page_size/2; + + //calculate the memory size + size_t map_size = + (_rb_size.num_pages_rx_flags + _rb_size.num_pages_tx_flags) * page_size + + (_rb_size.num_rx_frames + _rb_size.num_tx_frames) * _frame_size; + + //call mmap to get the memory + void *ring_buffer = mmap( + NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, _fd, 0 + ); + UHD_ASSERT_THROW(ring_buffer != MAP_FAILED); + + //calculate the memory offsets for info and buffers + size_t recv_info_off = 0; + size_t recv_buff_off = recv_info_off + (_rb_size.num_pages_rx_flags * page_size); + size_t send_info_off = recv_buff_off + (_rb_size.num_rx_frames * _frame_size); + size_t send_buff_off = send_info_off + (_rb_size.num_pages_tx_flags * page_size); + + //set the internal pointers for info and buffers + typedef ring_buffer_info (*rbi_pta)[]; + boost::uint8_t *rb_ptr = reinterpret_cast(ring_buffer); + _recv_info = reinterpret_cast(rb_ptr + recv_info_off); + _recv_buff = rb_ptr + recv_buff_off; + _send_info = reinterpret_cast(rb_ptr + send_info_off); + _send_buff = rb_ptr + send_buff_off; + } + + managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms){ + //grab pointers to the info and buffer + ring_buffer_info *info = (*_recv_info) + _recv_index; + void *mem = _recv_buff + _frame_size*_recv_index; + + //poll/wait for a ready frame + if (not (info->flags & RB_USER)){ + pollfd pfd; + pfd.fd = _fd; + pfd.events = POLLIN; + ssize_t poll_ret = poll(&pfd, 1, timeout_ms); + if (poll_ret <= 0) return managed_recv_buffer::sptr(); + } + + //increment the index for the next call + if (++_recv_index == size_t(_rb_size.num_rx_frames)) _recv_index = 0; + + //return the managed buffer for this frame + return managed_recv_buffer::sptr( + new usrp_e_mmap_managed_recv_buffer(mem, info->len, info) + ); + } + + size_t get_num_recv_frames(void) const{ + return _rb_size.num_rx_frames; + } + + managed_send_buffer::sptr get_send_buff(void){ + //grab pointers to the info and buffer + ring_buffer_info *info = (*_send_info) + _send_index; + void *mem = _send_buff + _frame_size*_send_index; + + //poll/wait for a ready frame + if (not (info->flags & RB_KERNEL)){ + pollfd pfd; + pfd.fd = _fd; + pfd.events = POLLOUT; + ssize_t poll_ret = poll(&pfd, 1, -1 /*forever*/); + if (poll_ret <= 0) return managed_send_buffer::sptr(); + } + + //increment the index for the next call + if (++_send_index == size_t(_rb_size.num_tx_frames)) _send_index = 0; + + //return the managed buffer for this frame + return managed_send_buffer::sptr( + new usrp_e_mmap_managed_send_buffer(mem, _frame_size, info, _fd) + ); + } + + size_t get_num_send_frames(void) const{ + return _rb_size.num_tx_frames; + } + +private: + int _fd; + usrp_e_ring_buffer_size_t _rb_size; + size_t _frame_size; + ring_buffer_info (*_recv_info)[], (*_send_info)[]; + boost::uint8_t *_recv_buff, *_send_buff; + size_t _recv_index, _send_index; +}; + +/*********************************************************************** + * The zero copy interface make function + **********************************************************************/ +zero_copy_if::sptr usrp_e_make_mmap_zero_copy(usrp_e_iface::sptr iface){ + return zero_copy_if::sptr(new usrp_e_mmap_zero_copy_impl(iface)); +} -- cgit v1.2.3 From c0e03bb2edea4645f46f25afcc9be8b7b03f68df Mon Sep 17 00:00:00 2001 From: root Date: Thu, 30 Sep 2010 18:25:24 +0000 Subject: Ignore direction for GPIO 114 since it is always an input. --- host/apps/omap_debug/fpga-downloader.cc | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/host/apps/omap_debug/fpga-downloader.cc b/host/apps/omap_debug/fpga-downloader.cc index fb96b64a3..4e475b5c1 100644 --- a/host/apps/omap_debug/fpga-downloader.cc +++ b/host/apps/omap_debug/fpga-downloader.cc @@ -97,15 +97,17 @@ gpio::gpio(unsigned int gpio_num, gpio_direction pin_direction) std::fstream direction_file; std::string direction_file_name; - direction_file_name = base_path.str() + "/direction"; - - direction_file.open(direction_file_name.c_str()); - if (!direction_file.is_open()) - std::cout << "Failed to open direction file." << std::endl; - if (pin_direction == OUT) - direction_file << "out" << std::endl; - else - direction_file << "in" << std::endl; + if (gpio_num != 114) { + direction_file_name = base_path.str() + "/direction"; + + direction_file.open(direction_file_name.c_str()); + if (!direction_file.is_open()) + std::cout << "Failed to open direction file." << std::endl; + if (pin_direction == OUT) + direction_file << "out" << std::endl; + else + direction_file << "in" << std::endl; + } std::string value_file_name; -- cgit v1.2.3 From 67e302ee255922c021ce2c12efdbbaad46a787dc Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Fri, 1 Oct 2010 11:07:11 -0700 Subject: TVRX: fixed antenna prop enumeration --- host/lib/usrp/dboard/db_tvrx.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 1cb74c5ae..41c52fbf5 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -58,7 +58,7 @@ static const bool tvrx_debug = false; static const freq_range_t tvrx_freq_range(50e6, 860e6); -static const std::string tvrx_antennas = std::string(""); //only got one +static const prop_names_t tvrx_antennas = list_of(""); //only got one static const uhd::dict tvrx_freq_ranges = map_list_of ("VHFLO", freq_range_t(50e6, 158e6)) @@ -436,7 +436,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_ANTENNA: - val = std::string(tvrx_antennas); + val = std::string(""); return; case SUBDEV_PROP_ANTENNA_NAMES: -- cgit v1.2.3 From 348b5b12ad9ec916c92d642bfb28e47264473535 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 1 Oct 2010 11:54:22 -0700 Subject: usb: catch open errors and print message, device: catch exceptions at discovery time --- host/lib/device.cpp | 18 ++++++++++++------ host/lib/transport/libusb1_base.cpp | 16 +++++++++++----- host/lib/usrp/usrp1/usrp1_impl.cpp | 28 +++++++++++++--------------- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/host/lib/device.cpp b/host/lib/device.cpp index d575ebaab..386588a08 100644 --- a/host/lib/device.cpp +++ b/host/lib/device.cpp @@ -26,6 +26,7 @@ #include #include #include +#include using namespace uhd; @@ -73,12 +74,17 @@ device_addrs_t device::find(const device_addr_t &hint){ device_addrs_t device_addrs; BOOST_FOREACH(const dev_fcn_reg_t &fcn, get_dev_fcn_regs()){ - device_addrs_t discovered_addrs = fcn.get<0>()(hint); - device_addrs.insert( - device_addrs.begin(), - discovered_addrs.begin(), - discovered_addrs.end() - ); + try{ + device_addrs_t discovered_addrs = fcn.get<0>()(hint); + device_addrs.insert( + device_addrs.begin(), + discovered_addrs.begin(), + discovered_addrs.end() + ); + } + catch(const std::exception &e){ + std::cerr << "Device discovery error: " << e.what() << std::endl; + } } return device_addrs; diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index 49f524a32..910b04fc8 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -213,15 +213,21 @@ private: libusb::device_handle::sptr libusb::device_handle::get_cached_handle(device::sptr dev){ static uhd::dict > handles; - //not expired -> get existing session + //not expired -> get existing handle if (handles.has_key(dev->get()) and not handles[dev->get()].expired()){ return handles[dev->get()].lock(); } - //create a new global session - sptr new_handle(new libusb_device_handle_impl(dev)); - handles[dev->get()] = new_handle; - return new_handle; + //create a new cached handle + try{ + sptr new_handle(new libusb_device_handle_impl(dev)); + handles[dev->get()] = new_handle; + return new_handle; + } + catch(const std::exception &e){ + std::cerr << "USB open failed: see the application notes for your device." << std::endl; + throw std::runtime_error(e.what()); + } } /*********************************************************************** diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 793e3027d..156fc119f 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -83,9 +83,7 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) //find the usrps and load firmware BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid, pid)) { - usb_control::sptr ctrl_transport = usb_control::make(handle); - usrp_ctrl::sptr usrp_ctrl = usrp_ctrl::make(ctrl_transport); - usrp_ctrl->usrp_load_firmware(usrp1_fw_image); + usrp_ctrl::make(usb_control::make(handle))->usrp_load_firmware(usrp1_fw_image); } //get descriptors again with serial number, but using the initialized VID/PID now since we have firmware @@ -93,13 +91,13 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) pid = USRP1_PRODUCT_ID; BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid, pid)) { - device_addr_t new_addr; - new_addr["type"] = "usrp1"; - new_addr["serial"] = handle->get_serial(); - //this is a found usrp1 when a hint serial is not specified or it matches - if (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]){ - usrp1_addrs.push_back(new_addr); - } + device_addr_t new_addr; + new_addr["type"] = "usrp1"; + new_addr["serial"] = handle->get_serial(); + //this is a found usrp1 when a hint serial is not specified or it matches + if (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]){ + usrp1_addrs.push_back(new_addr); + } } return usrp1_addrs; @@ -109,12 +107,12 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) * Make **********************************************************************/ template static output_type cast_from_dev_addr( - const device_addr_t &device_addr, - const std::string &key, - output_type def_val + const device_addr_t &device_addr, + const std::string &key, + output_type def_val ){ - return (device_addr.has_key(key))? - boost::lexical_cast(device_addr[key]) : def_val; + return (device_addr.has_key(key))? + boost::lexical_cast(device_addr[key]) : def_val; } static device::sptr usrp1_make(const device_addr_t &device_addr) -- cgit v1.2.3 From 3a1138bc4a8595c5ea95a10f5ffdf0cb6a326b08 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 1 Oct 2010 12:11:38 -0700 Subject: uhd: print system info on library load --- host/lib/version.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/host/lib/version.cpp b/host/lib/version.cpp index 5edbca09b..93fdecb1a 100644 --- a/host/lib/version.cpp +++ b/host/lib/version.cpp @@ -21,3 +21,17 @@ std::string uhd::get_version_string(void){ return UHD_VERSION_STRING; } + +#include +#include +#include + +UHD_STATIC_BLOCK(print_system_info){ + std::cout + << BOOST_PLATFORM << "; " + << BOOST_COMPILER << "; " + << "Boost_" << BOOST_VERSION << "; " + << "UHD_" << uhd::get_version_string() + << std::endl << std::endl + ; +} -- cgit v1.2.3 From bd3bd0dfbc1a87af5839c9b23450434cfb9c763c Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Fri, 1 Oct 2010 16:08:37 -0700 Subject: UHD: added mutex to fix race condition in device enumeration. --- host/lib/transport/libusb1_base.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index 910b04fc8..1dd0b48e8 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -35,7 +35,9 @@ public: libusb_session_impl(void){ UHD_ASSERT_THROW(libusb_init(&_context) == 0); libusb_set_debug(_context, debug_level); + _mutex.lock(); _thread_group.create_thread(boost::bind(&libusb_session_impl::run_event_loop, this)); + _mutex.lock(); } ~libusb_session_impl(void){ @@ -52,11 +54,13 @@ private: libusb_context *_context; boost::thread_group _thread_group; bool _running; + boost::mutex _mutex; void run_event_loop(void){ set_thread_priority_safe(); _running = true; timeval tv; + _mutex.unlock(); while(_running){ tv.tv_sec = 0; tv.tv_usec = 100000; //100ms -- cgit v1.2.3 From 00cd6018405b57a0982b0ce103ff858c646ee18c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 1 Oct 2010 18:22:41 -0700 Subject: uhd: implemented a double timeout (in seconds) for send and recv chains converted all size_t timeout_ms to double timeout bounded and alignment buffer now take double timeout added timeout to device::send and zero_copy_if::get_send_buff --- host/include/uhd/device.hpp | 27 ++++++++------ host/include/uhd/device.ipp | 9 +++-- host/include/uhd/transport/alignment_buffer.hpp | 9 ++--- host/include/uhd/transport/alignment_buffer.ipp | 15 +++----- host/include/uhd/transport/bounded_buffer.hpp | 12 ++---- host/include/uhd/transport/bounded_buffer.ipp | 15 ++++++-- host/include/uhd/transport/zero_copy.hpp | 18 +++++---- host/lib/transport/libusb1_zero_copy.cpp | 42 ++++++++++----------- host/lib/transport/udp_zero_copy_asio.cpp | 4 +- host/lib/transport/vrt_packet_handler.hpp | 49 +++++++++++++------------ host/lib/transport/zero_copy.cpp | 6 +-- host/lib/usrp/usrp1/io_impl.cpp | 20 +++++----- host/lib/usrp/usrp1/usrp1_impl.cpp | 4 +- host/lib/usrp/usrp1/usrp1_impl.hpp | 7 ++-- host/lib/usrp/usrp2/io_impl.cpp | 32 ++++++++-------- host/lib/usrp/usrp2/usrp2_impl.hpp | 6 +-- host/test/buffer_test.cpp | 2 +- 17 files changed, 140 insertions(+), 137 deletions(-) diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 2077cae62..992276928 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -41,9 +41,6 @@ public: typedef boost::function find_t; typedef boost::function make_t; - //! A reasonable default timeout for receive - static const size_t default_recv_timeout_ms = 100; - /*! * Register a device into the discovery and factory system. * @@ -112,12 +109,15 @@ public: * * This is a blocking call and will not return until the number * of samples returned have been read out of each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. * * \param buffs a vector of read-only memory containing IF data * \param nsamps_per_buff the number of samples to send, per buffer * \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 + * \param timeout the timeout in seconds to wait on a packet * \return the number of samples sent */ virtual size_t send( @@ -125,7 +125,8 @@ public: size_t nsamps_per_buff, const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode + send_mode_t send_mode, + double timeout = 0.1 ) = 0; /*! @@ -136,7 +137,8 @@ public: size_t nsamps_per_buff, const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode + send_mode_t send_mode, + double timeout = 0.1 ); /*! @@ -154,7 +156,9 @@ public: * See the rx metadata fragment flags and offset fields for details. * * This is a blocking call and will not return until the number - * of samples returned have been written into each buffer or timeout. + * of samples returned have been written into each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. * * When using the full buffer recv mode, the metadata only applies * to the first packet received and written into the recv buffers. @@ -165,7 +169,7 @@ public: * \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 - * \param timeout_ms the timeout in milliseconds to wait for a packet + * \param timeout the timeout in seconds to wait for a packet * \return the number of samples received or 0 on error */ virtual size_t recv( @@ -174,7 +178,7 @@ public: rx_metadata_t &metadata, const io_type_t &io_type, recv_mode_t recv_mode, - size_t timeout_ms = default_recv_timeout_ms + double timeout = 0.1 ) = 0; /*! @@ -186,7 +190,7 @@ public: rx_metadata_t &metadata, const io_type_t &io_type, recv_mode_t recv_mode, - size_t timeout_ms = default_recv_timeout_ms + double timeout = 0.1 ); /*! @@ -204,12 +208,11 @@ public: /*! * Receive and asynchronous message from the device. * \param async_metadata the metadata to be filled in - * \param timeout_ms the timeout in milliseconds to wait for a message + * \param timeout the timeout in seconds to wait for a message * \return true when the async_metadata is valid, false for timeout */ virtual bool recv_async_msg( - async_metadata_t &async_metadata, - size_t timeout_ms = default_recv_timeout_ms + async_metadata_t &async_metadata, double timeout = 0.1 ) = 0; }; diff --git a/host/include/uhd/device.ipp b/host/include/uhd/device.ipp index 60a3f535d..e2e51ecd0 100644 --- a/host/include/uhd/device.ipp +++ b/host/include/uhd/device.ipp @@ -25,12 +25,13 @@ namespace uhd{ size_t nsamps_per_buff, const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode + send_mode_t send_mode, + double timeout ){ return this->send( std::vector(1, buff), nsamps_per_buff, metadata, - io_type, send_mode + io_type, send_mode, timeout ); } @@ -40,12 +41,12 @@ namespace uhd{ rx_metadata_t &metadata, const io_type_t &io_type, recv_mode_t recv_mode, - size_t timeout_ms + double timeout ){ return this->recv( std::vector(1, buff), nsamps_per_buff, metadata, - io_type, recv_mode, timeout_ms + io_type, recv_mode, timeout ); } diff --git a/host/include/uhd/transport/alignment_buffer.hpp b/host/include/uhd/transport/alignment_buffer.hpp index 29ba74efc..f44a037f8 100644 --- a/host/include/uhd/transport/alignment_buffer.hpp +++ b/host/include/uhd/transport/alignment_buffer.hpp @@ -48,20 +48,17 @@ namespace uhd{ namespace transport{ * \return true if the element fit without popping for space */ virtual bool push_with_pop_on_full( - const elem_type &elem, - const seq_type &seq, - size_t index + const elem_type &elem, const seq_type &seq, size_t index ) = 0; /*! * Pop an aligned set of elements from this alignment buffer. * \param elems a collection to store the aligned elements - * \param time the timeout time + * \param timeout the timeout in seconds * \return false when the operation times out */ virtual bool pop_elems_with_timed_wait( - std::vector &elems, - const time_duration_t &time + std::vector &elems, double timeout ) = 0; }; diff --git a/host/include/uhd/transport/alignment_buffer.ipp b/host/include/uhd/transport/alignment_buffer.ipp index 61b3b60f5..5f09de0d9 100644 --- a/host/include/uhd/transport/alignment_buffer.ipp +++ b/host/include/uhd/transport/alignment_buffer.ipp @@ -41,9 +41,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ } UHD_INLINE bool push_with_pop_on_full( - const elem_type &elem, - const seq_type &seq, - size_t index + const elem_type &elem, const seq_type &seq, size_t index ){ //clear the buffer for this index if the seqs are mis-ordered if (seq < _last_seqs[index]){ @@ -54,17 +52,16 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ } UHD_INLINE bool pop_elems_with_timed_wait( - std::vector &elems, - const time_duration_t &time + std::vector &elems, double timeout ){ - boost::system_time exit_time = boost::get_system_time() + time; + boost::system_time exit_time = boost::get_system_time() + boost::posix_time::microseconds(long(timeout*1e6)); buff_contents_type buff_contents_tmp; std::list indexes_to_do(_all_indexes); //do an initial pop to load an initial sequence id size_t index = indexes_to_do.front(); if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, exit_time - boost::get_system_time() + buff_contents_tmp, 1e-6*(exit_time - boost::get_system_time()).total_microseconds() )) return false; elems[index] = buff_contents_tmp.first; seq_type expected_seq_id = buff_contents_tmp.second; @@ -79,7 +76,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ indexes_to_do = _all_indexes; index = indexes_to_do.front(); if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, exit_time - boost::get_system_time() + buff_contents_tmp, 1e-6*(exit_time - boost::get_system_time()).total_microseconds() )) return false; elems[index] = buff_contents_tmp.first; expected_seq_id = buff_contents_tmp.second; @@ -89,7 +86,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ //pop an element off for this index index = indexes_to_do.front(); if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, exit_time - boost::get_system_time() + buff_contents_tmp, 1e-6*(exit_time - boost::get_system_time()).total_microseconds() )) return false; //if the sequence id matches: diff --git a/host/include/uhd/transport/bounded_buffer.hpp b/host/include/uhd/transport/bounded_buffer.hpp index d1deece96..aca93b071 100644 --- a/host/include/uhd/transport/bounded_buffer.hpp +++ b/host/include/uhd/transport/bounded_buffer.hpp @@ -20,13 +20,9 @@ #include #include -#include namespace uhd{ namespace transport{ - //! typedef for the time duration type for wait operations - typedef boost::posix_time::time_duration time_duration_t; - /*! * Implement a templated bounded buffer: * Used for passing elements between threads in a producer-consumer model. @@ -64,10 +60,10 @@ namespace uhd{ namespace transport{ * Push a new element into the bounded_buffer. * Wait until the bounded_buffer becomes non-full or timeout. * \param elem the new element to push - * \param time the timeout time + * \param timeout the timeout in seconds * \return false when the operation times out */ - virtual bool push_with_timed_wait(const elem_type &elem, const time_duration_t &time) = 0; + virtual bool push_with_timed_wait(const elem_type &elem, double timeout) = 0; /*! * Pop an element from the bounded_buffer. @@ -80,10 +76,10 @@ namespace uhd{ namespace transport{ * Pop an element from the bounded_buffer. * Wait until the bounded_buffer becomes non-empty or timeout. * \param elem the element reference pop to - * \param time the timeout time + * \param timeout the timeout in seconds * \return false when the operation times out */ - virtual bool pop_with_timed_wait(elem_type &elem, const time_duration_t &time) = 0; + virtual bool pop_with_timed_wait(elem_type &elem, double timeout) = 0; /*! * Clear all elements from the bounded_buffer. diff --git a/host/include/uhd/transport/bounded_buffer.ipp b/host/include/uhd/transport/bounded_buffer.ipp index e106e229e..71143741e 100644 --- a/host/include/uhd/transport/bounded_buffer.ipp +++ b/host/include/uhd/transport/bounded_buffer.ipp @@ -21,6 +21,7 @@ #include #include #include +#include namespace uhd{ namespace transport{ namespace{ /*anon*/ @@ -57,9 +58,12 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ _empty_cond.notify_one(); } - bool push_with_timed_wait(const elem_type &elem, const time_duration_t &time){ + bool push_with_timed_wait(const elem_type &elem, double timeout){ boost::unique_lock lock(_mutex); - if (not _full_cond.timed_wait(lock, time, boost::bind(&bounded_buffer_impl::not_full, this))) return false; + if (not _full_cond.timed_wait( + lock, boost::posix_time::microseconds(long(timeout*1e6)), + boost::bind(&bounded_buffer_impl::not_full, this) + )) return false; _buffer.push_front(elem); lock.unlock(); _empty_cond.notify_one(); @@ -74,9 +78,12 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ _full_cond.notify_one(); } - bool pop_with_timed_wait(elem_type &elem, const time_duration_t &time){ + bool pop_with_timed_wait(elem_type &elem, double timeout){ boost::unique_lock lock(_mutex); - if (not _empty_cond.timed_wait(lock, time, boost::bind(&bounded_buffer_impl::not_empty, this))) return false; + if (not _empty_cond.timed_wait( + lock, boost::posix_time::microseconds(long(timeout*1e6)), + boost::bind(&bounded_buffer_impl::not_empty, this) + )) return false; elem = _buffer.back(); _buffer.pop_back(); lock.unlock(); _full_cond.notify_one(); diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp index 8ecafd3fb..ba19b193c 100644 --- a/host/include/uhd/transport/zero_copy.hpp +++ b/host/include/uhd/transport/zero_copy.hpp @@ -122,10 +122,10 @@ namespace uhd{ namespace transport{ /*! * Get a new receive buffer from this transport object. - * \param timeout_ms the timeout to get the buffer in ms + * \param timeout the timeout to get the buffer in seconds * \return a managed buffer, or null sptr on timeout/error */ - virtual managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms) = 0; + virtual managed_recv_buffer::sptr get_recv_buff(double timeout = 0.1) = 0; /*! * Get the maximum number of receive frames: @@ -138,9 +138,10 @@ namespace uhd{ namespace transport{ /*! * Get a new send buffer from this transport object. + * \param timeout the timeout to get the buffer in seconds * \return a managed buffer, or null sptr on timeout/error */ - virtual managed_send_buffer::sptr get_send_buff(void) = 0; + virtual managed_send_buffer::sptr get_send_buff(double timeout = 0.1) = 0; /*! * Get the maximum number of send frames: @@ -172,19 +173,19 @@ namespace uhd{ namespace transport{ /*! * Get a new receive buffer from this transport object. - * \param timeout_ms the timeout to get the buffer in ms + * \param timeout the timeout to get the buffer in seconds * \return a managed buffer, or null sptr on timeout/error */ - managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms); + managed_recv_buffer::sptr get_recv_buff(double timeout); private: /*! * Perform a private copying recv. * \param buff the buffer to write data into - * \param timeout_ms the timeout to get the buffer in ms + * \param timeout the timeout to get the buffer in seconds * \return the number of bytes written to buff, 0 for timeout, negative for error */ - virtual ssize_t recv(const boost::asio::mutable_buffer &buff, size_t timeout_ms) = 0; + virtual ssize_t recv(const boost::asio::mutable_buffer &buff, double timeout) = 0; UHD_PIMPL_DECL(impl) _impl; }; @@ -208,9 +209,10 @@ namespace uhd{ namespace transport{ /*! * Get a new send buffer from this transport object. + * \param timeout the timeout to get the buffer in seconds * \return a managed buffer, or null sptr on timeout/error */ - managed_send_buffer::sptr get_send_buff(void); + managed_send_buffer::sptr get_send_buff(double timeout); private: /*! diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index f9beb0b4c..7f2bc3468 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -24,12 +24,10 @@ #include #include #include -#include using namespace uhd::transport; -const int libusb_timeout = 0; - +static const double CLEANUP_TIMEOUT = 0.2; //seconds static const size_t DEFAULT_NUM_XFERS = 16; //num xfers static const size_t DEFAULT_XFER_SIZE = 32*512; //bytes @@ -84,10 +82,10 @@ public: * Get an available transfer: * For inputs, this is a just filled transfer. * For outputs, this is a just emptied transfer. - * \param timeout_ms the timeout to wait for a lut + * \param timeout the timeout to wait for a lut * \return the transfer pointer or NULL if timeout */ - libusb_transfer *get_lut_with_wait(size_t timeout_ms = 100); + libusb_transfer *get_lut_with_wait(double timeout); //Callback use only void callback_handle_transfer(libusb_transfer *lut); @@ -187,7 +185,7 @@ usb_endpoint::~usb_endpoint(void){ } //collect canceled transfers (drain the queue) - while (this->get_lut_with_wait() != NULL){}; + while (this->get_lut_with_wait(CLEANUP_TIMEOUT) != NULL){}; //free all transfers BOOST_FOREACH(libusb_transfer *lut, _all_luts){ @@ -274,12 +272,10 @@ void usb_endpoint::print_transfer_status(libusb_transfer *lut){ } } -libusb_transfer *usb_endpoint::get_lut_with_wait(size_t timeout_ms){ +libusb_transfer *usb_endpoint::get_lut_with_wait(double timeout){ boost::this_thread::disable_interruption di; //disable because the wait can throw libusb_transfer *lut; - if (_completed_list->pop_with_timed_wait( - lut, boost::posix_time::milliseconds(timeout_ms) - )) return lut; + if (_completed_list->pop_with_timed_wait(lut, timeout)) return lut; return NULL; } @@ -399,8 +395,8 @@ public: size_t send_xfer_size, size_t send_num_xfers ); - managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms); - managed_send_buffer::sptr get_send_buff(void); + managed_recv_buffer::sptr get_recv_buff(double); + managed_send_buffer::sptr get_send_buff(double); size_t get_num_recv_frames(void) const { return _recv_num_frames; } size_t get_num_send_frames(void) const { return _send_num_frames; } @@ -459,8 +455,8 @@ libusb_zero_copy_impl::libusb_zero_copy_impl( * Return empty pointer if no transfer is available (timeout or error). * \return pointer to a managed receive buffer */ -managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(size_t timeout_ms){ - libusb_transfer *lut = _recv_ep->get_lut_with_wait(timeout_ms); +managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(double timeout){ + libusb_transfer *lut = _recv_ep->get_lut_with_wait(timeout); if (lut == NULL) { return managed_recv_buffer::sptr(); } @@ -478,8 +474,8 @@ managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(size_t timeout_ms * (timeout or error). * \return pointer to a managed send buffer */ -managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(void){ - libusb_transfer *lut = _send_ep->get_lut_with_wait(/* TODO timeout API */); +managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(double timeout){ + libusb_transfer *lut = _send_ep->get_lut_with_wait(timeout); if (lut == NULL) { return managed_send_buffer::sptr(); } @@ -494,18 +490,18 @@ managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(void){ * USB zero_copy make functions **********************************************************************/ usb_zero_copy::sptr usb_zero_copy::make( - usb_device_handle::sptr handle, + usb_device_handle::sptr handle, unsigned int recv_endpoint, unsigned int send_endpoint, - size_t recv_xfer_size, size_t recv_num_xfers, - size_t send_xfer_size, size_t send_num_xfers + size_t recv_xfer_size, size_t recv_num_xfers, + size_t send_xfer_size, size_t send_num_xfers ){ libusb::device_handle::sptr dev_handle(libusb::device_handle::get_cached_handle( boost::static_pointer_cast(handle)->get_device() )); return sptr(new libusb_zero_copy_impl( - dev_handle, - recv_endpoint, send_endpoint, - recv_xfer_size, recv_num_xfers, - send_xfer_size, send_num_xfers + dev_handle, + recv_endpoint, send_endpoint, + recv_xfer_size, recv_num_xfers, + send_xfer_size, send_num_xfers )); } diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 0a6c9f2af..3130830a5 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -109,11 +109,11 @@ private: boost::asio::io_service _io_service; int _sock_fd; - ssize_t recv(const boost::asio::mutable_buffer &buff, size_t timeout_ms){ + ssize_t recv(const boost::asio::mutable_buffer &buff, double timeout){ //setup timeval for timeout timeval tv; tv.tv_sec = 0; - tv.tv_usec = timeout_ms*1000; + tv.tv_usec = long(timeout*1e6); //setup rset for timeout fd_set rset; diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index b603f1371..e11afff30 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -303,18 +303,18 @@ template UHD_INLINE T get_context_code( * Pack a vrt header, copy-convert the data, and send it. * - helper function for vrt_packet_handler::send ******************************************************************/ - static UHD_INLINE void _send1( + static UHD_INLINE size_t _send1( send_state &state, const std::vector &buffs, - size_t offset_bytes, - size_t num_samps, + const size_t offset_bytes, + const size_t num_samps, uhd::transport::vrt::if_packet_info_t &if_packet_info, const uhd::io_type_t &io_type, const uhd::otw_type_t &otw_type, const vrt_packer_t &vrt_packer, const get_send_buffs_t &get_send_buffs, - size_t vrt_header_offset_words32, - size_t chans_per_otw_buff + const size_t vrt_header_offset_words32, + const size_t chans_per_otw_buff ){ //load the rest of the if_packet_info in here if_packet_info.num_payload_words32 = (num_samps*chans_per_otw_buff*otw_type.get_sample_size())/sizeof(boost::uint32_t); @@ -322,7 +322,7 @@ template UHD_INLINE T get_context_code( //get send buffers for each channel managed_send_buffs_t send_buffs(buffs.size()/chans_per_otw_buff); - UHD_ASSERT_THROW(get_send_buffs(send_buffs)); + if (not get_send_buffs(send_buffs)) return 0; std::vector io_buffs(chans_per_otw_buff); for (size_t i = 0; i < buffs.size(); i+=chans_per_otw_buff){ @@ -347,6 +347,7 @@ template UHD_INLINE T get_context_code( std::cerr << "commit to send buffer returned less than commit size" << std::endl; } } + return num_samps; } /******************************************************************* @@ -381,7 +382,6 @@ template UHD_INLINE T get_context_code( //////////////////////////////////////////////////////////////// case uhd::device::SEND_MODE_ONE_PACKET:{ //////////////////////////////////////////////////////////////// - size_t num_samps = std::min(total_num_samps, max_samples_per_packet); //fill in parts of the packet info overwrote in full buff mode if_packet_info.has_tsi = metadata.has_time_spec; @@ -389,10 +389,10 @@ template UHD_INLINE T get_context_code( if_packet_info.sob = metadata.start_of_burst; if_packet_info.eob = metadata.end_of_burst; - _send1( + return _send1( state, buffs, 0, - num_samps, + std::min(total_num_samps, max_samples_per_packet), if_packet_info, io_type, otw_type, vrt_packer, @@ -400,31 +400,32 @@ template UHD_INLINE T get_context_code( vrt_header_offset_words32, chans_per_otw_buff ); - return num_samps; } //////////////////////////////////////////////////////////////// case uhd::device::SEND_MODE_FULL_BUFF:{ //////////////////////////////////////////////////////////////// - //calculate constants for fragmentation - const size_t num_fragments = (total_num_samps+max_samples_per_packet-1)/max_samples_per_packet; - static const size_t first_fragment_index = 0; - const size_t final_fragment_index = num_fragments-1; + size_t total_num_samps_sent = 0; //loop through the following fragment indexes - for (size_t n = first_fragment_index; n <= final_fragment_index; n++){ + while(total_num_samps_sent < total_num_samps){ + + //calculate per-loop-iteration variables + const size_t total_num_samps_unsent = total_num_samps - total_num_samps_sent; + const bool first_fragment = (total_num_samps_sent == 0); + const bool final_fragment = (total_num_samps_unsent <= max_samples_per_packet); //calculate new flags for the fragments - if_packet_info.has_tsi = metadata.has_time_spec and (n == first_fragment_index); - if_packet_info.has_tsf = metadata.has_time_spec and (n == first_fragment_index); - if_packet_info.sob = metadata.start_of_burst and (n == first_fragment_index); - if_packet_info.eob = metadata.end_of_burst and (n == final_fragment_index); + if_packet_info.has_tsi = metadata.has_time_spec and first_fragment; + if_packet_info.has_tsf = if_packet_info.has_tsi; + if_packet_info.sob = metadata.start_of_burst and first_fragment; + if_packet_info.eob = metadata.end_of_burst and final_fragment; //send the fragment with the helper function - _send1( + const size_t num_samps_sent = _send1( state, - buffs, n*max_samples_per_packet*io_type.size, - (n == final_fragment_index)?(total_num_samps%max_samples_per_packet):max_samples_per_packet, + buffs, total_num_samps_sent*io_type.size, + std::min(total_num_samps_unsent, max_samples_per_packet), if_packet_info, io_type, otw_type, vrt_packer, @@ -432,8 +433,10 @@ template UHD_INLINE T get_context_code( vrt_header_offset_words32, chans_per_otw_buff ); + total_num_samps_sent += num_samps_sent; + if (num_samps_sent == 0) return total_num_samps_sent; } - return total_num_samps; + return total_num_samps_sent; } default: throw std::runtime_error("unknown send mode"); diff --git a/host/lib/transport/zero_copy.cpp b/host/lib/transport/zero_copy.cpp index 1fcf846a0..dfb65951f 100644 --- a/host/lib/transport/zero_copy.cpp +++ b/host/lib/transport/zero_copy.cpp @@ -68,12 +68,12 @@ phony_zero_copy_recv_if::~phony_zero_copy_recv_if(void){ /* NOP */ } -managed_recv_buffer::sptr phony_zero_copy_recv_if::get_recv_buff(size_t timeout_ms){ +managed_recv_buffer::sptr phony_zero_copy_recv_if::get_recv_buff(double timeout){ //allocate memory boost::uint8_t *recv_mem = new boost::uint8_t[_impl->max_buff_size]; //call recv() with timeout option - ssize_t num_bytes = this->recv(boost::asio::buffer(recv_mem, _impl->max_buff_size), timeout_ms); + ssize_t num_bytes = this->recv(boost::asio::buffer(recv_mem, _impl->max_buff_size), timeout); if (num_bytes <= 0) return managed_recv_buffer::sptr(); //NULL sptr @@ -138,6 +138,6 @@ phony_zero_copy_send_if::~phony_zero_copy_send_if(void){ delete [] _impl->send_mem; } -managed_send_buffer::sptr phony_zero_copy_send_if::get_send_buff(void){ +managed_send_buffer::sptr phony_zero_copy_send_if::get_send_buff(double){ return _impl->send_buff; //FIXME there is only ever one send buff, we assume that the caller doesnt hang onto these } diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index aee760a83..8d9c68961 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -94,12 +94,13 @@ struct usrp1_impl::io_impl{ //all of this to ensure only full buffers are committed managed_send_buffer::sptr send_buff; size_t num_bytes_committed; + double send_timeout; boost::uint8_t pseudo_buff[BYTES_PER_PACKET]; ssize_t phony_commit_pseudo_buff(size_t num_bytes); ssize_t phony_commit_send_buff(size_t num_bytes); ssize_t commit_send_buff(void); void flush_send_buff(void); - bool get_send_buffs(vrt_packet_handler::managed_send_buffs_t &); + bool get_send_buffs(vrt_packet_handler::managed_send_buffs_t &, double); //helpers to get at the send buffer + offset inline void *get_send_mem_ptr(void){ @@ -159,14 +160,15 @@ void usrp1_impl::io_impl::flush_send_buff(void){ */ ssize_t usrp1_impl::io_impl::commit_send_buff(void){ ssize_t ret = send_buff->commit(num_bytes_committed); - send_buff = data_transport->get_send_buff(); + send_buff = data_transport->get_send_buff(send_timeout); num_bytes_committed = 0; return ret; } bool usrp1_impl::io_impl::get_send_buffs( - vrt_packet_handler::managed_send_buffs_t &buffs + vrt_packet_handler::managed_send_buffs_t &buffs, double timeout ){ + send_timeout = timeout; UHD_ASSERT_THROW(buffs.size() == 1); //not enough bytes free -> use the pseudo buffer @@ -216,7 +218,7 @@ static void usrp1_bs_vrt_packer( size_t usrp1_impl::send( const std::vector &buffs, size_t num_samps, const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode + send_mode_t send_mode, double timeout ){ size_t num_samps_sent = vrt_packet_handler::send( _io_impl->packet_handler_send_state, //last state of the send handler @@ -225,7 +227,7 @@ size_t usrp1_impl::send( io_type, _tx_otw_type, //input and output types to convert _clock_ctrl->get_master_clock_freq(), //master clock tick rate &usrp1_bs_vrt_packer, - boost::bind(&usrp1_impl::io_impl::get_send_buffs, _io_impl.get(), _1), + boost::bind(&usrp1_impl::io_impl::get_send_buffs, _io_impl.get(), _1, timeout), get_max_send_samps_per_packet(), 0, //vrt header offset _tx_subdev_spec.size() //num channels @@ -272,18 +274,18 @@ static void usrp1_bs_vrt_unpacker( } static bool get_recv_buffs( - zero_copy_if::sptr zc_if, size_t timeout_ms, + zero_copy_if::sptr zc_if, double timeout, vrt_packet_handler::managed_recv_buffs_t &buffs ){ UHD_ASSERT_THROW(buffs.size() == 1); - buffs[0] = zc_if->get_recv_buff(timeout_ms); + buffs[0] = zc_if->get_recv_buff(timeout); return buffs[0].get() != NULL; } size_t usrp1_impl::recv( const std::vector &buffs, size_t num_samps, rx_metadata_t &metadata, const io_type_t &io_type, - recv_mode_t recv_mode, size_t timeout_ms + recv_mode_t recv_mode, double timeout ){ size_t num_samps_recvd = vrt_packet_handler::recv( _io_impl->packet_handler_recv_state, //last state of the recv handler @@ -292,7 +294,7 @@ size_t usrp1_impl::recv( io_type, _rx_otw_type, //input and output types to convert _clock_ctrl->get_master_clock_freq(), //master clock tick rate &usrp1_bs_vrt_unpacker, - boost::bind(&get_recv_buffs, _data_transport, timeout_ms, _1), + boost::bind(&get_recv_buffs, _data_transport, timeout, _1), &vrt_packet_handler::handle_overflow_nop, 0, //vrt header offset _rx_subdev_spec.size() //num channels diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 156fc119f..6ebd6bb09 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -209,9 +209,9 @@ usrp1_impl::~usrp1_impl(void){ /* NOP */ } -bool usrp1_impl::recv_async_msg(uhd::async_metadata_t &, size_t timeout_ms){ +bool usrp1_impl::recv_async_msg(uhd::async_metadata_t &, double timeout){ //dummy fill-in for the recv_async_msg - boost::this_thread::sleep(boost::posix_time::milliseconds(timeout_ms)); + boost::this_thread::sleep(boost::posix_time::microseconds(long(timeout*1e6))); return false; } diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 20ae3c02a..f2c464610 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -83,13 +83,12 @@ public: size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, - send_mode_t); + send_mode_t, double); size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, - recv_mode_t, - size_t timeout); + recv_mode_t, double); static const size_t BYTES_PER_PACKET = 512*4; //under the transfer size @@ -101,7 +100,7 @@ public: return BYTES_PER_PACKET/_rx_otw_type.get_sample_size()/_rx_subdev_spec.size(); } - bool recv_async_msg(uhd::async_metadata_t &, size_t); + bool recv_async_msg(uhd::async_metadata_t &, double); private: /*! diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 3395f94e2..c0d8ab029 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -33,7 +33,6 @@ using namespace uhd::transport; namespace asio = boost::asio; static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; -static const double RECV_TIMEOUT_MS = 100; /*********************************************************************** * io impl details (internal to this file) @@ -59,9 +58,9 @@ struct usrp2_impl::io_impl{ recv_pirate_crew.join_all(); } - bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, size_t timeout_ms){ + bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, double timeout){ boost::this_thread::disable_interruption di; //disable because the wait can throw - return recv_pirate_booty->pop_elems_with_timed_wait(buffs, boost::posix_time::milliseconds(timeout_ms)); + return recv_pirate_booty->pop_elems_with_timed_wait(buffs, timeout); } //state management for the vrt packet handler code @@ -91,7 +90,7 @@ void usrp2_impl::io_impl::recv_pirate_loop( size_t next_packet_seq = 0; while(recv_pirate_crew_raiding){ - managed_recv_buffer::sptr buff = zc_if->get_recv_buff(RECV_TIMEOUT_MS); + managed_recv_buffer::sptr buff = zc_if->get_recv_buff(); if (not buff.get()) continue; //ignore timeout/error buffers try{ @@ -151,7 +150,7 @@ void usrp2_impl::io_init(void){ std::memcpy(send_buff->cast(), &data, sizeof(data)); send_buff->commit(sizeof(data)); //drain the recv buffers (may have junk) - while (data_transport->get_recv_buff(RECV_TIMEOUT_MS).get()){}; + while (data_transport->get_recv_buff().get()){}; } //the number of recv frames is the number for the first transport @@ -179,12 +178,10 @@ void usrp2_impl::io_init(void){ * Async Data **********************************************************************/ bool usrp2_impl::recv_async_msg( - async_metadata_t &async_metadata, size_t timeout_ms + async_metadata_t &async_metadata, double timeout ){ boost::this_thread::disable_interruption di; //disable because the wait can throw - return _io_impl->async_msg_fifo->pop_with_timed_wait( - async_metadata, boost::posix_time::milliseconds(timeout_ms) - ); + return _io_impl->async_msg_fifo->pop_with_timed_wait(async_metadata, timeout); } /*********************************************************************** @@ -192,19 +189,22 @@ bool usrp2_impl::recv_async_msg( **********************************************************************/ static bool get_send_buffs( const std::vector &trans, - vrt_packet_handler::managed_send_buffs_t &buffs + vrt_packet_handler::managed_send_buffs_t &buffs, + double timeout ){ UHD_ASSERT_THROW(trans.size() == buffs.size()); + bool good = true; for (size_t i = 0; i < buffs.size(); i++){ - buffs[i] = trans[i]->get_send_buff(); + buffs[i] = trans[i]->get_send_buff(timeout); + good = good and (buffs[i].get() != NULL); } - return true; + return good; } size_t usrp2_impl::send( const std::vector &buffs, size_t num_samps, const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode + send_mode_t send_mode, double timeout ){ return vrt_packet_handler::send( _io_impl->packet_handler_send_state, //last state of the send handler @@ -213,7 +213,7 @@ size_t usrp2_impl::send( io_type, _io_helper.get_tx_otw_type(), //input and output types to convert _mboards.front()->get_master_clock_freq(), //master clock tick rate uhd::transport::vrt::if_hdr_pack_be, - boost::bind(&get_send_buffs, _data_transports, _1), + boost::bind(&get_send_buffs, _data_transports, _1, timeout), get_max_send_samps_per_packet() ); } @@ -224,7 +224,7 @@ size_t usrp2_impl::send( size_t usrp2_impl::recv( const std::vector &buffs, size_t num_samps, rx_metadata_t &metadata, const io_type_t &io_type, - recv_mode_t recv_mode, size_t timeout_ms + recv_mode_t recv_mode, double timeout ){ return vrt_packet_handler::recv( _io_impl->packet_handler_recv_state, //last state of the recv handler @@ -233,6 +233,6 @@ size_t usrp2_impl::recv( io_type, _io_helper.get_rx_otw_type(), //input and output types to convert _mboards.front()->get_master_clock_freq(), //master clock tick rate uhd::transport::vrt::if_hdr_unpack_be, - boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout_ms) + boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout) ); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 157d17057..e8763b284 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -234,7 +234,7 @@ public: size_t send( const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, - uhd::device::send_mode_t + uhd::device::send_mode_t, double ); size_t get_max_recv_samps_per_packet(void) const{ return _io_helper.get_max_recv_samps_per_packet(); @@ -242,9 +242,9 @@ public: size_t recv( const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, - uhd::device::recv_mode_t, size_t + uhd::device::recv_mode_t, double ); - bool recv_async_msg(uhd::async_metadata_t &, size_t); + bool recv_async_msg(uhd::async_metadata_t &, double); private: //device properties interface diff --git a/host/test/buffer_test.cpp b/host/test/buffer_test.cpp index aadb3f951..8445412e7 100644 --- a/host/test/buffer_test.cpp +++ b/host/test/buffer_test.cpp @@ -23,7 +23,7 @@ using namespace boost::assign; using namespace uhd::transport; -static const boost::posix_time::milliseconds timeout(10); +static const double timeout = 0.01/*secs*/; BOOST_AUTO_TEST_CASE(test_bounded_buffer_with_timed_wait){ bounded_buffer::sptr bb(bounded_buffer::make(3)); -- cgit v1.2.3 From 7352c95037fa57d37dd7adc4c2ea6935006b56c8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 2 Oct 2010 23:15:46 -0700 Subject: uhd: reworked the zero copy interface - recv buffers have a release call - safe make function for recv buffers (buff + release callback) - send buffer commits now have a void return - safe make function for send buffers (buff + commit callback) The reason for the void return from commit is that ssize_t num_bytes was never returning anything of use. That is for all of the zero copy implementations so far, commit cannot really error (being asynchronous). libusb zero copy impl was reworked to support the new interface. USRP1 io_impl with the psuedo managed buffer was replaced with safe_make. Also, usrp1 io_impl was simplified greatly due to commit returning void now. UDP zero copy asio was disabled (in this commit, until its reworked). Phony send and recv interfaces were removed completely. --- host/include/uhd/transport/zero_copy.hpp | 112 +++++++--------------- host/lib/transport/CMakeLists.txt | 4 +- host/lib/transport/libusb1_zero_copy.cpp | 149 +++++++----------------------- host/lib/transport/vrt_packet_handler.hpp | 4 +- host/lib/transport/zero_copy.cpp | 121 +++++++++--------------- host/lib/usrp/usrp1/io_impl.cpp | 65 ++++--------- 6 files changed, 130 insertions(+), 325 deletions(-) diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp index ba19b193c..9dd16280c 100644 --- a/host/include/uhd/transport/zero_copy.hpp +++ b/host/include/uhd/transport/zero_copy.hpp @@ -19,10 +19,10 @@ #define INCLUDED_UHD_TRANSPORT_ZERO_COPY_HPP #include -#include #include #include #include +#include namespace uhd{ namespace transport{ @@ -34,14 +34,27 @@ namespace uhd{ namespace transport{ class UHD_API managed_recv_buffer : boost::noncopyable{ public: typedef boost::shared_ptr sptr; + typedef boost::function release_fcn_t; + + /*! + * Make a safe managed receive buffer: + * A safe managed buffer ensures that release is called once, + * either by the user or automatically upon deconstruction. + * \param buff a reference to the constant buffer + * \param release_fcn callback to release the memory + * \return a new managed receive buffer + */ + static sptr make_safe( + const boost::asio::const_buffer &buff, + const release_fcn_t &release_fcn + ); /*! - * 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. + * This should be called to release the buffer to the transport object. * After calling, the referenced memory should be considered invalid. */ - virtual ~managed_recv_buffer(void) = 0; + virtual void release(void) = 0; /*! * Get the size of the underlying buffer. @@ -71,20 +84,34 @@ namespace uhd{ namespace transport{ /*! * A managed send buffer: * Contains a reference to transport-managed memory, - * and a method to release the memory after writing. + * and a method to commit the memory after writing. */ class UHD_API managed_send_buffer : boost::noncopyable{ public: typedef boost::shared_ptr sptr; + typedef boost::function commit_fcn_t; + + /*! + * Make a safe managed send buffer: + * A safe managed buffer ensures that commit is called once, + * either by the user or automatically upon deconstruction. + * In the later case, the deconstructor will call commit(0). + * \param buff a reference to the mutable buffer + * \param commit_fcn callback to commit the memory + * \return a new managed send buffer + */ + static sptr make_safe( + const boost::asio::mutable_buffer &buff, + const commit_fcn_t &commit_fcn + ); /*! * Signal to the transport that we are done with the buffer. * This should be called to commit the write to the transport object. * After calling, the referenced memory should be considered invalid. * \param num_bytes the number of bytes written into the buffer - * \return the number of bytes written, 0 for timeout, negative for error */ - virtual ssize_t commit(size_t num_bytes) = 0; + virtual void commit(size_t num_bytes) = 0; /*! * Get the size of the underlying buffer. @@ -154,77 +181,6 @@ namespace uhd{ namespace transport{ }; - /*! - * A phony-zero-copy interface for transport objects that - * provides a zero-copy interface on top of copying transport. - * This interface implements the get managed recv buffer, - * the base class must implement the private recv method. - */ - class UHD_API phony_zero_copy_recv_if : public virtual zero_copy_if{ - public: - /*! - * Create a phony zero copy recv interface. - * \param max_buff_size max buffer size in bytes - */ - phony_zero_copy_recv_if(size_t max_buff_size); - - //! destructor - virtual ~phony_zero_copy_recv_if(void); - - /*! - * Get a new receive buffer from this transport object. - * \param timeout the timeout to get the buffer in seconds - * \return a managed buffer, or null sptr on timeout/error - */ - managed_recv_buffer::sptr get_recv_buff(double timeout); - - private: - /*! - * Perform a private copying recv. - * \param buff the buffer to write data into - * \param timeout the timeout to get the buffer in seconds - * \return the number of bytes written to buff, 0 for timeout, negative for error - */ - virtual ssize_t recv(const boost::asio::mutable_buffer &buff, double timeout) = 0; - - UHD_PIMPL_DECL(impl) _impl; - }; - - /*! - * A phony-zero-copy interface for transport objects that - * provides a zero-copy interface on top of copying transport. - * This interface implements the get managed send buffer, - * the base class must implement the private send method. - */ - class UHD_API phony_zero_copy_send_if : public virtual zero_copy_if{ - public: - /*! - * Create a phony zero copy send interface. - * \param max_buff_size max buffer size in bytes - */ - phony_zero_copy_send_if(size_t max_buff_size); - - //! destructor - virtual ~phony_zero_copy_send_if(void); - - /*! - * Get a new send buffer from this transport object. - * \param timeout the timeout to get the buffer in seconds - * \return a managed buffer, or null sptr on timeout/error - */ - managed_send_buffer::sptr get_send_buff(double timeout); - - private: - /*! - * Perform a private copying send. - * \param buff the buffer to read data from - * \return the number of bytes read from buff, 0 for timeout, negative for error - */ - virtual ssize_t send(const boost::asio::const_buffer &buff) = 0; - - UHD_PIMPL_DECL(impl) _impl; - }; - }} //namespace #endif /* INCLUDED_UHD_TRANSPORT_ZERO_COPY_HPP */ diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index 61616d077..2be2c89ec 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -36,6 +36,8 @@ IF(LIBUSB_FOUND) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/transport/msvc) ENDIF(MSVC) SET(HAVE_USB_SUPPORT TRUE) +ELSE(LIBUSB_FOUND) + #TODO dummy usb ENDIF(LIBUSB_FOUND) IF(HAVE_USB_SUPPORT) @@ -99,7 +101,7 @@ SET_SOURCE_FILES_PROPERTIES( 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/udp_zero_copy_asio.cpp ${CMAKE_SOURCE_DIR}/lib/transport/vrt_packet_handler.hpp ${CMAKE_SOURCE_DIR}/lib/transport/zero_copy.cpp ) diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index 7f2bc3468..e1cc8398c 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -95,9 +95,6 @@ private: int _endpoint; bool _input; - size_t _transfer_size; - size_t _num_transfers; - //! hold a bounded buffer of completed transfers typedef bounded_buffer lut_buff_type; lut_buff_type::sptr _completed_list; @@ -154,14 +151,12 @@ usb_endpoint::usb_endpoint( ): _handle(handle), _endpoint(endpoint), - _input(input), - _transfer_size(transfer_size), - _num_transfers(num_transfers) + _input(input) { _completed_list = lut_buff_type::make(num_transfers); - for (size_t i = 0; i < _num_transfers; i++){ - _all_luts.push_back(allocate_transfer(_transfer_size)); + for (size_t i = 0; i < num_transfers; i++){ + _all_luts.push_back(allocate_transfer(transfer_size)); //input luts are immediately submitted to be filled //output luts go into the completed list as free buffers @@ -280,126 +275,44 @@ libusb_transfer *usb_endpoint::get_lut_with_wait(double timeout){ } /*********************************************************************** - * Managed buffers + * USB zero_copy device class **********************************************************************/ -/* - * Libusb managed receive buffer - * Construct a recv buffer from a libusb transfer. The memory held by - * the libusb transfer is exposed through the managed buffer interface. - * Upon destruction, the transfer and buffer are resubmitted to the - * endpoint for further use. - */ -class libusb_managed_recv_buffer_impl : public managed_recv_buffer { +class libusb_zero_copy_impl : public usb_zero_copy { public: - libusb_managed_recv_buffer_impl(libusb_transfer *lut, - usb_endpoint::sptr endpoint) - : _buff(lut->buffer, lut->length) - { - _lut = lut; - _endpoint = endpoint; - } - - ~libusb_managed_recv_buffer_impl(void){ - _endpoint->submit(_lut); - } + typedef boost::shared_ptr sptr; -private: - const boost::asio::const_buffer &get(void) const{ - return _buff; - } + libusb_zero_copy_impl( + libusb::device_handle::sptr handle, + unsigned int recv_endpoint, unsigned int send_endpoint, + size_t recv_xfer_size, size_t recv_num_xfers, + size_t send_xfer_size, size_t send_num_xfers + ); - libusb_transfer *_lut; - usb_endpoint::sptr _endpoint; - const boost::asio::const_buffer _buff; -}; + managed_recv_buffer::sptr get_recv_buff(double); + managed_send_buffer::sptr get_send_buff(double); -/* - * Libusb managed send buffer - * Construct a send buffer from a libusb transfer. The memory held by - * the libusb transfer is exposed through the managed buffer interface. - * Committing the buffer will set the data length and submit the buffer - * to the endpoint. Submitting a buffer multiple times or destroying - * the buffer before committing is an error. For the latter, the transfer - * is returned to the endpoint with no data for reuse. - */ -class libusb_managed_send_buffer_impl : public managed_send_buffer { -public: - libusb_managed_send_buffer_impl(libusb_transfer *lut, - usb_endpoint::sptr endpoint) - : _buff(lut->buffer, lut->length), _committed(false) - { - _lut = lut; - _endpoint = endpoint; - } + size_t get_num_recv_frames(void) const { return _recv_num_frames; } + size_t get_num_send_frames(void) const { return _send_num_frames; } - ~libusb_managed_send_buffer_impl(void){ - if (!_committed) { - _lut->length = 0; - _lut->actual_length = 0; - _endpoint->submit(_lut); - } +private: + void release(libusb_transfer *lut){ + _recv_ep->submit(lut); } - ssize_t commit(size_t num_bytes) - { - if (_committed) { - std::cerr << "UHD: send buffer already committed" << std::endl; - return 0; - } - - UHD_ASSERT_THROW(num_bytes <= boost::asio::buffer_size(_buff)); - - _lut->length = num_bytes; - _lut->actual_length = 0; - + void commit(libusb_transfer *lut, size_t num_bytes){ + lut->length = num_bytes; try{ - _endpoint->submit(_lut); - _committed = true; - return num_bytes; + _send_ep->submit(lut); } catch(const std::exception &e){ std::cerr << "Error in commit: " << e.what() << std::endl; - return -1; } } -private: - const boost::asio::mutable_buffer &get(void) const{ - return _buff; - } - - libusb_transfer *_lut; - usb_endpoint::sptr _endpoint; - const boost::asio::mutable_buffer _buff; - bool _committed; -}; - - -/*********************************************************************** - * USB zero_copy device class - **********************************************************************/ -class libusb_zero_copy_impl : public usb_zero_copy -{ -private: libusb::device_handle::sptr _handle; + size_t _recv_xfer_size, _send_xfer_size; size_t _recv_num_frames, _send_num_frames; usb_endpoint::sptr _recv_ep, _send_ep; - -public: - typedef boost::shared_ptr sptr; - - libusb_zero_copy_impl( - libusb::device_handle::sptr handle, - unsigned int recv_endpoint, unsigned int send_endpoint, - size_t recv_xfer_size, size_t recv_num_xfers, - size_t send_xfer_size, size_t send_num_xfers - ); - - managed_recv_buffer::sptr get_recv_buff(double); - managed_send_buffer::sptr get_send_buff(double); - - size_t get_num_recv_frames(void) const { return _recv_num_frames; } - size_t get_num_send_frames(void) const { return _send_num_frames; } }; /* @@ -426,7 +339,9 @@ libusb_zero_copy_impl::libusb_zero_copy_impl( UHD_ASSERT_THROW(send_xfer_size % 512 == 0); //store the num xfers for the num frames count + _recv_xfer_size = recv_xfer_size; _recv_num_frames = recv_num_xfers; + _send_xfer_size = send_xfer_size; _send_num_frames = send_num_xfers; _handle->claim_interface(2 /*in interface*/); @@ -461,9 +376,10 @@ managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(double timeout){ return managed_recv_buffer::sptr(); } else { - return managed_recv_buffer::sptr( - new libusb_managed_recv_buffer_impl(lut, - _recv_ep)); + return managed_recv_buffer::make_safe( + boost::asio::const_buffer(lut->buffer, lut->actual_length), + boost::bind(&libusb_zero_copy_impl::release, this, lut) + ); } } @@ -480,9 +396,10 @@ managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(double timeout){ return managed_send_buffer::sptr(); } else { - return managed_send_buffer::sptr( - new libusb_managed_send_buffer_impl(lut, - _send_ep)); + return managed_send_buffer::make_safe( + boost::asio::mutable_buffer(lut->buffer, _send_xfer_size), + boost::bind(&libusb_zero_copy_impl::commit, this, lut, _1) + ); } } diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index e11afff30..939517411 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -343,9 +343,7 @@ template UHD_INLINE T get_context_code( //commit the samples to the zero-copy interface size_t num_bytes_total = (vrt_header_offset_words32+if_packet_info.num_packet_words32)*sizeof(boost::uint32_t); - if (send_buffs[i]->commit(num_bytes_total) < ssize_t(num_bytes_total)){ - std::cerr << "commit to send buffer returned less than commit size" << std::endl; - } + send_buffs[i]->commit(num_bytes_total); } return num_samps; } diff --git a/host/lib/transport/zero_copy.cpp b/host/lib/transport/zero_copy.cpp index dfb65951f..a5a864a04 100644 --- a/host/lib/transport/zero_copy.cpp +++ b/host/lib/transport/zero_copy.cpp @@ -16,32 +16,35 @@ // #include -#include -#include -#include using namespace uhd::transport; /*********************************************************************** - * The pure-virtual deconstructor needs an implementation to be happy + * Safe managed receive buffer **********************************************************************/ -managed_recv_buffer::~managed_recv_buffer(void){ +static void release_nop(void){ /* NOP */ } -/*********************************************************************** - * Phony zero-copy recv interface implementation - **********************************************************************/ - -//! phony zero-copy recv buffer implementation -class managed_recv_buffer_impl : public managed_recv_buffer{ +class safe_managed_receive_buffer : public managed_recv_buffer{ public: - managed_recv_buffer_impl(const boost::asio::const_buffer &buff) : _buff(buff){ + safe_managed_receive_buffer( + const boost::asio::const_buffer &buff, + const release_fcn_t &release_fcn + ): + _buff(buff), _release_fcn(release_fcn) + { /* NOP */ } - ~managed_recv_buffer_impl(void){ - delete [] this->cast(); + ~safe_managed_receive_buffer(void){ + _release_fcn(); + } + + void release(void){ + release_fcn_t release_fcn = _release_fcn; + _release_fcn = &release_nop; + return release_fcn(); } private: @@ -50,64 +53,42 @@ private: } const boost::asio::const_buffer _buff; + release_fcn_t _release_fcn; }; -//! phony zero-copy recv interface implementation -struct phony_zero_copy_recv_if::impl{ - impl(size_t max_buff_size) : max_buff_size(max_buff_size){ - /* NOP */ - } - size_t max_buff_size; -}; - -phony_zero_copy_recv_if::phony_zero_copy_recv_if(size_t max_buff_size){ - _impl = UHD_PIMPL_MAKE(impl, (max_buff_size)); -} - -phony_zero_copy_recv_if::~phony_zero_copy_recv_if(void){ - /* NOP */ -} - -managed_recv_buffer::sptr phony_zero_copy_recv_if::get_recv_buff(double timeout){ - //allocate memory - boost::uint8_t *recv_mem = new boost::uint8_t[_impl->max_buff_size]; - - //call recv() with timeout option - ssize_t num_bytes = this->recv(boost::asio::buffer(recv_mem, _impl->max_buff_size), timeout); - - if (num_bytes <= 0) return managed_recv_buffer::sptr(); //NULL sptr - - //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)) - ); +managed_recv_buffer::sptr managed_recv_buffer::make_safe( + const boost::asio::const_buffer &buff, + const release_fcn_t &release_fcn +){ + return sptr(new safe_managed_receive_buffer(buff, release_fcn)); } /*********************************************************************** - * Phony zero-copy send interface implementation + * Safe managed send buffer **********************************************************************/ +static void commit_nop(size_t){ + /* NOP */ +} -//! phony zero-copy send buffer implementation -class managed_send_buffer_impl : public managed_send_buffer{ +class safe_managed_send_buffer : public managed_send_buffer{ public: - typedef boost::function send_fcn_t; - - managed_send_buffer_impl( + safe_managed_send_buffer( const boost::asio::mutable_buffer &buff, - const send_fcn_t &send_fcn + const commit_fcn_t &commit_fcn ): - _buff(buff), - _send_fcn(send_fcn) + _buff(buff), _commit_fcn(commit_fcn) { /* NOP */ } - ~managed_send_buffer_impl(void){ - /* NOP */ + ~safe_managed_send_buffer(void){ + _commit_fcn(0); } - ssize_t commit(size_t num_bytes){ - return _send_fcn(boost::asio::buffer(_buff, num_bytes)); + void commit(size_t num_bytes){ + commit_fcn_t commit_fcn = _commit_fcn; + _commit_fcn = &commit_nop; + return commit_fcn(num_bytes); } private: @@ -116,28 +97,12 @@ private: } const boost::asio::mutable_buffer _buff; - const send_fcn_t _send_fcn; -}; - -//! phony zero-copy send interface implementation -struct phony_zero_copy_send_if::impl{ - boost::uint8_t *send_mem; - managed_send_buffer::sptr send_buff; + commit_fcn_t _commit_fcn; }; -phony_zero_copy_send_if::phony_zero_copy_send_if(size_t max_buff_size){ - _impl = UHD_PIMPL_MAKE(impl, ()); - _impl->send_mem = new boost::uint8_t[max_buff_size]; - _impl->send_buff = managed_send_buffer::sptr(new managed_send_buffer_impl( - boost::asio::buffer(_impl->send_mem, max_buff_size), - boost::bind(&phony_zero_copy_send_if::send, this, _1) - )); -} - -phony_zero_copy_send_if::~phony_zero_copy_send_if(void){ - delete [] _impl->send_mem; -} - -managed_send_buffer::sptr phony_zero_copy_send_if::get_send_buff(double){ - return _impl->send_buff; //FIXME there is only ever one send buff, we assume that the caller doesnt hang onto these +safe_managed_send_buffer::sptr managed_send_buffer::make_safe( + const boost::asio::mutable_buffer &buff, + const commit_fcn_t &commit_fcn +){ + return sptr(new safe_managed_send_buffer(buff, commit_fcn)); } diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 8d9c68961..676b1536a 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -33,35 +33,6 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; -/*********************************************************************** - * Pseudo send buffer implementation - **********************************************************************/ -class pseudo_managed_send_buffer : public managed_send_buffer{ -public: - - pseudo_managed_send_buffer( - const boost::asio::mutable_buffer &buff, - const boost::function &commit - ): - _buff(buff), - _commit(commit) - { - /* NOP */ - } - - ssize_t commit(size_t num_bytes){ - return _commit(num_bytes); - } - -private: - const boost::asio::mutable_buffer &get(void) const{ - return _buff; - } - - const boost::asio::mutable_buffer _buff; - const boost::function _commit; -}; - /*********************************************************************** * IO Implementation Details **********************************************************************/ @@ -96,9 +67,9 @@ struct usrp1_impl::io_impl{ size_t num_bytes_committed; double send_timeout; boost::uint8_t pseudo_buff[BYTES_PER_PACKET]; - ssize_t phony_commit_pseudo_buff(size_t num_bytes); - ssize_t phony_commit_send_buff(size_t num_bytes); - ssize_t commit_send_buff(void); + void phony_commit_pseudo_buff(size_t num_bytes); + void phony_commit_send_buff(size_t num_bytes); + void commit_send_buff(void); void flush_send_buff(void); bool get_send_buffs(vrt_packet_handler::managed_send_buffs_t &, double); @@ -119,28 +90,25 @@ struct usrp1_impl::io_impl{ * The first loop iteration will fill the remainder of the send buffer. * The second loop iteration will empty the pseudo buffer remainder. */ -ssize_t usrp1_impl::io_impl::phony_commit_pseudo_buff(size_t num_bytes){ +void usrp1_impl::io_impl::phony_commit_pseudo_buff(size_t num_bytes){ size_t bytes_to_copy = num_bytes, bytes_copied = 0; while(bytes_to_copy){ size_t bytes_copied_here = std::min(bytes_to_copy, get_send_mem_size()); std::memcpy(get_send_mem_ptr(), pseudo_buff + bytes_copied, bytes_copied_here); - ssize_t ret = phony_commit_send_buff(bytes_copied_here); - if (ret < 0) return ret; - bytes_to_copy -= ret; - bytes_copied += ret; + phony_commit_send_buff(bytes_copied_here); + bytes_to_copy -= bytes_copied_here; + bytes_copied += bytes_copied_here; } - return bytes_copied; } /*! * Accept a commit of num bytes to the send buffer. * Conditionally commit the send buffer if full. */ -ssize_t usrp1_impl::io_impl::phony_commit_send_buff(size_t num_bytes){ +void usrp1_impl::io_impl::phony_commit_send_buff(size_t num_bytes){ num_bytes_committed += num_bytes; - if (num_bytes_committed != send_buff->size()) return num_bytes; - ssize_t ret = commit_send_buff(); - return (ret < 0)? ret : num_bytes; + if (num_bytes_committed != send_buff->size()) return; + commit_send_buff(); } /*! @@ -158,11 +126,10 @@ void usrp1_impl::io_impl::flush_send_buff(void){ * Perform an actual commit on the send buffer: * Commit the contents of the send buffer and request a new buffer. */ -ssize_t usrp1_impl::io_impl::commit_send_buff(void){ - ssize_t ret = send_buff->commit(num_bytes_committed); +void usrp1_impl::io_impl::commit_send_buff(void){ + send_buff->commit(num_bytes_committed); send_buff = data_transport->get_send_buff(send_timeout); num_bytes_committed = 0; - return ret; } bool usrp1_impl::io_impl::get_send_buffs( @@ -173,17 +140,17 @@ bool usrp1_impl::io_impl::get_send_buffs( //not enough bytes free -> use the pseudo buffer if (get_send_mem_size() < BYTES_PER_PACKET){ - buffs[0] = managed_send_buffer::sptr(new pseudo_managed_send_buffer( + buffs[0] = managed_send_buffer::make_safe( boost::asio::buffer(pseudo_buff), boost::bind(&usrp1_impl::io_impl::phony_commit_pseudo_buff, this, _1) - )); + ); } //otherwise use the send buffer offset by the bytes written else{ - buffs[0] = managed_send_buffer::sptr(new pseudo_managed_send_buffer( + buffs[0] = managed_send_buffer::make_safe( boost::asio::buffer(get_send_mem_ptr(), get_send_mem_size()), boost::bind(&usrp1_impl::io_impl::phony_commit_send_buff, this, _1) - )); + ); } return buffs[0].get() != NULL; -- cgit v1.2.3 From b57c84b34bcdd6c66eb053695b83e6bd6c481774 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 3 Oct 2010 01:41:24 -0700 Subject: uhd: implemented udp zero copy asio with async calls --- host/lib/transport/CMakeLists.txt | 2 +- host/lib/transport/libusb1_zero_copy.cpp | 6 +- host/lib/transport/udp_zero_copy_asio.cpp | 186 +++++++++++++++++++++--------- 3 files changed, 133 insertions(+), 61 deletions(-) diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index 2be2c89ec..bf92b0822 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -101,7 +101,7 @@ SET_SOURCE_FILES_PROPERTIES( 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/udp_zero_copy_asio.cpp ${CMAKE_SOURCE_DIR}/lib/transport/vrt_packet_handler.hpp ${CMAKE_SOURCE_DIR}/lib/transport/zero_copy.cpp ) diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index e1cc8398c..c819302b6 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -277,7 +277,7 @@ libusb_transfer *usb_endpoint::get_lut_with_wait(double timeout){ /*********************************************************************** * USB zero_copy device class **********************************************************************/ -class libusb_zero_copy_impl : public usb_zero_copy { +class libusb_zero_copy_impl : public usb_zero_copy, public boost::enable_shared_from_this { public: typedef boost::shared_ptr sptr; @@ -378,7 +378,7 @@ managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(double timeout){ else { return managed_recv_buffer::make_safe( boost::asio::const_buffer(lut->buffer, lut->actual_length), - boost::bind(&libusb_zero_copy_impl::release, this, lut) + boost::bind(&libusb_zero_copy_impl::release, shared_from_this(), lut) ); } } @@ -398,7 +398,7 @@ managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(double timeout){ else { return managed_send_buffer::make_safe( boost::asio::mutable_buffer(lut->buffer, _send_xfer_size), - boost::bind(&libusb_zero_copy_impl::commit, this, lut, _1) + boost::bind(&libusb_zero_copy_impl::commit, shared_from_this(), lut, _1) ); } } diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 3130830a5..70e7514a1 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -17,20 +17,23 @@ #include #include //mtu +#include #include #include -#include +#include #include #include +#include #include using namespace uhd::transport; +namespace asio = boost::asio; /*********************************************************************** * Constants **********************************************************************/ //enough buffering for half a second of samples at full rate on usrp2 -static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(sizeof(boost::uint32_t) * 25e6 * 0.5); +static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(4 * 25e6 * 0.5); //Large buffers cause more underflow at high rates. //Perhaps this is due to the kernel scheduling, //but may change with host-based flow control. @@ -43,39 +46,55 @@ static const size_t MIN_SEND_SOCK_BUFF_SIZE = size_t(10e3); * However, it is not a true zero copy implementation as each * send and recv requires a copy operation to/from userspace. **********************************************************************/ -class udp_zero_copy_impl: - public phony_zero_copy_recv_if, - public phony_zero_copy_send_if, - public udp_zero_copy -{ +class udp_zero_copy_asio_impl : public udp_zero_copy, public boost::enable_shared_from_this { public: - typedef boost::shared_ptr sptr; - - udp_zero_copy_impl( - const std::string &addr, - const std::string &port - ): - phony_zero_copy_recv_if(udp_simple::mtu), - phony_zero_copy_send_if(udp_simple::mtu) - { + typedef boost::shared_ptr sptr; + + udp_zero_copy_asio_impl(const std::string &addr, const std::string &port){ //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; // resolve the address - boost::asio::ip::udp::resolver resolver(_io_service); - boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port); - boost::asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query); + asio::ip::udp::resolver resolver(_io_service); + asio::ip::udp::resolver::query query(asio::ip::udp::v4(), addr, port); + asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query); // create, open, and connect the socket - _socket = new boost::asio::ip::udp::socket(_io_service); - _socket->open(boost::asio::ip::udp::v4()); + _socket = new asio::ip::udp::socket(_io_service); + _socket->open(asio::ip::udp::v4()); _socket->connect(receiver_endpoint); - _sock_fd = _socket->native(); } - ~udp_zero_copy_impl(void){ + ~udp_zero_copy_asio_impl(void){ + _io_service.stop(); + _thread_group.join_all(); delete _socket; } + /*! + * Init, the second contructor: + * Allocate memory and spwan service thread. + */ + void init(void){ + //allocate all recv frames and release them to begin xfers + _pending_recv_buffs = pending_buffs_type::make(this->get_num_recv_frames()); + for (size_t i = 0; i < this->get_num_recv_frames(); i++){ + boost::shared_array buff(new char[udp_simple::mtu]); + _buffers.push_back(buff); //store a reference to this shared array + release(buff.get()); + } + + //allocate all send frames and push them into the fifo + _pending_send_buffs = pending_buffs_type::make(this->get_num_send_frames()); + for (size_t i = 0; i < this->get_num_send_frames(); i++){ + boost::shared_array buff(new char[udp_simple::mtu]); + _buffers.push_back(buff); //store a reference to this shared array + handle_send(buff.get()); + } + + //spawn the service thread that will run the io service + _thread_group.create_thread(boost::bind(&udp_zero_copy_asio_impl::service, this)); + } + //get size for internal socket buffer template size_t get_buff_size(void) const{ Opt option; @@ -90,60 +109,111 @@ public: return get_buff_size(); } - //The number of frames is approximately the buffer size divided by the max datagram size. //In reality, this is a phony zero-copy interface and the number of frames is infinite. //However, its sensible to advertise a frame count that is approximate to buffer size. //This way, the transport caller will have an idea about how much buffering to create. size_t get_num_recv_frames(void) const{ - return this->get_buff_size()/udp_simple::mtu; + return this->get_buff_size()/udp_simple::mtu; } size_t get_num_send_frames(void) const{ - return this->get_buff_size()/udp_simple::mtu; + return this->get_buff_size()/udp_simple::mtu; + } + + //! pop a filled recv buffer off of the fifo and bind with the release callback + managed_recv_buffer::sptr get_recv_buff(double timeout){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + asio::mutable_buffer buff; + if (_pending_recv_buffs->pop_with_timed_wait(buff, timeout)){ + return managed_recv_buffer::make_safe( + buff, boost::bind( + &udp_zero_copy_asio_impl::release, + shared_from_this(), + asio::buffer_cast(buff) + ) + ); + } + return managed_recv_buffer::sptr(); + } + + //! pop an empty send buffer off of the fifo and bind with the commit callback + managed_send_buffer::sptr get_send_buff(double timeout){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + asio::mutable_buffer buff; + if (_pending_send_buffs->pop_with_timed_wait(buff, timeout)){ + return managed_send_buffer::make_safe( + buff, boost::bind( + &udp_zero_copy_asio_impl::commit, + shared_from_this(), + asio::buffer_cast(buff), _1 + ) + ); + } + return managed_send_buffer::sptr(); } private: - boost::asio::ip::udp::socket *_socket; - boost::asio::io_service _io_service; - int _sock_fd; - - ssize_t recv(const boost::asio::mutable_buffer &buff, double timeout){ - //setup timeval for timeout - timeval tv; - tv.tv_sec = 0; - tv.tv_usec = long(timeout*1e6); - - //setup rset for timeout - fd_set rset; - FD_ZERO(&rset); - FD_SET(_sock_fd, &rset); - - //call select to perform timed wait - if (::select(_sock_fd+1, &rset, NULL, NULL, &tv) <= 0) return 0; - - return ::recv( - _sock_fd, - boost::asio::buffer_cast(buff), - boost::asio::buffer_size(buff), 0 + void service(void){ + _io_service.run(); + } + + /******************************************************************* + * The async send and receive callbacks + ******************************************************************/ + + //! handle a recv callback -> push the filled memory into the fifo + void handle_recv(void *mem, size_t len){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + _pending_recv_buffs->push_with_wait(boost::asio::buffer(mem, len)); + } + + //! release a recv buffer -> start an async recv on the buffer + void release(void *mem){ + _socket->async_receive( + boost::asio::buffer(mem, udp_simple::mtu), + boost::bind( + &udp_zero_copy_asio_impl::handle_recv, + shared_from_this(), mem, + asio::placeholders::bytes_transferred + ) ); } - ssize_t send(const boost::asio::const_buffer &buff){ - return ::send( - _sock_fd, - boost::asio::buffer_cast(buff), - boost::asio::buffer_size(buff), 0 + //! handle a send callback -> push the emptied memory into the fifo + void handle_send(void *mem){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + _pending_send_buffs->push_with_wait(boost::asio::buffer(mem, udp_simple::mtu)); + } + + //! commit a send buffer -> start an async send on the buffer + void commit(void *mem, size_t len){ + _socket->async_send( + boost::asio::buffer(mem, len), + boost::bind( + &udp_zero_copy_asio_impl::handle_send, + shared_from_this(), mem + ) ); } + + //asio guts -> socket and service + asio::ip::udp::socket *_socket; + asio::io_service _io_service; + + //memory management -> buffers and fifos + boost::thread_group _thread_group; + std::vector > _buffers; + typedef bounded_buffer pending_buffs_type; + pending_buffs_type::sptr _pending_recv_buffs, _pending_send_buffs; }; /*********************************************************************** * UDP zero copy make function **********************************************************************/ template static void resize_buff_helper( - udp_zero_copy_impl::sptr udp_trans, + udp_zero_copy_asio_impl::sptr udp_trans, size_t target_size, const std::string &name ){ @@ -183,11 +253,13 @@ udp_zero_copy::sptr udp_zero_copy::make( size_t recv_buff_size, size_t send_buff_size ){ - udp_zero_copy_impl::sptr udp_trans(new udp_zero_copy_impl(addr, port)); + udp_zero_copy_asio_impl::sptr udp_trans(new udp_zero_copy_asio_impl(addr, port)); //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"); + resize_buff_helper(udp_trans, recv_buff_size, "recv"); + resize_buff_helper (udp_trans, send_buff_size, "send"); + + udp_trans->init(); //buffers resized -> call init() to use return udp_trans; } -- cgit v1.2.3 From c6f17f1e2f908747ae1547fa43b2c22c3c20ba50 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 3 Oct 2010 19:34:41 -0700 Subject: uhd: changed buffer allocations to be in a single chunk, udp: pass frame sizes into the impl constructor --- host/lib/transport/libusb1_zero_copy.cpp | 27 +++++----- host/lib/transport/udp_zero_copy_asio.cpp | 85 ++++++++++++++++--------------- 2 files changed, 59 insertions(+), 53 deletions(-) diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index c819302b6..ab48e4fc4 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -100,13 +100,13 @@ private: lut_buff_type::sptr _completed_list; //! a list of all transfer structs we allocated - std::vector _all_luts; + std::vector _all_luts; - //! a list of shared arrays for the transfer buffers - std::vector > _buffers; + //! a block of memory for the transfer buffers + boost::shared_array _buffer; // Calls for processing asynchronous I/O - libusb_transfer *allocate_transfer(int buff_len); + libusb_transfer *allocate_transfer(void *mem, size_t len); void print_transfer_status(libusb_transfer *lut); }; @@ -154,9 +154,9 @@ usb_endpoint::usb_endpoint( _input(input) { _completed_list = lut_buff_type::make(num_transfers); - + _buffer = boost::shared_array(new char[num_transfers*transfer_size]); for (size_t i = 0; i < num_transfers; i++){ - _all_luts.push_back(allocate_transfer(transfer_size)); + _all_luts.push_back(allocate_transfer(_buffer.get() + i*transfer_size, transfer_size)); //input luts are immediately submitted to be filled //output luts go into the completed list as free buffers @@ -193,23 +193,23 @@ usb_endpoint::~usb_endpoint(void){ * Allocate a libusb transfer * The allocated transfer - and buffer it contains - is repeatedly * submitted, reaped, and reused and should not be freed until shutdown. - * \param buff_len size of the individual buffer held by each transfer + * \param mem a pointer to the buffer memory + * \param len size of the individual buffer * \return pointer to an allocated libusb_transfer */ -libusb_transfer *usb_endpoint::allocate_transfer(int buff_len){ +libusb_transfer *usb_endpoint::allocate_transfer(void *mem, size_t len){ libusb_transfer *lut = libusb_alloc_transfer(0); - - boost::shared_array buff(new boost::uint8_t[buff_len]); - _buffers.push_back(buff); //store a reference to this shared array + UHD_ASSERT_THROW(lut != NULL); unsigned int endpoint = ((_endpoint & 0x7f) | (_input ? 0x80 : 0)); + unsigned char *buff = reinterpret_cast(mem); libusb_transfer_cb_fn lut_callback = libusb_transfer_cb_fn(&callback); libusb_fill_bulk_transfer(lut, // transfer _handle->get(), // dev_handle endpoint, // endpoint - buff.get(), // buffer - buff_len, // length + buff, // buffer + len, // length lut_callback, // callback this, // user_data 0); // timeout @@ -232,6 +232,7 @@ void usb_endpoint::submit(libusb_transfer *lut){ * \param lut pointer to an libusb_transfer */ void usb_endpoint::print_transfer_status(libusb_transfer *lut){ + std::cout << "here " << lut->status << std::endl; switch (lut->status) { case LIBUSB_TRANSFER_COMPLETED: if (lut->actual_length < lut->length) { diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 70e7514a1..a1eb516fc 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -18,6 +18,7 @@ #include #include //mtu #include +#include #include #include #include @@ -26,6 +27,7 @@ #include #include +using namespace uhd; using namespace uhd::transport; namespace asio = boost::asio; @@ -34,11 +36,15 @@ namespace asio = boost::asio; **********************************************************************/ //enough buffering for half a second of samples at full rate on usrp2 static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(4 * 25e6 * 0.5); + //Large buffers cause more underflow at high rates. //Perhaps this is due to the kernel scheduling, //but may change with host-based flow control. static const size_t MIN_SEND_SOCK_BUFF_SIZE = size_t(10e3); +//the number of async frames to allocate for each send and recv +static const size_t DEFAULT_NUM_ASYNC_FRAMES = 32; + /*********************************************************************** * Zero Copy UDP implementation with ASIO: * This is the portable zero copy implementation for systems @@ -50,51 +56,52 @@ class udp_zero_copy_asio_impl : public udp_zero_copy, public boost::enable_share public: typedef boost::shared_ptr sptr; - udp_zero_copy_asio_impl(const std::string &addr, const std::string &port){ + udp_zero_copy_asio_impl( + const std::string &addr, const std::string &port, + size_t recv_frame_size, size_t num_recv_frames, + size_t send_frame_size, size_t num_send_frames + ): + _recv_frame_size(recv_frame_size), _num_recv_frames(num_recv_frames), + _send_frame_size(send_frame_size), _num_send_frames(num_send_frames) + { //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; - // resolve the address + //resolve the address asio::ip::udp::resolver resolver(_io_service); asio::ip::udp::resolver::query query(asio::ip::udp::v4(), addr, port); asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query); - // create, open, and connect the socket + //create, open, and connect the socket _socket = new asio::ip::udp::socket(_io_service); _socket->open(asio::ip::udp::v4()); _socket->connect(receiver_endpoint); } - ~udp_zero_copy_asio_impl(void){ - _io_service.stop(); - _thread_group.join_all(); - delete _socket; - } - - /*! - * Init, the second contructor: - * Allocate memory and spwan service thread. - */ void init(void){ //allocate all recv frames and release them to begin xfers - _pending_recv_buffs = pending_buffs_type::make(this->get_num_recv_frames()); - for (size_t i = 0; i < this->get_num_recv_frames(); i++){ - boost::shared_array buff(new char[udp_simple::mtu]); - _buffers.push_back(buff); //store a reference to this shared array - release(buff.get()); + _pending_recv_buffs = pending_buffs_type::make(_num_recv_frames); + _recv_buffer = boost::shared_array(new char[_num_recv_frames*_recv_frame_size]); + for (size_t i = 0; i < _num_recv_frames; i++){ + release(_recv_buffer.get() + i*_recv_frame_size); } //allocate all send frames and push them into the fifo - _pending_send_buffs = pending_buffs_type::make(this->get_num_send_frames()); - for (size_t i = 0; i < this->get_num_send_frames(); i++){ - boost::shared_array buff(new char[udp_simple::mtu]); - _buffers.push_back(buff); //store a reference to this shared array - handle_send(buff.get()); + _pending_send_buffs = pending_buffs_type::make(_num_send_frames); + _send_buffer = boost::shared_array(new char[_num_send_frames*_send_frame_size]); + for (size_t i = 0; i < _num_send_frames; i++){ + handle_send(_send_buffer.get() + i*_send_frame_size); } //spawn the service thread that will run the io service _thread_group.create_thread(boost::bind(&udp_zero_copy_asio_impl::service, this)); } + ~udp_zero_copy_asio_impl(void){ + _io_service.stop(); + _thread_group.join_all(); + delete _socket; + } + //get size for internal socket buffer template size_t get_buff_size(void) const{ Opt option; @@ -109,19 +116,6 @@ public: return get_buff_size(); } - //The number of frames is approximately the buffer size divided by the max datagram size. - //In reality, this is a phony zero-copy interface and the number of frames is infinite. - //However, its sensible to advertise a frame count that is approximate to buffer size. - //This way, the transport caller will have an idea about how much buffering to create. - - size_t get_num_recv_frames(void) const{ - return this->get_buff_size()/udp_simple::mtu; - } - - size_t get_num_send_frames(void) const{ - return this->get_buff_size()/udp_simple::mtu; - } - //! pop a filled recv buffer off of the fifo and bind with the release callback managed_recv_buffer::sptr get_recv_buff(double timeout){ boost::this_thread::disable_interruption di; //disable because the wait can throw @@ -138,6 +132,8 @@ public: return managed_recv_buffer::sptr(); } + size_t get_num_recv_frames(void) const {return _num_recv_frames;} + //! pop an empty send buffer off of the fifo and bind with the commit callback managed_send_buffer::sptr get_send_buff(double timeout){ boost::this_thread::disable_interruption di; //disable because the wait can throw @@ -154,8 +150,11 @@ public: return managed_send_buffer::sptr(); } + size_t get_num_send_frames(void) const {return _num_send_frames;} + private: void service(void){ + set_thread_priority_safe(); _io_service.run(); } @@ -172,7 +171,7 @@ private: //! release a recv buffer -> start an async recv on the buffer void release(void *mem){ _socket->async_receive( - boost::asio::buffer(mem, udp_simple::mtu), + boost::asio::buffer(mem, _recv_frame_size), boost::bind( &udp_zero_copy_asio_impl::handle_recv, shared_from_this(), mem, @@ -184,7 +183,7 @@ private: //! handle a send callback -> push the emptied memory into the fifo void handle_send(void *mem){ boost::this_thread::disable_interruption di; //disable because the wait can throw - _pending_send_buffs->push_with_wait(boost::asio::buffer(mem, udp_simple::mtu)); + _pending_send_buffs->push_with_wait(boost::asio::buffer(mem, _send_frame_size)); } //! commit a send buffer -> start an async send on the buffer @@ -204,9 +203,11 @@ private: //memory management -> buffers and fifos boost::thread_group _thread_group; - std::vector > _buffers; + boost::shared_array _send_buffer, _recv_buffer; typedef bounded_buffer pending_buffs_type; pending_buffs_type::sptr _pending_recv_buffs, _pending_send_buffs; + const size_t _recv_frame_size, _num_recv_frames; + const size_t _send_frame_size, _num_send_frames; }; /*********************************************************************** @@ -253,7 +254,11 @@ udp_zero_copy::sptr udp_zero_copy::make( size_t recv_buff_size, size_t send_buff_size ){ - udp_zero_copy_asio_impl::sptr udp_trans(new udp_zero_copy_asio_impl(addr, port)); + udp_zero_copy_asio_impl::sptr udp_trans(new udp_zero_copy_asio_impl( + addr, port, + udp_simple::mtu, DEFAULT_NUM_ASYNC_FRAMES, //recv + udp_simple::mtu, DEFAULT_NUM_ASYNC_FRAMES //send + )); //call the helper to resize send and recv buffers resize_buff_helper(udp_trans, recv_buff_size, "recv"); -- cgit v1.2.3 From 57ad303e850f143573d8c6edb1a88542b7b43350 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 4 Oct 2010 09:28:26 -0700 Subject: udp: added io service work to keep service running --- host/lib/transport/udp_zero_copy_asio.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index a1eb516fc..2cf7bde18 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -45,6 +45,9 @@ static const size_t MIN_SEND_SOCK_BUFF_SIZE = size_t(10e3); //the number of async frames to allocate for each send and recv static const size_t DEFAULT_NUM_ASYNC_FRAMES = 32; +//a single concurrent thread for io_service seems to be the fastest +static const size_t CONCURRENCY_HINT = 1; + /*********************************************************************** * Zero Copy UDP implementation with ASIO: * This is the portable zero copy implementation for systems @@ -61,6 +64,8 @@ public: size_t recv_frame_size, size_t num_recv_frames, size_t send_frame_size, size_t num_send_frames ): + _io_service(CONCURRENCY_HINT), + _work(new asio::io_service::work(_io_service)), _recv_frame_size(recv_frame_size), _num_recv_frames(num_recv_frames), _send_frame_size(send_frame_size), _num_send_frames(num_send_frames) { @@ -92,13 +97,15 @@ public: handle_send(_send_buffer.get() + i*_send_frame_size); } - //spawn the service thread that will run the io service - _thread_group.create_thread(boost::bind(&udp_zero_copy_asio_impl::service, this)); + //spawn the service threads that will run the io service + for (size_t i = 0; i < CONCURRENCY_HINT; i++) _thread_group.create_thread( + boost::bind(&udp_zero_copy_asio_impl::service, this) + ); } ~udp_zero_copy_asio_impl(void){ - _io_service.stop(); - _thread_group.join_all(); + delete _work; //allow io_service run to complete + _thread_group.join_all(); //wait for service threads to exit delete _socket; } @@ -200,6 +207,7 @@ private: //asio guts -> socket and service asio::ip::udp::socket *_socket; asio::io_service _io_service; + asio::io_service::work *_work; //memory management -> buffers and fifos boost::thread_group _thread_group; -- cgit v1.2.3 From 4fd922ba3acb8559a3d7d016b230d5e7a0a84da1 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 4 Oct 2010 09:48:25 -0700 Subject: usrp2: removed extra print-outs in init --- host/lib/usrp/usrp2/io_impl.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index c0d8ab029..33cec3cbc 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -168,10 +168,6 @@ void usrp2_impl::io_init(void){ _mboards.at(i), i )); } - - std::cout << "RX samples per packet: " << get_max_recv_samps_per_packet() << std::endl; - std::cout << "TX samples per packet: " << get_max_send_samps_per_packet() << std::endl; - std::cout << "Recv pirate num frames: " << num_frames << std::endl; } /*********************************************************************** -- cgit v1.2.3 From 9cea1342941e74b911ca26cc41c64e340f04c270 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 4 Oct 2010 10:06:17 -0700 Subject: uhd: modified tx timed samples to deal with timeout --- host/examples/tx_timed_samples.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index f34c121d5..2a15b2f66 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -95,8 +95,11 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ size_t num_tx_samps = dev->send( &buff.front(), samps_to_send, md, uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_FULL_BUFF + uhd::device::SEND_MODE_FULL_BUFF, + //send will backup into the host this many seconds before sending: + seconds_in_future + 0.1 //timeout (delay before transmit + padding) ); + if (num_tx_samps == 0) std::cout << "Send timeout..." << std::endl; if(verbose) std::cout << std::endl << boost::format("Sent %d samples") % num_tx_samps << std::endl; } -- cgit v1.2.3 From b34af3c910a54d8afd4b1f00f1254c3ab762c82a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 4 Oct 2010 11:17:01 -0700 Subject: usrp-e: implemented mmap with new zero_copy timeout work, added much debug verbosity --- host/lib/usrp/usrp_e/io_impl.cpp | 48 ++++---- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 6 +- host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp | 161 ++++++++++++------------- 3 files changed, 107 insertions(+), 108 deletions(-) diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 0b5fa054b..1e577a4df 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -37,7 +37,7 @@ zero_copy_if::sptr usrp_e_make_mmap_zero_copy(usrp_e_iface::sptr iface); **********************************************************************/ static const size_t tx_async_report_sid = 1; static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; -static const double recv_timeout_ms = 100; +static const bool recv_debug = true; /*********************************************************************** * io impl details (internal to this file) @@ -66,10 +66,10 @@ struct usrp_e_impl::io_impl{ recv_pirate_crew.join_all(); } - bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, size_t timeout_ms){ + bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, double timeout){ UHD_ASSERT_THROW(buffs.size() == 1); boost::this_thread::disable_interruption di; //disable because the wait can throw - return recv_pirate_booty->pop_with_timed_wait(buffs.front(), boost::posix_time::milliseconds(timeout_ms)); + return recv_pirate_booty->pop_with_timed_wait(buffs.front(), timeout); } //a pirate's life is the life for me! @@ -94,9 +94,17 @@ void usrp_e_impl::io_impl::recv_pirate_loop( //size_t next_packet_seq = 0; while(recv_pirate_crew_raiding){ - managed_recv_buffer::sptr buff = this->data_xport->get_recv_buff(recv_timeout_ms); + managed_recv_buffer::sptr buff = this->data_xport->get_recv_buff(); if (not buff.get()) continue; //ignore timeout/error buffers + if (recv_debug){ + std::cout << "len " << buff->size() << std::endl; + for (size_t i = 0; i < 9; i++){ + std::cout << boost::format(" 0x%08x") % buff->cast()[i] << std::endl; + } + std::cout << std::endl << std::endl; + } + try{ //extract the vrt header packet info vrt::if_packet_info_t if_packet_info; @@ -181,20 +189,18 @@ void usrp_e_impl::handle_overrun(size_t){ * Data Send **********************************************************************/ bool get_send_buffs( - zero_copy_if::sptr trans, + zero_copy_if::sptr trans, double timeout, vrt_packet_handler::managed_send_buffs_t &buffs ){ UHD_ASSERT_THROW(buffs.size() == 1); - buffs[0] = trans->get_send_buff(); + buffs[0] = trans->get_send_buff(timeout); return buffs[0].get() != NULL; } size_t usrp_e_impl::send( - const std::vector &buffs, - size_t num_samps, - const tx_metadata_t &metadata, - const io_type_t &io_type, - send_mode_t send_mode + const std::vector &buffs, size_t num_samps, + const tx_metadata_t &metadata, const io_type_t &io_type, + send_mode_t send_mode, double timeout ){ otw_type_t send_otw_type; send_otw_type.width = 16; @@ -208,7 +214,7 @@ size_t usrp_e_impl::send( io_type, send_otw_type, //input and output types to convert MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_pack_le, - boost::bind(&get_send_buffs, _io_impl->data_xport, _1), + boost::bind(&get_send_buffs, _io_impl->data_xport, timeout, _1), get_max_send_samps_per_packet() ); } @@ -217,12 +223,9 @@ size_t usrp_e_impl::send( * Data Recv **********************************************************************/ size_t usrp_e_impl::recv( - const std::vector &buffs, - size_t num_samps, - rx_metadata_t &metadata, - const io_type_t &io_type, - recv_mode_t recv_mode, - size_t timeout_ms + const std::vector &buffs, size_t num_samps, + rx_metadata_t &metadata, const io_type_t &io_type, + recv_mode_t recv_mode, double timeout ){ otw_type_t recv_otw_type; recv_otw_type.width = 16; @@ -236,7 +239,7 @@ size_t usrp_e_impl::recv( io_type, recv_otw_type, //input and output types to convert MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_unpack_le, - boost::bind(&usrp_e_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout_ms), + boost::bind(&usrp_e_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout), boost::bind(&usrp_e_impl::handle_overrun, this, _1) ); } @@ -245,11 +248,8 @@ size_t usrp_e_impl::recv( * Async Recv **********************************************************************/ bool usrp_e_impl::recv_async_msg( - async_metadata_t &async_metadata, - size_t timeout_ms + async_metadata_t &async_metadata, double timeout ){ boost::this_thread::disable_interruption di; //disable because the wait can throw - return _io_impl->async_msg_fifo->pop_with_timed_wait( - async_metadata, boost::posix_time::milliseconds(timeout_ms) - ); + return _io_impl->async_msg_fifo->pop_with_timed_wait(async_metadata, timeout); } diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 2457e27cc..49912050e 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -82,9 +82,9 @@ public: ~usrp_e_impl(void); //the io interface - size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t); - size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, size_t); - bool recv_async_msg(uhd::async_metadata_t &, size_t); + size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t, double); + size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, double); + bool recv_async_msg(uhd::async_metadata_t &, double); size_t get_max_send_samps_per_packet(void) const{return 503;} size_t get_max_recv_samps_per_packet(void) const{return 503;} diff --git a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp index 0910caa6f..e62205a3f 100644 --- a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp @@ -15,86 +15,27 @@ // along with this program. If not, see . // +#include "usrp_e_iface.hpp" #include #include #include #include //mmap #include //getpagesize #include //poll -#include -#include "usrp_e_iface.hpp" +#include +#include +#include using namespace uhd; using namespace uhd::transport; -static const bool debug_verbose = false; - -/*********************************************************************** - * The managed receive buffer implementation - **********************************************************************/ -class usrp_e_mmap_managed_recv_buffer : public managed_recv_buffer{ -public: - usrp_e_mmap_managed_recv_buffer( - const void *mem, size_t len, ring_buffer_info *info - ): - _buff(mem, len), _info(info) - { - /* NOP */ - } - - ~usrp_e_mmap_managed_recv_buffer(void){ - _info->flags = RB_KERNEL; - } - -private: - const boost::asio::const_buffer &get(void) const{ - return _buff; - } - - const boost::asio::const_buffer _buff; - ring_buffer_info *_info; -}; - -/*********************************************************************** - * The managed send buffer implementation - **********************************************************************/ -class usrp_e_mmap_managed_send_buffer : public managed_send_buffer{ -public: - usrp_e_mmap_managed_send_buffer( - void *mem, size_t len, ring_buffer_info *info, int fd - ): - _buff(mem, len), _info(info), _fd(fd), _commited(false) - { - /* NOP */ - } - - ~usrp_e_mmap_managed_send_buffer(void){ - if (not _commited) this->commit(0); - } - - ssize_t commit(size_t num_bytes){ - _commited = true; - _info->len = num_bytes; - _info->flags = RB_USER; - ssize_t ret = ::write(_fd, NULL, 0); - return (ret < 0)? ret : num_bytes; - } - -private: - const boost::asio::mutable_buffer &get(void) const{ - return _buff; - } - - const boost::asio::mutable_buffer _buff; - ring_buffer_info *_info; - int _fd; - bool _commited; -}; +static const bool fp_verbose = true; //fast-path verbose +static const bool sp_verbose = true; //slow-path verbose /*********************************************************************** * The zero copy interface implementation **********************************************************************/ -class usrp_e_mmap_zero_copy_impl : public zero_copy_if{ +class usrp_e_mmap_zero_copy_impl : public zero_copy_if, public boost::enable_shared_from_this { public: usrp_e_mmap_zero_copy_impl(usrp_e_iface::sptr iface): _fd(iface->get_file_descriptor()), _recv_index(0), _send_index(0) @@ -105,15 +46,26 @@ public: _frame_size = page_size/2; //calculate the memory size - size_t map_size = + _map_size = (_rb_size.num_pages_rx_flags + _rb_size.num_pages_tx_flags) * page_size + (_rb_size.num_rx_frames + _rb_size.num_tx_frames) * _frame_size; + //print sizes summary + if (sp_verbose){ + std::cout << "page_size: " << page_size << std::endl; + std::cout << "frame_size: " << _frame_size << std::endl; + std::cout << "num_pages_rx_flags: " << _rb_size.num_pages_rx_flags << std::endl; + std::cout << "num_rx_frames: " << _rb_size.num_rx_frames << std::endl; + std::cout << "num_pages_tx_flags: " << _rb_size.num_pages_tx_flags << std::endl; + std::cout << "num_tx_frames: " << _rb_size.num_tx_frames << std::endl; + std::cout << "map_size: " << _map_size << std::endl; + } + //call mmap to get the memory - void *ring_buffer = mmap( - NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, _fd, 0 + _mapped_mem = ::mmap( + NULL, _map_size, PROT_READ | PROT_WRITE, MAP_SHARED, _fd, 0 ); - UHD_ASSERT_THROW(ring_buffer != MAP_FAILED); + UHD_ASSERT_THROW(_mapped_mem != MAP_FAILED); //calculate the memory offsets for info and buffers size_t recv_info_off = 0; @@ -121,16 +73,31 @@ public: size_t send_info_off = recv_buff_off + (_rb_size.num_rx_frames * _frame_size); size_t send_buff_off = send_info_off + (_rb_size.num_pages_tx_flags * page_size); + //print offset summary + if (sp_verbose){ + std::cout << "recv_info_off: " << recv_info_off << std::endl; + std::cout << "recv_buff_off: " << recv_buff_off << std::endl; + std::cout << "send_info_off: " << send_info_off << std::endl; + std::cout << "send_buff_off: " << send_buff_off << std::endl; + } + //set the internal pointers for info and buffers typedef ring_buffer_info (*rbi_pta)[]; - boost::uint8_t *rb_ptr = reinterpret_cast(ring_buffer); + char *rb_ptr = reinterpret_cast(_mapped_mem); _recv_info = reinterpret_cast(rb_ptr + recv_info_off); _recv_buff = rb_ptr + recv_buff_off; _send_info = reinterpret_cast(rb_ptr + send_info_off); _send_buff = rb_ptr + send_buff_off; } - managed_recv_buffer::sptr get_recv_buff(size_t timeout_ms){ + ~usrp_e_mmap_zero_copy_impl(void){ + if (sp_verbose) std::cout << "cleanup: munmap" << std::endl; + ::munmap(_mapped_mem, _map_size); + } + + managed_recv_buffer::sptr get_recv_buff(double timeout){ + if (fp_verbose) std::cout << "get_recv_buff: " << _recv_index << std::endl; + //grab pointers to the info and buffer ring_buffer_info *info = (*_recv_info) + _recv_index; void *mem = _recv_buff + _frame_size*_recv_index; @@ -140,7 +107,8 @@ public: pollfd pfd; pfd.fd = _fd; pfd.events = POLLIN; - ssize_t poll_ret = poll(&pfd, 1, timeout_ms); + ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3)); + if (fp_verbose) std::cout << " POLLIN: " << poll_ret << std::endl; if (poll_ret <= 0) return managed_recv_buffer::sptr(); } @@ -148,8 +116,10 @@ public: if (++_recv_index == size_t(_rb_size.num_rx_frames)) _recv_index = 0; //return the managed buffer for this frame - return managed_recv_buffer::sptr( - new usrp_e_mmap_managed_recv_buffer(mem, info->len, info) + if (fp_verbose) std::cout << " make_recv_buff: " << info->len << std::endl; + return managed_recv_buffer::make_safe( + boost::asio::const_buffer(mem, info->len), + boost::bind(&usrp_e_mmap_zero_copy_impl::release, shared_from_this(), info) ); } @@ -157,7 +127,9 @@ public: return _rb_size.num_rx_frames; } - managed_send_buffer::sptr get_send_buff(void){ + managed_send_buffer::sptr get_send_buff(double timeout){ + if (fp_verbose) std::cout << "get_send_buff: " << _send_index << std::endl; + //grab pointers to the info and buffer ring_buffer_info *info = (*_send_info) + _send_index; void *mem = _send_buff + _frame_size*_send_index; @@ -167,7 +139,8 @@ public: pollfd pfd; pfd.fd = _fd; pfd.events = POLLOUT; - ssize_t poll_ret = poll(&pfd, 1, -1 /*forever*/); + ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3)); + if (fp_verbose) std::cout << " POLLOUT: " << poll_ret << std::endl; if (poll_ret <= 0) return managed_send_buffer::sptr(); } @@ -175,8 +148,10 @@ public: if (++_send_index == size_t(_rb_size.num_tx_frames)) _send_index = 0; //return the managed buffer for this frame - return managed_send_buffer::sptr( - new usrp_e_mmap_managed_send_buffer(mem, _frame_size, info, _fd) + if (fp_verbose) std::cout << " make_send_buff: " << _frame_size << std::endl; + return managed_send_buffer::make_safe( + boost::asio::mutable_buffer(mem, _frame_size), + boost::bind(&usrp_e_mmap_zero_copy_impl::commit, shared_from_this(), info, _1) ); } @@ -185,11 +160,35 @@ public: } private: + + void release(ring_buffer_info *info){ + if (fp_verbose) std::cout << "recv buff: release" << std::endl; + info->flags = RB_KERNEL; + } + + void commit(ring_buffer_info *info, size_t len){ + if (fp_verbose) std::cout << "send buff: commit " << len << std::endl; + info->len = len; + info->flags = RB_USER; + if (::write(_fd, NULL, 0) < 0){ + std::cerr << UHD_THROW_SITE_INFO("write error") << std::endl; + } + } + int _fd; + + //the mapped memory itself + void *_mapped_mem; + + //mapped memory sizes usrp_e_ring_buffer_size_t _rb_size; - size_t _frame_size; + size_t _frame_size, _map_size; + + //pointers to sections in the mapped memory ring_buffer_info (*_recv_info)[], (*_send_info)[]; - boost::uint8_t *_recv_buff, *_send_buff; + char *_recv_buff, *_send_buff; + + //indexes into sub-sections of mapped memory size_t _recv_index, _send_index; }; -- cgit v1.2.3 From 219183453b23a572ddd6eeec81c3bc1907754560 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 4 Oct 2010 11:30:14 -0700 Subject: uhd: added include for enable_shared_from_this when used --- host/lib/transport/libusb1_zero_copy.cpp | 2 +- host/lib/transport/udp_zero_copy_asio.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index ab48e4fc4..c7f084f62 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -280,7 +281,6 @@ libusb_transfer *usb_endpoint::get_lut_with_wait(double timeout){ **********************************************************************/ class libusb_zero_copy_impl : public usb_zero_copy, public boost::enable_shared_from_this { public: - typedef boost::shared_ptr sptr; libusb_zero_copy_impl( libusb::device_handle::sptr handle, diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 2cf7bde18..e9d91fe45 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include using namespace uhd; -- cgit v1.2.3 From 5bd863efa05f3c6cfd672cffe87f57b33d1c32b5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 4 Oct 2010 14:54:16 -0700 Subject: uhd: bounded buffer pop sets back element to empty to decrement references --- host/include/uhd/transport/bounded_buffer.ipp | 16 ++++++++++++++-- host/lib/transport/libusb1_zero_copy.cpp | 4 ---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/host/include/uhd/transport/bounded_buffer.ipp b/host/include/uhd/transport/bounded_buffer.ipp index 71143741e..58f78bab4 100644 --- a/host/include/uhd/transport/bounded_buffer.ipp +++ b/host/include/uhd/transport/bounded_buffer.ipp @@ -73,7 +73,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ UHD_INLINE void pop_with_wait(elem_type &elem){ boost::unique_lock lock(_mutex); _empty_cond.wait(lock, boost::bind(&bounded_buffer_impl::not_empty, this)); - elem = _buffer.back(); _buffer.pop_back(); + this->pop_back(elem); lock.unlock(); _full_cond.notify_one(); } @@ -84,7 +84,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ lock, boost::posix_time::microseconds(long(timeout*1e6)), boost::bind(&bounded_buffer_impl::not_empty, this) )) return false; - elem = _buffer.back(); _buffer.pop_back(); + this->pop_back(elem); lock.unlock(); _full_cond.notify_one(); return true; @@ -104,6 +104,18 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ bool not_full(void) const{return not _buffer.full();} bool not_empty(void) const{return not _buffer.empty();} + + /*! + * Three part operation to pop an element: + * 1) assign elem to the back element + * 2) assign the back element to empty + * 3) pop the back to move the counter + */ + UHD_INLINE void pop_back(elem_type &elem){ + elem = _buffer.back(); + _buffer.back() = elem_type(); + _buffer.pop_back(); + } }; }}} //namespace diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index c7f084f62..819874483 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -335,10 +335,6 @@ libusb_zero_copy_impl::libusb_zero_copy_impl( if (send_xfer_size == 0) send_xfer_size = DEFAULT_XFER_SIZE; if (send_num_xfers == 0) send_num_xfers = DEFAULT_NUM_XFERS; - //sanity check the transfer sizes - UHD_ASSERT_THROW(recv_xfer_size % 512 == 0); - UHD_ASSERT_THROW(send_xfer_size % 512 == 0); - //store the num xfers for the num frames count _recv_xfer_size = recv_xfer_size; _recv_num_frames = recv_num_xfers; -- cgit v1.2.3 From f642942dc364c1d26a9128c1ba631d3604d0671a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 4 Oct 2010 15:17:57 -0700 Subject: usrp-e: check if flags are ready after poll --- host/lib/usrp/usrp_e/io_impl.cpp | 6 +++--- host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp | 12 ++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 1e577a4df..2802a6b87 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -130,12 +130,12 @@ void usrp_e_impl::io_impl::recv_pirate_loop( continue; } + //same number of frames as the data transport -> always immediate + recv_pirate_booty->push_with_wait(buff); + }catch(const std::exception &e){ std::cerr << "Error (usrp-e recv pirate loop): " << e.what() << std::endl; } - - //usrp-e back-pressures on receive: push with wait - recv_pirate_booty->push_with_wait(buff); } } diff --git a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp index e62205a3f..9e25ed088 100644 --- a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp @@ -112,6 +112,12 @@ public: if (poll_ret <= 0) return managed_recv_buffer::sptr(); } + //check that the frame is really ready + if (not (info->flags & RB_USER)){ + if (fp_verbose) std::cout << " flags: not ready" << std::endl; + return managed_recv_buffer::sptr(); + } + //increment the index for the next call if (++_recv_index == size_t(_rb_size.num_rx_frames)) _recv_index = 0; @@ -144,6 +150,12 @@ public: if (poll_ret <= 0) return managed_send_buffer::sptr(); } + //check that the frame is really ready + if (not (info->flags & RB_KERNEL)){ + if (fp_verbose) std::cout << " flags: not ready" << std::endl; + return managed_send_buffer::sptr(); + } + //increment the index for the next call if (++_send_index == size_t(_rb_size.num_tx_frames)) _send_index = 0; -- cgit v1.2.3 From c2dc0fe98ddc6441cb989a49384b0c305a955368 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 4 Oct 2010 15:41:34 -0700 Subject: timeout: proper way to check for timeout in full buff mode --- host/examples/tx_timed_samples.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index 2a15b2f66..863446682 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -99,7 +99,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //send will backup into the host this many seconds before sending: seconds_in_future + 0.1 //timeout (delay before transmit + padding) ); - if (num_tx_samps == 0) std::cout << "Send timeout..." << std::endl; + if (num_tx_samps < samps_to_send) std::cout << "Send timeout..." << std::endl; if(verbose) std::cout << std::endl << boost::format("Sent %d samples") % num_tx_samps << std::endl; } -- cgit v1.2.3 From 50ff7e4d3bf4e196b4c054821f67f8d1bff5203b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 4 Oct 2010 16:34:24 -0700 Subject: usb: added dummy usb implementation for building without usb (throw, not segfault) --- host/lib/transport/CMakeLists.txt | 4 +++- host/lib/transport/usb_dummy_impl.cpp | 39 +++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 host/lib/transport/usb_dummy_impl.cpp diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index bf92b0822..b9ec7a6ad 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -37,7 +37,9 @@ IF(LIBUSB_FOUND) ENDIF(MSVC) SET(HAVE_USB_SUPPORT TRUE) ELSE(LIBUSB_FOUND) - #TODO dummy usb + LIBUHD_APPEND_SOURCES( + ${CMAKE_SOURCE_DIR}/lib/transport/usb_dummy_impl.cpp + ) ENDIF(LIBUSB_FOUND) IF(HAVE_USB_SUPPORT) diff --git a/host/lib/transport/usb_dummy_impl.cpp b/host/lib/transport/usb_dummy_impl.cpp new file mode 100644 index 000000000..518342aba --- /dev/null +++ b/host/lib/transport/usb_dummy_impl.cpp @@ -0,0 +1,39 @@ +// +// 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 + +using namespace uhd::transport; + +std::vector usb_device_handle::get_device_list(boost::uint16_t, boost::uint16_t){ + return std::vector(); //empty list +} + +usb_control::sptr usb_control::make(usb_device_handle::sptr){ + throw std::runtime_error("no usb support -> usb_control::make not implemented"); +} + +usb_zero_copy::sptr usb_zero_copy::make( + usb_device_handle::sptr, + unsigned int, unsigned int, + size_t, size_t, size_t, size_t +){ + throw std::runtime_error("no usb support -> usb_zero_copy::make not implemented"); +} -- cgit v1.2.3 From 0cd5375b5c8a928f112a963d9c9c2556bafed108 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 5 Oct 2010 10:30:28 -0700 Subject: uhd: replaced frame params for the zero copy interfaces with a device address the device address gives a key, value pair of infinite optional capabilities added a cast option to the device address to cast string to type T added call to the zero_copy_if to get send and recv frame sizes changed the usrp2 impl to calculate recv/send spp from the data transport --- host/include/uhd/transport/udp_zero_copy.hpp | 7 ++- host/include/uhd/transport/usb_control.hpp | 2 +- host/include/uhd/transport/usb_zero_copy.hpp | 17 +++---- host/include/uhd/transport/zero_copy.hpp | 26 +++++++--- host/include/uhd/types/device_addr.hpp | 20 ++++++++ host/lib/transport/libusb1_zero_copy.cpp | 67 +++++++++++-------------- host/lib/transport/udp_zero_copy_asio.cpp | 35 +++++++------ host/lib/transport/usb_dummy_impl.cpp | 4 +- host/lib/usrp/usrp1/usrp1_impl.cpp | 48 +++++++----------- host/lib/usrp/usrp2/io_impl.cpp | 4 +- host/lib/usrp/usrp2/mboard_impl.cpp | 8 +-- host/lib/usrp/usrp2/usrp2_impl.cpp | 40 ++++++--------- host/lib/usrp/usrp2/usrp2_impl.hpp | 75 ++++++++-------------------- 13 files changed, 162 insertions(+), 191 deletions(-) diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp index 818709973..bbba97b21 100644 --- a/host/include/uhd/transport/udp_zero_copy.hpp +++ b/host/include/uhd/transport/udp_zero_copy.hpp @@ -20,6 +20,7 @@ #include #include +#include #include namespace uhd{ namespace transport{ @@ -50,14 +51,12 @@ public: * * \param addr a string representing the destination address * \param port a string representing the destination port - * \param recv_buff_size size in bytes for the recv buffer, 0 for automatic - * \param send_buff_size size in bytes for the send buffer, 0 for automatic + * \param hints optional parameters to pass to the underlying transport */ static sptr make( const std::string &addr, const std::string &port, - size_t recv_buff_size = 0, - size_t send_buff_size = 0 + const device_addr_t &hints = device_addr_t() ); }; diff --git a/host/include/uhd/transport/usb_control.hpp b/host/include/uhd/transport/usb_control.hpp index f9829c3ec..e6c32f78e 100644 --- a/host/include/uhd/transport/usb_control.hpp +++ b/host/include/uhd/transport/usb_control.hpp @@ -18,7 +18,7 @@ #ifndef INCLUDED_UHD_TRANSPORT_USB_CONTROL_HPP #define INCLUDED_UHD_TRANSPORT_USB_CONTROL_HPP -#include "usb_device_handle.hpp" +#include namespace uhd { namespace transport { diff --git a/host/include/uhd/transport/usb_zero_copy.hpp b/host/include/uhd/transport/usb_zero_copy.hpp index 61bf380ba..b39171fba 100644 --- a/host/include/uhd/transport/usb_zero_copy.hpp +++ b/host/include/uhd/transport/usb_zero_copy.hpp @@ -18,8 +18,9 @@ #ifndef INCLUDED_UHD_TRANSPORT_USB_ZERO_COPY_HPP #define INCLUDED_UHD_TRANSPORT_USB_ZERO_COPY_HPP -#include "usb_device_handle.hpp" +#include #include +#include namespace uhd { namespace transport { @@ -47,19 +48,13 @@ public: * \param handle a device handle that uniquely identifying the device * \param recv_endpoint an integer specifiying an IN endpoint number * \param send_endpoint an integer specifiying an OUT endpoint number - * \param recv_xfer_size the number of bytes for each receive transfer - * \param recv_num_xfers the number of simultaneous receive transfers - * \param send_xfer_size the number of bytes for each send transfer - * \param send_num_xfers the number of simultaneous send transfers + * \param hints optional parameters to pass to the underlying transport */ static sptr make( usb_device_handle::sptr handle, - unsigned int recv_endpoint, - unsigned int send_endpoint, - size_t recv_xfer_size = 0, - size_t recv_num_xfers = 0, - size_t send_xfer_size = 0, - size_t send_num_xfers = 0 + size_t recv_endpoint, + size_t send_endpoint, + const device_addr_t &hints = device_addr_t() ); }; diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp index 9dd16280c..7d8fb4b83 100644 --- a/host/include/uhd/transport/zero_copy.hpp +++ b/host/include/uhd/transport/zero_copy.hpp @@ -155,14 +155,19 @@ namespace uhd{ namespace transport{ virtual managed_recv_buffer::sptr get_recv_buff(double timeout = 0.1) = 0; /*! - * Get the maximum number of receive frames: - * The maximum number of valid managed recv buffers, - * or the maximum number of frames in the ring buffer, - * depending upon the underlying implementation. + * Get the number of receive frames: + * The number of simultaneous receive buffers in use. * \return number of frames */ virtual size_t get_num_recv_frames(void) const = 0; + /*! + * Get the size of a receive frame: + * The maximum capacity of a single receive buffer. + * \return frame size in bytes + */ + virtual size_t get_recv_frame_size(void) const = 0; + /*! * Get a new send buffer from this transport object. * \param timeout the timeout to get the buffer in seconds @@ -171,14 +176,19 @@ namespace uhd{ namespace transport{ virtual managed_send_buffer::sptr get_send_buff(double timeout = 0.1) = 0; /*! - * Get the maximum number of send frames: - * The maximum number of valid managed send buffers, - * or the maximum number of frames in the ring buffer, - * depending upon the underlying implementation. + * Get the number of send frames: + * The number of simultaneous send buffers in use. * \return number of frames */ virtual size_t get_num_send_frames(void) const = 0; + /*! + * Get the size of a send frame: + * The maximum capacity of a single send buffer. + * \return frame size in bytes + */ + virtual size_t get_send_frame_size(void) const = 0; + }; }} //namespace diff --git a/host/include/uhd/types/device_addr.hpp b/host/include/uhd/types/device_addr.hpp index e359d9467..eb3394230 100644 --- a/host/include/uhd/types/device_addr.hpp +++ b/host/include/uhd/types/device_addr.hpp @@ -20,6 +20,8 @@ #include #include +#include +#include #include #include @@ -62,6 +64,24 @@ namespace uhd{ * \return a string with delimiter markup */ std::string to_string(void) const; + + /*! + * Lexically cast a parameter to the specified type, + * or use the default value if the key is not found. + * \param key the key as one of the address parameters + * \param def the value to use when key is not present + * \return the casted value as type T or the default + * \throw error when the parameter cannot be casted + */ + template T cast(const std::string &key, const T &def) const{ + if (not this->has_key(key)) return def; + try{ + return boost::lexical_cast((*this)[key]); + } + catch(const boost::bad_lexical_cast &){ + throw std::runtime_error("cannot cast " + key + " = " + (*this)[key]); + } + } }; //handy typedef for a vector of device addresses diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index 819874483..df6db1eb9 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -26,6 +26,7 @@ #include #include +using namespace uhd; using namespace uhd::transport; static const double CLEANUP_TIMEOUT = 0.2; //seconds @@ -284,16 +285,19 @@ public: libusb_zero_copy_impl( libusb::device_handle::sptr handle, - unsigned int recv_endpoint, unsigned int send_endpoint, - size_t recv_xfer_size, size_t recv_num_xfers, - size_t send_xfer_size, size_t send_num_xfers + size_t recv_endpoint, + size_t send_endpoint, + const device_addr_t &hints ); managed_recv_buffer::sptr get_recv_buff(double); managed_send_buffer::sptr get_send_buff(double); - size_t get_num_recv_frames(void) const { return _recv_num_frames; } - size_t get_num_send_frames(void) const { return _send_num_frames; } + size_t get_num_recv_frames(void) const { return _num_recv_frames; } + size_t get_num_send_frames(void) const { return _num_send_frames; } + + size_t get_recv_frame_size(void) const { return _recv_frame_size; } + size_t get_send_frame_size(void) const { return _send_frame_size; } private: void release(libusb_transfer *lut){ @@ -311,8 +315,8 @@ private: } libusb::device_handle::sptr _handle; - size_t _recv_xfer_size, _send_xfer_size; - size_t _recv_num_frames, _send_num_frames; + const size_t _recv_frame_size, _num_recv_frames; + const size_t _send_frame_size, _num_send_frames; usb_endpoint::sptr _recv_ep, _send_ep; }; @@ -323,24 +327,16 @@ private: */ libusb_zero_copy_impl::libusb_zero_copy_impl( libusb::device_handle::sptr handle, - unsigned int recv_endpoint, unsigned int send_endpoint, - size_t recv_xfer_size, size_t recv_num_xfers, - size_t send_xfer_size, size_t send_num_xfers -){ - _handle = handle; - - //if the sizes are left at 0 (automatic) -> use the defaults - if (recv_xfer_size == 0) recv_xfer_size = DEFAULT_XFER_SIZE; - if (recv_num_xfers == 0) recv_num_xfers = DEFAULT_NUM_XFERS; - if (send_xfer_size == 0) send_xfer_size = DEFAULT_XFER_SIZE; - if (send_num_xfers == 0) send_num_xfers = DEFAULT_NUM_XFERS; - - //store the num xfers for the num frames count - _recv_xfer_size = recv_xfer_size; - _recv_num_frames = recv_num_xfers; - _send_xfer_size = send_xfer_size; - _send_num_frames = send_num_xfers; - + size_t recv_endpoint, + size_t send_endpoint, + const device_addr_t &hints +): + _handle(handle), + _recv_frame_size(size_t(hints.cast("recv_frame_size", DEFAULT_XFER_SIZE))), + _num_recv_frames(size_t(hints.cast("num_recv_frames", DEFAULT_NUM_XFERS))), + _send_frame_size(size_t(hints.cast("send_frame_size", DEFAULT_XFER_SIZE))), + _num_send_frames(size_t(hints.cast("num_send_frames", DEFAULT_NUM_XFERS))) +{ _handle->claim_interface(2 /*in interface*/); _handle->claim_interface(1 /*out interface*/); @@ -348,16 +344,16 @@ libusb_zero_copy_impl::libusb_zero_copy_impl( _handle, // libusb device_handle recv_endpoint, // USB endpoint number true, // IN endpoint - recv_xfer_size, // buffer size per transfer - recv_num_xfers // number of libusb transfers + this->get_recv_frame_size(), // buffer size per transfer + this->get_num_recv_frames() // number of libusb transfers )); _send_ep = usb_endpoint::sptr(new usb_endpoint( _handle, // libusb device_handle send_endpoint, // USB endpoint number false, // OUT endpoint - send_xfer_size, // buffer size per transfer - send_num_xfers // number of libusb transfers + this->get_send_frame_size(), // buffer size per transfer + this->get_num_send_frames() // number of libusb transfers )); } @@ -394,7 +390,7 @@ managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(double timeout){ } else { return managed_send_buffer::make_safe( - boost::asio::mutable_buffer(lut->buffer, _send_xfer_size), + boost::asio::mutable_buffer(lut->buffer, this->get_send_frame_size()), boost::bind(&libusb_zero_copy_impl::commit, shared_from_this(), lut, _1) ); } @@ -405,17 +401,14 @@ managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(double timeout){ **********************************************************************/ usb_zero_copy::sptr usb_zero_copy::make( usb_device_handle::sptr handle, - unsigned int recv_endpoint, unsigned int send_endpoint, - size_t recv_xfer_size, size_t recv_num_xfers, - size_t send_xfer_size, size_t send_num_xfers + size_t recv_endpoint, + size_t send_endpoint, + const device_addr_t &hints ){ libusb::device_handle::sptr dev_handle(libusb::device_handle::get_cached_handle( boost::static_pointer_cast(handle)->get_device() )); return sptr(new libusb_zero_copy_impl( - dev_handle, - recv_endpoint, send_endpoint, - recv_xfer_size, recv_num_xfers, - send_xfer_size, send_num_xfers + dev_handle, recv_endpoint, send_endpoint, hints )); } diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index e9d91fe45..ada282e07 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -44,7 +44,7 @@ static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(4 * 25e6 * 0.5); static const size_t MIN_SEND_SOCK_BUFF_SIZE = size_t(10e3); //the number of async frames to allocate for each send and recv -static const size_t DEFAULT_NUM_ASYNC_FRAMES = 32; +static const size_t DEFAULT_NUM_FRAMES = 32; //a single concurrent thread for io_service seems to be the fastest static const size_t CONCURRENCY_HINT = 1; @@ -61,14 +61,15 @@ public: typedef boost::shared_ptr sptr; udp_zero_copy_asio_impl( - const std::string &addr, const std::string &port, - size_t recv_frame_size, size_t num_recv_frames, - size_t send_frame_size, size_t num_send_frames + const std::string &addr, + const std::string &port, + const device_addr_t &hints ): - _io_service(CONCURRENCY_HINT), - _work(new asio::io_service::work(_io_service)), - _recv_frame_size(recv_frame_size), _num_recv_frames(num_recv_frames), - _send_frame_size(send_frame_size), _num_send_frames(num_send_frames) + _io_service(hints.cast("concurrency_hint", CONCURRENCY_HINT)), + _recv_frame_size(size_t(hints.cast("recv_frame_size", udp_simple::mtu))), + _num_recv_frames(size_t(hints.cast("num_recv_frames", DEFAULT_NUM_FRAMES))), + _send_frame_size(size_t(hints.cast("send_frame_size", udp_simple::mtu))), + _num_send_frames(size_t(hints.cast("num_send_frames", DEFAULT_NUM_FRAMES))) { //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; @@ -99,6 +100,7 @@ public: } //spawn the service threads that will run the io service + _work = new asio::io_service::work(_io_service); //new work to delete later for (size_t i = 0; i < CONCURRENCY_HINT; i++) _thread_group.create_thread( boost::bind(&udp_zero_copy_asio_impl::service, this) ); @@ -141,6 +143,7 @@ public: } size_t get_num_recv_frames(void) const {return _num_recv_frames;} + size_t get_recv_frame_size(void) const {return _recv_frame_size;} //! pop an empty send buffer off of the fifo and bind with the commit callback managed_send_buffer::sptr get_send_buff(double timeout){ @@ -159,6 +162,7 @@ public: } size_t get_num_send_frames(void) const {return _num_send_frames;} + size_t get_send_frame_size(void) const {return _send_frame_size;} private: void service(void){ @@ -260,14 +264,15 @@ template static void resize_buff_helper( 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 + const device_addr_t &hints ){ - udp_zero_copy_asio_impl::sptr udp_trans(new udp_zero_copy_asio_impl( - addr, port, - udp_simple::mtu, DEFAULT_NUM_ASYNC_FRAMES, //recv - udp_simple::mtu, DEFAULT_NUM_ASYNC_FRAMES //send - )); + udp_zero_copy_asio_impl::sptr udp_trans( + new udp_zero_copy_asio_impl(addr, port, hints) + ); + + //extract buffer size hints from the device addr + size_t recv_buff_size = size_t(hints.cast("recv_buff_size", 0.0)); + size_t send_buff_size = size_t(hints.cast("send_buff_size", 0.0)); //call the helper to resize send and recv buffers resize_buff_helper(udp_trans, recv_buff_size, "recv"); diff --git a/host/lib/transport/usb_dummy_impl.cpp b/host/lib/transport/usb_dummy_impl.cpp index 518342aba..8a9772e7f 100644 --- a/host/lib/transport/usb_dummy_impl.cpp +++ b/host/lib/transport/usb_dummy_impl.cpp @@ -20,6 +20,7 @@ #include #include +using namespace uhd; using namespace uhd::transport; std::vector usb_device_handle::get_device_list(boost::uint16_t, boost::uint16_t){ @@ -32,8 +33,7 @@ usb_control::sptr usb_control::make(usb_device_handle::sptr){ usb_zero_copy::sptr usb_zero_copy::make( usb_device_handle::sptr, - unsigned int, unsigned int, - size_t, size_t, size_t, size_t + size_t, size_t, const device_addr_t & ){ throw std::runtime_error("no usb support -> usb_zero_copy::make not implemented"); } diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 6ebd6bb09..276ca86f6 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -106,17 +106,8 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) /*********************************************************************** * Make **********************************************************************/ -template static output_type cast_from_dev_addr( - const device_addr_t &device_addr, - const std::string &key, - output_type def_val -){ - return (device_addr.has_key(key))? - boost::lexical_cast(device_addr[key]) : def_val; -} +static device::sptr usrp1_make(const device_addr_t &device_addr){ -static device::sptr usrp1_make(const device_addr_t &device_addr) -{ //extract the FPGA path for the USRP1 std::string usrp1_fpga_image = find_image_path( device_addr.has_key("fpga")? device_addr["fpga"] : "usrp1_fpga.rbf" @@ -127,29 +118,26 @@ static device::sptr usrp1_make(const device_addr_t &device_addr) std::vector device_list = usb_device_handle::get_device_list(USRP1_VENDOR_ID, USRP1_PRODUCT_ID); - //create data and control transports - usb_zero_copy::sptr data_transport; - usrp_ctrl::sptr usrp_ctrl; - - - BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { - if (handle->get_serial() == device_addr["serial"]) { - usb_control::sptr ctrl_transport = usb_control::make(handle); - usrp_ctrl = usrp_ctrl::make(ctrl_transport); - usrp_ctrl->usrp_load_fpga(usrp1_fpga_image); - - data_transport = usb_zero_copy::make( - handle, // identifier - 6, // IN endpoint - 2, // OUT endpoint - size_t(cast_from_dev_addr(device_addr, "recv_xfer_size", 0)), - size_t(cast_from_dev_addr(device_addr, "recv_num_xfers", 0)), - size_t(cast_from_dev_addr(device_addr, "send_xfer_size", 0)), - size_t(cast_from_dev_addr(device_addr, "send_num_xfers", 0)) - ); + //locate the matching handle in the device list + usb_device_handle::sptr handle; + BOOST_FOREACH(usb_device_handle::sptr dev_handle, device_list) { + if (dev_handle->get_serial() == device_addr["serial"]){ + handle = dev_handle; break; } } + UHD_ASSERT_THROW(handle.get() != NULL); //better be found + + //create control objects and a data transport + usb_control::sptr ctrl_transport = usb_control::make(handle); + usrp_ctrl::sptr usrp_ctrl = usrp_ctrl::make(ctrl_transport); + usrp_ctrl->usrp_load_fpga(usrp1_fpga_image); + usb_zero_copy::sptr data_transport = usb_zero_copy::make( + handle, // identifier + 6, // IN endpoint + 2, // OUT endpoint + device_addr // param hints + ); //create the usrp1 implementation guts return device::sptr(new usrp1_impl(data_transport, usrp_ctrl)); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 33cec3cbc..07eda08c3 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -206,7 +206,7 @@ size_t usrp2_impl::send( _io_impl->packet_handler_send_state, //last state of the send handler buffs, num_samps, //buffer to fill metadata, send_mode, //samples metadata - io_type, _io_helper.get_tx_otw_type(), //input and output types to convert + io_type, _tx_otw_type, //input and output types to convert _mboards.front()->get_master_clock_freq(), //master clock tick rate uhd::transport::vrt::if_hdr_pack_be, boost::bind(&get_send_buffs, _data_transports, _1, timeout), @@ -226,7 +226,7 @@ size_t usrp2_impl::recv( _io_impl->packet_handler_recv_state, //last state of the recv handler buffs, num_samps, //buffer to fill metadata, recv_mode, //samples metadata - io_type, _io_helper.get_rx_otw_type(), //input and output types to convert + io_type, _rx_otw_type, //input and output types to convert _mboards.front()->get_master_clock_freq(), //master clock tick rate uhd::transport::vrt::if_hdr_unpack_be, boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout) diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 0b9f8ee83..a0e6adfad 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -38,10 +38,10 @@ using namespace uhd::usrp; usrp2_mboard_impl::usrp2_mboard_impl( size_t index, transport::udp_simple::sptr ctrl_transport, - const usrp2_io_helper &io_helper + size_t recv_frame_size ): _index(index), - _io_helper(io_helper) + _recv_frame_size(recv_frame_size) { //make a new interface for usrp2 stuff _iface = usrp2_iface::make(ctrl_transport); @@ -75,7 +75,7 @@ usrp2_mboard_impl::usrp2_mboard_impl( this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); //init the rx control registers - _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _io_helper.get_max_recv_samps_per_packet()); + _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _recv_frame_size); _iface->poke32(U2_REG_RX_CTRL_NCHANNELS, 1); _iface->poke32(U2_REG_RX_CTRL_CLEAR_OVERRUN, 1); //reset _iface->poke32(U2_REG_RX_CTRL_VRT_HEADER, 0 @@ -178,7 +178,7 @@ void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){ void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ _iface->poke32(U2_REG_RX_CTRL_STREAM_CMD, dsp_type1::calc_stream_cmd_word( - stream_cmd, _io_helper.get_max_recv_samps_per_packet() + stream_cmd, _recv_frame_size )); _iface->poke32(U2_REG_RX_CTRL_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); _iface->poke32(U2_REG_RX_CTRL_TIME_TICKS, stream_cmd.time_spec.get_tick_count(get_master_clock_freq())); diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 568c87a22..a680708ad 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -124,26 +124,7 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){ /*********************************************************************** * Make **********************************************************************/ -template -out_type lexical_cast(const in_type &in){ - try{ - return boost::lexical_cast(in); - }catch(...){ - throw std::runtime_error(str(boost::format( - "failed to cast \"%s\" to type \"%s\"" - ) % boost::lexical_cast(in) % typeid(out_type).name())); - } -} - static device::sptr usrp2_make(const device_addr_t &device_addr){ - //extract the receive and send buffer sizes - size_t recv_buff_size = 0, send_buff_size= 0 ; - if (device_addr.has_key("recv_buff_size")){ - recv_buff_size = size_t(lexical_cast(device_addr["recv_buff_size"])); - } - if (device_addr.has_key("send_buff_size")){ - send_buff_size = size_t(lexical_cast(device_addr["send_buff_size"])); - } //create a ctrl and data transport for each address std::vector ctrl_transports; @@ -154,8 +135,7 @@ static device::sptr usrp2_make(const device_addr_t &device_addr){ addr, num2str(USRP2_UDP_CTRL_PORT) )); data_transports.push_back(udp_zero_copy::make( - addr, num2str(USRP2_UDP_DATA_PORT), - recv_buff_size, send_buff_size + addr, num2str(USRP2_UDP_DATA_PORT), device_addr )); } @@ -178,11 +158,23 @@ usrp2_impl::usrp2_impl( ): _data_transports(data_transports) { + //setup rx otw type + _rx_otw_type.width = 16; + _rx_otw_type.shift = 0; + _rx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; + + //setup tx otw type + _tx_otw_type.width = 16; + _tx_otw_type.shift = 0; + _tx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; + + //!!!!! set the otw type here before continuing, its used below + //create a new mboard handler for each control transport for(size_t i = 0; i < ctrl_transports.size(); i++){ - _mboards.push_back(usrp2_mboard_impl::sptr( - new usrp2_mboard_impl(i, ctrl_transports[i], _io_helper) - )); + _mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl( + i, ctrl_transports[i], this->get_max_recv_samps_per_packet() + ))); //use an empty name when there is only one mboard std::string name = (ctrl_transports.size() > 1)? boost::lexical_cast(i) : ""; _mboard_dict[name] = _mboards.back(); diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index e8763b284..e12c4d6d4 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -71,54 +71,6 @@ private: void set(const wax::obj &key, const wax::obj &val){return _set(key, val);} }; -/*! - * The io helper class encapculates the max packet sizes and otw types. - * The otw types are read-only for now, this will be reimplemented - * when it becomes possible to change the otw type in the usrp2. - */ -class usrp2_io_helper{ -public: - usrp2_io_helper(void){ - //setup rx otw type - _rx_otw_type.width = 16; - _rx_otw_type.shift = 0; - _rx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; - - //setup tx otw type - _tx_otw_type.width = 16; - _tx_otw_type.shift = 0; - _tx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; - } - - inline size_t get_max_send_samps_per_packet(void) const{ - return _max_tx_bytes_per_packet/_tx_otw_type.get_sample_size(); - } - - inline size_t get_max_recv_samps_per_packet(void) const{ - return _max_rx_bytes_per_packet/_rx_otw_type.get_sample_size(); - } - - inline const uhd::otw_type_t &get_rx_otw_type(void) const{ - return _rx_otw_type; - } - - inline const uhd::otw_type_t &get_tx_otw_type(void) const{ - return _tx_otw_type; - } - -private: - uhd::otw_type_t _rx_otw_type, _tx_otw_type; - static const size_t _max_rx_bytes_per_packet = uhd::transport::udp_simple::mtu - - uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - - sizeof(uhd::transport::vrt::if_packet_info_t().tlr) //forced to have trailer - + sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used - ; - static const size_t _max_tx_bytes_per_packet = uhd::transport::udp_simple::mtu - - uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - + sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used - ; -}; - /*! * USRP2 mboard implementation guts: * The implementation details are encapsulated here. @@ -129,7 +81,11 @@ public: typedef boost::shared_ptr sptr; //structors - usrp2_mboard_impl(size_t index, uhd::transport::udp_simple::sptr, const usrp2_io_helper &); + usrp2_mboard_impl( + size_t index, + uhd::transport::udp_simple::sptr, + size_t recv_frame_size + ); ~usrp2_mboard_impl(void); inline double get_master_clock_freq(void){ @@ -139,7 +95,7 @@ public: private: size_t _index; int _rev_hi, _rev_lo; - const usrp2_io_helper &_io_helper; + const size_t _recv_frame_size; //properties for this mboard void get(const wax::obj &, wax::obj &); @@ -229,7 +185,8 @@ public: //the io interface size_t get_max_send_samps_per_packet(void) const{ - return _io_helper.get_max_send_samps_per_packet(); + const size_t bytes_per_packet = _data_transports.front()->get_send_frame_size() - _max_tx_header_bytes; + return bytes_per_packet/_tx_otw_type.get_sample_size(); } size_t send( const std::vector &, size_t, @@ -237,7 +194,8 @@ public: uhd::device::send_mode_t, double ); size_t get_max_recv_samps_per_packet(void) const{ - return _io_helper.get_max_recv_samps_per_packet(); + const size_t bytes_per_packet = _data_transports.front()->get_recv_frame_size() - _max_rx_header_bytes; + return bytes_per_packet/_rx_otw_type.get_sample_size(); } size_t recv( const std::vector &, size_t, @@ -257,9 +215,20 @@ private: //io impl methods and members std::vector _data_transports; - const usrp2_io_helper _io_helper; UHD_PIMPL_DECL(io_impl) _io_impl; void io_init(void); + + //over-the-wire structs and constants + uhd::otw_type_t _rx_otw_type, _tx_otw_type; + static const size_t _max_rx_header_bytes = 0 + + uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(uhd::transport::vrt::if_packet_info_t().tlr) //forced to have trailer + - sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used + ; + static const size_t _max_tx_header_bytes = 0 + + uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + - sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used + ; }; #endif /* INCLUDED_USRP2_IMPL_HPP */ -- cgit v1.2.3 From d2494b0313399b141913ad332315fefbba012e94 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 5 Oct 2010 12:50:53 -0700 Subject: uhd: transport docs for UDP and USB (moved from usrp docs) --- host/docs/CMakeLists.txt | 1 + host/docs/index.rst | 9 ++-- host/docs/transport.rst | 81 +++++++++++++++++++++++++++++++ host/docs/usrp1.rst | 23 --------- host/docs/usrp2.rst | 41 ---------------- host/lib/transport/udp_zero_copy_asio.cpp | 5 +- 6 files changed, 91 insertions(+), 69 deletions(-) create mode 100644 host/docs/transport.rst diff --git a/host/docs/CMakeLists.txt b/host/docs/CMakeLists.txt index bbb8812b0..65db3befc 100644 --- a/host/docs/CMakeLists.txt +++ b/host/docs/CMakeLists.txt @@ -25,6 +25,7 @@ SET(manual_sources dboards.rst general.rst images.rst + transport.rst usrp1.rst usrp2.rst ) diff --git a/host/docs/index.rst b/host/docs/index.rst index bd55edc0b..7f8129e2d 100644 --- a/host/docs/index.rst +++ b/host/docs/index.rst @@ -20,11 +20,12 @@ Building the UHD ^^^^^^^^^^^^^^^^^^^^^ Application Notes ^^^^^^^^^^^^^^^^^^^^^ -* `General App Notes <./general.html>`_ +* `General Application Notes <./general.html>`_ * `Firmware and FPGA Image Notes <./images.html>`_ -* `USRP1 App Notes <./usrp1.html>`_ -* `USRP2 App Notes <./usrp2.html>`_ -* `Daughterboard App Notes <./dboards.html>`_ +* `USRP1 Application Notes <./usrp1.html>`_ +* `USRP2 Application Notes <./usrp2.html>`_ +* `Daughterboard Application Notes <./dboards.html>`_ +* `Transport Application Notes <./transport.html>`_ ^^^^^^^^^^^^^^^^^^^^^ API Documentation diff --git a/host/docs/transport.rst b/host/docs/transport.rst new file mode 100644 index 000000000..d6a146c67 --- /dev/null +++ b/host/docs/transport.rst @@ -0,0 +1,81 @@ +======================================================================== +UHD - Transport Application Notes +======================================================================== + +.. contents:: Table of Contents + +The advanced user can pass optional parameters +into the underlying transport layer through the device address. +These optional parameters control how the transport object allocates memory, +resizes kernel buffers, spawns threads, etc. +When not spcified, the transport layer will use values for these parameters +that are known to perform well on a variety of systems. +The transport parameters are defined below for the various transports in the UHD: + +------------------------------------------------------------------------ +UDP transport (ASIO) +------------------------------------------------------------------------ +The UDP transport is implemented with Boost's ASIO library. +ASIO provides an asynchronous API for user-space sockets. +The transport implementation allocates a number of buffers +and submits asynchronous requests for send and receive. +IO service threads run in the background to process these requests. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Transport parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following parameters can be used to alter the transport's default behavior: + +* **recv_frame_size:** The size of a single receive buffer in bytes +* **num_recv_frames:** The number of receive buffers to allocate +* **send_frame_size:** The size of a single send buffer in bytes +* **num_send_frames:** The number of send buffers to allocate +* **concurrency_hint:** The number of threads to run the IO service + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Resize socket buffers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +It may be useful increase the size of the socket buffers to +move the burden of buffering samples into the kernel, or to +buffer incoming samples faster than they can be processed. +However, if your application cannot process samples fast enough, +no amount of buffering can save you. +The following parameters can be used to alter socket's buffer sizes: + +* **recv_buff_size:** The desired size of the receive buffer in bytes +* **send_buff_size:** The desired size of the send buffer in bytes + +**Note:** Large send buffers tend to decrease transmit performance. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Linux specific notes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +On linux, the maximum buffer sizes are capped by the sysctl values +**net.core.rmem_max** and **net.core.wmem_max**. +To change the maximum values, run the following commands: +:: + + sudo sysctl -w net.core.rmem_max= + sudo sysctl -w net.core.wmem_max= + +Set the values permanently by editing */etc/sysctl.conf* + +------------------------------------------------------------------------ +USB transport (libusb) +------------------------------------------------------------------------ +The USB transport is implemented with libusb. +Libusb provides an asynchronous API for USB bulk transfers. +The transport implementation allocates a number of buffers +and submits asynchronous requests through libusb. +A single thread runs in the background +and executes the libusb event handler to process these requests. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Transport parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following parameters can be used to alter the transport's default behavior: + +* **recv_frame_size:** The size of a single receive transfers in bytes +* **num_recv_frames:** The number of simultaneous receive transfers +* **send_frame_size:** The size of a single send transfers in bytes +* **num_send_frames:** The number of simultaneous send transfers diff --git a/host/docs/usrp1.rst b/host/docs/usrp1.rst index 0baa93a45..3443fd871 100644 --- a/host/docs/usrp1.rst +++ b/host/docs/usrp1.rst @@ -60,29 +60,6 @@ Example device address string representations to specify non-standard firmware a fpga=usrp1_fpga_4rx.rbf, fw=usrp1_fw_custom.ihx -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Change USB transfer parameters -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The advanced user may manipulate parameters of the usb bulk transfers -for various reasons, such as lowering latency or increasing buffer size. -By default, the UHD will use values for these parameters -that are known to perform well on a variety of systems. -The following device address parameters can be used to manipulate USB bulk transfers: - -* **recv_xfer_size:** the size of each receive bulk transfer in bytes -* **recv_num_xfers:** the number of simultaneous receive bulk transfers -* **send_xfer_size:** the size of each send bulk transfer in bytes -* **send_num_xfers:** the number of simultaneous send bulk transfers - -Example usage, set the device address markup string to the following: -:: - - serial=12345678, recv_num_xfers=16 - - -- OR -- - - serial=12345678, recv_xfer_size=2048, recv_num_xfers=16 - ------------------------------------------------------------------------ Specifying the subdevice to use ------------------------------------------------------------------------ diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index 70e5ea28b..1ebab388a 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -165,47 +165,6 @@ The device address string representation for 2 USRP2s with IPv4 addresses 192.16 addr=192.168.10.2 192.168.20.2 ------------------------------------------------------------------------- -Resize the send and receive buffers ------------------------------------------------------------------------- -It may be useful increase the size of the socket buffers to -move the burden of buffering samples into the kernel, or to -buffer incoming samples faster than they can be processed. -However, if you application cannot process samples fast enough, -no amount of buffering can save you. - -By default, the UHD will try to resize both the send and receive buffer for optimum performance. -A warning will be printed on instantiation if the actual buffer size is insufficient. -See the OS specific notes below: - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -OS specific notes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -On linux, the maximum buffer sizes are capped by the sysctl values -**net.core.rmem_max** and **net.core.wmem_max**. -To change the maximum values, run the following commands: -:: - - sudo sysctl -w net.core.rmem_max= - sudo sysctl -w net.core.wmem_max= - -Set the values permanently by editing */etc/sysctl.conf* - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Device address params -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -To manually set the size of the buffers, -the usrp2 will accept two optional parameters in the device address. -Each parameter will accept a numeric value for the number of bytes. - -* recv_buff_size -* send_buff_size - -Example usage, set the device address markup string to the following: -:: - - addr=192.168.10.2, recv_buff_size=100e6 - ------------------------------------------------------------------------ Hardware setup notes ------------------------------------------------------------------------ diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index ada282e07..a87f17a91 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -248,7 +248,10 @@ template static void resize_buff_helper( if (actual_size < target_size) uhd::print_warning(str(boost::format( "The %s buffer is smaller than the requested size.\n" "The minimum recommended buffer size is %d bytes.\n" - "See the USRP2 application notes on buffer resizing.\n" + "See the transport application notes on buffer resizing.\n" + #if defined(UHD_PLATFORM_LINUX) + "On Linux: sudo sysctl -w net.core.rmem_max=%2%\n" + #endif /*defined(UHD_PLATFORM_LINUX)*/ ) % name % min_sock_buff_size)); } -- cgit v1.2.3 From 0fc641042ef81731fa84f796fd983a5a602e260c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 5 Oct 2010 15:47:58 -0700 Subject: usb: moved event handler thread into the zero copy interface --- host/docs/transport.rst | 1 + host/lib/transport/libusb1_base.cpp | 18 ------------------ host/lib/transport/libusb1_zero_copy.cpp | 28 ++++++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/host/docs/transport.rst b/host/docs/transport.rst index d6a146c67..30fc1d78f 100644 --- a/host/docs/transport.rst +++ b/host/docs/transport.rst @@ -79,3 +79,4 @@ The following parameters can be used to alter the transport's default behavior: * **num_recv_frames:** The number of simultaneous receive transfers * **send_frame_size:** The size of a single send transfers in bytes * **num_send_frames:** The number of simultaneous send transfers +* **concurrency_hint:** The number of threads to run the event handler diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index 910b04fc8..cfa77d9ca 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -16,12 +16,10 @@ // #include "libusb1_base.hpp" -#include #include #include #include #include -#include #include using namespace uhd; @@ -35,12 +33,9 @@ public: libusb_session_impl(void){ UHD_ASSERT_THROW(libusb_init(&_context) == 0); libusb_set_debug(_context, debug_level); - _thread_group.create_thread(boost::bind(&libusb_session_impl::run_event_loop, this)); } ~libusb_session_impl(void){ - _running = false; - _thread_group.join_all(); libusb_exit(_context); } @@ -50,19 +45,6 @@ public: private: libusb_context *_context; - boost::thread_group _thread_group; - bool _running; - - void run_event_loop(void){ - set_thread_priority_safe(); - _running = true; - timeval tv; - while(_running){ - tv.tv_sec = 0; - tv.tv_usec = 100000; //100ms - libusb_handle_events_timeout(this->get_context(), &tv); - } - } }; libusb::session::sptr libusb::session::get_global_session(void){ diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index df6db1eb9..f589d7c77 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -18,6 +18,7 @@ #include "libusb1_base.hpp" #include #include +#include #include #include #include @@ -290,6 +291,11 @@ public: const device_addr_t &hints ); + ~libusb_zero_copy_impl(void){ + _threads_running = false; + _thread_group.join_all(); + } + managed_recv_buffer::sptr get_recv_buff(double); managed_send_buffer::sptr get_send_buff(double); @@ -318,6 +324,22 @@ private: const size_t _recv_frame_size, _num_recv_frames; const size_t _send_frame_size, _num_send_frames; usb_endpoint::sptr _recv_ep, _send_ep; + + //event handler threads + boost::thread_group _thread_group; + bool _threads_running; + + void run_event_loop(void){ + set_thread_priority_safe(); + libusb::session::sptr session = libusb::session::get_global_session(); + _threads_running = true; + while(_threads_running){ + timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 100000; //100ms + libusb_handle_events_timeout(session->get_context(), &tv); + } + } }; /* @@ -355,6 +377,12 @@ libusb_zero_copy_impl::libusb_zero_copy_impl( this->get_send_frame_size(), // buffer size per transfer this->get_num_send_frames() // number of libusb transfers )); + + //spawn the event handler threads + size_t concurrency = hints.cast("concurrency_hint", 1); + for (size_t i = 0; i < concurrency; i++) _thread_group.create_thread( + boost::bind(&libusb_zero_copy_impl::run_event_loop, this) + ); } /* -- cgit v1.2.3 From 7c127b6c82db773ca2dcab372ab28b4dc4e5b347 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 6 Oct 2010 10:34:10 -0700 Subject: udp: fixed boost format syntax for warning message --- host/lib/transport/udp_zero_copy_asio.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index a87f17a91..7e28caf2d 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -246,11 +246,11 @@ template static void resize_buff_helper( "Current %s sock buff size: %d bytes" ) % name % actual_size << std::endl; if (actual_size < target_size) uhd::print_warning(str(boost::format( - "The %s buffer is smaller than the requested size.\n" - "The minimum recommended buffer size is %d bytes.\n" + "The %1% buffer is smaller than the requested size.\n" + "The minimum recommended buffer size is %2% bytes.\n" "See the transport application notes on buffer resizing.\n" #if defined(UHD_PLATFORM_LINUX) - "On Linux: sudo sysctl -w net.core.rmem_max=%2%\n" + "Please run: sudo sysctl -w net.core.rmem_max=%2%\n" #endif /*defined(UHD_PLATFORM_LINUX)*/ ) % name % min_sock_buff_size)); } -- cgit v1.2.3 From 12901b055f021acf1b02f4bc7e9c3c8d1aa426e5 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Wed, 6 Oct 2010 18:48:03 -0400 Subject: Add flag that indicates userspace has started processing a frame. --- host/include/linux/usrp_e.h | 1 + 1 file changed, 1 insertion(+) diff --git a/host/include/linux/usrp_e.h b/host/include/linux/usrp_e.h index 80f3a287b..cb62d940d 100644 --- a/host/include/linux/usrp_e.h +++ b/host/include/linux/usrp_e.h @@ -71,6 +71,7 @@ struct usrp_e_i2c { #define RB_KERNEL (1<<1) #define RB_OVERRUN (1<<2) #define RB_DMA_ACTIVE (1<<3) +#define RB_USER_PROCESS (1<<4) struct ring_buffer_info { int flags; -- cgit v1.2.3 From d5a0960455560e9f6077aa45d52aa01c469769dd Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 6 Oct 2010 16:26:35 -0700 Subject: usrp-e: implemented the USER_PROCESS flag and CTM poll technique --- host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp | 33 +++++++++++--------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp index 9e25ed088..4e10bcc48 100644 --- a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp @@ -31,6 +31,7 @@ using namespace uhd::transport; static const bool fp_verbose = true; //fast-path verbose static const bool sp_verbose = true; //slow-path verbose +static const size_t poll_breakout = 10; //how many poll timeouts constitute a full timeout /*********************************************************************** * The zero copy interface implementation @@ -104,19 +105,19 @@ public: //poll/wait for a ready frame if (not (info->flags & RB_USER)){ - pollfd pfd; - pfd.fd = _fd; - pfd.events = POLLIN; - ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3)); - if (fp_verbose) std::cout << " POLLIN: " << poll_ret << std::endl; - if (poll_ret <= 0) return managed_recv_buffer::sptr(); - } - - //check that the frame is really ready - if (not (info->flags & RB_USER)){ - if (fp_verbose) std::cout << " flags: not ready" << std::endl; - return managed_recv_buffer::sptr(); - } + for (size_t i = 0; i < poll_breakout; i++){ + pollfd pfd; + pfd.fd = _fd; + pfd.events = POLLIN; + ssize_t poll_ret = ::poll(&pfd, 1, size_t(timeout*1e3/poll_breakout)); + if (fp_verbose) std::cout << " POLLIN: " << poll_ret << std::endl; + if (poll_ret > 0) goto found_user_frame; //good poll, continue on + } + return managed_recv_buffer::sptr(); //timed-out for real + } found_user_frame: + + //the process has claimed the frame + info->flags = RB_USER_PROCESS; //increment the index for the next call if (++_recv_index == size_t(_rb_size.num_rx_frames)) _recv_index = 0; @@ -150,12 +151,6 @@ public: if (poll_ret <= 0) return managed_send_buffer::sptr(); } - //check that the frame is really ready - if (not (info->flags & RB_KERNEL)){ - if (fp_verbose) std::cout << " flags: not ready" << std::endl; - return managed_send_buffer::sptr(); - } - //increment the index for the next call if (++_send_index == size_t(_rb_size.num_tx_frames)) _send_index = 0; -- cgit v1.2.3 From b40ace72dd1b940fc0ce6e4a5e06346439dd5625 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 6 Oct 2010 18:41:30 -0700 Subject: usrp1: use the transport frame sizes to calculate the max spp The max send spp is the frame size minus the alignment padding. This allows us to copy a remainder into a new buffer and always commit multiples of the alignment size (512 bytes). Reworked the managed send buffer implementation to handle the above. Uses only managed memory, and only mem-copied under the alignment. --- host/lib/usrp/usrp1/io_impl.cpp | 169 +++++++++++++++++++++---------------- host/lib/usrp/usrp1/usrp1_impl.hpp | 10 +-- 2 files changed, 99 insertions(+), 80 deletions(-) diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 676b1536a..0a16f7a43 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -33,6 +33,28 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; +static const size_t alignment_padding = 512; + +/*********************************************************************** + * Helper struct to associate an offset with a buffer + **********************************************************************/ +class offset_send_buffer{ +public: + typedef boost::shared_ptr sptr; + + static sptr make(managed_send_buffer::sptr buff, size_t offset = 0){ + return sptr(new offset_send_buffer(buff, offset)); + } + + //member variables + managed_send_buffer::sptr buff; + size_t offset; /* in bytes */ + +private: + offset_send_buffer(managed_send_buffer::sptr buff, size_t offset): + buff(buff), offset(offset){/* NOP */} +}; + /*********************************************************************** * IO Implementation Details **********************************************************************/ @@ -41,8 +63,7 @@ struct usrp1_impl::io_impl{ data_transport(data_transport), underflow_poll_samp_count(0), overflow_poll_samp_count(0), - send_buff(data_transport->get_send_buff()), - num_bytes_committed(0) + curr_buff(offset_send_buffer::make(data_transport->get_send_buff())) { /* NOP */ } @@ -62,98 +83,88 @@ struct usrp1_impl::io_impl{ size_t overflow_poll_samp_count; //wrapper around the actual send buffer interface - //all of this to ensure only full buffers are committed - managed_send_buffer::sptr send_buff; - size_t num_bytes_committed; - double send_timeout; - boost::uint8_t pseudo_buff[BYTES_PER_PACKET]; - void phony_commit_pseudo_buff(size_t num_bytes); - void phony_commit_send_buff(size_t num_bytes); - void commit_send_buff(void); + //all of this to ensure only aligned lengths are committed + //NOTE: you must commit before getting a new buffer + //since the vrt packet handler obeys this, we are ok + offset_send_buffer::sptr curr_buff; + void commit_send_buff(offset_send_buffer::sptr, offset_send_buffer::sptr, size_t); void flush_send_buff(void); bool get_send_buffs(vrt_packet_handler::managed_send_buffs_t &, double); - - //helpers to get at the send buffer + offset - inline void *get_send_mem_ptr(void){ - return send_buff->cast() + num_bytes_committed; - } - inline size_t get_send_mem_size(void){ - return send_buff->size() - num_bytes_committed; - } }; /*! - * Accept a commit of num bytes to the pseudo buffer. - * Memcpy the entire contents of pseudo buffer into send buffers. - * - * Under most conditions: - * The first loop iteration will fill the remainder of the send buffer. - * The second loop iteration will empty the pseudo buffer remainder. + * Perform an actual commit on the send buffer: + * Copy the remainder of alignment to the next buffer. + * Commit the current buffer at multiples of alignment. */ -void usrp1_impl::io_impl::phony_commit_pseudo_buff(size_t num_bytes){ - size_t bytes_to_copy = num_bytes, bytes_copied = 0; - while(bytes_to_copy){ - size_t bytes_copied_here = std::min(bytes_to_copy, get_send_mem_size()); - std::memcpy(get_send_mem_ptr(), pseudo_buff + bytes_copied, bytes_copied_here); - phony_commit_send_buff(bytes_copied_here); - bytes_to_copy -= bytes_copied_here; - bytes_copied += bytes_copied_here; - } -} +void usrp1_impl::io_impl::commit_send_buff( + offset_send_buffer::sptr curr, + offset_send_buffer::sptr next, + size_t num_bytes +){ + //total number of bytes now in the current buffer + size_t bytes_in_curr_buffer = curr->offset + num_bytes; -/*! - * Accept a commit of num bytes to the send buffer. - * Conditionally commit the send buffer if full. - */ -void usrp1_impl::io_impl::phony_commit_send_buff(size_t num_bytes){ - num_bytes_committed += num_bytes; - if (num_bytes_committed != send_buff->size()) return; - commit_send_buff(); + //calculate how many to commit and remainder + size_t num_bytes_remaining = bytes_in_curr_buffer % alignment_padding; + size_t num_bytes_to_commit = bytes_in_curr_buffer - num_bytes_remaining; + + //copy the remainder into the next buffer + std::memcpy( + next->buff->cast() + next->offset, + curr->buff->cast() + num_bytes_to_commit, + num_bytes_remaining + ); + + //update the offset into the next buffer + next->offset += num_bytes_remaining; + + //commit the current buffer + curr->buff->commit(num_bytes_to_commit); } /*! - * Flush the send buffer: - * Zero-pad the send buffer to the nearest 512 byte boundary and commit. + * Flush the current buffer by padding out to alignment and committing. */ void usrp1_impl::io_impl::flush_send_buff(void){ - size_t bytes_to_pad = (-1*num_bytes_committed)%512; - std::memset(get_send_mem_ptr(), 0, bytes_to_pad); - num_bytes_committed += bytes_to_pad; - commit_send_buff(); + //calculate the number of bytes to alignment + size_t bytes_to_pad = (-1*curr_buff->offset)%alignment_padding; + + //get the buffer, clear, and commit (really current buffer) + vrt_packet_handler::managed_send_buffs_t buffs(1); + if (this->get_send_buffs(buffs, 0.1)){ + std::memset(buffs[0]->cast(), 0, bytes_to_pad); + buffs[0]->commit(bytes_to_pad); + } } /*! - * Perform an actual commit on the send buffer: - * Commit the contents of the send buffer and request a new buffer. + * Get a managed send buffer with the alignment padding: + * Always grab the next send buffer so we can timeout here. */ -void usrp1_impl::io_impl::commit_send_buff(void){ - send_buff->commit(num_bytes_committed); - send_buff = data_transport->get_send_buff(send_timeout); - num_bytes_committed = 0; -} - bool usrp1_impl::io_impl::get_send_buffs( vrt_packet_handler::managed_send_buffs_t &buffs, double timeout ){ - send_timeout = timeout; UHD_ASSERT_THROW(buffs.size() == 1); - //not enough bytes free -> use the pseudo buffer - if (get_send_mem_size() < BYTES_PER_PACKET){ - buffs[0] = managed_send_buffer::make_safe( - boost::asio::buffer(pseudo_buff), - boost::bind(&usrp1_impl::io_impl::phony_commit_pseudo_buff, this, _1) - ); - } - //otherwise use the send buffer offset by the bytes written - else{ - buffs[0] = managed_send_buffer::make_safe( - boost::asio::buffer(get_send_mem_ptr(), get_send_mem_size()), - boost::bind(&usrp1_impl::io_impl::phony_commit_send_buff, this, _1) - ); - } + //try to get a new managed buffer with timeout + offset_send_buffer::sptr next_buff(offset_send_buffer::make(data_transport->get_send_buff(timeout))); + if (not next_buff->buff.get()) return false; /* propagate timeout here */ - return buffs[0].get() != NULL; + //calculate the buffer pointer and size given the offset + //references to the buffers are held in the bound function + buffs[0] = managed_send_buffer::make_safe( + boost::asio::buffer( + curr_buff->buff->cast() + curr_buff->offset, + curr_buff->buff->size() - curr_buff->offset + ), + boost::bind(&usrp1_impl::io_impl::commit_send_buff, this, curr_buff, next_buff, _1) + ); + + //store the next buffer for the next call + curr_buff = next_buff; + + return true; } /*********************************************************************** @@ -182,6 +193,13 @@ static void usrp1_bs_vrt_packer( if_packet_info.num_packet_words32 = if_packet_info.num_payload_words32; } +size_t usrp1_impl::get_max_send_samps_per_packet(void) const { + return (_data_transport->get_send_frame_size() - alignment_padding) + / _tx_otw_type.get_sample_size() + / _tx_subdev_spec.size() + ; +} + size_t usrp1_impl::send( const std::vector &buffs, size_t num_samps, const tx_metadata_t &metadata, const io_type_t &io_type, @@ -249,6 +267,13 @@ static bool get_recv_buffs( return buffs[0].get() != NULL; } +size_t usrp1_impl::get_max_recv_samps_per_packet(void) const { + return _data_transport->get_recv_frame_size() + / _rx_otw_type.get_sample_size() + / _rx_subdev_spec.size() + ; +} + size_t usrp1_impl::recv( const std::vector &buffs, size_t num_samps, rx_metadata_t &metadata, const io_type_t &io_type, diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index f2c464610..ff4d40762 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -90,15 +90,9 @@ public: const uhd::io_type_t &, recv_mode_t, double); - static const size_t BYTES_PER_PACKET = 512*4; //under the transfer size + size_t get_max_send_samps_per_packet(void) const; - size_t get_max_send_samps_per_packet(void) const { - return BYTES_PER_PACKET/_tx_otw_type.get_sample_size()/_tx_subdev_spec.size(); - } - - size_t get_max_recv_samps_per_packet(void) const { - return BYTES_PER_PACKET/_rx_otw_type.get_sample_size()/_rx_subdev_spec.size(); - } + size_t get_max_recv_samps_per_packet(void) const; bool recv_async_msg(uhd::async_metadata_t &, double); -- cgit v1.2.3 From be6a6b291400dde7b2b3b935e2eedd8d892e54f8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 7 Oct 2010 10:27:30 -0700 Subject: usrp-e: use frame size to calculate the max samples per packet --- host/lib/usrp/usrp_e/io_impl.cpp | 43 ++++++++++++++++++-------- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 6 ++-- host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp | 8 +++++ 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 2802a6b87..406b7269f 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -91,7 +91,6 @@ void usrp_e_impl::io_impl::recv_pirate_loop( ){ set_thread_priority_safe(); recv_pirate_crew_raiding = true; - //size_t next_packet_seq = 0; while(recv_pirate_crew_raiding){ managed_recv_buffer::sptr buff = this->data_xport->get_recv_buff(); @@ -143,6 +142,15 @@ void usrp_e_impl::io_impl::recv_pirate_loop( * Helper Functions **********************************************************************/ void usrp_e_impl::io_init(void){ + //setup otw types + _send_otw_type.width = 16; + _send_otw_type.shift = 0; + _send_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; + + _recv_otw_type.width = 16; + _recv_otw_type.shift = 0; + _recv_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; + //setup rx data path _iface->poke32(UE_REG_CTRL_RX_NSAMPS_PER_PKT, get_max_recv_samps_per_packet()); _iface->poke32(UE_REG_CTRL_RX_NCHANNELS, 1); @@ -197,21 +205,25 @@ bool get_send_buffs( return buffs[0].get() != NULL; } +size_t usrp_e_impl::get_max_send_samps_per_packet(void) const{ + static const size_t hdr_size = 0 + + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + - sizeof(vrt::if_packet_info_t().cid) //no class id ever used + ; + size_t bpp = _io_impl->data_xport->get_send_frame_size() - hdr_size; + return bpp/_send_otw_type.get_sample_size(); +} + size_t usrp_e_impl::send( const std::vector &buffs, size_t num_samps, const tx_metadata_t &metadata, const io_type_t &io_type, send_mode_t send_mode, double timeout ){ - otw_type_t send_otw_type; - send_otw_type.width = 16; - send_otw_type.shift = 0; - send_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - return vrt_packet_handler::send( _io_impl->packet_handler_send_state, //last state of the send handler buffs, num_samps, //buffer to fill metadata, send_mode, //samples metadata - io_type, send_otw_type, //input and output types to convert + io_type, _send_otw_type, //input and output types to convert MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_pack_le, boost::bind(&get_send_buffs, _io_impl->data_xport, timeout, _1), @@ -222,21 +234,26 @@ size_t usrp_e_impl::send( /*********************************************************************** * Data Recv **********************************************************************/ +size_t usrp_e_impl::get_max_recv_samps_per_packet(void) const{ + static const size_t hdr_size = 0 + + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer + - sizeof(vrt::if_packet_info_t().cid) //no class id ever used + ; + size_t bpp = _io_impl->data_xport->get_recv_frame_size() - hdr_size; + return bpp/_recv_otw_type.get_sample_size(); +} + size_t usrp_e_impl::recv( const std::vector &buffs, size_t num_samps, rx_metadata_t &metadata, const io_type_t &io_type, recv_mode_t recv_mode, double timeout ){ - otw_type_t recv_otw_type; - recv_otw_type.width = 16; - recv_otw_type.shift = 0; - recv_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - return vrt_packet_handler::recv( _io_impl->packet_handler_recv_state, //last state of the recv handler buffs, num_samps, //buffer to fill metadata, recv_mode, //samples metadata - io_type, recv_otw_type, //input and output types to convert + io_type, _recv_otw_type, //input and output types to convert MASTER_CLOCK_RATE, //master clock tick rate uhd::transport::vrt::if_hdr_unpack_le, boost::bind(&usrp_e_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout), diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 49912050e..95d80fed5 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -85,8 +86,8 @@ public: size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t, double); size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, double); bool recv_async_msg(uhd::async_metadata_t &, double); - size_t get_max_send_samps_per_packet(void) const{return 503;} - size_t get_max_recv_samps_per_packet(void) const{return 503;} + size_t get_max_send_samps_per_packet(void) const; + size_t get_max_recv_samps_per_packet(void) const; private: //interface to ioctls and file descriptor @@ -97,6 +98,7 @@ private: //handle io stuff UHD_PIMPL_DECL(io_impl) _io_impl; + uhd::otw_type_t _send_otw_type, _recv_otw_type; void io_init(void); void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd); void handle_overrun(size_t); diff --git a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp index 4e10bcc48..bc18c490b 100644 --- a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp @@ -134,6 +134,10 @@ public: return _rb_size.num_rx_frames; } + size_t get_recv_frame_size(void) const{ + return _frame_size; + } + managed_send_buffer::sptr get_send_buff(double timeout){ if (fp_verbose) std::cout << "get_send_buff: " << _send_index << std::endl; @@ -166,6 +170,10 @@ public: return _rb_size.num_tx_frames; } + size_t get_send_frame_size(void) const{ + return _frame_size; + } + private: void release(ring_buffer_info *info){ -- cgit v1.2.3 From 0059e62ed067a4844edfb720da73fcdb8e69db6a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 7 Oct 2010 10:43:58 -0700 Subject: usrp2: moved samples per packet calculation into io_impl --- host/lib/usrp/usrp2/io_impl.cpp | 19 +++++++++++++++++++ host/lib/usrp/usrp2/usrp2_impl.hpp | 23 +++-------------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 07eda08c3..eba704059 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -197,6 +197,15 @@ static bool get_send_buffs( return good; } +size_t usrp2_impl::get_max_send_samps_per_packet(void) const{ + static const size_t hdr_size = 0 + + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + - sizeof(vrt::if_packet_info_t().cid) //no class id ever used + ; + const size_t bpp = _data_transports.front()->get_send_frame_size() - hdr_size; + return bpp/_tx_otw_type.get_sample_size(); +} + size_t usrp2_impl::send( const std::vector &buffs, size_t num_samps, const tx_metadata_t &metadata, const io_type_t &io_type, @@ -217,6 +226,16 @@ size_t usrp2_impl::send( /*********************************************************************** * Receive Data **********************************************************************/ +size_t usrp2_impl::get_max_recv_samps_per_packet(void) const{ + static const size_t hdr_size = 0 + + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer + - sizeof(vrt::if_packet_info_t().cid) //no class id ever used + ; + const size_t bpp = _data_transports.front()->get_recv_frame_size() - hdr_size; + return bpp/_rx_otw_type.get_sample_size(); +} + size_t usrp2_impl::recv( const std::vector &buffs, size_t num_samps, rx_metadata_t &metadata, const io_type_t &io_type, diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index e12c4d6d4..558726a2b 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -184,24 +184,18 @@ public: ~usrp2_impl(void); //the io interface - size_t get_max_send_samps_per_packet(void) const{ - const size_t bytes_per_packet = _data_transports.front()->get_send_frame_size() - _max_tx_header_bytes; - return bytes_per_packet/_tx_otw_type.get_sample_size(); - } size_t send( const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, uhd::device::send_mode_t, double ); - size_t get_max_recv_samps_per_packet(void) const{ - const size_t bytes_per_packet = _data_transports.front()->get_recv_frame_size() - _max_rx_header_bytes; - return bytes_per_packet/_rx_otw_type.get_sample_size(); - } size_t recv( const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, uhd::device::recv_mode_t, double ); + size_t get_max_send_samps_per_packet(void) const; + size_t get_max_recv_samps_per_packet(void) const; bool recv_async_msg(uhd::async_metadata_t &, double); private: @@ -215,20 +209,9 @@ private: //io impl methods and members std::vector _data_transports; + uhd::otw_type_t _rx_otw_type, _tx_otw_type; UHD_PIMPL_DECL(io_impl) _io_impl; void io_init(void); - - //over-the-wire structs and constants - uhd::otw_type_t _rx_otw_type, _tx_otw_type; - static const size_t _max_rx_header_bytes = 0 - + uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - + sizeof(uhd::transport::vrt::if_packet_info_t().tlr) //forced to have trailer - - sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used - ; - static const size_t _max_tx_header_bytes = 0 - + uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - - sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used - ; }; #endif /* INCLUDED_USRP2_IMPL_HPP */ -- cgit v1.2.3 From 5514e67c64551e8c1d9e706f63be487aa6912705 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 7 Oct 2010 11:06:37 -0700 Subject: usrp1: ensure that the current buffer was committed before getting a new one --- host/lib/usrp/usrp1/io_impl.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 0a16f7a43..6728d9b15 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -63,6 +63,7 @@ struct usrp1_impl::io_impl{ data_transport(data_transport), underflow_poll_samp_count(0), overflow_poll_samp_count(0), + curr_buff_committed(true), curr_buff(offset_send_buffer::make(data_transport->get_send_buff())) { /* NOP */ @@ -86,6 +87,7 @@ struct usrp1_impl::io_impl{ //all of this to ensure only aligned lengths are committed //NOTE: you must commit before getting a new buffer //since the vrt packet handler obeys this, we are ok + bool curr_buff_committed; offset_send_buffer::sptr curr_buff; void commit_send_buff(offset_send_buffer::sptr, offset_send_buffer::sptr, size_t); void flush_send_buff(void); @@ -121,6 +123,7 @@ void usrp1_impl::io_impl::commit_send_buff( //commit the current buffer curr->buff->commit(num_bytes_to_commit); + curr_buff_committed = true; } /*! @@ -145,7 +148,7 @@ void usrp1_impl::io_impl::flush_send_buff(void){ bool usrp1_impl::io_impl::get_send_buffs( vrt_packet_handler::managed_send_buffs_t &buffs, double timeout ){ - UHD_ASSERT_THROW(buffs.size() == 1); + UHD_ASSERT_THROW(curr_buff_committed and buffs.size() == 1); //try to get a new managed buffer with timeout offset_send_buffer::sptr next_buff(offset_send_buffer::make(data_transport->get_send_buff(timeout))); @@ -163,6 +166,7 @@ bool usrp1_impl::io_impl::get_send_buffs( //store the next buffer for the next call curr_buff = next_buff; + curr_buff_committed = false; return true; } -- cgit v1.2.3 From d6e6d8bffc1663fe82ba57e4dcf1ecbcec59c53e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 7 Oct 2010 11:22:19 -0700 Subject: uhd: tweaked docs/notes on transports --- host/docs/transport.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/host/docs/transport.rst b/host/docs/transport.rst index 30fc1d78f..f247e9e34 100644 --- a/host/docs/transport.rst +++ b/host/docs/transport.rst @@ -4,6 +4,10 @@ UHD - Transport Application Notes .. contents:: Table of Contents +------------------------------------------------------------------------ +Introduction +------------------------------------------------------------------------ +A transport is the layer between the packet interface and a device IO interface. The advanced user can pass optional parameters into the underlying transport layer through the device address. These optional parameters control how the transport object allocates memory, @@ -67,8 +71,7 @@ The USB transport is implemented with libusb. Libusb provides an asynchronous API for USB bulk transfers. The transport implementation allocates a number of buffers and submits asynchronous requests through libusb. -A single thread runs in the background -and executes the libusb event handler to process these requests. +Event handler threads run in the background to process these requests. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Transport parameters -- cgit v1.2.3 From 4c3b5212b1b91b30b44af72365448ea6af66c408 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 7 Oct 2010 12:37:42 -0700 Subject: tvrx: converted floats to doubles to avoid msvc warnings --- host/lib/usrp/dboard/db_tvrx.cpp | 110 +++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 41c52fbf5..33507acaa 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -66,25 +66,25 @@ static const uhd::dict tvrx_freq_ranges = map_list_of ("UHF" , freq_range_t(454e6, 860e6)) ; -static const boost::array vhflo_gains_db = +static const boost::array vhflo_gains_db = {{-6.00000, -6.00000, -6.00000, -4.00000, 0.00000, 5.00000, 10.00000, 17.40000, 26.30000, 36.00000, 43.00000, 48.00000, 49.50000, 50.10000, 50.30000, 50.30000, 50.30000}}; - -static const boost::array vhfhi_gains_db = + +static const boost::array vhfhi_gains_db = {{13.3000, -13.3000, -13.3000, -1.0000, 7.7000, 11.0000, 14.7000, 19.3000, 26.1000, 36.0000, 42.7000, 46.0000, 47.0000, 47.8000, 48.2000, 48.2000, 48.2000}}; - -static const boost::array uhf_gains_db = + +static const boost::array uhf_gains_db = {{-8.0000, -8.0000, -7.0000, 4.0000, 10.2000, 14.5000, 17.5000, 20.0000, 24.5000, 30.8000, 37.0000, 39.8000, 40.7000, 41.6000, 42.6000, 43.2000, 43.8000}}; - -static const boost::array tvrx_if_gains_db = + +static const boost::array tvrx_if_gains_db = {{-1.50000, -1.50000, -1.50000, -1.00000, 0.20000, 2.10000, 4.30000, 6.40000, 9.00000, 12.00000, 14.80000, 18.20000, 26.10000, 32.50000, 32.50000, @@ -96,32 +96,32 @@ static const boost::array tvrx_if_gains_db = //need dang near as many coefficients as to just map it like this and interp. //these numbers are culled from the 4937DI5 datasheet and are probably totally inaccurate //but if it's better than the old linear fit i'm happy -static const uhd::dict > tvrx_rf_gains_db = map_list_of +static const uhd::dict > tvrx_rf_gains_db = map_list_of ("VHFLO", vhflo_gains_db) ("VHFHI", vhfhi_gains_db) ("UHF" , uhf_gains_db) ; //sample voltages for the above points -static const boost::array tvrx_gains_volts = +static const boost::array tvrx_gains_volts = {{0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0}}; static uhd::dict get_tvrx_gain_ranges(void) { - float rfmax = 0.0, rfmin = FLT_MAX; + double rfmax = 0.0, rfmin = FLT_MAX; BOOST_FOREACH(const std::string range, tvrx_rf_gains_db.keys()) { - float my_max = tvrx_rf_gains_db[range].back(); //we're assuming it's monotonic - float my_min = tvrx_rf_gains_db[range].front(); //if it's not this is wrong wrong wrong + double my_max = tvrx_rf_gains_db[range].back(); //we're assuming it's monotonic + double my_min = tvrx_rf_gains_db[range].front(); //if it's not this is wrong wrong wrong if(my_max > rfmax) rfmax = my_max; if(my_min < rfmin) rfmin = my_min; } - - float ifmin = tvrx_if_gains_db.front(); - float ifmax = tvrx_if_gains_db.back(); - + + double ifmin = tvrx_if_gains_db.front(); + double ifmax = tvrx_if_gains_db.back(); + return map_list_of - ("RF", gain_range_t(rfmin, rfmax, (rfmax-rfmin)/4096.0)) - ("IF", gain_range_t(ifmin, ifmax, (ifmax-ifmin)/4096.0)) - ; + ("RF", gain_range_t(float(rfmin), float(rfmax), float((rfmax-rfmin)/4096.0))) + ("IF", gain_range_t(float(ifmin), float(ifmax), float((ifmax-ifmin)/4096.0))) + ; } static const double opamp_gain = 1.22; //onboard DAC opamp gain @@ -136,7 +136,7 @@ class tvrx : public rx_dboard_base{ public: tvrx(ctor_args_t args); ~tvrx(void); - + void rx_get(const wax::obj &key, wax::obj &val); void rx_set(const wax::obj &key, const wax::obj &val); @@ -198,11 +198,11 @@ tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){ } //send initial register settings if necessary - + //set default freq _lo_freq = tvrx_freq_range.min + tvrx_if_freq; //init _lo_freq to a sane default set_freq(tvrx_freq_range.min); - + //set default gains BOOST_FOREACH(const std::string &name, get_tvrx_gain_ranges().keys()){ set_gain(get_tvrx_gain_ranges()[name].min, name); @@ -238,33 +238,33 @@ static std::string get_band(double freq) { * \return a voltage to feed the TVRX analog gain */ -static float gain_interp(float gain, boost::array db_vector, boost::array volts_vector) { - float volts; - gain = std::clip(gain, db_vector.front(), db_vector.back()); //let's not get carried away here - +static double gain_interp(double gain, boost::array db_vector, boost::array volts_vector) { + double volts; + gain = std::clip(gain, db_vector.front(), db_vector.back()); //let's not get carried away here + boost::uint8_t gain_step = 0; //find which bin we're in for(size_t i = 0; i < db_vector.size()-1; i++) { if(gain >= db_vector[i] && gain <= db_vector[i+1]) gain_step = i; } - + //find the current slope for linear interpolation - float slope = (volts_vector[gain_step + 1] - volts_vector[gain_step]) + double slope = (volts_vector[gain_step + 1] - volts_vector[gain_step]) / (db_vector[gain_step + 1] - db_vector[gain_step]); - + //the problem here is that for gains approaching the maximum, the voltage slope becomes infinite //i.e., a small change in gain requires an infinite change in voltage //to cope, we limit the slope - - if(slope == std::numeric_limits::infinity()) + + if(slope == std::numeric_limits::infinity()) return volts_vector[gain_step]; //use the volts per dB slope to find the final interpolated voltage volts = volts_vector[gain_step] + (slope * (gain - db_vector[gain_step])); - + if(tvrx_debug) std::cout << "Gain interp: gain: " << gain << ", gain_step: " << int(gain_step) << ", slope: " << slope << ", volts: " << volts << std::endl; - + return volts; } @@ -283,17 +283,17 @@ static float rf_gain_to_voltage(float gain, double lo_freq){ std::string band = get_band(lo_freq + tvrx_if_freq); //this is the voltage at the TVRX gain input - float gain_volts = gain_interp(gain, tvrx_rf_gains_db[band], tvrx_gains_volts); + double gain_volts = gain_interp(gain, tvrx_rf_gains_db[band], tvrx_gains_volts); //this is the voltage at the USRP DAC output - float dac_volts = gain_volts / opamp_gain; - - dac_volts = std::clip(dac_volts, 0.0, 3.3); + double dac_volts = gain_volts / opamp_gain; + + dac_volts = std::clip(dac_volts, 0.0, 3.3); if (tvrx_debug) std::cerr << boost::format( "tvrx RF AGC gain: %f dB, dac_volts: %f V" ) % gain % dac_volts << std::endl; - return dac_volts; + return float(dac_volts); } /*! @@ -306,17 +306,17 @@ static float rf_gain_to_voltage(float gain, double lo_freq){ static float if_gain_to_voltage(float gain){ //clip the input gain = std::clip(gain, get_tvrx_gain_ranges()["IF"].min, get_tvrx_gain_ranges()["IF"].max); - - float gain_volts = gain_interp(gain, tvrx_if_gains_db, tvrx_gains_volts); - float dac_volts = gain_volts / opamp_gain; - - dac_volts = std::clip(dac_volts, 0.0, 3.3); + + double gain_volts = gain_interp(gain, tvrx_if_gains_db, tvrx_gains_volts); + double dac_volts = gain_volts / opamp_gain; + + dac_volts = std::clip(dac_volts, 0.0, 3.3); if (tvrx_debug) std::cerr << boost::format( "tvrx IF AGC gain: %f dB, dac_volts: %f V" ) % gain % dac_volts << std::endl; - return dac_volts; + return float(dac_volts); } void tvrx::set_gain(float gain, const std::string &name){ @@ -337,27 +337,27 @@ void tvrx::set_gain(float gain, const std::string &name){ */ void tvrx::set_freq(double freq) { - freq = std::clip(freq, tvrx_freq_range.min, tvrx_freq_range.max); + freq = std::clip(freq, tvrx_freq_range.min, tvrx_freq_range.max); std::string prev_band = get_band(_lo_freq - tvrx_if_freq); std::string new_band = get_band(freq); - + double target_lo_freq = freq + tvrx_if_freq; //the desired LO freq for high-side mixing double f_ref = reference_freq / double(reference_divider); //your tuning step size - + int divisor = int((target_lo_freq + (f_ref * 4.0)) / (f_ref * 8)); //the divisor we'll use double actual_lo_freq = (f_ref * 8 * divisor); //the LO freq we'll actually get - + if((divisor & ~0x7fff)) UHD_THROW_INVALID_CODE_PATH(); - + //now we update the registers _tuner_4937di5_regs.db1 = (divisor >> 8) & 0xff; _tuner_4937di5_regs.db2 = divisor & 0xff; - + if(new_band == "VHFLO") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_VHFLO; else if(new_band == "VHFHI") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_VHFHI; else if(new_band == "UHF") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_UHF; else UHD_THROW_INVALID_CODE_PATH(); - + _tuner_4937di5_regs.power = tuner_4937di5_regs_t::POWER_OFF; update_regs(); @@ -365,10 +365,10 @@ void tvrx::set_freq(double freq) { //we do this because the gains are different for different band settings //not FAR off, but we do this to be consistent if(prev_band != new_band) set_gain(_gains["RF"], "RF"); - - if(tvrx_debug) + + if(tvrx_debug) std::cout << boost::format("set_freq: target LO: %f f_ref: %f divisor: %i actual LO: %f") % target_lo_freq % f_ref % divisor % actual_lo_freq << std::endl; - + _lo_freq = actual_lo_freq; //for rx props } @@ -422,7 +422,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_FREQ: - /* + /* * so here we have to do some magic. because the TVRX uses a relatively high IF, * we have to watch the sample rate to see if the IF will be aliased * or if it will fall within Nyquist. -- cgit v1.2.3 From 952db7702f52e34fa05b8795abe46fb22add137d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 7 Oct 2010 16:31:41 -0700 Subject: udp: implementation for blocking recv w/ timeout, switch async implementation w/ #define --- host/lib/transport/udp_zero_copy_asio.cpp | 140 +++++++++++++++++++++--------- 1 file changed, 101 insertions(+), 39 deletions(-) diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 7e28caf2d..798cc657d 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -35,6 +35,10 @@ namespace asio = boost::asio; /*********************************************************************** * Constants **********************************************************************/ +//Define this to the the boost async io calls to perform receive. +//Otherwise, get_recv_buff uses a blocking receive with timeout. +//#define USE_ASIO_ASYNC_RECV + //enough buffering for half a second of samples at full rate on usrp2 static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(4 * 25e6 * 0.5); @@ -43,8 +47,15 @@ static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(4 * 25e6 * 0.5); //but may change with host-based flow control. static const size_t MIN_SEND_SOCK_BUFF_SIZE = size_t(10e3); -//the number of async frames to allocate for each send and recv -static const size_t DEFAULT_NUM_FRAMES = 32; +//The number of async frames to allocate for each send and recv: +//The non-async recv can have a very large number of recv frames +//because the CPU overhead is independent of the number of frames. +#ifdef USE_ASIO_ASYNC_RECV +static const size_t DEFAULT_NUM_RECV_FRAMES = 32; +#else +static const size_t DEFAULT_NUM_RECV_FRAMES = MIN_RECV_SOCK_BUFF_SIZE/udp_simple::mtu; +#endif +static const size_t DEFAULT_NUM_SEND_FRAMES = 32; //a single concurrent thread for io_service seems to be the fastest static const size_t CONCURRENCY_HINT = 1; @@ -67,9 +78,9 @@ public: ): _io_service(hints.cast("concurrency_hint", CONCURRENCY_HINT)), _recv_frame_size(size_t(hints.cast("recv_frame_size", udp_simple::mtu))), - _num_recv_frames(size_t(hints.cast("num_recv_frames", DEFAULT_NUM_FRAMES))), + _num_recv_frames(size_t(hints.cast("num_recv_frames", DEFAULT_NUM_RECV_FRAMES))), _send_frame_size(size_t(hints.cast("send_frame_size", udp_simple::mtu))), - _num_send_frames(size_t(hints.cast("num_send_frames", DEFAULT_NUM_FRAMES))) + _num_send_frames(size_t(hints.cast("num_send_frames", DEFAULT_NUM_SEND_FRAMES))) { //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; @@ -82,6 +93,13 @@ public: _socket = new asio::ip::udp::socket(_io_service); _socket->open(asio::ip::udp::v4()); _socket->connect(receiver_endpoint); + _sock_fd = _socket->native(); + } + + ~udp_zero_copy_asio_impl(void){ + delete _work; //allow io_service run to complete + _thread_group.join_all(); //wait for service threads to exit + delete _socket; } void init(void){ @@ -106,10 +124,9 @@ public: ); } - ~udp_zero_copy_asio_impl(void){ - delete _work; //allow io_service run to complete - _thread_group.join_all(); //wait for service threads to exit - delete _socket; + void service(void){ + set_thread_priority_safe(); + _io_service.run(); } //get size for internal socket buffer @@ -126,6 +143,9 @@ public: return get_buff_size(); } + //////////////////////////////////////////////////////////////////// + #ifdef USE_ASIO_ASYNC_RECV + //////////////////////////////////////////////////////////////////// //! pop a filled recv buffer off of the fifo and bind with the release callback managed_recv_buffer::sptr get_recv_buff(double timeout){ boost::this_thread::disable_interruption di; //disable because the wait can throw @@ -142,6 +162,74 @@ public: return managed_recv_buffer::sptr(); } + //! handle a recv callback -> push the filled memory into the fifo + void handle_recv(void *mem, size_t len){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + _pending_recv_buffs->push_with_wait(boost::asio::buffer(mem, len)); + } + + //! release a recv buffer -> start an async recv on the buffer + void release(void *mem){ + _socket->async_receive( + boost::asio::buffer(mem, _recv_frame_size), + boost::bind( + &udp_zero_copy_asio_impl::handle_recv, + shared_from_this(), mem, + asio::placeholders::bytes_transferred + ) + ); + } + + //////////////////////////////////////////////////////////////////// + #else /*USE_ASIO_ASYNC_RECV*/ + //////////////////////////////////////////////////////////////////// + managed_recv_buffer::sptr get_recv_buff(double timeout){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + + //setup timeval for timeout + timeval tv; + tv.tv_sec = 0; + tv.tv_usec = timeout*1e6; + + //setup rset for timeout + fd_set rset; + FD_ZERO(&rset); + FD_SET(_sock_fd, &rset); + + //call select to perform timed wait + if (::select(_sock_fd+1, &rset, NULL, NULL, &tv) <= 0) + return managed_recv_buffer::sptr(); + + //grab an available buffer + asio::mutable_buffer buff; + if (not _pending_recv_buffs->pop_with_timed_wait(buff, timeout)) + return managed_recv_buffer::sptr(); + + //receive and return the buffer + return managed_recv_buffer::make_safe( + asio::buffer( + boost::asio::buffer_cast(buff), + _socket->receive(boost::asio::buffer(buff)) + ), + boost::bind( + &udp_zero_copy_asio_impl::release, + shared_from_this(), + asio::buffer_cast(buff) + ) + ); + } + + void release(void *mem){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + _pending_recv_buffs->push_with_wait( + boost::asio::buffer(mem, this->get_recv_frame_size()) + ); + } + + //////////////////////////////////////////////////////////////////// + #endif /*USE_ASIO_ASYNC_RECV*/ + //////////////////////////////////////////////////////////////////// + size_t get_num_recv_frames(void) const {return _num_recv_frames;} size_t get_recv_frame_size(void) const {return _recv_frame_size;} @@ -161,37 +249,6 @@ public: return managed_send_buffer::sptr(); } - size_t get_num_send_frames(void) const {return _num_send_frames;} - size_t get_send_frame_size(void) const {return _send_frame_size;} - -private: - void service(void){ - set_thread_priority_safe(); - _io_service.run(); - } - - /******************************************************************* - * The async send and receive callbacks - ******************************************************************/ - - //! handle a recv callback -> push the filled memory into the fifo - void handle_recv(void *mem, size_t len){ - boost::this_thread::disable_interruption di; //disable because the wait can throw - _pending_recv_buffs->push_with_wait(boost::asio::buffer(mem, len)); - } - - //! release a recv buffer -> start an async recv on the buffer - void release(void *mem){ - _socket->async_receive( - boost::asio::buffer(mem, _recv_frame_size), - boost::bind( - &udp_zero_copy_asio_impl::handle_recv, - shared_from_this(), mem, - asio::placeholders::bytes_transferred - ) - ); - } - //! handle a send callback -> push the emptied memory into the fifo void handle_send(void *mem){ boost::this_thread::disable_interruption di; //disable because the wait can throw @@ -209,10 +266,15 @@ private: ); } + size_t get_num_send_frames(void) const {return _num_send_frames;} + size_t get_send_frame_size(void) const {return _send_frame_size;} + +private: //asio guts -> socket and service asio::ip::udp::socket *_socket; asio::io_service _io_service; asio::io_service::work *_work; + asio::ip::udp::socket::native_type _sock_fd; //memory management -> buffers and fifos boost::thread_group _thread_group; -- cgit v1.2.3 From 201af62ccb4d1065a44822f0f3ce4c81755510b5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 7 Oct 2010 16:34:29 -0700 Subject: udp: fix msvc errors for udp transport --- host/lib/transport/udp_zero_copy_asio.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 798cc657d..40fe3fa0f 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -189,7 +189,7 @@ public: //setup timeval for timeout timeval tv; tv.tv_sec = 0; - tv.tv_usec = timeout*1e6; + tv.tv_usec = long(timeout*1e6); //setup rset for timeout fd_set rset; @@ -274,7 +274,7 @@ private: asio::ip::udp::socket *_socket; asio::io_service _io_service; asio::io_service::work *_work; - asio::ip::udp::socket::native_type _sock_fd; + int _sock_fd; //memory management -> buffers and fifos boost::thread_group _thread_group; -- cgit v1.2.3 From e8e9258acb8ce8499c40de52abaa4e6ba83d479d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 8 Oct 2010 11:20:30 -0700 Subject: udp: worked blocking send back into udp transport, enable async with #define tweaked some code in bounded buffer --- host/include/uhd/transport/alignment_buffer.ipp | 8 +- host/include/uhd/transport/bounded_buffer.ipp | 39 +++++--- host/lib/transport/udp_zero_copy_asio.cpp | 114 +++++++++++++++--------- 3 files changed, 99 insertions(+), 62 deletions(-) diff --git a/host/include/uhd/transport/alignment_buffer.ipp b/host/include/uhd/transport/alignment_buffer.ipp index 5f09de0d9..833b5d399 100644 --- a/host/include/uhd/transport/alignment_buffer.ipp +++ b/host/include/uhd/transport/alignment_buffer.ipp @@ -54,14 +54,14 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ UHD_INLINE bool pop_elems_with_timed_wait( std::vector &elems, double timeout ){ - boost::system_time exit_time = boost::get_system_time() + boost::posix_time::microseconds(long(timeout*1e6)); + boost::system_time exit_time = boost::get_system_time() + to_time_dur(timeout); buff_contents_type buff_contents_tmp; std::list indexes_to_do(_all_indexes); //do an initial pop to load an initial sequence id size_t index = indexes_to_do.front(); if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, 1e-6*(exit_time - boost::get_system_time()).total_microseconds() + buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time()) )) return false; elems[index] = buff_contents_tmp.first; seq_type expected_seq_id = buff_contents_tmp.second; @@ -76,7 +76,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ indexes_to_do = _all_indexes; index = indexes_to_do.front(); if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, 1e-6*(exit_time - boost::get_system_time()).total_microseconds() + buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time()) )) return false; elems[index] = buff_contents_tmp.first; expected_seq_id = buff_contents_tmp.second; @@ -86,7 +86,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ //pop an element off for this index index = indexes_to_do.front(); if (not _buffs[index]->pop_with_timed_wait( - buff_contents_tmp, 1e-6*(exit_time - boost::get_system_time()).total_microseconds() + buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time()) )) return false; //if the sequence id matches: diff --git a/host/include/uhd/transport/bounded_buffer.ipp b/host/include/uhd/transport/bounded_buffer.ipp index 58f78bab4..edc7faa06 100644 --- a/host/include/uhd/transport/bounded_buffer.ipp +++ b/host/include/uhd/transport/bounded_buffer.ipp @@ -19,18 +19,28 @@ #define INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_IPP #include +#include #include #include #include namespace uhd{ namespace transport{ namespace{ /*anon*/ + static UHD_INLINE boost::posix_time::time_duration to_time_dur(double timeout){ + return boost::posix_time::microseconds(long(timeout*1e6)); + } + + static UHD_INLINE double from_time_dur(const boost::posix_time::time_duration &time_dur){ + return 1e-6*time_dur.total_microseconds(); + } + template class bounded_buffer_impl : public bounded_buffer{ public: bounded_buffer_impl(size_t capacity) : _buffer(capacity){ - /* NOP */ + _not_full_fcn = boost::bind(&bounded_buffer_impl::not_full, this); + _not_empty_fcn = boost::bind(&bounded_buffer_impl::not_empty, this); } UHD_INLINE bool push_with_pop_on_full(const elem_type &elem){ @@ -52,17 +62,16 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ UHD_INLINE void push_with_wait(const elem_type &elem){ boost::unique_lock lock(_mutex); - _full_cond.wait(lock, boost::bind(&bounded_buffer_impl::not_full, this)); + _full_cond.wait(lock, _not_full_fcn); _buffer.push_front(elem); lock.unlock(); _empty_cond.notify_one(); } - bool push_with_timed_wait(const elem_type &elem, double timeout){ + UHD_INLINE bool push_with_timed_wait(const elem_type &elem, double timeout){ boost::unique_lock lock(_mutex); if (not _full_cond.timed_wait( - lock, boost::posix_time::microseconds(long(timeout*1e6)), - boost::bind(&bounded_buffer_impl::not_full, this) + lock, to_time_dur(timeout), _not_full_fcn )) return false; _buffer.push_front(elem); lock.unlock(); @@ -72,19 +81,18 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ UHD_INLINE void pop_with_wait(elem_type &elem){ boost::unique_lock lock(_mutex); - _empty_cond.wait(lock, boost::bind(&bounded_buffer_impl::not_empty, this)); - this->pop_back(elem); + _empty_cond.wait(lock, _not_empty_fcn); + elem = this->pop_back(); lock.unlock(); _full_cond.notify_one(); } - bool pop_with_timed_wait(elem_type &elem, double timeout){ + UHD_INLINE bool pop_with_timed_wait(elem_type &elem, double timeout){ boost::unique_lock lock(_mutex); if (not _empty_cond.timed_wait( - lock, boost::posix_time::microseconds(long(timeout*1e6)), - boost::bind(&bounded_buffer_impl::not_empty, this) + lock, to_time_dur(timeout), _not_empty_fcn )) return false; - this->pop_back(elem); + elem = this->pop_back(); lock.unlock(); _full_cond.notify_one(); return true; @@ -92,7 +100,7 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ UHD_INLINE void clear(void){ boost::unique_lock lock(_mutex); - while (not_empty()) _buffer.pop_back(); + while (not_empty()) this->pop_back(); lock.unlock(); _full_cond.notify_one(); } @@ -105,16 +113,19 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/ bool not_full(void) const{return not _buffer.full();} bool not_empty(void) const{return not _buffer.empty();} + boost::function _not_full_fcn, _not_empty_fcn; + /*! * Three part operation to pop an element: * 1) assign elem to the back element * 2) assign the back element to empty * 3) pop the back to move the counter */ - UHD_INLINE void pop_back(elem_type &elem){ - elem = _buffer.back(); + UHD_INLINE elem_type pop_back(void){ + elem_type elem = _buffer.back(); _buffer.back() = elem_type(); _buffer.pop_back(); + return elem; } }; }}} //namespace diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 40fe3fa0f..d84aeefdd 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -39,6 +39,10 @@ namespace asio = boost::asio; //Otherwise, get_recv_buff uses a blocking receive with timeout. //#define USE_ASIO_ASYNC_RECV +//Define this to the the boost async io calls to perform send. +//Otherwise, the commit callback uses a blocking send. +//#define USE_ASIO_ASYNC_SEND + //enough buffering for half a second of samples at full rate on usrp2 static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(4 * 25e6 * 0.5); @@ -55,7 +59,13 @@ static const size_t DEFAULT_NUM_RECV_FRAMES = 32; #else static const size_t DEFAULT_NUM_RECV_FRAMES = MIN_RECV_SOCK_BUFF_SIZE/udp_simple::mtu; #endif +//The non-async send only ever requires a single frame +//because the buffer will be committed before a new get. +#ifdef USE_ASIO_ASYNC_SEND static const size_t DEFAULT_NUM_SEND_FRAMES = 32; +#else +static const size_t DEFAULT_NUM_SEND_FRAMES = MIN_SEND_SOCK_BUFF_SIZE/udp_simple::mtu;; +#endif //a single concurrent thread for io_service seems to be the fastest static const size_t CONCURRENCY_HINT = 1; @@ -143,6 +153,12 @@ public: return get_buff_size(); } + //! handle a recv callback -> push the filled memory into the fifo + UHD_INLINE void handle_recv(void *mem, size_t len){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + _pending_recv_buffs->push_with_wait(boost::asio::buffer(mem, len)); + } + //////////////////////////////////////////////////////////////////// #ifdef USE_ASIO_ASYNC_RECV //////////////////////////////////////////////////////////////////// @@ -162,16 +178,10 @@ public: return managed_recv_buffer::sptr(); } - //! handle a recv callback -> push the filled memory into the fifo - void handle_recv(void *mem, size_t len){ - boost::this_thread::disable_interruption di; //disable because the wait can throw - _pending_recv_buffs->push_with_wait(boost::asio::buffer(mem, len)); - } - //! release a recv buffer -> start an async recv on the buffer void release(void *mem){ _socket->async_receive( - boost::asio::buffer(mem, _recv_frame_size), + boost::asio::buffer(mem, this->get_recv_frame_size()), boost::bind( &udp_zero_copy_asio_impl::handle_recv, shared_from_this(), mem, @@ -185,6 +195,7 @@ public: //////////////////////////////////////////////////////////////////// managed_recv_buffer::sptr get_recv_buff(double timeout){ boost::this_thread::disable_interruption di; //disable because the wait can throw + asio::mutable_buffer buff; //setup timeval for timeout timeval tv; @@ -196,34 +207,30 @@ public: FD_ZERO(&rset); FD_SET(_sock_fd, &rset); - //call select to perform timed wait - if (::select(_sock_fd+1, &rset, NULL, NULL, &tv) <= 0) - return managed_recv_buffer::sptr(); - - //grab an available buffer - asio::mutable_buffer buff; - if (not _pending_recv_buffs->pop_with_timed_wait(buff, timeout)) - return managed_recv_buffer::sptr(); - - //receive and return the buffer - return managed_recv_buffer::make_safe( - asio::buffer( - boost::asio::buffer_cast(buff), - _socket->receive(boost::asio::buffer(buff)) - ), - boost::bind( - &udp_zero_copy_asio_impl::release, - shared_from_this(), - asio::buffer_cast(buff) - ) - ); + //call select to perform timed wait and grab an available buffer with wait + //if the condition is true, call receive and return the managed buffer + if ( + ::select(_sock_fd+1, &rset, NULL, NULL, &tv) > 0 and + _pending_recv_buffs->pop_with_timed_wait(buff, timeout) + ){ + return managed_recv_buffer::make_safe( + asio::buffer( + boost::asio::buffer_cast(buff), + _socket->receive(asio::buffer(buff)) + ), + boost::bind( + &udp_zero_copy_asio_impl::release, + shared_from_this(), + asio::buffer_cast(buff) + ) + ); + } + return managed_recv_buffer::sptr(); } void release(void *mem){ boost::this_thread::disable_interruption di; //disable because the wait can throw - _pending_recv_buffs->push_with_wait( - boost::asio::buffer(mem, this->get_recv_frame_size()) - ); + handle_recv(mem, this->get_recv_frame_size()); } //////////////////////////////////////////////////////////////////// @@ -233,6 +240,12 @@ public: size_t get_num_recv_frames(void) const {return _num_recv_frames;} size_t get_recv_frame_size(void) const {return _recv_frame_size;} + //! handle a send callback -> push the emptied memory into the fifo + UHD_INLINE void handle_send(void *mem){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + _pending_send_buffs->push_with_wait(boost::asio::buffer(mem, this->get_send_frame_size())); + } + //! pop an empty send buffer off of the fifo and bind with the commit callback managed_send_buffer::sptr get_send_buff(double timeout){ boost::this_thread::disable_interruption di; //disable because the wait can throw @@ -249,12 +262,9 @@ public: return managed_send_buffer::sptr(); } - //! handle a send callback -> push the emptied memory into the fifo - void handle_send(void *mem){ - boost::this_thread::disable_interruption di; //disable because the wait can throw - _pending_send_buffs->push_with_wait(boost::asio::buffer(mem, _send_frame_size)); - } - + //////////////////////////////////////////////////////////////////// + #ifdef USE_ASIO_ASYNC_SEND + //////////////////////////////////////////////////////////////////// //! commit a send buffer -> start an async send on the buffer void commit(void *mem, size_t len){ _socket->async_send( @@ -266,6 +276,18 @@ public: ); } + //////////////////////////////////////////////////////////////////// + #else /*USE_ASIO_ASYNC_SEND*/ + //////////////////////////////////////////////////////////////////// + void commit(void *mem, size_t len){ + _socket->send(asio::buffer(mem, len)); + handle_send(mem); + } + + //////////////////////////////////////////////////////////////////// + #endif /*USE_ASIO_ASYNC_SEND*/ + //////////////////////////////////////////////////////////////////// + size_t get_num_send_frames(void) const {return _num_send_frames;} size_t get_send_frame_size(void) const {return _send_frame_size;} @@ -297,6 +319,13 @@ template static void resize_buff_helper( if (name == "recv") min_sock_buff_size = MIN_RECV_SOCK_BUFF_SIZE; if (name == "send") min_sock_buff_size = MIN_SEND_SOCK_BUFF_SIZE; + std::string help_message; + #if defined(UHD_PLATFORM_LINUX) + help_message = str(boost::format( + "Please run: sudo sysctl -w net.core.%smem_max=%d\n" + ) % ((name == "recv")?"r":"w") % min_sock_buff_size); + #endif /*defined(UHD_PLATFORM_LINUX)*/ + //resize the buffer if size was provided if (target_size > 0){ size_t actual_size = udp_trans->resize_buff(target_size); @@ -308,13 +337,10 @@ template static void resize_buff_helper( "Current %s sock buff size: %d bytes" ) % name % actual_size << std::endl; if (actual_size < target_size) uhd::print_warning(str(boost::format( - "The %1% buffer is smaller than the requested size.\n" - "The minimum recommended buffer size is %2% bytes.\n" - "See the transport application notes on buffer resizing.\n" - #if defined(UHD_PLATFORM_LINUX) - "Please run: sudo sysctl -w net.core.rmem_max=%2%\n" - #endif /*defined(UHD_PLATFORM_LINUX)*/ - ) % name % min_sock_buff_size)); + "The %s buffer is smaller than the requested size.\n" + "The minimum recommended buffer size is %d bytes.\n" + "See the transport application notes on buffer resizing.\n%s" + ) % name % min_sock_buff_size % help_message)); } //only enable on platforms that are happy with the large buffer resize -- cgit v1.2.3 From 83fd99cc7badb91a2e8c97048eb9ea694aba22eb Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 8 Oct 2010 13:50:37 -0700 Subject: udp: add docs note about the udp transport --- host/docs/transport.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/host/docs/transport.rst b/host/docs/transport.rst index f247e9e34..432db4bb5 100644 --- a/host/docs/transport.rst +++ b/host/docs/transport.rst @@ -36,6 +36,9 @@ The following parameters can be used to alter the transport's default behavior: * **num_send_frames:** The number of send buffers to allocate * **concurrency_hint:** The number of threads to run the IO service +**Note:** num_send_frames and concurrency_hint will not have an effect +as the asynchronous send implementation is currently disabled. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Resize socket buffers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From 4b5792d2a5c6d101f602b5854fb2e7cfb3acf602 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 8 Oct 2010 14:00:56 -0700 Subject: tvrx: added enabled prop to set and get --- host/lib/usrp/dboard/db_tvrx.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 33507acaa..b1fc2ea76 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -447,6 +447,10 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -467,10 +471,14 @@ void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_GAIN: this->set_gain(val.as(), key.name); return; + case SUBDEV_PROP_FREQ: this->set_freq(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } -- cgit v1.2.3 From 1190bc5c1a7bd0946bc55373eca58ec60a100f63 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 8 Oct 2010 15:52:33 -0700 Subject: usrp: added calls to get subdev and mboard canonical names --- host/include/uhd/usrp/single_usrp.hpp | 16 +++++++++++++--- host/lib/usrp/single_usrp.cpp | 18 +++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index 1b89a3620..bc6943478 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -57,15 +57,21 @@ public: */ virtual device::sptr get_device(void) = 0; + /******************************************************************* + * Mboard methods + ******************************************************************/ /*! * Get a printable name for this usrp. * \return a printable string */ virtual std::string get_pp_string(void) = 0; - /******************************************************************* - * Misc - ******************************************************************/ + /*! + * Get canonical name for this USRP motherboard. + * \return a string representing the name + */ + virtual std::string get_mboard_name(void) = 0; + /*! * Gets the current time in the usrp time registers. * \return a timespec representing current usrp time @@ -113,6 +119,8 @@ public: virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(void) = 0; + virtual std::string get_rx_subdev_name(size_t chan = 0) = 0; + virtual void set_rx_rate(double rate) = 0; virtual double get_rx_rate(void) = 0; @@ -146,6 +154,8 @@ public: virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(void) = 0; + virtual std::string get_tx_subdev_name(size_t chan = 0) = 0; + virtual void set_tx_rate(double rate) = 0; virtual double get_tx_rate(void) = 0; diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index bb4af44b8..08dc3bb1d 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -54,6 +54,9 @@ public: return _dev; } + /******************************************************************* + * Mboard methods + ******************************************************************/ std::string get_pp_string(void){ std::string buff = str(boost::format( "Single USRP:\n" @@ -101,9 +104,10 @@ public: return buff; } - /******************************************************************* - * Misc - ******************************************************************/ + std::string get_mboard_name(void){ + return _mboard()[MBOARD_PROP_NAME].as(); + } + time_spec_t get_time_now(void){ return _mboard()[MBOARD_PROP_TIME_NOW].as(); } @@ -135,6 +139,10 @@ public: return _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as(); } + std::string get_rx_subdev_name(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_NAME].as(); + } + void set_rx_rate(double rate){ _rx_dsp()[DSP_PROP_HOST_RATE] = rate; } @@ -206,6 +214,10 @@ public: return _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as(); } + std::string get_tx_subdev_name(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_NAME].as(); + } + void set_tx_rate(double rate){ _tx_dsp()[DSP_PROP_HOST_RATE] = rate; } -- cgit v1.2.3 From 787d89518d6dace0d8e6584e043eba99f5ff33e1 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 8 Oct 2010 16:04:22 -0700 Subject: uhd: better warning message for failing to set rt priority --- host/lib/utils/thread_priority.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/host/lib/utils/thread_priority.cpp b/host/lib/utils/thread_priority.cpp index c35e5fcb1..f09d1b1d6 100644 --- a/host/lib/utils/thread_priority.cpp +++ b/host/lib/utils/thread_priority.cpp @@ -16,6 +16,8 @@ // #include +#include +#include #include #include @@ -24,7 +26,12 @@ bool uhd::set_thread_priority_safe(float priority, bool realtime){ set_thread_priority(priority, realtime); return true; }catch(const std::exception &e){ - std::cerr << "set_thread_priority: " << e.what() << std::endl; + uhd::print_warning(str(boost::format( + "%s\n" + "Failed to set thread priority %d (%s):\n" + "Performance may be negatively affected.\n" + "See the general application notes.\n" + ) % e.what() % priority % (realtime?"realtime":""))); return false; } } -- cgit v1.2.3 From 58e1ca09772408d5d18ee219146fe57d2045c496 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 8 Oct 2010 16:33:48 -0700 Subject: usrp: comments for set subdev spec in single usrp --- host/include/uhd/usrp/single_usrp.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index bc6943478..3cd263bce 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -116,6 +116,11 @@ public: /******************************************************************* * RX methods ******************************************************************/ + /*! + * Set the RX subdevice specification: + * The subdev spec maps a physical part of a daughter-board to a channel number. + * Set the subdev spec before calling into any methods with a channel number. + */ virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(void) = 0; @@ -151,6 +156,11 @@ public: /******************************************************************* * TX methods ******************************************************************/ + /*! + * Set the TX subdevice specification: + * The subdev spec maps a physical part of a daughter-board to a channel number. + * Set the subdev spec before calling into any methods with a channel number. + */ virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(void) = 0; -- cgit v1.2.3 From 86d6bceb0d37197d0fd8ace19fdedc957c5dfb84 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Fri, 8 Oct 2010 17:03:27 -0700 Subject: Fixed Assertions to better document tuning failures --- host/lib/usrp/dboard/db_dbsrx.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 23cafea53..327cb5f75 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -277,15 +277,17 @@ void dbsrx::set_lo_freq(double target_freq){ } } - //Assert because we failed to find a suitable combination of ref_clock, R and N - UHD_ASSERT_THROW(ref_clock/(1 << m) < 1e6 or ref_clock/(1 << m) > 2.5e6); - UHD_ASSERT_THROW((pfd_freq < dbsrx_pfd_freq_range.min) or (pfd_freq > dbsrx_pfd_freq_range.max)); - UHD_ASSERT_THROW((N < 256) or (N > 32768)); done_loop: + //Assert because we failed to find a suitable combination of ref_clock, R and N + UHD_ASSERT_THROW(ref_clock < 27.0e6 and ref_clock > 0.0); + UHD_ASSERT_THROW(ref_clock/m > 1e6 and ref_clock/m < 2.5e6); + UHD_ASSERT_THROW((pfd_freq > dbsrx_pfd_freq_range.min) and (pfd_freq < dbsrx_pfd_freq_range.max)); + UHD_ASSERT_THROW((N > 256) and (N < 32768)); + if(dbsrx_debug) std::cerr << boost::format( - "DBSRX: choose ref_clock %f and m_divider %d" - ) % (this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX)) % m << std::endl; + "DBSRX: choose ref_clock (current: %f, new: %f) and m_divider %d" + ) % (this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX)) % ref_clock % m << std::endl; //if ref_clock or m divider changed, we need to update the filter settings if (ref_clock != this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX) or m != _max2118_write_regs.m_divider) update_filter_settings = true; -- cgit v1.2.3 From 8aac27fa3e427e0ff09c111127da162356d2bac5 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Fri, 8 Oct 2010 17:54:01 -0700 Subject: TVRX documentation and a bugfix in the cal table. Named the antenna "RX". --- host/docs/dboards.rst | 9 +++++++++ host/lib/usrp/dboard/db_tvrx.cpp | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst index 738a0696d..4ad724c82 100644 --- a/host/docs/dboards.rst +++ b/host/docs/dboards.rst @@ -107,6 +107,15 @@ Transmit Gains: **PGA0**, Range: 0-25dB Recieve Gains: **PGA0**, Range: 0-31.5dB +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +TVRX +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Receive Antennas: RX + +Receive Gains: + * **RF**, Range: -13.3-50.3dB (frequency-dependent) + * **IF**, Range: -1.5-32.5dB + ------------------------------------------------------------------------ Daughterboard Modifications ------------------------------------------------------------------------ diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index b1fc2ea76..10be8d1c3 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -58,7 +58,7 @@ static const bool tvrx_debug = false; static const freq_range_t tvrx_freq_range(50e6, 860e6); -static const prop_names_t tvrx_antennas = list_of(""); //only got one +static const prop_names_t tvrx_antennas = list_of("RX"); static const uhd::dict tvrx_freq_ranges = map_list_of ("VHFLO", freq_range_t(50e6, 158e6)) @@ -73,7 +73,7 @@ static const boost::array vhflo_gains_db = 50.30000, 50.30000}}; static const boost::array vhfhi_gains_db = - {{13.3000, -13.3000, -13.3000, -1.0000, 7.7000, + {{-13.3000, -13.3000, -13.3000, -1.0000, 7.7000, 11.0000, 14.7000, 19.3000, 26.1000, 36.0000, 42.7000, 46.0000, 47.0000, 47.8000, 48.2000, 48.2000, 48.2000}}; @@ -436,7 +436,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_ANTENNA: - val = std::string(""); + val = tvrx_antennas.front(); //there's only one return; case SUBDEV_PROP_ANTENNA_NAMES: -- cgit v1.2.3 From 445a5ca2c7d822ea576eab6aca51cf340df1ca15 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 8 Oct 2010 18:05:58 -0700 Subject: uhd: fix async msg test to reflect new timeout api --- host/examples/test_async_messages.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/host/examples/test_async_messages.cpp b/host/examples/test_async_messages.cpp index 0a5c076ea..e4a996ef5 100644 --- a/host/examples/test_async_messages.cpp +++ b/host/examples/test_async_messages.cpp @@ -26,8 +26,6 @@ namespace po = boost::program_options; -static const size_t async_to_ms = 100; - /*! * Test that no messages are received: * Send a burst of many samples that will fragment internally. @@ -52,7 +50,7 @@ void test_no_async_message(uhd::usrp::single_usrp::sptr sdev){ ); uhd::async_metadata_t async_md; - if (dev->recv_async_msg(async_md, async_to_ms)){ + if (dev->recv_async_msg(async_md)){ std::cout << boost::format( "failed:\n" " Got unexpected event code 0x%x.\n" @@ -88,7 +86,7 @@ void test_underflow_message(uhd::usrp::single_usrp::sptr sdev){ ); uhd::async_metadata_t async_md; - if (not dev->recv_async_msg(async_md, async_to_ms)){ + if (not dev->recv_async_msg(async_md)){ std::cout << boost::format( "failed:\n" " Async message recv timed out.\n" @@ -135,7 +133,7 @@ void test_time_error_message(uhd::usrp::single_usrp::sptr sdev){ ); uhd::async_metadata_t async_md; - if (not dev->recv_async_msg(async_md, async_to_ms)){ + if (not dev->recv_async_msg(async_md)){ std::cout << boost::format( "failed:\n" " Async message recv timed out.\n" -- cgit v1.2.3 From 5898d378522905208bc49b2a4a30a5c04fba639b Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Mon, 11 Oct 2010 16:25:15 -0700 Subject: DBSRX: Fixed some ASSERT statements. --- host/lib/usrp/dboard/db_dbsrx.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 327cb5f75..99137dda3 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -239,7 +239,6 @@ void dbsrx::set_lo_freq(double target_freq){ double actual_freq=0.0, pfd_freq=0.0, ref_clock=0.0; int R=0, N=0, r=0, m=0; bool update_filter_settings = false; - //choose refclock std::vector clock_rates = this->get_iface()->get_clock_rates(dboard_iface::UNIT_RX); BOOST_FOREACH(ref_clock, std::reversed(std::sorted(clock_rates))){ @@ -251,7 +250,7 @@ void dbsrx::set_lo_freq(double target_freq){ if(dbsrx_debug) std::cerr << boost::format( "DBSRX: trying ref_clock %f and m_divider %d" - ) % (this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX)) % m << std::endl; + ) % (ref_clock) % m << std::endl; if (m >= 32) continue; @@ -280,10 +279,10 @@ void dbsrx::set_lo_freq(double target_freq){ done_loop: //Assert because we failed to find a suitable combination of ref_clock, R and N - UHD_ASSERT_THROW(ref_clock < 27.0e6 and ref_clock > 0.0); - UHD_ASSERT_THROW(ref_clock/m > 1e6 and ref_clock/m < 2.5e6); - UHD_ASSERT_THROW((pfd_freq > dbsrx_pfd_freq_range.min) and (pfd_freq < dbsrx_pfd_freq_range.max)); - UHD_ASSERT_THROW((N > 256) and (N < 32768)); + UHD_ASSERT_THROW(ref_clock <= 27.0e6 and ref_clock >= 0.0); + UHD_ASSERT_THROW(ref_clock/m >= 1e6 and ref_clock/m <= 2.5e6); + UHD_ASSERT_THROW((pfd_freq >= dbsrx_pfd_freq_range.min) and (pfd_freq <= dbsrx_pfd_freq_range.max)); + UHD_ASSERT_THROW((N >= 256) and (N <= 32768)); if(dbsrx_debug) std::cerr << boost::format( "DBSRX: choose ref_clock (current: %f, new: %f) and m_divider %d" @@ -351,7 +350,7 @@ void dbsrx::set_lo_freq(double target_freq){ "DBSRX: Tuning exceeded vco range, _max2118_write_regs.osc_band == %d\n" ) % int(_max2118_write_regs.osc_band)) ); - UHD_ASSERT_THROW(_max2118_read_regs.adc == 0); + UHD_ASSERT_THROW(_max2118_read_regs.adc != 0); //just to cause a throw } if (_max2118_write_regs.osc_band <= 0) break; _max2118_write_regs.osc_band -= 1; @@ -365,7 +364,7 @@ void dbsrx::set_lo_freq(double target_freq){ "DBSRX: Tuning exceeded vco range, _max2118_write_regs.osc_band == %d\n" ) % int(_max2118_write_regs.osc_band)) ); - UHD_ASSERT_THROW(_max2118_read_regs.adc == 0); + UHD_ASSERT_THROW(_max2118_read_regs.adc != 7); //just to cause a throw } if (_max2118_write_regs.osc_band >= 7) break; _max2118_write_regs.osc_band += 1; @@ -403,6 +402,7 @@ void dbsrx::set_lo_freq(double target_freq){ << boost::format(" Ref Freq=%fMHz\n") % (ref_clock/1e6) << boost::format(" Target Freq=%fMHz\n") % (target_freq/1e6) << boost::format(" Actual Freq=%fMHz\n") % (_lo_freq/1e6) + << boost::format(" VCO Freq=%fMHz\n") % (vco_freq/1e6) << std::endl; if (update_filter_settings) set_bandwidth(_bandwidth); -- cgit v1.2.3 From f28c07db44694e3cce96502183c7570a386987f5 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Mon, 11 Oct 2010 18:21:11 -0700 Subject: UHD: Brought out set_rx_bandwidth for dboards with programmable rx filters. --- host/include/uhd/usrp/mimo_usrp.hpp | 2 ++ host/include/uhd/usrp/simple_usrp.hpp | 2 ++ host/include/uhd/usrp/single_usrp.hpp | 2 ++ host/lib/usrp/mimo_usrp.cpp | 4 ++++ host/lib/usrp/simple_usrp.cpp | 4 ++++ host/lib/usrp/single_usrp.cpp | 4 ++++ 6 files changed, 18 insertions(+) diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index 10a404059..ed40addb3 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -148,6 +148,8 @@ public: * \return the rssi in dB */ virtual float read_rssi(size_t chan) = 0; + + virtual void set_rx_bandwidth(float bandwidth, size_t chan) = 0; /******************************************************************* * TX methods diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index 6149f739c..6f3597ed7 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -139,6 +139,8 @@ public: virtual float read_rssi(void) = 0; virtual dboard_iface::sptr get_rx_dboard_iface(void) = 0; + + virtual void set_rx_bandwidth(float) = 0; /******************************************************************* * TX methods diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index 3cd263bce..fa6498d13 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -152,6 +152,8 @@ public: virtual float read_rssi(size_t chan = 0) = 0; virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan = 0) = 0; + + virtual void set_rx_bandwidth(float bandwidth, size_t chan = 0) = 0; /******************************************************************* * TX methods diff --git a/host/lib/usrp/mimo_usrp.cpp b/host/lib/usrp/mimo_usrp.cpp index 9331c7fbb..5437607a6 100644 --- a/host/lib/usrp/mimo_usrp.cpp +++ b/host/lib/usrp/mimo_usrp.cpp @@ -225,6 +225,10 @@ public: float read_rssi(size_t chan){ return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); } + + void set_rx_bandwidth(float bandwidth, size_t chan){ + _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } /******************************************************************* * TX methods diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp index b89b76eed..b4f34287b 100644 --- a/host/lib/usrp/simple_usrp.cpp +++ b/host/lib/usrp/simple_usrp.cpp @@ -136,6 +136,10 @@ public: dboard_iface::sptr get_rx_dboard_iface(void){ return _sdev->get_rx_dboard_iface(); } + + void set_rx_bandwidth(float bandwidth) { + return _sdev->set_rx_bandwidth(bandwidth); + } /******************************************************************* * TX methods diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index 08dc3bb1d..7d053535e 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -202,6 +202,10 @@ public: dboard_iface::sptr get_rx_dboard_iface(size_t chan){ return _rx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); } + + void set_rx_bandwidth(float bandwidth, size_t chan) { + _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } /******************************************************************* * TX methods -- cgit v1.2.3 From 3b36c206e56b415974ed83a52a652b65f9de1add Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Mon, 11 Oct 2010 18:37:04 -0700 Subject: UHD: reordered MIMO set_rx_bandwidth arg order --- host/include/uhd/usrp/mimo_usrp.hpp | 2 +- host/lib/usrp/mimo_usrp.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index ed40addb3..bdd84a148 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -149,7 +149,7 @@ public: */ virtual float read_rssi(size_t chan) = 0; - virtual void set_rx_bandwidth(float bandwidth, size_t chan) = 0; + virtual void set_rx_bandwidth(size_t chan, float bandwidth) = 0; /******************************************************************* * TX methods diff --git a/host/lib/usrp/mimo_usrp.cpp b/host/lib/usrp/mimo_usrp.cpp index 5437607a6..08618c288 100644 --- a/host/lib/usrp/mimo_usrp.cpp +++ b/host/lib/usrp/mimo_usrp.cpp @@ -226,7 +226,7 @@ public: return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); } - void set_rx_bandwidth(float bandwidth, size_t chan){ + void set_rx_bandwidth(size_t chan, float bandwidth){ _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; } -- cgit v1.2.3 From 8c0ca70d24f87ccc617ce79f2eedcc272a895204 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Tue, 12 Oct 2010 12:57:30 -0700 Subject: Enhance XCVR2450 to clip for high/low band tuning and add bandwidth property --- host/docs/dboards.rst | 11 ++- host/lib/usrp/dboard/db_xcvr2450.cpp | 147 ++++++++++++++++++++++++++++++++++- 2 files changed, 149 insertions(+), 9 deletions(-) diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst index 4ad724c82..f3d7d95b0 100644 --- a/host/docs/dboards.rst +++ b/host/docs/dboards.rst @@ -69,21 +69,20 @@ Recieve Gains: **PGA0**, Range: 0-70dB (except RFX400 range is 0-45dB) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ XCVR 2450 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The XCVR2450 has a non-contiguous tuning range consisting of a high band and a low band. -The high band consists of frequencies between...TODO +The XCVR2450 has a non-contiguous tuning range consisting of a +high band (4.9-6.0GHz) and a low band (2.4-2.5GHz). Transmit Antennas: **J1** or **J2** Receive Antennas: **J1** or **J2** -When using the XCVR2450 in full-duplex mode, -the user must set the receive antenna and the transmit antenna to be different; -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. +The XCVR2450 does not support full-duplex mode, attempting to operate +in full-duplex will result in transmit-only operation. + Transmit Gains: * **VGA**, Range: 0-30dB * **BB**, Range: 0-5dB diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 0ee133f3d..314c85a69 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,7 @@ using namespace boost::assign; static const bool xcvr2450_debug = false; static const freq_range_t xcvr_freq_range(2.4e9, 6.0e9); +static const freq_range_t xcvr_freq_band_seperation(2.5e9, 4.9e9); static const prop_names_t xcvr_antennas = list_of("J1")("J2"); @@ -100,6 +102,7 @@ public: private: double _lo_freq; + float _rx_bandwidth, _tx_bandwidth; uhd::dict _tx_gains, _rx_gains; std::string _tx_ant, _rx_ant; int _ad9515div; @@ -110,6 +113,8 @@ private: void set_rx_ant(const std::string &ant); void set_tx_gain(float gain, const std::string &name); void set_rx_gain(float gain, const std::string &name); + void set_rx_bandwidth(float bandwidth); + void set_tx_bandwidth(float bandwidth); void update_atr(void); void spi_reset(void); @@ -176,6 +181,9 @@ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){ spi_reset(); //prepare the spi + _rx_bandwidth = 9.5e6; + _tx_bandwidth = 12.0e6; + //setup the misc max2829 registers _max2829_regs.mimo_select = max2829_regs_t::MIMO_SELECT_MIMO; _max2829_regs.band_sel_mimo = max2829_regs_t::BAND_SEL_MIMO_MIMO; @@ -183,7 +191,7 @@ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){ _max2829_regs.rssi_high_bw = max2829_regs_t::RSSI_HIGH_BW_6MHZ; _max2829_regs.tx_lpf_coarse_adj = max2829_regs_t::TX_LPF_COARSE_ADJ_12MHZ; _max2829_regs.rx_lpf_coarse_adj = max2829_regs_t::RX_LPF_COARSE_ADJ_9_5MHZ; - _max2829_regs.rx_lpf_fine_adj = max2829_regs_t::RX_LPF_FINE_ADJ_95; + _max2829_regs.rx_lpf_fine_adj = max2829_regs_t::RX_LPF_FINE_ADJ_100; _max2829_regs.rx_vga_gain_spi = max2829_regs_t::RX_VGA_GAIN_SPI_SPI; _max2829_regs.rssi_output_range = max2829_regs_t::RSSI_OUTPUT_RANGE_HIGH; _max2829_regs.rssi_op_mode = max2829_regs_t::RSSI_OP_MODE_ENABLED; @@ -244,15 +252,24 @@ void xcvr2450::update_atr(void){ this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, POWER_UP_RXIO | RX_DIS_RXIO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, POWER_UP_RXIO | RX_ENB_RXIO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, POWER_UP_RXIO | RX_DIS_RXIO); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP_RXIO | RX_ENB_RXIO); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP_RXIO | RX_DIS_RXIO); } /*********************************************************************** * Tuning **********************************************************************/ void xcvr2450::set_lo_freq(double target_freq){ + //clip for highband and lowband + if((target_freq > xcvr_freq_band_seperation.min) and (target_freq < xcvr_freq_band_seperation.max)){ + if(target_freq - xcvr_freq_band_seperation.min < xcvr_freq_band_seperation.max - target_freq){ + target_freq = xcvr_freq_band_seperation.min; + }else{ + target_freq = xcvr_freq_band_seperation.max; + } + } + + //clip for max and min target_freq = std::clip(target_freq, xcvr_freq_range.min, xcvr_freq_range.max); - //TODO: clip for highband and lowband //variables used in the calculation below double scaler = xcvr2450::is_highband(target_freq)? (4.0/5.0) : (4.0/3.0); @@ -434,6 +451,114 @@ void xcvr2450::set_rx_gain(float gain, const std::string &name){ _rx_gains[name] = gain; } + +/*********************************************************************** + * Bandwidth Handling + **********************************************************************/ +static max2829_regs_t::tx_lpf_coarse_adj_t bandwidth_to_tx_lpf_coarse_reg(float &bandwidth){ + int reg = std::clip(boost::math::iround((bandwidth-6.0e6)/6.0e6), 1, 3); + + switch(reg){ + case 1: // bandwidth < 15MHz + bandwidth = 12e6; + return max2829_regs_t::TX_LPF_COARSE_ADJ_12MHZ; + case 2: // 15MHz < bandwidth < 21MHz + bandwidth = 18e6; + return max2829_regs_t::TX_LPF_COARSE_ADJ_18MHZ; + case 3: // bandwidth > 21MHz + bandwidth = 24e6; + return max2829_regs_t::TX_LPF_COARSE_ADJ_24MHZ; + } + UHD_THROW_INVALID_CODE_PATH(); +} + +static max2829_regs_t::rx_lpf_fine_adj_t bandwidth_to_rx_lpf_fine_reg(float &bandwidth, float requested_bandwidth){ + int reg = std::clip(boost::math::iround((requested_bandwidth/bandwidth)/0.05), 18, 22); + + switch(reg){ + case 18: // requested_bandwidth < 92.5% + bandwidth = 0.9 * bandwidth; + return max2829_regs_t::RX_LPF_FINE_ADJ_90; + case 19: // 92.5% < requested_bandwidth < 97.5% + bandwidth = 0.95 * bandwidth; + return max2829_regs_t::RX_LPF_FINE_ADJ_95; + case 20: // 97.5% < requested_bandwidth < 102.5% + bandwidth = 1.0 * bandwidth; + return max2829_regs_t::RX_LPF_FINE_ADJ_100; + case 21: // 102.5% < requested_bandwidth < 107.5% + bandwidth = 1.05 * bandwidth; + return max2829_regs_t::RX_LPF_FINE_ADJ_105; + case 22: // 107.5% < requested_bandwidth + bandwidth = 1.1 * bandwidth; + return max2829_regs_t::RX_LPF_FINE_ADJ_110; + } + UHD_THROW_INVALID_CODE_PATH(); +} + +static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(float &bandwidth){ + int reg = std::clip(boost::math::iround((bandwidth-7.0e6)/1.0e6), 0, 11); + + switch(reg){ + case 0: // bandwidth < 7.5MHz + case 1: // 7.5MHz < bandwidth < 8.5MHz + bandwidth = 7.5e6; + return max2829_regs_t::RX_LPF_COARSE_ADJ_7_5MHZ; + case 2: // 8.5MHz < bandwidth < 9.5MHz + case 3: // 9.5MHz < bandwidth < 10.5MHz + case 4: // 10.5MHz < bandwidth < 11.5MHz + bandwidth = 9.5e6; + return max2829_regs_t::RX_LPF_COARSE_ADJ_9_5MHZ; + case 5: // 11.5MHz < bandwidth < 12.5MHz + case 6: // 12.5MHz < bandwidth < 13.5MHz + case 7: // 13.5MHz < bandwidth < 14.5MHz + case 8: // 14.5MHz < bandwidth < 15.5MHz + bandwidth = 14e6; + return max2829_regs_t::RX_LPF_COARSE_ADJ_14MHZ; + case 9: // 15.5MHz < bandwidth < 16.5MHz + case 10: // 16.5MHz < bandwidth < 17.5MHz + case 11: // 17.5MHz < bandwidth + bandwidth = 18e6; + return max2829_regs_t::RX_LPF_COARSE_ADJ_18MHZ; + } + UHD_THROW_INVALID_CODE_PATH(); +} + +void xcvr2450::set_rx_bandwidth(float bandwidth){ + float requested_bandwidth = bandwidth; + + //compute coarse low pass cutoff frequency setting + _max2829_regs.rx_lpf_coarse_adj = bandwidth_to_rx_lpf_coarse_reg(bandwidth); + + //compute fine low pass cutoff frequency setting + _max2829_regs.rx_lpf_fine_adj = bandwidth_to_rx_lpf_fine_reg(bandwidth, requested_bandwidth); + + //shadow bandwidth setting + _rx_bandwidth = bandwidth; + + //update register + send_reg(0x7); + + if (xcvr2450_debug) std::cerr << boost::format( + "XCVR2450 RX Bandwidth (lp_fc): %f Hz, coarse reg: %d, fine reg: %d" + ) % _rx_bandwidth % (int(_max2829_regs.rx_lpf_coarse_adj)) % (int(_max2829_regs.rx_lpf_fine_adj)) << std::endl; +} + +void xcvr2450::set_tx_bandwidth(float bandwidth){ + //compute coarse low pass cutoff frequency setting + _max2829_regs.tx_lpf_coarse_adj = bandwidth_to_tx_lpf_coarse_reg(bandwidth); + + //shadow bandwidth setting + _tx_bandwidth = bandwidth; + + //update register + send_reg(0x7); + + if (xcvr2450_debug) std::cerr << boost::format( + "XCVR2450 TX Bandwidth (lp_fc): %f Hz, coarse reg: %d" + ) % _tx_bandwidth % (int(_max2829_regs.tx_lpf_coarse_adj)) << std::endl; +} + + /*********************************************************************** * RX Get and Set **********************************************************************/ @@ -500,6 +625,10 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){ val = this->get_rssi(); return; + case SUBDEV_PROP_BANDWIDTH: + val = _rx_bandwidth; + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -522,6 +651,10 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_rx_ant(val.as()); return; + case SUBDEV_PROP_BANDWIDTH: + this->set_rx_bandwidth(val.as()); + return; + case SUBDEV_PROP_ENABLED: return; //always enabled @@ -591,6 +724,10 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){ val = this->get_locked(); return; + case SUBDEV_PROP_BANDWIDTH: + val = _tx_bandwidth; + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -609,6 +746,10 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ this->set_tx_gain(val.as(), key.name); return; + case SUBDEV_PROP_BANDWIDTH: + this->set_tx_bandwidth(val.as()); + return; + case SUBDEV_PROP_ANTENNA: this->set_tx_ant(val.as()); return; -- cgit v1.2.3 From af1e0c122be189d75651dc52ae0847c0a5f1b4d7 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Tue, 12 Oct 2010 14:07:08 -0700 Subject: Added documentation of daughterboard filter bandwidths --- host/docs/dboards.rst | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst index f3d7d95b0..080117651 100644 --- a/host/docs/dboards.rst +++ b/host/docs/dboards.rst @@ -49,10 +49,12 @@ Receive Antennas: **J3** The board has no user selectable antenna setting -Recieve Gains: +Receive Gains: **GC1**, Range: 0-56dB **GC2**, Range: 0-24dB +Low-Pass Filter Bandwidth (Hz): 4M-33M + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ RFX Series ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +66,7 @@ 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. -Recieve Gains: **PGA0**, Range: 0-70dB (except RFX400 range is 0-45dB) +Receive Gains: **PGA0**, Range: 0-70dB (except RFX400 range is 0-45dB) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ XCVR 2450 @@ -91,6 +93,10 @@ Receive Gains: * **LNA**, Range: 0-30.5dB * **VGA**, Range: 0-62dB +Low-Pass Filter Bandwidths (Hz): + * **RX**: 7.5M, 9.5M, 14M, 18M; (each +-0, 5, or 10%) + * **TX**: 12M, 18M, 24M + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ WBX Series ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +110,11 @@ the receive antenna will always be set to RX2, regardless of the settings. Transmit Gains: **PGA0**, Range: 0-25dB -Recieve Gains: **PGA0**, Range: 0-31.5dB +Receive Gains: **PGA0**, Range: 0-31.5dB + +Low-Pass Filter Bandwidths (Hz): + * **RX**: 20M (Fixed) + * **TX**: 20M (Fixed) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ TVRX @@ -115,6 +125,8 @@ Receive Gains: * **RF**, Range: -13.3-50.3dB (frequency-dependent) * **IF**, Range: -1.5-32.5dB +Bandpass Filter Bandwidth: 6MHz + ------------------------------------------------------------------------ Daughterboard Modifications ------------------------------------------------------------------------ -- cgit v1.2.3 From c830a0d2c491fb61c2b401db94ed0a147bca4a24 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 13 Oct 2010 23:00:20 +0000 Subject: USRP-E: updated the loopback tester for length checking. Checks lengths by pushing them into a circular buffer and popping them out. Protected by mutex so it doesn't go chewing on itself. --- host/utils/usrp-e-loopback.c | 47 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/host/utils/usrp-e-loopback.c b/host/utils/usrp-e-loopback.c index f400fe0be..454d81ba7 100644 --- a/host/utils/usrp-e-loopback.c +++ b/host/utils/usrp-e-loopback.c @@ -8,7 +8,7 @@ #include #include -// max length #define PKT_DATA_LENGTH 1016 +#define MAX_PACKET_SIZE 1016 static int packet_data_length; static int error; @@ -19,6 +19,30 @@ struct pkt { short data[]; }; +static int length_array[2048]; +static int length_array_tail = 0; +static int length_array_head = 0; + +pthread_mutex_t length_array_mutex; //gotta lock the index to keep it from getting hosed + +//yes this is a circular buffer that does not check empty +//no i don't want to hear about it +void push_length_array(int length) { + pthread_mutex_lock(&length_array_mutex); + if(length_array_tail > 2047) length_array_tail = 0; + length_array[length_array_tail++] = length; + pthread_mutex_unlock(&length_array_mutex); +} + +int pop_length_array(void) { + int retval; + pthread_mutex_lock(&length_array_mutex); + if(length_array_head > 2047) length_array_head = 0; + retval = length_array[length_array_head++]; + pthread_mutex_unlock(&length_array_mutex); + return retval; +} + static int fp; static int calc_checksum(struct pkt *p) @@ -29,10 +53,10 @@ static int calc_checksum(struct pkt *p) sum = 0; for (i=0; i < p->len; i++) - sum += p->data[i]; + sum ^= p->data[i]; - sum += p->seq_num; - sum += p->len; + sum ^= p->seq_num; + sum ^= p->len; return sum; } @@ -44,6 +68,7 @@ static void *read_thread(void *threadid) struct pkt *p; unsigned long bytes_transfered, elapsed_seconds; struct timeval start_time, finish_time; + int expected_count; printf("Greetings from the reading thread!\n"); @@ -78,6 +103,11 @@ static void *read_thread(void *threadid) error = 1; } + expected_count = pop_length_array()*2+12; + if(cnt != expected_count) { + printf("Received %d bytes, expected %d\n", cnt, expected_count); + } + prev_seq_num = p->seq_num; if (calc_checksum(p) != p->checksum) { @@ -131,7 +161,9 @@ static void *write_thread(void *threadid) if (packet_data_length > 0) p->len = packet_data_length; else - p->len = (random() & 0x1ff) + (1004 - 512); + p->len = (random()<<1 & 0x1ff) + (1004 - 512); + + push_length_array(p->len); p->checksum = calc_checksum(p); @@ -146,6 +178,7 @@ static void *write_thread(void *threadid) int main(int argc, char *argv[]) { pthread_t tx, rx; + pthread_mutex_init(&length_array_mutex, 0); long int t; struct sched_param s = { .sched_priority = 1 @@ -159,6 +192,10 @@ int main(int argc, char *argv[]) } packet_data_length = atoi(argv[1]); + if(packet_data_length > MAX_PACKET_SIZE) { + printf("Packet size must be smaller than %i\n", MAX_PACKET_SIZE); + exit(-1); + } fp = open("/dev/usrp_e0", O_RDWR); printf("fp = %d\n", fp); -- cgit v1.2.3 From 0582d9f5bc4793aa0ce609933e8cc108255903e8 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Thu, 14 Oct 2010 16:52:48 +0000 Subject: USRP-E: brought loopback test updates in from usrp_e branch. --- host/utils/usrp-e-loopback.c | 47 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/host/utils/usrp-e-loopback.c b/host/utils/usrp-e-loopback.c index f400fe0be..454d81ba7 100644 --- a/host/utils/usrp-e-loopback.c +++ b/host/utils/usrp-e-loopback.c @@ -8,7 +8,7 @@ #include #include -// max length #define PKT_DATA_LENGTH 1016 +#define MAX_PACKET_SIZE 1016 static int packet_data_length; static int error; @@ -19,6 +19,30 @@ struct pkt { short data[]; }; +static int length_array[2048]; +static int length_array_tail = 0; +static int length_array_head = 0; + +pthread_mutex_t length_array_mutex; //gotta lock the index to keep it from getting hosed + +//yes this is a circular buffer that does not check empty +//no i don't want to hear about it +void push_length_array(int length) { + pthread_mutex_lock(&length_array_mutex); + if(length_array_tail > 2047) length_array_tail = 0; + length_array[length_array_tail++] = length; + pthread_mutex_unlock(&length_array_mutex); +} + +int pop_length_array(void) { + int retval; + pthread_mutex_lock(&length_array_mutex); + if(length_array_head > 2047) length_array_head = 0; + retval = length_array[length_array_head++]; + pthread_mutex_unlock(&length_array_mutex); + return retval; +} + static int fp; static int calc_checksum(struct pkt *p) @@ -29,10 +53,10 @@ static int calc_checksum(struct pkt *p) sum = 0; for (i=0; i < p->len; i++) - sum += p->data[i]; + sum ^= p->data[i]; - sum += p->seq_num; - sum += p->len; + sum ^= p->seq_num; + sum ^= p->len; return sum; } @@ -44,6 +68,7 @@ static void *read_thread(void *threadid) struct pkt *p; unsigned long bytes_transfered, elapsed_seconds; struct timeval start_time, finish_time; + int expected_count; printf("Greetings from the reading thread!\n"); @@ -78,6 +103,11 @@ static void *read_thread(void *threadid) error = 1; } + expected_count = pop_length_array()*2+12; + if(cnt != expected_count) { + printf("Received %d bytes, expected %d\n", cnt, expected_count); + } + prev_seq_num = p->seq_num; if (calc_checksum(p) != p->checksum) { @@ -131,7 +161,9 @@ static void *write_thread(void *threadid) if (packet_data_length > 0) p->len = packet_data_length; else - p->len = (random() & 0x1ff) + (1004 - 512); + p->len = (random()<<1 & 0x1ff) + (1004 - 512); + + push_length_array(p->len); p->checksum = calc_checksum(p); @@ -146,6 +178,7 @@ static void *write_thread(void *threadid) int main(int argc, char *argv[]) { pthread_t tx, rx; + pthread_mutex_init(&length_array_mutex, 0); long int t; struct sched_param s = { .sched_priority = 1 @@ -159,6 +192,10 @@ int main(int argc, char *argv[]) } packet_data_length = atoi(argv[1]); + if(packet_data_length > MAX_PACKET_SIZE) { + printf("Packet size must be smaller than %i\n", MAX_PACKET_SIZE); + exit(-1); + } fp = open("/dev/usrp_e0", O_RDWR); printf("fp = %d\n", fp); -- cgit v1.2.3 From 39ca8e25fc7f9b3170cb517b72640a62b15d253f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 14 Oct 2010 10:06:34 -0700 Subject: uhd: fix docs on boost version, also add additional version string for 1.44 --- host/CMakeLists.txt | 2 +- host/docs/build.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 566bfd538..a60eed0a5 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -84,7 +84,7 @@ IF(UNIX AND EXISTS "/usr/lib64") LIST(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix ENDIF(UNIX AND EXISTS "/usr/lib64") -SET(Boost_ADDITIONAL_VERSIONS "1.42.0" "1.42" "1.43.0" "1.43") +SET(Boost_ADDITIONAL_VERSIONS "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44") FIND_PACKAGE(Boost ${BOOST_MIN_VERSION} REQUIRED COMPONENTS date_time filesystem diff --git a/host/docs/build.rst b/host/docs/build.rst index 9cf37db4a..a41ce8331 100644 --- a/host/docs/build.rst +++ b/host/docs/build.rst @@ -47,7 +47,7 @@ CMake Boost ^^^^^^^^^^^^^^^^ * **Purpose:** C++ library -* **Version:** at least 3.6 unix, at least 4.0 windows +* **Version:** at least 1.36 unix, at least 1.40 windows * **Usage:** build time + run time (required) * **Download URL:** http://www.boost.org/users/download/ * **Download URL (windows installer):** http://www.boostpro.com/download -- cgit v1.2.3 From 9348c2764dbbdf01e34a3ec7b5c8e74964b355e0 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 14 Oct 2010 21:41:14 -0400 Subject: usrp_e: back out dynamic send/recv samples calculation. --- host/lib/usrp/usrp_e/io_impl.cpp | 6 +++++- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index 406b7269f..d89a7db07 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -37,7 +37,7 @@ zero_copy_if::sptr usrp_e_make_mmap_zero_copy(usrp_e_iface::sptr iface); **********************************************************************/ static const size_t tx_async_report_sid = 1; static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; -static const bool recv_debug = true; +static const bool recv_debug = false; /*********************************************************************** * io impl details (internal to this file) @@ -205,6 +205,7 @@ bool get_send_buffs( return buffs[0].get() != NULL; } +#if 0 size_t usrp_e_impl::get_max_send_samps_per_packet(void) const{ static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) @@ -213,6 +214,7 @@ size_t usrp_e_impl::get_max_send_samps_per_packet(void) const{ size_t bpp = _io_impl->data_xport->get_send_frame_size() - hdr_size; return bpp/_send_otw_type.get_sample_size(); } +#endif size_t usrp_e_impl::send( const std::vector &buffs, size_t num_samps, @@ -234,6 +236,7 @@ size_t usrp_e_impl::send( /*********************************************************************** * Data Recv **********************************************************************/ +#if 0 size_t usrp_e_impl::get_max_recv_samps_per_packet(void) const{ static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) @@ -243,6 +246,7 @@ size_t usrp_e_impl::get_max_recv_samps_per_packet(void) const{ size_t bpp = _io_impl->data_xport->get_recv_frame_size() - hdr_size; return bpp/_recv_otw_type.get_sample_size(); } +#endif size_t usrp_e_impl::recv( const std::vector &buffs, size_t num_samps, diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 95d80fed5..9799cd645 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -86,8 +86,13 @@ public: size_t send(const std::vector &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t, double); size_t recv(const std::vector &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, double); bool recv_async_msg(uhd::async_metadata_t &, double); +#if 0 size_t get_max_send_samps_per_packet(void) const; size_t get_max_recv_samps_per_packet(void) const; +#else + size_t get_max_send_samps_per_packet(void) const{return 503;} + size_t get_max_recv_samps_per_packet(void) const{return 503;} +#endif private: //interface to ioctls and file descriptor -- cgit v1.2.3 From 6b203950d9583ab882628311402e26cf40838aa0 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 14 Oct 2010 21:42:10 -0400 Subject: usrp_e: Disable debug. --- host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp index bc18c490b..274bb043e 100644 --- a/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_mmap_zero_copy.cpp @@ -29,8 +29,8 @@ using namespace uhd; using namespace uhd::transport; -static const bool fp_verbose = true; //fast-path verbose -static const bool sp_verbose = true; //slow-path verbose +static const bool fp_verbose = false; //fast-path verbose +static const bool sp_verbose = false; //slow-path verbose static const size_t poll_breakout = 10; //how many poll timeouts constitute a full timeout /*********************************************************************** -- cgit v1.2.3 From 816a07bee54e998e4fb25beeb44b9ac3888189bf Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 16 Oct 2010 01:18:47 -0700 Subject: usrp2: make the booty smaller than the number of recv frames This may fix some of our woes when the host cannot keep up. That is, with a smaller booty, the managed buffers will get freed up and the call to get buffer will never block waiting for a buffer to become free. This has several side effects: 1) Overflows are more likely to occur in the pirate thread. Pirate-based overflows will overwrite old packets, whereas socket-based overflows will discard newer incoming packets. 2) The pirate thread will continue to pull in async packets rather than loosing them in a socket-based overflow. --- host/lib/usrp/usrp2/io_impl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index eba704059..bbe9c273f 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -46,7 +46,7 @@ struct usrp2_impl::io_impl{ io_impl(size_t num_frames, size_t width): packet_handler_recv_state(width), - recv_pirate_booty(alignment_buffer_type::make(num_frames, width)), + recv_pirate_booty(alignment_buffer_type::make(num_frames-3, width)), async_msg_fifo(bounded_buffer::make(100/*messages deep*/)) { /* NOP */ -- cgit v1.2.3 From c861f98c55c38250a0d87ed91f5c19b10192a4b8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 16 Oct 2010 18:07:10 -0700 Subject: usrp: created multi-usrp (multi chan, multi board), and deprecated mimo-usrp --- host/include/uhd/usrp/CMakeLists.txt | 1 + host/include/uhd/usrp/mimo_usrp.hpp | 4 +- host/include/uhd/usrp/multi_usrp.hpp | 259 +++++++++++++++++++++ host/include/uhd/usrp/single_usrp.hpp | 6 +- host/lib/usrp/CMakeLists.txt | 1 + host/lib/usrp/mimo_usrp.cpp | 6 + host/lib/usrp/multi_usrp.cpp | 422 ++++++++++++++++++++++++++++++++++ host/lib/usrp/single_usrp.cpp | 4 - 8 files changed, 694 insertions(+), 9 deletions(-) create mode 100644 host/include/uhd/usrp/multi_usrp.hpp create mode 100644 host/lib/usrp/multi_usrp.cpp diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index f973e401a..abddf3951 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -42,6 +42,7 @@ INSTALL(FILES simple_usrp.hpp single_usrp.hpp mimo_usrp.hpp + multi_usrp.hpp DESTINATION ${INCLUDE_DIR}/uhd/usrp ) diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index bdd84a148..7c250b2fd 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -32,12 +32,12 @@ namespace uhd{ namespace usrp{ /*! - * The MIMO USRP device class: + * The MIMO USRP device class (DEPRECATED): * A mimo usrp facilitates ease-of-use for multi-usrp scenarios. * The wrapper provides convenience functions to control the group * of underlying devices as if they consisted of a single device. */ -class UHD_API mimo_usrp : boost::noncopyable{ +class UHD_API UHD_DEPRECATED mimo_usrp : boost::noncopyable{ public: typedef boost::shared_ptr sptr; diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp new file mode 100644 index 000000000..65c7e9044 --- /dev/null +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -0,0 +1,259 @@ +// +// 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_UHD_USRP_MULTI_USRP_HPP +#define INCLUDED_UHD_USRP_MULTI_USRP_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace uhd{ namespace usrp{ + +/*! + * The multi-USRP device class: + * A multi-USRP facilitates ease-of-use for multiple USRP scenarios. + * The wrapper provides convenience functions to control the group + * of underlying devices as if they consisted of a single device. + * + * A few notes about a multi-USRP configuration: + * - All boards share a common RX sample rate + * - All boards share a common TX sample rate + * - All boards share a common RX subdevice specification size + * - All boards share a common TX subdevice specification size + * - All boards must have synchronized times (see the set_time_*() calls) + * + * Example to setup channel mapping: + *
+ *
+ * //create a multi_usrp with two boards in the configuration
+ * device_addr_t dev_addr;
+ * dev_addr["addr"] = "192.168.10.2 192.168.10.3";
+ * multi_usrp::sptr dev = multi_usrp::make(dev_addr);
+ *
+ * //set the board on 10.2 to use the A RX subdevice (RX channel 0)
+ * dev->set_rx_subdev_spec(":A", 0);
+ *
+ * //set the board on 10.3 to use the B RX subdevice (RX channel 1)
+ * dev->set_rx_subdev_spec(":B", 1);
+ *
+ * //set both boards to use the AB TX subdevice (TX channels 0 and 1)
+ * dev->set_tx_subdev_spec(":AB", multi_usrp::ALL_MBOARDS);
+ *
+ * //now that all the channels are mapped, continue with configuration...
+ *
+ * 
+ */ +class UHD_API multi_usrp : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + //! A wildcard motherboard index + static const size_t ALL_MBOARDS = size_t(~0); + + /*! + * Make a new multi usrp from the device address. + * \param dev_addr the device address + * \return a new single usrp object + */ + static sptr make(const device_addr_t &dev_addr); + + /*! + * Get the underlying device object. + * This is needed to get access to the streaming API and properties. + * \return the device object within this single usrp + */ + virtual device::sptr get_device(void) = 0; + + /******************************************************************* + * Mboard methods + ******************************************************************/ + /*! + * Get a printable summary for this USRP configuration. + * \return a printable string + */ + virtual std::string get_pp_string(void) = 0; + + /*! + * Get canonical name for this USRP motherboard. + * \param mboard which motherboard to query + * \return a string representing the name + */ + virtual std::string get_mboard_name(size_t mboard) = 0; + + /*! + * Gets the current time in the usrp time registers. + * \return a timespec representing current usrp time + */ + virtual time_spec_t get_time_now(void) = 0; + + /*! + * Set the time registers on the usrp at the next pps tick. + * The values will not be latched in until the pulse occurs. + * It is recommended that the user sleep(1) after calling to ensure + * that the time registers will be in a known state prior to use. + * + * Note: Because this call sets the time on the "next" pps, + * the seconds in the time spec should be current seconds + 1. + * + * \param time_spec the time to latch into the usrp device + */ + virtual void set_time_next_pps(const time_spec_t &time_spec) = 0; + + /*! + * Synchronize the times across all motherboards in this configuration. + * Use this method to sync the times when the edge of the PPS is unknown. + * + * Ex: Host machine is not attached to serial port of GPSDO + * and can therefore not query the GPSDO for the PPS edge. + * + * This is a 3-step process, and will take at most 3 seconds to complete. + * Upon completion, the times will be synchronized to the time provided. + * + * - Step1: set the time at the next pps (potential race condition) + * - Step2: wait for the seconds to rollover to catch the pps edge + * - Step3: set the time at the next pps (synchronous for all boards) + * + * \param time_spec the time to latch into the usrp device + */ + virtual void set_time_unknown_pps(const time_spec_t &time_spec) = 0; + + /*! + * Issue a stream command to the usrp device. + * This tells the usrp to send samples into the host. + * See the documentation for stream_cmd_t for more info. + * \param stream_cmd the stream command to issue + */ + virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd) = 0; + + /*! + * Set the clock configuration for the usrp device. + * This tells the usrp how to get a 10Mhz reference and PPS clock. + * See the documentation for clock_config_t for more info. + * \param clock_config the clock configuration to set + * \param mboard which motherboard to set the config + */ + virtual void set_clock_config(const clock_config_t &clock_config, size_t mboard) = 0; + + /*! + * Get the number of USRP motherboards in this configuration. + */ + virtual size_t get_num_mboards(void) = 0; + + /******************************************************************* + * RX methods + ******************************************************************/ + /*! + * Set the RX subdevice specification: + * The subdev spec maps a physical part of a daughter-board to a channel number. + * Set the subdev spec before calling into any methods with a channel number. + * The subdev spec must be the same size across all motherboards. + */ + virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard) = 0; + virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(size_t mboard) = 0; + + /*! + * Get the number of RX channels in this configuration. + * This is the number of USRPs times the number of RX channels per board, + * where the number of RX channels per board is homogeneous among all USRPs. + */ + virtual size_t get_rx_num_channels(void) = 0; + + virtual std::string get_rx_subdev_name(size_t chan) = 0; + + virtual void set_rx_rate(double rate) = 0; + virtual double get_rx_rate(void) = 0; + + virtual tune_result_t set_rx_freq(double freq, size_t chan) = 0; + virtual tune_result_t set_rx_freq(double freq, double lo_off, size_t chan) = 0; + virtual double get_rx_freq(size_t chan) = 0; + virtual freq_range_t get_rx_freq_range(size_t chan) = 0; + + virtual void set_rx_gain(float gain, size_t chan) = 0; + virtual float get_rx_gain(size_t chan) = 0; + virtual gain_range_t get_rx_gain_range(size_t chan) = 0; + + virtual void set_rx_antenna(const std::string &ant, size_t chan) = 0; + virtual std::string get_rx_antenna(size_t chan) = 0; + virtual std::vector get_rx_antennas(size_t chan) = 0; + + virtual bool get_rx_lo_locked(size_t chan) = 0; + + /*! + * Read the RSSI value from a usrp device. + * Or throw if the dboard does not support an RSSI readback. + * \return the rssi in dB + */ + virtual float read_rssi(size_t chan) = 0; + + virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan) = 0; + + virtual void set_rx_bandwidth(float bandwidth, size_t chan) = 0; + + /******************************************************************* + * TX methods + ******************************************************************/ + /*! + * Set the TX subdevice specification: + * The subdev spec maps a physical part of a daughter-board to a channel number. + * Set the subdev spec before calling into any methods with a channel number. + * The subdev spec must be the same size across all motherboards. + */ + virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard) = 0; + virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(size_t mboard) = 0; + + /*! + * Get the number of TX channels in this configuration. + * This is the number of USRPs times the number of TX channels per board, + * where the number of TX channels per board is homogeneous among all USRPs. + */ + virtual size_t get_tx_num_channels(void) = 0; + + virtual std::string get_tx_subdev_name(size_t chan) = 0; + + virtual void set_tx_rate(double rate) = 0; + virtual double get_tx_rate(void) = 0; + + virtual tune_result_t set_tx_freq(double freq, size_t chan) = 0; + virtual tune_result_t set_tx_freq(double freq, double lo_off, size_t chan) = 0; + virtual double get_tx_freq(size_t chan) = 0; + virtual freq_range_t get_tx_freq_range(size_t chan) = 0; + + virtual void set_tx_gain(float gain, size_t chan) = 0; + virtual float get_tx_gain(size_t chan) = 0; + virtual gain_range_t get_tx_gain_range(size_t chan) = 0; + + virtual void set_tx_antenna(const std::string &ant, size_t chan) = 0; + virtual std::string get_tx_antenna(size_t chan) = 0; + virtual std::vector get_tx_antennas(size_t chan) = 0; + + virtual bool get_tx_lo_locked(size_t chan) = 0; + + virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan) = 0; +}; + +}} + +#endif /* INCLUDED_UHD_USRP_MULTI_USRP_HPP */ diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index fa6498d13..2266e7f2c 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -33,8 +33,8 @@ namespace uhd{ namespace usrp{ /*! - * The single USRP device class: - * A single usrp facilitates ease-of-use for most use-case scenarios. + * The single-USRP device class: + * A single-USRP facilitates ease-of-use for most use-case scenarios. * The wrapper provides convenience functions to tune the devices * as well as to set the dboard gains, antennas, and other properties. * This wrapper supports multi-channel configurations per motherboard. @@ -61,7 +61,7 @@ public: * Mboard methods ******************************************************************/ /*! - * Get a printable name for this usrp. + * Get a printable summary for this USRP configuration. * \return a printable string */ virtual std::string get_pp_string(void) = 0; diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index 69a190bfa..d8898caff 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -25,6 +25,7 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/dsp_utils.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/mimo_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/multi_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/simple_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/single_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/subdev_spec.cpp diff --git a/host/lib/usrp/mimo_usrp.cpp b/host/lib/usrp/mimo_usrp.cpp index 08618c288..f5a80a3e6 100644 --- a/host/lib/usrp/mimo_usrp.cpp +++ b/host/lib/usrp/mimo_usrp.cpp @@ -347,5 +347,11 @@ private: * The Make Function **********************************************************************/ mimo_usrp::sptr mimo_usrp::make(const device_addr_t &dev_addr){ + uhd::print_warning( + "The mimo USRP interface has been deprecated.\n" + "Please switch to the multi USRP interface.\n" + "#include \n" + "multi_usrp::sptr sdev = multi_usrp::make(args);\n" + ); return sptr(new mimo_usrp_impl(dev_addr)); } diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp new file mode 100644 index 000000000..d0fc5c0f6 --- /dev/null +++ b/host/lib/usrp/multi_usrp.cpp @@ -0,0 +1,422 @@ +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; + +static inline freq_range_t add_dsp_shift(const freq_range_t &range, wax::obj dsp){ + double codec_rate = dsp[DSP_PROP_CODEC_RATE].as(); + return freq_range_t(range.min - codec_rate/2.0, range.max + codec_rate/2.0); +} + +/*********************************************************************** + * Simple USRP Implementation + **********************************************************************/ +class multi_usrp_impl : public multi_usrp{ +public: + multi_usrp_impl(const device_addr_t &addr){ + _dev = device::make(addr); + } + + device::sptr get_device(void){ + return _dev; + } + + /******************************************************************* + * Mboard methods + ******************************************************************/ + std::string get_pp_string(void){ + std::string buff = str(boost::format( + "Multi USRP:\n" + " Device: %s\n" + ) + % (*_dev)[DEVICE_PROP_NAME].as() + ); + for (size_t m = 0; m < get_num_mboards(); m++){ + buff += str(boost::format( + " Mboard %d: %s\n" + ) % m + % _mboard(m)[MBOARD_PROP_NAME].as() + ); + } + + //----------- rx side of life ---------------------------------- + for (size_t m = 0, chan = 0; m < get_num_mboards(); m++){ + buff += str(boost::format( + " RX DSP %d: %s\n" + ) % m + % _rx_dsp(m)[DSP_PROP_NAME].as() + ); + for (; chan < (m + 1)*get_rx_subdev_spec(m).size(); chan++){ + buff += str(boost::format( + " RX Channel: %u\n" + " RX Dboard: %s\n" + " RX Subdev: %s\n" + ) % chan + % _rx_dboard(chan)[DBOARD_PROP_NAME].as() + % _rx_subdev(chan)[SUBDEV_PROP_NAME].as() + ); + } + } + + //----------- tx side of life ---------------------------------- + for (size_t m = 0, chan = 0; m < get_num_mboards(); m++){ + buff += str(boost::format( + " TX DSP %d: %s\n" + ) % m + % _tx_dsp(m)[DSP_PROP_NAME].as() + ); + for (; chan < (m + 1)*get_tx_subdev_spec(m).size(); chan++){ + buff += str(boost::format( + " TX Channel: %u\n" + " TX Dboard: %s\n" + " TX Subdev: %s\n" + ) % chan + % _tx_dboard(chan)[DBOARD_PROP_NAME].as() + % _tx_subdev(chan)[SUBDEV_PROP_NAME].as() + ); + } + } + + return buff; + } + + std::string get_mboard_name(size_t mboard){ + return _mboard(mboard)[MBOARD_PROP_NAME].as(); + } + + time_spec_t get_time_now(void){ + return _mboard(0)[MBOARD_PROP_TIME_NOW].as(); + } + + void set_time_next_pps(const time_spec_t &time_spec){ + for (size_t m = 0; m < get_num_mboards(); m++){ + _mboard(m)[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; + } + } + + void set_time_unknown_pps(const time_spec_t &time_spec){ + std::cout << "Set time with unknown pps edge:" << std::endl; + std::cout << " 1) set times next pps (race condition)" << std::endl; + set_time_next_pps(time_spec); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + + std::cout << " 2) catch seconds rollover at pps edge" << std::endl; + time_t last_secs = 0, curr_secs = 0; + while(curr_secs == last_secs){ + last_secs = curr_secs; + curr_secs = get_time_now().get_full_secs(); + } + + std::cout << " 3) set times next pps (synchronously)" << std::endl; + set_time_next_pps(time_spec); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + + //verify that the time registers are read to be within a few RTT + for (size_t m = 1; m < get_num_mboards(); m++){ + time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); + time_spec_t time_i = _mboard(m)[MBOARD_PROP_TIME_NOW].as(); + if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big + uhd::print_warning(str(boost::format( + "Detected time deviation between board %d and board 0.\n" + "Board 0 time is %f seconds.\n" + "Board %d time is %f seconds.\n" + ) % m % time_0.get_real_secs() % m % time_i.get_real_secs())); + } + } + } + + void issue_stream_cmd(const stream_cmd_t &stream_cmd){ + for (size_t m = 0; m < get_num_mboards(); m++){ + _mboard(m)[MBOARD_PROP_STREAM_CMD] = stream_cmd; + } + } + + void set_clock_config(const clock_config_t &clock_config, size_t mboard){ + if (mboard != ALL_MBOARDS){ + _mboard(mboard)[MBOARD_PROP_CLOCK_CONFIG] = clock_config; + return; + } + for (size_t m = 0; m < get_num_mboards(); m++){ + set_clock_config(clock_config, m); + } + } + + size_t get_num_mboards(void){ + return (*_dev)[DEVICE_PROP_MBOARD_NAMES].as().size(); + } + + /******************************************************************* + * RX methods + ******************************************************************/ + void set_rx_subdev_spec(const subdev_spec_t &spec, size_t mboard){ + if (mboard != ALL_MBOARDS){ + _mboard(mboard)[MBOARD_PROP_RX_SUBDEV_SPEC] = spec; + return; + } + for (size_t m = 0; m < get_num_mboards(); m++){ + set_rx_subdev_spec(spec, m); + } + } + + subdev_spec_t get_rx_subdev_spec(size_t mboard){ + return _mboard(mboard)[MBOARD_PROP_RX_SUBDEV_SPEC].as(); + } + + size_t get_rx_num_channels(void){ + size_t nchan = get_rx_subdev_spec(0).size(); + for (size_t m = 1; m < get_num_mboards(); m++){ + if (nchan != get_rx_subdev_spec(m).size()){ + throw std::runtime_error("rx subdev spec size inconsistent across all mboards"); + } + } + return nchan; + } + + std::string get_rx_subdev_name(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_NAME].as(); + } + + void set_rx_rate(double rate){ + for (size_t m = 0; m < get_num_mboards(); m++){ + _rx_dsp(m)[DSP_PROP_HOST_RATE] = rate; + } + } + + double get_rx_rate(void){ + return _rx_dsp(0)[DSP_PROP_HOST_RATE].as(); + } + + tune_result_t set_rx_freq(double target_freq, size_t chan){ + size_t nchan = get_rx_num_channels(); + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(nchan/chan), nchan%chan, target_freq); + } + + tune_result_t set_rx_freq(double target_freq, double lo_off, size_t chan){ + size_t nchan = get_rx_num_channels(); + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(nchan/chan), nchan%chan, target_freq, lo_off); + } + + double get_rx_freq(size_t chan){ + size_t nchan = get_rx_num_channels(); + return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(nchan/chan), nchan%chan); + } + + freq_range_t get_rx_freq_range(size_t chan){ + size_t nchan = get_rx_num_channels(); + return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp(nchan/chan)); + } + + void set_rx_gain(float gain, size_t chan){ + return _rx_gain_group(chan)->set_value(gain); + } + + float get_rx_gain(size_t chan){ + return _rx_gain_group(chan)->get_value(); + } + + gain_range_t get_rx_gain_range(size_t chan){ + return _rx_gain_group(chan)->get_range(); + } + + void set_rx_antenna(const std::string &ant, size_t chan){ + _rx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; + } + + std::string get_rx_antenna(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA].as(); + } + + std::vector get_rx_antennas(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); + } + + bool get_rx_lo_locked(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); + } + + float read_rssi(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); + } + + dboard_iface::sptr get_rx_dboard_iface(size_t chan){ + return _rx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); + } + + void set_rx_bandwidth(float bandwidth, size_t chan) { + _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + /******************************************************************* + * TX methods + ******************************************************************/ + void set_tx_subdev_spec(const subdev_spec_t &spec, size_t mboard){ + if (mboard != ALL_MBOARDS){ + _mboard(mboard)[MBOARD_PROP_TX_SUBDEV_SPEC] = spec; + return; + } + for (size_t m = 0; m < get_num_mboards(); m++){ + set_tx_subdev_spec(spec, m); + } + } + + subdev_spec_t get_tx_subdev_spec(size_t mboard){ + return _mboard(mboard)[MBOARD_PROP_TX_SUBDEV_SPEC].as(); + } + + std::string get_tx_subdev_name(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_NAME].as(); + } + + size_t get_tx_num_channels(void){ + size_t nchan = get_tx_subdev_spec(0).size(); + for (size_t m = 1; m < get_num_mboards(); m++){ + if (nchan != get_tx_subdev_spec(m).size()){ + throw std::runtime_error("tx subdev spec size inconsistent across all mboards"); + } + } + return nchan; + } + + void set_tx_rate(double rate){ + for (size_t m = 0; m < get_num_mboards(); m++){ + _tx_dsp(m)[DSP_PROP_HOST_RATE] = rate; + } + } + + double get_tx_rate(void){ + return _tx_dsp(0)[DSP_PROP_HOST_RATE].as(); + } + + tune_result_t set_tx_freq(double target_freq, size_t chan){ + size_t nchan = get_tx_num_channels(); + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(nchan/chan), nchan%chan, target_freq); + } + + tune_result_t set_tx_freq(double target_freq, double lo_off, size_t chan){ + size_t nchan = get_tx_num_channels(); + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(nchan/chan), nchan%chan, target_freq, lo_off); + } + + double get_tx_freq(size_t chan){ + size_t nchan = get_tx_num_channels(); + return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(nchan/chan), nchan%chan); + } + + freq_range_t get_tx_freq_range(size_t chan){ + size_t nchan = get_tx_num_channels(); + return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp(nchan/chan)); + } + + void set_tx_gain(float gain, size_t chan){ + return _tx_gain_group(chan)->set_value(gain); + } + + float get_tx_gain(size_t chan){ + return _tx_gain_group(chan)->get_value(); + } + + gain_range_t get_tx_gain_range(size_t chan){ + return _tx_gain_group(chan)->get_range(); + } + + void set_tx_antenna(const std::string &ant, size_t chan){ + _tx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; + } + + std::string get_tx_antenna(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA].as(); + } + + std::vector get_tx_antennas(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); + } + + bool get_tx_lo_locked(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); + } + + dboard_iface::sptr get_tx_dboard_iface(size_t chan){ + return _tx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); + } + +private: + device::sptr _dev; + wax::obj _mboard(size_t mboard){ + std::string mb_name = (*_dev)[DEVICE_PROP_MBOARD_NAMES].as().at(mboard); + return (*_dev)[named_prop_t(DEVICE_PROP_MBOARD, mb_name)]; + } + wax::obj _rx_dsp(size_t mboard){ + return _mboard(mboard)[MBOARD_PROP_RX_DSP]; + } + wax::obj _tx_dsp(size_t mboard){ + return _mboard(mboard)[MBOARD_PROP_TX_DSP]; + } + wax::obj _rx_dboard(size_t chan){ + size_t nchan = get_rx_num_channels(); + std::string db_name = get_rx_subdev_spec(chan/nchan).at(chan%nchan).db_name; + return _mboard(chan/nchan)[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; + } + wax::obj _tx_dboard(size_t chan){ + size_t nchan = get_tx_num_channels(); + std::string db_name = get_tx_subdev_spec(chan/nchan).at(chan%nchan).db_name; + return _mboard(chan/nchan)[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; + } + wax::obj _rx_subdev(size_t chan){ + size_t nchan = get_rx_num_channels(); + std::string sd_name = get_rx_subdev_spec(chan/nchan).at(chan%nchan).sd_name; + return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; + } + wax::obj _tx_subdev(size_t chan){ + size_t nchan = get_tx_num_channels(); + std::string sd_name = get_tx_subdev_spec(chan/nchan).at(chan%nchan).sd_name; + return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; + } + gain_group::sptr _rx_gain_group(size_t chan){ + size_t nchan = get_rx_num_channels(); + std::string sd_name = get_rx_subdev_spec(chan/nchan).at(chan%nchan).sd_name; + return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); + } + gain_group::sptr _tx_gain_group(size_t chan){ + size_t nchan = get_tx_num_channels(); + std::string sd_name = get_tx_subdev_spec(chan/nchan).at(chan%nchan).sd_name; + return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); + } +}; + +/*********************************************************************** + * The Make Function + **********************************************************************/ +multi_usrp::sptr multi_usrp::make(const device_addr_t &dev_addr){ + return sptr(new multi_usrp_impl(dev_addr)); +} diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index 7d053535e..fba04cd60 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -46,10 +46,6 @@ public: _dev = device::make(addr); } - ~single_usrp_impl(void){ - /* NOP */ - } - device::sptr get_device(void){ return _dev; } -- cgit v1.2.3 From a1e42e5d60be8fd74d3e93f86546343cb93c3a48 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 17 Oct 2010 23:37:52 -0700 Subject: usrp: moved warnings logic into wrappers --- host/lib/usrp/CMakeLists.txt | 1 + host/lib/usrp/multi_usrp.cpp | 24 +++++++++------ host/lib/usrp/single_usrp.cpp | 24 +++++++++------ host/lib/usrp/wrapper_utils.hpp | 66 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 18 deletions(-) create mode 100644 host/lib/usrp/wrapper_utils.hpp diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index d8898caff..906a5ff29 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -30,6 +30,7 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/single_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/subdev_spec.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/tune_helper.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/wrapper_utils.hpp ) INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/dboard/CMakeLists.txt) diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index d0fc5c0f6..7f7ea77b0 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -15,6 +15,7 @@ // along with this program. If not, see . // +#include "wrapper_utils.hpp" #include #include #include @@ -34,11 +35,6 @@ using namespace uhd; using namespace uhd::usrp; -static inline freq_range_t add_dsp_shift(const freq_range_t &range, wax::obj dsp){ - double codec_rate = dsp[DSP_PROP_CODEC_RATE].as(); - return freq_range_t(range.min - codec_rate/2.0, range.max + codec_rate/2.0); -} - /*********************************************************************** * Simple USRP Implementation **********************************************************************/ @@ -211,6 +207,7 @@ public: for (size_t m = 0; m < get_num_mboards(); m++){ _rx_dsp(m)[DSP_PROP_HOST_RATE] = rate; } + do_samp_rate_warning_message(rate, get_rx_rate(), "RX"); } double get_rx_rate(void){ @@ -219,12 +216,16 @@ public: tune_result_t set_rx_freq(double target_freq, size_t chan){ size_t nchan = get_rx_num_channels(); - return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(nchan/chan), nchan%chan, target_freq); + tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(nchan/chan), nchan%chan, target_freq); + do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX"); + return r; } tune_result_t set_rx_freq(double target_freq, double lo_off, size_t chan){ size_t nchan = get_rx_num_channels(); - return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(nchan/chan), nchan%chan, target_freq, lo_off); + tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(nchan/chan), nchan%chan, target_freq, lo_off); + do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX"); + return r; } double get_rx_freq(size_t chan){ @@ -312,6 +313,7 @@ public: for (size_t m = 0; m < get_num_mboards(); m++){ _tx_dsp(m)[DSP_PROP_HOST_RATE] = rate; } + do_samp_rate_warning_message(rate, get_tx_rate(), "TX"); } double get_tx_rate(void){ @@ -320,12 +322,16 @@ public: tune_result_t set_tx_freq(double target_freq, size_t chan){ size_t nchan = get_tx_num_channels(); - return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(nchan/chan), nchan%chan, target_freq); + tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(nchan/chan), nchan%chan, target_freq); + do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX"); + return r; } tune_result_t set_tx_freq(double target_freq, double lo_off, size_t chan){ size_t nchan = get_tx_num_channels(); - return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(nchan/chan), nchan%chan, target_freq, lo_off); + tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(nchan/chan), nchan%chan, target_freq, lo_off); + do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX"); + return r; } double get_tx_freq(size_t chan){ diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index fba04cd60..7a4df3eb5 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -15,6 +15,7 @@ // along with this program. If not, see . // +#include "wrapper_utils.hpp" #include #include #include @@ -32,11 +33,6 @@ using namespace uhd; using namespace uhd::usrp; -static inline freq_range_t add_dsp_shift(const freq_range_t &range, wax::obj dsp){ - double codec_rate = dsp[DSP_PROP_CODEC_RATE].as(); - return freq_range_t(range.min - codec_rate/2.0, range.max + codec_rate/2.0); -} - /*********************************************************************** * Simple USRP Implementation **********************************************************************/ @@ -141,6 +137,7 @@ public: void set_rx_rate(double rate){ _rx_dsp()[DSP_PROP_HOST_RATE] = rate; + do_samp_rate_warning_message(rate, get_rx_rate(), "RX"); } double get_rx_rate(void){ @@ -148,11 +145,15 @@ public: } tune_result_t set_rx_freq(double target_freq, size_t chan){ - return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, target_freq); + tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, target_freq); + do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX"); + return r; } tune_result_t set_rx_freq(double target_freq, double lo_off, size_t chan){ - return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, target_freq, lo_off); + tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, target_freq, lo_off); + do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX"); + return r; } double get_rx_freq(size_t chan){ @@ -220,6 +221,7 @@ public: void set_tx_rate(double rate){ _tx_dsp()[DSP_PROP_HOST_RATE] = rate; + do_samp_rate_warning_message(rate, get_tx_rate(), "TX"); } double get_tx_rate(void){ @@ -227,11 +229,15 @@ public: } tune_result_t set_tx_freq(double target_freq, size_t chan){ - return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, target_freq); + tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, target_freq); + do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX"); + return r; } tune_result_t set_tx_freq(double target_freq, double lo_off, size_t chan){ - return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, target_freq, lo_off); + tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, target_freq, lo_off); + do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX"); + return r; } double get_tx_freq(size_t chan){ diff --git a/host/lib/usrp/wrapper_utils.hpp b/host/lib/usrp/wrapper_utils.hpp new file mode 100644 index 000000000..aee230fc0 --- /dev/null +++ b/host/lib/usrp/wrapper_utils.hpp @@ -0,0 +1,66 @@ +// +// 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_USRP_WRAPPER_UTILS_HPP +#define INCLUDED_LIBUHD_USRP_WRAPPER_UTILS_HPP + +#include +#include +#include +#include +#include +#include + +static inline uhd::freq_range_t add_dsp_shift( + const uhd::freq_range_t &range, + wax::obj dsp +){ + double codec_rate = dsp[uhd::usrp::DSP_PROP_CODEC_RATE].as(); + return uhd::freq_range_t(range.min - codec_rate/2.0, range.max + codec_rate/2.0); +} + +static inline void do_samp_rate_warning_message( + double target_rate, + double actual_rate, + const std::string &xx +){ + static const double max_allowed_error = 1.0; //Sps + if (std::abs(target_rate - actual_rate) > max_allowed_error){ + uhd::print_warning(str(boost::format( + "The hardware does not support the requested %s sample rate:\n" + "Target sample rate: %f MSps\n" + "Actual sample rate: %f MSps\n" + ) % xx % (target_rate/1e6) % (actual_rate/1e6))); + } +} + +static inline void do_tune_freq_warning_message( + double target_freq, + double actual_freq, + const std::string &xx +){ + static const double max_allowed_error = 1.0; //Hz + if (std::abs(target_freq - actual_freq) > max_allowed_error){ + uhd::print_warning(str(boost::format( + "The hardware does not support the requested %s frequency:\n" + "Target frequency: %f MHz\n" + "Actual frequency: %f MHz\n" + ) % xx % (target_freq/1e6) % (actual_freq/1e6))); + } +} + +#endif /* INCLUDED_LIBUHD_USRP_WRAPPER_UTILS_HPP */ -- cgit v1.2.3 From 847512647f10241d9ba828c5c284176d11437cb8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 18 Oct 2010 17:39:34 -0700 Subject: usrp: deleted deprecated simple and mimo wrappers, moved implementations into headers --- host/include/uhd/usrp/mimo_usrp.hpp | 343 ++++++++++++++++++++++++++++++++ host/include/uhd/usrp/simple_usrp.hpp | 214 ++++++++++++++++++++ host/lib/usrp/CMakeLists.txt | 2 - host/lib/usrp/mimo_usrp.cpp | 357 ---------------------------------- host/lib/usrp/simple_usrp.cpp | 226 --------------------- 5 files changed, 557 insertions(+), 585 deletions(-) delete mode 100644 host/lib/usrp/mimo_usrp.cpp delete mode 100644 host/lib/usrp/simple_usrp.cpp diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index 7c250b2fd..78833e24e 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -179,4 +179,347 @@ public: }} +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace uhd{ namespace usrp{ namespace /*anon*/{ + +static inline freq_range_t add_dsp_shift(const freq_range_t &range, wax::obj dsp){ + double codec_rate = dsp[DSP_PROP_CODEC_RATE].as(); + return freq_range_t(range.min - codec_rate/2.0, range.max + codec_rate/2.0); +} + +/*********************************************************************** + * MIMO USRP Implementation + **********************************************************************/ +class mimo_usrp_impl : public mimo_usrp{ +public: + mimo_usrp_impl(const device_addr_t &addr){ + _dev = device::make(addr); + + //set the clock config across all mboards (TODO set through api) + clock_config_t clock_config; + clock_config.ref_source = clock_config_t::REF_SMA; + clock_config.pps_source = clock_config_t::PPS_SMA; + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _mboard(chan)[MBOARD_PROP_CLOCK_CONFIG] = clock_config; + } + } + + ~mimo_usrp_impl(void){ + /* NOP */ + } + + device::sptr get_device(void){ + return _dev; + } + + std::string get_pp_string(void){ + std::string buff = str(boost::format( + "MIMO USRP:\n" + " Device: %s\n" + ) + % (*_dev)[DEVICE_PROP_NAME].as() + ); + for (size_t chan = 0; chan < get_num_channels(); chan++){ + buff += str(boost::format( + " Channel: %u\n" + " Mboard: %s\n" + " RX DSP: %s\n" + " RX Dboard: %s\n" + " RX Subdev: %s\n" + " TX DSP: %s\n" + " TX Dboard: %s\n" + " TX Subdev: %s\n" + ) % chan + % _mboard(chan)[MBOARD_PROP_NAME].as() + % _rx_dsp(chan)[DSP_PROP_NAME].as() + % _rx_dboard(chan)[DBOARD_PROP_NAME].as() + % _rx_subdev(chan)[SUBDEV_PROP_NAME].as() + % _tx_dsp(chan)[DSP_PROP_NAME].as() + % _tx_dboard(chan)[DBOARD_PROP_NAME].as() + % _tx_subdev(chan)[SUBDEV_PROP_NAME].as() + ); + } + return buff; + } + + size_t get_num_channels(void){ + return (*_dev)[DEVICE_PROP_MBOARD_NAMES].as().size(); + } + + /******************************************************************* + * Misc + ******************************************************************/ + time_spec_t get_time_now(void){ + //the time on the first mboard better be the same on all + return _mboard(0)[MBOARD_PROP_TIME_NOW].as(); + } + + void set_time_next_pps(const time_spec_t &time_spec){ + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _mboard(chan)[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; + } + } + + void set_time_unknown_pps(const time_spec_t &time_spec){ + std::cout << "Set time with unknown pps edge:" << std::endl; + std::cout << " 1) set times next pps (race condition)" << std::endl; + set_time_next_pps(time_spec); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + + std::cout << " 2) catch seconds rollover at pps edge" << std::endl; + time_t last_secs = 0, curr_secs = 0; + while(curr_secs == last_secs){ + last_secs = curr_secs; + curr_secs = get_time_now().get_full_secs(); + } + + std::cout << " 3) set times next pps (synchronously)" << std::endl; + set_time_next_pps(time_spec); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + + //verify that the time registers are read to be within a few RTT + for (size_t chan = 1; chan < get_num_channels(); chan++){ + time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); + time_spec_t time_i = _mboard(chan)[MBOARD_PROP_TIME_NOW].as(); + if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big + uhd::print_warning(str(boost::format( + "Detected time deviation between board %d and board 0.\n" + "Board 0 time is %f seconds.\n" + "Board %d time is %f seconds.\n" + ) % chan % time_0.get_real_secs() % chan % time_i.get_real_secs())); + } + } + } + + void issue_stream_cmd(const stream_cmd_t &stream_cmd){ + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _mboard(chan)[MBOARD_PROP_STREAM_CMD] = stream_cmd; + } + } + + /******************************************************************* + * RX methods + ******************************************************************/ + void set_rx_subdev_spec(size_t chan, const subdev_spec_t &spec){ + UHD_ASSERT_THROW(spec.size() <= 1); + _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC] = spec; + } + + subdev_spec_t get_rx_subdev_spec(size_t chan){ + return _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as(); + } + + void set_rx_rate_all(double rate){ + std::vector _actual_rates; + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _rx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; + _actual_rates.push_back(_rx_dsp(chan)[DSP_PROP_HOST_RATE].as()); + } + _rx_rate = _actual_rates.front(); + if (std::count(_actual_rates, _rx_rate) != _actual_rates.size()) throw std::runtime_error( + "MIMO configuratio error: rx rate inconsistent across mboards" + ); + } + + double get_rx_rate_all(void){ + return _rx_rate; + } + + tune_result_t set_rx_freq(size_t chan, double target_freq){ + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq); + } + + tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){ + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq, lo_off); + } + + double get_rx_freq(size_t chan){ + return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0); + } + + freq_range_t get_rx_freq_range(size_t chan){ + return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp(chan)); + } + + void set_rx_gain(size_t chan, float gain){ + return _rx_gain_group(chan)->set_value(gain); + } + + float get_rx_gain(size_t chan){ + return _rx_gain_group(chan)->get_value(); + } + + gain_range_t get_rx_gain_range(size_t chan){ + return _rx_gain_group(chan)->get_range(); + } + + void set_rx_antenna(size_t chan, const std::string &ant){ + _rx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; + } + + std::string get_rx_antenna(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA].as(); + } + + std::vector get_rx_antennas(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); + } + + bool get_rx_lo_locked(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); + } + + float read_rssi(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); + } + + void set_rx_bandwidth(size_t chan, float bandwidth){ + _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + /******************************************************************* + * TX methods + ******************************************************************/ + void set_tx_subdev_spec(size_t chan, const subdev_spec_t &spec){ + UHD_ASSERT_THROW(spec.size() <= 1); + _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC] = spec; + } + + subdev_spec_t get_tx_subdev_spec(size_t chan){ + return _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as(); + } + + void set_tx_rate_all(double rate){ + std::vector _actual_rates; + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _tx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; + _actual_rates.push_back(_tx_dsp(chan)[DSP_PROP_HOST_RATE].as()); + } + _tx_rate = _actual_rates.front(); + if (std::count(_actual_rates, _tx_rate) != _actual_rates.size()) throw std::runtime_error( + "MIMO configuratio error: tx rate inconsistent across mboards" + ); + } + + double get_tx_rate_all(void){ + return _tx_rate; + } + + tune_result_t set_tx_freq(size_t chan, double target_freq){ + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq); + } + + tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){ + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq, lo_off); + } + + double get_tx_freq(size_t chan){ + return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0); + } + + freq_range_t get_tx_freq_range(size_t chan){ + return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp(chan)); + } + + void set_tx_gain(size_t chan, float gain){ + return _tx_gain_group(chan)->set_value(gain); + } + + float get_tx_gain(size_t chan){ + return _tx_gain_group(chan)->get_value(); + } + + gain_range_t get_tx_gain_range(size_t chan){ + return _tx_gain_group(chan)->get_range(); + } + + void set_tx_antenna(size_t chan, const std::string &ant){ + _tx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; + } + + std::string get_tx_antenna(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA].as(); + } + + std::vector get_tx_antennas(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); + } + + bool get_tx_lo_locked(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); + } + +private: + device::sptr _dev; + wax::obj _mboard(size_t chan){ + prop_names_t names = (*_dev)[DEVICE_PROP_MBOARD_NAMES].as(); + return (*_dev)[named_prop_t(DEVICE_PROP_MBOARD, names.at(chan))]; + } + wax::obj _rx_dsp(size_t chan){ + return _mboard(chan)[MBOARD_PROP_RX_DSP]; + } + wax::obj _tx_dsp(size_t chan){ + return _mboard(chan)[MBOARD_PROP_TX_DSP]; + } + wax::obj _rx_dboard(size_t chan){ + std::string db_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().db_name; + return _mboard(chan)[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; + } + wax::obj _tx_dboard(size_t chan){ + std::string db_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().db_name; + return _mboard(chan)[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; + } + wax::obj _rx_subdev(size_t chan){ + std::string sd_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().sd_name; + return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; + } + wax::obj _tx_subdev(size_t chan){ + std::string sd_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().sd_name; + return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; + } + gain_group::sptr _rx_gain_group(size_t chan){ + std::string sd_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().sd_name; + return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); + } + gain_group::sptr _tx_gain_group(size_t chan){ + std::string sd_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().sd_name; + return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); + } + + //shadows + double _rx_rate, _tx_rate; +}; +}}} + +namespace uhd{ namespace usrp{ +/*********************************************************************** + * The Make Function + **********************************************************************/ +inline mimo_usrp::sptr mimo_usrp::make(const device_addr_t &dev_addr){ + uhd::print_warning( + "The mimo USRP interface has been deprecated.\n" + "Please switch to the multi USRP interface.\n" + "#include \n" + "multi_usrp::sptr sdev = multi_usrp::make(args);\n" + ); + return sptr(new mimo_usrp_impl(dev_addr)); +} +}} + #endif /* INCLUDED_UHD_USRP_MIMO_USRP_HPP */ diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index 6f3597ed7..22f4d64ba 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -171,4 +171,218 @@ public: }} +#include +#include + +namespace uhd{ namespace usrp{ namespace /*anon*/{ + +/*********************************************************************** + * Simple USRP Implementation + **********************************************************************/ +class simple_usrp_impl : public simple_usrp{ +public: + simple_usrp_impl(const device_addr_t &addr){ + _sdev = single_usrp::make(addr); + } + + ~simple_usrp_impl(void){ + /* NOP */ + } + + device::sptr get_device(void){ + return _sdev->get_device(); + } + + std::string get_pp_string(void){ + return _sdev->get_pp_string(); + } + + /******************************************************************* + * Misc + ******************************************************************/ + time_spec_t get_time_now(void){ + return _sdev->get_time_now(); + } + + void set_time_now(const time_spec_t &time_spec){ + return _sdev->set_time_now(time_spec); + } + + void set_time_next_pps(const time_spec_t &time_spec){ + return _sdev->set_time_next_pps(time_spec); + } + + void issue_stream_cmd(const stream_cmd_t &stream_cmd){ + return _sdev->issue_stream_cmd(stream_cmd); + } + + void set_clock_config(const clock_config_t &clock_config){ + return _sdev->set_clock_config(clock_config); + } + + /******************************************************************* + * RX methods + ******************************************************************/ + void set_rx_subdev_spec(const subdev_spec_t &spec){ + return _sdev->set_rx_subdev_spec(spec); + } + + subdev_spec_t get_rx_subdev_spec(void){ + return _sdev->get_rx_subdev_spec(); + } + + void set_rx_rate(double rate){ + return _sdev->set_rx_rate(rate); + } + + double get_rx_rate(void){ + return _sdev->get_rx_rate(); + } + + tune_result_t set_rx_freq(double target_freq){ + return _sdev->set_rx_freq(target_freq); + } + + tune_result_t set_rx_freq(double target_freq, double lo_off){ + return _sdev->set_rx_freq(target_freq, lo_off); + } + + double get_rx_freq(void){ + return _sdev->get_rx_freq(); + } + + freq_range_t get_rx_freq_range(void){ + return _sdev->get_rx_freq_range(); + } + + void set_rx_gain(float gain){ + return _sdev->set_rx_gain(gain); + } + + float get_rx_gain(void){ + return _sdev->get_rx_gain(); + } + + gain_range_t get_rx_gain_range(void){ + return _sdev->get_rx_gain_range(); + } + + void set_rx_antenna(const std::string &ant){ + return _sdev->set_rx_antenna(ant); + } + + std::string get_rx_antenna(void){ + return _sdev->get_rx_antenna(); + } + + std::vector get_rx_antennas(void){ + return _sdev->get_rx_antennas(); + } + + bool get_rx_lo_locked(void){ + return _sdev->get_rx_lo_locked(); + } + + float read_rssi(void){ + return _sdev->read_rssi(); + } + + dboard_iface::sptr get_rx_dboard_iface(void){ + return _sdev->get_rx_dboard_iface(); + } + + void set_rx_bandwidth(float bandwidth) { + return _sdev->set_rx_bandwidth(bandwidth); + } + + /******************************************************************* + * TX methods + ******************************************************************/ + void set_tx_subdev_spec(const subdev_spec_t &spec){ + return _sdev->set_tx_subdev_spec(spec); + } + + subdev_spec_t get_tx_subdev_spec(void){ + return _sdev->get_tx_subdev_spec(); + } + + void set_tx_rate(double rate){ + return _sdev->set_tx_rate(rate); + } + + double get_tx_rate(void){ + return _sdev->get_tx_rate(); + } + + tune_result_t set_tx_freq(double target_freq){ + return _sdev->set_tx_freq(target_freq); + } + + tune_result_t set_tx_freq(double target_freq, double lo_off){ + return _sdev->set_tx_freq(target_freq, lo_off); + } + + double get_tx_freq(void){ + return _sdev->get_tx_freq(); + } + + freq_range_t get_tx_freq_range(void){ + return _sdev->get_tx_freq_range(); + } + + void set_tx_gain(float gain){ + return _sdev->set_tx_gain(gain); + } + + float get_tx_gain(void){ + return _sdev->get_tx_gain(); + } + + gain_range_t get_tx_gain_range(void){ + return _sdev->get_tx_gain_range(); + } + + void set_tx_antenna(const std::string &ant){ + return _sdev->set_tx_antenna(ant); + } + + std::string get_tx_antenna(void){ + return _sdev->get_tx_antenna(); + } + + std::vector get_tx_antennas(void){ + return _sdev->get_tx_antennas(); + } + + bool get_tx_lo_locked(void){ + return _sdev->get_tx_lo_locked(); + } + + dboard_iface::sptr get_tx_dboard_iface(void){ + return _sdev->get_tx_dboard_iface(); + } + +private: + single_usrp::sptr _sdev; +}; + +}}} + +namespace uhd{ namespace usrp{ + +/*********************************************************************** + * The Make Function + **********************************************************************/ +inline simple_usrp::sptr simple_usrp::make(const device_addr_t &dev_addr){ + uhd::print_warning( + "The simple USRP interface has been deprecated.\n" + "Please switch to the single USRP interface.\n" + "#include \n" + "single_usrp::sptr sdev = single_usrp::make(args);\n" + ); + return sptr(new simple_usrp_impl(dev_addr)); +} + +}} + #endif /* INCLUDED_UHD_USRP_SIMPLE_USRP_HPP */ diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index 906a5ff29..eeb181e0b 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -23,10 +23,8 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_id.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_manager.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/dsp_utils.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/mimo_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/multi_usrp.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/simple_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/single_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/subdev_spec.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/tune_helper.cpp diff --git a/host/lib/usrp/mimo_usrp.cpp b/host/lib/usrp/mimo_usrp.cpp deleted file mode 100644 index f5a80a3e6..000000000 --- a/host/lib/usrp/mimo_usrp.cpp +++ /dev/null @@ -1,357 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace uhd; -using namespace uhd::usrp; - -static inline freq_range_t add_dsp_shift(const freq_range_t &range, wax::obj dsp){ - double codec_rate = dsp[DSP_PROP_CODEC_RATE].as(); - return freq_range_t(range.min - codec_rate/2.0, range.max + codec_rate/2.0); -} - -/*********************************************************************** - * MIMO USRP Implementation - **********************************************************************/ -class mimo_usrp_impl : public mimo_usrp{ -public: - mimo_usrp_impl(const device_addr_t &addr){ - _dev = device::make(addr); - - //set the clock config across all mboards (TODO set through api) - clock_config_t clock_config; - clock_config.ref_source = clock_config_t::REF_SMA; - clock_config.pps_source = clock_config_t::PPS_SMA; - for (size_t chan = 0; chan < get_num_channels(); chan++){ - _mboard(chan)[MBOARD_PROP_CLOCK_CONFIG] = clock_config; - } - } - - ~mimo_usrp_impl(void){ - /* NOP */ - } - - device::sptr get_device(void){ - return _dev; - } - - std::string get_pp_string(void){ - std::string buff = str(boost::format( - "MIMO USRP:\n" - " Device: %s\n" - ) - % (*_dev)[DEVICE_PROP_NAME].as() - ); - for (size_t chan = 0; chan < get_num_channels(); chan++){ - buff += str(boost::format( - " Channel: %u\n" - " Mboard: %s\n" - " RX DSP: %s\n" - " RX Dboard: %s\n" - " RX Subdev: %s\n" - " TX DSP: %s\n" - " TX Dboard: %s\n" - " TX Subdev: %s\n" - ) % chan - % _mboard(chan)[MBOARD_PROP_NAME].as() - % _rx_dsp(chan)[DSP_PROP_NAME].as() - % _rx_dboard(chan)[DBOARD_PROP_NAME].as() - % _rx_subdev(chan)[SUBDEV_PROP_NAME].as() - % _tx_dsp(chan)[DSP_PROP_NAME].as() - % _tx_dboard(chan)[DBOARD_PROP_NAME].as() - % _tx_subdev(chan)[SUBDEV_PROP_NAME].as() - ); - } - return buff; - } - - size_t get_num_channels(void){ - return (*_dev)[DEVICE_PROP_MBOARD_NAMES].as().size(); - } - - /******************************************************************* - * Misc - ******************************************************************/ - time_spec_t get_time_now(void){ - //the time on the first mboard better be the same on all - return _mboard(0)[MBOARD_PROP_TIME_NOW].as(); - } - - void set_time_next_pps(const time_spec_t &time_spec){ - for (size_t chan = 0; chan < get_num_channels(); chan++){ - _mboard(chan)[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; - } - } - - void set_time_unknown_pps(const time_spec_t &time_spec){ - std::cout << "Set time with unknown pps edge:" << std::endl; - std::cout << " 1) set times next pps (race condition)" << std::endl; - set_time_next_pps(time_spec); - boost::this_thread::sleep(boost::posix_time::seconds(1)); - - std::cout << " 2) catch seconds rollover at pps edge" << std::endl; - time_t last_secs = 0, curr_secs = 0; - while(curr_secs == last_secs){ - last_secs = curr_secs; - curr_secs = get_time_now().get_full_secs(); - } - - std::cout << " 3) set times next pps (synchronously)" << std::endl; - set_time_next_pps(time_spec); - boost::this_thread::sleep(boost::posix_time::seconds(1)); - - //verify that the time registers are read to be within a few RTT - for (size_t chan = 1; chan < get_num_channels(); chan++){ - time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); - time_spec_t time_i = _mboard(chan)[MBOARD_PROP_TIME_NOW].as(); - if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big - uhd::print_warning(str(boost::format( - "Detected time deviation between board %d and board 0.\n" - "Board 0 time is %f seconds.\n" - "Board %d time is %f seconds.\n" - ) % chan % time_0.get_real_secs() % chan % time_i.get_real_secs())); - } - } - } - - void issue_stream_cmd(const stream_cmd_t &stream_cmd){ - for (size_t chan = 0; chan < get_num_channels(); chan++){ - _mboard(chan)[MBOARD_PROP_STREAM_CMD] = stream_cmd; - } - } - - /******************************************************************* - * RX methods - ******************************************************************/ - void set_rx_subdev_spec(size_t chan, const subdev_spec_t &spec){ - UHD_ASSERT_THROW(spec.size() <= 1); - _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC] = spec; - } - - subdev_spec_t get_rx_subdev_spec(size_t chan){ - return _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as(); - } - - void set_rx_rate_all(double rate){ - std::vector _actual_rates; - for (size_t chan = 0; chan < get_num_channels(); chan++){ - _rx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; - _actual_rates.push_back(_rx_dsp(chan)[DSP_PROP_HOST_RATE].as()); - } - _rx_rate = _actual_rates.front(); - if (std::count(_actual_rates, _rx_rate) != _actual_rates.size()) throw std::runtime_error( - "MIMO configuratio error: rx rate inconsistent across mboards" - ); - } - - double get_rx_rate_all(void){ - return _rx_rate; - } - - tune_result_t set_rx_freq(size_t chan, double target_freq){ - return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq); - } - - tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){ - return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq, lo_off); - } - - double get_rx_freq(size_t chan){ - return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0); - } - - freq_range_t get_rx_freq_range(size_t chan){ - return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp(chan)); - } - - void set_rx_gain(size_t chan, float gain){ - return _rx_gain_group(chan)->set_value(gain); - } - - float get_rx_gain(size_t chan){ - return _rx_gain_group(chan)->get_value(); - } - - gain_range_t get_rx_gain_range(size_t chan){ - return _rx_gain_group(chan)->get_range(); - } - - void set_rx_antenna(size_t chan, const std::string &ant){ - _rx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; - } - - std::string get_rx_antenna(size_t chan){ - return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA].as(); - } - - std::vector get_rx_antennas(size_t chan){ - return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); - } - - bool get_rx_lo_locked(size_t chan){ - return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); - } - - float read_rssi(size_t chan){ - return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); - } - - void set_rx_bandwidth(size_t chan, float bandwidth){ - _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; - } - - /******************************************************************* - * TX methods - ******************************************************************/ - void set_tx_subdev_spec(size_t chan, const subdev_spec_t &spec){ - UHD_ASSERT_THROW(spec.size() <= 1); - _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC] = spec; - } - - subdev_spec_t get_tx_subdev_spec(size_t chan){ - return _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as(); - } - - void set_tx_rate_all(double rate){ - std::vector _actual_rates; - for (size_t chan = 0; chan < get_num_channels(); chan++){ - _tx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; - _actual_rates.push_back(_tx_dsp(chan)[DSP_PROP_HOST_RATE].as()); - } - _tx_rate = _actual_rates.front(); - if (std::count(_actual_rates, _tx_rate) != _actual_rates.size()) throw std::runtime_error( - "MIMO configuratio error: tx rate inconsistent across mboards" - ); - } - - double get_tx_rate_all(void){ - return _tx_rate; - } - - tune_result_t set_tx_freq(size_t chan, double target_freq){ - return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq); - } - - tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){ - return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq, lo_off); - } - - double get_tx_freq(size_t chan){ - return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0); - } - - freq_range_t get_tx_freq_range(size_t chan){ - return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp(chan)); - } - - void set_tx_gain(size_t chan, float gain){ - return _tx_gain_group(chan)->set_value(gain); - } - - float get_tx_gain(size_t chan){ - return _tx_gain_group(chan)->get_value(); - } - - gain_range_t get_tx_gain_range(size_t chan){ - return _tx_gain_group(chan)->get_range(); - } - - void set_tx_antenna(size_t chan, const std::string &ant){ - _tx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; - } - - std::string get_tx_antenna(size_t chan){ - return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA].as(); - } - - std::vector get_tx_antennas(size_t chan){ - return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); - } - - bool get_tx_lo_locked(size_t chan){ - return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); - } - -private: - device::sptr _dev; - wax::obj _mboard(size_t chan){ - prop_names_t names = (*_dev)[DEVICE_PROP_MBOARD_NAMES].as(); - return (*_dev)[named_prop_t(DEVICE_PROP_MBOARD, names.at(chan))]; - } - wax::obj _rx_dsp(size_t chan){ - return _mboard(chan)[MBOARD_PROP_RX_DSP]; - } - wax::obj _tx_dsp(size_t chan){ - return _mboard(chan)[MBOARD_PROP_TX_DSP]; - } - wax::obj _rx_dboard(size_t chan){ - std::string db_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().db_name; - return _mboard(chan)[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; - } - wax::obj _tx_dboard(size_t chan){ - std::string db_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().db_name; - return _mboard(chan)[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; - } - wax::obj _rx_subdev(size_t chan){ - std::string sd_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().sd_name; - return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; - } - wax::obj _tx_subdev(size_t chan){ - std::string sd_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().sd_name; - return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; - } - gain_group::sptr _rx_gain_group(size_t chan){ - std::string sd_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().sd_name; - return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); - } - gain_group::sptr _tx_gain_group(size_t chan){ - std::string sd_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().sd_name; - return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); - } - - //shadows - double _rx_rate, _tx_rate; -}; - -/*********************************************************************** - * The Make Function - **********************************************************************/ -mimo_usrp::sptr mimo_usrp::make(const device_addr_t &dev_addr){ - uhd::print_warning( - "The mimo USRP interface has been deprecated.\n" - "Please switch to the multi USRP interface.\n" - "#include \n" - "multi_usrp::sptr sdev = multi_usrp::make(args);\n" - ); - return sptr(new mimo_usrp_impl(dev_addr)); -} diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp deleted file mode 100644 index b4f34287b..000000000 --- a/host/lib/usrp/simple_usrp.cpp +++ /dev/null @@ -1,226 +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 - -using namespace uhd; -using namespace uhd::usrp; - -/*********************************************************************** - * Simple USRP Implementation - **********************************************************************/ -class simple_usrp_impl : public simple_usrp{ -public: - simple_usrp_impl(const device_addr_t &addr){ - _sdev = single_usrp::make(addr); - } - - ~simple_usrp_impl(void){ - /* NOP */ - } - - device::sptr get_device(void){ - return _sdev->get_device(); - } - - std::string get_pp_string(void){ - return _sdev->get_pp_string(); - } - - /******************************************************************* - * Misc - ******************************************************************/ - time_spec_t get_time_now(void){ - return _sdev->get_time_now(); - } - - void set_time_now(const time_spec_t &time_spec){ - return _sdev->set_time_now(time_spec); - } - - void set_time_next_pps(const time_spec_t &time_spec){ - return _sdev->set_time_next_pps(time_spec); - } - - void issue_stream_cmd(const stream_cmd_t &stream_cmd){ - return _sdev->issue_stream_cmd(stream_cmd); - } - - void set_clock_config(const clock_config_t &clock_config){ - return _sdev->set_clock_config(clock_config); - } - - /******************************************************************* - * RX methods - ******************************************************************/ - void set_rx_subdev_spec(const subdev_spec_t &spec){ - return _sdev->set_rx_subdev_spec(spec); - } - - subdev_spec_t get_rx_subdev_spec(void){ - return _sdev->get_rx_subdev_spec(); - } - - void set_rx_rate(double rate){ - return _sdev->set_rx_rate(rate); - } - - double get_rx_rate(void){ - return _sdev->get_rx_rate(); - } - - tune_result_t set_rx_freq(double target_freq){ - return _sdev->set_rx_freq(target_freq); - } - - tune_result_t set_rx_freq(double target_freq, double lo_off){ - return _sdev->set_rx_freq(target_freq, lo_off); - } - - double get_rx_freq(void){ - return _sdev->get_rx_freq(); - } - - freq_range_t get_rx_freq_range(void){ - return _sdev->get_rx_freq_range(); - } - - void set_rx_gain(float gain){ - return _sdev->set_rx_gain(gain); - } - - float get_rx_gain(void){ - return _sdev->get_rx_gain(); - } - - gain_range_t get_rx_gain_range(void){ - return _sdev->get_rx_gain_range(); - } - - void set_rx_antenna(const std::string &ant){ - return _sdev->set_rx_antenna(ant); - } - - std::string get_rx_antenna(void){ - return _sdev->get_rx_antenna(); - } - - std::vector get_rx_antennas(void){ - return _sdev->get_rx_antennas(); - } - - bool get_rx_lo_locked(void){ - return _sdev->get_rx_lo_locked(); - } - - float read_rssi(void){ - return _sdev->read_rssi(); - } - - dboard_iface::sptr get_rx_dboard_iface(void){ - return _sdev->get_rx_dboard_iface(); - } - - void set_rx_bandwidth(float bandwidth) { - return _sdev->set_rx_bandwidth(bandwidth); - } - - /******************************************************************* - * TX methods - ******************************************************************/ - void set_tx_subdev_spec(const subdev_spec_t &spec){ - return _sdev->set_tx_subdev_spec(spec); - } - - subdev_spec_t get_tx_subdev_spec(void){ - return _sdev->get_tx_subdev_spec(); - } - - void set_tx_rate(double rate){ - return _sdev->set_tx_rate(rate); - } - - double get_tx_rate(void){ - return _sdev->get_tx_rate(); - } - - tune_result_t set_tx_freq(double target_freq){ - return _sdev->set_tx_freq(target_freq); - } - - tune_result_t set_tx_freq(double target_freq, double lo_off){ - return _sdev->set_tx_freq(target_freq, lo_off); - } - - double get_tx_freq(void){ - return _sdev->get_tx_freq(); - } - - freq_range_t get_tx_freq_range(void){ - return _sdev->get_tx_freq_range(); - } - - void set_tx_gain(float gain){ - return _sdev->set_tx_gain(gain); - } - - float get_tx_gain(void){ - return _sdev->get_tx_gain(); - } - - gain_range_t get_tx_gain_range(void){ - return _sdev->get_tx_gain_range(); - } - - void set_tx_antenna(const std::string &ant){ - return _sdev->set_tx_antenna(ant); - } - - std::string get_tx_antenna(void){ - return _sdev->get_tx_antenna(); - } - - std::vector get_tx_antennas(void){ - return _sdev->get_tx_antennas(); - } - - bool get_tx_lo_locked(void){ - return _sdev->get_tx_lo_locked(); - } - - dboard_iface::sptr get_tx_dboard_iface(void){ - return _sdev->get_tx_dboard_iface(); - } - -private: - single_usrp::sptr _sdev; -}; - -/*********************************************************************** - * The Make Function - **********************************************************************/ -simple_usrp::sptr simple_usrp::make(const device_addr_t &dev_addr){ - uhd::print_warning( - "The simple USRP interface has been deprecated.\n" - "Please switch to the single USRP interface.\n" - "#include \n" - "single_usrp::sptr sdev = single_usrp::make(args);\n" - ); - return sptr(new simple_usrp_impl(dev_addr)); -} -- cgit v1.2.3 From 982ac435e99a7bb9de3838f5919643cfe5cb8851 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 18 Oct 2010 18:24:53 -0700 Subject: multi-usrp: corrected calculations for channel and mboard indexes --- host/lib/usrp/multi_usrp.cpp | 55 ++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 7f7ea77b0..cb44bc468 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -215,27 +215,23 @@ public: } tune_result_t set_rx_freq(double target_freq, size_t chan){ - size_t nchan = get_rx_num_channels(); - tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(nchan/chan), nchan%chan, target_freq); + tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm(), target_freq); do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX"); return r; } tune_result_t set_rx_freq(double target_freq, double lo_off, size_t chan){ - size_t nchan = get_rx_num_channels(); - tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(nchan/chan), nchan%chan, target_freq, lo_off); + tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm(), target_freq, lo_off); do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX"); return r; } double get_rx_freq(size_t chan){ - size_t nchan = get_rx_num_channels(); - return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(nchan/chan), nchan%chan); + return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm()); } freq_range_t get_rx_freq_range(size_t chan){ - size_t nchan = get_rx_num_channels(); - return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp(nchan/chan)); + return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp(chan/rx_cpm())); } void set_rx_gain(float gain, size_t chan){ @@ -321,27 +317,23 @@ public: } tune_result_t set_tx_freq(double target_freq, size_t chan){ - size_t nchan = get_tx_num_channels(); - tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(nchan/chan), nchan%chan, target_freq); + tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm(), target_freq); do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX"); return r; } tune_result_t set_tx_freq(double target_freq, double lo_off, size_t chan){ - size_t nchan = get_tx_num_channels(); - tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(nchan/chan), nchan%chan, target_freq, lo_off); + tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm(), target_freq, lo_off); do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX"); return r; } double get_tx_freq(size_t chan){ - size_t nchan = get_tx_num_channels(); - return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(nchan/chan), nchan%chan); + return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm()); } freq_range_t get_tx_freq_range(size_t chan){ - size_t nchan = get_tx_num_channels(); - return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp(nchan/chan)); + return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp(chan/tx_cpm())); } void set_tx_gain(float gain, size_t chan){ @@ -378,6 +370,15 @@ public: private: device::sptr _dev; + + size_t rx_cpm(void){ //channels per mboard + return get_rx_num_channels()/get_num_mboards(); + } + + size_t tx_cpm(void){ //channels per mboard + return get_tx_num_channels()/get_num_mboards(); + } + wax::obj _mboard(size_t mboard){ std::string mb_name = (*_dev)[DEVICE_PROP_MBOARD_NAMES].as().at(mboard); return (*_dev)[named_prop_t(DEVICE_PROP_MBOARD, mb_name)]; @@ -389,33 +390,27 @@ private: return _mboard(mboard)[MBOARD_PROP_TX_DSP]; } wax::obj _rx_dboard(size_t chan){ - size_t nchan = get_rx_num_channels(); - std::string db_name = get_rx_subdev_spec(chan/nchan).at(chan%nchan).db_name; - return _mboard(chan/nchan)[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; + std::string db_name = get_rx_subdev_spec(chan/rx_cpm()).at(chan%rx_cpm()).db_name; + return _mboard(chan/rx_cpm())[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; } wax::obj _tx_dboard(size_t chan){ - size_t nchan = get_tx_num_channels(); - std::string db_name = get_tx_subdev_spec(chan/nchan).at(chan%nchan).db_name; - return _mboard(chan/nchan)[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; + std::string db_name = get_tx_subdev_spec(chan/tx_cpm()).at(chan%tx_cpm()).db_name; + return _mboard(chan/tx_cpm())[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; } wax::obj _rx_subdev(size_t chan){ - size_t nchan = get_rx_num_channels(); - std::string sd_name = get_rx_subdev_spec(chan/nchan).at(chan%nchan).sd_name; + std::string sd_name = get_rx_subdev_spec(chan/rx_cpm()).at(chan%rx_cpm()).sd_name; return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; } wax::obj _tx_subdev(size_t chan){ - size_t nchan = get_tx_num_channels(); - std::string sd_name = get_tx_subdev_spec(chan/nchan).at(chan%nchan).sd_name; + std::string sd_name = get_tx_subdev_spec(chan/tx_cpm()).at(chan%tx_cpm()).sd_name; return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; } gain_group::sptr _rx_gain_group(size_t chan){ - size_t nchan = get_rx_num_channels(); - std::string sd_name = get_rx_subdev_spec(chan/nchan).at(chan%nchan).sd_name; + std::string sd_name = get_rx_subdev_spec(chan/rx_cpm()).at(chan%rx_cpm()).sd_name; return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); } gain_group::sptr _tx_gain_group(size_t chan){ - size_t nchan = get_tx_num_channels(); - std::string sd_name = get_tx_subdev_spec(chan/nchan).at(chan%nchan).sd_name; + std::string sd_name = get_tx_subdev_spec(chan/tx_cpm()).at(chan%tx_cpm()).sd_name; return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as(); } }; -- cgit v1.2.3 From cd05791ac1f8a844517add54f005d019b201ebcd Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 19 Oct 2010 01:21:34 -0700 Subject: uhd: made ticks signed in time spec, fixed full secs implementation, added unit tests --- host/include/uhd/types/time_spec.hpp | 4 +-- host/lib/types.cpp | 21 ++++++++----- host/test/CMakeLists.txt | 1 + host/test/time_spec_test.cpp | 61 ++++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 9 deletions(-) create mode 100644 host/test/time_spec_test.cpp diff --git a/host/include/uhd/types/time_spec.hpp b/host/include/uhd/types/time_spec.hpp index 59b85f4b7..57d002d48 100644 --- a/host/include/uhd/types/time_spec.hpp +++ b/host/include/uhd/types/time_spec.hpp @@ -59,7 +59,7 @@ namespace uhd{ * \param tick_count the fractional seconds tick count * \param tick_rate the number of ticks per second */ - time_spec_t(time_t full_secs, size_t tick_count, double tick_rate); + time_spec_t(time_t full_secs, long tick_count, double tick_rate); /*! * Convert the fractional seconds to clock ticks. @@ -67,7 +67,7 @@ namespace uhd{ * \param tick_rate the number of ticks per second * \return the fractional seconds tick count */ - size_t get_tick_count(double tick_rate) const; + long get_tick_count(double tick_rate) const; /*! * Get the time as a real-valued seconds count. diff --git a/host/lib/types.cpp b/host/lib/types.cpp index f957cd83f..6aa82b012 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -124,14 +124,14 @@ time_spec_t::time_spec_t(time_t full_secs, double frac_secs): /* NOP */ } -time_spec_t::time_spec_t(time_t full_secs, size_t tick_count, double tick_rate): +time_spec_t::time_spec_t(time_t full_secs, long tick_count, double tick_rate): _full_secs(full_secs), _frac_secs(double(tick_count)/tick_rate) { /* NOP */ } -size_t time_spec_t::get_tick_count(double tick_rate) const{ +long time_spec_t::get_tick_count(double tick_rate) const{ return boost::math::iround(this->get_frac_secs()*tick_rate); } @@ -140,7 +140,9 @@ double time_spec_t::get_real_secs(void) const{ } time_t time_spec_t::get_full_secs(void) const{ - return this->_full_secs + time_t(std::floor(this->_frac_secs)); + double intpart; + std::modf(this->_frac_secs, &intpart); + return this->_full_secs + time_t(intpart); } double time_spec_t::get_frac_secs(void) const{ @@ -160,13 +162,18 @@ time_spec_t &time_spec_t::operator-=(const time_spec_t &rhs){ } bool uhd::operator==(const time_spec_t &lhs, const time_spec_t &rhs){ - return lhs.get_full_secs() == rhs.get_full_secs() and lhs.get_frac_secs() == rhs.get_frac_secs(); + return + lhs.get_full_secs() == rhs.get_full_secs() and + lhs.get_frac_secs() == rhs.get_frac_secs() + ; } bool uhd::operator<(const time_spec_t &lhs, const time_spec_t &rhs){ - if (lhs.get_full_secs() < rhs.get_full_secs()) return true; - if (lhs.get_full_secs() > rhs.get_full_secs()) return false; - return lhs.get_frac_secs() < rhs.get_frac_secs(); + return ( + (lhs.get_full_secs() < rhs.get_full_secs()) or ( + (lhs.get_full_secs() == rhs.get_full_secs()) and + (lhs.get_frac_secs() < rhs.get_frac_secs()) + )); } /*********************************************************************** diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt index c620fd641..fb075ea07 100644 --- a/host/test/CMakeLists.txt +++ b/host/test/CMakeLists.txt @@ -28,6 +28,7 @@ ADD_EXECUTABLE(main_test error_test.cpp gain_group_test.cpp subdev_spec_test.cpp + time_spec_test.cpp tune_helper_test.cpp vrt_test.cpp warning_test.cpp diff --git a/host/test/time_spec_test.cpp b/host/test/time_spec_test.cpp new file mode 100644 index 000000000..5ad782160 --- /dev/null +++ b/host/test/time_spec_test.cpp @@ -0,0 +1,61 @@ +// +// 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 + +BOOST_AUTO_TEST_CASE(test_time_spec_compare){ + std::cout << "Testing time specification compare..." << std::endl; + + BOOST_CHECK(uhd::time_spec_t(2.0) == uhd::time_spec_t(2.0)); + BOOST_CHECK(uhd::time_spec_t(2.0) > uhd::time_spec_t(1.0)); + BOOST_CHECK(uhd::time_spec_t(1.0) < uhd::time_spec_t(2.0)); + + BOOST_CHECK(uhd::time_spec_t(1.1) == uhd::time_spec_t(1.1)); + BOOST_CHECK(uhd::time_spec_t(1.1) > uhd::time_spec_t(1.0)); + BOOST_CHECK(uhd::time_spec_t(1.0) < uhd::time_spec_t(1.1)); + + BOOST_CHECK(uhd::time_spec_t(0.1) == uhd::time_spec_t(0.1)); + BOOST_CHECK(uhd::time_spec_t(0.2) > uhd::time_spec_t(0.1)); + BOOST_CHECK(uhd::time_spec_t(0.1) < uhd::time_spec_t(0.2)); +} + +#define CHECK_TS_EQUAL(lhs, rhs) \ + BOOST_CHECK_CLOSE((lhs).get_real_secs(), (rhs).get_real_secs(), 0.001) + +BOOST_AUTO_TEST_CASE(test_time_spec_arithmetic){ + std::cout << "Testing time specification arithmetic..." << std::endl; + + CHECK_TS_EQUAL(uhd::time_spec_t(2.3) + uhd::time_spec_t(1.0), uhd::time_spec_t(3.3)); + CHECK_TS_EQUAL(uhd::time_spec_t(2.3) - uhd::time_spec_t(1.0), uhd::time_spec_t(1.3)); + CHECK_TS_EQUAL(uhd::time_spec_t(1.0) + uhd::time_spec_t(2.3), uhd::time_spec_t(3.3)); + CHECK_TS_EQUAL(uhd::time_spec_t(1.0) - uhd::time_spec_t(2.3), uhd::time_spec_t(-1.3)); +} + +BOOST_AUTO_TEST_CASE(test_time_spec_parts){ + std::cout << "Testing time specification parts..." << std::endl; + + BOOST_CHECK_EQUAL(uhd::time_spec_t(1.1).get_full_secs(), 1); + BOOST_CHECK_CLOSE(uhd::time_spec_t(1.1).get_frac_secs(), 0.1, 0.001); + BOOST_CHECK_EQUAL(uhd::time_spec_t(1.1).get_tick_count(100), 10); + + BOOST_CHECK_EQUAL(uhd::time_spec_t(-1.1).get_full_secs(), -1); + BOOST_CHECK_CLOSE(uhd::time_spec_t(-1.1).get_frac_secs(), -0.1, 0.001); + BOOST_CHECK_EQUAL(uhd::time_spec_t(-1.1).get_tick_count(100), -10); +} -- cgit v1.2.3 From 561bb73ee3fca52e6d711de1030f027b30fcefaa Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 19 Oct 2010 10:37:00 -0700 Subject: uhd: split unit tests into individual tests by file + they get installed --- host/test/CMakeLists.txt | 17 +++++++++++++---- host/test/main_test.cpp | 3 --- 2 files changed, 13 insertions(+), 7 deletions(-) delete mode 100644 host/test/main_test.cpp diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt index fb075ea07..d67399e5b 100644 --- a/host/test/CMakeLists.txt +++ b/host/test/CMakeLists.txt @@ -18,8 +18,7 @@ ######################################################################## # unit test suite ######################################################################## -ADD_EXECUTABLE(main_test - main_test.cpp +SET(test_sources addr_test.cpp buffer_test.cpp byteswap_test.cpp @@ -34,8 +33,18 @@ ADD_EXECUTABLE(main_test warning_test.cpp wax_test.cpp ) -TARGET_LINK_LIBRARIES(main_test uhd) -ADD_TEST(test main_test) + +#turn each test cpp file into an executable with an int main() function +ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK -DBOOST_TEST_MAIN) + +#for each source: build an executable, register it as a test, and install +FOREACH(test_source ${test_sources}) + GET_FILENAME_COMPONENT(test_name ${test_source} NAME_WE) + ADD_EXECUTABLE(${test_name} ${test_source}) + TARGET_LINK_LIBRARIES(${test_name} uhd) + ADD_TEST(${test_name} ${test_name}) + INSTALL(TARGETS ${test_name} RUNTIME DESTINATION ${PKG_DATA_DIR}/tests) +ENDFOREACH(test_source) ######################################################################## # demo of a loadable module diff --git a/host/test/main_test.cpp b/host/test/main_test.cpp deleted file mode 100644 index 0b47303b7..000000000 --- a/host/test/main_test.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MAIN -#include -- cgit v1.2.3 From 083413de3dc67e34042ec4e3e77b0ebfaf19009b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 19 Oct 2010 13:04:07 -0700 Subject: multi-usrp: fixed num channel calculation, moved logic to cpm functions --- host/lib/usrp/multi_usrp.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index cb44bc468..6df3afbf8 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -190,13 +190,7 @@ public: } size_t get_rx_num_channels(void){ - size_t nchan = get_rx_subdev_spec(0).size(); - for (size_t m = 1; m < get_num_mboards(); m++){ - if (nchan != get_rx_subdev_spec(m).size()){ - throw std::runtime_error("rx subdev spec size inconsistent across all mboards"); - } - } - return nchan; + return rx_cpm()*get_num_mboards(); //total num channels } std::string get_rx_subdev_name(size_t chan){ @@ -296,13 +290,7 @@ public: } size_t get_tx_num_channels(void){ - size_t nchan = get_tx_subdev_spec(0).size(); - for (size_t m = 1; m < get_num_mboards(); m++){ - if (nchan != get_tx_subdev_spec(m).size()){ - throw std::runtime_error("tx subdev spec size inconsistent across all mboards"); - } - } - return nchan; + return tx_cpm()*get_num_mboards(); //total num channels } void set_tx_rate(double rate){ @@ -372,11 +360,23 @@ private: device::sptr _dev; size_t rx_cpm(void){ //channels per mboard - return get_rx_num_channels()/get_num_mboards(); + size_t nchan = get_rx_subdev_spec(0).size(); + for (size_t m = 1; m < get_num_mboards(); m++){ + if (nchan != get_rx_subdev_spec(m).size()){ + throw std::runtime_error("rx subdev spec size inconsistent across all mboards"); + } + } + return nchan; } size_t tx_cpm(void){ //channels per mboard - return get_tx_num_channels()/get_num_mboards(); + size_t nchan = get_tx_subdev_spec(0).size(); + for (size_t m = 1; m < get_num_mboards(); m++){ + if (nchan != get_tx_subdev_spec(m).size()){ + throw std::runtime_error("tx subdev spec size inconsistent across all mboards"); + } + } + return nchan; } wax::obj _mboard(size_t mboard){ -- cgit v1.2.3 From 799d5059bae77a24267cfc33b33c4af1c0de8c5b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 19 Oct 2010 15:42:21 -0700 Subject: usrp: change the bandwidth param to a double (its a frequency), add set and gets for BW in the wrappers --- host/include/uhd/usrp/multi_usrp.hpp | 8 ++++++-- host/include/uhd/usrp/single_usrp.hpp | 8 ++++++-- host/lib/usrp/dboard/db_dbsrx.cpp | 18 ++++++------------ host/lib/usrp/dboard/db_xcvr2450.cpp | 20 ++++++++++---------- host/lib/usrp/multi_usrp.cpp | 20 ++++++++++++++++---- host/lib/usrp/single_usrp.cpp | 20 ++++++++++++++++---- 6 files changed, 60 insertions(+), 34 deletions(-) diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 65c7e9044..dcec0c515 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -201,6 +201,9 @@ public: virtual bool get_rx_lo_locked(size_t chan) = 0; + virtual void set_rx_bandwidth(double bandwidth, size_t chan) = 0; + virtual double get_rx_bandwidth(size_t chan) = 0; + /*! * Read the RSSI value from a usrp device. * Or throw if the dboard does not support an RSSI readback. @@ -209,8 +212,6 @@ public: virtual float read_rssi(size_t chan) = 0; virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan) = 0; - - virtual void set_rx_bandwidth(float bandwidth, size_t chan) = 0; /******************************************************************* * TX methods @@ -251,6 +252,9 @@ public: virtual bool get_tx_lo_locked(size_t chan) = 0; + virtual void set_tx_bandwidth(double bandwidth, size_t chan) = 0; + virtual double get_tx_bandwidth(size_t chan) = 0; + virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan) = 0; }; diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index 2266e7f2c..9b2fd7ccf 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -144,6 +144,9 @@ public: virtual bool get_rx_lo_locked(size_t chan = 0) = 0; + virtual void set_rx_bandwidth(double bandwidth, size_t chan = 0) = 0; + virtual double get_rx_bandwidth(size_t chan = 0) = 0; + /*! * Read the RSSI value from a usrp device. * Or throw if the dboard does not support an RSSI readback. @@ -152,8 +155,6 @@ public: virtual float read_rssi(size_t chan = 0) = 0; virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan = 0) = 0; - - virtual void set_rx_bandwidth(float bandwidth, size_t chan = 0) = 0; /******************************************************************* * TX methods @@ -186,6 +187,9 @@ public: virtual bool get_tx_lo_locked(size_t chan = 0) = 0; + virtual void set_tx_bandwidth(double bandwidth, size_t chan = 0) = 0; + virtual double get_tx_bandwidth(size_t chan = 0) = 0; + virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan = 0) = 0; }; diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 99137dda3..939a79e58 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -69,7 +69,7 @@ public: private: double _lo_freq; - float _bandwidth; + double _bandwidth; uhd::dict _gains; max2118_write_regs_t _max2118_write_regs; max2118_read_regs_t _max2118_read_regs; @@ -79,7 +79,7 @@ private: void set_lo_freq(double target_freq); void set_gain(float gain, const std::string &name); - void set_bandwidth(float bandwidth); + void set_bandwidth(double bandwidth); void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0x5)); @@ -482,9 +482,9 @@ void dbsrx::set_gain(float gain, const std::string &name){ /*********************************************************************** * Bandwidth Handling **********************************************************************/ -void dbsrx::set_bandwidth(float bandwidth){ +void dbsrx::set_bandwidth(double bandwidth){ //clip the input - bandwidth = std::clip(bandwidth, 4e6, 33e6); + bandwidth = std::clip(bandwidth, 4e6, 33e6); double ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX); @@ -494,7 +494,7 @@ void dbsrx::set_bandwidth(float bandwidth){ _max2118_write_regs.f_dac = std::clip(int((((bandwidth*_max2118_write_regs.m_divider)/ref_clock) - 4)/0.145),0,127); //determine actual bandwidth - _bandwidth = float((ref_clock/(_max2118_write_regs.m_divider))*(4+0.145*_max2118_write_regs.f_dac)); + _bandwidth = double((ref_clock/(_max2118_write_regs.m_divider))*(4+0.145*_max2118_write_regs.f_dac)); if (dbsrx_debug) std::cerr << boost::format( "DBSRX Filter Bandwidth: %f MHz, m: %d, f_dac: %d\n" @@ -565,12 +565,6 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){ val = this->get_locked(); return; -/* - case SUBDEV_PROP_RSSI: - val = this->get_rssi(); - return; -*/ - case SUBDEV_PROP_BANDWIDTH: val = _bandwidth; return; @@ -597,7 +591,7 @@ void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - this->set_bandwidth(val.as()); + this->set_bandwidth(val.as()); return; default: UHD_THROW_PROP_SET_ERROR(); diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 314c85a69..99f2a231c 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -102,7 +102,7 @@ public: private: double _lo_freq; - float _rx_bandwidth, _tx_bandwidth; + double _rx_bandwidth, _tx_bandwidth; uhd::dict _tx_gains, _rx_gains; std::string _tx_ant, _rx_ant; int _ad9515div; @@ -113,8 +113,8 @@ private: void set_rx_ant(const std::string &ant); void set_tx_gain(float gain, const std::string &name); void set_rx_gain(float gain, const std::string &name); - void set_rx_bandwidth(float bandwidth); - void set_tx_bandwidth(float bandwidth); + void set_rx_bandwidth(double bandwidth); + void set_tx_bandwidth(double bandwidth); void update_atr(void); void spi_reset(void); @@ -455,7 +455,7 @@ void xcvr2450::set_rx_gain(float gain, const std::string &name){ /*********************************************************************** * Bandwidth Handling **********************************************************************/ -static max2829_regs_t::tx_lpf_coarse_adj_t bandwidth_to_tx_lpf_coarse_reg(float &bandwidth){ +static max2829_regs_t::tx_lpf_coarse_adj_t bandwidth_to_tx_lpf_coarse_reg(double &bandwidth){ int reg = std::clip(boost::math::iround((bandwidth-6.0e6)/6.0e6), 1, 3); switch(reg){ @@ -472,7 +472,7 @@ static max2829_regs_t::tx_lpf_coarse_adj_t bandwidth_to_tx_lpf_coarse_reg(float UHD_THROW_INVALID_CODE_PATH(); } -static max2829_regs_t::rx_lpf_fine_adj_t bandwidth_to_rx_lpf_fine_reg(float &bandwidth, float requested_bandwidth){ +static max2829_regs_t::rx_lpf_fine_adj_t bandwidth_to_rx_lpf_fine_reg(double &bandwidth, double requested_bandwidth){ int reg = std::clip(boost::math::iround((requested_bandwidth/bandwidth)/0.05), 18, 22); switch(reg){ @@ -495,7 +495,7 @@ static max2829_regs_t::rx_lpf_fine_adj_t bandwidth_to_rx_lpf_fine_reg(float &ban UHD_THROW_INVALID_CODE_PATH(); } -static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(float &bandwidth){ +static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(double &bandwidth){ int reg = std::clip(boost::math::iround((bandwidth-7.0e6)/1.0e6), 0, 11); switch(reg){ @@ -523,7 +523,7 @@ static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(float UHD_THROW_INVALID_CODE_PATH(); } -void xcvr2450::set_rx_bandwidth(float bandwidth){ +void xcvr2450::set_rx_bandwidth(double bandwidth){ float requested_bandwidth = bandwidth; //compute coarse low pass cutoff frequency setting @@ -543,7 +543,7 @@ void xcvr2450::set_rx_bandwidth(float bandwidth){ ) % _rx_bandwidth % (int(_max2829_regs.rx_lpf_coarse_adj)) % (int(_max2829_regs.rx_lpf_fine_adj)) << std::endl; } -void xcvr2450::set_tx_bandwidth(float bandwidth){ +void xcvr2450::set_tx_bandwidth(double bandwidth){ //compute coarse low pass cutoff frequency setting _max2829_regs.tx_lpf_coarse_adj = bandwidth_to_tx_lpf_coarse_reg(bandwidth); @@ -652,7 +652,7 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - this->set_rx_bandwidth(val.as()); + this->set_rx_bandwidth(val.as()); return; case SUBDEV_PROP_ENABLED: @@ -747,7 +747,7 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - this->set_tx_bandwidth(val.as()); + this->set_tx_bandwidth(val.as()); return; case SUBDEV_PROP_ANTENNA: diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 6df3afbf8..027530f31 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -256,6 +256,14 @@ public: return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); } + void set_rx_bandwidth(double bandwidth, size_t chan){ + _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + double get_rx_bandwidth(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as(); + } + float read_rssi(size_t chan){ return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); } @@ -263,10 +271,6 @@ public: dboard_iface::sptr get_rx_dboard_iface(size_t chan){ return _rx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); } - - void set_rx_bandwidth(float bandwidth, size_t chan) { - _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; - } /******************************************************************* * TX methods @@ -352,6 +356,14 @@ public: return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); } + void set_tx_bandwidth(double bandwidth, size_t chan){ + _tx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + double get_tx_bandwidth(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as(); + } + dboard_iface::sptr get_tx_dboard_iface(size_t chan){ return _tx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); } diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index 7a4df3eb5..2faa1280c 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -192,6 +192,14 @@ public: return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); } + void set_rx_bandwidth(double bandwidth, size_t chan){ + _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + double get_rx_bandwidth(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as(); + } + float read_rssi(size_t chan){ return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); } @@ -199,10 +207,6 @@ public: dboard_iface::sptr get_rx_dboard_iface(size_t chan){ return _rx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); } - - void set_rx_bandwidth(float bandwidth, size_t chan) { - _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; - } /******************************************************************* * TX methods @@ -276,6 +280,14 @@ public: return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); } + void set_tx_bandwidth(double bandwidth, size_t chan){ + _tx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + double get_tx_bandwidth(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as(); + } + dboard_iface::sptr get_tx_dboard_iface(size_t chan){ return _tx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); } -- cgit v1.2.3 From b405abf883a5b37de1468cde679644927d89abce Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 19 Oct 2010 17:13:56 -0700 Subject: uhd: remove some warnings in MSVC and with typo in xcvr2450 --- host/include/uhd/config.hpp | 5 +++-- host/lib/usrp/dboard/db_xcvr2450.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp index dacd3a96b..2918c2340 100644 --- a/host/include/uhd/config.hpp +++ b/host/include/uhd/config.hpp @@ -31,11 +31,12 @@ # pragma warning(disable: 4251) // class 'A' needs to have dll-interface to be used by clients of class 'B' //# pragma warning(disable: 4127) // conditional expression is constant //# pragma warning(disable: 4290) // C++ exception specification ignored except to ... -# pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored +//# pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored # pragma warning(disable: 4275) // non dll-interface class ... used as base for dll-interface class ... //# pragma warning(disable: 4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data //# pragma warning(disable: 4511) // 'class' : copy constructor could not be generated -# pragma warning(disable: 4250) // 'class' : inherits 'method' via dominance +//# pragma warning(disable: 4250) // 'class' : inherits 'method' via dominance +# pragma warning(disable: 4200) // nonstandard extension used : zero-sized array in struct/union #endif // define logical operators diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 99f2a231c..fb1367113 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -524,7 +524,7 @@ static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(double } void xcvr2450::set_rx_bandwidth(double bandwidth){ - float requested_bandwidth = bandwidth; + double requested_bandwidth = bandwidth; //compute coarse low pass cutoff frequency setting _max2829_regs.rx_lpf_coarse_adj = bandwidth_to_rx_lpf_coarse_reg(bandwidth); -- cgit v1.2.3 From 9efacf196c4f2f3a25e58db9d60028cea7ebb6ed Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 19 Oct 2010 22:05:03 -0700 Subject: usrp: updated docs to reflect switch to multi-usrp interface --- host/docs/coding.rst | 8 ++++---- host/docs/usrp2.rst | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/host/docs/coding.rst b/host/docs/coding.rst index d6a19d250..7533445ea 100644 --- a/host/docs/coding.rst +++ b/host/docs/coding.rst @@ -41,13 +41,13 @@ The single usrp provides ways to: See the documentation in *usrp/single_usrp.hpp* for reference. ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -High-Level: The mimo usrp +High-Level: The multi usrp ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The mimo usrp API provides a wrapper around a device that represents several motherboards. +The multi usrp API provides a wrapper around a device that represents several motherboards. This API provides convenience calls just like the single usrp, however the calls either work across all channels in the configuration, or take a channel argument to specify which channel to configure. -The mimo usrp provides ways to: +The multi usrp provides ways to: * Set and get the sample rate across all channels. * Issue a stream command across all channels. @@ -57,7 +57,7 @@ The mimo usrp provides ways to: * Tune individual DSPs and daughterboards. * Get the underlying device (as discussed above). -See the documentation in *usrp/mimo_usrp.hpp* for reference. +See the documentation in *usrp/multi_usrp.hpp* for reference. ------------------------------------------------------------------------ Integrating custom hardware diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index 1ebab388a..0ddcaa4e5 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -158,7 +158,7 @@ The value for the addr key is a white-space separated list of IPv4 addresses or resolvable hostnames. The first address in the list will represent channel 0, the second channel 1, and so on... -Use this addressing scheme with the *mimo_usrp* interface. +Use this addressing scheme with the *multi_usrp* interface. The device address string representation for 2 USRP2s with IPv4 addresses 192.168.10.2 and 192.168.20.2 :: -- cgit v1.2.3 From e0c48ba5cc1033cd330e2ce73ceb03740923e954 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 20 Oct 2010 12:11:26 -0700 Subject: usrp: added docstrings to single and multi usrp for undocumented methods --- host/include/uhd/usrp/multi_usrp.hpp | 219 +++++++++++++++++++++++++++++++++- host/include/uhd/usrp/single_usrp.hpp | 217 ++++++++++++++++++++++++++++++++- 2 files changed, 432 insertions(+), 4 deletions(-) diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index dcec0c515..6adba85bd 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -170,8 +170,16 @@ public: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. * The subdev spec must be the same size across all motherboards. + * \param spec the new subdevice specification + * \param mboard the motherboard index 0 to M-1 */ virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard) = 0; + + /*! + * Get the RX subdevice specification. + * \param mboard the motherboard index 0 to M-1 + * \return the subdevice specification in use + */ virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(size_t mboard) = 0; /*! @@ -181,36 +189,136 @@ public: */ virtual size_t get_rx_num_channels(void) = 0; + /*! + * Get the name of the RX subdevice. + * \param chan the channel index 0 to N-1 + * \return the subdevice name + */ virtual std::string get_rx_subdev_name(size_t chan) = 0; + /*! + * Set the RX sample rate across all channels. + * \param rate the rate in Sps + */ virtual void set_rx_rate(double rate) = 0; + + /*! + * Gets the RX sample rate for all channels. + * \return the rate in Sps + */ virtual double get_rx_rate(void) = 0; + /*! + * Set the RX center frequency. + * \param freq the frequency in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_rx_freq(double freq, size_t chan) = 0; + + /*! + * Set the RX center frequency. + * \param freq the frequency in Hz + * \param lo_off an LO offset in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_rx_freq(double freq, double lo_off, size_t chan) = 0; + + /*! + * Get the RX center frequency. + * \param chan the channel index 0 to N-1 + * \return the frequency in Hz + */ virtual double get_rx_freq(size_t chan) = 0; + + /*! + * Get the RX center frequency range. + * \param chan the channel index 0 to N-1 + * \return a frequency range object + */ virtual freq_range_t get_rx_freq_range(size_t chan) = 0; + /*! + * Set the RX gain: + * Distribute among gain elements in the RX path. + * \param gain the gain in dB + * \param chan the channel index 0 to N-1 + */ virtual void set_rx_gain(float gain, size_t chan) = 0; + + /*! + * Get the RX gain: + * Summation of gain elements in the RX path. + * \param chan the channel index 0 to N-1 + * \return the gain in dB + */ virtual float get_rx_gain(size_t chan) = 0; + + /*! + * Get the RX gain range. + * \param chan the channel index 0 to N-1 + * \return a gain range object + */ virtual gain_range_t get_rx_gain_range(size_t chan) = 0; + /*! + * Select the RX antenna on the subdevice. + * \param ant the antenna name + * \param chan the channel index 0 to N-1 + */ virtual void set_rx_antenna(const std::string &ant, size_t chan) = 0; + + /*! + * Get the selected RX antenna on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the antenna name + */ virtual std::string get_rx_antenna(size_t chan) = 0; + + /*! + * Get a list of possible RX antennas on the subdevice. + * \param chan the channel index 0 to N-1 + * \return a vector of antenna names + */ virtual std::vector get_rx_antennas(size_t chan) = 0; + /*! + * Get the locked status of the LO on the subdevice. + * \param chan the channel index 0 to N-1 + * \return true for locked + */ virtual bool get_rx_lo_locked(size_t chan) = 0; + /*! + * Set the RX bandwidth on the subdevice. + * \param bandwidth the bandwidth in Hz + * \param chan the channel index 0 to N-1 + */ virtual void set_rx_bandwidth(double bandwidth, size_t chan) = 0; + + /*! + * Get the RX bandwidth on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the bandwidth in Hz + */ virtual double get_rx_bandwidth(size_t chan) = 0; /*! - * Read the RSSI value from a usrp device. - * Or throw if the dboard does not support an RSSI readback. + * Read the RSSI value on the RX subdevice. + * \param chan the channel index 0 to N-1 * \return the rssi in dB + * \throw exception if RSSI readback not supported */ virtual float read_rssi(size_t chan) = 0; + /*! + * Get the dboard interface object for the RX subdevice. + * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. + * Use at your own risk! + * \param chan the channel index 0 to N-1 + * \return the dboard interface sptr + */ virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan) = 0; /******************************************************************* @@ -221,8 +329,16 @@ public: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. * The subdev spec must be the same size across all motherboards. + * \param spec the new subdevice specification + * \param mboard the motherboard index 0 to M-1 */ virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard) = 0; + + /*! + * Get the TX subdevice specification. + * \param mboard the motherboard index 0 to M-1 + * \return the subdevice specification in use + */ virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(size_t mboard) = 0; /*! @@ -232,29 +348,128 @@ public: */ virtual size_t get_tx_num_channels(void) = 0; + /*! + * Get the name of the TX subdevice. + * \param chan the channel index 0 to N-1 + * \return the subdevice name + */ virtual std::string get_tx_subdev_name(size_t chan) = 0; + /*! + * Set the TX sample rate across all channels. + * \param rate the rate in Sps + */ virtual void set_tx_rate(double rate) = 0; + + /*! + * Gets the TX sample rate for all channels. + * \return the rate in Sps + */ virtual double get_tx_rate(void) = 0; + /*! + * Set the TX center frequency. + * \param freq the frequency in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_tx_freq(double freq, size_t chan) = 0; + + /*! + * Set the TX center frequency. + * \param freq the frequency in Hz + * \param lo_off an LO offset in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_tx_freq(double freq, double lo_off, size_t chan) = 0; + + /*! + * Get the TX center frequency. + * \param chan the channel index 0 to N-1 + * \return the frequency in Hz + */ virtual double get_tx_freq(size_t chan) = 0; + + /*! + * Get the TX center frequency range. + * \param chan the channel index 0 to N-1 + * \return a frequency range object + */ virtual freq_range_t get_tx_freq_range(size_t chan) = 0; + /*! + * Set the TX gain: + * Distribute among gain elements in the TX path. + * \param gain the gain in dB + * \param chan the channel index 0 to N-1 + */ virtual void set_tx_gain(float gain, size_t chan) = 0; + + /*! + * Get the TX gain: + * Summation of gain elements in the TX path. + * \param chan the channel index 0 to N-1 + * \return the gain in dB + */ virtual float get_tx_gain(size_t chan) = 0; + + /*! + * Get the TX gain range. + * \param chan the channel index 0 to N-1 + * \return a gain range object + */ virtual gain_range_t get_tx_gain_range(size_t chan) = 0; + /*! + * Select the TX antenna on the subdevice. + * \param ant the antenna name + * \param chan the channel index 0 to N-1 + */ virtual void set_tx_antenna(const std::string &ant, size_t chan) = 0; + + /*! + * Get the selected TX antenna on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the antenna name + */ virtual std::string get_tx_antenna(size_t chan) = 0; + + /*! + * Get a list of possible TX antennas on the subdevice. + * \param chan the channel index 0 to N-1 + * \return a vector of antenna names + */ virtual std::vector get_tx_antennas(size_t chan) = 0; + /*! + * Get the locked status of the LO on the subdevice. + * \param chan the channel index 0 to N-1 + * \return true for locked + */ virtual bool get_tx_lo_locked(size_t chan) = 0; + /*! + * Set the TX bandwidth on the subdevice. + * \param bandwidth the bandwidth in Hz + * \param chan the channel index 0 to N-1 + */ virtual void set_tx_bandwidth(double bandwidth, size_t chan) = 0; + + /*! + * Get the TX bandwidth on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the bandwidth in Hz + */ virtual double get_tx_bandwidth(size_t chan) = 0; + /*! + * Get the dboard interface object for the TX subdevice. + * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. + * Use at your own risk! + * \param chan the channel index 0 to N-1 + * \return the dboard interface sptr + */ virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan) = 0; }; diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index 9b2fd7ccf..74a978f05 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -120,40 +120,147 @@ public: * Set the RX subdevice specification: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. + * The subdev spec must be the same size across all motherboards. + * \param spec the new subdevice specification */ virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; + + /*! + * Get the RX subdevice specification. + * \return the subdevice specification in use + */ virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(void) = 0; + /*! + * Get the name of the RX subdevice. + * \param chan the channel index 0 to N-1 + * \return the subdevice name + */ virtual std::string get_rx_subdev_name(size_t chan = 0) = 0; + /*! + * Set the RX sample rate across all channels. + * \param rate the rate in Sps + */ virtual void set_rx_rate(double rate) = 0; + + /*! + * Gets the RX sample rate for all channels. + * \return the rate in Sps + */ virtual double get_rx_rate(void) = 0; + /*! + * Set the RX center frequency. + * \param freq the frequency in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_rx_freq(double freq, size_t chan = 0) = 0; + + /*! + * Set the RX center frequency. + * \param freq the frequency in Hz + * \param lo_off an LO offset in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_rx_freq(double freq, double lo_off, size_t chan = 0) = 0; + + /*! + * Get the RX center frequency. + * \param chan the channel index 0 to N-1 + * \return the frequency in Hz + */ virtual double get_rx_freq(size_t chan = 0) = 0; + + /*! + * Get the RX center frequency range. + * \param chan the channel index 0 to N-1 + * \return a frequency range object + */ virtual freq_range_t get_rx_freq_range(size_t chan = 0) = 0; + /*! + * Set the RX gain: + * Distribute among gain elements in the RX path. + * \param gain the gain in dB + * \param chan the channel index 0 to N-1 + */ virtual void set_rx_gain(float gain, size_t chan = 0) = 0; + + /*! + * Get the RX gain: + * Summation of gain elements in the RX path. + * \param chan the channel index 0 to N-1 + * \return the gain in dB + */ virtual float get_rx_gain(size_t chan = 0) = 0; + + /*! + * Get the RX gain range. + * \param chan the channel index 0 to N-1 + * \return a gain range object + */ virtual gain_range_t get_rx_gain_range(size_t chan = 0) = 0; + /*! + * Select the RX antenna on the subdevice. + * \param ant the antenna name + * \param chan the channel index 0 to N-1 + */ virtual void set_rx_antenna(const std::string &ant, size_t chan = 0) = 0; + + /*! + * Get the selected RX antenna on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the antenna name + */ virtual std::string get_rx_antenna(size_t chan = 0) = 0; + + /*! + * Get a list of possible RX antennas on the subdevice. + * \param chan the channel index 0 to N-1 + * \return a vector of antenna names + */ virtual std::vector get_rx_antennas(size_t chan = 0) = 0; + /*! + * Get the locked status of the LO on the subdevice. + * \param chan the channel index 0 to N-1 + * \return true for locked + */ virtual bool get_rx_lo_locked(size_t chan = 0) = 0; + /*! + * Set the RX bandwidth on the subdevice. + * \param bandwidth the bandwidth in Hz + * \param chan the channel index 0 to N-1 + */ virtual void set_rx_bandwidth(double bandwidth, size_t chan = 0) = 0; + + /*! + * Get the RX bandwidth on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the bandwidth in Hz + */ virtual double get_rx_bandwidth(size_t chan = 0) = 0; /*! - * Read the RSSI value from a usrp device. - * Or throw if the dboard does not support an RSSI readback. + * Read the RSSI value on the RX subdevice. + * \param chan the channel index 0 to N-1 * \return the rssi in dB + * \throw exception if RSSI readback not supported */ virtual float read_rssi(size_t chan = 0) = 0; + /*! + * Get the dboard interface object for the RX subdevice. + * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. + * Use at your own risk! + * \param chan the channel index 0 to N-1 + * \return the dboard interface sptr + */ virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan = 0) = 0; /******************************************************************* @@ -163,33 +270,139 @@ public: * Set the TX subdevice specification: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. + * The subdev spec must be the same size across all motherboards. + * \param spec the new subdevice specification */ virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; + + /*! + * Get the TX subdevice specification. + * \return the subdevice specification in use + */ virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(void) = 0; + /*! + * Get the name of the TX subdevice. + * \param chan the channel index 0 to N-1 + * \return the subdevice name + */ virtual std::string get_tx_subdev_name(size_t chan = 0) = 0; + /*! + * Set the TX sample rate across all channels. + * \param rate the rate in Sps + */ virtual void set_tx_rate(double rate) = 0; + + /*! + * Gets the TX sample rate for all channels. + * \return the rate in Sps + */ virtual double get_tx_rate(void) = 0; + /*! + * Set the TX center frequency. + * \param freq the frequency in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_tx_freq(double freq, size_t chan = 0) = 0; + + /*! + * Set the TX center frequency. + * \param freq the frequency in Hz + * \param lo_off an LO offset in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ virtual tune_result_t set_tx_freq(double freq, double lo_off, size_t chan = 0) = 0; + + /*! + * Get the TX center frequency. + * \param chan the channel index 0 to N-1 + * \return the frequency in Hz + */ virtual double get_tx_freq(size_t chan = 0) = 0; + + /*! + * Get the TX center frequency range. + * \param chan the channel index 0 to N-1 + * \return a frequency range object + */ virtual freq_range_t get_tx_freq_range(size_t chan = 0) = 0; + /*! + * Set the TX gain: + * Distribute among gain elements in the TX path. + * \param gain the gain in dB + * \param chan the channel index 0 to N-1 + */ virtual void set_tx_gain(float gain, size_t chan = 0) = 0; + + /*! + * Get the TX gain: + * Summation of gain elements in the TX path. + * \param chan the channel index 0 to N-1 + * \return the gain in dB + */ virtual float get_tx_gain(size_t chan = 0) = 0; + + /*! + * Get the TX gain range. + * \param chan the channel index 0 to N-1 + * \return a gain range object + */ virtual gain_range_t get_tx_gain_range(size_t chan = 0) = 0; + /*! + * Select the TX antenna on the subdevice. + * \param ant the antenna name + * \param chan the channel index 0 to N-1 + */ virtual void set_tx_antenna(const std::string &ant, size_t chan = 0) = 0; + + /*! + * Get the selected TX antenna on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the antenna name + */ virtual std::string get_tx_antenna(size_t chan = 0) = 0; + + /*! + * Get a list of possible TX antennas on the subdevice. + * \param chan the channel index 0 to N-1 + * \return a vector of antenna names + */ virtual std::vector get_tx_antennas(size_t chan = 0) = 0; + /*! + * Get the locked status of the LO on the subdevice. + * \param chan the channel index 0 to N-1 + * \return true for locked + */ virtual bool get_tx_lo_locked(size_t chan = 0) = 0; + /*! + * Set the TX bandwidth on the subdevice. + * \param bandwidth the bandwidth in Hz + * \param chan the channel index 0 to N-1 + */ virtual void set_tx_bandwidth(double bandwidth, size_t chan = 0) = 0; + + /*! + * Get the TX bandwidth on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the bandwidth in Hz + */ virtual double get_tx_bandwidth(size_t chan = 0) = 0; + /*! + * Get the dboard interface object for the TX subdevice. + * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. + * Use at your own risk! + * \param chan the channel index 0 to N-1 + * \return the dboard interface sptr + */ virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan = 0) = 0; }; -- cgit v1.2.3 From 26aef3bae98aae5364deb40a62b52ba65b9aa16a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 20 Oct 2010 15:32:41 -0700 Subject: uhd: added name parameter to gain group, get range, set/get value by name --- host/include/uhd/utils/gain_group.hpp | 43 +++++++++++++++++++++++++++-------- host/lib/usrp/misc_utils.cpp | 4 ++-- host/lib/utils/gain_group.cpp | 26 +++++++++++++++++---- host/test/gain_group_test.cpp | 4 ++-- 4 files changed, 59 insertions(+), 18 deletions(-) diff --git a/host/include/uhd/utils/gain_group.hpp b/host/include/uhd/utils/gain_group.hpp index 3955dfa9a..c863248ce 100644 --- a/host/include/uhd/utils/gain_group.hpp +++ b/host/include/uhd/utils/gain_group.hpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include namespace uhd{ @@ -40,36 +42,57 @@ public: typedef boost::shared_ptr sptr; /*! - * Get the overall gain range for this group. + * Get the gain range for the gain element specified by name. + * For an empty name, get the overall gain range for this group. * Overall step is defined as the minimum step size. + * \param name name of the gain element (optional) * \return a gain range with overall min, max, step */ - virtual gain_range_t get_range(void) = 0; + virtual gain_range_t get_range(const std::string &name = "") = 0; /*! - * Get the overall gain value for this group. - * \return a summation of all the gain values + * Get the gain value for the gain element specified by name. + * For an empty name, get the overall gain value for this group. + * \param name name of the gain element (optional) + * \return a gain value of the element or all elements */ - virtual float get_value(void) = 0; + virtual float get_value(const std::string &name = "") = 0; /*! - * Set the overall gain value for this group. + * Set the gain value for the gain element specified by name. + * For an empty name, set the overall gain value for this group. * The power will be distributed across individual gain elements. * The semantics of how to do this are determined by the priority. - * \param gain the gain to set across the group + * \param gain the gain to set for the lement or across the group + * \param name name of the gain element (optional) */ - virtual void set_value(float gain) = 0; + virtual void set_value(float gain, const std::string &name = "") = 0; /*! - * Register a set of gain functions into this group. + * Get a list of names of registered gain elements. + * The names are in the order that they were registered. + * \return a vector of gain name strings + */ + virtual const std::vector get_names(void) = 0; + + /*! + * Register a set of gain functions into this group: + * + * The name should be a unique and non-empty name. + * Othwerwise, the implementation will rename it. + * * Priority determines how power will be distributed * with higher priorities getting the power first, * and lower priorities getting the remainder power. + * + * \param name the name of the gain element * \param gain_fcns the set of gain functions * \param priority the priority of the gain element */ virtual void register_fcns( - const gain_fcns_t &gain_fcns, size_t priority = 0 + const std::string &name, + const gain_fcns_t &gain_fcns, + size_t priority = 0 ) = 0; /*! diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp index 05308baba..499a6ebfb 100644 --- a/host/lib/usrp/misc_utils.cpp +++ b/host/lib/usrp/misc_utils.cpp @@ -95,7 +95,7 @@ gain_group::sptr usrp::make_gain_group( fcns.get_range = boost::bind(&get_subdev_gain_range, subdev, name); fcns.get_value = boost::bind(&get_subdev_gain, subdev, name); fcns.set_value = boost::bind(&set_subdev_gain, subdev, name, _1); - gg->register_fcns(fcns, subdev_gain_priority); + gg->register_fcns(name, fcns, subdev_gain_priority); } //add all the codec gains last (antenna to dsp order) BOOST_FOREACH(const std::string &name, codec[CODEC_PROP_GAIN_NAMES].as()){ @@ -119,7 +119,7 @@ gain_group::sptr usrp::make_gain_group( fcns.set_value = boost::bind(&set_codec_gain_q, codec, name, _1); break; } - gg->register_fcns(fcns, codec_gain_priority); + gg->register_fcns(name, fcns, codec_gain_priority); } return gg; } diff --git a/host/lib/utils/gain_group.cpp b/host/lib/utils/gain_group.cpp index 078fe56b2..54146726a 100644 --- a/host/lib/utils/gain_group.cpp +++ b/host/lib/utils/gain_group.cpp @@ -63,7 +63,9 @@ public: /*NOP*/ } - gain_range_t get_range(void){ + gain_range_t get_range(const std::string &name){ + if (not name.empty()) return _name_to_fcns[name].get_range(); + float overall_min = 0, overall_max = 0, overall_step = 0; BOOST_FOREACH(const gain_fcns_t &fcns, get_all_fcns()){ const gain_range_t range = fcns.get_range(); @@ -76,7 +78,9 @@ public: return gain_range_t(overall_min, overall_max, overall_step); } - float get_value(void){ + float get_value(const std::string &name){ + if (not name.empty()) return _name_to_fcns[name].get_value(); + float overall_gain = 0; BOOST_FOREACH(const gain_fcns_t &fcns, get_all_fcns()){ overall_gain += fcns.get_value(); @@ -84,7 +88,9 @@ public: return overall_gain; } - void set_value(float gain){ + void set_value(float gain, const std::string &name){ + if (not name.empty()) return _name_to_fcns[name].set_value(gain); + std::vector all_fcns = get_all_fcns(); if (all_fcns.size() == 0) return; //nothing to set! @@ -140,10 +146,21 @@ public: } } + const std::vector get_names(void){ + return _name_to_fcns.keys(); + } + void register_fcns( - const gain_fcns_t &gain_fcns, size_t priority + const std::string &name, + const gain_fcns_t &gain_fcns, + size_t priority ){ + if (name.empty() or _name_to_fcns.has_key(name)){ + //ensure the name name is unique and non-empty + return register_fcns(name + "_", gain_fcns, priority); + } _registry[priority].push_back(gain_fcns); + _name_to_fcns[name] = gain_fcns; } private: @@ -158,6 +175,7 @@ private: } uhd::dict > _registry; + uhd::dict _name_to_fcns; }; /*********************************************************************** diff --git a/host/test/gain_group_test.cpp b/host/test/gain_group_test.cpp index 761372e5a..555ccaed3 100644 --- a/host/test/gain_group_test.cpp +++ b/host/test/gain_group_test.cpp @@ -81,12 +81,12 @@ static gain_group::sptr get_gain_group(size_t pri1 = 0, size_t pri2 = 0){ gain_fcns.get_range = boost::bind(&gain_element1::get_range, &g1); gain_fcns.get_value = boost::bind(&gain_element1::get_value, &g1); gain_fcns.set_value = boost::bind(&gain_element1::set_value, &g1, _1); - gg->register_fcns(gain_fcns, pri1); + gg->register_fcns("g1", gain_fcns, pri1); gain_fcns.get_range = boost::bind(&gain_element2::get_range, &g2); gain_fcns.get_value = boost::bind(&gain_element2::get_value, &g2); gain_fcns.set_value = boost::bind(&gain_element2::set_value, &g2, _1); - gg->register_fcns(gain_fcns, pri2); + gg->register_fcns("g2", gain_fcns, pri2); return gg; } -- cgit v1.2.3 From 8e341caadf19db645635e3e7e1a26e6b00e64c70 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 20 Oct 2010 16:20:36 -0700 Subject: usrp: added gain element access by gain name to multi and single wrappers --- host/include/uhd/usrp/multi_usrp.hpp | 59 +++++++++++++++++++------- host/include/uhd/usrp/single_usrp.hpp | 79 ++++++++++++++++++++++++++++------- host/lib/usrp/multi_usrp.cpp | 34 +++++++++------ host/lib/usrp/single_usrp.cpp | 34 +++++++++------ 4 files changed, 150 insertions(+), 56 deletions(-) diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 6adba85bd..70901fc31 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -73,6 +73,9 @@ public: //! A wildcard motherboard index static const size_t ALL_MBOARDS = size_t(~0); + //! A wildcard gain element name + static const std::string ALL_GAINS; + /*! * Make a new multi usrp from the device address. * \param dev_addr the device address @@ -240,27 +243,39 @@ public: virtual freq_range_t get_rx_freq_range(size_t chan) = 0; /*! - * Set the RX gain: - * Distribute among gain elements in the RX path. + * Set the RX gain value for the specified gain element. + * For an empty name, distribute across all gain elements. * \param gain the gain in dB + * \param name the name of the gain element * \param chan the channel index 0 to N-1 */ - virtual void set_rx_gain(float gain, size_t chan) = 0; + virtual void set_rx_gain(float gain, const std::string &name, size_t chan) = 0; /*! - * Get the RX gain: - * Summation of gain elements in the RX path. + * Get the RX gain value for the specified gain element. + * For an empty name, sum across all gain elements. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return the gain in dB */ - virtual float get_rx_gain(size_t chan) = 0; + virtual float get_rx_gain(const std::string &name, size_t chan) = 0; /*! - * Get the RX gain range. + * Get the RX gain range for the specified gain element. + * For an empty name, calculate the overall gain range. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return a gain range object */ - virtual gain_range_t get_rx_gain_range(size_t chan) = 0; + virtual gain_range_t get_rx_gain_range(const std::string &name, size_t chan) = 0; + + /*! + * Get the names of the gain elements in the RX chain. + * Gain elements are ordered from antenna to FPGA. + * \param chan the channel index 0 to N-1 + * \return a vector of gain element names + */ + virtual std::vector get_rx_gain_names(size_t chan) = 0; /*! * Select the RX antenna on the subdevice. @@ -399,27 +414,39 @@ public: virtual freq_range_t get_tx_freq_range(size_t chan) = 0; /*! - * Set the TX gain: - * Distribute among gain elements in the TX path. + * Set the TX gain value for the specified gain element. + * For an empty name, distribute across all gain elements. * \param gain the gain in dB + * \param name the name of the gain element * \param chan the channel index 0 to N-1 */ - virtual void set_tx_gain(float gain, size_t chan) = 0; + virtual void set_tx_gain(float gain, const std::string &name, size_t chan) = 0; /*! - * Get the TX gain: - * Summation of gain elements in the TX path. + * Get the TX gain value for the specified gain element. + * For an empty name, sum across all gain elements. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return the gain in dB */ - virtual float get_tx_gain(size_t chan) = 0; + virtual float get_tx_gain(const std::string &name, size_t chan) = 0; /*! - * Get the TX gain range. + * Get the TX gain range for the specified gain element. + * For an empty name, calculate the overall gain range. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return a gain range object */ - virtual gain_range_t get_tx_gain_range(size_t chan) = 0; + virtual gain_range_t get_tx_gain_range(const std::string &name, size_t chan) = 0; + + /*! + * Get the names of the gain elements in the TX chain. + * Gain elements are ordered from antenna to FPGA. + * \param chan the channel index 0 to N-1 + * \return a vector of gain element names + */ + virtual std::vector get_tx_gain_names(size_t chan) = 0; /*! * Select the TX antenna on the subdevice. diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index 74a978f05..09bf9c84d 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -43,6 +43,9 @@ class UHD_API single_usrp : boost::noncopyable{ public: typedef boost::shared_ptr sptr; + //! A wildcard gain element name + static const std::string ALL_GAINS; + /*! * Make a new single usrp from the device address. * \param dev_addr the device address @@ -182,27 +185,49 @@ public: virtual freq_range_t get_rx_freq_range(size_t chan = 0) = 0; /*! - * Set the RX gain: - * Distribute among gain elements in the RX path. + * Set the RX gain value for the specified gain element. + * For an empty name, distribute across all gain elements. * \param gain the gain in dB + * \param name the name of the gain element * \param chan the channel index 0 to N-1 */ - virtual void set_rx_gain(float gain, size_t chan = 0) = 0; + virtual void set_rx_gain( + float gain, + const std::string &name = ALL_GAINS, + size_t chan = 0 + ) = 0; /*! - * Get the RX gain: - * Summation of gain elements in the RX path. + * Get the RX gain value for the specified gain element. + * For an empty name, sum across all gain elements. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return the gain in dB */ - virtual float get_rx_gain(size_t chan = 0) = 0; + virtual float get_rx_gain( + const std::string &name = ALL_GAINS, + size_t chan = 0 + ) = 0; /*! - * Get the RX gain range. + * Get the RX gain range for the specified gain element. + * For an empty name, calculate the overall gain range. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return a gain range object */ - virtual gain_range_t get_rx_gain_range(size_t chan = 0) = 0; + virtual gain_range_t get_rx_gain_range( + const std::string &name = ALL_GAINS, + size_t chan = 0 + ) = 0; + + /*! + * Get the names of the gain elements in the RX chain. + * Gain elements are ordered from antenna to FPGA. + * \param chan the channel index 0 to N-1 + * \return a vector of gain element names + */ + virtual std::vector get_rx_gain_names(size_t chan = 0) = 0; /*! * Select the RX antenna on the subdevice. @@ -332,27 +357,49 @@ public: virtual freq_range_t get_tx_freq_range(size_t chan = 0) = 0; /*! - * Set the TX gain: - * Distribute among gain elements in the TX path. + * Set the TX gain value for the specified gain element. + * For an empty name, distribute across all gain elements. * \param gain the gain in dB + * \param name the name of the gain element * \param chan the channel index 0 to N-1 */ - virtual void set_tx_gain(float gain, size_t chan = 0) = 0; + virtual void set_tx_gain( + float gain, + const std::string &name = ALL_GAINS, + size_t chan = 0 + ) = 0; /*! - * Get the TX gain: - * Summation of gain elements in the TX path. + * Get the TX gain value for the specified gain element. + * For an empty name, sum across all gain elements. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return the gain in dB */ - virtual float get_tx_gain(size_t chan = 0) = 0; + virtual float get_tx_gain( + const std::string &name = ALL_GAINS, + size_t chan = 0 + ) = 0; /*! - * Get the TX gain range. + * Get the TX gain range for the specified gain element. + * For an empty name, calculate the overall gain range. + * \param name the name of the gain element * \param chan the channel index 0 to N-1 * \return a gain range object */ - virtual gain_range_t get_tx_gain_range(size_t chan = 0) = 0; + virtual gain_range_t get_tx_gain_range( + const std::string &name = ALL_GAINS, + size_t chan = 0 + ) = 0; + + /*! + * Get the names of the gain elements in the TX chain. + * Gain elements are ordered from antenna to FPGA. + * \param chan the channel index 0 to N-1 + * \return a vector of gain element names + */ + virtual std::vector get_tx_gain_names(size_t chan = 0) = 0; /*! * Select the TX antenna on the subdevice. diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 027530f31..443b91594 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -35,6 +35,8 @@ using namespace uhd; using namespace uhd::usrp; +const std::string multi_usrp::ALL_GAINS = ""; + /*********************************************************************** * Simple USRP Implementation **********************************************************************/ @@ -228,16 +230,20 @@ public: return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp(chan/rx_cpm())); } - void set_rx_gain(float gain, size_t chan){ - return _rx_gain_group(chan)->set_value(gain); + void set_rx_gain(float gain, const std::string &name, size_t chan){ + return _rx_gain_group(chan)->set_value(gain, name); + } + + float get_rx_gain(const std::string &name, size_t chan){ + return _rx_gain_group(chan)->get_value(name); } - float get_rx_gain(size_t chan){ - return _rx_gain_group(chan)->get_value(); + gain_range_t get_rx_gain_range(const std::string &name, size_t chan){ + return _rx_gain_group(chan)->get_range(name); } - gain_range_t get_rx_gain_range(size_t chan){ - return _rx_gain_group(chan)->get_range(); + std::vector get_rx_gain_names(size_t chan){ + return _rx_gain_group(chan)->get_names(); } void set_rx_antenna(const std::string &ant, size_t chan){ @@ -328,16 +334,20 @@ public: return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp(chan/tx_cpm())); } - void set_tx_gain(float gain, size_t chan){ - return _tx_gain_group(chan)->set_value(gain); + void set_tx_gain(float gain, const std::string &name, size_t chan){ + return _tx_gain_group(chan)->set_value(gain, name); + } + + float get_tx_gain(const std::string &name, size_t chan){ + return _tx_gain_group(chan)->get_value(name); } - float get_tx_gain(size_t chan){ - return _tx_gain_group(chan)->get_value(); + gain_range_t get_tx_gain_range(const std::string &name, size_t chan){ + return _tx_gain_group(chan)->get_range(name); } - gain_range_t get_tx_gain_range(size_t chan){ - return _tx_gain_group(chan)->get_range(); + std::vector get_tx_gain_names(size_t chan){ + return _tx_gain_group(chan)->get_names(); } void set_tx_antenna(const std::string &ant, size_t chan){ diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index 2faa1280c..5e57849b8 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -33,6 +33,8 @@ using namespace uhd; using namespace uhd::usrp; +const std::string single_usrp::ALL_GAINS = ""; + /*********************************************************************** * Simple USRP Implementation **********************************************************************/ @@ -164,16 +166,20 @@ public: return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp()); } - void set_rx_gain(float gain, size_t chan){ - return _rx_gain_group(chan)->set_value(gain); + void set_rx_gain(float gain, const std::string &name, size_t chan){ + return _rx_gain_group(chan)->set_value(gain, name); + } + + float get_rx_gain(const std::string &name, size_t chan){ + return _rx_gain_group(chan)->get_value(name); } - float get_rx_gain(size_t chan){ - return _rx_gain_group(chan)->get_value(); + gain_range_t get_rx_gain_range(const std::string &name, size_t chan){ + return _rx_gain_group(chan)->get_range(name); } - gain_range_t get_rx_gain_range(size_t chan){ - return _rx_gain_group(chan)->get_range(); + std::vector get_rx_gain_names(size_t chan){ + return _rx_gain_group(chan)->get_names(); } void set_rx_antenna(const std::string &ant, size_t chan){ @@ -252,16 +258,20 @@ public: return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp()); } - void set_tx_gain(float gain, size_t chan){ - return _tx_gain_group(chan)->set_value(gain); + void set_tx_gain(float gain, const std::string &name, size_t chan){ + return _tx_gain_group(chan)->set_value(gain, name); + } + + float get_tx_gain(const std::string &name, size_t chan){ + return _tx_gain_group(chan)->get_value(name); } - float get_tx_gain(size_t chan){ - return _tx_gain_group(chan)->get_value(); + gain_range_t get_tx_gain_range(const std::string &name, size_t chan){ + return _tx_gain_group(chan)->get_range(name); } - gain_range_t get_tx_gain_range(size_t chan){ - return _tx_gain_group(chan)->get_range(); + std::vector get_tx_gain_names(size_t chan){ + return _tx_gain_group(chan)->get_names(); } void set_tx_antenna(const std::string &ant, size_t chan){ -- cgit v1.2.3 From d96b2e7587962c43c1db895b3340f9d868cbd704 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 20 Oct 2010 17:41:59 -0700 Subject: usrp: use the dboard id to prefix the subdev gain group names --- host/include/uhd/usrp/dboard_id.hpp | 6 ++++++ host/include/uhd/usrp/misc_utils.hpp | 3 +++ host/lib/usrp/dboard/db_dbsrx.cpp | 9 ++------- host/lib/usrp/dboard/db_rfx.cpp | 12 ++++++------ host/lib/usrp/dboard/db_tvrx.cpp | 2 +- host/lib/usrp/dboard_manager.cpp | 11 ++++++----- host/lib/usrp/misc_utils.cpp | 7 +++++-- host/lib/usrp/usrp1/codec_impl.cpp | 24 +++++++++++++----------- host/lib/usrp/usrp1/dboard_impl.cpp | 2 ++ host/lib/usrp/usrp2/dboard_impl.cpp | 2 ++ 10 files changed, 46 insertions(+), 32 deletions(-) diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp index 4c45e4334..1fda8182e 100644 --- a/host/include/uhd/usrp/dboard_id.hpp +++ b/host/include/uhd/usrp/dboard_id.hpp @@ -66,6 +66,12 @@ namespace uhd{ namespace usrp{ */ std::string to_string(void) const; + /*! + * Get the dboard id represented as a canonical name. + * \return the canonical string representation + */ + std::string to_cname(void) const; + /*! * Get the pretty print representation of this dboard id. * \return a string with the dboard name and id number diff --git a/host/include/uhd/usrp/misc_utils.hpp b/host/include/uhd/usrp/misc_utils.hpp index 2af9f5b40..37860a1a5 100644 --- a/host/include/uhd/usrp/misc_utils.hpp +++ b/host/include/uhd/usrp/misc_utils.hpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -35,11 +36,13 @@ namespace uhd{ namespace usrp{ /*! * Create a gain group that represents the subdevice and its codec. + * \param dboard_id the dboard id for this subdevice * \param subdev the object with subdevice properties * \param codec the object with codec properties * \param gain_group_policy the policy to use */ UHD_API gain_group::sptr make_gain_group( + const dboard_id_t &dboard_id, wax::obj subdev, wax::obj codec, gain_group_policy_t gain_group_policy ); diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 939a79e58..0b8b4db83 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -162,15 +162,10 @@ static dboard_base::sptr make_dbsrx(dboard_base::ctor_args_t args){ return dboard_base::sptr(new dbsrx(args)); } -//dbid for USRP2 version UHD_STATIC_BLOCK(reg_dbsrx_dboard){ - //register the factory function for the rx dbid + //register the factory function for the rx dbid (others version) dboard_manager::register_dboard(0x000D, &make_dbsrx, "DBSRX"); -} - -//dbid for USRP1 version -UHD_STATIC_BLOCK(reg_dbsrx_on_usrp1_dboard){ - //register the factory function for the rx dbid + //register the factory function for the rx dbid (USRP1 version) dboard_manager::register_dboard(0x0002, &make_dbsrx, "DBSRX"); } diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index cfc34381e..3c24d90db 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -152,12 +152,12 @@ static dboard_base::sptr make_rfx_flex2400(dboard_base::ctor_args_t args){ } UHD_STATIC_BLOCK(reg_rfx_dboards){ - dboard_manager::register_dboard(0x0024, 0x0028, &make_rfx_flex400, "Flex 400 MIMO B"); - dboard_manager::register_dboard(0x0025, 0x0029, &make_rfx_flex900, "Flex 900 MIMO B"); - dboard_manager::register_dboard(0x0034, 0x0035, &make_rfx_flex1800, "Flex 1800 MIMO B"); - dboard_manager::register_dboard(0x0026, 0x002a, &make_rfx_flex1200, "Flex 1200 MIMO B"); - dboard_manager::register_dboard(0x002c, 0x002d, &make_rfx_flex2200, "Flex 2200 MIMO B"); - dboard_manager::register_dboard(0x0027, 0x002b, &make_rfx_flex2400, "Flex 2400 MIMO B"); + dboard_manager::register_dboard(0x0024, 0x0028, &make_rfx_flex400, "RFX400"); + dboard_manager::register_dboard(0x0025, 0x0029, &make_rfx_flex900, "RFX900"); + dboard_manager::register_dboard(0x0034, 0x0035, &make_rfx_flex1800, "RFX1800"); + dboard_manager::register_dboard(0x0026, 0x002a, &make_rfx_flex1200, "RFX1200"); + dboard_manager::register_dboard(0x002c, 0x002d, &make_rfx_flex2200, "RFX2200"); + dboard_manager::register_dboard(0x0027, 0x002b, &make_rfx_flex2400, "RFX2400"); } /*********************************************************************** diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 10be8d1c3..d39dc3bf8 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -179,7 +179,7 @@ static dboard_base::sptr make_tvrx(dboard_base::ctor_args_t args){ UHD_STATIC_BLOCK(reg_tvrx_dboard){ //register the factory function for the rx dbid - dboard_manager::register_dboard(0x0040, &make_tvrx, "tvrx"); + dboard_manager::register_dboard(0x0040, &make_tvrx, "TVRX"); } /*********************************************************************** diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 78daa1b4d..d7e7943c4 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -77,12 +77,13 @@ void dboard_manager::register_dboard( get_xcvr_id_to_id_map()[tx_dboard_id] = rx_dboard_id; } +std::string dboard_id_t::to_cname(void) const{ + if (not get_id_to_args_map().has_key(*this)) return "Unknown"; + return get_id_to_args_map()[*this].get<1>(); +} + std::string dboard_id_t::to_pp_string(void) const{ - std::string name = "unknown"; - if (get_id_to_args_map().has_key(*this)){ - name = get_id_to_args_map()[*this].get<1>(); - } - return str(boost::format("%s (%s)") % name % this->to_string()); + return str(boost::format("%s (%s)") % this->to_cname() % this->to_string()); } /*********************************************************************** diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp index 499a6ebfb..e95af45bd 100644 --- a/host/lib/usrp/misc_utils.cpp +++ b/host/lib/usrp/misc_utils.cpp @@ -80,6 +80,7 @@ static void set_subdev_gain(wax::obj subdev, const std::string &name, float gain * gain group factory function for usrp **********************************************************************/ gain_group::sptr usrp::make_gain_group( + const dboard_id_t &dboard_id, wax::obj subdev, wax::obj codec, gain_group_policy_t gain_group_policy ){ @@ -87,6 +88,8 @@ gain_group::sptr usrp::make_gain_group( const size_t codec_gain_priority = (gain_group_policy == GAIN_GROUP_POLICY_RX)? (subdev_gain_priority - 1): //RX policy, codec gains fill last (lower priority) (subdev_gain_priority + 1); //TX policy, codec gains fill first (higher priority) + const std::string subdev_prefix = dboard_id.to_cname() + " "; + const std::string codec_prefix = (gain_group_policy == GAIN_GROUP_POLICY_RX)? "ADC " : "DAC "; gain_group::sptr gg = gain_group::make(); gain_fcns_t fcns; @@ -95,7 +98,7 @@ gain_group::sptr usrp::make_gain_group( fcns.get_range = boost::bind(&get_subdev_gain_range, subdev, name); fcns.get_value = boost::bind(&get_subdev_gain, subdev, name); fcns.set_value = boost::bind(&set_subdev_gain, subdev, name, _1); - gg->register_fcns(name, fcns, subdev_gain_priority); + gg->register_fcns(subdev_prefix+name, fcns, subdev_gain_priority); } //add all the codec gains last (antenna to dsp order) BOOST_FOREACH(const std::string &name, codec[CODEC_PROP_GAIN_NAMES].as()){ @@ -119,7 +122,7 @@ gain_group::sptr usrp::make_gain_group( fcns.set_value = boost::bind(&set_codec_gain_q, codec, name, _1); break; } - gg->register_fcns(name, fcns, codec_gain_priority); + gg->register_fcns(codec_prefix+name, fcns, codec_gain_priority); } return gg; } diff --git a/host/lib/usrp/usrp1/codec_impl.cpp b/host/lib/usrp/usrp1/codec_impl.cpp index 1756c1ed4..db53be53e 100644 --- a/host/lib/usrp/usrp1/codec_impl.cpp +++ b/host/lib/usrp/usrp1/codec_impl.cpp @@ -45,7 +45,7 @@ void usrp1_impl::codec_init(void) /*********************************************************************** * RX Codec Properties **********************************************************************/ -static const std::string ad9862_pga_gain_name = "ad9862 pga"; +static const std::string adc_pga_gain_name = "PGA"; void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot) { @@ -62,21 +62,21 @@ void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t return; case CODEC_PROP_GAIN_NAMES: - val = prop_names_t(1, ad9862_pga_gain_name); + val = prop_names_t(1, adc_pga_gain_name); return; case CODEC_PROP_GAIN_RANGE: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); val = usrp1_codec_ctrl::rx_pga_gain_range; return; case CODEC_PROP_GAIN_I: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); val = _codec_ctrls[dboard_slot]->get_rx_pga_gain('A'); return; case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); val = _codec_ctrls[dboard_slot]->get_rx_pga_gain('B'); return; @@ -91,12 +91,12 @@ void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_ //handle the set request conditioned on the key switch(key.as()) { case CODEC_PROP_GAIN_I: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as(), 'A'); return; case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as(), 'B'); return; @@ -107,6 +107,8 @@ void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_ /*********************************************************************** * TX Codec Properties **********************************************************************/ +static const std::string dac_pga_gain_name = "PGA"; + void usrp1_impl::tx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot) { named_prop_t key = named_prop_t::extract(key_); @@ -122,17 +124,17 @@ void usrp1_impl::tx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t return; case CODEC_PROP_GAIN_NAMES: - val = prop_names_t(1, ad9862_pga_gain_name); + val = prop_names_t(1, dac_pga_gain_name); return; case CODEC_PROP_GAIN_RANGE: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == dac_pga_gain_name); val = usrp1_codec_ctrl::tx_pga_gain_range; return; case CODEC_PROP_GAIN_I: //only one gain for I and Q case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == dac_pga_gain_name); val = _codec_ctrls[dboard_slot]->get_tx_pga_gain(); return; @@ -148,7 +150,7 @@ void usrp1_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_ switch(key.as()){ case CODEC_PROP_GAIN_I: //only one gain for I and Q case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == dac_pga_gain_name); _codec_ctrls[dboard_slot]->set_tx_pga_gain(val.as()); return; diff --git a/host/lib/usrp/usrp1/dboard_impl.cpp b/host/lib/usrp/usrp1/dboard_impl.cpp index 3a8480e1b..2a2762a82 100644 --- a/host/lib/usrp/usrp1/dboard_impl.cpp +++ b/host/lib/usrp/usrp1/dboard_impl.cpp @@ -124,6 +124,7 @@ void usrp1_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _rx_db_eeproms[dboard_slot].id, _dboard_managers[dboard_slot]->get_rx_subdev(key.name), _rx_codec_proxies[dboard_slot]->get_link(), GAIN_GROUP_POLICY_RX @@ -188,6 +189,7 @@ void usrp1_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _tx_db_eeproms[dboard_slot].id, _dboard_managers[dboard_slot]->get_tx_subdev(key.name), _tx_codec_proxies[dboard_slot]->get_link(), GAIN_GROUP_POLICY_TX diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index a462b93c2..540c9fefb 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -89,6 +89,7 @@ void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _rx_db_eeprom.id, _dboard_manager->get_rx_subdev(key.name), _rx_codec_proxy->get_link(), GAIN_GROUP_POLICY_RX @@ -145,6 +146,7 @@ void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _tx_db_eeprom.id, _dboard_manager->get_tx_subdev(key.name), _tx_codec_proxy->get_link(), GAIN_GROUP_POLICY_TX -- cgit v1.2.3 From 318d62a179806cec20b5adb4f2aad58ecc5a330e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 20 Oct 2010 18:16:34 -0700 Subject: usrp: convenience wrappers for dealing with overall gains --- host/include/uhd/usrp/multi_usrp.hpp | 30 +++++++++++++++++ host/include/uhd/usrp/single_usrp.hpp | 62 ++++++++++++++++++++--------------- 2 files changed, 66 insertions(+), 26 deletions(-) diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 70901fc31..2f71f80b1 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -251,6 +251,11 @@ public: */ virtual void set_rx_gain(float gain, const std::string &name, size_t chan) = 0; + //! A convenience wrapper for setting overall RX gain + void set_rx_gain(float gain, size_t chan){ + return this->set_rx_gain(gain, ALL_GAINS, chan); + } + /*! * Get the RX gain value for the specified gain element. * For an empty name, sum across all gain elements. @@ -260,6 +265,11 @@ public: */ virtual float get_rx_gain(const std::string &name, size_t chan) = 0; + //! A convenience wrapper for getting overall RX gain + float get_rx_gain(size_t chan){ + return this->get_rx_gain(ALL_GAINS, chan); + } + /*! * Get the RX gain range for the specified gain element. * For an empty name, calculate the overall gain range. @@ -269,6 +279,11 @@ public: */ virtual gain_range_t get_rx_gain_range(const std::string &name, size_t chan) = 0; + //! A convenience wrapper for getting overall RX gain range + gain_range_t get_rx_gain_range(size_t chan){ + return this->get_rx_gain_range(ALL_GAINS, chan); + } + /*! * Get the names of the gain elements in the RX chain. * Gain elements are ordered from antenna to FPGA. @@ -422,6 +437,11 @@ public: */ virtual void set_tx_gain(float gain, const std::string &name, size_t chan) = 0; + //! A convenience wrapper for setting overall TX gain + void set_tx_gain(float gain, size_t chan){ + return this->set_tx_gain(gain, ALL_GAINS, chan); + } + /*! * Get the TX gain value for the specified gain element. * For an empty name, sum across all gain elements. @@ -431,6 +451,11 @@ public: */ virtual float get_tx_gain(const std::string &name, size_t chan) = 0; + //! A convenience wrapper for getting overall TX gain + float get_tx_gain(size_t chan){ + return this->get_tx_gain(ALL_GAINS, chan); + } + /*! * Get the TX gain range for the specified gain element. * For an empty name, calculate the overall gain range. @@ -440,6 +465,11 @@ public: */ virtual gain_range_t get_tx_gain_range(const std::string &name, size_t chan) = 0; + //! A convenience wrapper for getting overall TX gain range + gain_range_t get_tx_gain_range(size_t chan){ + return this->get_tx_gain_range(ALL_GAINS, chan); + } + /*! * Get the names of the gain elements in the TX chain. * Gain elements are ordered from antenna to FPGA. diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index 09bf9c84d..a34f92cee 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -191,11 +191,12 @@ public: * \param name the name of the gain element * \param chan the channel index 0 to N-1 */ - virtual void set_rx_gain( - float gain, - const std::string &name = ALL_GAINS, - size_t chan = 0 - ) = 0; + virtual void set_rx_gain(float gain, const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for setting overall RX gain + void set_rx_gain(float gain, size_t chan = 0){ + return this->set_rx_gain(gain, ALL_GAINS, chan); + } /*! * Get the RX gain value for the specified gain element. @@ -204,10 +205,12 @@ public: * \param chan the channel index 0 to N-1 * \return the gain in dB */ - virtual float get_rx_gain( - const std::string &name = ALL_GAINS, - size_t chan = 0 - ) = 0; + virtual float get_rx_gain(const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for getting overall RX gain + float get_rx_gain(size_t chan = 0){ + return this->get_rx_gain(ALL_GAINS, chan); + } /*! * Get the RX gain range for the specified gain element. @@ -216,10 +219,12 @@ public: * \param chan the channel index 0 to N-1 * \return a gain range object */ - virtual gain_range_t get_rx_gain_range( - const std::string &name = ALL_GAINS, - size_t chan = 0 - ) = 0; + virtual gain_range_t get_rx_gain_range(const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for getting overall RX gain range + gain_range_t get_rx_gain_range(size_t chan = 0){ + return this->get_rx_gain_range(ALL_GAINS, chan); + } /*! * Get the names of the gain elements in the RX chain. @@ -363,11 +368,12 @@ public: * \param name the name of the gain element * \param chan the channel index 0 to N-1 */ - virtual void set_tx_gain( - float gain, - const std::string &name = ALL_GAINS, - size_t chan = 0 - ) = 0; + virtual void set_tx_gain(float gain, const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for setting overall TX gain + void set_tx_gain(float gain, size_t chan = 0){ + return this->set_tx_gain(gain, ALL_GAINS, chan); + } /*! * Get the TX gain value for the specified gain element. @@ -376,10 +382,12 @@ public: * \param chan the channel index 0 to N-1 * \return the gain in dB */ - virtual float get_tx_gain( - const std::string &name = ALL_GAINS, - size_t chan = 0 - ) = 0; + virtual float get_tx_gain(const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for getting overall TX gain + float get_tx_gain(size_t chan = 0){ + return this->get_tx_gain(ALL_GAINS, chan); + } /*! * Get the TX gain range for the specified gain element. @@ -388,10 +396,12 @@ public: * \param chan the channel index 0 to N-1 * \return a gain range object */ - virtual gain_range_t get_tx_gain_range( - const std::string &name = ALL_GAINS, - size_t chan = 0 - ) = 0; + virtual gain_range_t get_tx_gain_range(const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for getting overall TX gain range + gain_range_t get_tx_gain_range(size_t chan = 0){ + return this->get_tx_gain_range(ALL_GAINS, chan); + } /*! * Get the names of the gain elements in the TX chain. -- cgit v1.2.3 From c2ec8c143e569df115401fdf92483fab421ade2d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 20 Oct 2010 18:40:36 -0700 Subject: usrp: use a dash as the gain name prefix separator, removed RX/TX auto suffix for XCVR board cnames --- host/lib/usrp/dboard_manager.cpp | 4 ++-- host/lib/usrp/misc_utils.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index d7e7943c4..d73a698ae 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -69,8 +69,8 @@ void dboard_manager::register_dboard( const prop_names_t &subdev_names ){ //regular registration for ids - register_dboard(rx_dboard_id, dboard_ctor, name + " RX", subdev_names); - register_dboard(tx_dboard_id, dboard_ctor, name + " TX", subdev_names); + register_dboard(rx_dboard_id, dboard_ctor, name, subdev_names); + register_dboard(tx_dboard_id, dboard_ctor, name, subdev_names); //register xcvr mapping for ids get_xcvr_id_to_id_map()[rx_dboard_id] = tx_dboard_id; diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp index e95af45bd..7e49baa52 100644 --- a/host/lib/usrp/misc_utils.cpp +++ b/host/lib/usrp/misc_utils.cpp @@ -88,8 +88,8 @@ gain_group::sptr usrp::make_gain_group( const size_t codec_gain_priority = (gain_group_policy == GAIN_GROUP_POLICY_RX)? (subdev_gain_priority - 1): //RX policy, codec gains fill last (lower priority) (subdev_gain_priority + 1); //TX policy, codec gains fill first (higher priority) - const std::string subdev_prefix = dboard_id.to_cname() + " "; - const std::string codec_prefix = (gain_group_policy == GAIN_GROUP_POLICY_RX)? "ADC " : "DAC "; + const std::string subdev_prefix = dboard_id.to_cname() + "-"; + const std::string codec_prefix = (gain_group_policy == GAIN_GROUP_POLICY_RX)? "ADC-" : "DAC-"; gain_group::sptr gg = gain_group::make(); gain_fcns_t fcns; -- cgit v1.2.3 From e2f76bddae7845024056b479658651c6da2b0f4d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 21 Oct 2010 09:43:35 -0700 Subject: usrp: remove irrelevant copied comment from single usrp --- host/include/uhd/usrp/single_usrp.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index a34f92cee..a068fbed8 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -123,7 +123,6 @@ public: * Set the RX subdevice specification: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. - * The subdev spec must be the same size across all motherboards. * \param spec the new subdevice specification */ virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; @@ -300,7 +299,6 @@ public: * Set the TX subdevice specification: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. - * The subdev spec must be the same size across all motherboards. * \param spec the new subdevice specification */ virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; -- cgit v1.2.3 From c347ad973f4b51b00f66d7422cd03e8790de9be3 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 21 Oct 2010 13:57:50 -0400 Subject: usrp_e: Do not install main_test anymore. --- host/test/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt index 59a550f98..2cc987f0c 100644 --- a/host/test/CMakeLists.txt +++ b/host/test/CMakeLists.txt @@ -52,6 +52,5 @@ ENDFOREACH(test_source) ADD_LIBRARY(module_test MODULE module_test.cpp) INSTALL(TARGETS - main_test RUNTIME DESTINATION ${PKG_DATA_DIR}/tests ) -- cgit v1.2.3 From 3dc06cddaf0a0cf32f76be7077d1427ff4b71a7e Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 14 Oct 2010 14:47:34 -0400 Subject: usrp-e: Add example that reads data from uhd and sends it over a udp socket. --- host/examples/CMakeLists.txt | 4 ++ host/examples/rx_to_udp.cpp | 167 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 host/examples/rx_to_udp.cpp diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt index fb7777d42..3b36f3e71 100644 --- a/host/examples/CMakeLists.txt +++ b/host/examples/CMakeLists.txt @@ -25,6 +25,9 @@ TARGET_LINK_LIBRARIES(rx_timed_samples uhd) ADD_EXECUTABLE(rx_to_file rx_to_file.cpp) TARGET_LINK_LIBRARIES(rx_to_file uhd) +ADD_EXECUTABLE(rx_to_udp rx_to_udp.cpp) +TARGET_LINK_LIBRARIES(rx_to_udp uhd) + ADD_EXECUTABLE(test_async_messages test_async_messages.cpp) TARGET_LINK_LIBRARIES(test_async_messages uhd) @@ -48,6 +51,7 @@ INSTALL(TARGETS tx_timed_samples tx_from_file rx_to_file + rx_to_udp tx_waveforms RUNTIME DESTINATION ${PKG_DATA_DIR}/examples ) diff --git a/host/examples/rx_to_udp.cpp b/host/examples/rx_to_udp.cpp new file mode 100644 index 000000000..34b278599 --- /dev/null +++ b/host/examples/rx_to_udp.cpp @@ -0,0 +1,167 @@ +// +// 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 +#include +#include + +#include "sys/types.h" +#include "sys/socket.h" +#include "arpa/inet.h" + +namespace po = boost::program_options; + + +int UHD_SAFE_MAIN(int argc, char *argv[]){ + uhd::set_thread_priority_safe(); + + //variables to be set by po + std::string args; + time_t seconds_in_future; + size_t total_num_samps; + double rx_rate, freq; + short srv_port; + std::string srv_ip; + + //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 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") + ("port", po::value(&srv_port)->default_value(7124), "server port") + ("ip", po::value(&srv_ip)->default_value("192.168.1.10"), "server ip") + ("dilv", "specify to disable inner-loop verbose") + ; + 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 RX Timed Samples %s") % desc << std::endl; + return ~0; + } + + bool verbose = vm.count("dilv") == 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_pp_string() << std::endl; + + //set properties on the device + std::cout << boost::format("Setting RX Rate: %f Msps...") % (rx_rate/1e6) << std::endl; + 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.0)); + + uhd::gain_range_t rx_gain = sdev->get_rx_gain_range(); + std::cout << "Setting RX Gain to: " << rx_gain.max << std::endl; + sdev->set_rx_gain(rx_gain.max); + + sleep(1); + std::cout << "LO Locked = " << sdev->get_rx_lo_locked() << std::endl; + + //setup streaming + std::cout << std::endl; + std::cout << boost::format( + "Begin streaming %u samples, %d seconds in the future..." + ) % total_num_samps % seconds_in_future << std::endl; + uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); + stream_cmd.num_samps = total_num_samps; + stream_cmd.stream_now = false; + stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future); + sdev->issue_stream_cmd(stream_cmd); + + //loop until total number of samples reached + size_t num_acc_samps = 0; //number of accumulated samples + uhd::rx_metadata_t md; + std::vector > buff(368); + std::ofstream outfile("out.dat", std::ofstream::binary); + + int s; + struct sockaddr_in si_other; + if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { + std::cout << "Failid to open socket." << std::endl; + return -1; + } + + memset((char *) &si_other, 0, sizeof(si_other)); + si_other.sin_family = AF_INET; + si_other.sin_port = htons(srv_port); + if (inet_aton(srv_ip.c_str(), &si_other.sin_addr) == 0) { + std::cout << "Bad inet addr: " << srv_ip << std::endl; + return -1; + } + + while(num_acc_samps < total_num_samps){ + size_t num_rx_samps = dev->recv( + &buff.front(), buff.size(), md, + uhd::io_type_t::COMPLEX_FLOAT32, + uhd::device::RECV_MODE_ONE_PACKET + ); + + //handle the error codes + switch(md.error_code){ + case uhd::rx_metadata_t::ERROR_CODE_NONE: + break; + + case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: + if (num_acc_samps == 0) continue; + std::cout << boost::format( + "Got timeout before all samples received, possible packet loss, exiting loop..." + ) << std::endl; + goto done_loop; + + default: + std::cout << boost::format( + "Got error code 0x%x, exiting loop..." + ) % md.error_code << std::endl; + goto done_loop; + } + +// outfile.write((const char*)&buff[0], num_rx_samps * sizeof(std::complex)); + if (sendto(s, (const char *)&buff[0], num_rx_samps * sizeof(std::complex), 0 , (const sockaddr *)&si_other, sizeof(si_other)) == -1) + std::cout << "Sendto failed." << std::endl; + + if(verbose) std::cout << boost::format( + "Got packet: %u samples, %u full secs, %f frac secs" + ) % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl; + + num_acc_samps += num_rx_samps; + } done_loop: + + outfile.close(); + + //finished + std::cout << std::endl << "Done!" << std::endl << std::endl; + + return 0; +} -- cgit v1.2.3 From db0e3e574e9058ad51cacea91ccc42f0baed95fa Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 21 Oct 2010 22:26:53 -0400 Subject: usrp_e: Add driver compatibility ioctl to header file. --- host/apps/omap_debug/usrp_e.h | 3 +++ host/include/linux/usrp_e.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/host/apps/omap_debug/usrp_e.h b/host/apps/omap_debug/usrp_e.h index fd38027d4..f96706c4a 100644 --- a/host/apps/omap_debug/usrp_e.h +++ b/host/apps/omap_debug/usrp_e.h @@ -41,6 +41,9 @@ struct usrp_e_ctl32 { #define UE_SPI_PUSH_FALL UE_SPI_CTRL_TXNEG #define UE_SPI_LATCH_RISE 0 #define UE_SPI_LATCH_FALL UE_SPI_CTRL_RXNEG +#define USRP_E_GET_COMPAT_NUMBER _IO(USRP_E_IOC_MAGIC, 0x28) + +#define USRP_E_COMPAT_NUMBER 1 struct usrp_e_spi { __u8 readback; diff --git a/host/include/linux/usrp_e.h b/host/include/linux/usrp_e.h index cb62d940d..4c6a5dd89 100644 --- a/host/include/linux/usrp_e.h +++ b/host/include/linux/usrp_e.h @@ -65,6 +65,9 @@ struct usrp_e_i2c { #define USRP_E_I2C_READ _IOWR(USRP_E_IOC_MAGIC, 0x25, struct usrp_e_i2c) #define USRP_E_I2C_WRITE _IOW(USRP_E_IOC_MAGIC, 0x26, struct usrp_e_i2c) #define USRP_E_GET_RB_INFO _IOR(USRP_E_IOC_MAGIC, 0x27, struct usrp_e_ring_buffer_size_t) +#define USRP_E_GET_COMPAT_NUMBER _IO(USRP_E_IOC_MAGIC, 0x28) + +#define USRP_E_COMPAT_NUMBER 1 /* Flag defines */ #define RB_USER (1<<0) -- cgit v1.2.3 From 3974e544393bd5a720838cbf4790c532bca2aae4 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 22 Oct 2010 16:59:12 -0700 Subject: dbsrx: reject asymmetric clocks (odd divisors) --- host/lib/usrp/dboard/db_dbsrx.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 0b8b4db83..aecd7249d 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -236,8 +236,10 @@ void dbsrx::set_lo_freq(double target_freq){ bool update_filter_settings = false; //choose refclock std::vector clock_rates = this->get_iface()->get_clock_rates(dboard_iface::UNIT_RX); + const double max_clock_rate = std::sorted(clock_rates).back(); BOOST_FOREACH(ref_clock, std::reversed(std::sorted(clock_rates))){ if (ref_clock > 27.0e6) continue; + if (size_t(max_clock_rate/ref_clock)%2 == 1) continue; //reject asymmetric clocks (odd divisors) //choose m_divider such that filter tuning constraint is met m = 31; -- cgit v1.2.3 From 3c6ede3c4104d483f39b3c4d062e9e837a9e2e08 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 25 Oct 2010 10:23:59 -0700 Subject: created ascii art dft plotter in uhd --- host/examples/CMakeLists.txt | 12 ++ host/examples/ascii_art_dft.hpp | 320 ++++++++++++++++++++++++++++++++++++ host/examples/benchmark_rx_rate.cpp | 1 - host/examples/rx_ascii_art_dft.cpp | 143 ++++++++++++++++ 4 files changed, 475 insertions(+), 1 deletion(-) create mode 100644 host/examples/ascii_art_dft.hpp create mode 100644 host/examples/rx_ascii_art_dft.cpp diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt index d19838335..a8873f8d3 100644 --- a/host/examples/CMakeLists.txt +++ b/host/examples/CMakeLists.txt @@ -43,3 +43,15 @@ INSTALL(TARGETS tx_waveforms RUNTIME DESTINATION ${PKG_DATA_DIR}/examples ) + +######################################################################## +# ASCII Art DFT - requires curses, so this part is optional +######################################################################## +INCLUDE(FindCurses) + +IF(CURSES_FOUND) + INCLUDE_DIRECTORIES(${CURSES_INCLUDE_DIR}) + ADD_EXECUTABLE(rx_ascii_art_dft rx_ascii_art_dft.cpp) + TARGET_LINK_LIBRARIES(rx_ascii_art_dft uhd ${CURSES_LIBRARIES}) + INSTALL(TARGETS rx_ascii_art_dft RUNTIME DESTINATION ${PKG_DATA_DIR}/examples) +ENDIF(CURSES_FOUND) diff --git a/host/examples/ascii_art_dft.hpp b/host/examples/ascii_art_dft.hpp new file mode 100644 index 000000000..ee2267c2d --- /dev/null +++ b/host/examples/ascii_art_dft.hpp @@ -0,0 +1,320 @@ +// +// ASCII Art DFT Plotter - Josh Blum +// + +#ifndef ASCII_ART_DFT_HPP +#define ASCII_ART_DFT_HPP + +#include +#include +#include +#include +#include + +namespace acsii_art_dft{ + + //! Type produced by the log power DFT function + typedef std::vector log_pwr_dft_type; + + /*! + * Get a logarithmic power DFT of the input samples. + * Samples are expected to be in the range [-1.0, 1.0]. + * \param samps a pointer to an array of complex samples + * \param nsamps the number of samples in the array + * \return a real range of DFT bins in units of dB + */ + template log_pwr_dft_type log_pwr_dft( + const std::complex *samps, size_t nsamps + ); + + /*! + * Convert a DFT to a piroundable ascii plot. + * \param dft the log power dft bins + * \param width the frame width in characters + * \param height the frame height in characters + * \param samp_rate the sample rate in Sps + * \param dc_freq the DC frequency in Hz + * \param dyn_rng the dynamic range in dB + * \param ref_lvl the reference level in dB + * \return the plot as an ascii string + */ + std::string dft_to_plot( + const log_pwr_dft_type &dft, + size_t width, + size_t height, + double samp_rate, + double dc_freq, + float dyn_rng, + float ref_lvl + ); + +} //namespace ascii_dft + +/*********************************************************************** + * Implementation includes + **********************************************************************/ +#include +#include +#include + +/*********************************************************************** + * Helper functions + **********************************************************************/ +namespace {/*anon*/ + + static const double pi = double(std::acos(-1.0)); + + //! Round a floating-point value to the nearest integer + template int iround(T val){ + return (val > 0)? int(val + 0.5) : int(val - 0.5); + } + + //! Pick the closest number that is nice to display + template T to_clean_num(const T num){ + if (num == 0) return 0; + const T pow10 = std::pow(T(10), int(std::floor(std::log10(std::abs(num))))); + const T norm = std::abs(num)/pow10; + static const int cleans[] = {1, 2, 5, 10}; + int clean = cleans[0]; + for (size_t i = 1; i < sizeof(cleans)/sizeof(cleans[0]); i++){ + if (std::abs(norm - cleans[i]) < std::abs(norm - clean)) + clean = cleans[i]; + } + return ((num < 0)? -1 : 1)*clean*pow10; + } + + //! Compute an FFT with pre-computed factors using Cooley-Tukey + template std::complex ct_fft_f( + const std::complex *samps, size_t nsamps, + const std::complex *factors, + size_t start = 0, size_t step = 1 + ){ + if (nsamps == 1) return samps[start]; + std::complex E_k = ct_fft_f(samps, nsamps/2, factors+1, start, step*2); + std::complex O_k = ct_fft_f(samps, nsamps/2, factors+1, start+step, step*2); + return E_k + factors[0]*O_k; + } + + //! Compute an FFT for a particular bin k using Cooley-Tukey + template std::complex ct_fft_k( + const std::complex *samps, size_t nsamps, size_t k + ){ + //pre-compute the factors to use in Cooley-Tukey + std::vector > factors; + for (size_t N = nsamps; N != 0; N /= 2){ + factors.push_back(std::exp(std::complex(0, T(-2*pi*k/N)))); + } + return ct_fft_f(samps, nsamps, &factors.front()); + } + + //! Helper class to build a DFT plot frame + class frame_type{ + public: + frame_type(size_t width, size_t height): + _frame(width-1, std::vector(height, ' ')) + { + /* NOP */ + } + + //accessors to parts of the frame + char &get_plot(size_t b, size_t z){return _frame.at(b+albl_w).at(z+flbl_h);} + char &get_albl(size_t b, size_t z){return _frame.at(b) .at(z+flbl_h);} + char &get_ulbl(size_t b) {return _frame.at(b) .at(flbl_h-1);} + char &get_flbl(size_t b) {return _frame.at(b+albl_w).at(flbl_h-1);} + + //dimension accessors + size_t get_plot_h(void) const{return _frame.front().size() - flbl_h;} + size_t get_plot_w(void) const{return _frame.size() - albl_w;} + size_t get_albl_w(void) const{return albl_w;} + + std::string to_string(void){ + std::stringstream frame_ss; + for (size_t z = 0; z < _frame.front().size(); z++){ + for (size_t b = 0; b < _frame.size(); b++){ + frame_ss << _frame[b][_frame[b].size()-z-1]; + } + frame_ss << std::endl; + } + return frame_ss.str(); + } + + private: + static const size_t albl_w = 6, flbl_h = 1; + std::vector > _frame; + }; + +} //namespace /*anon*/ + +/*********************************************************************** + * Implementation code + **********************************************************************/ +namespace acsii_art_dft{ + + //! skip constants for amplitude and frequency labels + static const size_t albl_skip = 5, flbl_skip = 20; + + template log_pwr_dft_type log_pwr_dft( + const std::complex *samps, size_t nsamps + ){ + if (nsamps & (nsamps - 1)) + throw std::runtime_error("num samps is not a power of 2"); + + //compute the window + double win_pwr = 0; + std::vector > win_samps; + for(size_t n = 0; n < nsamps; n++){ + //double w_n = 1; + //double w_n = 0.54 //hamming window + // -0.46*std::cos(2*pi*n/(nsamps-1)) + //; + double w_n = 0.35875 //blackman-harris window + -0.48829*std::cos(2*pi*n/(nsamps-1)) + +0.14128*std::cos(4*pi*n/(nsamps-1)) + -0.01168*std::cos(6*pi*n/(nsamps-1)) + ; + //double w_n = 1 // flat top window + // -1.930*std::cos(2*pi*n/(nsamps-1)) + // +1.290*std::cos(4*pi*n/(nsamps-1)) + // -0.388*std::cos(6*pi*n/(nsamps-1)) + // +0.032*std::cos(8*pi*n/(nsamps-1)) + //; + win_samps.push_back(T(w_n)*samps[n]); + win_pwr += w_n*w_n; + } + + //compute the log-power dft + log_pwr_dft_type log_pwr_dft; + for(size_t k = 0; k < nsamps; k++){ + std::complex dft_k = ct_fft_k(&win_samps.front(), nsamps, k); + log_pwr_dft.push_back(float( + + 20*std::log10(std::abs(dft_k)) + - 20*std::log10(T(nsamps)) + - 10*std::log10(win_pwr/nsamps) + + 3 + )); + } + + return log_pwr_dft; + } + + std::string dft_to_plot( + const log_pwr_dft_type &dft_, + size_t width, + size_t height, + double samp_rate, + double dc_freq, + float dyn_rng, + float ref_lvl + ){ + frame_type frame(width, height); //fill this frame + + //re-order the dft so dc in in the center + const size_t num_bins = dft_.size() - 1 + dft_.size()%2; //make it odd + log_pwr_dft_type dft(num_bins); + for (size_t n = 0; n < num_bins; n++){ + dft[n] = dft_[(n + num_bins/2)%num_bins]; + } + + //fill the plot with dft bins + for (size_t b = 0; b < frame.get_plot_w(); b++){ + //indexes from the dft to grab for the plot + const size_t n_start = std::max(iround(double(b-0.5)*(num_bins-1)/(frame.get_plot_w()-1)), 0); + const size_t n_stop = std::min(iround(double(b+0.5)*(num_bins-1)/(frame.get_plot_w()-1)), int(num_bins)); + + //calculate val as the max across points + float val = dft.at(n_start); + for (size_t n = n_start; n < n_stop; n++) val = std::max(val, dft.at(n)); + + const float scaled = (val - (ref_lvl - dyn_rng))*(frame.get_plot_h()-1)/dyn_rng; + for (size_t z = 0; z < frame.get_plot_h(); z++){ + static const std::string syms(".:!|"); + if (scaled-z > 1) frame.get_plot(b, z) = syms.at(syms.size()-1); + else if (scaled-z > 0) frame.get_plot(b, z) = syms.at(size_t((scaled-z)*syms.size())); + } + } + + //create vertical amplitude labels + const float db_step = to_clean_num(dyn_rng/(frame.get_plot_h()-1)*albl_skip); + for ( + float db = db_step*(int((ref_lvl - dyn_rng)/db_step)); + db <= db_step*(int(ref_lvl/db_step)); + db += db_step + ){ + const int z = iround((db - (ref_lvl - dyn_rng))*(frame.get_plot_h()-1)/dyn_rng); + if (z < 0 or size_t(z) >= frame.get_plot_h()) continue; + std::stringstream ss; ss << db; std::string lbl = ss.str(); + for (size_t i = 0; i < lbl.size() and i < frame.get_albl_w(); i++){ + frame.get_albl(i, z) = lbl[i]; + } + } + + //create vertical units label + std::string ulbl = "dBfs"; + for (size_t i = 0; i < ulbl.size(); i++){ + frame.get_ulbl(i+1) = ulbl[i]; + } + + //create horizontal frequency labels + const double f_step = to_clean_num(samp_rate/frame.get_plot_w()*flbl_skip); + for ( + double freq = f_step*int((-samp_rate/2/f_step)); + freq <= f_step*int((+samp_rate/2/f_step)); + freq += f_step + ){ + const int b = iround((freq + samp_rate/2)*(frame.get_plot_w()-1)/samp_rate); + std::stringstream ss; ss << (freq+dc_freq)/1e6 << "MHz"; std::string lbl = ss.str(); + if (b < int(lbl.size()/2) or b + lbl.size() - lbl.size()/2 >= frame.get_plot_w()) continue; + for (size_t i = 0; i < lbl.size(); i++){ + frame.get_flbl(b + i - lbl.size()/2) = lbl[i]; + } + } + + return frame.to_string(); + } +} //namespace ascii_dft + +#endif /*ASCII_ART_DFT_HPP*/ + +/* + +//example main function to test the dft + +#include +#include +#include + +int main(void){ + initscr(); + + while (true){ + clear(); + + std::vector > samples; + for(size_t i = 0; i < 512; i++){ + samples.push_back(std::complex( + float(std::rand() - RAND_MAX/2)/(RAND_MAX)/4, + float(std::rand() - RAND_MAX/2)/(RAND_MAX)/4 + )); + samples[i] += 0.5*std::sin(i*3.14/2) + 0.7; + } + + acsii_art_dft::log_pwr_dft_type dft; + dft = acsii_art_dft::log_pwr_dft(&samples.front(), samples.size()); + + printw("%s", acsii_art_dft::dft_to_plot( + dft, COLS, LINES, + 12.5e4, 2.45e9, + 60, 0 + ).c_str()); + + sleep(1); + } + + + endwin(); + std::cout << "here\n"; + return 0; +} + +*/ + diff --git a/host/examples/benchmark_rx_rate.cpp b/host/examples/benchmark_rx_rate.cpp index 36611f97f..b189368f9 100644 --- a/host/examples/benchmark_rx_rate.cpp +++ b/host/examples/benchmark_rx_rate.cpp @@ -137,7 +137,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; - sdev->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); //stop if left running if (not vm.count("rate")){ sdev->set_rx_rate(500e3); //initial rate diff --git a/host/examples/rx_ascii_art_dft.cpp b/host/examples/rx_ascii_art_dft.cpp new file mode 100644 index 000000000..5a24867b4 --- /dev/null +++ b/host/examples/rx_ascii_art_dft.cpp @@ -0,0 +1,143 @@ +// +// 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 "ascii_art_dft.hpp" //implementation +#include +#include //gets time +#include +#include +#include +#include + +namespace po = boost::program_options; + +int UHD_SAFE_MAIN(int argc, char *argv[]){ + uhd::set_thread_priority_safe(); + + //variables to be set by po + std::string args; + size_t num_bins; + double rate, freq, frame_rate; + float gain, ref_lvl, dyn_rng; + + //setup the program options + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "help message") + ("args", po::value(&args)->default_value(""), "single uhd device address args") + // hardware parameters + ("rate", po::value(&rate), "rate of incoming samples (sps)") + ("freq", po::value(&freq)->default_value(0), "RF center frequency in Hz") + ("gain", po::value(&gain)->default_value(0), "gain for the RF chain") + // display parameters + ("num-bins", po::value(&num_bins)->default_value(512), "the number of bins in the DFT") + ("frame-rate", po::value(&frame_rate)->default_value(5), "frame rate of the display (fps)") + ("ref-lvl", po::value(&ref_lvl)->default_value(0), "reference level for the display (dB)") + ("dyn-rng", po::value(&dyn_rng)->default_value(60), "dynamic range for the display (dB)") + ; + 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") or not vm.count("rate")){ + std::cout << boost::format("UHD RX ASCII Art DFT %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::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); + std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; + + //set the rx sample rate + std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate/1e6) << std::endl; + sdev->set_rx_rate(rate); + std::cout << boost::format("Actual RX Rate: %f Msps...") % (sdev->get_rx_rate()/1e6) << std::endl << std::endl; + + //set the rx center frequency + std::cout << boost::format("Setting RX Freq: %f Mhz...") % (freq/1e6) << std::endl; + sdev->set_rx_freq(freq); + std::cout << boost::format("Actual RX Freq: %f Mhz...") % (sdev->get_rx_freq()/1e6) << std::endl << std::endl; + + //set the rx rf gain + std::cout << boost::format("Setting RX Gain: %f dB...") % gain << std::endl; + sdev->set_rx_gain(gain); + std::cout << boost::format("Actual RX Gain: %f dB...") % sdev->get_rx_gain() << std::endl << std::endl; + + //allocate recv buffer and metatdata + uhd::rx_metadata_t md; + std::vector > buff(num_bins); + //------------------------------------------------------------------ + //-- Initialize + //------------------------------------------------------------------ + initscr(); //curses init + sdev->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); + boost::system_time next_refresh = boost::get_system_time(); + + //------------------------------------------------------------------ + //-- Main loop + //------------------------------------------------------------------ + while (true){ + //read a buffer's worth of samples every iteration + size_t num_rx_samps = sdev->get_device()->recv( + &buff.front(), buff.size(), md, + uhd::io_type_t::COMPLEX_FLOAT32, + uhd::device::RECV_MODE_FULL_BUFF + ); + if (num_rx_samps != buff.size()) continue; + + //check and update the display refresh condition + if (boost::get_system_time() < next_refresh) continue; + next_refresh = boost::get_system_time() + boost::posix_time::microseconds(long(1e6/frame_rate)); + + //calculate the dft and create the ascii art frame + acsii_art_dft::log_pwr_dft_type lpdft( + acsii_art_dft::log_pwr_dft(&buff.front(), num_rx_samps) + ); + std::string frame = acsii_art_dft::dft_to_plot( + lpdft, COLS, LINES, + sdev->get_rx_rate(), + sdev->get_rx_freq(), + dyn_rng, ref_lvl + ); + + //curses screen handling: clear and print frame + clear(); + printw("%s", frame.c_str()); + + //curses key handling: no timeout, any key to exit + timeout(0); + int ch = getch(); + if (ch != KEY_RESIZE and ch != ERR) break; + } + + //------------------------------------------------------------------ + //-- Cleanup + //------------------------------------------------------------------ + sdev->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); + endwin(); //curses done + + //finished + std::cout << std::endl << "Done!" << std::endl << std::endl; + + return 0; +} -- cgit v1.2.3 From 359c4e16b2d2748a97ce33073c64502a7f190aa6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 25 Oct 2010 13:41:40 -0700 Subject: uhd: created tune request struct and implemented more fine grained tuning calls --- host/include/uhd/types/CMakeLists.txt | 1 + host/include/uhd/types/tune_request.hpp | 97 ++++++++++++++++++++++ host/include/uhd/usrp/mimo_usrp.hpp | 16 ++-- host/include/uhd/usrp/multi_usrp.hpp | 31 +++---- host/include/uhd/usrp/simple_usrp.hpp | 16 ++-- host/include/uhd/usrp/single_usrp.hpp | 31 +++---- host/include/uhd/usrp/tune_helper.hpp | 31 ++----- host/lib/types.cpp | 20 +++++ host/lib/usrp/multi_usrp.cpp | 24 ++---- host/lib/usrp/single_usrp.cpp | 24 ++---- host/lib/usrp/tune_helper.cpp | 138 ++++++++++++++++++-------------- 11 files changed, 247 insertions(+), 182 deletions(-) create mode 100644 host/include/uhd/types/tune_request.hpp diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt index dbce21c98..661dd2d39 100644 --- a/host/include/uhd/types/CMakeLists.txt +++ b/host/include/uhd/types/CMakeLists.txt @@ -28,6 +28,7 @@ INSTALL(FILES serial.hpp stream_cmd.hpp time_spec.hpp + tune_request.hpp tune_result.hpp DESTINATION ${INCLUDE_DIR}/uhd/types ) diff --git a/host/include/uhd/types/tune_request.hpp b/host/include/uhd/types/tune_request.hpp new file mode 100644 index 000000000..f80d2cb15 --- /dev/null +++ b/host/include/uhd/types/tune_request.hpp @@ -0,0 +1,97 @@ +// +// 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_UHD_TYPES_TUNE_REQUEST_HPP +#define INCLUDED_UHD_TYPES_TUNE_REQUEST_HPP + +#include + +namespace uhd{ + + /*! + * A tune request instructs the implementation how to tune the RF chain. + * The policies can be used to select automatic tuning or + * fined control over the daughterboard IF and DSP tuning. + * Not all combinations of policies are applicable. + * Convenience constructors are supplied for most use cases. + */ + struct UHD_API tune_request_t{ + /*! + * Make a new tune request for a particular center frequency. + * Use an automatic policy for the intermediate and DSP frequency + * to tune the chain as close as possible to the target frequency. + * \param target_freq the target frequency in Hz + */ + tune_request_t(double target_freq = 0); + + /*! + * Make a new tune request for a particular center frequency. + * Use a manual policy for the intermediate frequency, + * and an automatic policy for the DSP frequency, + * to tune the chain as close as possible to the target frequency. + * \param target_freq the target frequency in Hz + * \param lo_off the LO offset frequency in Hz + */ + tune_request_t(double target_freq, double lo_off); + + /*! + * Policy types for tune arguments: + * - None: do not set this argument, use current setting + * - Auto: automatically determine the argument's value + * - Manual: use the argument's value for the setting + */ + enum policy_t { + POLICY_NONE = 'N', + POLICY_AUTO = 'A', + POLICY_MANUAL = 'M' + }; + + /*! + * The target frequency of the overall chain in Hz. + * Use when one of the policies is set to automatic. + */ + double target_freq; + + /*! + * The policy for the intermediate frequency. + * Automatic behavior: the target frequency + default LO offset. + */ + policy_t inter_freq_policy; + + /*! + * The intermediate frequency in Hz. + * Set when the policy is set to manual. + */ + double inter_freq; + + /*! + * The policy for the DSP frequency. + * Automatic behavior: the difference between the target and IF. + */ + policy_t dsp_freq_policy; + + /*! + * The DSP frequency in Hz. + * Set when the policy is set to manual. + */ + double dsp_freq; + + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_TUNE_REQUEST_HPP */ diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index 78833e24e..b5acf84e1 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -127,7 +127,7 @@ public: virtual double get_rx_rate_all(void) = 0; virtual tune_result_t set_rx_freq(size_t chan, double freq) = 0; - virtual tune_result_t set_rx_freq(size_t chan, double freq, double lo_off) = 0; + //virtual tune_result_t set_rx_freq(size_t chan, double freq, double lo_off) = 0; virtual double get_rx_freq(size_t chan) = 0; virtual freq_range_t get_rx_freq_range(size_t chan) = 0; @@ -161,7 +161,7 @@ public: virtual double get_tx_rate_all(void) = 0; virtual tune_result_t set_tx_freq(size_t chan, double freq) = 0; - virtual tune_result_t set_tx_freq(size_t chan, double freq, double lo_off) = 0; + //virtual tune_result_t set_tx_freq(size_t chan, double freq, double lo_off) = 0; virtual double get_tx_freq(size_t chan) = 0; virtual freq_range_t get_tx_freq_range(size_t chan) = 0; @@ -345,9 +345,9 @@ public: return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq); } - tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){ - return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq, lo_off); - } + //tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){ + // return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq, lo_off); + //} double get_rx_freq(size_t chan){ return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0); @@ -425,9 +425,9 @@ public: return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq); } - tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){ - return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq, lo_off); - } + //tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){ + // return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq, lo_off); + //} double get_tx_freq(size_t chan){ return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0); diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 2f71f80b1..5380d177d 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -213,20 +214,13 @@ public: /*! * Set the RX center frequency. - * \param freq the frequency in Hz + * \param tune_request tune request instructions * \param chan the channel index 0 to N-1 * \return a tune result object */ - virtual tune_result_t set_rx_freq(double freq, size_t chan) = 0; - - /*! - * Set the RX center frequency. - * \param freq the frequency in Hz - * \param lo_off an LO offset in Hz - * \param chan the channel index 0 to N-1 - * \return a tune result object - */ - virtual tune_result_t set_rx_freq(double freq, double lo_off, size_t chan) = 0; + virtual tune_result_t set_rx_freq( + const tune_request_t &tune_request, size_t chan = 0 + ) = 0; /*! * Get the RX center frequency. @@ -399,20 +393,13 @@ public: /*! * Set the TX center frequency. - * \param freq the frequency in Hz - * \param chan the channel index 0 to N-1 - * \return a tune result object - */ - virtual tune_result_t set_tx_freq(double freq, size_t chan) = 0; - - /*! - * Set the TX center frequency. - * \param freq the frequency in Hz - * \param lo_off an LO offset in Hz + * \param tune_request tune request instructions * \param chan the channel index 0 to N-1 * \return a tune result object */ - virtual tune_result_t set_tx_freq(double freq, double lo_off, size_t chan) = 0; + virtual tune_result_t set_tx_freq( + const tune_request_t &tune_request, size_t chan = 0 + ) = 0; /*! * Get the TX center frequency. diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index 22f4d64ba..59fd9bb09 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -117,7 +117,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 tune_result_t set_rx_freq(double freq, double lo_off) = 0; virtual double get_rx_freq(void) = 0; virtual freq_range_t get_rx_freq_range(void) = 0; @@ -152,7 +152,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 tune_result_t set_tx_freq(double freq, double lo_off) = 0; virtual double get_tx_freq(void) = 0; virtual freq_range_t get_tx_freq_range(void) = 0; @@ -243,9 +243,9 @@ public: return _sdev->set_rx_freq(target_freq); } - tune_result_t set_rx_freq(double target_freq, double lo_off){ - return _sdev->set_rx_freq(target_freq, lo_off); - } + //tune_result_t set_rx_freq(double target_freq, double lo_off){ + // return _sdev->set_rx_freq(target_freq, lo_off); + //} double get_rx_freq(void){ return _sdev->get_rx_freq(); @@ -318,9 +318,9 @@ public: return _sdev->set_tx_freq(target_freq); } - tune_result_t set_tx_freq(double target_freq, double lo_off){ - return _sdev->set_tx_freq(target_freq, lo_off); - } + //tune_result_t set_tx_freq(double target_freq, double lo_off){ + // return _sdev->set_tx_freq(target_freq, lo_off); + //} double get_tx_freq(void){ return _sdev->get_tx_freq(); diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index a068fbed8..26303fe10 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -154,20 +155,13 @@ public: /*! * Set the RX center frequency. - * \param freq the frequency in Hz + * \param tune_request tune request instructions * \param chan the channel index 0 to N-1 * \return a tune result object */ - virtual tune_result_t set_rx_freq(double freq, size_t chan = 0) = 0; - - /*! - * Set the RX center frequency. - * \param freq the frequency in Hz - * \param lo_off an LO offset in Hz - * \param chan the channel index 0 to N-1 - * \return a tune result object - */ - virtual tune_result_t set_rx_freq(double freq, double lo_off, size_t chan = 0) = 0; + virtual tune_result_t set_rx_freq( + const tune_request_t &tune_request, size_t chan = 0 + ) = 0; /*! * Get the RX center frequency. @@ -330,20 +324,13 @@ public: /*! * Set the TX center frequency. - * \param freq the frequency in Hz - * \param chan the channel index 0 to N-1 - * \return a tune result object - */ - virtual tune_result_t set_tx_freq(double freq, size_t chan = 0) = 0; - - /*! - * Set the TX center frequency. - * \param freq the frequency in Hz - * \param lo_off an LO offset in Hz + * \param tune_request tune request instructions * \param chan the channel index 0 to N-1 * \return a tune result object */ - virtual tune_result_t set_tx_freq(double freq, double lo_off, size_t chan = 0) = 0; + virtual tune_result_t set_tx_freq( + const tune_request_t &tune_request, size_t chan = 0 + ) = 0; /*! * Get the TX center frequency. diff --git a/host/include/uhd/usrp/tune_helper.hpp b/host/include/uhd/usrp/tune_helper.hpp index ec133fa08..db12241c1 100644 --- a/host/include/uhd/usrp/tune_helper.hpp +++ b/host/include/uhd/usrp/tune_helper.hpp @@ -20,6 +20,7 @@ #include #include +#include #include namespace uhd{ namespace usrp{ @@ -32,23 +33,12 @@ namespace uhd{ namespace usrp{ * \param subdev the dboard subdevice object with properties * \param ddc the mboard dsp object with properties * \param chan the channel of the dsp to tune - * \param target_freq the desired center frequency - * \param lo_offset an offset for the subdevice IF from center + * \param tune_request tune request instructions * \return a tune result struct */ UHD_API tune_result_t tune_rx_subdev_and_dsp( wax::obj subdev, wax::obj ddc, size_t chan, - double target_freq, double lo_offset - ); - - /*! - * Tune a rx chain to the desired frequency: - * Same as the above, except the LO offset - * is calculated based on the subdevice and BW. - */ - UHD_API tune_result_t tune_rx_subdev_and_dsp( - wax::obj subdev, wax::obj ddc, - size_t chan, double target_freq + const tune_request_t &tune_request ); /*! @@ -70,23 +60,12 @@ namespace uhd{ namespace usrp{ * \param subdev the dboard subdevice object with properties * \param duc the mboard dsp object with properties * \param chan the channel of the dsp to tune - * \param target_freq the desired center frequency - * \param lo_offset an offset for the subdevice IF from center + * \param tune_request tune request instructions * \return a tune result struct */ UHD_API tune_result_t tune_tx_subdev_and_dsp( wax::obj subdev, wax::obj duc, size_t chan, - double target_freq, double lo_offset - ); - - /*! - * Tune a tx chain to the desired frequency: - * Same as the above, except the LO offset - * is calculated based on the subdevice and BW. - */ - UHD_API tune_result_t tune_tx_subdev_and_dsp( - wax::obj subdev, wax::obj duc, - size_t chan, double target_freq + const tune_request_t &tune_request ); /*! diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 6aa82b012..a8062b6ae 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -57,6 +58,25 @@ freq_range_t::freq_range_t(double min, double max): /* NOP */ } +/*********************************************************************** + * tune request + **********************************************************************/ +tune_request_t::tune_request_t(double target_freq): + target_freq(target_freq), + inter_freq_policy(POLICY_AUTO), + dsp_freq_policy(POLICY_AUTO) +{ + /* NOP */ +} + +tune_request_t::tune_request_t(double target_freq, double lo_off): + target_freq(target_freq + lo_off), + inter_freq_policy(POLICY_MANUAL), + dsp_freq_policy(POLICY_AUTO) +{ + /* NOP */ +} + /*********************************************************************** * tune result **********************************************************************/ diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 443b91594..8b82502ba 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -210,15 +210,9 @@ public: return _rx_dsp(0)[DSP_PROP_HOST_RATE].as(); } - tune_result_t set_rx_freq(double target_freq, size_t chan){ - tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm(), target_freq); - do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX"); - return r; - } - - tune_result_t set_rx_freq(double target_freq, double lo_off, size_t chan){ - tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm(), target_freq, lo_off); - do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX"); + tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){ + tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm(), tune_request); + do_tune_freq_warning_message(tune_request.target_freq, get_rx_freq(chan), "RX"); return r; } @@ -314,15 +308,9 @@ public: return _tx_dsp(0)[DSP_PROP_HOST_RATE].as(); } - tune_result_t set_tx_freq(double target_freq, size_t chan){ - tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm(), target_freq); - do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX"); - return r; - } - - tune_result_t set_tx_freq(double target_freq, double lo_off, size_t chan){ - tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm(), target_freq, lo_off); - do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX"); + tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){ + tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm(), tune_request); + do_tune_freq_warning_message(tune_request.target_freq, get_tx_freq(chan), "TX"); return r; } diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index 5e57849b8..a0456d1f0 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -146,15 +146,9 @@ public: return _rx_dsp()[DSP_PROP_HOST_RATE].as(); } - tune_result_t set_rx_freq(double target_freq, size_t chan){ - tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, target_freq); - do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX"); - return r; - } - - tune_result_t set_rx_freq(double target_freq, double lo_off, size_t chan){ - tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, target_freq, lo_off); - do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX"); + tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){ + tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, tune_request); + do_tune_freq_warning_message(tune_request.target_freq, get_rx_freq(chan), "RX"); return r; } @@ -238,15 +232,9 @@ public: return _tx_dsp()[DSP_PROP_HOST_RATE].as(); } - tune_result_t set_tx_freq(double target_freq, size_t chan){ - tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, target_freq); - do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX"); - return r; - } - - tune_result_t set_tx_freq(double target_freq, double lo_off, size_t chan){ - tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, target_freq, lo_off); - do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX"); + tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){ + tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, tune_request); + do_tune_freq_warning_message(tune_request.target_freq, get_tx_freq(chan), "TX"); return r; } diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp index 7633c67f2..8c57cc428 100644 --- a/host/lib/usrp/tune_helper.cpp +++ b/host/lib/usrp/tune_helper.cpp @@ -28,55 +28,97 @@ using namespace uhd::usrp; /*********************************************************************** * Tune Helper Functions **********************************************************************/ -static tune_result_t tune_xx_subdev_and_dxc( +static tune_result_t tune_xx_subdev_and_dsp( dboard_iface::unit_t unit, - wax::obj subdev, wax::obj dxc, size_t chan, - double target_freq, double lo_offset + wax::obj subdev, wax::obj dsp, size_t chan, + const tune_request_t &tune_request ){ wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ]; - std::string freq_name = dxc[DSP_PROP_FREQ_SHIFT_NAMES].as().at(chan); - wax::obj dxc_freq_proxy = dxc[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)]; - double dxc_sample_rate = dxc[DSP_PROP_CODEC_RATE].as(); + std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as().at(chan); + wax::obj dsp_freq_proxy = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)]; + double dsp_sample_rate = dsp[DSP_PROP_CODEC_RATE].as(); - // Ask the d'board to tune as closely as it can to target_freq+lo_offset - double target_inter_freq = target_freq + lo_offset; - subdev_freq_proxy = target_inter_freq; - double actual_inter_freq = subdev_freq_proxy.as(); - - //perform the correction correction for dxc rates outside of nyquist - double delta_freq = std::fmod(target_freq - actual_inter_freq, dxc_sample_rate); - bool outside_of_nyquist = std::abs(delta_freq) > dxc_sample_rate/2.0; - double target_dxc_freq = (outside_of_nyquist)? - boost::math::sign(delta_freq)*dxc_sample_rate - delta_freq : -delta_freq; + //------------------------------------------------------------------ + //-- calculate the LO offset, only used with automatic policy + //------------------------------------------------------------------ + double lo_offset = 0.0; + if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as()){ + //if the local oscillator will be in the passband, use an offset + //TODO make this nicer, use bandwidth property to clip bounds + lo_offset = 2.0*dsp[DSP_PROP_HOST_RATE].as(); + } - //invert the sign on the dxc freq given the following conditions - if (unit == dboard_iface::UNIT_TX) target_dxc_freq *= -1.0; + //------------------------------------------------------------------ + //-- set the intermediate frequency depending upon the IF policy + //------------------------------------------------------------------ + double target_inter_freq = 0.0; + switch (tune_request.inter_freq_policy){ + case tune_request_t::POLICY_AUTO: + target_inter_freq = tune_request.target_freq + lo_offset; + subdev_freq_proxy = target_inter_freq; + break; + + case tune_request_t::POLICY_MANUAL: + target_inter_freq = tune_request.inter_freq; + subdev_freq_proxy = target_inter_freq; + break; + + case tune_request_t::POLICY_NONE: break; //does not set + } + double actual_inter_freq = subdev_freq_proxy.as(); - dxc_freq_proxy = target_dxc_freq; - double actual_dxc_freq = dxc_freq_proxy.as(); + //------------------------------------------------------------------ + //-- calculate the dsp freq, only used with automatic policy + //------------------------------------------------------------------ + double delta_freq = std::fmod(target_inter_freq - actual_inter_freq, dsp_sample_rate); + bool outside_of_nyquist = std::abs(delta_freq) > dsp_sample_rate/2.0; + double target_dsp_freq = (outside_of_nyquist)? + boost::math::sign(delta_freq)*dsp_sample_rate - delta_freq : -delta_freq; + + //invert the sign on the dsp freq given the following conditions + if (unit == dboard_iface::UNIT_TX) target_dsp_freq *= -1.0; + + //------------------------------------------------------------------ + //-- set the dsp frequency depending upon the dsp frequency policy + //------------------------------------------------------------------ + switch (tune_request.dsp_freq_policy){ + case tune_request_t::POLICY_AUTO: + dsp_freq_proxy = target_dsp_freq; + break; + + case tune_request_t::POLICY_MANUAL: + target_dsp_freq = tune_request.dsp_freq; + dsp_freq_proxy = target_dsp_freq; + break; + + case tune_request_t::POLICY_NONE: break; //does not set + } + double actual_dsp_freq = dsp_freq_proxy.as(); - //load and return the tune result + //------------------------------------------------------------------ + //-- load and return the tune result + //------------------------------------------------------------------ tune_result_t tune_result; tune_result.target_inter_freq = target_inter_freq; tune_result.actual_inter_freq = actual_inter_freq; - tune_result.target_dsp_freq = target_dxc_freq; - tune_result.actual_dsp_freq = actual_dxc_freq; + tune_result.target_dsp_freq = target_dsp_freq; + tune_result.actual_dsp_freq = actual_dsp_freq; return tune_result; } -static double derive_freq_from_xx_subdev_and_dxc( +static double derive_freq_from_xx_subdev_and_dsp( dboard_iface::unit_t unit, - wax::obj subdev, wax::obj dxc, size_t chan + wax::obj subdev, wax::obj dsp, size_t chan ){ //extract actual dsp and IF frequencies double actual_inter_freq = subdev[SUBDEV_PROP_FREQ].as(); - std::string freq_name = dxc[DSP_PROP_FREQ_SHIFT_NAMES].as().at(chan); - double actual_dxc_freq = dxc[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)].as(); + std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as().at(chan); + double actual_dsp_freq = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)].as(); - //invert the sign on the dxc freq given the following conditions - if (unit == dboard_iface::UNIT_TX) actual_dxc_freq *= -1.0; + //invert the sign on the dsp freq given the following conditions + if (unit == dboard_iface::UNIT_TX) actual_dsp_freq *= -1.0; - return actual_inter_freq - actual_dxc_freq; + return actual_inter_freq - actual_dsp_freq; } /*********************************************************************** @@ -84,27 +126,15 @@ static double derive_freq_from_xx_subdev_and_dxc( **********************************************************************/ tune_result_t usrp::tune_rx_subdev_and_dsp( wax::obj subdev, wax::obj ddc, size_t chan, - double target_freq, double lo_offset -){ - return tune_xx_subdev_and_dxc(dboard_iface::UNIT_RX, subdev, ddc, chan, target_freq, lo_offset); -} - -tune_result_t usrp::tune_rx_subdev_and_dsp( - wax::obj subdev, wax::obj ddc, - size_t chan, double target_freq + const tune_request_t &tune_request ){ - double lo_offset = 0.0; - //if the local oscillator will be in the passband, use an offset - if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as()){ - lo_offset = 2.0*ddc[DSP_PROP_HOST_RATE].as(); - } - return tune_rx_subdev_and_dsp(subdev, ddc, chan, target_freq, lo_offset); + return tune_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, chan, tune_request); } double usrp::derive_freq_from_rx_subdev_and_dsp( wax::obj subdev, wax::obj ddc, size_t chan ){ - return derive_freq_from_xx_subdev_and_dxc(dboard_iface::UNIT_RX, subdev, ddc, chan); + return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, chan); } /*********************************************************************** @@ -112,25 +142,13 @@ double usrp::derive_freq_from_rx_subdev_and_dsp( **********************************************************************/ tune_result_t usrp::tune_tx_subdev_and_dsp( wax::obj subdev, wax::obj duc, size_t chan, - double target_freq, double lo_offset + const tune_request_t &tune_request ){ - return tune_xx_subdev_and_dxc(dboard_iface::UNIT_TX, subdev, duc, chan, target_freq, lo_offset); -} - -tune_result_t usrp::tune_tx_subdev_and_dsp( - wax::obj subdev, wax::obj duc, - size_t chan, double target_freq -){ - double lo_offset = 0.0; - //if the local oscillator will be in the passband, use an offset - if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as()){ - lo_offset = 2.0*duc[DSP_PROP_HOST_RATE].as(); - } - return tune_tx_subdev_and_dsp(subdev, duc, chan, target_freq, lo_offset); + return tune_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, chan, tune_request); } double usrp::derive_freq_from_tx_subdev_and_dsp( wax::obj subdev, wax::obj duc, size_t chan ){ - return derive_freq_from_xx_subdev_and_dxc(dboard_iface::UNIT_TX, subdev, duc, chan); + return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, chan); } -- cgit v1.2.3 From f7966440b41b71f56009a78f5d7a7754f83aa04d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 25 Oct 2010 15:22:24 -0700 Subject: fix copy/paste typo piroundable --- host/examples/ascii_art_dft.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/examples/ascii_art_dft.hpp b/host/examples/ascii_art_dft.hpp index ee2267c2d..92fb77596 100644 --- a/host/examples/ascii_art_dft.hpp +++ b/host/examples/ascii_art_dft.hpp @@ -28,7 +28,7 @@ namespace acsii_art_dft{ ); /*! - * Convert a DFT to a piroundable ascii plot. + * Convert a DFT to a printable ascii plot. * \param dft the log power dft bins * \param width the frame width in characters * \param height the frame height in characters -- cgit v1.2.3 From bb82453a77c4bb8ff585fc498b300cd83bb62314 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Mon, 25 Oct 2010 15:42:08 -0700 Subject: Added bandwidth property to all daughterboards Updated existing bandwidth property to reflect double-sided bandwidth rather than lowpass bandwidth --- host/lib/usrp/dboard/db_basic_and_lf.cpp | 29 +++++++++++++++++++++++++++-- host/lib/usrp/dboard/db_dbsrx.cpp | 4 ++-- host/lib/usrp/dboard/db_rfx.cpp | 21 +++++++++++++++++++++ host/lib/usrp/dboard/db_tvrx.cpp | 10 ++++++++++ host/lib/usrp/dboard/db_unknown.cpp | 23 ++++++++++++++++++++++- host/lib/usrp/dboard/db_wbx.cpp | 21 +++++++++++++++++++++ host/lib/usrp/dboard/db_xcvr2450.cpp | 8 ++++---- 7 files changed, 107 insertions(+), 9 deletions(-) diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 41f6f8002..5a87f4ecf 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -68,11 +69,11 @@ static const uhd::dict sd_name_to_conn = map_list_of * Register the basic and LF dboards **********************************************************************/ static dboard_base::sptr make_basic_rx(dboard_base::ctor_args_t args){ - return dboard_base::sptr(new basic_rx(args, 90e9)); + return dboard_base::sptr(new basic_rx(args, 250e6)); } static dboard_base::sptr make_basic_tx(dboard_base::ctor_args_t args){ - return dboard_base::sptr(new basic_tx(args, 90e9)); + return dboard_base::sptr(new basic_tx(args, 250e6)); } static dboard_base::sptr make_lf_rx(dboard_base::ctor_args_t args){ @@ -161,6 +162,10 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ val = true; //there is no LO, so it must be true! return; + case SUBDEV_PROP_BANDWIDTH: + val = 2*_max_freq; //we want complex double-sided + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -185,6 +190,14 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("%s: No tunable bandwidth, fixed filtered to %0.2fMHz") + % get_rx_id().to_pp_string() % _max_freq + ) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -260,6 +273,10 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ val = true; //there is no LO, so it must be true! return; + case SUBDEV_PROP_BANDWIDTH: + val = 2*_max_freq; //we want complex double-sided + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -284,6 +301,14 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("%s: No tunable bandwidth, fixed filtered to %0.2fMHz") + % get_tx_id().to_pp_string() % _max_freq + ) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index aecd7249d..10e7f292b 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -563,7 +563,7 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - val = _bandwidth; + val = 2*_bandwidth; //_bandwidth is low-pass, we want complex double-sided return; default: UHD_THROW_PROP_GET_ERROR(); @@ -588,7 +588,7 @@ void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - this->set_bandwidth(val.as()); + this->set_bandwidth(val.as()/2.0); //complex double-sided, we want low-pass return; default: UHD_THROW_PROP_SET_ERROR(); diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 3c24d90db..0eeb0bfdf 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -456,6 +457,10 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ val = this->get_locked(dboard_iface::UNIT_RX); return; + case SUBDEV_PROP_BANDWIDTH: + val = 2*20.0e6; //30MHz low-pass, we want complex double-sided + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -481,6 +486,12 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("RFX: No tunable bandwidth, fixed filtered to 40MHz")) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -543,6 +554,10 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ val = this->get_locked(dboard_iface::UNIT_TX); return; + case SUBDEV_PROP_BANDWIDTH: + val = 2*20.0e6; //30MHz low-pass, we want complex double-sided + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -568,6 +583,12 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("RFX: No tunable bandwidth, fixed filtered to 40MHz")) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index d39dc3bf8..c7aecf195 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -459,6 +459,10 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ val = true; return; + case SUBDEV_PROP_BANDWIDTH: + val = 6.0e6; //30MHz low-pass, we want complex double-sided + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -479,6 +483,12 @@ void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("TVRX: No tunable bandwidth, fixed filtered to 6MHz")) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp index ec7ab440b..11293a1ba 100644 --- a/host/lib/usrp/dboard/db_unknown.cpp +++ b/host/lib/usrp/dboard/db_unknown.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -134,6 +135,10 @@ void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){ val = true; //there is no LO, so it must be true! return; + case SUBDEV_PROP_BANDWIDTH: + val = 0.0; + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -158,12 +163,18 @@ void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz")) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } /*********************************************************************** - * Basic and LF TX dboard + * Unknown TX dboard **********************************************************************/ unknown_tx::unknown_tx(ctor_args_t args) : tx_dboard_base(args){ /* NOP */ @@ -230,6 +241,10 @@ void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){ val = true; //there is no LO, so it must be true! return; + case SUBDEV_PROP_BANDWIDTH: + val = 0.0; + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -254,6 +269,12 @@ void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz")) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index 907268aac..b07f179a3 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -71,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -525,6 +526,10 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ val = this->get_locked(dboard_iface::UNIT_RX); return; + case SUBDEV_PROP_BANDWIDTH: + val = 2*30.0e6; //20MHz low-pass, we want complex double-sided + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -550,6 +555,12 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("WBX: No tunable bandwidth, fixed filtered to 40MHz")) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -616,6 +627,10 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ val = this->get_locked(dboard_iface::UNIT_TX); return; + case SUBDEV_PROP_BANDWIDTH: + val = 2*30.0e6; //20MHz low-pass, we want complex double-sided + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -641,6 +656,12 @@ void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("WBX: No tunable bandwidth, fixed filtered to 40MHz")) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index fb1367113..be0e42b92 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -626,7 +626,7 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - val = _rx_bandwidth; + val = 2*_rx_bandwidth; //_tx_bandwidth is low-pass, we want complex double-sided return; default: UHD_THROW_PROP_GET_ERROR(); @@ -652,7 +652,7 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - this->set_rx_bandwidth(val.as()); + this->set_rx_bandwidth(val.as()/2.0); //complex double-sided, we want low-pass return; case SUBDEV_PROP_ENABLED: @@ -725,7 +725,7 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - val = _tx_bandwidth; + val = 2*_tx_bandwidth; //_tx_bandwidth is low-pass, we want complex double-sided return; default: UHD_THROW_PROP_GET_ERROR(); @@ -747,7 +747,7 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - this->set_tx_bandwidth(val.as()); + this->set_tx_bandwidth(val.as()/2.0); //complex double-sided, we want low-pass return; case SUBDEV_PROP_ANTENNA: -- cgit v1.2.3 From c398e8f437cd21ca9132f7227546060f8dcf9e5c Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Mon, 25 Oct 2010 16:45:09 -0700 Subject: Updated bandwidths in daughterboard docs --- host/docs/dboards.rst | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst index 080117651..d93fb9d6a 100644 --- a/host/docs/dboards.rst +++ b/host/docs/dboards.rst @@ -26,6 +26,10 @@ The boards have no tunable elements or programmable gains. Though the magic of aliasing, you can down-convert signals greater than the Nyquist rate of the ADC. +BasicRX Bandwidth (Hz): 250M + +LFRX Bandwidth (Hz): 30M + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Basic TX and and LFTX ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,6 +44,10 @@ The boards have no tunable elements or programmable gains. Though the magic of aliasing, you can up-convert signals greater than the Nyquist rate of the DAC. +BasicTX Bandwidth (Hz): 250M + +LFTX Bandwidth (Hz): 30M + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ DBSRX ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -53,7 +61,7 @@ Receive Gains: **GC1**, Range: 0-56dB **GC2**, Range: 0-24dB -Low-Pass Filter Bandwidth (Hz): 4M-33M +Bandwidth (Hz): 8M-66M ^^^^^^^^^^^^^^^^^^^^^^^^^^^ RFX Series @@ -68,6 +76,10 @@ the receive antenna will always be set to RX2, regardless of the settings. Receive Gains: **PGA0**, Range: 0-70dB (except RFX400 range is 0-45dB) +Bandwidths (Hz): + * **RX**: 40M + * **TX**: 40M + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ XCVR 2450 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -93,9 +105,9 @@ Receive Gains: * **LNA**, Range: 0-30.5dB * **VGA**, Range: 0-62dB -Low-Pass Filter Bandwidths (Hz): - * **RX**: 7.5M, 9.5M, 14M, 18M; (each +-0, 5, or 10%) - * **TX**: 12M, 18M, 24M +Bandwidths (Hz): + * **RX**: 15M, 19M, 28M, 36M; (each +-0, 5, or 10%) + * **TX**: 24M, 36M, 48M ^^^^^^^^^^^^^^^^^^^^^^^^^^^ WBX Series @@ -112,9 +124,9 @@ Transmit Gains: **PGA0**, Range: 0-25dB Receive Gains: **PGA0**, Range: 0-31.5dB -Low-Pass Filter Bandwidths (Hz): - * **RX**: 20M (Fixed) - * **TX**: 20M (Fixed) +Bandwidths (Hz): + * **RX**: 40M + * **TX**: 40M ^^^^^^^^^^^^^^^^^^^^^^^^^^^ TVRX @@ -125,7 +137,7 @@ Receive Gains: * **RF**, Range: -13.3-50.3dB (frequency-dependent) * **IF**, Range: -1.5-32.5dB -Bandpass Filter Bandwidth: 6MHz +Bandwidth: 6MHz ------------------------------------------------------------------------ Daughterboard Modifications -- cgit v1.2.3 From 2d21958e1b7ecc9ff083f2e60b0b5d06ccb3c638 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 25 Oct 2010 17:04:51 -0700 Subject: uhd: tune helper + request, forgot to use and set target freq --- host/lib/types.cpp | 3 ++- host/lib/usrp/tune_helper.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/host/lib/types.cpp b/host/lib/types.cpp index a8062b6ae..4188568aa 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -70,8 +70,9 @@ tune_request_t::tune_request_t(double target_freq): } tune_request_t::tune_request_t(double target_freq, double lo_off): - target_freq(target_freq + lo_off), + target_freq(target_freq), inter_freq_policy(POLICY_MANUAL), + inter_freq(target_freq + lo_off), dsp_freq_policy(POLICY_AUTO) { /* NOP */ diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp index 8c57cc428..a6b615926 100644 --- a/host/lib/usrp/tune_helper.cpp +++ b/host/lib/usrp/tune_helper.cpp @@ -70,7 +70,7 @@ static tune_result_t tune_xx_subdev_and_dsp( //------------------------------------------------------------------ //-- calculate the dsp freq, only used with automatic policy //------------------------------------------------------------------ - double delta_freq = std::fmod(target_inter_freq - actual_inter_freq, dsp_sample_rate); + double delta_freq = std::fmod(tune_request.target_freq - actual_inter_freq, dsp_sample_rate); bool outside_of_nyquist = std::abs(delta_freq) > dsp_sample_rate/2.0; double target_dsp_freq = (outside_of_nyquist)? boost::math::sign(delta_freq)*dsp_sample_rate - delta_freq : -delta_freq; -- cgit v1.2.3 From 01f670e81c615a16fb5a931d3842f92b56cc6c09 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 25 Oct 2010 18:09:48 -0700 Subject: uhd: doxygen comments, moved enum comments, added to metadata for all entities --- host/include/uhd/types/metadata.hpp | 76 ++++++++++++++++----------------- host/include/uhd/types/tune_request.hpp | 12 +++--- 2 files changed, 43 insertions(+), 45 deletions(-) diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp index 65952941c..3f250d13e 100644 --- a/host/include/uhd/types/metadata.hpp +++ b/host/include/uhd/types/metadata.hpp @@ -19,7 +19,6 @@ #define INCLUDED_UHD_TYPES_METADATA_HPP #include -#include #include namespace uhd{ @@ -30,58 +29,59 @@ namespace uhd{ * The receive routines will convert IF data headers into metadata. */ struct UHD_API rx_metadata_t{ - /*! - * Time specification: - * Set from timestamps on incoming data when provided. - */ + //! Has time specification? bool has_time_spec; + + //! Time of the first sample. time_spec_t time_spec; /*! - * Fragmentation flag and offset: + * Fragmentation flag: * Similar to IPv4 fragmentation: http://en.wikipedia.org/wiki/IPv4#Fragmentation_and_reassembly * More fragments is true when the input buffer has insufficient size to fit * an entire received packet. More fragments will be false for the last fragment. - * The fragment offset is the sample number at the start of the receive buffer. - * For non-fragmented receives, the fragment offset should always be zero. */ bool more_fragments; - size_t fragment_offset; /*! - * Burst flags: - * Start of burst will be true for the first packet in the chain. - * End of burst will be true for the last packet in the chain. + * Fragmentation offset: + * The fragment offset is the sample number at the start of the receive buffer. + * For non-fragmented receives, the fragment offset should always be zero. */ + size_t fragment_offset; + + //! Start of burst will be true for the first packet in the chain. bool start_of_burst; + + //! End of burst will be true for the last packet in the chain. bool end_of_burst; /*! - * Error conditions: - * - none: no error associated with this metadata - * - timeout: no packet received, underlying code timed-out - * - late command: a stream command was issued in the past - * - broken chain: expected another stream command - * - overflow: an internal receive buffer has filled - * - bad packet: the buffer was unrecognizable as a vrt packet + * The error condition on a receive call. * * Note: When an overrun occurs in continuous streaming mode, * the device will continue to send samples to the host. * For other streaming modes, streaming will discontinue * until the user issues a new stream command. * - * Note: The metadata fields have meaning for the following error codes: + * The metadata fields have meaning for the following error codes: * - none * - late command * - broken chain * - overflow */ enum error_code_t { + //! No error associated with this metadata. ERROR_CODE_NONE = 0x0, + //! No packet received, implementation timed-out. ERROR_CODE_TIMEOUT = 0x1, + //! A stream command was issued in the past. ERROR_CODE_LATE_COMMAND = 0x2, + //! Expected another stream command. ERROR_CODE_BROKEN_CHAIN = 0x4, + //! An internal receive buffer has filled. ERROR_CODE_OVERFLOW = 0x8, + //! The packet could not be parsed. ERROR_CODE_BAD_PACKET = 0xf } error_code; }; @@ -93,19 +93,19 @@ namespace uhd{ */ struct UHD_API tx_metadata_t{ /*! - * Time specification: - * Set has time spec to false to perform a send "now". - * Or, set to true, and fill in time spec for a send "at". + * Has time specification? + * - Set false to send immediately. + * - Set true to send at the time specified by time spec. */ bool has_time_spec; + + //! When to send the first sample. time_spec_t time_spec; - /*! - * Burst flags: - * Set start of burst to true for the first packet in the chain. - * Set end of burst to true for the last packet in the chain. - */ + //! Set start of burst to true for the first packet in the chain. bool start_of_burst; + + //! Set end of burst to true for the last packet in the chain. bool end_of_burst; /*! @@ -122,27 +122,27 @@ namespace uhd{ //! The channel number in a mimo configuration size_t channel; - /*! - * Time specification: when the async event occurred. - */ + //! Has time specification? bool has_time_spec; + + //! When the async event occurred. time_spec_t time_spec; /*! - * Event codes: - * - success: a packet was successfully transmitted - * - underflow: an internal send buffer has emptied - * - sequence error: packet loss between host and device - * - time error: packet had time that was late (or too early) - * - underflow in packet: underflow occurred inside a packet - * - sequence error in burst: packet loss within a burst + * The type of event for a receive async message call. */ enum event_code_t { + //! A packet was successfully transmitted. EVENT_CODE_SUCCESS = 0x1, + //! An internal send buffer has emptied. EVENT_CODE_UNDERFLOW = 0x2, + //! Packet loss between host and device. EVENT_CODE_SEQ_ERROR = 0x4, + //! Packet had time that was late (or too early). EVENT_CODE_TIME_ERROR = 0x8, + //! Underflow occurred inside a packet. EVENT_CODE_UNDERFLOW_IN_PACKET = 0x10, + //! Packet loss within a burst. EVENT_CODE_SEQ_ERROR_IN_BURST = 0x20 } event_code; }; diff --git a/host/include/uhd/types/tune_request.hpp b/host/include/uhd/types/tune_request.hpp index f80d2cb15..b05ab5cc7 100644 --- a/host/include/uhd/types/tune_request.hpp +++ b/host/include/uhd/types/tune_request.hpp @@ -48,21 +48,19 @@ namespace uhd{ */ tune_request_t(double target_freq, double lo_off); - /*! - * Policy types for tune arguments: - * - None: do not set this argument, use current setting - * - Auto: automatically determine the argument's value - * - Manual: use the argument's value for the setting - */ + //! Policy options for tunable elements in the RF chain. enum policy_t { + //! Do not set this argument, use current setting. POLICY_NONE = 'N', + //! Automatically determine the argument's value. POLICY_AUTO = 'A', + //! Use the argument's value for the setting. POLICY_MANUAL = 'M' }; /*! * The target frequency of the overall chain in Hz. - * Use when one of the policies is set to automatic. + * Use in conjunction with the automatic policies. */ double target_freq; -- cgit v1.2.3 From 0168bff835371140c0d75cc381e3228f8093fe70 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 25 Oct 2010 19:22:51 -0700 Subject: usrp: rework lo offset logic to use bandwidth, add test case --- host/lib/usrp/tune_helper.cpp | 9 +++-- host/test/tune_helper_test.cpp | 79 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 6 deletions(-) diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp index a6b615926..fa40a8a26 100644 --- a/host/lib/usrp/tune_helper.cpp +++ b/host/lib/usrp/tune_helper.cpp @@ -19,6 +19,7 @@ #include #include #include //unit_t +#include #include #include @@ -43,9 +44,11 @@ static tune_result_t tune_xx_subdev_and_dsp( //------------------------------------------------------------------ double lo_offset = 0.0; if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as()){ - //if the local oscillator will be in the passband, use an offset - //TODO make this nicer, use bandwidth property to clip bounds - lo_offset = 2.0*dsp[DSP_PROP_HOST_RATE].as(); + //If the local oscillator will be in the passband, use an offset. + //But constrain the LO offset by the width of the filter bandwidth. + double rate = dsp[DSP_PROP_HOST_RATE].as(); + double bw = subdev[SUBDEV_PROP_BANDWIDTH].as(); + if (bw > rate) lo_offset = std::min((bw - rate)/2, rate/2); } //------------------------------------------------------------------ diff --git a/host/test/tune_helper_test.cpp b/host/test/tune_helper_test.cpp index 1ef4af330..e0500ae3f 100644 --- a/host/test/tune_helper_test.cpp +++ b/host/test/tune_helper_test.cpp @@ -91,6 +91,44 @@ private: } }; +class dummy_subdev_bw : public wax::obj{ +private: + void get(const wax::obj &key, wax::obj &val){ + switch(key.as()){ + + case SUBDEV_PROP_FREQ: + val = _freq; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = true; + return; + + case SUBDEV_PROP_BANDWIDTH: + val = _bandwidth; + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } + } + + void set(const wax::obj &key, const wax::obj &val){ + switch(key.as()){ + case SUBDEV_PROP_FREQ: + _freq = val.as(); + return; + + case SUBDEV_PROP_BANDWIDTH: + _bandwidth = val.as(); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } + } + + double _freq, _bandwidth; +}; + class dummy_dsp : public wax::obj{ public: dummy_dsp(double codec_rate): @@ -106,6 +144,10 @@ private: val = _codec_rate; return; + case DSP_PROP_HOST_RATE: + val = _host_rate; + return; + case DSP_PROP_FREQ_SHIFT: val = _freq_shift; return; @@ -125,11 +167,15 @@ private: _freq_shift = val.as(); return; + case DSP_PROP_HOST_RATE: + _host_rate = val.as(); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } - double _codec_rate, _freq_shift; + double _codec_rate, _freq_shift, _host_rate; }; /*********************************************************************** @@ -141,7 +187,7 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx){ dummy_subdev subdev(1e6); dummy_dsp dsp(100e6); - std::cout << "Testing tune helper RX automatic LO offset" << std::endl; + std::cout << "Testing tune helper RX automatic IF offset" << std::endl; tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9); std::cout << tr.to_pp_string() << std::endl; BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance); @@ -155,7 +201,7 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_tx){ dummy_subdev subdev(1e6); dummy_dsp dsp(100e6); - std::cout << "Testing tune helper TX automatic LO offset" << std::endl; + std::cout << "Testing tune helper TX automatic IF offset" << std::endl; tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9); std::cout << tr.to_pp_string() << std::endl; BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance); @@ -178,3 +224,30 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx_nyquist){ double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0); BOOST_CHECK_CLOSE(freq_derived, -45e6, tolerance); } + +BOOST_AUTO_TEST_CASE(test_tune_helper_rx_lo_off){ + dummy_subdev_bw subdev; + dummy_dsp dsp(100e6); + tune_result_t tr; + + std::cout << "Testing tune helper RX automatic LO offset B >> fs" << std::endl; + subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6); + dsp[DSP_PROP_HOST_RATE] = double(4e6); + tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9); + std::cout << tr.to_pp_string() << std::endl; + BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+4e6/2, tolerance); + + std::cout << "Testing tune helper RX automatic LO offset B > fs" << std::endl; + subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6); + dsp[DSP_PROP_HOST_RATE] = double(25e6); + tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9); + std::cout << tr.to_pp_string() << std::endl; + BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+(40e6-25e6)/2, tolerance); + + std::cout << "Testing tune helper RX automatic LO offset B < fs" << std::endl; + subdev[SUBDEV_PROP_BANDWIDTH] = double(20e6); + dsp[DSP_PROP_HOST_RATE] = double(25e6); + tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9); + std::cout << tr.to_pp_string() << std::endl; + BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9, tolerance); +} -- cgit v1.2.3 From ef8ed898cbc6cb6cd1994d2a8b090112f4f3a664 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 26 Oct 2010 09:47:53 -0700 Subject: usrp: fixed validate subdev spec typo for empty string cases --- host/lib/usrp/misc_utils.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp index 7e49baa52..5856d706f 100644 --- a/host/lib/usrp/misc_utils.cpp +++ b/host/lib/usrp/misc_utils.cpp @@ -164,13 +164,13 @@ static void verify_xx_subdev_spec( } //sanity check that the dboard/subdevice names exist for this mboard - BOOST_FOREACH(const subdev_spec_pair_t &pair, subdev_spec){ + BOOST_FOREACH(subdev_spec_pair_t &pair, subdev_spec){ //empty db name means select dboard automatically if (pair.db_name.empty()){ if (dboard_names.size() != 1) throw std::runtime_error( "A daughterboard name must be provided for multi-slot motherboards: " + subdev_spec.to_string() ); - pair.db_name == dboard_names.front(); + pair.db_name = dboard_names.front(); } uhd::assert_has(dboard_names, pair.db_name, xx_type + " dboard name"); wax::obj dboard = mboard[named_prop_t(dboard_prop, pair.db_name)]; @@ -181,7 +181,7 @@ static void verify_xx_subdev_spec( if (subdev_names.size() != 1) throw std::runtime_error( "A subdevice name must be provided for multi-subdev daughterboards: " + subdev_spec.to_string() ); - pair.sd_name == subdev_names.front(); + pair.sd_name = subdev_names.front(); } uhd::assert_has(subdev_names, pair.sd_name, xx_type + " subdev name"); } -- cgit v1.2.3 From cea3d05095202413be12cd4792ab9f781cbccef7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 26 Oct 2010 14:14:01 -0700 Subject: uhd: replaced print warning with a post warning call and registry renamed print warning calls in the implementation fixed issue with dict::pop so it now works even if the value is not comparable --- host/include/uhd/types/dict.hpp | 23 ++++++++---- host/include/uhd/types/tune_request.hpp | 2 +- host/include/uhd/usrp/mimo_usrp.hpp | 4 +-- host/include/uhd/usrp/simple_usrp.hpp | 2 +- host/include/uhd/utils/warning.hpp | 36 ++++++++++++++++--- host/lib/transport/udp_zero_copy_asio.cpp | 2 +- host/lib/usrp/dboard/db_basic_and_lf.cpp | 4 +-- host/lib/usrp/dboard/db_dbsrx.cpp | 8 ++--- host/lib/usrp/dboard/db_rfx.cpp | 4 +-- host/lib/usrp/dboard/db_tvrx.cpp | 2 +- host/lib/usrp/dboard/db_unknown.cpp | 4 +-- host/lib/usrp/dboard/db_wbx.cpp | 4 +-- host/lib/usrp/dboard_manager.cpp | 4 +-- host/lib/usrp/multi_usrp.cpp | 2 +- host/lib/usrp/usrp1/mboard_impl.cpp | 2 +- host/lib/usrp/usrp1/usrp1_impl.cpp | 2 +- host/lib/usrp/wrapper_utils.hpp | 4 +-- host/lib/utils/thread_priority.cpp | 2 +- host/lib/utils/warning.cpp | 59 ++++++++++++++++++++++++++++--- host/test/warning_test.cpp | 4 +-- 20 files changed, 131 insertions(+), 43 deletions(-) diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp index de96ea768..3d0acf888 100644 --- a/host/include/uhd/types/dict.hpp +++ b/host/include/uhd/types/dict.hpp @@ -120,10 +120,7 @@ namespace uhd{ BOOST_FOREACH(const pair_t &p, _map){ if (p.first == key) return p.second; } - throw std::invalid_argument(str(boost::format( - "key \"%s\" not found in dict(%s, %s)" - ) % boost::lexical_cast(key) - % typeid(Key).name() % typeid(Val).name())); + throw key_not_found_in_dict(key); } /*! @@ -147,12 +144,24 @@ namespace uhd{ * \throw an exception when not found */ Val pop(const Key &key){ - Val val = (*this)[key]; - _map.remove(pair_t(key, val)); - return val; + typename std::list::iterator it; + for (it = _map.begin(); it != _map.end(); it++){ + if (it->first != key) continue; + Val val = it->second; + _map.erase(it); + return val; + } + throw key_not_found_in_dict(key); } private: + std::exception key_not_found_in_dict(const Key &key) const{ + return std::out_of_range(str(boost::format( + "key \"%s\" not found in dict(%s, %s)" + ) % boost::lexical_cast(key) + % typeid(Key).name() % typeid(Val).name())); + } + std::list _map; //private container }; diff --git a/host/include/uhd/types/tune_request.hpp b/host/include/uhd/types/tune_request.hpp index b05ab5cc7..942b93251 100644 --- a/host/include/uhd/types/tune_request.hpp +++ b/host/include/uhd/types/tune_request.hpp @@ -60,7 +60,7 @@ namespace uhd{ /*! * The target frequency of the overall chain in Hz. - * Use in conjunction with the automatic policies. + * Set this even if all policies are set to manual. */ double target_freq; diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index b5acf84e1..a2092f04f 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -298,7 +298,7 @@ public: time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); time_spec_t time_i = _mboard(chan)[MBOARD_PROP_TIME_NOW].as(); if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "Detected time deviation between board %d and board 0.\n" "Board 0 time is %f seconds.\n" "Board %d time is %f seconds.\n" @@ -512,7 +512,7 @@ namespace uhd{ namespace usrp{ * The Make Function **********************************************************************/ inline mimo_usrp::sptr mimo_usrp::make(const device_addr_t &dev_addr){ - uhd::print_warning( + uhd::warning::post( "The mimo USRP interface has been deprecated.\n" "Please switch to the multi USRP interface.\n" "#include \n" diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index 59fd9bb09..77416dbbd 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -374,7 +374,7 @@ namespace uhd{ namespace usrp{ * The Make Function **********************************************************************/ inline simple_usrp::sptr simple_usrp::make(const device_addr_t &dev_addr){ - uhd::print_warning( + uhd::warning::post( "The simple USRP interface has been deprecated.\n" "Please switch to the single USRP interface.\n" "#include \n" diff --git a/host/include/uhd/utils/warning.hpp b/host/include/uhd/utils/warning.hpp index 91d8400ab..a1e3f0d1e 100644 --- a/host/include/uhd/utils/warning.hpp +++ b/host/include/uhd/utils/warning.hpp @@ -19,16 +19,44 @@ #define INCLUDED_UHD_UTILS_WARNING_HPP #include +#include +#include #include -namespace uhd{ +namespace uhd{ namespace warning{ + + //! Callback function type for a message handler + typedef boost::function handler_t; /*! - * Print a formatted warning string to stderr. + * Post a warning message to all registered handlers. * \param msg the multiline warning message */ - UHD_API void print_warning(const std::string &msg); + UHD_API void post(const std::string &msg); + + /*! + * Register a new handler with this name. + * If the name was already registered for this name, + * the old registered handler will be replaced. + * \param name a unique name for this handler + * \param handler the callback handler function + */ + UHD_API void register_handler(const std::string &name, const handler_t &handler); + + /*! + * Unregister a handler for this name. + * \param name a unique name for a registered handler + * \return the handler that was registered + * \throw error when the name was not found in the registry + */ + UHD_API handler_t unregister_handler(const std::string &name); + + /*! + * Get a list of registered handler names. + * \return a vector of unique string names + */ + UHD_API const std::vector registry_names(void); -} //namespace uhd +}} //namespace uhd::warning #endif /* INCLUDED_UHD_UTILS_WARNING_HPP */ diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index d84aeefdd..ed29864e9 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -336,7 +336,7 @@ template static void resize_buff_helper( else std::cout << boost::format( "Current %s sock buff size: %d bytes" ) % name % actual_size << std::endl; - if (actual_size < target_size) uhd::print_warning(str(boost::format( + if (actual_size < target_size) uhd::warning::post(str(boost::format( "The %s buffer is smaller than the requested size.\n" "The minimum recommended buffer size is %d bytes.\n" "See the transport application notes on buffer resizing.\n%s" diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 5a87f4ecf..4c49b3bff 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -191,7 +191,7 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("%s: No tunable bandwidth, fixed filtered to %0.2fMHz") % get_rx_id().to_pp_string() % _max_freq ) @@ -302,7 +302,7 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("%s: No tunable bandwidth, fixed filtered to %0.2fMHz") % get_tx_id().to_pp_string() % _max_freq ) diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 10e7f292b..85251bdf9 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -175,7 +175,7 @@ UHD_STATIC_BLOCK(reg_dbsrx_dboard){ dbsrx::dbsrx(ctor_args_t args) : rx_dboard_base(args){ //warn user about incorrect DBID on USRP1, requires R193 populated if (this->get_iface()->get_special_props().soft_clock_divider and this->get_rx_id() == 0x000D) - uhd::print_warning( + uhd::warning::post( str(boost::format( "DBSRX: incorrect dbid\n" "Expected dbid 0x0002 and R193\n" @@ -186,7 +186,7 @@ dbsrx::dbsrx(ctor_args_t args) : rx_dboard_base(args){ //warn user about incorrect DBID on non-USRP1, requires R194 populated if (not this->get_iface()->get_special_props().soft_clock_divider and this->get_rx_id() == 0x0002) - uhd::print_warning( + uhd::warning::post( str(boost::format( "DBSRX: incorrect dbid\n" "Expected dbid 0x000D and R194\n" @@ -342,7 +342,7 @@ void dbsrx::set_lo_freq(double target_freq){ //vtune is too low, try lower frequency vco if (_max2118_read_regs.adc == 0){ if (_max2118_write_regs.osc_band == 0){ - uhd::print_warning( + uhd::warning::post( str(boost::format( "DBSRX: Tuning exceeded vco range, _max2118_write_regs.osc_band == %d\n" ) % int(_max2118_write_regs.osc_band)) @@ -356,7 +356,7 @@ void dbsrx::set_lo_freq(double target_freq){ //vtune is too high, try higher frequency vco if (_max2118_read_regs.adc == 7){ if (_max2118_write_regs.osc_band == 7){ - uhd::print_warning( + uhd::warning::post( str(boost::format( "DBSRX: Tuning exceeded vco range, _max2118_write_regs.osc_band == %d\n" ) % int(_max2118_write_regs.osc_band)) diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 0eeb0bfdf..12e458d8c 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -487,7 +487,7 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("RFX: No tunable bandwidth, fixed filtered to 40MHz")) ); return; @@ -584,7 +584,7 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("RFX: No tunable bandwidth, fixed filtered to 40MHz")) ); return; diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index c7aecf195..1f3c76556 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -484,7 +484,7 @@ void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("TVRX: No tunable bandwidth, fixed filtered to 6MHz")) ); return; diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp index 11293a1ba..a342471c4 100644 --- a/host/lib/usrp/dboard/db_unknown.cpp +++ b/host/lib/usrp/dboard/db_unknown.cpp @@ -164,7 +164,7 @@ void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz")) ); return; @@ -270,7 +270,7 @@ void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz")) ); return; diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index b07f179a3..647f1b975 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -556,7 +556,7 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("WBX: No tunable bandwidth, fixed filtered to 40MHz")) ); return; @@ -657,7 +657,7 @@ void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("WBX: No tunable bandwidth, fixed filtered to 40MHz")) ); return; diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index d73a698ae..5a98bb8eb 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -189,7 +189,7 @@ static args_t get_dboard_args( //verify that there is a registered constructor for this id if (not get_id_to_args_map().has_key(dboard_id)){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "Unknown dboard ID: %s.\n" ) % dboard_id.to_pp_string())); return get_dboard_args(unit, dboard_id, true); @@ -217,7 +217,7 @@ dboard_manager_impl::dboard_manager_impl( //warn for invalid dboard id xcvr combinations if (rx_dboard_is_xcvr != this_dboard_is_xcvr or tx_dboard_is_xcvr != this_dboard_is_xcvr){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "Unknown transceiver board ID combination...\n" "RX dboard ID: %s\n" "TX dboard ID: %s\n" diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 8b82502ba..024a6152d 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -145,7 +145,7 @@ public: time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); time_spec_t time_i = _mboard(m)[MBOARD_PROP_TIME_NOW].as(); if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "Detected time deviation between board %d and board 0.\n" "Board 0 time is %f seconds.\n" "Board %d time is %f seconds.\n" diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index fe3774eb4..669b20efa 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -98,7 +98,7 @@ static boost::uint32_t calc_rx_mux( // for all quadrature sources: Z = 0 // for mixed sources: warning + Z = 0 int Z = (num_quads > 0)? 0 : 1; - if (num_quads != 0 and num_reals != 0) uhd::print_warning( + if (num_quads != 0 and num_reals != 0) uhd::warning::post( "Mixing real and quadrature rx subdevices is not supported.\n" "The Q input to the real source(s) will be non-zero.\n" ); diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 276ca86f6..314384e72 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -64,7 +64,7 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) ); } catch(...){ - uhd::print_warning( + uhd::warning::post( "Could not locate USRP1 firmware.\n" "Please install the images package.\n" ); diff --git a/host/lib/usrp/wrapper_utils.hpp b/host/lib/usrp/wrapper_utils.hpp index aee230fc0..6f9fdbfca 100644 --- a/host/lib/usrp/wrapper_utils.hpp +++ b/host/lib/usrp/wrapper_utils.hpp @@ -40,7 +40,7 @@ static inline void do_samp_rate_warning_message( ){ static const double max_allowed_error = 1.0; //Sps if (std::abs(target_rate - actual_rate) > max_allowed_error){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "The hardware does not support the requested %s sample rate:\n" "Target sample rate: %f MSps\n" "Actual sample rate: %f MSps\n" @@ -55,7 +55,7 @@ static inline void do_tune_freq_warning_message( ){ static const double max_allowed_error = 1.0; //Hz if (std::abs(target_freq - actual_freq) > max_allowed_error){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "The hardware does not support the requested %s frequency:\n" "Target frequency: %f MHz\n" "Actual frequency: %f MHz\n" diff --git a/host/lib/utils/thread_priority.cpp b/host/lib/utils/thread_priority.cpp index f09d1b1d6..40b74f655 100644 --- a/host/lib/utils/thread_priority.cpp +++ b/host/lib/utils/thread_priority.cpp @@ -26,7 +26,7 @@ bool uhd::set_thread_priority_safe(float priority, bool realtime){ set_thread_priority(priority, realtime); return true; }catch(const std::exception &e){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "%s\n" "Failed to set thread priority %d (%s):\n" "Performance may be negatively affected.\n" diff --git a/host/lib/utils/warning.cpp b/host/lib/utils/warning.cpp index 8a7d35a23..05be7ae4d 100644 --- a/host/lib/utils/warning.cpp +++ b/host/lib/utils/warning.cpp @@ -17,16 +17,67 @@ #include #include +#include +#include #include +#include +#include #include #include using namespace uhd; -void uhd::print_warning(const std::string &msg){ - //print the warning message - std::cerr << std::endl << "Warning:" << std::endl; +/*********************************************************************** + * Registry implementation + **********************************************************************/ +//create the registry for the handlers +typedef uhd::dict registry_t; +UHD_SINGLETON_FCN(registry_t, get_registry) + +//the default warning handler +static void stderr_warning(const std::string &msg){ + std::cerr << msg; +} + +//register a default handler +UHD_STATIC_BLOCK(warning_register_default){ + warning::register_handler("default", &stderr_warning); +} + +/*********************************************************************** + * Post + format + **********************************************************************/ +void warning::post(const std::string &msg){ + std::stringstream ss; + + //format the warning message + ss << std::endl << "Warning:" << std::endl; BOOST_FOREACH(const std::string &line, std::split_string(msg, "\n")){ - std::cerr << " " << line << std::endl; + ss << " " << line << std::endl; + } + + //post the formatted message + BOOST_FOREACH(const std::string &name, get_registry().keys()){ + get_registry()[name](ss.str()); } } + +/*********************************************************************** + * Registry accessor functions + **********************************************************************/ +void warning::register_handler( + const std::string &name, const handler_t &handler +){ + get_registry()[name] = handler; +} + +warning::handler_t warning::unregister_handler(const std::string &name){ + if (not get_registry().has_key(name)) throw std::runtime_error( + "The warning registry does not have a handler registered to " + name + ); + return get_registry().pop(name); +} + +const std::vector warning::registry_names(void){ + return get_registry().keys(); +} diff --git a/host/test/warning_test.cpp b/host/test/warning_test.cpp index 6202c4270..db19955de 100644 --- a/host/test/warning_test.cpp +++ b/host/test/warning_test.cpp @@ -19,9 +19,9 @@ #include #include -BOOST_AUTO_TEST_CASE(test_print_warning){ +BOOST_AUTO_TEST_CASE(test_warning_post){ std::cerr << "---begin print test ---" << std::endl; - uhd::print_warning( + uhd::warning::post( "This is a test print for a warning message.\n" "And this is the second line of the test print.\n" ); -- cgit v1.2.3 From a7840ebb3f7d7f807d05059e2809eb45cff04899 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 26 Oct 2010 18:11:40 -0700 Subject: uhd: moved templated dict implementation into ipp file --- host/include/uhd/types/CMakeLists.txt | 1 + host/include/uhd/types/dict.hpp | 87 ++++-------------------- host/include/uhd/types/dict.ipp | 120 ++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 75 deletions(-) create mode 100644 host/include/uhd/types/dict.ipp diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt index 661dd2d39..a96976b5e 100644 --- a/host/include/uhd/types/CMakeLists.txt +++ b/host/include/uhd/types/CMakeLists.txt @@ -19,6 +19,7 @@ INSTALL(FILES clock_config.hpp device_addr.hpp + dict.ipp dict.hpp io_type.hpp mac_addr.hpp diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp index 3d0acf888..b14fc5425 100644 --- a/host/include/uhd/types/dict.hpp +++ b/host/include/uhd/types/dict.hpp @@ -19,11 +19,6 @@ #define INCLUDED_UHD_TYPES_DICT_HPP #include -#include -#include -#include -#include -#include #include #include @@ -34,14 +29,10 @@ namespace uhd{ */ template class dict{ public: - typedef std::pair pair_t; - /*! * Create a new empty dictionary. */ - dict(void){ - /* NOP */ - } + dict(void); /*! * Input iterator constructor: @@ -50,64 +41,34 @@ namespace uhd{ * \param last the end iterator */ template - dict(InputIterator first, InputIterator last){ - for(InputIterator it = first; it != last; it++){ - _map.push_back(*it); - } - } - - /*! - * Destroy this dict. - */ - ~dict(void){ - /* NOP */ - } + dict(InputIterator first, InputIterator last); /*! * Get the number of elements in this dict. * \return the number of elements */ - std::size_t size(void) const{ - return _map.size(); - } + std::size_t size(void) const; /*! * Get a list of the keys in this dict. * Key order depends on insertion precedence. * \return vector of keys */ - const std::vector keys(void) const{ - std::vector keys; - BOOST_FOREACH(const pair_t &p, _map){ - keys.push_back(p.first); - } - return keys; - } + const std::vector keys(void) const; /*! * Get a list of the values in this dict. * Value order depends on insertion precedence. * \return vector of values */ - const std::vector vals(void) const{ - std::vector vals; - BOOST_FOREACH(const pair_t &p, _map){ - vals.push_back(p.second); - } - return vals; - } + const std::vector vals(void) const; /*! * Does the dictionary contain this key? * \param key the key to look for * \return true if found */ - bool has_key(const Key &key) const{ - BOOST_FOREACH(const pair_t &p, _map){ - if (p.first == key) return true; - } - return false; - } + bool has_key(const Key &key) const; /*! * Get a value for the given key if it exists. @@ -116,12 +77,7 @@ namespace uhd{ * \return the value at the key * \throw an exception when not found */ - const Val &operator[](const Key &key) const{ - BOOST_FOREACH(const pair_t &p, _map){ - if (p.first == key) return p.second; - } - throw key_not_found_in_dict(key); - } + const Val &operator[](const Key &key) const; /*! * Set a value for the given key, however, in reality @@ -129,13 +85,7 @@ namespace uhd{ * \param key the key to set to * \return a reference to the value */ - Val &operator[](const Key &key){ - BOOST_FOREACH(pair_t &p, _map){ - if (p.first == key) return p.second; - } - _map.push_back(std::make_pair(key, Val())); - return _map.back().second; - } + Val &operator[](const Key &key); /*! * Pop an item out of the dictionary. @@ -143,28 +93,15 @@ namespace uhd{ * \return the value of the item * \throw an exception when not found */ - Val pop(const Key &key){ - typename std::list::iterator it; - for (it = _map.begin(); it != _map.end(); it++){ - if (it->first != key) continue; - Val val = it->second; - _map.erase(it); - return val; - } - throw key_not_found_in_dict(key); - } + Val pop(const Key &key); private: - std::exception key_not_found_in_dict(const Key &key) const{ - return std::out_of_range(str(boost::format( - "key \"%s\" not found in dict(%s, %s)" - ) % boost::lexical_cast(key) - % typeid(Key).name() % typeid(Val).name())); - } - + typedef std::pair pair_t; std::list _map; //private container }; } //namespace uhd +#include + #endif /* INCLUDED_UHD_TYPES_DICT_HPP */ diff --git a/host/include/uhd/types/dict.ipp b/host/include/uhd/types/dict.ipp new file mode 100644 index 000000000..85071e6fd --- /dev/null +++ b/host/include/uhd/types/dict.ipp @@ -0,0 +1,120 @@ +// +// 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_UHD_TYPES_DICT_IPP +#define INCLUDED_UHD_TYPES_DICT_IPP + +#include +#include +#include +#include +#include + +namespace uhd{ + + namespace /*anon*/{ + template + struct UHD_API key_not_found: std::out_of_range{ + key_not_found(const Key &key): std::out_of_range( + str(boost::format( + "key \"%s\" not found in dict(%s, %s)" + ) % boost::lexical_cast(key) + % typeid(Key).name() % typeid(Val).name() + ) + ){ + /* NOP */ + } + }; + } // namespace /*anon*/ + + template + dict::dict(void){ + /* NOP */ + } + + template + template + dict::dict(InputIterator first, InputIterator last){ + for(InputIterator it = first; it != last; it++){ + _map.push_back(*it); + } + } + + template + std::size_t dict::size(void) const{ + return _map.size(); + } + + template + const std::vector dict::keys(void) const{ + std::vector keys; + BOOST_FOREACH(const pair_t &p, _map){ + keys.push_back(p.first); + } + return keys; + } + + template + const std::vector dict::vals(void) const{ + std::vector vals; + BOOST_FOREACH(const pair_t &p, _map){ + vals.push_back(p.second); + } + return vals; + } + + template + bool dict::has_key(const Key &key) const{ + BOOST_FOREACH(const pair_t &p, _map){ + if (p.first == key) return true; + } + return false; + } + + template + const Val &dict::operator[](const Key &key) const{ + BOOST_FOREACH(const pair_t &p, _map){ + if (p.first == key) return p.second; + } + throw key_not_found(key); + } + + template + Val &dict::operator[](const Key &key){ + BOOST_FOREACH(pair_t &p, _map){ + if (p.first == key) return p.second; + } + _map.push_back(std::make_pair(key, Val())); + return _map.back().second; + } + + template + Val dict::pop(const Key &key){ + typename std::list::iterator it; + for (it = _map.begin(); it != _map.end(); it++){ + if (it->first == key){ + Val val = it->second; + _map.erase(it); + return val; + } + } + throw key_not_found(key); + } + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_DICT_IPP */ -- cgit v1.2.3 From fa689c7202a0cab6bf0debc3524f1f46636a7ba0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 08:31:01 -0700 Subject: usrp_e: fix to get compiling with next branch --- host/lib/usrp/usrp_e/dboard_impl.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/host/lib/usrp/usrp_e/dboard_impl.cpp b/host/lib/usrp/usrp_e/dboard_impl.cpp index d4a27cb72..f2840dcfc 100644 --- a/host/lib/usrp/usrp_e/dboard_impl.cpp +++ b/host/lib/usrp/usrp_e/dboard_impl.cpp @@ -87,6 +87,7 @@ void usrp_e_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _rx_db_eeprom.id, _dboard_manager->get_rx_subdev(key.name), _rx_codec_proxy->get_link(), GAIN_GROUP_POLICY_RX @@ -145,6 +146,7 @@ void usrp_e_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _tx_db_eeprom.id, _dboard_manager->get_tx_subdev(key.name), _tx_codec_proxy->get_link(), GAIN_GROUP_POLICY_TX -- cgit v1.2.3 From 211e190619652be145fdcd79cd54eda0e84d3313 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 10:45:15 -0700 Subject: usrp: added a time sync check for multi usrp --- host/include/uhd/usrp/multi_usrp.hpp | 8 ++++++++ host/lib/usrp/multi_usrp.cpp | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 5380d177d..98ba07fc0 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -144,6 +144,14 @@ public: */ virtual void set_time_unknown_pps(const time_spec_t &time_spec) = 0; + /*! + * Are the times across all motherboards in this configuration synchronized? + * Checks that all time registers are approximately close but not exact, + * given that the RTT may varying for a control packet transaction. + * \return true when all motherboards time registers are in sync + */ + virtual bool get_time_synchronized(void) = 0; + /*! * Issue a stream command to the usrp device. * This tells the usrp to send samples into the host. diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 024a6152d..876f1a3fc 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -154,6 +154,15 @@ public: } } + bool get_time_synchronized(void){ + for (size_t m = 1; m < get_num_mboards(); m++){ + time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); + time_spec_t time_i = _mboard(m)[MBOARD_PROP_TIME_NOW].as(); + if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)) return false; + } + return true; + } + void issue_stream_cmd(const stream_cmd_t &stream_cmd){ for (size_t m = 0; m < get_num_mboards(); m++){ _mboard(m)[MBOARD_PROP_STREAM_CMD] = stream_cmd; -- cgit v1.2.3 From 630c007bbbabce90ffe3578d47ad7acc187bdc30 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 11:15:37 -0700 Subject: usrp: added to subdev spec comments/docs --- host/include/uhd/usrp/subdev_spec.hpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/host/include/uhd/usrp/subdev_spec.hpp b/host/include/uhd/usrp/subdev_spec.hpp index 5de3bb3b8..b189724c9 100644 --- a/host/include/uhd/usrp/subdev_spec.hpp +++ b/host/include/uhd/usrp/subdev_spec.hpp @@ -26,10 +26,10 @@ namespace uhd{ namespace usrp{ /*! - * A subdevice specification (daughterboard, subdevice) name pairing. + * A subdevice specification (daughterboard slot, subdevice) name pairing. */ struct UHD_API subdev_spec_pair_t : boost::equality_comparable{ - //! The daughterboard name + //! The daughterboard slot name std::string db_name; //! The subdevice name @@ -50,7 +50,7 @@ namespace uhd{ namespace usrp{ UHD_API bool operator==(const subdev_spec_pair_t &, const subdev_spec_pair_t &); /*! - * A list of (daughterboard name, subdevice name) pairs: + * A list of (daughterboard slot name, subdevice name) pairs: * * A subdevice specification represents a list of subdevices on a motherboard. * The subdevices specified may span across multiple daughterboards; @@ -62,6 +62,11 @@ namespace uhd{ namespace usrp{ * The markup-string is a whitespace separated list of dboard:subdev pairs. * The first pair represents the subdevice for channel zero, * the second pair represents the subdevice for channel one, and so on. + * + * Special handling for empty conditions: + * - An empty subdevice specification means: select the first subdevice found in the configuration + * - An empty daughterboard name means: select the only daughterboard slot or error if multiple exist + * - An empty subdevice name means: select the only subdevice on that board or error if multiple exist */ class UHD_API subdev_spec_t : public std::vector{ public: -- cgit v1.2.3 From 9585a0b6fd88efd2a8bd43c8b034ae21264b9fc4 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 11:42:52 -0700 Subject: usrp_e: added support for building fpga image into images Makefile --- images/Makefile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/images/Makefile b/images/Makefile index 57277e787..92379271d 100644 --- a/images/Makefile +++ b/images/Makefile @@ -111,6 +111,22 @@ $(_usrp2_fpga_bin): endif +######################################################################## +# USRP-E100 fpga +######################################################################## +ifdef HAS_XTCLSH + +_usrp_e100_fpga_dir = $(TOP_FPGA_DIR)/usrp2/top/u1e +_usrp_e100_fpga_bin = $(BUILT_IMAGES_DIR)/usrp_e100_fpga.bin +IMAGES_LIST += $(_usrp_e100_fpga_bin) + +$(_usrp_e100_fpga_bin): + cd $(_usrp_e100_fpga_dir) && make clean + cd $(_usrp_e100_fpga_dir) && make bin + cp $(_usrp_e100_fpga_dir)/build/u1e.bin $@ + +endif + ######################################################################## # Build rules ######################################################################## -- cgit v1.2.3 From fa7704be20005a705efdc96aa785d80911638107 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 13:10:48 -0700 Subject: usrp-e: implemented fpga loading and compat checking --- host/examples/rx_to_file.cpp | 8 ++-- host/examples/rx_to_udp.cpp | 8 ++-- host/lib/usrp/usrp_e/fpga-downloader.cc | 30 ++++++++------ host/lib/usrp/usrp_e/usrp_e_impl.cpp | 69 ++++++++++++++++++++++++++++++--- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 4 +- host/lib/usrp/usrp_e/usrp_e_regs.hpp | 2 +- 6 files changed, 94 insertions(+), 27 deletions(-) diff --git a/host/examples/rx_to_file.cpp b/host/examples/rx_to_file.cpp index 79d3e9d8b..f08f7cee3 100644 --- a/host/examples/rx_to_file.cpp +++ b/host/examples/rx_to_file.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -40,7 +40,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") - ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("args", po::value(&args)->default_value(""), "single uhd device address args") ("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") @@ -53,7 +53,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //print the help message if (vm.count("help")){ - std::cout << boost::format("UHD RX Timed Samples %s") % desc << std::endl; + std::cout << boost::format("UHD RX to File %s") % desc << std::endl; return ~0; } @@ -62,7 +62,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //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::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); uhd::device::sptr dev = sdev->get_device(); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; diff --git a/host/examples/rx_to_udp.cpp b/host/examples/rx_to_udp.cpp index 34b278599..c8b3d506b 100644 --- a/host/examples/rx_to_udp.cpp +++ b/host/examples/rx_to_udp.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -46,7 +46,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") - ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("args", po::value(&args)->default_value(""), "single uhd device address args") ("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") @@ -61,7 +61,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //print the help message if (vm.count("help")){ - std::cout << boost::format("UHD RX Timed Samples %s") % desc << std::endl; + std::cout << boost::format("UHD RX to UDP %s") % desc << std::endl; return ~0; } @@ -70,7 +70,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //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::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); uhd::device::sptr dev = sdev->get_device(); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; diff --git a/host/lib/usrp/usrp_e/fpga-downloader.cc b/host/lib/usrp/usrp_e/fpga-downloader.cc index ff8671e98..b0d56e856 100644 --- a/host/lib/usrp/usrp_e/fpga-downloader.cc +++ b/host/lib/usrp/usrp_e/fpga-downloader.cc @@ -15,11 +15,14 @@ // along with this program. If not, see . // +#include + #include #include #include #include #include +#include #include #include @@ -82,8 +85,9 @@ gpio::gpio(unsigned int gpio_num, gpio_direction pin_direction) std::fstream export_file; export_file.open("/sys/class/gpio/export", std::ios::out); - if (!export_file.is_open()) ///\todo Poor error handling - std::cout << "Failed to open gpio export file." << std::endl; + if (not export_file.is_open()) throw std::runtime_error( + "Failed to open gpio export file." + ); export_file << gpio_num << std::endl; @@ -92,15 +96,17 @@ gpio::gpio(unsigned int gpio_num, gpio_direction pin_direction) std::fstream direction_file; std::string direction_file_name; - direction_file_name = base_path.str() + "/direction"; + if (gpio_num != 114) { + direction_file_name = base_path.str() + "/direction"; - direction_file.open(direction_file_name.c_str()); - if (!direction_file.is_open()) - std::cout << "Failed to open direction file." << std::endl; - if (pin_direction == OUT) - direction_file << "out" << std::endl; - else - direction_file << "in" << std::endl; + direction_file.open(direction_file_name.c_str()); + if (!direction_file.is_open()) + std::cout << "Failed to open direction file." << std::endl; + if (pin_direction == OUT) + direction_file << "out" << std::endl; + else + direction_file << "in" << std::endl; + } std::string value_file_name; @@ -251,11 +257,11 @@ void usrp_e_load_fpga(const std::string &bin_file){ gpio gpio_init_b(INIT_B, IN); gpio gpio_done (DONE, IN); - std::cout << "FPGA config file: " << bin_file << std::endl; + std::cout << "Loading FPGA image: " << bin_file << "... " << std::flush; prepare_fpga_for_configuration(gpio_prog_b, gpio_init_b); - std::cout << "Done = " << gpio_done.get_value() << std::endl; + std::cout << "done = " << gpio_done.get_value() << std::endl; send_file_to_fpga(bin_file, gpio_init_b, gpio_done); } diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 5c0e1dbb0..0a7295ff9 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -16,13 +16,17 @@ // #include "usrp_e_impl.hpp" +#include "usrp_e_regs.hpp" #include #include #include #include +#include #include #include +#include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -66,7 +70,64 @@ static device_addrs_t usrp_e_find(const device_addr_t &hint){ * Make **********************************************************************/ static device::sptr usrp_e_make(const device_addr_t &device_addr){ - return device::sptr(new usrp_e_impl(device_addr["node"])); + + //The fpga is loaded when: + // 1) The compatibility number matches. + // 2) The hash in the hash-file matches. + + //setup the main interface into fpga + std::string node = device_addr["node"]; + std::cout << boost::format("Opening USRP-E on %s") % node << std::endl; + usrp_e_iface::sptr iface = usrp_e_iface::make(node); + + //------------------------------------------------------------------ + //-- Handle the FPGA loading... + //-- The image can be confimed as already loaded when: + //-- 1) The compatibility number matches. + //-- 2) The hash in the hash-file matches. + //------------------------------------------------------------------ + + //extract the fpga path for usrp-e + std::string usrp_e_fpga_image = find_image_path( + device_addr.has_key("fpga")? device_addr["fpga"] : "usrp_e100_fpga.bin" + ); + + //calculate a hash of the fpga file + size_t fpga_hash = 0; + { + std::ifstream file(usrp_e_fpga_image.c_str()); + if (not file.good()) throw std::runtime_error( + "cannot open fpga file for read: " + usrp_e_fpga_image + ); + do{ + boost::hash_combine(fpga_hash, file.get()); + } while (file.good()); + file.close(); + } + + //read the compatibility number + boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); + + //read the hash in the hash-file + size_t loaded_hash = 0; + try{std::ifstream(hash_file_path) >> loaded_hash;}catch(...){} + + //if not loaded: load the fpga image and write the hash-file + if (fpga_compat_num != USRP_E_COMPAT_NUM or loaded_hash != fpga_hash){ + usrp_e_load_fpga(usrp_e_fpga_image); + try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){} + } + + //check that the compatibility is correct + fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); + if (fpga_compat_num != USRP_E_COMPAT_NUM){ + throw std::runtime_error(str(boost::format( + "Expected fpga compatibility number 0x%x, but got 0x%x:\n" + "The fpga build is not compatible with the host code build." + ) % USRP_E_COMPAT_NUM % fpga_compat_num)); + } + + return device::sptr(new usrp_e_impl(iface)); } UHD_STATIC_BLOCK(register_usrp_e_device){ @@ -76,11 +137,9 @@ UHD_STATIC_BLOCK(register_usrp_e_device){ /*********************************************************************** * Structors **********************************************************************/ -usrp_e_impl::usrp_e_impl(const std::string &node){ - std::cout << boost::format("Opening USRP-E on %s") % node << std::endl; +usrp_e_impl::usrp_e_impl(usrp_e_iface::sptr iface): _iface(iface){ - //setup various interfaces into hardware - _iface = usrp_e_iface::make(node); + //setup interfaces into hardware _clock_ctrl = usrp_e_clock_ctrl::make(_iface); _codec_ctrl = usrp_e_codec_ctrl::make(_iface); diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 9799cd645..421a9623d 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -31,6 +31,8 @@ #define INCLUDED_USRP_E_IMPL_HPP static const double MASTER_CLOCK_RATE = 64e6; //TODO get from clock control +static const char *hash_file_path = "/tmp/usrp_e100_hash"; +static const boost::uint16_t USRP_E_COMPAT_NUM = 0x02; //! load an fpga image from a bin file into the usrp-e fpga extern void usrp_e_load_fpga(const std::string &bin_file); @@ -79,7 +81,7 @@ private: class usrp_e_impl : public uhd::device{ public: //structors - usrp_e_impl(const std::string &node); + usrp_e_impl(usrp_e_iface::sptr); ~usrp_e_impl(void); //the io interface diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp index a4f42093e..f74358f00 100644 --- a/host/lib/usrp/usrp_e/usrp_e_regs.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp @@ -30,7 +30,7 @@ #define UE_REG_MISC_CGEN_ST UE_REG_MISC_BASE + 6 #define UE_REG_MISC_TEST UE_REG_MISC_BASE + 8 #define UE_REG_MISC_RX_LEN UE_REG_MISC_BASE + 10 -#define UE_REG_MISC_TX_LEN UE_REG_MISC_BASE + 12 +#define UE_REG_MISC_COMPAT UE_REG_MISC_BASE + 12 ///////////////////////////////////////////////////// // Slave 1 -- UART -- cgit v1.2.3 From 0208b28e58e3719dc4dfb8df73fe5ae49e4a6306 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 15:57:35 -0700 Subject: usrp-e: use clock control to get clock rate, removed temporary constant --- host/lib/usrp/usrp_e/dsp_impl.cpp | 16 ++++++++-------- host/lib/usrp/usrp_e/io_impl.cpp | 17 ++++++++--------- host/lib/usrp/usrp_e/mboard_impl.cpp | 2 +- host/lib/usrp/usrp_e/usrp_e_impl.cpp | 5 +---- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 5 ----- 5 files changed, 18 insertions(+), 27 deletions(-) diff --git a/host/lib/usrp/usrp_e/dsp_impl.cpp b/host/lib/usrp/usrp_e/dsp_impl.cpp index 9312bb603..97f173c1a 100644 --- a/host/lib/usrp/usrp_e/dsp_impl.cpp +++ b/host/lib/usrp/usrp_e/dsp_impl.cpp @@ -65,11 +65,11 @@ void usrp_e_impl::rx_ddc_get(const wax::obj &key_, wax::obj &val){ return; case DSP_PROP_CODEC_RATE: - val = MASTER_CLOCK_RATE; + val = _clock_ctrl->get_fpga_clock_rate(); return; case DSP_PROP_HOST_RATE: - val = MASTER_CLOCK_RATE/_ddc_decim; + val = _clock_ctrl->get_fpga_clock_rate()/_ddc_decim; return; default: UHD_THROW_PROP_GET_ERROR(); @@ -87,7 +87,7 @@ void usrp_e_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){ case DSP_PROP_FREQ_SHIFT:{ double new_freq = val.as(); _iface->poke32(UE_REG_DSP_RX_FREQ, - dsp_type1::calc_cordic_word_and_update(new_freq, MASTER_CLOCK_RATE) + dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_fpga_clock_rate()) ); _ddc_freq = new_freq; //shadow } @@ -95,7 +95,7 @@ void usrp_e_impl::rx_ddc_set(const wax::obj &key_, const wax::obj &val){ case DSP_PROP_HOST_RATE:{ //set the decimation - _ddc_decim = rint(MASTER_CLOCK_RATE/val.as()); + _ddc_decim = rint(_clock_ctrl->get_fpga_clock_rate()/val.as()); _iface->poke32(UE_REG_DSP_RX_DECIM_RATE, dsp_type1::calc_cic_filter_word(_ddc_decim)); //set the scaling @@ -148,11 +148,11 @@ void usrp_e_impl::tx_duc_get(const wax::obj &key_, wax::obj &val){ return; case DSP_PROP_CODEC_RATE: - val = MASTER_CLOCK_RATE; + val = _clock_ctrl->get_fpga_clock_rate(); return; case DSP_PROP_HOST_RATE: - val = MASTER_CLOCK_RATE/_duc_interp; + val = _clock_ctrl->get_fpga_clock_rate()/_duc_interp; return; default: UHD_THROW_PROP_GET_ERROR(); @@ -170,14 +170,14 @@ void usrp_e_impl::tx_duc_set(const wax::obj &key_, const wax::obj &val){ case DSP_PROP_FREQ_SHIFT:{ double new_freq = val.as(); _iface->poke32(UE_REG_DSP_TX_FREQ, - dsp_type1::calc_cordic_word_and_update(new_freq, MASTER_CLOCK_RATE) + dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_fpga_clock_rate()) ); _duc_freq = new_freq; //shadow } return; case DSP_PROP_HOST_RATE:{ - _duc_interp = rint(MASTER_CLOCK_RATE/val.as()); + _duc_interp = rint(_clock_ctrl->get_fpga_clock_rate()/val.as()); //set the interpolation _iface->poke32(UE_REG_DSP_TX_INTERP_RATE, dsp_type1::calc_cic_filter_word(_duc_interp)); diff --git a/host/lib/usrp/usrp_e/io_impl.cpp b/host/lib/usrp/usrp_e/io_impl.cpp index d89a7db07..9996e7172 100644 --- a/host/lib/usrp/usrp_e/io_impl.cpp +++ b/host/lib/usrp/usrp_e/io_impl.cpp @@ -73,7 +73,7 @@ struct usrp_e_impl::io_impl{ } //a pirate's life is the life for me! - void recv_pirate_loop(); + void recv_pirate_loop(usrp_e_clock_ctrl::sptr); typedef bounded_buffer recv_booty_type; recv_booty_type::sptr recv_pirate_booty; bounded_buffer::sptr async_msg_fifo; @@ -86,9 +86,8 @@ struct usrp_e_impl::io_impl{ * - while raiding, loot for recv buffers * - put booty into the alignment buffer **********************************************************************/ -void usrp_e_impl::io_impl::recv_pirate_loop( - -){ +void usrp_e_impl::io_impl::recv_pirate_loop(usrp_e_clock_ctrl::sptr clock_ctrl) +{ set_thread_priority_safe(); recv_pirate_crew_raiding = true; @@ -119,7 +118,7 @@ void usrp_e_impl::io_impl::recv_pirate_loop( metadata.channel = 0; metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf; metadata.time_spec = time_spec_t( - time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), MASTER_CLOCK_RATE + time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), clock_ctrl->get_fpga_clock_rate() ); metadata.event_code = vrt_packet_handler::get_context_code(vrt_hdr, if_packet_info); @@ -172,7 +171,7 @@ void usrp_e_impl::io_init(void){ //spawn a pirate, yarrr! _io_impl->recv_pirate_crew.create_thread(boost::bind( - &usrp_e_impl::io_impl::recv_pirate_loop, _io_impl.get() + &usrp_e_impl::io_impl::recv_pirate_loop, _io_impl.get(), _clock_ctrl )); } @@ -182,7 +181,7 @@ void usrp_e_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd){ stream_cmd, get_max_recv_samps_per_packet() )); _iface->poke32(UE_REG_CTRL_RX_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); - _iface->poke32(UE_REG_CTRL_RX_TIME_TICKS, stream_cmd.time_spec.get_tick_count(MASTER_CLOCK_RATE)); + _iface->poke32(UE_REG_CTRL_RX_TIME_TICKS, stream_cmd.time_spec.get_tick_count(_clock_ctrl->get_fpga_clock_rate())); } void usrp_e_impl::handle_overrun(size_t){ @@ -226,7 +225,7 @@ size_t usrp_e_impl::send( buffs, num_samps, //buffer to fill metadata, send_mode, //samples metadata io_type, _send_otw_type, //input and output types to convert - MASTER_CLOCK_RATE, //master clock tick rate + _clock_ctrl->get_fpga_clock_rate(), //master clock tick rate uhd::transport::vrt::if_hdr_pack_le, boost::bind(&get_send_buffs, _io_impl->data_xport, timeout, _1), get_max_send_samps_per_packet() @@ -258,7 +257,7 @@ size_t usrp_e_impl::recv( buffs, num_samps, //buffer to fill metadata, recv_mode, //samples metadata io_type, _recv_otw_type, //input and output types to convert - MASTER_CLOCK_RATE, //master clock tick rate + _clock_ctrl->get_fpga_clock_rate(), //master clock tick rate uhd::transport::vrt::if_hdr_unpack_le, boost::bind(&usrp_e_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout), boost::bind(&usrp_e_impl::handle_overrun, this, _1) diff --git a/host/lib/usrp/usrp_e/mboard_impl.cpp b/host/lib/usrp/usrp_e/mboard_impl.cpp index 3d4cef069..f0118aa4b 100644 --- a/host/lib/usrp/usrp_e/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e/mboard_impl.cpp @@ -125,7 +125,7 @@ void usrp_e_impl::mboard_set(const wax::obj &key, const wax::obj &val){ case MBOARD_PROP_TIME_NOW: case MBOARD_PROP_TIME_NEXT_PPS:{ time_spec_t time_spec = val.as(); - _iface->poke32(UE_REG_TIME64_TICKS, time_spec.get_tick_count(MASTER_CLOCK_RATE)); + _iface->poke32(UE_REG_TIME64_TICKS, time_spec.get_tick_count(_clock_ctrl->get_fpga_clock_rate())); boost::uint32_t imm_flags = (key.as() == MBOARD_PROP_TIME_NOW)? 1 : 0; _iface->poke32(UE_REG_TIME64_IMM, imm_flags); _iface->poke32(UE_REG_TIME64_SECS, time_spec.get_full_secs()); diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 0a7295ff9..1b71c0a52 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -71,10 +71,6 @@ static device_addrs_t usrp_e_find(const device_addr_t &hint){ **********************************************************************/ static device::sptr usrp_e_make(const device_addr_t &device_addr){ - //The fpga is loaded when: - // 1) The compatibility number matches. - // 2) The hash in the hash-file matches. - //setup the main interface into fpga std::string node = device_addr["node"]; std::cout << boost::format("Opening USRP-E on %s") % node << std::endl; @@ -86,6 +82,7 @@ static device::sptr usrp_e_make(const device_addr_t &device_addr){ //-- 1) The compatibility number matches. //-- 2) The hash in the hash-file matches. //------------------------------------------------------------------ + static const char *hash_file_path = "/tmp/usrp_e100_hash"; //extract the fpga path for usrp-e std::string usrp_e_fpga_image = find_image_path( diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 421a9623d..e55b46b80 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -30,8 +30,6 @@ #ifndef INCLUDED_USRP_E_IMPL_HPP #define INCLUDED_USRP_E_IMPL_HPP -static const double MASTER_CLOCK_RATE = 64e6; //TODO get from clock control -static const char *hash_file_path = "/tmp/usrp_e100_hash"; static const boost::uint16_t USRP_E_COMPAT_NUM = 0x02; //! load an fpga image from a bin file into the usrp-e fpga @@ -100,9 +98,6 @@ private: //interface to ioctls and file descriptor usrp_e_iface::sptr _iface; - //FIXME fetch from ioctl? - static const size_t _max_num_samples = 2048/sizeof(boost::uint32_t); - //handle io stuff UHD_PIMPL_DECL(io_impl) _io_impl; uhd::otw_type_t _send_otw_type, _recv_otw_type; -- cgit v1.2.3 From f820cce9be9bcea9723cf7b4e85a4ded2f1d2c62 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 18:55:35 -0700 Subject: uhd: added rx to file example, simplified cmake file for examples --- host/examples/CMakeLists.txt | 44 ++++++------- host/examples/rx_to_file.cpp | 144 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 26 deletions(-) create mode 100644 host/examples/rx_to_file.cpp diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt index a8873f8d3..e355ce241 100644 --- a/host/examples/CMakeLists.txt +++ b/host/examples/CMakeLists.txt @@ -16,34 +16,26 @@ # ######################################################################## -ADD_EXECUTABLE(benchmark_rx_rate benchmark_rx_rate.cpp) -TARGET_LINK_LIBRARIES(benchmark_rx_rate uhd) - -ADD_EXECUTABLE(rx_timed_samples rx_timed_samples.cpp) -TARGET_LINK_LIBRARIES(rx_timed_samples uhd) - -ADD_EXECUTABLE(test_async_messages test_async_messages.cpp) -TARGET_LINK_LIBRARIES(test_async_messages uhd) - -ADD_EXECUTABLE(test_pps_input test_pps_input.cpp) -TARGET_LINK_LIBRARIES(test_pps_input uhd) - -ADD_EXECUTABLE(tx_timed_samples tx_timed_samples.cpp) -TARGET_LINK_LIBRARIES(tx_timed_samples uhd) - -ADD_EXECUTABLE(tx_waveforms tx_waveforms.cpp) -TARGET_LINK_LIBRARIES(tx_waveforms uhd) - -INSTALL(TARGETS - benchmark_rx_rate - rx_timed_samples - test_async_messages - test_pps_input - tx_timed_samples - tx_waveforms - RUNTIME DESTINATION ${PKG_DATA_DIR}/examples +# example applications +######################################################################## +SET(example_sources + benchmark_rx_rate.cpp + rx_timed_samples.cpp + rx_to_file.cpp + test_async_messages.cpp + test_pps_input.cpp + tx_timed_samples.cpp + tx_waveforms.cpp ) +#for each source: build an executable and install +FOREACH(example_source ${example_sources}) + GET_FILENAME_COMPONENT(example_name ${example_source} NAME_WE) + ADD_EXECUTABLE(${example_name} ${example_source}) + TARGET_LINK_LIBRARIES(${example_name} uhd) + INSTALL(TARGETS ${example_name} RUNTIME DESTINATION ${PKG_DATA_DIR}/examples) +ENDFOREACH(example_source) + ######################################################################## # ASCII Art DFT - requires curses, so this part is optional ######################################################################## diff --git a/host/examples/rx_to_file.cpp b/host/examples/rx_to_file.cpp new file mode 100644 index 000000000..25727a7d3 --- /dev/null +++ b/host/examples/rx_to_file.cpp @@ -0,0 +1,144 @@ +// +// 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 +#include +#include + +namespace po = boost::program_options; + + +int UHD_SAFE_MAIN(int argc, char *argv[]){ + uhd::set_thread_priority_safe(); + + //variables to be set by po + std::string args, file; + time_t seconds_in_future; + size_t total_num_samps; + double rx_rate, freq; + + //setup the program options + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "help message") + ("args", po::value(&args)->default_value(""), "single uhd device address args") + ("file", po::value(&file)->default_value("out.16sc.dat"), "name of the file to write binary samples to") + ("secs", po::value(&seconds_in_future)->default_value(1), "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") + ("dilv", "specify to disable inner-loop verbose") + ; + 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 RX to File %s") % desc << std::endl; + return ~0; + } + + bool verbose = vm.count("dilv") == 0; + + //create a usrp device + std::cout << std::endl; + std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; + uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); + uhd::device::sptr dev = sdev->get_device(); + std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; + + //set properties on the device + std::cout << boost::format("Setting RX Rate: %f Msps...") % (rx_rate/1e6) << std::endl; + 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.0)); + + uhd::gain_range_t rx_gain = sdev->get_rx_gain_range(); + std::cout << "Setting RX Gain to: " << rx_gain.max << std::endl; + sdev->set_rx_gain(rx_gain.max); + + sleep(1); + std::cout << "LO Locked = " << sdev->get_rx_lo_locked() << std::endl; + + //setup streaming + std::cout << std::endl; + std::cout << boost::format( + "Begin streaming %u samples, %d seconds in the future..." + ) % total_num_samps % seconds_in_future << std::endl; + uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); + stream_cmd.num_samps = total_num_samps; + stream_cmd.stream_now = false; + stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future); + sdev->issue_stream_cmd(stream_cmd); + + //loop until total number of samples reached + size_t num_acc_samps = 0; //number of accumulated samples + uhd::rx_metadata_t md; + std::vector > buff(dev->get_max_recv_samps_per_packet()); + std::ofstream outfile(file.c_str(), std::ofstream::binary); + + while(num_acc_samps < total_num_samps){ + size_t num_rx_samps = dev->recv( + &buff.front(), buff.size(), md, + uhd::io_type_t::COMPLEX_INT16, + uhd::device::RECV_MODE_ONE_PACKET + ); + + //handle the error codes + switch(md.error_code){ + case uhd::rx_metadata_t::ERROR_CODE_NONE: + break; + + case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: + if (num_acc_samps == 0) continue; + std::cout << boost::format( + "Got timeout before all samples received, possible packet loss, exiting loop..." + ) << std::endl; + goto done_loop; + + default: + std::cout << boost::format( + "Got error code 0x%x, exiting loop..." + ) % md.error_code << std::endl; + goto done_loop; + } + + //write complex short integer samples to the binary file + outfile.write((const char*)&buff[0], num_rx_samps * sizeof(std::complex)); + + if(verbose) std::cout << boost::format( + "Got packet: %u samples, %u full secs, %f frac secs" + ) % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl; + + num_acc_samps += num_rx_samps; + } done_loop: + + outfile.close(); + + //finished + std::cout << std::endl << "Done!" << std::endl << std::endl; + + return 0; +} -- cgit v1.2.3 From dc9f22c9a7989e4485d6f03b0ccf6ea19e6ae42d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 19:18:26 -0700 Subject: uhd: added rx samples to udp example, cleaned up other examples, added gain options --- host/examples/CMakeLists.txt | 3 +- host/examples/rx_samples_to_file.cpp | 142 ++++++++++++++++++++++++++++++++++ host/examples/rx_samples_to_udp.cpp | 142 ++++++++++++++++++++++++++++++++++ host/examples/rx_timed_samples.cpp | 19 +++-- host/examples/rx_to_file.cpp | 144 ----------------------------------- host/examples/tx_timed_samples.cpp | 19 +++-- 6 files changed, 310 insertions(+), 159 deletions(-) create mode 100644 host/examples/rx_samples_to_file.cpp create mode 100644 host/examples/rx_samples_to_udp.cpp delete mode 100644 host/examples/rx_to_file.cpp diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt index e355ce241..ce2ca9640 100644 --- a/host/examples/CMakeLists.txt +++ b/host/examples/CMakeLists.txt @@ -20,8 +20,9 @@ ######################################################################## SET(example_sources benchmark_rx_rate.cpp + rx_samples_to_file.cpp + rx_samples_to_udp.cpp rx_timed_samples.cpp - rx_to_file.cpp test_async_messages.cpp test_pps_input.cpp tx_timed_samples.cpp diff --git a/host/examples/rx_samples_to_file.cpp b/host/examples/rx_samples_to_file.cpp new file mode 100644 index 000000000..6671644fa --- /dev/null +++ b/host/examples/rx_samples_to_file.cpp @@ -0,0 +1,142 @@ +// +// 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 +#include +#include +#include + +namespace po = boost::program_options; + +int UHD_SAFE_MAIN(int argc, char *argv[]){ + uhd::set_thread_priority_safe(); + + //variables to be set by po + std::string args, file; + size_t total_num_samps; + double rate, freq; + float gain; + + //setup the program options + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "help message") + ("args", po::value(&args)->default_value(""), "single uhd device address args") + ("file", po::value(&file)->default_value("out.16sc.dat"), "name of the file to write binary samples to") + ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to receive") + ("rate", po::value(&rate)->default_value(100e6/16), "rate of incoming samples") + ("freq", po::value(&freq)->default_value(0), "rf center frequency in Hz") + ("gain", po::value(&gain)->default_value(0), "gain for the RF chain") + ("dilv", "specify to disable inner-loop verbose") + ; + 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 RX to File %s") % desc << std::endl; + return ~0; + } + + bool verbose = vm.count("dilv") == 0; + + //create a usrp device + std::cout << std::endl; + std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; + uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); + uhd::device::sptr dev = sdev->get_device(); + std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; + + //set the rx sample rate + std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate/1e6) << std::endl; + sdev->set_rx_rate(rate); + std::cout << boost::format("Actual RX Rate: %f Msps...") % (sdev->get_rx_rate()/1e6) << std::endl << std::endl; + + //set the rx center frequency + std::cout << boost::format("Setting RX Freq: %f Mhz...") % (freq/1e6) << std::endl; + sdev->set_rx_freq(freq); + std::cout << boost::format("Actual RX Freq: %f Mhz...") % (sdev->get_rx_freq()/1e6) << std::endl << std::endl; + + //set the rx rf gain + std::cout << boost::format("Setting RX Gain: %f dB...") % gain << std::endl; + sdev->set_rx_gain(gain); + std::cout << boost::format("Actual RX Gain: %f dB...") % sdev->get_rx_gain() << std::endl << std::endl; + + boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow for some setup time + std::cout << "LO Locked = " << sdev->get_rx_lo_locked() << std::endl; + + //setup streaming + uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); + stream_cmd.num_samps = total_num_samps; + stream_cmd.stream_now = true; + sdev->issue_stream_cmd(stream_cmd); + + //loop until total number of samples reached + size_t num_acc_samps = 0; //number of accumulated samples + uhd::rx_metadata_t md; + std::vector > buff(dev->get_max_recv_samps_per_packet()); + std::ofstream outfile(file.c_str(), std::ofstream::binary); + + while(num_acc_samps < total_num_samps){ + size_t num_rx_samps = dev->recv( + &buff.front(), buff.size(), md, + uhd::io_type_t::COMPLEX_INT16, + uhd::device::RECV_MODE_ONE_PACKET + ); + + //handle the error codes + switch(md.error_code){ + case uhd::rx_metadata_t::ERROR_CODE_NONE: + break; + + case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: + if (num_acc_samps == 0) continue; + std::cout << boost::format( + "Got timeout before all samples received, possible packet loss, exiting loop..." + ) << std::endl; + goto done_loop; + + default: + std::cout << boost::format( + "Got error code 0x%x, exiting loop..." + ) % md.error_code << std::endl; + goto done_loop; + } + + //write complex short integer samples to the binary file + outfile.write((const char*)&buff[0], num_rx_samps * sizeof(std::complex)); + + if(verbose) std::cout << boost::format( + "Got packet: %u samples, %u full secs, %f frac secs" + ) % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl; + + num_acc_samps += num_rx_samps; + } done_loop: + + outfile.close(); + + //finished + std::cout << std::endl << "Done!" << std::endl << std::endl; + + return 0; +} diff --git a/host/examples/rx_samples_to_udp.cpp b/host/examples/rx_samples_to_udp.cpp new file mode 100644 index 000000000..c81b43ee3 --- /dev/null +++ b/host/examples/rx_samples_to_udp.cpp @@ -0,0 +1,142 @@ +// +// 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 +#include +#include +#include + +namespace po = boost::program_options; + +int UHD_SAFE_MAIN(int argc, char *argv[]){ + uhd::set_thread_priority_safe(); + + //variables to be set by po + std::string args; + size_t total_num_samps; + double rate, freq; + float gain; + std::string addr, port; + + //setup the program options + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "help message") + ("args", po::value(&args)->default_value(""), "single uhd device address args") + ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to receive") + ("rate", po::value(&rate)->default_value(100e6/16), "rate of incoming samples") + ("freq", po::value(&freq)->default_value(0), "rf center frequency in Hz") + ("gain", po::value(&gain)->default_value(0), "gain for the RF chain") + ("port", po::value(&port)->default_value("7124"), "server udp port") + ("addr", po::value(&addr)->default_value("192.168.1.10"), "resolvable server address") + ("dilv", "specify to disable inner-loop verbose") + ; + 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 RX to UDP %s") % desc << std::endl; + return ~0; + } + + bool verbose = vm.count("dilv") == 0; + + //create a usrp device + std::cout << std::endl; + std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; + uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); + uhd::device::sptr dev = sdev->get_device(); + std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; + + //set the rx sample rate + std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate/1e6) << std::endl; + sdev->set_rx_rate(rate); + std::cout << boost::format("Actual RX Rate: %f Msps...") % (sdev->get_rx_rate()/1e6) << std::endl << std::endl; + + //set the rx center frequency + std::cout << boost::format("Setting RX Freq: %f Mhz...") % (freq/1e6) << std::endl; + sdev->set_rx_freq(freq); + std::cout << boost::format("Actual RX Freq: %f Mhz...") % (sdev->get_rx_freq()/1e6) << std::endl << std::endl; + + //set the rx rf gain + std::cout << boost::format("Setting RX Gain: %f dB...") % gain << std::endl; + sdev->set_rx_gain(gain); + std::cout << boost::format("Actual RX Gain: %f dB...") % sdev->get_rx_gain() << std::endl << std::endl; + + boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow for some setup time + std::cout << "LO Locked = " << sdev->get_rx_lo_locked() << std::endl; + + //setup streaming + uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); + stream_cmd.num_samps = total_num_samps; + stream_cmd.stream_now = true; + sdev->issue_stream_cmd(stream_cmd); + + //loop until total number of samples reached + size_t num_acc_samps = 0; //number of accumulated samples + uhd::rx_metadata_t md; + std::vector > buff(dev->get_max_recv_samps_per_packet()); + uhd::transport::udp_simple::sptr udp_xport = uhd::transport::udp_simple::make_connected(addr, port); + + while(num_acc_samps < total_num_samps){ + size_t num_rx_samps = dev->recv( + &buff.front(), buff.size(), md, + uhd::io_type_t::COMPLEX_FLOAT32, + uhd::device::RECV_MODE_ONE_PACKET + ); + + //handle the error codes + switch(md.error_code){ + case uhd::rx_metadata_t::ERROR_CODE_NONE: + break; + + case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: + if (num_acc_samps == 0) continue; + std::cout << boost::format( + "Got timeout before all samples received, possible packet loss, exiting loop..." + ) << std::endl; + goto done_loop; + + default: + std::cout << boost::format( + "Got error code 0x%x, exiting loop..." + ) % md.error_code << std::endl; + goto done_loop; + } + + //send complex single precision floating point samples over udp + udp_xport->send(boost::asio::buffer(buff, num_rx_samps)); + + if(verbose) std::cout << boost::format( + "Got packet: %u samples, %u full secs, %f frac secs" + ) % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl; + + num_acc_samps += num_rx_samps; + } done_loop: + + //finished + std::cout << std::endl << "Done!" << std::endl << std::endl; + + return 0; +} diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 441665900..8a810811f 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -32,7 +32,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::string args; time_t seconds_in_future; size_t total_num_samps; - double rx_rate, freq; + double rate, freq; //setup the program options po::options_description desc("Allowed options"); @@ -41,7 +41,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("args", po::value(&args)->default_value(""), "single uhd device address args") ("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") + ("rate", po::value(&rate)->default_value(100e6/16), "rate of incoming samples") ("freq", po::value(&freq)->default_value(0), "rf center frequency in Hz") ("dilv", "specify to disable inner-loop verbose") ; @@ -64,12 +64,17 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::device::sptr dev = sdev->get_device(); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; - //set properties on the device - std::cout << boost::format("Setting RX Rate: %f Msps...") % (rx_rate/1e6) << std::endl; - 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; + //set the rx sample rate + std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate/1e6) << std::endl; + sdev->set_rx_rate(rate); + std::cout << boost::format("Actual RX Rate: %f Msps...") % (sdev->get_rx_rate()/1e6) << std::endl << std::endl; + + //set the rx center frequency + std::cout << boost::format("Setting RX Freq: %f Mhz...") % (freq/1e6) << std::endl; sdev->set_rx_freq(freq); + std::cout << boost::format("Actual RX Freq: %f Mhz...") % (sdev->get_rx_freq()/1e6) << std::endl << std::endl; + + std::cout << boost::format("Setting device timestamp to 0...") << std::endl; sdev->set_time_now(uhd::time_spec_t(0.0)); //setup streaming diff --git a/host/examples/rx_to_file.cpp b/host/examples/rx_to_file.cpp deleted file mode 100644 index 25727a7d3..000000000 --- a/host/examples/rx_to_file.cpp +++ /dev/null @@ -1,144 +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 -#include -#include - -namespace po = boost::program_options; - - -int UHD_SAFE_MAIN(int argc, char *argv[]){ - uhd::set_thread_priority_safe(); - - //variables to be set by po - std::string args, file; - time_t seconds_in_future; - size_t total_num_samps; - double rx_rate, freq; - - //setup the program options - po::options_description desc("Allowed options"); - desc.add_options() - ("help", "help message") - ("args", po::value(&args)->default_value(""), "single uhd device address args") - ("file", po::value(&file)->default_value("out.16sc.dat"), "name of the file to write binary samples to") - ("secs", po::value(&seconds_in_future)->default_value(1), "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") - ("dilv", "specify to disable inner-loop verbose") - ; - 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 RX to File %s") % desc << std::endl; - return ~0; - } - - bool verbose = vm.count("dilv") == 0; - - //create a usrp device - std::cout << std::endl; - std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; - uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); - uhd::device::sptr dev = sdev->get_device(); - std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; - - //set properties on the device - std::cout << boost::format("Setting RX Rate: %f Msps...") % (rx_rate/1e6) << std::endl; - 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.0)); - - uhd::gain_range_t rx_gain = sdev->get_rx_gain_range(); - std::cout << "Setting RX Gain to: " << rx_gain.max << std::endl; - sdev->set_rx_gain(rx_gain.max); - - sleep(1); - std::cout << "LO Locked = " << sdev->get_rx_lo_locked() << std::endl; - - //setup streaming - std::cout << std::endl; - std::cout << boost::format( - "Begin streaming %u samples, %d seconds in the future..." - ) % total_num_samps % seconds_in_future << std::endl; - uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); - stream_cmd.num_samps = total_num_samps; - stream_cmd.stream_now = false; - stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future); - sdev->issue_stream_cmd(stream_cmd); - - //loop until total number of samples reached - size_t num_acc_samps = 0; //number of accumulated samples - uhd::rx_metadata_t md; - std::vector > buff(dev->get_max_recv_samps_per_packet()); - std::ofstream outfile(file.c_str(), std::ofstream::binary); - - while(num_acc_samps < total_num_samps){ - size_t num_rx_samps = dev->recv( - &buff.front(), buff.size(), md, - uhd::io_type_t::COMPLEX_INT16, - uhd::device::RECV_MODE_ONE_PACKET - ); - - //handle the error codes - switch(md.error_code){ - case uhd::rx_metadata_t::ERROR_CODE_NONE: - break; - - case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: - if (num_acc_samps == 0) continue; - std::cout << boost::format( - "Got timeout before all samples received, possible packet loss, exiting loop..." - ) << std::endl; - goto done_loop; - - default: - std::cout << boost::format( - "Got error code 0x%x, exiting loop..." - ) % md.error_code << std::endl; - goto done_loop; - } - - //write complex short integer samples to the binary file - outfile.write((const char*)&buff[0], num_rx_samps * sizeof(std::complex)); - - if(verbose) std::cout << boost::format( - "Got packet: %u samples, %u full secs, %f frac secs" - ) % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl; - - num_acc_samps += num_rx_samps; - } done_loop: - - outfile.close(); - - //finished - std::cout << std::endl << "Done!" << std::endl << std::endl; - - return 0; -} diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index 863446682..799da37e0 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -33,7 +33,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ time_t seconds_in_future; size_t total_num_samps; size_t samps_per_packet; - double tx_rate, freq; + double rate, freq; float ampl; //setup the program options @@ -44,7 +44,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("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") ("spp", po::value(&samps_per_packet)->default_value(1000), "number of samples per packet") - ("txrate", po::value(&tx_rate)->default_value(100e6/16), "rate of outgoing samples") + ("rate", po::value(&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(float(0.3)), "amplitude of each sample") ("dilv", "specify to disable inner-loop verbose") @@ -68,12 +68,17 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::device::sptr dev = sdev->get_device(); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << 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; + //set the tx sample rate + std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate/1e6) << std::endl; + sdev->set_tx_rate(rate); + std::cout << boost::format("Actual TX Rate: %f Msps...") % (sdev->get_tx_rate()/1e6) << std::endl << std::endl; + + //set the tx center frequency + std::cout << boost::format("Setting TX Freq: %f Mhz...") % (freq/1e6) << std::endl; sdev->set_tx_freq(freq); + std::cout << boost::format("Actual TX Freq: %f Mhz...") % (sdev->get_tx_freq()/1e6) << std::endl << std::endl; + + std::cout << boost::format("Setting device timestamp to 0...") << std::endl; sdev->set_time_now(uhd::time_spec_t(0.0)); //allocate data to send -- cgit v1.2.3 From d7c7351bb66cb4c455e77f83edd581d6afbcef9c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 19:30:45 -0700 Subject: uhd: removed dilv in rx files examples --- host/examples/rx_samples_to_file.cpp | 7 ------- host/examples/rx_samples_to_udp.cpp | 7 ------- 2 files changed, 14 deletions(-) diff --git a/host/examples/rx_samples_to_file.cpp b/host/examples/rx_samples_to_file.cpp index 6671644fa..c80d2a6de 100644 --- a/host/examples/rx_samples_to_file.cpp +++ b/host/examples/rx_samples_to_file.cpp @@ -46,7 +46,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("rate", po::value(&rate)->default_value(100e6/16), "rate of incoming samples") ("freq", po::value(&freq)->default_value(0), "rf center frequency in Hz") ("gain", po::value(&gain)->default_value(0), "gain for the RF chain") - ("dilv", "specify to disable inner-loop verbose") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -58,8 +57,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ return ~0; } - bool verbose = vm.count("dilv") == 0; - //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; @@ -126,10 +123,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //write complex short integer samples to the binary file outfile.write((const char*)&buff[0], num_rx_samps * sizeof(std::complex)); - if(verbose) std::cout << boost::format( - "Got packet: %u samples, %u full secs, %f frac secs" - ) % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl; - num_acc_samps += num_rx_samps; } done_loop: diff --git a/host/examples/rx_samples_to_udp.cpp b/host/examples/rx_samples_to_udp.cpp index c81b43ee3..488c95494 100644 --- a/host/examples/rx_samples_to_udp.cpp +++ b/host/examples/rx_samples_to_udp.cpp @@ -48,7 +48,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("gain", po::value(&gain)->default_value(0), "gain for the RF chain") ("port", po::value(&port)->default_value("7124"), "server udp port") ("addr", po::value(&addr)->default_value("192.168.1.10"), "resolvable server address") - ("dilv", "specify to disable inner-loop verbose") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -60,8 +59,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ return ~0; } - bool verbose = vm.count("dilv") == 0; - //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; @@ -128,10 +125,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //send complex single precision floating point samples over udp udp_xport->send(boost::asio::buffer(buff, num_rx_samps)); - if(verbose) std::cout << boost::format( - "Got packet: %u samples, %u full secs, %f frac secs" - ) % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl; - num_acc_samps += num_rx_samps; } done_loop: -- cgit v1.2.3