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

0520 uart_led

내머리속은이런걸로 2024. 7. 9. 17:41
  • PC에서 FPGA 보드로 '1'을 보내면 Led 1개 ON
  • PC에서 FPGA 보드로 '2'을 보내면 Led 2개 ON
  • PC에서 FPGA 보드로 '3'을 보내면 Led 3개 ON

 

led_FSM

`timescale 1ns / 1ps

module led_FSM (
    input            clk,
    input            reset,
    input      [7:0] data,
    output reg [2:0] led
);

    localparam LED0 = 0, LED1 = 1, LED2 = 2, LED3 = 3;

    reg [1:0] state, state_next;

    always @(posedge clk, posedge reset) begin
        if (reset) begin
            state <= LED0;
        end else begin
            state <= state_next;
        end
    end

    always @(*) begin
        state_next = state;

        case (state)
            LED0: begin
                if (data == 8'h30) state_next = state;
                else if (data == 8'h31) state_next = LED1;
                else if (data == 8'h32) state_next = LED2;
                else if (data == 8'h33) state_next = LED3;
            end
            LED1: begin
                if (data == 8'h30) state_next = LED0;
                else if (data == 8'h31) state_next = state;
                else if (data == 8'h32) state_next = LED2;
                else if (data == 8'h33) state_next = LED3;
            end
            LED2: begin
                if (data == 8'h30) state_next = LED0;
                else if (data == 8'h31) state_next = LED1;
                else if (data == 8'h32) state_next = state;
                else if (data == 8'h33) state_next = LED3;
            end
            LED3: begin
                if (data == 8'h30) state_next = LED0;
                else if (data == 8'h31) state_next = LED1;
                else if (data == 8'h32) state_next = LED2;
                else if (data == 8'h33) state_next = LED3;
            end
        endcase
    end

    always @(*) begin
        led = 3'b000;

        case (state)
            LED0: begin
                led = 3'b000;
            end
            LED1: begin
                led = 3'b001;
            end
            LED2: begin
                led = 3'b011;
            end
            LED3: begin
                led = 3'b111;
            end
        endcase
    end

endmodule

 

 

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;
    wire [7:0] w_rx_data;

    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_tx_rx_loop

`timescale 1ns / 1ps

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

    // led
    output [2:0] led
    );

    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)
    );

    led_FSM U_LED(
        .clk(clk),
        .reset(reset),
        .data(w_rx_data),
        .led(led)
    );
    
endmodule

 

schematic

 

 

 

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]
## LEDs

set_property -dict { PACKAGE_PIN U16  IOSTANDARD LVCMOS33 } [get_ports { led[0]  }]; #IO_L23N_T3_A02_D18_14        ,Sch=LED0
set_property -dict { PACKAGE_PIN E19  IOSTANDARD LVCMOS33 } [get_ports { led[1]  }]; #IO_L3N_T0_DQS_EMCCLK_14      ,Sch=LED1
set_property -dict { PACKAGE_PIN U19  IOSTANDARD LVCMOS33 } [get_ports { led[2]  }]; #IO_L15P_T2_DQS_RDWR_B_14     ,Sch=LED2
set_property -dict { PACKAGE_PIN V19  IOSTANDARD LVCMOS33 } [get_ports { led[3]  }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 ,Sch=LED3
##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 num.sv  (0) 2024.07.09
0521 system verilog, adder.sv  (0) 2024.07.09
0520 oversampling, uart  (0) 2024.06.22
0517 uart_tx_rx  (0) 2024.06.22
0517 uart_tx  (0) 2024.06.22