diff options
author | Wade Fife <wade.fife@ettus.com> | 2021-06-08 19:40:46 -0500 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2021-06-10 11:56:58 -0500 |
commit | 6d3765605262016a80f71e36357f749ea35cbe5a (patch) | |
tree | 7d62d6622befd4132ac1ee085effa1426f7f53e5 /fpga/usrp3/top/x400/rfdc_timing_control.v | |
parent | f706b89e6974e28ce76aadeeb06169becc86acba (diff) | |
download | uhd-6d3765605262016a80f71e36357f749ea35cbe5a.tar.gz uhd-6d3765605262016a80f71e36357f749ea35cbe5a.tar.bz2 uhd-6d3765605262016a80f71e36357f749ea35cbe5a.zip |
fpga: x400: Add support for X410 motherboard FPGA
Co-authored-by: Andrew Moch <Andrew.Moch@ni.com>
Co-authored-by: Daniel Jepson <daniel.jepson@ni.com>
Co-authored-by: Javier Valenzuela <javier.valenzuela@ni.com>
Co-authored-by: Joerg Hofrichter <joerg.hofrichter@ni.com>
Co-authored-by: Kumaran Subramoniam <kumaran.subramoniam@ni.com>
Co-authored-by: Max Köhler <max.koehler@ni.com>
Co-authored-by: Michael Auchter <michael.auchter@ni.com>
Co-authored-by: Paul Butler <paul.butler@ni.com>
Co-authored-by: Wade Fife <wade.fife@ettus.com>
Co-authored-by: Hector Rubio <hrubio@ni.com>
Diffstat (limited to 'fpga/usrp3/top/x400/rfdc_timing_control.v')
-rw-r--r-- | fpga/usrp3/top/x400/rfdc_timing_control.v | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/fpga/usrp3/top/x400/rfdc_timing_control.v b/fpga/usrp3/top/x400/rfdc_timing_control.v new file mode 100644 index 000000000..f1f1cfad1 --- /dev/null +++ b/fpga/usrp3/top/x400/rfdc_timing_control.v @@ -0,0 +1,289 @@ +// +// 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 +// +//<regmap name="RADIO_CTRLPORT_REGMAP" readablestrobes="false" generatevhdl="true" ettusguidelines="true"> +// <group name="RADIO_CTRLPORT_WINDOWS"> +// <info>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.</info> +// <window name="DB_WINDOW" offset="0x00000" size="0x08000"> +// <info>Daughterboard GPIO interface. Register access within this space +// is directed to the associated daughterboard CPLD.</info> +// </window> +// <window name="RFDC_TIMING_WINDOW" offset="0x08000" size="0x08000" targetregmap="RFDC_TIMING_REGMAP"> +// <info>RFDC timing control interface.</info> +// </window> +// </group> +//</regmap> +// +//<regmap name="RFDC_TIMING_REGMAP" readablestrobes="false" generatevhdl="true" ettusguidelines="true"> +// <group name="RFDC_TIMING_REGS"> +// <register name="NCO_RESET_REG" offset="0x00" size="32" readable="true" writable="true"> +// <info>NCO reset control register.</info> +// <bitfield name="NCO_RESET_START" range="0" readable="false" strobe="true"> +// <info>Write a 1 to this bit to start a reset the RFDC's NCO.</info> +// </bitfield> +// <bitfield name="NCO_RESET_DONE" range="1" writable="false"> +// <info>When 1, indicates that the NCO reset has completed.</info> +// </bitfield> +// </register> +// <register name="GEARBOX_RESET_REG" offset="0x04" size="32" readable="true" writable="true"> +// <info>Gearbox reset control register.</info> +// <bitfield name="ADC_RESET" range="0" readable="false" strobe="true"> +// <info> +// 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. +// </info> +// </bitfield> +// <bitfield name="DAC_RESET" range="1" readable="false" strobe="true"> +// <info> +// 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. +// </info> +// </bitfield> +// </register> +// </group> +//</regmap> +// +//XmlParse xml_off |