Altifigence Academy

52 / 52 · 概念

Capstone: a UART transmitter

분주 카운터·시프트 레지스터·흐름 제어를 결합해 8N1 프레임을 만들고 비트 경계를 검증합니다.

译文尚未提供,以下显示课时原文。 (한국어)

프레임 명세를 먼저 고정합니다

선수 지식: 카운터, 시프트 레지스터, valid/ready, 동기식 리셋.

UART의 8N1 형식은 시작 비트 1개, 데이터 8개, parity 없음, 정지 비트 1개입니다. idle과 stop은 1, start는 0이며 데이터는 LSB부터 보냅니다. 모든 비트는 동일한 길이로 유지합니다. 이 실습은 송신만 다루며 같은 클록의 데이터 제공자를 가정합니다.

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

48MHz에서 115200 baud를 목표로 하면 정수 분주값 D=417을 선택할 수 있습니다. 실제 속도는 약 115108 baud, 오차는 약 -0.080%입니다. 수신 측까지 포함한 허용 오차는 장치 사양으로 검토해야 합니다.

0x53을 실제 전송 순서로 펼치기

0x53의 표기는 01010011이지만, 선로에는 낮은 비트부터 1, 1, 0, 0, 1, 0, 1, 0 순서로 나갑니다. 그림에서 한 칸은 시스템 클록 한 주기가 아니라 D클록으로 이루어진 비트 기간입니다. 앞뒤 idle 구간은 비교를 위해 한 칸씩 표시했습니다.

UART 8N1 · 0x53 · LSB first
View waveform data
Wave data: each character is one interval; a dot holds the previous state; p is a clock cycle.
SignalWaveBus values
tx101.0.10101.
phase234523452345idle → start → d0 → d1 → d2 → d3 → d4 → d5 → d6 → d7 → stop → idle

start부터 stop까지는 정확히 10D클록입니다. 연속된 1이나 0도 각각 한 비트 기간을 차지하며, 선로에 전이가 없다고 비트가 사라지는 것은 아닙니다.

데이터 한 바이트를 한 번만 캡처합니다

아래 구현은 CLKS_PER_BIT가 1 이상의 상수라는 계약입니다. busy일 때 입력은 수락하지 않고, 프레임 시작 시 캡처한 data만 사용합니다. bit-clock을 새 클록으로 만들지 않고 원래 클록 안에서 카운터로 이동 시점을 제어합니다.

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

입력 수락 에지를 E0라고 하면 tx가 start=0으로 바뀝니다. 이후 정확히 D개 클록 간격으로 다음 비트로 이동합니다. E0+9D에서 stop 비트가 시작되고 E0+10D에서 busy가 내려가며 done이 한 사이클 발생합니다. 마지막 stop 구간도 D주기를 채워야 합니다.

이 구현은 종료 에지 직전까지 in_ready=0이므로 다음 프레임은 가장 빨라도 그 다음 에지에 수락합니다. 따라서 연속 프레임 수락 간격은 10D+110D+1클록입니다. 이 한 클록의 idle 간격도 정상 동작의 일부입니다.

비트열을 손으로 예측합니다

8'h53의 데이터 비트는 LSB부터 1,1,0,0,1,0,1,0입니다. 전체 프레임은 다음 순서입니다.

순서startd0d1d2d3d4d5d6d7stop
tx0110010101

검증에서는 tx가 바뀐 횟수만 세면 안 됩니다. 연속된 같은 값의 비트에서는 전환이 없기 때문입니다. 프레임 시작을 기준으로 각 비트 구간의 중앙을 샘플링해 예상 비트와 대조하고, start·stop의 길이도 확인합니다. 빠른 단위 검증에는 D=1, 2, 3 같은 작은 값도 사용하세요.

FIFO와 연결하는 확장 설계

등록형 읽기 FIFO는 pop 수락 에지 직후 dout과 dout_valid를 갱신합니다. 같은 클록의 다음 회로는 그 다음 상승 에지에서 응답을 샘플링합니다. pop을 수락하는 바로 그 에지의 dout을 UART에 보내면 이전 값일 수 있습니다. 반환된 바이트를 보관하는 1칸 버퍼와 pending 상태를 두고, UART가 ready일 때 정확히 한 번 전달하도록 연결하세요.

최종 검증에는 00·FF·01·80·55·53, busy 중 바뀌는 입력, 연속 프레임, 프레임 중 reset을 포함합니다. reset은 전송을 중단하고 tx를 idle=1로 되돌린다는 정책입니다. 수신기는 중단된 프레임을 정상 데이터로 취급하면 안 됩니다.

추가 읽기: Microchip — EUSART and 8N1 framing

自己试试

CLKS_PER_BIT=4이고 E0에서 데이터를 수락했습니다. d0 시작, stop 시작, done 발생 에지를 각각 구하세요. E40에서 새 in_valid=1이면 그 에지에 다음 바이트가 수락됩니까?

阅读解释

d0는 E4, stop은 E36, done은 E40 직후입니다. E40 직전에는 busy=1이어서 in_ready=0이므로 새 바이트는 아직 수락되지 않습니다. 송신자는 valid와 data를 유지해야 하며, 다음 바이트는 E41에서 수락할 수 있습니다. 각 프레임은 40클록이고 수락 간격은 최소 41클록입니다.

你的选择适用于此浏览器,可随时在页脚更改。