| module ERROR_OUTPUT_LOGIC #( |
| parameter [7:0] DATA_WIDTH = 1, |
| parameter [7:0] ADDR_WIDTH = 6 |
| ) ( |
| input rst, |
| input clk, |
| |
| input loop_complete, |
| input error_detected, |
| input [7:0] error_state, |
| input [ADDR_WIDTH-1:0] error_address, |
| input [DATA_WIDTH-1:0] expected_data, |
| input [DATA_WIDTH-1:0] actual_data, |
| |
| // Output to UART |
| input tx_data_accepted, |
| output reg tx_data_ready, |
| output reg [7:0] tx_data |
| ); |
| reg reg_error_detected; |
| reg [7:0] reg_error_state; |
| reg [ADDR_WIDTH-1:0] reg_error_address; |
| reg [DATA_WIDTH-1:0] reg_expected_data; |
| reg [DATA_WIDTH-1:0] reg_actual_data; |
| |
| reg [7:0] error_count; |
| reg [7:0] output_shift; |
| |
| wire [7:0] next_output_shift = output_shift + 8; |
| wire count_shift_done = next_output_shift >= 8'd16; |
| wire address_shift_done = next_output_shift >= ADDR_WIDTH; |
| wire data_shift_done = next_output_shift >= DATA_WIDTH; |
| |
| reg loop_ready; |
| reg [7:0] latched_error_count; |
| |
| reg [7:0] errors; |
| reg [10:0] state; |
| reg [15:0] loop_count; |
| reg [15:0] latched_loop_count; |
| |
| localparam START = (1 << 0), |
| ERROR_COUNT_HEADER = (1 << 1), |
| ERROR_COUNT_COUNT = (1 << 2), |
| CR = (1 << 3), |
| LF = (1 << 4), |
| ERROR_HEADER = (1 << 5), |
| ERROR_STATE = (1 << 6), |
| ERROR_ADDRESS = (1 << 7), |
| ERROR_EXPECTED_DATA = (1 << 8), |
| ERROR_ACTUAL_DATA = (1 << 9), |
| LOOP_COUNT = (1 << 10); |
| |
| initial begin |
| tx_data_ready <= 1'b0; |
| tx_data <= 8'b0; |
| state <= START; |
| reg_error_detected <= 1'b0; |
| end |
| |
| always @(posedge clk) begin |
| if(rst) begin |
| state <= START; |
| error_count <= 0; |
| reg_error_detected <= 0; |
| tx_data_ready <= 0; |
| tx_data <= 8'b0; |
| loop_count <= 0; |
| loop_ready <= 0; |
| end else begin |
| |
| if(error_detected) begin |
| if(error_count < 255) begin |
| error_count <= error_count + 1; |
| end |
| |
| if(!reg_error_detected) begin |
| reg_error_detected <= 1; |
| reg_error_state <= error_state; |
| reg_error_address <= error_address; |
| reg_expected_data <= expected_data; |
| reg_actual_data <= actual_data; |
| end |
| end |
| |
| if(tx_data_accepted) begin |
| tx_data_ready <= 0; |
| end |
| |
| if(loop_complete) begin |
| loop_count <= loop_count + 1; |
| if(!loop_ready) begin |
| loop_ready <= 1; |
| latched_error_count <= error_count; |
| latched_loop_count <= loop_count; |
| error_count <= 0; |
| end |
| end |
| |
| case(state) |
| START: begin |
| if(reg_error_detected) begin |
| state <= ERROR_HEADER; |
| end else if(loop_ready) begin |
| state <= ERROR_COUNT_HEADER; |
| end |
| end |
| ERROR_COUNT_HEADER: begin |
| if(!tx_data_ready) begin |
| tx_data <= "L"; |
| tx_data_ready <= 1; |
| state <= ERROR_COUNT_COUNT; |
| end |
| end |
| ERROR_COUNT_COUNT: begin |
| if(!tx_data_ready) begin |
| tx_data <= latched_error_count; |
| tx_data_ready <= 1; |
| output_shift <= 0; |
| state <= LOOP_COUNT; |
| end |
| end |
| LOOP_COUNT: begin |
| if(!tx_data_ready) begin |
| tx_data <= (latched_loop_count >> output_shift); |
| tx_data_ready <= 1; |
| |
| if(count_shift_done) begin |
| output_shift <= 0; |
| loop_ready <= 0; |
| state <= CR; |
| end else begin |
| output_shift <= next_output_shift; |
| end |
| end |
| end |
| CR: begin |
| if(!tx_data_ready) begin |
| tx_data <= 8'h0D; // "\r" |
| tx_data_ready <= 1; |
| state <= LF; |
| end |
| end |
| LF: begin |
| if(!tx_data_ready) begin |
| tx_data <= 8'h0A; // "\n" |
| tx_data_ready <= 1; |
| state <= START; |
| end |
| end |
| ERROR_HEADER: begin |
| if(!tx_data_ready) begin |
| tx_data <= "E"; |
| tx_data_ready <= 1; |
| state <= ERROR_STATE; |
| end |
| end |
| ERROR_STATE: begin |
| if(!tx_data_ready) begin |
| tx_data <= reg_error_state; |
| tx_data_ready <= 1; |
| output_shift <= 0; |
| state <= ERROR_ADDRESS; |
| end |
| end |
| ERROR_ADDRESS: begin |
| if(!tx_data_ready) begin |
| tx_data <= (reg_error_address >> output_shift); |
| tx_data_ready <= 1; |
| |
| if(address_shift_done) begin |
| output_shift <= 0; |
| state <= ERROR_EXPECTED_DATA; |
| end else begin |
| output_shift <= next_output_shift; |
| end |
| end |
| end |
| ERROR_EXPECTED_DATA: begin |
| if(!tx_data_ready) begin |
| tx_data <= (reg_expected_data >> output_shift); |
| tx_data_ready <= 1; |
| |
| if(data_shift_done) begin |
| output_shift <= 0; |
| state <= ERROR_ACTUAL_DATA; |
| end else begin |
| output_shift <= next_output_shift; |
| end |
| end |
| end |
| ERROR_ACTUAL_DATA: begin |
| if(!tx_data_ready) begin |
| tx_data <= (reg_actual_data >> output_shift); |
| tx_data_ready <= 1; |
| |
| if(data_shift_done) begin |
| state <= CR; |
| reg_error_detected <= 0; |
| end else begin |
| output_shift <= output_shift + 8; |
| end |
| end |
| end |
| default: begin |
| state <= START; |
| end |
| endcase |
| end |
| end |
| endmodule |