module sobel_scharr
#(
	parameter	Y_DEPTH	= 8
)
(
	input	i_arst,
	input	i_pclk,
	
	input	[Y_DEPTH-1:0]i_pixel_11_01,
	input	[Y_DEPTH-1:0]i_pixel_00_01,
	input	[Y_DEPTH-1:0]i_pixel_01_01,
	
	
	output	[Y_DEPTH-1:0]o_pixel
);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// x -1  0 +1  y
//
//   -1  0  1 -1
//   -2  0  2  0
//   -1  0  1 +1
//
//   -1 -2 -1 -1
//    0  0  0  0
//    1  2  1 +1
//
//	PL_11_11_2P		PL_11_00_1P		PL_11_01_0P
//	PL_00_11_2P		PL_00_00_1P		PL_00_01_0P
//	PL_01_11_2P		PL_01_00_1P		PL_01_01_0P
//
//					GX_11_11_3P		GX_11_00_2P		GX_11_01_1P
//					GX_00_11_3P		GX_00_00_2P		GX_00_01_1P
//					GX_01_11_3P		GX_01_00_2P		GX_01_01_1P
//										0
//									GXS_11_4P						GX_11_01_2P		GXS_11_5P
//									GXS_00_4P						GX_00_01_2P     GXS_00_5P	GXS_00_6P	GXS_00_7P
//									GXS_01_4P						GX_01_01_2P		GXS_01_5P	GXS_01_6P
//
//					GY_11_11_3P		GY_11_00_2P		GY_11_01_1P
//					GY_00_11_3P		GY_00_00_2P		GY_00_01_1P		0
//					GY_01_11_3P		GY_01_00_2P		GY_01_01_1P
//
//									GYS_11_4P						GY_11_01_2P		GYS_11_5P
//									GYS_00_4P						GY_00_01_2P		GYS_00_5P	GYS_00_6P	GYS_00_7P
//									GYS_01_4P						GY_01_01_2P		GYS_01_5P	GYS_01_6P
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

reg		[Y_DEPTH-1:0]r_p_11_00_1P, r_p_11_11_2P;
reg		[Y_DEPTH-1:0]r_p_00_00_1P, r_p_00_11_2P;
reg		[Y_DEPTH-1:0]r_p_01_00_1P, r_p_01_11_2P;

reg		[Y_DEPTH+5-1:0]r_gx_11_01_2P;
reg		[Y_DEPTH+5-1:0]r_gx_00_01_2P;
reg		[Y_DEPTH+5-1:0]r_gx_01_01_2P;

reg		[Y_DEPTH+5-1:0]r_gxs_11_4P, r_gxs_11_5P;
reg		[Y_DEPTH+5-1:0]r_gxs_00_4P, r_gxs_00_5P, r_gxs_00_6P, r_gxs_00_7P;
reg		[Y_DEPTH+5-1:0]r_gxs_01_4P, r_gxs_01_5P, r_gxs_01_6P;

reg		[Y_DEPTH+5-1:0]r_gy_11_01_2P;
reg		[Y_DEPTH+5-1:0]r_gy_00_01_2P;
reg		[Y_DEPTH+5-1:0]r_gy_01_01_2P;

reg		[Y_DEPTH+5-1:0]r_gys_11_4P, r_gys_11_5P;
reg		[Y_DEPTH+5-1:0]r_gys_00_4P, r_gys_00_5P, r_gys_00_6P, r_gys_00_7P;
reg		[Y_DEPTH+5-1:0]r_gys_01_4P, r_gys_01_5P, r_gys_01_6P;

reg		[Y_DEPTH+5-1:0]r_gxs_00_8P;
reg		[Y_DEPTH+5-1:0]r_gys_00_8P;

reg		[Y_DEPTH+5-1:0]r_g_9P;
reg		[Y_DEPTH-1:0]r_g_10P;

////////
wire	[Y_DEPTH+5-1:0]w_xp1_11_01_1P, w_xp2_11_01_1P;
wire	[Y_DEPTH+5-1:0]w_gx_11_00_2P;
wire	[Y_DEPTH+5-1:0]w_xn1_11_11_3P, w_xn2_11_11_3P;
////
wire	[Y_DEPTH+5-1:0]w_xp2_00_01_1P, w_xp8_00_01_1P;
wire	[Y_DEPTH+5-1:0]w_gx_00_00_2P;
wire	[Y_DEPTH+5-1:0]w_xn2_00_11_3P, w_xn8_00_11_3P;
////
wire	[Y_DEPTH+5-1:0]w_xp1_01_01_1P, w_xp2_01_01_1P;
wire	[Y_DEPTH+5-1:0]w_gx_01_00_2P;
wire	[Y_DEPTH+5-1:0]w_xn1_01_11_3P, w_xn2_01_11_3P;
////////

wire	[Y_DEPTH+5-1:0]w_yn1_11_01_1P, w_yn2_11_01_1P;
wire	[Y_DEPTH+5-1:0]w_yn2_11_00_2P, w_yn8_11_00_2P;
wire	[Y_DEPTH+5-1:0]w_yn1_11_11_3P, w_yn2_11_11_3P;
////
wire	[Y_DEPTH+5-1:0]w_gy_00_11_3P, w_gy_00_00_2P, w_gy_00_01_1P;
////
wire	[Y_DEPTH+5-1:0]w_yn1_01_01_1P, w_yn2_01_01_1P;
wire	[Y_DEPTH+5-1:0]w_yp2_01_00_2P, w_yp8_01_00_2P;
wire	[Y_DEPTH+5-1:0]w_yn1_01_11_3P, w_yn2_01_11_3P;

assign	w_gx_11_00_2P	= {Y_DEPTH+5{1'b0}};
assign	w_gx_00_00_2P	= {Y_DEPTH+5{1'b0}};
assign	w_gx_01_00_2P	= {Y_DEPTH+5{1'b0}};

assign	w_gy_00_11_3P	= {Y_DEPTH+5{1'b0}};
assign	w_gy_00_00_2P	= {Y_DEPTH+5{1'b0}};
assign	w_gy_00_01_1P	= {Y_DEPTH+5{1'b0}};

////////////////////////////////////////////////////////////////
// x - 1

multi_n1_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_xn1_11_11
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(r_p_11_11_2P),
	.o_q	(w_xn1_11_11_3P)
);

multi_n2_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_xn2_11_11
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(r_p_11_11_2P),
	.o_q	(w_xn2_11_11_3P)
);
////
multi_n2_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_xn2_00_11
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(r_p_00_11_2P),
	.o_q	(w_xn2_00_11_3P)
);

multi_n8_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_xn8_00_11
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(r_p_00_11_2P),
	.o_q	(w_xn8_00_11_3P)
);
////
multi_n1_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_xn1_01_11
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(r_p_01_11_2P),
	.o_q	(w_xn1_01_11_3P)
);

multi_n2_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_xn2_01_11
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(r_p_01_11_2P),
	.o_q	(w_xn2_01_11_3P)
);

////////////////////////////////////////////////////////////////
// x + 1

multi_p1_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_xp1_11_01
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(i_pixel_11_01),
	.o_q	(w_xp1_11_01_1P)
);

multi_p2_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_xp2_11_01
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(i_pixel_11_01),
	.o_q	(w_xp2_11_01_1P)
);
////
multi_p2_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_xp2_00_01
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(i_pixel_00_01),
	.o_q	(w_xp2_00_01_1P)
);

multi_p8_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_xp8_00_01
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(i_pixel_00_01),
	.o_q	(w_xp8_00_01_1P)
);
////
multi_p1_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_xp1_01_01
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(i_pixel_01_01),
	.o_q	(w_xp1_01_01_1P)
);

multi_p2_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_xp2_01_01
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(i_pixel_01_01),
	.o_q	(w_xp2_01_01_1P)
);

////////////////////////////////////////////////////////////////
// y - 1

multi_n1_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_yn1_11_01
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(i_pixel_11_01),
	.o_q	(w_yn1_11_01_1P)
);

multi_n2_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_yn2_11_01
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(i_pixel_11_01),
	.o_q	(w_yn2_11_01_1P)
);
////
multi_n2_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_yn2_11_00
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(r_p_11_00_1P),
	.o_q	(w_yn2_11_00_2P)
);

multi_n8_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_yn8_11_00
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(r_p_11_00_1P),
	.o_q	(w_yn8_11_00_2P)
);
///
multi_n1_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_yn1_11_11
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(r_p_11_11_2P),
	.o_q	(w_yn1_11_11_3P)
);

multi_n2_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_yn2_11_11
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(r_p_11_11_2P),
	.o_q	(w_yn2_11_11_3P)
);

////////////////////////////////////////////////////////////////
// y + 1

multi_p1_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_yp1_01_01
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(i_pixel_01_01),
	.o_q	(w_yn1_01_01_1P)
);

multi_p2_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_yp2_01_01
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(i_pixel_01_01),
	.o_q	(w_yn2_01_01_1P)
);
////
multi_p2_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_yp2_01_00
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(r_p_01_00_1P),
	.o_q	(w_yp2_01_00_2P)
);

multi_p8_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_yp8_01_00
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(r_p_01_00_1P),
	.o_q	(w_yp8_01_00_2P)
);
////
multi_p1_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_yp1_01_11
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(r_p_01_11_2P),
	.o_q	(w_yn1_01_11_3P)
);

multi_p2_ext5
#(
	.D_WIDTH(Y_DEPTH)
)
inst_yp2_01_11
(
	.i_arst	(i_arst),
	.i_clk	(i_pclk),
	.i_d	(r_p_01_11_2P),
	.o_q	(w_yn2_01_11_3P)
);

always@(posedge i_arst or posedge i_pclk)
begin
	if (i_arst)
	begin
		r_p_11_00_1P	<= {Y_DEPTH{1'b0}};
		r_p_11_11_2P	<= {Y_DEPTH{1'b0}};
		r_p_00_00_1P	<= {Y_DEPTH{1'b0}};
		r_p_00_11_2P	<= {Y_DEPTH{1'b0}};
		r_p_01_00_1P	<= {Y_DEPTH{1'b0}};
		r_p_01_11_2P	<= {Y_DEPTH{1'b0}};
		
		////////////////////////////////
		
		r_gx_11_01_2P	<= {Y_DEPTH+4{1'b0}};
		r_gx_00_01_2P	<= {Y_DEPTH+4{1'b0}};
		r_gx_01_01_2P	<= {Y_DEPTH+4{1'b0}};
		
		r_gxs_11_4P		<= {Y_DEPTH+4{1'b0}};
		r_gxs_00_4P		<= {Y_DEPTH+4{1'b0}};
		r_gxs_01_4P		<= {Y_DEPTH+4{1'b0}};
		
		r_gxs_11_5P		<= {Y_DEPTH+4{1'b0}};
		r_gxs_00_5P		<= {Y_DEPTH+4{1'b0}};
		r_gxs_01_5P		<= {Y_DEPTH+4{1'b0}};
		
		r_gxs_00_6P		<= {Y_DEPTH+4{1'b0}};
		r_gxs_01_6P		<= {Y_DEPTH+4{1'b0}};
		
		r_gxs_00_7P		<= {Y_DEPTH+4{1'b0}};
		
		////////////////////////////////
		
		r_gy_11_01_2P	<= {Y_DEPTH+4{1'b0}};
		r_gy_00_01_2P	<= {Y_DEPTH+4{1'b0}};
		r_gy_01_01_2P	<= {Y_DEPTH+4{1'b0}};
		
		r_gys_11_4P		<= {Y_DEPTH+4{1'b0}};
		r_gys_00_4P		<= {Y_DEPTH+4{1'b0}};
		r_gys_01_4P		<= {Y_DEPTH+4{1'b0}};
		
		r_gys_11_5P		<= {Y_DEPTH+4{1'b0}};
		r_gys_00_5P		<= {Y_DEPTH+4{1'b0}};
		r_gys_01_5P		<= {Y_DEPTH+4{1'b0}};
		
		r_gys_00_6P		<= {Y_DEPTH+4{1'b0}};
		r_gys_01_6P		<= {Y_DEPTH+4{1'b0}};
		
		r_gys_00_7P		<= {Y_DEPTH+4{1'b0}};
		
		////////////////////////////////
		
		r_gxs_00_8P		<= {Y_DEPTH+4{1'b0}};
		r_gys_00_8P		<= {Y_DEPTH+4{1'b0}};
		
		r_g_9P			<= {Y_DEPTH+4{1'b0}};
		r_g_10P			<= {Y_DEPTH{1'b0}};
	end
	else
	begin
		r_p_11_00_1P	<= i_pixel_11_01;
		r_p_00_00_1P	<= i_pixel_00_01;
		r_p_01_00_1P	<= i_pixel_01_01;
		
		r_p_11_11_2P	<= r_p_11_00_1P;
		r_p_00_11_2P	<= r_p_00_00_1P;
		r_p_01_11_2P	<= r_p_01_00_1P;
		
		////////////////////////////////
		
		r_gx_11_01_2P	<= w_xp1_11_01_1P + w_xp2_11_01_1P;
		r_gx_00_01_2P	<= w_xp2_00_01_1P + w_xp8_00_01_1P;
		r_gx_01_01_2P	<= w_xp1_01_01_1P + w_xp2_01_01_1P;
		
		////////////////////////////////
		
		r_gxs_11_4P		<= w_xn1_11_11_3P + w_xn2_11_11_3P;
		r_gxs_00_4P		<= w_xn2_00_11_3P + w_xn8_00_11_3P;
		r_gxs_01_4P		<= w_xn1_01_11_3P + w_xn2_01_11_3P;
		
		r_gxs_11_5P		<= r_gxs_11_4P + r_gx_11_01_2P;
		r_gxs_00_5P		<= r_gxs_00_4P + r_gx_00_01_2P;
		r_gxs_01_5P		<= r_gxs_01_4P + r_gx_01_01_2P;
		
		r_gxs_00_6P		<= r_gxs_00_5P + r_gxs_11_5P;
		r_gxs_01_6P		<= r_gxs_01_5P;
		
		r_gxs_00_7P		<= r_gxs_00_6P + r_gxs_01_6P;
		
		////////////////////////////////
		
		r_gy_11_01_2P	<= w_yn1_11_01_1P + w_yn2_11_01_1P;
		r_gy_00_01_2P	<= w_gy_00_11_3P;
		r_gy_01_01_2P	<= w_yn1_01_01_1P + w_yn2_01_01_1P;
		
		////////////////////////////////
		
		r_gys_11_4P		<= w_yn2_11_00_2P + w_yn8_11_00_2P + w_yn1_11_11_3P + w_yn2_11_11_3P;
		r_gys_00_4P		<= w_gy_00_00_2P + w_gy_00_01_1P;
		r_gys_01_4P		<= w_yp2_01_00_2P + w_yp8_01_00_2P + w_yn1_01_11_3P + w_yn2_01_11_3P;
		
		r_gys_11_5P		<= r_gys_11_4P + r_gy_11_01_2P;
		r_gys_00_5P		<= r_gys_00_4P + r_gy_00_01_2P;
		r_gys_01_5P		<= r_gys_01_4P + r_gy_01_01_2P;
		
		r_gys_00_6P		<= r_gys_00_5P + r_gys_11_5P;
		r_gys_01_6P		<= r_gys_01_5P;
		
		r_gys_00_7P		<= r_gys_00_6P + r_gys_01_6P;
		
		////////////////////////////////
		
		if (r_gxs_00_7P[Y_DEPTH+5-1])
			r_gxs_00_8P	<= ~r_gxs_00_7P + 1'b1;
		else
			r_gxs_00_8P	<= r_gxs_00_7P;
		
		if (r_gys_00_7P[Y_DEPTH+5-1])
			r_gys_00_8P	<= ~r_gys_00_7P + 1'b1;
		else
			r_gys_00_8P	<= r_gys_00_7P;
		
		r_g_9P	<= r_gxs_00_8P + r_gys_00_8P;
		
		if (r_g_9P[Y_DEPTH+5-1] || r_g_9P[Y_DEPTH+5-2])
			r_g_10P	<= {Y_DEPTH{1'b0}};
		else
//			r_g_10P	<= {Y_DEPTH{1'b1}} - r_g_9P[Y_DEPTH-1:0];
			r_g_10P	<= r_g_9P[Y_DEPTH-1:0];
	end
end

assign	o_pixel	= r_g_10P;

endmodule