summaryrefslogtreecommitdiff
path: root/cocotb_try/cic3_pdm.v
blob: 4e8d664c467ed485b87c31b52e48ddff79b608db (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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)
    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
);

    // 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_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
            integrator1 <= 0;
            integrator2 <= 0;
        end else begin
            integrator1 <= integrator1 + pdm_signed;
            integrator2 <= integrator2 + integrator1;
        end
    end
    
    // Decimation counter and CIC comb stages
    always @(posedge clk) begin
        if (rst) begin
            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
    
    // 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
        if (rst) begin
            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
        end
    end

endmodule