本文用了DDS来产生LFM信号,DDS的原理可以查看赛灵思的官方文档,这里不做赘述,同时对于LFM信号也不做赘述,直接上工程实现及其方法。
首先,我们要确定脉宽和PRI,在这里脉宽选取10us,PRI选取200us(fpga内部时钟用来100MHz),所以使用计数器去实现这两个信号的计数,当计数器计数到一定值的时候,使用使能信号来反应该计数状态,根据使能信号和成脉冲门信号,在脉冲门信号里面对DDS进行频率的步进,达到最后的输出效果。
DDS配置如下:
其余保持默认配置
`timescale 1ns / 1ps
//
// Company: xidian
// Engineer: CC
//
// Create Date: 2023/04/29 20:03:54
// Design Name:
// Module Name: lfm_gen
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module lfm_gen
#(
parameter CNT_TAO_MAX = 10'd999,
parameter CNT_PRI_MAX = 15'd19_999 //实际pri=(19999+1)*10ns*2=400us
)
(
input wire sys_clk,
input wire sys_rst_n,
// output wire meng,
// output wire [31:0]data,
// output wire [15:0]sin_imag,
// output wire [15:0]cos_real,
output wire wr_en,
output wire [13:0]data_out,
output wire clk_125M
);
reg pri_en;
reg tao_en;
reg cnt_ctrl1; //脉宽前沿检测
reg cnt_ctrl2; //脉宽后沿检测
reg cnt_ctrl3; //PRI后沿检测
reg [9:0]cnt_tao;
reg [14:0]cnt_pri;
reg [7:0]tao_reg; //一个周期内对脉宽的计数
reg freq_en;
reg [31:0]dds_pinc_in;
reg [31:0]dds_poff_in;
wire [63:0]s_axis_phase_tdata;
parameter FREQ_START = 32'd858_993_460; //起始频率为20MHz
parameter FREQ_STEP = 32'd214_749; //步进频率为5KHz
wire [31:0] data;
wire meng;
wire [15:0]sin_imag;
wire [15:0]cos_real;
wire [13:0]data_reg;
//pri计数器,产生对应时间的脉冲间隔
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
cnt_pri <= 15'b0;
else if (cnt_pri == CNT_PRI_MAX)
cnt_pri <= 15'b0;
else
cnt_pri <= cnt_pri + 1'b1;
//脉冲前沿信号产生
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
cnt_ctrl1 <= 1'b0;
else if (cnt_pri == CNT_PRI_MAX && tao_reg == 8'b0 )
cnt_ctrl1 <= 1'b1;
else
cnt_ctrl1 <= 1'b0;
//脉冲后沿信号产生
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
cnt_ctrl2 <= 1'b0;
else if (tao_reg == 8'b0 && cnt_tao == CNT_TAO_MAX)
cnt_ctrl2 <= 1'b1;
else
cnt_ctrl2 <= 1'b0;
//PRI后沿检测
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
cnt_ctrl3 <= 1'b0;
else if (cnt_pri == CNT_PRI_MAX && pri_en == 1'b0)
cnt_ctrl3 <= 1'b1;
else
cnt_ctrl3 <= 1'b0;
//tao计数器,产生对应时间的脉宽
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
cnt_tao <= 10'b0;
else if (pri_en == 1'b1)
cnt_tao <= cnt_tao + 1'b1;
else if (cnt_ctrl2 == 1'b1) //cnt_tao == CNT_TAO_MAX && tao_reg == 8'b1
cnt_tao <= 10'b0;
else if (pri_en == 1'b0)
cnt_tao <= 10'b0;
//pri使能信号
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
pri_en <= 1'b0;
else if (cnt_ctrl1 == 1'b1)
pri_en <= 1'b1;
else if (tao_reg == ((CNT_PRI_MAX + 1'b1)/(CNT_TAO_MAX + 1'b1)) - 1'b1)
pri_en <= 1'b0;
else
pri_en <= pri_en;
//tao使能信号
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
tao_en <= 1'b0;
else if (cnt_ctrl1 == 1'b1)
tao_en <= 1'b1;
else if (cnt_ctrl2 == 1'b1)
tao_en <= 1'b0;
else
tao_en <= tao_en;
//一个周期内对脉宽的计数
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
tao_reg <= 8'b0;
else if (pri_en == 1'b1 && cnt_tao == CNT_TAO_MAX)
tao_reg <= tao_reg + 1'b1;
else if (tao_reg == ((CNT_PRI_MAX + 1'b1)/(CNT_TAO_MAX + 1'b1)) - 1'b1)
tao_reg <= 8'b0;
//脉冲门信号合成
assign meng = tao_en;
//频率控制字使能
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
freq_en <= 1'b0;
else if (cnt_ctrl1 == 1'b1)
freq_en <= 1'b1;
else if (cnt_tao == CNT_TAO_MAX/2)
freq_en <= 1'b0;
else
freq_en <= freq_en;
//频率控制字产生
//always @(posedge sys_clk or posedge sys_rst_n) //正在TAO内累加,在TAO外面清除
// if(sys_rst_n == 1'b0)
// begin
// dds_pinc_in <= FREQ_START;
// dds_poff_in <= 32'b0;
// end
// else if(freq_en == 1'b1 && tao_en == 1'b1)
// begin
// dds_pinc_in <= dds_pinc_in - (FREQ_STEP/2);//hband_phase + (step_phase/2)
// dds_poff_in <= 32'b0000_0000;//init_phase
// end
// else if(freq_en == 1'b0 && tao_en == 1'b1)
// begin
// dds_pinc_in <= dds_pinc_in - (FREQ_STEP/2);//dds_pinc_in + step_phase(10,976,027) 159,243,070,680 4,294,967,296
// dds_poff_in <= 32'b0000_0000;//init_phase
// end
// else
// begin
// dds_pinc_in <= FREQ_START;//32'b0;
// dds_poff_in <= 32'b0;
// end
always @(posedge sys_clk or posedge sys_rst_n)
if(sys_rst_n == 1'b0)
begin
dds_pinc_in <= FREQ_START;
dds_poff_in <= 32'b0;
end
else if(tao_en == 1'b1)
begin
dds_pinc_in <= dds_pinc_in - (FREQ_STEP/2);//hband_phase + (step_phase/2)
dds_poff_in <= 32'b0000_0000;//init_phase
end
else
begin
dds_pinc_in <= FREQ_START;
dds_poff_in <= 32'b0;
end
assign s_axis_phase_tdata={dds_poff_in[31:0],dds_pinc_in[31:0]};
//雷达信号产生
dds dds_inst (
.aclk(sys_clk), // input wire aclk
.aclken(tao_en), // input wire aclken
.s_axis_phase_tvalid(tao_en), // input wire s_axis_phase_tvalid
.s_axis_phase_tdata(s_axis_phase_tdata), // input wire [63 : 0] s_axis_phase_tdata
.m_axis_data_tvalid(), // output wire m_axis_data_tvalid
.m_axis_data_tdata(data), // output wire [15 : 0] m_axis_data_tdata
.m_axis_phase_tvalid(), // output wire m_axis_phase_tvalid
.m_axis_phase_tdata() // output wire [31 : 0] m_axis_phase_tdata
);
clk clk_inst
(
// Clock out ports
.clk_out1(clk_125M), // output clk_out1
// Status and control signals
.reset(~sys_rst_n), // input reset
.locked(), // output locked
// Clock in ports
.clk_in1(sys_clk)); // input clk_in1
assign sin_imag = data[31:16];
assign cos_real = data[15:0];
assign data_reg = data[31:18];
assign data_out = data_reg + 8192;
assign wr_en = clk_125M;
ila_0 ila_inst (
.clk(sys_clk), // input wire clk
.probe0(data_out) // input wire [13:0] probe0
);
endmodule
其中代码中例化的ila和clk是为了上板,才例化的(可以根据自己的板子修改)
仿真代码如下:
`timescale 1ns / 1ps
//
// Company: xidian
// Engineer: CC
//
// Create Date: 2023/04/29 20:37:23
// Design Name:
// Module Name: tb_lfm_gen
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module tb_lfm_gen();
reg sys_clk;
reg sys_rst_n;
//wire meng;
//wire [31:0]data;
//wire [15:0]sin_imag;
//wire [15:0]cos_real;
wire [13:0]data_out;
wire clk_125M;
wire wr_en;
initial
begin
sys_clk = 1'b0;
sys_rst_n = 1'b0;
#20
sys_rst_n = 1'b1;
end
always #5 sys_clk = ~sys_clk;
lfm_gen
#(
.CNT_TAO_MAX (10'd999),
.CNT_PRI_MAX (15'd19_999)
)
lfm_gen_inst
(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
// .meng(meng),
// .data(data),
// .sin_imag(sin_imag),
// .cos_real(cos_real),
.wr_en(wr_en),
.clk_125M(clk_125M),
.data_out(data_out)
);
endmodule
仿真图
(注意:输出的data_out是无符号数,在最后输出到板子上的时候要将有符号数转换成无符号数)
信号说明:
clk_125M是板子上DAC的采样时钟
wr_en是DAC的写入使能
data_out是fpga给DAC的信号
pri_en在一个pri周期内会拉高,但是由于下一个pri周期会和上一个pri周期是连续的,会影响下一个脉冲前沿的赋值,所以这里了pri_en不是正真意义上的一个pri周期,在上一个pri周期快要结束的时候要提前拉低,这里就用到了tao_reg计数器,tao_reg = pri / tao。
tao_en在脉冲出现的地方拉高。
cnt_ctrl1脉冲前沿信号
cnt_ctrl2脉冲后沿信号
cnt_ctrl3 pri周期开始信号及其结束信号
cnt_tao脉宽计数器
cnt_pri pri计数器
tao_reg pri的时间和tao时间的比值
dds_pinc_in相位增加量的计算信号
dds_poff_in相位偏移量的计算
data dds输出的数据
从上图我们可以看出已近产生了对应的脉宽和pri
由于加入了tao_ref计数器,所以可以灵活的修改你想要的脉宽和pri参数
上图就是改变pri为100us时候的结果。
下面介绍频率控制字的计算:
上式是对于调谐率的计算,因为条斜率决定了频率变换的快慢。
带宽是10M,从20M变换到10M,Fbase是开始频率,detaF是变化频率,所以 Fout输出频率就是开始频率加变化频率(计算公式在赛灵思的官方手册中有说明)
硬件实现(zynq7010 + an9767)
文章来源:https://www.toymoban.com/news/detail-599481.html
文章来源地址https://www.toymoban.com/news/detail-599481.html
到了这里,关于基于FPGA线性调频信号LFM的产生的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!