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


// ============================================================
//  Модуль: multi_melody_player
//  8 мелодий, выбираемых кнопками btn[7:0]
//  LED индикация: [7:0] показывают номер выбранной мелодии
//  и текущий шаг.
//  4-разрядный 7-сегм. дисплей: номер мелодии, символ ноты,
//  октава, P (пауза) или длительность.
//  Тактовая: 12 МГц, темп фиксированный ♩=60.
// ============================================================
module multi_melody_player(
    input  wire         clk,
    input  wire [7:0]   btn,       // кнопки выбора мелодии
    output wire [7:0]   led,       // светодиоды
    output wire [6:0]   seg,       // сегменты A..G (общий катод)
    output wire [3:0]   an,        // аноды (выбор разряда)
    output wire         audio
);

// ----------------------------------------------------------
// Антидребезг кнопок + выбор активной мелодии
// ----------------------------------------------------------
reg [19:0] debounce_cnt = 0;  // примерно 20 мс при 12 МГц (240000 тактов)
// Для простоты будем считывать кнопки каждые 2^19 /12e6 ≈ 43 мс
wire sample_tick = (debounce_cnt == 20'd1_000_000); // ~83 мс на самом деле, можно точнее
reg [7:0] btn_r1 = 8'hFF, btn_r2 = 8'hFF;
reg [7:0] stable_btn = 8'h00;
reg [2:0] melody_select = 3'd0; // выбранная мелодия 0..7

always @(posedge clk) begin
    debounce_cnt <= debounce_cnt + 1'b1;
    if (sample_tick) begin
        btn_r1 <= btn;
        btn_r2 <= btn_r1;
        if (btn_r1 == btn_r2) // стабильно в течение двух выборок
            stable_btn <= btn_r1;
    end
end

// Приоритетный шифратор 8 в 3 (можно простой энкодер)
always @* begin
    casez(stable_btn)
        8'b1111_1110: melody_select = 3'd0;
        8'b1111_1101: melody_select = 3'd1;
        8'b1111_1011: melody_select = 3'd2;
        8'b1111_0111: melody_select = 3'd3;
        8'b1110_1111: melody_select = 3'd4;
        8'b1101_1111: melody_select = 3'd5;
        8'b1011_1111: melody_select = 3'd6;
        8'b0111_1111: melody_select = 3'd7;
        default:      melody_select = 3'd0; // если ничего не нажато
    endcase
end

// ----------------------------------------------------------
// Генератор темпа (как раньше)
// ----------------------------------------------------------
localparam [23:0] TEMPO_MAX = 24'd2_999_999; // 0.25 с на шаг
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

// ----------------------------------------------------------
// ПЗУ мелодий (таблица шаг -> код ноты)
// для каждой из 8 мелодий. Здесь заполним только первые 3,
// остальные можно сделать аналогично.
// ----------------------------------------------------------
reg [3:0] note_num;
always @* begin
    case(melody_select)
        3'd0:  // Дебюсси (те же данные, что и раньше, но ноты из новой таблицы)
            case(step_num)
                6'd0,6'd1: note_num = 4'd4; // F4
                6'd2,6'd3: note_num = 4'd14; // Bb4
                6'd4,6'd5: note_num = 4'd15; // Db4 (C#4)
                // ... далее заполнить соответственно новым кодам
                default: note_num = 4'd0;
            endcase

        3'd1:  // Ода к радости (упрощённо)
            case(step_num)
                6'd0,6'd1: note_num = 4'd3; // E4
                6'd2,6'd3: note_num = 4'd3; // E4
                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; // G4
                6'd10,6'd11: note_num = 4'd4; // F4
                6'd12,6'd13: note_num = 4'd3; // E4
                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; // C4
                6'd20,6'd21: note_num = 4'd2; // D4
                6'd22,6'd23: note_num = 4'd3; // E4
                6'd24,6'd25,6'd26,6'd27: note_num = 4'd3; // E4 (четверть с точкой)
                6'd28,6'd29: note_num = 4'd2; // D4
                6'd30,6'd31: note_num = 4'd2; // D4
                default: note_num = 4'd0;
            endcase

        3'd2:  // Happy Birthday
            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; // G4 G4
                6'd8,6'd9: note_num = 4'd5; // G4
                6'd10,6'd11: note_num = 4'd6; // A4
                6'd12,6'd13: note_num = 4'd5; // G4
                6'd14,6'd15: note_num = 4'd9; // D5
                6'd16,6'd17: note_num = 4'd8; // C5
                6'd18,6'd19: note_num = 4'd5; // G4
                default: note_num = 4'd0;
            endcase

        // ... ещё 5 мелодий аналогично
        default: note_num = 4'd0;
    endcase
end

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

// ----------------------------------------------------------
// Генератор звука (аналогичен предыдущему)
// ----------------------------------------------------------
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 audio = audio_reg;

// ----------------------------------------------------------
// LED индикация: показываем выбранную мелодию на 3 битах,
// и анимируем младшие 5 бит по step_num (для эффекта)
// ----------------------------------------------------------
wire [2:0] led_melody = melody_select;
wire [4:0] led_step   = step_num[4:0];
assign led = {led_melody, led_step}; // 8 бит

// ----------------------------------------------------------
// Динамическая индикация для 4х 7-сегм. индикаторов
// ----------------------------------------------------------
// Разряды: an[3] = левый, an[0] = правый
// Назначение:
// an[3] -> номер мелодии (0-7)
// an[2] -> символ ноты (C,D,E,F,G,A,B,P или диез/бемоль) – упростим до цифры кода ноты 0..15
// an[1] -> октава (3,4,5) или '-'
// an[0] -> 'P' если пауза, иначе пробел/ничего
// Для простоты будем выводить шестнадцатеричные цифры, соответствующие кодам.
// Таблица символов 7-сегм (0..F), общий катод.
//-----------------------------------------------------------
reg [15:0] seg_data; // 4 ниббла
always @* begin
    seg_data[15:12] = {1'b0, melody_select};   // номер мелодии 0..7
    seg_data[11:8]  = note_num;                // код ноты
    // октава: определим по note_num (C4..B4 => октава 4, C5..A5 => октава 5)
    case(note_num)
        4'd1,4'd2,4'd3,4'd4,4'd5,4'd6,4'd7,4'd14,4'd15: seg_data[7:4] = 4'h4;
        4'd8,4'd9,4'd10,4'd11,4'd12,4'd13: seg_data[7:4] = 4'h5;
        default: seg_data[7:4] = 4'hA; // "-"
    endcase
    seg_data[3:0] = (note_num == 4'd0) ? 4'hP : 4'hF; // P (код 16) или F (пусто)
end

// Сканирование индикаторов с частотой ~1 кГц
reg [16:0] scan_cnt = 0;
wire scan_tick = (scan_cnt == 17'd119999); // 100 Гц на разряд
reg [1:0] digit_sel = 0;

always @(posedge clk) begin
    scan_cnt <= scan_cnt + 1'b1;
    if (scan_tick) begin
        scan_cnt <= 0;
        digit_sel <= digit_sel + 1'b1;
    end
end

// Дешифратор выбора разряда
reg [3:0] an_reg;
always @* begin
    case(digit_sel)
        2'b00: an_reg = 4'b1110; // правый
        2'b01: an_reg = 4'b1101;
        2'b10: an_reg = 4'b1011;
        2'b11: an_reg = 4'b0111; // левый
        default: an_reg = 4'b1111;
    endcase
end
assign an = an_reg;

// Мультиплексор данных для сегментов
reg [3:0] current_nibble;
always @* begin
    case(digit_sel)
        2'b00: current_nibble = seg_data[3:0];
        2'b01: current_nibble = seg_data[7:4];
        2'b10: current_nibble = seg_data[11:8];
        2'b11: current_nibble = seg_data[15:12];
        default: current_nibble = 4'h0;
    endcase
end

// Преобразователь 4 бит -> 7 сегментов (a,b,c,d,e,f,g)
function [6:0] hex_to_7seg;
    input [3:0] hex;
    begin
        case(hex)
            4'h0: hex_to_7seg = 7'b1000000; // 0
            4'h1: hex_to_7seg = 7'b1111001; // 1
            4'h2: hex_to_7seg = 7'b0100100; // 2
            4'h3: hex_to_7seg = 7'b0110000; // 3
            4'h4: hex_to_7seg = 7'b0011001; // 4
            4'h5: hex_to_7seg = 7'b0010010; // 5
            4'h6: hex_to_7seg = 7'b0000010; // 6
            4'h7: hex_to_7seg = 7'b1111000; // 7
            4'h8: hex_to_7seg = 7'b0000000; // 8
            4'h9: hex_to_7seg = 7'b0010000; // 9
            4'hA: hex_to_7seg = 7'b0001000; // A
            4'hB: hex_to_7seg = 7'b0000011; // b
            4'hC: hex_to_7seg = 7'b1000110; // C
            4'hD: hex_to_7seg = 7'b0100001; // d
            4'hE: hex_to_7seg = 7'b0000110; // E
            4'hF: hex_to_7seg = 7'b1111111; // всё выкл (или 0)
            4'hP: hex_to_7seg = 7'b0001100; // P (приблизительно)
            default: hex_to_7seg = 7'b1111111;
        endcase
    end
endfunction

assign seg = hex_to_7seg(current_nibble);

endmodule