summaryrefslogtreecommitdiff
path: root/hdl/command_parser.sv
blob: d15d72d889240480023b015e6c9c1a5db1cba153 (plain) (blame)
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
module command_parser
    (   input   bit         clock
    ,   input   bit         resetn

    ,   output  bit         uart_ready
    ,   input   bit         uart_valid
    ,   input   bit [7:0]   uart_data

    ,   input   bit         echo_ready
    ,   output  bit         echo_valid
    ,   output  bit [7:0]   echo_data

    ,   input   bit         command_ready
    ,   output  bit         command_valid
    ,   output  bit [22:0]  command_address
    ,   output  bit         command_write
    ,   output  bit [15:0]  command_data
    );

    bit         input_byte_valid;
    bit [7:0]   input_byte;

    (* syn_encoding = "one-hot" *) enum int unsigned
        {   READ_ADDRESS_OR_COMMAND
        ,   READ_DATA_1
        ,   READ_DATA_2
        ,   READ_DATA_3
        ,   READ_DATA_4
        } state;

    always @(posedge clock) begin
        if (!resetn) begin
            uart_ready = 0;
            command_valid = 0;
            command_address = 0;
            command_write = 0;
            command_data = 0;
            input_byte_valid = 0;
            input_byte = 0;
            state = state.first;
        end else begin
            if (echo_ready) echo_valid = 0;
            if (command_ready && command_valid) begin
                command_valid = 0;
                command_address = 0;
                command_write = 0;
                command_data = 0;
            end
            if (uart_ready && uart_valid) begin
                echo_valid = 1;
                echo_data = uart_data;
                input_byte_valid = 1;
                input_byte = uart_data;
            end

            if (!command_valid && input_byte_valid) begin
                case (state)

                READ_ADDRESS_OR_COMMAND: begin
                    if (input_byte >= "0" && input_byte <= "9") begin
                        command_address = command_address << 4;
                        command_address[3:0] = input_byte - "0";
                    end else if (input_byte >= "a" && input_byte <= "f") begin
                        command_address = command_address << 4;
                        command_address[3:0] = input_byte - "a" + 10;
                    end else if (input_byte >= "A" && input_byte <= "F") begin
                        command_address = command_address << 4;
                        command_address[3:0] = input_byte - "A" + 10;
                    end else if (input_byte == "?") begin
                        command_valid = 1;
                        command_write = 0;
                        command_data = 0;
                    end else if (input_byte == "=") begin
                        command_write = 1;
                        command_data = 0;
                        state = READ_DATA_1;
                    end else begin
                        command_address = 0;
                        command_write = 0;
                        command_data = 0;
                    end
                end

                READ_DATA_1, READ_DATA_2, READ_DATA_3, READ_DATA_4: begin
                    if (input_byte >= "0" && input_byte <= "9") begin
                        command_data = command_data << 4;
                        command_data[3:0] = input_byte - "0";
                        state = state.next;
                    end else if (input_byte >= "a" && input_byte <= "f") begin
                        command_data = command_data << 4;
                        command_data[3:0] = input_byte - "a" + 10;
                        state = state.next;
                    end else if (input_byte >= "A" && input_byte <= "F") begin
                        command_data = command_data << 4;
                        command_data[3:0] = input_byte - "A" + 10;
                        state = state.next;
                    end else begin
                        state = state.first;
                    end
                    command_valid = state == state.first;
                end

                endcase
                input_byte_valid = 0;
            end

            uart_ready = !echo_valid && !input_byte_valid;
        end
    end

endmodule