Altifigence Academy

63 / 63 · Concept

Projet pratique : émetteur UART et timing des trames

Combiner division d'horloge, décalage et contrôle de flux pour une trame 8N1, puis vérifier les limites de bits.

Fixer d'abord la trame

Prérequis : compteurs, registres à décalageRegistre Circuit stockant plusieurs bits d'état. Les registres synchrones du cours capturent leur entrée définie sur un front d'horloge. En savoir plus, valid/ready et reset synchroneReset Commande ramenant l'état à la valeur initiale spécifiée. Son caractère synchrone/asynchrone et sa priorité sur les autres commandes doivent être définis. En savoir plus.

Le format UARTUART Dispositif de communication série utilisant bits de départ, données et arrêt sans ligne d'horloge séparée. Émetteur et récepteur doivent convenir du débit en baud et du format de trame. 8N1 contient un bit de départ, huit bits de données, aucune parité et un bit d'arrêt. Idle et stop valent 1, start vaut 0, et les données partent LSBLSB Bit de poids le plus faible. Vérifiez ensemble sens d'écriture et règles d'indexation. En savoir plus d'abord. Tous les bits ont la même durée. Ce TP traite seulement l'émission avec un fournisseur de données dans le même domaine d'horloge.

Bactual=fclkD,ϵ=Bactual−BtargetBtarget×100%B_{\mathrm{actual}}=\frac{f_{\mathrm{clk}}}{D},\qquad \epsilon=\frac{B_{\mathrm{actual}}-B_{\mathrm{target}}}{B_{\mathrm{target}}}\times100\%

Pour 48MHz et 115200 baud visés, choisissez par exemple le diviseur entier D=417. Le débit réel vaut environ 115108 baud, soit −0.080 %. La tolérance incluant le récepteur doit être vérifiée dans les spécifications des composants.

Dérouler 0x53 dans l'ordre transmis

0x53 s'écrit 01010011, mais les données sur le fil sont 1,1,0,0,1,0,1,0. Une case du dessin est une durée de bit de D cycles système, pas un cycle. Les intervalles idle avant et après sont montrés chacun sur une case pour comparaison.

UART 8N1 · 0x53 · LSB en premier
Voir les données du chronogramme
Données du chronogramme : chaque caractère représente un intervalle ; un point maintient l'état précédent ; p représente un cycle d'horloge.
SignalForme d'ondeValeurs du bus
tx101.0.10101.
phase234523452345repos → départ → d0 → d1 → d2 → d3 → d4 → d5 → d6 → d7 → arrêt → repos

De start à la fin de stop, il y a exactement 10D cycles. Deux bits égaux successifs occupent chacun leur durée ; l'absence de transition ne supprime pas un bit.

Capturer l'octet une seule fois

CLKS_PER_BIT est une constante ≥1. Pendant busy, aucune entrée n'est acceptée ; seule la donnée capturée au début est utilisée. Un compteur dans l'horloge originale commande le déplacement, sans créer une nouvelle horloge de bit.

SystemVerilog
module uart_tx #(
    parameter int unsigned CLKS_PER_BIT = 417,
    localparam int CW = (CLKS_PER_BIT <= 1) ? 1 : $clog2(CLKS_PER_BIT)
) (
    input  logic       clk, rst,
    input  logic       in_valid,
    output logic       in_ready,
    input  logic [7:0] in_data,
    output logic       tx, busy, done
);
    logic [9:0] frame;
    logic [3:0] bits_left;
    logic [CW-1:0] ticks_left;
    assign in_ready = !busy;

    always_ff @(posedge clk) begin
        if (rst) begin
            tx         <= 1'b1;
            busy       <= 1'b0;
            done       <= 1'b0;
            bits_left  <= 4'd0;
            ticks_left <= '0;
        end else begin
            done <= 1'b0;
            if (!busy) begin
                if (in_valid) begin
                    frame      <= {1'b1, in_data, 1'b0};
                    tx         <= 1'b0;
                    busy       <= 1'b1;
                    bits_left  <= 4'd10;
                    ticks_left <= CW'(CLKS_PER_BIT-1);
                end
            end else if (ticks_left != 0) begin
                ticks_left <= ticks_left - 1'b1;
            end else if (bits_left == 4'd1) begin
                tx   <= 1'b1;
                busy <= 1'b0;
                done <= 1'b1;
            end else begin
                frame      <= {1'b1, frame[9:1]};
                tx         <= frame[1];
                bits_left  <= bits_left - 1'b1;
                ticks_left <= CW'(CLKS_PER_BIT-1);
            end
        end
    end
endmodule

Si l'acceptation est à E0, tx passe au start=0. Chaque bit suivant commence exactement D cycles plus tard. Stop commence à E0+9D ; busy tombe et une impulsion apparaît sur done à E0+10D. Le dernier stop doit aussi durer D périodes.

in_ready reste à 0 jusqu'avant le front d'achèvement. La trame suivante n'est donc acceptée qu'au front suivant au plus tôt, pour un intervalle minimal 10D+110D+1 cycles. Ce cycle idle supplémentaire fait partie du fonctionnement normal.

Prédire les bits à la main

Les données de 8'h53, LSB d'abord, sont 1,1,0,0,1,0,1,0. La trame complète est :

Positionstartd0d1d2d3d4d5d6d7stop
tx0110010101

Ne comptez pas seulement les changements de tx : deux bits égaux ne créent aucune transition. Échantillonnez au milieu de chaque intervalle depuis le début de trame, comparez les bits et vérifiez les durées start/stop. Utilisez aussi D=1,2,3 pour des tests unitaires rapides.

Prolongement avec un FIFO

Un FIFOFIFO File où la première donnée entrée sort en premier. Les règles à plein, à vide et en lecture/écriture simultanée font partie du contrat. En savoir plus à lecture enregistrée actualise dout et dout_valid après le front acceptant pop. Le circuit suivant sur la même horloge capture au prochain front montantFront montant Instant où l'horloge passe de 0 à 1, distinct du niveau désignant tout l'intervalle CLK=1. En savoir plus. Envoyer dout à l'UART dès le front de pop peut donc transmettre l'ancienne donnée. Ajoutez un tampon d'un octet et un état pending pour conserver la réponse et la transmettre exactement une fois lorsque l'UART est prêt.

Testez 00,FF,01,80,55,53, les changements d'entrée pendant busy, les trames consécutives et un reset en cours de trame. La politique de reset interrompt l'émission et remet tx à idle=1 ; le récepteur peut néanmoins voir une trame valide, de sorte que le seul contrôle du format UART ne garantit pas la détection de l’interruption. Si les données concernées doivent être rejetées, définissez un contrat système qui coordonne le reset du récepteur avec l’émetteur ou transmet un signal d’abandon de transmission distinct au récepteur.

Pour aller plus loin : Microchip — EUSART and 8N1 framing

Essayez vous-même

Avec CLKS_PER_BIT=4 et une acceptation à E0, donnez les fronts de début d0, début stop et done. Un nouveau in_valid=1 à E40 est-il accepté sur ce front ?

Lire l’explication

d0 commence à E4, stop à E36 et done après E40. Avant E40 busy=1, donc in_ready=0 : le nouvel octet n'est pas accepté. L'émetteur garde valid et data jusqu'à E41, première acceptation possible. Chaque trame dure 40 cycles et l'intervalle minimal d'acceptation est 41 cycles.

Votre choix s’applique à ce navigateur. Modifiez-le à tout moment en bas de page.