Jump to content
    

Цифровая "синусойда"

Всем привет!

Подскажите, правильно ли я думаю относительно того, как сделать синусойду в цифре (потом если на ЦАП и подать уже реальную синусойду).

Возьмем на 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 Сильно не пинайте, начал только разбиратся(

Share this post


Link to post
Share on other sites

Далее получается: например нам надо синусойду с f0 = 6 МГц, получается ситемная частота должна быть 6 МГц * 32 (отсчета за период) * 16 (бит на отсчет) = 3072 МГц, я правильно считаю?

16 бит на отсчёт откуда взялось?

ЦАП что, SPI-шный чтоли?

Share this post


Link to post
Share on other sites

Как я понял, бит на отсчет тут вообще не причем (если взять обычный 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, там многоразрядный сигнал можно представить в аналоговой форме

Share this post


Link to post
Share on other sites

Подскажите, правильно ли я думаю относительно того, как сделать синусойду в цифре (потом если на ЦАП и подать уже реальную синусойду).

в блочную память прописываете 1/4 периода синусоиды + счетчик на период, 2 старших бита счетчика будут определять какой именно это 1/4 период и преобразование его данных.

Share this post


Link to post
Share on other sites

Всем привет!

Подскажите, правильно ли я думаю относительно того, как сделать синусойду в цифре

Если я правильно понял вопрос и вам надо сделать генератор синусоиды на основе ПЛИС и ЦАП то тут есть стандартное решение под названием - прямой цифровой синтез или по ихнему Direct Digital Synthesis (DDS). По сути это аккумулятор фазы старшие разряды которого заведены на адрес таблицы отсчетов SIN, а отсчеты синуса с таблицы подаются на ЦАП. От шага приращения фазы и от тактовой частоты аккумулятора зависит генерируемая частота. Например для 32 разрядного аккумулятора шаг приращения расчитывается следующим образом:

?\font{5} Step = \frac{F_{generatora}}{F_{taktov}} \cdot 2^{32}

Где ?F_{generatora} - частота которую необходимо получить на выходе генератора, а ?F_{taktov} - тактовая частота. Если нет памяти для хранения таблицы отсчетов, то ее можно получить например с помощью CORDIC методов. Вроде нигде не ошибся :) . Успехов.

Share this post


Link to post
Share on other sites

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

 

Прошу помощи...

Share this post


Link to post
Share on other sites

Вроде сделал 1 период...примерно:

sine_wave.JPG

Сколько лучше использовать отсчетов? Сколько бит на отсчет? Как выразить из первых 1/4 периода 3 и 4 1/4 периода?

Спасибо!

Share this post


Link to post
Share on other sites

Код, если надо:

`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 by Djony1987

Share this post


Link to post
Share on other sites

Сколько лучше использовать отсчетов? Сколько бит на отсчет? Как выразить из первых 1/4 периода 3 и 4 1/4 периода?

Спасибо!

Вот кусок справки матлаба на блок NCO. Там приведены некоторые соотношения по расчету разрядностей.

NCO___Blocks__Signal_Processing_Blockset_.zip

Share this post


Link to post
Share on other sites

в блочную память прописываете 1/4 периода синусоиды + счетчик на период, 2 старших бита счетчика будут определять какой именно это 1/4 период и преобразование его данных.

немного добавлю. Если хотите сэкономить, и есть время для вычислений, то можно в память занести не всю "горбушку", а только нелинейную часть, т.е разность, между "горбушкой" и линейным значением...

Удачи!

Share this post


Link to post
Share on other sites

Вот кусок справки матлаба на блок 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.

Share this post


Link to post
Share on other sites

Некоторые добавления, за ранее извиняюсь, если немного не по теме:

1. Фактически у Вас есть набор векторов (отсчетов синусоиды), разрядность каждого отсчета определяется исходя из разрядности входного сигнала и разрядности ЦАП (а вообще говоря из ТЗ, т.к. на выходе при BPSK модуляции все равно будет стоять полосовой фильтр). Если разрядность входа - 1бит, то при 16-разрядном ЦАП у вас будет отсчет разрядности 15+1(знаковый).

2. Кол-во отсчетов при модуляции определяется тактовой частотой схемы и полосой сигнала (например при тактовой в 120МГц, а полосе 30МГц требуется всего 4 отсчета, логично взять 0,90,180,270 градусов). При демодуляции (синхронизации по несущей) зависит от чувствительности и полосе захвата/удержания ФАПЧ, но в любом случае без памяти тут уже не обойтись так как кол-во отсчетов будет большим (по личному опыту в сложным проектах >2^10)).

3. И еще, коли речь зашла о Cordic, то я так понимаю это будет использоваться при реализации демодулятора, советую использовать пютлю Костаса с петлевыми фильтрами, а вместо кордика БИХ-фильтр 1-го,2-го порядка, так как по частоте он работает гораздо быстрее при той же точности.

За помощью по этим вопросам лучше обращайтесь к спецам по ЦОС.

Share this post


Link to post
Share on other sites

Код, если надо:

`timescale 1 ns / 1 ps

.......

помучил код, работает, но показывает только половину синусодиды. а как сделать так, чтобы весь синус показывал?

я начинающий плисовод, поэтому не пинайте сильно....

Share this post


Link to post
Share on other sites

потому что это нерабочий код, у него заявлено полпериода, судя по названиям, а сами числа как на целый период.

В прикрепленном архиве файл со значениями синусоиды на весь период в hex и bin форматах и матлабовский файл, который генерит это дело.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...