├── README.md ├── fpga-src ├── README.md ├── noc_block_cir_avg.v ├── noc_block_cir_avg_tb │ ├── Makefile │ └── noc_block_cir_avg_tb.sv ├── noc_block_correlator.v ├── noc_block_correlator_tb │ ├── Makefile │ └── noc_block_correlator_tb.sv ├── noc_block_spec_spreader.v └── noc_block_spec_spreader_tb │ ├── Makefile │ └── noc_block_spec_spreader_tb.sv ├── hls-projects ├── averaging │ ├── averaging.cpp │ ├── rfnoc.h │ └── script.tcl ├── correlator │ ├── README.md │ ├── correlator.cpp │ ├── rfnoc.h │ └── script.tcl ├── pn_seq_gen_lfsr │ ├── README.md │ ├── pn_seq_gen_lfsr.cpp │ └── script.tcl └── spreader │ ├── README.md │ ├── rfnoc.h │ ├── script.tcl │ └── spreader.cpp └── host ├── blocks ├── cir_avg.xml ├── cir_avg_block_ctrl.hpp ├── cir_avg_block_ctrl_impl.cpp ├── correlator.xml ├── correlator_block_ctrl.hpp ├── correlator_block_ctrl_impl.cpp ├── spec_spreader.xml ├── spec_spreader_block_ctrl.hpp └── spec_spreader_block_ctrl_impl.cpp └── examples ├── rfnoc_multi_chan_correlator.cpp └── rfnoc_spreader.cpp /README.md: -------------------------------------------------------------------------------- 1 | # RFNoC-HLS-WINLAB 2 | 3 | Bhargav Gokalgandhi bvg8@scarletmail.rutgers.edu 4 | 5 | Prasanthi Maddala prasanti@winlab.rutgers.edu 6 | 7 | Ivan Seskar seskar@winlab.rutgers.edu 8 | 9 | ## Introduction 10 | This project aims at building a real-time wide band channel sounder using USRPs, which computes the power delay profile of a multi-path channel, and focuses mainly on large scale antenna systems as shown below. This channel sounder is used for computation of the power delay profile of a multipath channel in a massive multiple antenna system in the ORCA framework (https://www.orca-project.eu/). 11 | 12 | ![channel_sounding_demo](https://user-images.githubusercontent.com/9439021/27981986-ee9480fa-6364-11e7-8bd5-c1f9374eb964.jpg) 13 | 14 | A spread spectrum channel sounder as shown below is implemented. 15 | ![channel_sounder_block_diagram](https://user-images.githubusercontent.com/9439021/27981984-e9af8008-6364-11e7-981e-91cf151f054d.jpg) 16 | 17 | To enable real-time channel sounding at multiple receive antennas at high bandwidths, the computationally intensive task of correlation has been moved to the FPGA. Also, the correlation power (output of correlation module) obtained is averaged over a given number of data symbols in order to reduce the USRP to host data rate. 18 | 19 | The system has been tested using USRP X310s on ORBIT testbed. All the X310s in the testbed are synchronized with an external reference clock. 20 | 21 | ## RFNoC Blocks implemented 22 | 23 | 1) [Spreader](hls-projects/spreader/README.md) 24 | 2) [Correlator](hls-projects/correlator/README.md) 25 | 3) Averaging Block 26 | 27 | ## Steps to build Channel sounder 28 | 29 | 1) Generate HDL using Vivado HLS 30 |   Go to each of the 4 HLS projects (@hls-projects) and run script.tcl - vivado_hls script.tcl 31 |   Generated verilog files can be found @solution1/syn/verilog of each folder. 32 | NOTE : while generating correlator uncomment either COR_SIZE_256 or COR_SIZE_512 to select a size 256 or size 512 correlator 33 | 34 | 2) Move HDL files 35 | Move all the contents of fpga-src folder to your local RFNoC installation folder uhd/fpga-src/usrp3/lib/rfnoc/ 36 | Move all the HLS generated verilog files (from all the 4 projects) to uhd/fpga-src/usrp3/lib/rfnoc/ 37 | 38 | 3) Test NoC Blocks 39 | In uhd/fpga-src/usrp3/lib/rfnoc/, go to each test bench folder (noc_block_spec_spreader_tb) and run make vsim to run the test bench using Modelsim or run make xsim to use Vivado simulator. 40 | 41 | 4) Build Channel sounder Tx 42 | In uhd/fpga-src/usrp3/tools/scripts/ run 43 | ./uhd_image_builder.py duc spec_spreader -m 4 --fill-with-fifos -d x310 -t X310_RFNOC_HG 44 | 45 | 5) Build Channel sounder Rx 46 | To use 1 Rx channel in X310 - In uhd/fpga-src/usrp3/tools/scripts/ run 47 | ./uhd_image_builder.py ddc correlator cir_avg -m 4 --fill-with-fifos -d x310 -t X310_RFNOC_HG 48 | 49 | To use 2 Rx channels in X310 - In uhd/fpga-src/usrp3/tools/scripts/ run 50 | ./uhd_image_builder.py ddc ddc correlator correlator cir_avg cir_avg -m 7 --fill-with-fifos -d x310 -t X310_RFNOC_HG 51 | 52 | ## Run the Channel sounder 53 | Host side application files for the transmit and receive hosts can be found at host/examples. These files and how to run them will be explained in detail in the demo video which will be posted soon. 54 | -------------------------------------------------------------------------------- /fpga-src/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## fpga-src 3 | 4 | This folder contains all the noc_block verilog files and test benches for each of them. To run the test benches, all these files can be moved to /uhd/fpga-src/usrp3/lib/rfnoc of your local UHD (with RFNoC) installation. 5 | -------------------------------------------------------------------------------- /fpga-src/noc_block_cir_avg.v: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /*noc_block_cir_avg.v - used noc_block_skeleton.v as a template to wrap Vivado HLS generated module, avergaing.v into a noc_block. 24 | */ 25 | 26 | module noc_block_cir_avg #( 27 | parameter NOC_ID = 64'hFFFF_C200_0000_0000, 28 | parameter STR_SINK_FIFOSIZE = 11) 29 | ( 30 | input bus_clk, input bus_rst, 31 | input ce_clk, input ce_rst, 32 | input [63:0] i_tdata, input i_tlast, input i_tvalid, output i_tready, 33 | output [63:0] o_tdata, output o_tlast, output o_tvalid, input o_tready, 34 | output [63:0] debug 35 | ); 36 | 37 | //////////////////////////////////////////////////////////// 38 | // 39 | // RFNoC Shell 40 | // 41 | //////////////////////////////////////////////////////////// 42 | wire [31:0] set_data; 43 | wire [7:0] set_addr; 44 | wire set_stb; 45 | reg [63:0] rb_data; 46 | wire [7:0] rb_addr; 47 | 48 | wire [63:0] cmdout_tdata, ackin_tdata; 49 | wire cmdout_tlast, cmdout_tvalid, cmdout_tready, ackin_tlast, ackin_tvalid, ackin_tready; 50 | 51 | wire [63:0] str_sink_tdata, str_src_tdata; 52 | wire str_sink_tlast, str_sink_tvalid, str_sink_tready, str_src_tlast, str_src_tvalid, str_src_tready; 53 | 54 | wire clear_tx_seqnum; 55 | wire [15:0] next_dst_sid; 56 | 57 | noc_shell #( 58 | .NOC_ID(NOC_ID), 59 | .STR_SINK_FIFOSIZE(STR_SINK_FIFOSIZE)) 60 | noc_shell ( 61 | .bus_clk(bus_clk), .bus_rst(bus_rst), 62 | .i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready), 63 | .o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready), 64 | // Computer Engine Clock Domain 65 | .clk(ce_clk), .reset(ce_rst), 66 | // Control Sink 67 | .set_data(set_data), .set_addr(set_addr), .set_stb(set_stb), .set_time(), 68 | .rb_stb(1'b1), .rb_data(rb_data), .rb_addr(rb_addr), 69 | // Control Source 70 | .cmdout_tdata(cmdout_tdata), .cmdout_tlast(cmdout_tlast), .cmdout_tvalid(cmdout_tvalid), .cmdout_tready(cmdout_tready), 71 | .ackin_tdata(ackin_tdata), .ackin_tlast(ackin_tlast), .ackin_tvalid(ackin_tvalid), .ackin_tready(ackin_tready), 72 | // Stream Sink 73 | .str_sink_tdata(str_sink_tdata), .str_sink_tlast(str_sink_tlast), .str_sink_tvalid(str_sink_tvalid), .str_sink_tready(str_sink_tready), 74 | // Stream Source 75 | .str_src_tdata(str_src_tdata), .str_src_tlast(str_src_tlast), .str_src_tvalid(str_src_tvalid), .str_src_tready(str_src_tready), 76 | // Misc 77 | .vita_time(64'd0), .clear_tx_seqnum(clear_tx_seqnum), 78 | .src_sid(), .next_dst_sid(next_dst_sid), .resp_in_dst_sid(), .resp_out_dst_sid(), 79 | .debug(debug)); 80 | 81 | //////////////////////////////////////////////////////////// 82 | // 83 | // AXI Wrapper 84 | // Convert RFNoC Shell interface into AXI stream interface 85 | // 86 | //////////////////////////////////////////////////////////// 87 | localparam NUM_AXI_CONFIG_BUS = 1; 88 | 89 | wire [31:0] m_axis_data_tdata; 90 | wire m_axis_data_tlast; 91 | wire m_axis_data_tvalid; 92 | wire m_axis_data_tready; 93 | 94 | wire [31:0] s_axis_data_tdata; 95 | wire s_axis_data_tlast; 96 | wire s_axis_data_tvalid; 97 | wire s_axis_data_tready; 98 | 99 | wire [31:0] m_axis_config_tdata; 100 | wire m_axis_config_tvalid; 101 | wire m_axis_config_tready; 102 | 103 | localparam AXI_WRAPPER_BASE = 128; 104 | localparam SR_AXI_CONFIG_BASE = AXI_WRAPPER_BASE + 1; 105 | 106 | axi_wrapper #( 107 | .SIMPLE_MODE(1), 108 | .SR_AXI_CONFIG_BASE(SR_AXI_CONFIG_BASE), 109 | .NUM_AXI_CONFIG_BUS(NUM_AXI_CONFIG_BUS)) 110 | inst_axi_wrapper ( 111 | .clk(ce_clk), .reset(ce_rst), 112 | .clear_tx_seqnum(clear_tx_seqnum), 113 | .next_dst(next_dst_sid), 114 | .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), 115 | .i_tdata(str_sink_tdata), .i_tlast(str_sink_tlast), .i_tvalid(str_sink_tvalid), .i_tready(str_sink_tready), 116 | .o_tdata(str_src_tdata), .o_tlast(str_src_tlast), .o_tvalid(str_src_tvalid), .o_tready(str_src_tready), 117 | .m_axis_data_tdata(m_axis_data_tdata), 118 | .m_axis_data_tlast(m_axis_data_tlast), 119 | .m_axis_data_tvalid(m_axis_data_tvalid), 120 | .m_axis_data_tready(m_axis_data_tready), 121 | .m_axis_data_tuser(), 122 | .s_axis_data_tdata(s_axis_data_tdata), 123 | .s_axis_data_tlast(s_axis_data_tlast), 124 | .s_axis_data_tvalid(s_axis_data_tvalid), 125 | .s_axis_data_tready(s_axis_data_tready), 126 | .s_axis_data_tuser(), 127 | .m_axis_config_tdata(m_axis_config_tdata), 128 | .m_axis_config_tlast(), 129 | .m_axis_config_tvalid(m_axis_config_tvalid), 130 | .m_axis_config_tready(m_axis_config_tready), 131 | .m_axis_pkt_len_tdata(), 132 | .m_axis_pkt_len_tvalid(), 133 | .m_axis_pkt_len_tready()); 134 | 135 | //////////////////////////////////////////////////////////// 136 | // 137 | // User code 138 | // 139 | //////////////////////////////////////////////////////////// 140 | 141 | // Control Source Unused 142 | assign cmdout_tdata = 64'd0; 143 | assign cmdout_tlast = 1'b0; 144 | assign cmdout_tvalid = 1'b0; 145 | assign ackin_tready = 1'b1; 146 | 147 | localparam [7:0] SR_BLOCK_RESET = 131; 148 | localparam [7:0] SR_THRESHOLD = 132; 149 | localparam [7:0] SR_AVG_SIZE_SEQ_LEN = 133; 150 | 151 | wire block_reset; 152 | wire [31:0] threshold; 153 | wire [13:0] avg_size_seq_len ; 154 | setting_reg #( 155 | .my_addr(SR_BLOCK_RESET), .awidth(8), .width(1)) 156 | sr_block_reset ( 157 | .clk(ce_clk), .rst(ce_rst), 158 | .strobe(set_stb), .addr(set_addr), .in(set_data), .out(block_reset), .changed()); 159 | 160 | setting_reg #( 161 | .my_addr(SR_THRESHOLD), .awidth(8), .width(32)) 162 | sr_gen_poly ( 163 | .clk(ce_clk), .rst(ce_rst), 164 | .strobe(set_stb), .addr(set_addr), .in(set_data), .out(threshold), .changed());// input sample Threshold 165 | 166 | setting_reg #( 167 | .my_addr(SR_AVG_SIZE_SEQ_LEN), .awidth(8), .width(13)) 168 | sr_gen_seed( 169 | .clk(ce_clk), .rst(ce_rst), 170 | .strobe(set_stb), .addr(set_addr), .in(set_data), .out(avg_size_seq_len), .changed());// [12:10] - log2(averaging_factor) enter 4 for an averaging factor of 16, [9:0] - pn sequence length/packet length 171 | 172 | wire[2:0] log_avg_size = avg_size_seq_len[12:10]; 173 | wire[9:0] seq_len = avg_size_seq_len[9:0]; 174 | 175 | averaging inst_cir_avg( 176 | .ap_clk(ce_clk), .ap_rst_n(~(ce_rst | block_reset)), 177 | .i_data_TDATA(m_axis_data_tdata), // 32 bit integer 178 | .i_data_TVALID(m_axis_data_tvalid), 179 | .i_data_TREADY(m_axis_data_tready), 180 | .i_data_TLAST(m_axis_data_tlast), 181 | .o_data_TDATA(s_axis_data_tdata), // 32 bit integer 182 | .o_data_TVALID(s_axis_data_tvalid), 183 | .o_data_TREADY(s_axis_data_tready), 184 | .o_data_TLAST(s_axis_data_tlast), 185 | .seq_len_V(seq_len), 186 | .threshold_V(threshold), 187 | .log_avg_size_V(log_avg_size) 188 | ); 189 | 190 | 191 | // Readback registers 192 | always @* 193 | case(rb_addr) 194 | 8'd0 : rb_data <= {63'd0, block_reset}; 195 | 8'd1 : rb_data <= {32'd0, threshold}; 196 | 8'd2 : rb_data <= {51'd0, avg_size_seq_len}; 197 | default : rb_data <= 64'h0BADC0DE0BADC0DE; 198 | endcase 199 | 200 | endmodule 201 | -------------------------------------------------------------------------------- /fpga-src/noc_block_cir_avg_tb/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016 Ettus Research 3 | # 4 | 5 | #------------------------------------------------- 6 | # Top-of-Makefile 7 | #------------------------------------------------- 8 | # Define BASE_DIR to point to the "top" dir 9 | BASE_DIR = $(abspath ../../../top) 10 | # Include viv_sim_preample after defining BASE_DIR 11 | include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak 12 | 13 | #------------------------------------------------- 14 | # IP Specific 15 | #------------------------------------------------- 16 | # If simulation contains IP, define the IP_DIR and point 17 | # it to the base level IP directory 18 | LIB_IP_DIR = $(BASE_DIR)/../lib/ip 19 | 20 | # Include makefiles and sources for all IP components 21 | # *after* defining the LIB_IP_DIR 22 | 23 | 24 | #------------------------------------------------- 25 | # Testbench Specific 26 | #------------------------------------------------- 27 | # Define only one toplevel module 28 | SIM_TOP = noc_block_correlator_tb 29 | 30 | # Add test bench, user design under test, and 31 | # additional user created files 32 | SIM_SRCS = \ 33 | $(abspath noc_block_cir_avg_tb.sv) 34 | 35 | MODELSIM_USER_DO = $(abspath wave.do) 36 | 37 | #------------------------------------------------- 38 | # Bottom-of-Makefile 39 | #------------------------------------------------- 40 | # Include all simulator specific makefiles here 41 | # Each should define a unique target to simulate 42 | # e.g. xsim, vsim, etc and a common "clean" target 43 | include $(BASE_DIR)/../tools/make/viv_simulator.mak 44 | -------------------------------------------------------------------------------- /fpga-src/noc_block_cir_avg_tb/noc_block_cir_avg_tb.sv: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /*noc_block_cir_avg_tb.sv - used noc_block_skeleton.sv as a template. 24 | Test bench for the cir_avg(averaging) NOC block. 25 | */ 26 | 27 | `timescale 1ns/1ps 28 | `define SIM_TIMEOUT_US 50000 29 | `define NS_PER_TICK 1 30 | `define NUM_TEST_CASES 7 31 | `include "sim_exec_report.vh" 32 | `include "sim_rfnoc_lib.svh" 33 | 34 | 35 | typedef logic pn_seq_t[$]; 36 | typedef logic[31:0] sample_t[$]; 37 | 38 | module noc_block_cir_avg_tb(); 39 | 40 | function pn_seq_t get_pn_seq(int seq_len, int gen_poly, int gen_order, int gen_seed); 41 | logic [9:0] shift_reg, tmp_reg; 42 | logic new_bit; 43 | pn_seq_t seq; 44 | begin 45 | shift_reg = gen_seed; 46 | for(int i = 0; i>= 1; 52 | shift_reg[9] = new_bit; 53 | $display ("sequence[%d] - %b", i,seq[i]); 54 | end 55 | end 56 | return seq; 57 | endfunction 58 | 59 | function sample_t get_random_samples(int num_samples); 60 | sample_t sample; 61 | begin 62 | for(int i = 0; i Spreader -> Correlator -> cir_avg -> Test bench 161 | `RFNOC_CONNECT(noc_block_tb /* From */, noc_block_spec_spreader /* To */, SC16 /* Type */, 256 /* Samples per packet */); 162 | `RFNOC_CONNECT(noc_block_spec_spreader, noc_block_correlator, SC16, 512); 163 | `RFNOC_CONNECT(noc_block_correlator, noc_block_cir_avg, SC16, 512); 164 | `RFNOC_CONNECT(noc_block_cir_avg,noc_block_tb,SC16,260); 165 | `TEST_CASE_DONE(1); 166 | 167 | /******************************************************************* 168 | ** Test 4 -- Set up the module by writing to the setting registers 169 | ********************************************************************/ 170 | `TEST_CASE_START("Write to setting registers"); 171 | tb_streamer.write_reg(sid_noc_block_cir_avg, noc_block_cir_avg.SR_THRESHOLD, threshold); 172 | tb_streamer.write_reg(sid_noc_block_cir_avg, noc_block_cir_avg.SR_AVG_SIZE_SEQ_LEN, avg_size_seq_len); 173 | 174 | tb_streamer.write_reg(sid_noc_block_correlator, noc_block_correlator.SR_GEN_SEED_POLY, gen_seed_poly); 175 | tb_streamer.write_reg(sid_noc_block_correlator, noc_block_correlator.SR_GEN_ORDER_LEN, gen_order_len); 176 | tb_streamer.write_reg(sid_noc_block_correlator, noc_block_correlator.SR_BLOCK_START, 1); 177 | tb_streamer.write_reg(sid_noc_block_correlator, noc_block_correlator.SR_BLOCK_START, 0); 178 | 179 | tb_streamer.write_reg(sid_noc_block_spec_spreader, noc_block_spec_spreader.SR_GEN_SEED_POLY, gen_seed_poly); 180 | tb_streamer.write_reg(sid_noc_block_spec_spreader, noc_block_spec_spreader.SR_GEN_ORDER_LEN, gen_order_len); 181 | `TEST_CASE_DONE(1); 182 | 183 | /******************************************************** 184 | ** Test 5 -- Send Samples 185 | ********************************************************/ 186 | `TEST_CASE_START("Send samples"); 187 | fork 188 | begin 189 | sample = get_random_samples(num_samples); 190 | payload = get_payload(sample, num_samples); // 64 bit word i.e., one payload word = 2 samples 191 | tb_streamer.send(payload); 192 | end 193 | begin 194 | for(int n = 0; n < 7 ; n++) begin 195 | for(int i = 0; i < seq_len ; i++) begin 196 | tb_streamer.pull_word({out_val},last); 197 | end 198 | $display("Out pkt : %d", n); 199 | end 200 | end 201 | join 202 | `TEST_CASE_DONE(1); 203 | 204 | /******************************************************************* 205 | ** Test 6 -- Reset the module and set new parameters 206 | ********************************************************************/ 207 | `TEST_CASE_START("Write to setting registers"); 208 | tb_streamer.write_reg(sid_noc_block_cir_avg, noc_block_cir_avg.SR_BLOCK_RESET, 1'b1); 209 | #100 210 | tb_streamer.write_reg(sid_noc_block_cir_avg, noc_block_cir_avg.SR_BLOCK_RESET, 1'b0); 211 | #100 212 | tb_streamer.write_reg(sid_noc_block_cir_avg, noc_block_cir_avg.SR_THRESHOLD, threshold); 213 | tb_streamer.write_reg(sid_noc_block_cir_avg, noc_block_cir_avg.SR_AVG_SIZE_SEQ_LEN, avg_size_seq_len1); 214 | 215 | tb_streamer.write_reg(sid_noc_block_correlator, noc_block_correlator.SR_BLOCK_RESET, 1'b1); 216 | #100 217 | tb_streamer.write_reg(sid_noc_block_correlator, noc_block_correlator.SR_BLOCK_RESET, 1'b0); 218 | #100 219 | tb_streamer.write_reg(sid_noc_block_correlator, noc_block_correlator.SR_GEN_SEED_POLY, gen_seed_poly1); 220 | tb_streamer.write_reg(sid_noc_block_correlator, noc_block_correlator.SR_GEN_ORDER_LEN, gen_order_len1); 221 | tb_streamer.write_reg(sid_noc_block_correlator, noc_block_correlator.SR_BLOCK_START, 1); 222 | tb_streamer.write_reg(sid_noc_block_correlator, noc_block_correlator.SR_BLOCK_START, 0); 223 | 224 | tb_streamer.write_reg(sid_noc_block_spec_spreader, noc_block_spec_spreader.SR_BLOCK_RESET, 1'b1); 225 | #100 226 | tb_streamer.write_reg(sid_noc_block_spec_spreader, noc_block_spec_spreader.SR_BLOCK_RESET, 1'b0); 227 | #100 228 | tb_streamer.write_reg(sid_noc_block_spec_spreader, noc_block_spec_spreader.SR_GEN_SEED_POLY, gen_seed_poly1); 229 | tb_streamer.write_reg(sid_noc_block_spec_spreader, noc_block_spec_spreader.SR_GEN_ORDER_LEN, gen_order_len1); 230 | 231 | `TEST_CASE_DONE(1); 232 | 233 | /******************************************************** 234 | ** Test 7 -- Send Samples 235 | ********************************************************/ 236 | `TEST_CASE_START("Send samples"); 237 | avg_size = 2^log_avg_size1; 238 | fork 239 | begin 240 | sample = get_random_samples(num_samples1); 241 | payload = get_payload(sample, num_samples1); // 64 bit word i.e., one payload word = 2 samples 242 | tb_streamer.send(payload); 243 | end 244 | begin 245 | for(int n = 0; n < ((num_samples1)/(avg_size)) ; n++) begin 246 | for(int i = 0; i < seq_len1 ; i++) begin 247 | tb_streamer.pull_word({out_val},last); 248 | end 249 | end 250 | end 251 | join 252 | `TEST_CASE_DONE(1); 253 | 254 | 255 | `TEST_BENCH_DONE; 256 | end 257 | endmodule 258 | -------------------------------------------------------------------------------- /fpga-src/noc_block_correlator.v: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /*noc_block_correlator.v - used noc_block_skeleton.v as a template to wrap 24 | Vivado HLS generated modules, correlator.v and pn_seq_gen_lfsr.v into a noc_block. 25 | */ 26 | 27 | module noc_block_correlator #( 28 | parameter NOC_ID = 64'hFFFF_C100_0000_0000, 29 | parameter STR_SINK_FIFOSIZE = 11) 30 | ( 31 | input bus_clk, input bus_rst, 32 | input ce_clk, input ce_rst, 33 | input [63:0] i_tdata, input i_tlast, input i_tvalid, output i_tready, 34 | output [63:0] o_tdata, output o_tlast, output o_tvalid, input o_tready, 35 | output [63:0] debug 36 | ); 37 | 38 | //////////////////////////////////////////////////////////// 39 | // 40 | // RFNoC Shell 41 | // 42 | //////////////////////////////////////////////////////////// 43 | wire [31:0] set_data; 44 | wire [7:0] set_addr; 45 | wire set_stb; 46 | reg [63:0] rb_data; 47 | wire [7:0] rb_addr; 48 | 49 | wire [63:0] cmdout_tdata, ackin_tdata; 50 | wire cmdout_tlast, cmdout_tvalid, cmdout_tready, ackin_tlast, ackin_tvalid, ackin_tready; 51 | 52 | wire [63:0] str_sink_tdata, str_src_tdata; 53 | wire str_sink_tlast, str_sink_tvalid, str_sink_tready, str_src_tlast, str_src_tvalid, str_src_tready; 54 | 55 | wire clear_tx_seqnum; 56 | wire [15:0] next_dst_sid; 57 | 58 | noc_shell #( 59 | .NOC_ID(NOC_ID), 60 | .STR_SINK_FIFOSIZE(STR_SINK_FIFOSIZE)) 61 | noc_shell ( 62 | .bus_clk(bus_clk), .bus_rst(bus_rst), 63 | .i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready), 64 | .o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready), 65 | // Computer Engine Clock Domain 66 | .clk(ce_clk), .reset(ce_rst), 67 | // Control Sink 68 | .set_data(set_data), .set_addr(set_addr), .set_stb(set_stb), .set_time(), 69 | .rb_stb(1'b1), .rb_data(rb_data), .rb_addr(rb_addr), 70 | // Control Source 71 | .cmdout_tdata(cmdout_tdata), .cmdout_tlast(cmdout_tlast), .cmdout_tvalid(cmdout_tvalid), .cmdout_tready(cmdout_tready), 72 | .ackin_tdata(ackin_tdata), .ackin_tlast(ackin_tlast), .ackin_tvalid(ackin_tvalid), .ackin_tready(ackin_tready), 73 | // Stream Sink 74 | .str_sink_tdata(str_sink_tdata), .str_sink_tlast(str_sink_tlast), .str_sink_tvalid(str_sink_tvalid), .str_sink_tready(str_sink_tready), 75 | // Stream Source 76 | .str_src_tdata(str_src_tdata), .str_src_tlast(str_src_tlast), .str_src_tvalid(str_src_tvalid), .str_src_tready(str_src_tready), 77 | // Misc 78 | .vita_time(64'd0), .clear_tx_seqnum(clear_tx_seqnum), 79 | .src_sid(), .next_dst_sid(next_dst_sid), .resp_in_dst_sid(), .resp_out_dst_sid(), 80 | .debug(debug)); 81 | 82 | //////////////////////////////////////////////////////////// 83 | // 84 | // AXI Wrapper 85 | // Convert RFNoC Shell interface into AXI stream interface 86 | // 87 | //////////////////////////////////////////////////////////// 88 | localparam NUM_AXI_CONFIG_BUS = 1; 89 | 90 | wire [31:0] m_axis_data_tdata; 91 | wire m_axis_data_tlast; 92 | wire m_axis_data_tvalid; 93 | wire m_axis_data_tready; 94 | 95 | wire [31:0] s_axis_data_tdata; 96 | wire s_axis_data_tlast; 97 | wire s_axis_data_tvalid; 98 | wire s_axis_data_tready; 99 | 100 | wire [31:0] m_axis_config_tdata; 101 | wire m_axis_config_tvalid; 102 | wire m_axis_config_tready; 103 | 104 | localparam AXI_WRAPPER_BASE = 128; 105 | localparam SR_AXI_CONFIG_BASE = AXI_WRAPPER_BASE + 1; 106 | 107 | axi_wrapper #( 108 | .SIMPLE_MODE(1), 109 | .SR_AXI_CONFIG_BASE(SR_AXI_CONFIG_BASE), 110 | .NUM_AXI_CONFIG_BUS(NUM_AXI_CONFIG_BUS)) 111 | inst_axi_wrapper ( 112 | .clk(ce_clk), .reset(ce_rst), 113 | .clear_tx_seqnum(clear_tx_seqnum), 114 | .next_dst(next_dst_sid), 115 | .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), 116 | .i_tdata(str_sink_tdata), .i_tlast(str_sink_tlast), .i_tvalid(str_sink_tvalid), .i_tready(str_sink_tready), 117 | .o_tdata(str_src_tdata), .o_tlast(str_src_tlast), .o_tvalid(str_src_tvalid), .o_tready(str_src_tready), 118 | .m_axis_data_tdata(m_axis_data_tdata), 119 | .m_axis_data_tlast(m_axis_data_tlast), 120 | .m_axis_data_tvalid(m_axis_data_tvalid), 121 | .m_axis_data_tready(m_axis_data_tready), 122 | .m_axis_data_tuser(), 123 | .s_axis_data_tdata(s_axis_data_tdata), 124 | .s_axis_data_tlast(s_axis_data_tlast), 125 | .s_axis_data_tvalid(s_axis_data_tvalid), 126 | .s_axis_data_tready(s_axis_data_tready), 127 | .s_axis_data_tuser(), 128 | .m_axis_config_tdata(m_axis_config_tdata), 129 | .m_axis_config_tlast(), 130 | .m_axis_config_tvalid(m_axis_config_tvalid), 131 | .m_axis_config_tready(m_axis_config_tready), 132 | .m_axis_pkt_len_tdata(), 133 | .m_axis_pkt_len_tvalid(), 134 | .m_axis_pkt_len_tready()); 135 | 136 | //////////////////////////////////////////////////////////// 137 | // 138 | // User code 139 | // 140 | //////////////////////////////////////////////////////////// 141 | 142 | // Control Source Unused 143 | assign cmdout_tdata = 64'd0; 144 | assign cmdout_tlast = 1'b0; 145 | assign cmdout_tvalid = 1'b0; 146 | assign ackin_tready = 1'b1; 147 | 148 | localparam [7:0] SR_BLOCK_RESET = 131; 149 | localparam [7:0] SR_BLOCK_START = 132; 150 | localparam [7:0] SR_GEN_SEED_POLY = 133; 151 | localparam [7:0] SR_GEN_ORDER_LEN = 134; 152 | 153 | wire block_reset; 154 | wire block_start; 155 | wire [19:0] pnseq_gen_seed_poly; 156 | wire [13:0] pnseq_gen_order_len; 157 | setting_reg #( 158 | .my_addr(SR_BLOCK_RESET), .awidth(8), .width(1)) 159 | sr_block_reset ( 160 | .clk(ce_clk), .rst(ce_rst), 161 | .strobe(set_stb), .addr(set_addr), .in(set_data), .out(block_reset), .changed()); 162 | 163 | setting_reg #( 164 | .my_addr(SR_BLOCK_START), .awidth(8), .width(1)) 165 | sr_block_start ( 166 | .clk(ce_clk), .rst(ce_rst), 167 | .strobe(set_stb), .addr(set_addr), .in(set_data), .out(block_start), .changed()); // block start signal 168 | 169 | 170 | setting_reg #( 171 | .my_addr(SR_GEN_SEED_POLY), .awidth(8), .width(20)) 172 | sr_gen_poly ( 173 | .clk(ce_clk), .rst(ce_rst), 174 | .strobe(set_stb), .addr(set_addr), .in(set_data), .out(pnseq_gen_seed_poly), .changed());// [19:10] - seed, [9:0] - generator polynomial 175 | 176 | setting_reg #( 177 | .my_addr(SR_GEN_ORDER_LEN), .awidth(8), .width(14)) 178 | sr_gen_seed( 179 | .clk(ce_clk), .rst(ce_rst), 180 | .strobe(set_stb), .addr(set_addr), .in(set_data), .out(pnseq_gen_order_len), .changed());// [13:10] - polynomial order, [9:0] - pn sequence length 181 | 182 | wire pnseq, pnseq_req, pnseq_load; 183 | wire [9:0] pnseq_gen_seed = pnseq_gen_seed_poly[19:10]; 184 | wire [9:0] pnseq_gen_poly = pnseq_gen_seed_poly[9:0]; 185 | wire [3:0] pnseq_gen_order = pnseq_gen_order_len[13:10]; 186 | wire [9:0] pnseq_len = pnseq_gen_order_len[9:0]; 187 | 188 | reg block_start_reg; 189 | wire block_start_pulse; 190 | // start pulse for the correlator is generated from the user start signal, when it changes from 1 to 0. 191 | always @(posedge ce_clk) begin 192 | if (ce_rst) begin 193 | block_start_reg <= 1'b0; 194 | end else begin 195 | block_start_reg <= block_start; 196 | end 197 | end 198 | 199 | assign block_start_pulse = block_start_reg && (! block_start); 200 | 201 | // pn_seq_gen_lfsr module 202 | pn_seq_gen_lfsr inst_pn_seq_gen_lfsr( 203 | .ap_clk(ce_clk), .ap_rst(ce_rst |block_reset), 204 | .load_V(block_start), // start signal is used as load input 205 | .poly_V(pnseq_gen_poly), 206 | .seed_V(pnseq_gen_seed), 207 | .order_V(pnseq_gen_order), 208 | .pn_req_V(pnseq_req), 209 | .ap_return(pnseq)); 210 | 211 | // correlator module 212 | correlator inst_correlator( 213 | .ap_clk(ce_clk), .ap_rst_n(~(ce_rst | block_reset)), 214 | .i_data_TDATA(m_axis_data_tdata), // SC16 215 | .i_data_TVALID(m_axis_data_tvalid), 216 | .i_data_TREADY(m_axis_data_tready), 217 | .i_data_TLAST(m_axis_data_tlast), 218 | .o_data_TDATA(s_axis_data_tdata), // 32 bit integer 219 | .o_data_TVALID(s_axis_data_tvalid), 220 | .o_data_TREADY(s_axis_data_tready), 221 | .o_data_TLAST(s_axis_data_tlast), 222 | .pnseq_in_V_V(pnseq), 223 | .pnseq_in_V_V_ap_ack(pnseq_req), 224 | .pnseq_in_V_V_ap_vld(1'b1), 225 | .pnseq_len_V(pnseq_len), 226 | .start_V(block_start_pulse)); 227 | 228 | 229 | // Readback registers 230 | always @* 231 | case(rb_addr) 232 | 8'd0 : rb_data <= {63'd0, block_reset}; 233 | 8'd1 : rb_data <= {63'd0, block_start}; 234 | 8'd2 : rb_data <= {44'd0, pnseq_gen_seed_poly}; 235 | 8'd3 : rb_data <= {50'd0, pnseq_gen_order_len}; 236 | default : rb_data <= 64'h0BADC0DE0BADC0DE; 237 | endcase 238 | 239 | endmodule 240 | -------------------------------------------------------------------------------- /fpga-src/noc_block_correlator_tb/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016 Ettus Research 3 | # 4 | 5 | #------------------------------------------------- 6 | # Top-of-Makefile 7 | #------------------------------------------------- 8 | # Define BASE_DIR to point to the "top" dir 9 | BASE_DIR = $(abspath ../../../top) 10 | # Include viv_sim_preample after defining BASE_DIR 11 | include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak 12 | 13 | #------------------------------------------------- 14 | # IP Specific 15 | #------------------------------------------------- 16 | # If simulation contains IP, define the IP_DIR and point 17 | # it to the base level IP directory 18 | LIB_IP_DIR = $(BASE_DIR)/../lib/ip 19 | 20 | # Include makefiles and sources for all IP components 21 | # *after* defining the LIB_IP_DIR 22 | 23 | 24 | #------------------------------------------------- 25 | # Testbench Specific 26 | #------------------------------------------------- 27 | # Define only one toplevel module 28 | SIM_TOP = noc_block_correlator_tb 29 | 30 | # Add test bench, user design under test, and 31 | # additional user created files 32 | SIM_SRCS = \ 33 | $(abspath noc_block_correlator_tb.sv) 34 | 35 | MODELSIM_USER_DO = $(abspath wave.do) 36 | 37 | #------------------------------------------------- 38 | # Bottom-of-Makefile 39 | #------------------------------------------------- 40 | # Include all simulator specific makefiles here 41 | # Each should define a unique target to simulate 42 | # e.g. xsim, vsim, etc and a common "clean" target 43 | include $(BASE_DIR)/../tools/make/viv_simulator.mak 44 | -------------------------------------------------------------------------------- /fpga-src/noc_block_correlator_tb/noc_block_correlator_tb.sv: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /*noc_block_correlator_tb.sv - used noc_block_skeleton.sv as a template. 24 | Test bench for the correlator NOC block. Input for the correlator comes from the spreader NOC block 25 | */ 26 | `timescale 1ns/1ps 27 | `define SIM_TIMEOUT_US 50000 28 | `define NS_PER_TICK 1 29 | `define NUM_TEST_CASES 5 30 | `include "sim_exec_report.vh" 31 | `include "sim_rfnoc_lib.svh" 32 | 33 | 34 | typedef logic pn_seq_t[$]; 35 | typedef logic[31:0] sample_t[$]; 36 | 37 | module noc_block_correlator_tb(); 38 | 39 | function pn_seq_t get_pn_seq(int seq_len, int gen_poly, int gen_order, int gen_seed); 40 | logic [9:0] shift_reg, tmp_reg; 41 | logic new_bit; 42 | pn_seq_t seq; 43 | begin 44 | shift_reg = gen_seed; 45 | for(int i = 0; i>= 1; 51 | shift_reg[9] = new_bit; 52 | $display ("sequence[%d] - %b", i,seq[i]); 53 | end 54 | end 55 | return seq; 56 | endfunction 57 | 58 | function sample_t get_random_samples(int num_samples); 59 | sample_t sample; 60 | begin 61 | for(int i = 0; i Spreader -> Correlator -> Test bench 152 | `RFNOC_CONNECT(noc_block_tb /* From */, noc_block_spec_spreader /* To */, SC16 /* Type */, 256 /* Samples per packet */); 153 | `RFNOC_CONNECT(noc_block_spec_spreader, noc_block_correlator, SC16, 256); 154 | `RFNOC_CONNECT(noc_block_correlator,noc_block_tb,SC16,64); 155 | `TEST_CASE_DONE(1); 156 | 157 | /******************************************************************* 158 | ** Test 4 -- Set up the module by writing to the setting registers 159 | ********************************************************************/ 160 | `TEST_CASE_START("Write to setting registers"); 161 | tb_streamer.write_reg(sid_noc_block_correlator, noc_block_correlator.SR_GEN_SEED_POLY, gen_seed_poly); 162 | tb_streamer.write_reg(sid_noc_block_correlator, noc_block_correlator.SR_GEN_ORDER_LEN, gen_order_len); 163 | tb_streamer.write_reg(sid_noc_block_correlator, noc_block_correlator.SR_BLOCK_START, 1); 164 | tb_streamer.write_reg(sid_noc_block_correlator, noc_block_correlator.SR_BLOCK_START, 0); 165 | 166 | tb_streamer.write_reg(sid_noc_block_spec_spreader, noc_block_spec_spreader.SR_GEN_SEED_POLY, gen_seed_poly); 167 | tb_streamer.write_reg(sid_noc_block_spec_spreader, noc_block_spec_spreader.SR_GEN_ORDER_LEN, gen_order_len); 168 | `TEST_CASE_DONE(1); 169 | 170 | /******************************************************** 171 | ** Test 5 -- Send Samples 172 | ********************************************************/ 173 | `TEST_CASE_START("Send samples"); 174 | fork 175 | begin 176 | sample = get_random_samples(num_samples); 177 | payload = get_payload(sample, num_samples); // 64 bit word i.e., one payload word = 2 samples 178 | tb_streamer.send(payload); 179 | end 180 | begin 181 | for(int n = 0; n < num_samples ; n++) begin 182 | for(int i = 0; i < seq_len ; i++) begin 183 | tb_streamer.pull_word({out_val},last); 184 | end 185 | end 186 | end 187 | join 188 | `TEST_CASE_DONE(1); 189 | 190 | `TEST_BENCH_DONE; 191 | end 192 | endmodule 193 | -------------------------------------------------------------------------------- /fpga-src/noc_block_spec_spreader.v: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /*noc_block_spec_spreader.v - used noc_block_skeleton.v as a template to wrap Vivado HLS generated modules, spreader.v and pn_seq_gen_lfsr.v into a noc_block. 24 | */ 25 | module noc_block_spec_spreader #( 26 | parameter NOC_ID = 64'hFFFF_C000_0000_0000, 27 | parameter STR_SINK_FIFOSIZE = 11) 28 | ( 29 | input bus_clk, input bus_rst, 30 | input ce_clk, input ce_rst, 31 | input [63:0] i_tdata, input i_tlast, input i_tvalid, output i_tready, 32 | output [63:0] o_tdata, output o_tlast, output o_tvalid, input o_tready, 33 | output [63:0] debug 34 | ); 35 | 36 | //////////////////////////////////////////////////////////// 37 | // 38 | // RFNoC Shell 39 | // 40 | //////////////////////////////////////////////////////////// 41 | wire [31:0] set_data; 42 | wire [7:0] set_addr; 43 | wire set_stb; 44 | reg [63:0] rb_data; 45 | wire [7:0] rb_addr; 46 | 47 | wire [63:0] cmdout_tdata, ackin_tdata; 48 | wire cmdout_tlast, cmdout_tvalid, cmdout_tready, ackin_tlast, ackin_tvalid, ackin_tready; 49 | 50 | wire [63:0] str_sink_tdata, str_src_tdata; 51 | wire str_sink_tlast, str_sink_tvalid, str_sink_tready, str_src_tlast, str_src_tvalid, str_src_tready; 52 | 53 | wire clear_tx_seqnum; 54 | wire [15:0] next_dst_sid; 55 | 56 | noc_shell #( 57 | .NOC_ID(NOC_ID), 58 | .STR_SINK_FIFOSIZE(STR_SINK_FIFOSIZE)) 59 | noc_shell ( 60 | .bus_clk(bus_clk), .bus_rst(bus_rst), 61 | .i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready), 62 | .o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready), 63 | // Computer Engine Clock Domain 64 | .clk(ce_clk), .reset(ce_rst), 65 | // Control Sink 66 | .set_data(set_data), .set_addr(set_addr), .set_stb(set_stb), .set_time(), 67 | .rb_stb(1'b1), .rb_data(rb_data), .rb_addr(rb_addr), 68 | // Control Source 69 | .cmdout_tdata(cmdout_tdata), .cmdout_tlast(cmdout_tlast), .cmdout_tvalid(cmdout_tvalid), .cmdout_tready(cmdout_tready), 70 | .ackin_tdata(ackin_tdata), .ackin_tlast(ackin_tlast), .ackin_tvalid(ackin_tvalid), .ackin_tready(ackin_tready), 71 | // Stream Sink 72 | .str_sink_tdata(str_sink_tdata), .str_sink_tlast(str_sink_tlast), .str_sink_tvalid(str_sink_tvalid), .str_sink_tready(str_sink_tready), 73 | // Stream Source 74 | .str_src_tdata(str_src_tdata), .str_src_tlast(str_src_tlast), .str_src_tvalid(str_src_tvalid), .str_src_tready(str_src_tready), 75 | // Misc 76 | .vita_time(64'd0), .clear_tx_seqnum(clear_tx_seqnum), 77 | .src_sid(), .next_dst_sid(next_dst_sid), .resp_in_dst_sid(), .resp_out_dst_sid(), 78 | .debug(debug)); 79 | 80 | //////////////////////////////////////////////////////////// 81 | // 82 | // AXI Wrapper 83 | // Convert RFNoC Shell interface into AXI stream interface 84 | // 85 | //////////////////////////////////////////////////////////// 86 | localparam NUM_AXI_CONFIG_BUS = 1; 87 | 88 | wire [31:0] m_axis_data_tdata; 89 | wire m_axis_data_tlast; 90 | wire m_axis_data_tvalid; 91 | wire m_axis_data_tready; 92 | 93 | wire [31:0] s_axis_data_tdata; 94 | wire s_axis_data_tlast; 95 | wire s_axis_data_tvalid; 96 | wire s_axis_data_tready; 97 | 98 | wire [31:0] m_axis_config_tdata; 99 | wire m_axis_config_tvalid; 100 | wire m_axis_config_tready; 101 | 102 | localparam AXI_WRAPPER_BASE = 128; 103 | localparam SR_AXI_CONFIG_BASE = AXI_WRAPPER_BASE + 1; 104 | 105 | axi_wrapper #( 106 | .SIMPLE_MODE(1), 107 | .SR_AXI_CONFIG_BASE(SR_AXI_CONFIG_BASE), 108 | .NUM_AXI_CONFIG_BUS(NUM_AXI_CONFIG_BUS)) 109 | inst_axi_wrapper ( 110 | .clk(ce_clk), .reset(ce_rst), 111 | .clear_tx_seqnum(clear_tx_seqnum), 112 | .next_dst(next_dst_sid), 113 | .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), 114 | .i_tdata(str_sink_tdata), .i_tlast(str_sink_tlast), .i_tvalid(str_sink_tvalid), .i_tready(str_sink_tready), 115 | .o_tdata(str_src_tdata), .o_tlast(str_src_tlast), .o_tvalid(str_src_tvalid), .o_tready(str_src_tready), 116 | .m_axis_data_tdata(m_axis_data_tdata), 117 | .m_axis_data_tlast(m_axis_data_tlast), 118 | .m_axis_data_tvalid(m_axis_data_tvalid), 119 | .m_axis_data_tready(m_axis_data_tready), 120 | .m_axis_data_tuser(), 121 | .s_axis_data_tdata(s_axis_data_tdata), 122 | .s_axis_data_tlast(s_axis_data_tlast), 123 | .s_axis_data_tvalid(s_axis_data_tvalid), 124 | .s_axis_data_tready(s_axis_data_tready), 125 | .s_axis_data_tuser(), 126 | .m_axis_config_tdata(m_axis_config_tdata), 127 | .m_axis_config_tlast(), 128 | .m_axis_config_tvalid(m_axis_config_tvalid), 129 | .m_axis_config_tready(m_axis_config_tready), 130 | .m_axis_pkt_len_tdata(), 131 | .m_axis_pkt_len_tvalid(), 132 | .m_axis_pkt_len_tready()); 133 | 134 | //////////////////////////////////////////////////////////// 135 | // 136 | // User code 137 | // 138 | //////////////////////////////////////////////////////////// 139 | 140 | // Control Source Unused 141 | assign cmdout_tdata = 64'd0; 142 | assign cmdout_tlast = 1'b0; 143 | assign cmdout_tvalid = 1'b0; 144 | assign ackin_tready = 1'b1; 145 | 146 | localparam [7:0] SR_BLOCK_RESET = 131; 147 | localparam [7:0] SR_GEN_SEED_POLY = 132; 148 | localparam [7:0] SR_GEN_ORDER_LEN = 133; 149 | 150 | wire block_reset; 151 | wire [19:0] pnseq_gen_seed_poly; 152 | wire [13:0] pnseq_gen_order_len; 153 | setting_reg #( 154 | .my_addr(SR_BLOCK_RESET), .awidth(8), .width(1)) 155 | sr_fft_reset ( 156 | .clk(ce_clk), .rst(ce_rst), 157 | .strobe(set_stb), .addr(set_addr), .in(set_data), .out(block_reset), .changed()); 158 | 159 | setting_reg #( 160 | .my_addr(SR_GEN_SEED_POLY), .awidth(8), .width(20)) 161 | sr_gen_poly ( 162 | .clk(ce_clk), .rst(ce_rst), 163 | .strobe(set_stb), .addr(set_addr), .in(set_data), .out(pnseq_gen_seed_poly), .changed());// [19:10] - seed, [9:0] - generator polynomial 164 | 165 | setting_reg #( 166 | .my_addr(SR_GEN_ORDER_LEN), .awidth(8), .width(14)) 167 | sr_gen_seed( 168 | .clk(ce_clk), .rst(ce_rst), 169 | .strobe(set_stb), .addr(set_addr), .in(set_data), .out(pnseq_gen_order_len), .changed());// [13:10] - polynomial order, [9:0] - pn sequence length 170 | 171 | wire pnseq, pnseq_req, pnseq_load; 172 | wire [9:0] pnseq_gen_seed = pnseq_gen_seed_poly[19:10]; 173 | wire [9:0] pnseq_gen_poly = pnseq_gen_seed_poly[9:0]; 174 | wire [3:0] pnseq_gen_order = pnseq_gen_order_len[13:10]; 175 | wire [9:0] pnseq_len = pnseq_gen_order_len[9:0]; 176 | 177 | pn_seq_gen_lfsr inst_pn_seq_gen_lfsr( 178 | .ap_clk(ce_clk), .ap_rst(ce_rst |block_reset), 179 | .load_V(pnseq_load), 180 | .poly_V(pnseq_gen_poly), 181 | .seed_V(pnseq_gen_seed), 182 | .order_V(pnseq_gen_order), 183 | .pn_req_V(pnseq_req), 184 | .ap_return(pnseq)); 185 | 186 | spreader inst_spreader( 187 | .ap_clk(ce_clk), .ap_rst_n(~(ce_rst | block_reset)), 188 | .i_data_TDATA(m_axis_data_tdata), // SC16 189 | .i_data_TVALID(m_axis_data_tvalid), 190 | .i_data_TREADY(m_axis_data_tready), 191 | .i_data_TLAST(m_axis_data_tlast), 192 | .o_data_TDATA(s_axis_data_tdata), // SC16 193 | .o_data_TVALID(s_axis_data_tvalid), 194 | .o_data_TREADY(s_axis_data_tready), 195 | .o_data_TLAST(s_axis_data_tlast), 196 | .pnseq_V_V(pnseq), // PN sequence from inst_pn_seq_gen_lfsr 197 | .pnseq_V_V_ap_ack(pnseq_req), 198 | .pnseq_V_V_ap_vld(1'b1), 199 | .ap_return(pnseq_load),// load signal to inst_pn_seq_gen_lfsr 200 | .pnseq_len_V(pnseq_len)); 201 | 202 | 203 | // Readback registers 204 | always @* 205 | case(rb_addr) 206 | 8'd0 : rb_data <= {63'd0, block_reset}; 207 | 8'd1 : rb_data <= {44'd0, pnseq_gen_seed_poly}; 208 | 8'd2 : rb_data <= {50'd0, pnseq_gen_order_len}; 209 | default : rb_data <= 64'h0BADC0DE0BADC0DE; 210 | endcase 211 | 212 | endmodule 213 | -------------------------------------------------------------------------------- /fpga-src/noc_block_spec_spreader_tb/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016 Ettus Research 3 | # 4 | 5 | #------------------------------------------------- 6 | # Top-of-Makefile 7 | #------------------------------------------------- 8 | # Define BASE_DIR to point to the "top" dir 9 | BASE_DIR = $(abspath ../../../top) 10 | # Include viv_sim_preample after defining BASE_DIR 11 | include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak 12 | 13 | #------------------------------------------------- 14 | # IP Specific 15 | #------------------------------------------------- 16 | # If simulation contains IP, define the IP_DIR and point 17 | # it to the base level IP directory 18 | LIB_IP_DIR = $(BASE_DIR)/../lib/ip 19 | 20 | # Include makefiles and sources for all IP components 21 | # *after* defining the LIB_IP_DIR 22 | 23 | #------------------------------------------------- 24 | # Testbench Specific 25 | #------------------------------------------------- 26 | # Define only one toplevel module 27 | SIM_TOP = noc_block_spec_spreader_tb 28 | 29 | # Add test bench, user design under test, and 30 | # additional user created files 31 | SIM_SRCS = \ 32 | $(abspath noc_block_spec_spreader_tb.sv) 33 | 34 | MODELSIM_USER_DO = $(abspath wave.do) 35 | 36 | #------------------------------------------------- 37 | # Bottom-of-Makefile 38 | #------------------------------------------------- 39 | # Include all simulator specific makefiles here 40 | # Each should define a unique target to simulate 41 | # e.g. xsim, vsim, etc and a common "clean" target 42 | include $(BASE_DIR)/../tools/make/viv_simulator.mak 43 | -------------------------------------------------------------------------------- /fpga-src/noc_block_spec_spreader_tb/noc_block_spec_spreader_tb.sv: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /*noc_block_spec_spreader_tb.sv - used noc_block_skeleton.sv as a template. 24 | Test bench for the spectrum spreader NOC block. 25 | */ 26 | 27 | `timescale 1ns/1ps 28 | `define SIM_TIMEOUT_US 50000 29 | `define NS_PER_TICK 1 30 | `define NUM_TEST_CASES 7 31 | `include "sim_exec_report.vh" 32 | `include "sim_rfnoc_lib.svh" 33 | 34 | 35 | typedef logic pn_seq_t[$]; 36 | typedef logic[31:0] sample_t[$]; 37 | 38 | 39 | module noc_block_spec_spreader_tb(); 40 | 41 | 42 | function pn_seq_t get_pn_seq(int seq_len, int gen_poly, int gen_order, int gen_seed); 43 | logic [9:0] shift_reg, tmp_reg; 44 | logic new_bit; 45 | pn_seq_t seq; 46 | begin 47 | shift_reg = gen_seed; 48 | for(int i = 0; i>= 1; 54 | shift_reg[9] = new_bit; 55 | $display ("sequence[%d] - %b", i,seq[i]); 56 | end 57 | end 58 | return seq; 59 | endfunction 60 | 61 | function sample_t get_random_samples(int num_samples); 62 | sample_t sample; 63 | begin 64 | for(int i = 0; i Spreader -> Test bench 155 | `RFNOC_CONNECT(noc_block_tb /* From */, noc_block_spec_spreader /* To */, SC16 /* Type */, 256 /* Samples per packet */); 156 | `RFNOC_CONNECT(noc_block_spec_spreader,noc_block_tb,SC16,64); 157 | `TEST_CASE_DONE(1); 158 | 159 | /******************************************************************* 160 | ** Test 4 -- Set up the module by writing to the setting registers 161 | ********************************************************************/ 162 | `TEST_CASE_START("Write to setting registers"); 163 | tb_streamer.write_reg(sid_noc_block_spec_spreader, noc_block_spec_spreader.SR_GEN_SEED_POLY, gen_seed_poly); 164 | tb_streamer.write_reg(sid_noc_block_spec_spreader, noc_block_spec_spreader.SR_GEN_ORDER_LEN, gen_order_len); 165 | `TEST_CASE_DONE(1); 166 | 167 | /******************************************************** 168 | ** Test 5 -- Send Samples 169 | ********************************************************/ 170 | `TEST_CASE_START("Send samples"); 171 | fork 172 | begin 173 | seq = get_pn_seq(seq_len, gen_poly, gen_order, gen_seed); 174 | sample = get_random_samples(num_samples); 175 | payload = get_payload(sample, num_samples); // 64 bit word i.e., one payload word = 2 samples 176 | tb_streamer.send(payload); 177 | end 178 | begin 179 | for(int n = 0; n < num_samples ; n++) begin 180 | for(int i = 0; i < seq_len ; i++) begin 181 | tb_streamer.pull_word({out_val},last); 182 | if(seq[i]== 0) begin 183 | expected_word[31:16] = (0 - sample[n][31:16]); 184 | expected_word[15:0] = (0 - sample[n][15:0]); 185 | end else begin 186 | expected_word = sample[n]; 187 | end 188 | /*if(expected_word != out_val) begin 189 | $info("expected: %d, output : %d", expected_word, out_val); 190 | end*/ 191 | 192 | `ASSERT_ERROR(expected_word == out_val, "Bad output value!!"); 193 | if(i == seq_len-1) begin 194 | `ASSERT_ERROR(last == 1'b1, "Detected late tlast!"); 195 | end else begin 196 | `ASSERT_ERROR(last == 1'b0, "Detected early tlast!"); 197 | end 198 | end 199 | end 200 | end 201 | join 202 | `TEST_CASE_DONE(1); 203 | 204 | /******************************************************************* 205 | ** Test 6 -- Reset the module and set new parameters 206 | ********************************************************************/ 207 | `TEST_CASE_START("Write to setting registers"); 208 | tb_streamer.write_reg(sid_noc_block_spec_spreader, noc_block_spec_spreader.SR_BLOCK_RESET, 1'b1); 209 | #100 210 | tb_streamer.write_reg(sid_noc_block_spec_spreader, noc_block_spec_spreader.SR_BLOCK_RESET, 1'b0); 211 | #100 212 | tb_streamer.write_reg(sid_noc_block_spec_spreader, noc_block_spec_spreader.SR_GEN_SEED_POLY, gen_seed_poly1); 213 | tb_streamer.write_reg(sid_noc_block_spec_spreader, noc_block_spec_spreader.SR_GEN_ORDER_LEN, gen_order_len1); 214 | 215 | `TEST_CASE_DONE(1); 216 | 217 | /******************************************************** 218 | ** Test 7 -- Send Samples 219 | ********************************************************/ 220 | `TEST_CASE_START("Send samples"); 221 | fork 222 | begin 223 | seq = get_pn_seq(seq_len1, gen_poly1, gen_order1, gen_seed1); 224 | sample = get_random_samples(num_samples1); 225 | payload = get_payload(sample, num_samples1); // 64 bit word i.e., one payload word = 2 samples 226 | tb_streamer.send(payload); 227 | end 228 | begin 229 | for(int n = 0; n < num_samples1 ; n++) begin 230 | for(int i = 0; i < seq_len1 ; i++) begin 231 | tb_streamer.pull_word({out_val},last); 232 | if(seq[i]== 0) begin 233 | expected_word[31:16] = (0 - sample[n][31:16]); 234 | expected_word[15:0] = (0 - sample[n][15:0]); 235 | end else begin 236 | expected_word = sample[n]; 237 | end 238 | /*if(expected_word != out_val) begin 239 | $info("expected: %d, output : %d", expected_word, out_val); 240 | end*/ 241 | 242 | `ASSERT_ERROR(expected_word == out_val, "Bad output value!!"); 243 | if(i == seq_len1-1) begin 244 | `ASSERT_ERROR(last == 1'b1, "Detected late tlast!"); 245 | end else begin 246 | `ASSERT_ERROR(last == 1'b0, "Detected early tlast!"); 247 | end 248 | end 249 | end 250 | end 251 | join 252 | `TEST_CASE_DONE(1); 253 | 254 | 255 | `TEST_BENCH_DONE; 256 | end 257 | endmodule 258 | -------------------------------------------------------------------------------- /hls-projects/averaging/averaging.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | // 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /* averaging.cpp - Used to generate RTL for the averaging module used in noc_block_cir_avg 24 | i_data - AXI stream input data (with tlast) Packets of PDP of incoming samples 25 | o_data - AXI stream output data (with tlast) Average PDP over 'K'(averaging factor) packets 26 | threshold - to discard noise at the beginning of signal reception (before any signal is sent), and to get the LOS path as the first output in a packet, this threshold input could be set by the user, so that the averaging module starts processing samples only after it finds a sample whose value is over the threshold. 27 | seq_len - input parameter PN sequence length 28 | log_avg_size - user provided input parameter log2(averaging_factor). 29 | */ 30 | 31 | #include 32 | #include "ap_int.h" 33 | #include "rfnoc.h" 34 | 35 | void averaging(hls::stream i_data, hls::stream o_data, ap_uint<32> threshold, ap_uint<10> seq_len, ap_uint<3> log_avg_size) 36 | { 37 | #pragma HLS PIPELINE II=1 38 | #pragma HLS INTERFACE axis port=o_data 39 | #pragma HLS INTERFACE axis port=i_data 40 | #pragma HLS INTERFACE ap_ctrl_none port=return 41 | 42 | static ap_uint<32> data_in_reg; 43 | static ap_uint<1> data_in_valid; 44 | 45 | static ap_uint<10> seq_len_reg; 46 | static ap_uint<8> avg_size_reg; 47 | static ap_uint<3> log_avg_size_reg; 48 | 49 | enum averagingState {ST_IDLE = 0, ST_FIRST_BLK, ST_NOT_FIRST_BLK}; 50 | static averagingState currentState; 51 | #pragma HLS RESET variable=currentState 52 | 53 | static hls::stream > data_fifo; 54 | #pragma HLS STREAM variable=data_fifo depth=1024 dim=1 55 | #pragma HLS RESOURCE variable=data_fifo core=FIFO_BRAM 56 | // 40 bits to accommodate for accumulation over 128 samples (max averaging size) 57 | static hls::stream > out_fifo; 58 | #pragma HLS STREAM variable=out_fifo depth=1024 dim=1 59 | #pragma HLS RESOURCE variable=out_fifo core=FIFO_BRAM 60 | 61 | static ap_uint<40> pfetch_data; 62 | #pragma HLS DEPENDENCE variable=pfetch_data inter false 63 | static ap_uint<10> wr_cnt; 64 | #pragma HLS RESET variable=wr_cnt 65 | static ap_uint<10> rd_cnt; 66 | #pragma HLS RESET variable=rd_cnt 67 | static ap_int<1> threshold_met; 68 | #pragma HLS RESET variable=threshold_met 69 | 70 | static ap_uint<8> blk_cnt; 71 | static ap_uint<9> out_sample_cnt; 72 | rfnoc_axis out_sample; 73 | ap_uint<32> tmp_data; 74 | 75 | switch(currentState){ 76 | case ST_IDLE : 77 | if(data_in_valid) 78 | { 79 | if(!threshold_met) 80 | { 81 | seq_len_reg = seq_len; 82 | log_avg_size_reg = log_avg_size; 83 | avg_size_reg = 1 << log_avg_size; 84 | } 85 | if(!threshold_met && (data_in_reg > threshold)) 86 | threshold_met = 1; 87 | if((!threshold_met && (data_in_reg > threshold)) || threshold_met) 88 | { 89 | data_fifo.write(data_in_reg); 90 | wr_cnt = wr_cnt + 1; 91 | currentState = ST_FIRST_BLK; 92 | } 93 | } 94 | break; 95 | case ST_FIRST_BLK: 96 | if(data_in_valid) 97 | { 98 | data_fifo.write(data_in_reg); // First block/packet is stored in the data fifo 99 | if(wr_cnt == seq_len_reg - 1) 100 | { 101 | wr_cnt = 0; 102 | blk_cnt = 1; 103 | currentState = ST_NOT_FIRST_BLK; 104 | } 105 | else 106 | { 107 | wr_cnt = wr_cnt + 1; 108 | currentState = ST_FIRST_BLK; 109 | } 110 | } 111 | break; 112 | case ST_NOT_FIRST_BLK: 113 | if(data_in_valid) 114 | { 115 | if(blk_cnt < (avg_size_reg - 1)) 116 | { 117 | data_fifo.write(data_in_reg + data_fifo.read()); // subsequent blocks are added to the stored data (element by element) and stored back in the data fifo 118 | if(wr_cnt == seq_len_reg - 1) 119 | { 120 | wr_cnt = 0; 121 | blk_cnt = blk_cnt + 1; 122 | currentState = ST_NOT_FIRST_BLK; 123 | } 124 | else 125 | { 126 | wr_cnt = wr_cnt + 1; 127 | } 128 | } 129 | else 130 | { 131 | tmp_data = ((data_in_reg + data_fifo.read())).range(31+log_avg_size_reg, log_avg_size_reg); // for the last block, log_avg_size bits are discarded to approximate division (/K) operation 132 | out_fifo.write(tmp_data); // Average block is written to a different FIFO out_fifo 133 | if(wr_cnt == seq_len_reg - 1) 134 | { 135 | wr_cnt = 0; 136 | blk_cnt = 0; 137 | currentState = ST_IDLE; 138 | } 139 | else 140 | { 141 | wr_cnt = wr_cnt + 1; 142 | } 143 | } 144 | } 145 | break; 146 | } 147 | 148 | 149 | if(!out_fifo.empty()) 150 | { 151 | out_sample.data = (out_fifo.read()); // sending average data out 152 | 153 | if ((out_sample_cnt == 259) || (rd_cnt == seq_len_reg - 1) ) // fragmenting output packet in case of incoming packet size > 260, i.e., 260*4 = 1040 bytes to fit in an Ethernet packet. 154 | { 155 | out_sample.last = 1; 156 | out_sample_cnt = 0; 157 | } 158 | else 159 | { 160 | out_sample.last = 0; 161 | out_sample_cnt = out_sample_cnt + 1; 162 | } 163 | 164 | if(rd_cnt == seq_len_reg - 1) 165 | rd_cnt = 0; 166 | else 167 | rd_cnt = rd_cnt + 1; 168 | 169 | 170 | o_data.write(out_sample); 171 | } 172 | 173 | 174 | if(!i_data.empty()) // reading incoming data 175 | { 176 | data_in_reg = i_data.read().data; // internal register to store incoming data 177 | data_in_valid = 1; 178 | } 179 | else 180 | data_in_valid = 0; 181 | 182 | 183 | } 184 | -------------------------------------------------------------------------------- /hls-projects/averaging/rfnoc.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /*rfnoc.h - Used to define custom AXI stream interface required for noc_blocks 24 | The default AXI stream interface in Vivado HLS consists of data, valid and ready signals. rfnoc_axis has 'last' signal along with those. 25 | */ 26 | #include "ap_int.h" 27 | 28 | struct rfnoc_axis{ 29 | ap_int<32> data; 30 | ap_uint<1> last; 31 | }; 32 | 33 | -------------------------------------------------------------------------------- /hls-projects/averaging/script.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2015 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | open_project averaging 7 | set_top averaging 8 | add_files averaging.cpp 9 | open_solution "solution1" 10 | set_part {xc7k410tffg900-2} 11 | create_clock -period 5 -name default 12 | #source "./averaging/solution1/directives.tcl" 13 | #csim_design 14 | csynth_design 15 | #cosim_design 16 | export_design -format ip_catalog 17 | -------------------------------------------------------------------------------- /hls-projects/correlator/README.md: -------------------------------------------------------------------------------- 1 | # Correlator 2 | 3 | The correlator module built using this project, continuously correlates incoming samples with a locally generated PN sequence and gives correlation power as the output. Two parallel correlator structures as shown below are used to process real and imaginary parts of the incoming samples. 4 | 5 | ![correlator](https://user-images.githubusercontent.com/9439021/27982474-e8eb412e-636f-11e7-9de3-45a50634e94d.jpg) 6 | 7 | 8 | Shift register sample storage and parallel adders are generated by using 9 | 10 | _#pragma HLS ARRAY_PARTITION_ 11 | 12 | with each of the data storage and sum variables. 13 | 14 | Binary adder tree is implemented by unrolling each of the adder stages using 15 | 16 | _#pragma HLS UNROLL_ 17 | 18 | PN sequence stream comes from a [PN sequence generator](../pn_seq_gen_lfsr/README.md) connected to the correlator module in noc_block_correlator. 19 | 20 | 21 | -------------------------------------------------------------------------------- /hls-projects/correlator/correlator.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /*correlator.cpp - Used to generate RTL for correlator module used in RFNoC block noc_block_correlator. 24 | i_data - AXI stream input data (with tlast) 25 | o_data - AXI stream output data (with tlast) 26 | start - User sent start signal, to start the correlation task 27 | pnseq - PN sequence used for correlation wit the input data. As this port is setup as 'ap_hs', handshaking signals 'valid' and 'ack' are generated. All these 3 signals are connected to the PN sequence generator instance in noc_block_correlator 28 | pnseq_len - input parameter PN sequence length 29 | 30 | */ 31 | #include 32 | #include "ap_int.h" 33 | #include "rfnoc.h" 34 | // Uncomment to generate correlator size 256 35 | //#define COR_SIZE_256 36 | // Uncomment to generate correlator size 512 37 | #define COR_SIZE_512 38 | 39 | void correlator (hls::stream i_data, hls::stream o_data, ap_uint<1> start, hls::stream > pnseq_in, ap_uint<10> pnseq_len) 40 | { 41 | 42 | #ifdef COR_SIZE_256 43 | const int COR_SIZE = 256; 44 | #endif 45 | 46 | #ifdef COR_SIZE_512 47 | const int COR_SIZE = 512; 48 | #endif 49 | 50 | #pragma HLS RESOURCE variable=o_data latency=1 51 | #pragma HLS INTERFACE ap_hs port=pnseq_in 52 | #pragma HLS INTERFACE ap_ctrl_none port=return 53 | #pragma HLS INTERFACE axis port=o_data 54 | #pragma HLS INTERFACE axis port=i_data 55 | #pragma HLS PIPELINE II=1 56 | static ap_int<16> data_reg_i[COR_SIZE]; 57 | #pragma HLS RESET variable=data_reg_i 58 | #pragma HLS ARRAY_PARTITION variable=data_reg_i complete dim=1 59 | static ap_int<16> data_reg_q[COR_SIZE]; 60 | #pragma HLS RESET variable=data_reg_q 61 | #pragma HLS ARRAY_PARTITION variable=data_reg_q complete dim=1 62 | static ap_int<16> product_reg_i[COR_SIZE]; 63 | #pragma HLS ARRAY_PARTITION variable=product_reg_i complete dim=1 64 | static ap_int<16> product_reg_q[COR_SIZE]; 65 | #pragma HLS ARRAY_PARTITION variable=product_reg_q complete dim=1 66 | static ap_int<16> adder_in_reg_i[COR_SIZE]; 67 | #pragma HLS ARRAY_PARTITION variable=adder_in_reg_i complete dim=1 68 | static ap_int<16> adder_in_reg_q[COR_SIZE]; 69 | #pragma HLS ARRAY_PARTITION variable=adder_in_reg_q complete dim=1 70 | 71 | static ap_int<17> sum1_reg_i[COR_SIZE/2]; 72 | #pragma HLS ARRAY_PARTITION variable=sum1_reg_i complete dim=1 73 | static ap_int<17> sum1_reg_q[COR_SIZE/2]; 74 | #pragma HLS ARRAY_PARTITION variable=sum1_reg_q complete dim=1 75 | 76 | static ap_int<18> sum2_reg_i[COR_SIZE/4]; 77 | #pragma HLS ARRAY_PARTITION variable=sum2_reg_i complete dim=1 78 | static ap_int<18> sum2_reg_q[COR_SIZE/4]; 79 | #pragma HLS ARRAY_PARTITION variable=sum2_reg_q complete dim=1 80 | 81 | static ap_int<19> sum3_reg_i[COR_SIZE/8]; 82 | #pragma HLS ARRAY_PARTITION variable=sum3_reg_i complete dim=1 83 | static ap_int<19> sum3_reg_q[COR_SIZE/8]; 84 | #pragma HLS ARRAY_PARTITION variable=sum3_reg_q complete dim=1 85 | 86 | static ap_int<20> sum4_reg_i[COR_SIZE/16]; 87 | #pragma HLS ARRAY_PARTITION variable=sum4_reg_i complete dim=1 88 | static ap_int<20> sum4_reg_q[COR_SIZE/16]; 89 | #pragma HLS ARRAY_PARTITION variable=sum4_reg_q complete dim=1 90 | 91 | static ap_int<21> sum5_reg_i[COR_SIZE/32]; 92 | #pragma HLS ARRAY_PARTITION variable=sum5_reg_i complete dim=1 93 | static ap_int<21> sum5_reg_q[COR_SIZE/32]; 94 | #pragma HLS ARRAY_PARTITION variable=sum5_reg_q complete dim=1 95 | 96 | static ap_int<22> sum6_reg_i[COR_SIZE/64]; 97 | #pragma HLS ARRAY_PARTITION variable=sum6_reg_i complete dim=1 98 | static ap_int<22> sum6_reg_q[COR_SIZE/64]; 99 | #pragma HLS ARRAY_PARTITION variable=sum6_reg_q complete dim=1 100 | 101 | static ap_int<23> sum7_reg_i[COR_SIZE/128]; 102 | #pragma HLS ARRAY_PARTITION variable=sum7_reg_i complete dim=1 103 | static ap_int<23> sum7_reg_q[COR_SIZE/128]; 104 | #pragma HLS ARRAY_PARTITION variable=sum7_reg_q complete dim=1 105 | 106 | 107 | 108 | rfnoc_axis out_sample; 109 | 110 | static ap_uint<10> out_sample_cnt; 111 | #pragma HLS RESET variable=out_sample_cnt 112 | 113 | static ap_uint<1> pn_seq[512]; 114 | #pragma HLS ARRAY_PARTITION variable=pn_seq complete dim=1 115 | 116 | rfnoc_axis tmp_data; 117 | 118 | static ap_uint<10> load_cnt; 119 | #pragma HLS RESET variable=load_cnt 120 | static ap_uint<24> data_valid_reg; 121 | static ap_uint<10> pnseq_len_reg; 122 | 123 | enum correlatorState {ST_IDLE = 0, ST_LOAD, ST_GEN, ST_CORRELATE}; 124 | static correlatorState currentState; 125 | #pragma HLS RESET variable=currentState 126 | 127 | enum writeState {ST_NOWRITE = 0, ST_WRITE}; 128 | static writeState currentwrState; 129 | #pragma HLS RESET variable=currentwrState 130 | 131 | #ifdef COR_SIZE_256 132 | 133 | static ap_int<24> sum_reg_i; 134 | static ap_int<24> sum_reg_q; 135 | 136 | static ap_int<48> sq_reg_i; 137 | static ap_int<48> sq_reg_q; 138 | 139 | static ap_int<49> sq_sum; 140 | 141 | // Output write state machine 142 | switch(currentwrState) { 143 | case ST_NOWRITE: 144 | if(data_valid_reg[11]) 145 | currentwrState = ST_WRITE; 146 | break; 147 | case ST_WRITE: 148 | if(out_sample_cnt == pnseq_len_reg-1){ 149 | out_sample.last = 1; 150 | out_sample_cnt = 0; } 151 | else{ 152 | out_sample.last = 0; 153 | out_sample_cnt = out_sample_cnt + 1;} 154 | 155 | if(!data_valid_reg[11]) 156 | currentwrState = ST_NOWRITE; 157 | else 158 | currentwrState = ST_WRITE; 159 | 160 | out_sample.data = sq_sum.range(48,17); 161 | o_data.write(out_sample); 162 | 163 | break; 164 | } 165 | 166 | // correlation power I^2 + Q^2 167 | sq_sum = (sq_reg_i + sq_reg_q); 168 | 169 | sq_reg_i = sum_reg_i*sum_reg_i; // I*I 170 | sq_reg_q = sum_reg_q*sum_reg_q; // Q*Q 171 | 172 | //Last addder stage 173 | sum_reg_i = sum7_reg_i[0] + sum7_reg_i[1]; 174 | sum_reg_q = sum7_reg_q[0] + sum7_reg_q[1]; 175 | #endif 176 | 177 | #ifdef COR_SIZE_512 178 | 179 | static ap_int<24> sum8_reg_i[COR_SIZE/256]; 180 | #pragma HLS ARRAY_PARTITION variable=sum8_reg_i complete dim=1 181 | static ap_int<24> sum8_reg_q[COR_SIZE/256]; 182 | #pragma HLS ARRAY_PARTITION variable=sum8_reg_q complete dim=1 183 | 184 | static ap_int<25> sum_reg_i; 185 | static ap_int<25> sum_reg_q; 186 | 187 | static ap_int<50> sq_reg_i; 188 | static ap_int<50> sq_reg_q; 189 | 190 | static ap_int<51> sq_sum; 191 | 192 | // Output write state machine 193 | switch(currentwrState) { 194 | case ST_NOWRITE: 195 | if(data_valid_reg[12]) 196 | currentwrState = ST_WRITE; 197 | break; 198 | case ST_WRITE: 199 | if(out_sample_cnt == pnseq_len_reg-1){ 200 | out_sample.last = 1; 201 | out_sample_cnt = 0; } 202 | else{ 203 | out_sample.last = 0; 204 | out_sample_cnt = out_sample_cnt + 1;} 205 | 206 | if(!data_valid_reg[12]) 207 | currentwrState = ST_NOWRITE; 208 | else 209 | currentwrState = ST_WRITE; 210 | 211 | out_sample.data = sq_sum.range(50,19); 212 | o_data.write(out_sample); 213 | 214 | break; 215 | } 216 | 217 | // correlation power I^2 + Q^2 218 | sq_sum = (sq_reg_i + sq_reg_q); 219 | 220 | sq_reg_i = sum_reg_i*sum_reg_i; // I*I 221 | sq_reg_q = sum_reg_q*sum_reg_q; // Q*Q 222 | 223 | //Last adder stage 224 | sum_reg_i = sum8_reg_i[0] + sum8_reg_i[1]; 225 | sum_reg_q = sum8_reg_q[0] + sum8_reg_q[1]; 226 | 227 | // An additional adder stage for size 512 228 | ADDER_STAGE8_LOOP: for(int i = 0; i 0 ; i--){ 334 | #pragma HLS UNROLL 335 | data_reg_i[i] = data_reg_i[i - 1]; 336 | data_reg_q[i] = data_reg_q[i - 1];} 337 | 338 | i_data.read(tmp_data); 339 | data_reg_q[0] = tmp_data.data.range(15,0); // IM 340 | data_reg_i[0] = tmp_data.data.range(31,16); // RE 341 | data_valid_reg[0] = 1; // shift in valid pulse 342 | } 343 | else 344 | data_valid_reg[0] = 0; 345 | break; 346 | } 347 | 348 | 349 | } 350 | 351 | -------------------------------------------------------------------------------- /hls-projects/correlator/rfnoc.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /*rfnoc.h - Used to define custom AXI stream interface required for noc_blocks 24 | The default AXI stream interface in Vivado HLS consists of data, valid and ready signals. rfnoc_axis has 'last' signal along with those. 25 | */ 26 | #include "ap_int.h" 27 | 28 | struct rfnoc_axis{ 29 | ap_int<32> data; 30 | ap_uint<1> last; 31 | }; 32 | 33 | -------------------------------------------------------------------------------- /hls-projects/correlator/script.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2015 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | open_project correlator 7 | set_top correlator 8 | add_files correlator.cpp 9 | open_solution "solution1" 10 | set_part {xc7k410tffg900-2} 11 | create_clock -period 5 -name default 12 | config_rtl -encoding onehot -reset state -reset_level high 13 | config_interface -m_axi_offset off -register_io off 14 | #source "./correlator/solution1/directives.tcl" 15 | #csim_design 16 | csynth_design 17 | #cosim_design 18 | export_design -format ip_catalog 19 | -------------------------------------------------------------------------------- /hls-projects/pn_seq_gen_lfsr/README.md: -------------------------------------------------------------------------------- 1 | # PN Sequence Generator 2 | 3 | The PN sequence generator module built using this project is used in both noc_block_spec_spreader and noc_block_correlator. The c++ code here builds an LFSR based programmable PN sequence generator as shown below. It can take a generator polynomial up to an order of 10, i.e., the longest sequence that it can generate is of length 1023. For a polynomial of order N, output is taken from the Nth bit. 4 | 5 | ![pnseqgen](https://user-images.githubusercontent.com/9439021/27982375-251f4e6c-636e-11e7-9cb2-7e1f0d9df33a.jpg) 6 | 7 | -------------------------------------------------------------------------------- /hls-projects/pn_seq_gen_lfsr/pn_seq_gen_lfsr.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | // 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /* pn_seq_gen_lfsr.cpp - Used to generate RTL for LFSR based PN sequence generator 24 | load - load input to load the generator polynomial and seed 25 | pn_req - request for next bit in the sequence. Works like an enable signal for the LFSR 26 | poly - generator polynomial input. Maximum order 10 27 | seed - Initial seed for the LFSR 28 | order - generator polynomial order 29 | */ 30 | 31 | #include "ap_int.h" 32 | 33 | // Maximum order of generator polynomial = 10 34 | ap_uint<1> pn_seq_gen_lfsr(ap_uint<1> load, ap_uint<1> pn_req, ap_uint<10> poly, ap_uint<10> seed, ap_uint<4> order){ 35 | //#pragma HLS INTERFACE ap_none port=out_bit 36 | #pragma HLS INTERFACE ap_ctrl_none port=return 37 | // For a 63 length (maximal) length sequence, the generator poly is x^6 + x^5 + 1. Let's say the seed is 000001 38 | // Input poly : 0000110000 Input Seed : 0000010000 39 | ap_uint<1> out_bit, next_bit; 40 | #pragma HLS RESET variable=next_bit 41 | static ap_uint<10> poly_reg, shift_reg, next_reg_state; 42 | #pragma HLS RESET variable=next_reg_state 43 | #pragma HLS RESET variable=shift_reg 44 | #pragma HLS RESET variable=poly_reg 45 | 46 | 47 | next_bit = (shift_reg & poly_reg).xor_reduce(); 48 | next_reg_state = (next_bit, shift_reg(9,1)); // shift all the bits 49 | out_bit = shift_reg[10 - order];// take output only in the middle of the register (or the LSB for order = 10) 50 | 51 | if(load){ 52 | shift_reg = seed; 53 | poly_reg = poly; 54 | } 55 | else 56 | { 57 | if(pn_req){ 58 | shift_reg = next_reg_state; 59 | } 60 | } 61 | return out_bit; 62 | 63 | } 64 | -------------------------------------------------------------------------------- /hls-projects/pn_seq_gen_lfsr/script.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2015 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | open_project pn_seq_lfsr 7 | set_top pn_seq_gen_lfsr 8 | add_files pn_seq_gen_lfsr.cpp 9 | open_solution "solution1" 10 | set_part {xc7k410tffg900-2} 11 | create_clock -period 5 -name default 12 | #source "./pn_seq_lfsr/solution1/directives.tcl" 13 | #csim_design 14 | csynth_design 15 | #cosim_design 16 | export_design -format ip_catalog 17 | -------------------------------------------------------------------------------- /hls-projects/spreader/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Spreader 3 | 4 | The spreader HLs project is used to generate HDL for spreading task, which is wrapped into a CE to plug into the RFNoC framework. 5 | To conform with the requirements of an RFNoC block, axi stream input and output interfaces are used. The spreader takes in data symbols in SC16 format(signed complex numbers with 16 bit real and imaginary parts) and spreads them using a real PN sequence giving L SC16 output symbols for each input, where L is the sequence length. The PN sequence is locally generated by a [PN sequence generator.](../pn_seq_gen_lfsr/README.md) 6 | 7 | Incoming packet is stored in a local FIFO. The variable data_fifo was declared as hls::stream type and resource set to FIFO as shown. 8 | 9 | _static hls::stream > data_fifo;_ 10 | 11 | _#pragma HLS STREAM variable=data_fifo depth=256 dim=1_ 12 | 13 | _#pragma HLS RESOURCE variable=data_fifo core=FIFO_ 14 | 15 | The spreader module uses a state machine to wait for incoming data, loading the PN sequence generator and spreading the incoming data. Once all the samples in an incoming packet are processed, a new packet is read into the data_fifo. Since the data_fifo depth is set to 256, the maximum size of an incoming packet is 256. 16 | 17 | 18 | -------------------------------------------------------------------------------- /hls-projects/spreader/rfnoc.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /*rfnoc.h - Used to define custom AXI stream interface required for noc_blocks 24 | The default AXI stream interface in Vivado HLS consists of data, valid and ready signals. rfnoc_axis has 'last' signal along with those. 25 | */ 26 | #include "ap_int.h" 27 | 28 | struct rfnoc_axis{ 29 | ap_int<32> data; 30 | ap_uint<1> last; 31 | }; 32 | 33 | -------------------------------------------------------------------------------- /hls-projects/spreader/script.tcl: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | ## This file is generated automatically by Vivado HLS. 3 | ## Please DO NOT edit it. 4 | ## Copyright (C) 2015 Xilinx Inc. All rights reserved. 5 | ############################################################ 6 | open_project spreading_fsm 7 | set_top spreader 8 | add_files spreader.cpp 9 | open_solution "solution1" 10 | set_part {xc7k410tffg900-2} 11 | create_clock -period 5 -name default 12 | set_clock_uncertainty 12% 13 | config_interface -m_axi_offset off -register_io off -trim_dangling_port 14 | config_rtl -encoding onehot -reset all -reset_level high 15 | #source "./spreading_fsm/solution1/directives.tcl" 16 | #csim_design 17 | csynth_design 18 | #cosim_design 19 | export_design -format ip_catalog 20 | -------------------------------------------------------------------------------- /hls-projects/spreader/spreader.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | // 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /* spreader.cpp - Used to generate RTL for the spreader module used in noc_block_spreader 24 | i_data - AXI stream input data (with tlast) 25 | o_data - AXI stream output data (with tlast) 26 | pnseq - PN sequence used for spreading the input data. As this port is setup as 'ap_hs', handshaking signals 'valid' and 'ack' are generated. All these 3 signals are connected to the PN sequence generator instance in noc_block_spreader 27 | pnseq_len - input parameter PN sequence length 28 | */ 29 | #include 30 | #include "rfnoc.h" 31 | 32 | ap_uint<1> spreader(hls::stream i_data, hls::stream o_data, hls::stream > pnseq,ap_uint<10> pnseq_len){ 33 | #pragma HLS PIPELINE II=1 34 | #pragma HLS INTERFACE ap_ctrl_none port=return 35 | #pragma HLS INTERFACE ap_hs port=pnseq 36 | #pragma HLS INTERFACE axis port=i_data 37 | #pragma HLS INTERFACE axis port=o_data 38 | 39 | static ap_uint<10> reg_pnseq_len, out_sample_cnt; 40 | #pragma HLS RESET variable=out_sample_cnt 41 | #pragma HLS RESET variable=reg_pnseq_len 42 | 43 | static hls::stream > data_fifo; 44 | #pragma HLS STREAM variable=data_fifo depth=256 dim=1 45 | #pragma HLS RESOURCE variable=data_fifo core=FIFO 46 | // internal FIFO with depth = 256, to store incoming data 47 | 48 | static ap_uint<32> reg_data; 49 | rfnoc_axis out_sample, tmp_data; 50 | static ap_uint<1> last_in_sample, load; 51 | #pragma HLS RESET variable=last_in_sample 52 | 53 | enum spreadState {ST_IDLE = 0, ST_LOAD, ST_WAIT, ST_READ, ST_SPREAD}; 54 | static spreadState currentState; 55 | 56 | switch(currentState) { 57 | case ST_IDLE: // Wait for incoming data 58 | load = 0; 59 | last_in_sample = 0; 60 | reg_pnseq_len = pnseq_len; 61 | if(!i_data.empty()){ 62 | data_fifo.write(i_data.read().data); 63 | currentState = ST_LOAD;} 64 | else 65 | currentState = ST_IDLE; 66 | break; 67 | 68 | case ST_LOAD: 69 | load = 1; // load the pn seq generator (generator polynomial and seed are loaded) 70 | currentState = ST_WAIT; 71 | break; 72 | 73 | case ST_WAIT: 74 | currentState = ST_READ; 75 | break; 76 | 77 | case ST_READ: 78 | load = 0; 79 | if(data_fifo.read_nb(reg_data)) // non-blocking read from data fifo. 80 | currentState = ST_SPREAD; // go to ST_SPREAD if the read is successful 81 | else 82 | currentState = ST_IDLE; // ST_IDLE when there is no data in the FIFO 83 | break; 84 | 85 | case ST_SPREAD: 86 | load = 0; 87 | if(!last_in_sample & !data_fifo.full()){ // Write into the FIFO when it is not full, and write only this frame 88 | if(i_data.read_nb(tmp_data)){ // a temporary data variable. 89 | last_in_sample = tmp_data.last; 90 | data_fifo.write(tmp_data.data); 91 | } 92 | } 93 | 94 | if (out_sample_cnt == reg_pnseq_len-1) 95 | out_sample.last = 1; 96 | else 97 | out_sample.last = 0; 98 | if(pnseq.read() == 1) 99 | out_sample.data = reg_data; 100 | else{ 101 | out_sample.data.range(31,16) = (0 - reg_data.range(31,16)); 102 | out_sample.data.range(15,0) = (0 - reg_data.range(15,0)); // IM, RE 103 | } 104 | if (out_sample_cnt == reg_pnseq_len-1) 105 | { 106 | currentState = ST_LOAD; 107 | out_sample_cnt = 0; 108 | } 109 | else 110 | { 111 | currentState = ST_SPREAD; 112 | out_sample_cnt = out_sample_cnt+1; 113 | } 114 | o_data.write(out_sample); 115 | 116 | break; 117 | } 118 | 119 | return load; 120 | } 121 | 122 | -------------------------------------------------------------------------------- /host/blocks/cir_avg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | CIRAvg 4 | CIRAvg 5 | 6 | 7 | FFFFC200 8 | 9 | 10 | 11 | 12 | 13 | BLOCK_RESET 14 |
131
15 |
16 | 17 | THRESHOLD 18 |
132
19 |
20 | 21 | AVG_SIZE_SEQ_LEN 22 |
133
23 |
24 | 25 | RB_BLOCK_RESET 26 |
0
27 |
28 |
29 | 30 | 31 | 32 | 33 | in 34 | sc16 35 | 36 | 37 | out 38 | sc16 39 | 40 | 41 |
42 | -------------------------------------------------------------------------------- /host/blocks/cir_avg_block_ctrl.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /* cir_avg_block_ctrl.hpp - Block controller for cir_avg NoC block 24 | Used Ettus provided block controllers for reference 25 | */ 26 | 27 | #ifndef INCLUDED_LIBUHD_RFNOC_cir_avg_block_ctrl_HPP 28 | #define INCLUDED_LIBUHD_RFNOC_cir_avg_block_ctrl_HPP 29 | 30 | #include 31 | #include 32 | 33 | namespace uhd { 34 | namespace rfnoc { 35 | 36 | class UHD_RFNOC_API cir_avg_block_ctrl : public source_block_ctrl_base, public sink_block_ctrl_base 37 | { 38 | public: 39 | UHD_RFNOC_BLOCK_OBJECT(cir_avg_block_ctrl) 40 | 41 | //! Configure the averaging block 42 | // 43 | virtual void set_cir_avg(const uint32_t threshold, const int log_avg_size, const int seq_len) = 0; 44 | 45 | }; /* class cir_avg_block_ctrl*/ 46 | 47 | }} /* namespace uhd::rfnoc */ 48 | 49 | #endif /* INCLUDED_LIBUHD_RFNOC_cir_avg_block_ctrl_HPP */ 50 | // vim: sw=4 et: 51 | -------------------------------------------------------------------------------- /host/blocks/cir_avg_block_ctrl_impl.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /* cir_avg_block_ctrl_impl.cpp - Block controller implementation for cir_avg NoC block 24 | Used Ettus provided block controllers for reference 25 | */ 26 | #include 27 | #include 28 | #include 29 | 30 | using namespace uhd::rfnoc; 31 | 32 | class cir_avg_block_ctrl_impl : public cir_avg_block_ctrl 33 | { 34 | public: 35 | 36 | UHD_RFNOC_BLOCK_CONSTRUCTOR(cir_avg_block_ctrl) 37 | { 38 | set_cir_avg(0xFFFF/*threshold*/, 4/*log_avg_size*/, 255/*pn seq len*/); 39 | } 40 | 41 | void set_cir_avg(const uint32_t threshold, const int log_avg_size, const int seq_len) 42 | { 43 | UHD_RFNOC_BLOCK_TRACE() << "cir_avg::set_cir_avg()" << std::endl; 44 | UHD_MSG(status) << "Configuring CIR avg. Threshold : " << threshold << "Log2(avg_size) : " << log_avg_size << "Seq_len : " << seq_len << std::endl; 45 | 46 | if(log_avg_size > 7) { 47 | throw uhd::value_error(str(boost::format("log2(avg_size) should be <= 7 - Maximum averaging factor is 256"))); 48 | } 49 | if(seq_len > 1023){ 50 | throw uhd::value_error(str(boost::format("PN sequence too long!! length should be <= 1023"))); 51 | } 52 | 53 | sr_write("BLOCK_RESET", 1); 54 | sr_write("BLOCK_RESET", 0); 55 | 56 | uint32_t log_avg_size_seq_len = (log_avg_size << 10) + seq_len; 57 | sr_write("THRESHOLD", threshold); 58 | 59 | sr_write("AVG_SIZE_SEQ_LEN", log_avg_size_seq_len ); 60 | } 61 | 62 | }; 63 | 64 | UHD_RFNOC_BLOCK_REGISTER(cir_avg_block_ctrl, "CIRAvg"); 65 | -------------------------------------------------------------------------------- /host/blocks/correlator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Correlator 4 | Correlator 5 | 6 | 7 | FFFFC100 8 | 9 | 10 | 11 | 12 | 13 | BLOCK_RESET 14 |
131
15 |
16 | 17 | BLOCK_START 18 |
132
19 |
20 | 21 | GEN_SEED_POLY 22 |
133
23 |
24 | 25 | GEN_ORDER_LEN 26 |
134
27 |
28 | 29 | RB_BLOCK_RESET 30 |
0
31 |
32 |
33 | 34 | 35 | 36 | in 37 | sc16 38 | 39 | 40 | out 41 | sc16 42 | 43 | 44 |
45 | -------------------------------------------------------------------------------- /host/blocks/correlator_block_ctrl.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /* correlator_block_ctrl.hpp - Block controller for correlator NoC block 24 | Used Ettus provided block controllers for reference 25 | */ 26 | 27 | #ifndef INCLUDED_LIBUHD_RFNOC_correlator_block_ctrl_HPP 28 | #define INCLUDED_LIBUHD_RFNOC_correlator_block_ctrl_HPP 29 | 30 | #include 31 | #include 32 | 33 | namespace uhd { 34 | namespace rfnoc { 35 | 36 | class UHD_RFNOC_API correlator_block_ctrl : public source_block_ctrl_base, public sink_block_ctrl_base 37 | { 38 | public: 39 | UHD_RFNOC_BLOCK_OBJECT(correlator_block_ctrl) 40 | 41 | //! Configure the PN sequence generator 42 | // 43 | virtual void set_pn_seq_gen(const std::string poly, const std::string seed, const int seq_len) = 0; 44 | 45 | }; /* class correlator_block_ctrl*/ 46 | 47 | }} /* namespace uhd::rfnoc */ 48 | 49 | #endif /* INCLUDED_LIBUHD_RFNOC_correlator_block_ctrl_HPP */ 50 | // vim: sw=4 et: 51 | -------------------------------------------------------------------------------- /host/blocks/correlator_block_ctrl_impl.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /* correlator_block_ctrl_impl.cpp - Block controller implementation for correlator NoC block 24 | Used Ettus provided block controllers for reference 25 | */ 26 | #include 27 | #include 28 | #include 29 | 30 | using namespace uhd::rfnoc; 31 | 32 | class correlator_block_ctrl_impl : public correlator_block_ctrl 33 | { 34 | public: 35 | 36 | UHD_RFNOC_BLOCK_CONSTRUCTOR(correlator_block_ctrl) 37 | { 38 | //Set default generator polynomial - x^6+x^5+1, seed - 000001, pn seq len - 63 39 | set_pn_seq_gen("000011"/*poly*/, "000001"/*seed*/, 63/*pn seq len*/); 40 | //Set default generator polynomial - x^8+x^6+x^5+x^4+1, seed - 000001, pn seq len - 63 41 | //set_pn_seq_gen("00011101"/*poly*/, "000001"/*seed*/, 255/*pn seq len*/); 42 | } 43 | 44 | void set_pn_seq_gen(const std::string poly, const std::string seed, const int seq_len) 45 | { 46 | UHD_RFNOC_BLOCK_TRACE() << "spec_spreader::set_pn_seq_gen()" << std::endl; 47 | UHD_MSG(status) << "Configuring PN seq gen. Poly : " << poly << "Seed : " << seed << "Seq_len : " << seq_len << std::endl; 48 | 49 | if(poly.length() > 10) { 50 | throw uhd::value_error(str(boost::format("Generator polynomial too long!! length should be <= 10"))); 51 | } 52 | if(seed.length() > 10) { 53 | throw uhd::value_error(str(boost::format("Generator seed too long!! length should be <= 10"))); 54 | } 55 | if(seq_len > 1023){ 56 | throw uhd::value_error(str(boost::format("PN sequence too long!! length should be <= 1023"))); 57 | } 58 | 59 | int gen_order = 0; 60 | for(int i = 0; i < poly.length(); i++) 61 | { 62 | if(poly[i] == '1') 63 | gen_order = i+1; 64 | else if(poly[i] != '0') 65 | throw uhd::value_error(str(boost::format("Please specify the generator polynomial in binary format"))); 66 | } 67 | for(int i = 0; i < seed.length(); i++) 68 | { 69 | if(seed[i] != '0' && seed[i] != '1') 70 | throw uhd::value_error(str(boost::format("Please specify the seed in binary format"))); 71 | } 72 | 73 | sr_write("BLOCK_RESET", 1); 74 | sr_write("BLOCK_RESET", 0); 75 | int gen_poly = stoi(poly, nullptr, 2); 76 | int gen_seed = stoi(seed, nullptr, 2); 77 | gen_poly = gen_poly << (10 - poly.length()); 78 | gen_seed = gen_seed << ((10 - seed.length()) + 10); 79 | uint32_t gen_seed_poly = gen_seed + gen_poly; 80 | 81 | sr_write("GEN_SEED_POLY", gen_seed_poly); 82 | 83 | gen_order = gen_order << 10; 84 | uint32_t gen_order_len = gen_order + seq_len; 85 | 86 | sr_write("GEN_ORDER_LEN", gen_order_len); 87 | sr_write("BLOCK_START", 1); 88 | sr_write("BLOCK_START", 0); 89 | } 90 | 91 | 92 | /*std::string get_poly() 93 | { 94 | uint64_t gen_seed_poly = user_reg_read64(1); 95 | std::string poly; 96 | for (int i = 0; i < 10; i++) 97 | { 98 | if(gen_seed_poly & 1) 99 | poly = '1' + poly; 100 | else 101 | poly = '0' + poly; 102 | 103 | gen_seed_poly >> 1; 104 | } 105 | return poly; 106 | }*/ 107 | 108 | 109 | }; 110 | 111 | UHD_RFNOC_BLOCK_REGISTER(correlator_block_ctrl, "Correlator"); 112 | -------------------------------------------------------------------------------- /host/blocks/spec_spreader.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | SpectrumSpreader 4 | Spreader 5 | 6 | 7 | FFFFC000 8 | 9 | 10 | 11 | 12 | 13 | BLOCK_RESET 14 |
131
15 |
16 | 17 | GEN_SEED_POLY 18 |
132
19 |
20 | 21 | GEN_ORDER_LEN 22 |
133
23 |
24 | 25 | RB_BLOCK_RESET 26 |
0
27 |
28 |
29 | 30 | 31 | 32 | in 33 | sc16 34 | 35 | 36 | out 37 | sc16 38 | 39 | 40 |
41 | -------------------------------------------------------------------------------- /host/blocks/spec_spreader_block_ctrl.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /* spec_spreader_block_ctrl.hpp - Block controller for spec_spreader NoC block 24 | Used Ettus provided block controllers for reference 25 | */ 26 | 27 | #ifndef INCLUDED_LIBUHD_RFNOC_spec_spreader_block_ctrl_HPP 28 | #define INCLUDED_LIBUHD_RFNOC_spec_spreader__block_ctrl_HPP 29 | 30 | #include 31 | #include 32 | 33 | namespace uhd { 34 | namespace rfnoc { 35 | 36 | class UHD_RFNOC_API spec_spreader_block_ctrl : public source_block_ctrl_base, public sink_block_ctrl_base 37 | { 38 | public: 39 | UHD_RFNOC_BLOCK_OBJECT(spec_spreader_block_ctrl) 40 | 41 | //! Configure the PN sequence generator 42 | // 43 | virtual void set_pn_seq_gen(const std::string poly, const std::string seed, const int seq_len) = 0; 44 | 45 | }; /* class spec_spreader_block_ctrl*/ 46 | 47 | }} /* namespace uhd::rfnoc */ 48 | 49 | #endif /* INCLUDED_LIBUHD_RFNOC_spec_spreader_block_ctrl_HPP */ 50 | // vim: sw=4 et: 51 | -------------------------------------------------------------------------------- /host/blocks/spec_spreader_block_ctrl_impl.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | //Team WINLAB 22 | //RFNoC HLS Challenge 23 | /* spec_spreader_block_ctrl_impl.cpp - Block controller implementation for spec_spreader NoC block 24 | Used Ettus provided block controllers for reference 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | using namespace uhd::rfnoc; 32 | 33 | class spec_spreader_block_ctrl_impl : public spec_spreader_block_ctrl 34 | { 35 | public: 36 | 37 | UHD_RFNOC_BLOCK_CONSTRUCTOR(spec_spreader_block_ctrl) 38 | { 39 | //Set default generator polynomial - x^6+x^5+1, seed - 000001, pn seq len - 63 40 | set_pn_seq_gen("000011"/*poly*/, "000001"/*seed*/, 63/*pn seq len*/); 41 | //Set default generator polynomial - x^8+x^6+x^5+x^4+1, seed - 000001, pn seq len - 63 42 | //set_pn_seq_gen("00011101"/*poly*/, "000001"/*seed*/, 255/*pn seq len*/); 43 | } 44 | 45 | void set_pn_seq_gen(const std::string poly, const std::string seed, const int seq_len) 46 | { 47 | UHD_RFNOC_BLOCK_TRACE() << "spec_spreader::set_pn_seq_gen()" << std::endl; 48 | UHD_MSG(status) << "Configuring PN seq gen. Poly : " << poly << "Seed : " << seed << "Seq_len : " << seq_len << std::endl; 49 | 50 | if(poly.length() > 10) { 51 | throw uhd::value_error(str(boost::format("Generator polynomial too long!! length should be <= 10"))); 52 | } 53 | if(seed.length() > 10) { 54 | throw uhd::value_error(str(boost::format("Generator seed too long!! length should be <= 10"))); 55 | } 56 | if(seq_len > 1023){ 57 | throw uhd::value_error(str(boost::format("PN sequence too long!! length should be <= 1023"))); 58 | } 59 | 60 | int gen_order = 0; 61 | for(int i = 0; i < poly.length(); i++) 62 | { 63 | if(poly[i] == '1') 64 | gen_order = i+1; 65 | else if(poly[i] != '0') 66 | throw uhd::value_error(str(boost::format("Please specify the generator polynomial in binary format"))); 67 | } 68 | for(int i = 0; i < seed.length(); i++) 69 | { 70 | if(seed[i] != '0' && seed[i] != '1') 71 | throw uhd::value_error(str(boost::format("Please specify the seed in binary format"))); 72 | } 73 | 74 | sr_write("BLOCK_RESET", 1); 75 | sr_write("BLOCK_RESET", 0); 76 | 77 | int gen_poly = stoi(poly, nullptr, 2); 78 | int gen_seed = stoi(seed, nullptr, 2); 79 | gen_poly = gen_poly << (10 - poly.length()); 80 | gen_seed = gen_seed << ((10 - seed.length()) + 10); 81 | uint32_t gen_seed_poly = gen_seed + gen_poly; 82 | 83 | sr_write("GEN_SEED_POLY", gen_seed_poly); 84 | 85 | gen_order = gen_order << 10; 86 | uint32_t gen_order_len = gen_order + seq_len; 87 | 88 | sr_write("GEN_ORDER_LEN", gen_order_len); 89 | } 90 | 91 | 92 | /*std::string get_poly() 93 | { 94 | uint64_t gen_seed_poly = user_reg_read64(1); 95 | std::string poly; 96 | for (int i = 0; i < 10; i++) 97 | { 98 | if(gen_seed_poly & 1) 99 | poly = '1' + poly; 100 | else 101 | poly = '0' + poly; 102 | 103 | gen_seed_poly >> 1; 104 | } 105 | return poly; 106 | }*/ 107 | 108 | 109 | }; 110 | 111 | UHD_RFNOC_BLOCK_REGISTER(spec_spreader_block_ctrl, "Spreader"); 112 | -------------------------------------------------------------------------------- /host/examples/rfnoc_multi_chan_correlator.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | namespace po = boost::program_options; 45 | 46 | static bool stop_signal_called = false; 47 | void sig_int_handler(int){stop_signal_called = true;} 48 | 49 | // Receiver streamer function 50 | template void recv_to_file( 51 | uhd::rx_streamer::sptr rx_stream, 52 | const std::string &file, 53 | const size_t samps_per_buff, 54 | const double rx_rate, 55 | const unsigned long long num_requested_samples, 56 | double time_requested = 0.0, 57 | bool continue_on_bad_packet = false, 58 | int num_usrp = 1, 59 | int num_chan = 1, 60 | uhd::usrp::multi_usrp::sptr usrp_temp = 0 61 | ){ 62 | unsigned long long num_total_samps = 0; 63 | uhd::rx_metadata_t md; 64 | std::vector > buff( 65 | num_usrp*num_chan, std::vector(samps_per_buff) 66 | ); 67 | std::vector buff_ptrs; 68 | for (size_t i = 0; i < buff.size(); i++) buff_ptrs.push_back(&buff[i].front()); 69 | bool overflow_message = true; 70 | std::ofstream outfile; 71 | std::string outfilename; 72 | 73 | //setup streaming 74 | uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); 75 | stream_cmd.stream_now = false; 76 | stream_cmd.time_spec = usrp_temp->get_time_now() + uhd::time_spec_t(1.0); 77 | double timeout = stream_cmd.time_spec.get_real_secs() + 0.5; 78 | std::cout << "Issuing stream cmd" << std::endl; 79 | rx_stream->issue_stream_cmd(stream_cmd); 80 | std::cout << "Done" << std::endl; 81 | 82 | // If want to stream packets for certain duration 83 | boost::system_time start = boost::get_system_time(); 84 | unsigned long long ticks_requested = (long)(time_requested * (double)boost::posix_time::time_duration::ticks_per_second()); 85 | boost::posix_time::time_duration ticks_diff; 86 | //boost::system_time last_update = start; 87 | //unsigned long long last_update_samps = 0; 88 | 89 | while(not stop_signal_called) { 90 | boost::system_time now = boost::get_system_time(); 91 | 92 | size_t num_rx_samps = rx_stream->recv(buff_ptrs, samps_per_buff, md, timeout); 93 | stream_cmd.stream_now = true; 94 | timeout = 0.5; 95 | if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) { 96 | std::cout << boost::format("Timeout while streaming") << std::endl; 97 | break; 98 | } 99 | if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW){ 100 | if (overflow_message) { 101 | overflow_message = false; 102 | std::cerr << boost::format( 103 | "Got an overflow indication. Please consider the following:\n" 104 | " Your write medium must sustain a rate of %fMB/s.\n" 105 | " Dropped samples will not be written to the file.\n" 106 | " Please modify this example for your purposes.\n" 107 | " This message will not appear again.\n" 108 | ) % (rx_rate*sizeof(samp_type)/1e6); 109 | } 110 | continue; 111 | } 112 | if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE){ 113 | std::string error = str(boost::format("Receiver error: %s") % md.strerror()); 114 | if (continue_on_bad_packet){ 115 | std::cerr << error << std::endl; 116 | continue; 117 | } 118 | else 119 | throw std::runtime_error(error); 120 | } 121 | if (num_requested_samples > 0) { 122 | if (not file.empty()) { 123 | for (int i = 0; i < num_usrp*num_chan; i++) { 124 | outfilename = file + "_ch_" + boost::lexical_cast(i) + "_binary"; 125 | outfile.open(outfilename.c_str(), std::ofstream::binary); 126 | outfile.write((const char*)buff_ptrs.at(i), samps_per_buff*sizeof(samp_type)); 127 | if (outfile.is_open()) { 128 | outfile.close(); 129 | } 130 | } 131 | } 132 | num_total_samps += num_rx_samps; 133 | if (num_total_samps >= num_rx_samps) { 134 | break; 135 | } 136 | } 137 | ticks_diff = now - start; 138 | if (ticks_requested > 0){ 139 | if ((unsigned long long)ticks_diff.ticks() > ticks_requested) { 140 | break; 141 | } 142 | } 143 | } 144 | stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; 145 | std::cout << "Issuing stop stream cmd" << std::endl; 146 | rx_stream->issue_stream_cmd(stream_cmd); 147 | std::cout << "Done" << std::endl; 148 | } 149 | 150 | 151 | int UHD_SAFE_MAIN(int argc, char *argv[]){ 152 | uhd::set_thread_priority_safe(); 153 | 154 | //variables to be set by po 155 | std::string args, file, ant, subdev, ref, streamargs, ddc_args, corr_args, pn_seed, pn_poly, sync, radio_args; 156 | size_t total_num_samps, spb; 157 | double rate, freq, gain, bw, total_time, setup_time; 158 | int pn_len, num_usrp, num_chan, avg, thres; 159 | 160 | 161 | //setup the program options 162 | po::options_description desc("Allowed options"); 163 | desc.add_options() 164 | ("help", "help message") 165 | ("file", po::value(&file)->default_value("usrp_samples"), "name of the file to write binary samples to") 166 | ("duration", po::value(&total_time)->default_value(0), "total number of seconds to receive (will stream continuously if set to 0)") 167 | ("nsamps", po::value(&total_num_samps)->default_value(0), "total number of samples to receive (will stream continouosly if set to 0)") 168 | ("spb", po::value(&spb)->default_value(10000), "samples per buffer") 169 | ("continue", "don't abort on a bad packet") 170 | ("args", po::value(&args)->default_value(""), "USRP device address args") 171 | ("setup", po::value(&setup_time)->default_value(1.0), "seconds of setup time") 172 | ("subdev", po::value(&subdev), "subdev spec (homogeneous across motherboards)") 173 | ("rate", po::value(&rate)->default_value(1e6), "RX rate of the radio block") 174 | ("freq", po::value(&freq)->default_value(0.0), "RF center frequency in Hz") 175 | ("gain", po::value(&gain), "gain for the RF chain") 176 | ("ant", po::value(&ant), "antenna selection") 177 | ("bw", po::value(&bw), "analog frontend filter bandwidth in Hz") 178 | ("ref", po::value(&ref), "reference source (internal, external, mimo)") 179 | ("sync", po::value(&sync)->default_value("now"), "Sync (now (for no sync) or pps)") 180 | ("skip-lo", "skip checking LO lock status") 181 | ("int-n", "tune USRP with integer-N tuning") 182 | ("ddc-args", po::value(&ddc_args)->default_value(""), "These args are passed straight to the DDC block.") 183 | ("PN-length", po::value(&pn_len)->default_value(255), "length of PN Sequence (default = 255)") 184 | ("PN-seed", po::value(&pn_seed)->default_value("00000001"), "Seed polynomial (default = 00000001)") 185 | ("PN-gen-poly", po::value(&pn_poly)->default_value("00011101"), "Generator polynomial (default = 00011101)") 186 | ("num-usrp", po::value(&num_usrp)->default_value(1), "number of devices to use") 187 | ("radio-args", po::value(&radio_args)->default_value("0"), "Radio args (0, 1, (0,1))") 188 | ("avg", po::value(&avg)->default_value(4), "\"2^avg\" times the correlator output will be averaged") 189 | ("threshold", po::value(&thres)->default_value(0xFFFF), "correlator threshold (peaks below this threshold will not be considered)") 190 | ("streamargs", po::value(&streamargs)->default_value(""), "additional stream args") 191 | ; 192 | po::variables_map vm; 193 | po::store(po::parse_command_line(argc, argv, desc), vm); 194 | po::notify(vm); 195 | 196 | //print the help message 197 | if (vm.count("help")) { 198 | std::cout << boost::format("UHD/RFNoC RX samples to file %s") % desc << std::endl; 199 | std::cout 200 | << std::endl 201 | << "This application streams the Channel Impulse Resonse (CIR) output from multiple USRPs based on certain PN sequence.\n" 202 | << std::endl; 203 | return ~0; 204 | } 205 | 206 | // Receiver streamer continues even if a bad packet is received 207 | bool continue_on_bad_packet = vm.count("continue") > 0; 208 | 209 | /************************************************************************ 210 | * Create device and block controls 211 | ***********************************************************************/ 212 | std::cout << std::endl; 213 | std::cout << boost::format("Creating the USRP device with: %s...") % args << std::endl; 214 | std::vector radio_ctrl_vector; 215 | //Creating multi-usrp pointer to handle control of multiple channels and converting to device3 pointer to give RFNoC graph commands 216 | uhd::usrp::multi_usrp::sptr usrp_temp = uhd::usrp::multi_usrp::make(args); 217 | uhd::device3::sptr usrp = usrp_temp->get_device3(); 218 | 219 | std::vector radio_arg_vec; 220 | boost::split(radio_arg_vec, radio_args, boost::is_any_of("\"',")); 221 | num_chan = radio_arg_vec.size(); 222 | if (num_chan > 2 or num_chan < 1) { 223 | std::cout << "Radio arguments should be 0,1,or (0,1)..." << std::endl; 224 | return ~0; 225 | } 226 | 227 | for (int i = 0; i < num_usrp; i++) { 228 | for (int ch = 0; ch < num_chan; ch++) { 229 | uhd::rfnoc::block_id_t radio_ctrl_id(i, "Radio", boost::lexical_cast(radio_arg_vec[ch])); 230 | // This next line will fail if the radio is not actually available 231 | radio_ctrl_vector.push_back(usrp->get_block_ctrl< uhd::rfnoc::radio_ctrl >(radio_ctrl_id)); 232 | std::cout << "Using radio " << i << ", channel " << radio_arg_vec[ch] << std::endl; 233 | } 234 | } 235 | 236 | //Set clock reference for all devices 237 | if (vm.count("ref")) { 238 | usrp_temp->set_clock_source(ref); 239 | } 240 | 241 | 242 | for (int i = 0; i < num_usrp*num_chan; ++i) { 243 | // Set center frequency for all rx chains 244 | if (vm.count("freq")) { 245 | std::cout << boost::format("Setting RX Freq: %f MHz...") % (freq/1e6) << std::endl; 246 | uhd::tune_request_t tune_request(freq); 247 | if (vm.count("int-n")) { 248 | tune_request.args = uhd::device_addr_t("mode_n=integer"); 249 | } 250 | usrp_temp->set_rx_freq(freq, i); 251 | std::cout << boost::format("Actual RX Freq: %f MHz...") % (usrp_temp->get_rx_freq(i)/1e6) << std::endl << std::endl; 252 | } 253 | 254 | // Set the RF gain 255 | if (vm.count("gain")) { 256 | std::cout << boost::format("Setting RX Gain: %f dB...") % gain << std::endl; 257 | usrp_temp->set_rx_gain(gain, i); 258 | std::cout << boost::format("Actual RX Gain: %f dB...") % usrp_temp->get_rx_gain(i) << std::endl << std::endl; 259 | } 260 | 261 | //set the IF filter bandwidth 262 | if (vm.count("bw")) { 263 | std::cout << boost::format("Setting RX Bandwidth: %f MHz...") % (bw/1e6) << std::endl; 264 | usrp_temp->set_rx_bandwidth(bw, i); 265 | std::cout << boost::format("Actual RX Bandwidth: %f MHz...") % (usrp_temp->get_rx_bandwidth(i)/1e6) << std::endl << std::endl; 266 | } 267 | 268 | // Set the antenna 269 | if (vm.count("ant")) { 270 | usrp_temp->set_rx_antenna(ant, i); 271 | } 272 | } 273 | boost::this_thread::sleep(boost::posix_time::milliseconds(long(setup_time*1000))); //allow for some setup time 274 | 275 | if (sync == "now") { 276 | usrp_temp->set_time_now(uhd::time_spec_t(0.0)); 277 | } 278 | else if (sync == "pps") { 279 | usrp_temp->set_time_source("external"); 280 | usrp_temp->set_time_unknown_pps(uhd::time_spec_t(0.0)); 281 | boost::this_thread::sleep(boost::posix_time::seconds(2)); //wait for pps sync pulse 282 | } 283 | /************************************************************************ 284 | * Set up streaming 285 | ***********************************************************************/ 286 | 287 | 288 | uhd::device_addr_t streamer_args(streamargs); 289 | uhd::rx_streamer::sptr rx_stream; 290 | uhd::rfnoc::graph::sptr rx_graph; 291 | uhd::rfnoc::source_block_ctrl_base::sptr ddc_ctrl; 292 | uhd::rfnoc::correlator_block_ctrl::sptr corr_ctrl; 293 | uhd::rfnoc::cir_avg_block_ctrl::sptr cir_avg_ctrl; 294 | rx_graph = usrp->create_graph("rfnoc_corr_rx_to_file"); 295 | usrp->clear(); 296 | 297 | for (size_t i = 0; i < num_usrp; i++) { 298 | for (int ch = 0; ch < num_chan; ch++) { 299 | uhd::rfnoc::block_id_t radio_ctrl_id(i, "Radio", boost::lexical_cast(radio_arg_vec[ch])); 300 | std::string ddc_id(boost::lexical_cast(i)+"/DDC_"+radio_arg_vec[ch]); 301 | std::string corr_id(boost::lexical_cast(i)+"/Correlator_"+radio_arg_vec[ch]); 302 | std::string cir_avg_id(boost::lexical_cast(i)+"/CIRAvg_"+radio_arg_vec[ch]); 303 | ddc_ctrl = usrp->get_block_ctrl(ddc_id); 304 | corr_ctrl = usrp->get_block_ctrl(corr_id); 305 | cir_avg_ctrl = usrp->get_block_ctrl(cir_avg_id); 306 | 307 | ddc_ctrl->set_args(uhd::device_addr_t(ddc_args)); 308 | corr_ctrl->set_pn_seq_gen(pn_poly,pn_seed,pn_len); 309 | cir_avg_ctrl->set_cir_avg(thres, avg, pn_len); 310 | std::cout << "Connecting " << radio_ctrl_id << " ==> " << ddc_ctrl->get_block_id() << std::endl; 311 | rx_graph->connect(radio_ctrl_id, ch, ddc_ctrl->get_block_id(), uhd::rfnoc::ANY_PORT); 312 | std::cout << "Connecting " << ddc_ctrl->get_block_id() << " ==> " << corr_ctrl->get_block_id() << std::endl; 313 | rx_graph->connect(ddc_ctrl->get_block_id(), uhd::rfnoc::ANY_PORT, corr_ctrl->get_block_id(), uhd::rfnoc::ANY_PORT); 314 | std::cout << "Connecting " << corr_ctrl->get_block_id() << " ==> " << cir_avg_ctrl->get_block_id() << std::endl; 315 | rx_graph->connect(corr_ctrl->get_block_id(), uhd::rfnoc::ANY_PORT, cir_avg_ctrl->get_block_id(), uhd::rfnoc::ANY_PORT); 316 | streamer_args["block_id"+boost::lexical_cast(ch + i*num_chan)] = cir_avg_id; 317 | } 318 | } 319 | 320 | 321 | //create a receive streamer 322 | //Setting the samples per packet for streaming 323 | size_t spp = pn_len; 324 | UHD_MSG(status) << "Samples per packet: " << spp << std::endl; 325 | uhd::stream_args_t stream_args("sc16", "sc16"); // We should read the wire format from the blocks 326 | stream_args.args = streamer_args; 327 | stream_args.args["spp"] = boost::lexical_cast(spp); 328 | std::vector usrp_nums; 329 | for (int i = 0; i < num_usrp*num_chan; i++) { 330 | usrp_nums.push_back(i); 331 | } 332 | stream_args.channels = usrp_nums; 333 | UHD_MSG(status) << "Using streamer args: " << stream_args.args.to_string() << std::endl; 334 | rx_stream = usrp->get_rx_stream(stream_args); 335 | 336 | if (total_num_samps == 0) { 337 | std::signal(SIGINT, &sig_int_handler); 338 | std::cout << "Press Ctrl + C to stop streaming..." << std::endl; 339 | } 340 | #define recv_to_file_args() \ 341 | (rx_stream, file, spb, rate, total_num_samps, total_time, continue_on_bad_packet, num_usrp, num_chan, usrp_temp) 342 | //recv to file 343 | recv_to_file >recv_to_file_args(); 344 | //finished 345 | std::cout << std::endl << "Done!" << std::endl << std::endl; 346 | 347 | return EXIT_SUCCESS; 348 | } 349 | -------------------------------------------------------------------------------- /host/examples/rfnoc_spreader.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 - WINLAB, Rutgers University, USA 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | namespace po = boost::program_options; 42 | 43 | static bool stop_signal_called = false; 44 | void sig_int_handler(int){stop_signal_called = true;} 45 | 46 | 47 | int UHD_SAFE_MAIN(int argc, char *argv[]){ 48 | uhd::set_thread_priority_safe(); 49 | 50 | //variables to be set by po 51 | std::string args, file, format, ant, subdev, ref, wirefmt, streamargs, duc_args, spreader_args, pn_seed, pn_poly; 52 | size_t total_num_samps, radio_id; 53 | double freq, gain, setup_time; 54 | int pn_len; 55 | 56 | //setup the program options 57 | po::options_description desc("Allowed options"); 58 | desc.add_options() 59 | ("help", "help message") 60 | ("nsamps", po::value(&total_num_samps)->default_value(10000), "total number of samples to transmit") 61 | ("args", po::value(&args)->default_value(""), "USRP device address args") 62 | ("setup", po::value(&setup_time)->default_value(1.0), "seconds of setup time") 63 | ("radio-id", po::value(&radio_id)->default_value(0), "Radio ID to use (0 or 1).") 64 | ("freq", po::value(&freq)->default_value(0.0), "RF center frequency in Hz") 65 | ("gain", po::value(&gain), "gain for the RF chain") 66 | ("ant", po::value(&ant)->default_value("TX/RX"), "antenna selection") 67 | ("ref", po::value(&ref), "reference source (internal, external, mimo)") 68 | ("PN-length", po::value(&pn_len)->default_value(255), "length of PN Sequence (default = 255)") 69 | ("PN-seed", po::value(&pn_seed)->default_value("00000001"), "Seed polynomial (default = 00000001)") 70 | ("PN-gen-poly", po::value(&pn_poly)->default_value("00011101"), "Generator polynomial (default = 00011101)") 71 | ("duc-args", po::value(&duc_args)->default_value(""), "These args are passed straight to the block.") 72 | ("streamargs", po::value(&streamargs)->default_value(""), "additional stream args") 73 | ; 74 | po::variables_map vm; 75 | po::store(po::parse_command_line(argc, argv, desc), vm); 76 | po::notify(vm); 77 | 78 | //print the help message 79 | if (vm.count("help")) { 80 | std::cout << boost::format("RFNoC Spec Spreader %s") % desc << std::endl; 81 | std::cout 82 | << std::endl 83 | << "This application demonstrates RFNoC based spectrum spreading using PN sequences\n" 84 | << std::endl; 85 | return ~0; 86 | } 87 | 88 | /************************************************************************ 89 | * Create device and block controls 90 | ***********************************************************************/ 91 | std::cout << std::endl; 92 | std::cout << boost::format("Creating the USRP device with: %s...") % args << std::endl; 93 | uhd::usrp::multi_usrp::sptr usrp_temp = uhd::usrp::multi_usrp::make(args); 94 | uhd::device3::sptr usrp = usrp_temp->get_device3(); 95 | // Create handle for radio object 96 | uhd::rfnoc::block_id_t radio_ctrl_id(0, "Radio", radio_id); 97 | // This next line will fail if the radio is not actually available 98 | uhd::rfnoc::radio_ctrl::sptr radio_ctrl = usrp->get_block_ctrl< uhd::rfnoc::radio_ctrl >(radio_ctrl_id); 99 | std::cout << "Using radio 0" << ", channel " << radio_id << std::endl; 100 | 101 | /************************************************************************ 102 | * Set up radio 103 | ***********************************************************************/ 104 | 105 | //Setting clock reference for the device 106 | if (vm.count("ref")) { 107 | usrp_temp->set_clock_source(ref); 108 | } 109 | 110 | //set the center frequency 111 | if (vm.count("freq")) { 112 | std::cout << boost::format("Setting TX Freq: %f MHz...") % (freq/1e6) << std::endl; 113 | uhd::tune_request_t tune_request(freq); 114 | radio_ctrl->set_tx_frequency(freq, radio_id); 115 | std::cout << boost::format("Actual TX Freq: %f MHz...") % (radio_ctrl->get_tx_frequency(radio_id)/1e6) << std::endl << std::endl; 116 | } 117 | 118 | //set the rf gain 119 | if (vm.count("gain")) { 120 | std::cout << boost::format("Setting TX Gain: %f dB...") % gain << std::endl; 121 | radio_ctrl->set_tx_gain(gain, radio_id); 122 | std::cout << boost::format("Actual TX Gain: %f dB...") % radio_ctrl->get_tx_gain(radio_id) << std::endl << std::endl; 123 | } 124 | 125 | //set the antenna 126 | if (vm.count("ant")) { 127 | radio_ctrl->set_tx_antenna(ant, radio_id); 128 | } 129 | 130 | boost::this_thread::sleep(boost::posix_time::milliseconds(long(setup_time*1000))); //allow for some setup time 131 | 132 | /************************************************************************ 133 | * Set up streaming 134 | ***********************************************************************/ 135 | uhd::device_addr_t streamer_args(streamargs); 136 | 137 | uhd::rfnoc::graph::sptr tx_graph = usrp->create_graph("rfnoc_spreader"); 138 | usrp->clear(); 139 | // Setting the PN sequence properties and connecting the Spreader block 140 | //---------------------------------------------------------------------- 141 | std::string duc_id("0/DUC_0"); 142 | std::string spreader_id("0/Spreader_0"); 143 | 144 | uhd::rfnoc::spec_spreader_block_ctrl::sptr spreader_ctrl = usrp->get_block_ctrl(spreader_id); 145 | uhd::rfnoc::sink_block_ctrl_base::sptr duc_ctrl = usrp->get_block_ctrl(duc_id); 146 | 147 | duc_ctrl->set_args(uhd::device_addr_t(duc_args)); 148 | spreader_ctrl->set_pn_seq_gen(pn_poly,pn_seed,pn_len); 149 | std::cout << "Connecting " << duc_ctrl->get_block_id() <<" ==> " << radio_ctrl_id << std::endl; 150 | tx_graph->connect(duc_ctrl->get_block_id(), uhd::rfnoc::ANY_PORT, radio_ctrl_id, radio_id); 151 | std::cout << "Connecting " << spreader_ctrl->get_block_id() << " ==> " << duc_ctrl->get_block_id(); 152 | tx_graph->connect(spreader_ctrl->get_block_id(), uhd::rfnoc::ANY_PORT, duc_ctrl->get_block_id(), uhd::rfnoc::ANY_PORT); 153 | streamer_args["block_id"] = spreader_ctrl->get_block_id().to_string(); 154 | //---------------------------------------------------------------------- 155 | 156 | 157 | //Creating a transmit streamer 158 | uhd::stream_args_t stream_args("fc32", "sc16"); // We should read the wire format from the blocks 159 | stream_args.args = streamer_args; 160 | UHD_MSG(status) << "Using streamer args: " << stream_args.args.to_string() << std::endl; 161 | uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); 162 | 163 | //Creating a packet to stream same symbol to the device multiple times 164 | uhd::tx_metadata_t md; 165 | std::vector > buff(total_num_samps); 166 | for (int i = 0; i < buff.size(); i++) { 167 | buff.at(i) = 0.707 + 0.707i; 168 | } 169 | 170 | //Transmit streamer metadata properties 171 | md.start_of_burst = true; 172 | md.end_of_burst = false; 173 | md.has_time_spec = false; 174 | std::cout << "Sending samples...\n"; 175 | std::signal(SIGINT, &sig_int_handler); 176 | std::cout << "Press Ctrl + C to stop streaming..." << std::endl; 177 | //md.time_spec = usrp->get_time_now(); 178 | while (not stop_signal_called) { 179 | tx_stream->send(&buff.front(), buff.size(), md); 180 | //md.start_of_burst = false; 181 | } 182 | 183 | //finished 184 | std::cout << std::endl << "Done!" << std::endl << std::endl; 185 | 186 | return EXIT_SUCCESS; 187 | } 188 | --------------------------------------------------------------------------------