`timescale 1ns/1ps module sampling( input wire adc_A, input wire adc_B, output wire adc_O, input wire clk_15, input wire clk_120, input wire reset_n ); wire sigmadelta_sample; sigmadelta_sampler m_sdsampler( .clk(clk_15), .A(adc_A), .B(adc_B), .out(sigmadelta_sample) ); assign adc_O = sigmadelta_sample; // RC model, output is y_next_q15 // ------------------------------ reg signed [15:0] y_q15; wire signed [15:0] x_q15 = sigmadelta_sample ? 16'sh7fff : 16'sh0000; wire signed [15:0] e_q15 = x_q15 - y_q15; wire signed [31:0] prod_q30 = $signed(16'sh0b00) * $signed(e_q15); // factor should be 0b3b, used bit simplified here wire signed [15:0] delta_q15 = prod_q30 >>> 15; wire signed [15:0] y_next_q15 = y_q15 + delta_q15; // Optional clamp to [0, 0x7FFF] (keeps GTKWave tidy) function signed [15:0] clamp01_q15(input signed [15:0] v); if (v < 16'sd0000) clamp01_q15 = 16'sd0000; else if (v > 16'sh7FFF) clamp01_q15 = 16'sh7FFF; else clamp01_q15 = v; endfunction always @(posedge clk_15 or negedge reset_n) begin if (!reset_n) y_q15 <= 16'sd0000; else y_q15 <= clamp01_q15(y_next_q15); end // ------------------------------ wire signed [15:0] lpfed_q15; lpf_iir_q15 #(.K(7)) m_lpf ( .clk(clk_15), .rst_n(reset_n), .x_q15(y_next_q15), .y_q15(lpfed_q15) ); wire signed [15:0] decimated_q15; decimate_by_r #(.R(375)) m_decimator ( .clk(clk_15), .rst_n(reset_n), .in_valid(1'b1), .in_q15(lpfed_q15), .out_valid(), .out_q15(decimated_q15) ); // decimated_q15 + out_valid @ 40KHz endmodule // -------------------------------------------------------------------- // Simple 1-pole IIR LPF, Q1.15 in/out, multiplier-less (alpha = 1/2^K) // -------------------------------------------------------------------- module lpf_iir_q15 #( parameter integer K = 10 // try 8..12; bigger = more smoothing )( input wire clk, input wire rst_n, input wire signed [15:0] x_q15, // Q1.15 input (e.g., 0..0x7FFF) output reg signed [15:0] y_q15 // Q1.15 output ); wire signed [15:0] e_q15 = x_q15 - y_q15; wire signed [15:0] delta_q15 = e_q15 >>> K; // arithmetic shift wire signed [15:0] y_next = y_q15 + delta_q15; // clamp to [0, 0x7FFF] (handy if your signal is non-negative) function signed [15:0] clamp01; input signed [15:0] v; begin if (v < 16'sd0) clamp01 = 16'sd0; else if (v > 16'sh7FFF) clamp01 = 16'sh7FFF; else clamp01 = v; end endfunction always @(posedge clk or negedge rst_n) begin if (!rst_n) y_q15 <= 16'sd0; else y_q15 <= clamp01(y_next); end endmodule // ------------------------------------------------------------- // Decimate-by-R: passes through one sample every R input clocks // No $clog2 used; set CNT_W wide enough for your R. // ------------------------------------------------------------- module decimate_by_r #( parameter integer R = 400, // decimation factor parameter integer CNT_W = 10 // width so that 2^CNT_W > R (e.g., 10 for 750) )( input wire clk, input wire rst_n, input wire in_valid, // assert 1'b1 if always valid input wire signed [15:0] in_q15, // Q1.15 sample at full rate output reg out_valid, // 1-cycle pulse every R samples output reg signed [15:0] out_q15 // Q1.15 sample at decimated rate ); reg [CNT_W-1:0] cnt; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin cnt <= {CNT_W{1'b0}}; out_valid <= 1'b0; out_q15 <= 16'sd0; end else begin out_valid <= 1'b0; if (in_valid) begin if (cnt == R-1) begin cnt <= {CNT_W{1'b0}}; out_q15 <= in_q15; out_valid <= 1'b1; end else begin cnt <= cnt + 1'b1; end end end end endmodule