[하만]세미콘 아카데미/verilog

0520 oversampling, uart

내머리속은이런걸로 2024. 6. 22. 11:34

oversmapling

oversampling

: 수신기에서 신호를 더 정확하게 복구하기 위해 사용되는 기술이다.

비트당 8, 16 등 샘플을 나눠 가운데 샘플의 값을 얻는 방식이다.

→ 샘플링 속도를 원래 신호의 대역폭에 필요한 최소한 샘플링 속도보다 높이는 기술.

잡음, 타이밍 오류를 줄이고 데이터 정확도를 높이는 기술이다.

 

transmitter

transmitter ASM

: oversampling bit = br_cnt

START, STOP: br_cnt == 15가 될 때마다 다음 상태로 넘어간다.

DATA : br_cnt == 15가 될 때마다 data의 LSB를 보낸다.

 

receiver

receiver ASM

: oversampling bit = br_cnt

  • START : br_cnt == 7이 되면 다음 상태인 DATA로 넘어간다.
  • DATA : br_cnt == 15가 되면 다음 tx_data의 1bit를 받고 저장한다. 8개의 bit를 모두 받으면 STOP 상태로 넘어간다.
  • STOP : br_cnt == 15가 되면 IDLE 상태로 넘어간다.

uart .v

`timescale 1ns / 1ps

module uart (  // PC
    input        clk,
    input        reset,
    // Transmitter
    output       tx,
    input        start,
    input  [7:0] tx_data,
    output       tx_done,
    // Receiver
    input        rx,
    output [7:0] rx_data,
    output       rx_done

);
    wire w_br_tick;

    baudrate_generator U_BAUDRATE_GEN (
        .clk(clk),
        .reset(reset),
        .br_tick(w_br_tick)
    );

    transmitter U_Transmitter (
        .clk(clk),
        .reset(reset),
        .br_tick(w_br_tick),
        .start(start),
        .tx_data(tx_data),
        .tx(tx),
        .tx_done(tx_done)
    );

    receiver U_Receiver (
        .clk(clk),
        .reset(reset),
        .br_tick(w_br_tick),
        .rx(rx),
        .rx_data(rx_data),
        .rx_done(rx_done)
    );

endmodule

module baudrate_generator (
    input  clk,
    input  reset,
    output br_tick
);
    // 16 bit sampling -> baudrate 16 times
    reg [$clog2(100_000_000 / 9600 / 16)-1 : 0] counter_reg, counter_next;
    reg tick_reg, tick_next;

    assign br_tick = tick_reg;

    always @(posedge clk, posedge reset) begin
        if (reset) begin
            counter_reg <= 0;
            tick_reg <= 1'b0;
        end else begin
            counter_reg <= counter_next;
            tick_reg <= tick_next;
        end
    end


    always @(*) begin
        counter_next = counter_reg;
        if (counter_reg == 100_000_000 / 9600 / 16 - 1) begin
        //if (counter_reg == 3) begin // for simulation
            counter_next = 0;
            tick_next = 1'b1;
        end else begin
            counter_next = counter_reg + 1;
            tick_next = 1'b0;
        end
    end
endmodule

module transmitter (
    input        clk,
    input        reset,
    input        br_tick,
    input        start,
    input  [7:0] tx_data,
    output       tx,
    output       tx_done
);

    localparam IDLE = 0, START = 1, DATA = 2, STOP = 3;

    reg [1:0] state, state_next;
    reg tx_reg, tx_next;
    reg tx_done_reg, tx_done_next;
    reg [7:0] data_tmp_reg, data_tmp_next;
    reg [3:0] br_cnt_reg, br_cnt_next;
    reg [2:0] data_bit_cnt_reg, data_bit_cnt_next;

    assign tx = tx_reg;
    assign tx_done = tx_done_reg;

    always @(posedge clk, posedge reset) begin
        if (reset) begin
            state            <= IDLE;
            tx_reg           <= 1'b0;
            br_cnt_reg       <= 0;
            data_bit_cnt_reg <= 0;
            data_tmp_reg     <= 0;
            tx_done_reg      <= 1'b0;
        end else begin
            state            <= state_next;
            tx_reg           <= tx_next;
            br_cnt_reg       <= br_cnt_next;
            data_bit_cnt_reg <= data_bit_cnt_next;
            data_tmp_reg     <= data_tmp_next;
            tx_done_reg      <= tx_done_next;
        end
    end

    always @(*) begin
        state_next        = state;
        data_tmp_next     = data_tmp_reg;
        tx_next           = tx_reg;
        br_cnt_next       = br_cnt_reg;
        data_bit_cnt_next = data_bit_cnt_reg;
        tx_done_next      = tx_done_reg;
        case (state)
            IDLE: begin
                tx_done_next = 1'b0;
                tx_next      = 1'b1;
                if (start) begin
                    state_next = START;
                    data_tmp_next = tx_data;
                    br_cnt_next = 0;  // baud rate 16bit sampling
                    data_bit_cnt_next = 0;
                end
            end
            START: begin
                tx_next = 1'b0;
                if (br_tick) begin
                    if (br_cnt_reg == 15) begin
                        state_next  = DATA;
                        br_cnt_next = 0;
                    end else begin
                        br_cnt_next = br_cnt_reg + 1;
                    end
                end
            end
            DATA: begin
                tx_next = data_tmp_reg[0];
                if (br_tick) begin
                    if (br_cnt_reg == 15) begin
                        if (data_bit_cnt_reg == 7) begin
                            state_next  = STOP;
                            br_cnt_next = 0;
                        end else begin
                            data_bit_cnt_next = data_bit_cnt_reg + 1;
                            data_tmp_next     = {1'b0, data_tmp_reg[7:1]};
                        br_cnt_next = 0;
                        end
                        
                    end else begin
                        br_cnt_next = br_cnt_reg + 1;
                    end
                end
            end
            STOP: begin
                tx_next = 1'b1;
                if (br_tick) begin
                    if (br_cnt_reg == 15) begin
                        tx_done_next = 1'b1;
                        state_next   = IDLE;
                    end else begin
                        br_cnt_next = br_cnt_reg + 1;
                    end
                end
            end
        endcase
    end

endmodule

module receiver (
    input        clk,
    input        reset,
    input        br_tick,
    input        rx,
    output [7:0] rx_data,
    output       rx_done
);

    localparam IDLE = 0, START = 1, DATA = 2, STOP = 3;

    reg [1:0] state, state_next;
    reg [7:0] rx_data_reg, rx_data_next;
    reg rx_done_reg, rx_done_next;
    reg [3:0] br_cnt_reg, br_cnt_next;
    reg [2:0] data_bit_cnt_reg, data_bit_cnt_next;

    assign rx_data = rx_data_reg;
    assign rx_done = rx_done_reg;

    always @(posedge clk, posedge reset) begin
        if (reset) begin
            state            <= IDLE;
            rx_data_reg      <= 0;
            rx_done_reg      <= 1'b0;
            br_cnt_reg       <= 0;
            data_bit_cnt_reg <= 0;
        end else begin
            state            <= state_next;
            rx_data_reg      <= rx_data_next;
            rx_done_reg      <= rx_done_next;
            br_cnt_reg       <= br_cnt_next;
            data_bit_cnt_reg <= data_bit_cnt_next;
        end
    end

    always @(*) begin
        state_next        = state;
        br_cnt_next       = br_cnt_reg;
        data_bit_cnt_next = data_bit_cnt_reg;
        rx_data_next      = rx_data_reg;
        rx_done_next      = rx_done_reg;
        case (state)
            IDLE: begin
                rx_done_next = 1'b0;
                if (rx == 1'b0) begin
                    br_cnt_next       = 0;
                    data_bit_cnt_next = 0;
                    rx_data_next      = 0;
                    state_next        = START;
                end
            end
            START: begin
                if (br_tick) begin
                    if (br_cnt_reg == 7) begin
                        br_cnt_next = 0;
                        state_next  = DATA;
                    end else begin
                        br_cnt_next = br_cnt_reg + 1;
                    end
                end
            end
            DATA: begin
                if (br_tick) begin
                    if (br_cnt_reg == 15) begin
                        br_cnt_next  = 0;
                        rx_data_next = {rx, rx_data_reg[7:1]};
                        if (data_bit_cnt_reg == 7) begin
                            state_next = STOP;
                            br_cnt_next = 0;
                        end else begin
                            data_bit_cnt_next = data_bit_cnt_reg + 1;
                        end
                    end else begin
                        br_cnt_next = br_cnt_reg + 1;
                    end
                end
            end
            STOP: begin
                if (br_tick) begin
                    if (br_cnt_reg == 15) begin
                        br_cnt_next  = 0;
                        rx_done_next = 1'b1;
                        state_next   = IDLE;
                    end else begin
                        br_cnt_next = br_cnt_reg + 1;
                    end
                end
            end
        endcase
    end

endmodule

 

top_txrx_loop

`timescale 1ns / 1ps

module top_txrx_loop(
    input        clk,
    input        reset,
    // Transmitter
    output       tx,
    // Receiver
    input        rx
    );

    wire [7:0] w_rx_data;
    wire w_rx_done;

    uart U_UART(  // PC
        .clk(clk),
        .reset(reset),
    // Transmitter
        .tx(tx),
        .start(w_rx_done),
        .tx_data(w_rx_data),
        .tx_done(),
    // Receiver
        .rx(rx),
        .rx_data(w_rx_data),
        .rx_done(w_rx_done)

    );

endmodule

 

tb_uart

`timescale 1ns / 1ps


module tb_uart();

    reg        clk;
    reg        reset;
    // Transmitter
    wire       tx;
    reg        start;
    reg  [7:0] tx_data;
    wire       tx_done;
    // Receiver
    reg        rx;
    wire [7:0] rx_data;
    wire       rx_done;
  /*
    uart dut(
       .clk(clk),
       .reset(reset),

       .tx(tx),
       .start(start),
       .tx_data(tx_data),
       .tx_done(tx_done),

       .rx(rx), // loop test
       .rx_data(rx_data),
       .rx_done(rx_done)

    );*/
    
    // loop test
    wire w_tx_rx;

    uart dut(
       .clk(clk),
       .reset(reset),

       .tx(w_tx_rx),
       .start(start),
       .tx_data(tx_data),
       .tx_done(tx_done),

       .rx(w_tx_rx), // loop test
       .rx_data(rx_data),
       .rx_done(rx_done)

    );

    always #5 clk = ~clk;

    initial begin
        clk = 1'b0;
        reset = 1'b1;
        start = 1'b0;
        rx = 1'b1;
    end

    initial begin
        #20 reset = 1'b0;
        #100 tx_data = 8'b11000101; start = 1'b1;
        #10 start = 1'b0;
    end

endmodule

 

schematic

simulation

 

constraint

## Clock signal
set_property -dict { PACKAGE_PIN W5   IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L12P_T1_MRCC_34 ,Sch=CLK100MHZ
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
##7 segment display

set_property -dict { PACKAGE_PIN W7  IOSTANDARD LVCMOS33 } [get_ports { switch }]; #IO_L13P_T2_MRCC_34 ,Sch=CA
##Buttons

set_property -dict { PACKAGE_PIN U18  IOSTANDARD LVCMOS33 } [get_ports { reset }]; #IO_L18N_T2_A11_D27_14 ,Sch=BTNC
##USB-RS232 Interface

set_property -dict { PACKAGE_PIN B18  IOSTANDARD LVCMOS33 } [get_ports { rx }]; #IO_L19P_T3_16      ,Sch=UART_RXD_IN
set_property -dict { PACKAGE_PIN A18  IOSTANDARD LVCMOS33 } [get_ports { tx }]; #IO_L19N_T3_VREF_16 ,Sch=UART_TXD_OUT

 

video

 

'[하만]세미콘 아카데미 > verilog' 카테고리의 다른 글

0521 system verilog, adder.sv  (0) 2024.07.09
0520 uart_led  (0) 2024.07.09
0517 uart_tx_rx  (0) 2024.06.22
0517 uart_tx  (0) 2024.06.22
0516 UART  (0) 2024.06.22