Verilog实现QPSK的载波同步,采用costas环实现,15位IQ信号进入硬判决鉴相器计算误差信号,再由环路滤波器输出dds的频率控制字
时间: 2024-05-08 10:16:32 浏览: 75
,最后通过乘法器和正弦余弦表生成正交载波。
以下是Verilog代码实现:
```
module qpsk_csync (
input clk,
input [14:0] i_data,
input [14:0] q_data,
output reg [31:0] freq_ctrl_word,
output reg [14:0] i_out,
output reg [14:0] q_out
);
reg [14:0] i_delay, q_delay;
reg [14:0] i_error, q_error;
reg [14:0] i_filt_out, q_filt_out;
reg [31:0] phase_acc;
reg [31:0] freq_acc;
reg [31:0] freq_acc_prev;
reg [31:0] phase_acc_prev;
reg [1:0] phase_sel;
reg [31:0] phase_sel_acc;
reg [1:0] freq_sel;
reg [31:0] freq_sel_acc;
reg [31:0] freq_sel_max;
reg [31:0] freq_sel_min;
reg [1:0] freq_dir;
reg [31:0] freq_step;
reg [1:0] phase_dir;
reg [31:0] phase_step;
reg [31:0] dds_out;
reg [31:0] sin_out;
reg [31:0] cos_out;
reg [31:0] i_input, q_input;
// Costas loop parameters
parameter Kp = 1;
parameter Ki = 0.001;
parameter Kd = 0.1;
parameter Kf = 0.001;
// DDS parameters
parameter Fs = 50000000; // Sampling frequency
parameter Fc = 1000000; // Carrier frequency
parameter N = 32; // Number of bits in phase accumulator
// Sin/cos table
reg [31:0] sin_table [0:255];
reg [31:0] cos_table [0:255];
// Initialize sin/cos table
initial begin
for (int i = 0; i < 256; i = i + 1) begin
sin_table[i] = sin(2 * $pi * i / 256) * 2147483647;
cos_table[i] = cos(2 * $pi * i / 256) * 2147483647;
end
end
// Delay input signals
always @(posedge clk) begin
i_delay <= i_data;
q_delay <= q_data;
end
// Compute error signal
always @(posedge clk) begin
i_input <= i_delay;
q_input <= q_delay;
i_error <= i_input * cos_out - q_input * sin_out;
q_error <= q_input * cos_out + i_input * sin_out;
end
// Filter error signal
always @(posedge clk) begin
i_filt_out <= i_error * Kf + i_filt_out * (1 - Kf);
q_filt_out <= q_error * Kf + q_filt_out * (1 - Kf);
end
// Compute frequency control word
always @(posedge clk) begin
freq_acc_prev <= freq_acc;
freq_sel_max <= Fs / (Fc - 1);
freq_sel_min <= Fs / (Fc + 1);
if (freq_sel == 0) begin
freq_dir <= 2'b01;
freq_step <= freq_sel_max;
end else if (freq_sel == 1) begin
freq_dir <= 2'b10;
freq_step <= freq_sel_min;
end
if (i_error < 0 && q_error < 0) begin
freq_sel <= 2'b00;
end else if (i_error < 0 && q_error > 0) begin
freq_sel <= freq_dir;
end else if (i_error > 0 && q_error < 0) begin
freq_sel <= freq_dir;
end else if (i_error > 0 && q_error > 0) begin
freq_sel <= 2'b11;
end
freq_sel_acc <= freq_sel_acc + freq_step;
freq_acc <= freq_acc_prev + freq_sel_acc;
freq_ctrl_word <= freq_acc / (2 ** (32 - N));
end
// Compute phase control word
always @(posedge clk) begin
phase_acc_prev <= phase_acc;
if (q_filt_out > 0) begin
phase_dir <= 2'b01;
phase_step <= Kp * q_filt_out;
end else if (q_filt_out < 0) begin
phase_dir <= 2'b10;
phase_step <= Kp * q_filt_out;
end else begin
phase_dir <= 2'b00;
phase_step <= 0;
end
phase_sel_acc <= phase_sel_acc + phase_step + Ki * q_filt_out;
phase_sel <= phase_sel_acc[31:30];
phase_acc <= phase_acc_prev + phase_sel + Kd * (phase_sel - phase_sel_acc_prev[1:0]);
end
// Compute DDS output
always @(posedge clk) begin
dds_out <= phase_acc[31:N];
sin_out <= sin_table[dds_out[7:0]];
cos_out <= cos_table[dds_out[7:0]];
end
// Generate output signals
always @(posedge clk) begin
i_out <= i_input * cos_out - q_input * sin_out;
q_out <= q_input * cos_out + i_input * sin_out;
end
endmodule
```
阅读全文