diff options
Diffstat (limited to 'cocotb_try/cic3_pdm.v')
-rw-r--r-- | cocotb_try/cic3_pdm.v | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/cocotb_try/cic3_pdm.v b/cocotb_try/cic3_pdm.v new file mode 100644 index 0000000..f572d64 --- /dev/null +++ b/cocotb_try/cic3_pdm.v @@ -0,0 +1,68 @@ + +// XXX: A chatbot wrote this, might be complete crack + +module cic3_pdm ( + input wire clk, // PDM clock + input wire rst, // active-high synchronous reset + input wire pdm_in, // 1-bit PDM data input + output wire signed [15:0] pcm_out, // Decimated PCM output + output wire pcm_valid // High when pcm_out is valid +); + parameter DECIMATION = 64; // Decimation factor + + // Internal registers + reg signed [31:0] integrator_0 = 0; + reg signed [31:0] integrator_1 = 0; + reg signed [31:0] integrator_2 = 0; + + reg [5:0] decim_counter = 0; + reg signed [31:0] comb_0 = 0, comb_1 = 0, comb_2 = 0; + reg signed [31: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) + always @(posedge clk) begin + if (rst) begin + integrator_0 <= 0; + integrator_1 <= 0; + integrator_2 <= 0; + end else begin + integrator_0 <= integrator_0 + (pdm_in ? 1 : -1); + integrator_1 <= integrator_1 + integrator_0; + integrator_2 <= integrator_2 + integrator_1; + end + end + + // Decimation counter + always @(posedge clk) begin + if (rst) + decim_counter <= 0; + else + decim_counter <= decim_counter + 1; + end + + // Comb stage (runs every DECIMATION clocks) + always @(posedge clk) begin + pcm_valid_r <= 0; + if (decim_counter == DECIMATION[5:0] - 1) 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; + + // Bit-shift down to get 16-bit output (tune shift based on DECIMATION and stage count) + pcm_out_r <= comb_2[31:16]; + pcm_valid_r <= 1; + end + end + + assign pcm_out = pcm_out_r; + assign pcm_valid = pcm_valid_r; + +endmodule |