Djony1987 0 March 1, 2010 Posted March 1, 2010 · Report post Всем привет! Подскажите, правильно ли я думаю относительно того, как сделать синусойду в цифре (потом если на ЦАП и подать уже реальную синусойду). Возьмем на 1 период 32 отсчета (16 бит) - можно меньше (По теореме Котельникова, мы знаем что синусойду с частотой f0 можно передавать с любой точностью при помощи чисел, следующих друг за другом через 1/2*f0 сек. ) sin (0) = 0, 32768, 1000_0000_0000_0000 sin (11.25) = 0.195, 39161, 1001_1000_1111_1001 sin (22.5) = 0.387, 45308, 1011_0000_1111_1100 sin (33.75) = 0.556, 50973, 1100_0111_0001_1101 sin (45) = 0.707, 55938, 1101_1010_1000_0010 sin (56.25) = 0.831, 60014, 1110_1010_0110_1110 sin (67.5) = 0.924, 63042, 1111_0110_0100_0010 sin (78.75) = 0.981, 64906, 1111_1101_1000_1010 sin (90) = 0.831, 65535, 1111_1111_1111_1111 А в Verilog'е сделать так: T90 = {sin0, sin1125, .....sin90}; T180 = {sin7875, sin675, .....}; T270 = {...}; // как лучше отрицательну часть представить? T360 = {...}; forever begin out = {T90, T180, T270, T360}; end Далее получается: например нам надо синусойду с f0 = 6 МГц, получается ситемная частота должна быть 6 МГц * 32 (отсчета за период) * 16 (бит на отсчет) = 3072 МГц, я правильно считаю? Если абсолютно неправильно, то как правильно? Где лучше смоделировать эту синусойду? (чтобы наглядно было, если есть такая возможность) Заранее спасибо! PS Сильно не пинайте, начал только разбиратся( Quote Share this post Link to post Share on other sites More sharing options...
MrYuran 34 March 1, 2010 Posted March 1, 2010 · Report post Далее получается: например нам надо синусойду с f0 = 6 МГц, получается ситемная частота должна быть 6 МГц * 32 (отсчета за период) * 16 (бит на отсчет) = 3072 МГц, я правильно считаю? 16 бит на отсчёт откуда взялось? ЦАП что, SPI-шный чтоли? Quote Share this post Link to post Share on other sites More sharing options...
bogaev_roman 0 March 1, 2010 Posted March 1, 2010 · Report post Как я понял, бит на отсчет тут вообще не причем (если взять обычный 16-разрядный цап), соответственно тактовая частота 6*32=192МГц. Отрицательную часть в лоб можно дополнительным кодом представить. Тогда будет всего 32 параметра значений частоты: sin_0 = 17'd0; sin_11_25 = 17'd12785; ... sin_90=17'd65535; sin_101_25=17'd64277; .... sin_270=~sin_90+1=-17'd65535; .... sin_348_75=~sin_11_25+1=-17'd12785; Далее по фронту (срезу) тактовой частоты пускается счетчик на 32 значения и выбирается последовательно одно из значений синусоиды (При большем кол-ве отсчетов лучше использовать память, где счетчик-адресный вход, при этом можно оставить только четверть периода, остальные три четверти фактически получаются из первой четверти согласно простым тригонометрическим формулам). На Verilog примерно так: always @(posedge sys_clk) counter<=counter+5'd1; always @(posedge sys_clk) case(counter) 5'b00000:sin_out<=sin_0; 5'b00000:sin_out<=sin_11_25; ... 5'b11111:sin_out<=sin_348_75 default:; endcase Смоделировать синусоиду проще всего в ModelSim, там многоразрядный сигнал можно представить в аналоговой форме Quote Share this post Link to post Share on other sites More sharing options...
des00 27 March 1, 2010 Posted March 1, 2010 · Report post Подскажите, правильно ли я думаю относительно того, как сделать синусойду в цифре (потом если на ЦАП и подать уже реальную синусойду). в блочную память прописываете 1/4 периода синусоиды + счетчик на период, 2 старших бита счетчика будут определять какой именно это 1/4 период и преобразование его данных. Quote Share this post Link to post Share on other sites More sharing options...
MKS 0 March 1, 2010 Posted March 1, 2010 · Report post Всем привет! Подскажите, правильно ли я думаю относительно того, как сделать синусойду в цифре Если я правильно понял вопрос и вам надо сделать генератор синусоиды на основе ПЛИС и ЦАП то тут есть стандартное решение под названием - прямой цифровой синтез или по ихнему Direct Digital Synthesis (DDS). По сути это аккумулятор фазы старшие разряды которого заведены на адрес таблицы отсчетов SIN, а отсчеты синуса с таблицы подаются на ЦАП. От шага приращения фазы и от тактовой частоты аккумулятора зависит генерируемая частота. Например для 32 разрядного аккумулятора шаг приращения расчитывается следующим образом: Где - частота которую необходимо получить на выходе генератора, а - тактовая частота. Если нет памяти для хранения таблицы отсчетов, то ее можно получить например с помощью CORDIC методов. Вроде нигде не ошибся :) . Успехов. Quote Share this post Link to post Share on other sites More sharing options...
Des333 0 March 1, 2010 Posted March 1, 2010 · Report post Пример реализации предложенного des00 варианта ( если уж совсем думать станет лень ) :) http://www.fpga4fun.com/DDS.html Quote Share this post Link to post Share on other sites More sharing options...
Djony1987 0 March 2, 2010 Posted March 2, 2010 · Report post MKS. des333 - Спасибо за новодку! Сейчас попробую моим методом попробовать) Вообще задача стоит сделать BPSK модулятор, решил для начала генератор синусойды сделать. В правильном ли я направлении иду? MrYuran, 16 битовое число которое представляет числа от 0 до 65535, через них выражать отсчеты синусойды пытаюсь. des00, Спасибо за совет, про 1/4 периода было понятно, про остальное буду разбиратся... bogaev_roman, Спасибо за ответ, решил для начала пол периода повторить много раз... Как должны быть описаны значения синусойды? Как 1 число или как вектор? (если я правильно выразился) http://dl.dropbox.com/u/2907327/sin_gen.JPG Вот что получается, видимо что-то не допонимаю... Вот код: `timescale 1 ns / 1 ps //{module {sin_generator}} module sin_generator ( clk, out ); output out; reg out; input clk; wire clk; reg sin_0 = 16'b1000_0000_0000_0000; reg sin_11_25 = 16'b1001_1000_1111_1001; reg sin_22_5 = 16'b1011_0000_1111_1100; reg sin_33_75 = 16'b1100_0111_0001_1101; reg sin_45 = 16'b1101_1010_1000_0010; reg sin_56_25 = 16'b1110_1010_0110_1110; reg sin_67_5 = 16'b1111_0110_0100_0010; reg sin_78_75 = 16'b1111_1101_1000_1010; reg sin_90 = 16'b1111_1111_1111_1111; reg sin_101_25 = 16'b1111_1101_1000_1010; reg sin_112_5 = 16'b1111_0110_0100_0010; reg sin_123_75 = 16'b1110_1010_0110_1110; reg sin_135 = 16'b1101_1010_1000_0010; reg sin_146_25 = 16'b1100_0111_0001_1101; reg sin_157_5 = 16'b1011_0000_1111_1100; reg sin_168_75 = 16'b1001_1000_1111_1001; reg sin_180 = 16'b1000_0000_0000_0000; reg [3:0] counter = 4'b0000; always @(posedge clk) counter <= counter + 1; always @(posedge clk) case(counter) 4'b0000:out<=sin_0; 4'b0001:out<=sin_11_25; 4'b0010:out<=sin_22_5; 4'b0011:out<=sin_33_75; 4'b0100:out<=sin_45; 4'b0101:out<=sin_56_25; 4'b0110:out<=sin_67_5; 4'b0111:out<=sin_78_75; 4'b1000:out<=sin_90; 4'b1001:out<=sin_101_25; 4'b1010:out<=sin_112_5; 4'b1011:out<=sin_123_75; 4'b1100:out<=sin_135; 4'b1101:out<=sin_146_25; 4'b1110:out<=sin_157_5; 4'b1111:out<=sin_180; default:; endcase endmodule Прошу помощи... Quote Share this post Link to post Share on other sites More sharing options...
Djony1987 0 March 3, 2010 Posted March 3, 2010 · Report post Вроде сделал 1 период...примерно: Сколько лучше использовать отсчетов? Сколько бит на отсчет? Как выразить из первых 1/4 периода 3 и 4 1/4 периода? Спасибо! Quote Share this post Link to post Share on other sites More sharing options...
Djony1987 0 March 3, 2010 Posted March 3, 2010 (edited) · Report post Код, если надо: `timescale 1 ns / 1 ps //{module {sin_generator}} module sin_generator ( clk, out ); output [15:0] out; reg [15:0] out; input clk; wire clk; reg [15:0] sin_0 = 16'b1000_0000_0000_0000; reg [15:0] sin_11_25 = 16'b1001_1000_1111_1001; reg [15:0] sin_22_5 = 16'b1011_0000_1111_1100; reg [15:0] sin_33_75 = 16'b1100_0111_0001_1101; reg [15:0] sin_45 = 16'b1101_1010_1000_0010; reg [15:0] sin_56_25 = 16'b1110_1010_0110_1110; reg [15:0] sin_67_5 = 16'b1111_0110_0100_0010; reg [15:0] sin_78_75 = 16'b1111_1101_1000_1010; reg [15:0] sin_90 = 16'b1111_1111_1111_1111; reg [15:0] sin_101_25 = 16'b1111_1101_1000_1010; reg [15:0] sin_112_5 = 16'b1111_0110_0100_0010; reg [15:0] sin_123_75 = 16'b1110_1010_0110_1110; reg [15:0] sin_135 = 16'b1101_1010_1000_0010; reg [15:0] sin_146_25 = 16'b1100_0111_0001_1101; reg [15:0] sin_157_5 = 16'b1011_0000_1111_1100; reg [15:0] sin_168_75 = 16'b1001_1000_1111_1001; reg [15:0] sin_180 = 16'b1000_0000_0000_0000; // Binary counter, 5-bits wide reg [3:0] counter = 4'b0000; always @(posedge clk) counter <= counter + 1; always @(posedge clk) case(counter) 4'b0000:out<=sin_0; 4'b0001:out<=sin_11_25; 4'b0010:out<=sin_22_5; 4'b0011:out<=sin_33_75; 4'b0100:out<=sin_45; 4'b0101:out<=sin_56_25; 4'b0110:out<=sin_67_5; 4'b0111:out<=sin_78_75; 4'b1000:out<=sin_90; 4'b1001:out<=sin_101_25; 4'b1010:out<=sin_112_5; 4'b1011:out<=sin_123_75; 4'b1100:out<=sin_135; 4'b1101:out<=sin_146_25; 4'b1110:out<=sin_157_5; 4'b1111:out<=sin_180; default:; endcase endmodule Немного просчитался с отсчетами, в этом описании 16, а посчитал 17, 1 отсчет не влез) sin_168_75. Теперь надо уменьшить количество хранимых значений. Edited March 3, 2010 by Djony1987 Quote Share this post Link to post Share on other sites More sharing options...
MKS 0 March 3, 2010 Posted March 3, 2010 · Report post Сколько лучше использовать отсчетов? Сколько бит на отсчет? Как выразить из первых 1/4 периода 3 и 4 1/4 периода? Спасибо! Вот кусок справки матлаба на блок NCO. Там приведены некоторые соотношения по расчету разрядностей. NCO___Blocks__Signal_Processing_Blockset_.zip Quote Share this post Link to post Share on other sites More sharing options...
iosifk 3 March 3, 2010 Posted March 3, 2010 · Report post в блочную память прописываете 1/4 периода синусоиды + счетчик на период, 2 старших бита счетчика будут определять какой именно это 1/4 период и преобразование его данных. немного добавлю. Если хотите сэкономить, и есть время для вычислений, то можно в память занести не всю "горбушку", а только нелинейную часть, т.е разность, между "горбушкой" и линейным значением... Удачи! Quote Share this post Link to post Share on other sites More sharing options...
Djony1987 0 March 4, 2010 Posted March 4, 2010 · Report post Вот кусок справки матлаба на блок NCO. Там приведены некоторые соотношения по расчету разрядностей. NCO___Blocks__Signal_Processing_Blockset_.zip Спасибо! Буду разбиратся... немного добавлю. Если хотите сэкономить, и есть время для вычислений, то можно в память занести не всю "горбушку", а только нелинейную часть, т.е разность, между "горбушкой" и линейным значением... Удачи! Сенк! Кстати насчет метода CORDIC: CORDIC is generally faster than other approaches when a hardware multiplier is unavailable (e.g., in a microcontroller based system), or when the number of gates required to implement the functions it supports should be minimized (e.g., in an FPGA). On the other hand, when a hardware multiplier is available (e.g., in a DSP microprocessor), table-lookup methods and power series are generally faster than CORDIC. In recent years, CORDIC algorithm is used extensively for various biomedical applications, especially in FPGA implementations. Quote Share this post Link to post Share on other sites More sharing options...
bogaev_roman 0 March 5, 2010 Posted March 5, 2010 · Report post Некоторые добавления, за ранее извиняюсь, если немного не по теме: 1. Фактически у Вас есть набор векторов (отсчетов синусоиды), разрядность каждого отсчета определяется исходя из разрядности входного сигнала и разрядности ЦАП (а вообще говоря из ТЗ, т.к. на выходе при BPSK модуляции все равно будет стоять полосовой фильтр). Если разрядность входа - 1бит, то при 16-разрядном ЦАП у вас будет отсчет разрядности 15+1(знаковый). 2. Кол-во отсчетов при модуляции определяется тактовой частотой схемы и полосой сигнала (например при тактовой в 120МГц, а полосе 30МГц требуется всего 4 отсчета, логично взять 0,90,180,270 градусов). При демодуляции (синхронизации по несущей) зависит от чувствительности и полосе захвата/удержания ФАПЧ, но в любом случае без памяти тут уже не обойтись так как кол-во отсчетов будет большим (по личному опыту в сложным проектах >2^10)). 3. И еще, коли речь зашла о Cordic, то я так понимаю это будет использоваться при реализации демодулятора, советую использовать пютлю Костаса с петлевыми фильтрами, а вместо кордика БИХ-фильтр 1-го,2-го порядка, так как по частоте он работает гораздо быстрее при той же точности. За помощью по этим вопросам лучше обращайтесь к спецам по ЦОС. Quote Share this post Link to post Share on other sites More sharing options...
andreichk 0 April 15, 2011 Posted April 15, 2011 · Report post Код, если надо: `timescale 1 ns / 1 ps ....... помучил код, работает, но показывает только половину синусодиды. а как сделать так, чтобы весь синус показывал? я начинающий плисовод, поэтому не пинайте сильно.... Quote Share this post Link to post Share on other sites More sharing options...
tAmega 0 April 16, 2011 Posted April 16, 2011 · Report post потому что это нерабочий код, у него заявлено полпериода, судя по названиям, а сами числа как на целый период. В прикрепленном архиве файл со значениями синусоиды на весь период в hex и bin форматах и матлабовский файл, который генерит это дело. Quote Share this post Link to post Share on other sites More sharing options...