§ Описание

Этот модуль сделан специально для платы Марсоход2, а точнее говоря, для его шилда коннектов. Конечно, его можно адаптировать для каких угодно проектов, просто там создана особая схема, которую, если переделывать, надо тоже учитывать.
Схема этого шилда я прикрепил в этом PDF.

Модуль генерирует некоторый уровень напряжения на выходе, основываясь на скорости обновления 0 или 1 на входе. То есть уровень напряжения напрямую зависит от скважности 0 и 1 на входе, то есть, другими словами, двоичный сигнал на 1 проводе преобразуется в аналоговый.

§ Верхний уровень

PWM-модуль для преобразования числа 0..255 в PWM для канала аудио на шилде Марсоход2
1audio_pwm AUDIO_PWM(
2
3    .clk  (clk),                  // 100 MHz
4    .vol  (...),                  // громкость 0..255 [0..1]
5    .pwm  (sound_left)            // sound_left или sound_right, либо другой wire
6);

§ Код

PWM-модуль для преобразования числа 0..255 в PWM для канала аудио на шилде Марсоход2
1module audio_pwm(
2
3    input  wire       clk,    // 100 mhz
4    input  wire [7:0] vol,    // 0..255
5    output reg        pwm     // 0/1
6
7);
8
9    reg [9:0] DeltaAdder; // Output of Delta adder
10    reg [9:0] SigmaAdder; // Output of Sigma adder
11    reg [9:0] SigmaLatch; // Latches output of Sigma adder
12    reg [9:0] DeltaB;     // B input of Delta adder
13
14    always @(SigmaLatch)
15        DeltaB = {SigmaLatch[9], SigmaLatch[9]} << (8);
16
17    always @(vol or DeltaB)
18        DeltaAdder = vol + DeltaB;
19
20    always @(DeltaAdder or SigmaLatch)
21        SigmaAdder = DeltaAdder + SigmaLatch;
22
23    always @(posedge clk)
24    begin
25        SigmaLatch <= SigmaAdder;
26        pwm <=  SigmaLatch[9];
27    end
28
29endmodule

§ Бинауральные биения

Простой пример, который выдает нечто похожее на бинауральные ритмы
1audio_pwm AudioLf(
2
3    .clk  (clk),
4    .vol  (vol_lf),
5    .pwm  (sound_left)
6);
7
8audio_pwm AudioRt(
9
10    .clk  (clk),
11    .vol  (vol_rt),
12    .pwm  (sound_right)
13);
14
15// --------------------------------------------------------------------------
16integer lcnt;
17integer rcnt;
18integer ncnt;
19
20parameter vol = 1;
21
22// 1HZ = (25.000.000/2)
23// Nhz = (25.000.000/2)/N
24integer llen = 50000; // 250 hz
25integer rlen = 48076; // 260 hz
26
27always @(posedge clock_25) begin
28
29	lcnt <= lcnt + 1;
30	rcnt <= rcnt + 1;
31
32	if (lcnt > llen) begin lcnt <= 0; vol_lf <= vol_lf == 128-vol ? 128+vol : 128-vol; end
33	if (rcnt > rlen) begin rcnt <= 0; vol_rt <= vol_rt == 128-vol ? 128+vol : 128-vol; end
34
35end