How can I have different clock constraints on signals in the same clock domain ?
In my design, I have a PLL which is configurable through APB registers.
I am also working with 2 modes (mode1 and mode2).
Depending on the mode (selectable by the user), the clock output is either 100 MHz or 70 MHz.
Because the clock come from the same PLL output, the same clock is used for the design working #100 MHz in mode 1 and #70 MHz in mode 2.
Below is the structure of the top level entity :
entity myTopLevel is
port(
I_clk : in std_logic; -- the PLL output; #100MHz or 70 MHz
I_rst : in std_logic; -- input rst
I_mode1 : in std_logic; -- when '1' : I_clk is running # 100 MHz, when '0' : 70 MHz
I_data : in std_logic_vector(15 downto 0);
O_data : out std_logic_vector(15 downto 0));
Inside the top level entity, there are 2 modules. 1 is running # 100 MHz and is under reset when I_mode1 = '0'. The other is running # 70 MHz and is under reset when I_mode1 = '1' :
INST1 : myProcessModuleMode1
port (
I_clk1 => I_clk,
I_rst1 => S_rst1, -- asserted when I_mode1 = '0'
I_data1=> I_data,
O_data1=> S_data1)
INST2 : myProcessModuleMode2
port (
I_clk2 => I_clk,
I_rst2 => S_rst2, -- asserted when I_mode2 = '0'
I_data2=> I_data,
O_data2=> S_data2)
O_data <= S_data1 when I_mode1='1' else S_data2;
However, the myProcessModuleMode2 is slower than myProcessModuleMode1. So I want to add a constraint # 70 MHz on the module2 and 100 MHz on module1. Is it possible ?
With the current version, I am constraining the clock # 100 MHz and I get (after synthesis/ Place&Route) 90 MHz with negative slack in module 2 (which is ok, I want 70 MHz) and some negatives slacks in module 1 ...
I would like to release the constraint in module 2 to get better results in module1.
Using multicycle path on module2 could be a solution with clocks #100 MHz and 50MHz and not with clocks # 100 MHz & 70 MHz.
Note : I_mode1 (the configuration mode) is considered static.
Note 2 : I_* stands for input, O_* output and S_* signal.
Regards,
However OP has not mentioned the tool and platform, I'll show the constraints in SDC format, which is widely supported (by Synopsys, Cadence, Xilinx, Intel/Altera etc.).
Each module can have its own clock constraint through its clock input.
create_clock -name CLK1 -period 10 -waveform "0 5" [get_pins myProcessModuleMode1/I_clk1]
create_clock -name CLK2 -period 14 -waveform "0 7" [get_pins myProcessModuleMode2/I_clk2]
Now Module1 and Module2 are constrained at 100MHz and ~70MHz respectively.
Since S_data1 and S_data2 are multiplexed, there is clock domain crossing there. I would define the clocks logically exclusive to avoid timing violations between different clock domains.
set_clock_groups -logically_exclusive -group CLK1 -group CLK2
Related
I trying to use custom pins for SPI on the pico-mini-02 board. The board has esp32 (pico-v3-02). I'm using Arduino IDE (with arduino-esp32) and windows 10.
When I try to use the SPI example (multiple buses example), I'm getting Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled. error. I have decoded the exception backtrace
0x40080f31: __pinMode at C:\Users\newto\OneDrive\Documents\ArduinoData\packages\esp32\hardware\esp32\1.0.5\cores\esp32\esp32-hal-gpio.c line 115
0x400d0f3a: spiAttachSCK at C:\Users\newto\OneDrive\Documents\ArduinoData\packages\esp32\hardware\esp32\1.0.5\cores\esp32\esp32-hal-spi.c line 87
0x400d0db2: SPIClass::begin(signed char, signed char, signed char, signed char) at C:\Users\newto\OneDrive\Documents\ArduinoData\packages\esp32\hardware\esp32\1.0.5\libraries\SPI\src\SPI.cpp line 57
0x400d0c2b: setup() at C:\Users\newto\OneDrive\Documents\ArduinoData\packages\esp32\hardware\esp32\1.0.5\libraries\SPI\examples\SPI_Multiple_Buses/SPI_Multiple_Buses.ino line 67
0x400d190a: loopTask(void*) at C:\Users\newto\OneDrive\Documents\ArduinoData\packages\esp32\hardware\esp32\1.0.5\cores\esp32\main.cpp line 32
0x40085fa5: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143
The full error message:
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 271414342, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5856
entry 0x400806a8
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x40080f31 PS : 0x00060730 A0 : 0x800d0f3d A1 : 0x3ffb1f30
A2 : 0x0000000e A3 : 0x00000002 A4 : 0x3ffb8364 A5 : 0x00000001
A6 : 0x00000000 A7 : 0x00000004 A8 : 0x3f400674 A9 : 0xaaaaaaaa
A10 : 0xaaaaaaaa A11 : 0x00000030 A12 : 0x3ffb82cc A13 : 0x00000000
A14 : 0x00000000 A15 : 0x00000000 SAR : 0x00000009 EXCCAUSE: 0x0000001c
EXCVADDR: 0xaaaaaaaa LBEG : 0x400d1258 LEND : 0x400d1265 LCOUNT : 0x00000000
ELF file SHA256: 0000000000000000
Backtrace: 0x40080f31:0x3ffb1f30 0x400d0f3a:0x3ffb1f50 0x400d0db2:0x3ffb1f70 0x400d0c2b:0x3ffb1f90 0x400d190a:0x3ffb1fb0 0x40085fa5:0x3ffb1fd0
Rebooting...
ets Jul 29 2019 12:21:46
Any help would be appreciated.
The sketch:
/* The ESP32 has four SPi buses, however as of right now only two of
* them are available to use, HSPI and VSPI. Simply using the SPI API
* as illustrated in Arduino examples will use VSPI, leaving HSPI unused.
*
* However if we simply intialise two instance of the SPI class for both
* of these buses both can be used. However when just using these the Arduino
* way only will actually be outputting at a time.
*
* Logic analyser capture is in the same folder as this example as
* "multiple_bus_output.png"
*
* created 30/04/2018 by Alistair Symonds
*/
#include <SPI.h>
// Define ALTERNATE_PINS to use non-standard GPIO pins for SPI bus
#ifdef ALTERNATE_PINS
#define VSPI_MISO 2
#define VSPI_MOSI 4
#define VSPI_SCLK 0
#define VSPI_SS 33
#define HSPI_MISO 26
#define HSPI_MOSI 27
#define HSPI_SCLK 25
#define HSPI_SS 32
#else
#define VSPI_MISO MISO
#define VSPI_MOSI MOSI
#define VSPI_SCLK SCK
#define VSPI_SS SS
#define HSPI_MISO 12
#define HSPI_MOSI 13
#define HSPI_SCLK 14
#define HSPI_SS 15
#endif
static const int spiClk = 1000000; // 1 MHz
//uninitalised pointers to SPI objects
SPIClass * vspi = NULL;
SPIClass * hspi = NULL;
void setup() {
//initialise two instances of the SPIClass attached to VSPI and HSPI respectively
vspi = new SPIClass(VSPI);
hspi = new SPIClass(HSPI);
//clock miso mosi ss
#ifndef ALTERNATE_PINS
//initialise vspi with default pins
//SCLK = 18, MISO = 19, MOSI = 23, SS = 5
vspi->begin();
#else
//alternatively route through GPIO pins of your choice
vspi->begin(VSPI_SCLK, VSPI_MISO, VSPI_MOSI, VSPI_SS); //SCLK, MISO, MOSI, SS
#endif
#ifndef ALTERNATE_PINS
//initialise hspi with default pins
//SCLK = 14, MISO = 12, MOSI = 13, SS = 15
hspi->begin();
#else
//alternatively route through GPIO pins
hspi->begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI, HSPI_SS); //SCLK, MISO, MOSI, SS
#endif
//set up slave select pins as outputs as the Arduino API
//doesn't handle automatically pulling SS low
pinMode(VSPI_SS, OUTPUT); //VSPI SS
pinMode(HSPI_SS, OUTPUT); //HSPI SS
}
// the loop function runs over and over again until power down or reset
void loop() {
//use the SPI buses
vspiCommand();
hspiCommand();
delay(100);
}
void vspiCommand() {
byte data = 0b01010101; // junk data to illustrate usage
//use it as you would the regular arduino SPI API
vspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
digitalWrite(VSPI_SS, LOW); //pull SS slow to prep other end for transfer
vspi->transfer(data);
digitalWrite(VSPI_SS, HIGH); //pull ss high to signify end of data transfer
vspi->endTransaction();
}
void hspiCommand() {
byte stuff = 0b11001100;
hspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
digitalWrite(HSPI_SS, LOW);
hspi->transfer(stuff);
digitalWrite(HSPI_SS, HIGH);
hspi->endTransaction();
}
Hi Mate I tried the code and it works. I have selected AI Thinker ESP32 that matches my board,and I have selected Flash Mode QIO and also DIO: both working fine. If you may still have the issue I would suggest to select DOUT or DIO.
Basically please check if your board matches the one selected on Tools->Board and check also the selection of 'Flash mode'.
Not all chips support all of these modes. The datasheet is the best source to know what supports what.
DIO - SPI host uses the "Dual I/O Fast Read" command (BBh). Two SPI pins are used to write the flash address part of the command, and to read flash data out. Therefore these phases need half the clock cycles compared to standard SPI.
DOUT - SPI host uses the "Dual Output Fast Read" command (3Bh). Two SPI pins are used to read flash data out. Slightly slower than DIO, because the address is written via the single MOSI data pin.
QIO - SPI host uses the "Quad I/O Fast Read" command (EBh). Four SPI pins are used to write the flash address part of the command, and to read flash data out. Therefore these phases need a quarter the clock cycles compared to standard SPI.
QOUT - SPI host uses the "Quad Output Fast Read" command (6Bh). Four SPI pins are used to read the flash data out. Slightly slower than QIO, because the address is written via the single MOSI data pin.
ESP-IDF defaults to DIO because some flash chips use a mode bit to enable QIO & QOUT support, and this can vary between manufacturers.
If using DIO/DOUT mode, GPIOs 9 & 10 are available for other uses. However note that if they are wired to the SPI flash chip (as they are in WROOM, for example) then the SPI flash chip may use them for other pin functions. Consult the SPI flash chip data sheet to be sure.
Very interesting discussion on this subject here: https://www.esp32.com/viewtopic.php?t=1250
Hope this helps. All the best.
I've been trying to update someone else' software to work on a new machine.
They built a Modbus controller using the Pymodbus library to work with the main software.
The only difference between the original working machine and this new one is that the DAQ is different.
I had assumed going in that this would just mean changing addresses but probably due to my lack of knowledge about Pymodbus this has been very far from the case.
The main issue I am having right now is that is that I am trying to simply communicate with holding registers and the only response I can get back is "(131, 3, Slave Device Busy)".
I am really not sure what to do with this information, It happens as soon as it is started and nothing is able to change it.
Has anyone else had any experience where a device always outputting this same error code?
the DAQ I am using is a Aspar IO Slim Module MOD-ETH
Any advice would be much appreciated.
Thank you
J
(I would attached the code here but it is quite long and I'm not sure a snippet would really help but do let me know if it would be helpful)
Short test code
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)
log.debug("Connecting to controller (IP=169.254.54.23, Port 502)")
client = ModbusClient('192.168.1.135', port=502)
59 #client = ModbusClient(method='ascii', port='/dev/pts/2', timeout=1)
60 # client = ModbusClient(method='rtu', port='/dev/ttyp0', timeout=1)
client.connect()
log.debug("Connected to controller (IP=192.168.1.135, Port 502)")
log.debug("Reading Sump Oil Temperature")
rr = client.read_holding_registers(1021, 1, unit=1)
log.debug("Read Sump Oil Temperature")
if rr.function_code > 0x80:
print( "Error has occured!\n" + str( rr.function_code ) + "\n" + str( rr.exception_code ) )
else:
print( rr.getRegister(0) )
client.close()
Response:
DEBUG:root:Connecting to controller (IP=169.254.54.23, Port 502)
DEBUG:root:Connected to controller (IP=192.168.1.135, Port 502)
DEBUG:root:Reading Sump Oil Temperature
DEBUG:pymodbus.transaction:Current transaction state - IDLE
DEBUG:pymodbus.transaction:Running transaction 1
DEBUG:pymodbus.transaction:SEND: 0x0 0x1 0x0 0x0 0x0 0x6 0x1 0x3 0x3 0xfd 0x0 0x1
DEBUG:pymodbus.client.sync:New Transaction state 'SENDING'
DEBUG:pymodbus.transaction:Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
DEBUG:pymodbus.transaction:Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
DEBUG:pymodbus.transaction:RECV: 0x0 0x1 0x0 0x0 0x0 0x3 0x1 0x83 0x6
DEBUG:pymodbus.framer.socket_framer:Processing: 0x0 0x1 0x0 0x0 0x0 0x3 0x1 0x83 0x6
DEBUG:pymodbus.factory:Factory Response[131]
DEBUG:pymodbus.transaction:Adding transaction 1
DEBUG:pymodbus.transaction:Getting transaction 1
DEBUG:pymodbus.transaction:Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
DEBUG:root:Read Sump Oil Temperature
Error has occured!
131
6
I am experimenting with Vivante GPU GC2000 Series, where the clinfo produced the below result.
CL_DEVICE_GLOBAL_MEM_SIZE: 64 MByte
CL_DEVICE_MAX_MEM_ALLOC_SIZE: 32 MByte
CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: Read/Write
CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: 64
CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: 4096
CL_DEVICE_LOCAL_MEM_SIZE: 1 KByte
CL_DEVICE_LOCAL_MEM_TYPE: Global
CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: 4 KByte
CL_DEVICE_MAX_CONSTANT_ARGS: 9
From above output, it is clear that 64MByte is the limit for Global Memory allocation.
Now, when I tried allocating 900Mbytes global size, i have not received any error and it is successful.
int noOfBytes = (900 * 1024 * 1024);
memPtr = clCreateBuffer(context, CL_MEM_READ_WRITE, noOfBytes, NULL, &err);
if ( err != CL_SUCESS) {
printf ("Ooops.. Failed");
}
Sounds this experiment is show proving what the clinfo claims. Am i missing any theory or something else ?
Because buffers and images are allocated on an OpenCL context (not an OpenCL device) the actual device allocation is often deferred until the buffer is used on a specific device. So while this allocation seemed to work, if you try to actually use that buffer on your device, you'll get an error.
I am using ESP32 DEVKIT link and Adafruit VS1053 Codec + MicroSD Breakout - MP3/WAV/MIDI/OGG Play + Record - v4 link to record and then play the sound. I am using Arduino IDE for coding.
I am facing an issue right now that the module uses hardware interrupt for playing purposes. But ESP32 is resetting again and again when I try to play a sound track. The debug log says:
Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1)
Core 1 register dump:
PC : 0x400d1280 PS : 0x00060834 A0 : 0x800d128f A1 : 0x3ffc0bb0
A2 : 0x3ffc241c A3 : 0x3ffb1f20 A4 : 0x800d1779 A5 : 0x3ffb1f00
A6 : 0x3ffc241c A7 : 0x3f400f9c A8 : 0x800d1280 A9 : 0x3ffc0b90
A10 : 0x0000002b A11 : 0x3f401067 A12 : 0x800d1691 A13 : 0x3ffb1ed0
A14 : 0x3ffc241c A15 : 0x00000000 SAR : 0x0000001f EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
Core 1 was running in ISR context:
EPC1 : 0x400d4123 EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x400d1280
Backtrace: 0x400d1280:0x3ffc0bb0 0x400d128c:0x3ffc0bd0 0x40080e21:0x3ffc0bf0 0x400817d5:0x3ffc0c10 0x400d3ae5:0x00000000
Core 0 register dump:
PC : 0x400ee86e PS : 0x00060934 A0 : 0x8008656c A1 : 0x3ffc7910
A2 : 0x00000008 A3 : 0x00000000 A4 : 0x00000001 A5 : 0x3ffc7f4c
A6 : 0x00000000 A7 : 0x00000001 A8 : 0x3ffc3404 A9 : 0x3ffc33e8
A10 : 0x00000000 A11 : 0x00000001 A12 : 0x00000000 A13 : 0x00000001
A14 : 0x00060b20 A15 : 0x00000000 SAR : 0x00000000 EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x00000000 LEND : 0x00000000 LCOUNT : 0x00000000
Backtrace: 0x400ee86e:0x3ffc7910 0x40086569:0x3ffc7930
Rebooting...
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:952
load:0x40078000,len:6084
load:0x40080000,len:7936
entry 0x40080310
Adafruit VS1053 Simple Test
VS1053 found
The line Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1) indicates that its interrupt wdt.
I searched ways to disable interrupt WDT but no help. The file esp_int_wdt.h in ~Documents\Arduino\hardware\espressif\esp32\tools\sdk\include\esp32 provides two functions for enabling interrupt WDT for both or one CPU. There is no function to disable it.
How to disable ESP32 interrupt WDT?
#include "soc/rtc_wdt.h"
rtc_wdt_protect_off();
rtc_wdt_disable();
Or turn it off in menuconfig. I agree with other posters though, you should not turn it off, instead, you can also feed it with the following function:
rtc_wdt_feed();
I usually create a lowest priority FreeRTOS task that just loops and calls the feed method with a delay less then the timeout, giving enough time for higher priority "business logic" to run. Example:
Set timeout to 250 ms in menuconfig or in code:
rtc_wdt_set_length_of_reset_signal(RTC_WDT_SYS_RESET_SIG, RTC_WDT_LENGTH_3_2us);
rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_SYSTEM);
rtc_wdt_set_time(RTC_WDT_STAGE0, 250);
Then do this in your task:
while(true) {
rtc_wdt_feed();
vTaskDelay(pdMS_TO_TICKS(100));
}
This will feed both the FreeRTOS WDT and the RTC WDT and reset your system if it gets stuck in a loop or doesn't processes within your time requirements. You'll need to play with the timeout and how often you feed the timer to get it right for your system.Keep in mind the Wifi, PHY, and BT are not deterministic so you'll have a lot of unpredictability in timing if you are dependent on DAQ from from "the net".
I don't know how to disable watchdog using arduino, but I can tell you how to disable it using esp-idf and its make menuconfig
Open menuconfig: make menuconfig
Enter component config
Enter ESP32-specific
Remove star from interrupt watchdog
P.S. According to esp-idf docs void esp_int_wdt_init() is used to init interrupt watchdog. This function is called when IWDT enabled in menuconfig. So you can try to find call of this function and remove it ;)
BUT:
I advise you to not disable watchdog. Instead of this, try to use FreeRTOS tasks to execute large amount of code on interrupt.
Im not sure how to do it exactly in arduino platform, but I can tell how I did it using esp-idf
First, create interrupt handler with signature void f(void*)
void MyHandler(void* pData){
/* Your code here */
vTaskDelete(NULL); // delete current taks, must have
}
Second, in interrupt handler you have to create new task, using xTaskCreate or xTaskCreatePinnedToCore. For example, xTaskCreate(MyHandler, "int_handler", 256, NULL, 4, NULL); (Check out api reference)
That's all, now you can run big code on your interrupt. In addition to this, I advise you to not create too many tasks. System may hang.
P.S. If you need to handle tonns of interurpt requests per second, try to use FreeRTOS queues
The watchdog timer plays an important role in system stability.
Rather than disabling the watchdog timer, try to make sure that you don't stay in loop() for too long. You should always structure your code so that you do the least work you can in loop() and let it return. When it returns the software that supports your ESP32 application gets to do important housekeeping tasks, and reset the watchdog timer.
For instance, you should never write:
void loop() {
while(1) {
do_some_work();
}
}
and instead you should write:
void loop() {
do_some_work();
}
If you absolutely have to do more work in loop() than the watchdog timer allows for, make sure you call yield() or delay() occasionally from your code; this will allow the system to catch up on things it needs to do. yield() will return immediately after doing any needed housekeeping work; delay(milliseconds) will return milliseconds later after doing any needed work.
So rather than write
void loop() {
unsigned long start_time = millis();
while(millis() - start_time < 10*1000) { }
do_some_work();
}
which would cause the watchdog timer to go off, you'd want to write
void loop() {
delay(10*1000);
do_some_work();
start_time = millis();
}
or even better, if your loop may be servicing multiple needs:
void loop() {
static unsigned long start_time1 = millis();
static unsigned long start_time2 = millis();
if(millis() - start_time >= 10*1000) {
do_some_work1();
start_time1 = millis();
}
if(millis() - start_time >= 20*1000) {
do_some_work2();
start_time2 = millis();
}
}
I use HELTEC ESP32 LORA.
Board selected in arduino HELTEC WIFI LORA 32 (V2)
My firmware works fine, but same firmware one year later the esp32 start to reset in the interrupt.
the message in the terminal
Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1).
I checked the :
1.- Watch dog, it did not work
2.- decrease the program inside the interrupt, it did not work.
Finally, the solution WAS...
Downgrade the ESp32 by expressive system library from 2.0.6 to 2.0.3
I hope it be useful
Bye
Is there anyway to make ip address words display in the decimal dotted format in the waves window?
As far as I know, not...
But you could create virtual signals for the 4 parts ('virtual signal ...').
Display those as decimal ('-radix unsigned').
And create a group with those 4 virtual signals ('add wave ... -group ...) .
I found creating virtual signals and groups easier in the GUI then typing it yourself in the DO file ('Tools' -> 'Virtual Builder').
A test VHDL file:
library ieee;
use ieee.std_logic_1164.all;
entity test is
end entity test;
architecture rtl of test is
signal ip : std_logic_vector(31 downto 0) := x"AC_10_41_3D"; -- 172.16.65.61
begin -- architecture rtl
end architecture rtl;
The important parts of a wave.do file:
quietly virtual signal -install /test { /test/ip(31 downto 24)} ip_3
quietly virtual signal -install /test { /test/ip(23 downto 16)} ip_2
quietly virtual signal -install /test { /test/ip(15 downto 8)} ip_1
quietly virtual signal -install /test { /test/ip(7 downto 0)} ip_0
add wave -noupdate /test/ip; # without formatting
# group the 4 parts of the IP address and display them as decimal
add wave -noupdate -expand -group {IP_formatted} -radix unsigned /test/ip_3
add wave -noupdate -expand -group {IP_formatted} -radix unsigned /test/ip_2
add wave -noupdate -expand -group {IP_formatted} -radix unsigned /test/ip_1
add wave -noupdate -expand -group {IP_formatted} -radix unsigned /test/ip_0