You are an expert Verilog hardware designer working on a complete FPGA or ASIC project. You are given the full source code of a Verilog project. One of the modules in the project is incomplete — its implementation is missing and marked with:

// >>> Module Implementation Begin

// <<< Module Implementation End

Your task is to complete the missing implementation so that the entire project functions correctly. You must infer what the missing module or logic is supposed to do by analyzing the rest of the codebase: module names, signal connections, instantiations, comments, and usage patterns.

Follow these rules:

1. Only generate Verilog code to go between the `// >>> Module Implementation Begin` and `// <<< Module Implementation End` comments.
2. Use Verilog-2001 syntax. Ensure the code is synthesizable.
3. Assume the goal is a working, integrated hardware design — your code must make the whole system function as intended.
4. Analyze the naming, I/O ports, and how the module is instantiated or used in other parts of the project.
5. Implement correct behavior based on design context. Do not guess randomly — reason it out.
6. Avoid vendor-specific features unless explicitly required.
7. Do not output comments, explanation, or anything outside the required code region unless explicitly asked.

Your output should contain **only the Verilog code** that fits inside the marked region.

`default_nettype none


module first_bit_position#(
	parameter WIDTH = 32
)(
	input [WIDTH - 1: 0] value,
	output [$clog2(WIDTH) - 1: 0] pos /* verilator split_var */
);
	localparam l2 = $clog2(WIDTH);
	wire [(1 << l2) - 1 : 0] layers[l2 + 1] /* verilator split_var */;
	wire pos_bits[l2] /* verilator split_var */;
	assign layers[l2][WIDTH - 1 : 0] = value;
	assign layers[l2][(1 << l2) - 1: WIDTH] = 0;
	
	genvar it;
	generate
		for(it = l2; it >= 1; it = it - 1)
		begin
			assign pos_bits[it - 1] = |layers[it][(1 << it) - 1 : 1 << (it - 1)];
			assign pos[it - 1] = pos_bits[it - 1];
		end
		for(it = l2; it >= 1; it = it - 1)
		begin
			assign layers[it - 1][(1 << (it - 1)) - 1 : 0] = pos_bits[it - 1] ? 
				layers[it][(1 << it) - 1 : (1 << (it - 1))]:
				layers[it][(1 << (it - 1)) - 1 :         0];
		end
	endgenerate
endmodule


`default_nettype none


// In reference to http://users.encs.concordia.ca/~asim/COEN_6501/Lecture_Notes/L4_Slides.pdf


`define WIDTH (MANTISSA_WIDTH + EXPONENT_WIDTH + 1)
`define EXP(f) f[MANTISSA_WIDTH +: EXPONENT_WIDTH]
`define MAN(f) f[0              +: MANTISSA_WIDTH]
`define SIGN(f) f[MANTISSA_WIDTH + EXPONENT_WIDTH]
module float_adder_v2 #(
	parameter MANTISSA_WIDTH = 23,
	parameter EXPONENT_WIDTH = 8
) (
	input clock,
	input reset,
	input                 in_valid,
	input  [`WIDTH - 1:0] in_a,
	input  [`WIDTH - 1:0] in_b,
	output                out_valid,
	output [`WIDTH - 1:0] out,

	/* verilator lint_off UNUSED */
	input [`WIDTH - 1 :0] out_reference

);

	wire [EXPONENT_WIDTH - 1 : 0] ref_exp;
	wire [MANTISSA_WIDTH - 1 : 0] ref_man;
	assign ref_exp = `EXP(out_reference);
	assign ref_man = `MAN(out_reference);
	/* verilator lint_on UNUSED */


	// Stage 1
	//  Swap inputs correct way around
	//  compute exponent difference

	reg s1_valid;
	reg s1_nan;
	reg s1_inf;
	reg [`WIDTH - 1 : 0] s1_smaler;
	reg [`WIDTH - 1 : 0] s1_larger;
	reg [EXPONENT_WIDTH - 1 : 0] s1_in_a_exp_comb;
	reg [EXPONENT_WIDTH - 1 : 0] s1_in_b_exp_comb;
	reg signed [EXPONENT_WIDTH + 1:0] s1_exponent_difference_comb;
	reg [EXPONENT_WIDTH + 1:0] s1_exp_diff;

	reg s1_a_nan_comb;
	reg s1_b_nan_comb;
	reg s1_a_inf_comb;
	reg s1_b_inf_comb;
	always @(*)
	begin
		s1_in_a_exp_comb = `EXP(in_a) == 0 ? 1 : `EXP(in_a);
		s1_in_b_exp_comb = `EXP(in_b) == 0 ? 1 : `EXP(in_b);
		s1_exponent_difference_comb = $signed({2'sb0, s1_in_a_exp_comb}) - $signed({2'sb0, s1_in_b_exp_comb});
	end
	reg s1_flip;

	always @(*)
		s1_flip = s1_exponent_difference_comb < 0;
	always @(*)
	begin
		s1_a_nan_comb = ((`EXP(in_a) == (1 << EXPONENT_WIDTH) - 1) &&  |`MAN(in_a));
		s1_b_nan_comb = ((`EXP(in_b) == (1 << EXPONENT_WIDTH) - 1) &&  |`MAN(in_b));
		s1_a_inf_comb = ((`EXP(in_a) == (1 << EXPONENT_WIDTH) - 1) && ~|`MAN(in_a));
		s1_b_inf_comb = ((`EXP(in_b) == (1 << EXPONENT_WIDTH) - 1) && ~|`MAN(in_b));
	end

	always @(posedge clock) if(reset) s1_valid <= 0; else
	begin
		s1_valid <= in_valid;
		s1_exp_diff <= s1_flip ? -s1_exponent_difference_comb : s1_exponent_difference_comb;
		s1_larger   <= s1_flip ? in_b : in_a;
		s1_smaler   <= s1_flip ? in_a : in_b;
		s1_nan      <= s1_a_nan_comb || s1_b_nan_comb || (`SIGN(in_a) != `SIGN(in_b) && s1_a_inf_comb && s1_b_inf_comb);
		s1_inf      <= ((`SIGN(in_a) & `SIGN(in_b)) & s1_a_inf_comb & s1_b_inf_comb) || ((`SIGN(in_a) != `SIGN(in_b)) & (s1_a_inf_comb ^ s1_b_inf_comb));
	end


	// Stage 2
	//  Right shifter
	//  bit inverter
	reg s2_valid;
	reg s2_flip_sign;
	reg s2_nan;
	reg s2_inf;
	reg s2_shared_sign;
	reg  signed [2 * MANTISSA_WIDTH + 3 - 1 : 0] s2_smaler_mant_expanded_comb;
	reg  signed [2 * MANTISSA_WIDTH + 3 - 1 : 0] s2_larger_mant_expanded_comb;
	wire signed [2 * MANTISSA_WIDTH + 3 - 1 : 0] s2_smaler_mant_comb;
	reg  signed [2 * MANTISSA_WIDTH + 3 - 1 : 0] s2_smaler;
	reg  signed [2 * MANTISSA_WIDTH + 3 - 1 : 0] s2_larger;
	reg  signed [EXPONENT_WIDTH + 1 : 0] s2_exponent;
	always @(*)
	begin
		s2_smaler_mant_expanded_comb = 0;
		s2_larger_mant_expanded_comb = 0;
		s2_smaler_mant_expanded_comb[MANTISSA_WIDTH +: MANTISSA_WIDTH + 1] = {`EXP(s1_smaler) == 0 ? 1'b0 : 1'b1, `MAN(s1_smaler)};
		s2_larger_mant_expanded_comb[MANTISSA_WIDTH +: MANTISSA_WIDTH + 1] = {`EXP(s1_larger) == 0 ? 1'b0 : 1'b1, `MAN(s1_larger)};
	end
	right_shifter #(
		.WIDTH(2 * MANTISSA_WIDTH + 3)
	) s1_rs (
		.value(s2_smaler_mant_expanded_comb),
		.ammount(s1_exp_diff > 10'b11_1111 ? 6'b11_1111 : s1_exp_diff[5:0]),
		.result(s2_smaler_mant_comb)
	);

	always @(posedge clock) if(reset) s2_valid <= 0; else
	begin
		s2_valid <= s1_valid;
		s2_flip_sign <= `SIGN(s1_smaler) ^ `SIGN(s1_larger);
		s2_smaler <= s2_smaler_mant_comb;
		s2_larger <= s2_larger_mant_expanded_comb;
		s2_exponent <= {2'sb0, `EXP(s1_larger)};
		s2_nan <= s1_nan;
		s2_inf <= s1_inf;
		s2_shared_sign <= `SIGN(s1_larger);
	end

	// Stage 3
	//  Addition

	reg s3_valid;
	reg s3_nan;
	reg s3_inf;
	reg s3_flipped;
	reg s3_shared_sign;
	reg  signed [2 * MANTISSA_WIDTH + 3 - 1 : 0] s3_sum;
	reg  signed [EXPONENT_WIDTH + 1 : 0] s3_exponent;
	
	always @(posedge clock) if(reset) s3_valid <= 0; else
	begin
		s3_valid <= s2_valid;
		s3_sum   <= s2_smaler + (s2_flip_sign ? -s2_larger : s2_larger);
		s3_exponent <= s2_exponent;
		s3_nan <= s2_nan;
		s3_inf <= s2_inf;
		s3_flipped <= s2_flip_sign;
		s3_shared_sign <= s2_shared_sign;
	end



	// Stage 4
	//  first bit position
	reg s4_valid;
	reg s4_flipped;
	reg s4_shared_sign;
	reg s4_nan;
	reg s4_inf;
	reg  signed [EXPONENT_WIDTH + 1 : 0] s4_exponent;
	reg  [EXPONENT_WIDTH + 1 : 0] s4_exponent_adjust_comb;
	reg  [2 * MANTISSA_WIDTH + 3 - 1 : 0] s4_mant_comb;
	reg  [EXPONENT_WIDTH + 1 : 0] s4_exponent_adjust;
	reg  [2 * MANTISSA_WIDTH + 3 - 1 : 0] s4_mant;
	reg  signed [2 * MANTISSA_WIDTH + 3 - 1 : 0] s4_sum;
	wire [5:0] s4_pos;

	always @(*)
	begin
		s4_mant_comb =  s3_sum < 0 ? -s3_sum : s3_sum;
		s4_exponent_adjust_comb = LEADING_1_POSITION - {4'b0, s4_pos};
		if(s4_exponent_adjust_comb > s3_exponent)
		begin
			s4_exponent_adjust_comb = s3_exponent + 1;
		end
	end

	first_bit_position #(
		.WIDTH(2 * MANTISSA_WIDTH + 3)
	) s5_fbp (
		.value(s4_mant_comb),
		.pos(s4_pos)
	);


	always @(posedge clock) if(reset) s4_valid <= 0; else
	begin
		s4_valid <= s3_valid;
		s4_exponent_adjust <= s4_exponent_adjust_comb;
		s4_mant <= s4_mant_comb;
		s4_flipped <= s3_flipped;
		s4_shared_sign <= s3_shared_sign;
		s4_sum <= s3_sum;
		s4_exponent <= s3_exponent;
		s4_nan <= s3_nan;
		s4_inf <= s3_inf;
	end

	localparam LEADING_1_POSITION = 2 * MANTISSA_WIDTH + 1;





	// Stage 5
	//  Complement
	reg s5_valid;
	reg s5_sign;
	reg [MANTISSA_WIDTH : 0] s5_mant;
	reg s5_R;
	reg s5_S;
	reg s5_nan;
	reg s5_inf;


	reg  signed [EXPONENT_WIDTH + 1: 0] s5_exponent;

	wire [2 * MANTISSA_WIDTH + 3 - 1 : 0] s5_mant_shifted_comb;

	left_shifter #(
		.WIDTH(2 * MANTISSA_WIDTH + 3)
	) s5_ls (
		.value(s4_mant),
		.ammount(s4_exponent_adjust > 10'b11_1111 ? 6'b11_1111 : s4_exponent_adjust[5:0]),
		.result(s5_mant_shifted_comb)
	);


	always @(posedge clock) if(reset) s5_valid <= 0; else
	begin
		s5_valid <= s4_valid;
		if(s4_flipped)
			s5_sign <= s4_sum < 0 ^ (s4_shared_sign ^ s4_flipped);
		else
			s5_sign <= s4_shared_sign;
		s5_mant <=  s5_mant_shifted_comb[MANTISSA_WIDTH + 1 +: MANTISSA_WIDTH + 1];
		s5_R    <=  s5_mant_shifted_comb[MANTISSA_WIDTH + 0 +: 1];
		s5_S    <= |s5_mant_shifted_comb[MANTISSA_WIDTH - 1  : 0];
		if(s3_exponent == 0 && s5_mant_shifted_comb[LEADING_1_POSITION])
			s5_exponent <= s4_exponent - s4_exponent_adjust + 2;
		else
			s5_exponent <= s4_exponent - s4_exponent_adjust + 1;
		s5_nan <= s4_nan;
		s5_inf <= s4_inf;
	end

	// Stage 6
	//  Rounding
	//  Overflow

	reg s6_valid;
	reg s6_sign;
	reg [MANTISSA_WIDTH - 1 : 0] s6_mant;
	reg [EXPONENT_WIDTH - 1 : 0] s6_expo;

	reg [MANTISSA_WIDTH     : 0] s6_mant_comb;
	reg signed [EXPONENT_WIDTH + 1 : 0] s6_expo_comb;
	always @(*)
	if((s5_R & s5_S) || (s5_mant[0] & s5_R & !s5_S))
	begin
		if(&s5_mant)
		begin
			if(s5_exponent == (1 << EXPONENT_WIDTH) - 2)
				s6_expo_comb = (1 << EXPONENT_WIDTH) - 1;
			else
				s6_expo_comb = s5_exponent + 1;
			s6_mant_comb = 0;
		end else
		begin
			s6_mant_comb = s5_mant + 1;
			s6_expo_comb = s5_exponent;
		end
		
	end else
	begin
		s6_expo_comb = s5_exponent;
		s6_mant_comb = s5_mant;
	end


	always @(posedge clock) if (reset) s6_valid <= 0; else
	begin
		s6_valid <= s5_valid;
		s6_sign <= s5_sign;
		if(s5_nan)
		begin
			s6_expo <= (1 << EXPONENT_WIDTH) - 1;
			s6_mant <= 1;
		end else if(s5_inf || s6_expo_comb >= (1 << EXPONENT_WIDTH) - 1) begin
			s6_expo <= (1 << EXPONENT_WIDTH) - 1;
			s6_mant <= 0;
		end else begin
			s6_expo <= s6_mant_comb == 0 ? 0 : s6_expo_comb[EXPONENT_WIDTH - 1 : 0];
			s6_mant <= s6_mant_comb[MANTISSA_WIDTH - 1 : 0];
		end


	end




	assign out_valid = s6_valid;
	assign out       = {s6_sign, s6_expo, s6_mant};
endmodule






module left_shifter #(
	parameter WIDTH = 32
) (
	input [WIDTH - 1:0] value,
	input [$clog2(WIDTH)-1:0] ammount,
	output[WIDTH - 1:0] result
);

	wire [WIDTH - 1:0] levels[$clog2(WIDTH) + 1] /* verilator split_var */;
	assign levels[0] = value;
	genvar layer;
	genvar bit_;
	generate
		for(layer = 0; layer < $clog2(WIDTH); layer = layer + 1)
		begin
			for(bit_ = 0; bit_ < WIDTH; bit_ = bit_ + 1)
			begin
				assign levels[layer + 1][bit_] = ammount[layer] ? (bit_ - (1<<layer) < 0 ? 1'b0 : levels[layer][bit_ - (1 << layer)]) : levels[layer][bit_];
			end
		end
	endgenerate
	assign result = levels[$clog2(WIDTH)];
endmodule


/*
 * Copyright (c) 2024 Sebastian Pfeiler
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_Qwendu_spi_fpu (
	  input  wire [7:0] ui_in,    // Dedicated inputs
	  output wire [7:0] uo_out,   // Dedicated outputs
	  input  wire [7:0] uio_in,   // IOs: Input path
	  output wire [7:0] uio_out,  // IOs: Output path
	  output wire [7:0] uio_oe,   // IOs: Enable path (active high: 0=input, 1=output)
	  input  wire       ena,      // always 1 when the design is powered, so you can ignore it
	  input  wire       clk,      // clock
	  input  wire       rst_n     // reset_n - low to reset
);
	assign uo_out[7:1]  = 7'b0;
	assign uio_out = 0;
	assign uio_oe  = 0;

	spi_fpu main(
		.clock(clk),
		.reset(!rst_n),
		.SPI_clock(ui_in[0]),
		.SPI_not_chip_select(ui_in[1]),
		.SPI_in(ui_in[2]),
		.SPI_out(uo_out[0])
	);
endmodule



module right_shifter #(
	parameter WIDTH = 32
) (
	input [WIDTH - 1:0] value,
	input [$clog2(WIDTH)-1:0] ammount,
	output[WIDTH - 1:0] result
);

	wire [WIDTH - 1:0] levels[$clog2(WIDTH) + 1] /* verilator split_var */;
	assign levels[0] = value;
	genvar layer;
	genvar bit_;
	generate
		for(layer = 0; layer < $clog2(WIDTH); layer = layer + 1)
		begin
			for(bit_ = 0; bit_ < WIDTH; bit_ = bit_ + 1)
			begin
				assign levels[layer + 1][bit_] = ammount[layer] ? (bit_ + (1<<layer) >= WIDTH ? 1'b0 : levels[layer][bit_ + (1 << layer)]) : levels[layer][bit_];
			end
		end
	endgenerate
	assign result = levels[$clog2(WIDTH)];
endmodule


`default_nettype none

module sampler(
	input clock,
	input reset,
	input signal,
	output sampled_signal,

	output falling,
	output rising
);
// >>> Module Implementation Begin

// <<< Module Implementation End
endmodule




`default_nettype none

module serial_in_parallel_out #(
	parameter DATA_WIDTH=8
) (
	input clock,
	input reset,
	input shift_trigger,
	
	input signal,
	output reg [DATA_WIDTH-1:0] data
);

	always @(posedge clock)
	if(reset)
		data <= 0;
	else if(shift_trigger)
		data <= {data[DATA_WIDTH-2:0], signal};
endmodule


`default_nettype none

// icetime says max of 3 MHz, which is fine

module spi_fpu(
	input reset,
	input clock,
	input SPI_clock,
	input SPI_in,
	output SPI_out,
	input SPI_not_chip_select
);
	/* verilator lint_off UNUSED */
	wire [7:0] SPI_input_data;
	wire       SPI_input_data_valid;

	wire [7:0] SPI_output_data;
	wire       SPI_output_data_valid;
	wire       SPI_output_data_ready;
	wire       SPI_active;
	/* verilator lint_on UNUSED */
	spi_rx spi(
		.clock(clock),
		.reset(reset),
		.SPI_in(SPI_in),
		.SPI_out(SPI_out),
		.SPI_clock(SPI_clock),
		.SPI_not_chip_select(SPI_not_chip_select),

		.in_data_valid(SPI_input_data_valid),
		.in_data(SPI_input_data),

		.out_data_valid(SPI_output_data_valid),
		.out_data(SPI_output_data),
		.out_data_ready(SPI_output_data_ready),
		.active(SPI_active)
	);

	wire        float_result_ready;
	wire [31:0] float_result;
	reg  [31:0] float_registers[4] /*verilator public */;

	localparam COMMAND_WRITE_TO_REG  = 2'h0;
	localparam COMMAND_PERFORM_ADD   = 2'h1;
	localparam COMMAND_READ_FROM_REG = 2'h2;



	localparam STATE_IDLE               = 0;
	localparam STATE_READ_COMMAND       = 1;
	localparam STATE_IO_READ_TARGET_REG = 2;
	localparam STATE_IO                 = 3;
	localparam STATE_COMPUTE_READ_REGS  = 4;
	localparam STATE_COMPUTE_WAIT_FOR   = 5;
	localparam STATE_WAIT_FOR_END       = 6;

	reg [2:0] state;
	reg [1:0] read_command;
	reg [1:0] byte_counter;
	reg [1:0] register_id_result;
	reg [1:0] register_id_input_a;
	reg [1:0] register_id_input_b;

	always @(posedge clock)
	if(reset)
	begin
		state               <= STATE_IDLE;
		register_id_result  <= 0;
		register_id_input_a <= 0;
		register_id_input_b <= 0;
		float_registers[0] <= 0;
		float_registers[1] <= 0;
		float_registers[2] <= 0;
		float_registers[3] <= 0;
	end else if(!SPI_active)
		state <= STATE_IDLE;
	else case(state)
	STATE_IDLE: 
	begin
		if(SPI_active)
			state <= STATE_READ_COMMAND;
	end
	STATE_READ_COMMAND:
	begin
		if(SPI_input_data_valid)
		begin
			byte_counter <= 0;
			read_command[1:0] <= SPI_input_data[1:0];
			case(SPI_input_data[1:0])
			COMMAND_WRITE_TO_REG : state <= STATE_IO_READ_TARGET_REG;
			COMMAND_PERFORM_ADD  : state <= STATE_COMPUTE_READ_REGS;
			COMMAND_READ_FROM_REG: state <= STATE_IO_READ_TARGET_REG;
			default: state <= STATE_WAIT_FOR_END;
			endcase
		end
	end
	STATE_IO_READ_TARGET_REG:
	begin
		if(SPI_input_data_valid)
		begin
			register_id_result <= SPI_input_data[1:0];
			state <= STATE_IO;
		end
	end
	STATE_IO:
	begin
		case(read_command)
		COMMAND_WRITE_TO_REG:
			if(SPI_input_data_valid)
			begin
				float_registers[register_id_result][byte_counter * 8 +: 8] <= SPI_input_data;
				byte_counter <= byte_counter + 1;

				if(byte_counter == 2'd3)  state <= STATE_WAIT_FOR_END;
			end
		COMMAND_READ_FROM_REG:
			if(SPI_output_data_ready)
			begin
				byte_counter <= byte_counter + 1;
				if(byte_counter == 2'd3)  state <= STATE_WAIT_FOR_END;
			end
		default: state <= STATE_WAIT_FOR_END;
		endcase
	end
	STATE_COMPUTE_READ_REGS:
	begin
		if(SPI_input_data_valid)
		begin
			case(byte_counter)
			2'h0: register_id_input_a <= SPI_input_data[1:0];
			2'h1: register_id_input_b <= SPI_input_data[1:0];
			2'h2:
			begin
				register_id_result  <= SPI_input_data[1:0];
				state <= STATE_COMPUTE_WAIT_FOR;
			end
			default: state <= STATE_WAIT_FOR_END;
			endcase
			byte_counter <= byte_counter + 1;
		end
	end
	STATE_COMPUTE_WAIT_FOR:
		if(float_result_ready)
		begin
			float_registers[register_id_result] <= float_result;
			state <= STATE_WAIT_FOR_END;
		end
	STATE_WAIT_FOR_END:
	begin
	end

	endcase
	assign SPI_output_data       = state == STATE_IO ? float_registers[register_id_result][byte_counter * 8 +: 8] : 8'b0;
	assign SPI_output_data_valid = state == STATE_IO && read_command == COMMAND_READ_FROM_REG;

	float_adder_v2 adder(
		.clock(clock),
		.reset(reset),
		.in_valid(state == STATE_COMPUTE_WAIT_FOR),
		.in_a(float_registers[register_id_input_a]),
		.in_b(float_registers[register_id_input_b]),
		.out(float_result),
		.out_valid(float_result_ready),
		.out_reference(32'b0)
	);
endmodule


`default_nettype none

// CPOL=1
// CPHA=1
module spi_rx (
	input clock,
	input reset,

	input  SPI_clock,
	input  SPI_in,
	output SPI_out,
	input  SPI_not_chip_select,

	output reg   in_data_valid,
	output [7:0] in_data,
	// DO not wait for the next module to be ready, blocking will miss SPI data! input        in_data_ready,

/* verilator lint_off UNUSED */
	input        out_data_valid,

	input  [7:0] out_data,
/* verilator lint_on UNUSED */
	output reg   out_data_ready,

	output active
);
	/* verilator lint_off UNUSED */
	wire [7:0] unused;
	/* verilator lint_on UNUSED */
	wire SPI_clock_sampled, SPI_clock_rising, SPI_clock_falling;
	sampler SPI_clock_sampler(
		.clock(clock),
		.reset(reset),
		.signal(SPI_clock),
		.sampled_signal(SPI_clock_sampled),
		.falling(SPI_clock_falling),
		.rising(SPI_clock_rising)
	);
	wire SPI_not_chip_select_sampled, SPI_not_chip_select_rising, SPI_not_chip_select_falling;
	sampler SPI_not_chip_select_sampler(
		.clock(clock),
		.reset(reset),
		.signal(SPI_not_chip_select),
		.sampled_signal(SPI_not_chip_select_sampled),
		.falling(SPI_not_chip_select_falling),
		.rising(SPI_not_chip_select_rising)
	);
	assign active = !SPI_not_chip_select_sampled;
	wire SPI_in_sampled, SPI_in_rising, SPI_in_falling;
	sampler SPI_in_sampler(
		.clock(clock),
		.reset(reset),
		.signal(SPI_in),
		.sampled_signal(SPI_in_sampled),
		.falling(SPI_in_falling),
		.rising(SPI_in_rising)
	);
	wire [7:0] SPI_in_shift_data;
	serial_in_parallel_out #(.DATA_WIDTH(8)) SPI_in_shifter (
		.clock(clock),
		.reset(reset),
		.shift_trigger(SPI_clock_rising),
		.signal(SPI_in_sampled),
		.data(SPI_in_shift_data)
	);
	assign in_data = SPI_in_shift_data;

	localparam STATE_idle = 0;
	localparam STATE_io   = 1;

	reg [3:0] state = STATE_idle;
	reg [2:0] in_bit_counter;

	always @(posedge clock)
	if(reset)
		in_bit_counter <= 7;
	else case(state)
	STATE_io:
	begin
		if(SPI_clock_falling)
			in_bit_counter <= in_bit_counter + 1;
		
		if(in_bit_counter == 7 && SPI_clock_rising)
			in_data_valid <= 1'b1;
		else
			in_data_valid <= 1'b0;
	end
	default: begin end
	endcase

	always @(posedge clock)
	if(reset)
	begin
		state <= STATE_idle;
	end else begin
		if(SPI_not_chip_select_falling)
			state <= STATE_io;
		if(SPI_not_chip_select_rising)
			state <= STATE_idle;
	end

	reg [7:0] out_data_r;
	always @(posedge clock)
	if(reset)
	begin
		out_data_r <= 8'b0;
		out_data_ready <= 1;
	end else begin
		if(out_data_valid & out_data_ready)
		begin
			out_data_r <= out_data;
			out_data_ready <= 0;
		end else if(SPI_clock_falling & out_bit_counter == 7)
			out_data_ready <= 1;
	end

	reg [2:0] out_bit_counter;
	always @(posedge clock)
	if(reset)
	begin
		out_bit_counter <= 0;
	end else if(state == STATE_io)
	begin
		if(SPI_clock_rising)
			out_bit_counter <= out_bit_counter + 1;
	end

	reg SPI_out_r;
	always @(posedge clock)
		if(SPI_clock_falling)
			SPI_out_r <= out_data_r[7 - out_bit_counter];
	
	assign SPI_out = SPI_out_r;

	assign unused = {3'b0, SPI_clock_sampled, SPI_not_chip_select_sampled, SPI_not_chip_select_falling, SPI_in_rising, SPI_in_falling};
endmodule


Reference solution:
rtl/generated.v: 	reg [1:0] sample_register;
	always @(posedge clock)
	if(reset)
		sample_register <= {signal, signal};
	else
		sample_register <= {sample_register[0], signal};

	assign sampled_signal = sample_register[1];
	assign falling =  sample_register[1] & !sample_register[0];
	assign rising  = !sample_register[1] &  sample_register[0];