Languages

CommunityCategory: XMODELComputing the power spectral density (PSD) of an xreal-type signal

XMODEL

Computing the power spectral density (PSD) of an xreal-type signal

SA Support Team Staff 2024-05-20

Can you show me an example of plotting the power spectral density (PSD) of some random signal and computing its power within a certain frequency range?

1 Answers
SA Support Team Staff 2024-05-20

Yes. With the XMODEL Release 2024.05 or later, you can estimate the power spectral density (PSD) of an xreal-typed signal and compute the signal's power within a certain frequency range using a Python script explained below. For plotting the PSD only, you can also use the XWAVE's PSD analysis.

First, we generate a random non-return-to-zero (NRZ) signal using a testbench shown below. The 'clk_gen' primitive sets the data rate at 1Gb/s, the 'prbs_gen' primitive generates an xbit-type, random binary signal named 'data', and the 'transition' primitive converts it to an xreal-type, analog signal 'out' with the levels of +1.0 and -1.0. The expected average power of this signal is 1.0. The commands $xmodel_dumpfile() and $xmodel_dumpvars() store the signal's waveform into a file named 'xmodel.jez' in JEZ format.

// TESTBENCH tb_nrz.sv
// Generating a 1Gb/s random NRZ signal.

module tb_nrz;

xbit clk, data;
xreal out;

clk_gen     #(.freq(1e9))   U_CLK (.out(clk));
prbs_gen    #(.length(31))  U_DATA (.out(data), .trig(clk));
transition  #(.value0(-1.0), .value1(1.0)) U_DRV (.in(data), .out(out));

initial begin
    $xmodel_dumpfile("xmodel.jez");
    $xmodel_dumpvars();
end

endmodule

The following Python script reads the simulated random NRZ signal from the waveform file and computes its PSD. Once you read a 'trace' object of the signal from the waveform file, you can compute its PSD over specified time and frequency ranges using the 'eval_psd()' method. This 'eval_psd()' method returns a set of sampled PSD values of the signal along with their frequency values. With these results, you can either plot the PSD in a graph or compute the signal power within a certain frequency range.

#!/usr/bin/env xmodelpy

import numpy as np
import matplotlib.pyplot as plt
import xmulan
import xwave

# parameters
filename = "xmodel.jez"                 # waveform filename
signame = "tb_nrz.out"                  # signal name
time_range = (0.0, 10e-6)               # measurement time range (0~10us)
freq_range = (0.0, 10e9)                # measurement frequency range (0~10GHz)
window = 'Rectangular'                  # window function

# read waveform file
row = xmulan.rowml().readmeas(filename)
trace = row[signame]

# compute PSD 
psd, freq = trace.eval_psd(interval=time_range, freq_range=freq_range, window=window)

# calculate power over the entire frequency range
Ptot = np.trapz(psd, freq)

# calculate power over the frequency range of f1 ~ f2
f1, f2 = 0.0, 0.5e9                     # 0 ~ 0.5GHz
index, = np.where(np.logical_and(f1 <= freq, freq <= f2))
Pnyq = np.trapz(psd[index], freq[index])

# plot results using XWAVE
ax = xwave.create_plotaxes(use_xlabel=True)
ax.plot(freq, 10*np.log10(psd), label=signame)
ax.set_xlabel('Frequency (Hz)', fontsize=12)
ax.set_ylabel('Magnitude (dB)', fontsize=12)
ax.set_xlim([np.min(freq), np.max(freq)])
ax.grid(True)
ax.text(5e9, -100, 'Power(f=0~10GHz) = %.4g\nPower(f=0~0.5GHz) = %.4g' % (Ptot, Pnyq))

window = xwave.open_xwave()
page = window.create_page("Meas 1", "analysis")
page.add_newpane(['PSD:']+xwave.get_legends(ax), ax.figure)
xwave.show_xwave()

This example script computes two power values using the PSD results. The first power value 'Ptot' computes the total power by integrating the PSD values over the entire frequency range. The 'trapz' function of 'numpy' is handy when computing this integration. The second power value 'Pnyq' computes the power within the Nyquist frequency of this NRZ signal (=0.5GHz). Again, the integration is computed using the 'trapz' function, after finding the data indices that correspond to the desired frequency range of 0~0.5GHz.

The attached package includes the XMODEL testbench and Python script explained above. Use the following commands on the Linux prompt to run them:

$ xmodel tb_nrz.sv --top tb_nrz --simtime 10us
$ xmodelpy calc_psd.py

And shown below is the PSD plot of the 1Gb/s NRZ signal and the calculated power values. The total power 'Ptot' has a value of 0.9919 which is close to the expected value of 1.0 and the power within the Nyquist frequency 'Pnyq' has a value of 0.8244. In other words, an NRZ signal has 82.4% of its total power within the Nyquist frequency.

Attachment: calc_psd_20240520.tar.gz

XMODEL

xreal 타입 신호의 파워 스펙트럼 밀도(power spectral density; PSD) 계산하는 방법

SA Support Team Staff 2024-05-20

어떤 랜덤한 신호의 파워 스펙트럼 밀도(power spectral density; PSD)를 그리고, 특정 주파수 대역내의 파워 수치를 계산하는 예제를 보여주실 수 있나요?

1 Answers
SA Support Team Staff 2024-05-20

Yes. With the XMODEL Release 2024.05 or later, you can estimate the power spectral density (PSD) of an xreal-typed signal and compute the signal's power within a certain frequency range using a Python script explained below. For plotting the PSD only, you can also use the XWAVE's PSD analysis.

First, we generate a random non-return-to-zero (NRZ) signal using a testbench shown below. The 'clk_gen' primitive sets the data rate at 1Gb/s, the 'prbs_gen' primitive generates an xbit-type, random binary signal named 'data', and the 'transition' primitive converts it to an xreal-type, analog signal 'out' with the levels of +1.0 and -1.0. The expected average power of this signal is 1.0. The commands $xmodel_dumpfile() and $xmodel_dumpvars() store the signal's waveform into a file named 'xmodel.jez' in JEZ format.

// TESTBENCH tb_nrz.sv
// Generating a 1Gb/s random NRZ signal.

module tb_nrz;

xbit clk, data;
xreal out;

clk_gen     #(.freq(1e9))   U_CLK (.out(clk));
prbs_gen    #(.length(31))  U_DATA (.out(data), .trig(clk));
transition  #(.value0(-1.0), .value1(1.0)) U_DRV (.in(data), .out(out));

initial begin
    $xmodel_dumpfile("xmodel.jez");
    $xmodel_dumpvars();
end

endmodule

The following Python script reads the simulated random NRZ signal from the waveform file and computes its PSD. Once you read a 'trace' object of the signal from the waveform file, you can compute its PSD over specified time and frequency ranges using the 'eval_psd()' method. This 'eval_psd()' method returns a set of sampled PSD values of the signal along with their frequency values. With these results, you can either plot the PSD in a graph or compute the signal power within a certain frequency range.

#!/usr/bin/env xmodelpy

import numpy as np
import matplotlib.pyplot as plt
import xmulan
import xwave

# parameters
filename = "xmodel.jez"                 # waveform filename
signame = "tb_nrz.out"                  # signal name
time_range = (0.0, 10e-6)               # measurement time range (0~10us)
freq_range = (0.0, 10e9)                # measurement frequency range (0~10GHz)
window = 'Rectangular'                  # window function

# read waveform file
row = xmulan.rowml().readmeas(filename)
trace = row[signame]

# compute PSD 
psd, freq = trace.eval_psd(interval=time_range, freq_range=freq_range, window=window)

# calculate power over the entire frequency range
Ptot = np.trapz(psd, freq)

# calculate power over the frequency range of f1 ~ f2
f1, f2 = 0.0, 0.5e9                     # 0 ~ 0.5GHz
index, = np.where(np.logical_and(f1 <= freq, freq <= f2))
Pnyq = np.trapz(psd[index], freq[index])

# plot results using XWAVE
ax = xwave.create_plotaxes(use_xlabel=True)
ax.plot(freq, 10*np.log10(psd), label=signame)
ax.set_xlabel('Frequency (Hz)', fontsize=12)
ax.set_ylabel('Magnitude (dB)', fontsize=12)
ax.set_xlim([np.min(freq), np.max(freq)])
ax.grid(True)
ax.text(5e9, -100, 'Power(f=0~10GHz) = %.4g\nPower(f=0~0.5GHz) = %.4g' % (Ptot, Pnyq))

window = xwave.open_xwave()
page = window.create_page("Meas 1", "analysis")
page.add_newpane(['PSD:']+xwave.get_legends(ax), ax.figure)
xwave.show_xwave()

This example script computes two power values using the PSD results. The first power value 'Ptot' computes the total power by integrating the PSD values over the entire frequency range. The 'trapz' function of 'numpy' is handy when computing this integration. The second power value 'Pnyq' computes the power within the Nyquist frequency of this NRZ signal (=0.5GHz). Again, the integration is computed using the 'trapz' function, after finding the data indices that correspond to the desired frequency range of 0~0.5GHz.

The attached package includes the XMODEL testbench and Python script explained above. Use the following commands on the Linux prompt to run them:

$ xmodel tb_nrz.sv --top tb_nrz --simtime 10us
$ xmodelpy calc_psd.py

And shown below is the PSD plot of the 1Gb/s NRZ signal and the calculated power values. The total power 'Ptot' has a value of 0.9919 which is close to the expected value of 1.0 and the power within the Nyquist frequency 'Pnyq' has a value of 0.8244. In other words, an NRZ signal has 82.4% of its total power within the Nyquist frequency.

Attachment: calc_psd_20240520.tar.gz