Comments 21
Сигнал уже не такой "красивый", но его частота 5 МГц.
Используя нехитрые целочисленные математические приёмы, можно ощутимо улучшить качество синуса.
По-моему, канал передачи данных проще генератором треугольника сделать, который многократно проще реализуется.
А прямо в питоне нельзя было посчитать синус? Зачем тут матлаб?
Рекомендую "A Technical Tutorial on Digital Signal Synthesis." Кратко:
Разрядность данных таблицы синуса - разрядность ЦАП плюс 2 бита;
Использовать симметрию синуса для сжатия ROM;
Фильтровать выход ЦАП.
Вероятно самый громоздкий и дорогой генератор синуса . Китайский модуль за 2 бакса умеет ... ну вы знаете . Зачем тут ПЛИС ? Реализуется на голой stm32 / esp32 без вот этого вот всего если Вы хотите в математику или на 1 транзисторе и колебательном контуре со средней точкой . Без питонов и прочих .
Даёшь PSK31 в массы на МК или ПЛИС
Я такое люблю, спасибо
Мой ответ https://habr.com/p/865480/
Если вы используете Матлаб, почему сразу не сгенерировать HDL файл NCO?
Ради интереса сгенерировал и скомпилировал NCO с 32-разрядным аккумулятором, 12-битной фазой и 9-разрядным выходным сигналом (синус и косинус). Получилось 79 логических элементов и 8192 бита памяти (Quartus + Cyclone IV).
Сергей, своим комментарием хочу поддержать Вас!
Вы потрясающе и кропотливо пишите свои статьи. Вкладываете все свои знания, весь свой опыт и делясь этим с огромной количеством людей!
Верю и даже не сомневаюсь, что Вы к каждому делу подходите основательно и достигаете профессионализма, там где это Вам действительно интересно!
Вы делаете огромный вклад, в этом я Вам лично очень признательна.
Желаю, что бы Ваша КАРМА росла только вверх, а Ваши статьи набирали все больше положительных откликов, были понятны для установленной аудитории и делали мир Хабра да и в целом мир лучше!
Успехов!
p.s. С удовольствием прочту еще Ваши статьи, пишите, у Вас это прекрасно получается!
Сергей, своим комментарием хочу поддержать Вас!
Вы потрясающе и кропотливо пишите свои статьи. Вкладываете все свои знания, весь свой опыт и делясь этим с огромным количеством людей!
Верю и даже не сомневаюсь, что Вы к каждому делу подходите основательно и достигаете профессионализма, там где это Вам действительно интересно!
Вы делаете огромный вклад, в этом я лично очень признательна.
Желаю, что бы Ваша карма росла только вверх, а Ваши статьи набирали все больше положительных откликов, были понятны для установленной аудитории и делали мир Хабра да и в целом мир лучше!
Успехов!
p.s. С удовольствием прочту еще Ваши статьи, пишите, у Вас это прекрасно получается!
Привет. Спасибо за статью.
Не уверен, что это так. Но понял так, что в памяти у вас целый период. А это не нужно. Можно ж только одну четверть в память положить. А дальше отзеркаливать.
module sinetabledds(
input wire CLK,
input wire RESET,
input wire [31:0] DDS,
output reg [31:0] out_sine
);
wire [2:0] table_idx;
assign table_idx = DDS[31:29];
always @ (posedge CLK)
begin
case (table_idx)
3'b000: out_sine <= 0.0000 * 32'hFFFFFFFF; //sin(0.0000) = 0.0000
3'b001: out_sine <= 0.1710 * 32'hFFFFFFFF; //sin(0.1718) = 0.1710
3'b010: out_sine <= 0.3599 * 32'hFFFFFFFF; //sin(0.3682) = 0.3599
3'b011: out_sine <= 0.5350 * 32'hFFFFFFFF; //sin(0.5645) = 0.5350
3'b100: out_sine <= 0.6895 * 32'hFFFFFFFF; //sin(0.7609) = 0.6895
3'b101: out_sine <= 0.8176 * 32'hFFFFFFFF; //sin(0.9572) = 0.8176
3'b110: out_sine <= 0.9142 * 32'hFFFFFFFF; //sin(1.1536) = 0.9142
3'b111: out_sine <= 0.9757 * 32'hFFFFFFFF; //sin(1.3499) = 0.9757
default: out_sine <= 0.0000 * 32'hFFFFFFFF;
endcase
end
endmodule
получаю прямое соответствие старших 3х бит значения ддс - значению синуса

теперь нужно только с адресами работать
сменил получение индекса
assign table_idx = DDS[30:28];
получил два прохода по таблице за период

assign table_idx = DDS[29:27]; а так четыре

теперь это нужно просто правильно модифицировать
каждая вторая четверть, это предпоследний старший бит. в зависимости от его значения - переворачиваем по горизонтали изображение синуса. то есть из максимального значения числа вычитаем значение синуса
assign table_idx = (!DDS[30]) ? DDS[29:27] : 32'hFFFFFFFF - DDS[29:27];

получаются синусы, но только положительные
после этого надо во второй части периода сменить знак. это старший бит слова
но у нас знака нет. поэтому ноль у нас - это половина от максимального значения числа.
при положительном значении синуса мы к этой половине прибавляем. при отрицательном - вычитаем
следовательно, разрядность таблицы синусов снизим с 32 до 31 бита в моем примере
module sinetabledds(
input wire CLK,
input wire RESET,
input wire [31:0] DDS,
output wire [31:0] out_sine
);
reg [30:0] table_sine;
wire [2:0] table_idx;
assign table_idx = (!DDS[30]) ? DDS[29:27] : 32'hFFFFFFFF - DDS[29:27];
assign out_sine = (!DDS[31]) ? (32'hFFFFFFFF / 2) + table_sine : (32'hFFFFFFFF / 2) - table_sine;
always @ (posedge CLK)
begin
case (table_idx)
3'b000: table_sine <= 0.0000 * (32'hFFFFFFFF / 2); //sin(0.0000) = 0.0000
3'b001: table_sine <= 0.1710 * (32'hFFFFFFFF / 2); //sin(0.1718) = 0.1710
3'b010: table_sine <= 0.3599 * (32'hFFFFFFFF / 2); //sin(0.3682) = 0.3599
3'b011: table_sine <= 0.5350 * (32'hFFFFFFFF / 2); //sin(0.5645) = 0.5350
3'b100: table_sine <= 0.6895 * (32'hFFFFFFFF / 2); //sin(0.7609) = 0.6895
3'b101: table_sine <= 0.8176 * (32'hFFFFFFFF / 2); //sin(0.9572) = 0.8176
3'b110: table_sine <= 0.9142 * (32'hFFFFFFFF / 2); //sin(1.1536) = 0.9142
3'b111: table_sine <= 0.9757 * (32'hFFFFFFFF / 2); //sin(1.3499) = 0.9757
default: table_sine <= 0.0000 * (32'hFFFFFFFF / 2);
endcase
end
endmodule

Но у меня 3 разряда всего. Если таблицу побольше - будет красивее.
Генератор синуса и коротковолновый радиопередатчик