Hay un montón de soluciones, nombraré algunas y luego mostraré cuál usaré.
- Una solución de hardware, a saber, un detector de envolvente pero con otro capacitor en la entrada. Así que terminas con un total de dos condensadores, ve el enlace e imagina un segundo condensador en la entrada. El capacitor en la entrada dejará pasar más potencia a medida que aumenta la frecuencia, lo que a su vez aumentará el voltaje en la salida. La salida puede simplemente leerse digitalmente y listo.
- Utilice correlación cruzada , en otras palabras, simplemente multiplique los datos entrantes por una forma de onda esperada y la suma y el valor que reciba aumentará cuando se superponga, busque aquí para obtener más información.
- Use FFT con una ventana deslizante de menos de 100 ns y simplemente busque en la bandeja de frecuencia la forma de onda que espera .
- Use Algoritmo de Goertzel que es esencialmente una versión reducida de la FFT. Literalmente es solo un tono de la FFT mientras que la FFT recupera todas las frecuencias hasta la frecuencia de nyquist. Solo te interesan dos frecuencias, pero esto puede reducirse a una frecuencia porque hay una forma de onda A o una forma de onda B. No estás tratando con una tercera y una cuarta. Por lo tanto, solo necesita un filtro de Goertzel para recuperar un 1 o un 0. El algoritmo de Goertzel tiene que decaer, de lo contrario sumará y sobrecargará su FPGA.
- Registre el valor del tiempo transcurrido entre los últimos flancos. En otras palabras, es solo un contador que se restablece en el flanco ascendente o descendente, lo que sea más fácil. Y simultáneamente en el reinicio pasa su valor a otro registro. Luego toma ese valor y pasa bajo. Este valor filtrado será muy fácil de trabajar.
- O en lo que casi estabas. Cuente el número de bordes detectados en un tiempo dado. Y luego pase el número de conteo como el punto anterior y eventualmente obtenga la información.
La forma de onda de oscilación rápida parece ser 14 / (100 ns) = 140 MHz y la forma de onda de oscilación lenta parece ser 8 / (100 ns) = 80 MHz. Los FPGA normalmente se ejecutan a 50 MHz, lo que significa que la frecuencia de nyquist es de 25 MHz, lo que significa que sus señales tendrán un alias.
La última viñeta que mencioné, que es lo que estaba cerca, quizás funcionaría si usara el conteo asíncrono, porque entonces su reloj de 50 MHz no está relacionado con los eventos. Pero el conteo asíncrono también tiene un límite superior, revise su hoja de datos para su FPGA, podría llegar a 140 MHz, quién sabe. Yo no. Realmente no recomiendo esta solución porque su FPGA podría calentarse drásticamente porque está contando muy rápido.
Con una frecuencia de reloj de 50 MHz, el 140 Mhz se doblará a 140 mod 25 = 15 MHz y su 80 MHz se doblará a 80 mod 25 = 5 MHz debido a aliasing ( undersampling ). Esto significa que se puede implementar un algoritmo simple de Goertzel que solo mire a 15 MHz o 5 MHz. Elijo 15 MHz.
Aquí hay un pseudocódigo que implementaría un algoritmo de Goertzel deslizante que decae. La fase no es realmente 100% correcta porque no me importa. Nos preocupa la amplitud, la presencia de una onda, no la fase.
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!
}
}
El pseudocódigo asume que sabes números complejos y lo que estás haciendo. Nunca he tratado con Verilog y, por lo tanto, no puedo producir nada cercano a él. Pero este pseudocódigo debería ser implementado fácilmente.
Si tuviera más conocimiento sobre el FPGA, tal vez lo resolvería con la solución de hardware porque entonces no hay relojes involucrados, pero esto significa que es posible que tenga que soldar una PCB, lo que puede ser problemático. Oh bien. Si algo se ve mal o no está claro, haga un comentario y actualizaré esta respuesta. O tal vez incluso eliminarlo.