diff options
Diffstat (limited to 'cocotb_try/cic3_pdm.v')
-rw-r--r-- | cocotb_try/cic3_pdm.v | 185 |
1 files changed, 106 insertions, 79 deletions
diff --git a/cocotb_try/cic3_pdm.v b/cocotb_try/cic3_pdm.v index fc5de46..4e8d664 100644 --- a/cocotb_try/cic3_pdm.v +++ b/cocotb_try/cic3_pdm.v @@ -1,100 +1,127 @@ - - module cic3_pdm ( - input wire clk, // PDM clock - input wire rst, // active-high synchronous reset - input wire pdm_in, // 1-bit PDM data input - input wire [7:0] hpf_alpha, // HPF coefficient (0-255, 255=bypass) - output wire signed [15:0] pcm_out, // Decimated PCM output - output wire pcm_valid - + input wire clk, // PDM clock + input wire rst, // active-high synchronous reset + input wire pdm_in, // 1-bit PDM data input + input wire [7:0] hpf_alpha, // HPF coefficient (0-255, 255=bypass) + input wire [2:0] scale_shift, // Right shift amount (0-7 bits) + output reg signed [15:0] pcm_out, // Decimated PCM output + output reg pcm_valid // Output valid pulse ); - //parameter DECIMATION = 64; // Decimation factor - parameter OUTPUT_SHIFT = 10; // Can tune this - - // Internal registers - reg signed [38:0] integrator_0 = 0; - reg signed [38:0] integrator_1 = 0; - reg signed [38:0] integrator_2 = 0; - - reg [5:0] decim_counter = 0; - reg signed [38:0] comb_0 = 0, comb_1 = 0; - - /* verilator lint_off UNUSEDSIGNAL */ - reg signed [38:0] comb_2 = 0; + // CIC filter parameters + localparam DECIMATION = 64; + localparam CIC_WIDTH = 17; // 17 bits for safe margin against overflow + + // CIC integrator and comb stages + reg signed [CIC_WIDTH-1:0] integrator1, integrator2; + reg signed [CIC_WIDTH-1:0] comb1, comb2; + reg signed [CIC_WIDTH-1:0] comb1_d1, comb2_d1; + + // Decimation counter + reg [6:0] decim_count; // 7 bits to match DECIMATION width + + // CIC output and scaling + reg signed [CIC_WIDTH-1:0] cic_out; + reg signed [15:0] scaled_out; + reg cic_valid; + // HPF registers - reg signed [15:0] hpf_prev = 0; // Previous input sample - reg signed [15:0] cic_reg = 0; // Registered CIC output - reg cic_valid = 0; - - // CIC output - wire signed [15:0] cic_out = comb_2[OUTPUT_SHIFT + 15 : OUTPUT_SHIFT]; - - reg signed [38:0] delay_0 = 0, delay_1 = 0, delay_2 = 0; - - reg signed [15:0] pcm_out_r = 0; - reg pcm_valid_r = 0; - - // Integrator stage (runs every clk) + reg signed [15:0] hpf_x_prev; + reg signed [15:0] hpf_y_prev; + + // HPF calculation wires + /* verilator lint_off UNUSEDSIGNAL */ + wire signed [23:0] hpf_temp; + /* verilator lint_on UNUSEDSIGNAL */ + wire signed [15:0] hpf_calc; + + // Convert 1-bit PDM to signed + wire signed [CIC_WIDTH-1:0] pdm_signed = pdm_in ? 17'sd1 : -17'sd1; + + // CIC Integrator stages (run at PDM rate) always @(posedge clk) begin if (rst) begin - integrator_0 <= 0; - integrator_1 <= 0; - integrator_2 <= 0; + integrator1 <= 0; + integrator2 <= 0; end else begin - integrator_0 <= integrator_0 + (pdm_in ? 1 : -1); - integrator_1 <= integrator_1 + integrator_0; - integrator_2 <= integrator_2 + integrator_1; + integrator1 <= integrator1 + pdm_signed; + integrator2 <= integrator2 + integrator1; end end - - // Decimation counter - always @(posedge clk) begin - if (rst) - decim_counter <= 0; - else - decim_counter <= decim_counter + 1; - end - - // Comb stage + + // Decimation counter and CIC comb stages always @(posedge clk) begin - cic_valid <= 0; if (rst) begin - cic_reg <= 0; - end else if (decim_counter == 63) begin - comb_0 <= integrator_2 - delay_0; - delay_0 <= integrator_2; - comb_1 <= comb_0 - delay_1; - delay_1 <= comb_0; - comb_2 <= comb_1 - delay_2; - delay_2 <= comb_1; - end else if (decim_counter == 0) begin - // CIC output is now stable, register it - cic_reg <= cic_out; - cic_valid <= 1; + decim_count <= 0; + comb1 <= 0; + comb2 <= 0; + comb1_d1 <= 0; + comb2_d1 <= 0; + cic_out <= 0; + cic_valid <= 0; + end else begin + cic_valid <= 0; + + if (decim_count == DECIMATION - 1) begin + decim_count <= 0; + + // Comb stage 1 + comb1 <= integrator2 - comb1_d1; + comb1_d1 <= integrator2; + + // Comb stage 2 + comb2 <= comb1 - comb2_d1; + comb2_d1 <= comb1; + + cic_out <= comb2; + cic_valid <= 1; + end else begin + decim_count <= decim_count + 1; + end end end - // HPF stage (runs after CIC settles) + // Output scaling + always @(*) begin + case (scale_shift) + 3'd0: scaled_out = cic_out[15:0]; + 3'd1: scaled_out = cic_out[16:1]; + 3'd2: scaled_out = {{1{cic_out[16]}}, cic_out[16:2]}; // Sign extend from bit 16 + 3'd3: scaled_out = {{2{cic_out[16]}}, cic_out[16:3]}; // Sign extend from bit 16 + 3'd4: scaled_out = {{3{cic_out[16]}}, cic_out[16:4]}; // Sign extend from bit 16 + 3'd5: scaled_out = {{4{cic_out[16]}}, cic_out[16:5]}; // Sign extend from bit 16 + 3'd6: scaled_out = {{5{cic_out[16]}}, cic_out[16:6]}; // Sign extend from bit 16 + 3'd7: scaled_out = {{6{cic_out[16]}}, cic_out[16:7]}; // Sign extend from bit 16 + endcase + end + + // HPF calculation + assign hpf_temp = ((hpf_alpha * hpf_y_prev) + (({8'd0, scaled_out} - {8'd0, hpf_x_prev}) << 8)) >>> 8; + assign hpf_calc = hpf_temp[15:0]; + + // High-pass filter (1st order IIR: y[n] = alpha/256 * y[n-1] + (x[n] - x[n-1])) always @(posedge clk) begin - pcm_valid_r <= 0; if (rst) begin - hpf_prev <= 0; - pcm_out_r <= 0; - end else if (cic_valid) begin - if (hpf_alpha == 8'd255) begin - pcm_out_r <= cic_reg; - end else begin - // HPF: y[n] = x[n] - x[n-1] + alpha*y[n-1] - pcm_out_r <= cic_reg - hpf_prev + ((pcm_out_r * hpf_alpha) >>> 8); + hpf_x_prev <= 0; + hpf_y_prev <= 0; + pcm_out <= 0; + pcm_valid <= 0; + end else begin + pcm_valid <= 0; + + if (cic_valid) begin + if (hpf_alpha == 8'd255) begin + // Bypass HPF completely + pcm_out <= scaled_out; + end else begin + // HPF computation: y[n] = alpha/256 * y[n-1] + (x[n] - x[n-1]) + pcm_out <= hpf_calc; + hpf_x_prev <= scaled_out; + hpf_y_prev <= hpf_calc; + end + pcm_valid <= 1; end - hpf_prev <= cic_reg; - pcm_valid_r <= 1; end end - assign pcm_out = pcm_out_r; - assign pcm_valid = pcm_valid_r; - endmodule |