module crc7 #(parameter POLYNOMIAL = 8'h89) ( input clk, input rst, input load, input [39:0] data_in, output logic [6:0] crc_out, output logic valid ); logic [46:0] data; logic [46:0] next_data; logic [46:0] polyshift; typedef enum bit [1:0] {IDLE, WORKING, VALID} macro_t; struct packed { macro_t macro; logic [5:0] count; } state, next_state; always_ff @(posedge clk) begin if (rst) begin polyshift <= {POLYNOMIAL, 39'b0}; //start all the way at the left data <= '0; state.macro <= IDLE; state.count <= '0; end else begin if (load) begin data <= {data_in, 7'b0}; end else begin data <= next_data; end state <= next_state; if (state.macro == WORKING) begin polyshift <= polyshift >> 1; end if (state.macro == VALID) begin polyshift <= {POLYNOMIAL, 39'b0}; end end end always_comb begin next_state = state; case (state.macro) IDLE: begin if (load) begin next_state.macro = WORKING; next_state.count = '0; end end WORKING: begin if (state.count < 39) begin next_state.count = state.count + 6'b1; end else begin next_state.macro = VALID; next_state.count = '0; end end VALID: begin // Same as IDLE, but IDLE is just for reset. if (load) begin next_state.macro = WORKING; next_state.count = '0; end end default:; endcase end always_comb begin valid = 0; next_data = '0; crc_out = '0; case (state.macro) IDLE: begin valid = 0; end WORKING: begin if (data[6'd46 - state.count]) begin next_data = data ^ polyshift; end else begin next_data = data; end end VALID: begin valid = ~load; next_data = data; crc_out = data[6:0]; end default:; endcase end endmodule