module 	bgm(clock, 
		reset,
		sigma_a, 
		sigma_b, 
		sigma_c,
		Fn,
		dw_x,
		dw_y,
		dw_z,
		dt,
		Fn_out 
);

// SIGNAL DECLARATIONS
input	clock;
input 	reset;

input [`BITS-1:0] sigma_a;
input [`BITS-1:0] sigma_b;
input [`BITS-1:0] sigma_c;
input [`BITS-1:0] Fn;
input [`BITS-1:0] dw_x;
input [`BITS-1:0] dw_y;
input [`BITS-1:0] dw_z;
input [`BITS-1:0] dt;

output [`BITS-1:0] Fn_out;

wire [`BITS-1:0]	x0;
wire [`BITS-1:0]	x1;
wire [`BITS-1:0]	x2;
wire [`BITS-1:0]	x3;
wire [`BITS-1:0]	x4;
wire [`BITS-1:0]	x5;
wire [`BITS-1:0]	x6;
wire [`BITS-1:0]	x7;
wire [`BITS-1:0]	x8;
wire [`BITS-1:0]	x9;
wire [`BITS-1:0]	x10;

wire [`BITS-1:0]	a0;
wire [`BITS-1:0]	a1;
wire [`BITS-1:0]	a2;
wire [`BITS-1:0]	a3;
wire [`BITS-1:0]	a4;
wire [`BITS-1:0]	a5;
wire [`BITS-1:0]	a6;
wire [`BITS-1:0]	a7;
wire [`BITS-1:0]	a8;

wire [`BITS-1:0] Fn_out;
wire [`BITS-1:0] Fn_delay_chain;
wire [`BITS-1:0] Fn_delay_chain_delay5;

wire [`BITS-1:0] dw_x_delay;
wire [`BITS-1:0] dw_y_delay;
wire [`BITS-1:0] dw_z_delay;
wire [`BITS-1:0] sigma_a_delay;
wire [`BITS-1:0] sigma_b_delay;
wire [`BITS-1:0] sigma_c_delay;

wire [`BITS-1:0] fifo_out1;
wire [`BITS-1:0] fifo_out2;
wire [`BITS-1:0] fifo_out3;

wire [`BITS-1:0] a4_delay5;
/*
delay44 delay_u1(clock, dw_x, dw_x_delay);
delay44 delay_u2(clock, dw_y, dw_y_delay);
delay44 delay_u3(clock, dw_z, dw_z_delay);
delay44 delay_u4(clock, sigma_a, sigma_a_delay);
delay44 delay_u5(clock, sigma_b, sigma_b_delay);
delay44 delay_u6(clock, sigma_c, sigma_c_delay);

fifo fifo_1(clock, a0, fifo_out1);
fifo fifo_2(clock, a1, fifo_out2);
fifo fifo_3(clock, a2, fifo_out3);
*/

delay5 delay_u1(clock, dw_x, dw_x_delay);
delay5 delay_u2(clock, dw_y, dw_y_delay);
delay5 delay_u3(clock, dw_z, dw_z_delay);
delay5 delay_u4(clock, sigma_a, sigma_a_delay);
delay5 delay_u5(clock, sigma_b, sigma_b_delay);
delay5 delay_u6(clock, sigma_c, sigma_c_delay);

delay5 fifo_1(clock, a0, fifo_out1);
delay5 fifo_2(clock, a1, fifo_out2);
delay5 fifo_3(clock, a2, fifo_out3);



//assign x0 = Fn * sigma_a;
wire [7:0] x0_control;
fpu_mul x0_mul
( 
	.clk(clock), 
	.opa(Fn), 
	.opb(sigma_a), 
	.out(x0), 
	.control(x0_control) 
);

//assign x1 = Fn * sigma_b;
wire [7:0] x1_control;
fpu_mul x1_mul
( 
	.clk(clock), 
	.opa(Fn), 
	.opb(sigma_b), 
	.out(x1), 
	.control(x1_control) 
);


//assign x2 = Fn * sigma_c;
wire [7:0] x2_control;
fpu_mul x2_mul
( 
	.clk(clock), 
	.opa(Fn), 
	.opb(sigma_c), 
	.out(x2), 
	.control(x2_control) 
);

//assign a0 = x0 + fifo_out1;
wire [7:0] a0_control;
fpu_add a0_add
( 
	.clk(clock), 
	.opa(x0), 
	.opb(fifo_out1), 
	.out(a0), 
	.control(a0_control) 
);


//assign a1 = x1 + fifo_out2;
wire [7:0] a1_control;
fpu_add a1_add
( 
	.clk(clock), 
	.opa(x1), 
	.opb(fifo_out2), 
	.out(a1), 
	.control(a1_control) 
);

//assign a2 = x2 + fifo_out3;
wire [7:0] a2_control;
fpu_add a2_add
( 
	.clk(clock), 
	.opa(x2), 
	.opb(fifo_out3), 
	.out(a2), 
	.control(a2_control) 
);

//assign x3 = dw_x_delay * sigma_a_delay;
wire [7:0] x3_control;
fpu_mul x3_mul
( 
	.clk(clock), 
	.opa(dw_x_delay), 
	.opb(sigma_a_delay), 
	.out(x3), 
	.control(x3_control) 
);


//assign x4 = a0 * sigma_a_delay;
wire [7:0] x4_control;
fpu_mul x4_mul
( 
	.clk(clock), 
	.opa(a0), 
	.opb(sigma_a_delay), 
	.out(x4), 
	.control(x4_control) 
);


//assign x5 = dw_y_delay * sigma_b_delay;
wire [7:0] x5_control;
fpu_mul x5_mul
( 
	.clk(clock), 
	.opa(dw_y_delay), 
	.opb(sigma_b_delay), 
	.out(x5), 
	.control(x5_control) 
);

//assign x6 = a1 * sigma_b_delay;
wire [7:0] x6_control;
fpu_mul x6_mul
( 
	.clk(clock), 
	.opa(a1), 
	.opb(sigma_b_delay), 
	.out(x6), 
	.control(x6_control) 
);

//assign x7 = dw_z_delay * sigma_c_delay;
wire [7:0] x7_control;
fpu_mul x7_mul
( 
	.clk(clock), 
	.opa(dw_z_delay), 
	.opb(sigma_c_delay), 
	.out(x7), 
	.control(x7_control) 
);

//assign x8 = a2 * sigma_c_delay;
wire [7:0] x8_control;
fpu_mul x8_mul
( 
	.clk(clock), 
	.opa(a2), 
	.opb(sigma_c_delay), 
	.out(x8), 
	.control(x8_control) 
);

//assign a3 = x3 + x5;
wire [7:0] a3_control;
fpu_add a3_add
( 
	.clk(clock), 
	.opa(x3), 
	.opb(x5), 
	.out(a3), 
	.control(a3_control) 
);

//assign a4 = a3 + x7;
wire [7:0] a4_control;
fpu_add a4_add
( 
	.clk(clock), 
	.opa(a3), 
	.opb(x7), 
	.out(a4), 
	.control(a4_control) 
);


//assign a5 = x4 + x6;
wire [7:0] a5_control;
fpu_add a5_add
( 
	.clk(clock), 
	.opa(x4), 
	.opb(x6), 
	.out(a5), 
	.control(a5_control) 
);

//assign a6 = a5 + x8;
wire [7:0] a6_control;
fpu_add a6_add
( 
	.clk(clock), 
	.opa(a5), 
	.opb(x8), 
	.out(a6), 
	.control(a6_control) 
);

delay5 delay_a5(clock, a4, a4_delay5);

//assign x9 = dt * a6;
wire [7:0] x9_control;
fpu_mul x9_mul
( 
	.clk(clock), 
	.opa(dt), 
	.opb(a6), 
	.out(x9), 
	.control(x9_control) 
);

//assign a7 = a4_delay5 + x9;
wire [7:0] a7_control;
fpu_add a7_add
( 
	.clk(clock), 
	.opa(a4_delay5), 
	.opb(x9), 
	.out(a7), 
	.control(a7_control) 
);


//delay_chain delay_Fn(clock, Fn, Fn_delay_chain);
delay5 delay_Fn(clock, Fn, Fn_delay_chain);
delay5 delay_Fn_delay5(clock, Fn_delay_chain, Fn_delay_chain_delay5);

//assign x10 = a7 * Fn_delay_chain;
wire [7:0] x10_control;
fpu_mul x10_mul
( 
	.clk(clock), 
	.opa(a7), 
	.opb(Fn_delay_chain), 
	.out(x10), 
	.control(x10_control) 
);

//assign a8 = Fn_delay_chain_delay5 + x10;
wire [7:0] a8_control;
fpu_add a8_add
( 
	.clk(clock), 
	.opa(Fn_delay_chain_delay5), 
	.opb(x10), 
	.out(a8), 
	.control(a8_control) 
);

assign	Fn_out	= a8;


endmodule