UART Serial 통신 프로토콜 FPGA Verilog HDL 설계 #2 Tx module, Baud Rate generator

Yonghee·2023년 9월 16일

UART Tx module (송신부)

UART의 Tx 모듈에서는 데이터를 1bit씩 PC(컴퓨터)로 전송합니다. Rx module에서 done 신호를 입력으로 받으면 IDLE 상태에서 START 상태로 전환되면서 동작을 시작합니다.

저는 각각 총 11개의 상태(STATE)를 둬서 clock에 동기화되면서 1bit씩 값이 내보내도록 설계하였습니다. 먼저 IDLE 상태에서는 1을 출력하다가 START 상태가 되면 start bit(1'b0)을 출력합니다. 그리고 ST2 상태부터 ST9 상태까지 Rx 수신 모듈에서 입력받은 din[7:0]의 데이터를 LSB(최하위 비트)부터 차례대로 출력합니다. 모든 데이터가 전송되면 STOP 상태로 넘어가고 다시 1을 출력하면서 초기(IDLE) 상태로 돌아갑니다.

    localparam IDEL = 0, START = 1, ST2 = 2, ST3 = 3, ST4 = 4, 
    ST5 = 5, ST6 = 6, ST7 = 7, ST8 = 8, ST9 = 9, STOP = 10;

    (*keep="true"*) reg [3:0] state;

    ///////////////state transition///////////////
    always @(posedge clk) begin
        case (state)
            IDEL : if(start==1) state <= START;
                   else state <= IDEL;
            START  : state <= ST2;
            ST2  : state <= ST3;
            ST3  : state <= ST4;
            ST4  : state <= ST5;
            ST5  : state <= ST6;
            ST6  : state <= ST7;
            ST7  : state <= ST8;
            ST8  : state <= ST9;
            ST9  : state <= STOP;
            STOP : state <= IDEL;
            default : state <= IDEL;
        endcase
    end
    always @(posedge clk) begin
        case (state)
            IDEL  : tx_data <= 1; 
            START : tx_data <= 0;       // start bit(1'b0)
            ST2   : tx_data <= din[0];
            ST3   : tx_data <= din[1];
            ST4   : tx_data <= din[2];
            ST5   : tx_data <= din[3];
            ST6   : tx_data <= din[4];
            ST7   : tx_data <= din[5];
            ST8   : tx_data <= din[6];
            ST9   : tx_data <= din[7];
            STOP  : tx_data <= 1;      // stop bit(1'b1)
            default: tx_data <= 1; 
        endcase
    end

UART Tx wave form

Tx module의 wave form으로 동작을 확인하였습니다. 0100_1111(2)=79(10)의 din 숫자를 입력으로 줬을 때 START 상태와, ST2~ST9, STOP 상태에 맞춰 1bit씩 값이 출력되는 것을 확인할 수 있습니다.

Clock module (Baud Rate generator)

Clock module에는 두 개의 모듈이 instance 되어 있습니다. Vivado Tool은 Clock wizard의 IP를 지원합니다. Clock wizard를 사용할 경우 FPGA에서 각 모듈에 Clock을 안정적으로 보낼 수 있고 출력의 clock 주기를 쉽게 바꿀 수 있습니다.

제가 사용한 FPGA(Xilinx Ultra 96)의 경우 입력되는 동작 주파수가 40mhz 입니다. 저는 Clock wizard의 출력 주파수를 100mhz로 만들었고 이는 다시 Baud Rate generator로 들어가게 연결하였습니다.

주파수 역수가 주기이기 때문에 40mhz 주파수의 주기는 25ns이고 100mz 주파수의 주기는 10ns입니다. 10ns의 clock 주기는 PC가 동작하는 주파수인 8,680ns(115,200Hz)로 바꿔야 하므로 8680/10을 하면 868번을 반복 진동해 줘야 PC 주기로 맞출 수 있습니다.

저는 Baud Rate generator 모듈에 counter를 두어서 숫자가 세어지도록 하였습니다. 434번의 진동이 발생하면 새롭게 선언한 clk1가 반전하고 다시 868번까지 counter가 세어지면 clk1가 반전하여 8,680ns가 만들어지도록 설계하였습니다.

Baud generator까지 설계하고 testbench로 결과 값을 출력하였습니다. 100ns의 주기에 따라 Counter가 반복되고 434와 867까지 증가하면 clk1가 반전되는 것을 확인할 수 있습니다. 그 이후 clk1는 다시 0으로 초기화되어 반복되는 것을 확인할 수 있었습니다.

module clock_module(
    input wire clk_in,
    output wire clk_out
    );
    
    (*keep="true"*) wire locked;
    (*keep="true"*) wire clk_100mhz;
   
    clk_wiz_0 u0(.clk_out1(clk_100mhz), .locked(locked), .clk_in1(clk_in));  // clock wizard instance
    baudrate_gen u1(.clk(clk_100mhz), .clk1(clk_out));         				 // baud rate generator instance
    
endmodule
module baudrate_gen(
    input wire clk,            		 // 입력 주기 100mhz, 10ns
    output reg clk1
    );
    (*keep="true"*) reg [27:0] counter = 28'b0;
    
    always @(posedge clk)begin 		 // 100mhz 주기의 카운터
        if(counter == 867)   
            counter <= 28'b0;
        else 
            counter <= counter + 1'b1;
    end

    always @(posedge clk) begin
        if(counter == 0)
            clk1 <= 1'b0;
        else if(counter == 434)
            clk1 <= ~clk1;
        else if (counter == 867)
            clk1 <= ~clk1;
        else   
            clk1 <= clk1;
    end

endmodule

Clock module wave form

clock wizard에서 나온 100mhz 출력 주기에 맞춰 카운터가 세어지는 것을 확인할 수 있습니다.

카운터가 434까지 세어졌을 때 반전(inversion)하는 것을 확인할 수 있습니다.

867번까지 세어졌을 때 다시 반전되면서 clk_out(8,680ns) 주기가 만들어집니다.

clock wizard에서 출력되는 100mhz가 baud rate_gen 모듈을 거치면서 8,680ns로 전환되고 해당 동작 주파수가 Tx, Rx 모듈로 들어가면서 PC와 통신할 수 있는 상태가 됩니다. UART 통신을 PC와 하기 위해서는 반드시 통신할 수 있는 동작 주파수를 맞춰줘야 하는 과정이 필요합니다.

profile
SoC 설계 엔지니어 성장 기록

0개의 댓글