Verilog实现的qpsk解调采用costas环载波同步和Gardner环的位同步的代码
时间: 2023-10-03 14:06:17 浏览: 206
以下是Verilog实现的QPSK解调采用Costas环载波同步和Gardner环位同步的示例代码:
module qpsk_demodulator(
input clk,
input rst,
input [15:0] iq_data_in,
output reg [7:0] data_out,
output reg lock
);
parameter PHASE_STEP = 8'h10; // Costas环相位步进值
parameter LOCK_THRESHOLD = 10; // Costas环锁定门限值
parameter TAU_STEP = 4'h2; // Gardner环时间步进值
parameter TAU_MAX = 8'h7f; // Gardner环最大延时值
parameter TAU_MIN = 8'h00; // Gardner环最小延时值
parameter THRESHOLD = 8'h30; // Gardner环错误门限值
reg [15:0] iq_data; // 输入IQ数据
reg [1:0] phase; // Costas环相位状态
reg [7:0] tau; // Gardner环延时状态
reg [1:0] quad; // 当前象限
reg [7:0] error; // Gardner环误差
reg [7:0] output; // 输出数据
reg locked; // Costas环锁定标志
// 初始化
initial begin
iq_data <= 16'h0000;
phase <= 2'b00;
tau <= 8'h00;
quad <= 2'b00;
error <= 8'h00;
output <= 8'h00;
locked <= 0;
lock <= 0;
end
// 每个时钟周期处理
always @(posedge clk or posedge rst) begin
if (rst) begin
iq_data <= 16'h0000;
phase <= 2'b00;
tau <= 8'h00;
quad <= 2'b00;
error <= 8'h00;
output <= 8'h00;
locked <= 0;
lock <= 0;
end else begin
// IQ数据输入
iq_data <= iq_data_in;
// Costas环载波同步
case (phase)
2'b00: begin
if (iq_data[15] && iq_data[14]) phase <= 2'b01;
else if (!iq_data[15] && iq_data[14]) phase <= 2'b10;
end
2'b01: begin
if (iq_data[15] && !iq_data[14]) phase <= 2'b00;
else if (!iq_data[15] && iq_data[14]) phase <= 2'b11;
end
2'b10: begin
if (!iq_data[15] && iq_data[14]) phase <= 2'b00;
else if (iq_data[15] && !iq_data[14]) phase <= 2'b11;
end
2'b11: begin
if (!iq_data[15] && !iq_data[14]) phase <= 2'b10;
else if (iq_data[15] && !iq_data[14]) phase <= 2'b01;
end
endcase
// Gardner环位同步
case (quad)
2'b00: begin
if (iq_data[15] && iq_data[14]) begin
error <= error + TAU_STEP;
tau <= tau + TAU_STEP;
end else if (!iq_data[15] && iq_data[14]) begin
error <= error - TAU_STEP;
tau <= tau - TAU_STEP;
end
quad <= 2'b01;
end
2'b01: begin
if (iq_data[15] && !iq_data[14]) begin
error <= error + TAU_STEP;
tau <= tau + TAU_STEP;
end else if (!iq_data[15] && !iq_data[14]) begin
error <= error - TAU_STEP;
tau <= tau - TAU_STEP;
end
quad <= 2'b10;
end
2'b10: begin
if (!iq_data[15] && !iq_data[14]) begin
error <= error + TAU_STEP;
tau <= tau + TAU_STEP;
end else if (iq_data[15] && !iq_data[14]) begin
error <= error - TAU_STEP;
tau <= tau - TAU_STEP;
end
quad <= 2'b11;
end
2'b11: begin
if (!iq_data[15] && iq_data[14]) begin
error <= error + TAU_STEP;
tau <= tau + TAU_STEP;
end else if (iq_data[15] && iq_data[14]) begin
error <= error - TAU_STEP;
tau <= tau - TAU_STEP;
end
quad <= 2'b00;
end
endcase
// 输出数据
if (tau > TAU_MAX) tau <= TAU_MAX;
if (tau < TAU_MIN) tau <= TAU_MIN;
output <= ((8'h80 & iq_data) >> (8'h07 - tau)) ^ (8'h80 >> quad);
if (error > THRESHOLD || error < -THRESHOLD) begin
output <= 8'h00;
tau <= 8'h00;
error <= 8'h00;
locked <= 0;
end else if (!locked && error > -LOCK_THRESHOLD && error < LOCK_THRESHOLD) begin
locked <= 1;
lock <= 1;
end
if (locked) data_out <= output;
end
end
endmodule
阅读全文