fpga: Add X440/FBX support
Co-authored-by: Martin Braun <martin.braun@ettus.com> Co-authored-by: Wade Fife <wade.fife@ni.com> Co-authored-by: Ryan Marlow <ryan@lmarlow.com> Original-commit: 596760a12e4834e47589c12f8a4fd083aa2f7c25
This commit is contained in:
committed by
Aki Tomita
co-authored by
Martin Braun
Wade Fife
Ryan Marlow
parent
a405111ce7
commit
5cadf901c7
@@ -0,0 +1,162 @@
|
||||
//
|
||||
// Copyright 2022 Ettus Research, a National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: clock_en_control
|
||||
//
|
||||
// Description:
|
||||
// Implements control over clock enable. clk_in is always active.
|
||||
// The enable controls whether clk_out is active or not.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// REG_BASE : Base address to use for registers.
|
||||
// REG_SIZE : Register space size.
|
||||
//
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module clock_en_control #(
|
||||
parameter BASE_ADDRESS = 0,
|
||||
parameter REGMAP_SIZE = 8'h4
|
||||
) (
|
||||
// Clock and reset
|
||||
input wire ctrlport_clk,
|
||||
input wire ctrlport_rst,
|
||||
|
||||
// Request
|
||||
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
|
||||
output reg s_ctrlport_resp_ack,
|
||||
output reg [ 1:0] s_ctrlport_resp_status,
|
||||
output reg [31:0] s_ctrlport_resp_data,
|
||||
|
||||
// Clock Enable (domain: ctrlport_clk)
|
||||
input wire clk_in,
|
||||
output wire clk_out
|
||||
);
|
||||
|
||||
`include "../../../../lib/rfnoc/core/ctrlport.vh"
|
||||
`include "regmap/clock_en_regmap_utils.vh"
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// ATR memory signals
|
||||
//---------------------------------------------------------------
|
||||
reg [31:0] clk_ctrl_reg;
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Handling of CtrlPort
|
||||
//---------------------------------------------------------------
|
||||
// Check of request address is targeted for this module.
|
||||
wire address_in_range = (s_ctrlport_req_addr >= BASE_ADDRESS) && (s_ctrlport_req_addr < BASE_ADDRESS + REGMAP_SIZE);
|
||||
|
||||
always @(posedge ctrlport_clk) begin
|
||||
// reset internal registers and responses
|
||||
if (ctrlport_rst) begin
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
s_ctrlport_resp_status <= 2'b0;
|
||||
s_ctrlport_resp_data <= 32'b0;
|
||||
clk_ctrl_reg <= 32'b0;
|
||||
|
||||
end else begin
|
||||
// write requests
|
||||
if (s_ctrlport_req_wr) begin
|
||||
// always issue an ack and no data
|
||||
s_ctrlport_resp_ack <= 1'b1;
|
||||
s_ctrlport_resp_data <= {32{1'bx}};
|
||||
s_ctrlport_resp_status <= CTRL_STS_OKAY;
|
||||
|
||||
case (s_ctrlport_req_addr)
|
||||
BASE_ADDRESS + CLK_EN_CONTROL: begin
|
||||
clk_ctrl_reg <= s_ctrlport_req_data;
|
||||
end
|
||||
|
||||
// error on undefined address
|
||||
default: begin
|
||||
if (address_in_range) begin
|
||||
s_ctrlport_resp_status <= CTRL_STS_CMDERR;
|
||||
|
||||
// no response if out of range
|
||||
end else begin
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
|
||||
//req_rd not delayed
|
||||
end else if (s_ctrlport_req_rd) begin
|
||||
// default assumption: valid request
|
||||
s_ctrlport_resp_ack <= 1'b1;
|
||||
s_ctrlport_resp_status <= CTRL_STS_OKAY;
|
||||
s_ctrlport_resp_data <= {32{1'b0}};
|
||||
|
||||
case (s_ctrlport_req_addr)
|
||||
BASE_ADDRESS + CLK_EN_CONTROL: begin
|
||||
s_ctrlport_resp_data <= clk_ctrl_reg & CLK_EN_CONTROL_MASK;
|
||||
end
|
||||
|
||||
// error on undefined address
|
||||
default: begin
|
||||
if (address_in_range) begin
|
||||
s_ctrlport_resp_status <= CTRL_STS_CMDERR;
|
||||
|
||||
// no response if out of range
|
||||
end else begin
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
|
||||
// no request
|
||||
end else begin
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Clock Enable
|
||||
//---------------------------------------------------------------
|
||||
|
||||
wire clk_en;
|
||||
|
||||
synchronizer synchronizer_i (
|
||||
.clk(clk_in ),
|
||||
.rst(1'b0 ),
|
||||
.in (clk_ctrl_reg[CLK_EN]),
|
||||
.out(clk_en )
|
||||
);
|
||||
|
||||
BUFGCE BUFGCE_i (
|
||||
.O (clk_out),
|
||||
.CE(clk_en ),
|
||||
.I (clk_in )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
`default_nettype wire
|
||||
|
||||
//XmlParse xml_on
|
||||
//<regmap name="CLK_EN_REGMAP" readablestrobes="false" generatevhdl="true" ettusguidelines="true">
|
||||
// <group name="CLK_EN_REGISTERS">
|
||||
// <info>
|
||||
// Clock Enable Register
|
||||
// </info>
|
||||
// <register name="CLK_EN_CONTROL" size="32" offset="0x0" attributes="Readable|Writable">
|
||||
// <info>
|
||||
// This register configures Clock Enable.
|
||||
// </info>
|
||||
// <bitfield name="CLK_EN" range="0" initialvalue="0">
|
||||
// <info>
|
||||
// Enables the Clock.
|
||||
// </info>
|
||||
// </bitfield>
|
||||
// </register>
|
||||
// </group>
|
||||
//</regmap>
|
||||
//XmlParse xml_off
|
||||
@@ -0,0 +1,618 @@
|
||||
//
|
||||
// Copyright 2022 Ettus Research, A National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: ctrlport_to_i2c_sync_ctrl
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// This module wraps a I2C WB master and provides a ControlPort interface
|
||||
// specific to the SYNC IO expander peripheral.
|
||||
// Sync switch control sequence is as follows:
|
||||
// 1. Setup core and IO expander:
|
||||
// a. Write to SETUP_REG
|
||||
// b. Poll/read from SETUP_STATUS_REG until bit SETUP_STATUS == 1
|
||||
// 2. Write sync switch configuration to SYNC_[1-5]_REG and RFS_EN_REG
|
||||
// 3. Initiate io expander config
|
||||
// a. Write to CONFIG_IO_REG
|
||||
// b. Poll/read from CONFIG_IO_STATUS_REG until bit CONFIG_IO_STATUS == 1
|
||||
// Step 1 only needs to happen once after power up or core reset.
|
||||
// Repeat steps 2 and 3 as needed.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// BASE_ADDRESS : Base address for CtrlPort registers.
|
||||
// PRESCALE : Scaling factor to determine clock speed of I2C SCL.
|
||||
// Must be divisible by 5.
|
||||
//
|
||||
|
||||
`default_nettype wire
|
||||
|
||||
module ctrlport_to_i2c_sync_ctrl #(
|
||||
parameter BASE_ADDRESS = 0,
|
||||
parameter [15:0] PRESCALE = 'd500
|
||||
) (
|
||||
//---------------------------------------------------------------
|
||||
// ControlPort Slave
|
||||
//---------------------------------------------------------------
|
||||
|
||||
input wire ctrlport_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,
|
||||
|
||||
output reg s_ctrlport_resp_ack,
|
||||
output reg [ 1:0] s_ctrlport_resp_status = 2'b0,
|
||||
output reg [31:0] s_ctrlport_resp_data = 32'b0,
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// I2C signals
|
||||
//---------------------------------------------------------------
|
||||
// i2c clock line
|
||||
input wire scl_pad_i, // SCL-line input
|
||||
output wire scl_pad_o, // SCL-line output
|
||||
output wire scl_pad_en_o, // SCL-line output enable (active low)
|
||||
|
||||
// i2c data line
|
||||
input wire sda_pad_i, // SDA-line input
|
||||
output wire sda_pad_o, // SDA-line output
|
||||
output wire sda_pad_en_o // SDA-line output enable (active low)
|
||||
);
|
||||
|
||||
`include "../../../../lib/rfnoc/core/ctrlport.vh"
|
||||
`include "../../../../lib/wishbone/i2c_master.vh"
|
||||
`include "./regmap/rf_sync_regmap_utils.vh"
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// CtrlPort Interface Regs and Triggers to Initiate I2C
|
||||
//---------------------------------------------------------------
|
||||
reg [2:0] sync1, sync2, sync3, sync4, sync5;
|
||||
reg rfs_en;
|
||||
reg setup_trig; // initiate setup
|
||||
reg config_io_trig; // configure IO
|
||||
reg setup_finished;
|
||||
reg setup_finished_hold;
|
||||
reg config_io_finished;
|
||||
reg config_io_finished_hold;
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// WishBone interface
|
||||
//---------------------------------------------------------------
|
||||
reg wb_cyc_i; // Active bus cycle
|
||||
reg wb_we_i = 1'b0; // Write access
|
||||
reg [2:0] wb_adr_i = 3'b0;
|
||||
reg [7:0] wb_dat_i = 8'b0;
|
||||
wire wb_ack_o;
|
||||
wire [7:0] wb_dat_o;
|
||||
|
||||
// Check for address to be in range [base_addr..base_addr+32)
|
||||
localparam NUM_ADDRESSES = 32;
|
||||
wire address_in_range = (s_ctrlport_req_addr >= BASE_ADDRESS) &&
|
||||
(s_ctrlport_req_addr < BASE_ADDRESS + NUM_ADDRESSES);
|
||||
|
||||
// The scaling factor (PRESCALE) of the input clock (ctrlport_clk) to SCL
|
||||
// isn't direct but instead the relationship between the input clock and
|
||||
// the state machine inside the i2c_master that controls SCL.
|
||||
// This state machine has 5 repeated stages per SCL clock cycle so
|
||||
// the scaling is divided by a factor of 5. The division here
|
||||
// obscures a need for the user to do an extra step to calculate the
|
||||
// PRESCALE parameter.
|
||||
// For example, if a user wants to have an actual rescaling of 1:500
|
||||
// (SCL to ctrlpor_clk), the PRESCALE parameter is divided by 5
|
||||
// here so the i2c_master prescale value is set to 100.
|
||||
if (PRESCALE % 5 != 0) begin : gen_assertion
|
||||
ERROR_PRESCALE_must_be_div_by_5();
|
||||
end
|
||||
|
||||
// constants to configure wb i2c master core
|
||||
localparam PRESCALE_5 = PRESCALE/5;
|
||||
localparam PRER_LO_CONST = PRESCALE_5[7:0];
|
||||
localparam PRER_HI_CONST = PRESCALE_5[15:8];
|
||||
|
||||
//constants for interfacing with i2c master core
|
||||
localparam I2C_WR = 1'b0;
|
||||
localparam I2C_RD = 1'b1;
|
||||
localparam SYNC_IO_SLV_ADR = 7'h20;
|
||||
|
||||
// CtrlPort Interface
|
||||
// configure sync switch IO and trigger I2C transactions
|
||||
always @(posedge ctrlport_clk) begin
|
||||
// Reset internal registers and responses
|
||||
if (ctrlport_rst) begin
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
s_ctrlport_resp_status <= 2'b0;
|
||||
s_ctrlport_resp_data <= 32'b0;
|
||||
setup_trig <= 1'b0;
|
||||
config_io_trig <= 1'b0;
|
||||
setup_finished_hold <= 1'b0;
|
||||
config_io_finished_hold <= 1'b0;
|
||||
sync1 <= 3'b0;
|
||||
sync2 <= 3'b0;
|
||||
sync3 <= 3'b0;
|
||||
sync4 <= 3'b0;
|
||||
sync5 <= 3'b0;
|
||||
rfs_en <= 1'b0;
|
||||
end else begin
|
||||
// Only ack under certain conditions
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
if (setup_finished) begin
|
||||
setup_finished_hold <= 1'b1;
|
||||
end
|
||||
if (config_io_finished) begin
|
||||
config_io_finished_hold <= 1'b1;
|
||||
end
|
||||
if (s_ctrlport_req_wr) begin // Write requests
|
||||
// if address is normal ctrlport, immediately ack
|
||||
if (address_in_range) begin
|
||||
s_ctrlport_resp_ack <= 1'b1;
|
||||
s_ctrlport_resp_status <= CTRL_STS_OKAY;
|
||||
end
|
||||
case (s_ctrlport_req_addr)
|
||||
BASE_ADDRESS + SYNC_1_REG: begin
|
||||
sync1 <= s_ctrlport_req_data[2:0];
|
||||
end
|
||||
|
||||
BASE_ADDRESS + SYNC_2_REG: begin
|
||||
sync2 <= s_ctrlport_req_data[2:0];
|
||||
end
|
||||
|
||||
BASE_ADDRESS + SYNC_3_REG: begin
|
||||
sync3 <= s_ctrlport_req_data[2:0];
|
||||
end
|
||||
|
||||
BASE_ADDRESS + SYNC_4_REG: begin
|
||||
sync4 <= s_ctrlport_req_data[2:0];
|
||||
end
|
||||
|
||||
BASE_ADDRESS + SYNC_5_REG: begin
|
||||
sync5 <= s_ctrlport_req_data[2:0];
|
||||
end
|
||||
|
||||
BASE_ADDRESS + RFS_EN_REG: begin
|
||||
rfs_en <= s_ctrlport_req_data[0];
|
||||
end
|
||||
//initialize SYNC_IO peripheral
|
||||
BASE_ADDRESS + SETUP_REG: begin
|
||||
setup_trig <= 1'b1;
|
||||
setup_finished_hold <= 1'b0;
|
||||
end
|
||||
//configure IO
|
||||
BASE_ADDRESS + CONFIG_IO_REG: begin
|
||||
config_io_trig <= 1'b1;
|
||||
config_io_finished_hold <= 1'b0;
|
||||
end
|
||||
endcase
|
||||
|
||||
// Read requests
|
||||
end else if (s_ctrlport_req_rd) begin
|
||||
// Acknowledge by default
|
||||
if (address_in_range) begin
|
||||
s_ctrlport_resp_ack <= 1'b1;
|
||||
s_ctrlport_resp_status <= CTRL_STS_OKAY;
|
||||
end
|
||||
case (s_ctrlport_req_addr)
|
||||
BASE_ADDRESS + SYNC_1_REG: begin
|
||||
s_ctrlport_resp_data[2:0] <= sync1;
|
||||
end
|
||||
BASE_ADDRESS + SYNC_2_REG: begin
|
||||
s_ctrlport_resp_data[2:0] <= sync2;
|
||||
end
|
||||
BASE_ADDRESS + SYNC_3_REG: begin
|
||||
s_ctrlport_resp_data[2:0] <= sync3;
|
||||
end
|
||||
BASE_ADDRESS + SYNC_4_REG: begin
|
||||
s_ctrlport_resp_data[2:0] <= sync4;
|
||||
end
|
||||
BASE_ADDRESS + SYNC_5_REG: begin
|
||||
s_ctrlport_resp_data[2:0] <= sync5;
|
||||
end
|
||||
BASE_ADDRESS + RFS_EN_REG: begin
|
||||
s_ctrlport_resp_data[2:0] <= {2'b00, rfs_en};
|
||||
end
|
||||
BASE_ADDRESS + SETUP_STATUS_REG: begin
|
||||
s_ctrlport_resp_data[2:0] <= {2'b00, setup_finished_hold};
|
||||
if(setup_finished_hold) begin
|
||||
setup_trig <= 1'b0;
|
||||
end
|
||||
end
|
||||
BASE_ADDRESS + CONFIG_IO_STATUS_REG: begin
|
||||
s_ctrlport_resp_data[2:0] <= {2'b00, config_io_finished_hold};
|
||||
if(config_io_finished_hold) begin
|
||||
config_io_trig <= 1'b0;
|
||||
end
|
||||
end
|
||||
// Respond with 0
|
||||
default: begin
|
||||
if (address_in_range) begin
|
||||
s_ctrlport_resp_status <= CTRL_STS_CMDERR;
|
||||
end
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
s_ctrlport_resp_data <= 32'b0;
|
||||
end
|
||||
endcase
|
||||
// No request
|
||||
end else begin
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
end
|
||||
end
|
||||
end // always
|
||||
|
||||
// state machine for I2C Write Transactions and WB Controls
|
||||
localparam I2C_IDLE = 0;
|
||||
localparam I2C_PRE_LO = 1;
|
||||
localparam I2C_PRE_HI = 2;
|
||||
localparam I2C_EN = 3;
|
||||
localparam I2C_TXR = 4;
|
||||
localparam I2C_CR = 5;
|
||||
localparam I2C_TIP_START = 6;
|
||||
localparam I2C_TIP = 7;
|
||||
localparam I2C_TIP_FIN = 8;
|
||||
|
||||
reg i2c_tip_fin; // indicates transfer is finished
|
||||
reg i2c_master_en; // indicates i2c master setup and enabled
|
||||
reg [3:0] i2c_state;
|
||||
wire wb_cyc_valid; // determines what states wb_cyc_i should be high
|
||||
reg i2c_wr; //trigger an i2c wr cmd
|
||||
reg i2c_core_setup; //trigger i2c master setup
|
||||
reg [7:0] wb_txr;
|
||||
reg [7:0] wb_cr;
|
||||
|
||||
assign wb_cyc_valid = (i2c_state >= I2C_PRE_LO ) && (i2c_state < I2C_TIP_FIN);
|
||||
|
||||
always @(posedge ctrlport_clk) begin
|
||||
if (ctrlport_rst) begin
|
||||
i2c_state <= I2C_IDLE;
|
||||
wb_cyc_i <= 1'b0;
|
||||
wb_we_i <= 1'b0;
|
||||
wb_adr_i <= 3'b0;
|
||||
wb_dat_i <= 8'b0;
|
||||
i2c_tip_fin <= 1'b0;
|
||||
i2c_master_en <= 1'b0;
|
||||
//more regs need to be set here.
|
||||
end
|
||||
else begin
|
||||
//handle wb_cyc_i for all states. dependent on i2c transaction states
|
||||
//and wb_ack_o
|
||||
if (wb_cyc_i) begin
|
||||
if (wb_ack_o) begin
|
||||
wb_cyc_i <= 1'b0;
|
||||
end
|
||||
end else begin
|
||||
if (wb_cyc_valid) begin
|
||||
wb_cyc_i <= 1'b1;
|
||||
end
|
||||
end
|
||||
case(i2c_state)
|
||||
I2C_IDLE: begin
|
||||
i2c_tip_fin <= 1'b0;
|
||||
if (i2c_wr) begin
|
||||
i2c_state <= I2C_TXR;
|
||||
end
|
||||
else if (i2c_core_setup) begin
|
||||
i2c_state <= I2C_PRE_LO;
|
||||
end
|
||||
end //I2C_IDLE
|
||||
//begin cases to setup i2c master core
|
||||
I2C_PRE_LO: begin
|
||||
wb_adr_i <= WB_PRER_LO;
|
||||
wb_dat_i <= PRER_LO_CONST;
|
||||
wb_we_i <= 1'b1;
|
||||
if (wb_ack_o) begin
|
||||
i2c_state <= I2C_PRE_HI;
|
||||
end
|
||||
end
|
||||
I2C_PRE_HI: begin
|
||||
wb_adr_i <= WB_PRER_HI;
|
||||
wb_dat_i <= PRER_HI_CONST;
|
||||
wb_we_i <= 1'b1;
|
||||
if (wb_ack_o) begin
|
||||
i2c_state <= I2C_EN;
|
||||
end
|
||||
end
|
||||
I2C_EN: begin
|
||||
wb_adr_i <= WB_CTR;
|
||||
wb_dat_i <= WB_CORE_EN;
|
||||
wb_we_i <= 1'b1;
|
||||
i2c_master_en <= 1'b1;
|
||||
if (wb_ack_o) begin
|
||||
i2c_state <= I2C_IDLE;
|
||||
end
|
||||
end
|
||||
//end cases to setup i2c master core
|
||||
//begin cases to initiate i2c write transfer
|
||||
I2C_TXR: begin
|
||||
wb_adr_i <= WB_TXR;
|
||||
wb_dat_i <= wb_txr;
|
||||
wb_we_i <= 1'b1;
|
||||
if (wb_ack_o) begin
|
||||
i2c_state <= I2C_CR;
|
||||
end
|
||||
end
|
||||
I2C_CR: begin
|
||||
wb_adr_i <= WB_CR;
|
||||
wb_dat_i <= wb_cr;
|
||||
wb_we_i <= 1'b1;
|
||||
if (wb_ack_o) begin
|
||||
i2c_state <= I2C_TIP_START;
|
||||
end
|
||||
end
|
||||
I2C_TIP_START: begin
|
||||
wb_adr_i <= WB_SR;
|
||||
wb_dat_i <= 8'b0;
|
||||
wb_we_i <= 1'b0;
|
||||
if (wb_ack_o && wb_dat_o[1]) begin
|
||||
i2c_state <= I2C_TIP;
|
||||
end
|
||||
end
|
||||
I2C_TIP: begin //TIP transfer in progress
|
||||
wb_adr_i <= WB_SR;
|
||||
wb_dat_i <= 8'b0;
|
||||
wb_we_i <= 1'b0;
|
||||
if (wb_ack_o && !wb_dat_o[1]) begin
|
||||
i2c_state <= I2C_TIP_FIN;
|
||||
i2c_tip_fin <= 1'b1; //pulse this as we transition to final state
|
||||
end
|
||||
end
|
||||
I2C_TIP_FIN: begin
|
||||
i2c_tip_fin <= 1'b0;
|
||||
if (!i2c_wr) begin
|
||||
i2c_state <= I2C_IDLE;
|
||||
end
|
||||
end
|
||||
//end cases to initiate i2c write transfer
|
||||
//default case, just go to I2C_IDLE
|
||||
default : begin
|
||||
i2c_state <= I2C_IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end //always
|
||||
|
||||
|
||||
|
||||
// i2c master top controller state machine
|
||||
localparam IDLE = 0;
|
||||
localparam EN = 1;
|
||||
localparam IO_EXP_CONFIG_1 = 2;
|
||||
localparam IO_EXP_CONFIG_2 = 3;
|
||||
localparam IO_EXP_CONFIG_3 = 4;
|
||||
localparam IO_EXP_CONFIG_4 = 5;
|
||||
localparam IO_EXP_FIN = 6;
|
||||
|
||||
wire [15:0] io_config;
|
||||
assign io_config = { rfs_en, sync5, sync4, sync3, sync2, sync1 };
|
||||
reg [2:0] master_state;
|
||||
always @(posedge ctrlport_clk) begin
|
||||
if (ctrlport_rst) begin
|
||||
master_state <= IDLE;
|
||||
wb_txr <= 8'b0;
|
||||
wb_cr <= 8'b0;
|
||||
i2c_wr <= 1'b0;
|
||||
setup_finished <= 1'b0;
|
||||
config_io_finished <= 1'b0;
|
||||
i2c_core_setup <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
case(master_state)
|
||||
IDLE: begin
|
||||
i2c_wr <= 1'b0;
|
||||
setup_finished <= 1'b0;
|
||||
config_io_finished <= 1'b0;
|
||||
i2c_core_setup <= 1'b0;
|
||||
if (setup_trig) begin
|
||||
master_state <= EN;
|
||||
end
|
||||
else if (config_io_trig) begin
|
||||
master_state <= IO_EXP_CONFIG_1;
|
||||
end
|
||||
end
|
||||
EN: begin //all the prescale and enable setup happens in i2c_state machine
|
||||
i2c_core_setup <= 1'b1; //triggers setup sequence in i2c state machine.
|
||||
i2c_wr <= 1'b0;
|
||||
if (i2c_master_en) begin //indicates setup sequence finished
|
||||
master_state <= IO_EXP_CONFIG_1;
|
||||
end
|
||||
end
|
||||
IO_EXP_CONFIG_1: begin //first stage of setting up IO EXP with startup configurations
|
||||
wb_txr <= { SYNC_IO_SLV_ADR, I2C_WR};
|
||||
wb_cr <= CR_START_AND_WRITE;
|
||||
if (i2c_tip_fin) begin //when transfer is done, i2c_wr is disabled
|
||||
i2c_wr <= 1'b0;
|
||||
master_state <= IO_EXP_CONFIG_2;
|
||||
end else begin
|
||||
i2c_wr <= 1'b1;
|
||||
end
|
||||
end
|
||||
IO_EXP_CONFIG_2: begin
|
||||
if (setup_trig) begin
|
||||
wb_txr <= IO_EXP_CONFIG0_REG; //CONFIG0 reg is what we set to configure I/O as output
|
||||
end else if (config_io_trig) begin
|
||||
wb_txr <= IO_EXP_OUTPUT_PORT0_REG;
|
||||
end
|
||||
wb_cr <= CR_WRITE;
|
||||
if (i2c_tip_fin) begin //when transfer is done, i2c_wr is disabled
|
||||
i2c_wr <= 1'b0;
|
||||
master_state <= IO_EXP_CONFIG_3;
|
||||
end else begin
|
||||
i2c_wr <= 1'b1;
|
||||
end
|
||||
end
|
||||
IO_EXP_CONFIG_3: begin
|
||||
if (setup_trig) begin
|
||||
wb_txr <= 1'b0;
|
||||
end else if (config_io_trig) begin
|
||||
wb_txr <= io_config[7:0];
|
||||
end
|
||||
wb_cr <= CR_WRITE;
|
||||
if (i2c_tip_fin) begin //when transfer is done, i2c_wr is disabled
|
||||
i2c_wr <= 1'b0;
|
||||
master_state <= IO_EXP_CONFIG_4;
|
||||
end else begin
|
||||
i2c_wr <= 1'b1;
|
||||
end
|
||||
end
|
||||
IO_EXP_CONFIG_4: begin
|
||||
if (setup_trig) begin
|
||||
wb_txr <= 1'b0;
|
||||
end else if (config_io_trig) begin
|
||||
wb_txr <= io_config[15:8];
|
||||
end
|
||||
wb_cr <= CR_WRITE_AND_STOP;
|
||||
if (i2c_tip_fin) begin //when transfer is done, i2c_wr is disabled
|
||||
i2c_wr <= 1'b0;
|
||||
setup_finished <= setup_trig;
|
||||
config_io_finished <= config_io_trig;
|
||||
master_state <= IO_EXP_FIN;
|
||||
end else begin
|
||||
i2c_wr <= 1'b1;
|
||||
end
|
||||
end
|
||||
IO_EXP_FIN : begin //final state to make sure triggers are unset before returning to IDLE;
|
||||
i2c_wr <= 1'b0;
|
||||
setup_finished <= 1'b0;
|
||||
config_io_finished <= 1'b0;
|
||||
if (!setup_trig && !config_io_trig) begin
|
||||
master_state <= IDLE;
|
||||
end
|
||||
end
|
||||
default : begin
|
||||
master_state <= IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end //always
|
||||
|
||||
//wishbone-based i2c core
|
||||
i2c_master_top #(
|
||||
.ARST_LVL(1)
|
||||
) i2c_master (
|
||||
.wb_clk_i(ctrlport_clk),
|
||||
.wb_rst_i(ctrlport_rst),
|
||||
.arst_i(1'b0),
|
||||
.wb_adr_i(wb_adr_i),
|
||||
.wb_dat_i(wb_dat_i),
|
||||
.wb_dat_o(wb_dat_o),
|
||||
.wb_we_i(wb_we_i),
|
||||
.wb_stb_i(wb_cyc_i),
|
||||
.wb_cyc_i(wb_cyc_i),
|
||||
.wb_ack_o(wb_ack_o),
|
||||
.wb_inta_o(),
|
||||
.scl_pad_i(scl_pad_i),
|
||||
.scl_pad_o(scl_pad_o),
|
||||
.scl_padoen_o(scl_pad_en_o),
|
||||
.sda_pad_i(sda_pad_i),
|
||||
.sda_pad_o(sda_pad_o),
|
||||
.sda_padoen_o(sda_pad_en_o)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
//XmlParse xml_on
|
||||
//<regmap name="RF_SYNC_REGMAP" readablestrobes="false" generatevhdl="true" ettusguidelines="true">
|
||||
// <group name="RF_SYNC_REGISTERS">
|
||||
// <info>
|
||||
// Each channel in the FBX daughterboard has 4 switches in its path. 3 of these are HMC849A 2:1
|
||||
// switches and the last one is a PE42442 4:1 switch. The latter, as well as the enable lines for
|
||||
// all four switches are not considered time critical controls, and are hence driven by a
|
||||
// TCA6416A I/O expander controlled via I2C.
|
||||
// This register map controls that I/O expander. The first 6 registers in
|
||||
// this space set the values of the 5 3-pin sync switches and then an
|
||||
// RFS enable bit. The 2 additional registers trigger a init sequence for
|
||||
// the expander peripheral and configuring the I/O with the contents of
|
||||
// the value registers both with a series of I2C commands.
|
||||
// </info>
|
||||
// <regtype name="SYNC_SWITCH" size="32" attributes="Readable|Writable">
|
||||
// <info>
|
||||
// Sets I/O to control Sync Switch.
|
||||
// </info>
|
||||
// <bitfield name="CONTROL_PIN_V1" range="0" initialvalue="0"/>
|
||||
// <bitfield name="CONTROL_PIN_V2" range="1" initialvalue="0"/>
|
||||
// <bitfield name="CONTROL_PIN_V3" range="2" initialvalue="0"/>
|
||||
// </regtype>
|
||||
// <register name="SYNC_1_REG" offset="0x00" typename="SYNC_SWITCH">
|
||||
// <info>
|
||||
// Sets I/O state to control Sync Switch 1.
|
||||
// </info>
|
||||
// </register>
|
||||
// <register name="SYNC_2_REG" offset="0x04" typename="SYNC_SWITCH">
|
||||
// <info>
|
||||
// Sets I/O state to control Sync Switch 2.
|
||||
// </info>
|
||||
// </register>
|
||||
// <register name="SYNC_3_REG" offset="0x08" typename="SYNC_SWITCH">
|
||||
// <info>
|
||||
// Sets I/O state to control Sync Switch 3.
|
||||
// </info>
|
||||
// </register>
|
||||
// <register name="SYNC_4_REG" offset="0x0C" typename="SYNC_SWITCH">
|
||||
// <info>
|
||||
// Sets I/O state to control Sync Switch 4.
|
||||
// </info>
|
||||
// </register>
|
||||
// <register name="SYNC_5_REG" offset="0x10" typename="SYNC_SWITCH">
|
||||
// <info>
|
||||
// Sets I/O state to control Sync Switch 5.
|
||||
// </info>
|
||||
// </register>
|
||||
// <register name="RFS_EN_REG" offset="0x014" size="32" attributes="Readable|Writable">
|
||||
// <info>
|
||||
// Sets I/O state to control RFS Enable.
|
||||
// </info>
|
||||
// <bitfield name="RFS_EN_PIN" range="0" initialvalue="0" />
|
||||
// </register>
|
||||
// <register name="SETUP_REG" offset="0x18" size="32" attributes="Writable">
|
||||
// <info>
|
||||
// Write to this register to trigger initialization sequence of
|
||||
// I2C Master core and TCA6416A I/O expander peripheral.
|
||||
// </info>
|
||||
// <bitfield name="SETUP_TRIG" range="0" initialvalue="0"/>
|
||||
// </register>
|
||||
// <register name="SETUP_STATUS_REG" offset="0x18" size="32" attributes="Readable">
|
||||
// <info>
|
||||
// Read from this register to check the status of setup.
|
||||
// </info>
|
||||
// <bitfield name="SETUP_STATUS" range="0" initialvalue="0"/>
|
||||
// </register>
|
||||
// <register name="CONFIG_IO_REG" offset="0x1C" size="32" attributes="Writable">
|
||||
// <info>
|
||||
// Write to this register to trigger I/O configuration I2C sequence of
|
||||
// TCA6416A I/O expander peripheral.
|
||||
// Read from this register to check the status of reconfiguring the setup.
|
||||
// </info>
|
||||
// <bitfield name="CONFIG_IO_TRIG" range="0" initialvalue="0"/>
|
||||
// </register>
|
||||
// <register name="CONFIG_IO_STATUS_REG" offset="0x1C" size="32" attributes="Readable">
|
||||
// <info>
|
||||
// Read from this register to check the status of reconfiguring the setup.
|
||||
// </info>
|
||||
// <bitfield name="CONFIG_IO_STATUS" range="0" initialvalue="0"/>
|
||||
// </register>
|
||||
//
|
||||
// <enumeratedtype name="IO_EXPANDER_REGISTER_ADRS">
|
||||
// <info>
|
||||
// This is not a register spaces for this ctrlport interface but
|
||||
// instead register addresses on the TCA6416A. Therefore, we will just
|
||||
// define an enum with these addresses so there is no clash with the
|
||||
// above ctrlport regmap.
|
||||
// </info>
|
||||
// <value name="IO_EXP_INPUT_PORT0_REG" integer="0"/>
|
||||
// <value name="IO_EXP_INPUT_PORT1_REG" integer="1"/>
|
||||
// <value name="IO_EXP_OUTPUT_PORT0_REG" integer="2"/>
|
||||
// <value name="IO_EXP_OUTPUT_PORT1_REG" integer="3"/>
|
||||
// <value name="IO_EXP_POLARITY_INV0_REG" integer="4"/>
|
||||
// <value name="IO_EXP_POLARITY_INV1_REG" integer="5"/>
|
||||
// <value name="IO_EXP_CONFIG0_REG" integer="6"/>
|
||||
// <value name="IO_EXP_CONFIG1_REG" integer="7"/>
|
||||
// </enumeratedtype>
|
||||
// </group>
|
||||
//</regmap>
|
||||
|
||||
//XmlParse xml_off
|
||||
|
||||
@@ -0,0 +1,444 @@
|
||||
//
|
||||
// Copyright 2022 Ettus Research, a National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: db_gpio_interface
|
||||
//
|
||||
// Description:
|
||||
// Interface for GPIO interface towards FBX daughterboards.
|
||||
//
|
||||
//
|
||||
// The 20 available GPIO lines are assigned with
|
||||
// - 12x RF switches(3x per channel)
|
||||
// - 2x I2C to Sync switches IO Expander
|
||||
// - 6x empty
|
||||
//
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module db_gpio_interface #(
|
||||
parameter LED_REGISTER_ADDRESS = 0
|
||||
) (
|
||||
// Clocks and reset
|
||||
input wire radio_clk,
|
||||
input wire pll_ref_clk,
|
||||
input wire in_sync_clk,
|
||||
output wire out_sync_clk,
|
||||
|
||||
// DB state lines (domain: radio_clk)
|
||||
input wire [ 7: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,
|
||||
|
||||
// ControlPort request to CPLD (domain: radio_clk)
|
||||
output wire m_ctrlport_req_wr,
|
||||
output wire m_ctrlport_req_rd,
|
||||
output wire [19:0] m_ctrlport_req_addr,
|
||||
output wire [31:0] m_ctrlport_req_data,
|
||||
output wire [ 3:0] m_ctrlport_req_byte_en,
|
||||
|
||||
// ControlPort response from CPLD (domain: radio_clk)
|
||||
input wire m_ctrlport_resp_ack,
|
||||
input wire [ 1:0] m_ctrlport_resp_status,
|
||||
input wire [31:0] m_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/x440/versioning_regs_regmap_utils.vh"
|
||||
`include "regmap/fbx_ctrl_regmap_utils.vh"
|
||||
`include "../../regmap/versioning_utils.vh"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Radio_clk -> pll_ref_clk clock crossing
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
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_cross core_clk_cross_slave (
|
||||
.rst (ctrlport_rst),
|
||||
.s_ctrlport_clk (radio_clk),
|
||||
.s_ctrlport_req_wr (s_ctrlport_req_wr),
|
||||
.s_ctrlport_req_rd (s_ctrlport_req_rd),
|
||||
.s_ctrlport_req_addr (s_ctrlport_req_addr),
|
||||
.s_ctrlport_req_portid (),
|
||||
.s_ctrlport_req_rem_epid (),
|
||||
.s_ctrlport_req_rem_portid (),
|
||||
.s_ctrlport_req_data (s_ctrlport_req_data),
|
||||
.s_ctrlport_req_byte_en (),
|
||||
.s_ctrlport_req_has_time (),
|
||||
.s_ctrlport_req_time (),
|
||||
.s_ctrlport_resp_ack (s_ctrlport_resp_ack),
|
||||
.s_ctrlport_resp_status (s_ctrlport_resp_status),
|
||||
.s_ctrlport_resp_data (s_ctrlport_resp_data),
|
||||
.m_ctrlport_clk (pll_ref_clk),
|
||||
.m_ctrlport_req_wr (ctrlport_req_wr_prc),
|
||||
.m_ctrlport_req_rd (ctrlport_req_rd_prc),
|
||||
.m_ctrlport_req_addr (ctrlport_req_addr_prc),
|
||||
.m_ctrlport_req_portid (),
|
||||
.m_ctrlport_req_rem_epid (),
|
||||
.m_ctrlport_req_rem_portid (),
|
||||
.m_ctrlport_req_data (ctrlport_req_data_prc),
|
||||
.m_ctrlport_req_byte_en (),
|
||||
.m_ctrlport_req_has_time (),
|
||||
.m_ctrlport_req_time (),
|
||||
.m_ctrlport_resp_ack (ctrlport_resp_ack_prc),
|
||||
.m_ctrlport_resp_status (ctrlport_resp_status_prc),
|
||||
.m_ctrlport_resp_data (ctrlport_resp_data_prc)
|
||||
);
|
||||
|
||||
reset_sync reset_sync_prc (
|
||||
.clk (pll_ref_clk),
|
||||
.reset_in (ctrlport_rst),
|
||||
.reset_out (ctrlport_rst_prc)
|
||||
);
|
||||
|
||||
wire [7:0] db_state_prc;
|
||||
|
||||
handshake #(
|
||||
.WIDTH (8)
|
||||
) synchronizer_db_state (
|
||||
.clk_a (radio_clk),
|
||||
.rst_a (ctrlport_rst),
|
||||
.valid_a (1'b1),
|
||||
.data_a (db_state),
|
||||
.busy_a (),
|
||||
.clk_b (pll_ref_clk),
|
||||
.valid_b (),
|
||||
.data_b (db_state_prc)
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// CtrlPort Splitter
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
wire [19:0] rf_atr_ctrlport_req_addr;
|
||||
wire [31:0] rf_atr_ctrlport_req_data;
|
||||
wire rf_atr_ctrlport_req_rd;
|
||||
wire rf_atr_ctrlport_req_wr;
|
||||
wire rf_atr_ctrlport_resp_ack;
|
||||
wire [31:0] rf_atr_ctrlport_resp_data;
|
||||
wire [ 1:0] rf_atr_ctrlport_resp_status;
|
||||
|
||||
wire [19:0] sync_ctrlport_req_addr;
|
||||
wire [31:0] sync_ctrlport_req_data;
|
||||
wire sync_ctrlport_req_rd;
|
||||
wire sync_ctrlport_req_wr;
|
||||
wire sync_ctrlport_resp_ack;
|
||||
wire [31:0] sync_ctrlport_resp_data;
|
||||
wire [ 1:0] sync_ctrlport_resp_status;
|
||||
|
||||
wire [19:0] led_atr_ctrlport_req_addr;
|
||||
wire [31:0] led_atr_ctrlport_req_data;
|
||||
wire led_atr_ctrlport_req_rd;
|
||||
wire led_atr_ctrlport_req_wr;
|
||||
wire led_atr_ctrlport_resp_ack;
|
||||
wire [31:0] led_atr_ctrlport_resp_data;
|
||||
wire [ 1:0] led_atr_ctrlport_resp_status;
|
||||
|
||||
wire [19:0] clk_en_ctrlport_req_addr;
|
||||
wire [31:0] clk_en_ctrlport_req_data;
|
||||
wire clk_en_ctrlport_req_rd;
|
||||
wire clk_en_ctrlport_req_wr;
|
||||
wire clk_en_ctrlport_resp_ack;
|
||||
wire [31:0] clk_en_ctrlport_resp_data;
|
||||
wire [ 1:0] clk_en_ctrlport_resp_status;
|
||||
|
||||
ctrlport_splitter #(
|
||||
.NUM_SLAVES (4)
|
||||
) fbx_ctrlport_splitter (
|
||||
.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_req_byte_en (4'hF),
|
||||
.s_ctrlport_req_has_time (1'b0),
|
||||
.s_ctrlport_req_time (64'b0),
|
||||
.s_ctrlport_resp_ack (ctrlport_resp_ack_prc),
|
||||
.s_ctrlport_resp_status (ctrlport_resp_status_prc),
|
||||
.s_ctrlport_resp_data (ctrlport_resp_data_prc),
|
||||
.m_ctrlport_req_wr ({ clk_en_ctrlport_req_wr, led_atr_ctrlport_req_wr, sync_ctrlport_req_wr, rf_atr_ctrlport_req_wr }),
|
||||
.m_ctrlport_req_rd ({ clk_en_ctrlport_req_rd, led_atr_ctrlport_req_rd, sync_ctrlport_req_rd, rf_atr_ctrlport_req_rd }),
|
||||
.m_ctrlport_req_addr ({ clk_en_ctrlport_req_addr, led_atr_ctrlport_req_addr, sync_ctrlport_req_addr, rf_atr_ctrlport_req_addr }),
|
||||
.m_ctrlport_req_data ({ clk_en_ctrlport_req_data, led_atr_ctrlport_req_data, sync_ctrlport_req_data, rf_atr_ctrlport_req_data }),
|
||||
.m_ctrlport_req_byte_en (),
|
||||
.m_ctrlport_req_has_time (),
|
||||
.m_ctrlport_req_time (),
|
||||
.m_ctrlport_resp_ack ({ clk_en_ctrlport_resp_ack, led_atr_ctrlport_resp_ack, sync_ctrlport_resp_ack, rf_atr_ctrlport_resp_ack }),
|
||||
.m_ctrlport_resp_status ({ clk_en_ctrlport_resp_status, led_atr_ctrlport_resp_status, sync_ctrlport_resp_status, rf_atr_ctrlport_resp_status }),
|
||||
.m_ctrlport_resp_data ({ clk_en_ctrlport_resp_data, led_atr_ctrlport_resp_data, sync_ctrlport_resp_data, rf_atr_ctrlport_resp_data })
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Switch Control
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
wire rf0_tx_rx_rfs, rf0_rx_rfs, rf0_tdds;
|
||||
wire rf1_tx_rx_rfs, rf1_rx_rfs, rf1_tdds;
|
||||
wire rf2_tx_rx_rfs, rf2_rx_rfs, rf2_tdds;
|
||||
wire rf3_tx_rx_rfs, rf3_rx_rfs, rf3_tdds;
|
||||
|
||||
rf_atr_control #(
|
||||
.REG_BASE (RF_ATR_REGS),
|
||||
.REG_SIZE (RF_ATR_REGS_SIZE)
|
||||
) rf_atr_control_i (
|
||||
.ctrlport_clk (pll_ref_clk),
|
||||
.ctrlport_rst (ctrlport_rst_prc),
|
||||
.s_ctrlport_req_wr (rf_atr_ctrlport_req_wr),
|
||||
.s_ctrlport_req_rd (rf_atr_ctrlport_req_rd),
|
||||
.s_ctrlport_req_addr (rf_atr_ctrlport_req_addr),
|
||||
.s_ctrlport_req_data (rf_atr_ctrlport_req_data),
|
||||
.s_ctrlport_resp_ack (rf_atr_ctrlport_resp_ack),
|
||||
.s_ctrlport_resp_status (rf_atr_ctrlport_resp_status),
|
||||
.s_ctrlport_resp_data (rf_atr_ctrlport_resp_data),
|
||||
.db_state (db_state_prc),
|
||||
.rf0_tx_rx_rfs (rf0_tx_rx_rfs),
|
||||
.rf0_rx_rfs (rf0_rx_rfs),
|
||||
.rf0_tdds (rf0_tdds),
|
||||
.rf1_tx_rx_rfs (rf1_tx_rx_rfs),
|
||||
.rf1_rx_rfs (rf1_rx_rfs),
|
||||
.rf1_tdds (rf1_tdds),
|
||||
.rf2_tx_rx_rfs (rf2_tx_rx_rfs),
|
||||
.rf2_rx_rfs (rf2_rx_rfs),
|
||||
.rf2_tdds (rf2_tdds),
|
||||
.rf3_tx_rx_rfs (rf3_tx_rx_rfs),
|
||||
.rf3_rx_rfs (rf3_rx_rfs),
|
||||
.rf3_tdds (rf3_tdds)
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// LED Control
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
wire cpld_ctrlport_req_wr;
|
||||
wire cpld_ctrlport_req_rd;
|
||||
wire [19:0] cpld_ctrlport_req_addr;
|
||||
wire [31:0] cpld_ctrlport_req_data;
|
||||
wire [ 3:0] cpld_ctrlport_req_byte_en;
|
||||
|
||||
wire cpld_ctrlport_resp_ack;
|
||||
wire [ 1:0] cpld_ctrlport_resp_status;
|
||||
wire [31:0] cpld_ctrlport_resp_data;
|
||||
|
||||
|
||||
led_atr_control #(
|
||||
.LED_REGISTER_ADDRESS (LED_REGISTER_ADDRESS),
|
||||
.REG_BASE (LED_ATR_REGS),
|
||||
.REG_SIZE (LED_ATR_REGS_SIZE)
|
||||
) led_atr_control_i (
|
||||
.ctrlport_clk (pll_ref_clk),
|
||||
.ctrlport_rst (ctrlport_rst_prc),
|
||||
.s_ctrlport_req_wr (led_atr_ctrlport_req_wr),
|
||||
.s_ctrlport_req_rd (led_atr_ctrlport_req_rd),
|
||||
.s_ctrlport_req_addr (led_atr_ctrlport_req_addr),
|
||||
.s_ctrlport_req_data (led_atr_ctrlport_req_data),
|
||||
.s_ctrlport_resp_ack (led_atr_ctrlport_resp_ack),
|
||||
.s_ctrlport_resp_status (led_atr_ctrlport_resp_status),
|
||||
.s_ctrlport_resp_data (led_atr_ctrlport_resp_data),
|
||||
.db_state (db_state_prc),
|
||||
.m_ctrlport_req_wr (cpld_ctrlport_req_wr),
|
||||
.m_ctrlport_req_rd (cpld_ctrlport_req_rd),
|
||||
.m_ctrlport_req_addr (cpld_ctrlport_req_addr),
|
||||
.m_ctrlport_req_data (cpld_ctrlport_req_data),
|
||||
.m_ctrlport_req_byte_en (cpld_ctrlport_req_byte_en),
|
||||
.m_ctrlport_resp_ack (cpld_ctrlport_resp_ack),
|
||||
.m_ctrlport_resp_status (cpld_ctrlport_resp_status),
|
||||
.m_ctrlport_resp_data (cpld_ctrlport_resp_data)
|
||||
);
|
||||
|
||||
ctrlport_clk_cross core_clk_cross_cpld_master (
|
||||
.rst (ctrlport_rst_prc),
|
||||
.s_ctrlport_clk (pll_ref_clk),
|
||||
.s_ctrlport_req_wr (cpld_ctrlport_req_wr),
|
||||
.s_ctrlport_req_rd (cpld_ctrlport_req_rd),
|
||||
.s_ctrlport_req_addr (cpld_ctrlport_req_addr),
|
||||
.s_ctrlport_req_portid (),
|
||||
.s_ctrlport_req_rem_epid (),
|
||||
.s_ctrlport_req_rem_portid (),
|
||||
.s_ctrlport_req_data (cpld_ctrlport_req_data),
|
||||
.s_ctrlport_req_byte_en (cpld_ctrlport_req_byte_en),
|
||||
.s_ctrlport_req_has_time (),
|
||||
.s_ctrlport_req_time (),
|
||||
.s_ctrlport_resp_ack (cpld_ctrlport_resp_ack),
|
||||
.s_ctrlport_resp_status (cpld_ctrlport_resp_status),
|
||||
.s_ctrlport_resp_data (cpld_ctrlport_resp_data),
|
||||
.m_ctrlport_clk (radio_clk),
|
||||
.m_ctrlport_req_wr (m_ctrlport_req_wr),
|
||||
.m_ctrlport_req_rd (m_ctrlport_req_rd),
|
||||
.m_ctrlport_req_addr (m_ctrlport_req_addr),
|
||||
.m_ctrlport_req_portid (),
|
||||
.m_ctrlport_req_rem_epid (),
|
||||
.m_ctrlport_req_rem_portid (),
|
||||
.m_ctrlport_req_data (m_ctrlport_req_data),
|
||||
.m_ctrlport_req_byte_en (m_ctrlport_req_byte_en),
|
||||
.m_ctrlport_req_has_time (),
|
||||
.m_ctrlport_req_time (),
|
||||
.m_ctrlport_resp_ack (m_ctrlport_resp_ack),
|
||||
.m_ctrlport_resp_status (m_ctrlport_resp_status),
|
||||
.m_ctrlport_resp_data (m_ctrlport_resp_data)
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// I2C Control
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
wire i2c_scl_i, i2c_scl_o, i2c_scl_en_o;
|
||||
wire i2c_sda_i, i2c_sda_o, i2c_sda_en_o;
|
||||
|
||||
ctrlport_to_i2c_sync_ctrl #(
|
||||
.BASE_ADDRESS(RF_SYNC_REGS),
|
||||
.PRESCALE(1000)
|
||||
) ctrlport_to_i2c_inst (
|
||||
.ctrlport_clk (pll_ref_clk),
|
||||
.ctrlport_rst (ctrlport_rst_prc),
|
||||
.s_ctrlport_req_wr (sync_ctrlport_req_wr),
|
||||
.s_ctrlport_req_rd (sync_ctrlport_req_rd),
|
||||
.s_ctrlport_req_addr (sync_ctrlport_req_addr),
|
||||
.s_ctrlport_req_data (sync_ctrlport_req_data),
|
||||
.s_ctrlport_resp_ack (sync_ctrlport_resp_ack),
|
||||
.s_ctrlport_resp_status (sync_ctrlport_resp_status),
|
||||
.s_ctrlport_resp_data (sync_ctrlport_resp_data),
|
||||
.scl_pad_i (i2c_scl_i),
|
||||
.scl_pad_o (i2c_scl_o),
|
||||
.scl_pad_en_o (i2c_scl_en_o),
|
||||
.sda_pad_i (i2c_sda_i),
|
||||
.sda_pad_o (i2c_sda_o),
|
||||
.sda_pad_en_o (i2c_sda_en_o)
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Sync Clock Enable
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
clock_en_control #(
|
||||
.BASE_ADDRESS(SYNC_CLK_EN_REGS)
|
||||
) clock_en_control_inst (
|
||||
.ctrlport_clk (pll_ref_clk),
|
||||
.ctrlport_rst (ctrlport_rst_prc),
|
||||
.s_ctrlport_req_wr (clk_en_ctrlport_req_wr),
|
||||
.s_ctrlport_req_rd (clk_en_ctrlport_req_rd),
|
||||
.s_ctrlport_req_addr (clk_en_ctrlport_req_addr),
|
||||
.s_ctrlport_req_data (clk_en_ctrlport_req_data),
|
||||
.s_ctrlport_resp_ack (clk_en_ctrlport_resp_ack),
|
||||
.s_ctrlport_resp_status (clk_en_ctrlport_resp_status),
|
||||
.s_ctrlport_resp_data (clk_en_ctrlport_resp_data),
|
||||
.clk_in (in_sync_clk),
|
||||
.clk_out (out_sync_clk)
|
||||
);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// wire assignment
|
||||
//----------------------------------------------------------------------------
|
||||
// RFS1, RFS2, RFS3, RFS4, RFS5, RFS6, RFS7, RFS8, TDDS1, TDDS2, TDDS3, TDDS4,
|
||||
// 2 unused, 2 for I2C, 4 unused.
|
||||
|
||||
assign i2c_sda_i = gpio_in[4];
|
||||
assign i2c_scl_i = gpio_in[5];
|
||||
|
||||
assign gpio_out = {rf0_tx_rx_rfs, rf0_rx_rfs,
|
||||
rf1_tx_rx_rfs, rf1_rx_rfs,
|
||||
rf2_tx_rx_rfs, rf2_rx_rfs,
|
||||
rf3_tx_rx_rfs, rf3_rx_rfs,
|
||||
rf0_tdds, rf1_tdds,
|
||||
rf2_tdds, rf3_tdds,
|
||||
2'b0, // Unused
|
||||
i2c_scl_o, i2c_sda_o, // I2C
|
||||
4'b0 // Unused
|
||||
};
|
||||
|
||||
assign gpio_out_en = {12'hFFF, // Switches
|
||||
2'b0, // Unused
|
||||
~i2c_scl_en_o, ~i2c_sda_en_o, // I2C enables tri-state when HIGH
|
||||
4'b0 // Unused
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
// 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="0x22070116"/>
|
||||
// </enumeratedtype>
|
||||
// </group>
|
||||
//</regmap>
|
||||
|
||||
//<regmap name="FBX_CTRL_REGMAP" readablestrobes="false" generatevhdl="true" ettusguidelines="true">
|
||||
// <info>
|
||||
// This map contains register windows for controlling the different sources
|
||||
// that drive the state of FBX control lines.
|
||||
// </info>
|
||||
// <group name="FBX_CONTROLS">
|
||||
// <window name="RF_ATR_REGS" offset="0x0" size="0x2000" targetregmap="RF_ATR_REGMAP">
|
||||
// <info>Control RF switches in FBX daughterboard based on the ATR state of the accessed radio</info>
|
||||
// </window>
|
||||
// <window name="RF_SYNC_REGS" offset="0x2000" size="0x2000" targetregmap="RF_SYNC_REGMAP">
|
||||
// <info>I2C interface to FBX daughterboard IO Expander that controls SYNC switches and rfs en</info>
|
||||
// </window>
|
||||
// <window name="LED_ATR_REGS" offset="0x4000" size="0x2000" targetregmap="LED_ATR_REGMAP">
|
||||
// <info>Control TX/RX LEDs based on the ATR state of the accessed radio</info>
|
||||
// </window>
|
||||
// <window name="SYNC_CLK_EN_REGS" offset="0x6000" size="0x2000" targetregmap="CLK_EN_REGMAP">
|
||||
// <info>Clock enable register for SYNC INJECT 5 MHz clock</info>
|
||||
// </window>
|
||||
// </group>
|
||||
//</regmap>
|
||||
//XmlParse xml_off
|
||||
@@ -0,0 +1,569 @@
|
||||
//
|
||||
// Copyright 2022 Ettus Research, A National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: led_atr_control
|
||||
//
|
||||
// Description:
|
||||
// Translates db_status to implement control over RF LEDs via CtrlPort.
|
||||
// Uses RAM to store multiple ATR configurations. Triggers CtrlPort
|
||||
// requests to transfer changes to LEDs to MB CPLD.
|
||||
// There are three supported control schemes for these switches:
|
||||
// - ATR Disabled - Single persistent state.
|
||||
// - Classic ATR - Each channel's LEDs depend on the transmission state
|
||||
// of the respective channel.
|
||||
// - DB State - Each channel's LEDs depend on the transmission state
|
||||
// of all channels in this radio.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// LED_REGISTER_ADDRESS : Address of LED register within CPLD.
|
||||
// REG_BASE : Base address to use for registers.
|
||||
// REG_SIZE : Register space size.
|
||||
//
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module led_atr_control #(
|
||||
parameter LED_REGISTER_ADDRESS = 0,
|
||||
parameter REG_BASE = 'h2000,
|
||||
parameter REG_SIZE = 'h2000
|
||||
|
||||
) (
|
||||
// Common ControlPort signals
|
||||
input wire ctrlport_clk,
|
||||
input wire ctrlport_rst,
|
||||
|
||||
// Slave ctrlport inteledace
|
||||
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,
|
||||
output reg s_ctrlport_resp_ack = 1'b0,
|
||||
output reg [ 1:0] s_ctrlport_resp_status = 2'b00,
|
||||
output reg [31:0] s_ctrlport_resp_data = {32 {1'b0}},
|
||||
|
||||
// DB state lines
|
||||
input wire [7:0] db_state,
|
||||
|
||||
// ControlPort request
|
||||
output reg m_ctrlport_req_wr,
|
||||
output wire m_ctrlport_req_rd,
|
||||
output wire [19:0] m_ctrlport_req_addr,
|
||||
output wire [31:0] m_ctrlport_req_data,
|
||||
output wire [ 3:0] m_ctrlport_req_byte_en,
|
||||
|
||||
// ControlPort response
|
||||
input wire m_ctrlport_resp_ack,
|
||||
input wire [ 1:0] m_ctrlport_resp_status,
|
||||
input wire [31:0] m_ctrlport_resp_data
|
||||
|
||||
);
|
||||
|
||||
`include "../../cpld/regmap/x440/led_setup_regmap_utils.vh"
|
||||
`include "../../../../lib/rfnoc/core/ctrlport.vh"
|
||||
`include "regmap/led_atr_regmap_utils.vh"
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// ATR memory signals
|
||||
//---------------------------------------------------------------
|
||||
reg ram_led0_wea;
|
||||
wire [LED_SIZE-1:0] ram_led0_doa;
|
||||
wire [LED_SIZE-1:0] ram_led0_dob;
|
||||
|
||||
reg ram_led1_wea;
|
||||
wire [LED_SIZE-1:0] ram_led1_doa;
|
||||
wire [LED_SIZE-1:0] ram_led1_dob;
|
||||
|
||||
reg ram_led2_wea;
|
||||
wire [LED_SIZE-1:0] ram_led2_doa;
|
||||
wire [LED_SIZE-1:0] ram_led2_dob;
|
||||
|
||||
reg ram_led3_wea;
|
||||
wire [LED_SIZE-1:0] ram_led3_doa;
|
||||
wire [LED_SIZE-1:0] ram_led3_dob;
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// ATR Scheme signals
|
||||
//---------------------------------------------------------------
|
||||
reg [3:0] atr_disable = 4'b0;
|
||||
|
||||
// DB state/Classic ATR selector
|
||||
reg [3:0] atr_mode = 4'b0;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Control inteledace handling
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Check that address is within this module's range.
|
||||
wire address_in_range = (s_ctrlport_req_addr >= REG_BASE) && (s_ctrlport_req_addr < REG_BASE + REG_SIZE);
|
||||
|
||||
// Check that address is targeting an ATR state.
|
||||
wire address_is_atr = (s_ctrlport_req_addr >= REG_BASE + LED0_ATR_STATE(0)) && (s_ctrlport_req_addr <= REG_BASE + LED3_ATR_STATE(LED3_ATR_STATE_COUNT-1));
|
||||
|
||||
// Read request shift register to align memory read and response generation.
|
||||
reg [ 1:0] read_req_shift_reg = 2'b0;
|
||||
// Mask out 8 bits for ATR configurations to be able to compare all ATR
|
||||
// configurations against the same base register address.
|
||||
wire [31:0] register_base_address = {s_ctrlport_req_addr[19:10], 8'b0, s_ctrlport_req_addr[1:0]};
|
||||
// Decode the ATR state being addressed.
|
||||
wire [ 7:0] atr_address = s_ctrlport_req_addr[9:2];
|
||||
|
||||
always @ (posedge ctrlport_clk) begin
|
||||
if (ctrlport_rst) begin
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
s_ctrlport_resp_data <= 32'b0;
|
||||
s_ctrlport_resp_status <= 2'b00;
|
||||
|
||||
atr_disable <= 4'b0;
|
||||
atr_mode <= 4'b0;
|
||||
|
||||
ram_led0_wea <= 1'b0;
|
||||
ram_led1_wea <= 1'b0;
|
||||
ram_led2_wea <= 1'b0;
|
||||
ram_led3_wea <= 1'b0;
|
||||
|
||||
end else begin
|
||||
// default assignments
|
||||
read_req_shift_reg <= {read_req_shift_reg[0], s_ctrlport_req_rd};
|
||||
|
||||
ram_led0_wea <= 1'b0;
|
||||
ram_led1_wea <= 1'b0;
|
||||
ram_led2_wea <= 1'b0;
|
||||
ram_led3_wea <= 1'b0;
|
||||
|
||||
// Write registers
|
||||
if (s_ctrlport_req_wr) begin
|
||||
// Acknowledge by default
|
||||
s_ctrlport_resp_ack <= 1'b1;
|
||||
s_ctrlport_resp_status <= CTRL_STS_OKAY;
|
||||
|
||||
// Address ATR state writes
|
||||
if(address_is_atr) begin
|
||||
|
||||
case (register_base_address)
|
||||
REG_BASE + LED0_ATR_STATE(0): begin
|
||||
ram_led0_wea <= 1'b1;
|
||||
end
|
||||
|
||||
REG_BASE + LED1_ATR_STATE(0): begin
|
||||
ram_led1_wea <= 1'b1;
|
||||
end
|
||||
|
||||
REG_BASE + LED2_ATR_STATE(0): begin
|
||||
ram_led2_wea <= 1'b1;
|
||||
end
|
||||
|
||||
REG_BASE + LED3_ATR_STATE(0): begin
|
||||
ram_led3_wea <= 1'b1;
|
||||
end
|
||||
|
||||
// error on undefined address
|
||||
default: begin
|
||||
s_ctrlport_resp_status <= CTRL_STS_CMDERR;
|
||||
end
|
||||
endcase
|
||||
end else begin
|
||||
|
||||
// Address writes to the rest of the register space
|
||||
case (s_ctrlport_req_addr)
|
||||
|
||||
REG_BASE + LED_ATR_OPTION_REGISTER: begin
|
||||
atr_mode[0] <= s_ctrlport_req_data[LED0_ATR_OPTION];
|
||||
atr_mode[1] <= s_ctrlport_req_data[LED1_ATR_OPTION];
|
||||
atr_mode[2] <= s_ctrlport_req_data[LED2_ATR_OPTION];
|
||||
atr_mode[3] <= s_ctrlport_req_data[LED3_ATR_OPTION];
|
||||
end
|
||||
|
||||
REG_BASE + LED_ATR_DISABLED: begin
|
||||
atr_disable[0] <= s_ctrlport_req_data[LED0_ATR_DISABLED];
|
||||
atr_disable[1] <= s_ctrlport_req_data[LED1_ATR_DISABLED];
|
||||
atr_disable[2] <= s_ctrlport_req_data[LED2_ATR_DISABLED];
|
||||
atr_disable[3] <= s_ctrlport_req_data[LED3_ATR_DISABLED];
|
||||
end
|
||||
|
||||
// No register implementation for provided address
|
||||
default: begin
|
||||
// Acknowledge and provide error status if address is in range
|
||||
if (address_in_range) begin
|
||||
s_ctrlport_resp_status <= CTRL_STS_CMDERR;
|
||||
|
||||
// No response if out of range
|
||||
end else begin
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
// Read registers
|
||||
end else if (read_req_shift_reg[1]) begin
|
||||
// Acknowledge by default
|
||||
s_ctrlport_resp_ack <= 1'b1;
|
||||
s_ctrlport_resp_status <= CTRL_STS_OKAY;
|
||||
|
||||
// Address ATR state reads
|
||||
if(address_is_atr) begin
|
||||
|
||||
case (register_base_address)
|
||||
REG_BASE + LED0_ATR_STATE(0): begin
|
||||
s_ctrlport_resp_data <= ram_led0_doa & LED_ATR_STATE_MASK;
|
||||
end
|
||||
REG_BASE + LED1_ATR_STATE(0): begin
|
||||
s_ctrlport_resp_data <= ram_led1_doa & LED_ATR_STATE_MASK;
|
||||
end
|
||||
REG_BASE + LED2_ATR_STATE(0): begin
|
||||
s_ctrlport_resp_data <= ram_led2_doa & LED_ATR_STATE_MASK;
|
||||
end
|
||||
REG_BASE + LED3_ATR_STATE(0): begin
|
||||
s_ctrlport_resp_data <= ram_led3_doa & LED_ATR_STATE_MASK;
|
||||
end
|
||||
|
||||
default: begin
|
||||
s_ctrlport_resp_status <= CTRL_STS_CMDERR;
|
||||
end
|
||||
endcase
|
||||
|
||||
end else begin
|
||||
|
||||
// Address reads to the rest of the register space
|
||||
case (s_ctrlport_req_addr)
|
||||
|
||||
REG_BASE + LED_ATR_OPTION_REGISTER: begin
|
||||
s_ctrlport_resp_data[LED0_ATR_OPTION] <= atr_mode[0];
|
||||
s_ctrlport_resp_data[LED1_ATR_OPTION] <= atr_mode[1];
|
||||
s_ctrlport_resp_data[LED2_ATR_OPTION] <= atr_mode[2];
|
||||
s_ctrlport_resp_data[LED3_ATR_OPTION] <= atr_mode[3];
|
||||
end
|
||||
|
||||
REG_BASE + LED_ATR_DISABLED: begin
|
||||
s_ctrlport_resp_data[LED0_ATR_DISABLED] <= atr_disable[0];
|
||||
s_ctrlport_resp_data[LED1_ATR_DISABLED] <= atr_disable[1];
|
||||
s_ctrlport_resp_data[LED2_ATR_DISABLED] <= atr_disable[2];
|
||||
s_ctrlport_resp_data[LED3_ATR_DISABLED] <= atr_disable[3];
|
||||
end
|
||||
|
||||
// No register implementation for provided address
|
||||
default: begin
|
||||
// Acknowledge and provide error status if address is in range
|
||||
if (address_in_range) begin
|
||||
s_ctrlport_resp_status <= CTRL_STS_CMDERR;
|
||||
|
||||
// No response if out of range
|
||||
end else begin
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
end else begin
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// register without reset
|
||||
reg [ 7:0] ram_addr = 8'b0;
|
||||
reg [LED_SIZE-1:0] ram_datain = {LED_SIZE{1'b0}};
|
||||
always @(posedge ctrlport_clk) begin
|
||||
// memories
|
||||
ram_addr <= atr_address;
|
||||
ram_datain <= s_ctrlport_req_data[LED_SIZE-1:0];
|
||||
end
|
||||
|
||||
// ATR Scheme selection
|
||||
reg [7:0] atr_config_led [3:0];
|
||||
|
||||
generate
|
||||
genvar i;
|
||||
for (i = 0; i < 4; i = i + 1) begin: read_address_gen
|
||||
|
||||
always @(posedge ctrlport_clk) begin
|
||||
if (atr_disable[i]) begin
|
||||
atr_config_led[i] <= 8'b0;
|
||||
end else begin
|
||||
if (atr_mode[i]) begin
|
||||
atr_config_led[i] <= {6'b0, db_state[2*i+:2]};
|
||||
end else begin
|
||||
atr_config_led[i] <= db_state;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
reg [31:0] led_combined = 32'b0;
|
||||
always @(posedge ctrlport_clk) begin
|
||||
led_combined[CH0_RX2_LED_EN] <= ram_led0_dob[RX2_LED];
|
||||
led_combined[CH0_TRX1_LED_RED_EN] <= ram_led0_dob[TXRX_RED_LED];
|
||||
led_combined[CH0_TRX1_LED_GR_EN] <= ram_led0_dob[TXRX_GR_LED];
|
||||
|
||||
led_combined[CH1_RX2_LED_EN] <= ram_led1_dob[RX2_LED];
|
||||
led_combined[CH1_TRX1_LED_RED_EN] <= ram_led1_dob[TXRX_RED_LED];
|
||||
led_combined[CH1_TRX1_LED_GR_EN] <= ram_led1_dob[TXRX_GR_LED];
|
||||
|
||||
led_combined[CH2_RX2_LED_EN] <= ram_led2_dob[RX2_LED];
|
||||
led_combined[CH2_TRX1_LED_RED_EN] <= ram_led2_dob[TXRX_RED_LED];
|
||||
led_combined[CH2_TRX1_LED_GR_EN] <= ram_led2_dob[TXRX_GR_LED];
|
||||
|
||||
led_combined[CH3_RX2_LED_EN] <= ram_led3_dob[RX2_LED];
|
||||
led_combined[CH3_TRX1_LED_RED_EN] <= ram_led3_dob[TXRX_RED_LED];
|
||||
led_combined[CH3_TRX1_LED_GR_EN] <= ram_led3_dob[TXRX_GR_LED];
|
||||
|
||||
end
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// ATR memory
|
||||
//---------------------------------------------------------------
|
||||
ram_2port #(
|
||||
.DWIDTH (LED_SIZE),
|
||||
.AWIDTH (8),
|
||||
.RW_MODE ("READ-FIRST"),
|
||||
.RAM_TYPE ("AUTOMATIC"),
|
||||
.OUT_REG (0)
|
||||
) ram_led0_i (
|
||||
.clka (ctrlport_clk),
|
||||
.ena (1'b1),
|
||||
.wea (ram_led0_wea),
|
||||
.addra (ram_addr),
|
||||
.dia (ram_datain),
|
||||
.doa (ram_led0_doa),
|
||||
.clkb (ctrlport_clk),
|
||||
.enb (1'b1),
|
||||
.web (1'b0),
|
||||
.addrb (atr_config_led[0]),
|
||||
.dib ({LED_SIZE{1'b0}}),
|
||||
.dob (ram_led0_dob));
|
||||
|
||||
ram_2port #(
|
||||
.DWIDTH (LED_SIZE),
|
||||
.AWIDTH (8),
|
||||
.RW_MODE ("READ-FIRST"),
|
||||
.RAM_TYPE ("AUTOMATIC"),
|
||||
.OUT_REG (0)
|
||||
) ram_led1_i (
|
||||
.clka (ctrlport_clk),
|
||||
.ena (1'b1),
|
||||
.wea (ram_led1_wea),
|
||||
.addra (ram_addr),
|
||||
.dia (ram_datain),
|
||||
.doa (ram_led1_doa),
|
||||
.clkb (ctrlport_clk),
|
||||
.enb (1'b1),
|
||||
.web (1'b0),
|
||||
.addrb (atr_config_led[1]),
|
||||
.dib ({LED_SIZE{1'b0}}),
|
||||
.dob (ram_led1_dob));
|
||||
|
||||
ram_2port #(
|
||||
.DWIDTH (LED_SIZE),
|
||||
.AWIDTH (8),
|
||||
.RW_MODE ("READ-FIRST"),
|
||||
.RAM_TYPE ("AUTOMATIC"),
|
||||
.OUT_REG (0)
|
||||
) ram_led2_i (
|
||||
.clka (ctrlport_clk),
|
||||
.ena (1'b1),
|
||||
.wea (ram_led2_wea),
|
||||
.addra (ram_addr),
|
||||
.dia (ram_datain),
|
||||
.doa (ram_led2_doa),
|
||||
.clkb (ctrlport_clk),
|
||||
.enb (1'b1),
|
||||
.web (1'b0),
|
||||
.addrb (atr_config_led[2]),
|
||||
.dib ({LED_SIZE{1'b0}}),
|
||||
.dob (ram_led2_dob));
|
||||
|
||||
ram_2port #(
|
||||
.DWIDTH (LED_SIZE),
|
||||
.AWIDTH (8),
|
||||
.RW_MODE ("READ-FIRST"),
|
||||
.RAM_TYPE ("AUTOMATIC"),
|
||||
.OUT_REG (0)
|
||||
) ram_led3_i (
|
||||
.clka (ctrlport_clk),
|
||||
.ena (1'b1),
|
||||
.wea (ram_led3_wea),
|
||||
.addra (ram_addr),
|
||||
.dia (ram_datain),
|
||||
.doa (ram_led3_doa),
|
||||
.clkb (ctrlport_clk),
|
||||
.enb (1'b1),
|
||||
.web (1'b0),
|
||||
.addrb (atr_config_led[3]),
|
||||
.dib ({LED_SIZE{1'b0}}),
|
||||
.dob (ram_led3_dob));
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Logic to wait for response after triggering request
|
||||
//----------------------------------------------------------
|
||||
|
||||
reg transfer_in_progress;
|
||||
reg [31:0] led_combined_delayed = 32'b0;
|
||||
|
||||
always @(posedge ctrlport_clk) begin
|
||||
if (ctrlport_rst) begin
|
||||
m_ctrlport_req_wr <= 1'b0;
|
||||
transfer_in_progress <= 1'b0;
|
||||
led_combined_delayed <= 16'b0;
|
||||
end else begin
|
||||
// Default assignment
|
||||
m_ctrlport_req_wr <= 1'b0;
|
||||
|
||||
// Issue new request on change if no request is pending
|
||||
if (led_combined != led_combined_delayed && ~transfer_in_progress) begin
|
||||
transfer_in_progress <= 1'b1;
|
||||
m_ctrlport_req_wr <= 1'b1;
|
||||
led_combined_delayed <= led_combined;
|
||||
end
|
||||
|
||||
// Reset pending request
|
||||
if (m_ctrlport_resp_ack) begin
|
||||
transfer_in_progress <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Static ControlPort assignments
|
||||
//----------------------------------------------------------
|
||||
|
||||
assign m_ctrlport_req_rd = 0;
|
||||
assign m_ctrlport_req_byte_en = 4'b1111;
|
||||
assign m_ctrlport_req_addr = LED_REGISTER_ADDRESS;
|
||||
assign m_ctrlport_req_data = {led_combined_delayed};
|
||||
|
||||
endmodule
|
||||
|
||||
//XmlParse xml_on
|
||||
//<regmap name="LED_ATR_REGMAP" readablestrobes="false" generatevhdl="true" ettusguidelines="true">
|
||||
// <group name="LED_ATR_REGISTERS">
|
||||
// <info>
|
||||
// Each channel in the FBX daughterboard has 3 LEDs. TXRX Red/Green LEDs and RX2 Green LED.
|
||||
// This register map describes how to control the behavior of the 3 LEDs.
|
||||
// There are three supported control schemes for these LEDs:</br>
|
||||
// <ul>
|
||||
// <li>ATR Disabled - Single persistent state.</li>
|
||||
// <li>Classic ATR - Each channel's LEDs depend on the transmission state
|
||||
// of the respective channel.</li>
|
||||
// <li>DB State - Each channel's LEDs depend on the transmission state
|
||||
// of all channels in this radio.</li>
|
||||
// </ul>
|
||||
// </info>
|
||||
//
|
||||
// <enumeratedtype name="LED_SIZE_TYPE">
|
||||
// <value name="LED_SIZE" integer="3"/>
|
||||
// </enumeratedtype>
|
||||
//
|
||||
// <regtype name="LED_ATR_STATE" size="32">
|
||||
// <info>Holds the value for the control lines of each channel's LEDs
|
||||
// for a particular ATR sate</info>
|
||||
// <bitfield name="RX2_LED" range="0" initialvalue="0"/>
|
||||
// <bitfield name="TXRX_RED_LED" range="1" initialvalue="0"/>
|
||||
// <bitfield name="TXRX_GR_LED" range="2" initialvalue="0"/>
|
||||
// </regtype>
|
||||
//
|
||||
// <register name="LED0_ATR_STATE" typename="LED_ATR_STATE" offset="0x00" count="256" options="--step 4">
|
||||
// <info>
|
||||
// Describes led behavior for the different ATR states. When @.LED0_ATR_OPTION
|
||||
// is set to use the DB states, TX and RX states for LED0-LED3 are
|
||||
// combined to create a single vector. This creates 256 different
|
||||
// combinations, each with its own register. When @.LED0_ATR_OPTION is set to
|
||||
// classic ATR, the first 4 offsets in this register group will be driven
|
||||
// in accordance with the state of RF0.
|
||||
// CLASSIC ATR MAPPING: Idle[RF0: TX=0, RX=0], RX[RF0: TX=0, RX=1,
|
||||
// TX[RF0: TX=1, RX=0], FDX[RF0: TX=1, RX=1]
|
||||
// </info>
|
||||
// </register>
|
||||
//
|
||||
// <register name="LED1_ATR_STATE" typename="LED_ATR_STATE" offset="0x400" count="256" options="--step 4">
|
||||
// <info>
|
||||
// Describes led behavior for the different ATR states. When @.LED1_ATR_OPTION
|
||||
// is set to use the DB states, TX and RX states for LED0-LED3 are
|
||||
// combined to create a single vector. This creates 256 different
|
||||
// combinations, each with its own register. When @.LED1_ATR_OPTION is set to
|
||||
// classic ATR, the first 4 offsets in this register group will be driven
|
||||
// in accordance with the state of RF1.
|
||||
// CLASSIC ATR MAPPING: Idle[RF1: TX=0, RX=0], RX[RF1: TX=0, RX=1,
|
||||
// TX[RF1: TX=1, RX=0], FDX[RF1: TX=1, RX=1]
|
||||
// </info>
|
||||
// </register>
|
||||
//
|
||||
// <register name="LED2_ATR_STATE" typename="LED_ATR_STATE" offset="0x800" count="256" options="--step 4">
|
||||
// <info>
|
||||
// Describes led behavior for the different ATR states. When @.LED2_ATR_OPTION
|
||||
// is set to use the DB states, TX and RX states for LED0-LED3 are
|
||||
// combined to create a single vector. This creates 256 different
|
||||
// combinations, each with its own register. When @.LED2_ATR_OPTION is set to
|
||||
// classic ATR, the first 4 offsets in this register group will be driven
|
||||
// in accordance with the state of RF2.
|
||||
// CLASSIC ATR MAPPING: Idle[RF2: TX=0, RX=0], RX[RF2: TX=0, RX=1,
|
||||
// TX[RF2: TX=1, RX=0], FDX[RF2: TX=1, RX=1]
|
||||
// </info>
|
||||
// </register>
|
||||
//
|
||||
// <register name="LED3_ATR_STATE" typename="LED_ATR_STATE" offset="0xC00" count="256" options="--step 4">
|
||||
// <info>
|
||||
// Describes led behavior for the different ATR states. When @.LED3_ATR_OPTION
|
||||
// is set to use the DB states, TX and RX states for LED0-LED3 are
|
||||
// combined to create a single vector. This creates 256 different
|
||||
// combinations, each with its own register. When @.LED3_ATR_OPTION is set to
|
||||
// classic ATR, the first 4 offsets in this register group will be driven
|
||||
// in accordance with the state of RF3.
|
||||
// CLASSIC ATR MAPPING: Idle[RF3: TX=0, RX=0], RX[RF3: TX=0, RX=1,
|
||||
// TX[RF3: TX=1, RX=0], FDX[RF3: TX=1, RX=1]
|
||||
// </info>
|
||||
// </register>
|
||||
// <register name="LED_ATR_OPTION_REGISTER" offset="0x1000" size="32">
|
||||
// <info>
|
||||
// Controls whether switch control lines use the TX and RX state of
|
||||
// their respective channel (Classic ATR) or the daughterboard state
|
||||
// to select which state to use from values set in LED_ATR_STATE registers.
|
||||
// For each particular bit:</br>
|
||||
// 0: Use DB state for ATR</br>
|
||||
// 1: Classic ATR mode.
|
||||
// </info>
|
||||
// <bitfield name="LED0_ATR_OPTION" range="0" initialvalue="0">
|
||||
// <info>
|
||||
// Control ATR scheme for RF0.
|
||||
// </info>
|
||||
// </bitfield>
|
||||
// <bitfield name="LED1_ATR_OPTION" range="1" initialvalue="0">
|
||||
// <info>
|
||||
// Control ATR scheme for RF1.
|
||||
// </info>
|
||||
// </bitfield>
|
||||
// <bitfield name="LED2_ATR_OPTION" range="2" initialvalue="0">
|
||||
// <info>
|
||||
// Control ATR scheme for RF2.
|
||||
// </info>
|
||||
// </bitfield>
|
||||
// <bitfield name="LED3_ATR_OPTION" range="3" initialvalue="0">
|
||||
// <info>
|
||||
// Control ATR scheme for RF3.
|
||||
// </info>
|
||||
// </bitfield>
|
||||
// </register>
|
||||
// <register name="LED_ATR_DISABLED" offset="0x1004" size="32">
|
||||
// <info>
|
||||
// Disable ATR Control. DB state 0 will be reflected regardless of the ATR state.
|
||||
// </info>
|
||||
// <bitfield name="LED0_ATR_DISABLED" range="0" initialvalue="0"/>
|
||||
// <bitfield name="LED1_ATR_DISABLED" range="1" initialvalue="0"/>
|
||||
// <bitfield name="LED2_ATR_DISABLED" range="2" initialvalue="0"/>
|
||||
// <bitfield name="LED3_ATR_DISABLED" range="3" initialvalue="0"/>
|
||||
// </register>
|
||||
// </group>
|
||||
//</regmap>
|
||||
//XmlParse xml_off
|
||||
|
||||
|
||||
`default_nettype wire
|
||||
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// Copyright 2022 Ettus Research, A National Instruments Company
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: clock_en_regmap_utils.vh
|
||||
// Description:
|
||||
// The constants in this file are autogenerated by XmlParse.
|
||||
|
||||
//===============================================================================
|
||||
// A numerically ordered list of registers and their HDL source files
|
||||
//===============================================================================
|
||||
|
||||
// CLK_EN_CONTROL : 0x0 (clock_en_control.v)
|
||||
|
||||
//===============================================================================
|
||||
// RegTypes
|
||||
//===============================================================================
|
||||
|
||||
//===============================================================================
|
||||
// Register Group CLOCK_EN_REGISTERS
|
||||
//===============================================================================
|
||||
|
||||
// CLK_EN_CONTROL Register (from clock_en_control.v)
|
||||
localparam CLK_EN_CONTROL = 'h0; // Register Offset
|
||||
localparam CLK_EN_CONTROL_SIZE = 32; // register width in bits
|
||||
localparam CLK_EN_CONTROL_MASK = 32'h1;
|
||||
localparam CLK_EN_SIZE = 1; //CLK_EN_CONTROL:CLK_EN
|
||||
localparam CLK_EN_MSB = 0; //CLK_EN_CONTROL:CLK_EN
|
||||
localparam CLK_EN = 0; //CLK_EN_CONTROL:CLK_EN
|
||||
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// Copyright 2023 Ettus Research, A National Instruments Company
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: fbx_ctrl_regmap_utils.vh
|
||||
// Description:
|
||||
// The constants in this file are autogenerated by XmlParse.
|
||||
|
||||
//===============================================================================
|
||||
// A numerically ordered list of registers and their HDL source files
|
||||
//===============================================================================
|
||||
|
||||
// RF_ATR_REGS : 0x0 (db_gpio_interface.v)
|
||||
// RF_SYNC_REGS : 0x2000 (db_gpio_interface.v)
|
||||
// LED_ATR_REGS : 0x4000 (db_gpio_interface.v)
|
||||
// SYNC_CLK_EN_REGS : 0x6000 (db_gpio_interface.v)
|
||||
|
||||
//===============================================================================
|
||||
// RegTypes
|
||||
//===============================================================================
|
||||
|
||||
//===============================================================================
|
||||
// Register Group FBX_CONTROLS
|
||||
//===============================================================================
|
||||
|
||||
// RF_ATR_REGS Window (from db_gpio_interface.v)
|
||||
localparam RF_ATR_REGS = 'h0; // Window Offset
|
||||
localparam RF_ATR_REGS_SIZE = 'h2000; // size in bytes
|
||||
|
||||
// RF_SYNC_REGS Window (from db_gpio_interface.v)
|
||||
localparam RF_SYNC_REGS = 'h2000; // Window Offset
|
||||
localparam RF_SYNC_REGS_SIZE = 'h2000; // size in bytes
|
||||
|
||||
// LED_ATR_REGS Window (from db_gpio_interface.v)
|
||||
localparam LED_ATR_REGS = 'h4000; // Window Offset
|
||||
localparam LED_ATR_REGS_SIZE = 'h2000; // size in bytes
|
||||
|
||||
// SYNC_CLK_EN_REGS Window (from db_gpio_interface.v)
|
||||
localparam SYNC_CLK_EN_REGS = 'h6000; // Window Offset
|
||||
localparam SYNC_CLK_EN_REGS_SIZE = 'h2000; // size in bytes
|
||||
@@ -0,0 +1,110 @@
|
||||
//
|
||||
// Copyright 2023 Ettus Research, A National Instruments Company
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: led_atr_regmap_utils.vh
|
||||
// Description:
|
||||
// The constants in this file are autogenerated by XmlParse.
|
||||
|
||||
//===============================================================================
|
||||
// A numerically ordered list of registers and their HDL source files
|
||||
//===============================================================================
|
||||
|
||||
// LED0_ATR_STATE : 0x0 (led_atr_control.v)
|
||||
// LED1_ATR_STATE : 0x400 (led_atr_control.v)
|
||||
// LED2_ATR_STATE : 0x800 (led_atr_control.v)
|
||||
// LED3_ATR_STATE : 0xC00 (led_atr_control.v)
|
||||
// LED_ATR_OPTION_REGISTER : 0x1000 (led_atr_control.v)
|
||||
// LED_ATR_DISABLED : 0x1004 (led_atr_control.v)
|
||||
|
||||
//===============================================================================
|
||||
// RegTypes
|
||||
//===============================================================================
|
||||
|
||||
// LED_ATR_STATE Type (from led_atr_control.v)
|
||||
localparam LED_ATR_STATE_SIZE = 32;
|
||||
localparam LED_ATR_STATE_MASK = 32'h7;
|
||||
localparam RX2_LED_SIZE = 1; //LED_ATR_STATE:RX2_LED
|
||||
localparam RX2_LED_MSB = 0; //LED_ATR_STATE:RX2_LED
|
||||
localparam RX2_LED = 0; //LED_ATR_STATE:RX2_LED
|
||||
localparam TXRX_RED_LED_SIZE = 1; //LED_ATR_STATE:TXRX_RED_LED
|
||||
localparam TXRX_RED_LED_MSB = 1; //LED_ATR_STATE:TXRX_RED_LED
|
||||
localparam TXRX_RED_LED = 1; //LED_ATR_STATE:TXRX_RED_LED
|
||||
localparam TXRX_GR_LED_SIZE = 1; //LED_ATR_STATE:TXRX_GR_LED
|
||||
localparam TXRX_GR_LED_MSB = 2; //LED_ATR_STATE:TXRX_GR_LED
|
||||
localparam TXRX_GR_LED = 2; //LED_ATR_STATE:TXRX_GR_LED
|
||||
|
||||
//===============================================================================
|
||||
// Register Group LED_ATR_REGISTERS
|
||||
//===============================================================================
|
||||
|
||||
// Enumerated type LED_SIZE_TYPE
|
||||
localparam LED_SIZE_TYPE_SIZE = 1;
|
||||
localparam LED_SIZE = 'h3; // LED_SIZE_TYPE:LED_SIZE
|
||||
|
||||
// LED0_ATR_STATE Register (from led_atr_control.v)
|
||||
localparam LED0_ATR_STATE_COUNT = 256; // Number of elements in array
|
||||
|
||||
// LED1_ATR_STATE Register (from led_atr_control.v)
|
||||
localparam LED1_ATR_STATE_COUNT = 256; // Number of elements in array
|
||||
|
||||
// LED2_ATR_STATE Register (from led_atr_control.v)
|
||||
localparam LED2_ATR_STATE_COUNT = 256; // Number of elements in array
|
||||
|
||||
// LED3_ATR_STATE Register (from led_atr_control.v)
|
||||
localparam LED3_ATR_STATE_COUNT = 256; // Number of elements in array
|
||||
|
||||
// LED_ATR_OPTION_REGISTER Register (from led_atr_control.v)
|
||||
localparam LED_ATR_OPTION_REGISTER = 'h1000; // Register Offset
|
||||
localparam LED_ATR_OPTION_REGISTER_SIZE = 32; // register width in bits
|
||||
localparam LED_ATR_OPTION_REGISTER_MASK = 32'hF;
|
||||
localparam LED0_ATR_OPTION_SIZE = 1; //LED_ATR_OPTION_REGISTER:LED0_ATR_OPTION
|
||||
localparam LED0_ATR_OPTION_MSB = 0; //LED_ATR_OPTION_REGISTER:LED0_ATR_OPTION
|
||||
localparam LED0_ATR_OPTION = 0; //LED_ATR_OPTION_REGISTER:LED0_ATR_OPTION
|
||||
localparam LED1_ATR_OPTION_SIZE = 1; //LED_ATR_OPTION_REGISTER:LED1_ATR_OPTION
|
||||
localparam LED1_ATR_OPTION_MSB = 1; //LED_ATR_OPTION_REGISTER:LED1_ATR_OPTION
|
||||
localparam LED1_ATR_OPTION = 1; //LED_ATR_OPTION_REGISTER:LED1_ATR_OPTION
|
||||
localparam LED2_ATR_OPTION_SIZE = 1; //LED_ATR_OPTION_REGISTER:LED2_ATR_OPTION
|
||||
localparam LED2_ATR_OPTION_MSB = 2; //LED_ATR_OPTION_REGISTER:LED2_ATR_OPTION
|
||||
localparam LED2_ATR_OPTION = 2; //LED_ATR_OPTION_REGISTER:LED2_ATR_OPTION
|
||||
localparam LED3_ATR_OPTION_SIZE = 1; //LED_ATR_OPTION_REGISTER:LED3_ATR_OPTION
|
||||
localparam LED3_ATR_OPTION_MSB = 3; //LED_ATR_OPTION_REGISTER:LED3_ATR_OPTION
|
||||
localparam LED3_ATR_OPTION = 3; //LED_ATR_OPTION_REGISTER:LED3_ATR_OPTION
|
||||
|
||||
// LED_ATR_DISABLED Register (from led_atr_control.v)
|
||||
localparam LED_ATR_DISABLED = 'h1004; // Register Offset
|
||||
localparam LED_ATR_DISABLED_SIZE = 32; // register width in bits
|
||||
localparam LED_ATR_DISABLED_MASK = 32'hF;
|
||||
localparam LED0_ATR_DISABLED_SIZE = 1; //LED_ATR_DISABLED:LED0_ATR_DISABLED
|
||||
localparam LED0_ATR_DISABLED_MSB = 0; //LED_ATR_DISABLED:LED0_ATR_DISABLED
|
||||
localparam LED0_ATR_DISABLED = 0; //LED_ATR_DISABLED:LED0_ATR_DISABLED
|
||||
localparam LED1_ATR_DISABLED_SIZE = 1; //LED_ATR_DISABLED:LED1_ATR_DISABLED
|
||||
localparam LED1_ATR_DISABLED_MSB = 1; //LED_ATR_DISABLED:LED1_ATR_DISABLED
|
||||
localparam LED1_ATR_DISABLED = 1; //LED_ATR_DISABLED:LED1_ATR_DISABLED
|
||||
localparam LED2_ATR_DISABLED_SIZE = 1; //LED_ATR_DISABLED:LED2_ATR_DISABLED
|
||||
localparam LED2_ATR_DISABLED_MSB = 2; //LED_ATR_DISABLED:LED2_ATR_DISABLED
|
||||
localparam LED2_ATR_DISABLED = 2; //LED_ATR_DISABLED:LED2_ATR_DISABLED
|
||||
localparam LED3_ATR_DISABLED_SIZE = 1; //LED_ATR_DISABLED:LED3_ATR_DISABLED
|
||||
localparam LED3_ATR_DISABLED_MSB = 3; //LED_ATR_DISABLED:LED3_ATR_DISABLED
|
||||
localparam LED3_ATR_DISABLED = 3; //LED_ATR_DISABLED:LED3_ATR_DISABLED
|
||||
|
||||
// Return the offset of an element of register array LED0_ATR_STATE
|
||||
function integer LED0_ATR_STATE (input integer i);
|
||||
LED0_ATR_STATE = (i * 'h4) + 'h0;
|
||||
endfunction
|
||||
|
||||
// Return the offset of an element of register array LED1_ATR_STATE
|
||||
function integer LED1_ATR_STATE (input integer i);
|
||||
LED1_ATR_STATE = (i * 'h4) + 'h400;
|
||||
endfunction
|
||||
|
||||
// Return the offset of an element of register array LED2_ATR_STATE
|
||||
function integer LED2_ATR_STATE (input integer i);
|
||||
LED2_ATR_STATE = (i * 'h4) + 'h800;
|
||||
endfunction
|
||||
|
||||
// Return the offset of an element of register array LED3_ATR_STATE
|
||||
function integer LED3_ATR_STATE (input integer i);
|
||||
LED3_ATR_STATE = (i * 'h4) + 'hC00;
|
||||
endfunction
|
||||
@@ -0,0 +1,110 @@
|
||||
//
|
||||
// Copyright 2023 Ettus Research, A National Instruments Company
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: rf_atr_regmap_utils.vh
|
||||
// Description:
|
||||
// The constants in this file are autogenerated by XmlParse.
|
||||
|
||||
//===============================================================================
|
||||
// A numerically ordered list of registers and their HDL source files
|
||||
//===============================================================================
|
||||
|
||||
// RF0_ATR_STATE : 0x0 (rf_atr_control.v)
|
||||
// RF1_ATR_STATE : 0x400 (rf_atr_control.v)
|
||||
// RF2_ATR_STATE : 0x800 (rf_atr_control.v)
|
||||
// RF3_ATR_STATE : 0xC00 (rf_atr_control.v)
|
||||
// ATR_OPTION_REGISTER : 0x1000 (rf_atr_control.v)
|
||||
// RF_ATR_DISABLED : 0x1004 (rf_atr_control.v)
|
||||
|
||||
//===============================================================================
|
||||
// RegTypes
|
||||
//===============================================================================
|
||||
|
||||
// RF_ATR_STATE Type (from rf_atr_control.v)
|
||||
localparam RF_ATR_STATE_SIZE = 32;
|
||||
localparam RF_ATR_STATE_MASK = 32'h7;
|
||||
localparam TX_RX_RFS_SIZE = 1; //RF_ATR_STATE:TX_RX_RFS
|
||||
localparam TX_RX_RFS_MSB = 0; //RF_ATR_STATE:TX_RX_RFS
|
||||
localparam TX_RX_RFS = 0; //RF_ATR_STATE:TX_RX_RFS
|
||||
localparam RX_RFS_SIZE = 1; //RF_ATR_STATE:RX_RFS
|
||||
localparam RX_RFS_MSB = 1; //RF_ATR_STATE:RX_RFS
|
||||
localparam RX_RFS = 1; //RF_ATR_STATE:RX_RFS
|
||||
localparam TDDS_SIZE = 1; //RF_ATR_STATE:TDDS
|
||||
localparam TDDS_MSB = 2; //RF_ATR_STATE:TDDS
|
||||
localparam TDDS = 2; //RF_ATR_STATE:TDDS
|
||||
|
||||
//===============================================================================
|
||||
// Register Group RF_ATR_REGISTERS
|
||||
//===============================================================================
|
||||
|
||||
// Enumerated type RF_SWITCHES_SIZE_TYPE
|
||||
localparam RF_SWITCHES_SIZE_TYPE_SIZE = 1;
|
||||
localparam RFS_SIZE = 'h3; // RF_SWITCHES_SIZE_TYPE:RFS_SIZE
|
||||
|
||||
// RF0_ATR_STATE Register (from rf_atr_control.v)
|
||||
localparam RF0_ATR_STATE_COUNT = 256; // Number of elements in array
|
||||
|
||||
// RF1_ATR_STATE Register (from rf_atr_control.v)
|
||||
localparam RF1_ATR_STATE_COUNT = 256; // Number of elements in array
|
||||
|
||||
// RF2_ATR_STATE Register (from rf_atr_control.v)
|
||||
localparam RF2_ATR_STATE_COUNT = 256; // Number of elements in array
|
||||
|
||||
// RF3_ATR_STATE Register (from rf_atr_control.v)
|
||||
localparam RF3_ATR_STATE_COUNT = 256; // Number of elements in array
|
||||
|
||||
// ATR_OPTION_REGISTER Register (from rf_atr_control.v)
|
||||
localparam ATR_OPTION_REGISTER = 'h1000; // Register Offset
|
||||
localparam ATR_OPTION_REGISTER_SIZE = 32; // register width in bits
|
||||
localparam ATR_OPTION_REGISTER_MASK = 32'hF;
|
||||
localparam RF0_ATR_OPTION_SIZE = 1; //ATR_OPTION_REGISTER:RF0_ATR_OPTION
|
||||
localparam RF0_ATR_OPTION_MSB = 0; //ATR_OPTION_REGISTER:RF0_ATR_OPTION
|
||||
localparam RF0_ATR_OPTION = 0; //ATR_OPTION_REGISTER:RF0_ATR_OPTION
|
||||
localparam RF1_ATR_OPTION_SIZE = 1; //ATR_OPTION_REGISTER:RF1_ATR_OPTION
|
||||
localparam RF1_ATR_OPTION_MSB = 1; //ATR_OPTION_REGISTER:RF1_ATR_OPTION
|
||||
localparam RF1_ATR_OPTION = 1; //ATR_OPTION_REGISTER:RF1_ATR_OPTION
|
||||
localparam RF2_ATR_OPTION_SIZE = 1; //ATR_OPTION_REGISTER:RF2_ATR_OPTION
|
||||
localparam RF2_ATR_OPTION_MSB = 2; //ATR_OPTION_REGISTER:RF2_ATR_OPTION
|
||||
localparam RF2_ATR_OPTION = 2; //ATR_OPTION_REGISTER:RF2_ATR_OPTION
|
||||
localparam RF3_ATR_OPTION_SIZE = 1; //ATR_OPTION_REGISTER:RF3_ATR_OPTION
|
||||
localparam RF3_ATR_OPTION_MSB = 3; //ATR_OPTION_REGISTER:RF3_ATR_OPTION
|
||||
localparam RF3_ATR_OPTION = 3; //ATR_OPTION_REGISTER:RF3_ATR_OPTION
|
||||
|
||||
// RF_ATR_DISABLED Register (from rf_atr_control.v)
|
||||
localparam RF_ATR_DISABLED = 'h1004; // Register Offset
|
||||
localparam RF_ATR_DISABLED_SIZE = 32; // register width in bits
|
||||
localparam RF_ATR_DISABLED_MASK = 32'hF;
|
||||
localparam RF0_ATR_DISABLED_SIZE = 1; //RF_ATR_DISABLED:RF0_ATR_DISABLED
|
||||
localparam RF0_ATR_DISABLED_MSB = 0; //RF_ATR_DISABLED:RF0_ATR_DISABLED
|
||||
localparam RF0_ATR_DISABLED = 0; //RF_ATR_DISABLED:RF0_ATR_DISABLED
|
||||
localparam RF1_ATR_DISABLED_SIZE = 1; //RF_ATR_DISABLED:RF1_ATR_DISABLED
|
||||
localparam RF1_ATR_DISABLED_MSB = 1; //RF_ATR_DISABLED:RF1_ATR_DISABLED
|
||||
localparam RF1_ATR_DISABLED = 1; //RF_ATR_DISABLED:RF1_ATR_DISABLED
|
||||
localparam RF2_ATR_DISABLED_SIZE = 1; //RF_ATR_DISABLED:RF2_ATR_DISABLED
|
||||
localparam RF2_ATR_DISABLED_MSB = 2; //RF_ATR_DISABLED:RF2_ATR_DISABLED
|
||||
localparam RF2_ATR_DISABLED = 2; //RF_ATR_DISABLED:RF2_ATR_DISABLED
|
||||
localparam RF3_ATR_DISABLED_SIZE = 1; //RF_ATR_DISABLED:RF3_ATR_DISABLED
|
||||
localparam RF3_ATR_DISABLED_MSB = 3; //RF_ATR_DISABLED:RF3_ATR_DISABLED
|
||||
localparam RF3_ATR_DISABLED = 3; //RF_ATR_DISABLED:RF3_ATR_DISABLED
|
||||
|
||||
// Return the offset of an element of register array RF0_ATR_STATE
|
||||
function integer RF0_ATR_STATE (input integer i);
|
||||
RF0_ATR_STATE = (i * 'h4) + 'h0;
|
||||
endfunction
|
||||
|
||||
// Return the offset of an element of register array RF1_ATR_STATE
|
||||
function integer RF1_ATR_STATE (input integer i);
|
||||
RF1_ATR_STATE = (i * 'h4) + 'h400;
|
||||
endfunction
|
||||
|
||||
// Return the offset of an element of register array RF2_ATR_STATE
|
||||
function integer RF2_ATR_STATE (input integer i);
|
||||
RF2_ATR_STATE = (i * 'h4) + 'h800;
|
||||
endfunction
|
||||
|
||||
// Return the offset of an element of register array RF3_ATR_STATE
|
||||
function integer RF3_ATR_STATE (input integer i);
|
||||
RF3_ATR_STATE = (i * 'h4) + 'hC00;
|
||||
endfunction
|
||||
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Copyright 2023 Ettus Research, A National Instruments Company
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: rf_sync_regmap_utils.vh
|
||||
// Description:
|
||||
// The constants in this file are autogenerated by XmlParse.
|
||||
|
||||
//===============================================================================
|
||||
// A numerically ordered list of registers and their HDL source files
|
||||
//===============================================================================
|
||||
|
||||
// SYNC_1_REG : 0x0 (ctrlport_to_i2c_sync_ctrl.v)
|
||||
// SYNC_2_REG : 0x4 (ctrlport_to_i2c_sync_ctrl.v)
|
||||
// SYNC_3_REG : 0x8 (ctrlport_to_i2c_sync_ctrl.v)
|
||||
// SYNC_4_REG : 0xC (ctrlport_to_i2c_sync_ctrl.v)
|
||||
// SYNC_5_REG : 0x10 (ctrlport_to_i2c_sync_ctrl.v)
|
||||
// RFS_EN_REG : 0x14 (ctrlport_to_i2c_sync_ctrl.v)
|
||||
// SETUP_REG/SETUP_STATUS_REG : 0x18 (ctrlport_to_i2c_sync_ctrl.v, ctrlport_to_i2c_sync_ctrl.v)
|
||||
// CONFIG_IO_REG/CONFIG_IO_STATUS_REG : 0x1C (ctrlport_to_i2c_sync_ctrl.v, ctrlport_to_i2c_sync_ctrl.v)
|
||||
|
||||
//===============================================================================
|
||||
// RegTypes
|
||||
//===============================================================================
|
||||
|
||||
// SYNC_SWITCH Type (from ctrlport_to_i2c_sync_ctrl.v)
|
||||
localparam SYNC_SWITCH_SIZE = 32;
|
||||
localparam SYNC_SWITCH_MASK = 32'h7;
|
||||
localparam CONTROL_PIN_V1_SIZE = 1; //SYNC_SWITCH:CONTROL_PIN_V1
|
||||
localparam CONTROL_PIN_V1_MSB = 0; //SYNC_SWITCH:CONTROL_PIN_V1
|
||||
localparam CONTROL_PIN_V1 = 0; //SYNC_SWITCH:CONTROL_PIN_V1
|
||||
localparam CONTROL_PIN_V2_SIZE = 1; //SYNC_SWITCH:CONTROL_PIN_V2
|
||||
localparam CONTROL_PIN_V2_MSB = 1; //SYNC_SWITCH:CONTROL_PIN_V2
|
||||
localparam CONTROL_PIN_V2 = 1; //SYNC_SWITCH:CONTROL_PIN_V2
|
||||
localparam CONTROL_PIN_V3_SIZE = 1; //SYNC_SWITCH:CONTROL_PIN_V3
|
||||
localparam CONTROL_PIN_V3_MSB = 2; //SYNC_SWITCH:CONTROL_PIN_V3
|
||||
localparam CONTROL_PIN_V3 = 2; //SYNC_SWITCH:CONTROL_PIN_V3
|
||||
|
||||
//===============================================================================
|
||||
// Register Group RF_SYNC_REGISTERS
|
||||
//===============================================================================
|
||||
|
||||
// Enumerated type IO_EXPANDER_REGISTER_ADRS
|
||||
localparam IO_EXPANDER_REGISTER_ADRS_SIZE = 8;
|
||||
localparam IO_EXP_INPUT_PORT0_REG = 'h0; // IO_EXPANDER_REGISTER_ADRS:IO_EXP_INPUT_PORT0_REG
|
||||
localparam IO_EXP_INPUT_PORT1_REG = 'h1; // IO_EXPANDER_REGISTER_ADRS:IO_EXP_INPUT_PORT1_REG
|
||||
localparam IO_EXP_OUTPUT_PORT0_REG = 'h2; // IO_EXPANDER_REGISTER_ADRS:IO_EXP_OUTPUT_PORT0_REG
|
||||
localparam IO_EXP_OUTPUT_PORT1_REG = 'h3; // IO_EXPANDER_REGISTER_ADRS:IO_EXP_OUTPUT_PORT1_REG
|
||||
localparam IO_EXP_POLARITY_INV0_REG = 'h4; // IO_EXPANDER_REGISTER_ADRS:IO_EXP_POLARITY_INV0_REG
|
||||
localparam IO_EXP_POLARITY_INV1_REG = 'h5; // IO_EXPANDER_REGISTER_ADRS:IO_EXP_POLARITY_INV1_REG
|
||||
localparam IO_EXP_CONFIG0_REG = 'h6; // IO_EXPANDER_REGISTER_ADRS:IO_EXP_CONFIG0_REG
|
||||
localparam IO_EXP_CONFIG1_REG = 'h7; // IO_EXPANDER_REGISTER_ADRS:IO_EXP_CONFIG1_REG
|
||||
|
||||
// SYNC_1_REG Register (from ctrlport_to_i2c_sync_ctrl.v)
|
||||
localparam SYNC_1_REG = 'h0; // Register Offset
|
||||
localparam SYNC_1_REG_SIZE = 32; // register width in bits
|
||||
|
||||
// SYNC_2_REG Register (from ctrlport_to_i2c_sync_ctrl.v)
|
||||
localparam SYNC_2_REG = 'h4; // Register Offset
|
||||
localparam SYNC_2_REG_SIZE = 32; // register width in bits
|
||||
|
||||
// SYNC_3_REG Register (from ctrlport_to_i2c_sync_ctrl.v)
|
||||
localparam SYNC_3_REG = 'h8; // Register Offset
|
||||
localparam SYNC_3_REG_SIZE = 32; // register width in bits
|
||||
|
||||
// SYNC_4_REG Register (from ctrlport_to_i2c_sync_ctrl.v)
|
||||
localparam SYNC_4_REG = 'hC; // Register Offset
|
||||
localparam SYNC_4_REG_SIZE = 32; // register width in bits
|
||||
|
||||
// SYNC_5_REG Register (from ctrlport_to_i2c_sync_ctrl.v)
|
||||
localparam SYNC_5_REG = 'h10; // Register Offset
|
||||
localparam SYNC_5_REG_SIZE = 32; // register width in bits
|
||||
|
||||
// RFS_EN_REG Register (from ctrlport_to_i2c_sync_ctrl.v)
|
||||
localparam RFS_EN_REG = 'h14; // Register Offset
|
||||
localparam RFS_EN_REG_SIZE = 32; // register width in bits
|
||||
localparam RFS_EN_REG_MASK = 32'h1;
|
||||
localparam RFS_EN_PIN_SIZE = 1; //RFS_EN_REG:RFS_EN_PIN
|
||||
localparam RFS_EN_PIN_MSB = 0; //RFS_EN_REG:RFS_EN_PIN
|
||||
localparam RFS_EN_PIN = 0; //RFS_EN_REG:RFS_EN_PIN
|
||||
|
||||
// SETUP_REG Register (from ctrlport_to_i2c_sync_ctrl.v)
|
||||
localparam SETUP_REG = 'h18; // Register Offset
|
||||
localparam SETUP_REG_SIZE = 32; // register width in bits
|
||||
localparam SETUP_REG_MASK = 32'h1;
|
||||
localparam SETUP_TRIG_SIZE = 1; //SETUP_REG:SETUP_TRIG
|
||||
localparam SETUP_TRIG_MSB = 0; //SETUP_REG:SETUP_TRIG
|
||||
localparam SETUP_TRIG = 0; //SETUP_REG:SETUP_TRIG
|
||||
|
||||
// SETUP_STATUS_REG Register (from ctrlport_to_i2c_sync_ctrl.v)
|
||||
localparam SETUP_STATUS_REG = 'h18; // Register Offset
|
||||
localparam SETUP_STATUS_REG_SIZE = 32; // register width in bits
|
||||
localparam SETUP_STATUS_REG_MASK = 32'h1;
|
||||
localparam SETUP_STATUS_SIZE = 1; //SETUP_STATUS_REG:SETUP_STATUS
|
||||
localparam SETUP_STATUS_MSB = 0; //SETUP_STATUS_REG:SETUP_STATUS
|
||||
localparam SETUP_STATUS = 0; //SETUP_STATUS_REG:SETUP_STATUS
|
||||
|
||||
// CONFIG_IO_REG Register (from ctrlport_to_i2c_sync_ctrl.v)
|
||||
localparam CONFIG_IO_REG = 'h1C; // Register Offset
|
||||
localparam CONFIG_IO_REG_SIZE = 32; // register width in bits
|
||||
localparam CONFIG_IO_REG_MASK = 32'h1;
|
||||
localparam CONFIG_IO_TRIG_SIZE = 1; //CONFIG_IO_REG:CONFIG_IO_TRIG
|
||||
localparam CONFIG_IO_TRIG_MSB = 0; //CONFIG_IO_REG:CONFIG_IO_TRIG
|
||||
localparam CONFIG_IO_TRIG = 0; //CONFIG_IO_REG:CONFIG_IO_TRIG
|
||||
|
||||
// CONFIG_IO_STATUS_REG Register (from ctrlport_to_i2c_sync_ctrl.v)
|
||||
localparam CONFIG_IO_STATUS_REG = 'h1C; // Register Offset
|
||||
localparam CONFIG_IO_STATUS_REG_SIZE = 32; // register width in bits
|
||||
localparam CONFIG_IO_STATUS_REG_MASK = 32'h1;
|
||||
localparam CONFIG_IO_STATUS_SIZE = 1; //CONFIG_IO_STATUS_REG:CONFIG_IO_STATUS
|
||||
localparam CONFIG_IO_STATUS_MSB = 0; //CONFIG_IO_STATUS_REG:CONFIG_IO_STATUS
|
||||
localparam CONFIG_IO_STATUS = 0; //CONFIG_IO_STATUS_REG:CONFIG_IO_STATUS
|
||||
@@ -0,0 +1,519 @@
|
||||
//
|
||||
// Copyright 2022 Ettus Research, A National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: rf_atr_control
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Implements control over RF switches via CtrlPort. Uses RAM to store multiple
|
||||
// ATR configurations.
|
||||
// There are three supported control schemes for these switches:
|
||||
// - ATR Disabled - Single persistent state.
|
||||
// - Classic ATR - Each channel's switches depend on the transmission state
|
||||
// of the respective channel.
|
||||
// - DB State - Each channel's switches depend on the transmission state
|
||||
// of all channels in this radio.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// REG_BASE : Base address to use for registers.
|
||||
// REG_SIZE : Register space size.
|
||||
//
|
||||
|
||||
module rf_atr_control #(
|
||||
parameter REG_BASE = 0,
|
||||
parameter REG_SIZE = 'h2000
|
||||
) (
|
||||
// Slave ctrlport interface
|
||||
input wire ctrlport_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,
|
||||
output reg s_ctrlport_resp_ack = 1'b0,
|
||||
output reg [ 1:0] s_ctrlport_resp_status = 2'b00,
|
||||
output reg [31:0] s_ctrlport_resp_data = {32 {1'b0}},
|
||||
// Run state signals that indicate tx and rx operation
|
||||
input wire [7:0] db_state,
|
||||
// Switch control outputs
|
||||
output reg rf0_tx_rx_rfs,
|
||||
output reg rf0_rx_rfs,
|
||||
output reg rf0_tdds,
|
||||
output reg rf1_tx_rx_rfs,
|
||||
output reg rf1_rx_rfs,
|
||||
output reg rf1_tdds,
|
||||
output reg rf2_tx_rx_rfs,
|
||||
output reg rf2_rx_rfs,
|
||||
output reg rf2_tdds,
|
||||
output reg rf3_tx_rx_rfs,
|
||||
output reg rf3_rx_rfs,
|
||||
output reg rf3_tdds
|
||||
);
|
||||
|
||||
`include "../../../../lib/rfnoc/core/ctrlport.vh"
|
||||
`include "regmap/rf_atr_regmap_utils.vh"
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// ATR memory signals
|
||||
//---------------------------------------------------------------
|
||||
reg ram_rf0_wea;
|
||||
wire [RFS_SIZE-1:0] ram_rf0_doa;
|
||||
wire [RFS_SIZE-1:0] ram_rf0_dob;
|
||||
|
||||
reg ram_rf1_wea;
|
||||
wire [RFS_SIZE-1:0] ram_rf1_doa;
|
||||
wire [RFS_SIZE-1:0] ram_rf1_dob;
|
||||
|
||||
reg ram_rf2_wea;
|
||||
wire [RFS_SIZE-1:0] ram_rf2_doa;
|
||||
wire [RFS_SIZE-1:0] ram_rf2_dob;
|
||||
|
||||
reg ram_rf3_wea;
|
||||
wire [RFS_SIZE-1:0] ram_rf3_doa;
|
||||
wire [RFS_SIZE-1:0] ram_rf3_dob;
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// ATR Scheme signals
|
||||
//---------------------------------------------------------------
|
||||
reg [3:0] atr_disable = 4'b0;
|
||||
|
||||
// DB state/Classic ATR selector
|
||||
reg [3:0] atr_mode = 4'b0;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Control interface handling
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Check that address is within this module's range.
|
||||
wire address_in_range = (s_ctrlport_req_addr >= REG_BASE) && (s_ctrlport_req_addr < REG_BASE + REG_SIZE);
|
||||
|
||||
// Check that address is targeting an ATR state.
|
||||
wire address_is_atr = (s_ctrlport_req_addr >= REG_BASE + RF0_ATR_STATE(0)) && (s_ctrlport_req_addr <= REG_BASE + RF3_ATR_STATE(RF3_ATR_STATE_COUNT-1));
|
||||
|
||||
// Read request shift register to align memory read and response generation.
|
||||
reg [ 1:0] read_req_shift_reg = 2'b0;
|
||||
// Mask out 8 bits for ATR configurations to be able to compare all ATR
|
||||
// configurations against the same base register address.
|
||||
wire [31:0] register_base_address = {s_ctrlport_req_addr[19:10], 8'b0, s_ctrlport_req_addr[1:0]};
|
||||
// Decode the ATR state being addressed.
|
||||
wire [ 7:0] atr_address = s_ctrlport_req_addr[9:2];
|
||||
|
||||
always @ (posedge ctrlport_clk) begin
|
||||
if (ctrlport_rst) begin
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
s_ctrlport_resp_data <= 32'b0;
|
||||
s_ctrlport_resp_status <= 2'b00;
|
||||
|
||||
atr_disable <= 4'b0;
|
||||
atr_mode <= 4'b0;
|
||||
|
||||
ram_rf0_wea <= 1'b0;
|
||||
ram_rf1_wea <= 1'b0;
|
||||
ram_rf2_wea <= 1'b0;
|
||||
ram_rf3_wea <= 1'b0;
|
||||
|
||||
end else begin
|
||||
// default assignments
|
||||
read_req_shift_reg <= {read_req_shift_reg[0], s_ctrlport_req_rd};
|
||||
|
||||
ram_rf0_wea <= 1'b0;
|
||||
ram_rf1_wea <= 1'b0;
|
||||
ram_rf2_wea <= 1'b0;
|
||||
ram_rf3_wea <= 1'b0;
|
||||
|
||||
// Write registers
|
||||
if (s_ctrlport_req_wr) begin
|
||||
// Acknowledge by default
|
||||
s_ctrlport_resp_ack <= 1'b1;
|
||||
s_ctrlport_resp_status <= CTRL_STS_OKAY;
|
||||
|
||||
// Address ATR state writes
|
||||
if(address_is_atr) begin
|
||||
|
||||
case (register_base_address)
|
||||
REG_BASE + RF0_ATR_STATE(0): begin
|
||||
ram_rf0_wea <= 1'b1;
|
||||
end
|
||||
|
||||
REG_BASE + RF1_ATR_STATE(0): begin
|
||||
ram_rf1_wea <= 1'b1;
|
||||
end
|
||||
|
||||
REG_BASE + RF2_ATR_STATE(0): begin
|
||||
ram_rf2_wea <= 1'b1;
|
||||
end
|
||||
|
||||
REG_BASE + RF3_ATR_STATE(0): begin
|
||||
ram_rf3_wea <= 1'b1;
|
||||
end
|
||||
|
||||
// error on undefined address
|
||||
default: begin
|
||||
s_ctrlport_resp_status <= CTRL_STS_CMDERR;
|
||||
end
|
||||
endcase
|
||||
end else begin
|
||||
|
||||
// Address writes to the rest of the register space
|
||||
case (s_ctrlport_req_addr)
|
||||
|
||||
REG_BASE + ATR_OPTION_REGISTER: begin
|
||||
atr_mode[0] <= s_ctrlport_req_data[RF0_ATR_OPTION];
|
||||
atr_mode[1] <= s_ctrlport_req_data[RF1_ATR_OPTION];
|
||||
atr_mode[2] <= s_ctrlport_req_data[RF2_ATR_OPTION];
|
||||
atr_mode[3] <= s_ctrlport_req_data[RF3_ATR_OPTION];
|
||||
end
|
||||
|
||||
REG_BASE + RF_ATR_DISABLED: begin
|
||||
atr_disable[0] <= s_ctrlport_req_data[RF0_ATR_DISABLED];
|
||||
atr_disable[1] <= s_ctrlport_req_data[RF1_ATR_DISABLED];
|
||||
atr_disable[2] <= s_ctrlport_req_data[RF2_ATR_DISABLED];
|
||||
atr_disable[3] <= s_ctrlport_req_data[RF3_ATR_DISABLED];
|
||||
end
|
||||
|
||||
// No register implementation for provided address
|
||||
default: begin
|
||||
// Acknowledge and provide error status if address is in range
|
||||
if (address_in_range) begin
|
||||
s_ctrlport_resp_status <= CTRL_STS_CMDERR;
|
||||
|
||||
// No response if out of range
|
||||
end else begin
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
// Read registers
|
||||
end else if (read_req_shift_reg[1]) begin
|
||||
// Acknowledge by default
|
||||
s_ctrlport_resp_ack <= 1'b1;
|
||||
s_ctrlport_resp_status <= CTRL_STS_OKAY;
|
||||
|
||||
// Address ATR state reads
|
||||
if(address_is_atr) begin
|
||||
|
||||
case (register_base_address)
|
||||
REG_BASE + RF0_ATR_STATE(0): begin
|
||||
s_ctrlport_resp_data <= ram_rf0_doa & RF_ATR_STATE_MASK;
|
||||
end
|
||||
REG_BASE + RF1_ATR_STATE(0): begin
|
||||
s_ctrlport_resp_data <= ram_rf1_doa & RF_ATR_STATE_MASK;
|
||||
end
|
||||
REG_BASE + RF2_ATR_STATE(0): begin
|
||||
s_ctrlport_resp_data <= ram_rf2_doa & RF_ATR_STATE_MASK;
|
||||
end
|
||||
REG_BASE + RF3_ATR_STATE(0): begin
|
||||
s_ctrlport_resp_data <= ram_rf3_doa & RF_ATR_STATE_MASK;
|
||||
end
|
||||
|
||||
default: begin
|
||||
s_ctrlport_resp_status <= CTRL_STS_CMDERR;
|
||||
end
|
||||
endcase
|
||||
|
||||
end else begin
|
||||
|
||||
// Address reads to the rest of the register space
|
||||
case (s_ctrlport_req_addr)
|
||||
|
||||
REG_BASE + ATR_OPTION_REGISTER: begin
|
||||
s_ctrlport_resp_data[RF0_ATR_OPTION] <= atr_mode[0];
|
||||
s_ctrlport_resp_data[RF1_ATR_OPTION] <= atr_mode[1];
|
||||
s_ctrlport_resp_data[RF2_ATR_OPTION] <= atr_mode[2];
|
||||
s_ctrlport_resp_data[RF3_ATR_OPTION] <= atr_mode[3];
|
||||
end
|
||||
|
||||
REG_BASE + RF_ATR_DISABLED: begin
|
||||
s_ctrlport_resp_data[RF0_ATR_DISABLED] <= atr_disable[0];
|
||||
s_ctrlport_resp_data[RF1_ATR_DISABLED] <= atr_disable[1];
|
||||
s_ctrlport_resp_data[RF2_ATR_DISABLED] <= atr_disable[2];
|
||||
s_ctrlport_resp_data[RF3_ATR_DISABLED] <= atr_disable[3];
|
||||
end
|
||||
|
||||
// No register implementation for provided address
|
||||
default: begin
|
||||
// Acknowledge and provide error status if address is in range
|
||||
if (address_in_range) begin
|
||||
s_ctrlport_resp_status <= CTRL_STS_CMDERR;
|
||||
|
||||
// No response if out of range
|
||||
end else begin
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
end else begin
|
||||
s_ctrlport_resp_ack <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// register without reset
|
||||
reg [ 7:0] ram_addr = 8'b0;
|
||||
reg [RFS_SIZE-1:0] ram_datain = {RFS_SIZE{1'b0}};
|
||||
always @(posedge ctrlport_clk) begin
|
||||
// memories
|
||||
ram_addr <= atr_address;
|
||||
ram_datain <= s_ctrlport_req_data[RFS_SIZE-1:0];
|
||||
end
|
||||
|
||||
// ATR Scheme selection
|
||||
reg [7:0] atr_config_rf [3:0];
|
||||
|
||||
generate
|
||||
genvar i;
|
||||
for (i = 0; i < 4; i = i + 1) begin: read_address_gen
|
||||
|
||||
always @(posedge ctrlport_clk) begin
|
||||
if (atr_disable[i]) begin
|
||||
atr_config_rf[i] <= 8'b0;
|
||||
end else begin
|
||||
if (atr_mode[i]) begin
|
||||
atr_config_rf[i] <= {6'b0, db_state[2*i+:2]};
|
||||
end else begin
|
||||
atr_config_rf[i] <= db_state;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
// Output decoding
|
||||
always @(posedge ctrlport_clk) begin
|
||||
rf0_tx_rx_rfs <= ram_rf0_dob[TX_RX_RFS];
|
||||
rf0_rx_rfs <= ram_rf0_dob[RX_RFS];
|
||||
rf0_tdds <= ram_rf0_dob[TDDS];
|
||||
|
||||
rf1_tx_rx_rfs <= ram_rf1_dob[TX_RX_RFS];
|
||||
rf1_rx_rfs <= ram_rf1_dob[RX_RFS];
|
||||
rf1_tdds <= ram_rf1_dob[TDDS];
|
||||
|
||||
rf2_tx_rx_rfs <= ram_rf2_dob[TX_RX_RFS];
|
||||
rf2_rx_rfs <= ram_rf2_dob[RX_RFS];
|
||||
rf2_tdds <= ram_rf2_dob[TDDS];
|
||||
|
||||
rf3_tx_rx_rfs <= ram_rf3_dob[TX_RX_RFS];
|
||||
rf3_rx_rfs <= ram_rf3_dob[RX_RFS];
|
||||
rf3_tdds <= ram_rf3_dob[TDDS];
|
||||
end
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// ATR memory
|
||||
//---------------------------------------------------------------
|
||||
ram_2port #(
|
||||
.DWIDTH (RFS_SIZE),
|
||||
.AWIDTH (8),
|
||||
.RW_MODE ("READ-FIRST"),
|
||||
.RAM_TYPE ("AUTOMATIC"),
|
||||
.OUT_REG (0)
|
||||
) ram_rf0_i (
|
||||
.clka (ctrlport_clk),
|
||||
.ena (1'b1),
|
||||
.wea (ram_rf0_wea),
|
||||
.addra (ram_addr),
|
||||
.dia (ram_datain),
|
||||
.doa (ram_rf0_doa),
|
||||
.clkb (ctrlport_clk),
|
||||
.enb (1'b1),
|
||||
.web (1'b0),
|
||||
.addrb (atr_config_rf[0]),
|
||||
.dib ({RFS_SIZE{1'b0}}),
|
||||
.dob (ram_rf0_dob));
|
||||
|
||||
ram_2port #(
|
||||
.DWIDTH (RFS_SIZE),
|
||||
.AWIDTH (8),
|
||||
.RW_MODE ("READ-FIRST"),
|
||||
.RAM_TYPE ("AUTOMATIC"),
|
||||
.OUT_REG (0)
|
||||
) ram_rf1_i (
|
||||
.clka (ctrlport_clk),
|
||||
.ena (1'b1),
|
||||
.wea (ram_rf1_wea),
|
||||
.addra (ram_addr),
|
||||
.dia (ram_datain),
|
||||
.doa (ram_rf1_doa),
|
||||
.clkb (ctrlport_clk),
|
||||
.enb (1'b1),
|
||||
.web (1'b0),
|
||||
.addrb (atr_config_rf[1]),
|
||||
.dib ({RFS_SIZE{1'b0}}),
|
||||
.dob (ram_rf1_dob));
|
||||
|
||||
ram_2port #(
|
||||
.DWIDTH (RFS_SIZE),
|
||||
.AWIDTH (8),
|
||||
.RW_MODE ("READ-FIRST"),
|
||||
.RAM_TYPE ("AUTOMATIC"),
|
||||
.OUT_REG (0)
|
||||
) ram_rf2_i (
|
||||
.clka (ctrlport_clk),
|
||||
.ena (1'b1),
|
||||
.wea (ram_rf2_wea),
|
||||
.addra (ram_addr),
|
||||
.dia (ram_datain),
|
||||
.doa (ram_rf2_doa),
|
||||
.clkb (ctrlport_clk),
|
||||
.enb (1'b1),
|
||||
.web (1'b0),
|
||||
.addrb (atr_config_rf[2]),
|
||||
.dib ({RFS_SIZE{1'b0}}),
|
||||
.dob (ram_rf2_dob));
|
||||
|
||||
ram_2port #(
|
||||
.DWIDTH (RFS_SIZE),
|
||||
.AWIDTH (8),
|
||||
.RW_MODE ("READ-FIRST"),
|
||||
.RAM_TYPE ("AUTOMATIC"),
|
||||
.OUT_REG (0)
|
||||
) ram_rf3_i (
|
||||
.clka (ctrlport_clk),
|
||||
.ena (1'b1),
|
||||
.wea (ram_rf3_wea),
|
||||
.addra (ram_addr),
|
||||
.dia (ram_datain),
|
||||
.doa (ram_rf3_doa),
|
||||
.clkb (ctrlport_clk),
|
||||
.enb (1'b1),
|
||||
.web (1'b0),
|
||||
.addrb (atr_config_rf[3]),
|
||||
.dib ({RFS_SIZE{1'b0}}),
|
||||
.dob (ram_rf3_dob));
|
||||
|
||||
endmodule
|
||||
|
||||
//XmlParse xml_on
|
||||
//<regmap name="RF_ATR_REGMAP" readablestrobes="false" generatevhdl="true" ettusguidelines="true">
|
||||
// <group name="RF_ATR_REGISTERS">
|
||||
// <info>
|
||||
// Each channel in the FBX daughterboard has 4 switches in its path. 3 of these are HMC849A 2:1
|
||||
// switches and the last one is a PE42442 4:1 switch. The latter, as well as the enable lines for
|
||||
// all four switches are not considered time critical controls, and are hence driven by an I/O
|
||||
// expander controlled via I2C.
|
||||
// This register map describes how to control the behavior of the 3 HMC849A switches' control lines.
|
||||
// There are three supported control schemes for these switches:</br>
|
||||
// <ul>
|
||||
// <li>ATR Disabled - Single persistent state.</li>
|
||||
// <li>Classic ATR - Each channel's switches depend on the transmission state
|
||||
// of the respective channel.</li>
|
||||
// <li>DB State - Each channel's switches depend on the transmission state
|
||||
// of all channels in this radio.</li>
|
||||
// </ul>
|
||||
// </info>
|
||||
//
|
||||
// <enumeratedtype name="RF_SWITCHES_SIZE_TYPE">
|
||||
// <value name="RFS_SIZE" integer="3"/>
|
||||
// </enumeratedtype>
|
||||
//
|
||||
// <regtype name="RF_ATR_STATE" size="32">
|
||||
// <info>Holds the value for the control lines of each channel's switches
|
||||
// for a particular ATR sate</info>
|
||||
// <bitfield name="TX_RX_RFS" range="0" initialvalue="0"/>
|
||||
// <bitfield name="RX_RFS" range="1" initialvalue="0"/>
|
||||
// <bitfield name="TDDS" range="2" initialvalue="0"/>
|
||||
// </regtype>
|
||||
//
|
||||
// <register name="RF0_ATR_STATE" typename="RF_ATR_STATE" offset="0x00" count="256" options="--step 4">
|
||||
// <info>
|
||||
// Describes switch control behavior for the different ATR states. When @.RF0_ATR_OPTION
|
||||
// is set to use the DB states, TX and RX states for RF0-RF3 are
|
||||
// combined to create a single vector. This creates 256 different
|
||||
// combinations, each with its own register. When @.RF0_ATR_OPTION is set to
|
||||
// classic ATR, the first 4 offsets in this register group will be driven
|
||||
// in accordance with the state of RF0.
|
||||
// CLASSIC ATR MAPPING: Idle[RF0: TX=0, RX=0], RX[RF0: TX=0, RX=1,
|
||||
// TX[RF0: TX=1, RX=0], FDX[RF0: TX=1, RX=1]
|
||||
// </info>
|
||||
// </register>
|
||||
//
|
||||
// <register name="RF1_ATR_STATE" typename="RF_ATR_STATE" offset="0x400" count="256" options="--step 4">
|
||||
// <info>
|
||||
// Describes switch control behavior for the different ATR states. When @.RF1_ATR_OPTION
|
||||
// is set to use the DB states, TX and RX states for RF0-RF3 are
|
||||
// combined to create a single vector. This creates 256 different
|
||||
// combinations, each with its own register. When @.RF1_ATR_OPTION is set to
|
||||
// classic ATR, the first 4 offsets in this register group will be driven
|
||||
// in accordance with the state of RF1.
|
||||
// CLASSIC ATR MAPPING: Idle[RF1: TX=0, RX=0], RX[RF1: TX=0, RX=1,
|
||||
// TX[RF1: TX=1, RX=0], FDX[RF1: TX=1, RX=1]
|
||||
// </info>
|
||||
// </register>
|
||||
//
|
||||
// <register name="RF2_ATR_STATE" typename="RF_ATR_STATE" offset="0x800" count="256" options="--step 4">
|
||||
// <info>
|
||||
// Describes switch control behavior for the different ATR states. When @.RF2_ATR_OPTION
|
||||
// is set to use the DB states, TX and RX states for RF0-RF3 are
|
||||
// combined to create a single vector. This creates 256 different
|
||||
// combinations, each with its own register. When @.RF2_ATR_OPTION is set to
|
||||
// classic ATR, the first 4 offsets in this register group will be driven
|
||||
// in accordance with the state of RF2.
|
||||
// CLASSIC ATR MAPPING: Idle[RF2: TX=0, RX=0], RX[RF2: TX=0, RX=1,
|
||||
// TX[RF2: TX=1, RX=0], FDX[RF2: TX=1, RX=1]
|
||||
// </info>
|
||||
// </register>
|
||||
//
|
||||
// <register name="RF3_ATR_STATE" typename="RF_ATR_STATE" offset="0xC00" count="256" options="--step 4">
|
||||
// <info>
|
||||
// Describes switch control behavior for the different ATR states. When @.RF3_ATR_OPTION
|
||||
// is set to use the DB states, TX and RX states for RF0-RF3 are
|
||||
// combined to create a single vector. This creates 256 different
|
||||
// combinations, each with its own register. When @.RF3_ATR_OPTION is set to
|
||||
// classic ATR, the first 4 offsets in this register group will be driven
|
||||
// in accordance with the state of RF3.
|
||||
// CLASSIC ATR MAPPING: Idle[RF3: TX=0, RX=0], RX[RF3: TX=0, RX=1,
|
||||
// TX[RF3: TX=1, RX=0], FDX[RF3: TX=1, RX=1]
|
||||
// </info>
|
||||
// </register>
|
||||
// <register name="ATR_OPTION_REGISTER" offset="0x1000" size="32">
|
||||
// <info>
|
||||
// Controls whether switch control lines use the TX and RX state of
|
||||
// their respective channel (Classic ATR) or the daughterboard state
|
||||
// to select which state to use from values set in RF_ATR_STATE registers.
|
||||
// For each particular bit:</br>
|
||||
// 0: Use DB state for ATR</br>
|
||||
// 1: Classic ATR mode.
|
||||
// </info>
|
||||
// <bitfield name="RF0_ATR_OPTION" range="0" initialvalue="0">
|
||||
// <info>
|
||||
// Control ATR scheme for RF0.
|
||||
// </info>
|
||||
// </bitfield>
|
||||
// <bitfield name="RF1_ATR_OPTION" range="1" initialvalue="0">
|
||||
// <info>
|
||||
// Control ATR scheme for RF1.
|
||||
// </info>
|
||||
// </bitfield>
|
||||
// <bitfield name="RF2_ATR_OPTION" range="2" initialvalue="0">
|
||||
// <info>
|
||||
// Control ATR scheme for RF2.
|
||||
// </info>
|
||||
// </bitfield>
|
||||
// <bitfield name="RF3_ATR_OPTION" range="3" initialvalue="0">
|
||||
// <info>
|
||||
// Control ATR scheme for RF3.
|
||||
// </info>
|
||||
// </bitfield>
|
||||
// </register>
|
||||
// <register name="RF_ATR_DISABLED" offset="0x1004" size="32">
|
||||
// <info>
|
||||
// Disable ATR Control. DB state 0 will be reflected regardless of the ATR state.
|
||||
// </info>
|
||||
// <bitfield name="RF0_ATR_DISABLED" range="0" initialvalue="0"/>
|
||||
// <bitfield name="RF1_ATR_DISABLED" range="1" initialvalue="0"/>
|
||||
// <bitfield name="RF2_ATR_DISABLED" range="2" initialvalue="0"/>
|
||||
// <bitfield name="RF3_ATR_DISABLED" range="3" initialvalue="0"/>
|
||||
// </register>
|
||||
// </group>
|
||||
//</regmap>
|
||||
//XmlParse xml_off
|
||||
@@ -0,0 +1,74 @@
|
||||
#
|
||||
# Copyright 2022 Ettus Research, a National Instruments Brand
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
#
|
||||
|
||||
#-------------------------------------------------
|
||||
# Top-of-Makefile
|
||||
#-------------------------------------------------
|
||||
# Define BASE_DIR to point to the "top" dir.
|
||||
BASE_DIR = ../../../../..
|
||||
# Include viv_sim_preample after defining BASE_DIR
|
||||
include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak
|
||||
|
||||
#-------------------------------------------------
|
||||
# Design Specific
|
||||
#-------------------------------------------------
|
||||
# Define part using PART_ID (<device>/<package>/<speedgrade>)
|
||||
ARCH = zynquplusRFSOC
|
||||
PART_ID = xczu28dr/ffvg1517/-1/e
|
||||
|
||||
# Include makefiles and sources for the DUT and its dependencies
|
||||
include $(BASE_DIR)/../lib/control/Makefile.srcs
|
||||
|
||||
|
||||
DESIGN_SRCS += $(abspath \
|
||||
$(FIFO_SRCS) \
|
||||
$(AXI_SRCS) \
|
||||
$(CONTROL_LIB_SRCS) \
|
||||
$(WISHBONE_SRCS) \
|
||||
)
|
||||
|
||||
|
||||
DESIGN_SRCS += $(abspath \
|
||||
../../regmap/fbx_ctrl_regmap_utils.vh \
|
||||
../../regmap/clock_en_regmap_utils.vh \
|
||||
../../clock_en_control.v \
|
||||
)
|
||||
|
||||
#-------------------------------------------------
|
||||
# IP Specific
|
||||
#-------------------------------------------------
|
||||
# If simulation contains IP, define the IP_DIR and point
|
||||
# it to the base level IP directory
|
||||
IP_DIR = $(BASE_DIR)/x400/ip
|
||||
LIB_IP_DIR = $(BASE_DIR)/../lib/ip
|
||||
|
||||
# Include makefiles and sources for all IP components
|
||||
# *after* defining the IP_DIR
|
||||
#
|
||||
# These TBs don't use any IP yet :)
|
||||
|
||||
#-------------------------------------------------
|
||||
# Testbench Specific
|
||||
#-------------------------------------------------
|
||||
include $(BASE_DIR)/../sim/general/Makefile.srcs
|
||||
|
||||
# Define only one top-level module
|
||||
SIM_TOP = clock_en_control_tb glbl
|
||||
|
||||
# Simulation runtime in microseconds
|
||||
SIM_RUNTIME_US = 100000
|
||||
|
||||
SIM_SRCS = \
|
||||
$(abspath clock_en_control_tb.sv) \
|
||||
$(VIVADO_PATH)/data/verilog/src/glbl.v \
|
||||
|
||||
#-------------------------------------------------
|
||||
# Bottom-of-Makefile
|
||||
#-------------------------------------------------
|
||||
# Include all simulator specific makefiles here
|
||||
# Each should define a unique target to simulate
|
||||
# e.g. xsim, vsim, etc and a common "clean" target
|
||||
include $(BASE_DIR)/../tools/make/viv_simulator.mak
|
||||
@@ -0,0 +1,172 @@
|
||||
//
|
||||
// Copyright 2022 Ettus Research, a National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: clock_en_control_tb
|
||||
//
|
||||
// Description:
|
||||
// Testbench for clock_en_control and clock_div modules. Tasks defined for ctrlport write and
|
||||
// read transactions. Tests clock enable control with ctrlport reads and writes.
|
||||
//
|
||||
`timescale 1ns / 1ps
|
||||
`define NS_PER_TICK 1
|
||||
`define NUM_TEST_CASES 4
|
||||
`include "sim_exec_report.vh"
|
||||
`include "sim_clks_rsts.vh"
|
||||
|
||||
|
||||
module clock_en_control_tb();
|
||||
import PkgRandom::*;
|
||||
PkgRandom::Rand #(5) rand_clk_count;
|
||||
`TEST_BENCH_INIT("clock_en_control_tb", `NUM_TEST_CASES, `NS_PER_TICK);
|
||||
//sets up clock
|
||||
localparam CLK_PERIOD = $ceil(1e9/50.0e6);
|
||||
localparam CLK_PERIOD_10 = $ceil(1e9/10.0e6);
|
||||
`DEFINE_CLK(clk50, CLK_PERIOD, 50);
|
||||
`DEFINE_CLK(clk10, CLK_PERIOD_10, 50);
|
||||
localparam N = 2;
|
||||
localparam N_DIV2 = N/2;
|
||||
|
||||
reg reset_clk50;
|
||||
reg clk10_rst;
|
||||
reg s_ctrlport_req_wr;
|
||||
reg s_ctrlport_req_rd;
|
||||
reg [19:0] s_ctrlport_req_addr;
|
||||
reg [31:0] s_ctrlport_req_data;
|
||||
|
||||
// Response
|
||||
wire s_ctrlport_resp_ack;
|
||||
wire [ 1:0] s_ctrlport_resp_status;
|
||||
wire [31:0] s_ctrlport_resp_data;
|
||||
|
||||
|
||||
wire clk5, clk5_buf;
|
||||
`include "../../regmap/clock_en_regmap_utils.vh"
|
||||
|
||||
task cp_write;
|
||||
input [19:0] a;
|
||||
input [31:0] d;
|
||||
begin
|
||||
s_ctrlport_req_addr = a;
|
||||
s_ctrlport_req_data = d;
|
||||
@(posedge clk50);
|
||||
s_ctrlport_req_wr = 1;
|
||||
@(posedge clk50);
|
||||
while(~s_ctrlport_resp_ack) @(posedge clk50);
|
||||
s_ctrlport_req_wr = 0;
|
||||
@(posedge clk50);
|
||||
end
|
||||
endtask
|
||||
|
||||
task cp_read;
|
||||
input [19:0] a;
|
||||
input [31:0] d;
|
||||
input debug;
|
||||
begin
|
||||
s_ctrlport_req_addr = a;
|
||||
@(posedge clk50);
|
||||
s_ctrlport_req_rd = 1;
|
||||
@(posedge clk50);
|
||||
while(~s_ctrlport_resp_ack) @(posedge clk50);
|
||||
s_ctrlport_req_rd = 0;
|
||||
@(posedge clk50);
|
||||
if(debug) begin
|
||||
$display("status: read addr %h at %t value = %h", a, $time, s_ctrlport_resp_data);
|
||||
end
|
||||
`ASSERT_ERROR( s_ctrlport_resp_data == d, "CtrlPort read returned unexpected value.");
|
||||
end
|
||||
endtask
|
||||
|
||||
clock_div #(
|
||||
.N(N)
|
||||
) clock_div_5mhz (
|
||||
.clk_in (clk10),
|
||||
.clk_in_rst (clk10_rst),
|
||||
.clk_out (clk5)
|
||||
);
|
||||
|
||||
clock_en_control #(
|
||||
.BASE_ADDRESS(0)
|
||||
) clock_en_control_inst (
|
||||
.ctrlport_clk (clk50),
|
||||
.ctrlport_rst (reset_clk50),
|
||||
.s_ctrlport_req_wr (s_ctrlport_req_wr),
|
||||
.s_ctrlport_req_rd (s_ctrlport_req_rd),
|
||||
.s_ctrlport_req_addr (s_ctrlport_req_addr),
|
||||
.s_ctrlport_req_data (s_ctrlport_req_data),
|
||||
.s_ctrlport_resp_ack (s_ctrlport_resp_ack),
|
||||
.s_ctrlport_resp_status (s_ctrlport_resp_status),
|
||||
.s_ctrlport_resp_data (s_ctrlport_resp_data),
|
||||
.clk_in (clk5),
|
||||
.clk_out (clk5_buf)
|
||||
);
|
||||
|
||||
// clock counters to verify clock division
|
||||
reg counter_reset;
|
||||
reg [8:0] clock_counter;
|
||||
reg [10:0] div_clock_counter;
|
||||
reg [10:0] expected_clock_count;
|
||||
reg [8:0] expected_div_clock_count;
|
||||
|
||||
always @(posedge clk10) begin
|
||||
if(counter_reset) begin
|
||||
clock_counter <= 0;
|
||||
end else begin
|
||||
clock_counter <= clock_counter + 1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk5_buf) begin
|
||||
if(counter_reset) begin
|
||||
div_clock_counter <= 0;
|
||||
end else begin
|
||||
div_clock_counter <= div_clock_counter + 1;
|
||||
end
|
||||
end
|
||||
|
||||
// main test cases
|
||||
initial begin : tb_main
|
||||
`TEST_CASE_START("initialize UUT");
|
||||
reset_clk50 = 1;
|
||||
clk10_rst = 1;
|
||||
s_ctrlport_req_wr = 0;
|
||||
s_ctrlport_req_rd = 0;
|
||||
s_ctrlport_req_addr = 0;
|
||||
s_ctrlport_req_data = 0;
|
||||
#200 //wait a cycle for the 10mhz clk rst
|
||||
reset_clk50 = 0;
|
||||
clk10_rst = 0;
|
||||
$display("status: %t done reset here", $time);
|
||||
`TEST_CASE_DONE(~reset_clk50);
|
||||
// trigger setup
|
||||
`TEST_CASE_START("Check that clock_out is not running");
|
||||
@(posedge clk5);
|
||||
@(posedge clk10);
|
||||
`ASSERT_ERROR( clk5_buf == 0, "clk5_buf should be zero now.");
|
||||
repeat (N) @(posedge clk10);
|
||||
`TEST_CASE_DONE(clk5_buf == 0 && clk5 == 1);
|
||||
`TEST_CASE_START("Enable clock with clock_en_control enable register");
|
||||
cp_read(CLK_EN_CONTROL, 0, 1); //initial value should be zero
|
||||
cp_write(CLK_EN_CONTROL, CLK_EN_CONTROL_MASK);
|
||||
cp_read(CLK_EN_CONTROL, CLK_EN_CONTROL_MASK, 1);
|
||||
@(posedge clk5_buf);
|
||||
repeat (N_DIV2+1) @(posedge clk10);
|
||||
`ASSERT_ERROR( clk5_buf == 0, "clk5_buf should be zero now.");
|
||||
repeat (N_DIV2) @(posedge clk10);
|
||||
`TEST_CASE_DONE(clk5_buf == 1 && s_ctrlport_resp_data == CLK_EN_CONTROL_MASK);
|
||||
`TEST_CASE_START("Verify expected clock division.");
|
||||
expected_div_clock_count = 5 + rand_clk_count.rand_bit();
|
||||
expected_clock_count = N*expected_div_clock_count;
|
||||
$display("Reset clock counters @ time %t and then count main clock &d times and divided clock %d times", $time, expected_clock_count, expected_div_clock_count);
|
||||
@(posedge clk5_buf);
|
||||
counter_reset = 1;
|
||||
@(posedge clk5_buf);
|
||||
counter_reset = 0;
|
||||
repeat (expected_div_clock_count) @(posedge clk5_buf);
|
||||
@(posedge clk10);
|
||||
`TEST_CASE_DONE(div_clock_counter == expected_div_clock_count && clock_counter == expected_clock_count);
|
||||
`TEST_BENCH_DONE;
|
||||
end
|
||||
endmodule
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
#
|
||||
# Copyright 2022 Ettus Research, a National Instruments Brand
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
#
|
||||
|
||||
#-------------------------------------------------
|
||||
# Top-of-Makefile
|
||||
#-------------------------------------------------
|
||||
# Define BASE_DIR to point to the "top" dir.
|
||||
BASE_DIR = ../../../../..
|
||||
# Include viv_sim_preample after defining BASE_DIR
|
||||
include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak
|
||||
|
||||
#-------------------------------------------------
|
||||
# Design Specific
|
||||
#-------------------------------------------------
|
||||
# Define part using PART_ID (<device>/<package>/<speedgrade>)
|
||||
ARCH = zynquplusRFSOC
|
||||
PART_ID = xczu28dr/ffvg1517/-1/e
|
||||
|
||||
# Include makefiles and sources for the DUT and its dependencies
|
||||
include $(BASE_DIR)/../lib/control/Makefile.srcs
|
||||
include $(BASE_DIR)/../lib/wishbone/Makefile.srcs
|
||||
|
||||
|
||||
DESIGN_SRCS += $(abspath \
|
||||
$(FIFO_SRCS) \
|
||||
$(AXI_SRCS) \
|
||||
$(CONTROL_LIB_SRCS) \
|
||||
$(WISHBONE_SRCS) \
|
||||
)
|
||||
|
||||
|
||||
DESIGN_SRCS += $(abspath \
|
||||
../../regmap/fbx_ctrl_regmap_utils.vh \
|
||||
../../regmap/rf_sync_regmap_utils.vh \
|
||||
../../ctrlport_to_i2c_sync_ctrl.v \
|
||||
)
|
||||
|
||||
#-------------------------------------------------
|
||||
# IP Specific
|
||||
#-------------------------------------------------
|
||||
# If simulation contains IP, define the IP_DIR and point
|
||||
# it to the base level IP directory
|
||||
IP_DIR = $(BASE_DIR)/x400/ip
|
||||
LIB_IP_DIR = $(BASE_DIR)/../lib/ip
|
||||
|
||||
# Include makefiles and sources for all IP components
|
||||
# *after* defining the IP_DIR
|
||||
#
|
||||
# These TBs don't use any IP yet :)
|
||||
|
||||
#-------------------------------------------------
|
||||
# Testbench Specific
|
||||
#-------------------------------------------------
|
||||
include $(BASE_DIR)/../sim/general/Makefile.srcs
|
||||
|
||||
# Define only one top-level module
|
||||
SIM_TOP = ctrlport_to_i2c_sync_ctrl_tb
|
||||
|
||||
# Simulation runtime in microseconds
|
||||
SIM_RUNTIME_US = 200000
|
||||
|
||||
SIM_SRCS = \
|
||||
$(abspath ctrlport_to_i2c_sync_ctrl_tb.sv) \
|
||||
$(abspath $(BASE_DIR)/../lib/sim/wishbone/i2c/i2c_slave_model.v) \
|
||||
|
||||
#-------------------------------------------------
|
||||
# Bottom-of-Makefile
|
||||
#-------------------------------------------------
|
||||
# Include all simulator specific makefiles here
|
||||
# Each should define a unique target to simulate
|
||||
# e.g. xsim, vsim, etc and a common "clean" target
|
||||
include $(BASE_DIR)/../tools/make/viv_simulator.mak
|
||||
@@ -0,0 +1,204 @@
|
||||
//
|
||||
// Copyright 2022 Ettus Research, a National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: ctrlport_to_i2c_sync_ctrl_tb
|
||||
//
|
||||
// Description:
|
||||
// testbench for ctrlport_to_i2c_sync_ctrl module. Tasks defined for ctrlport write and
|
||||
// read transactions. Tests ability to write to SYNC/RFS_EN regs and then
|
||||
// initialize i2c_master and i2c peripheral and then configure io through the
|
||||
// i2c interface to the io expander.
|
||||
//
|
||||
`timescale 1ns / 1ps
|
||||
`define NS_PER_TICK 1
|
||||
`define NUM_TEST_CASES 5
|
||||
`include "sim_exec_report.vh"
|
||||
`include "sim_clks_rsts.vh"
|
||||
`define SIM_TIMEOUT_US 200000 //overwrite this def from sim_exec_report.vh
|
||||
|
||||
|
||||
module ctrlport_to_i2c_sync_ctrl_tb();
|
||||
import PkgRandom::*;
|
||||
|
||||
`TEST_BENCH_INIT("ctrlport_to_i2c_sync_ctrl_tb", `NUM_TEST_CASES, `NS_PER_TICK);
|
||||
//sets up clock
|
||||
localparam CLK_PERIOD = $ceil(1e9/50.0e6);
|
||||
`DEFINE_CLK(clk50, CLK_PERIOD, 50);
|
||||
|
||||
reg reset_clk50;
|
||||
reg s_ctrlport_req_wr;
|
||||
reg s_ctrlport_req_rd;
|
||||
reg [19:0] s_ctrlport_req_addr;
|
||||
reg [31:0] s_ctrlport_req_data;
|
||||
|
||||
// Response
|
||||
wire s_ctrlport_resp_ack;
|
||||
wire [ 1:0] s_ctrlport_resp_status;
|
||||
wire [31:0] s_ctrlport_resp_data;
|
||||
|
||||
|
||||
wire i2c_scl_i, i2c_scl_o, i2c_scl_en_o;
|
||||
wire i2c_sda_i, i2c_sda_o, i2c_sda_en_o;
|
||||
PkgRandom::Rand #(3) rand_sync;
|
||||
PkgRandom::Rand #(1) rand_rfs_en;
|
||||
reg [2:0] sync1, sync2, sync3, sync4, sync5;
|
||||
reg rfs_en;
|
||||
`include "../../regmap/rf_sync_regmap_utils.vh"
|
||||
|
||||
task cp_write;
|
||||
input [19:0] a;
|
||||
input [31:0] d;
|
||||
begin
|
||||
s_ctrlport_req_addr = a;
|
||||
s_ctrlport_req_data = d;
|
||||
@(posedge clk50);
|
||||
s_ctrlport_req_wr = 1;
|
||||
@(posedge clk50);
|
||||
while(~s_ctrlport_resp_ack) @(posedge clk50);
|
||||
s_ctrlport_req_wr = 0;
|
||||
@(posedge clk50);
|
||||
end
|
||||
endtask
|
||||
|
||||
task cp_read;
|
||||
input [19:0] a;
|
||||
input [31:0] d;
|
||||
input debug;
|
||||
begin
|
||||
s_ctrlport_req_addr = a;
|
||||
s_ctrlport_req_rd = 1;
|
||||
@(posedge clk50);
|
||||
while(~s_ctrlport_resp_ack) @(posedge clk50);
|
||||
s_ctrlport_req_rd = 0;
|
||||
@(posedge clk50);
|
||||
if(debug) begin
|
||||
$display("status: read addr %h at %t value = %h", a, $time, s_ctrlport_resp_data);
|
||||
end
|
||||
`ASSERT_ERROR( s_ctrlport_resp_data == d, "CtrlPort read returned unexpected value.");
|
||||
end
|
||||
endtask
|
||||
|
||||
task cp_poll;
|
||||
input [19:0] a;
|
||||
input [31:0] d;
|
||||
input debug;
|
||||
begin
|
||||
s_ctrlport_req_addr = a;
|
||||
s_ctrlport_req_rd = 1;
|
||||
@(posedge clk50);
|
||||
while(~s_ctrlport_resp_ack) @(posedge clk50);
|
||||
s_ctrlport_req_rd = 0;
|
||||
@(posedge clk50);
|
||||
while(s_ctrlport_resp_data != d && s_ctrlport_req_addr == a) begin
|
||||
s_ctrlport_req_addr = a;
|
||||
s_ctrlport_req_rd = 1;
|
||||
@(posedge clk50);
|
||||
while(~s_ctrlport_resp_ack) @(posedge clk50);
|
||||
s_ctrlport_req_rd = 0;
|
||||
@(posedge clk50);
|
||||
end
|
||||
if(debug) begin
|
||||
$display("status: read addr %h at %t value = %h", a, $time, s_ctrlport_resp_data);
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
|
||||
ctrlport_to_i2c_sync_ctrl #(
|
||||
.BASE_ADDRESS(0)
|
||||
) ctrlport_to_i2c_inst (
|
||||
.ctrlport_clk (clk50),
|
||||
.ctrlport_rst (reset_clk50),
|
||||
.s_ctrlport_req_wr (s_ctrlport_req_wr),
|
||||
.s_ctrlport_req_rd (s_ctrlport_req_rd),
|
||||
.s_ctrlport_req_addr (s_ctrlport_req_addr),
|
||||
.s_ctrlport_req_data (s_ctrlport_req_data),
|
||||
.s_ctrlport_resp_ack (s_ctrlport_resp_ack),
|
||||
.s_ctrlport_resp_status (s_ctrlport_resp_status),
|
||||
.s_ctrlport_resp_data (s_ctrlport_resp_data),
|
||||
.scl_pad_i (i2c_scl_i),
|
||||
.scl_pad_o (i2c_scl_o),
|
||||
.scl_pad_en_o (i2c_scl_en_o),
|
||||
.sda_pad_i (i2c_sda_i),
|
||||
.sda_pad_o (i2c_sda_o),
|
||||
.sda_pad_en_o (i2c_sda_en_o)
|
||||
);
|
||||
|
||||
// hookup i2c slave model
|
||||
i2c_slave_model #(
|
||||
ctrlport_to_i2c_inst.SYNC_IO_SLV_ADR
|
||||
) i2c_slave (
|
||||
.scl(i2c_scl_i),
|
||||
.sda(i2c_sda_i)
|
||||
);
|
||||
|
||||
// create i2c lines
|
||||
delay m0_scl (i2c_scl_en_o ? 1'bz : i2c_scl_o, i2c_scl_i),
|
||||
m0_sda (i2c_sda_en_o ? 1'bz : i2c_sda_o, i2c_sda_i);
|
||||
|
||||
pullup p1(i2c_scl_i); // pullup scl line
|
||||
pullup p2(i2c_sda_i); // pullup sda line
|
||||
|
||||
initial begin : tb_main
|
||||
`TEST_CASE_START("initialize UUT");
|
||||
clk50 = 0;
|
||||
reset_clk50 = 1;
|
||||
s_ctrlport_req_wr = 0;
|
||||
s_ctrlport_req_rd = 0;
|
||||
s_ctrlport_req_addr = 0;
|
||||
s_ctrlport_req_data = 0;
|
||||
#100
|
||||
reset_clk50 = 0;
|
||||
$display("status: %t done reset here", $time);
|
||||
`TEST_CASE_DONE(~reset_clk50);
|
||||
// trigger setup
|
||||
`TEST_CASE_START("Initialize core and I2C peripheral");
|
||||
cp_write(SETUP_REG, 1);
|
||||
cp_poll(SETUP_STATUS_REG,1,1);
|
||||
`TEST_CASE_DONE(i2c_slave.mem[7] == 0 & i2c_slave.mem[6] == 0);
|
||||
$display("status: %t SETUP DONE", $time);
|
||||
// configure SYNC and RFS_EN Regs
|
||||
for (int i=0; i<3; i=i+1) begin
|
||||
`TEST_CASE_START("configure SYNC and RFS_EN Regs loop");
|
||||
$display("loop # %d", i);
|
||||
sync1 = rand_sync.rand_bit();
|
||||
sync2 = rand_sync.rand_bit();
|
||||
sync3 = rand_sync.rand_bit();
|
||||
sync4 = rand_sync.rand_bit();
|
||||
sync5 = rand_sync.rand_bit();
|
||||
rfs_en = rand_rfs_en.rand_bit();
|
||||
cp_write(SYNC_1_REG, sync1);
|
||||
cp_write(SYNC_2_REG, sync2);
|
||||
cp_write(SYNC_3_REG, sync3);
|
||||
cp_write(SYNC_4_REG, sync4);
|
||||
cp_write(SYNC_5_REG, sync5);
|
||||
cp_write(RFS_EN_REG, rfs_en);
|
||||
cp_read(SYNC_1_REG, {28'b0, sync1}, 1);
|
||||
cp_read(SYNC_2_REG, {28'b0, sync2}, 1);
|
||||
cp_read(SYNC_3_REG, {28'b0, sync3}, 1);
|
||||
cp_read(SYNC_4_REG, {28'b0, sync4}, 1);
|
||||
cp_read(SYNC_5_REG, {28'b0, sync5}, 1);
|
||||
cp_read(RFS_EN_REG, {31'b0, rfs_en}, 1);
|
||||
$display("status: %t Configured ControlPort regs, now configure I2C peripheral.", $time);
|
||||
cp_write(CONFIG_IO_REG, 1);
|
||||
cp_poll(CONFIG_IO_STATUS_REG,32'h1,1);
|
||||
`TEST_CASE_DONE(i2c_slave.mem[2] == {sync3[1:0], sync2, sync1} &
|
||||
i2c_slave.mem[3] == {rfs_en, sync5, sync4, sync3[2]});
|
||||
end
|
||||
`TEST_BENCH_DONE;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module delay (in, out);
|
||||
input in;
|
||||
output out;
|
||||
|
||||
assign out = in;
|
||||
|
||||
specify
|
||||
(in => out) = (600,600);
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user