// // Copyright 2021 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: LGPL-3.0-or-later // // Module: rfdc_timing_control // // Description: // // This module handles timed register writes for the RFDC, such as NCO reset // control. It takes the CtrlPort master from each radio block and splits it // into a CtrlPort bus for the associated daughter board and another CtrlPort // bus for the RFDC timing control. Timed commands on the RF timing bus are // handled by the ctrlport_timer module. // // Parameters: // // NUM_DBOARDS : Number of daughter boards to support // `default_nettype none module rfdc_timing_control #( parameter NUM_DBOARDS = 2 ) ( // Clocks and resets input wire clk, input wire rst, // Time input wire [63:0] time_now, input wire time_now_stb, input wire [ 3:0] time_ignore_bits, // CtrlPort Slave (from RFNoC Radio Block) input wire [ 1*NUM_DBOARDS-1:0] s_ctrlport_req_wr, input wire [ 1*NUM_DBOARDS-1:0] s_ctrlport_req_rd, input wire [ 20*NUM_DBOARDS-1:0] s_ctrlport_req_addr, input wire [ 32*NUM_DBOARDS-1:0] s_ctrlport_req_data, input wire [ 4*NUM_DBOARDS-1:0] s_ctrlport_req_byte_en, input wire [ 1*NUM_DBOARDS-1:0] s_ctrlport_req_has_time, input wire [ 64*NUM_DBOARDS-1:0] s_ctrlport_req_time, output wire [ 1*NUM_DBOARDS-1:0] s_ctrlport_resp_ack, output wire [ 2*NUM_DBOARDS-1:0] s_ctrlport_resp_status, output wire [ 32*NUM_DBOARDS-1:0] s_ctrlport_resp_data, // CtrlPort Master (to Daughter Boards) output wire [ 1*NUM_DBOARDS-1:0] m_ctrlport_req_wr, output wire [ 1*NUM_DBOARDS-1:0] m_ctrlport_req_rd, output wire [ 20*NUM_DBOARDS-1:0] m_ctrlport_req_addr, output wire [ 32*NUM_DBOARDS-1:0] m_ctrlport_req_data, output wire [ 4*NUM_DBOARDS-1:0] m_ctrlport_req_byte_en, output wire [ 1*NUM_DBOARDS-1:0] m_ctrlport_req_has_time, output wire [ 64*NUM_DBOARDS-1:0] m_ctrlport_req_time, input wire [ 1*NUM_DBOARDS-1:0] m_ctrlport_resp_ack, input wire [ 2*NUM_DBOARDS-1:0] m_ctrlport_resp_status, input wire [ 32*NUM_DBOARDS-1:0] m_ctrlport_resp_data, // RF Reset Control output reg start_nco_reset, input wire nco_reset_done, output reg adc_reset_pulse, output reg dac_reset_pulse ); `include "regmap/radio_ctrlport_regmap_utils.vh" `include "regmap/rfdc_timing_regmap_utils.vh" // Reset registers reg [NUM_DBOARDS-1:0] reg_nco_reset_start = 0; reg [NUM_DBOARDS-1:0] reg_adc_reset_pulse = 0; reg [NUM_DBOARDS-1:0] reg_dac_reset_pulse = 0; genvar db; generate for (db = 0; db < NUM_DBOARDS; db = db+1) begin : gen_db_ctrlport //----------------------------------------------------------------------- // CtrlPort Splitter //----------------------------------------------------------------------- wire [ 1-1:0] rf_ctrlport_req_wr; wire [ 1-1:0] rf_ctrlport_req_rd; wire [ 20-1:0] rf_ctrlport_req_addr; wire [ 32-1:0] rf_ctrlport_req_data; wire [ 4-1:0] rf_ctrlport_req_byte_en; wire [ 1-1:0] rf_ctrlport_req_has_time; wire [ 64-1:0] rf_ctrlport_req_time; wire [ 1-1:0] rf_ctrlport_resp_ack; wire [ 2-1:0] rf_ctrlport_resp_status; wire [ 32-1:0] rf_ctrlport_resp_data; localparam [31:0] RFDC_TIMING_WINDOW_SIZE_W = $clog2(RFDC_TIMING_WINDOW_SIZE); localparam [31:0] DB_WINDOW_SIZE_W = $clog2(DB_WINDOW_SIZE); ctrlport_decoder_param #( .NUM_SLAVES (2), .PORT_BASE ({ RFDC_TIMING_WINDOW[19:0], DB_WINDOW[19:0] }), .PORT_ADDR_W ({ RFDC_TIMING_WINDOW_SIZE_W, DB_WINDOW_SIZE_W }) ) ctrlport_decoder_param_i ( .ctrlport_clk (clk), .ctrlport_rst (rst), .s_ctrlport_req_wr (s_ctrlport_req_wr [ 1*db+: 1]), .s_ctrlport_req_rd (s_ctrlport_req_rd [ 1*db+: 1]), .s_ctrlport_req_addr (s_ctrlport_req_addr [20*db+:20]), .s_ctrlport_req_data (s_ctrlport_req_data [32*db+:32]), .s_ctrlport_req_byte_en (s_ctrlport_req_byte_en [ 4*db+: 4]), .s_ctrlport_req_has_time (s_ctrlport_req_has_time [ 1*db+: 1]), .s_ctrlport_req_time (s_ctrlport_req_time [64*db+:64]), .s_ctrlport_resp_ack (s_ctrlport_resp_ack [ 1*db+: 1]), .s_ctrlport_resp_status (s_ctrlport_resp_status [ 2*db+: 2]), .s_ctrlport_resp_data (s_ctrlport_resp_data [32*db+:32]), .m_ctrlport_req_wr ({ rf_ctrlport_req_wr, m_ctrlport_req_wr [ 1*db+: 1] }), .m_ctrlport_req_rd ({ rf_ctrlport_req_rd, m_ctrlport_req_rd [ 1*db+: 1] }), .m_ctrlport_req_addr ({ rf_ctrlport_req_addr, m_ctrlport_req_addr [20*db+:20] }), .m_ctrlport_req_data ({ rf_ctrlport_req_data, m_ctrlport_req_data [32*db+:32] }), .m_ctrlport_req_byte_en ({ rf_ctrlport_req_byte_en, m_ctrlport_req_byte_en [ 4*db+: 4] }), .m_ctrlport_req_has_time ({ rf_ctrlport_req_has_time, m_ctrlport_req_has_time [ 1*db+: 1] }), .m_ctrlport_req_time ({ rf_ctrlport_req_time, m_ctrlport_req_time [64*db+:64] }), .m_ctrlport_resp_ack ({ rf_ctrlport_resp_ack, m_ctrlport_resp_ack [ 1*db+: 1] }), .m_ctrlport_resp_status ({ rf_ctrlport_resp_status, m_ctrlport_resp_status [ 2*db+: 2] }), .m_ctrlport_resp_data ({ rf_ctrlport_resp_data, m_ctrlport_resp_data [32*db+:32] }) ); //----------------------------------------------------------------------- // RF Reset Control //----------------------------------------------------------------------- wire [ 1-1:0] nco_ctrlport_req_wr; wire [ 1-1:0] nco_ctrlport_req_rd; wire [ 20-1:0] nco_ctrlport_req_addr; wire [ 32-1:0] nco_ctrlport_req_data; reg [ 1-1:0] nco_ctrlport_resp_ack; reg [ 32-1:0] nco_ctrlport_resp_data; ctrlport_timer #( .EXEC_LATE_CMDS (1) ) ctrlport_timer_nco ( .clk (clk), .rst (rst), .time_now (time_now), .time_now_stb (time_now_stb), .time_ignore_bits (time_ignore_bits), .s_ctrlport_req_wr (rf_ctrlport_req_wr), .s_ctrlport_req_rd (rf_ctrlport_req_rd), .s_ctrlport_req_addr (rf_ctrlport_req_addr), .s_ctrlport_req_data (rf_ctrlport_req_data), .s_ctrlport_req_byte_en (rf_ctrlport_req_byte_en), .s_ctrlport_req_has_time (rf_ctrlport_req_has_time), .s_ctrlport_req_time (rf_ctrlport_req_time), .s_ctrlport_resp_ack (rf_ctrlport_resp_ack), .s_ctrlport_resp_status (rf_ctrlport_resp_status), .s_ctrlport_resp_data (rf_ctrlport_resp_data), .m_ctrlport_req_wr (nco_ctrlport_req_wr), .m_ctrlport_req_rd (nco_ctrlport_req_rd), .m_ctrlport_req_addr (nco_ctrlport_req_addr), .m_ctrlport_req_data (nco_ctrlport_req_data), .m_ctrlport_req_byte_en (), .m_ctrlport_resp_ack (nco_ctrlport_resp_ack), .m_ctrlport_resp_status (2'b0), .m_ctrlport_resp_data (nco_ctrlport_resp_data) ); always @(posedge clk) begin if (rst) begin nco_ctrlport_resp_ack <= 0; reg_nco_reset_start[db] <= 0; nco_ctrlport_resp_data <= 'bX; end else begin // Default assignments reg_nco_reset_start[db] <= 0; reg_adc_reset_pulse[db] <= 0; reg_dac_reset_pulse[db] <= 0; nco_ctrlport_resp_ack <= 0; nco_ctrlport_resp_data <= 0; // Handle register reads if (nco_ctrlport_req_rd) begin case (nco_ctrlport_req_addr) NCO_RESET_REG: begin nco_ctrlport_resp_ack <= 1; nco_ctrlport_resp_data[NCO_RESET_DONE] <= nco_reset_done; end GEARBOX_RESET_REG: begin nco_ctrlport_resp_ack <= 1; end endcase end // Handle register writes if (nco_ctrlport_req_wr) begin case (nco_ctrlport_req_addr) NCO_RESET_REG: begin nco_ctrlport_resp_ack <= 1; reg_nco_reset_start[db] <= nco_ctrlport_req_data[NCO_RESET_START]; end GEARBOX_RESET_REG: begin nco_ctrlport_resp_ack <= 1; reg_adc_reset_pulse[db] <= nco_ctrlport_req_data[ADC_RESET]; reg_dac_reset_pulse[db] <= nco_ctrlport_req_data[DAC_RESET]; end endcase end end end end endgenerate //--------------------------------------------------------------------------- // Merge Resets //--------------------------------------------------------------------------- // // There are multiple DBs but only one reset signal for each RF component. // Since the reset is simply a single cycle pulse, we OR the reset registers // for each daughter board together. // //--------------------------------------------------------------------------- always @(posedge clk) begin if (rst) begin start_nco_reset <= 0; adc_reset_pulse <= 0; dac_reset_pulse <= 0; end else begin start_nco_reset <= |reg_nco_reset_start; adc_reset_pulse <= |reg_adc_reset_pulse; dac_reset_pulse <= |reg_dac_reset_pulse; end end endmodule `default_nettype wire //XmlParse xml_on // // // // Each radio's CtrlPort peripheral interface is divided into the // following memory spaces. Note that the CtrlPort peripheral interface // starts at offset 0x80000 in the RFNoC Radio block's register space. // // Daughterboard GPIO interface. Register access within this space // is directed to the associated daughterboard CPLD. // // // RFDC timing control interface. // // // // // // // // NCO reset control register. // // Write a 1 to this bit to start a reset the RFDC's NCO. // // // When 1, indicates that the NCO reset has completed. // // // // Gearbox reset control register. // // // This reset is for the gearbox on the ADC data path that is used to // move data from one clock domain to another outside the RFDC. Write // a 1 to this bit to send a reset pulse to the ADC gearbox. // // // // // This reset is for the gearbox on the DAC data path that is used to // move data from one clock domain to another outside the RFDC. Write // a 1 to this bit to send a reset pulse to the DAC gearbox. // // // // // // //XmlParse xml_off