module uwt_bior31
	#(
		parameter	level	=	1, // transform level
		parameter	width	=	12 // bit width of the input data (unsigned)

	)
	(
		input	wire					clock, frame, reset,
		input	wire	[width-1:0]		inp_data,
		output	wire	[widthr-1:0]	out_data,
		output	wire	[1:0]			out_flag
	);

	localparam	widthr = width + 3;

	localparam	index1 = 1 << (level - 1);
	localparam	index2 = 2 << (level - 1);
	localparam	index3 = 3 << (level - 1);
	
	// Tapped delay line
	reg		[width-1:0]		tap_data_reg [index3:0], tap_data_next [index3:0];
	
	wire	[1:0]			int_comp_wire;
	reg		[1:0]			int_comp_reg, int_comp_next;

	reg		[1:0]			out_flag_reg, out_flag_next;
	
	wire	[widthr-1:0]	add_data_wire [1:0];
	reg		[widthr-1:0]	add_data_reg [1:0], add_data_next [1:0];

	reg		[widthr-1:0]	out_data_reg, out_data_next;

	integer i;
	
	assign add_data_wire[0] = tap_data_reg[index3] + {tap_data_reg[index2][width-2:0], 1'b0} + tap_data_reg[index2];
	assign add_data_wire[1] = {tap_data_reg[index1][width-2:0], 1'b0} + tap_data_reg[index1] + tap_data_reg[0];
	assign int_comp_wire[0] = (add_data_reg[0] > add_data_reg[1]);
	assign int_comp_wire[1] = (add_data_reg[0] < add_data_reg[1]);

	always @(posedge clock)
	begin
		if (reset)
		begin
			add_data_reg[0] <= {(widthr){1'b0}};
			add_data_reg[1] <= {(widthr){1'b0}};
			out_data_reg <= {(widthr){1'b0}};
			int_comp_reg <= 2'd0;
			out_flag_reg <= 2'd0;

			for(i = 0; i <= index3; i = i + 1)
			begin
				tap_data_reg[i] <= {(width){1'b0}};
			end
		end
		else
		begin
			add_data_reg[0] <= add_data_next[0];
			add_data_reg[1] <= add_data_next[1];
			out_data_reg <= out_data_next;
			int_comp_reg <= int_comp_next;
			out_flag_reg <= out_flag_next;

			for(i = 0; i <= index3; i = i + 1)
			begin
				tap_data_reg[i] <= tap_data_next[i];
			end			
		end
	end
	
	always @*
	begin
		add_data_next[0] = add_data_reg[0];
		add_data_next[1] = add_data_reg[1];
		out_data_next = out_data_reg;
		int_comp_next = int_comp_reg;
		out_flag_next = out_flag_reg;

		for(i = 0; i <= index3; i = i + 1)
		begin
			tap_data_next[i] = tap_data_reg[i];
		end

		if (frame)
		begin		
			// Tapped delay line: shift one
			for(i = 0; i < index3; i = i + 1)
			begin
				tap_data_next[i+1] = tap_data_reg[i];
			end
			
			// Input in register 0
			tap_data_next[0] = inp_data;

			add_data_next[0] = add_data_wire[0];
			add_data_next[1] = add_data_wire[1];
			
			out_data_next = add_data_next[0] + add_data_next[1];
	
			int_comp_next = int_comp_wire;
			out_flag_next[0] = (~int_comp_reg[0]) & (int_comp_wire[0]);
			out_flag_next[1] = (~int_comp_reg[1]) & (int_comp_wire[1]);

		end

	end

	// output logic
	assign	out_data = out_data_reg;
	assign	out_flag = out_flag_reg;

endmodule
