diff --git a/rtl/frame_monitor.sv b/rtl/frame_monitor.sv new file mode 100644 index 0000000..5eb9b37 --- /dev/null +++ b/rtl/frame_monitor.sv @@ -0,0 +1,48 @@ +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