Altifigence Academy

63 / 63 · Concetto

Laboratorio integrato: trasmettitore UART e tempi del frame

Unire divisore, registro e controllo di flusso per 8N1 verificando i confini dei bit.

Fissare prima il formato del frame

Prerequisiti: contatori, registri a scorrimentoRegistro Memorizza uno stato di più bit. I registri sincroni del corso acquisiscono gli ingressi specificati al fronte di clock. Approfondisci, valid/ready e reset sincronoReset Controllo che riporta allo stato iniziale specificato. Occorre definirne sincronicità e priorità rispetto agli altri controlli. Approfondisci.

UARTUART Comunicazione seriale con start, dati e stop senza linea di clock separata. Mittente e destinatario devono concordare baud rate e formato. 8N1 usa un bit start, otto dati, nessuna parità e un bit stop. Idle e stop valgono 1, start 0; i dati partono dal LSBLSB Bit di peso minore. Vanno controllati insieme direzione di scrittura e convenzione degli indici. Approfondisci. Tutti i bit hanno uguale durata. Il laboratorio tratta solo la trasmissione con una sorgente dati sullo stesso clock.

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\%

A 48MHz con obiettivo 115200 baud si può scegliere D=417 intero. La velocità reale è circa 115108 baud, errore circa −0.080%. La tolleranza complessiva, compreso il ricevitore, va verificata nelle specifiche dei dispositivi.

Espandere 0x53 nell'ordine trasmesso

0x53 si scrive 01010011, ma sulla linea esce dal bit basso: 1,1,0,0,1,0,1,0. Ogni colonna è un periodo di bit di D clock, non un singolo clock di sistema. Gli intervalli idle prima e dopo sono rappresentati con una colonna ciascuno per confronto.

UART 8N1 · 0x53 · LSB first
Mostra i dati della forma d’onda
Dati della forma d’onda: ogni carattere è un intervallo; il punto mantiene lo stato precedente; p è un ciclo di clock.
SegnaleForma d’ondaValori del bus
tx101.0.10101.
phase234523452345idle → start → d0 → d1 → d2 → d3 → d4 → d5 → d6 → d7 → stop → idle

Da start a stop occorrono esattamente 10D clock. Anche bit consecutivi uguali occupano ciascuno un periodo: nessuna transizione non significa bit assenti.

Acquisire un byte una sola volta

CLKS_PER_BIT è una costante almeno 1. Durante busy non si accettano dati; si usa solo il byte acquisito all'inizio. Non si crea un nuovo bit-clock: un contatore controlla l'avanzamento nello stesso clock originale.

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

Con accettazione a E0, tx passa a start=0. Poi si avanza ogni D clock esatti. A E0+9D comincia stop; a E0+10D busy scende e done pulsa per un ciclo. Anche stop deve durare tutti i D periodi.

Poiché prima del fronte finale in_ready è ancora 0, il frame seguente si accetta al più presto al fronte dopo. La distanza minima fra accettazioni è 10D+110D+1 clock. Il singolo clock idle fa parte del comportamento normale.

Prevedere la sequenza a mano

I dati di 8'h53 sono LSB-first 1,1,0,0,1,0,1,0. Il frame completo è:

Posizionestartd0d1d2d3d4d5d6d7stop
tx0110010101

Non contate soltanto le variazioni di tx: bit uguali consecutivi non ne generano. Dall'inizio del frame campionate al centro di ogni periodo e confrontate anche durata di start e stop. Valori piccoli di D, come 1,2,3, sono utili nei test rapidi.

Estensione con FIFO

Una FIFOFIFO Coda che estrae prima i dati inseriti prima. Pieno, vuoto e regole di lettura/scrittura simultanee fanno parte del contratto. Approfondisci con lettura registrata aggiorna dout e dout_valid dopo il fronte che accetta pop. La logica seguente sullo stesso clock li campiona al prossimo fronte di salitaFronte di salita Passaggio del clock da 0 a 1, distinto dall’intero intervallo di livello CLK=1. Approfondisci. Inviare dout a UART già al fronte pop può trasmettere il vecchio dato. Usate un buffer da un posto per la risposta e uno stato pending, consegnando esattamente una volta quando UART è ready.

La verifica finale comprende 00, FF,01,80,55,53, cambi d'ingresso durante busy, frame consecutivi e reset a metà frame. Reset interrompe e riporta tx a idle=1. Il ricevitore può comunque vedere un frame valido, quindi il solo formato del frame UART non garantisce il rilevamento di una trasmissione interrotta. Se i dati interessati devono essere scartati, definire un contratto di sistema che coordini il reset del ricevitore con il trasmettitore o invii al ricevitore un segnale separato di interruzione della trasmissione.

Per approfondire: Microchip — EUSART and 8N1 framing

Prova tu

CLKS_PER_BIT=4, accettazione a E0: quando iniziano d0 e stop, e quando arriva done? Un nuovo in_valid=1 è accettato già a E40?

Leggi la spiegazione

d0 inizia dopo E4, stop dopo E36, done dopo E40. Prima di E40 busy=1 e in_ready=0: nessuna accettazione. Il mittente mantiene valid e data; il prossimo byte può essere accettato a E41. Durata frame 40 clock, distanza minima 41.

La scelta vale per questo browser. Puoi modificarla in qualsiasi momento dal piè di pagina.