module lab3 # (
	parameter DATA_WIDTH = 8,
	localparam DATA_WIDTH_M1 = DATA_WIDTH - 1
)(
	input clk, input rst_n,
	input use_seed,
	input [DATA_WIDTH_M1:0] data_i,
	input valid_i,
	output reg [DATA_WIDTH_M1+2:0] data_o,
	output reg valid_o
);

localparam SEED = 333;
localparam ST_START = 2'b00;
localparam ST_IDLE = 2'b01;
localparam ST_RUN = 2'b10;
localparam ST_FIX = 2'b11;

reg [DATA_WIDTH_M1+2:0] hash, next_hash;

reg [1:0] state, next_state;

reg overflow;

always @(posedge clk or negedge rst_n) begin
	if (rst_n == 1'b0) begin
		state <= ST_START;
		hash <= 'd0;
	end
	else begin
		state <= next_state;
		hash <= next_hash;
	end
end

always @(*) begin
	next_hash = hash;
	overflow = 1'b0;
	valid_o = 1'b1;
	data_o = hash;
	case (state) 
		ST_START: begin 
			next_state = ST_IDLE;
			if (use_seed) begin
				next_hash = SEED;
			end
		end
		ST_IDLE: begin 
			if (valid_i) begin
				next_state = ST_RUN;
			end
			else begin
				next_state = ST_IDLE;
			end
		end
		ST_RUN: begin
			{overflow, next_hash} = hash + data_i;
			if (overflow) begin
				next_state = ST_FIX;
				valid_o = 1'b0;
			end
			else begin
				if (!valid_i) begin
					next_state = ST_IDLE;
				end
				else begin
					next_state = ST_RUN;
				end
			end
		end
		ST_FIX: begin 
			next_hash = ({1'b1,hash} % 997) + 7;
			next_state = ST_RUN;
		end
	endcase
end

endmodule