module audiodac_dsmod(
	input 		[15:0]	audio_i,	// audio data from FIFO
	output wire		audio_rd_o, 	// indicates a read from FIFO
	input			rst_n_i,
	input			clk_i,
	input			mode_i, 	// 0 = 1st order, 1 = 2nd order SD-modulator
	input 		[3:0]	volume_i,	// 0 = off, 15 = max volume
	input		[1:0]	osr_i, 		// 0 = 32; 1 = 64, 2 = 128, 3 = 256
	output reg		ds_o,		// single-bit SD-modulator output
	output wire		ds_n_o		//  plus the complementary output
);

	reg 		[15:0]	accu1;
	reg		[15:0]	accu2;
	reg		[1:0]	accu3;
	wire 		[15:0]	audio_scaled;	// audio data treated with volume control
	reg		[7:0]	fetch_ctr;	// clock divideid by osr

	reg		[1:0]	mod2_ctr;	// clk divide by 4 for 1st stage of 2nd order mod.
	reg		[1:0]	mod2_out;	// output 1st stage

	localparam	[7:0]	CTR_OSR32  	=  8'd31;
	localparam	[7:0]	CTR_OSR64  	=  8'd63;
	localparam	[7:0]	CTR_OSR128 	=  8'd127;
	localparam	[7:0]	CTR_OSR256 	=  8'd255;
	localparam	[1:0]	OSR32  		= 2'd0;
	localparam	[1:0]	OSR64  		= 2'd1;
	localparam	[1:0]	OSR128 		= 2'd2;
	localparam	[1:0]	OSR256 		= 2'd3;
	localparam		ORD1 		= 1'd0;
	localparam		ORD2 		= 1'd1;

	// provide out and out_n to make levelshifter easier
  	assign ds_n_o = ~ds_o;

	// we provide volume control in 6dB steps, 0=min (off), 15=max
	assign audio_scaled = (volume_i === 4'd0) ? 16'b0 : audio_i >> (4'd15 - volume_i);

	// the fetch counter controls the read of the next sample from the FIFO
	// counter runs down so decoding is easier for different counter
	// cycles
	assign audio_rd_o = (fetch_ctr === 8'd0);

  	always @(posedge clk_i) begin
		if (!rst_n_i) begin
			// reset all registers
			accu1 <= 16'b0;
			accu2 <= 16'b0;
			accu3 <=  2'b0;
			ds_o <= 1'b0;
			fetch_ctr <= 8'b0;
			mod2_ctr <= 2'b0;
			mod2_out <= 2'b0;
		end else begin
			// sd-modulator is running

			if (fetch_ctr === 8'd0) begin
			// fetch_ctr finished, restart with proper cycle count
			// depending on osr
				case (osr_i)
					OSR32:		fetch_ctr <= CTR_OSR32;
					OSR64:		fetch_ctr <= CTR_OSR64;
					OSR128:		fetch_ctr <= CTR_OSR128;
					OSR256:		fetch_ctr <= CTR_OSR256;
					default:	fetch_ctr <= 8'bx;
				endcase
			end else
				//just keep counting down
				fetch_ctr <= fetch_ctr - 1'b1;
		
			if (mode_i === ORD1) begin
				// delta-sigma modulator 1st order
				// this simple structure works if everything
				// is UINT
				{ds_o,accu1} <= audio_scaled + accu1;
			
			end else if (mode_i === ORD2) begin
				// delta-sigma modulator 2nd order
				// the first stage runs on clk/4, the second
				// stage runs on clk

				if (mod2_ctr === 2'b0) begin
					// this only happens every 4th clk
					// cycle
					{mod2_out,accu1} <= {2'b00,audio_scaled} 
								+ {1'b0,accu1,1'b0} 
								+ 18'h10000 
								- {2'b0,accu2};
					accu2 <= accu1;
				end

				// this is the clk divider for the 1st stage
				mod2_ctr <= mod2_ctr + 1'b1;
				
				// this simple structure is the 2nd stage
				// running on clk
				{ds_o,accu3} <= mod2_out + accu3;
			end
		end
	end
endmodule // audiodac_dsmod