module frame_monitor #( parameter int MAX_LENGTH = 32 ) ( input logic clk, rst_n, byte_valid, input logic [7:0] byte_data, output logic frame_valid, output logic [15:0] length_errors, parity_errors ); import frame_types::*; state_t state; logic [7:0] length; logic parity, clear_parity, feed_parity; logic length_error, parity_error; assign clear_parity = byte_valid && state == WAIT_START && byte_data == START_BYTE; assign feed_parity = byte_valid && state == COLLECT && byte_data != END_BYTE && length < MAX_LENGTH; parity_accumulator checksum(clk, rst_n, clear_parity, feed_parity, byte_data, parity); error_counters counters(clk, rst_n, length_error, parity_error, length_errors, parity_errors); always_ff @(posedge clk or negedge rst_n) begin if (!rst_n) begin state <= WAIT_START; length <= 0; frame_valid <= 0; length_error <= 0; parity_error <= 0; end else begin frame_valid <= 0; length_error <= 0; parity_error <= 0; if (byte_valid) begin case (state) WAIT_START: if (byte_data == START_BYTE) begin state <= COLLECT; length <= 0; end COLLECT: if (byte_data == END_BYTE) begin if (length == 0) length_error <= 1; else if (parity) parity_error <= 1; else frame_valid <= 1; state <= WAIT_START; end else if (length >= MAX_LENGTH) begin length_error <= 1; state <= DROP; end else begin length <= length + 1'b1; end DROP: if (byte_data == END_BYTE) state <= WAIT_START; default: state <= WAIT_START; endcase end end end endmodule