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.
Translating the times that the frequency of the pulses is more to "1"
.... what do you mean by frequency being "1"? ... 1Hz, 1kHz, 1MHz ????? \$\endgroup\$