Сводка
Фазовый детектор – это устройство, используемое для определения разницы в фазе между сигналами. Он играет важную роль в различных областях, таких как радиосвязь, медицинская техника, радары, телекоммуникации и многое другое.
В данной статье мы рассмотрим Балансный Фазовый Детектор написанный на языке Verilog. Укажем про особенности и применение кода в своих проектах.
Реализация Балансного Фазового Детектора на языке Verilog
В данном случае код написан и синтезирован в Проприетарное ПО Quartus 2. Для пользователей ПО Vivado от компании Xilinx или другими синтезаторами написан более простой код для автоматизированного вычисления.
Модуль BFD(Balanced Phase Detector) включает 2 экземпляра модуля:
- single_port_rom — имитирующий ROM. Данного модуль использует ресурсы памяти ПЛИС, а не регистровую память.
- signed_multiply — модуль умножения с учетом знака.
BFD также входит счетчик counter, написанный в модуле верхнего уровня, и параметры:
- FREQ — частота сигнала. Данный показатель написан через параметр, полагаясь на знание несущей частоты сигнала. Если в схеме присутствует Частотный Детектор, то можно сделать как входной сигнал, но придется менять код адресации к памяти.
- ADC_FREQ — частота дискретизации АЦП.
- DW — битовая длина внутренних линий.
Управляющие и информационные сигналы:
- i_signal — входной сигнала значения с АЦП.
- i_clk — внутренний тактовый сигнал ПЛИС.
- o_fd — выходной сигнал фазового детектора.
`default_nettype wire
module BFD
#(
parameter FREQ = 100,
parameter ADC_FREQ = 10_000,
parameter DW = 16
)
(
input [(DW - 1): 0] i_signal,
input i_clk,
output [(DW) - 1: 0] o_fd
);
localparam ADDR_DEPTH = 100; //INTEL FPGA
// localparam ADDR_DEPTH = ADC_FREQ / FREQ; //XILINX FPGA
reg [6: 0] counter; // INTEL
// reg [$clog2(ADDR_DEPTH): 0] counter; // XILINX FPGA
wire [(DW - 1): 0] cos_val;
initial begin
counter = 0;
end
single_port_rom #(DW, ADDR_DEPTH) rom1(counter, i_clk, cos_val);
signed_multiply #(DW) mult(i_signal, cos_val, o_fd);
always @(i_clk) begin
if (ADDR_DEPTH == counter)
counter <= 0;
else
counter <= counter + 1;
end
endmodule
module single_port_rom
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=8)
(
input [(ADDR_WIDTH-1):0] addr,
input clk,
output reg [(DATA_WIDTH-1):0] q
);
// Объявление Памяти
reg [DATA_WIDTH-1:0] rom[2**ADDR_WIDTH-1:0];
genvar i;
initial
begin
$readmemb("cos_val.txt", rom); // INTEL
// для других синтезаторов через for используя $cos
end
always @ (posedge clk)
begin
q <= rom[addr];
end
endmodule
module signed_multiply
#(parameter WIDTH=8)
(
input signed [WIDTH-1:0] dataa,
input signed [WIDTH-1:0] datab,
output [2*WIDTH-1:0] dataout
);
assign dataout = dataa * datab;
endmodule
Особенности
Результатом выхода фазового детектора является следующая формула:

Для получения получения фазовой составляющей нужно на выход поставить фильтр ФНЧ с частотой среза меньше 2f. Выходные данные будут представлять собой низкочастотную составляющую.
Следует заметить, что при не правильных расчетах глубины Памяти ROM или счетчика counter, меняется частота косинуса. На результирующем сигнале появятся колебания равные разности частот целевого и гармонического сигнала.