[Programmation] Synchronisation horloge FPGA
Répondre à la discussion
Affichage des résultats 1 à 15 sur 15

Synchronisation horloge FPGA



  1. #1
    GregoireZ

    Synchronisation horloge FPGA


    ------

    Bonjour,

    je travaille actuellement sur un projet de transmission de données et je travaille actuellement sur la mise en place de la chaine de réception sur FPGA (cyclone ii) via Quartus 2.
    Alors voilà, la trame de données que je reçois en réception possède un débit de 4 Mbits/s, et je voudrais pouvoir synchroniser ma réception afin de coller à ces 4MHz théoriques pour pallier à toute dérive de fréquence.
    J'ai cru comprendre que la mise en place d'une PLL était la meilleure solution, les personnes qui ont mis en place l'émission (que je peux difficilement contacter) génère donc une suite de 0 et de 1 dans l'entête qui à mon avis doit servir comme horloge d'entrée à la PLL.
    Le problème qui m'empêche d'avancer est que la PLL disponible sous cyclone ii possède une fréquence minimale d'environ 10 MHz, je ne peux donc pas passer mes 4 MHz en entrée. J'aimerais donc savoir s'il y a possibilité de pallier à ce problème ou sinon est-ce que la réalisation d'une PLL est faisable sous VHDL?

    Merci,

    Grégoire

    -----

  2. #2
    bobflux

    Re : Synchronisation horloge FPGA

    Quel est le protocole ? L'encodage ? (Manchester, 8b10b...)

    Pour 4 MHz, une PLL n'est pas nécessaire, tu peux suréchantillonner le signal en x3 ou x4 et faire tout le décodage en numérique ! Tu as une FPGA après tout...

  3. #3
    GregoireZ

    Re : Synchronisation horloge FPGA

    Tout d'abord merci pour la réponse, j'utilise un codage 8b10b.
    Pour ce qui est du protocole, rien de particulier pour l'instant, l'entête est sur 40 bits (succession de 0 et de 1) et les data sur 80 bits. Ca va être amené à être changé une fois la chaine complète fonctionnelle avec la synchro.
    Et c'est-à-dire effectuer le décodage en numérique? Faire ca sous Matlab ou Scilab?
    Dernière modification par GregoireZ ; 27/06/2017 à 11h40.

  4. #4
    bobflux

    Re : Synchronisation horloge FPGA

    Si j'ai bien compris l'horloge est contenue dans le flux de données, comme pour l'ethernet. Dans ce cas il est impératif d'utiliser un encodage style 8b10b, Manchester ou autre qui garantit que le nombre de bits identiques transmis à la suite ne dépassera pas une certaine limite. En effet le décodeur ne pourrait pas se synchroniser sur un flux constant de zéros par exemple. L'encodage a un autre but, celui de définir le début des paquets, le début des octets, etc, dans le flux.

    Donc grosso modo ce que tu fais est un SERDES. On utilise une PLL seulement si on a pas le choix, par exemple si ton débit est à la limite de la fréquence d'horloge de ton hardware, tu peux pas suréchantillonner, donc t'es obligé d'avoir une horloge. Dans ton cas 4 MHz c'est peanuts donc tu vas le faire en suréchantillonnant, mettons 3x ou 4x.

    Supposons qu'on transmet le flux encodé suivant :

    0101

    Le récepteur suréchantillonne à 4x donc chaque bit est reçu en 4 exemplaires. Si tout est parfaitement synchronisé, on reçoit :

    Code:
    0000
    1111
    0000
    1111
    Note que je te mets les bits par 4, c'est la sortie du désérialiseur dans le récepteur, un simple registre à décalage, il prend 4 bits (à 16MHz) et après il les sort sur 4 lignes. Bon, si le récepteur est en retard, on reçoit:

    Code:
    0011 <== note pour la présentation que les bits sont dans l'ordre reçu par le désérialiseur, ici le 00 est reçu avant le 11
    1100
    0011
    1100
    Et si l'horloge du récepteur est légèrement moins rapide que celle du transmetteur, certains bits ne seront pas reçus en 4 exemplaires, mais seulement en triple. À l'opposé, si l'horloge du récepteur est trop rapide, certains bits seront reçus avec une longueur de 5 au lieu de 4. Exemple:

    Code:
    0000
    1111
    1000 <== ici le 1 a été un peu plus long !
    0111
    La solution est en réalité extrêmement simple. Il suffit de garder en réserve les bits précédent:

    Colonne A: sortie précédente du désérialiseur (4 bits reçus précédemment)
    Colonne B: sortie actuelle du désérialiseur (derniers 4 bits reçus)

    Code:
    0000 1111
    1111 1000 <== ici le 1 a duré 1 cycle de trop car notre horloge va plus vite que celle de la source
    1000 0111 <== et merde on est décalé !
    0111 1000
    Il suffit d'avoir un circuit qui regarde ces bits et tente de placer la transition au milieu. C'est hyper simple.

    - Si une transision apparaît 1 cycle trop tôt, alors on est en avance, et on shift 3 bits au lieu de 4 le prochain coup
    - Si une transision apparaît 1 cycle trop tard, alors on est en retard, et on shift 5 bits au lieu de 4 le prochain coup
    - Si la transition est au bon endroit ou qu'il n'y a pas de transition, on shift 4 bits comme d'hab.

    Toute la subtilité est que sur ton horloge à 4MHz, le bidule va sortir 1 bit par coup d'horloge, mais si ton 4MHz est 1% plus rapide que l'horloge de la source, alors une fois sur 100 ils sortira pas de bit, faudra attendre le coup suivant. Et si ton horloge locale est plus lente que la source, parfois il devra sortir 2 bits d'un coup. Donc y faut gérer ça proprement.

    Une fois que t'as compris le truc c'est simple et l'implémentation va prendre une quantité de ressources minuscule dans ta fpga.

    Tiens, des exemples fort intéressants, avec du code !

    http://hamsterworks.co.nz/mediawiki/...igh_Speed_Link
    https://opencores.org/project,tosnet
    http://www.ipcsit.com/vol51/057-A806.pdf

  5. A voir en vidéo sur Futura
  6. #5
    bobflux

    Re : Synchronisation horloge FPGA

    Atta, c'est pas fini, j'ai retrouvé un vieux code que j'avais fait pour prototyper le même genre de truc, en python bien sûr. Vais nettoyer ça et te le poster, mais d'abord... à table !

  7. #6
    GregoireZ

    Re : Synchronisation horloge FPGA

    Ta solution m'a l'air vraiment pas mal, c'est vrai que ca sera beaucoup plus simple à mettre en place de cette manière la.
    Dès demain je vais essayer ca.
    Tu m'as vachement éclairé sur ce coup, merci !

  8. #7
    jiherve

    Re : Synchronisation horloge FPGA

    Bonsoir
    Sans serdes cela va être un peu plus compliqué que çà car il faudra forcement échantillonner le flux entrant avec une horloge HF (avec un Cyclone 2 cela on doit pouvoir le faire avec une horloge à 128Mhz ou plus) il faudra forcement 2 bascules pour résoudre les métastabilités donc il y aura du jitter (une période de l'horloge HF) sur chaque transition.
    Ce qu'il faut soigner c'est la clock recovery (DDS ?) car ensuite la fonction de décodage existe.
    JR
    l'électronique c'est pas du vaudou!

  9. #8
    bobflux

    Re : Synchronisation horloge FPGA

    De rien

    J'ai ressorti mon vieux code ! (mais je pense que tu as sais). c'est du python, et il a l'air de fonctionner.
    Je l'ai écrit un peu à la manière verilog, donc pas pythonesque du tout !
    Attention lors du portage, par exemple la décrémentation de la variable wait n'arriverait qu'au cycle suivant en verilog.

    Sans les commentaires le désérialiseur prend 25 lignes de code ! LOL. Y a sûrement moyen de réduire l'utilisation de slices en ajustant le registre à décalage etc.

    Code:
    # -*- coding: utf-8 -*-
    
    # formate un octet en binaire pour affichage/debug
    def sbin(i):
        return ('{0:08b}'.format( i )).replace('0','-' )
    
    # désérialiseur avec synchro
    def deserialize( rx_symbols_str ):
        locked      = 0 # récepteur verrouillé
        shift_reg   = 0 # notre désérialiseur
        wait        = 0 # nombre de symboles restant dans le bit en cours
            
        # cette boucle tourne à Fs*4 donc 16MHz pour ton 4Mbps (oversampling)
        for r in rx_symbols_str:
            
            rx_symbol    = (r == "1")                         # string => bool
            shift_reg    = (shift_reg<<1 | rx_symbol) & 0xFF  # rentre un bit par la droite
            transitions  = 0x7F & ((shift_reg >> 1) ^ shift_reg) # xor détecte les différences, cette variable fait 7 bits
            
            # sortie: la façon classique ! Quand output_valid=1, output_bit contient le bit, valide pendant 1 cycle.
            output_bit   = "01"[(shift_reg & 8) != 0]
            output_valid = 0
            
            # décrémente le compteur, il fait juste 2 bits donc 4 = 0 !...
            wait = (wait-1) & 3
            
            print( "%s %s %s" % (sbin( shift_reg ), wait, ("LOCK" if locked else "") ))
            print( sbin( transitions ))
    
            # le but: quand la transition est entre les bits 3 et 4 de shift_reg
            # on est synchro. Donc, si un bit est à 1 dans la variable transitions
            # ça doit être le bit 3 (poids 8)
    
           
            if (transitions & 8):
                print("Locked.")
                locked = 1          # On a une transition à la bonne position, donc on a un lock.
                output_valid = 1    # on sort le bit qui vient après la transition
                wait = 0            # ... et on revient dans 4 symboles pour le prochain...
                
                # note: J'ai pas regardé la variable "wait", ici on s'en fout.
                # Si il y a une transition, on s'aligne dessus, point.
            
            # if transitions & 16
            # Le registre à décalage décale... donc si on a le bit 4 (poids 16) maintenant, ça veut dire
            # qu'au cycle précédent il était en position 3, donc il a déjà été traité par le if du dessus
            # donc on ne fait rien du tout.
            
            # on ne regarde que tous les 4 cycles ! Sinon on sortirait chaque bit 4 fois...
            elif locked:
                if not wait: # on a fini d'attendre
                    # y a pas de transition après le bit 3, ce qui nous laisse deux possibilités:
    
                    if transitions & 4:         # une transition arrive juste après, il va falloir rentrer un symbole de plus
                        print("Wait+1.")
                        wait = 1                # donc on attend juste 1 cycle qu'il soit là
                    
                    else:                       # y a pas de transition, donc on a une suite de symboles identiques
                        print("Output.")
                        output_valid = 1        # on sort le bit
                        wait = 0                # ... et on revient dans 4 symboles pour le prochain...
                        
                elif wait > 1 and (transitions & 4):
                    # une transition dans cette position avec wait>1 signifie une erreur
                    # càd un bit était plus court que 3 symboles, donc oust
                    print("ERROR.")
                    locked = 0
                    
    
            if output_valid:
                print("=> "+output_bit)
                yield output_bit
            
            print("")
    
    
    # Ce qu'on reçoit, après suréchantillonnage 4x
    # Un bit donne 4 symboles en général
    # ou 3-5 symboles selon la dérive des horloges
    # Attention: entrer un bit (donc 3 à 5 symboles identiques) par ligne !
    rx_symbols = """
    0000
    1111
    0000
    1111
    0000
    1111
    0000
    1111
    0000
    1111
    1111
    0000
    0000
    0000
    1111
    0000
    11111
    0000
    1111
    0000
    0000
    0000
    1111
    0000
    111
    0000
    0000
    1111
    1111
    0000
    1111
    00
    1111
    0000
    1111
    """
    
    # Préparation des données
    rx_lines   = rx_symbols.strip().split()
    rx_symbols = "".join( rx_lines )        # ce qu'on reçoit (sous forme de string)
    
    # Comme on a entré 1 bit par ligne, c'est facile d'extraire les bits transmis pour tester le code
    tx_bits = "".join( s[0] for s in rx_lines )
    
    rx_bits = "".join(deserialize(rx_symbols))
    
    print( " "+rx_bits )
    print( tx_bits )
    Dernière modification par bobflux ; 27/06/2017 à 22h14.

  10. #9
    bobflux

    Re : Synchronisation horloge FPGA

    Citation Envoyé par jiherve Voir le message
    Bonsoir
    Sans serdes cela va être un peu plus compliqué que çà car il faudra forcement échantillonner le flux entrant avec une horloge HF (avec un Cyclone 2 cela on doit pouvoir le faire avec une horloge à 128Mhz ou plus) il faudra forcement 2 bascules pour résoudre les métastabilités donc il y aura du jitter (une période de l'horloge HF) sur chaque transition.
    Ce qu'il faut soigner c'est la clock recovery (DDS ?) car ensuite la fonction de décodage existe.
    JR
    C'est à 4Mbits donc y aura pas de souci de fréquence... Pas besoin de clock recovery ou PLL non plus avec le principe du suréchantillonnage.

  11. #10
    jiherve

    Re : Synchronisation horloge FPGA

    Re
    Le soucis c'est que malgré le codage 8b10b il peut y avoir plusieurs zéro ou un consécutifs donc la détection de la désynchronisation demandera un grand registre si j'ai bien compris ton principe.
    Le suréchantillonnage fonctionne bien sur des mots courts(exemple UART), là il faudrait faire un test de vraisemblance entre le mot reçu(10bits) et les codes autorisés.
    Ce qui est dommage c'est d'avoir une transmission qui est trop lente pour utiliser un SERDES du commerce(Texas descend jusqu’à 10MHZ) . Mais pas de regret pour les PLL des Cyclone II elles ne sont pas utilisables pour çà.
    JR
    l'électronique c'est pas du vaudou!

  12. #11
    bobflux

    Re : Synchronisation horloge FPGA

    Citation Envoyé par jiherve Voir le message
    Le soucis c'est que malgré le codage 8b10b il peut y avoir plusieurs zéro ou un consécutifs donc la détection de la désynchronisation demandera un grand registre si j'ai bien compris ton principe.
    Non, c'est vachement plus simple que ça en fait. Quand il y a une succession de plusieurs bits identiques, il continue à piocher un bit sur 4. Quand il trouve une transition, il se recale dessus. Le registre à décalage doit faire 6 bits au maximum, plus deux pour la métastabilité, qui peuvent d'ailleurs être cadencés à une fréquence supérieure si on en a sous la main.

    Ce système n'est bien sûr utilisable que si les 2 bouts ont une horloge de fréquence à peu près égale, puisque la dérive permise durant une séquence de bits identiques ne peut excéder 1/4 de bit ! (1/16MHz ici). Heureusement n'importe quel oscillateur quartz premier prix fait ça sans problème. Une PLL aurait le même problème, il lui faut des transitions pour garder le rythme aussi.

    D'ailleurs un UART produit des séquences de bits égaux plus longues que le 8b10b (ce dernier limite à 5 bits successifs identiques, tandis que l'UART transmet ton octet brut, donc au minimum 8 si tu envoies un octet nul).

    Les liens que j'ai mis ont des trucs un peu plus évolués.

    Par contre il faut faire attention à l'intégrité du signal, si le média de transmission agit comme un filtre passe-bas ou passe-haut, alors un 1 placé après une longue séquence de zéros aura une longueur différente d'un 1 dans une séquence genre 10101010. Donc attention à avoir un "eye diagram" propre ! Mais ça c'est valable pour tous les styles de transmission.

    D'ailleurs à 4Mbps on peut utiliser les transmetteurs et récepteurs optiques dédiés au SPDIF, ça coûte 1$ et ça passe 12 Mbps... si tu as besoin d'isolation Grégoire penses-y ! (par contre les fibres optiques en plastoc qui vont avec ont une atténuation ridiculement élevée avec la distance, c'est pas du matos de haut de gamme !).
    Dernière modification par bobflux ; 28/06/2017 à 00h19.

  13. #12
    GregoireZ

    Re : Synchronisation horloge FPGA

    "Le registre à décalage doit faire 6 bits au maximum, plus deux pour la métastabilité, qui peuvent d'ailleurs être cadencés à une fréquence supérieure si on en a sous la main."

    A quoi correspondent les bits de metastabilité exactement? J'ai essayé de me renseigner mais j'ai rien trouver de bien concret.

    Sinon ce n'est pas moi qui m'occupe de la transmission des données à proprement parler, je m'occupe seulement des chaînes de traitement à l'emission et à la réception. Le type de transmission utilisé est une transmission VLC (envoi de données via des LEDs), qui est mise en place par une autre personne.

  14. #13
    albanxiii
    Modérateur

    Re : Synchronisation horloge FPGA

    Citation Envoyé par GregoireZ Voir le message
    A quoi correspondent les bits de metastabilité exactement? J'ai essayé de me renseigner mais j'ai rien trouver de bien concret.
    Les bits de métastabilité, je ne sais pas ce que c'est. LA métastabilité, oui, lié au clock domain crossing dans le cas présent (chercher avec ces mots là, il y a des réponses).

    Quand on échantillonne un signal qui a été généré à partir d'une autre horloge que celle d'échantillonnage, on n'est pas sur de taper à des instants où le signal est "propre". Il en résulte une sortie indéfinie pour l'échantillonneur. Elle peut passer à 1 ou à 0 après un certain temps.
    Ce phénomène est très bien documenté http://webee.technion.ac.il/~ran/pap...ers.posted.pdf donne de belles courbes. On peut regarder https://www.altera.com/content/dam/a...astability.pdf aussi.

    Et c'est effectivement à prendre en compte quand plusieurs horloges entrent en jeu.
    Not only is it not right, it's not even wrong!

  15. #14
    bobflux

    Re : Synchronisation horloge FPGA

    Oui, tout signal entrant et non synchronisé sur ton horloge doit d'abord passer par au minimum 2 flops pour éviter ces effets qui sont ennuyeux.

    Tu peux soit:
    - les instancier séparément du registre à décalage du décodeur, ce qui te permet d'utiliser une horloge plus rapide si tu en as une, je ne suis pas sûr de l'utilité de cette démarche...
    - ou bien les mettre dans le registre à décalage, ce qui rallonge ton registre de 2 bits (c'est pour ça que je parlais de bits).

  16. #15
    jiherve

    Re : Synchronisation horloge FPGA

    Bonsoir,
    Il faut de façon générale effectuer le traitement anti métastabilité avec l'horloge des circuits situés en aval, exception a ce cas si on connait avec certitude la relation de phase entre les deux horloges et que celle ci est fixe, exemple on échantillonne sur le front montant une horloge à 2F et on traite le front montant d' une horloge à F si ceux ci sont synchrone du front descendant de 2F et si l'écart entre les deux fronts actif est > à Tplh (bascule entrée)+ T setup (registre).
    L'un des pièges classique dans les FPGA c'est l'utilisation d'horloges dérivées dont les fronts montants sont presque en phase , cela tombe en marche durant le maquettage et explose lors de la série (du vécu traité par culpédothérapie ensuite).
    JR
    l'électronique c'est pas du vaudou!

Discussions similaires

  1. Synchronisation horloge
    Par CaptainBobb dans le forum Internet - Réseau - Sécurité générale
    Réponses: 0
    Dernier message: 01/10/2015, 18h09
  2. Synchronisation horloge
    Par Arateriou dans le forum Électronique
    Réponses: 8
    Dernier message: 09/06/2015, 21h46
  3. Synchronisation entre horloge atomique et horloge d'un récepteur GPS
    Par invite0e188b54 dans le forum Électronique
    Réponses: 10
    Dernier message: 06/12/2012, 22h56
  4. Synchronisation horloge (DCF77 ?)
    Par invite5e9b0d45 dans le forum Électronique
    Réponses: 8
    Dernier message: 06/07/2010, 16h03
  5. Horloge atomique, synchronisation du GPS
    Par invite2088ca37 dans le forum Technologies
    Réponses: 4
    Dernier message: 27/11/2008, 07h18
Découvrez nos comparatifs produits sur l'informatique et les technologies.