While teaching communication system to my students, I showed different ways to define the diagram block of the system responsible for transforming a bandpass signal, $x(t) \in \mathbb{R}$, into its lowpass equivalent signal, $x_l(t)\in\mathbb{C}$. This module is commonly called a down-converter (some authors ambiguously refer to it as demodulator).

Here are the most common approaches (sorry for the different notations, I am extracting these images from multiple sources):

1 Real-valued signal implementation

enter image description here

2 Complex-valued signal implementation

enter image description here

3 Implementation via Hilbert filter (more called Hilbert transform)

enter image description here

You find the first two notations in the most elementary communication systems textbooks, while the third one is preferable in the most advanced ones. Nevertheless, all architectures must result in the same signal since their mathematical definitions agree.

I am used to implement and use the first two architectures. The system model, implemented in Simulink, has the following architecture (shown here is the complex-valued implementation): enter image description here

where the FIR filter is a lowpass filter implemented in direct-form and using the equiripple design method. The real-part of the complex envelope agrees with the baseband signal, except for the delay that is naturally introduced by the filtering (there is no impairments, such as white noise or loss of synchronism): enter image description here

However, out of curiosity, I implemented the third one. To my surprise, it didn't work well... The down-converter has the following architecture: enter image description here

where the Hilbert filter is a built-in Simulink block that filters the input signal via Hilbert transform. Unfortunately, the complex envelope does not agree with the transmitted one (again, only the real part is shown). enter image description here

  • Is there a practical constrainment regarding the Hilbert transform?
  • Has anyone here already down-converted signals via Hilbert transform?

Here is my Simulink model, if you are up for seeing it. Any feedback is welcome :)

  • 3
    $\begingroup$ I suspect that one issue is that you have to compensate for the delay of the Hilbert filter and it's combination with the main signal $\endgroup$
    – David
    Nov 23, 2022 at 18:50
  • $\begingroup$ @David That is right, I must do so. I just corrected here, but the result is not good yet :( $\endgroup$ Nov 23, 2022 at 22:39

2 Answers 2


Having a look at the design of your Hilbert FIR filter, I don't think having +5 dB to -10 dB ripple on the magnitude response will give a good result. You might want to play with the design parameters and get a flatter response.

Magnitude response of Hilbert filter in OP's SLX file.

  • $\begingroup$ How did you figger out how his Hilbert filter was designed? $\endgroup$ Nov 23, 2022 at 19:36
  • $\begingroup$ @robertbristow-johnson I opened up the SLX file (Simulink file) that was in the OP. Then I opened up the Hilbert block to see what the filter looked like. It looks like that. $\endgroup$
    – Peter K.
    Nov 23, 2022 at 19:51
  • $\begingroup$ @PeterK. that is a good guess. I will investigate it and give a feedback soon. $\endgroup$ Nov 23, 2022 at 22:08

I've found some interesting clues so far. Matlab have a command called hilbert() and I decided to compare the output of a getting on Simulink with this function.

If you pay attention, the Hilbert block

enter image description here

is actually a mask. If you click on the down arrow, you will see the coefficients of a FIR filter, which are the coefficients of the implemented Hilbert filter on Simulink. I saved these coefficients in the variable h.

In order to get rid of Simulink and go to Matlab command window, I collected the signals of my model enter image description here

In addition, I collect the output of the complex-based implementation as well (this signal was called r_hat_n).

On command window, I got the data only:

r_n = reshape(out.r_n.Data(1:10e3),[], 1);
r_hat_n = reshape(out.r_hat_n.Data(1:10e3),[], 1);
r_hathilbert_n = reshape(out.r_hathilbert_n.Data(1:10e3),[], 1);

Then, the convolution of r_n and h confirmed that h is, indeed, that impulse response of Simulink block as both it matches with r_hathilbert_n:

enter image description here

By taking the low-pass equivalent via Hilbert transform in code-line, we get

t = out.tout(1:10e3);
r_hat2_n = (circshift(r_n,-length(h)) + 1i*hilbert(r_n)).*exp(-1i*2*pi*fc.*circshift(t,-length(h)));
plot([real(r_hat2_n) real(r_hat_n)])

enter image description here

Note that I took into account the delay of the Hilbert transform. It resembles the low-pass equivalent base-band, but with high-order interference...

The signal of code-line is rather different from the signal obtained in Simulink model, though...

plot([real(r_hat2_n) real(r_hathilbert_n)])

enter image description here

My partial conclusions

  • Hilbert filter differs from the hilbert() command line. Honestly, I only know the mathematical definition of the Hilbert transform, but I never went after the implementation aspects of it.
  • The Hilbert transform seems to have implementation issues, probably due to its exotic transfer function (abrupt discontinuity on DC level and unlimited in frequency). Such limitation leads to a poor down-conversion.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.