module uwt_bior31
	#(
		parameter	L	=	1 // transform level
	)
	(
		input	wire			clk, reset,
		input	wire	[31:0]	x,
		output	wire	[31:0]	d,
		output	wire	[31:0]	a,
		output	wire	[31:0]	peak,
		output	wire	[1:0]	flag
	);

	localparam	index1		=	1 << (L - 1);
	localparam	index2		=	2 << (L - 1);
	localparam	index3		=	3 << (L - 1);
	localparam	peak_index	=	((3 << (L - 1)) + 1) >> 1;
	localparam	peak_shift	=	((L - 1) << 1) + (L - 1);
	localparam	zero		=	32'h80000000;
	
	// Tapped delay line
	reg		[31:0]	tap [index3:0];
	
	reg		[31:0]	d_reg, d_next;
	reg		[31:0]	a_reg, a_next;
	reg		[31:0]	peak_reg, peak_next;

	reg		[1:0]	flag_reg;

	integer			i;
	
	always @(posedge clk, posedge reset)
	begin
		if (reset)
		begin
			d_reg <= 0;
			a_reg <= 0;
			peak_reg <= 0;
			flag_reg <= 0;

			for(i = 0; i <= index3; i = i + 1)
			begin
				tap[i] <= 0;
			end
		end
		else
		begin
			d_reg <= d_next;
			a_reg <= a_next;
			peak_reg <= peak_next;
			
			flag_reg[0] <= (d_reg > zero) & (d_next <= zero);
			flag_reg[1] <= (d_reg < zero) & (d_next >= zero);
	
			// Tapped delay line: shift one
			for(i = 0; i < index3; i = i + 1)
			begin
				tap[i+1] <= tap[i];
			end
			
			// Input in register 0
			tap[0] <= x;
		end
	end
	
	always @*
	begin
		// Compute d and a with the filter coefficients.
		// The coefficients are [1, 3, -3, -1] and [1, 3, 3, 1]

		d_next = zero - (tap[index3])
			   - (tap[index2] << 1) - tap[index2]
			   + (tap[index1] << 1) + tap[index1]
			   + (tap[0]);
		
		a_next = (tap[index3])
			   + (tap[index2] << 1) + tap[index2]
			   + (tap[index1] << 1) + tap[index1]
			   + (tap[0]);

		peak_next = (tap[peak_index] >> peak_shift);
	end

	// output logic
	assign	d		=	d_reg;
	assign	a		=	a_reg;
	assign	peak	=	peak_reg;
	assign	flag	=	flag_reg;

endmodule
