From 639541728f5576ea3924c4b32184d1ee7abeaab0 Mon Sep 17 00:00:00 2001 From: Jojojoppe Date: Wed, 1 Oct 2025 21:52:21 +0200 Subject: [PATCH] Added decimator --- HW/sampling.v | 98 ++++++++++++++++++++++++++++++++++++++-- SIM/sampling_tb.v | 15 +++--- SIM/sigmadelta_sampler.v | 2 +- 3 files changed, 104 insertions(+), 11 deletions(-) diff --git a/HW/sampling.v b/HW/sampling.v index 71ea1b2..db78dbf 100644 --- a/HW/sampling.v +++ b/HW/sampling.v @@ -5,13 +5,14 @@ module sampling( input wire adc_B, output wire adc_O, - input wire clk, + input wire clk_15, + input wire clk_120, input wire reset_n ); wire sigmadelta_sample; sigmadelta_sampler m_sdsampler( - .clk(clk), + .clk(clk_15), .A(adc_A), .B(adc_B), .out(sigmadelta_sample) @@ -34,10 +35,99 @@ module sampling( else clamp01_q15 = v; endfunction - always @(posedge clk or negedge reset_n) begin + 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 // ------------------------------ -endmodule \ No newline at end of file + 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 diff --git a/SIM/sampling_tb.v b/SIM/sampling_tb.v index a9e2624..27fd1f0 100644 --- a/SIM/sampling_tb.v +++ b/SIM/sampling_tb.v @@ -1,11 +1,13 @@ `timescale 1ns/1ps module sampling_tb; - reg clk; + reg clk_15; + reg clk_120; reg reset_n; sampling m_sampling( - .clk(clk), + .clk_15(clk_15), + .clk_120(clk_120), .reset_n(reset_n) ); @@ -13,15 +15,16 @@ module sampling_tb; $dumpfile("sampling_tb.vcd"); $dumpvars (0, sampling_tb); - clk <= 1'b0; + clk_15 <= 1'b0; + clk_120 <= 1'b0; reset_n <= 1'b0; #50 reset_n <= 1'b1; - #1000000 + #2000000 $finish; end - //15 MHz clock - always #33.33 clk = ~clk; + always #(500/15) clk_15 = ~clk_15; + always #(500/120) clk_120 = ~clk_120; endmodule \ No newline at end of file diff --git a/SIM/sigmadelta_sampler.v b/SIM/sigmadelta_sampler.v index c497048..ffdf6dc 100644 --- a/SIM/sigmadelta_sampler.v +++ b/SIM/sigmadelta_sampler.v @@ -8,7 +8,7 @@ module sigmadelta_sampler( ); // ===== Tunable parameters ===== // Sine source (A input / P) - parameter real F_HZ = 2.0e3; // input sine frequency (1 kHz) + parameter real F_HZ = 1.5e3; // input sine frequency (1 kHz) parameter real AMP = 1.5; // sine amplitude (V) parameter real VCM = 1.65; // common-mode (V), centered in 0..3.3V