initial
[fpgammix.git] / rtl / pdm.v
blob6472526bbdb5960a54f89a794e6f36a1cd38fb14
1 module pdm(clk, level, O);
3 parameter N = 16; /* The resolution in bits */
6 input wire clk;
7 input wire [N-1:0] level;
8 output wire O;
11 * A completely ridiculous side project. Pulse Density Modulation
12 * for controlling led intensity. The theory is pretty simple:
13 * given a desired target level 0 <= T <= 1, control the output O
14 * in {1,0}, such that O on on average is T. Do this by
15 * integrating the error T - O over time and switching O such that
16 * the sum of (T - O) is finite.
18 * S = 0, O = 0
19 * forever
20 * S = S + (T - O)
21 * if (S >= 0)
22 * O = 1
23 * else
24 * O = 0
26 * Check: T=0, O is never turned on; T=1, O is always on; T=0.5, O toggles
28 * In fixed point arithmetic this becomes even simpler (assume N-bit arith)
29 * S = Sf * 2^N = Sf << N. As |S| <= 1, N+2 bits is sufficient
31 * S = 0, O = 0
32 * forever
33 * D = T + (~O + 1) << N === T + (O << N) + (O << (N+1))
34 * S = S + D
35 * O = 1 & ~(S >> (N+1))
38 reg [N+1:0] sigma = 0;
39 assign O = ~sigma[N+1];
40 always @(posedge clk) sigma <= sigma + {O,O,level};
41 endmodule // pdm