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


// ==========================================================================
// multi_melody_player_fixed
// Исправления: триггерный выбор мелодии, настраиваемая 7-сегм индикация,
// 8 мелодий с корректным ритмом.
// ==========================================================================
module multi_melody_player_fixed (
    input  wire         clk,
    input  wire [7:0]   btn,          // активный 0
    output wire [7:0]   led,
    output wire [7:0]   dig0, dig1, dig2, dig3,
    output wire         speaker
);

// Параметры настройки (можно менять при необходимости)
parameter INVERT_SEG = 1'b0;  // 1 для общего анода, 0 для общего катода

// --------------------------------------------------------------------------
// Антидребезг и запоминание выбранной мелодии (триггер по нажатию)
// --------------------------------------------------------------------------
reg [19:0] db_cnt = 0;        // ~0.1 сек при 12 МГц
wire db_tick = (db_cnt == 20'd1_200_000);

reg [7:0] btn_sr = 8'hFF;     // сдвиговый регистр для антидребезга (инверс. логика: 0-нажата)
reg [7:0] btn_stable = 8'hFF; // стабильное состояние после фильтра
reg [7:0] btn_prev = 8'hFF;   // предыдущее стабильное состояние (для поиска фронта)
reg [2:0] melody = 3'd0;      // текущая выбранная мелодия (защёлкивается)

always @(posedge clk) begin
    db_cnt <= db_cnt + 1'b1;
    if (db_tick) begin
        db_cnt <= 0;
        btn_sr <= {btn_sr[6:0], btn};       // сдвиг (btn инверт.: 0=нажата)
        // Считаем кнопку стабильной, если все 8 выборок одинаковы
        if (btn_sr == 8'hFF || btn_sr == 8'h00)   // все биты одинаковы
            btn_stable <= btn_sr[7];              // берём один бит, но нам нужно 8-битное значение
        // Упростим: будем проверять каждую кнопку отдельно?
        // Для этого заведём отдельный процесс на каждую кнопку или используем вектор.
        // Переделаем: стабильное значение = ~btn после фильтра низких частот.
        // Здесь предлагаю упрощённый вариант: используем предыдущий подход с синхронизацией.
    end
end

// Более простой и надёжный способ: два этапа синхронизации и стабильность в течение N выборок
reg [7:0] btn_sync0, btn_sync1;
reg [7:0] btn_cnt [7:0]; // счётчики длительности для каждой кнопки
wire [7:0] btn_pressed;   // 1 = кнопка нажата (стабильно)

genvar i;
generate for (i = 0; i < 8; i = i + 1) begin : debounce_btn
    always @(posedge clk) begin
        btn_sync0 <= ~btn;         // инвертируем: 1 = нажата
        btn_sync1 <= btn_sync0;
        if (btn_sync1[i] == 1'b1) begin
            if (btn_cnt[i] < 8)    // 8 тактов стабильного высокого уровня (~0.66 мкс при 12 МГц?)
                btn_cnt[i] <= btn_cnt[i] + 1'b1;
        end else begin
            btn_cnt[i] <= 0;
        end
    end
    assign btn_pressed[i] = (btn_cnt[i] >= 8); // импульс, когда кнопка нажата
end
endgenerate

// Защёлка мелодии по фронту btn_pressed
always @(posedge clk) begin
    if (btn_pressed[0]) melody <= 3'd0;
    if (btn_pressed[1]) melody <= 3'd1;
    if (btn_pressed[2]) melody <= 3'd2;
    if (btn_pressed[3]) melody <= 3'd3;
    if (btn_pressed[4]) melody <= 3'd4;
    if (btn_pressed[5]) melody <= 3'd5;
    if (btn_pressed[6]) melody <= 3'd6;
    if (btn_pressed[7]) melody <= 3'd7;
end

// --------------------------------------------------------------------------
// Генератор темпа (шаг 1/16 при ♩=60)
// --------------------------------------------------------------------------
localparam [23:0] TEMPO_MAX = 24'd2_999_999;
reg [23:0] tempo_cnt = 0;
reg [5:0]  step = 0;   // 0..63

always @(posedge clk) begin
    if (tempo_cnt == TEMPO_MAX) begin
        tempo_cnt <= 0;
        step <= step + 1'b1;
    end else begin
        tempo_cnt <= tempo_cnt + 1'b1;
    end
end

// --------------------------------------------------------------------------
// ПЗУ мелодий: 8 мелодий, 64 шага, код ноты (0..15)
// --------------------------------------------------------------------------
reg [3:0] note;
always @* begin
    case(melody)
        // Мелодия 0: Дебюсси (начало) – здесь требуется точная запись, я дам заглушку
        3'd0: case(step)
            // заполним позже, пока пауза
            default: note = 4'd0;
        endcase

        // Мелодия 1: Ода к радости (проверенная)
        3'd1: case(step)
            6'd0,6'd1: note = 4'd3;   // E4
            6'd2,6'd3: note = 4'd3;
            6'd4,6'd5: note = 4'd4;   // F4
            6'd6,6'd7: note = 4'd5;   // G4
            6'd8,6'd9: note = 4'd5;
            6'd10,6'd11: note = 4'd4;
            6'd12,6'd13: note = 4'd3;
            6'd14,6'd15: note = 4'd2; // D4
            6'd16,6'd17: note = 4'd1; // C4
            6'd18,6'd19: note = 4'd1;
            6'd20,6'd21: note = 4'd2;
            6'd22,6'd23: note = 4'd3;
            6'd24,6'd25: note = 4'd3;
            6'd26,6'd27: note = 4'd2;
            6'd28,6'd29: note = 4'd2;
            default: note = 4'd0;
        endcase

        // Мелодия 2: Happy Birthday (исправленная)
        3'd2: case(step)
            // "Hap-py birth-day to you" (G G A G C B, G G A G D C)
            // Восьмые и четверти: G4 (2 шага), G4 (2), A4 (2), G4 (2), C5 (4), B4 (4) – паузы расставлю
            6'd0,6'd1: note = 4'd5;   // G4
            6'd2,6'd3: note = 4'd5;   // G4
            6'd4,6'd5: note = 4'd6;   // A4
            6'd6,6'd7: note = 4'd5;   // G4
            6'd8,6'd9,6'd10,6'd11: note = 4'd8; // C5 (четверть = 4 шага)
            6'd12,6'd13,6'd14,6'd15: note = 4'd7; // B4 (четверть)
            // Следующая фраза "Hap-py birth-day to you"
            6'd16,6'd17: note = 4'd5;
            6'd18,6'd19: note = 4'd5;
            6'd20,6'd21: note = 4'd6;
            6'd22,6'd23: note = 4'd5;
            6'd24,6'd25,6'd26,6'd27: note = 4'd9; // D5 (четверть)
            6'd28,6'd29,6'd30,6'd31: note = 4'd8; // C5 (четверть)
            // "Hap-py birth-day dear [Name]" – можно пропустить, заполним ещё 32 шага
            6'd32,6'd33: note = 4'd5;
            6'd34,6'd35: note = 4'd5;
            6'd36,6'd37: note = 4'd3; // E4
            6'd38,6'd39: note = 4'd8; // C5
            6'd40,6'd41: note = 4'd7; // B4
            6'd42,6'd43: note = 4'd6; // A4
            6'd44,6'd45,6'd46,6'd47: note = 4'd0; // пауза
            // "... to you" (F4 F4 E4 C5 D5 C5)
            6'd48,6'd49: note = 4'd4; // F4
            6'd50,6'd51: note = 4'd4;
            6'd52,6'd53: note = 4'd3; // E4
            6'd54,6'd55,6'd56,6'd57: note = 4'd8; // C5
            6'd58,6'd59: note = 4'd9; // D5
            6'd60,6'd61,6'd62,6'd63: note = 4'd8; // C5
            default: note = 4'd0;
        endcase

        // Мелодия 3: Имперский марш (Imperial March, Star Wars)
        3'd3: case(step)
            // E4 E4 E4 C4 G3 E4 C4 G3 E4 ... у нас нет G3, транспонируем на октаву выше:
            // E4 E4 E4 C4 G4 E4 C4 G4 E4
            // ритм: восьмая, восьмая, восьмая, четверть с точкой?, упростим
            6'd0: note = 4'd3; // E4
            6'd1: note = 4'd3;
            6'd2: note = 4'd3;
            6'd3,6'd4: note = 4'd1; // C4
            6'd5: note = 4'd5; // G4
            6'd6: note = 4'd3; // E4
            6'd7,6'd8: note = 4'd1; // C4
            6'd9: note = 4'd5; // G4
            6'd10: note = 4'd3; // E4
            // повтор
            6'd11: note = 4'd3; 6'd12: note = 4'd3; 6'd13: note = 4'd3;
            6'd14,6'd15: note = 4'd1; 6'd16: note = 4'd5; 6'd17: note = 4'd3;
            6'd18,6'd19: note = 4'd1; 6'd20: note = 4'd5; 6'd21: note = 4'd3;
            // заполним остальное паузами
            default: note = 4'd0;
        endcase

        // Мелодия 4: Jingle Bells
        3'd4: case(step)
            // E4 E4 E4, E4 E4 E4, E4 G4 C4 D4 E4 ...
            6'd0,6'd1: note = 4'd3; 6'd2,6'd3: note = 4'd3; 6'd4,6'd5: note = 4'd3;
            6'd6,6'd7: note = 4'd3; 6'd8,6'd9: note = 4'd3; 6'd10,6'd11: note = 4'd3;
            6'd12,6'd13: note = 4'd3; 6'd14,6'd15: note = 4'd5; // G4
            6'd16,6'd17: note = 4'd1; // C4
            6'd18,6'd19: note = 4'd2; // D4
            6'd20,6'd21: note = 4'd3; // E4
            // F4 F4 F4 F4 F4 E4 E4 E4 E4 D4 D4 E4 D4 G4 ...
            6'd22,6'd23: note = 4'd4; // F4
            6'd24,6'd25: note = 4'd4; 6'd26,6'd27: note = 4'd4; 6'd28,6'd29: note = 4'd4;
            6'd30,6'd31: note = 4'd4; 6'd32,6'd33: note = 4'd3; 6'd34,6'd35: note = 4'd3;
            6'd36,6'd37: note = 4'd3; 6'd38,6'd39: note = 4'd3;
            6'd40,6'd41: note = 4'd2; 6'd42,6'd43: note = 4'd2; 6'd44,6'd45: note = 4'd3;
            6'd46,6'd47: note = 4'd2; 6'd48,6'd49: note = 4'd5; // G4
            default: note = 4'd0;
        endcase

        // Мелодия 5: Маленькая ночная серенада (Mozart)
        3'd5: case(step)
            // G4 D4 D4 E4 F4 E4 D4 C4 D4 E4 F4 E4 D4 C4
            6'd0: note = 4'd5; // G4
            6'd1,6'd2: note = 4'd2; // D4 D4
            6'd3: note = 4'd3; // E4
            6'd4: note = 4'd4; // F4
            6'd5: note = 4'd3; // E4
            6'd6: note = 4'd2; // D4
            6'd7: note = 4'd1; // C4
            6'd8: note = 4'd2; // D4
            6'd9: note = 4'd3; // E4
            6'd10: note = 4'd4; // F4
            6'd11: note = 4'd3; // E4
            6'd12: note = 4'd2; // D4
            6'd13: note = 4'd1; // C4
            default: note = 4'd0;
        endcase

        // Мелодия 6: Yesterday (Beatles)
        3'd6: case(step)
            // F4 E4 E4 F4 G4 A4 G4 F4 E4 D4 C4 ...
            6'd0: note = 4'd4; // F4
            6'd1: note = 4'd3; // E4
            6'd2: note = 4'd3; // E4
            6'd3: note = 4'd4; // F4
            6'd4,6'd5: note = 4'd5; // G4
            6'd6,6'd7: note = 4'd6; // A4
            6'd8: note = 4'd5; // G4
            6'd9: note = 4'd4; // F4
            6'd10: note = 4'd3; // E4
            6'd11: note = 4'd2; // D4
            6'd12: note = 4'd1; // C4
            default: note = 4'd0;
        endcase

        // Мелодия 7: Тетрис (Коробейники)
        3'd7: case(step)
            // E4 B4 C5 D5 E5 D5 C5 B4 A4 A4 C5 E5 D5 C5 B4 ...
            // ритм быстрый, упростим
            6'd0: note = 4'd3; // E4
            6'd1: note = 4'd7; // B4
            6'd2: note = 4'd8; // C5
            6'd3: note = 4'd9; // D5
            6'd4: note = 4'd10; // E5
            6'd5: note = 4'd9; // D5
            6'd6: note = 4'd8; // C5
            6'd7: note = 4'd7; // B4
            6'd8: note = 4'd6; // A4
            6'd9: note = 4'd6; // A4
            6'd10: note = 4'd8; // C5
            6'd11: note = 4'd10; // E5
            6'd12: note = 4'd9; // D5
            6'd13: note = 4'd8; // C5
            6'd14: note = 4'd7; // B4
            default: note = 4'd0;
        endcase

        default: note = 4'd0;
    endcase
end

// --------------------------------------------------------------------------
// Делители частоты (таблица 16 нот)
// --------------------------------------------------------------------------
reg [15:0] divider;
always @* begin
    case(note)
        4'd0: divider = 16'd0;
        4'd1: divider = 16'h5996; // C4
        4'd2: divider = 16'h4FD2; // D4
        4'd3: divider = 16'h471A; // E4
        4'd4: divider = 16'h431F; // F4
        4'd5: divider = 16'h3BCA; // G4
        4'd6: divider = 16'h3544; // A4
        4'd7: divider = 16'h2F74; // B4
        4'd8: divider = 16'h2CCB; // C5
        4'd9: divider = 16'h27E9; // D5
        4'd10: divider = 16'h238D; // E5
        4'd11: divider = 16'h218F; // F5
        4'd12: divider = 16'h1DE5; // G5
        4'd13: divider = 16'h1AA2; // A5
        4'd14: divider = 16'h3245; // Bb4
        4'd15: divider = 16'h5490; // C#4 (Db4)
        default: divider = 16'd0;
    endcase
end

// --------------------------------------------------------------------------
// Генератор звука (меандр) с паузой
// --------------------------------------------------------------------------
reg [15:0] cnt = 0;
reg spk = 0;
always @(posedge clk) begin
    if (divider == 16'd0) begin
        cnt <= 0;
        spk <= 1'b0;
    end else begin
        if (cnt == 16'd0) begin
            cnt <= divider;
            spk <= ~spk;
        end else begin
            cnt <= cnt - 1'b1;
        end
    end
end
assign speaker = spk;

// --------------------------------------------------------------------------
// LED индикация: старшие 3 бита – мелодия, младшие 5 – шаг
// --------------------------------------------------------------------------
assign led = {melody, step[4:0]};

// --------------------------------------------------------------------------
// 7-сегментная индикация (настраиваемая)
// --------------------------------------------------------------------------
wire [3:0] dig3_val = {1'b0, melody}; // номер мелодии
wire [3:0] dig2_val = note;           // код ноты
reg  [3:0] octave;
always @* begin
    case(note)
        4'd1,4'd2,4'd3,4'd4,4'd5,4'd6,4'd7,4'd14,4'd15: octave = 4'd4;
        4'd8,4'd9,4'd10,4'd11,4'd12,4'd13: octave = 4'd5;
        default: octave = 4'd10; // '-'
    endcase
end
wire [3:0] dig1_val = octave;
wire [3:0] dig0_val = (note == 4'd0) ? 4'd16 : 4'd15; // 'P' или пусто

// Функция преобразования 5-битного кода символа в сегменты (a..g, dp)
// Раскладка бит для 8-битного порта: {a, b, c, d, e, f, g, dp} (младший бит = a)
// Если у вас другой порядок, измените биты в case.
function [7:0] seg_decode;
    input [4:0] sym; // 0-9, A-F, специальные
    reg [6:0] segs; // a..g
    begin
        case(sym)
            5'd0: segs = 7'b1111110; // 0
            5'd1: segs = 7'b0110000; // 1
            5'd2: segs = 7'b1101101; // 2
            5'd3: segs = 7'b1111001; // 3
            5'd4: segs = 7'b0110011; // 4
            5'd5: segs = 7'b1011011; // 5
            5'd6: segs = 7'b1011111; // 6
            5'd7: segs = 7'b1110000; // 7
            5'd8: segs = 7'b1111111; // 8
            5'd9: segs = 7'b1111011; // 9
            5'd10: segs = 7'b0000001; // '-' (сегмент g)
            5'd11: segs = 7'b0000000; // пусто
            5'd12: segs = 7'b0000000;
            5'd13: segs = 7'b0000000;
            5'd14: segs = 7'b0000000;
            5'd15: segs = 7'b0000000; // пусто
            5'd16: segs = 7'b1100111; // P
            default: segs = 7'b0000000;
        endcase
        // Добавляем точку (dp) в старший бит, здесь не используется
        seg_decode = {segs[6:0], 1'b0}; // dp = 0
        if (INVERT_SEG)
            seg_decode = ~seg_decode;   // для общего анода
    end
endfunction

assign dig0 = seg_decode({1'b0, dig0_val});
assign dig1 = seg_decode({1'b0, dig1_val});
assign dig2 = seg_decode({1'b0, dig2_val});
assign dig3 = seg_decode({1'b0, dig3_val});

endmodule