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.

/*
Based on paper: 
R. Murillo, A. A. Del Barrio and G. Botella, "Customized Posit Adders and Multipliers using the FloPoCo Core Generator," 2020 IEEE International Symposium on Circuits and Systems (ISCAS), 2020, pp. 1-5, 
doi: 10.1109/ISCAS45731.2020.9180771.
*/
module add #(parameter N=16) (
   input wire  i_s_1,
   input wire [N-11:0]  i_sf_1,
   input wire [N-5:0] i_mant_1,
   input wire  i_nzn_1,
   input wire  i_s_2,
   input wire [N-11:0]  i_sf_2,
   input wire [N-5:0] i_mant_2,
   input wire  i_nzn_2,
   output wire o_s,
   output wire [N-10:0]o_sf,
   output wire [N-5:0] o_mant,
   output wire o_guard,
   output wire o_sticky,
   output wire o_nzn
);

 
  wire X_not_zero ;
  wire X_nar ;
  wire Y_not_zero ;
  wire Y_nar ;
  wire check_larger ;
  wire [$clog2(N)+1:0] larger_number ;
  wire [$clog2(N)+1:0] smallest_number ;
  wire [N-3:0] larger_mant ;
  wire [N-3:0] smaller_mant ;
  wire [$clog2(N)+1:0] offset;
  wire shift_saturate;
  wire [$clog2(N):0]mant_offset ;
  wire [N-1:0]input_shifter ;
  wire pad_bit;
  wire [N-1:0] shifted_mant ;
  wire stk_tmp ;
  wire [N-3:0] smaller_mant_sh;
  wire grd_tmp ;
  wire rnd_tmp ;
  wire [N-2:0]add_mant;
  wire grd_bit;
  wire rnd_bit;
  wire stk_bit;
  wire count_type;
  wire [N:0]add_mant_shift ;
  wire [$clog2(N):0]count ;
  wire [(N):0]norm_mant_tmp;
  wire [N-10:0]add_sf ;
  wire is_not_zero ;
  wire is_nar;
  wire Xi_nzn_2;

  assign X_not_zero = i_s_1 | i_nzn_1;
  assign X_nar      = i_s_1 & ~(i_nzn_1);
  assign Y_not_zero = i_s_2 | i_nzn_2;
  assign Y_nar      = i_s_2 & ~(i_nzn_2);

  assign check_larger    = (($signed(i_sf_1))>($signed(i_sf_2))) ?  1 : 0;
  assign larger_number    = (check_larger) ? i_sf_1 : i_sf_2;
  assign smallest_number   = (check_larger) ? i_sf_2 : i_sf_1;
  assign larger_mant  = (check_larger) ? {i_s_1 , (~i_s_1 & X_not_zero) ,i_mant_1} : {i_s_2,(~i_s_2 & Y_not_zero),i_mant_2};
  assign smaller_mant = (check_larger) ? {i_s_2,(~i_s_2 & Y_not_zero),i_mant_2} :{i_s_1 , (~i_s_1 & X_not_zero) ,i_mant_1};

  assign offset         = larger_number - smallest_number;
  assign shift_saturate = (!offset[5]) ? 0 : 1;
  assign mant_offset    = (shift_saturate) ? 16 : offset[4:0];

  assign input_shifter = {smaller_mant, 2'b00};

  assign pad_bit = smaller_mant[N-3];
  right_shifter_sticky_16 #(.N(N)) inst_right_shifter_sticky_16_2
    (  .i_s     (mant_offset),
      .i_in    (input_shifter),
      .i_padbit(pad_bit),
      .o_r     (shifted_mant),
      .o_sticky(stk_tmp)
    );
  assign smaller_mant_sh = shifted_mant[15:2];
  assign grd_tmp         = shifted_mant[1];
  assign rnd_tmp         = shifted_mant[0];



  assign add_mant = {larger_mant[13], larger_mant} + {smaller_mant_sh[13], smaller_mant_sh};
  assign grd_bit  = grd_tmp;
  assign rnd_bit  = rnd_tmp;
  assign stk_bit  = stk_tmp;

  assign count_type     = add_mant[14];
  assign add_mant_shift = {add_mant[13:0], grd_bit , rnd_bit , stk_bit};

  normalizer_16 #(.N(N)) inst_normalizer_16
    ( .i_ozb  (count_type),
      .i_in   (add_mant_shift),
      .o_count(count),
      .o_r  (norm_mant_tmp)
    );

  assign add_sf = {larger_number[5] , larger_number} - ({2'b00 , count}) + 1;

  assign is_not_zero = (count==5'b11111) ? count_type : 1;
  assign is_nar      = X_nar | Y_nar;
  assign Xi_nzn_2      = is_not_zero & ~(is_nar);
  assign o_s        = is_nar | (is_not_zero & add_mant[14]);
  assign o_mant   = norm_mant_tmp[N-1:4];
  assign o_guard         = norm_mant_tmp[3];
  assign o_sticky         = norm_mant_tmp[2] | norm_mant_tmp[1] | norm_mant_tmp[0];
  assign o_sf =  add_sf;
  assign o_nzn = Xi_nzn_2;


endmodule


/*
Based on paper: 
R. Murillo, A. A. Del Barrio and G. Botella, "Customized Posit Adders and Multipliers using the FloPoCo Core Generator," 2020 IEEE International Symposium on Circuits and Systems (ISCAS), 2020, pp. 1-5, 
doi: 10.1109/ISCAS45731.2020.9180771.
*/


module data_posit_encoder #( parameter N=16) (
  input wire i_s ,
  input wire [N-10:0]i_sf ,
  input wire [N-5:0]i_mant ,
  input wire i_guard ,
  input wire i_sticky ,
  input wire i_nzn ,
  output wire [N-1:0] o_r
);

  wire rc ;
  wire [$clog2(N):0]rcVect;
  wire [$clog2(N):0] k ;
  wire sgnVect ;
  wire exp ;
  wire ovf ;
  wire [$clog2(N)-1:0] regValue;
  wire regNeg ;
  wire padBit ;
  wire [N-2:0]inputShifter ;
  wire [N-2:0]shiftedPosit ;
  wire stkBit ;
  wire [N-2:0] unroundedPosit ;
  wire lsb ;
  wire rnd ;
  wire stk ;
  wire round;
  wire [N-2:0]roundedPosit ;
  wire [N-2:0]unsignedPosit ;


  assign rc      = i_sf[N-10];
  assign rcVect  = {5{rc}};
  assign k       =  i_sf[5:1] ^ rcVect;
  assign sgnVect = i_s;
  assign exp = i_sf[0] ^ sgnVect;

  assign ovf      = (k>13) ? 1 :0;
  assign regValue = (!ovf) ? k[3:0] : 4'b1110;

  assign regNeg       = i_s ^ rc;
  assign padBit       = ~(regNeg);
  assign inputShifter = {regNeg, exp , i_mant, i_guard};
  right_shifter_sticky_18 #(.N(N))  inst_right_shifter_sticky_18
    ( .i_s(regValue),
      .i_in(inputShifter),
      .i_padbit(padBit),
      .o_r     (shiftedPosit),
      .o_sticky(stkBit)
    );
  
  assign unroundedPosit = {padBit, shiftedPosit[N-2:1]};

  assign lsb = shiftedPosit[1];
  assign rnd = shiftedPosit[0];
  assign stk = stkBit | i_sticky;
  assign round = rnd & (lsb | stk | ovf);
  assign roundedPosit = unroundedPosit + {14'd0,round};
  
  assign unsignedPosit = (i_nzn) ? roundedPosit : 0;
  assign o_r = { i_s  ,unsignedPosit};



endmodule



module Fixed16toPosit16(
    input [15:0]    fixed_number_input,
    output [3:0]    regime_value,
    output          exponent,
    output wire [11:0]   mantissa,
    output          Q,
    output          sign
    );
wire [15:0] fixed_number,fixed_numberaux, fixed_number_neg;

// 2's complement to extract value and sign of the fixed point input
assign fixed_numberaux = {(16){fixed_number_input[15]}} ;
assign fixed_number_neg = fixed_number_input ^ fixed_numberaux ;
assign fixed_number = fixed_number_neg + {15'b000000000000000, fixed_number_input[15]};
assign sign =  fixed_number_input[15];
reg [11:0] mantissa_compl;
wire [3:0] xaux,x;
wire [2:0] xaux2;
wire first_regime_bit;
//
//  zlc value       regime value
//      1,2     ->      2
//      3,4     ->      3
//      5,6     ->      4
//      7,8     ->      5
//      9,10    ->      6
//      11,12   ->      7
//      13,14   ->      8
//      15      ->      9
//  
//  regime value -  2   =   {y2,y1,y0}
//
//  x3  x2  x1  x0  |   y2  y1  y0
//  0   0   0   0   |   0   0   0
//  0   0   0   1   |   0   0   0
//  0   0   1   0   |   0   0   1
//  0   0   1   1   |   0   0   1
//  0   1   0   0   |   0   1   0
//  0   1   0   1   |   0   1   0
//  0   1   1   0   |   0   1   1
//  0   1   1   1   |   0   1   1
//  1   0   0   0   |   1   0   0
//  1   0   0   1   |   1   0   0
//  1   0   1   0   |   1   0   1
//  1   0   1   1   |   1   0   1
//  1   1   0   0   |   1   1   0
//  1   1   0   1   |   1   1   0
//  1   1   1   0   |   1   1   1
//  1   1   1   1   |   1   1   1
//

LeadingZeroCounter_16b LeadingZeroCounter_16b(
    .x(fixed_number),
    .count(x),
    .Q(Q)
    );
    
assign xaux = (sign & first_regime_bit)? x : x-1;
assign xaux2 = ~(xaux[3:1]);
assign regime_value = {1'b1,xaux2};
assign exponent = (first_regime_bit ) ? ~x[0]:x[0];
assign first_regime_bit = (fixed_number_input[14]==0 && sign==1) ? 1 : 0;
assign mantissa = (first_regime_bit) ? -mantissa_compl : mantissa_compl;
always @(*)
case (x)
      4'b0001: begin
                  mantissa_compl = fixed_number [13:2];  //
               end
      4'b0010: begin
                  mantissa_compl = fixed_number [12:1];  //
               end
      4'b0011: begin
                  mantissa_compl = fixed_number [11:0];  //
               end
      4'b0100: begin
                  mantissa_compl = {fixed_number [10:0],1'b0};  //
               end
      4'b0101: begin
                  mantissa_compl = {fixed_number [9:0],2'b00};  //
               end
      4'b0110: begin
                  mantissa_compl = {fixed_number [8:0],3'b000};  //
               end
      4'b0111: begin
                  mantissa_compl = {fixed_number [7:0],4'b0000};  //
               end
      4'b1000: begin
                  mantissa_compl = {fixed_number [6:0],5'b00000};  //
               end
      4'b1001: begin
                  mantissa_compl = {fixed_number [5:0],6'b000000};  //
               end
      4'b1010: begin
                  mantissa_compl = {fixed_number [4:0],7'b0000000};  //
               end
      4'b1011: begin
                  mantissa_compl = {fixed_number [3:0],8'b00000000};  //
               end
      4'b1100: begin
                  mantissa_compl = {fixed_number [2:0],9'b000000000};  //
               end
      4'b1101: begin
                  mantissa_compl = {fixed_number [1:0],10'b0000000000};  //
               end
      4'b1110: begin
                  mantissa_compl = {fixed_number [0],11'b00000000000};  //
                end
      default: begin
                  mantissa_compl = {12'b00000000000};  //
                end
   endcase
				
endmodule



module LeadingZeroCounter_16b(
    input  wire [15:0] x,
    output wire [3:0] count,
    output wire Q
    );

wire [3:0] auxa;
wire [7:0] auxz;
wire [1:0] auxcount;

genvar k;
generate
  for (k=0; k < 4; k=k+1)
  begin: NLC_generation
     NLC_16b NLC (.x(x[15-4*k : 12-4*k]),
              .a(auxa[k]),
              .z(auxz[2*k+1 : 2*k])
              );
  end
endgenerate

BNE_16b BNEncoder (.a(auxa), 
               .Q(Q),
               .y(auxcount[1 : 0]));

assign count[3 : 2] = auxcount;

Mux_LZC_16b Mux (.i0(auxz[1:0]), 
             .i1(auxz[3:2]), 
             .i2(auxz[5:4]), 
             .i3(auxz[7:6]), 
             .s(auxcount),
             .o(count[1 : 0])
             );

endmodule


module BNE_16b(
    input  wire [3:0] a,    
    output  wire  Q,    
    output  wire [1:0] y    
    );
// >>> Module Implementation Begin

// <<< Module Implementation End
endmodule



module NLC_16b (
    input  wire [3:0] x,    // Dedicated inputs 
    output  wire  a,    // Dedicated inputs 
    output  wire [1:0] z    // Dedicated inputs 
    );

wire aprimo,z1,z0,aux1;
assign aprimo = x[3] | x[2] | x[1] | x[0];
assign a = ! aprimo;
assign z1 = x[3] | x[2];
assign z[1] = ! z1; 
assign z0 = aux1 | x[3];
assign aux1 = x[1] & ! (x[2]);
assign z[0] = ! z0;

endmodule 

module Mux_LZC_16b(
    input wire [1:0] i0 ,
    input wire [1:0] i1  ,
    input wire [1:0] i2  ,
    input wire [1:0] i3  ,
    input wire [1:0]  s  ,
    output reg [1:0] o  
    );

always @(*)
  case (s)
     2'b00: o = i0;
     2'b01: o = i1;
     2'b10: o = i2;
     2'b11: o = i3;

  endcase
      
endmodule


/*
Based on paper: 
R. Murillo, A. A. Del Barrio and G. Botella, "Customized Posit Adders and Multipliers using the FloPoCo Core Generator," 2020 IEEE International Symposium on Circuits and Systems (ISCAS), 2020, pp. 1-5, 
doi: 10.1109/ISCAS45731.2020.9180771.
*/

module normalizer_16 #(parameter N=16) (
	input wire [N:0] i_in,
	input wire i_ozb,
	output wire [$clog2(N):0]o_count,
	output wire [N:0] o_r
);

	wire [N:0] level5 ;
	wire [N:0] level4 ;
	wire count4;
	wire sozb ;
	wire count3 ;
	wire [N:0] level3 ;
	wire count2 ;
	wire [N:0]level2 ;
	wire count1;
	wire [N:0]level1 ;
	wire count0;
	wire [N:0]level0;
	wire [$clog2(N):0]sCount ;

	assign level5 = i_in;
	assign sozb = i_ozb;

	assign count4 = (level5[N:1] == {16{sozb}}) ? 1: 0;
	assign level4 =(!count4) ? level5 : {level5[0],{16{1'b0}}};

	assign count3 = (level4[N:N-7] == {8{sozb}}) ? 1: 0;
	assign level3 = (!count3) ? level4 : {level4[8:0],{8{1'b0}}};

	assign count2 = (level3[N : N-3] == {4{sozb}})? 1 : 0;

	assign level2 = (!count2) ? level3  : {level3[12:0],{4{1'b0}}};
	assign count1 = level2[N:N-1]=={sozb,sozb} ?  1 : 0;

	assign level1 = (!count1) ? level2 : {level2[14:0], 2'b00};

	assign count0 = (level1[N]==sozb) ? 1 : 0;
	assign level0 = (!count0) ? level1 : {level1[15:0],1'b0};

	assign o_r    = level0;
	assign sCount = {count4,count3,count2,count1,count0};
	assign o_count  = sCount;

endmodule 


module posit_top_open_hw #(parameter  N=16) (
  input wire [N-1:0] i_in_1,
  input wire [N-1:0] i_in_2,
  output wire [5:0] o_sign_regime_exp_1,
  output wire [5:0] o_sign_regime_exp_2,
  output wire [N-5:0] o_mantissa_1,
  output wire [N-5:0] o_mantissa_2,
  output wire [N-1:0] o_res
);
  
  wire [$clog2(N)+1:0]w_sf_1;
  wire [N-5:0] w_mant_1;

  wire [$clog2(N)+1:0]w_sf_2;
  wire [N-5:0] w_mant_2;

  wire [N-10:0]w_sf_res_add;
  wire [N-5:0]w_mant_res_add;
  wire w_guard_res_add;
  wire w_sticky_res_add;
  wire w_nzn_res_add;
  wire w_Q_1;
  wire w_sign_1;
  wire w_exponent_1;
  wire [3:0]w_regime_value_1;
  wire w_Q_2;
  wire w_s_res_add;
  wire w_sign_2;
  wire w_exponent_2;
  wire [3:0]w_regime_value_2;

Fixed16toPosit16 instFixed16toPosit16_1(
  .fixed_number_input(i_in_1),
  .Q                 (w_Q_1),
  .sign              (w_sign_1),
  .exponent          (w_exponent_1),
  .mantissa          (w_mant_1),
  .regime_value      (w_regime_value_1)
  );

Fixed16toPosit16 instFixed16toPosit16_2(
  .fixed_number_input(i_in_2),
  .Q                 (w_Q_2),
  .sign              (w_sign_2),
  .exponent          (w_exponent_2),
  .mantissa          (w_mant_2),
  .regime_value      (w_regime_value_2)
  );

assign w_sf_1 =(!w_sign_1) ? {1'b1, w_regime_value_1,w_exponent_1}: {1'b1, w_regime_value_1,~w_exponent_1} ;
assign w_sf_2 =(!w_sign_2) ? {1'b1, w_regime_value_2,w_exponent_2}:  {1'b1, w_regime_value_2,~w_exponent_2};
assign o_sign_regime_exp_1 = (!w_sign_1) ?  {w_sign_1,w_regime_value_1,w_exponent_1} : {w_sign_1,w_regime_value_1,~w_exponent_1};
assign o_sign_regime_exp_2 = (!w_sign_2) ?  {w_sign_2,w_regime_value_2,w_exponent_2} : {w_sign_2,w_regime_value_2,~w_exponent_2};
assign o_mantissa_1 = w_mant_1;
assign o_mantissa_2 = w_mant_2;

  add #(.N(N)) inst_add(
    .i_s_1   (w_sign_1),
    .i_sf_1  (w_sf_1),
    .i_mant_1(w_mant_1),
    .i_nzn_1 (~w_Q_1),
    .i_sf_2  (w_sf_2),
    .i_mant_2(w_mant_2),
    .i_nzn_2 (~w_Q_2),
    .i_s_2   (w_sign_2),
    .o_nzn   (w_nzn_res_add),
    .o_s     (w_s_res_add),
    .o_sticky(w_sticky_res_add),
    .o_guard (w_guard_res_add),
    .o_sf    (w_sf_res_add),
    .o_mant  (w_mant_res_add)
  );

  data_posit_encoder #(.N(N)) inst_data_posit_encoder
    (  .i_mant  (w_mant_res_add),
      .i_guard (w_guard_res_add),

      .i_nzn   (w_nzn_res_add),
      .i_sf(w_sf_res_add),
      .i_s     (w_s_res_add),
      .i_sticky(w_sticky_res_add),
      .o_r     (o_res)
    );

endmodule


/*
Based on paper: 
R. Murillo, A. A. Del Barrio and G. Botella, "Customized Posit Adders and Multipliers using the FloPoCo Core Generator," 2020 IEEE International Symposium on Circuits and Systems (ISCAS), 2020, pp. 1-5, 
doi: 10.1109/ISCAS45731.2020.9180771.
*/

module right_shifter_sticky_16 #(parameter N=16) (
  input wire [N-1:0] i_in,
  input wire [$clog2(N):0] i_s,
  input wire i_padbit,
  output wire [N-1:0] o_r,
  output wire o_sticky
);


  wire [$clog2(N):0] ps;
  wire [N-1:0] Xpadded;
  wire [N-1:0] level5;
  wire stk4 ;
  wire [N-1:0] level4 ;
  wire stk3 ;
  wire [N-1:0] level3 ;
  wire stk2 ;
  wire [N-1:0] level2 ;
  wire stk1 ;
  wire [N-1:0] level1 ;
  wire stk0 ;
  wire [N-1:0] level0 ;

  assign ps      = i_s;
  assign Xpadded = i_in;
  assign level5  = Xpadded;
  assign stk4    = (level5!=0 && ps[4]==1) ?  1 : 0;
  assign level4  = (ps[4]==0) ?  level5 : {16{i_padbit}} ;
  assign stk3    = ((level4[7:0]!=0 && ps[3]==1)|| stk4==1) ? 1 : 0;
  assign level3 =  ps[3]==0 ?  level4 : {{8{i_padbit}},level4[15 : 8]};
  assign stk2 = ((level3[3:0]!=0 && ps[2]==1)|| stk3==1) ? 1 : 0;
  assign level2 =  ps[2]==0 ?  level3 : {{4{i_padbit}},level3[15 : 4]};
  assign stk1 = ((level2[1:0]!=0 && ps[1]==1)|| stk2==1) ? 1 : 0;
  assign level1 =  ps[1]==0 ?  level2 : {{2{i_padbit}},level2[15 : 2]};
  assign stk0 = ((level1[0]!=0 && ps[0]==1)|| stk1==1) ? 1 : 0;
  assign level0 =   ps[0]==0 ?  level1 : {i_padbit,level1[15 : 1]};
  assign o_r = level0;
  assign o_sticky = stk0;




endmodule


/*
Based on paper: 
R. Murillo, A. A. Del Barrio and G. Botella, "Customized Posit Adders and Multipliers using the FloPoCo Core Generator," 2020 IEEE International Symposium on Circuits and Systems (ISCAS), 2020, pp. 1-5, 
doi: 10.1109/ISCAS45731.2020.9180771.
*/

module right_shifter_sticky_18 #(parameter N=16) (
  input wire [N-2:0] i_in,
  input wire [$clog2(N)-1:0] i_s,
  input wire i_padbit,
  output wire [N-2:0] o_r,
  output wire o_sticky
);


  wire [$clog2(N)-1:0] ps;
  wire [N-2:0] Xpadded;
  wire [N-2:0] level4 ;
  wire stk3 ;
  wire [N-2:0] level3 ;
  wire stk2 ;
  wire [N-2:0] level2 ;
  wire stk1 ;
  wire [N-2:0] level1 ;
  wire stk0 ;
  wire [N-2:0] level0 ;

  assign ps      = i_s;
  assign Xpadded = i_in;
  assign level4  = Xpadded ;
  assign stk3    = ((level4[7:0]!=0 && ps[3]==1)) ? 1 : 0;
  assign level3 =  ps[3]==0 ?  level4 : {{8{i_padbit}},level4[14 : 8]};
  assign stk2 = ((level3[3:0]!=0 && ps[2]==1)|| stk3==1) ? 1 : 0;
  assign level2 =  ps[2]==0 ?  level3 : {{4{i_padbit}},level3[14 : 4]};
  assign stk1 = ((level2[1:0]!=0 && ps[1]==1)|| stk2==1) ? 1 : 0;
  assign level1 =  ps[1]==0 ?  level2 : {{2{i_padbit}},level2[14 : 2]};
  assign stk0 = ((level1[0]!=0 && ps[0]==1)|| stk1==1) ? 1 : 0;
  assign level0 =   ps[0]==0 ?  level1 : {i_padbit,level1[14 : 1]};
  assign o_r = level0;
  assign o_sticky = stk0;




endmodule


/*
* Copyright (c) 2024 Your Name
* SPDX-License-Identifier: Apache-2.0
*/
//////////////////////////////////////////////////////////////////////////////////
// Companies: (a) University of Salerno, Fisciano (SA), Italy; 
//            (b) STMicroelectronics, Napoli, Italy.
// Engineer: Andrea Fasolino (a), Gian Domenico Licciardo (a), Aldo Torino (b), Francesco Del Prete (b), Claudio Parrella (b).
// 
// Module Name: tt_um_afasolino
// 
// 
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

`default_nettype none

module tt_um_afasolino (
  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
);

// All output pins must be assigned. If not used, assign to 0.
//  assign uo_out  = ui_in + uio_in;  // Example: ou_out is the sum of ui_in and uio_in
//  assign uio_out = 0;
//  assign uio_oe  = 0;
  localparam  data_buffer_size_bit=8;
  localparam  data_posit_size_bit=16;
  localparam  buffer_size = 4;
  localparam  buffer_size_read = 12;
  reg alu_ready;
  reg [clog2(buffer_size+1)-1:0] wr_data_pointer;
  reg [clog2(buffer_size_read+1)-1:0] rd_data_pointer;
  wire data_input_valid;
  wire [data_posit_size_bit-1:0]data_input_1;
  wire [data_posit_size_bit-1:0]data_input_2;
  wire [data_posit_size_bit-1:0]o_result;
  reg [data_buffer_size_bit-1:0] input_buffer_data_1;
  reg [data_buffer_size_bit-1:0] input_buffer_data_2;
  reg [data_buffer_size_bit-1:0] input_buffer_data_3;
  reg [data_buffer_size_bit-1:0] input_buffer_data_4;
  reg data_valid_sync1;
  reg data_valid_sync2;
  reg read_data_valid_sync1;
  reg read_data_valid_sync2;
  reg read_data;
  wire read_data_valid;
  wire [5:0]w_sign_regime_exp_1;
  wire [5:0]w_sign_regime_exp_2;
  wire [11:0]w_mantissa_1;
  wire [11:0]w_mantissa_2;

  reg read_data_ready;
  reg [7:0]out_reg;
  assign data_input_valid = uio_in[0]; //Data valid on IO in 0
  assign uio_oe[0]        = 0;
  assign uio_oe[1]        = 1;
  assign data_input_1     = {input_buffer_data_2,input_buffer_data_1};
  assign data_input_2     = {input_buffer_data_4,input_buffer_data_3};
  assign uio_out[1]       = alu_ready;//alu ready on Output 1

  assign read_data_valid = uio_in[2];// Read Data valid on IO in 0
  assign uio_oe[2]       = 0;
  assign uio_out[3]      = read_data_ready;
  assign uio_oe[3]       = 1;
  assign uo_out     = out_reg;
  assign uio_oe[7:4] = 0; 
  assign uio_out[7:4]=0;
  assign uio_out[0]=0;
  assign uio_out[2]=0;
  always@(posedge clk, negedge rst_n)begin
    if(rst_n==0)begin
      data_valid_sync1<=0;
      data_valid_sync2<=0;
      read_data_valid_sync1<=0;
      read_data_valid_sync2<=0;
    end
    else begin
      data_valid_sync1<=data_input_valid;
      data_valid_sync2<=data_valid_sync1;
      read_data_valid_sync1<=read_data_valid;
      read_data_valid_sync2<=read_data_valid_sync1;
    end
  end

  always@(posedge clk, negedge rst_n)begin
    if(rst_n==0)begin
      input_buffer_data_1<=0;
      input_buffer_data_2<=0;
      input_buffer_data_3<=0;
      input_buffer_data_4<=0;
      wr_data_pointer<=0;
      rd_data_pointer<=0;
      alu_ready<=1;
      read_data<=0;
      out_reg<=0;
      read_data_ready<=0;
    end
    else begin
      if(data_valid_sync2==1 && alu_ready==1) begin
        case(wr_data_pointer)
          'd0: begin
            input_buffer_data_1<=ui_in;
            wr_data_pointer<=wr_data_pointer+1;
            alu_ready<=0;
          end
          'd1: begin
            input_buffer_data_2<=ui_in;
            wr_data_pointer<=wr_data_pointer+1;
            alu_ready<=0;
          end
          'd2: begin
            input_buffer_data_3<=ui_in;
            wr_data_pointer<=wr_data_pointer+1;
            alu_ready<=0;
          end
          'd3: begin
            input_buffer_data_4<=ui_in;
            alu_ready<=0;
            read_data<=1;
            read_data_ready<=1;
            rd_data_pointer<=0;
          end

          default:begin
            input_buffer_data_1<=0;
            input_buffer_data_2<=0;
            input_buffer_data_3<=0;
            input_buffer_data_4<=0;
            wr_data_pointer<=0;
            alu_ready<=1;
            read_data_ready<=0;
          end
        endcase
      end
      if(read_data==0)begin
        if(data_valid_sync2==0)begin
          alu_ready<=1;
        end
      end
      else begin
        if(read_data_ready)begin
          case(rd_data_pointer)
            'd0: begin
              out_reg<=data_input_1[7:0];
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd1: begin
              out_reg<=data_input_1[15:8];
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd2: begin
              out_reg<=data_input_2[7:0];
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd3: begin
              out_reg<=data_input_2[15:8];
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd4: begin
              out_reg<={2'b00,w_sign_regime_exp_1};
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd5: begin
              out_reg<={2'b00,w_sign_regime_exp_2};
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end 
            'd6: begin
              out_reg<=w_mantissa_1[7:0];
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd7: begin
              out_reg<={4'd0,w_mantissa_1[11:8]};
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end 
            'd8: begin
              out_reg<=w_mantissa_2[7:0];
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd9: begin
              out_reg<={4'd0,w_mantissa_2[11:8]};
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end                                      

            'd10: begin
              out_reg<=o_result[7:0];
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd11: begin
             out_reg<=o_result[15:8];
              if(read_data_valid_sync2==1) begin
                read_data_ready<=0;
                read_data<=0;
                alu_ready<=1;
                wr_data_pointer<=0;
              end
            end
            default:begin
              out_reg<=0;
              alu_ready<=1;
              rd_data_pointer<=0;
              read_data_ready<=0;
            end
          endcase
        end
        else if(read_data_valid_sync2==0)begin
          read_data_ready<=1;
        end
      end
    end
  end

  posit_top_open_hw inst_posit_top(
    .i_in_1(data_input_1),
    .i_in_2(data_input_2),
    .o_res(o_result),
    .o_sign_regime_exp_1(w_sign_regime_exp_1),
    .o_sign_regime_exp_2(w_sign_regime_exp_2),
    .o_mantissa_1       (w_mantissa_1),
    .o_mantissa_2       (w_mantissa_2)
  );

  function integer clog2;
    input integer value;
    begin
      value = value-1;
      for (clog2=0; value>0; clog2=clog2+1)
        value = value>>1;
    end
  endfunction

endmodule


Reference solution:
rtl/generated.v: 

 assign Q = a[0] & a[1] & a[2] & a[3];
 assign y[1] = a[0] & a[1];
 assign y[0] = a[0] & (!a[1] | a[2] );