Загрузка данных


// ============================================================================
//  Модуль: debussy_melody
//  Воспроизводит фрагмент прелюдии К.Дебюсси "Девушка с волосами цвета льна"
//  через однобитный PWM-выход (или простой меандр) для прямого подключения
//  к пьезодинамику / RC-фильтру + усилителю.
//
//  Тактовая частота: 12 МГц
//  Разрядность нот:  16 бит (точность частот ~0.2..0.5 Гц)
//  Темп:             ♩ = 60 (медленно, четверть = 1 сек)
//  Длительность шага: 1/16 нота (0.25 сек)
//  Размер мелодии:    64 шага (4 такта по 3/4, циклически)
// ============================================================================

module debussy_melody(
    input  wire clk,      // 12 МГц
    output wire audio     // 1-битный звук
);

// ---------------------------------------------------------------------------
// 1. Генератор темпа – задаёт длительность одного шага мелодии
//    Чтобы получить шаг 0.25 сек (1/16 при ♩=60):
//    TEMPO_MAX = 0.25 * 12e6 - 1 = 2 999 999
//    Если нужно изменить темп, меняйте это значение.
// ---------------------------------------------------------------------------
localparam [23:0] TEMPO_MAX = 24'd2_999_999; // 0.25 сек при 12 МГц

reg [23:0] tempo_cnt = 24'd0;
reg [5:0]  step_num  = 6'd0;       // 64 шага (0..63)

always @(posedge clk) begin
    if (tempo_cnt == TEMPO_MAX) begin
        tempo_cnt <= 24'd0;
        step_num  <= step_num + 1'b1;   // автоматический сброс на 0 после 63
    end else begin
        tempo_cnt <= tempo_cnt + 1'b1;
    end
end

// ---------------------------------------------------------------------------
// 2. Нотная последовательность (ПЗУ мелодии)
//    Каждому шагу соответствует код ноты (0 – пауза, 1..13 – ноты)
//    Здесь записана первая фраза (такты 1–4) и небольшое продолжение.
// ---------------------------------------------------------------------------
reg [3:0] note_num; // 4 бита позволяют задать до 16 разных звуков

always @* begin
    case(step_num)
        // Такт 1 (3/4): Gb3(8-я) Bb3(8-я) Db4(8-я) Gb4(8-я с точкой) Ab4(16-я)
        6'd0, 6'd1:                          note_num = 4'd2;   // Gb3 (восьмая = 2 шага)
        6'd2, 6'd3:                          note_num = 4'd4;   // Bb3
        6'd4, 6'd5:                          note_num = 4'd6;   // Db4
        6'd6, 6'd7, 6'd8:                    note_num = 4'd9;   // Gb4 (восьмая с точкой = 3 шага)
        6'd9:                                note_num = 4'd10;  // Ab4 (шестнадцатая = 1 шаг)

        // Такт 2: Gb4(16-я) F4(8-я) Eb4(8-я с точкой) Db4(16-я)
        6'd10:                               note_num = 4'd9;   // Gb4
        6'd11, 6'd12:                        note_num = 4'd8;   // F4  (восьмая)
        6'd13, 6'd14, 6'd15:                 note_num = 4'd7;   // Eb4 (восьмая с точкой)
        6'd16:                               note_num = 4'd6;   // Db4 (шестнадцатая)

        // Пауза восьмая (2 шага)
        6'd17, 6'd18:                        note_num = 4'd0;   // тишина

        // Такт 3: Db4(8-я) Cb4(8-я) Db4(8-я) Eb4(четверть)
        6'd19, 6'd20:                        note_num = 4'd6;   // Db4
        6'd21, 6'd22:                        note_num = 4'd5;   // Cb4 (B3)
        6'd23, 6'd24:                        note_num = 4'd6;   // Db4
        6'd25, 6'd26, 6'd27, 6'd28:          note_num = 4'd7;   // Eb4 (четверть = 4 шага)

        // Такт 4: F4(8-я с точкой) Gb4(16-я) F4(8-я) Eb4(8-я) Db4(четверть)
        6'd29, 6'd30, 6'd31:                 note_num = 4'd8;   // F4
        6'd32:                               note_num = 4'd9;   // Gb4
        6'd33, 6'd34:                        note_num = 4'd8;   // F4
        6'd35, 6'd36:                        note_num = 4'd7;   // Eb4
        6'd37, 6'd38, 6'd39, 6'd40:          note_num = 4'd6;   // Db4 (четверть)

        // Оставшиеся шаги зацикливаем паузой (можно повторить мелодию)
        default:                             note_num = 4'd0;
    endcase
end

// ---------------------------------------------------------------------------
// 3. Таблица частот – преобразует код ноты в коэффициент деления
//    Для каждой ноты вычислен N = 12e6 / (2*F) - 1, округлённый до целого.
//    Нота 0 -> clkdivider = 0 (специальный код для паузы).
// ---------------------------------------------------------------------------
reg [15:0] clkdivider;

always @* begin
    case(note_num)
        4'd0:  clkdivider = 16'd0;           // пауза
        4'd1:  clkdivider = 16'd34366;       // F3   174.61 Гц
        4'd2:  clkdivider = 16'd32432;       // Gb3  185.00 Гц
        4'd3:  clkdivider = 16'd28895;       // Ab3  207.65 Гц
        4'd4:  clkdivider = 16'd25739;       // Bb3  233.08 Гц
        4'd5:  clkdivider = 16'd24296;       // Cb4 (B3) 246.94 Гц
        4'd6:  clkdivider = 16'd21648;       // Db4  277.18 Гц
        4'd7:  clkdivider = 16'd19284;       // Eb4  311.13 Гц
        4'd8:  clkdivider = 16'd17183;       // F4   349.23 Гц
        4'd9:  clkdivider = 16'd16215;       // Gb4  369.99 Гц
        4'd10: clkdivider = 16'd14447;       // Ab4  415.30 Гц
        4'd11: clkdivider = 16'd12869;       // Bb4  466.16 Гц
        4'd12: clkdivider = 16'd12148;       // Cb5 (B4) 493.88 Гц
        4'd13: clkdivider = 16'd10824;       // Db5  554.37 Гц
        default: clkdivider = 16'd0;
    endcase
end

// ---------------------------------------------------------------------------
// 4. Генератор звука (с коррекцией паузы)
//    Если clkdivider == 0 (пауза), выход жёстко удерживается в 0.
//    Иначе работает классический счётчик-делитель с автоперезагрузкой,
//    генерируя меандр (прямоугольную волну).
// ---------------------------------------------------------------------------
reg [15:0] counter = 16'd0;
reg        audio_reg = 1'b0;

always @(posedge clk) begin
    if (clkdivider == 16'd0) begin
        // Пауза: сбрасываем всё и держим низкий уровень
        counter   <= 16'd0;
        audio_reg <= 1'b0;
    end else begin
        if (counter == 16'd0) begin
            counter   <= clkdivider;
            audio_reg <= ~audio_reg;   // переключение меандра
        end else begin
            counter   <= counter - 1'b1;
        end
    end
end

assign audio = audio_reg;

endmodule