mpm/fpga: x4xx: Major updates in preparation for future devices
FPGA: - Split up MB registers that control daughterboard specific settings so that daughterboards 0 and 1 could have different setings, in preparation for future devices that require different settings. This requires a compat number bump to 8.0. - Add registers for additional RFDC information, including the block/tile mapping of the individual channels, and information about resampling capabilities - Identify sections of code that would be specific to X410/ZBX and move them to their own headers, so it's trivial to add device-specific sections of code instead for other devices in the future. - This includes constraints for clocks and I/O pins. - Remove ability to do timed ctrlport transactions to the MB CPLD, this was unused and possibly broken. - Move daughterboard-specific code into its own code location (dboards/zbx) - Move X410-specific register documentation to its own location (doc/X410) - Refactor Makefiles to split out X410/ZBX specific components and allow switching between device types - Add 512-bit AXI interconnects - Make number of timekeepers configurable (X410 keeps the single timekeeper) MPM: - Required compat is bumped to 8.0 - Now supports new registers for detecting DSP capabilities and multi-rate settings for the daughterboards - Adds MMCM controls (currently unused) Co-authored-by: Wade Fife <wade.fife@ni.com> Co-authored-by: Ryan Marlow <ryan@lmarlow.com> Co-authored-by: Martin Braun <martin.braun@ettus.com> Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com> Original-commit: c1d268917ea65dd9c5a42366014cb96d3c025223
This commit is contained in:
committed by
Martin Braun
co-authored by
Wade Fife
Ryan Marlow
Martin Braun
Humberto Jimenez
parent
ffdcc016cc
commit
adf6f576c6
@@ -0,0 +1,130 @@
|
||||
//
|
||||
// Copyright 2022 Ettus Research, a National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: ctrlport_clk_crossing_derived
|
||||
//
|
||||
// Description:
|
||||
// Performs a simplified clk crossing for a ctrlport interface.
|
||||
// i_clk must be derived from o_clk by an integer multiplier and
|
||||
// originate from the same PLL. This ensures the clock crossing
|
||||
// can be achieved by using simple registers, as STA will be able
|
||||
// to meet setup and hold requirements on them.
|
||||
//
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module ctrlport_clk_crossing_derived (
|
||||
// Clocks
|
||||
input wire i_clk,
|
||||
input wire o_clk,
|
||||
|
||||
// Request (domain: i_clk)
|
||||
input wire i_ctrlport_rst,
|
||||
input wire i_ctrlport_req_wr,
|
||||
input wire i_ctrlport_req_rd,
|
||||
input wire [19:0] i_ctrlport_req_addr,
|
||||
input wire [31:0] i_ctrlport_req_data,
|
||||
|
||||
// Response (domain: i_clk)
|
||||
output wire i_ctrlport_resp_ack,
|
||||
output reg [ 1:0] i_ctrlport_resp_status,
|
||||
output reg [31:0] i_ctrlport_resp_data,
|
||||
|
||||
// Request (domain: o_clk)
|
||||
output reg o_ctrlport_rst,
|
||||
output reg o_ctrlport_req_wr,
|
||||
output reg o_ctrlport_req_rd,
|
||||
output reg [19:0] o_ctrlport_req_addr,
|
||||
output reg [31:0] o_ctrlport_req_data,
|
||||
|
||||
// Response (domain: o_clk)
|
||||
input wire o_ctrlport_resp_ack,
|
||||
input wire [ 1:0] o_ctrlport_resp_status,
|
||||
input wire [31:0] o_ctrlport_resp_data
|
||||
|
||||
);
|
||||
|
||||
// holding read and write flags for multiple i_clk cycles
|
||||
reg ctrlport_req_wr_hold = 1'b0;
|
||||
reg ctrlport_req_rd_hold = 1'b0;
|
||||
|
||||
reg ctrlport_req_rd_fall = 1'b0;
|
||||
reg ctrlport_req_wr_fall = 1'b0;
|
||||
reg [31:0] ctrlport_resp_data_fall = 32'b0;
|
||||
reg [ 1:0] ctrlport_resp_status_fall = 2'b0;
|
||||
reg ctrlport_resp_ack_fall = 1'b0;
|
||||
|
||||
// Retime signals to falling edge of i_clk. By sampling on the falling edge of
|
||||
// i_clk, we provide (nominally) half a i_clk period of hold, while
|
||||
// reducing setup time by half. The late arrival of i_clk adds back some
|
||||
// of the lost setup margin.
|
||||
always @(negedge i_clk) begin
|
||||
ctrlport_req_rd_fall <= o_ctrlport_req_rd;
|
||||
ctrlport_req_wr_fall <= o_ctrlport_req_wr;
|
||||
ctrlport_resp_ack_fall <= o_ctrlport_resp_ack;
|
||||
ctrlport_resp_status_fall <= o_ctrlport_resp_status;
|
||||
ctrlport_resp_data_fall <= o_ctrlport_resp_data;
|
||||
end
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (ctrlport_req_wr_fall) begin
|
||||
ctrlport_req_wr_hold <= 1'b0;
|
||||
end else if (i_ctrlport_req_wr) begin
|
||||
ctrlport_req_wr_hold <= 1'b1;
|
||||
end
|
||||
if (ctrlport_req_rd_fall) begin
|
||||
ctrlport_req_rd_hold <= 1'b0;
|
||||
end else if (i_ctrlport_req_rd) begin
|
||||
ctrlport_req_rd_hold <= 1'b1;
|
||||
end
|
||||
|
||||
// capture request address and data
|
||||
if (i_ctrlport_req_wr || i_ctrlport_req_rd) begin
|
||||
o_ctrlport_req_addr <= i_ctrlport_req_addr;
|
||||
o_ctrlport_req_data <= i_ctrlport_req_data;
|
||||
end
|
||||
end
|
||||
|
||||
// capture extended flags in o_clk domain
|
||||
always @(posedge o_clk) begin
|
||||
o_ctrlport_req_wr <= ctrlport_req_wr_hold;
|
||||
o_ctrlport_req_rd <= ctrlport_req_rd_hold;
|
||||
end
|
||||
|
||||
// search for rising edge in response
|
||||
reg [1:0] ctrlport_resp_ack_reg = 2'b0;
|
||||
always @(posedge i_clk) begin
|
||||
ctrlport_resp_ack_reg = {ctrlport_resp_ack_reg[0], ctrlport_resp_ack_fall};
|
||||
end
|
||||
assign i_ctrlport_resp_ack = ctrlport_resp_ack_reg[0] & ~ctrlport_resp_ack_reg[1];
|
||||
|
||||
// capture response data
|
||||
always @(posedge i_clk) begin
|
||||
if (ctrlport_resp_ack_fall) begin
|
||||
i_ctrlport_resp_status <= ctrlport_resp_status_fall;
|
||||
i_ctrlport_resp_data <= ctrlport_resp_data_fall;
|
||||
end
|
||||
end
|
||||
|
||||
// transfer reset
|
||||
reg ctrlport_rst_hold = 1'b0;
|
||||
reg ctrlport_rst_fall = 1'b0;
|
||||
always @(posedge i_clk) begin
|
||||
if (i_ctrlport_rst) begin
|
||||
ctrlport_rst_hold <= 1'b1;
|
||||
end else if (ctrlport_rst_fall) begin
|
||||
ctrlport_rst_hold <= 1'b0;
|
||||
end
|
||||
end
|
||||
always @(posedge o_clk) begin
|
||||
o_ctrlport_rst <= ctrlport_rst_hold;
|
||||
end
|
||||
always @(negedge i_clk) begin
|
||||
ctrlport_rst_fall <= o_ctrlport_rst;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
`default_nettype wire
|
||||
@@ -827,14 +827,14 @@ set_instance_assignment -name CURRENT_STRENGTH_NEW 2MA -to CH1_TX_LED
|
||||
set_global_assignment -name VERILOG_FILE ../zbx_top_cpld.v
|
||||
set_global_assignment -name VERILOG_FILE ../../../../../../lib/rfnoc/utils/ctrlport_decoder.v
|
||||
set_global_assignment -name SDC_FILE ../../../../constraints/timing/shared_constants.sdc
|
||||
set_global_assignment -name SDC_FILE ../../../../cpld/db_spi_shared_constants.sdc
|
||||
set_global_assignment -name SDC_FILE ../../../../cpld/x410/db_spi_shared_constants.sdc
|
||||
set_global_assignment -name SDC_FILE ../zbx_top_cpld.sdc
|
||||
set_global_assignment -name VERILOG_FILE ../../../../../../lib/control/synchronizer_impl.v
|
||||
set_global_assignment -name VERILOG_FILE ../../../../../../lib/control/synchronizer.v
|
||||
set_global_assignment -name VERILOG_FILE ../../../../../../lib/control/reset_sync.v
|
||||
set_global_assignment -name VERILOG_FILE ../../../../../../lib/rfnoc/utils/ctrlport_splitter.v
|
||||
set_global_assignment -name VERILOG_FILE ../../../../cpld/spi_slave.v
|
||||
set_global_assignment -name VERILOG_FILE ../../../../cpld/spi_slave_to_ctrlport_master.v
|
||||
set_global_assignment -name VERILOG_FILE ../../../../cpld/common/spi_slave.v
|
||||
set_global_assignment -name VERILOG_FILE ../../../../cpld/common/spi_slave_to_ctrlport_master.v
|
||||
set_global_assignment -name VERILOG_FILE ../register_endpoints/basic_regs.v
|
||||
set_global_assignment -name VERILOG_FILE ../register_endpoints/power_regs.v
|
||||
set_global_assignment -name VERILOG_FILE ../register_endpoints/switch_control.v
|
||||
@@ -847,7 +847,7 @@ set_global_assignment -name VERILOG_FILE ../register_endpoints/lo_control.v
|
||||
set_global_assignment -name VERILOG_FILE ../zbx_cpld_core.v
|
||||
set_global_assignment -name VERILOG_FILE ../../../ctrlport_byte_deserializer.v
|
||||
set_global_assignment -name VERILOG_FILE ../../../../../../lib/rfnoc/utils/ctrlport_clk_cross.v
|
||||
set_global_assignment -name VERILOG_FILE ../../../../cpld/reconfig_engine.v
|
||||
set_global_assignment -name VERILOG_FILE ../../../../cpld/common/reconfig_engine.v
|
||||
set_global_assignment -name VERILOG_FILE ../../../../../../lib/rfnoc/utils/ctrlport_combiner.v
|
||||
set_global_assignment -name VERILOG_FILE ../register_endpoints/atr_controller.v
|
||||
set_global_assignment -name VERILOG_INCLUDE_FILE ../../../../../../lib/control/ram_2port_impl.vh
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
//
|
||||
// Copyright 2021 Ettus Research, a National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: db_gpio_interface
|
||||
//
|
||||
// Description:
|
||||
// Interface for GPIO interface towards daughterboards.
|
||||
//
|
||||
// A ControlPort interface is serialized into bytes along with a valid signal.
|
||||
// The ControlPort supports write requests only. Byte enables are not supported.
|
||||
// There is support for timed commands.
|
||||
// Furthermore there are 4 state wires towards the DB. Ensure an appropriate
|
||||
// hold time on the states as the transmission happens in pll_ref_clk, which is
|
||||
// slower than radio_clk. Pulses of e.g. just a single clock cycle may not get
|
||||
// transferred to the DB.
|
||||
//
|
||||
// The 20 available GPIO lines are assigned with
|
||||
// - 5x empty
|
||||
// - bytestream direction
|
||||
// - bytestream valid
|
||||
// - bytestream data (8 bits)
|
||||
// - 1x empty
|
||||
// - db_state (4 bits)
|
||||
//
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module db_gpio_interface (
|
||||
// Clocks and reset
|
||||
input wire radio_clk,
|
||||
input wire pll_ref_clk,
|
||||
|
||||
// DB state lines (domain: radio_clk)
|
||||
input wire [ 3:0] db_state,
|
||||
// Request (domain: radio_clk)
|
||||
input wire ctrlport_rst,
|
||||
input wire s_ctrlport_req_wr,
|
||||
input wire s_ctrlport_req_rd,
|
||||
input wire [19:0] s_ctrlport_req_addr,
|
||||
input wire [31:0] s_ctrlport_req_data,
|
||||
|
||||
// Response (domain: radio_clk)
|
||||
output wire s_ctrlport_resp_ack,
|
||||
output wire [ 1:0] s_ctrlport_resp_status,
|
||||
output wire [31:0] s_ctrlport_resp_data,
|
||||
|
||||
// GPIO interface (domain: pll_ref_clk)
|
||||
input wire [19:0] gpio_in,
|
||||
output wire [19:0] gpio_out,
|
||||
output wire [19:0] gpio_out_en,
|
||||
|
||||
// Version (Constant)
|
||||
output wire [95:0] version_info
|
||||
);
|
||||
|
||||
`include "../../regmap/x410/versioning_regs_regmap_utils.vh"
|
||||
`include "../../regmap/versioning_utils.vh"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Clock domain crossing (radio_clk -> pll_ref_clk)
|
||||
//----------------------------------------------------------------------------
|
||||
// Radio_clk is derived from pll_ref_clk by an integer multiplier and
|
||||
// originate from the same PLL.
|
||||
// Therefore the clock crossing can be achieved by using simple registers.
|
||||
// Static timing analysis will be able to meet setup and hold requirements on
|
||||
// them.
|
||||
|
||||
wire ctrlport_rst_prc;
|
||||
|
||||
wire ctrlport_req_wr_prc;
|
||||
wire ctrlport_req_rd_prc;
|
||||
wire [19:0] ctrlport_req_addr_prc;
|
||||
wire [31:0] ctrlport_req_data_prc;
|
||||
|
||||
wire ctrlport_resp_ack_prc;
|
||||
wire [ 1:0] ctrlport_resp_status_prc;
|
||||
wire [31:0] ctrlport_resp_data_prc;
|
||||
|
||||
ctrlport_clk_crossing_derived ctrlport_clk_crossing_derived_i(
|
||||
.i_clk (radio_clk),
|
||||
.o_clk (pll_ref_clk),
|
||||
.i_ctrlport_rst (ctrlport_rst),
|
||||
.i_ctrlport_req_wr (s_ctrlport_req_wr),
|
||||
.i_ctrlport_req_rd (s_ctrlport_req_rd),
|
||||
.i_ctrlport_req_addr (s_ctrlport_req_addr),
|
||||
.i_ctrlport_req_data (s_ctrlport_req_data),
|
||||
.i_ctrlport_resp_ack (s_ctrlport_resp_ack),
|
||||
.i_ctrlport_resp_status (s_ctrlport_resp_status),
|
||||
.i_ctrlport_resp_data (s_ctrlport_resp_data),
|
||||
.o_ctrlport_rst (ctrlport_rst_prc),
|
||||
.o_ctrlport_req_wr (ctrlport_req_wr_prc),
|
||||
.o_ctrlport_req_rd (ctrlport_req_rd_prc),
|
||||
.o_ctrlport_req_addr (ctrlport_req_addr_prc),
|
||||
.o_ctrlport_req_data (ctrlport_req_data_prc),
|
||||
.o_ctrlport_resp_ack (ctrlport_resp_ack_prc),
|
||||
.o_ctrlport_resp_status (ctrlport_resp_status_prc),
|
||||
.o_ctrlport_resp_data (ctrlport_resp_data_prc)
|
||||
);
|
||||
|
||||
// transfer state lines
|
||||
reg [3:0] db_state_prc = 4'b0;
|
||||
reg [3:0] db_state_prc_fe = 4'b0;
|
||||
always @(posedge pll_ref_clk) begin
|
||||
db_state_prc <= db_state;
|
||||
end
|
||||
always @(negedge pll_ref_clk) begin
|
||||
db_state_prc_fe <= db_state_prc;
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Ctrlport serializer
|
||||
//----------------------------------------------------------------------------
|
||||
wire [7:0] bytestream_data_in;
|
||||
wire [7:0] bytestream_data_out;
|
||||
wire bytestream_direction;
|
||||
wire bytestream_output_enable;
|
||||
wire bytestream_valid_in;
|
||||
wire bytestream_valid_out;
|
||||
|
||||
ctrlport_byte_serializer serializer_i (
|
||||
.ctrlport_clk (pll_ref_clk),
|
||||
.ctrlport_rst (ctrlport_rst_prc),
|
||||
.s_ctrlport_req_wr (ctrlport_req_wr_prc),
|
||||
.s_ctrlport_req_rd (ctrlport_req_rd_prc),
|
||||
.s_ctrlport_req_addr (ctrlport_req_addr_prc),
|
||||
.s_ctrlport_req_data (ctrlport_req_data_prc),
|
||||
.s_ctrlport_resp_ack (ctrlport_resp_ack_prc),
|
||||
.s_ctrlport_resp_status (ctrlport_resp_status_prc),
|
||||
.s_ctrlport_resp_data (ctrlport_resp_data_prc),
|
||||
.bytestream_data_in (bytestream_data_in),
|
||||
.bytestream_valid_in (bytestream_valid_in),
|
||||
.bytestream_data_out (bytestream_data_out),
|
||||
.bytestream_valid_out (bytestream_valid_out),
|
||||
.bytestream_direction (bytestream_direction),
|
||||
.bytestream_output_enable (bytestream_output_enable)
|
||||
);
|
||||
|
||||
// IOB registers to drive data on the falling edge
|
||||
reg [7:0] bytestream_data_out_fe;
|
||||
reg bytestream_direction_fe;
|
||||
reg bytestream_output_enable_fe;
|
||||
reg bytestream_valid_out_fe;
|
||||
|
||||
// Signals are shifted into a falling edge domain to help meet
|
||||
// hold requirements at CPLD
|
||||
always @(negedge pll_ref_clk) begin
|
||||
if (ctrlport_rst_prc) begin
|
||||
bytestream_data_out_fe <= 8'b0;
|
||||
bytestream_valid_out_fe <= 1'b0;
|
||||
bytestream_direction_fe <= 1'b0;
|
||||
bytestream_output_enable_fe <= 1'b1;
|
||||
end else begin
|
||||
bytestream_data_out_fe <= bytestream_data_out;
|
||||
bytestream_valid_out_fe <= bytestream_valid_out;
|
||||
bytestream_direction_fe <= bytestream_direction;
|
||||
bytestream_output_enable_fe <= bytestream_output_enable;
|
||||
end
|
||||
end
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// wire assignment
|
||||
//----------------------------------------------------------------------------
|
||||
// 5 unused, 10 used, 1 unused and 4 used signals
|
||||
assign gpio_out = {5'b0, bytestream_direction_fe, bytestream_valid_out_fe, bytestream_data_out_fe, 1'b0, db_state_prc_fe};
|
||||
assign gpio_out_en = {5'b0, 1'b1, {9 {bytestream_output_enable_fe}}, 1'b0, {4 {1'b1}} };
|
||||
|
||||
assign bytestream_valid_in = gpio_in[13];
|
||||
assign bytestream_data_in = gpio_in[12:5];
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// version_info
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Version metadata, constants come from auto-generated versioning_regs_regmap_utils.vh
|
||||
assign version_info = build_component_versions(
|
||||
DB_GPIO_IFC_VERSION_LAST_MODIFIED_TIME,
|
||||
build_version(
|
||||
DB_GPIO_IFC_OLDEST_COMPATIBLE_VERSION_MAJOR,
|
||||
DB_GPIO_IFC_OLDEST_COMPATIBLE_VERSION_MINOR,
|
||||
DB_GPIO_IFC_OLDEST_COMPATIBLE_VERSION_BUILD),
|
||||
build_version(
|
||||
DB_GPIO_IFC_CURRENT_VERSION_MAJOR,
|
||||
DB_GPIO_IFC_CURRENT_VERSION_MINOR,
|
||||
DB_GPIO_IFC_CURRENT_VERSION_BUILD));
|
||||
|
||||
endmodule
|
||||
|
||||
`default_nettype wire
|
||||
|
||||
//XmlParse xml_on
|
||||
//<regmap name="VERSIONING_REGS_REGMAP">
|
||||
// <group name="VERSIONING_CONSTANTS">
|
||||
// <enumeratedtype name="DB_GPIO_IFC_VERSION" showhex="true">
|
||||
// <info>
|
||||
// Daughterboard GPIO interface.{BR/}
|
||||
// For guidance on when to update these revision numbers,
|
||||
// please refer to the register map documentation accordingly:
|
||||
// <li> Current version: @.VERSIONING_REGS_REGMAP..CURRENT_VERSION
|
||||
// <li> Oldest compatible version: @.VERSIONING_REGS_REGMAP..OLDEST_COMPATIBLE_VERSION
|
||||
// <li> Version last modified: @.VERSIONING_REGS_REGMAP..VERSION_LAST_MODIFIED
|
||||
// </info>
|
||||
// <value name="DB_GPIO_IFC_CURRENT_VERSION_MAJOR" integer="1"/>
|
||||
// <value name="DB_GPIO_IFC_CURRENT_VERSION_MINOR" integer="0"/>
|
||||
// <value name="DB_GPIO_IFC_CURRENT_VERSION_BUILD" integer="0"/>
|
||||
// <value name="DB_GPIO_IFC_OLDEST_COMPATIBLE_VERSION_MAJOR" integer="1"/>
|
||||
// <value name="DB_GPIO_IFC_OLDEST_COMPATIBLE_VERSION_MINOR" integer="0"/>
|
||||
// <value name="DB_GPIO_IFC_OLDEST_COMPATIBLE_VERSION_BUILD" integer="0"/>
|
||||
// <value name="DB_GPIO_IFC_VERSION_LAST_MODIFIED_TIME" integer="0x20110616"/>
|
||||
// </enumeratedtype>
|
||||
// </group>
|
||||
//</regmap>
|
||||
//XmlParse xml_off
|
||||
Reference in New Issue
Block a user