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.

module FSM(
	input clk, reset, bank0_full, bank1_full, memorization_completed, 
	input [7:0] idx_final, 
	output [8:0] addr_out, 
	output reg SL_ch, SL_time, selection_bit, re, serial_readout, sending_data,
	output reg [2:0] state_reg
	);


  
  reg [7:0] idx, reg_idx_final;
  reg [2:0] state_next;
  reg [4:0] cpt;
  reg signal_duration, sending_pending, read_bank, sending_started;
  localparam [2:0]
  s0 = 0,
  s1 = 1,
  s2 = 2,
  s3 = 3,
  s4 = 4,
  s5 = 5,
  s6 = 6,
  s7 = 7;	

  //reg signal_duration; //0 => short signal (<200 us), 1 => long signal (>200us)
  //reg[2:0] state_reg, state_next;
  //reg sending_pending, sending_started;

  
  assign addr_out[7:0] = idx[7:0];
  assign addr_out[8] = read_bank;


// change state process
always @(posedge clk or posedge reset) begin
	if (reset) begin
		state_reg <= s0;
      	end 
	else begin        
      state_reg <=  state_next; 
    end
end


// sequential outputs of the state machine
// idx => counter for read address in memory
// re => read_enable
// cpt => counter for number of bits sent
// sending_data => '1' when bits are sent (RTC or memory)
always @(posedge clk or posedge reset) begin
	if(reset) begin
		re <= 0;
		cpt <= 0;
		idx <= 0;
		sending_data <= 0;
		 read_bank <= 0;
	end
	else begin
	case (state_reg)
		s0 : begin //wait for a emission
			re <= 0;
			cpt <= 0;
			idx <= 0;
			sending_data <= 0;
		end
		s1 : begin //load of RTC
			
			cpt <= 0;
			idx <= 0;
			sending_data <= 1;
		end
		s2 : begin //shift of RTC
			idx <= 0;
			cpt <= cpt + 1;//counter increment
			
			if(cpt == 5'b11101) begin //all bits of RTC have been sent => enable reading of memories
				re <= 1; 
			end
			
		end
		s3 : begin //load of memory data (in case of reading full memory)
			cpt <= 0;
			sending_data <= 1;
			
			idx <= idx + 1; //reading address increment
			if(idx == 199 && cpt == 2) begin // if the memory has been completely read => disable reading
				re <= 0;
			end
			else begin
				re <= 1;
			end
			
		end	
		s4 : begin //shift of memory data (in case of reading full memory)
			cpt <= cpt + 1; //counter increment
			
			if(idx == 200 && cpt == 1) begin //reset of idx counter when memory has been completely read 
				idx <= 0;
			end
			
			if(state_next == s5) begin
				read_bank <= ~read_bank;
			end
			
			// if memory has been completely read => disable reading
			if((idx==200 && sending_pending == 1 && cpt == 0) || (idx==200 && sending_pending == 0)) begin
				re <= 0;
			end
			else begin
				re <= 1;
			end
			
		end
		s5 : begin //waiting for sending next bank
			cpt <= 0;
			idx <= 0;
			sending_data <= 0;
			
			//memorization ended => enable reading
			if(bank0_full == 1 || bank1_full == 1 || sending_pending) begin
				re <= 1;
			end
			else begin
				re <= 0;
			end
			
		end 
		s6 : begin //load of memory data (in case of reading part of memory)
			cpt <= 0;
			idx <= idx + 1; //reading address increment
			sending_data <= 1;
		end
		s7 : begin//shift of memory data (in case of reading part of memory)
			cpt <= cpt + 1; //counter increment
			
			if(state_next == s0) begin
				read_bank <= ~read_bank;
			end
			
			//reset idx counter when the reading address reaches the final address
			if(idx == reg_idx_final  && cpt == 2) begin
				idx <= 0;
				sending_data <= 0;
				
			end
			
			if(idx == reg_idx_final) begin //when reaching final address => disable reading
				re <= 0;
			end
			
		end
		 endcase
	end                                                                              
end


// asynchronous process, when a memorization end => register final address
always @(posedge memorization_completed or posedge reset) begin

	if(reset) begin   
		reg_idx_final <= 0; 
	end
	else begin
		reg_idx_final <= idx_final;						
	end                                                                   
end
 
// sequential outputs which do not depend on the state
// signal_duration => when '1', a bank has been completely filled (AE last longer than 200 us)
// sending_pending => '1' when the acquisition ended but readout is still in progress 
always @(posedge clk or posedge reset) begin

	if(reset) begin
		signal_duration <= 0; 
      sending_pending <= 0;  
	end
	else begin
		if(sending_started) begin
			sending_pending <= 0;
		end
		else if(memorization_completed) begin
			sending_pending <= 1; 
			signal_duration <= 0; //short signal
		end
		else if(bank0_full || bank1_full) begin
			signal_duration <= 1; //long signal	
		end
	end                                                                   
end
/*
//asynchonous process for changing bank, when a sending starts => changing the bank to read into
always @(posedge sending_started or posedge reset) begin
	if(reset) begin
      read_bank <= 1;  
	end
	else begin
		read_bank <= ~read_bank;
	end
end
*/

//combinatory outputs of the state machine
//sending_started => pulse when we start to read memory 
//serial_readout => '1' when datas of an AE are sent
always @(*) begin 

	//Default
   state_next = state_reg;
	SL_ch = 0;
	SL_time = 0;
	selection_bit = 0;
	serial_readout = 0;
	sending_started = 0;

        case (state_reg)
            s0 : begin
					SL_ch = 0;
					SL_time = 0;
					selection_bit = 0;
					serial_readout = 0;
					sending_started = 0;

					//a acquisition ended => start sate machine
					if (sending_pending == 1 || bank0_full== 1 || bank1_full== 1) begin 
                    	state_next = s1;
					end
					else begin
                    	state_next = s0;
					end	
					
				end
				
            s1: begin//load of RTC

					SL_ch = 0;
					SL_time = 1;
					serial_readout = 0;
					selection_bit = 0;
					sending_started = 0;
					state_next = s2;

				end	  
				
            s2: begin //shift of RTC

					serial_readout = 1;
					SL_ch = 0;
					SL_time = 0;
					selection_bit = 0;
					
					//when all the bits of RTC have been sent => sending of memory
					if (cpt == 5'b11110) begin    
						sending_started = 1;
						if(signal_duration) begin	
							state_next = s3; //full memory must be read
						end
						else begin
							state_next = s6; //part of memory must be read
						end
					end
					else begin
						sending_started = 0;
                  state_next = s2;
					end
				end
            s3: begin //load of memory data (in case of reading full memory)

					selection_bit = 1;
					serial_readout = 1;
					SL_ch = 1;
					SL_time = 0;
					sending_started = 0;
               state_next = s4;

				end
				
            s4: begin//shift of channel memory (in case of reading full memory)

					selection_bit = 1;
					serial_readout = 1;
					SL_ch = 0;
					SL_time = 0;
					sending_started = 0;
	
					if (idx == 200 && cpt == 1) begin //all memory has been read => wait for next sending     
						state_next = s5;
					end
					else if (cpt == 1) begin 
						state_next = s3;
					end
					else begin
						state_next = s4;
					end
				end

            s5: begin//waiting for sending next bank
				
					selection_bit = 1;
					SL_ch = 0;
					SL_time = 0;
					serial_readout = 1;
		

					if (sending_pending == 1) begin //part of a bank must be sent  
						sending_started = 1;
						if(re == 1) begin //check that reading has been enable
							state_next = s6;	
						end
						else begin 
							state_next = s5;
						end
					end
					else if(bank0_full == 1 || bank1_full == 1) begin //full bank must be sent 
						
						if(re == 1) begin //check that reading has been enable
							sending_started = 1;
							state_next = s3;
						end
						else begin
							sending_started = 0;
							state_next = s5;
						end
				
					end
					else begin
						sending_started = 0;
						state_next = s5;
					end
				end

            s6: begin //load of channel memory (in case of reading part of memory)

					selection_bit = 1;
					SL_ch = 1;
					SL_time = 0;
					serial_readout = 1;
					sending_started = 0;
               state_next = s7;

				end

				s7: begin//shift of channel memory (in case of reading part of memory)

					selection_bit = 1;
					serial_readout = 1;
					SL_ch = 0;
					SL_time = 0;
					sending_started = 0;

					//all the datas of an AE have been sent => return to state S0
					if (idx == reg_idx_final && cpt == 2) begin 
						state_next = s0;
					end
					else if (idx != reg_idx_final && cpt == 1) begin
						state_next = s6;
					end
					else begin
						state_next = s7;
					end
				end    
        endcase
 
end


endmodule



/*
clk : clock for shif and load operations
parallel_in : output of the MUX, data to be send
SL : '1' => load, '0' => shift
serial_out : data serialization
*/

module PISO_register(
  input wire clk, reset,
  input wire [2:0] parallel_in,
  input wire SL, 
  output reg serial_out
  
);
  
reg [1:0] register;
	
always @(posedge clk or posedge reset) begin

    if(reset == 1) begin
	serial_out <= 0;
	register <= 2'b0;
    end
    else begin
    	if(SL==1) begin
	
	    register[1:0] <= parallel_in[2:1]; // Load 
	    serial_out <= parallel_in[0];  // Output the least significant bit
	       
    	end
    	else if (SL==0) begin
	
	serial_out <= register[0]; // Output the least significant bit
        register <= register >>> 1; //shift
	
    	end
    end
end

endmodule


/*
clk : clock for shif and load operations
parallel_in : output of the MUX, data to be send
SL : '1' => load, '0' => shift
serial_out : data serialization
*/

module PISO_time_register(
  input wire clk, reset,
  input wire [31:0] parallel_in,
  input wire SL, 
  output reg serial_out
  
);
  
reg [30:0] register;
	
always @(posedge clk or posedge reset) begin

    if(reset == 1) begin
	serial_out <= 0;
	register <= 31'b0;
    end
    else begin 
    	if(SL==1) begin
	
	    register[30:0] <= parallel_in[31:1]; // Load 
	    serial_out <= parallel_in[0];  // Output the least significant bit
	       
    	end
    	else if (SL==0) begin
	
	serial_out <= register[0]; // Output the least significant bit
        register <= register >>> 1; //shift
	
    	end
    end
end

endmodule


module RTC(input clk, input reset, output reg [5:0] sec, output reg [9:0] millisec,
               output reg [5:0] min, output reg [4:0] hour, output reg [4:0] day);



//-- Sensitive to rising edge
  always @(posedge clk or posedge reset) begin
  //-- Incrementar el registro
    if(reset == 1) begin
  	millisec <= 10'b0;
  	sec <= 6'b0;
  	min <= 6'b0;
  	hour <= 5'b0;
  	day <= 5'b0;
    end
    else begin

    	millisec <= millisec + 1;
    	if(millisec == 999) begin
    		millisec <= 0;
      		sec <= sec + 1;
    	end
    	if(sec == 59 && millisec == 999) begin
		millisec <= 0;
    		sec <= 0;
      		min <= min + 1;
    	end
    	if(sec == 59 & min == 59 && millisec == 999) begin
		millisec <= 0;
      		sec <= 6'b0;
  		min <= 6'b0;
		hour <= hour + 1;
    	end
    	if(hour == 23 && sec == 59 & min == 59 && millisec == 999) begin
		millisec <= 0;
      		sec <= 6'b0;
  		min <= 6'b0;
		hour <= 5'b0;	
		day <= day + 1;
    	end
    	if(day == 30 && hour == 23 && sec == 59 & min == 59 && millisec == 999) begin
		millisec <= 0;
      		sec <= 6'b0;
  		min <= 6'b0;
		hour <= 5'b0;	
		day <= 0;
    	end
	
     end
  end
  
  
endmodule


module mux_2to1(input wire PISO_time, PISO_ch1,
                input wire select,
           output reg data_out
          );


  always @(*) begin
  data_out = 0;
    casez (select)  
      0 : data_out = PISO_time; 
      1 : data_out = PISO_ch1; 

     endcase  
   end  
  
endmodule 


module time_register(input clk, reset, input [31:0] event_time, output reg [31:0] event_time_out );

  always @(posedge clk or posedge reset) begin
	if(reset == 1) begin
		event_time_out <= 32'b0;
	end
	else begin
		event_time_out <= event_time;
	end
  end 

endmodule 


module encoder( input wire [6:0] channel,
           output reg [2:0] channel_decode
           );

	always @(*) begin

			if(channel[6] == 1) begin
				channel_decode = 3'b111;
			end
			else if(channel[5] == 1) begin
				channel_decode = 3'b110;
			end
			else if(channel[4] == 1) begin
				channel_decode = 3'b101;
			end
			else if(channel[3] == 1) begin
				channel_decode = 3'b100;
			end
			else if(channel[2] == 1) begin
				channel_decode = 3'b011;
			end
			else if(channel[1] == 1) begin
				channel_decode = 3'b010;
			end
			else if(channel[0] == 1) begin
				channel_decode = 3'b001;
			end
			else begin
				channel_decode = 3'b0;
			end
				
	end

endmodule


module memory(
    input wire clk_write,  
    input wire clk_read,                 
    input wire write_enable,
    input wire read_enable,           
    input wire [8:0] address_in,
    input wire [8:0] address_out,        
    input wire [2:0] data_in,       
    output reg [2:0] data_out
	 //output  [2:0] mem1_test,
	 //output  [2:0] mem2_test
);

initial begin

	data_out = 3'b0;
end
	//assign mem1_test = mem1[0];
	//assign mem2_test = mem2[0];
    // two blocs of 200 box of 8 
    reg [2:0] mem1 [199:0];
    reg [2:0] mem2 [199:0];

    // Processus de lecture/ecriture
    always @(posedge clk_write) begin
        if (write_enable) begin
		if(address_in[8] == 0) begin
      mem1[address_in[7:0]] <= data_in; // ecrire dans la memoire
		end
		else if(address_in[8] == 1) begin
			mem2[address_in[7:0]] <= data_in;
		end
        end
    end

    always @(posedge clk_read) begin
	if (read_enable) begin
		if(address_out[8] == 0) begin
      data_out <= mem1[address_out[7:0]]; // Lire de la memoire
		end
		else if(address_out[8] == 1) begin
      data_out <= mem2[address_out[7:0]]; // Lire de la memoire
		end

        end
    end
endmodule


module memory_controller(
    input clk, reset, signal_detected,               
    output reg [7:0] idx_final,
	 output  [8:0] addr_in,
	 output reg [1:0] state_reg,
    output reg we, bank0_full, bank1_full, memorization_completed   
);
// >>> Module Implementation Begin

// <<< Module Implementation End
endmodule

 


module top(
    	input input_acquisition_clk, input_serial_readout_clk, RTC_clk, 	reset,
	 input wire [6:0] ch1, ch2, 
	 output wire [1:0] serial_out,	 
	 output SL_ch, SL_time, serial_readout, signal_detected, memorization_completed,sending_data  

);

	wire [8:0] addr_in;
	wire [8:0] addr_out;
	wire [2:0] data_decode [1:0];
	wire [2:0] data_sent [1:0];
	//wire signal_detected;
	wire acquisition_clk_enable;
	wire serial_readout_clk_enable;
	wire acquisition_clk;
	wire serial_readout_clk;
	wire we, bank0_full, bank1_full, selection_bit, re, PISO_ch1, PISO_time;
	wire [1:0] state_reg_memctr;
	wire [2:0] state_reg_FSM;
	//wire memorization_completed;


wire [7:0] idx_final;


memory_controller mem_ctl(.clk(acquisition_clk), .reset(reset), .signal_detected(signal_detected), .addr_in(addr_in[8:0]), .idx_final(idx_final[7:0]), .we(we), .bank0_full(bank0_full), .bank1_full(bank1_full),
				.memorization_completed(memorization_completed), .state_reg(state_reg_memctr[1:0]));

FSM fsm(.clk(serial_readout_clk),.reset(reset), .bank0_full(bank0_full), .bank1_full(bank1_full), .memorization_completed(memorization_completed), .idx_final(idx_final[7:0]),
		.addr_out(addr_out[8:0]), .SL_ch(SL_ch), .SL_time(SL_time), .selection_bit(selection_bit), 
	.re(re), .serial_readout(serial_readout), .sending_data(sending_data), .state_reg(state_reg_FSM));

		
	//signal detector
	assign signal_detected = ch1[0] || ch2[0];
	
	//clk _activators
	assign acquisition_clk_enable = memorization_completed || signal_detected || we || (state_reg_memctr != 0) ;
	assign serial_readout_clk_enable = memorization_completed || serial_readout || acquisition_clk_enable || (state_reg_FSM != 0) ;
	assign acquisition_clk = acquisition_clk_enable && input_acquisition_clk; 
	assign serial_readout_clk = serial_readout_clk_enable && input_serial_readout_clk;
	
	
	//encode data
	encoder enc1( .channel(ch1[6:0]), .channel_decode(data_decode[0][2:0]));
	encoder enc2( .channel(ch2[6:0]), .channel_decode(data_decode[1][2:0]));

	
	memory memory1(.clk_write(acquisition_clk),.clk_read(serial_readout_clk),.write_enable(we), .address_in(addr_in[8:0]), .data_in(data_decode[0][2:0]), .read_enable(re), .address_out(addr_out[8:0]), .data_out(data_sent[0][2:0]));
  	memory memory2(.clk_write(acquisition_clk),.clk_read(serial_readout_clk),.write_enable(we), .address_in(addr_in[8:0]), .data_in(data_decode[1][2:0]), .read_enable(re), .address_out(addr_out[8:0]), .data_out(data_sent[1][2:0]));

	PISO_register reg1(.clk(serial_readout_clk), .reset(reset), .SL(SL_ch), .parallel_in(data_sent[0][2:0]), .serial_out(PISO_ch1));
	PISO_register reg2(.clk(serial_readout_clk),.reset(reset), .SL(SL_ch), .parallel_in(data_sent[1][2:0]), .serial_out(serial_out[1]));


	mux_2to1 mux(.PISO_ch1(PISO_ch1), .PISO_time(PISO_time), .select(selection_bit), .data_out(serial_out[0]));

	wire [31:0] event_time;
	wire [31:0] event_time_out;
	RTC rtc(.clk(RTC_clk), .reset(reset), .sec(event_time[15:10]), .millisec(event_time[9:0]),
               .min(event_time[21:16]), .hour(event_time[26:22]), .day(event_time[31:27]));
	time_register time_reg(.clk(signal_detected), .reset(reset), .event_time(event_time[31:0]),.event_time_out(event_time_out[31:0]));
	PISO_time_register piso_time_reg(.clk(serial_readout_clk),.reset(reset), .SL(SL_time), .parallel_in(event_time_out[31:0]), .serial_out(PISO_time));


endmodule 


/*
 * Copyright (c) 2024 Your Name
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_Coline3003_spect_top(
    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,      // will go high when the design is enabled
    input  wire       clk,      // clock
    input  wire       rst_n     // reset_n - low to reset
                              );

   wire reset;
   assign reset = ~rst_n;

    top top1(.reset(reset), 
	     .input_acquisition_clk(clk), 
	     .RTC_clk(ui_in[7]), 
	     .input_serial_readout_clk(uio_in[7]), 
	     .ch1({ui_in[6],ui_in[5],ui_in[4],ui_in[3],ui_in[2],ui_in[1],ui_in[0]}), 
	     .ch2({uio_in[6],uio_in[5],uio_in[4],uio_in[3],uio_in[2],uio_in[1],uio_in[0]}), 
	     .serial_out({uo_out[1],uo_out[0]}), 
	     .SL_time(uo_out[2]), 
	     .SL_ch(uo_out[3]), 
	     .signal_detected(uo_out[4]), 
             .memorization_completed(uo_out[5]), 
	     .serial_readout(uo_out[6]), 
	     .sending_data(uo_out[7]));
	
    assign uio_out = 8'b0;
    assign uio_oe = 8'b0; //inputs enable

  // List all unused inputs to prevent warnings
  wire _unused = &{ena, clk, rst_n, 1'b0};

endmodule


Reference solution:
rtl/generated.v: 

  localparam [1:0]
  s0 = 0,
  s1 = 1,
  s2 = 2;

  reg [1:0]  state_next;
  reg [7:0] idx;
  reg bank;
  assign addr_in[7:0] = idx[7:0];
  assign addr_in[8] = bank;

  // changing state process
always @(posedge clk or posedge reset) begin
	if (reset) begin
		state_reg <= s0;
   end 
	else begin        
        state_reg <=  state_next; 
    end
end

// synchronous outputs
always @(posedge clk or posedge reset) begin
		if(reset) begin
			idx <= 0;
			bank <= 0;
			bank0_full <= 0;
			bank1_full <= 0;
			idx_final <= 0;
			
		end
		else begin
      	if (state_reg == s0) begin 
       		idx <= 0;
				bank0_full <= 0;
				bank1_full <= 0;
      	end  
			else if (state_reg == s2) begin 
       		idx <= 0;
				bank0_full <= 0;
				bank1_full <= 0;
				bank <= ~bank; //changing bank
      	end 
			else if(state_reg == s1 && idx == 199) begin //bank full
				idx <= 0;
				bank <= ~bank; //changing bank
				if(bank == 0) begin
					bank0_full <= 1;
				end
				else begin //bank == 1
					bank1_full <= 1;
				end
			end
			else begin //state_reg == s1 && idx != 199
				idx <= idx + 1;
				if(!signal_detected) begin //if no more signal => register idx_final
					idx_final <= idx;
				end
				bank0_full <= 0;
				bank1_full <= 0;
      	end     
		end
end

// combinatory outputs 			
always @(state_reg, signal_detected, idx, bank) begin
	
	//default state_next
	state_next = state_reg;
	//default outputs
	we = 0;
	memorization_completed = 0;
	

        case (state_reg)

            s0 : begin	
		we = 0;
		memorization_completed = 0;   

		if(signal_detected ) begin
				state_next  = s1;
		end
			
		end	

            s1: begin

		we = 1;
		memorization_completed = 0;
		
		
		
		if(!signal_detected) begin //no more signal => stop memorization
			state_next = s2;
		end
		else begin
			state_next = s1;
		end

	     end	                    


            s2: begin 
		memorization_completed = 1;
		we = 0;
		state_next = s0;
	
	     end


        endcase
   
end