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

0517 uart_tx

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

UART Moore Machine
transmitter ASM

 

uart.v

`timescale 1ns / 1ps

module uart (
    input        clk,
    input        reset,
    input        tx_start,
    input  [7:0] tx_data,
    output       tx,
    output       tx_done
);
    wire w_br_tick;

    buadrate_generator U_BR_GEN (
        .clk(clk),
        .reset(reset),
        .br_tick(w_br_tick)
    );

    transmitter U_TxD (
        .clk(clk),
        .reset(reset),
        .br_tick(w_br_tick),
        .tx_start(tx_start),
        .tx_data(tx_data),
        .tx(tx),
        .tx_done(tx_done)
    );

endmodule

module buadrate_generator (
    input  clk,
    input  reset,
    output br_tick
);
    reg [$clog2(100_000_000 / 9600)-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
        if(counter_reg == 100_000_000 / 9600 -1) begin // comportmaster
        //if (counter_reg == 10 - 1) 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        tx_start,
    input  [7:0] tx_data,
    output       tx,
    output       tx_done
);
    localparam IDLE = 0, START = 1, DATA = 2, STOP = 3;  // state

    reg [1:0] state, state_next;
    reg [7:0] tx_data_reg, tx_data_next;
    reg [2:0] bit_cnt_reg, bit_cnt_next;  // DATA bit count
    reg tx_reg, tx_next;
    reg tx_done_reg, tx_done_next;

    // output logic
    assign tx = tx_reg;
    assign tx_done = tx_done_reg;

    // state register
    always @(posedge clk, posedge reset) begin
        if (reset) begin
            state <= IDLE;
            tx_data_reg <= 0;
            bit_cnt_reg <= 0;
            tx_reg <= 1'b1;
            tx_done_reg <= 1'b0;
        end else begin
            state <= state_next;
            tx_data_reg <= tx_data_next;
            bit_cnt_reg <= bit_cnt_next;
            tx_reg <= tx_next;
            tx_done_reg <= tx_done_next;
        end
    end

    // next state combinational logic
    always @(*) begin
        state_next   = state;
        tx_done_next = tx_done_reg;
        tx_data_next = tx_data_reg;
        tx_next      = tx_reg;
        bit_cnt_next = bit_cnt_reg;
        case (state)
            IDLE: begin
                tx_next = 1'b1;
                tx_done_next = 1'b0;
                if (tx_start) begin
                    tx_data_next = tx_data;
                    bit_cnt_next = 0;
                    state_next   = START;
                end
            end
            START: begin
                tx_next = 1'b0;
                if (br_tick)
                    state_next = DATA;  // baudrate start later START state
            end
            DATA: begin
                tx_next = tx_data_reg[0];  // send from LSB
                if (br_tick) begin
                    if (bit_cnt_reg == 7) begin
                        state_next = STOP;
                    end else begin
                        bit_cnt_next = bit_cnt_reg + 1;
                        tx_data_next = {
                            1'b0, tx_data_reg[7:1]
                        };  // right shift register
                    end
                end
            end
            STOP: begin
                tx_next = 1'b1;
                if (br_tick) begin
                    state_next   = IDLE;
                    tx_done_next = 1'b1;
                end
            end
        endcase
    end

endmodule

 

top.v

`timescale 1ns / 1ps

module top(
    input clk,
    input reset,
    input btn_tx_start,
    output txd
    );

    wire w_btn_tx_start;

    button U_BTN_TX(
        .clk(clk),
        .in(btn_tx_start),
        .out(w_btn_tx_start)
    );

    uart U_UART(
        .clk(clk),
        .reset(reset),
        .tx_start(w_btn_tx_start),
        .tx_data(8'h41),    // 'A'
        .tx(txd),
        .tx_done()  // non-connect
    );

endmodule

 

button.v

`timescale 1ns / 1ps

module button (
    input  clk,
    input  in,
    output out
);

    localparam N = 64;  // shift 횟수

    wire w_debounce_out;
    reg [N-1 : 0] Q_reg, Q_next;
    reg [1:0] dff_reg, dff_next;
 
    // Output logic
    assign out = ~dff_reg[0] & dff_reg[1];
 
    always @(posedge clk) begin
        Q_reg <= Q_next;
        dff_reg <= dff_next;
    end

    // Next state logic
    always @(*) begin
        Q_next = {Q_reg[N-2:0], in}; // debounce circuit, left shift
    end
    assign w_debounce_out = &Q_reg;

    always @(*) begin
        dff_next[0] = w_debounce_out;   // D-F/F
        dff_next[1] = dff_reg[0];
    end

endmodule

 

tb_uart

`timescale 1ns / 1ps

module tb_uart();
    reg clk;
    reg reset;
    reg tx_start;
    reg [7:0] tx_data;
    wire tx;
    wire tx_done;

    uart dut(
        .clk(clk),
        .reset(reset),
        .tx_start(tx_start),
        .tx_data(tx_data),
        .tx(tx),
        .tx_done(tx_done)
    );

    always #5 clk = ~clk;

    initial begin
        clk = 1'b0;
        reset = 1'b1;
        tx_start = 1'b0;
        tx_data = 0;
    end

    initial begin
        #100 reset = 1'b0;
        #100 tx_start = 1'b1; tx_data = 8'b11001010;
        #10 tx_start = 1'b0;
    end
    
endmodule

 

schematic

 

simulation

constraint

##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
set_property -dict { PACKAGE_PIN T18  IOSTANDARD LVCMOS33 } [get_ports { btn_tx_start }]; #IO_L17N_T2_A13_D29_14 ,Sch=BTNU
#set_property -dict { PACKAGE_PIN W19  IOSTANDARD LVCMOS33 } [get_ports { fndSel[1] }]; #IO_L16N_T2_A15_D31_14 ,Sch=BTNL
#set_property -dict { PACKAGE_PIN T17  IOSTANDARD LVCMOS33 } [get_ports { fndSel[0] }]; #IO_L17P_T2_A14_D30_14 ,Sch=BTNR
#set_property -dict { PACKAGE_PIN U17  IOSTANDARD LVCMOS33 } [get_ports {  }]; #IO_L18P_T2_A12_D28_14 ,Sch=BTND
##USB-RS232 Interface

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

 

video

 

 

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

0520 oversampling, uart  (0) 2024.06.22
0517 uart_tx_rx  (0) 2024.06.22
0516 UART  (0) 2024.06.22
0516 upCounter_FSM  (0) 2024.06.22
0514 upCounter_FND_FSM  (0) 2024.06.22