aboutsummaryrefslogtreecommitdiffstats
path: root/atk16_fpga/top.v
blob: 07486cb3580cc4b6f8352b49dceb55cf3562ddb9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Top-level module for the iCE40 HX8K FPGA.
// This module instantiates the UART transmitter and sends the bytes for
// "Hello" and a newline character, then stops.
module top (
    input  SYSCLK,     // 100 MHz system clock
    input  SERIAL_RX,   // UART receive input
    output SERIAL_TX,   // UART transmit output
    output LED1,
    output LED2
);

    // State machine states.
    localparam RX_START = 0;
    localparam WAIT_RX_DONE = 1;
    localparam START_TX = 2;
    localparam TX_IN_PROG = 3;
    localparam WAIT_TX_DONE = 4;
    localparam SEND_STRING_WELCOME = 5;
    localparam RECEIVE_PROGRAM_DATA = 6;

    reg [7:0] state = SEND_STRING_WELCOME;

    // SEND_WELCOME data
    `STR_welcome
    reg [7:0] welcome_index = 0;

    // Synchronous state machine with reset.
    always @(posedge SYSCLK) begin
        case (state)
            // STATES FOR RX
            RX_START: begin
                if (!rx_done) begin
                    state <= WAIT_RX_DONE;
                end
            end

            WAIT_RX_DONE: begin
                if (rx_done) begin
                    state <= state_after_rx;
                end
            end

            // STATES FOR TX
            START_TX: begin
                if (!tx_busy) begin
                    start_tx <= 1'b1;  // trigger transmission
                    state <= TX_IN_PROG;
                end
            end

            // After issuing the start pulse, wait for tx_busy to go high.
            TX_IN_PROG: begin
                start_tx <= 1'b0;  // ensure pulse is only one cycle.
                state <= WAIT_TX_DONE;
            end

            // Wait for the transmitter to finish sending the byte.
            WAIT_TX_DONE: begin
                if (!tx_busy) begin
                    state <= state_after_tx;
                end
            end

            SEND_STRING_WELCOME: begin
                if (welcome_index < 8'd`LEN_welcome) begin
                    data_tx <= str_welcome[welcome_index];
                    welcome_index <= welcome_index + 1;
                    state <= START_TX;
                    state_after_tx <= SEND_STRING_WELCOME;
                end else begin
                    welcome_index <= 0;
                    state <= RECEIVE_PROGRAM_DATA;
                    state_after_tx <= RX_START;
                end
            end

            RECEIVE_PROGRAM_DATA: begin
                // TODO write data to flash
                state <= RX_START;
                state_after_rx <= RECEIVE_PROGRAM_DATA;
            end

            default: state <= RX_START;
        endcase

    end

    // One-cycle pulse to trigger transmission.
    reg        start_tx = 1'b0;
    // Data byte to be transmitted.
    reg  [7:0] data_tx = 8'b0;
    // Busy flag from the transmitter.
    wire       tx_busy;
    // State to transition to after TX done.
    reg  [7:0] state_after_tx = RX_START;

    // Instantiate the UART transmitter.
    uart_tx uart_inst (
        .clk  (SYSCLK),
        .start(start_tx),   // One-cycle pulse to start transmission.
        .data (data_tx),
        .tx   (SERIAL_TX),
        .busy (tx_busy)
    );

    wire [7:0] data_rx;
    wire rx_done;
    reg [7:0] state_after_rx = RECEIVE_PROGRAM_DATA;

    uart_rx uart_rx_inst (
        .clk (SYSCLK),
        .rx  (SERIAL_RX),
        .data(data_rx),
        .done(rx_done)
    );

    assign LED1 = 1;
    assign LED2 = LED1;

endmodule