# Demodulation of a data

As seen in this picture, I have a circuit that has created those desired pulses in the output. There is a last stage in my circuit and that is: Translating the times that more pulses have happened to "1", and the times that fewer pulses have been received to "0" (for examples as seen in the picture). in other words I need to get the second signal in the picture as my output (Latency is not important, but the width is important). I tried low pass filtering the output. but it doesn't give me a square wave. I thought of counting the pulses. (more than 5 pulses in 50 nanoseconds would translate into "1"). But I don't know if it can be done using a Verilog-A cell view in Cadence.

Update: This is a Super-Regenerative Receiver (SRR) which mostly works with an oscillator that periodically turns on and off. when there is an input signal, the oscillator triggers sooner compared to when there is no input signal. Then there is an envelope detector that tracks the envelope and compares it with a reference voltage. then the output of envelope detector is fed to a comparator which creates these pulses in the first picture. now I need to demodulate these narrowly spaced pulses as high value and the widely spaced ones as low value. I don't know how to do that.:(

• it is unclear what you are asking .... please try to rewrite your question .... Translating the times that the frequency of the pulses is more to "1" .... what do you mean by frequency being "1"? ... 1Hz, 1kHz, 1MHz ????? – jsotola Aug 23 '18 at 18:25
• @jsotola As you see in the picture, in the first 100 nano seconds, there are 8 pulses, and from 100ns to 200ns there are 14 pulses. I want to find a way to see 0-100ns as zero level (because there are fewer pulses compared to 100ns - 200ns) and 100ns - 200ns as the high level received. – Fateme Aug 23 '18 at 18:45
• @Fateme as in ... a low pass filter? Or a resettable counter? – Marcus Müller Aug 23 '18 at 18:59
• @Fateme What frequency is your FPGA running at? Or rather, which frequency can you reach for a digital filter internally on the FPGA? – Harry Svensson Aug 23 '18 at 19:04
• At first this can look out trivial (except if it must be implemented in a certain programmable logic system) But it isn't. The accuracy will vary drastically depending on is the signal somehow synchronized with the data stream - should the decision be based on a single pulse interval or on a known bit interval or on even more complex known patterns? – user287001 Aug 23 '18 at 19:11

There are tons of solutions, I will name a few and then show which one I'd use.

• A hardware solution, namely an envelope detector but with another capacitor on the input. So you end up with a total of two capacitors, see link and imagine a second capacitor on the input. The capacitor on the input will let through more power as frequency goes up which in turn will increase the voltage at the output. The output can simply be read digitally and you're done.
• Use cross-correlation, in other words just multiply the incoming data by an expected waveform and sum and the value you receive will spike when it overlaps, look here for more information.
• Use FFT with a sliding window that is less than 100ns long and simply look in the frequency bin for your expected waveform.
• Use Goertzel's Algorithm which essentially is a stripped down version of the FFT. It is literally just one tone of the FFT while the FFT retrieves all the frequencies up to the nyquist frequency. You are only interested in two frequencies, but this can be reduced to one frequency because either there is a waveform A, or a waveform B. You are not dealing with a third and a fourth. So you only need one Goertzel filter to retrieve a 1 or a 0. The Goertzel's Algorithm needs to decay, otherwise it will sum and overload your FPGA.
• Give a register the value of the time elapsed between the last flanks. In other words it's just a counter that resets on rising or falling edge, whichever is easiest. And simultaneously on the reset it passes its value off to another register. Then take that value and low-pass it. This filtered value will be very easy to work with.
• Or what you were almost at. Count the number of edges detected in a given time. And then low-pass the counting number as the previous bullet and eventually acquire the information.

The fast oscillating waveform appears to be 14/(100 ns) = 140 MHz and the slow oscillating waveform appears to be 8/(100 ns) = 80 MHz. FPGA's usually run at 50 MHz meaning that the nyquist frequency is 25 MHz which means that your signals will be aliased.

The last bullet I mentioned which is what you were close to would maybe work if you used asynchronous counting, because then your 50 MHz clock is not related to the events. But the asynchronous counting has an upper limit as well, check your datasheet for your FPGA, it might go up to 140 MHz, who knows. I don't. I don't really recommend this solution because your FPGA might heat up drastically because it's counting very fast.

With 50 MHz clock frequency, the 140 Mhz will bend over to 140 mod 25 = 15 MHz and your 80 MHz will bend over to 80 mod 25 = 5 MHz due to aliasing (undersampling). This means that a simple Goertzel's Algorithm can be implemented that is only looking at either 15 MHz or 5 MHz. I choose 15 MHz.

Here's some pseudo-code that would implement a sliding Goertzel's Algorithm that decays. The phase isn't really 100% correct because I don't care about. We're caring about the amplitude, the presence of a wave, not the phase.

void setup(){
Complex G = 0
//in my pseudo-code "Complex" is a datatype that means a+ib

Re A = 0.5
//This is for making a decaying Goertzel filter.
//Re means Real
//Im means Imaginary

//The resulting amplification of a 140 Mhz(= 15 Mhz) sine wave
//will be 1/(1-A) = 2. So if the amplitude is 8
//then the amplitude of G will be around 16, and squared around 256

Complex W = A*e^(-i*2*pi*15/50)
= A(cos(-2*pi*15/50) + i*sin(-2*pi*15/50))
= a+ib
≃ -0.15 -0.47i
//I hope you know how complex numbers works.

bool X = 140/80 Mhz waveform
//This is the 140/80 MHz waveform, one sample.
//You can multiply this value so it's large,
//like 8 or higher if you want higher resolution
//it's effectively fixed point arithmetic.
//(a multiplication by 8 is the same as padding 3 LSB zeros)

Re amplitude = 0
//This will be proportional to the amplitude of 140 Mhz
//waveform. So you will want to compare this variable to something
}

void loop(){//@always posedge (50 Mhz clock) or whatever it is
G = X + G*W

//Here's the same information but verbose
//A = Re(X) + Re(G)Re(W) - Im(G)Im(W)
//B = Im(X) + Re(G)Im(W) + Im(G)Re(W)
//Re(G) = A
//Im(G) = B

amplitude = Re(G)*Re(G)+Im(G)*Im(G)
//you could square root the amplitude if you want the actual length
//but just "square" your value you are comparing and get rid of
//the square root. It's more efficient this way.
if (amplitude > 100){
//We've detected a 1!
//since we didn't square root it,
//the amplitude of G is above sqrt(100) = 10.
}else{
//If we haven't detected 140 Mhz
//then it must be 80 Mhz
//then it must be a 0
//We've detected a 0!
}
}


The pseudo-code assumes that you know complex numbers and what you are doing. I've never dealt with Verilog and can therefor not produce anything remotely close to it. But this pseudo-code should be easily implemented.

If I had more knowledge about the FPGA I would maybe solve it with the hardware solution because then there's no clocks involved, but this means that you might have to solder on a PCB which can be troublesome. Oh well. If anything looks wrong or is not clear then make a comment and I will update this answer. Or maybe even delete it.

• "FPGA's usually run at 50 MHz"? Not really. FPGAs run at whatever frequency you clock them with, subject to meeting timing. 50MHz is quite glacial with modern FPGAs. – Tom Carpenter Feb 1 at 14:27

Think of the widely spaced pulses as missing a pulse.

The rising edge of the bottom signal would be where you detect no missing pulse. (marked in red)

The falling edge would be when the pulse start to miss again. (marked in yellow)

The resulting waveform would have ~66% duty cycle.

The blue line is midpoint between the red lines and its position would have to be calculated (if you want 50% duty cycle).

If you want a waveform with 50% duty cycle, then you could also have the falling edge at the first pulse after a wide space, then count pulses to obtain the rising edge. (purple waveform)

• Thanks for the reply. No I don't need a 50 % duty cycle. I want the times that I have more pulses to give me the level high. please read the question. I edited it – Fateme Aug 24 '18 at 17:05
• i understand what you want now ..... you have to be very careful about how you describe your requirement ..... I want the times that I have more pulses to give me the level high ..... you could have more of the widely spaced pulses .... i think that you need to refer to the spacing between the pulses ... do not refer to the number of the pulses – jsotola Aug 24 '18 at 17:39
• referring to the picture at i attached, would the rising edges at the red lines and the falling edge at the yellow line satisfy your requirement? .... could the falling edge be further to the right, so that it lines up with the rising edge of the pulse? (where the purple waveform falls) – jsotola Aug 24 '18 at 17:44
• yes it would be fine. But this first picture that I attached is not how my circuit always responds. this response is for a somehow high input value. dependent on the input level (the strength of the signal injected to the oscillator as seen in the second picture I posted), the space between pulses while the input is high varies. If a lower level input is applied the space between pulses, when the input is high becomes more. If I lessen the input level to the circuit even more, I'll reach to a point that all the pulses are spaced equally (sensitivity level). – Fateme Aug 24 '18 at 18:17
• all the pulses are spaced equally .... then there would be no data that could be extracted, unless there is some other property in the signal that would indicate a 1 or a 0 – jsotola Aug 24 '18 at 18:24

Filter your pulses to get a varying DC level. Then simply use level detection to produce your highs and lows.