diff options
author | Nick Foster <nick@nerdnetworks.org> | 2010-08-10 17:02:47 -0700 |
---|---|---|
committer | Nick Foster <nick@nerdnetworks.org> | 2010-08-10 17:02:47 -0700 |
commit | 663808e847c4970551c6c8127c2c5d816e2a2014 (patch) | |
tree | 12183a2d7ea5434880dccfa414d8a378ae134abc | |
parent | 90a5d84a18aaa338092e572ff257aab1fdcc8e6b (diff) | |
parent | 9e419c7b7f35062ceb2ed4e508cadb163067593f (diff) | |
download | uhd-663808e847c4970551c6c8127c2c5d816e2a2014.tar.gz uhd-663808e847c4970551c6c8127c2c5d816e2a2014.tar.bz2 uhd-663808e847c4970551c6c8127c2c5d816e2a2014.zip |
Merge branch 'master' into usrp2p
this was the merge from hell
Conflicts:
firmware/microblaze/Makefile.am
firmware/microblaze/bootstrap
firmware/microblaze/configure.ac
firmware/microblaze/lib/Makefile.inc
host/lib/CMakeLists.txt
host/lib/usrp/mimo_usrp.cpp
host/lib/usrp/simple_usrp.cpp
host/lib/usrp/usrp2/clock_ctrl.cpp
host/lib/usrp/usrp2/codec_impl.cpp
host/lib/usrp/usrp2/dboard_impl.cpp
host/lib/usrp/usrp2/mboard_impl.cpp
host/lib/usrp/usrp2/usrp2_iface.hpp
host/lib/usrp/usrp2/usrp2_impl.hpp
host/lib/usrp/usrp2/usrp2_regs.hpp
host/test/CMakeLists.txt
88 files changed, 2991 insertions, 6425 deletions
diff --git a/firmware/microblaze/Makefile.am b/firmware/microblaze/Makefile.am index ffc59192d..52fa649c2 100644 --- a/firmware/microblaze/Makefile.am +++ b/firmware/microblaze/Makefile.am @@ -26,3 +26,4 @@ SUBDIRS = \ usrp2 \ usrp2p \ usrp2p/bootloader + diff --git a/firmware/microblaze/apps/burnrev40.c b/firmware/microblaze/apps/burnrev40.c deleted file mode 100644 index 362270961..000000000 --- a/firmware/microblaze/apps/burnrev40.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2007,2008 Free Software Foundation, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include <stdbool.h> -#include "ethernet.h" -#include "nonstdio.h" -#include "usrp2_eth_packet.h" -#include "dbsm.h" -#include "app_common_v2.h" -#include "memcpy_wa.h" -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <i2c.h> -#include <usrp2_i2c_addr.h> -#include <clocks.h> -#include "sd.h" -#include "mdelay.h" - -#define HW_REV_MAJOR 4 -#define HW_REV_MINOR 0 - -int test_ram() -{ - int i,j,k; - output_regs->ram_page = 1<<10; - - extram[0] = 0xDEADBEEF; - extram[1] = 0xF00D1234; - extram[7] = 0x76543210; - - output_regs->ram_page = 2<<10; - extram[7] = 0x55555555; - extram[1] = 0xaaaaaaaa; - extram[0] = 0xeeeeeeee; - - output_regs->ram_page = 1<<10; - - i = extram[0]; - k = extram[1]; - j = extram[7]; - - if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) { - puts("RAM FAIL1!\n"); - puthex32_nl(i); - puthex32_nl(j); - puthex32_nl(k); - return 0; - } - - output_regs->ram_page = 2<<10; - - j = extram[7]; - k = extram[1]; - i = extram[0]; - - if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) { - puts("RAM FAIL2!\n"); - puthex32_nl(i); - puthex32_nl(j); - puthex32_nl(k); - return 0; - } - return 1; -} - -int test_sd() -{ - int i = sd_init(); - if(i==0) { - puts("FAILED INIT of Card\n"); - return 0; - } - - unsigned char buf[512]; - i = sd_read_block(2048,buf); - if(i == 0) { - puts("READ Command Rejected\n"); - return 0; - } - if((buf[0]==0xb8)&&(buf[1]==0x08)&&(buf[2]==0x00)&&(buf[3]==0x50)) - ; - else { - puts("Read bad data from SD Card\n"); - return 0; - } - return 1; -} - -int -main(void) -{ - u2_init(); - - putstr("\nFactory Test, Board Rev 4.0\n"); - - bool ok = true; - unsigned char maj = HW_REV_MAJOR; - unsigned char min = HW_REV_MINOR; - ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &maj, 1); - ok &= eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &min, 1); - - putstr("\nset_hw_rev\n"); - if (ok) - printf("OK: set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR); - else { - printf("FAILED to set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR); - hal_finish(); - return 0; - } - - if(test_sd()) - puts("SD OK\n"); - else { - puts("SD FAIL\n"); - //hal_finish(); - //return 0; - } - if(test_ram()) - puts("RAM OK\n"); - else { - puts("RAM FAIL\n"); - hal_finish(); - return 0; - } - - print_mac_addr(ethernet_mac_addr()->addr); - newline(); - - clocks_mimo_config(MC_WE_LOCK_TO_SMA); - - while (!clocks_lock_detect()) { - puts("No Lock"); - mdelay(1000); - } - puts("Clock Locked\n"); - -} diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 092d216aa..f0a9702be 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -181,9 +181,9 @@ void handle_udp_ctrl_packet( uint32_t ctrl_data_in_id = ctrl_data_in->id; //ensure that the protocol versions match - if (payload_len >= sizeof(uint32_t) && ctrl_data_in->proto_ver != USRP2_PROTO_VERSION){ - printf("!Error in control packet handler: Expected protocol version %d, but got %d\n", - USRP2_PROTO_VERSION, ctrl_data_in->proto_ver + if (payload_len >= sizeof(uint32_t) && ctrl_data_in->proto_ver != USRP2_FW_COMPAT_NUM){ + printf("!Error in control packet handler: Expected compatibility number %d, but got %d\n", + USRP2_FW_COMPAT_NUM, ctrl_data_in->proto_ver ); ctrl_data_in_id = USRP2_CTRL_ID_WAZZUP_BRO; } @@ -198,7 +198,7 @@ void handle_udp_ctrl_packet( //setup the output data usrp2_ctrl_data_t ctrl_data_out = { - .proto_ver = USRP2_PROTO_VERSION, + .proto_ver = USRP2_FW_COMPAT_NUM, .id=USRP2_CTRL_ID_HUH_WHAT, .seq=ctrl_data_in->seq }; @@ -441,7 +441,8 @@ main(void) print_mac_addr(ethernet_mac_addr()->addr); newline(); print_ip_addr(get_ip_addr()); newline(); - printf("Control protocol version: %d\n", USRP2_PROTO_VERSION); + printf("FPGA compatibility number: %d\n", USRP2_FPGA_COMPAT_NUM); + printf("Firmware compatibility number: %d\n", USRP2_FW_COMPAT_NUM); ethernet_register_link_changed_callback(link_changed_callback); ethernet_init(); diff --git a/firmware/microblaze/config.guess b/firmware/microblaze/config.guess deleted file mode 120000 index 405bc3235..000000000 --- a/firmware/microblaze/config.guess +++ /dev/null @@ -1 +0,0 @@ -/usr/share/automake-1.11/config.guess
\ No newline at end of file diff --git a/firmware/microblaze/config.sub b/firmware/microblaze/config.sub deleted file mode 120000 index 4d47fbcbc..000000000 --- a/firmware/microblaze/config.sub +++ /dev/null @@ -1 +0,0 @@ -/usr/share/automake-1.11/config.sub
\ No newline at end of file diff --git a/fpga/usrp2/control_lib/Makefile.srcs b/fpga/usrp2/control_lib/Makefile.srcs index 5e2a96a53..bc8e4d5bc 100644 --- a/fpga/usrp2/control_lib/Makefile.srcs +++ b/fpga/usrp2/control_lib/Makefile.srcs @@ -20,6 +20,7 @@ mux8.v \ nsgpio.v \ ram_2port.v \ ram_harv_cache.v \ +ram_harvard.v \ ram_loader.v \ setting_reg.v \ settings_bus.v \ diff --git a/fpga/usrp2/control_lib/ram_harvard.v b/fpga/usrp2/control_lib/ram_harvard.v new file mode 100644 index 000000000..948f9b36f --- /dev/null +++ b/fpga/usrp2/control_lib/ram_harvard.v @@ -0,0 +1,69 @@ + + +// 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 [3:0] ram_loader_sel_i, + input ram_loader_stb_i, + input ram_loader_we_i, + 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), + .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), + .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_harvard diff --git a/fpga/usrp2/control_lib/ram_loader.v b/fpga/usrp2/control_lib/ram_loader.v index cb67de739..c53ea7aa7 100644 --- a/fpga/usrp2/control_lib/ram_loader.v +++ b/fpga/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/fpga/usrp2/fifo/Makefile.srcs b/fpga/usrp2/fifo/Makefile.srcs index 22867da7e..c66979132 100644 --- a/fpga/usrp2/fifo/Makefile.srcs +++ b/fpga/usrp2/fifo/Makefile.srcs @@ -20,4 +20,6 @@ fifo19_to_ll8.v \ ll8_to_fifo19.v \ fifo36_to_fifo19.v \ fifo19_to_fifo36.v \ +fifo36_mux.v \ +fifo36_demux.v \ )) diff --git a/fpga/usrp2/fifo/fifo36_demux.v b/fpga/usrp2/fifo/fifo36_demux.v new file mode 100644 index 000000000..a54759d4d --- /dev/null +++ b/fpga/usrp2/fifo/fifo36_demux.v @@ -0,0 +1,50 @@ + +// Demux packets from a fifo based on the contents of the first line +// If first line matches the parameter and mask, send to data1, otherwise send to data0 + +module fifo36_demux + #(parameter match_data = 0, + parameter match_mask = 0) + (input clk, input reset, input clear, + input [35:0] data_i, input src_rdy_i, output dst_rdy_o, + output [35:0] data0_o, output src0_rdy_o, input dst0_rdy_i, + output [35:0] data1_o, output src1_rdy_o, input dst1_rdy_i); + + localparam DMX_IDLE = 0; + localparam DMX_DATA0 = 1; + localparam DMX_DATA1 = 2; + + reg [1:0] state; + + wire match = |( (data_i ^ match_data) & match_mask ); + wire eof = data_i[33]; + + always @(posedge clk) + if(reset | clear) + state <= DMX_IDLE; + else + case(state) + DMX_IDLE : + if(src_rdy_i) + if(match) + state <= DMX_DATA1; + else + state <= DMX_DATA0; + DMX_DATA0 : + if(src_rdy_i & dst0_rdy_i & eof) + state <= DMX_IDLE; + DMX_DATA1 : + if(src_rdy_i & dst1_rdy_i & eof) + state <= DMX_IDLE; + default : + state <= DMX_IDLE; + endcase // case (state) + + assign dst_rdy_o = (state==DMX_IDLE) ? 0 : (state==DMX_DATA0) ? dst0_rdy_i : dst1_rdy_i; + assign src0_rdy_o = (state==DMX_DATA0) ? src_rdy_i : 0; + assign src1_rdy_o = (state==DMX_DATA1) ? src_rdy_i : 0; + + assign data0_o = data_i; + assign data1_o = data_i; + +endmodule // fifo36_demux diff --git a/fpga/usrp2/fifo/fifo36_mux.v b/fpga/usrp2/fifo/fifo36_mux.v new file mode 100644 index 000000000..92bf13ff9 --- /dev/null +++ b/fpga/usrp2/fifo/fifo36_mux.v @@ -0,0 +1,57 @@ + +// Mux packets from multiple FIFO interfaces onto a single one. +// Can alternate or give priority to one port (port 0) +// In prio mode, port 1 will never get access if port 0 is always busy + +module fifo36_mux + #(parameter prio = 0) + (input clk, input reset, input clear, + input [35:0] data0_i, input src0_rdy_i, output dst0_rdy_o, + input [35:0] data1_i, input src1_rdy_i, output dst1_rdy_o, + output [35:0] data_o, output src_rdy_o, input dst_rdy_i); + + localparam MUX_IDLE0 = 0; + localparam MUX_DATA0 = 1; + localparam MUX_IDLE1 = 2; + localparam MUX_DATA1 = 3; + + reg [1:0] state; + + wire eof0 = data0_i[33]; + wire eof1 = data1_i[33]; + + always @(posedge clk) + if(reset | clear) + state <= MUX_IDLE0; + else + case(state) + MUX_IDLE0 : + if(src0_rdy_i) + state <= MUX_DATA0; + else if(src1_rdy_i) + state <= MUX_DATA1; + + MUX_DATA0 : + if(src0_rdy_i & dst_rdy_i & eof0) + state <= prio ? MUX_IDLE0 : MUX_IDLE1; + + MUX_IDLE1 : + if(src1_rdy_i) + state <= MUX_DATA1; + else if(src0_rdy_i) + state <= MUX_DATA0; + + MUX_DATA1 : + if(src1_rdy_i & dst_rdy_i & eof1) + state <= MUX_IDLE0; + + default : + state <= MUX_IDLE0; + endcase // case (state) + + 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_o = (state==MUX_DATA0) ? data0_i : data1_i; + +endmodule // fifo36_demux diff --git a/fpga/usrp2/fifo/fifo_new_tb.vcd b/fpga/usrp2/fifo/fifo_new_tb.vcd deleted file mode 100644 index 796889e7d..000000000 --- a/fpga/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/fpga/usrp2/fifo/fifo_tb.v b/fpga/usrp2/fifo/fifo_tb.v index f561df7fa..327da4700 100644 --- a/fpga/usrp2/fifo/fifo_tb.v +++ b/fpga/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/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_bpcu.v b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_bpcu.v index a7c686e7e..81587e25c 100644 --- a/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_bpcu.v +++ b/fpga/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/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_core_BE.v b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_core_BE.v index 9ffa20ff2..38ca3a023 100644 --- a/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_core_BE.v +++ b/fpga/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/fpga/usrp2/sdr_lib/dsp_core_tx.v b/fpga/usrp2/sdr_lib/dsp_core_tx.v index 22d3d44a3..79d92c9b3 100644 --- a/fpga/usrp2/sdr_lib/dsp_core_tx.v +++ b/fpga/usrp2/sdr_lib/dsp_core_tx.v @@ -29,11 +29,11 @@ module dsp_core_tx (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), .in(set_data),.out({scale_i,scale_q}),.changed()); - setting_reg #(.my_addr(BASE+2)) sr_2 + setting_reg #(.my_addr(BASE+2), .width(10)) sr_2 (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), .in(set_data),.out({enable_hb1, enable_hb2, interp_rate}),.changed()); - setting_reg #(.my_addr(BASE+4)) sr_4 + setting_reg #(.my_addr(BASE+4), .width(8)) sr_4 (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), .in(set_data),.out({dacmux_b,dacmux_a}),.changed()); diff --git a/fpga/usrp2/top/Makefile.common b/fpga/usrp2/top/Makefile.common index d0435fa1e..4da64ac28 100644 --- a/fpga/usrp2/top/Makefile.common +++ b/fpga/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/fpga/usrp2/top/u2_rev3/u2_core.v b/fpga/usrp2/top/u2_rev3/u2_core.v index b67d8edd6..9ba3cc136 100644..100755 --- a/fpga/usrp2/top/u2_rev3/u2_core.v +++ b/fpga/usrp2/top/u2_rev3/u2_core.v @@ -277,33 +277,33 @@ 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 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)) 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), @@ -317,16 +317,16 @@ 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), .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), - .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), @@ -622,7 +622,7 @@ module u2_core // /////////////////////////////////////////////////////////////////////////////////// // External RAM Interface - +/* localparam PAGE_SIZE = 10; // PAGE SIZE is in bytes, 10 = 1024 bytes wire [15:0] bus2ram, ram2bus; @@ -650,6 +650,7 @@ module u2_core .sram_bw(),.sram_adv(RAM_LDn),.sram_ce(RAM_CENn),.sram_oe(RAM_OEn), .sram_mode(),.sram_zz() ); +*/ assign RAM_CE1n = 0; assign RAM_D[17:16] = 2'bzz; @@ -700,7 +701,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 diff --git a/fpga/usrp2/top/u2_rev3/u2_core_udp.v b/fpga/usrp2/top/u2_rev3/u2_core_udp.v index cb0ed78c7..124930c23 100644 --- a/fpga/usrp2/top/u2_rev3/u2_core_udp.v +++ b/fpga/usrp2/top/u2_rev3/u2_core_udp.v @@ -180,6 +180,11 @@ module u2_core wire [31:0] irq; wire [63:0] vita_time; + wire run_rx, run_tx; + reg run_rx_d1; + always @(posedge dsp_clk) + run_rx_d1 <= run_rx; + // /////////////////////////////////////////////////////////////////////////////////////////////// // Wishbone Single Master INTERCON localparam dw = 32; // Data bus width @@ -279,33 +284,33 @@ 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 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)) 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), @@ -319,16 +324,16 @@ 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), .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), - .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), @@ -418,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), @@ -426,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) ); // ///////////////////////////////////////////////////////////////////////// @@ -461,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), @@ -509,12 +526,13 @@ module u2_core // In Rev3 there are only 6 leds, and the highest one is on the ETH connector wire [7:0] led_src, led_sw; - wire [7:0] led_hw = {clk_status,serdes_link_up}; + wire [7:0] led_hw = {run_tx, run_rx, clk_status, serdes_link_up, 1'b0}; setting_reg #(.my_addr(3),.width(8)) sr_led (.clk(wb_clk),.rst(wb_rst),.strobe(set_stb),.addr(set_addr), .in(set_data),.out(led_sw),.changed()); - setting_reg #(.my_addr(8),.width(8)) sr_led_src (.clk(wb_clk),.rst(wb_rst),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out(led_src),.changed()); + + setting_reg #(.my_addr(8),.width(8), .at_reset(8'b0001_1110)) + sr_led_src (.clk(wb_clk),.rst(wb_rst), .strobe(set_stb),.addr(set_addr), .in(set_data),.out(led_src),.changed()); assign leds = (led_src & led_hw) | (~led_src & led_sw); @@ -565,11 +583,6 @@ module u2_core // ///////////////////////////////////////////////////////////////////////// // ATR Controller, Slave #11 - wire run_rx, run_tx; - reg run_rx_d1; - always @(posedge dsp_clk) - run_rx_d1 <= run_rx; - atr_controller atr_controller (.clk_i(wb_clk),.rst_i(wb_rst), .adr_i(sb_adr[5:0]),.sel_i(sb_sel),.dat_i(sb_dat_o),.dat_o(sb_dat_i), @@ -638,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; // /////////////////////////////////////////////////////////////////////////////////// @@ -773,8 +772,7 @@ endmodule // u2_core { 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 }, @@ -783,7 +781,6 @@ endmodule // 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 = vrc_debug; @@ -794,9 +791,8 @@ endmodule // u2_core {wr1_ready_i, wr1_ready_o, rx1_src_rdy, rx1_dst_rdy, rx1_data[35:32]}}; */ // 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 } }; diff --git a/fpga/usrp2/udp/prot_eng_tx.v b/fpga/usrp2/udp/prot_eng_tx.v index 9031011f7..a18eb73ae 100644 --- a/fpga/usrp2/udp/prot_eng_tx.v +++ b/fpga/usrp2/udp/prot_eng_tx.v @@ -40,11 +40,16 @@ module prot_eng_tx // Store header values in a small dual-port (distributed) ram reg [HDR_WIDTH-1:0] header_ram[0:HDR_LEN-1]; wire [HDR_WIDTH-1:0] header_word; + reg [15:0] chk_precompute; always @(posedge clk) if(set_stb & ((set_addr & 8'hE0) == BASE)) - header_ram[set_addr[4:0]] <= set_data; - + begin + header_ram[set_addr[4:0]] <= set_data; + if(set_data[18]) + chk_precompute <= set_data[15:0]; + end + assign header_word = header_ram[state]; wire last_hdr_line = header_word[19]; @@ -56,7 +61,7 @@ module prot_eng_tx reg [15:0] length; wire [15:0] ip_length = length + 28; // IP HDR + UDP HDR wire [15:0] udp_length = length + 8; // UDP HDR - + always @(posedge clk) if(reset) begin @@ -101,12 +106,16 @@ module prot_eng_tx wire [15:0] checksum; add_onescomp #(.WIDTH(16)) add_onescomp - (.A(header_word[15:0]),.B(ip_length),.SUM(checksum)); + (.A(chk_precompute),.B(ip_length),.SUM(checksum)); + reg [15:0] checksum_reg; + always @(posedge clk) + checksum_reg <= checksum; + always @* if(ip_chk) //dataout_int <= header_word[15:0] ^ ip_length; - dataout_int <= 16'hFFFF ^ checksum; + dataout_int <= 16'hFFFF ^ checksum_reg; else if(ip_len) dataout_int <= ip_length; else if(udp_len) diff --git a/fpga/usrp2/vrt/Makefile.srcs b/fpga/usrp2/vrt/Makefile.srcs index 07c62224b..dc4bd8c96 100644 --- a/fpga/usrp2/vrt/Makefile.srcs +++ b/fpga/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/fpga/usrp2/vrt/gen_context_pkt.v b/fpga/usrp2/vrt/gen_context_pkt.v new file mode 100644 index 000000000..780a027ba --- /dev/null +++ b/fpga/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/fpga/usrp2/vrt/vita_rx.build b/fpga/usrp2/vrt/vita_rx.build index f6d2d75a3..010d1be6e 100755 --- a/fpga/usrp2/vrt/vita_rx.build +++ b/fpga/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 diff --git a/fpga/usrp2/vrt/vita_rx_control.v b/fpga/usrp2/vrt/vita_rx_control.v index 742dd47e0..93673d292 100644 --- a/fpga/usrp2/vrt/vita_rx_control.v +++ b/fpga/usrp2/vrt/vita_rx_control.v @@ -67,7 +67,7 @@ module vita_rx_control shortfifo #(.WIDTH(96)) commandfifo (.clk(clk),.rst(reset),.clear(clear_int), .datain({new_command,new_time}), .write(write_ctrl&~full_ctrl), .full(full_ctrl), - .dataout({send_imm_pre,chain_pre,reload_pre,numlines_pre,rcvtime_pre}), + .dataout({send_imm_pre,chain_pre,reload_pre,numlines_pre,rcvtime_pre}), .read(read_ctrl), .empty(empty_ctrl), .occupied(command_queue_len), .space() ); @@ -98,7 +98,7 @@ module vita_rx_control .src_rdy_o(sample_fifo_src_rdy_o), .dst_rdy_i(sample_fifo_dst_rdy_i), .space(), .occupied() ); - // Inband Signallling State Machine + // Inband Signalling State Machine time_compare time_compare (.time_now(vita_time), .trigger_time(rcvtime), .now(now), .early(early), .late(late)); @@ -189,4 +189,3 @@ module vita_rx_control { 2'b0, overrun, chain_pre, sample_fifo_in_rdy, attempt_sample_write, sample_fifo_src_rdy_o,sample_fifo_dst_rdy_i} }; endmodule // rx_control - diff --git a/fpga/usrp2/vrt/vita_rx_framer.v b/fpga/usrp2/vrt/vita_rx_framer.v index f3a81664a..fd82263d0 100644 --- a/fpga/usrp2/vrt/vita_rx_framer.v +++ b/fpga/usrp2/vrt/vita_rx_framer.v @@ -99,7 +99,7 @@ module vita_rx_framer localparam VITA_ERR_TICS = 12; localparam VITA_ERR_TICS2 = 13; localparam VITA_ERR_PAYLOAD = 14; - localparam VITA_ERR_TRAILER = 15; + localparam VITA_ERR_TRAILER = 15; // Extension context packets have no trailer always @(posedge clk) if(reset | clear_pkt_count) @@ -107,17 +107,30 @@ module vita_rx_framer else if((vita_state == VITA_TRAILER) & pkt_fifo_rdy) pkt_count <= pkt_count + 1; + wire has_streamid = vita_header[28]; + wire has_trailer = vita_header[26]; + reg trl_eob; + always @* case(vita_state) - VITA_HEADER, VITA_ERR_HEADER : pkt_fifo_line <= {2'b01,vita_header[31:20],pkt_count,vita_pkt_len}; - VITA_STREAMID, VITA_ERR_STREAMID : pkt_fifo_line <= {2'b00,vita_streamid}; - VITA_SECS, VITA_ERR_SECS : pkt_fifo_line <= {2'b00,vita_time_fifo_o[63:32]}; - VITA_TICS, VITA_ERR_TICS : pkt_fifo_line <= {2'b00,32'd0}; - VITA_TICS2, VITA_ERR_TICS2 : pkt_fifo_line <= {2'b00,vita_time_fifo_o[31:0]}; + // Data packets are IF Data packets with or w/o streamid, no classid, with trailer + VITA_HEADER : pkt_fifo_line <= {2'b01,3'b000,vita_header[28],2'b01,vita_header[25:20],pkt_count,vita_pkt_len}; + VITA_STREAMID : pkt_fifo_line <= {2'b00,vita_streamid}; + VITA_SECS : pkt_fifo_line <= {2'b00,vita_time_fifo_o[63:32]}; + VITA_TICS : pkt_fifo_line <= {2'b00,32'd0}; + VITA_TICS2 : pkt_fifo_line <= {2'b00,vita_time_fifo_o[31:0]}; VITA_PAYLOAD : pkt_fifo_line <= {2'b00,data_fifo_o}; - VITA_ERR_PAYLOAD : pkt_fifo_line <= {2'b00,28'd0,flags_fifo_o}; - VITA_TRAILER : pkt_fifo_line <= {2'b10,vita_trailer}; - VITA_ERR_TRAILER : pkt_fifo_line <= {2'b11,vita_trailer}; + VITA_TRAILER : pkt_fifo_line <= {2'b10,vita_trailer[31:21],1'b1,vita_trailer[19:9],trl_eob,8'd0}; + + // Error packets are Extension Context packets, which have no trailer + VITA_ERR_HEADER : pkt_fifo_line <= {2'b01,4'b0101,4'b0000,vita_header[23:20],pkt_count,16'd6}; + VITA_ERR_STREAMID : pkt_fifo_line <= {2'b00,vita_streamid}; + 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_TRAILER : pkt_fifo_line <= {2'b11,vita_trailer}; + default : pkt_fifo_line <= 34'h0_FFFF_FFFF; endcase // case (vita_state) @@ -141,6 +154,11 @@ module vita_rx_framer end else if(pkt_fifo_rdy) case(vita_state) + VITA_HEADER : + if(has_streamid) + vita_state <= VITA_STREAMID; + else + vita_state <= VITA_SECS; VITA_PAYLOAD : if(sample_fifo_src_rdy_i) begin @@ -148,6 +166,7 @@ module vita_rx_framer begin sample_phase <= 0; sample_ctr <= sample_ctr + 1; + trl_eob <= flags_fifo_o[0]; if(sample_ctr == samples_per_packet) vita_state <= VITA_TRAILER; if(|flags_fifo_o) // end early if any flag is set @@ -155,8 +174,10 @@ module vita_rx_framer end else sample_phase <= sample_phase + 1; - end - VITA_TRAILER, VITA_ERR_TRAILER : + end // if (sample_fifo_src_rdy_i) + VITA_ERR_PAYLOAD : + vita_state <= VITA_IDLE; + VITA_TRAILER : vita_state <= VITA_IDLE; default : vita_state <= vita_state + 1; @@ -172,7 +193,7 @@ module vita_rx_framer VITA_PAYLOAD : // Write if sample ready and no error flags req_write_pkt_fifo <= (sample_fifo_src_rdy_i & ~|flags_fifo_o[3:1]); - VITA_ERR_HEADER, VITA_ERR_STREAMID, VITA_ERR_SECS, VITA_ERR_TICS, VITA_ERR_TICS2, VITA_ERR_PAYLOAD, VITA_ERR_TRAILER : + VITA_ERR_HEADER, VITA_ERR_STREAMID, VITA_ERR_SECS, VITA_ERR_TICS, VITA_ERR_TICS2, VITA_ERR_PAYLOAD : req_write_pkt_fifo <= 1; default : req_write_pkt_fifo <= 0; @@ -192,7 +213,7 @@ module vita_rx_framer ( ((vita_state==VITA_PAYLOAD) & (sample_phase == (numchan-4'd1)) & ~|flags_fifo_o[3:1]) | - (vita_state==VITA_ERR_TRAILER)); + (vita_state==VITA_ERR_PAYLOAD)); assign debug_rx = vita_state; diff --git a/fpga/usrp2/vrt/vita_rx_tb.v b/fpga/usrp2/vrt/vita_rx_tb.v index b4fda9622..3e01e2ee2 100644 --- a/fpga/usrp2/vrt/vita_rx_tb.v +++ b/fpga/usrp2/vrt/vita_rx_tb.v @@ -3,8 +3,8 @@ module vita_rx_tb; localparam DECIM = 8'd4; - localparam MAXCHAN=4; - localparam NUMCHAN=4; + localparam MAXCHAN=1; + localparam NUMCHAN=1; reg clk = 0; reg reset = 1; @@ -94,7 +94,7 @@ module vita_rx_tb; @(posedge clk); write_setting(4,32'hDEADBEEF); // VITA header write_setting(5,32'hF00D1234); // VITA streamid - write_setting(6,32'h98765432); // VITA trailer + write_setting(6,32'hF0000000); // VITA trailer write_setting(7,8); // Samples per VITA packet write_setting(8,NUMCHAN); // Samples per VITA packet queue_rx_cmd(1,0,8,32'h0,32'h0); // send imm, single packet @@ -111,8 +111,13 @@ module vita_rx_tb; queue_rx_cmd(0,0,8,32'h0,32'h340); // send at, on time queue_rx_cmd(0,0,8,32'h0,32'h100); // send at, but late + #100000; + $display("\nChained, break chain\n"); queue_rx_cmd(1,1,8,32'h0,32'h0); // chained, but break chain #100000; + $display("\nSingle packet\n"); + queue_rx_cmd(1,0,8,32'h0,32'h0); // send imm, single packet + #100000; $display("\nEnd chain with zero samples, shouldn't error\n"); queue_rx_cmd(1,1,8,32'h0,32'h0); // chained queue_rx_cmd(0,0,0,32'h0,32'h0); // end chain with zero samples, should keep us out of error diff --git a/fpga/usrp2/vrt/vita_tx_chain.v b/fpga/usrp2/vrt/vita_tx_chain.v new file mode 100644 index 000000000..662cdca62 --- /dev/null +++ b/fpga/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/fpga/usrp2/vrt/vita_tx_control.v b/fpga/usrp2/vrt/vita_tx_control.v index bffc64e52..d0516bec8 100644 --- a/fpga/usrp2/vrt/vita_tx_control.v +++ b/fpga/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/fpga/usrp2/vrt/vita_tx_deframer.v b/fpga/usrp2/vrt/vita_tx_deframer.v index 220d3b061..f9cd7d00d 100644 --- a/fpga/usrp2/vrt/vita_tx_deframer.v +++ b/fpga/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,8 +21,10 @@ 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)) sr_numchan + setting_reg #(.my_addr(BASE), .at_reset(0), .width(2)) sr_numchan (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),.out(numchan),.changed()); @@ -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) ; diff --git a/host/README b/host/README index 6eaf6bb42..5018ef541 100644 --- a/host/README +++ b/host/README @@ -18,6 +18,7 @@ LF TX RFX Series XCVR 2450 WBX Series +DBSRX ######################################################################## # Documentation diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst index 9c496ebee..b66fd2069 100644 --- a/host/docs/dboards.rst +++ b/host/docs/dboards.rst @@ -32,7 +32,20 @@ The Basic TX and LFTX boards have 1 quadrature subdevice using both antennas. 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. +greater than the Nyquist rate of the DAC. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +DBSRX +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The DBSRX board has 1 quadrature subdevice. + +Receive Antennas: **J3** + +The board has no user selectable antenna setting + +Recieve Gains: + **GC1**, Range: 0-56dB + **GC2**, Range: 0-24dB ^^^^^^^^^^^^^^^^^^^^^^^^^^^ RFX Series @@ -45,7 +58,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-45dB +Recieve Gains: **PGA0**, Range: 0-70dB (except RFX400 range is 0-45dB) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ XCVR 2450 @@ -87,3 +100,44 @@ 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 + +------------------------------------------------------------------------ +Daughterboard Modifications +------------------------------------------------------------------------ + +Sometimes, daughterboards will require modification +to work on certain frequencies or to work with certain hardware. +Modification usually involves moving/removing a SMT component +and burning a new daughterboard id into the eeprom. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +DBSRX +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Due to different clocking capabilities, +the DBSRX will require modifications to operate on a non-USRP1 motherboard. +On a USRP1 motherboard, a divided clock is provided from an FPGA pin +because the standard daughterboard clock lines cannot provided a divided clock. +However, on other USRP motherboards, the divided clock is provided +over the standard daughterboard clock lines. + +**Step 1: Move the clock configuration resistor** + +Remove R193 (which is 10 ohms, 0603 size) and put it on R194, which is empty. +This is made somewhat more complicated by the fact that the silkscreen is not clear in that area. +R193 is on the back, immediately below the large beige connector, J2. +R194 is just below, and to the left of R193. +The silkscreen for R193 is ok, but for R194, +it is upside down, and partially cut off. +If you lose R193, you can use anything from 0 to 10 ohms there. + +**Step 2: Burn a new daughterboard id into the EEPROM** + +With the daughterboard plugged-in, run the following commands: +:: + + cd <prefix>/share/uhd/utils + ./usrp_burn_db_eeprom --id=0x000d --unit=RX --args=<args> --db=<db> + +* <args> are device address arguments (optional if only one USRP is on your machine) +* <db> is the name of the daughterboard slot (optional if the USRP has only one slot) diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index 76b27fd31..bc4ea0e44 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -38,7 +38,7 @@ Run the following commands: ./configure --host=mb make -*The image file will be ./apps/txrx_uhd.bin* +*The image file will be ./usrp2/usrp2_txrx_uhd.bin* ------------------------------------------------------------------------ Load the images onto the SD card @@ -161,7 +161,7 @@ The USRP2 will reply to icmp echo requests. **Monitor the USRP2:** You can read the serial port on the rear of the USRP2 to get debug verbose from the embedded microcontroller. -Use a standard USB to tty-level serial converter at 230400 baud. +Use a standard USB to 3.3v-level serial converter at 230400 baud. The microcontroller prints useful information about IP addresses, MAC addresses, control packets, and fast-path settings. diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 78bb83c66..c48b3dfff 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -161,12 +161,7 @@ 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. - * However, a call to receive may timeout and return zero samples. - * The timeout duration is decided by the underlying transport layer. - * The caller should assume that the call to receive will not return - * immediately when no packets are available to the transport layer, - * and that the timeout duration is reasonably tuned for performance. + * of samples returned have been written into each buffer or timeout. * * When using the full buffer recv mode, the metadata only applies * to the first packet received and written into the recv buffers. diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index bdb4b90a8..76ee24e5f 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -33,6 +33,7 @@ INSTALL(FILES dboard_manager.hpp ### utilities ### + subdev_spec.hpp tune_helper.hpp ### interfaces ### diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp index caf1e6ee6..fc7ea3052 100644 --- a/host/include/uhd/usrp/dboard_iface.hpp +++ b/host/include/uhd/usrp/dboard_iface.hpp @@ -22,6 +22,7 @@ #include <uhd/types/serial.hpp> #include <boost/shared_ptr.hpp> #include <boost/cstdint.hpp> +#include <string> #include <vector> namespace uhd{ namespace usrp{ @@ -65,6 +66,12 @@ public: }; /*! + * Get the motherboard name of the form: usrp1, usrp2... + * \return string representing the motherboard name + */ + virtual std::string get_mboard_name(void) = 0; + + /*! * Write to an aux dac. * * \param unit which unit rx or tx diff --git a/host/include/uhd/usrp/dboard_props.hpp b/host/include/uhd/usrp/dboard_props.hpp index e2c0f9c7b..aab6c31ce 100644 --- a/host/include/uhd/usrp/dboard_props.hpp +++ b/host/include/uhd/usrp/dboard_props.hpp @@ -31,7 +31,6 @@ namespace uhd{ namespace usrp{ DBOARD_PROP_NAME = 'n', //ro, std::string DBOARD_PROP_SUBDEV = 's', //ro, wax::obj DBOARD_PROP_SUBDEV_NAMES = 'S', //ro, prop_names_t - DBOARD_PROP_USED_SUBDEVS = 'u', //ro, prop_names_t DBOARD_PROP_DBOARD_ID = 'i', //rw, dboard_id_t DBOARD_PROP_DBOARD_IFACE = 'f', //ro, dboard_iface::sptr DBOARD_PROP_CODEC = 'c', //ro, wax::obj diff --git a/host/include/uhd/usrp/mboard_props.hpp b/host/include/uhd/usrp/mboard_props.hpp index a432ce50c..0f250f439 100644 --- a/host/include/uhd/usrp/mboard_props.hpp +++ b/host/include/uhd/usrp/mboard_props.hpp @@ -39,6 +39,8 @@ namespace uhd{ namespace usrp{ MBOARD_PROP_RX_DBOARD_NAMES = 'E', //ro, prop_names_t MBOARD_PROP_TX_DBOARD = 'v', //ro, wax::obj MBOARD_PROP_TX_DBOARD_NAMES = 'V', //ro, prop_names_t + MBOARD_PROP_RX_SUBDEV_SPEC = 'r', //rw, subdev_spec_t + MBOARD_PROP_TX_SUBDEV_SPEC = 'R', //rw, subdev_spec_t MBOARD_PROP_CLOCK_CONFIG = 'C', //rw, clock_config_t MBOARD_PROP_TIME_NOW = 't', //rw, time_spec_t MBOARD_PROP_TIME_NEXT_PPS = 'T', //wo, time_spec_t diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index fd0f4596f..10a404059 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -24,6 +24,7 @@ #include <uhd/types/stream_cmd.hpp> #include <uhd/types/clock_config.hpp> #include <uhd/types/tune_result.hpp> +#include <uhd/usrp/subdev_spec.hpp> #include <boost/shared_ptr.hpp> #include <boost/utility.hpp> #include <vector> @@ -119,6 +120,9 @@ public: /******************************************************************* * RX methods ******************************************************************/ + virtual void set_rx_subdev_spec(size_t chan, const uhd::usrp::subdev_spec_t &spec) = 0; + virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(size_t chan) = 0; + virtual void set_rx_rate_all(double rate) = 0; virtual double get_rx_rate_all(void) = 0; @@ -148,6 +152,9 @@ public: /******************************************************************* * TX methods ******************************************************************/ + virtual void set_tx_subdev_spec(size_t chan, const uhd::usrp::subdev_spec_t &spec) = 0; + virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(size_t chan) = 0; + virtual void set_tx_rate_all(double rate) = 0; virtual double get_tx_rate_all(void) = 0; diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index 8fc6d59d9..c2c7505af 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -24,6 +24,7 @@ #include <uhd/types/stream_cmd.hpp> #include <uhd/types/clock_config.hpp> #include <uhd/types/tune_result.hpp> +#include <uhd/usrp/subdev_spec.hpp> #include <boost/shared_ptr.hpp> #include <boost/utility.hpp> #include <vector> @@ -107,6 +108,9 @@ public: /******************************************************************* * RX methods ******************************************************************/ + 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 void set_rx_rate(double rate) = 0; virtual double get_rx_rate(void) = 0; @@ -135,6 +139,9 @@ public: /******************************************************************* * TX methods ******************************************************************/ + 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 void set_tx_rate(double rate) = 0; virtual double get_tx_rate(void) = 0; diff --git a/host/include/uhd/usrp/subdev_spec.hpp b/host/include/uhd/usrp/subdev_spec.hpp new file mode 100644 index 000000000..4d8f03b77 --- /dev/null +++ b/host/include/uhd/usrp/subdev_spec.hpp @@ -0,0 +1,95 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_SUBDEV_SPEC_HPP +#define INCLUDED_UHD_USRP_SUBDEV_SPEC_HPP + +#include <uhd/config.hpp> +#include <vector> +#include <string> + +namespace uhd{ namespace usrp{ + + /*! + * A subdevice specification (daughterboard, subdevice) name pairing. + */ + struct UHD_API subdev_spec_pair_t{ + //! The daughterboard name + std::string db_name; + + //! The subdevice name + std::string sd_name; + + /*! + * Create a new subdevice specification pair from dboard and subdev names. + * \param db_name the name of a daughterboard slot + * \param sd_name the name of a subdevice on that daughterboard + */ + subdev_spec_pair_t( + const std::string &db_name, const std::string &sd_name + ); + }; + + /*! + * A list of (daughterboard name, subdevice name) pairs: + * + * A subdevice specification represents a list of subdevices on a motherboard. + * The subdevices specified may span across multiple daughterboards; + * Hence the need for a subdevice specification over a simple list of strings. + * Typically, the user will pass a RX or TX subdevice specification into the API, + * and the implementation will infer the channel configuration from the specification. + * + * The subdevice specification can be represented as a markup-string. + * The markup-string is a whitespace separated list of dboard:subdev pairs. + * The "dboard:" part is optional on boards with only one daughterboard slot. + * The first pair represents the subdevice for channel zero, + * the second pair represents the subdevice for channel one, and so on. + * + * Examples: + * - Use subdevice AB on daughterboard A (USRP1): "A:AB" + * - Use subdevice A on daughterboard A for channel zero and subdevice A on daughterboard B for channel one (USRP1): "A:A B:A" + * - Use subdevice AB (USRP2): "AB" or ":AB" + * + * An empty subdevice specification can be used to automatically + * select the first subdevice on the first present daughterboard. + */ + class UHD_API subdev_spec_t : public std::vector<subdev_spec_pair_t>{ + public: + + /*! + * Create a subdev specification from a markup string. + * \param markup the markup string + */ + subdev_spec_t(const std::string &markup = ""); + + /*! + * Convert a subdev specification into a pretty print string. + * \return a printable string representing the subdev specification + */ + std::string to_pp_string(void) const; + + /*! + * Convert the subdevice specification into a markup string. + * The markup string contains the delimiter symbols. + * \return a string with delimiter markup + */ + std::string to_string(void) const; + }; + +}} + +#endif /* INCLUDED_UHD_USRP_SUBDEV_SPEC_HPP */ diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index f7feab5a8..ef8e64ce0 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -28,5 +28,6 @@ INSTALL(FILES safe_main.hpp static.hpp thread_priority.hpp + warning.hpp DESTINATION ${INCLUDE_DIR}/uhd/utils ) diff --git a/host/include/uhd/utils/algorithm.hpp b/host/include/uhd/utils/algorithm.hpp index 54bc78494..1b5eacfa9 100644 --- a/host/include/uhd/utils/algorithm.hpp +++ b/host/include/uhd/utils/algorithm.hpp @@ -69,6 +69,31 @@ namespace std{ } /*! + * A wrapper around std::reverse that takes a range instead of an iterator. + * + * The elements are reversed into descending order using the less-than operator. + * + * \param range the range of elements to be reversed + */ + template<typename Range> inline void reverse(Range &range){ + return std::reverse(boost::begin(range), boost::end(range)); + } + + /*! + * A wrapper around std::reverse that takes a range instead of an iterator. + * + * The elements are reversed into descending order using the less-than operator. + * This wrapper reverses the elements non-destructively into a new range. + * Based on the builtin python function reversed(...) + * + * \param range the range of elements to be reversed + * \return a new range with the elements reversed + */ + template<typename Range> inline Range reversed(const Range &range){ + Range srange(range); std::reverse(srange); return srange; + } + + /*! * Is the value found within the elements in this range? * * Uses std::find to search the iterable for an element. diff --git a/host/include/uhd/utils/warning.hpp b/host/include/uhd/utils/warning.hpp new file mode 100644 index 000000000..91d8400ab --- /dev/null +++ b/host/include/uhd/utils/warning.hpp @@ -0,0 +1,34 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_WARNING_HPP +#define INCLUDED_UHD_UTILS_WARNING_HPP + +#include <uhd/config.hpp> +#include <string> + +namespace uhd{ + + /*! + * Print a formatted warning string to stderr. + * \param msg the multiline warning message + */ + UHD_API void print_warning(const std::string &msg); + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_WARNING_HPP */ diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 4899d3dbc..48cfe742e 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -22,6 +22,10 @@ MACRO(LIBUHD_APPEND_SOURCES) LIST(APPEND libuhd_sources ${ARGV}) ENDMACRO(LIBUHD_APPEND_SOURCES) +MACRO(LIBUHD_APPEND_LIBS) + LIST(APPEND libuhd_libs ${ARGV}) +ENDMACRO(LIBUHD_APPEND_LIBS) + MACRO(LIBUHD_PYTHON_GEN_SOURCE pyfile outfile) #ensure that the directory exists for outfile GET_FILENAME_COMPONENT(outfile_dir ${outfile} PATH) @@ -44,80 +48,22 @@ ENDMACRO(LIBUHD_PYTHON_GEN_SOURCE) INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/CMakeLists.txt) INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/transport/CMakeLists.txt) INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/usrp/CMakeLists.txt) -INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/usrp/dboard/CMakeLists.txt) -INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/usrp/usrp2/CMakeLists.txt) - -######################################################################## -# Setup defines for process scheduling -######################################################################## -MESSAGE(STATUS "Configuring priority scheduling...") - -INCLUDE(CheckCXXSourceCompiles) -CHECK_CXX_SOURCE_COMPILES(" - #include <pthread.h> - int main(){ - struct sched_param sp; - pthread_setschedparam(pthread_self(), SCHED_RR, &sp); - return 0; - } - " HAVE_PTHREAD_SETSCHEDPARAM -) - -CHECK_CXX_SOURCE_COMPILES(" - #include <windows.h> - int main(){ - SetThreadPriority(GetCurrentThread(), 0); - SetPriorityClass(GetCurrentProcess(), 0); - return 0; - } - " HAVE_WIN_SETTHREADPRIORITY -) - -IF(HAVE_PTHREAD_SETSCHEDPARAM) - MESSAGE(STATUS " Priority scheduling supported through pthread_setschedparam.") - ADD_DEFINITIONS(-DHAVE_PTHREAD_SETSCHEDPARAM) -ELSEIF(HAVE_WIN_SETTHREADPRIORITY) - MESSAGE(STATUS " Priority scheduling supported through windows SetThreadPriority.") - ADD_DEFINITIONS(-DHAVE_WIN_SETTHREADPRIORITY) -ELSE(HAVE_PTHREAD_SETSCHEDPARAM) - MESSAGE(STATUS " Priority scheduling not supported.") -ENDIF(HAVE_PTHREAD_SETSCHEDPARAM) - -######################################################################## -# Setup defines for module loading -######################################################################## -MESSAGE(STATUS "Configuring module loading...") - -INCLUDE(CheckIncludeFileCXX) -CHECK_INCLUDE_FILE_CXX(dlfcn.h HAVE_DLFCN_H) -CHECK_INCLUDE_FILE_CXX(windows.h HAVE_WINDOWS_H) - -IF(HAVE_DLFCN_H) - MESSAGE(STATUS " Module loading supported through dlopen.") - ADD_DEFINITIONS(-DHAVE_DLFCN_H) -ELSEIF(HAVE_WINDOWS_H) - MESSAGE(STATUS " Module loading supported through LoadLibrary.") - ADD_DEFINITIONS(-DHAVE_WINDOWS_H) -ELSE(HAVE_DLFCN_H) - MESSAGE(STATUS " Module loading not supported.") -ENDIF(HAVE_DLFCN_H) +INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/utils/CMakeLists.txt) ######################################################################## # Append to the list of sources for lib uhd ######################################################################## CONFIGURE_FILE( - ${CMAKE_CURRENT_SOURCE_DIR}/version.cpp.in - ${CMAKE_CURRENT_BINARY_DIR}/version.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/constants.hpp.in + ${CMAKE_CURRENT_BINARY_DIR}/constants.hpp @ONLY) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) LIBUHD_APPEND_SOURCES( + ${CMAKE_CURRENT_BINARY_DIR}/constants.hpp ${CMAKE_CURRENT_SOURCE_DIR}/device.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/gain_group.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/load_modules.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/thread_priority.cpp ${CMAKE_CURRENT_SOURCE_DIR}/types.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/utils.cpp - ${CMAKE_CURRENT_BINARY_DIR}/version.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/version.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wax.cpp ) @@ -125,9 +71,7 @@ LIBUHD_APPEND_SOURCES( # Setup libuhd library ######################################################################## ADD_LIBRARY(uhd SHARED ${libuhd_sources}) - -TARGET_LINK_LIBRARIES(uhd ${Boost_LIBRARIES} ${CMAKE_DL_LIBS}) - +TARGET_LINK_LIBRARIES(uhd ${Boost_LIBRARIES} ${libuhd_libs}) SET_TARGET_PROPERTIES(uhd PROPERTIES DEFINE_SYMBOL "UHD_DLL_EXPORTS") INSTALL(TARGETS uhd diff --git a/host/lib/constants.hpp.in b/host/lib/constants.hpp.in new file mode 100644 index 000000000..295c8f16c --- /dev/null +++ b/host/lib/constants.hpp.in @@ -0,0 +1,28 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_LIBUHD_CONSTANTS_HPP +#define INCLUDED_LIBUHD_CONSTANTS_HPP + +#include <uhd/config.hpp> +#include <string> + +static const std::string UHD_VERSION_STRING = "@CPACK_PACKAGE_VERSION@"; +static const std::string UHD_INSTALL_PREFIX = "@CMAKE_INSTALL_PREFIX@"; +static const std::string UHD_PKG_DATA_DIR = "@PKG_DATA_DIR@"; + +#endif /* INCLUDED_LIBUHD_CONSTANTS_HPP */ diff --git a/host/lib/ic_reg_maps/CMakeLists.txt b/host/lib/ic_reg_maps/CMakeLists.txt index 39f26a5a6..dd188d4c0 100644 --- a/host/lib/ic_reg_maps/CMakeLists.txt +++ b/host/lib/ic_reg_maps/CMakeLists.txt @@ -55,6 +55,11 @@ LIBUHD_PYTHON_GEN_SOURCE( ) LIBUHD_PYTHON_GEN_SOURCE( + ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_max2118_regs.py + ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/max2118_regs.hpp +) + +LIBUHD_PYTHON_GEN_SOURCE( ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_ad9862_regs.py ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/ad9862_regs.hpp ) diff --git a/host/lib/ic_reg_maps/common.py b/host/lib/ic_reg_maps/common.py index 47325a7e3..986093004 100644 --- a/host/lib/ic_reg_maps/common.py +++ b/host/lib/ic_reg_maps/common.py @@ -173,7 +173,7 @@ class mreg: def get_type(self): return 'boost::uint%d_t'%max(2**math.ceil(math.log(self.get_bit_width(), 2)), 8) -def generate(name, regs_tmpl, body_tmpl='', file=__file__): +def generate(name, regs_tmpl, body_tmpl='', file=__file__, append=False): #evaluate the regs template and parse each line into a register regs = list(); mregs = list() for entry in parse_tmpl(regs_tmpl).splitlines(): @@ -193,4 +193,4 @@ def generate(name, regs_tmpl, body_tmpl='', file=__file__): ) #write the generated code to file specified by argv1 - open(sys.argv[1], 'w').write(code) + open(sys.argv[1], 'a' if append else 'w').write(code) diff --git a/host/lib/ic_reg_maps/gen_max2118_regs.py b/host/lib/ic_reg_maps/gen_max2118_regs.py new file mode 100644 index 000000000..506fbaec8 --- /dev/null +++ b/host/lib/ic_reg_maps/gen_max2118_regs.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python +# +# Copyright 2010 Ettus Research LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +######################################################################## +# Template for raw text data describing write registers +# name addr[bit range inclusive] default optional enums +######################################################################## +WRITE_REGS_TMPL="""\ +######################################################################## +## Note: offsets given from perspective of data bits (excludes address) +######################################################################## +## +######################################################################## +## N-Divider MSB (0) Write +######################################################################## +div2 0[7] 0 div4, div2 +n_divider_msb 0[0:6] 3 +######################################################################## +## N-Divider LSB (1) Write +######################################################################## +n_divider_lsb 1[0:7] 0xB6 +~n_divider n_divider_lsb, n_divider_msb +######################################################################## +## R, Charge Pump, and VCO (2) Write +######################################################################## +#set $r_divider_names = ', '.join(map(lambda x: 'div' + str(2**(x+1)), range(0,8))) +r_divider 2[5:7] 1 $r_divider_names +#set $cp_current_bias = ', '.join(map(lambda x: 'i_cp_%dua'%(50*2**x), range(0,4))) +cp_current 2[3:4] 3 $cp_current_bias +osc_band 2[0:2] 5 +######################################################################## +## I/Q Filter DAC (3) Write +######################################################################## +##unused 3[7] 0 +f_dac 3[0:6] 0x7F ## filter tuning dac, depends on m +######################################################################## +## LPF Divider DAC (4) Write +######################################################################## +adl_vco_adc_latch 4[7] 0 disabled, enabled +ade_vco_ade_read 4[6] 0 disabled, enabled +dl_output_drive 4[5] 0 iq_590m_vpp, iq_1_vpp +m_divider 4[0:4] 2 ## filter tuning counter +######################################################################## +## GC2 and Diag (5) Write +######################################################################## +diag 5[5:7] 0 normal, cp_i_source, cp_i_sink, cp_high_z, unused, n_and_filt, r_and_gc2, m_div +gc2 5[0:4] 0x1F ## Step Size: 0-1: 0dB, 2-22: 1dB, 23-31: 0.5dB +""" + +######################################################################## +# Template for raw text data describing read registers +# name addr[bit range inclusive] default optional enums +######################################################################## +READ_REGS_TMPL="""\ +######################################################################## +## Status (0) Read +######################################################################## +pwr 0[6] 0 not_reset, reset +adc 0[2:4] 0 ## VCO tuning voltage, Lock Status +######################################################################## +## I/Q Filter DAC (1) Read +######################################################################## +filter_dac 1[0:6] 0 ## I/Q Filter tuning DAC, current +""" + +######################################################################## +# 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); +} + +void set_reg(boost::uint8_t addr, boost::uint8_t reg){ + 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.get_name() = $(reg.get_type())((reg >> $reg.get_shift()) & $reg.get_mask()); + #end for + break; + #end for + } +} +""" + +if __name__ == '__main__': + import common; common.generate( + name='max2118_write_regs', + regs_tmpl=WRITE_REGS_TMPL, + body_tmpl=BODY_TMPL, + file=__file__, + ) + + import common; common.generate( + name='max2118_read_regs', + regs_tmpl=READ_REGS_TMPL, + body_tmpl=BODY_TMPL, + file=__file__, + append=True, + ) diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index bbbabf6d0..ee989ee2b 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -18,6 +18,7 @@ #include <uhd/transport/udp_zero_copy.hpp> #include <uhd/transport/udp_simple.hpp> //mtu #include <uhd/utils/assert.hpp> +#include <uhd/utils/warning.hpp> #include <boost/cstdint.hpp> #include <boost/asio.hpp> #include <boost/format.hpp> @@ -161,12 +162,11 @@ template<typename Opt> 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) std::cerr << boost::format( - "Warning:\n" - " 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" - ) % name % min_sock_buff_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" + "See the USRP2 application notes on buffer resizing.\n" + ) % name % min_sock_buff_size)); } //only enable on platforms that are happy with the large buffer resize diff --git a/host/lib/transport/zero_copy.cpp b/host/lib/transport/zero_copy.cpp index 42f69d77b..8a1cde694 100644 --- a/host/lib/transport/zero_copy.cpp +++ b/host/lib/transport/zero_copy.cpp @@ -54,12 +54,14 @@ private: //! 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, ()); - _impl->max_buff_size = max_buff_size; + _impl = UHD_PIMPL_MAKE(impl, (max_buff_size)); } phony_zero_copy_recv_if::~phony_zero_copy_recv_if(void){ diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 1cfe84832..5c0fb1f42 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -36,6 +36,7 @@ #include <boost/thread.hpp> #include <stdexcept> #include <complex> +#include <sstream> using namespace uhd; @@ -190,7 +191,7 @@ device_addr_t::device_addr_t(const std::string &args){ std::vector<std::string> key_val; boost::split(key_val, pair, boost::is_any_of(pair_delim)); if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args); - (*this)[trim(key_val[0])] = trim(key_val[1]); + (*this)[trim(key_val.front())] = trim(key_val.back()); } } @@ -198,16 +199,18 @@ std::string device_addr_t::to_pp_string(void) const{ if (this->size() == 0) return "Empty Device Address"; std::stringstream ss; + ss << "Device Address:" << std::endl; BOOST_FOREACH(std::string key, this->keys()){ - ss << boost::format("%s: %s") % key % (*this)[key] << std::endl; + ss << boost::format(" %s: %s") % key % (*this)[key] << std::endl; } return ss.str(); } std::string device_addr_t::to_string(void) const{ std::string args_str; + size_t count = 0; BOOST_FOREACH(const std::string &key, this->keys()){ - args_str += key + pair_delim + (*this)[key] + arg_delim; + args_str += ((count++)? arg_delim : "") + key + pair_delim + (*this)[key]; } return args_str; } diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index 4f0710b20..d951ab412 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -27,5 +27,9 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.hpp ${CMAKE_SOURCE_DIR}/lib/usrp/simple_usrp.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/subdev_spec.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/tune_helper.cpp ) + +INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/dboard/CMakeLists.txt) +INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/CMakeLists.txt) diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index 6093583d3..3e995009e 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -22,6 +22,7 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_rfx.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_xcvr2450.cpp ${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 ) diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp new file mode 100644 index 000000000..03e6b6255 --- /dev/null +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -0,0 +1,610 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +// No RX IO Pins Used + +// RX IO Functions + +#include "max2118_regs.hpp" +#include <uhd/utils/static.hpp> +#include <uhd/utils/assert.hpp> +#include <uhd/utils/algorithm.hpp> +#include <uhd/utils/warning.hpp> +#include <uhd/types/ranges.hpp> +#include <uhd/types/dict.hpp> +#include <uhd/usrp/subdev_props.hpp> +#include <uhd/usrp/dboard_base.hpp> +#include <uhd/usrp/dboard_manager.hpp> +#include <boost/assign/list_of.hpp> +#include <boost/format.hpp> +#include <boost/thread.hpp> +#include <boost/math/special_functions/round.hpp> +#include <utility> +#include <cmath> + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + +/*********************************************************************** + * The DBSRX constants + **********************************************************************/ +static const bool dbsrx_debug = false; + +static const freq_range_t dbsrx_freq_range(0.8e9, 2.4e9); + +static const freq_range_t dbsrx_pfd_freq_range(0.15e6, 2.01e6); + +static const prop_names_t dbsrx_antennas = list_of("J3"); + +static const uhd::dict<std::string, gain_range_t> dbsrx_gain_ranges = map_list_of + ("GC1", gain_range_t(0, 56, 0.5)) + ("GC2", gain_range_t(0, 24, 1)) +; + +/*********************************************************************** + * The DBSRX dboard class + **********************************************************************/ +class dbsrx : public rx_dboard_base{ +public: + dbsrx(ctor_args_t args, boost::uint8_t max2118_addr); + ~dbsrx(void); + + void rx_get(const wax::obj &key, wax::obj &val); + void rx_set(const wax::obj &key, const wax::obj &val); + +private: + double _lo_freq; + float _bandwidth; + uhd::dict<std::string, float> _gains; + max2118_write_regs_t _max2118_write_regs; + max2118_read_regs_t _max2118_read_regs; + boost::uint8_t _max2118_addr; //0x67 or 0x65 depending on which side + + void set_lo_freq(double target_freq); + void set_gain(float gain, const std::string &name); + void set_bandwidth(float 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)); + 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; i<num_bytes; i++){ + regs_vector[1+i] = _max2118_write_regs.get_reg(start_addr+i); + if(dbsrx_debug) std::cerr << boost::format( + "DBSRX: send reg 0x%02x, value 0x%04x, start_addr = 0x%04x, num_bytes %d" + ) % int(start_addr+i) % int(regs_vector[1+i]) % int(start_addr) % num_bytes << std::endl; + } + + //send the data + this->get_iface()->write_i2c( + _max2118_addr, regs_vector + ); + } + } + + void read_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ + static const boost::uint8_t status_addr = 0x0; + start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0x1)); + stop_reg = boost::uint8_t(std::clip(int(stop_reg), 0x0, 0x1)); + + for(boost::uint8_t start_addr=start_reg; start_addr <= stop_reg; start_addr += sizeof(boost::uint32_t)){ + int num_bytes = int(stop_reg - start_addr + 1) > int(sizeof(boost::uint32_t)) ? sizeof(boost::uint32_t) : stop_reg - start_addr + 1; + + //create buffer for register data + byte_vector_t regs_vector(num_bytes); + + //read from i2c + regs_vector = this->get_iface()->read_i2c( + _max2118_addr, num_bytes + ); + + for(boost::uint8_t i=0; i < num_bytes; i++){ + if (i + start_addr >= status_addr){ + _max2118_read_regs.set_reg(i + start_addr, regs_vector[i]); + } + if(dbsrx_debug) std::cerr << boost::format( + "DBSRX: read reg 0x%02x, value 0x%04x, start_addr = 0x%04x, num_bytes %d" + ) % int(start_addr+i) % int(regs_vector[i]) % int(start_addr) % num_bytes << std::endl; + } + } + } + + /*! + * Is the LO locked? + * \return true for locked + */ + bool get_locked(void){ + read_reg(0x0, 0x0); + + //mask and return lock detect + bool locked = 5 >= _max2118_read_regs.adc and _max2118_read_regs.adc >= 2; + + if(dbsrx_debug) std::cerr << boost::format( + "DBSRX: locked %d" + ) % locked << std::endl; + + return locked; + } + +}; + +/*********************************************************************** + * Register the DBSRX dboard + **********************************************************************/ +// FIXME 0x67 is the default i2c address on USRP2 +// need to handle which side for USRP1 with different address +static dboard_base::sptr make_dbsrx(dboard_base::ctor_args_t args){ + return dboard_base::sptr(new dbsrx(args, 0x67)); +} + +//dbid for USRP2 version +UHD_STATIC_BLOCK(reg_dbsrx_dboard){ + //register the factory function for the rx dbid + 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 + dboard_manager::register_dboard(0x0002, &make_dbsrx, "DBSRX"); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +dbsrx::dbsrx(ctor_args_t args, boost::uint8_t max2118_addr) : rx_dboard_base(args){ + //warn user about incorrect DBID on USRP1, requires R193 populated + if (this->get_iface()->get_mboard_name() == "usrp1" and this->get_rx_id() == 0x000D) + uhd::print_warning( + str(boost::format( + "DBSRX: incorrect dbid\n" + "%s expects dbid 0x0002 and R193\n" + "found dbid == %d\n" + "Please see the daughterboard app notes" + ) % (this->get_iface()->get_mboard_name()) % (this->get_rx_id().to_pp_string())) + ); + + //warn user about incorrect DBID on non-USRP1, requires R194 populated + if (this->get_iface()->get_mboard_name() != "usrp1" and this->get_rx_id() == 0x0002) + uhd::print_warning( + str(boost::format( + "DBSRX: incorrect dbid\n" + "%s expects dbid 0x000D and R194\n" + "found dbid == %d\n" + "Please see the daughterboard app notes" + ) % (this->get_iface()->get_mboard_name()) % (this->get_rx_id().to_pp_string())) + ); + + //enable only the clocks we need + 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 + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs + + //set the i2c address for the max2118 + _max2118_addr = max2118_addr; + + //send initial register settings + this->send_reg(0x0, 0x5); + + //set defaults for LO, gains, and filter bandwidth + _bandwidth = 33e6; + set_lo_freq(dbsrx_freq_range.min); + + BOOST_FOREACH(const std::string &name, dbsrx_gain_ranges.keys()){ + set_gain(dbsrx_gain_ranges[name].min, name); + } + + set_bandwidth(33e6); // default bandwidth from datasheet +} + +dbsrx::~dbsrx(void){ +} + + +/*********************************************************************** + * Tuning + **********************************************************************/ +void dbsrx::set_lo_freq(double target_freq){ + target_freq = std::clip(target_freq, dbsrx_freq_range.min, dbsrx_freq_range.max); + + 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<double> clock_rates = this->get_iface()->get_clock_rates(dboard_iface::UNIT_RX); + BOOST_FOREACH(ref_clock, std::reversed(std::sorted(clock_rates))){ + if (ref_clock > 27.0e6) continue; + + //choose m_divider such that filter tuning constraint is met + m = 31; + while ((ref_clock/m < 1e6 or ref_clock/m > 2.5e6) and m > 0){ m--; } + + 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; + + if (m >= 32) continue; + + //choose R + for(r = 0; r <= 6; r += 1) { + //compute divider from setting + R = 1 << (r+1); + if (dbsrx_debug) std::cerr << boost::format("DBSRX R:%d\n") % R << std::endl; + + //compute PFD compare frequency = ref_clock/R + pfd_freq = ref_clock / R; + + //constrain the PFD frequency to specified range + if ((pfd_freq < dbsrx_pfd_freq_range.min) or (pfd_freq > dbsrx_pfd_freq_range.max)) continue; + + //compute N + N = int(std::floor(target_freq/pfd_freq)); + + //constrain N to specified range + if ((N < 256) or (N > 32768)) continue; + + goto done_loop; + } + } + + //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: + + 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; + + //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; + + //compute resulting output frequency + actual_freq = pfd_freq * N; + + //apply ref_clock, R, and N settings + this->get_iface()->set_clock_rate(dboard_iface::UNIT_RX, ref_clock); + ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX); + _max2118_write_regs.m_divider = m; + _max2118_write_regs.r_divider = (max2118_write_regs_t::r_divider_t) r; + _max2118_write_regs.set_n_divider(N); + _max2118_write_regs.ade_vco_ade_read = max2118_write_regs_t::ADE_VCO_ADE_READ_ENABLED; + + //compute prescaler variables + int scaler = actual_freq > 1125e6 ? 2 : 4; + _max2118_write_regs.div2 = scaler == 4 ? max2118_write_regs_t::DIV2_DIV4 : max2118_write_regs_t::DIV2_DIV2; + + if(dbsrx_debug) std::cerr << boost::format( + "DBSRX: scaler %d, actual_freq %f MHz, register bit: %d" + ) % scaler % (actual_freq/1e6) % int(_max2118_write_regs.div2) << std::endl; + + //compute vco frequency and select vco + double vco_freq = actual_freq * scaler; + if (vco_freq < 2433e6) + _max2118_write_regs.osc_band = 0; + else if (vco_freq < 2711e6) + _max2118_write_regs.osc_band = 1; + else if (vco_freq < 3025e6) + _max2118_write_regs.osc_band = 2; + else if (vco_freq < 3341e6) + _max2118_write_regs.osc_band = 3; + else if (vco_freq < 3727e6) + _max2118_write_regs.osc_band = 4; + else if (vco_freq < 4143e6) + _max2118_write_regs.osc_band = 5; + else if (vco_freq < 4493e6) + _max2118_write_regs.osc_band = 6; + else + _max2118_write_regs.osc_band = 7; + + //send settings over i2c + send_reg(0x0, 0x4); + + //check vtune for lock condition + read_reg(0x0, 0x0); + + if(dbsrx_debug) std::cerr << boost::format( + "DBSRX: initial guess for vco %d, vtune adc %d" + ) % int(_max2118_write_regs.osc_band) % int(_max2118_read_regs.adc) << std::endl; + + //if we are out of lock for chosen vco, change vco + while ((_max2118_read_regs.adc == 0) or (_max2118_read_regs.adc == 7)){ + + //vtune is too low, try lower frequency vco + if (_max2118_read_regs.adc == 0){ + if (_max2118_write_regs.osc_band == 0){ + uhd::print_warning( + str(boost::format( + "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); + } + if (_max2118_write_regs.osc_band <= 0) break; + _max2118_write_regs.osc_band -= 1; + } + + //vtune is too high, try higher frequency vco + if (_max2118_read_regs.adc == 7){ + if (_max2118_write_regs.osc_band == 7){ + uhd::print_warning( + str(boost::format( + "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); + } + if (_max2118_write_regs.osc_band >= 7) break; + _max2118_write_regs.osc_band += 1; + } + + if(dbsrx_debug) std::cerr << boost::format( + "DBSRX: trying vco %d, vtune adc %d" + ) % int(_max2118_write_regs.osc_band) % int(_max2118_read_regs.adc) << std::endl; + + //update vco selection and check vtune + send_reg(0x2, 0x2); + read_reg(0x0, 0x0); + } + + if(dbsrx_debug) std::cerr << boost::format( + "DBSRX: final vco %d, vtune adc %d" + ) % int(_max2118_write_regs.osc_band) % int(_max2118_read_regs.adc) << std::endl; + + //select charge pump bias current + if (_max2118_read_regs.adc <= 2) _max2118_write_regs.cp_current = max2118_write_regs_t::CP_CURRENT_I_CP_100UA; + else if (_max2118_read_regs.adc >= 5) _max2118_write_regs.cp_current = max2118_write_regs_t::CP_CURRENT_I_CP_400UA; + else _max2118_write_regs.cp_current = max2118_write_regs_t::CP_CURRENT_I_CP_200UA; + + //update charge pump bias current setting + send_reg(0x2, 0x2); + + //compute actual tuned frequency + _lo_freq = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX) / std::pow(2.0,(1 + _max2118_write_regs.r_divider)) * _max2118_write_regs.get_n_divider(); + + //debug output of calculated variables + if (dbsrx_debug) std::cerr + << boost::format("DBSRX tune:\n") + << boost::format(" VCO=%d, CP=%d, PFD Freq=%fMHz\n") % int(_max2118_write_regs.osc_band) % _max2118_write_regs.cp_current % (pfd_freq/1e6) + << boost::format(" R=%d, N=%f, scaler=%d, div2=%d\n") % R % N % scaler % int(_max2118_write_regs.div2) + << 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) + << std::endl; + + if (update_filter_settings) set_bandwidth(_bandwidth); + get_locked(); +} + +/*********************************************************************** + * 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 + */ +static int gain_to_gc2_vga_reg(float &gain){ + int reg = 0; + gain = std::clip<float>(float(boost::math::iround(gain)), dbsrx_gain_ranges["GC2"].min, dbsrx_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 (dbsrx_debug) std::cerr << boost::format( + "DBSRX GC2 Gain: %f dB, reg: %d" + ) % gain % reg << std::endl; + + return reg; +} + +/*! + * Convert a requested gain for the GC1 rf vga 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 + */ +static float gain_to_gc1_rfvga_dac(float &gain){ + //clip the input + gain = std::clip<float>(gain, dbsrx_gain_ranges["GC1"].min, dbsrx_gain_ranges["GC1"].max); + + //voltage level constants + static const float max_volts = float(1.2), min_volts = float(2.7); + static const float slope = (max_volts-min_volts)/dbsrx_gain_ranges["GC1"].max; + + //calculate the voltage for the aux dac + float dac_volts = gain*slope + min_volts; + + if (dbsrx_debug) std::cerr << boost::format( + "DBSRX GC1 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 dbsrx::set_gain(float gain, const std::string &name){ + assert_has(dbsrx_gain_ranges.keys(), name, "dbsrx gain name"); + if (name == "GC2"){ + _max2118_write_regs.gc2 = gain_to_gc2_vga_reg(gain); + send_reg(0x5, 0x5); + } + else if(name == "GC1"){ + //write the new voltage to the aux dac + 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; +} + +/*********************************************************************** + * Bandwidth Handling + **********************************************************************/ +void dbsrx::set_bandwidth(float bandwidth){ + //clip the input + bandwidth = std::clip<float>(bandwidth, 4e6, 33e6); + + double ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX); + + //NOTE: _max2118_write_regs.m_divider set in set_lo_freq + + //compute f_dac setting + _max2118_write_regs.f_dac = std::clip<int>(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)); + + if (dbsrx_debug) std::cerr << boost::format( + "DBSRX Filter Bandwidth: %f MHz, m: %d, f_dac: %d\n" + ) % (_bandwidth/1e6) % int(_max2118_write_regs.m_divider) % int(_max2118_write_regs.f_dac) << std::endl; + + this->send_reg(0x3, 0x4); +} + +/*********************************************************************** + * RX Get and Set + **********************************************************************/ +void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as<subdev_prop_t>()){ + 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(), name, "dbsrx gain name"); + val = _gains[name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(dbsrx_gain_ranges.keys(), name, "dbsrx gain name"); + val = dbsrx_gain_ranges[name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(dbsrx_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = _lo_freq; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = dbsrx_freq_range; + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string("J3"); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = dbsrx_antennas; + return; + +/* + case SUBDEV_PROP_QUADRATURE: + val = true; + return; + + case SUBDEV_PROP_IQ_SWAPPED: + val = false; + return; + + case SUBDEV_PROP_SPECTRUM_INVERTED: + val = false; + 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 = this->get_locked(); + return; + +/* + case SUBDEV_PROP_RSSI: + val = this->get_rssi(); + return; +*/ + + case SUBDEV_PROP_BANDWIDTH: + val = _bandwidth; + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as<subdev_prop_t>()){ + + case SUBDEV_PROP_FREQ: + this->set_lo_freq(val.as<double>()); + return; + + case SUBDEV_PROP_GAIN: + this->set_gain(val.as<float>(), name); + return; + + case SUBDEV_PROP_BANDWIDTH: + this->set_bandwidth(val.as<float>()); + 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 914ca5e19..b6b44199a 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -43,6 +43,7 @@ #include <uhd/utils/assert.hpp> #include <uhd/utils/static.hpp> #include <uhd/utils/algorithm.hpp> +#include <uhd/usrp/dboard_id.hpp> #include <uhd/usrp/dboard_base.hpp> #include <uhd/usrp/dboard_manager.hpp> #include <boost/assign/list_of.hpp> @@ -65,6 +66,10 @@ static const prop_names_t rfx_rx_antennas = list_of("TX/RX")("RX2"); static const uhd::dict<std::string, gain_range_t> rfx_tx_gain_ranges; //empty static const uhd::dict<std::string, gain_range_t> rfx_rx_gain_ranges = map_list_of + ("PGA0", gain_range_t(0, 70, float(0.022))) +; + +static const uhd::dict<std::string, gain_range_t> rfx400_rx_gain_ranges = map_list_of ("PGA0", gain_range_t(0, 45, float(0.022))) ; @@ -88,6 +93,7 @@ public: private: freq_range_t _freq_range; + uhd::dict<std::string, gain_range_t> _rx_gain_ranges; uhd::dict<dboard_iface::unit_t, bool> _div2; double _rx_lo_freq, _tx_lo_freq; std::string _rx_ant; @@ -166,6 +172,14 @@ rfx_xcvr::rfx_xcvr( _div2[dboard_iface::UNIT_RX] = rx_div2; _div2[dboard_iface::UNIT_TX] = tx_div2; + if(this->get_rx_id() == 0x0024) { //RFX400 + _rx_gain_ranges = rfx400_rx_gain_ranges; + } + else { + _rx_gain_ranges = rfx_rx_gain_ranges; + } + + //enable the clocks that we need this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); @@ -193,8 +207,8 @@ rfx_xcvr::rfx_xcvr( set_tx_lo_freq((_freq_range.min + _freq_range.max)/2.0); set_rx_ant("RX2"); - BOOST_FOREACH(const std::string &name, rfx_rx_gain_ranges.keys()){ - set_rx_gain(rfx_rx_gain_ranges[name].min, name); + BOOST_FOREACH(const std::string &name, _rx_gain_ranges.keys()){ + set_rx_gain(_rx_gain_ranges[name].min, name); } } @@ -227,10 +241,10 @@ void rfx_xcvr::set_tx_ant(const std::string &ant){ /*********************************************************************** * Gain Handling **********************************************************************/ -static float rx_pga0_gain_to_dac_volts(float &gain){ +static float rx_pga0_gain_to_dac_volts(float &gain, float range){ //voltage level constants (negative slope) static const float max_volts = float(.2), min_volts = float(1.2); - static const float slope = (max_volts-min_volts)/45; + static const float slope = (max_volts-min_volts)/(range); //calculate the voltage for the aux dac float dac_volts = std::clip<float>(gain*slope + min_volts, max_volts, min_volts); @@ -247,9 +261,10 @@ void rfx_xcvr::set_tx_gain(float, const std::string &name){ } void rfx_xcvr::set_rx_gain(float gain, const std::string &name){ - assert_has(rfx_rx_gain_ranges.keys(), name, "rfx rx gain name"); + assert_has(_rx_gain_ranges.keys(), name, "rfx rx gain name"); if(name == "PGA0"){ - float dac_volts = rx_pga0_gain_to_dac_volts(gain); + float dac_volts = rx_pga0_gain_to_dac_volts(gain, + (_rx_gain_ranges["PGA0"].max - _rx_gain_ranges["PGA0"].min)); _rx_gains[name] = gain; //write the new voltage to the aux dac @@ -402,12 +417,12 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_GAIN_RANGE: - assert_has(rfx_rx_gain_ranges.keys(), name, "rfx rx gain name"); - val = rfx_rx_gain_ranges[name]; + assert_has(_rx_gain_ranges.keys(), name, "rfx rx gain name"); + val = _rx_gain_ranges[name]; return; case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(rfx_rx_gain_ranges.keys()); + val = prop_names_t(_rx_gain_ranges.keys()); return; case SUBDEV_PROP_FREQ: diff --git a/host/lib/usrp/mimo_usrp.cpp b/host/lib/usrp/mimo_usrp.cpp index 6b9318c39..e78d38fc0 100644 --- a/host/lib/usrp/mimo_usrp.cpp +++ b/host/lib/usrp/mimo_usrp.cpp @@ -20,6 +20,7 @@ #include <uhd/utils/assert.hpp> #include <uhd/utils/gain_group.hpp> #include <uhd/utils/algorithm.hpp> +#include <uhd/utils/warning.hpp> #include <uhd/usrp/subdev_props.hpp> #include <uhd/usrp/mboard_props.hpp> #include <uhd/usrp/device_props.hpp> @@ -47,31 +48,12 @@ public: mimo_usrp_impl(const device_addr_t &addr){ _dev = device::make(addr); - //extract each mboard and its sub-devices - BOOST_FOREACH(const std::string &name, (*_dev)[DEVICE_PROP_MBOARD_NAMES].as<prop_names_t>()){ - _mboards.push_back((*_dev)[named_prop_t(DEVICE_PROP_MBOARD, name)]); - _rx_dsps.push_back(_mboards.back()[MBOARD_PROP_RX_DSP]); - _tx_dsps.push_back(_mboards.back()[MBOARD_PROP_TX_DSP]); - - //extract rx subdevice - _rx_dboards.push_back(_mboards.back()[MBOARD_PROP_RX_DBOARD]); - std::string rx_subdev_in_use = _rx_dboards.back()[DBOARD_PROP_USED_SUBDEVS].as<prop_names_t>().at(0); - _rx_subdevs.push_back(_rx_dboards.back()[named_prop_t(DBOARD_PROP_SUBDEV, rx_subdev_in_use)]); - _rx_gain_groups.push_back(_rx_dboards.back()[named_prop_t(DBOARD_PROP_GAIN_GROUP, rx_subdev_in_use)].as<gain_group::sptr>()); - - //extract tx subdevice - _tx_dboards.push_back(_mboards.back()[MBOARD_PROP_TX_DBOARD]); - std::string tx_subdev_in_use = _tx_dboards.back()[DBOARD_PROP_USED_SUBDEVS].as<prop_names_t>().at(0); - _tx_subdevs.push_back(_tx_dboards.back()[named_prop_t(DBOARD_PROP_SUBDEV, tx_subdev_in_use)]); - _tx_gain_groups.push_back(_tx_dboards.back()[named_prop_t(DBOARD_PROP_GAIN_GROUP, tx_subdev_in_use)].as<gain_group::sptr>()); - } - //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; - BOOST_FOREACH(wax::obj mboard, _mboards){ - mboard[MBOARD_PROP_CLOCK_CONFIG] = clock_config; + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _mboard(chan)[MBOARD_PROP_CLOCK_CONFIG] = clock_config; } } @@ -90,7 +72,7 @@ public: ) % (*_dev)[DEVICE_PROP_NAME].as<std::string>() ); - for (size_t i = 0; i < get_num_channels(); i++){ + for (size_t chan = 0; chan < get_num_channels(); chan++){ buff += str(boost::format( " Channel: %u\n" " Mboard: %s\n" @@ -100,21 +82,21 @@ public: " TX DSP: %s\n" " TX Dboard: %s\n" " TX Subdev: %s\n" - ) % i - % _mboards.at(i)[MBOARD_PROP_NAME].as<std::string>() - % _rx_dsps.at(i)[DSP_PROP_NAME].as<std::string>() - % _rx_dboards.at(i)[DBOARD_PROP_NAME].as<std::string>() - % _rx_subdevs.at(i)[SUBDEV_PROP_NAME].as<std::string>() - % _tx_dsps.at(i)[DSP_PROP_NAME].as<std::string>() - % _tx_dboards.at(i)[DBOARD_PROP_NAME].as<std::string>() - % _tx_subdevs.at(i)[SUBDEV_PROP_NAME].as<std::string>() + ) % chan + % _mboard(chan)[MBOARD_PROP_NAME].as<std::string>() + % _rx_dsp(chan)[DSP_PROP_NAME].as<std::string>() + % _rx_dboard(chan)[DBOARD_PROP_NAME].as<std::string>() + % _rx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>() + % _tx_dsp(chan)[DSP_PROP_NAME].as<std::string>() + % _tx_dboard(chan)[DBOARD_PROP_NAME].as<std::string>() + % _tx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>() ); } return buff; } size_t get_num_channels(void){ - return _mboards.size(); + return (*_dev)[DEVICE_PROP_MBOARD_NAMES].as<prop_names_t>().size(); } /******************************************************************* @@ -122,12 +104,12 @@ public: ******************************************************************/ time_spec_t get_time_now(void){ //the time on the first mboard better be the same on all - return _mboards.front()[MBOARD_PROP_TIME_NOW].as<time_spec_t>(); + return _mboard(0)[MBOARD_PROP_TIME_NOW].as<time_spec_t>(); } void set_time_next_pps(const time_spec_t &time_spec){ - BOOST_FOREACH(wax::obj mboard, _mboards){ - mboard[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _mboard(chan)[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; } } @@ -149,33 +131,42 @@ public: 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 i = 1; i < get_num_channels(); i++){ - time_spec_t time_0 = _mboards.front()[MBOARD_PROP_TIME_NOW].as<time_spec_t>(); - time_spec_t time_i = _mboards.at(i)[MBOARD_PROP_TIME_NOW].as<time_spec_t>(); + 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_spec_t time_i = _mboard(chan)[MBOARD_PROP_TIME_NOW].as<time_spec_t>(); if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big - std::cerr << boost::format( - "Error: time deviation between board %d and board 0.\n" - " Board 0 time is %f seconds.\n" - " Board %d time is %f seconds.\n" - ) % i % time_0.get_real_secs() % i % time_i.get_real_secs() << std::endl; + 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){ - BOOST_FOREACH(wax::obj mboard, _mboards){ - mboard[MBOARD_PROP_STREAM_CMD] = 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<subdev_spec_t>(); + } + void set_rx_rate_all(double rate){ std::vector<double> _actual_rates; - BOOST_FOREACH(wax::obj rx_dsp, _rx_dsps){ - rx_dsp[DSP_PROP_HOST_RATE] = rate; - _actual_rates.push_back(rx_dsp[DSP_PROP_HOST_RATE].as<double>()); + 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<double>()); } _rx_rate = _actual_rates.front(); if (std::count(_actual_rates, _rx_rate) != _actual_rates.size()) throw std::runtime_error( @@ -188,61 +179,70 @@ public: } tune_result_t set_rx_freq(size_t chan, double target_freq){ - return tune_rx_subdev_and_dsp(_rx_subdevs.at(chan), _rx_dsps.at(chan), target_freq); + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), target_freq); } tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){ - return tune_rx_subdev_and_dsp(_rx_subdevs.at(chan), _rx_dsps.at(chan), target_freq, lo_off); + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), target_freq, lo_off); } double get_rx_freq(size_t chan){ - return derive_freq_from_rx_subdev_and_dsp(_rx_subdevs.at(chan), _rx_dsps.at(chan)); + return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan)); } freq_range_t get_rx_freq_range(size_t chan){ - return add_dsp_shift(_rx_subdevs.at(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsps.at(chan)); + return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsp(chan)); } void set_rx_gain(size_t chan, float gain){ - _rx_gain_groups.at(chan)->set_value(gain); + return _rx_gain_group(chan)->set_value(gain); } float get_rx_gain(size_t chan){ - return _rx_gain_groups.at(chan)->get_value(); + return _rx_gain_group(chan)->get_value(); } gain_range_t get_rx_gain_range(size_t chan){ - return _rx_gain_groups.at(chan)->get_range(); + return _rx_gain_group(chan)->get_range(); } void set_rx_antenna(size_t chan, const std::string &ant){ - _rx_subdevs.at(chan)[SUBDEV_PROP_ANTENNA] = ant; + _rx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; } std::string get_rx_antenna(size_t chan){ - return _rx_subdevs.at(chan)[SUBDEV_PROP_ANTENNA].as<std::string>(); + return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA].as<std::string>(); } std::vector<std::string> get_rx_antennas(size_t chan){ - return _rx_subdevs.at(chan)[SUBDEV_PROP_ANTENNA_NAMES].as<prop_names_t>(); + return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as<prop_names_t>(); } bool get_rx_lo_locked(size_t chan){ - return _rx_subdevs.at(chan)[SUBDEV_PROP_LO_LOCKED].as<bool>(); + return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as<bool>(); } float read_rssi(size_t chan){ - return _rx_subdevs.at(chan)[SUBDEV_PROP_RSSI].as<float>(); + return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as<float>(); } /******************************************************************* * 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<subdev_spec_t>(); + } + void set_tx_rate_all(double rate){ std::vector<double> _actual_rates; - BOOST_FOREACH(wax::obj tx_dsp, _tx_dsps){ - tx_dsp[DSP_PROP_HOST_RATE] = rate; - _actual_rates.push_back(tx_dsp[DSP_PROP_HOST_RATE].as<double>()); + 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<double>()); } _tx_rate = _actual_rates.front(); if (std::count(_actual_rates, _tx_rate) != _actual_rates.size()) throw std::runtime_error( @@ -255,60 +255,85 @@ public: } tune_result_t set_tx_freq(size_t chan, double target_freq){ - return tune_tx_subdev_and_dsp(_tx_subdevs.at(chan), _tx_dsps.at(chan), target_freq); + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), target_freq); } tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){ - return tune_tx_subdev_and_dsp(_tx_subdevs.at(chan), _tx_dsps.at(chan), target_freq, lo_off); + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), target_freq, lo_off); } double get_tx_freq(size_t chan){ - return derive_freq_from_tx_subdev_and_dsp(_tx_subdevs.at(chan), _tx_dsps.at(chan)); + return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan)); } freq_range_t get_tx_freq_range(size_t chan){ - return add_dsp_shift(_tx_subdevs.at(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsps.at(chan)); + return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsp(chan)); } void set_tx_gain(size_t chan, float gain){ - _tx_gain_groups.at(chan)->set_value(gain); + return _tx_gain_group(chan)->set_value(gain); } float get_tx_gain(size_t chan){ - return _tx_gain_groups.at(chan)->get_value(); + return _tx_gain_group(chan)->get_value(); } gain_range_t get_tx_gain_range(size_t chan){ - return _tx_gain_groups.at(chan)->get_range(); + return _tx_gain_group(chan)->get_range(); } void set_tx_antenna(size_t chan, const std::string &ant){ - _tx_subdevs.at(chan)[SUBDEV_PROP_ANTENNA] = ant; + _tx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; } std::string get_tx_antenna(size_t chan){ - return _tx_subdevs.at(chan)[SUBDEV_PROP_ANTENNA].as<std::string>(); + return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA].as<std::string>(); } std::vector<std::string> get_tx_antennas(size_t chan){ - return _tx_subdevs.at(chan)[SUBDEV_PROP_ANTENNA_NAMES].as<prop_names_t>(); + return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as<prop_names_t>(); } bool get_tx_lo_locked(size_t chan){ - return _tx_subdevs.at(chan)[SUBDEV_PROP_LO_LOCKED].as<bool>(); + return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as<bool>(); } private: device::sptr _dev; - std::vector<wax::obj> _mboards; - std::vector<wax::obj> _rx_dsps; - std::vector<wax::obj> _tx_dsps; - std::vector<wax::obj> _rx_dboards; - std::vector<wax::obj> _tx_dboards; - std::vector<wax::obj> _rx_subdevs; - std::vector<wax::obj> _tx_subdevs; - std::vector<gain_group::sptr> _rx_gain_groups; - std::vector<gain_group::sptr> _tx_gain_groups; + wax::obj _mboard(size_t chan){ + prop_names_t names = (*_dev)[DEVICE_PROP_MBOARD_NAMES].as<prop_names_t>(); + 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<subdev_spec_t>().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<subdev_spec_t>().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<subdev_spec_t>().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<subdev_spec_t>().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<subdev_spec_t>().front().sd_name; + return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>(); + } + gain_group::sptr _tx_gain_group(size_t chan){ + std::string sd_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name; + return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>(); + } //shadows double _rx_rate, _tx_rate; diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp index a8c20c439..5b4a58805 100644 --- a/host/lib/usrp/simple_usrp.cpp +++ b/host/lib/usrp/simple_usrp.cpp @@ -27,6 +27,7 @@ #include <boost/foreach.hpp> #include <boost/format.hpp> #include <stdexcept> +#include <iostream> using namespace uhd; using namespace uhd::usrp; @@ -43,21 +44,6 @@ class simple_usrp_impl : public simple_usrp{ public: simple_usrp_impl(const device_addr_t &addr){ _dev = device::make(addr); - _mboard = (*_dev)[DEVICE_PROP_MBOARD]; - _rx_dsp = _mboard[MBOARD_PROP_RX_DSP]; - _tx_dsp = _mboard[MBOARD_PROP_TX_DSP]; - - //extract rx subdevice - _rx_dboard = _mboard[MBOARD_PROP_RX_DBOARD]; - std::string rx_subdev_in_use = _rx_dboard[DBOARD_PROP_USED_SUBDEVS].as<prop_names_t>().at(0); - _rx_subdev = _rx_dboard[named_prop_t(DBOARD_PROP_SUBDEV, rx_subdev_in_use)]; - _rx_gain_group = _rx_dboard[named_prop_t(DBOARD_PROP_GAIN_GROUP, rx_subdev_in_use)].as<gain_group::sptr>(); - - //extract tx subdevice - _tx_dboard = _mboard[MBOARD_PROP_TX_DBOARD]; - std::string tx_subdev_in_use = _tx_dboard[DBOARD_PROP_USED_SUBDEVS].as<prop_names_t>().at(0); - _tx_subdev = _tx_dboard[named_prop_t(DBOARD_PROP_SUBDEV, tx_subdev_in_use)]; - _tx_gain_group = _tx_dboard[named_prop_t(DBOARD_PROP_GAIN_GROUP, tx_subdev_in_use)].as<gain_group::sptr>(); } ~simple_usrp_impl(void){ @@ -81,13 +67,13 @@ public: " TX Subdev: %s\n" ) % (*_dev)[DEVICE_PROP_NAME].as<std::string>() - % _mboard[MBOARD_PROP_NAME].as<std::string>() - % _rx_dsp[DSP_PROP_NAME].as<std::string>() - % _rx_dboard[DBOARD_PROP_NAME].as<std::string>() - % _rx_subdev[SUBDEV_PROP_NAME].as<std::string>() - % _tx_dsp[DSP_PROP_NAME].as<std::string>() - % _tx_dboard[DBOARD_PROP_NAME].as<std::string>() - % _tx_subdev[SUBDEV_PROP_NAME].as<std::string>() + % _mboard()[MBOARD_PROP_NAME].as<std::string>() + % _rx_dsp()[DSP_PROP_NAME].as<std::string>() + % _rx_dboard()[DBOARD_PROP_NAME].as<std::string>() + % _rx_subdev()[SUBDEV_PROP_NAME].as<std::string>() + % _tx_dsp()[DSP_PROP_NAME].as<std::string>() + % _tx_dboard()[DBOARD_PROP_NAME].as<std::string>() + % _tx_subdev()[SUBDEV_PROP_NAME].as<std::string>() ); } @@ -95,137 +81,155 @@ public: * Misc ******************************************************************/ time_spec_t get_time_now(void){ - return _mboard[MBOARD_PROP_TIME_NOW].as<time_spec_t>(); + return _mboard()[MBOARD_PROP_TIME_NOW].as<time_spec_t>(); } void set_time_now(const time_spec_t &time_spec){ - _mboard[MBOARD_PROP_TIME_NOW] = time_spec; + _mboard()[MBOARD_PROP_TIME_NOW] = time_spec; } void set_time_next_pps(const time_spec_t &time_spec){ - _mboard[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; + _mboard()[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; } void issue_stream_cmd(const stream_cmd_t &stream_cmd){ - _mboard[MBOARD_PROP_STREAM_CMD] = stream_cmd; + _mboard()[MBOARD_PROP_STREAM_CMD] = stream_cmd; } void set_clock_config(const clock_config_t &clock_config){ - _mboard[MBOARD_PROP_CLOCK_CONFIG] = clock_config; + _mboard()[MBOARD_PROP_CLOCK_CONFIG] = clock_config; } /******************************************************************* * RX methods ******************************************************************/ + void set_rx_subdev_spec(const subdev_spec_t &spec){ + _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC] = spec; + std::cout << "RX " << _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>().to_pp_string() << std::endl; + } + + subdev_spec_t get_rx_subdev_spec(void){ + return _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>(); + } + void set_rx_rate(double rate){ - _rx_dsp[DSP_PROP_HOST_RATE] = rate; + _rx_dsp()[DSP_PROP_HOST_RATE] = rate; } double get_rx_rate(void){ - return _rx_dsp[DSP_PROP_HOST_RATE].as<double>(); + return _rx_dsp()[DSP_PROP_HOST_RATE].as<double>(); } tune_result_t set_rx_freq(double target_freq){ - return tune_rx_subdev_and_dsp(_rx_subdev, _rx_dsp, target_freq); + return tune_rx_subdev_and_dsp(_rx_subdev(), _rx_dsp(), target_freq); } tune_result_t set_rx_freq(double target_freq, double lo_off){ - return tune_rx_subdev_and_dsp(_rx_subdev, _rx_dsp, target_freq, lo_off); + return tune_rx_subdev_and_dsp(_rx_subdev(), _rx_dsp(), target_freq, lo_off); } double get_rx_freq(void){ - return derive_freq_from_rx_subdev_and_dsp(_rx_subdev, _rx_dsp); + return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(), _rx_dsp()); } freq_range_t get_rx_freq_range(void){ - return add_dsp_shift(_rx_subdev[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsp); + return add_dsp_shift(_rx_subdev()[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsp()); } void set_rx_gain(float gain){ - _rx_gain_group->set_value(gain); + return _rx_gain_group()->set_value(gain); } float get_rx_gain(void){ - return _rx_gain_group->get_value(); + return _rx_gain_group()->get_value(); } gain_range_t get_rx_gain_range(void){ - return _rx_gain_group->get_range(); + return _rx_gain_group()->get_range(); } void set_rx_antenna(const std::string &ant){ - _rx_subdev[SUBDEV_PROP_ANTENNA] = ant; + _rx_subdev()[SUBDEV_PROP_ANTENNA] = ant; } std::string get_rx_antenna(void){ - return _rx_subdev[SUBDEV_PROP_ANTENNA].as<std::string>(); + return _rx_subdev()[SUBDEV_PROP_ANTENNA].as<std::string>(); } std::vector<std::string> get_rx_antennas(void){ - return _rx_subdev[SUBDEV_PROP_ANTENNA_NAMES].as<prop_names_t>(); + return _rx_subdev()[SUBDEV_PROP_ANTENNA_NAMES].as<prop_names_t>(); } bool get_rx_lo_locked(void){ - return _rx_subdev[SUBDEV_PROP_LO_LOCKED].as<bool>(); + return _rx_subdev()[SUBDEV_PROP_LO_LOCKED].as<bool>(); } float read_rssi(void){ - return _rx_subdev[SUBDEV_PROP_RSSI].as<float>(); + return _rx_subdev()[SUBDEV_PROP_RSSI].as<float>(); } /******************************************************************* * TX methods ******************************************************************/ + void set_tx_subdev_spec(const subdev_spec_t &spec){ + _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC] = spec; + std::cout << "TX " << _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>().to_pp_string() << std::endl; + } + + subdev_spec_t get_tx_subdev_spec(void){ + return _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>(); + } + void set_tx_rate(double rate){ - _tx_dsp[DSP_PROP_HOST_RATE] = rate; + _tx_dsp()[DSP_PROP_HOST_RATE] = rate; } double get_tx_rate(void){ - return _tx_dsp[DSP_PROP_HOST_RATE].as<double>(); + return _tx_dsp()[DSP_PROP_HOST_RATE].as<double>(); } tune_result_t set_tx_freq(double target_freq){ - return tune_tx_subdev_and_dsp(_tx_subdev, _tx_dsp, target_freq); + return tune_tx_subdev_and_dsp(_tx_subdev(), _tx_dsp(), target_freq); } tune_result_t set_tx_freq(double target_freq, double lo_off){ - return tune_tx_subdev_and_dsp(_tx_subdev, _tx_dsp, target_freq, lo_off); + return tune_tx_subdev_and_dsp(_tx_subdev(), _tx_dsp(), target_freq, lo_off); } double get_tx_freq(void){ - return derive_freq_from_tx_subdev_and_dsp(_tx_subdev, _tx_dsp); + return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(), _tx_dsp()); } freq_range_t get_tx_freq_range(void){ - return add_dsp_shift(_tx_subdev[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsp); + return add_dsp_shift(_tx_subdev()[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsp()); } void set_tx_gain(float gain){ - _tx_gain_group->set_value(gain); + return _tx_gain_group()->set_value(gain); } float get_tx_gain(void){ - return _tx_gain_group->get_value(); + return _tx_gain_group()->get_value(); } gain_range_t get_tx_gain_range(void){ - return _tx_gain_group->get_range(); + return _tx_gain_group()->get_range(); } void set_tx_antenna(const std::string &ant){ - _tx_subdev[SUBDEV_PROP_ANTENNA] = ant; + _tx_subdev()[SUBDEV_PROP_ANTENNA] = ant; } std::string get_tx_antenna(void){ - return _tx_subdev[SUBDEV_PROP_ANTENNA].as<std::string>(); + return _tx_subdev()[SUBDEV_PROP_ANTENNA].as<std::string>(); } std::vector<std::string> get_tx_antennas(void){ - return _tx_subdev[SUBDEV_PROP_ANTENNA_NAMES].as<prop_names_t>(); + return _tx_subdev()[SUBDEV_PROP_ANTENNA_NAMES].as<prop_names_t>(); } bool get_tx_lo_locked(void){ - return _tx_subdev[SUBDEV_PROP_LO_LOCKED].as<bool>(); + return _tx_subdev()[SUBDEV_PROP_LO_LOCKED].as<bool>(); } /******************************************************************* @@ -233,24 +237,48 @@ public: ******************************************************************/ wax::obj get_rx_dboard_iface(void) { - return _rx_dboard; + return _rx_dboard(); } wax::obj get_tx_dboard_iface(void) { - return _tx_dboard; + return _tx_dboard(); } private: device::sptr _dev; - wax::obj _mboard; - wax::obj _rx_dsp; - wax::obj _tx_dsp; - wax::obj _rx_dboard; - wax::obj _tx_dboard; - wax::obj _rx_subdev; - wax::obj _tx_subdev; - gain_group::sptr _rx_gain_group; - gain_group::sptr _tx_gain_group; + wax::obj _mboard(void){ + return (*_dev)[DEVICE_PROP_MBOARD]; + } + wax::obj _rx_dsp(void){ + return _mboard()[MBOARD_PROP_RX_DSP]; + } + wax::obj _tx_dsp(void){ + return _mboard()[MBOARD_PROP_TX_DSP]; + } + wax::obj _rx_dboard(void){ + std::string db_name = _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>().front().db_name; + return _mboard()[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; + } + wax::obj _tx_dboard(void){ + std::string db_name = _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>().front().db_name; + return _mboard()[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; + } + wax::obj _rx_subdev(void){ + std::string sd_name = _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name; + return _rx_dboard()[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; + } + wax::obj _tx_subdev(void){ + std::string sd_name = _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name; + return _tx_dboard()[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; + } + gain_group::sptr _rx_gain_group(void){ + std::string sd_name = _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name; + return _rx_dboard()[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>(); + } + gain_group::sptr _tx_gain_group(void){ + std::string sd_name = _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name; + return _tx_dboard()[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>(); + } }; /*********************************************************************** diff --git a/host/lib/usrp/subdev_spec.cpp b/host/lib/usrp/subdev_spec.cpp new file mode 100644 index 000000000..0f00e2f74 --- /dev/null +++ b/host/lib/usrp/subdev_spec.cpp @@ -0,0 +1,77 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/usrp/subdev_spec.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/format.hpp> +#include <boost/foreach.hpp> +#include <stdexcept> +#include <sstream> + +using namespace uhd; +using namespace uhd::usrp; + +subdev_spec_pair_t::subdev_spec_pair_t( + const std::string &db_name, const std::string &sd_name +): + db_name(db_name), + sd_name(sd_name) +{ + /* NOP */ +} + +subdev_spec_t::subdev_spec_t(const std::string &markup){ + std::vector<std::string> pairs; + boost::split(pairs, markup, boost::is_any_of("\t ")); + BOOST_FOREACH(const std::string &pair, pairs){ + if (pair == "") continue; + std::vector<std::string> db_sd; + boost::split(db_sd, pair, boost::is_any_of(":")); + switch(db_sd.size()){ + case 1: this->push_back(subdev_spec_pair_t("", db_sd.front())); break; + case 2: this->push_back(subdev_spec_pair_t(db_sd.front(), db_sd.back())); break; + default: throw std::runtime_error("invalid subdev-spec markup string: "+markup); + } + } +} + +std::string subdev_spec_t::to_pp_string(void) const{ + if (this->size() == 0) return "Empty Subdevice Specification"; + + std::stringstream ss; + size_t count = 0; + ss << "Subdevice Specification:" << std::endl; + BOOST_FOREACH(const subdev_spec_pair_t &pair, *this){ + std::string db_name = pair.db_name; + if (db_name == "") db_name = "0"; + std::string sd_name = pair.sd_name; + if (sd_name == "") sd_name = "0"; + ss << boost::format( + " Channel %d: Daughterboard %s, Subdevice %s" + ) % (count++) % db_name % sd_name << std::endl; + } + return ss.str(); +} + +std::string subdev_spec_t::to_string(void) const{ + std::string markup; + size_t count = 0; + BOOST_FOREACH(const subdev_spec_pair_t &pair, *this){ + markup += ((count++)? " " : "") + pair.db_name + ":" + pair.sd_name; + } + return markup; +} diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp index 5ed8ec079..ef027c1df 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.cpp +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -90,7 +90,7 @@ public: void set_rate_rx_dboard_clock(double rate){ assert_has(get_rates_rx_dboard_clock(), rate, "rx dboard clock rate"); - size_t divider = size_t(rate/get_master_clock_rate()); + size_t divider = size_t(get_master_clock_rate()/rate); //bypass when the divider ratio is one _ad9510_regs.bypass_divider_out7 = (divider == 1)? 1 : 0; //calculate the low and high dividers @@ -132,7 +132,9 @@ public: void set_rate_tx_dboard_clock(double rate){ assert_has(get_rates_tx_dboard_clock(), rate, "tx dboard clock rate"); - size_t divider = size_t(rate/get_master_clock_rate()); + size_t divider = size_t(get_master_clock_rate()/rate); + //bypass when the divider ratio is one + _ad9510_regs.bypass_divider_out6 = (divider == 1)? 1 : 0; //calculate the low and high dividers size_t high = divider/2; size_t low = divider - high; diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index 5c81856bb..be45c2c9e 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -37,6 +37,8 @@ public: usrp2_dboard_iface(usrp2_iface::sptr iface, usrp2_clock_ctrl::sptr clock_ctrl); ~usrp2_dboard_iface(void); + std::string get_mboard_name(void){return "usrp2";} + void write_aux_dac(unit_t, aux_dac_t, float); float read_aux_adc(unit_t, aux_adc_t); diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 3a2a53674..075f22388 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -53,10 +53,6 @@ void usrp2_mboard_impl::dboard_init(void){ boost::bind(&usrp2_mboard_impl::tx_dboard_get, this, _1, _2), boost::bind(&usrp2_mboard_impl::tx_dboard_set, this, _1, _2) ); - - //init the subdevs in use (use the first subdevice) - rx_dboard_set(DBOARD_PROP_USED_SUBDEVS, prop_names_t(1, _dboard_manager->get_rx_subdev_names().at(0))); - tx_dboard_set(DBOARD_PROP_USED_SUBDEVS, prop_names_t(1, _dboard_manager->get_tx_subdev_names().at(0))); } /*********************************************************************** @@ -80,10 +76,6 @@ void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _dboard_manager->get_rx_subdev_names(); return; - case DBOARD_PROP_USED_SUBDEVS: - val = _rx_subdevs_in_use; - return; - case DBOARD_PROP_DBOARD_ID: val = _rx_db_eeprom.id; return; @@ -108,16 +100,6 @@ void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ void usrp2_mboard_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ switch(key.as<dboard_prop_t>()){ - case DBOARD_PROP_USED_SUBDEVS:{ - _rx_subdevs_in_use = val.as<prop_names_t>(); - UHD_ASSERT_THROW(_rx_subdevs_in_use.size() == 1); - wax::obj rx_subdev = _dboard_manager->get_rx_subdev(_rx_subdevs_in_use.at(0)); - std::cout << "Using: " << rx_subdev[SUBDEV_PROP_NAME].as<std::string>() << std::endl; - _iface->poke32(_iface->regs.dsp_rx_mux, dsp_type1::calc_rx_mux_word( - rx_subdev[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() - )); - } - return; case DBOARD_PROP_DBOARD_ID: _rx_db_eeprom.id = val.as<dboard_id_t>(); @@ -149,10 +131,6 @@ void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _dboard_manager->get_tx_subdev_names(); return; - case DBOARD_PROP_USED_SUBDEVS: - val = _tx_subdevs_in_use; - return; - case DBOARD_PROP_DBOARD_ID: val = _tx_db_eeprom.id; return; @@ -177,16 +155,6 @@ void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ void usrp2_mboard_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){ switch(key.as<dboard_prop_t>()){ - case DBOARD_PROP_USED_SUBDEVS:{ - _tx_subdevs_in_use = val.as<prop_names_t>(); - UHD_ASSERT_THROW(_tx_subdevs_in_use.size() == 1); - wax::obj tx_subdev = _dboard_manager->get_tx_subdev(_tx_subdevs_in_use.at(0)); - std::cout << "Using: " << tx_subdev[SUBDEV_PROP_NAME].as<std::string>() << std::endl; - _iface->poke32(_iface->regs.dsp_tx_mux, dsp_type1::calc_tx_mux_word( - tx_subdev[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() - )); - } - return; case DBOARD_PROP_DBOARD_ID: _tx_db_eeprom.id = val.as<dboard_id_t>(); diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 389ac9892..85d41d57f 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -32,9 +32,9 @@ extern "C" { #define __stdint(type) type #endif -//defines the protocol version in this shared header -//increment this value when the protocol is changed -#define USRP2_PROTO_VERSION 5 +//fpga and firmware compatibility numbers +#define USRP2_FPGA_COMPAT_NUM 1 +#define USRP2_FW_COMPAT_NUM 5 //used to differentiate control packets over data port #define USRP2_INVALID_VRT_HEADER 0 diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index aa6d15783..c67bd02fd 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -144,11 +144,13 @@ void usrp2_impl::io_impl::recv_pirate_loop( **********************************************************************/ void usrp2_impl::io_init(void){ //send a small data packet so the usrp2 knows the udp source port - for(size_t i = 0; i < _data_transports.size(); i++){ - managed_send_buffer::sptr send_buff = _data_transports[i]->get_send_buff(); - boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER); - memcpy(send_buff->cast<void*>(), &data, sizeof(data)); + BOOST_FOREACH(zero_copy_if::sptr data_transport, _data_transports){ + managed_send_buffer::sptr send_buff = data_transport->get_send_buff(); + static const boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER); + std::memcpy(send_buff->cast<void*>(), &data, sizeof(data)); send_buff->commit(sizeof(data)); + //drain the recv buffers (may have junk) + while (data_transport->get_recv_buff().get()){;} } //the number of recv frames is the number for the first transport diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index c8e22a709..a3d5e8955 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -105,6 +105,15 @@ usrp2_mboard_impl::usrp2_mboard_impl( //init the tx and rx dboards (do last) dboard_init(); + + //set default subdev specs + (*this)[MBOARD_PROP_RX_SUBDEV_SPEC] = subdev_spec_t(); + (*this)[MBOARD_PROP_TX_SUBDEV_SPEC] = subdev_spec_t(); + + //Issue a stop streaming command (in case it was left running). + //Since this command is issued before the networking is setup, + //most if not all junk packets will never make it to the socket. + this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); } usrp2_mboard_impl::~usrp2_mboard_impl(void){ @@ -265,6 +274,14 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){ } return; + case MBOARD_PROP_RX_SUBDEV_SPEC: + val = _rx_subdev_spec; + return; + + case MBOARD_PROP_TX_SUBDEV_SPEC: + val = _tx_subdev_spec; + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -309,6 +326,38 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){ issue_ddc_stream_cmd(val.as<stream_cmd_t>()); return; + case MBOARD_PROP_RX_SUBDEV_SPEC: + _rx_subdev_spec = val.as<subdev_spec_t>(); + //handle automatic + if (_rx_subdev_spec.empty()) _rx_subdev_spec.push_back( + subdev_spec_pair_t("", _dboard_manager->get_rx_subdev_names().front()) + ); + //sanity check + UHD_ASSERT_THROW(_rx_subdev_spec.size() == 1); + uhd::assert_has((*this)[MBOARD_PROP_RX_DBOARD_NAMES].as<prop_names_t>(), _rx_subdev_spec.front().db_name, "rx dboard names"); + uhd::assert_has(_dboard_manager->get_rx_subdev_names(), _rx_subdev_spec.front().sd_name, "rx subdev names"); + //set the mux + _iface->poke32(_iface->regs.dsp_rx_mux, dsp_type1::calc_rx_mux_word( + _dboard_manager->get_rx_subdev(_rx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() + )); + return; + + case MBOARD_PROP_TX_SUBDEV_SPEC: + _tx_subdev_spec = val.as<subdev_spec_t>(); + //handle automatic + if (_tx_subdev_spec.empty()) _tx_subdev_spec.push_back( + subdev_spec_pair_t("", _dboard_manager->get_tx_subdev_names().front()) + ); + //sanity check + UHD_ASSERT_THROW(_tx_subdev_spec.size() == 1); + uhd::assert_has((*this)[MBOARD_PROP_TX_DBOARD_NAMES].as<prop_names_t>(), _tx_subdev_spec.front().db_name, "tx dboard names"); + uhd::assert_has(_dboard_manager->get_tx_subdev_names(), _tx_subdev_spec.front().sd_name, "tx subdev names"); + //set the mux + _iface->poke32(_iface->regs.dsp_tx_mux, dsp_type1::calc_tx_mux_word( + _dboard_manager->get_tx_subdev(_tx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() + )); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 2a380dc44..44aef2a34 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -15,6 +15,7 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. // +#include "usrp2_regs.hpp" #include "usrp2_iface.hpp" #include <uhd/utils/assert.hpp> #include <uhd/types/dict.hpp> @@ -22,6 +23,7 @@ #include <boost/foreach.hpp> #include <boost/asio.hpp> //used for htonl and ntohl #include <boost/assign/list_of.hpp> +#include <boost/format.hpp> #include <stdexcept> #include <algorithm> @@ -47,6 +49,15 @@ public: **********************************************************************/ usrp2_iface_impl(udp_simple::sptr ctrl_transport){ _ctrl_transport = ctrl_transport; + + //check the fpga compatibility number + const boost::uint32_t fpga_compat_num = this->peek32(this->regs.compat_num_rb); + if (fpga_compat_num != USRP2_FPGA_COMPAT_NUM){ + throw std::runtime_error(str(boost::format( + "Expected fpga compatibility number %d, but got %d:\n" + "The fpga build is not compatible with the host code build." + ) % int(USRP2_FPGA_COMPAT_NUM) % fpga_compat_num)); + } } ~usrp2_iface_impl(void){ @@ -168,7 +179,7 @@ public: //fill in the seq number and send usrp2_ctrl_data_t out_copy = out_data; - out_copy.proto_ver = htonl(USRP2_PROTO_VERSION); + out_copy.proto_ver = htonl(USRP2_FW_COMPAT_NUM); out_copy.seq = htonl(++_ctrl_seq_num); _ctrl_transport->send(boost::asio::buffer(&out_copy, sizeof(usrp2_ctrl_data_t))); @@ -177,12 +188,11 @@ public: const usrp2_ctrl_data_t *ctrl_data_in = reinterpret_cast<const usrp2_ctrl_data_t *>(usrp2_ctrl_data_in_mem); while(true){ size_t len = _ctrl_transport->recv(boost::asio::buffer(usrp2_ctrl_data_in_mem), CONTROL_TIMEOUT_MS); - if(len >= sizeof(boost::uint32_t) and ntohl(ctrl_data_in->proto_ver) != USRP2_PROTO_VERSION){ - throw std::runtime_error(str( - boost::format("Expected protocol version %d, but got %d\n" - "The firmware build does not match the host code build." - ) % int(USRP2_PROTO_VERSION) % ntohl(ctrl_data_in->proto_ver) - )); + if(len >= sizeof(boost::uint32_t) and ntohl(ctrl_data_in->proto_ver) != USRP2_FW_COMPAT_NUM){ + throw std::runtime_error(str(boost::format( + "Expected protocol compatibility number %d, but got %d:\n" + "The firmware build is not compatible with the host code build." + ) % int(USRP2_FW_COMPAT_NUM) % ntohl(ctrl_data_in->proto_ver))); } if (len >= sizeof(usrp2_ctrl_data_t) and ntohl(ctrl_data_in->seq) == _ctrl_seq_num){ return *ctrl_data_in; diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 2c314c085..21f411afe 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -97,7 +97,7 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){ //send a hello control packet usrp2_ctrl_data_t ctrl_data_out; - ctrl_data_out.proto_ver = htonl(USRP2_PROTO_VERSION); + ctrl_data_out.proto_ver = htonl(USRP2_FW_COMPAT_NUM); ctrl_data_out.id = htonl(USRP2_CTRL_ID_WAZZUP_BRO); udp_transport->send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out))); diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 8421b6b39..21a56cb67 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -35,6 +35,7 @@ #include <uhd/transport/udp_simple.hpp> //mtu #include <uhd/transport/udp_zero_copy.hpp> #include <uhd/usrp/dboard_manager.hpp> +#include <uhd/usrp/subdev_spec.hpp> /*! * Make a usrp2 dboard interface. @@ -143,6 +144,7 @@ private: //properties for this mboard void get(const wax::obj &, wax::obj &); void set(const wax::obj &, const wax::obj &); + uhd::usrp::subdev_spec_t _rx_subdev_spec, _tx_subdev_spec; //interfaces usrp2_iface::sptr _iface; @@ -177,14 +179,12 @@ private: void rx_dboard_get(const wax::obj &, wax::obj &); void rx_dboard_set(const wax::obj &, const wax::obj &); wax_obj_proxy::sptr _rx_dboard_proxy; - uhd::prop_names_t _rx_subdevs_in_use; uhd::usrp::dboard_eeprom_t _rx_db_eeprom; //properties interface for tx dboard void tx_dboard_get(const wax::obj &, wax::obj &); void tx_dboard_set(const wax::obj &, const wax::obj &); wax_obj_proxy::sptr _tx_dboard_proxy; - uhd::prop_names_t _tx_subdevs_in_use; uhd::usrp::dboard_eeprom_t _tx_db_eeprom; //methods and shadows for the ddc dsp diff --git a/host/lib/usrp/usrp2/usrp2_regs.cpp b/host/lib/usrp/usrp2/usrp2_regs.cpp index 857fbda9c..49f077221 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.cpp +++ b/host/lib/usrp/usrp2/usrp2_regs.cpp @@ -58,6 +58,7 @@ usrp2_regs_t usrp2_get_regs(int hw_rev) { x.time64_tps = sr_addr(misc_output_base, x.sr_time64 + 4); x.time64_secs_rb = bp_base + 4*10; x.time64_ticks_rb = bp_base + 4*11; + x.compat_num_rb = bp_base + 4*12; x.dsp_tx_freq = sr_addr(misc_output_base, x.sr_tx_dsp + 0); x.dsp_tx_scale_iq = sr_addr(misc_output_base, x.sr_tx_dsp + 1); x.dsp_tx_interp_rate = sr_addr(misc_output_base, x.sr_tx_dsp + 2); diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index c12098c8e..0a171d20c 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -61,6 +61,7 @@ typedef struct { int time64_tps; // ticks per second rollover count int time64_secs_rb; int time64_ticks_rb; + int compat_num_rb; int dsp_tx_freq; int dsp_tx_scale_iq; int dsp_tx_interp_rate; diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt new file mode 100644 index 000000000..68945545a --- /dev/null +++ b/host/lib/utils/CMakeLists.txt @@ -0,0 +1,87 @@ +# +# Copyright 2010 Ettus Research LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +#This file will be included by cmake, use absolute paths! + +######################################################################## +# Setup defines for process scheduling +######################################################################## +MESSAGE(STATUS "Configuring priority scheduling...") + +INCLUDE(CheckCXXSourceCompiles) +CHECK_CXX_SOURCE_COMPILES(" + #include <pthread.h> + int main(){ + struct sched_param sp; + pthread_setschedparam(pthread_self(), SCHED_RR, &sp); + return 0; + } + " HAVE_PTHREAD_SETSCHEDPARAM +) + +CHECK_CXX_SOURCE_COMPILES(" + #include <windows.h> + int main(){ + SetThreadPriority(GetCurrentThread(), 0); + SetPriorityClass(GetCurrentProcess(), 0); + return 0; + } + " HAVE_WIN_SETTHREADPRIORITY +) + +IF(HAVE_PTHREAD_SETSCHEDPARAM) + MESSAGE(STATUS " Priority scheduling supported through pthread_setschedparam.") + ADD_DEFINITIONS(-DHAVE_PTHREAD_SETSCHEDPARAM) +ELSEIF(HAVE_WIN_SETTHREADPRIORITY) + MESSAGE(STATUS " Priority scheduling supported through windows SetThreadPriority.") + ADD_DEFINITIONS(-DHAVE_WIN_SETTHREADPRIORITY) +ELSE(HAVE_PTHREAD_SETSCHEDPARAM) + MESSAGE(STATUS " Priority scheduling not supported.") +ENDIF(HAVE_PTHREAD_SETSCHEDPARAM) + +######################################################################## +# Setup defines for module loading +######################################################################## +MESSAGE(STATUS "Configuring module loading...") + +INCLUDE(CheckIncludeFileCXX) +CHECK_INCLUDE_FILE_CXX(dlfcn.h HAVE_DLFCN_H) +CHECK_INCLUDE_FILE_CXX(windows.h HAVE_WINDOWS_H) + +IF(HAVE_DLFCN_H) + MESSAGE(STATUS " Module loading supported through dlopen.") + ADD_DEFINITIONS(-DHAVE_DLFCN_H) + LIBUHD_APPEND_LIBS(${CMAKE_DL_LIBS}) +ELSEIF(HAVE_WINDOWS_H) + MESSAGE(STATUS " Module loading supported through LoadLibrary.") + ADD_DEFINITIONS(-DHAVE_WINDOWS_H) +ELSE(HAVE_DLFCN_H) + MESSAGE(STATUS " Module loading not supported.") +ENDIF(HAVE_DLFCN_H) + +######################################################################## +# Append sources +######################################################################## +LIBUHD_APPEND_SOURCES( + ${CMAKE_SOURCE_DIR}/lib/utils/assert.cpp + ${CMAKE_SOURCE_DIR}/lib/utils/gain_group.cpp + ${CMAKE_SOURCE_DIR}/lib/utils/load_modules.cpp + ${CMAKE_SOURCE_DIR}/lib/utils/paths.cpp + ${CMAKE_SOURCE_DIR}/lib/utils/props.cpp + ${CMAKE_SOURCE_DIR}/lib/utils/thread_priority.cpp + ${CMAKE_SOURCE_DIR}/lib/utils/warning.cpp +) diff --git a/host/lib/utils/assert.cpp b/host/lib/utils/assert.cpp new file mode 100644 index 000000000..7ace9024c --- /dev/null +++ b/host/lib/utils/assert.cpp @@ -0,0 +1,24 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/utils/assert.hpp> + +using namespace uhd; + +assert_error::assert_error(const std::string &what) : std::runtime_error(what){ + /* NOP */ +} diff --git a/host/lib/utils/gain_group.cpp b/host/lib/utils/gain_group.cpp new file mode 100644 index 000000000..c113719c8 --- /dev/null +++ b/host/lib/utils/gain_group.cpp @@ -0,0 +1,149 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/utils/gain_group.hpp> +#include <uhd/types/dict.hpp> +#include <uhd/utils/algorithm.hpp> +#include <uhd/utils/assert.hpp> +#include <boost/foreach.hpp> +#include <boost/bind.hpp> +#include <algorithm> +#include <vector> +#include <iostream> + +using namespace uhd; + +static const bool verbose = false; + +static bool compare_by_step_size( + const size_t &rhs, const size_t &lhs, std::vector<gain_fcns_t> &fcns +){ + return fcns.at(rhs).get_range().step > fcns.at(lhs).get_range().step; +} + +/*********************************************************************** + * gain group implementation + **********************************************************************/ +class gain_group_impl : public gain_group{ +public: + gain_group_impl(void){ + /*NOP*/ + } + + gain_range_t get_range(void){ + 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(); + overall_min += range.min; + overall_max += range.max; + //the overall step is the min (zero is invalid, first run) + if (overall_step == 0) overall_step = range.step; + overall_step = std::min(overall_step, range.step); + } + return gain_range_t(overall_min, overall_max, overall_step); + } + + float get_value(void){ + float overall_gain = 0; + BOOST_FOREACH(const gain_fcns_t &fcns, get_all_fcns()){ + overall_gain += fcns.get_value(); + } + return overall_gain; + } + + void set_value(float gain){ + std::vector<gain_fcns_t> all_fcns = get_all_fcns(); + if (all_fcns.size() == 0) return; //nothing to set! + + //get the max step size among the gains + float max_step = 0; + BOOST_FOREACH(const gain_fcns_t &fcns, all_fcns){ + max_step = std::max(max_step, fcns.get_range().step); + } + + //create gain bucket to distribute power + std::vector<float> gain_bucket; + + //distribute power according to priority (round to max step) + float gain_left_to_distribute = gain; + BOOST_FOREACH(const gain_fcns_t &fcns, all_fcns){ + const gain_range_t range = fcns.get_range(); + gain_bucket.push_back( + max_step*int(std::clip(gain_left_to_distribute, range.min, range.max)/max_step) + ); + gain_left_to_distribute -= gain_bucket.back(); + } + + //get a list of indexes sorted by step size large to small + std::vector<size_t> indexes_step_size_dec; + for (size_t i = 0; i < all_fcns.size(); i++){ + indexes_step_size_dec.push_back(i); + } + std::sort( + indexes_step_size_dec.begin(), indexes_step_size_dec.end(), + boost::bind(&compare_by_step_size, _1, _2, all_fcns) + ); + UHD_ASSERT_THROW( + all_fcns.at(indexes_step_size_dec.front()).get_range().step >= + all_fcns.at(indexes_step_size_dec.back()).get_range().step + ); + + //distribute the remainder (less than max step) + //fill in the largest step sizes first that are less than the remainder + BOOST_FOREACH(size_t i, indexes_step_size_dec){ + const gain_range_t range = all_fcns.at(i).get_range(); + float additional_gain = range.step*int( + std::clip(gain_bucket.at(i) + gain_left_to_distribute, range.min, range.max + )/range.step) - gain_bucket.at(i); + gain_bucket.at(i) += additional_gain; + gain_left_to_distribute -= additional_gain; + } + if (verbose) std::cout << "gain_left_to_distribute " << gain_left_to_distribute << std::endl; + + //now write the bucket out to the individual gain values + for (size_t i = 0; i < gain_bucket.size(); i++){ + if (verbose) std::cout << gain_bucket.at(i) << std::endl; + all_fcns.at(i).set_value(gain_bucket.at(i)); + } + } + + void register_fcns( + const gain_fcns_t &gain_fcns, size_t priority + ){ + _registry[priority].push_back(gain_fcns); + } + +private: + //! get the gain function sets in order (highest priority first) + std::vector<gain_fcns_t> get_all_fcns(void){ + std::vector<gain_fcns_t> all_fcns; + BOOST_FOREACH(size_t key, std::sorted(_registry.keys())){ + const std::vector<gain_fcns_t> &fcns = _registry[key]; + all_fcns.insert(all_fcns.begin(), fcns.begin(), fcns.end()); + } + return all_fcns; + } + + uhd::dict<size_t, std::vector<gain_fcns_t> > _registry; +}; + +/*********************************************************************** + * gain group factory function + **********************************************************************/ +gain_group::sptr gain_group::make(void){ + return sptr(new gain_group_impl()); +} diff --git a/host/lib/load_modules.cpp b/host/lib/utils/load_modules.cpp index dbb8d0695..623d31eb6 100644 --- a/host/lib/load_modules.cpp +++ b/host/lib/utils/load_modules.cpp @@ -18,13 +18,12 @@ #include <uhd/utils/static.hpp> #include <boost/format.hpp> #include <boost/foreach.hpp> -#include <boost/algorithm/string.hpp> #include <boost/filesystem.hpp> -#include <boost/program_options.hpp> #include <iostream> #include <stdexcept> +#include <string> +#include <vector> -namespace po = boost::program_options; namespace fs = boost::filesystem; /*********************************************************************** @@ -32,7 +31,6 @@ namespace fs = boost::filesystem; **********************************************************************/ #if defined(HAVE_DLFCN_H) #include <dlfcn.h> -static const std::string env_path_sep = ":"; static void load_module(const std::string &file_name){ if (dlopen(file_name.c_str(), RTLD_LAZY) == NULL){ @@ -44,7 +42,6 @@ static void load_module(const std::string &file_name){ #elif defined(HAVE_WINDOWS_H) #include <windows.h> -static const std::string env_path_sep = ";"; static void load_module(const std::string &file_name){ if (LoadLibrary(file_name.c_str()) == NULL){ @@ -55,7 +52,6 @@ static void load_module(const std::string &file_name){ } #else -static const std::string env_path_sep = ":"; static void load_module(const std::string &file_name){ throw std::runtime_error(str( @@ -74,9 +70,9 @@ static void load_module(const std::string &file_name){ * Does not throw, prints to std error. * \param path the filesystem path */ -static void load_path(const fs::path &path){ +static void load_module_path(const fs::path &path){ if (not fs::exists(path)){ - std::cerr << boost::format("Module path \"%s\" not found.") % path.file_string() << std::endl; + //std::cerr << boost::format("Module path \"%s\" not found.") % path.file_string() << std::endl; return; } @@ -87,7 +83,7 @@ static void load_path(const fs::path &path){ dir_itr != fs::directory_iterator(); ++dir_itr ){ - load_path(dir_itr->path()); + load_module_path(dir_itr->path()); } return; } @@ -101,46 +97,13 @@ static void load_path(const fs::path &path){ } } -//! The string constant for the module path environment variable -static const std::string MODULE_PATH_KEY = "UHD_MODULE_PATH"; +std::vector<fs::path> get_module_paths(void); //defined in paths.cpp /*! - * Name mapper function for the environment variable parser. - * Map environment variable names (that we use) to option names. - * \param the variable name - * \return the option name or blank string - */ -static std::string name_mapper(const std::string &var_name){ - if (var_name == MODULE_PATH_KEY) return var_name; - return ""; -} - -/*! - * Load all the modules given by the module path enviroment variable. - * The path variable may be several paths split by path separators. + * Load all the modules given in the module paths. */ UHD_STATIC_BLOCK(load_modules){ - //register the options - std::string env_module_path; - po::options_description desc("UHD Module Options"); - desc.add_options() - (MODULE_PATH_KEY.c_str(), po::value<std::string>(&env_module_path)->default_value("")) - ; - - //parse environment variables - po::variables_map vm; - po::store(po::parse_environment(desc, &name_mapper), vm); - po::notify(vm); - - if (env_module_path == "") return; - //std::cout << "env_module_path: " << env_module_path << std::endl; - - //split the path at the path separators - std::vector<std::string> module_paths; - boost::split(module_paths, env_module_path, boost::is_any_of(env_path_sep)); - - //load modules in each path - BOOST_FOREACH(const std::string &module_path, module_paths){ - load_path(fs::system_complete(fs::path(module_path))); + BOOST_FOREACH(const fs::path &path, get_module_paths()){ + load_module_path(path); } } diff --git a/host/lib/utils/paths.cpp b/host/lib/utils/paths.cpp new file mode 100644 index 000000000..0805a44fe --- /dev/null +++ b/host/lib/utils/paths.cpp @@ -0,0 +1,103 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include "constants.hpp" +#include <uhd/config.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/program_options.hpp> +#include <boost/filesystem.hpp> +#include <boost/foreach.hpp> +#include <boost/bind.hpp> +#include <stdexcept> +#include <string> +#include <vector> + +namespace po = boost::program_options; +namespace fs = boost::filesystem; + +/*********************************************************************** + * Determine the paths separator + **********************************************************************/ +#ifdef UHD_PLATFORM_WIN32 + static const std::string env_path_sep = ";"; +#else + static const std::string env_path_sep = ":"; +#endif /*UHD_PLATFORM_WIN32*/ + +/*********************************************************************** + * Get a list of paths for an environment variable + **********************************************************************/ +static std::string name_mapper(const std::string &key, const std::string &var_name){ + return (var_name == key)? var_name : ""; +} + +static std::vector<fs::path> get_env_paths(const std::string &var_name){ + //register the options + std::string var_value; + po::options_description desc; + desc.add_options() + (var_name.c_str(), po::value<std::string>(&var_value)->default_value("")) + ; + + //parse environment variables + po::variables_map vm; + po::store(po::parse_environment(desc, boost::bind(&name_mapper, var_name, _1)), vm); + po::notify(vm); + + //split the path at the path separators + std::vector<std::string> path_strings; + boost::split(path_strings, var_value, boost::is_any_of(env_path_sep)); + + //convert to filesystem path, filter blank paths + std::vector<fs::path> paths; + BOOST_FOREACH(std::string &path_string, path_strings){ + if (path_string.size() == 0) continue; + paths.push_back(fs::system_complete(path_string)); + } + return paths; +} + +/*********************************************************************** + * Get a list of special purpose paths + **********************************************************************/ +static const fs::path pkg_data_path = fs::path(UHD_INSTALL_PREFIX) / UHD_PKG_DATA_DIR; + +std::vector<fs::path> get_image_paths(void){ + std::vector<fs::path> paths = get_env_paths("UHD_IMAGE_PATH"); + paths.push_back(pkg_data_path / "images"); + return paths; +} + +std::vector<fs::path> get_module_paths(void){ + std::vector<fs::path> paths = get_env_paths("UHD_MODULE_PATH"); + paths.push_back(pkg_data_path / "modules"); + return paths; +} + +/*********************************************************************** + * Find a image in the image paths + **********************************************************************/ +std::string find_image_path(const std::string &image_name){ + if (fs::exists(image_name)){ + return fs::system_complete(image_name).file_string(); + } + BOOST_FOREACH(const fs::path &path, get_image_paths()){ + fs::path image_path = path / image_name; + if (fs::exists(image_path)) return image_path.file_string(); + } + throw std::runtime_error("Could not find path for image: " + image_name); +} diff --git a/host/lib/utils.cpp b/host/lib/utils/props.cpp index d2f4dfc6e..fac5fe24f 100644 --- a/host/lib/utils.cpp +++ b/host/lib/utils/props.cpp @@ -15,28 +15,18 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. // -#include <uhd/utils/assert.hpp> #include <uhd/utils/props.hpp> -#include <stdexcept> using namespace uhd; -/*********************************************************************** - * Assert - **********************************************************************/ -assert_error::assert_error(const std::string &what) : std::runtime_error(what){ - /* NOP */ -} - -/*********************************************************************** - * Props - **********************************************************************/ named_prop_t::named_prop_t( - const wax::obj &key_, - const std::string &name_ -){ - key = key_; - name = name_; + const wax::obj &key, + const std::string &name +): + key(key), + name(name) +{ + /* NOP */ } typedef boost::tuple<wax::obj, std::string> named_prop_tuple; diff --git a/host/lib/thread_priority.cpp b/host/lib/utils/thread_priority.cpp index c35e5fcb1..c35e5fcb1 100644 --- a/host/lib/thread_priority.cpp +++ b/host/lib/utils/thread_priority.cpp diff --git a/host/lib/utils/warning.cpp b/host/lib/utils/warning.cpp new file mode 100644 index 000000000..ae4d4c7aa --- /dev/null +++ b/host/lib/utils/warning.cpp @@ -0,0 +1,36 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/utils/warning.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/foreach.hpp> +#include <iostream> +#include <vector> + +using namespace uhd; + +void uhd::print_warning(const std::string &msg){ + //extract the message lines + std::vector<std::string> lines; + boost::split(lines, msg, boost::is_any_of("\n")); + + //print the warning message + std::cerr << std::endl << "Warning:" << std::endl; + BOOST_FOREACH(const std::string &line, lines){ + std::cerr << " " << line << std::endl; + } +} diff --git a/host/lib/version.cpp.in b/host/lib/version.cpp index f3a5afc45..5edbca09b 100644 --- a/host/lib/version.cpp.in +++ b/host/lib/version.cpp @@ -15,8 +15,9 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. // +#include "constants.hpp" #include <uhd/version.hpp> std::string uhd::get_version_string(void){ - return "@CPACK_PACKAGE_VERSION@"; + return UHD_VERSION_STRING; } diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt index 37832edde..c620fd641 100644 --- a/host/test/CMakeLists.txt +++ b/host/test/CMakeLists.txt @@ -27,8 +27,10 @@ ADD_EXECUTABLE(main_test dict_test.cpp error_test.cpp gain_group_test.cpp + subdev_spec_test.cpp tune_helper_test.cpp vrt_test.cpp + warning_test.cpp wax_test.cpp ) TARGET_LINK_LIBRARIES(main_test uhd) diff --git a/host/test/addr_test.cpp b/host/test/addr_test.cpp index 0c50200d6..d4b45aa1a 100644 --- a/host/test/addr_test.cpp +++ b/host/test/addr_test.cpp @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(test_device_addr){ uhd::device_addr_t new_dev_addr(args_str); //they should be the same size - BOOST_CHECK_EQUAL(dev_addr.size(), new_dev_addr.size()); + BOOST_REQUIRE_EQUAL(dev_addr.size(), new_dev_addr.size()); //the keys should match std::vector<std::string> old_dev_addr_keys = dev_addr.keys(); diff --git a/host/test/subdev_spec_test.cpp b/host/test/subdev_spec_test.cpp new file mode 100644 index 000000000..8817d5eee --- /dev/null +++ b/host/test/subdev_spec_test.cpp @@ -0,0 +1,45 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <boost/test/unit_test.hpp> +#include <uhd/usrp/subdev_spec.hpp> +#include <boost/foreach.hpp> +#include <iostream> + +BOOST_AUTO_TEST_CASE(test_subdevice_spec){ + std::cout << "Testing subdevice specification..." << std::endl; + + //load the subdev spec with something + uhd::usrp::subdev_spec_t sd_spec; + sd_spec.push_back(uhd::usrp::subdev_spec_pair_t("A", "AB")); + sd_spec.push_back(uhd::usrp::subdev_spec_pair_t("B", "AB")); + + //convert to and from args string + std::cout << "Pretty Print: " << std::endl << sd_spec.to_pp_string(); + std::string markup_str = sd_spec.to_string(); + std::cout << "Markup String: " << markup_str << std::endl; + uhd::usrp::subdev_spec_t new_sd_spec(markup_str); + + //they should be the same size + BOOST_REQUIRE_EQUAL(sd_spec.size(), new_sd_spec.size()); + + //the contents should match + for (size_t i = 0; i < sd_spec.size(); i++){ + BOOST_CHECK_EQUAL(sd_spec.at(i).db_name, new_sd_spec.at(i).db_name); + BOOST_CHECK_EQUAL(sd_spec.at(i).sd_name, new_sd_spec.at(i).sd_name); + } +} diff --git a/host/test/warning_test.cpp b/host/test/warning_test.cpp new file mode 100644 index 000000000..6202c4270 --- /dev/null +++ b/host/test/warning_test.cpp @@ -0,0 +1,29 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <boost/test/unit_test.hpp> +#include <uhd/utils/warning.hpp> +#include <iostream> + +BOOST_AUTO_TEST_CASE(test_print_warning){ + std::cerr << "---begin print test ---" << std::endl; + uhd::print_warning( + "This is a test print for a warning message.\n" + "And this is the second line of the test print.\n" + ); + std::cerr << "---end print test ---" << std::endl; +} diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py index d47a4f5f4..1db5e59ce 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -21,6 +21,7 @@ import tempfile import subprocess import urllib import optparse +import math import os import re @@ -59,6 +60,14 @@ def get_dd_path(): return dd_path return 'dd' +def int_ceil_div(num, den): + return int(math.ceil(float(num)/float(den))) + +def get_tmp_file(): + tmp = tempfile.mkstemp() + os.close(tmp[0]) + return tmp[1] + ######################################################################## # list possible devices ######################################################################## @@ -136,10 +145,12 @@ def get_raw_device_hints(): # write and verify with dd ######################################################################## def verify_image(image_file, device_file, offset): - #create a temporary file to store the readback - tmp = tempfile.mkstemp() - os.close(tmp[0]) - tmp_file = tmp[1] + #create a temporary file to store the readback image + tmp_file = get_tmp_file() + + #read the image data + img_data = open(image_file, 'rb').read() + count = int_ceil_div(len(img_data), SECTOR_SIZE) #execute a dd subprocess verbose = command( @@ -148,24 +159,33 @@ def verify_image(image_file, device_file, offset): "if=%s"%device_file, "skip=%d"%(offset/SECTOR_SIZE), "bs=%d"%SECTOR_SIZE, - "count=%d"%(MAX_FILE_SIZE/SECTOR_SIZE), + "count=%d"%count, ) - #read in the image and readback - img_data = open(image_file, 'rb').read() - tmp_data = open(tmp_file, 'rb').read(len(img_data)) - #verfy the data + tmp_data = open(tmp_file, 'rb').read(len(img_data)) if img_data != tmp_data: return 'Verification Failed:\n%s'%verbose return 'Verification Passed:\n%s'%verbose def write_image(image_file, device_file, offset): + #create a temporary file to store the padded image + tmp_file = get_tmp_file() + + #write the padded image data + img_data = open(image_file, 'rb').read() + count = int_ceil_div(len(img_data), SECTOR_SIZE) + pad_len = SECTOR_SIZE*count - len(img_data) + pad_str = ''.join([chr(0)]*pad_len) #zero-padding + open(tmp_file, 'wb').write(img_data + pad_str) + + #execute a dd subprocess verbose = command( get_dd_path(), - "if=%s"%image_file, + "if=%s"%tmp_file, "of=%s"%device_file, "seek=%d"%(offset/SECTOR_SIZE), "bs=%d"%SECTOR_SIZE, + "count=%d"%count, ) try: #exec the sync command (only works on linux) diff --git a/host/utils/usrp2_card_burner_gui.py b/host/utils/usrp2_card_burner_gui.py index 61fbadbe3..58b7a514a 100755 --- a/host/utils/usrp2_card_burner_gui.py +++ b/host/utils/usrp2_card_burner_gui.py @@ -17,7 +17,7 @@ # import usrp2_card_burner #import implementation -import Tkinter, Tkconstants, tkFileDialog, tkFont, tkMessageBox +import Tkinter, tkFileDialog, tkFont, tkMessageBox import os class BinFileEntry(Tkinter.Frame): @@ -53,7 +53,7 @@ class BinFileEntry(Tkinter.Frame): class DeviceEntryWidget(Tkinter.Frame): """ - Simple entry widget for getting the raw device name. + Simple entry widget for getting the raw device name. Combines a label, entry, and helpful text box with hints. """ diff --git a/images/.gitignore b/images/.gitignore new file mode 100644 index 000000000..8947b7a83 --- /dev/null +++ b/images/.gitignore @@ -0,0 +1,2 @@ +/build +/images diff --git a/images/CMakeLists.txt b/images/CMakeLists.txt new file mode 100644 index 000000000..75cb4c9d3 --- /dev/null +++ b/images/CMakeLists.txt @@ -0,0 +1,42 @@ +# +# Copyright 2010 Ettus Research LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(UHD-images NONE) + +######################################################################## +# Config Files (include order is important) +######################################################################## +INCLUDE(${CMAKE_SOURCE_DIR}/../host/config/Python.cmake) +INCLUDE(${CMAKE_SOURCE_DIR}/../host/config/Version.cmake) + +######################################################################## +# Setup CPack +######################################################################## +SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Ettus Research - Universal Hardware Driver Images") +SET(CPACK_PACKAGE_VENDOR "Ettus Research LLC") +SET(CPACK_PACKAGE_CONTACT "support@ettus.com") +SET(CPACK_PACKAGE_VERSION_MAJOR ${UHD_VERSION_MAJOR}) +SET(CPACK_PACKAGE_VERSION_MINOR ${UHD_VERSION_MINOR}) +SET(CPACK_PACKAGE_VERSION_PATCH ${UHD_VERSION_PATCH}) +INCLUDE(CPack) #include after setting vars +MESSAGE(STATUS "Version: ${CPACK_PACKAGE_VERSION}") + +######################################################################## +# Install Images +######################################################################## +INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/images DESTINATION share/uhd) diff --git a/images/Makefile b/images/Makefile new file mode 100644 index 000000000..6ab54e6ac --- /dev/null +++ b/images/Makefile @@ -0,0 +1,86 @@ +# +# Copyright 2010 Ettus Research LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +all: + @echo "Pick a specific target" + +######################################################################## +# Common Variables +######################################################################## +TOP_DIR = $(shell pwd) +TOP_FW_DIR = $(TOP_DIR)/../firmware +TOP_FPGA_DIR = $(TOP_DIR)/../fpga +BUILT_IMAGES_DIR = $(TOP_DIR)/images +CMAKE_BUILD_DIR = $(TOP_DIR)/build + +##filled in below +IMAGES_LIST = + +######################################################################## +# USRP2 firmware +######################################################################## +_usrp2_fw_dir = $(TOP_FW_DIR)/microblaze +_usrp2_fw_bin = $(BUILT_IMAGES_DIR)/usrp2_fw.bin +IMAGES_LIST += $(_usrp2_fw_bin) + +$(_usrp2_fw_bin): + cd $(_usrp2_fw_dir) && ./bootstrap + cd $(_usrp2_fw_dir) && ./configure --host=mb + make -C $(_usrp2_fw_dir) clean + make -C $(_usrp2_fw_dir) all + cp $(_usrp2_fw_dir)/usrp2/usrp2_txrx_uhd.bin $@ + +######################################################################## +# USRP2 fpga +######################################################################## +_usrp2_fpga_dir = $(TOP_FPGA_DIR)/usrp2/top/u2_rev3 +_usrp2_fpga_bin = $(BUILT_IMAGES_DIR)/usrp2_fpga.bin +IMAGES_LIST += $(_usrp2_fpga_bin) + +$(_usrp2_fpga_bin): + cd $(_usrp2_fpga_dir) && make -f Makefile.udp clean + cd $(_usrp2_fpga_dir) && make -f Makefile.udp bin + cp $(_usrp2_fpga_dir)/build-udp/u2_rev3.bin $@ + +######################################################################## +# Build rules +######################################################################## +##little rule to make the images directory +$(BUILT_IMAGES_DIR): + mkdir $@ + +images: $(BUILT_IMAGES_DIR) $(IMAGES_LIST) + +clean: + $(RM) -rf $(BUILT_IMAGES_DIR) + $(RM) -rf $(CMAKE_BUILD_DIR) + +#packages that a linux machine can build +linux-packages: + mkdir -p $(CMAKE_BUILD_DIR) + + cd $(CMAKE_BUILD_DIR) && cmake -DCPACK_GENERATOR=TGZ $(TOP_DIR) + make -C $(CMAKE_BUILD_DIR) package + + cd $(CMAKE_BUILD_DIR) && cmake -DCPACK_GENERATOR=ZIP $(TOP_DIR) + make -C $(CMAKE_BUILD_DIR) package + + cd $(CMAKE_BUILD_DIR) && cmake -DCPACK_GENERATOR=DEB $(TOP_DIR) + make -C $(CMAKE_BUILD_DIR) package + + cd $(CMAKE_BUILD_DIR) && cmake -DCPACK_GENERATOR=RPM $(TOP_DIR) + make -C $(CMAKE_BUILD_DIR) package diff --git a/images/README b/images/README new file mode 100644 index 000000000..ec8391826 --- /dev/null +++ b/images/README @@ -0,0 +1,20 @@ +The images directory contains the following: + - a Makefile for building firmware and fpga images + - a CMake file for building an images package + +The Makefile and build systems for the images are probably Unix specific. +Its best to build the images on a Unix system with standard build tools. +The CMake package target will create an images package for your system. + +To build the images (unix): + make clean + make images + +To build the package (unix): + mkdir build + cd build + cmake -DCPACK_GENERATOR=<type> ../ + make package + +The package generator types are described here: + http://www.cmake.org/Wiki/CMake:CPackPackageGenerators |