`timescale 1ns/1ps // ============================================================================= // RC model to convert sigma delta samples to Q1.15 // Models the RC circuit on the outside of the FPGA // Uses: Yn+1 = Yn + (sd - Yn)*(1-exp(-T/RC)) // parameters: // -- alpha_q15 : the 1-exp(-T/RC), defaults to R=3k3, C=220p and T=1/15MHz // rounded to only use two bits (0b3b -> 0b00), the less // bits the better // inout: // -- clk : input clock // -- resetn : reset signal // -- sd_sample : 1 bit sample output from sd sampler // -- sample_q15 : output samples in q.15 // ============================================================================= module sigmadelta_rcmodel_q15 #( parameter integer alpha_q15 = 16'sh0b00 )( input wire clk, input wire resetn, input wire sd_sample, output wire [15:0] sample_q15 ); reg signed [15:0] y_q15; wire signed [15:0] sd_q15 = sd_sample ? 16'sh7fff : 16'sh0000; wire signed [15:0] e_q15 = sd_q15 - y_q15; // wire signed [31:0] prod_q30 = $signed(e_q15) * $signed(alpha_q15); wire signed [31:0] prod_q30; // Use shift-add algorithm for multiplication mul_const_shiftadd #(.C($signed(alpha_q15))) alpha_times_e ($signed(e_q15), prod_q30); wire signed [15:0] y_next_q15 = y_q15 + (prod_q30>>>15); // clamp to [0, 0x7FFF] (keeps signal view 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 or negedge resetn) begin if (!resetn) y_q15 <= 16'sd0000; else y_q15 <= clamp01_q15(y_next_q15); end assign sample_q15 = y_q15; endmodule