Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend XRFDC driver for MTS support #1384

Open
wants to merge 5 commits into
base: image_v3.1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 6 additions & 15 deletions sdbuild/packages/xrfclk/package/README.md
Expand Up @@ -3,22 +3,13 @@
This is a package implementing the drivers to configure RF reference clocks
for the Xilinx Zynq RFSoC boards (e.g., ZCU111).

## Boards and Chips

For simple (safe) use, refer to `set_ref_clks()`.

For RFSoC experts, you can specify custom clock frequencies, assuming you
know what you're doing. In that case, you can leverage the following methods:

1. `set_lmk04208_clks()` for boards with LMK04208.
2. `set_lmk04832_clks()` for boards with LMK04832.
3. `set_lmx2594_clks()` for boards with LMX2594.

For example, checking ZCU111 schematic, you should be able to find that the
ZCU111 board has LMK04208 and LMX2594 chips.

For other boards you may also need to adjust the I2C and SPI addresses
specified in `src/xrfdc_clk.h`.
## Instructions
The LMKxxxxx and LMXxxxx clocking configurations are set via the `set_ref_clks()` command:
```python
from xrfclk import set_ref_clks
set_ref_clks(lmk_freq=122.88, lmx_freq=409.6)
```

## Register Values

Expand Down
26 changes: 26 additions & 0 deletions sdbuild/packages/xrfclk/package/xrfclk/LMK04208_128.00.txt
@@ -0,0 +1,26 @@
R0 (INIT) 0x00160040
R0 0x00143000 #PL: SYSREF_FPGA --> 8MHz
R1 0x00143001 #DAC: SYSREF_RFSOC --> 8MHz
R2 0x00140302 #PL: FPGA_REFCLK_OUT --> 128MHz
R3 0xC0140023 #SYNC --> 122.88MHz
R4 0x40140024 #REFIN_2594 --> 122.88MHz
R5 0x80141E05 #SMA: REF_OUT --> 12.8MHz
R6 0x01100006
R7 0x01100007
R8 0x06010008
R9 0x55555549
R10 0x9102410A
R11 0x0401100B
R12 0x1B0C006C
R13 0x2302886D
R14 0x0200000E
R15 0x8000800F
R16 0xC1550410
R24 0x00000058
R25 0x02C9C419
R26 0x8FA8001A
R27 0x10001E1B
R28 0x0021201C
R29 0x0180033D
R30 0x0200033E
R31 0x003F001F
26 changes: 26 additions & 0 deletions sdbuild/packages/xrfclk/package/xrfclk/LMK04208_256.00.txt
@@ -0,0 +1,26 @@
R0 (INIT) 0x00160040
R0 0x00143000 #PL: SYSREF_FPGA --> 8MHz
R1 0x00143001 #DAC: SYSREF_RFSOC --> 8MHz
R2 0x00140182 #PL: FPGA_REFCLK_OUT --> 256MHz
R3 0xC0140023 #SYNC --> 122.88MHz
R4 0x40140024 #REFIN_2594 --> 122.88MHz
R5 0x80141E05 #SMA: REF_OUT --> 12.8MHz
R6 0x01100006
R7 0x01100007
R8 0x06010008
R9 0x55555549
R10 0x9102410A
R11 0x0401100B
R12 0x1B0C006C
R13 0x2302886D
R14 0x0200000E
R15 0x8000800F
R16 0xC1550410
R24 0x00000058
R25 0x02C9C419
R26 0x8FA8001A
R27 0x10001E1B
R28 0x0021201C
R29 0x0180033D
R30 0x0200033E
R31 0x003F001F
29 changes: 29 additions & 0 deletions sdbuild/packages/xrfdc/package/README.md
Expand Up @@ -119,6 +119,10 @@ u32 XRFdc_GetLinkCoupling(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id,
u32 *ModePtr);
u32 XRFdc_GetFabClkOutDiv(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
u16 *FabClkDivPtr);
u32 XRFdc_MultiConverter_Sync(XRFdc *InstancePtr, u32 Type,
XRFdc_MultiConverter_Sync_Config *ConfigPtr);
void XRFdc_MultiConverter_Init(XRFdc_MultiConverter_Sync_Config *ConfigPtr,
int *PLL_CodesPtr, int *T1_CodesPtr);
```

This list can also be found at the `Function Prototypes` section of
Expand All @@ -139,6 +143,31 @@ If attempting to use one of these functions on a Gen 1 board, the user will see
metal: error:
Requested functionality not available for this IP


## Multi-Tile Synchronization (MTS)
The underlying implementation is based on the [xrfdc_mts_example.c](https://github.com/Xilinx/embeddedsw/blob/master/XilinxProcessorIPLib/drivers/rfdc/examples/xrfdc_mts_example.c), which first defines the MTS configuration object and thereafter performs the actual MTS function call.

The following code snippet achieves MTS on all ADC (4) and DAC (2) tiles in flow:

```python
import pynq
import xrfclk
import xrfdc

#Config RF clocks (optional, lmk_freq and lmx_freq may differ depending on your application)
xrfclk.set_ref_clks(lmk_freq=122.88, lmx_freq=409.6)

#Load bitstream
ol = pynq.Overlay("bitstream_name.bit")

#MTS
ol.usp_rf_data_converter_0.mts_adc_config.Tiles = 0xf
ol.usp_rf_data_converter_0.mts_dac_config.Tiles = 0x3
ol.usp_rf_data_converter_0.mts_adc()
ol.usp_rf_data_converter_0.mts_dac()
```


Copyright (C) 2021 Xilinx, Inc

SPDX-License-Identifier: BSD-3-Clause
12 changes: 12 additions & 0 deletions sdbuild/packages/xrfdc/package/xrfdc/__init__.py
Expand Up @@ -397,10 +397,22 @@ def __init__(self, description):
_lib.XRFdc_CfgInitialize(self._instance, self._config)
self.adc_tiles = [RFdcAdcTile(self, i) for i in range(4)]
self.dac_tiles = [RFdcDacTile(self, i) for i in range(4)]
self.mts_adc_config = _ffi.new('XRFdc_MultiConverter_Sync_Config*')
self.mts_dac_config = _ffi.new('XRFdc_MultiConverter_Sync_Config*')
_safe_wrapper("XRFdc_MultiConverter_Init", self.mts_adc_config, cffi.FFI.NULL, cffi.FFI.NULL)
_safe_wrapper("XRFdc_MultiConverter_Init", self.mts_dac_config, cffi.FFI.NULL, cffi.FFI.NULL)


def _call_function(self, name, *args):
_safe_wrapper(f"XRFdc_{name}", self._instance, *args)

def mts_adc(self):
return _safe_wrapper("XRFdc_MultiConverter_Sync", self._instance, 0, self.mts_adc_config)

def mts_dac(self):
return _safe_wrapper("XRFdc_MultiConverter_Sync", self._instance, 1, self.mts_dac_config)



# Finally we can add our data-driven properties to each class in the hierarchy

Expand Down
44 changes: 43 additions & 1 deletion sdbuild/packages/xrfdc/package/xrfdc/xrfdc_functions.c
Expand Up @@ -80,6 +80,44 @@ typedef struct {
XRFdc_Distribution DistributionStatus[8];
} XRFdc_Distribution_Settings;

/**
* MTS DTC Settings.
*/
typedef struct {
u32 RefTile;
u32 IsPLL;
int Target[4];
int Scan_Mode;
int DTC_Code[4];
int Num_Windows[4];
int Max_Gap[4];
int Min_Gap[4];
int Max_Overlap[4];
} XRFdc_MTS_DTC_Settings;

/**
* MTS Sync Settings.
*/
typedef struct {
u32 RefTile;
u32 Tiles;
int Target_Latency;
int Offset[4];
int Latency[4];
int Marker_Delay;
int SysRef_Enable;
XRFdc_MTS_DTC_Settings DTC_Set_PLL;
XRFdc_MTS_DTC_Settings DTC_Set_T1;
} XRFdc_MultiConverter_Sync_Config;

/**
* MTS Marker Struct.
*/
typedef struct {
u32 Count[4];
u32 Loc[4];
} XRFdc_MTS_Marker;

/**
* ADC Signal Detect Settings.
*/
Expand Down Expand Up @@ -412,6 +450,8 @@ typedef struct {
} XRFdc;




/***************** Macros (Inline Functions) Definitions *********************/
#define XRFDC_ADC_TILE 0U
#define XRFDC_DAC_TILE 1U
Expand Down Expand Up @@ -517,4 +557,6 @@ u32 XRFdc_GetDSA(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id, XRFdc_DSA_Settin
u32 XRFdc_SetPwrMode(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, u32 Block_Id, XRFdc_Pwr_Mode_Settings *SettingsPtr);
u32 XRFdc_GetPwrMode(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, u32 Block_Id, XRFdc_Pwr_Mode_Settings *SettingsPtr);
u32 XRFdc_ResetInternalFIFOWidth(XRFdc *InstancePtr, u32 Type, u32 Tile_Id, u32 Block_Id);
u32 XRFdc_ResetInternalFIFOWidthObs(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id);
u32 XRFdc_ResetInternalFIFOWidthObs(XRFdc *InstancePtr, u32 Tile_Id, u32 Block_Id);
u32 XRFdc_MultiConverter_Sync(XRFdc *InstancePtr, u32 Type, XRFdc_MultiConverter_Sync_Config *ConfigPtr);
void XRFdc_MultiConverter_Init(XRFdc_MultiConverter_Sync_Config *ConfigPtr, int *PLL_CodesPtr, int *T1_CodesPtr);