Search
Write a publication
Pull to refresh

Comments 21

По-моему, канал передачи данных проще генератором треугольника сделать, который многократно проще реализуется.

Спасибо, тогда попробую и посмотрю что получится.

А прямо в питоне нельзя было посчитать синус? Зачем тут матлаб?

В питоне тоже можно. Просто я когда-то это сделал в matlab и решил поделиться таким способом в статье.

А прямо в питоне нельзя было посчитать синус? Зачем тут матлаб?

Более того, чтобы получить синус не нужны FPGA и ПЛИС. Но это же не интересно :)

Рекомендую "A Technical Tutorial on Digital Signal Synthesis." Кратко:

Разрядность данных таблицы синуса - разрядность ЦАП плюс 2 бита;

Использовать симметрию синуса для сжатия ROM;

Фильтровать выход ЦАП.

Вероятно самый громоздкий и дорогой генератор синуса . Китайский модуль за 2 бакса умеет ... ну вы знаете . Зачем тут ПЛИС ? Реализуется на голой stm32 / esp32 без вот этого вот всего если Вы хотите в математику или на 1 транзисторе и колебательном контуре со средней точкой . Без питонов и прочих .

Высокостабилный перестраиваемый опорный генератор сложная и дорогая штука. За 2 бакса на Si получите нестабильный и грязный сигнал.

Да, согласен, я иногда включаю для экспериментов свой ad9833 или si5351. У второго шире диапазон

Если вы используете Матлаб, почему сразу не сгенерировать 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 разряда всего. Если таблицу побольше - будет красивее.

Здравствуйте, и Вам спасибо за хороший комментарий. Действительно, это еще один способ сформировать синусоиду :)

Sign up to leave a comment.

Articles