UART Loopback Test

module uart_top(
    input        clk,
    input        rst,
    input        rx,
    output       tx
);
    wire w_b_tick, w_tx;
    wire w_tx_start, w_rx_done;
    wire [7:0] w_rx_data;

    assign tx = w_tx;

    // Module Instantiation for btn_debounce_fsm
    // btn_debounce_fsm U_DB_TX_START (
    //     .clk   (clk),
    //     .rst   (rst),
    //     .i_btn (tx_start),
    //     .o_btn (w_tx_start)
    // );

    // Module Instantiation for uart_tx
    uart_tx U_UART_TX (
        .clk     (clk),
        .rst     (rst),
        .b_tick  (w_b_tick),
        .start   (w_rx_done),
        .tx_data (w_rx_data),
        .tx      (tx),
        .tx_done (),
        .tx_busy ()
    );

    // Module Instantiation for uart_rx
    uart_rx U_UART_RX (
        .clk     (clk),
        .rst     (rst),
        .b_tick  (w_b_tick),
        .rx      (rx),
        .rx_data (w_rx_data),
        .rx_busy (rx_busy),
        .rx_done (w_rx_done)
    );

    // Module Instantiation for baud_tick_gen
    baud_tick_gen U_BAUD_TICK_GEN (
        .clk    (clk),
        .rst    (rst),
        .b_tick (w_b_tick)
    );
    
endmodule

Topmodule을 rx, tx만 주고 받고 하도록 변경

basys3 보드에 업로드하고

PC의 Comportmaster와 통신!!

image.png

PC에서 보낸 데이터가 잘 반환되는 것을 확인할 수 있다.

testbench code

`timescale 1ns / 1ps

module tb_loopback_v2();
    parameter MS = 1_000_000;
    parameter TX_DELAY = (100_000_000 / 9600) * 10 * 10;
    parameter BAUD_RATE = 9600;
    
    reg clk,rst, rx;
    wire tx;

    reg  [7:0] tx_data;
    wire [7:0] rx_data;
    reg [7:0] receive_data;
    reg [7:0] expected_data;

    assign rx_data = dut.w_rx_data;

    uart_top dut(
        .clk(clk),
        .rst(rst),
        .rx(rx),
        .tx(tx)
    );

    always #5 clk = ~clk;

    integer i, j, pass_cnt, fail_cnt;

    initial begin
        #0 rst = 1; clk = 0;
        #10 rst = 0;

        // verification process
        $display("UART Loopback testbench started");
        $display("BAUD Rate      : %d", BAUD_RATE);
        pass_cnt = 0; fail_cnt = 0;

        // test task
        for(i = 0; i < 5; i = i + 1) begin
            tx_data = $random % 256;
            single_byte_uart_loopback_test(tx_data);
            //#1000;
        end

        $display("Passed : %d", pass_cnt);
        $display("Failed : %d", fail_cnt);
        #1000;
        $stop;
    end

    task single_byte_uart_loopback_test(input [7:0] send_data);
        fork
            send_uart(send_data);
            receiver();
        join
    endtask

    task send_uart(
        input [7:0] send_data
    );
        integer j;

        begin
            expected_data = send_data;
            // start bit
            rx = 1'b0; 
            #(104166); // uart 9600 bps bit time
            for(j = 0; j < 8; j = j+1) begin
                rx = send_data[j];
                #(104166); // uart 9600 bps bit time
            end
            rx = 1;
            wait(dut.w_rx_done); // uart 9600 bps bit time
        end

    endtask

    task receiver();
        begin
            receive_data = 0;
            @(negedge dut.w_rx_done);
            receive_data = dut.w_rx_data;

            //i == 4 인때에 한해서 receive_data를 임의 조작하고 fail하는지 test
            // if (i == 4) begin
            //     receive_data = 8'h30;
            // end

            // pass/fail 
            if (expected_data != receive_data) begin
                $display("Fail Receiving ");
                fail_cnt = fail_cnt + 1;
            end else begin
                $display("Success Receiving ");
                pass_cnt = pass_cnt + 1;
            end
        end
    endtask

endmodule

UART + Counter 10000

image.png

Schematic

스케메틱.png

시뮬레이션

rsc커맨드시뮬레이션.png

UART rx로 받은 r,s,c command에 따라 count가 증가,감소,초기화 되는 것을 알 수 있다.

Latch, Flip-Flop

NOR, NAND 진리표를 그린다음

image.png