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
128
129
130
131
132
133
134
135
|
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;
// Leaky integrator HPF registers
reg signed [23:0] hpf_integrator; // 24-bit for precision
reg signed [15:0] hpf_output;
// HPF calculation wires
wire signed [8:0] hpf_complement;
wire signed [23:0] hpf_scaled_input;
wire signed [23:0] hpf_dc_estimate;
/* verilator lint_off UNUSEDSIGNAL */
wire signed [23:0] hpf_temp_result;
/* verilator lint_on UNUSEDSIGNAL */
// HPF wire assignments
assign hpf_complement = 9'd256 - {1'b0, hpf_alpha};
assign hpf_scaled_input = {{8{scaled_out[15]}}, scaled_out};
assign hpf_dc_estimate = hpf_integrator >>> 8;
assign hpf_temp_result = hpf_scaled_input - hpf_dc_estimate;
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
// Leaky integrator-based DC blocker
// y[n] = x[n] - dc_estimate
// dc_estimate[n] = alpha/256 * dc_estimate[n-1] + (1-alpha/256) * x[n]
always @(posedge clk) begin
if (rst) begin
hpf_integrator <= 0;
hpf_output <= 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
// Update leaky integrator (DC estimate)
// integrator = alpha * integrator + (256-alpha) * input
hpf_integrator <= (hpf_alpha * hpf_dc_estimate) +
(hpf_complement * hpf_scaled_input);
// Output = input - DC estimate
hpf_output <= hpf_temp_result[15:0];
pcm_out <= hpf_output;
end
pcm_valid <= 1;
end
end
end
endmodule
|