1///////////////////////////////////////////////////////////////////// 2// 3// Copyright 2018 Ettus Research, A National Instruments Company 4// Copyright 2019 Ettus Research, A National Instruments Brand 5// 6// SPDX-License-Identifier: LGPL-3.0 7// 8// Module: e31x_core 9// Description: 10// - Motherboard Registers 11// - RFNoC Image Core + Blocks 12// - Radio Front End control 13// 14///////////////////////////////////////////////////////////////////// 15 16`default_nettype none 17module e31x_core #( 18 parameter REG_DWIDTH = 32, // Width of the AXI4-Lite data bus (must be 32 or 64) 19 parameter REG_AWIDTH = 32, // Width of the address bus 20 parameter BUS_CLK_RATE = 200000000, // bus_clk rate 21 parameter NUM_SFP_PORTS = 0, // Number of SFP Ports 22 parameter NUM_RADIOS = 1, 23 parameter NUM_CHANNELS_PER_RADIO = 2, 24 parameter NUM_CHANNELS = 2, 25 parameter NUM_DBOARDS = 1, 26 parameter NUM_CHANNELS_PER_DBOARD = 2, 27 parameter FP_GPIO_WIDTH = 8, // Front panel GPIO width 28 parameter DB_GPIO_WIDTH = 16, // Daughterboard GPIO width 29 parameter CHDR_WIDTH = 16'd64 , 30 parameter RFNOC_PROTOVER = {8'd1, 8'd0} 31)( 32 // Clocks and resets 33 input wire radio_clk, 34 input wire radio_rst, 35 input wire bus_clk, 36 input wire bus_rst, 37 input wire clk40, 38 39 // Motherboard Registers: AXI lite interface 40 input wire s_axi_aclk, 41 input wire s_axi_aresetn, 42 input wire [REG_AWIDTH-1:0] s_axi_awaddr, 43 input wire s_axi_awvalid, 44 output wire s_axi_awready, 45 46 input wire [REG_DWIDTH-1:0] s_axi_wdata, 47 input wire [REG_DWIDTH/8-1:0] s_axi_wstrb, 48 input wire s_axi_wvalid, 49 output wire s_axi_wready, 50 51 output wire [1:0] s_axi_bresp, 52 output wire s_axi_bvalid, 53 input wire s_axi_bready, 54 55 input wire [REG_AWIDTH-1:0] s_axi_araddr, 56 input wire s_axi_arvalid, 57 output wire s_axi_arready, 58 59 output wire [REG_DWIDTH-1:0] s_axi_rdata, 60 output wire [1:0] s_axi_rresp, 61 output wire s_axi_rvalid, 62 input wire s_axi_rready, 63 64 // PPS and Clock Control 65 input wire pps_refclk, 66 input wire refclk_locked, 67 output reg [1:0] pps_select, 68 69 // PS GPIO source 70 input wire [FP_GPIO_WIDTH-1:0] ps_gpio_out, 71 input wire [FP_GPIO_WIDTH-1:0] ps_gpio_tri, 72 output wire [FP_GPIO_WIDTH-1:0] ps_gpio_in, 73 74 // Front Panel GPIO 75 input wire [FP_GPIO_WIDTH-1:0] fp_gpio_in, 76 output wire [FP_GPIO_WIDTH-1:0] fp_gpio_tri, 77 output wire [FP_GPIO_WIDTH-1:0] fp_gpio_out, 78 79 // Radio GPIO control 80 output wire [DB_GPIO_WIDTH*NUM_CHANNELS-1:0] db_gpio_out_flat, 81 output wire [DB_GPIO_WIDTH*NUM_CHANNELS-1:0] db_gpio_ddr_flat, 82 input wire [DB_GPIO_WIDTH*NUM_CHANNELS-1:0] db_gpio_in_flat, 83 input wire [DB_GPIO_WIDTH*NUM_CHANNELS-1:0] db_gpio_fab_flat, 84 85 // TX/RX LEDs 86 output wire [32*NUM_CHANNELS-1:0] leds_flat, 87 88 // Radio ATR 89 output wire [NUM_CHANNELS-1:0] rx_atr, 90 output wire [NUM_CHANNELS-1:0] tx_atr, 91 92 // Radio Data 93 input wire [NUM_CHANNELS-1:0] rx_stb, 94 input wire [NUM_CHANNELS-1:0] tx_stb, 95 input wire [32*NUM_CHANNELS-1:0] rx, 96 output wire [32*NUM_CHANNELS-1:0] tx, 97 98 // DMA xport adapter to PS 99 input wire [63:0] s_dma_tdata, 100 input wire s_dma_tlast, 101 output wire s_dma_tready, 102 input wire s_dma_tvalid, 103 104 output wire [63:0] m_dma_tdata, 105 output wire m_dma_tlast, 106 input wire m_dma_tready, 107 output wire m_dma_tvalid, 108 109 // Misc 110 input wire [31:0] build_datestamp, 111 input wire [31:0] sfp_ports_info, 112 input wire [31:0] dboard_status, 113 input wire [31:0] xadc_readback, 114 output reg [31:0] fp_gpio_ctrl, 115 output reg [31:0] dboard_ctrl, 116 output reg [15:0] device_id 117); 118 `include "../../lib/rfnoc/core/ctrlport.vh" 119 120 ///////////////////////////////////////////////////////////////////////////////// 121 // 122 // FPGA Compatibility Number 123 // Rules for modifying compat number: 124 // - Major is updated when the FPGA is changed and requires a software 125 // change as a result. 126 // - Minor is updated when a new feature is added to the FPGA that does not 127 // break software compatibility. 128 // 129 ///////////////////////////////////////////////////////////////////////////////// 130 131 localparam [15:0] COMPAT_MAJOR = 16'd6; 132 localparam [15:0] COMPAT_MINOR = 16'd0; 133 134 ///////////////////////////////////////////////////////////////////////////////// 135 136 ///////////////////////////////////////////////////////////////////////////////// 137 // 138 // Motherboard Registers 139 // 140 ///////////////////////////////////////////////////////////////////////////////// 141 142 // Register base 143 localparam [CTRLPORT_ADDR_W-1:0] REG_BASE_MISC = 20'h0; 144 localparam [CTRLPORT_ADDR_W-1:0] REG_BASE_TIMEKEEPER = 20'h1000; 145 146 // Register region sizes. Give each register region a 256-byte window. 147 localparam REG_GLOB_ADDR_W = 8; 148 localparam REG_TIMEKEEPER_ADDR_W = 8; 149 150 // Misc Registers 151 localparam REG_COMPAT_NUM = REG_BASE_MISC + 14'h00; 152 localparam REG_DATESTAMP = REG_BASE_MISC + 14'h04; 153 localparam REG_GIT_HASH = REG_BASE_MISC + 14'h08; 154 localparam REG_SCRATCH = REG_BASE_MISC + 14'h0C; 155 localparam REG_DEVICE_ID = REG_BASE_MISC + 14'h10; 156 localparam REG_RFNOC_INFO = REG_BASE_MISC + 14'h14; 157 localparam REG_CLOCK_CTRL = REG_BASE_MISC + 14'h18; 158 localparam REG_XADC_READBACK = REG_BASE_MISC + 14'h1C; 159 localparam REG_BUS_CLK_RATE = REG_BASE_MISC + 14'h20; 160 localparam REG_BUS_CLK_COUNT = REG_BASE_MISC + 14'h24; 161 localparam REG_SFP_PORT_INFO = REG_BASE_MISC + 14'h28; 162 localparam REG_FP_GPIO_CTRL = REG_BASE_MISC + 14'h2C; 163 localparam REG_FP_GPIO_MASTER = REG_BASE_MISC + 14'h30; 164 localparam REG_FP_GPIO_RADIO_SRC = REG_BASE_MISC + 14'h34; 165 localparam REG_DBOARD_CTRL = REG_BASE_MISC + 14'h40; 166 localparam REG_DBOARD_STATUS = REG_BASE_MISC + 14'h44; 167 localparam REG_NUM_TIMEKEEPERS = REG_BASE_MISC + 14'h48; 168 169 localparam NUM_TIMEKEEPERS = 1; 170 171 wire m_ctrlport_req_wr; 172 wire m_ctrlport_req_rd; 173 wire [19:0] m_ctrlport_req_addr; 174 wire [31:0] m_ctrlport_req_data; 175 wire m_ctrlport_req_has_time; 176 wire [63:0] m_ctrlport_req_time; 177 wire m_ctrlport_resp_ack; 178 wire [31:0] m_ctrlport_resp_data; 179 180 reg [31:0] fp_gpio_master_reg = 32'h0; 181 reg [31:0] fp_gpio_src_reg = 32'h0; 182 183 reg [31:0] scratch_reg = 32'h0; 184 reg [31:0] bus_counter = 32'h0; 185 186 always @(posedge bus_clk) begin 187 if (bus_rst) 188 bus_counter <= 32'd0; 189 else 190 bus_counter <= bus_counter + 32'd1; 191 end 192 193 ///////////////////////////////////////////////////////////////////////////// 194 // 195 // Bus Bridge 196 // 197 ///////////////////////////////////////////////////////////////////////////// 198 199 // We need a really long timeout for CtrlPort transactions, since the 200 // radio_clk for the timekeeper might be really slow compared to s_axi_aclk. 201 localparam CTRLPORT_TIMEOUT = 20; 202 203 wire cp_req_wr_aclk; 204 wire cp_req_rd_aclk; 205 wire [CTRLPORT_ADDR_W-1:0] cp_req_addr_aclk; 206 wire [CTRLPORT_DATA_W-1:0] cp_req_data_aclk; 207 wire cp_resp_ack_aclk; 208 wire [ CTRLPORT_STS_W-1:0] cp_resp_status_aclk; 209 wire [CTRLPORT_DATA_W-1:0] cp_resp_data_aclk; 210 211 // Convert the AXI4-Lite transactions to CtrlPort 212 axil_ctrlport_master #( 213 .TIMEOUT (CTRLPORT_TIMEOUT), 214 .AXI_AWIDTH (REG_AWIDTH), 215 .CTRLPORT_AWIDTH (CTRLPORT_ADDR_W) 216 ) axil_ctrlport_master_i ( 217 .s_axi_aclk (s_axi_aclk), 218 .s_axi_aresetn (s_axi_aresetn), 219 .s_axi_awaddr (s_axi_awaddr), 220 .s_axi_awvalid (s_axi_awvalid), 221 .s_axi_awready (s_axi_awready), 222 .s_axi_wdata (s_axi_wdata), 223 .s_axi_wstrb (s_axi_wstrb), 224 .s_axi_wvalid (s_axi_wvalid), 225 .s_axi_wready (s_axi_wready), 226 .s_axi_bresp (s_axi_bresp), 227 .s_axi_bvalid (s_axi_bvalid), 228 .s_axi_bready (s_axi_bready), 229 .s_axi_araddr (s_axi_araddr), 230 .s_axi_arvalid (s_axi_arvalid), 231 .s_axi_arready (s_axi_arready), 232 .s_axi_rdata (s_axi_rdata), 233 .s_axi_rresp (s_axi_rresp), 234 .s_axi_rvalid (s_axi_rvalid), 235 .s_axi_rready (s_axi_rready), 236 .m_ctrlport_req_wr (cp_req_wr_aclk), 237 .m_ctrlport_req_rd (cp_req_rd_aclk), 238 .m_ctrlport_req_addr (cp_req_addr_aclk), 239 .m_ctrlport_req_portid (), 240 .m_ctrlport_req_rem_epid (), 241 .m_ctrlport_req_rem_portid (), 242 .m_ctrlport_req_data (cp_req_data_aclk), 243 .m_ctrlport_req_byte_en (), 244 .m_ctrlport_req_has_time (), 245 .m_ctrlport_req_time (), 246 .m_ctrlport_resp_ack (cp_resp_ack_aclk), 247 .m_ctrlport_resp_status (cp_resp_status_aclk), 248 .m_ctrlport_resp_data (cp_resp_data_aclk) 249 ); 250 251 wire cp_req_wr; 252 wire cp_req_rd; 253 wire [CTRLPORT_ADDR_W-1:0] cp_req_addr; 254 wire [CTRLPORT_DATA_W-1:0] cp_req_data; 255 wire cp_resp_ack; 256 wire [ CTRLPORT_STS_W-1:0] cp_resp_status; 257 wire [CTRLPORT_DATA_W-1:0] cp_resp_data; 258 259 // Cross transactions from s_axi_clk to bus_clk domain 260 ctrlport_clk_cross ctrlport_clk_cross_i ( 261 .rst (~s_axi_aresetn), 262 .s_ctrlport_clk (s_axi_aclk), 263 .s_ctrlport_req_wr (cp_req_wr_aclk), 264 .s_ctrlport_req_rd (cp_req_rd_aclk), 265 .s_ctrlport_req_addr (cp_req_addr_aclk), 266 .s_ctrlport_req_portid ({CTRLPORT_PORTID_W{1'b0}}), 267 .s_ctrlport_req_rem_epid ({CTRLPORT_REM_EPID_W{1'b0}}), 268 .s_ctrlport_req_rem_portid ({CTRLPORT_PORTID_W{1'b0}}), 269 .s_ctrlport_req_data (cp_req_data_aclk), 270 .s_ctrlport_req_byte_en ({CTRLPORT_BYTE_EN_W{1'b1}}), 271 .s_ctrlport_req_has_time (1'b0), 272 .s_ctrlport_req_time ({CTRLPORT_TIME_W{1'b0}}), 273 .s_ctrlport_resp_ack (cp_resp_ack_aclk), 274 .s_ctrlport_resp_status (cp_resp_status_aclk), 275 .s_ctrlport_resp_data (cp_resp_data_aclk), 276 .m_ctrlport_clk (bus_clk), 277 .m_ctrlport_req_wr (cp_req_wr), 278 .m_ctrlport_req_rd (cp_req_rd), 279 .m_ctrlport_req_addr (cp_req_addr), 280 .m_ctrlport_req_portid (), 281 .m_ctrlport_req_rem_epid (), 282 .m_ctrlport_req_rem_portid (), 283 .m_ctrlport_req_data (cp_req_data), 284 .m_ctrlport_req_byte_en (), 285 .m_ctrlport_req_has_time (), 286 .m_ctrlport_req_time (), 287 .m_ctrlport_resp_ack (cp_resp_ack), 288 .m_ctrlport_resp_status (cp_resp_status), 289 .m_ctrlport_resp_data (cp_resp_data) 290 ); 291 292 wire cp_glob_req_wr; 293 wire cp_glob_req_rd; 294 wire [CTRLPORT_ADDR_W-1:0] cp_glob_req_addr; 295 wire [CTRLPORT_DATA_W-1:0] cp_glob_req_data; 296 reg cp_glob_resp_ack = 1'b0; 297 reg [CTRLPORT_DATA_W-1:0] cp_glob_resp_data = 1'bX; 298 299 wire cp_tk_req_wr; 300 wire cp_tk_req_rd; 301 wire [CTRLPORT_ADDR_W-1:0] cp_tk_req_addr; 302 wire [CTRLPORT_DATA_W-1:0] cp_tk_req_data; 303 wire cp_tk_resp_ack; 304 wire [CTRLPORT_DATA_W-1:0] cp_tk_resp_data; 305 306 // Split the CtrlPort for the global registers and the timekeeper registers 307 ctrlport_decoder_param #( 308 .NUM_SLAVES (2), 309 .PORT_BASE ({ REG_BASE_TIMEKEEPER, REG_BASE_MISC }), 310 .PORT_ADDR_W ({ REG_TIMEKEEPER_ADDR_W, REG_GLOB_ADDR_W }) 311 ) ctrlport_decoder_param_i ( 312 .ctrlport_clk (bus_clk), 313 .ctrlport_rst (bus_rst), 314 .s_ctrlport_req_wr (cp_req_wr), 315 .s_ctrlport_req_rd (cp_req_rd), 316 .s_ctrlport_req_addr (cp_req_addr), 317 .s_ctrlport_req_data (cp_req_data), 318 .s_ctrlport_req_byte_en ({CTRLPORT_BYTE_EN_W{1'b1}}), 319 .s_ctrlport_req_has_time (1'b0), 320 .s_ctrlport_req_time ({CTRLPORT_TIME_W{1'b0}}), 321 .s_ctrlport_resp_ack (cp_resp_ack), 322 .s_ctrlport_resp_status (cp_resp_status), 323 .s_ctrlport_resp_data (cp_resp_data), 324 .m_ctrlport_req_wr ({ cp_tk_req_wr, cp_glob_req_wr }), 325 .m_ctrlport_req_rd ({ cp_tk_req_rd, cp_glob_req_rd }), 326 .m_ctrlport_req_addr ({ cp_tk_req_addr, cp_glob_req_addr }), 327 .m_ctrlport_req_data ({ cp_tk_req_data, cp_glob_req_data }), 328 .m_ctrlport_req_byte_en (), 329 .m_ctrlport_req_has_time (), 330 .m_ctrlport_req_time (), 331 .m_ctrlport_resp_ack ({ cp_tk_resp_ack, cp_glob_resp_ack }), 332 .m_ctrlport_resp_status ({2{CTRL_STS_OKAY}}), 333 .m_ctrlport_resp_data ({ cp_tk_resp_data, cp_glob_resp_data }) 334 ); 335 336 337 ///////////////////////////////////////////////////////////////////////////// 338 // 339 // Global Registers 340 // 341 ///////////////////////////////////////////////////////////////////////////// 342 343 // Write Registers 344 always @ (posedge bus_clk) begin 345 if (bus_rst) begin 346 scratch_reg <= 32'h0; 347 pps_select <= 2'b01; // Default to internal 348 fp_gpio_ctrl <= 32'h9; // Default to OFF - 4'b1001 349 dboard_ctrl <= 32'h1; // Default to mimo 350 device_id <= 16'h0; 351 cp_glob_resp_ack <= 1'b0; 352 cp_glob_resp_data <= 'bX; 353 end else begin 354 cp_glob_resp_ack <= 1'b0; 355 356 if (cp_glob_req_wr) begin 357 cp_glob_resp_ack <= 1'b1; 358 359 case (cp_glob_req_addr[REG_GLOB_ADDR_W-1:0]) 360 REG_DEVICE_ID: 361 device_id <= cp_glob_req_data[15:0]; 362 363 REG_FP_GPIO_MASTER: 364 fp_gpio_master_reg <= cp_glob_req_data; 365 366 REG_FP_GPIO_RADIO_SRC: 367 fp_gpio_src_reg <= cp_glob_req_data; 368 369 REG_SCRATCH: 370 scratch_reg <= cp_glob_req_data; 371 372 REG_CLOCK_CTRL: 373 pps_select <= cp_glob_req_data[1:0]; 374 375 REG_FP_GPIO_CTRL: 376 fp_gpio_ctrl <= cp_glob_req_data; 377 378 REG_DBOARD_CTRL: 379 dboard_ctrl <= cp_glob_req_data; 380 381 default : begin 382 // Don't acknowledge if the address doesn't match 383 cp_glob_resp_ack <= 1'b0; 384 end 385 endcase 386 end 387 388 if (cp_glob_req_rd) begin 389 cp_glob_resp_data <= 0; // Unused bits will read 0 390 cp_glob_resp_ack <= 1'b1; 391 392 case (cp_glob_req_addr[REG_GLOB_ADDR_W-1:0]) 393 REG_DEVICE_ID: 394 cp_glob_resp_data <= {16'd0, device_id}; 395 396 REG_RFNOC_INFO: 397 cp_glob_resp_data <= {CHDR_WIDTH[15:0], RFNOC_PROTOVER[15:0]}; 398 399 REG_COMPAT_NUM: 400 cp_glob_resp_data <= {COMPAT_MAJOR[15:0], COMPAT_MINOR[15:0]}; 401 402 REG_FP_GPIO_CTRL: 403 cp_glob_resp_data <= fp_gpio_ctrl; 404 405 REG_FP_GPIO_MASTER: 406 cp_glob_resp_data <= fp_gpio_master_reg; 407 408 REG_FP_GPIO_RADIO_SRC: 409 cp_glob_resp_data <= fp_gpio_src_reg; 410 411 REG_DATESTAMP: 412 cp_glob_resp_data <= build_datestamp; 413 414 REG_GIT_HASH: begin 415 `ifndef GIT_HASH 416 `define GIT_HASH 32'h0BADC0DE 417 `endif 418 cp_glob_resp_data <= `GIT_HASH; 419 end 420 421 REG_SCRATCH: 422 cp_glob_resp_data <= scratch_reg; 423 424 REG_CLOCK_CTRL: begin 425 cp_glob_resp_data <= 32'b0; 426 cp_glob_resp_data[1:0] <= pps_select; 427 cp_glob_resp_data[3] <= refclk_locked; 428 end 429 430 REG_XADC_READBACK: 431 cp_glob_resp_data <= xadc_readback; 432 433 REG_BUS_CLK_RATE: 434 cp_glob_resp_data <= BUS_CLK_RATE; 435 436 REG_BUS_CLK_COUNT: 437 cp_glob_resp_data <= bus_counter; 438 439 REG_SFP_PORT_INFO: 440 cp_glob_resp_data <= sfp_ports_info; 441 442 REG_DBOARD_CTRL: 443 cp_glob_resp_data <= dboard_ctrl; 444 445 REG_DBOARD_STATUS: 446 cp_glob_resp_data <= dboard_status; 447 448 REG_NUM_TIMEKEEPERS: 449 cp_glob_resp_data <= NUM_TIMEKEEPERS; 450 451 default: begin 452 // Don't acknowledge if the address doesn't match 453 cp_glob_resp_ack <= 1'b0; 454 end 455 endcase 456 end 457 end 458 end 459 460 wire pps_radioclk; 461 462 // Synchronize the PPS signal to the radio clock domain 463 synchronizer pps_radio_sync ( 464 .clk(radio_clk), .rst(1'b0), .in(pps_refclk), .out(pps_radioclk) 465 ); 466 467 ///////////////////////////////////////////////////////////////////////////// 468 // 469 // Radio Daughter board and Front End Control 470 // 471 ///////////////////////////////////////////////////////////////////////////// 472 473 // Radio Daughter board GPIO 474 wire [DB_GPIO_WIDTH-1:0] db_gpio_in[0:NUM_CHANNELS-1]; 475 wire [DB_GPIO_WIDTH-1:0] db_gpio_out[0:NUM_CHANNELS-1]; 476 wire [DB_GPIO_WIDTH-1:0] db_gpio_ddr[0:NUM_CHANNELS-1]; 477 wire [DB_GPIO_WIDTH-1:0] db_gpio_fab[0:NUM_CHANNELS-1]; 478 wire [31:0] radio_gpio_out[0:NUM_CHANNELS-1]; 479 wire [31:0] radio_gpio_ddr[0:NUM_CHANNELS-1]; 480 wire [31:0] radio_gpio_in[0:NUM_CHANNELS-1]; 481 wire [31:0] leds[0:NUM_CHANNELS-1]; 482 483 // Daughter board I/O 484 wire rx_running[0:NUM_CHANNELS-1], tx_running[0:NUM_CHANNELS-1]; 485 wire [31:0] rx_int[0:NUM_CHANNELS-1], rx_data[0:NUM_CHANNELS-1], tx_int[0:NUM_CHANNELS-1], tx_data[0:NUM_CHANNELS-1]; 486 //wire rx_stb[0:NUM_CHANNELS-1], tx_stb[0:NUM_CHANNELS-1]; 487 wire db_fe_set_stb[0:NUM_CHANNELS-1]; 488 wire [7:0] db_fe_set_addr[0:NUM_CHANNELS-1]; 489 wire [31:0] db_fe_set_data[0:NUM_CHANNELS-1]; 490 wire db_fe_rb_stb[0:NUM_CHANNELS-1]; 491 wire [7:0] db_fe_rb_addr[0:NUM_CHANNELS-1]; 492 wire [63:0] db_fe_rb_data[0:NUM_CHANNELS-1]; 493 494 wire [NUM_RADIOS-1:0] sync_out; 495 496 genvar i; 497 generate 498 for (i = 0; i < NUM_CHANNELS; i = i + 1) begin 499 assign rx_atr[i] = rx_running[i]; 500 assign tx_atr[i] = tx_running[i]; 501 end 502 endgenerate 503 504 505 //------------------------------------ 506 // Daughterboard Control 507 // ----------------------------------- 508 509 localparam [7:0] SR_DB_BASE = 8'd160; 510 localparam [7:0] RB_DB_BASE = 8'd16; 511 512 generate 513 for (i = 0; i < NUM_CHANNELS; i = i + 1) begin: gen_db_control 514 db_control #( 515 .USE_SPI_CLK(0), 516 .SR_BASE(SR_DB_BASE), 517 .RB_BASE(RB_DB_BASE) 518 ) db_control_i ( 519 .clk(radio_clk), .reset(radio_rst), 520 .set_stb(db_fe_set_stb[i]), .set_addr(db_fe_set_addr[i]), .set_data(db_fe_set_data[i]), 521 .rb_stb(db_fe_rb_stb[i]), .rb_addr(db_fe_rb_addr[i]), .rb_data(db_fe_rb_data[i]), 522 .run_rx(rx_running[i]), .run_tx(tx_running[i]), 523 .misc_ins(32'h0), .misc_outs(), 524 .fp_gpio_in(radio_gpio_in[i]), .fp_gpio_out(radio_gpio_out[i]), .fp_gpio_ddr(radio_gpio_ddr[i]), .fp_gpio_fab(32'h0), 525 .db_gpio_in(db_gpio_in[i]), .db_gpio_out(db_gpio_out[i]), .db_gpio_ddr(db_gpio_ddr[i]), .db_gpio_fab(), 526 .leds(leds[i]), 527 .spi_clk(1'b0), .spi_rst(1'b0), .sen(), .sclk(), .mosi(), .miso(1'b0) 528 ); 529 end 530 endgenerate 531 532 generate 533 for (i = 0; i < NUM_CHANNELS; i = i + 1) begin: gen_gpio_control 534 // Radio Data 535 assign rx_data[i] = rx[32*i+31:32*i]; 536 assign tx[32*i+31:32*i] = tx_data[i]; 537 // GPIO 538 assign db_gpio_out_flat[DB_GPIO_WIDTH*i +: DB_GPIO_WIDTH] = db_gpio_out[i]; 539 assign db_gpio_ddr_flat[DB_GPIO_WIDTH*i +: DB_GPIO_WIDTH] = db_gpio_ddr[i]; 540 assign db_gpio_in[i] = db_gpio_in_flat[DB_GPIO_WIDTH*i +: DB_GPIO_WIDTH]; 541 assign db_gpio_fab[i] = db_gpio_fab_flat[DB_GPIO_WIDTH*i +: DB_GPIO_WIDTH]; 542 // LEDs 543 assign leds_flat[32*i+31:32*i] = leds[i]; 544 end 545 endgenerate 546 547 ///////////////////////////////////////////////////////////////////////////// 548 // 549 // Front-panel GPIO 550 // 551 ///////////////////////////////////////////////////////////////////////////// 552 553 wire [FP_GPIO_WIDTH-1:0] radio_gpio_in_sync; 554 wire [FP_GPIO_WIDTH-1:0] radio_gpio_src_out; 555 reg [FP_GPIO_WIDTH-1:0] radio_gpio_src_out_reg; 556 wire [FP_GPIO_WIDTH-1:0] radio_gpio_src_ddr; 557 reg [FP_GPIO_WIDTH-1:0] radio_gpio_src_ddr_reg = ~0; 558 559 // Double-synchronize the inputs to the PS 560 synchronizer #( 561 .INITIAL_VAL(1'b0), .WIDTH(FP_GPIO_WIDTH) 562 ) ps_gpio_in_sync_i ( 563 .clk(bus_clk), .rst(1'b0), .in(fp_gpio_in), .out(ps_gpio_in) 564 ); 565 566 // Double-synchronize the inputs to the radio 567 synchronizer #( 568 .INITIAL_VAL(1'b0), .WIDTH(FP_GPIO_WIDTH) 569 ) radio_gpio_in_sync_i ( 570 .clk(radio_clk), .rst(1'b0), .in(fp_gpio_in), .out(radio_gpio_in_sync) 571 ); 572 573 // Map the double-synchronized inputs to all radio channels 574 generate 575 for (i=0; i<NUM_CHANNELS; i=i+1) begin: gen_fp_gpio_in_sync 576 assign radio_gpio_in[i][FP_GPIO_WIDTH-1:0] = radio_gpio_in_sync; 577 end 578 endgenerate 579 580 // For each of the FP GPIO bits, implement four control muxes 581 generate 582 for (i=0; i<FP_GPIO_WIDTH; i=i+1) begin: gpio_muxing_gen 583 584 // 1) Select which radio drives the output 585 assign radio_gpio_src_out[i] = radio_gpio_out[fp_gpio_src_reg[2*i+1:2*i]][i]; 586 always @ (posedge radio_clk) begin 587 if (radio_rst) begin 588 radio_gpio_src_out_reg <= 0; 589 end else begin 590 radio_gpio_src_out_reg <= radio_gpio_src_out; 591 end 592 end 593 594 // 2) Select which radio drives the direction 595 assign radio_gpio_src_ddr[i] = radio_gpio_ddr[fp_gpio_src_reg[2*i+1:2*i]][i]; 596 always @ (posedge radio_clk) begin 597 if (radio_rst) begin 598 radio_gpio_src_ddr_reg <= ~0; 599 end else begin 600 radio_gpio_src_ddr_reg <= radio_gpio_src_ddr; 601 end 602 end 603 604 // 3) Select if the radio or the ps drives the output 605 // 606 // The following implements a 2:1 mux in a LUT explicitly to avoid 607 // glitches that can be introduced by unexpected Vivado synthesis. 608 // 609 (* dont_touch = "TRUE" *) LUT3 #( 610 .INIT(8'hCA) // Specify LUT Contents. O = ~I2&I0 | I2&I1 611 ) mux_out_i ( 612 .O(fp_gpio_out[i]), // LUT general output. Mux output 613 .I0(radio_gpio_src_out_reg[i]), // LUT input. Input 1 614 .I1(ps_gpio_out[i]), // LUT input. Input 2 615 .I2(fp_gpio_master_reg[i]) // LUT input. Select bit 616 ); 617 618 // 4) Select if the radio or the PS drives the direction 619 // 620 (* dont_touch = "TRUE" *) LUT3 #( 621 .INIT(8'hC5) // Specify LUT Contents. O = ~I2&I0 | I2&~I1 622 ) mux_ddr_i ( 623 .O(fp_gpio_tri[i]), // LUT general output. Mux output 624 .I0(radio_gpio_src_ddr_reg[i]), // LUT input. Input 1 625 .I1(ps_gpio_tri[i]), // LUT input. Input 2 626 .I2(fp_gpio_master_reg[i]) // LUT input. Select bit 627 ); 628 629 end 630 endgenerate 631 632 ///////////////////////////////////////////////////////////////////////////// 633 // 634 // Timekeeper 635 // 636 ///////////////////////////////////////////////////////////////////////////// 637 638 wire [63:0] radio_time; 639 640 timekeeper #( 641 .BASE_ADDR (0), // ctrlport_decoder removes the base offset 642 .TIME_INCREMENT (1'b1) 643 ) timekeeper_i ( 644 .tb_clk (radio_clk), 645 .tb_rst (radio_rst), 646 .s_ctrlport_clk (bus_clk), 647 .s_ctrlport_req_wr (cp_tk_req_wr), 648 .s_ctrlport_req_rd (cp_tk_req_rd), 649 .s_ctrlport_req_addr (cp_tk_req_addr), 650 .s_ctrlport_req_data (cp_tk_req_data), 651 .s_ctrlport_resp_ack (cp_tk_resp_ack), 652 .s_ctrlport_resp_data (cp_tk_resp_data), 653 .sample_rx_stb (rx_stb[0]), 654 .pps (pps_radioclk), 655 .tb_timestamp (radio_time), 656 .tb_timestamp_last_pps (), 657 .tb_period_ns_q32 () 658 ); 659 660 ///////////////////////////////////////////////////////////////////////////// 661 // 662 // RFNoC Image Core 663 // 664 ///////////////////////////////////////////////////////////////////////////// 665 666 rfnoc_image_core #( 667 .PROTOVER(RFNOC_PROTOVER) 668 ) rfnoc_image_core_i ( 669 .chdr_aclk (bus_clk ), 670 .ctrl_aclk (clk40 ), 671 .core_arst (bus_rst ), 672 .device_id (device_id ), 673 .radio_clk (radio_clk ), 674 .m_ctrlport_req_wr (m_ctrlport_req_wr ), 675 .m_ctrlport_req_rd (m_ctrlport_req_rd ), 676 .m_ctrlport_req_addr (m_ctrlport_req_addr ), 677 .m_ctrlport_req_data (m_ctrlport_req_data ), 678 .m_ctrlport_req_byte_en (), 679 .m_ctrlport_req_has_time (m_ctrlport_req_has_time), 680 .m_ctrlport_req_time (m_ctrlport_req_time ), 681 .m_ctrlport_resp_ack (m_ctrlport_resp_ack ), 682 .m_ctrlport_resp_status (2'b0), 683 .m_ctrlport_resp_data (m_ctrlport_resp_data ), 684 .radio_time (radio_time ), 685 .radio_rx_stb ({rx_stb[1], rx_stb[0] }), 686 .radio_rx_data ({rx_data[1], rx_data[0] }), 687 .radio_rx_running ({rx_running[1], rx_running[0]}), 688 .radio_tx_stb ({tx_stb[1], tx_stb[0] }), 689 .radio_tx_data ({tx_data[1], tx_data[0] }), 690 .radio_tx_running ({tx_running[1], tx_running[0]}), 691 .s_dma_tdata (s_dma_tdata), 692 .s_dma_tlast (s_dma_tlast), 693 .s_dma_tvalid (s_dma_tvalid), 694 .s_dma_tready (s_dma_tready), 695 .m_dma_tdata (m_dma_tdata), 696 .m_dma_tlast (m_dma_tlast), 697 .m_dma_tvalid (m_dma_tvalid), 698 .m_dma_tready (m_dma_tready) 699 ); 700 701 //--------------------------------------------------------------------------- 702 // Convert Control Port to Settings Bus 703 //--------------------------------------------------------------------------- 704 705 ctrlport_to_settings_bus # ( 706 .NUM_PORTS (2), 707 .USE_TIME (1) 708 ) ctrlport_to_settings_bus_i ( 709 .ctrlport_clk (radio_clk), 710 .ctrlport_rst (radio_rst), 711 .s_ctrlport_req_wr (m_ctrlport_req_wr), 712 .s_ctrlport_req_rd (m_ctrlport_req_rd), 713 .s_ctrlport_req_addr (m_ctrlport_req_addr), 714 .s_ctrlport_req_data (m_ctrlport_req_data), 715 .s_ctrlport_req_has_time (m_ctrlport_req_has_time), 716 .s_ctrlport_req_time (m_ctrlport_req_time), 717 .s_ctrlport_resp_ack (m_ctrlport_resp_ack), 718 .s_ctrlport_resp_data (m_ctrlport_resp_data), 719 .set_data ({db_fe_set_data[1], db_fe_set_data[0]}), 720 .set_addr ({db_fe_set_addr[1], db_fe_set_addr[0]}), 721 .set_stb ({db_fe_set_stb[1], db_fe_set_stb[0] }), 722 .set_time (), 723 .set_has_time (), 724 .rb_stb ({db_fe_rb_stb[1], db_fe_rb_stb[0] }), 725 .rb_addr ({db_fe_rb_addr[1], db_fe_rb_addr[0] }), 726 .rb_data ({db_fe_rb_data[1], db_fe_rb_data[0] }), 727 .timestamp (radio_time) 728 ); 729 730endmodule //e31x_core 731`default_nettype wire 732 733