ADC_DeltaSigmaADCOrder2_DecimationFilter

ADC_DeltaSigmaADCOrder2_DecimationFilter : A decimation filter for a second-order delta-sigma ADC

A decimation filter converts a single-bit digital input stream of in to a multi-bit digital output stream of out via decimation and filtering. In particular, this decimation filter model converts a 1-bit stream of in to a 21-bit stream of out with a decimation factor of 16. The input in and output out are updated at each rising edge of the input clock iclk and the output clock oclk, respectively. The ratio between the iclk frequency and oclk frequency determines the decimation factor, which is 16.

This decimation filter model describes a cascaded integrator-comb (CIC) filter in Verilog, consisting of a set of 5 accumulators, a down sampler, and a set of 5 differentiators. The more details on the CIC filter can be found at this link (https://en.wikipedia.org/wiki/Cascaded_integrator%E2%80%93comb_filter).

module ADC_DeltaSigmaADCOrder2_DecimationFilter (in, iclk, out, oclk, gl_reset);

input           in;                 // 1-bit input
input           iclk;               // input clock
output	[20:0]  out;                // 21-bit output
output          oclk;               // output clock
input           gl_reset;           // global reset

reg     [20:0]  out;                // output register
wire            oclk;               // output clock
wire            aclk;               // internal clock for accumulators
wire            dclk;               // internal clock for differentiators 
reg     [3:0]   div;                // clock divider
reg             in_reg;             // input register

wire	[20:0]	a1, a2, a3, a4, a5; // accumulators
reg     [20:0]  s0, s1;             // decimators
wire	[20:0]	d1, d2, d3, d4, d5; // differentiator

// internal clock
assign	aclk = ~iclk;

// input register
always @(posedge aclk, posedge gl_reset) begin
	if (gl_reset) in_reg <= 0;
	else in_reg <= in;
end

// accumulator stages
sinc_acc acc1({{20{1'b0}}, in_reg}, a1, aclk, gl_reset);
sinc_acc acc2(a1, a2, aclk, gl_reset);
sinc_acc acc3(a2, a3, aclk, gl_reset);
sinc_acc acc4(a3, a4, aclk, gl_reset);
sinc_acc acc5(a4, a5, aclk, gl_reset);

// decimator
always @(posedge aclk, posedge gl_reset) begin
	if (gl_reset) div <= 0;
	else div <= div + 1;
end

always @(posedge aclk, posedge gl_reset) begin
	if (gl_reset) s0 <= 0;
	else if (div == {4{1'b1}}) s0 <= a5;
end

assign dclk = div[3];

always @(posedge dclk, posedge gl_reset) begin
	if (gl_reset) s1 <= 0;
	else s1 <= s0;
end

// differentiator stages
sinc_diff diff1(s1, d1, dclk, gl_reset);
sinc_diff diff2(d1, d2, dclk, gl_reset);
sinc_diff diff3(d2, d3, dclk, gl_reset);
sinc_diff diff4(d3, d4, dclk, gl_reset);
sinc_diff diff5(d4, d5, dclk, gl_reset);

// output register
always @(posedge dclk, posedge gl_reset) begin
	if (gl_reset) out <= 0;
	else out <= d5;
end

// clocks used by the subsequent FIR filter
assign	oclk = ~dclk;		// indicates the center of the data eye 

endmodule


////////////////////////////////////////////////////////////////////////////////
//
// Block Name 	: sinc_acc.v
// Block Description : 
//		accumulator used in sinc^k decimator
//
////////////////////////////////////////////////////////////////////////////////

module sinc_acc(in, out, clk, gl_reset);


input   [20:0]      in;         // 21-bit input
input               clk;        // input clock
input               gl_reset;   // global reset
output  [20:0]      out;        // 21-bit output

wire    [20:0]      out;        
reg     [20:0]      acc;

// accumulator
always @(posedge clk, posedge gl_reset) begin
	if (gl_reset) acc <= 0;
	else acc <= out;
end

assign	out = in + acc;

endmodule


////////////////////////////////////////////////////////////////////////////////
//
// Block Name 	: sinc_diff.v
// Block Description : 
//		differentiator used in sinc^k decimator
//
////////////////////////////////////////////////////////////////////////////////

module sinc_diff(in, out, clk, gl_reset);

input   [20:0]     in;          // 21-bit input
output  [20:0]     out;         // 21-bit output
input              clk;         // input clock
input              gl_reset;    // global reset
 
wire	[20:0]     out;
reg     [20:0]     prev;

always @(posedge clk, posedge gl_reset) begin
	if (gl_reset) prev <= 0;
	else prev <= in;
end

assign	out = in - prev;

endmodule

Input/Output Terminals

Name I/O Type Description
in input wire 1-bit input
iclk input wire input clock
out[20:0] output wire 21-bit output
oclk output wire output clock
gl_reset input wire global reset