FPGA移相
需要对MHz级别的信号移相,最开始考虑用运放,但是需要高速的运放,而且运放的压摆率还是个问题,没法做到0-360度连续可调。需要整两个以上高速运放级联,显得很繁琐,所以写了个代码,用FPGA去操作。
需要注意,移相的输出与输入有一个时钟的延时
以下是FPGA测试程序
`timescale 100ps/10ps //
module test_PhaseShift ;
reg [0:0]clk ; //clk
reg rst_n ; //rest
reg [7:0]clk_fre ; //system clock frequency,MHZ
reg [15:0]din_fre ; //input signal clock frequency,MHZ
reg [8:0]phase_angle ; //phase shift angle
reg [0:0]din ; //input signal
wire [0:0]dout ; //output signal
initial
begin
clk = 0;
din = 0 ;
din_fre = 4000 ;
phase_angle = 90;
clk_fre = 100;
rst_n = 1;
#12 rst_n = 0;
#4 rst_n = 1;
#10000 $stop; // end
end
always #5 clk = ~clk;
always #125 din = ~din;
PhaseShift u_(
.clk(clk),
.rst_n(rst_n),
.clk_fre(clk_fre),
.din_fre(din_fre),
.phase_angle(phase_angle),
.din(din),
.dout(dout)
);
endmodule
以下是FPGA程序
/*
Function : Phase Shift
Interface : clk_fre---unit(MHZ) din_fre---unit(KHz) phase_angle---unit(0-360 Angle)
Author: lichangwu
Mobile phone:18862120629
Email : 18862120629@qq.com
Version : V1.0
Date: 20200708
Description:
Phase shift is carried out on the input square wave.
The phase Angle unit is Angle (0-360), or the input can be greater than 360.
The system clock unit is MHz and the input signal clock is KHz.
*/
module PhaseShift(
input clk , //clk
input rst_n , //rest
input [7:0]clk_fre , //system clock frequency,MHZ
input [15:0]din_fre , //input signal clock frequency,MHZ
input [8:0]phase_angle ,//phase shift angle
input [0:0]din , //input signal
output reg [0:0]dout //output signal
);
reg [31:0]posedge_counter;
reg [31:0]negedge_counter;
reg [31:0]delay_counter;
reg [0:0]in_posedge_flg;
reg [0:0]in_negedge_flg;
reg [0:0]out_posedge_flg;
reg [0:0]out_negedge_flg;
reg [0:0]old_din;
reg [0:0]init_data=1'b1;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
posedge_counter <= 1'b0 ;
negedge_counter <= 1'b0 ;
in_posedge_flg <= 1'b0 ;
in_negedge_flg <= 1'b0 ;
out_posedge_flg <= 1'b0 ;
out_negedge_flg <= 1'b0 ;
end
else
begin
if( ~old_din & din )
in_posedge_flg = 1'b1 ;
if( old_din & ~din )
in_negedge_flg = 1'b1 ;
old_din <= din ;
if(init_data)
begin
delay_counter <= ((1000000000 / din_fre * clk_fre ))/360*(phase_angle%360)/1000000;
dout <= din ;
init_data <= 1'b0 ;
end
if (in_posedge_flg && posedge_counter <= delay_counter)
begin
posedge_counter <= posedge_counter + 1'b1 ;
out_posedge_flg <= 1'b0 ;
end
else
begin
posedge_counter <= 1'b0 ;
in_posedge_flg <= 1'b0 ;
if(~out_posedge_flg)
begin
dout <= 1'b1 ;
out_posedge_flg <= 1'b1 ;
end
end
if (in_negedge_flg && negedge_counter <= delay_counter)
begin
negedge_counter <= negedge_counter + 1'b1 ;
out_negedge_flg <= 1'b0 ;
end
else
begin
negedge_counter <= 1'b0 ;
in_negedge_flg <= 1'b0 ;
if(~out_negedge_flg)
begin
dout <= 1'b0 ;
out_negedge_flg <= 1'b1;
end
end
end
end
endmodule