1// 2// Copyright 2011-2013 Ettus Research LLC 3// 4// This program is free software: you can redistribute it and/or modify 5// it under the terms of the GNU General Public License as published by 6// the Free Software Foundation, either version 3 of the License, or 7// (at your option) any later version. 8// 9// This program is distributed in the hope that it will be useful, 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12// GNU General Public License for more details. 13// 14// You should have received a copy of the GNU General Public License 15// along with this program. If not, see <http://www.gnu.org/licenses/>. 16// 17 18 19 20module u1plus_core 21#( 22 parameter NUM_RX_DSPS = 2, 23 parameter CTRL_ACK_SID = 20, //needed for reply 24 25 parameter DSP_TX_FIFOSIZE = 10, //4K MTU 26 parameter DSP_RX_FIFOSIZE = 10, //4K MTU 27 28 parameter DSP_RX_XTRA_FIFOSIZE = 11, 29 parameter DSP_TX_XTRA_FIFOSIZE = 11, 30 31 parameter USE_PACKET_PADDER = 0 32) 33 (input clk, input reset, 34 output [31:0] debug, output [1:0] debug_clk, 35 36 // Host Interface 37 input [35:0] tx_data, input tx_src_rdy, output tx_dst_rdy, 38 output [35:0] rx_data, output rx_src_rdy, input rx_dst_rdy, 39 input [35:0] ctrl_data, input ctrl_src_rdy, output ctrl_dst_rdy, 40 output [35:0] resp_data, output resp_src_rdy, input resp_dst_rdy, 41 42 output dsp_rx_run, output dsp_tx_run, output clock_sync, 43 44 inout db_sda, inout db_scl, 45 output sclk, output [7:0] sen, output mosi, input miso, 46 47 inout [15:0] io_tx, inout [15:0] io_rx, 48 output [13:0] tx_i, output [13:0] tx_q, 49 input [11:0] rx_i, input [11:0] rx_q, 50 input pps_in 51 ); 52 53 localparam SR_MISC = 0; // 5 54 localparam SR_USER_REGS = 5; // 2 55 localparam SR_PADDER = 10; // 2 56 57 localparam SR_TX_CTRL = 32; // 6 58 localparam SR_TX_DSP = 40; // 5 59 localparam SR_TX_FE = 48; // 5 60 61 localparam SR_RX_CTRL0 = 96; // 9 62 localparam SR_RX_DSP0 = 106; // 7 63 localparam SR_RX_FE = 114; // 5 64 65 localparam SR_RX_CTRL1 = 128; // 9 66 localparam SR_RX_DSP1 = 138; // 7 67 68 localparam SR_TIME64 = 192; // 6 69 localparam SR_SPI = 208; // 3 70 localparam SR_I2C = 216; // 1 71 localparam SR_GPIO = 224; // 5 72 73 //compatibility number -> increment when the fpga has been sufficiently altered 74 localparam compat_num = {16'd11, 16'd4}; //major, minor 75 76 //assign run signals used for ATR logic 77 wire [NUM_RX_DSPS-1:0] run_rx_n; 78 wire run_tx; 79 wire run_rx = |(run_rx_n); 80 assign dsp_rx_run = run_rx; 81 assign dsp_tx_run = run_tx; 82 83 //shared time core signals 84 wire [63:0] vita_time, vita_time_pps; 85 86 //shared settings bus signals 87 wire set_stb, set_stb_user; 88 wire [31:0] set_data, set_data_user; 89 wire [7:0] set_addr, set_addr_user; 90 91 //shared SPI core signals 92 wire [31:0] spi_readback; 93 wire spi_ready; 94 95 //shared I2C core signals 96 wire [31:0] i2c_readback; 97 wire i2c_ready; 98 99 //shared GPIO core signals 100 wire [31:0] gpio_readback; 101 102 /////////////////////////////////////////////////////////////////////////// 103 // Misc Registers - persistent across resets 104 /////////////////////////////////////////////////////////////////////////// 105 wire [31:0] config_word0; 106 setting_reg #(.my_addr(SR_MISC+0), .width(32)) sr_misc_config0 107 (.clk(clk), .rst(1'b0/*reset*/), .strobe(set_stb), .addr(set_addr), .in(set_data), .out(config_word0)); 108 109 wire [31:0] config_word1; 110 setting_reg #(.my_addr(SR_MISC+1), .width(32)) sr_misc_config1 111 (.clk(clk), .rst(1'b0/*reset*/), .strobe(set_stb), .addr(set_addr), .in(set_data), .out(config_word1)); 112 113 wire clock_sync_inv, clock_sync_enb; 114 setting_reg #(.my_addr(SR_MISC+2), .width(2)) sr_misc_clock_sync 115 (.clk(clk), .rst(reset), .strobe(set_stb), .addr(set_addr), .in(set_data), 116 .out({clock_sync_inv, clock_sync_enb})); 117 118 /////////////////////////////////////////////////////////////////////////// 119 // Settings Bus and Readback 120 /////////////////////////////////////////////////////////////////////////// 121 user_settings #(.BASE(SR_USER_REGS)) user_settings 122 (.clk(clk),.rst(reset), 123 .set_stb(set_stb), .set_addr(set_addr),.set_data(set_data), 124 .set_addr_user(set_addr_user),.set_data_user(set_data_user), .set_stb_user(set_stb_user) ); 125 126 wire [35:0] ctrl_out_data, ctrl_int_data; 127 wire ctrl_out_src_rdy, ctrl_out_dst_rdy; 128 wire ctrl_int_src_rdy, ctrl_int_dst_rdy; 129 130 fifo_cascade #(.WIDTH(36), .SIZE(9)) ctrl_fifo 131 (.clk(clk), .reset(reset), .clear(1'b0), 132 .datain(ctrl_data), .src_rdy_i(ctrl_src_rdy), .dst_rdy_o(ctrl_dst_rdy), .space(), 133 .dataout(ctrl_int_data), .src_rdy_o(ctrl_int_src_rdy), .dst_rdy_i(ctrl_int_dst_rdy), .occupied()); 134 135 wire [31:0] num_rx_dsps_rb = NUM_RX_DSPS; 136 137 wire [31:0] sfc_debug; 138 settings_fifo_ctrl #(.PROT_HDR(0), .ACK_SID(CTRL_ACK_SID), .XPORT_HDR(0)) sfc 139 ( 140 .clock(clk), .reset(reset), .clear(1'b0), 141 .vita_time(vita_time), .perfs_ready(spi_ready & i2c_ready), 142 .in_data(ctrl_int_data), .in_valid(ctrl_int_src_rdy), .in_ready(ctrl_int_dst_rdy), 143 .out_data(ctrl_out_data), .out_valid(ctrl_out_src_rdy), .out_ready(ctrl_out_dst_rdy), 144 .strobe(set_stb), .addr(set_addr), .data(set_data), 145 .word00(spi_readback),.word01(compat_num),.word02(i2c_readback),.word03(gpio_readback), 146 .word04(config_word0),.word05(config_word1),.word06(num_rx_dsps_rb),.word07(32'hffff_ffff), 147 .word08(32'hffff_ffff),.word09(32'hffff_ffff),.word10(vita_time[63:32]), 148 .word11(vita_time[31:0]),.word12(32'hffff_ffff),.word13(32'hffff_ffff), 149 .word14(vita_time_pps[63:32]),.word15(vita_time_pps[31:0]), 150 .debug(sfc_debug) 151 ); 152 153 /////////////////////////////////////////////////////////////////////////// 154 // Time Core 155 /////////////////////////////////////////////////////////////////////////// 156 time_64bit #(.BASE(SR_TIME64)) time_64bit 157 (.clk(clk), .rst(reset), .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), 158 .pps(pps_in), .vita_time(vita_time), .vita_time_pps(vita_time_pps), 159 .exp_time_in(0)); 160 161 assign clock_sync = (clock_sync_enb)? (pps_in ^ clock_sync_inv) : 1'b0; 162 163 /////////////////////////////////////////////////////////////////////////// 164 // SPI Core 165 /////////////////////////////////////////////////////////////////////////// 166 simple_spi_core #(.BASE(SR_SPI), .WIDTH(8), .CLK_IDLE(0), .SEN_IDLE(8'hff)) 167 simple_spi_core (.clock(clk), .reset(reset), 168 .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), 169 .readback(spi_readback), .ready(spi_ready), 170 .sen(sen), .sclk(sclk), .mosi(mosi), .miso(miso)); 171 172 /////////////////////////////////////////////////////////////////////////// 173 // I2C Core 174 /////////////////////////////////////////////////////////////////////////// 175 wire scl_pad_i, scl_pad_o, scl_pad_oen_o, sda_pad_i, sda_pad_o, sda_pad_oen_o; 176 simple_i2c_core #(.BASE(SR_I2C)) i2c_core 177 (.clock(clk),.reset(reset), 178 .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), 179 .readback(i2c_readback), .ready(i2c_ready), 180 .scl_pad_i(scl_pad_i),.scl_pad_o(scl_pad_o),.scl_padoen_o(scl_pad_oen_o), 181 .sda_pad_i(sda_pad_i),.sda_pad_o(sda_pad_o),.sda_padoen_o(sda_pad_oen_o) ); 182 183 // I2C -- Don't use external transistors for open drain, the FPGA implements this 184 IOBUF scl_pin(.O(scl_pad_i), .IO(db_scl), .I(scl_pad_o), .T(scl_pad_oen_o)); 185 IOBUF sda_pin(.O(sda_pad_i), .IO(db_sda), .I(sda_pad_o), .T(sda_pad_oen_o)); 186 187 /////////////////////////////////////////////////////////////////////////// 188 // GPIO Core 189 /////////////////////////////////////////////////////////////////////////// 190 gpio_atr #(.BASE(SR_GPIO), .WIDTH(32)) 191 gpio_atr(.clk(clk),.reset(reset), 192 .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), 193 .rx(run_rx), .tx(run_tx), .gpio({io_tx, io_rx}), .gpio_readback(gpio_readback) ); 194 195 // ///////////////////////////////////////////////////////////////////////// 196 // RX ADC Frontend, does IQ Balance, DC Offset, muxing 197 198 wire [23:0] rx_fe_i, rx_fe_q; // 24 bits is total overkill here, but it matches u2/u2p 199 200 rx_frontend #(.BASE(SR_RX_FE)) rx_frontend 201 (.clk(clk),.rst(reset), 202 .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), 203 .adc_a({rx_i,4'b00}),.adc_ovf_a(0), 204 .adc_b({rx_q,4'b00}),.adc_ovf_b(0), 205 .i_out(rx_fe_i), .q_out(rx_fe_q), .run(run_rx), .debug()); 206 207 // ///////////////////////////////////////////////////////////////////////// 208 // DSP RX * 209 210 wire [35:0] rx_int2_data [NUM_RX_DSPS-1:0]; 211 wire rx_int2_src_rdy [NUM_RX_DSPS-1:0]; 212 wire rx_int2_dst_rdy [NUM_RX_DSPS-1:0]; 213 214 genvar dspno; 215 generate 216 for(dspno = 0; dspno < NUM_RX_DSPS; dspno = dspno + 1) begin:gen_rx_dsps 217 218 wire [31:0] sample_rx; 219 wire strobe_rx, clear_rx; 220 wire [35:0] vita_rx_data; 221 wire vita_rx_src_rdy, vita_rx_dst_rdy; 222 wire [35:0] int_rx_data; 223 wire int_rx_src_rdy, int_rx_dst_rdy; 224 225 ddc_chain #(.BASE(SR_RX_DSP0+dspno*32), .DSPNO(dspno)) ddc_chain 226 (.clk(clk), .rst(reset), .clr(clear_rx), 227 .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), 228 .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user), 229 .rx_fe_i(rx_fe_i),.rx_fe_q(rx_fe_q), 230 .sample(sample_rx), .run(run_rx_n[dspno]), .strobe(strobe_rx), 231 .debug() ); 232 233 vita_rx_chain #(.BASE(SR_RX_CTRL0+dspno*32), .UNIT(dspno), .FIFOSIZE(DSP_RX_FIFOSIZE), .PROT_ENG_FLAGS(0), .DSP_NUMBER(dspno)) vita_rx_chain 234 (.clk(clk),.reset(reset), 235 .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), 236 .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user), 237 .vita_time(vita_time), .overrun(), 238 .sample(sample_rx), .run(run_rx_n[dspno]), .strobe(strobe_rx), .clear_o(clear_rx), 239 .rx_data_o(vita_rx_data), .rx_dst_rdy_i(vita_rx_dst_rdy), .rx_src_rdy_o(vita_rx_src_rdy), 240 .debug() ); 241 242 fifo_cascade #(.WIDTH(36), .SIZE(DSP_RX_FIFOSIZE+1)) rx_data_fifo 243 (.clk(clk), .reset(reset), .clear(1'b0), 244 .datain(vita_rx_data), .src_rdy_i(vita_rx_src_rdy), .dst_rdy_o(vita_rx_dst_rdy), .space(), 245 .dataout(int_rx_data), .src_rdy_o(int_rx_src_rdy), .dst_rdy_i(int_rx_dst_rdy), .occupied()); 246 247 if (dspno == 0) begin 248 assign rx_int2_data[dspno] = int_rx_data; 249 assign rx_int2_src_rdy[dspno] = int_rx_src_rdy; 250 assign int_rx_dst_rdy = rx_int2_dst_rdy[dspno]; 251 end 252 else begin 253 fifo36_mux #(.prio(0)) // No priority, fair sharing 254 combine_rx_dsps ( 255 .clk(clk), .reset(reset), .clear(1'b0/*noclear*/), 256 .data0_i(rx_int2_data[dspno-1]), .src0_rdy_i(rx_int2_src_rdy[dspno-1]), .dst0_rdy_o(rx_int2_dst_rdy[dspno-1]), 257 .data1_i(int_rx_data), .src1_rdy_i(int_rx_src_rdy), .dst1_rdy_o(int_rx_dst_rdy), 258 .data_o(rx_int2_data[dspno]), .src_rdy_o(rx_int2_src_rdy[dspno]), .dst_rdy_i(rx_int2_dst_rdy[dspno]) 259 ); 260 end 261 262 end 263 endgenerate 264 265 // ///////////////////////////////////////////////////////////////////////// 266 // RX Stream muxing 267 268 wire [35:0] rx_int3_data; 269 wire rx_int3_src_rdy, rx_int3_dst_rdy; 270 271 fifo_cascade #(.WIDTH(36), .SIZE(DSP_RX_XTRA_FIFOSIZE)) rx_data_fifo_combined 272 (.clk(clk), .reset(reset), .clear(1'b0), 273 .datain(rx_int2_data[NUM_RX_DSPS-1]), .src_rdy_i(rx_int2_src_rdy[NUM_RX_DSPS-1]), .dst_rdy_o(rx_int2_dst_rdy[NUM_RX_DSPS-1]), .space(), 274 .dataout(rx_int3_data), .src_rdy_o(rx_int3_src_rdy), .dst_rdy_i(rx_int3_dst_rdy), .occupied()); 275 276 generate 277 if (USE_PACKET_PADDER) begin 278 packet_padder36 #(.BASE(SR_PADDER)) packet_padder_rx_data36( 279 .clk(clk), .reset(reset), 280 .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), 281 .data_i(rx_int3_data), .src_rdy_i(rx_int3_src_rdy), .dst_rdy_o(rx_int3_dst_rdy), 282 .data_o(rx_data), .src_rdy_o(rx_src_rdy), .dst_rdy_i(rx_dst_rdy), 283 .always_flush(~dsp_rx_run)); 284 end 285 else begin 286 assign rx_data = rx_int3_data; 287 assign rx_src_rdy = rx_int3_src_rdy; 288 assign rx_int3_dst_rdy = rx_dst_rdy; 289 end 290 endgenerate 291 292 /////////////////////////////////////////////////////////////////////////// 293 // MUX for TX async and resp data 294 /////////////////////////////////////////////////////////////////////////// 295 wire [35:0] tx_err_data, resp_data_int; 296 wire tx_err_src_rdy, resp_src_rdy_int; 297 wire tx_err_dst_rdy, resp_dst_rdy_int; 298 299 fifo36_mux #(.prio(0)) // No priority, fair sharing 300 combine_async_and_resp ( 301 .clk(clk), .reset(reset), .clear(1'b0/*noclear*/), 302 .data0_i(ctrl_out_data), .src0_rdy_i(ctrl_out_src_rdy), .dst0_rdy_o(ctrl_out_dst_rdy), 303 .data1_i(tx_err_data), .src1_rdy_i(tx_err_src_rdy), .dst1_rdy_o(tx_err_dst_rdy), 304 .data_o(resp_data_int), .src_rdy_o(resp_src_rdy_int), .dst_rdy_i(resp_dst_rdy_int) 305 ); 306 307 fifo_cascade #(.WIDTH(36), .SIZE(9)) resp_fifo 308 (.clk(clk), .reset(reset), .clear(1'b0), 309 .datain(resp_data_int), .src_rdy_i(resp_src_rdy_int), .dst_rdy_o(resp_dst_rdy_int), .space(), 310 .dataout(resp_data), .src_rdy_o(resp_src_rdy), .dst_rdy_i(resp_dst_rdy), .occupied()); 311 312 // /////////////////////////////////////////////////////////////////////////////////// 313 // DSP TX 314 315 wire [23:0] tx_fe_i, tx_fe_q; 316 wire [31:0] sample_tx; 317 wire strobe_tx, clear_tx; 318 319`ifdef DISABLE_TX_DSP 320 assign tx_dst_rdy = 1; //null sink 321 assign run_tx = 0; 322 assign tx_i = 0; 323 assign tx_q = 0; 324`else 325 vita_tx_chain #(.BASE(SR_TX_CTRL), 326 .FIFOSIZE(DSP_TX_FIFOSIZE), 327 .POST_ENGINE_FIFOSIZE(DSP_TX_XTRA_FIFOSIZE), 328 .REPORT_ERROR(1), .DO_FLOW_CONTROL(0), 329 .PROT_ENG_FLAGS(0), .USE_TRANS_HEADER(0), 330 .DSP_NUMBER(0)) 331 vita_tx_chain 332 (.clk(clk), .reset(reset), 333 .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), 334 .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user), 335 .vita_time(vita_time), 336 .tx_data_i(tx_data), .tx_src_rdy_i(tx_src_rdy), .tx_dst_rdy_o(tx_dst_rdy), 337 .err_data_o(tx_err_data), .err_src_rdy_o(tx_err_src_rdy), .err_dst_rdy_i(tx_err_dst_rdy), 338 .sample(sample_tx), .strobe(strobe_tx), 339 .underrun(), .run(run_tx), .clear_o(clear_tx), 340 .debug()); 341 342 duc_chain #(.BASE(SR_TX_DSP), .DSPNO(0)) duc_chain 343 (.clk(clk), .rst(reset), .clr(clear_tx), 344 .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), 345 .set_stb_user(set_stb_user), .set_addr_user(set_addr_user), .set_data_user(set_data_user), 346 .tx_fe_i(tx_fe_i),.tx_fe_q(tx_fe_q), 347 .sample(sample_tx), .run(run_tx), .strobe(strobe_tx), 348 .debug() ); 349 350 tx_frontend #(.BASE(SR_TX_FE), .WIDTH_OUT(14)) tx_frontend 351 (.clk(clk), .rst(reset), 352 .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), 353 .tx_i(tx_fe_i), .tx_q(tx_fe_q), .run(1'b1), 354 .dac_a(tx_i), .dac_b(tx_q)); 355`endif 356 // ///////////////////////////////////////////////////////////////////////////////////// 357 // Debug circuitry 358 359 assign debug_clk = 2'b11; 360 assign debug = 32'hffffffff; 361 362endmodule // u1plus_core 363