`include "defs.svh" module command_parser #( TAG = 0 ) ( input bit clock , input bit reset , output bit uart_ready , input bit uart_valid , input uart_byte_t uart_data , input bit echo_ready , output bit echo_valid , output uart_byte_t echo_data , input bit command_ready , output bit command_valid , output arb_to_ram_t command_data , input bit loop_ready , output bit loop_valid , output bit loop_data , output bit clear_caches ); bit input_byte_valid; uart_byte_t input_byte; bit [`RAM_ADDRESS_BITS:0] loop_count; (* syn_encoding = "one-hot" *) enum int unsigned { READ_COMMAND , READ_ADDRESS , READ_DATA , READ_LOOP_COUNT , LOOP_MEMORY } state; always @(posedge clock) begin if (reset) begin uart_ready = 0; command_valid = 0; for (int i = 0; i < `RAM_LINE_WORDS; i = i + 1) command_data.mask[i] = ~0; command_data.tag = TAG; loop_valid = 0; clear_caches = 0; input_byte_valid = 0; input_byte = 0; loop_count = 0; state = state.first; end else begin if (echo_ready) echo_valid = 0; if (command_ready && command_valid) begin command_valid = 0; ++command_data.address; end if (uart_ready && uart_valid) begin echo_valid = 1; echo_data = uart_data; input_byte_valid = 1; input_byte = uart_data; end if (loop_ready && loop_valid) begin loop_valid = 0; end clear_caches = 0; if (!command_valid && !loop_valid) begin case (state) READ_COMMAND: if (input_byte_valid) begin case (input_byte) "@": begin command_data.address = 0; loop_valid = 1; loop_data = 0; state = READ_ADDRESS; end "?": begin command_valid = 1; command_data.write = 0; loop_valid = 1; loop_data = 0; end "=": begin command_data.write = 1; for (int i = 0; i < `RAM_LINE_WORDS; i = i + 1) command_data.data[i] = 0; loop_valid = 1; loop_data = 0; state = READ_DATA; end "!": begin command_data.write = 1; for (int i = 0; i < `RAM_LINE_WORDS; i = i + 1) command_data.data[i] = 0; loop_count = 0; state = READ_LOOP_COUNT; end "#": begin command_data.write = 0; loop_count = 0; state = READ_LOOP_COUNT; end "$": begin clear_caches = 1; end endcase input_byte_valid = 0; end READ_ADDRESS: if (input_byte_valid) begin if (input_byte == ":") begin // ignore end else if (input_byte >= "0" && input_byte <= "9") begin command_data.address = command_data.address << 4; command_data.address[$clog2(`RAM_LINE_WORDS)+:4] = input_byte - "0"; end else if (input_byte >= "a" && input_byte <= "f") begin command_data.address = command_data.address << 4; command_data.address[$clog2(`RAM_LINE_WORDS)+:4] = input_byte - "a" + 10; end else if (input_byte >= "A" && input_byte <= "F") begin command_data.address = command_data.address << 4; command_data.address[$clog2(`RAM_LINE_WORDS)+:4] = input_byte - "A" + 10; end else begin state = state.first; end input_byte_valid = 0; end READ_DATA: if (input_byte_valid) begin automatic bit [$bits(command_data.data)-1:0] flat_data = command_data.data; flat_data = flat_data << 4; if (input_byte == ":") begin // ignore end else if (input_byte >= "0" && input_byte <= "9") begin flat_data[3:0] = input_byte - "0"; command_data.data = flat_data; end else if (input_byte >= "a" && input_byte <= "f") begin flat_data[3:0] = input_byte - "a" + 10; command_data.data = flat_data; end else if (input_byte >= "A" && input_byte <= "F") begin flat_data[3:0] = input_byte - "A" + 10; command_data.data = flat_data; end else begin command_valid = 1; state = state.first; end input_byte_valid = 0; end READ_LOOP_COUNT: if (input_byte_valid) begin if (input_byte == ":") begin // ignore end else if (input_byte >= "0" && input_byte <= "9") begin loop_count = loop_count << 4; loop_count[3:0] = input_byte - "0"; end else if (input_byte >= "a" && input_byte <= "f") begin loop_count = loop_count << 4; loop_count[3:0] = input_byte - "a" + 10; end else if (input_byte >= "A" && input_byte <= "F") begin loop_count = loop_count << 4; loop_count[3:0] = input_byte - "A" + 10; end else begin loop_valid = 1; loop_data = 1; state = LOOP_MEMORY; end input_byte_valid = 0; end `ifdef SLOW_LOOPING LOOP_MEMORY: if (!echo_valid) begin if (loop_count == 0) begin echo_valid = 1; echo_data = "\n"; state = state.first; end else begin echo_valid = 1; echo_data = "."; command_valid = 1; --loop_count; end end `else LOOP_MEMORY: begin if (loop_count == 0) begin state = state.first; end else begin command_valid = 1; if (--loop_count == 0) begin state = state.first; end end end `endif endcase end uart_ready = !echo_valid && !input_byte_valid; end end endmodule