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.
Le lezioni sono gratuite. Iscriviti per salvare i progressi.
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.
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.
Mostra i dati della forma d’onda
| Segnale | Forma d’onda | Valori del bus |
|---|---|---|
| tx | 101.0.10101. | |
| phase | 234523452345 | idle → 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.
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
endmoduleCon 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 è 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 è:
| Posizione | start | d0 | d1 | d2 | d3 | d4 | d5 | d6 | d7 | stop |
|---|---|---|---|---|---|---|---|---|---|---|
| tx | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 1 |
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.