Загрузка данных
// ============================================================================
// 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