Dac pcm5102¶
// BCK -> bclk Bit Clock (Тактирование бит)
// OUT (или DIN) -> dout Data In (Серийные данные)
// LRCK -> lrck Word Select (Левый/Правый канал)
// SCK -> GND (на плате модуля часто уже есть перемычка) или подать clk
// VCC -> 3.3V
// GND -> GND
/*
Перемычки для пайки:
H1L: FLT - Выбор фильтра: Нормальная задержка (Низкая) / Низкая задержка (Высокая)
H2L: DEMP - Управление де-эмфазисом для частоты дискретизации 44.1 кГц: Выкл (Низкая) / Вкл (Высокая)
H3L: XSMT - Управление мягким отключением звука: Мягкое отключение звука (Низкая) / Мягкое включение звука (Высокая)
H4L: FMT - Выбор аудиоформата: I2S (Низкая) / Left justified (Высокая)
Обычно работает без всякой пайки! Однако, если возникнут какие-либо проблемы, предлагаю попробовать с
FLT:Низкая, DEMP: Низкая, XSMT: Высокая, FMT: Низкая”
Эти платы приходят в приглушенном состоянии.
Чтобы включить звук, нужно подтянуть XSMT к высокому уровню.
Можно припаять перемычку 3 к H на задней стороне платы или соединить вывод "3" с A3V3 (тот, что между выводом 4 и G).
Состояние подтяжки FMT важно для чистого звука. Если подтянуть неправильно, звук может быть искажен.
Характеристики
Разрешение ЦАП До 32 бит
Частота дискретизации (макс.) 384 кГц
Динамический диапазон 112 дБ
Отношение сигнал/шум 112 дБ
Выходное напряжение (RMS) 2.1 В
Интерфейс I2S
Напряжение питания От 2.7 до 3.6 В (для чипа); модули обычно используют 3.3 В или 5 В
Таблица настроек для популярных частот
Частота (Fs) Нужный CLK (256 * Fs) Делитель (bclk_divider) BCLK (Fs * 64)
44.1 кГц 11.2896 МГц 2 (т.к. 11.28/2.82/2) 2.8224 МГц
48 кГц 12.288 МГц 2 3.072 МГц
48 кГц 24.576 МГц 4 3.072 МГц
96 кГц 24.576 МГц 2 6.144 МГц
192 кГц 49.152 МГц 2 12.288 МГц
I2S Format: 24-bit, 64 BCLKs per frame, MSB first, 1-bit delay after LRCK
*/
module dac_pcm5102 #(
parameter RATIO = 4 // Делитель для BCLK (по умолчанию 4 для 48кГц при 24.576МГц)
)(
input wire clk, // Основной тактовый сигнал (н-р, 24.576 МГц) SCK
input wire rst_n, // reset удерживается в низком состоянии во время перенастройки тактовых генераторов
input wire [23:0] data_left, // Входные данные левого канала
input wire [23:0] data_right, // Входные данные правого канала
input wire data_valid, // Импульс готовности новых данных
output reg bclk, // Bit Clock на PCM5102 BCK
output reg lrck, // Left/Right Clock (WS) LRCK
output reg dout, // Data Out OUT (или DIN)
output reg data_req // Запрос на новые данные (для AGC/Фильтров)
);
// Параметры для частоты 48 кГц при clk 24.576 МГц:
// BCLK = 48кГц * 64 = 3.072 МГц. Делитель = 24.576 / 3.072 / 2 = 4.
reg [7:0] bclk_divider;
reg [5:0] bit_cnt; // Счетчик бит (0-63)
reg [63:0] shift_reg; // Сдвиговый регистр для двух каналов
// Генерация BCLK (Bit Clock)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
bclk_divider <= 0;
bclk <= 0;
end else begin
if (bclk_divider == RATIO - 1) begin
bclk_divider <= 0;
bclk <= ~bclk;
end else begin
bclk_divider <= bclk_divider + 1'b1;
end
end
end
// Основная логика передачи (по спаду BCLK для стабильности на PCM5102)
always @(negedge bclk or negedge rst_n) begin
if (!rst_n) begin
bit_cnt <= 6'd63;
lrck <= 1'b1;
dout <= 0;
shift_reg <= 0;
data_req <= 0;
end else begin
// Управление счетчиком и LRCK
if (bit_cnt == 63) begin
bit_cnt <= 0;
lrck <= 1'b0; // Начало левого канала
data_req <= 1'b1;
end else begin
bit_cnt <= bit_cnt + 1'b1;
data_req <= 0;
if (bit_cnt == 31) begin
lrck <= 1'b1; // Начало правого канала
end
end
// Логика загрузки и сдвига (одновременно)
if (bit_cnt == 63) begin
// Загружаем данные. Сразу ставим MSB левого канала в dout.
// Формат: {MSB, остальные_биты...}
// Для I2S MSB идет первым после паузы в 1 бит.
// I2S формат: данные начинаются со 2-го такта BCLK (отступ 1 бит)
// Формируем 64-битный фрейм: {L_data(24), 8'z, R_data(24), 8'z}
// Если PCM5102 будет «хрипеть» или вы услышите щелчки, попробуйте изменить строку загрузки данных,
// добавив один нулевой бит в начале, чтобы сдвинуть данные на 1 такт:
// shift_reg <= {1'b0, data_left, 7'd0, data_right, 8'd0}; //(для классического I2S).
// shift_reg <= {data_left, 8'd0, data_right, 8'd0};
shift_reg <= {data_left, 8'd0, data_right, 8'd0};
dout <= 1'b0; // 1 бит задержки перед данными по стандарту I2S
end else begin
dout <= shift_reg[63];
shift_reg <= {shift_reg[62:0], 1'b0};
end
end
end
endmodule