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


// ============================================================================
// multi_melody_player_top
// Платформа: EPM7064, 12 МГц, кнопки инвертированы (0=нажата),
// 4 статических 7-сегм. индикатора (dig0..dig3), LED[7:0], speaker.
// ============================================================================
module multi_melody_player_top (
    input  wire         clk,
    input  wire [7:0]   btn,          // активный уровень 0
    output wire [7:0]   led,
    output wire [7:0]   dig0,         // правый индикатор (сегменты + точка)
    output wire [7:0]   dig1,
    output wire [7:0]   dig2,
    output wire [7:0]   dig3,         // левый индикатор
    output wire         speaker       // выход на динамик
);

// ---------------------------------------------------------------------------
// 1. Антидребезг и выбор мелодии (кнопки инвертированы)
// ---------------------------------------------------------------------------
reg [19:0] debounce_cnt = 0;
wire sample_tick = (debounce_cnt == 20'd1_200_000); // ~0.1 сек при 12 МГц
reg [7:0] btn_sync1 = 8'hFF, btn_sync2 = 8'hFF;
reg [7:0] stable_btn = 8'hFF; // инвертированное значение (1 = нажата)
reg [2:0] melody_select = 3'd0;

always @(posedge clk) begin
    debounce_cnt <= debounce_cnt + 1'b1;
    if (sample_tick) begin
        debounce_cnt <= 0;
        btn_sync1 <= ~btn;              // инвертируем, чтобы 1 = нажата
        btn_sync2 <= btn_sync1;
        if (btn_sync1 == btn_sync2)     // стабильно две выборки подряд
            stable_btn <= btn_sync1;
    end
end

// Приоритетный шифратор 8->3 (можно заменить на casez)
always @* begin
    casez(stable_btn)
        8'b1???_????: melody_select = 3'd7;
        8'b01??_????: melody_select = 3'd6;
        8'b001?_????: melody_select = 3'd5;
        8'b0001_????: melody_select = 3'd4;
        8'b0000_1???: melody_select = 3'd3;
        8'b0000_01??: melody_select = 3'd2;
        8'b0000_001?: melody_select = 3'd1;
        8'b0000_0001: melody_select = 3'd0;
        default:      melody_select = 3'd0; // ничего не нажато – мелодия 0
    endcase
end

// ---------------------------------------------------------------------------
// 2. Генератор темпа (шаг = 1/16 нота при ♩=60 -> 0.25 сек)
// ---------------------------------------------------------------------------
localparam [23:0] TEMPO_MAX = 24'd2_999_999;
reg [23:0] tempo_cnt = 0;
reg [5:0]  step_num  = 0;   // 64 шага для мелодии

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

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

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

        // Мелодия 2: Happy Birthday
        3'd2: case(step_num)
            6'd0: note_num = 4'd5; // G4
            6'd1: note_num = 4'd5;
            6'd2: note_num = 4'd6; // A4
            6'd3: note_num = 4'd5;
            6'd4: note_num = 4'd8; // C5
            6'd5: note_num = 4'd7; // B4
            6'd6,6'd7: note_num = 4'd5;
            6'd8: note_num = 4'd5;
            6'd9: note_num = 4'd6;
            6'd10: note_num = 4'd5;
            6'd11: note_num = 4'd9; // D5
            6'd12,6'd13: note_num = 4'd8; // C5
            6'd14,6'd15: note_num = 4'd5;
            default: note_num = 4'd0;
        endcase

        // Мелодии 3–7 – можно добавить аналогично (Имперский марш, Jingle Bells и т.д.)
        default: note_num = 4'd0;
    endcase
end

// ---------------------------------------------------------------------------
// 4. Таблица делителей частоты (16 нот, 16-битный делитель)
// ---------------------------------------------------------------------------
reg [15:0] clkdivider;
always @* begin
    case(note_num)
        4'd0: clkdivider = 16'd0;
        4'd1: clkdivider = 16'h5996; // C4 261.63
        4'd2: clkdivider = 16'h4FD2; // D4 293.66
        4'd3: clkdivider = 16'h471A; // E4 329.63
        4'd4: clkdivider = 16'h431F; // F4 349.23
        4'd5: clkdivider = 16'h3BCA; // G4 392.00
        4'd6: clkdivider = 16'h3544; // A4 440.00
        4'd7: clkdivider = 16'h2F74; // B4 493.88
        4'd8: clkdivider = 16'h2CCB; // C5 523.25
        4'd9: clkdivider = 16'h27E9; // D5 587.33
        4'd10: clkdivider = 16'h238D; // E5 659.26
        4'd11: clkdivider = 16'h218F; // F5 698.46
        4'd12: clkdivider = 16'h1DE5; // G5 783.99
        4'd13: clkdivider = 16'h1AA2; // A5 880.00
        4'd14: clkdivider = 16'h3245; // Bb4 466.16
        4'd15: clkdivider = 16'h5490; // C#4 (Db4) 277.18
        default: clkdivider = 16'd0;
    endcase
end

// ---------------------------------------------------------------------------
// 5. Генератор звука (меандр) с паузой
// ---------------------------------------------------------------------------
reg [15:0] counter = 0;
reg        audio_reg = 0;

always @(posedge clk) begin
    if (clkdivider == 16'd0) begin
        counter <= 0;
        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 speaker = audio_reg;

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

// ---------------------------------------------------------------------------
// 7. Статическая 7-сегментная индикация (dig0..dig3)
// ---------------------------------------------------------------------------
// Формат дисплея (слева направо):
// dig3: номер мелодии (0..7)
// dig2: код ноты (0..F)
// dig1: октава (4 или 5) или '-' (0xA)
// dig0: 'P' если пауза, иначе погашен (0xF)
// -------------------------------------------------
wire [3:0] dig3_data = {1'b0, melody_select};    // 0..7
wire [3:0] dig2_data = note_num;                 // 0..15
reg  [3:0] octave_disp;
always @* begin
    case(note_num)
        4'd1,4'd2,4'd3,4'd4,4'd5,4'd6,4'd7,
        4'd14,4'd15: octave_disp = 4'd4; // октава 4
        4'd8,4'd9,4'd10,4'd11,4'd12,4'd13: octave_disp = 4'd5;
        default: octave_disp = 4'd10; // '-'
    endcase
end
wire [3:0] dig1_data = octave_disp;
wire [3:0] dig0_data = (note_num == 4'd0) ? 4'd16 : 4'd15; // 16='P', 15=пусто

// Функция 4 бита -> 7-сегментный код (a..g, dp=0)
function [7:0] nibble_to_seg;
    input [4:0] nibble; // 5 бит для специального символа P (16)
    begin
        case(nibble)
            5'd0: nibble_to_seg = 8'b11111100; // 0
            5'd1: nibble_to_seg = 8'b01100000; // 1
            5'd2: nibble_to_seg = 8'b11011010; // 2
            5'd3: nibble_to_seg = 8'b11110010; // 3
            5'd4: nibble_to_seg = 8'b01100110; // 4
            5'd5: nibble_to_seg = 8'b10110110; // 5
            5'd6: nibble_to_seg = 8'b10111110; // 6
            5'd7: nibble_to_seg = 8'b11100000; // 7
            5'd8: nibble_to_seg = 8'b11111110; // 8
            5'd9: nibble_to_seg = 8'b11110110; // 9
            5'd10: nibble_to_seg = 8'b00000010; // '-'
            5'd11: nibble_to_seg = 8'b11111100; // (пусто – можно всё выкл)
            5'd12: nibble_to_seg = 8'b11111100;
            5'd13: nibble_to_seg = 8'b11111100;
            5'd14: nibble_to_seg = 8'b11111100;
            5'd15: nibble_to_seg = 8'b00000000; // всё выключено
            5'd16: nibble_to_seg = 8'b00110010; // 'P' (приблизительно)
            default: nibble_to_seg = 8'b00000000;
        endcase
    end
endfunction

assign dig0 = nibble_to_seg({1'b0, dig0_data}); // расширяем до 5 бит
assign dig1 = nibble_to_seg({1'b0, dig1_data});
assign dig2 = nibble_to_seg({1'b0, dig2_data});
assign dig3 = nibble_to_seg({1'b0, dig3_data});

endmodule