среда, 13 ноября 2013 г.

QAM CORDIC

Еще раз пройдемся по наличию. У нас есть метод CORDIC, который для заданной фазы считает квадратурные компоненты I и Q. У нас есть обертки для этого метода, реализующие фазовую, частотную и амплитудную  манипуляцию. Легко заметить, что они очень похожи, поэтому сделать гибрид фазовой и амплитудной манипуляции не составит никакого труда. Называется эта манипуляция квадратурной или QAM. Я буду реализовывать от лени совсем нереальный случай QAM4, когда точки на фазовой плоскости будут располагаться так:
Эта реализация, наверно, нигде не используется, ибо глупая. Но это пример. Код на Verilog выглядит так:
Exported from Notepad++
module cordic_qam #(parameter INPUT_CLK = 100000000, parameter INPUT_SAMPLE_RATE = 8000, parameter OUTPUT_SAMPLE_RATE = 10000000) ( input wire clk, input wire en, input wire [ 1 : 0 ] din, output wire [ 19 : 0 ] phase ); localparam SAMPLES_PER_BIT = OUTPUT_SAMPLE_RATE/INPUT_SAMPLE_RATE; localparam PERIODS_PER_BIT = 5; localparam TWO_PI = 524287; localparam PI = 524287>>1; localparam ARG = (TWO_PI * PERIODS_PER_BIT) / SAMPLES_PER_BIT; reg signed [ 31 : 0 ] r_sr = 32'b0; wire signed [ 31 : 0 ] inc_sr = r_sr[31] ? OUTPUT_SAMPLE_RATE : OUTPUT_SAMPLE_RATE-INPUT_CLK; wire signed [ 31 : 0 ] tic_sr = r_sr + inc_sr; wire w_en = ~r_sr[31]; reg r_en = 1'b0; always@(posedge clk) begin r_sr <= tic_sr; r_en <= w_en; end reg [ 19 : 0 ] my_phase = 20'b0; wire [ 19 : 0 ] next_phase = my_phase + ARG; wire [ 19 : 0 ] next_phase_0 = my_phase + (ARG >>> 1); always@(posedge clk) begin if(en) my_phase <= din[0] ? 0 : PI; else if(w_en) begin my_phase <= my_phase + ARG; if(next_phase[19]) my_phase <= next_phase - TWO_PI; end end //cordic delay 14+2 wire signed [ 15 : 0 ] w_re_out; wire signed [ 15 : 0 ] w_im_out; reg [ 15 : 0 ] r_din = 16'b0; always@(posedge clk) r_din <= {r_din[14:0], din[1]}; cordic_phase u0 ( .clk(clk), .arg(my_phase), .Re_out(w_re_out), .Im_out(w_im_out) ); wire [ 15 : 0 ] QAM4 = r_din[15] ? w_im_out : w_im_out >>> 1; assign phase = my_phase; endmodule

И картинка:

четверг, 7 ноября 2013 г.

Фазовая манипуляция с использованием CORDIC

Был рассмотрен случай частотной манипуляции FSK и амплитудной манипуляции ASK, осталась только фазовая манипуляция. Будет показана обертка для CORDIC для случая BPSK. Если сравнить обертки для разных видов манипуляции, то видно, что они все очень похожи.
Exported from Notepad++
module cordic_freq #(parameter INPUT_CLK = 100000000, parameter INPUT_SAMPLE_RATE = 8000, parameter OUTPUT_SAMPLE_RATE = 10000000) ( input wire clk, input wire en, input wire din, output wire [ 19 : 0 ] phase ); localparam SAMPLES_PER_BIT = OUTPUT_SAMPLE_RATE/INPUT_SAMPLE_RATE; localparam PERIODS_PER_BIT = 5; localparam TWO_PI = 524287; localparam PI = 524287>>1; localparam ARG = (TWO_PI * PERIODS_PER_BIT) / SAMPLES_PER_BIT; reg signed [ 31 : 0 ] r_sr = 32'b0; wire signed [ 31 : 0 ] inc_sr = r_sr[31] ? OUTPUT_SAMPLE_RATE : OUTPUT_SAMPLE_RATE-INPUT_CLK; wire signed [ 31 : 0 ] tic_sr = r_sr + inc_sr; wire w_en = ~r_sr[31]; reg r_en = 1'b0; always@(posedge clk) begin r_sr <= tic_sr; r_en <= w_en; end reg [ 19 : 0 ] my_phase = 20'b0; wire [ 19 : 0 ] next_phase = my_phase + ARG; wire [ 19 : 0 ] next_phase_0 = my_phase + (ARG >>> 1); always@(posedge clk) begin if(en) my_phase <= din ? 0 : PI; else if(w_en) begin my_phase <= my_phase + ARG; if(next_phase[19]) my_phase <= next_phase - TWO_PI; end end //cordic delay 14+2 wire signed [ 15 : 0 ] w_re_out; wire signed [ 15 : 0 ] w_im_out; reg [ 15 : 0 ] r_din = 16'b0; always@(posedge clk) r_din <= {r_din[14:0], din}; cordic_phase u0 ( .clk(clk), .arg(my_phase), .Re_out(w_re_out), .Im_out(w_im_out) ); wire [ 15 : 0 ] BPSK = w_im_out; assign phase = my_phase; endmodule


Частотная манипуляция с использованием CORDIC

Продолжаем клепать обертки для CORDIC. Чуток изменяем обертку для ASK и получаем FSK:
Exported from Notepad++
module cordic_freq #(parameter INPUT_CLK = 100000000, parameter INPUT_SAMPLE_RATE = 8000, parameter OUTPUT_SAMPLE_RATE = 10000000) ( input wire clk, input wire din, output wire [ 19 : 0 ] phase ); localparam SAMPLES_PER_BIT = OUTPUT_SAMPLE_RATE/INPUT_SAMPLE_RATE; localparam PERIODS_PER_BIT = 5; localparam TWO_PI = 524287; localparam ARG = (TWO_PI * PERIODS_PER_BIT) / SAMPLES_PER_BIT; reg signed [ 31 : 0 ] r_sr = 32'b0; wire signed [ 31 : 0 ] inc_sr = r_sr[31] ? OUTPUT_SAMPLE_RATE : OUTPUT_SAMPLE_RATE-INPUT_CLK; wire signed [ 31 : 0 ] tic_sr = r_sr + inc_sr; wire w_en = ~r_sr[31]; reg r_en = 1'b0; always@(posedge clk) begin r_sr <= tic_sr; r_en <= w_en; end reg [ 19 : 0 ] my_phase = 20'b0; wire [ 19 : 0 ] next_phase = my_phase + ARG; wire [ 19 : 0 ] next_phase_0 = my_phase + (ARG >>> 1); always@(posedge clk) if(w_en) if(din) begin my_phase <= my_phase + ARG; if(next_phase[19]) my_phase <= next_phase - TWO_PI; end else begin my_phase <= my_phase + (ARG >>> 1); if(next_phase_0[19]) my_phase <= next_phase - TWO_PI; end //cordic delay 14+2 wire signed [ 15 : 0 ] w_re_out; wire signed [ 15 : 0 ] w_im_out; reg [ 15 : 0 ] r_din = 16'b0; always@(posedge clk) r_din <= {r_din[14:0], din}; cordic_phase u0 ( .clk(clk), .arg(my_phase), .Re_out(w_re_out), .Im_out(w_im_out) ); wire [ 15 : 0 ] FSK = w_im_out; assign phase = my_phase; endmodule

И картинка:

среда, 6 ноября 2013 г.

Амплитудная манипуляция с использованием CORDIC

Амплитудная манипуляция или ASK представляет информационные биты в аналоговый сигнал постоянной частоты с амплитудой, зависящей от значения бита. Так, если уровень кодируется одним битом, то амплитуд соответственно будет 2. Если 2 бита - 4 уровня. CORDIC на Verilog уже отлажен и в него лезть не будем, поэтому будет писать обертку для нашего модуля, реализующие ASK.
Exported from Notepad++
module cordic_am #(parameter INPUT_CLK = 100000000, parameter INPUT_SAMPLE_RATE = 8000, parameter OUTPUT_SAMPLE_RATE = 10000000) ( input wire clk, input wire din, output wire [ 19 : 0 ] phase ); localparam SAMPLES_PER_BIT = OUTPUT_SAMPLE_RATE/INPUT_SAMPLE_RATE; localparam PERIODS_PER_BIT = 5; localparam TWO_PI = 524287; localparam ARG = (TWO_PI * PERIODS_PER_BIT) / SAMPLES_PER_BIT; //make OUTPUT_SAMPLE_RATE reg signed [ 31 : 0 ] r_sr = 32'b0; wire signed [ 31 : 0 ] inc_sr = r_sr[31] ? OUTPUT_SAMPLE_RATE : OUTPUT_SAMPLE_RATE-INPUT_CLK; wire signed [ 31 : 0 ] tic_sr = r_sr + inc_sr; wire w_en = ~r_sr[31]; reg r_en = 1'b0; always@(posedge clk) begin r_sr <= tic_sr; r_en <= w_en; end reg [ 19 : 0 ] my_phase = 20'b0; wire [ 19 : 0 ] next_phase = my_phase + ARG; always@(posedge clk) if(w_en) begin my_phase <= my_phase + ARG; if(next_phase[19]) my_phase <= next_phase - TWO_PI; end //cordic delay 14+2 wire signed [ 15 : 0 ] w_re_out; wire signed [ 15 : 0 ] w_im_out; reg [ 15 : 0 ] r_din = 16'b0; always@(posedge clk) r_din <= {r_din[14:0], din}; cordic_phase u0 ( .clk(clk), .arg(my_phase), .Re_out(w_re_out), .Im_out(w_im_out) ); wire [ 15 : 0 ] ASK = r_din[15] ? w_im_out : w_im_out >>> 3; assign phase = my_phase; endmodule

Тут нет ничего не знакомого, кроме счетчика выходной частоты отсчетов. Частота гармонического колебания будет равна INPUT_SAMPLE_RATE*PERIODS_PER_BIT. Чем выше OUTPUT_SAMPLE_RATE, тем больше точек на период. Все завязано на константах, и желательно подбирать их кратными друг другу. В результате получается такая вот картинка: