news 2026/7/4 6:57:51

FPGA入门中高级项目 雷达信息处理及Verilog代码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FPGA入门中高级项目 雷达信息处理及Verilog代码

前言

由于各种原因,我们无法在网上给FPGA学习者展示雷达一些核心技术,比较遗憾。

大家都知道,FPGA起家的领域是通信和雷达。

通信因为大规模商业化进入各位生活日常,大家都还能获得较多的知识。雷达由于其特殊性,特别是前沿雷达网上公开资料不多。这给广大学子进入这个领域造成障碍。

但是随着现在4D激光雷达、4D成像毫米波雷达等民用产品上车以来,雷达离我们越来越近。自动驾驶离不开这种先进传感器,我们今天就来从FPGA工程师的角度剖析以下雷达的关键技术。

我们都知道雷达核心在信息处理(信处)和波束控制(相控阵雷达的核心),波控我们以后再说,今天我们就通过这个开源项目来了解雷达信息处理。

https://github.com/ajackevic/ELEC5882github.com/ajackevic/ELEC5882

脉冲压缩理论学习

脉冲压缩雷达是目前雷达信号的主流。因为它解决了简单脉冲雷达的问题。

我个人觉得这篇小文章讲得比大道理好些;

​编辑谈谈 雷达信号处理之脉冲压缩-CSDN博客blog.csdn.net/hahahahhahha/article/details/107040648

1.概念说明

概念澄清,在雷达信号处理中,脉冲压缩、匹配滤波、相关接收 在很多时候其实就指的是一回事。这三个词语是通过不同角度对事物的理解。

1)脉冲压缩:

在时域上来看,输入的宽脉冲经过“脉冲压缩(或者说:匹配滤波)”被压缩成窄的脉冲信号。所以,我猜这就是脉冲压缩的叫法来源。

2)匹配滤波:

滤波这个词语是频域上的概念,滤出有用信号,滤除杂波噪声等无用信号。匹配,这个词是个常识词,匹配肯定是要有对象的,那么和谁匹配呢,这里是和发射的信号相匹配呢。那么怎么就算是匹配呢,或者怎么和发射信号匹配呢?使用的是“频域上的共轭匹配”。

3)相关接收:

这个是从时域的相关性理解。利用信号和噪声相关特性的差异,进行相关运算。

2.脉冲压缩怎么来的

脉冲压缩,脉冲脉冲首先针对的是脉冲雷达,而不是连续波雷达。

雷达有两个关键指标,距离和距离分辨率。

距离就是雷达的威力作用范围,能看多远。

距离分辨率就是能够去呗多么近的多个目标。

这二者是矛盾的,为什么呢?

增大作用距离,那么就得增加功率,增加功率就需要增大我的脉冲宽度。但是增大脉冲宽度会有什么问题?答案是增大了脉冲宽度,会降低距离分辨率,具体如下图所示。

传统的单载频脉冲,面临着“看得远”与“看得清”之间的取舍。采用短脉冲,能量不够,限制了作用距离;

为了解决传统单频脉冲面临的作用距离和空间分辨率之间的矛盾,脉冲压缩技术采用这样的策略,发射宽度相对较宽而峰值功率低的脉冲,使信号有足够的能量以保证作用距离;接收时做匹配滤波,将低峰值的宽脉冲压缩成高峰值的窄脉冲,避免脉冲重叠现象,从而提高空间分辨率。

三张图都是接受 注意左边收到的信号第三张图分辨出两个目标

为了能同时兼顾探测距离和距离分辨力,脉冲雷达必须同时具备宽脉冲和窄脉冲两种能力。

随着技术发展,雷达设计人员发现,距离分辨力对窄脉冲的限制,并不需要通过压窄发射脉冲宽度来实现,也可以通过对回波脉冲的压缩处理来实现。

即在电磁波发射时采用具备特殊调制的宽脉冲信号,以提高雷达的平均发射功率,在回波接收处理时采用特殊的信号处理手段,获取窄的回波信号,以提高雷达的距离分辨率,这种技术称为脉冲压缩技术。

3.脉冲压缩原理

为了实现压缩,在接收机上设置一个与发射信号“共轭匹配”的压缩网络。如图5所示,时域上,匹配滤波器的冲击响应函数构造为输入信号的镜像;频域上,匹配滤波器的幅频特性与信号的幅频特性一致,如图4。当信号通过匹配滤波器时,信号越强的频率点,滤波器的放大倍数也越大;信号越弱的频率点,滤波器的放大倍数也越小,从而使信号在时域更集中。

另外一方面,从相频特性上看,匹配滤波器的相频特性和输入信号正好完全相反。这样,通过匹配滤波器后,信号的相位为0,正好能实现信号时域上的相干叠加。而噪声的相位是随机的,只能实现非相干叠加。这样在时域上保证了输出信噪比的最大。

我理解:所谓匹配滤波就是移相90度,刚好相位相反。

可以进行脉冲压缩的信号

脉冲压缩策略的实施有个重要思路就是:设计一个可以进行进行脉冲压缩的波形,代替传统的单载频脉冲波形。

这个信号的要求就是:拥有大的时宽带宽积。

上面的线性调频信号相对于单载频信号,同样的时宽下却有着更大的带宽(频域的带宽),所以可以作为一种脉冲压缩信号。就是我们需要的发射信号

以上是国内同学的笔记。来自CSDN,在这里对这位同学表示感谢。

另外推荐看wiki百科:

https://en.wikipedia.org/wiki/Pulse_compressionen.wikipedia.org/wiki/Pulse_compression

稍微有点长。

具体到本项目中脉冲压缩滤波器如何工作?

脉冲压缩滤波器用于调制发射脉冲。这会增加发射信号的带宽,从而提高距离分辨率。调制可以是频率或相位。在本项目中,线性频率调制 (LFM 或有时也称为 chirp) 用于调制发射脉冲。

脉冲压缩滤波器主要作用于匹配滤波器(本项目重点介绍匹配滤波器的时间域实现)。匹配滤波器执行雷达系统回波信号与匹配滤波器脉冲响应之间的卷积。其中脉冲响应是发射脉冲的复共轭时间反转。

为了避免混叠,回波信号和匹配滤波器脉冲响应都经过希尔伯特变换,从而消除负频率。希尔伯特变换输出一个复数值,因此匹配滤波器执行复卷积,这是通过使用复 FIR 滤波器实现的。有关 FIR 和复 FIR 滤波器如何工作的详细说明,请参阅文件夹“FIR 滤波器的工作原理”。计算匹配滤波器的绝对值以获得信号的包络,从而获得脉冲压缩滤波器的输出。

有关匹配滤波器、LFM 和希尔伯特变换的更多信息,请参阅以下链接:https://en.wikipedia.org/wiki/Matched_filter

https://en.wikipedia.org/wiki/Chirp

https://en.wikipedia.org/wiki/Hilbert_transform

我们回到重点:

FPGA代码实现:

首先我们通过MATLAB仿真,

下面回波输入信号(在 FPGAPulseCompressionFilter.m 中创建并加载到 FPGA 设计的合成数据)

计算复数FIR滤波器的系数

项目提供得有matlab代码,大家可以仿真,也可以修改成自己需要参数。

下面是整个项目的代码目录

下面是TOP模块,

设计了一个简单的状态机,当参数输入完成之后 开始处理脉冲压缩滤波(Matched Filter匹配滤波)

module pulse_compression_filter #( parameter COEFF_LENGTH = 800, parameter DATA_LENGTH = 7700, parameter HT_COEFF_LENGTH = 27, parameter DATA_WIDTH = 12 // It should be noted the stated parameters must match the values in the MATLAB script. // COEFF_LENGTH and DATA_LENGTH must be exactly half the length of the data in the MIF files. This is done so // as muiltiplication is easier to do than devisision. )( input clock, input enable, output reg [31:0] MFOutput ); // Local parameters for the module read_MIF_file. localparam COEFF = 1; localparam DATA_IN = 2; // Local parameters for the module square_root_cal. // ABS_DATA_IN_WIDTH is determind by log2[(2^(DATA_WIDTH - 1) - 1)^2 + (2^(DATA_WIDTH - 1) - 1)^2] // rounded up even value. ABS_DATA_OUT_WIDTH must be half of ABS_DATA_IN_WIDTH. localparam ABS_DATA_IN_WIDTH = 84; localparam ABS_DATA_OUT_WIDTH = 42; // Enable regs for the instantiated modules. reg enableMFCoeff; reg enableMFDataIn; reg enablecomplexFIRCoeff; reg enableHT; reg enableComplexFIRData; reg enableSquar; reg [ABS_DATA_IN_WIDTH - 1:0] absInputValue; wire [ABS_DATA_OUT_WIDTH - 1:0] absOutputValue; // A reg for informing the complex FIR filter when the data is about to be stopped. reg stopDataLoadFlag; // Output ports for the instantiated modules. wire coeffFinishedFlag; wire dataInFinishedFlag; wire signed [DATA_WIDTH - 1:0] coeffMIFOutRe; wire signed [DATA_WIDTH - 1:0] coeffMIFOutIm; wire signed [DATA_WIDTH - 1:0] dataMIFOutRe; wire signed [(DATA_WIDTH * 3) - 1:0] HTOutRe; wire signed [(DATA_WIDTH * 3) - 1:0] HTOutIm; wire signed [(DATA_WIDTH * 4) - 1:0] MFOutputRe; wire signed [(DATA_WIDTH * 4) - 1:0] MFOutputIm; // FSM reg [2:0] state; localparam IDLE = 1; localparam SET_ENABLE = 2; localparam STOP = 3; // Set the initial values of the local parameters. initial begin enableMFCoeff <= 1'd0; enableMFDataIn <= 1'd0; enablecomplexFIRCoeff <= 1'd0; enableHT <= 1'd0; enableSquar <= 1'd0; enableComplexFIRData <= 1'd0; stopDataLoadFlag <= 1'd0; absInputValue <= {(ABS_DATA_IN_WIDTH){1'd0}}; state <= IDLE; end // Instantiating the module read_MIF_file. This is used to read the coefficients from the MFImpulseCoeff.mif file. read_MIF_file #( .LENGTH (COEFF_LENGTH), .DATA_WIDTH (DATA_WIDTH), .DATA_TYPE (COEFF) ) MFCoeff ( .clock (clock), .enable (enableMFCoeff), .dataFinishedFlag (coeffFinishedFlag), .outputRe (coeffMIFOutRe), .outputIm (coeffMIFOutIm) ); // Instantiating the module read_MIF_file. This is used to read the data in from the MFInputData.mif file. read_MIF_file #( .LENGTH (DATA_LENGTH), .DATA_WIDTH (DATA_WIDTH), .DATA_TYPE (DATA_IN) ) MFDataIn ( .clock (clock), .enable (enableMFDataIn), .dataFinishedFlag (dataInFinishedFlag), .outputRe (dataMIFOutRe), .outputIm () // This port is ignored as all data is passed through outputRe. ); // Instantiating the module n_tap_complex_fir. This is used for the main opperation of the matched filter // between the complex input data and the complex impulse reponse of the matched filter. n_tap_complex_fir #( .LENGTH (COEFF_LENGTH), .DATA_WIDTH (DATA_WIDTH) ) coplexFIR ( .clock (clock), .loadCoeff (enablecomplexFIRCoeff), .coeffSetFlag (coeffFinishedFlag), .loadDataFlag (enableComplexFIRData), .stopDataLoadFlag (stopDataLoadFlag), .dataInRe (HTOutRe), .dataInIm (HTOutIm), .coeffInRe (coeffMIFOutRe), .coeffInIm (coeffMIFOutIm), .dataOutRe (MFOutputRe), .dataOutIm (MFOutputIm) ); // Instantiating the module hilbert_transform. This is used to aquire a complex signal from a real signal // by performing hilbert transform filtering of the data aquired from MFInputData.mif. hilbert_transform #( .LENGTH (HT_COEFF_LENGTH), .DATA_WIDTH (DATA_WIDTH) ) hilbertTransform ( .clock (clock), .enable (enableHT), .stopDataInFlag (), .dataIn (dataMIFOutRe), .dataOutRe (HTOutRe), .dataOutIm (HTOutIm) ); square_root_cal #( .INPUT_DATA_WIDTH (ABS_DATA_IN_WIDTH), .OUTPUT_DATA_WIDTH (ABS_DATA_OUT_WIDTH) ) squr( .clock (clock), .enable (enableSquar), .inputData (absInputValue), .outputData (absOutputValue) ); always @ (posedge clock) begin case(state) // State IDLE. This state waits until enable is set before transistioning to LOAD_COEFF. IDLE: begin if(enable) begin state <= SET_ENABLE; end end // State LOAD_COEFF. This state enables the majority of the enable regs for the instantiated modules. // Since the input data is only 14400 long, after it has read thoes values, the output of this module // will be 'don't care bits'/unkown. To prevent that, supply more input data. SET_ENABLE: begin // When the coefficients have been loaded do the following. if(coeffFinishedFlag) begin enableMFCoeff <= 1'd0; enablecomplexFIRCoeff <= 1'd0; enableMFDataIn <= 1'd1; enableHT <= 1'd1; enableComplexFIRData <= 1'd1; enableSquar <= 1'd1; end // Whilst the coefficients are being loaded do the following. else begin enableMFCoeff <= 1'd1; enableMFDataIn <= 1'd1; enablecomplexFIRCoeff <= 1'd1; enableHT <= 1'd1; enableComplexFIRData <= 1'd1; enableSquar <= 1'd1; end absInputValue <= (MFOutputRe * MFOutputRe) + (MFOutputIm * MFOutputIm); MFOutput <= absOutputValue[41:10]; end // State STOP. This is an empty state that is not used in this design. STOP: begin end // State default. This state sets the default values just incase the FSM is in an unknown state. default: begin enableMFCoeff <= 1'd0; enableMFDataIn <= 1'd0; enablecomplexFIRCoeff <= 1'd0; enableHT <= 1'd0; enableComplexFIRData <= 1'd0; stopDataLoadFlag <= 1'd0; state <= IDLE; end endcase end endmodule

整个项目的仿真

滤波器

module n_tap_complex_fir #( parameter LENGTH = 12, parameter DATA_WIDTH = 8 )( input clock, input loadCoeff, input coeffSetFlag, input loadDataFlag, input stopDataLoadFlag, input signed [(DATA_WIDTH * 3) - 1:0] dataInRe, input signed [(DATA_WIDTH * 3) - 1:0] dataInIm, input signed [DATA_WIDTH - 1:0] coeffInRe, input signed [DATA_WIDTH - 1:0] coeffInIm, output reg signed [(DATA_WIDTH * 4) - 1:0] dataOutRe, output reg signed [(DATA_WIDTH * 4) - 1:0] dataOutIm ); // Creating the buffers to store the input data and coefficients. reg signed [DATA_WIDTH - 1:0] coeffBufferRe [0:LENGTH - 1]; reg signed [DATA_WIDTH - 1:0] coeffBufferIm [0:LENGTH - 1]; reg signed [(DATA_WIDTH * 3) - 1:0] inputDataBufferRe [0:LENGTH -1]; reg signed [(DATA_WIDTH * 3) - 1:0] inputDataBufferIm [0:LENGTH -1]; // Note the range of reg signed [7:0] is [-128 to 127]. reg signed [DATA_WIDTH - 1:0] coeffPreBufferRe [0:2]; reg signed [DATA_WIDTH - 1:0] coeffPreBufferIm [0:2]; // FIR = output width = input data width + coefficient width + log(N) reg signed [(DATA_WIDTH * 4) - 1:0] firOutputReRe; reg signed [(DATA_WIDTH * 4) - 1:0] firOutputReIm; reg signed [(DATA_WIDTH * 4) - 1:0] firOutputImRe; reg signed [(DATA_WIDTH * 4) - 1:0] firOutputImIm; reg [19:0] coeffBufferCounter; // FSM states. reg [2:0] state; reg [2:0] IDLE = 3'd0; reg [2:0] WAIT_1_CYCLE = 3'd1; reg [2:0] FIR_MAIN = 3'd2; reg [2:0] STOP = 3'd3; reg [2:0] EMPTY_STATE1 = 3'd4; reg [2:0] EMPTY_STATE2 = 3'd5; reg [2:0] EMPTY_STATE3 = 3'd6; reg [2:0] EMPTY_STATE4 = 3'd7; // Setting the initial values. initial begin : init_values // Set all the values inside the buffers to 0. integer k; for (k = 0; k <= LENGTH - 1 ; k = k + 1) begin coeffBufferRe[k] <= 0; coeffBufferIm[k] <= 0; inputDataBufferRe[k] <= 0; inputDataBufferIm[k] <= 0; end coeffBufferCounter <= 20'd0; state <= IDLE; coeffPreBufferRe[0] <= {(DATA_WIDTH){1'd0}}; coeffPreBufferIm[0] <= {(DATA_WIDTH){1'd0}}; coeffPreBufferRe[1] <= {(DATA_WIDTH){1'd0}}; coeffPreBufferIm[1] <= {(DATA_WIDTH){1'd0}}; coeffPreBufferRe[2] <= {(DATA_WIDTH){1'd0}}; coeffPreBufferIm[2] <= {(DATA_WIDTH){1'd0}}; firOutputReRe <= 0; firOutputReIm <= 0; firOutputImRe <= 0; firOutputImIm <= 0; dataOutRe <= 0; dataOutIm <= 0; end integer n; always @(posedge clock) begin case(state) // State IDLE. This state transitions to WAIT_1_CYCLE. IDLE: begin if(loadCoeff) begin state <= WAIT_1_CYCLE; end end // State WAIT_1_CYCLE. This state is waits for 1 clock cyle. WAIT_1_CYCLE: begin state <= FIR_MAIN; end // State FIR_MAIN. This state is responsiable for the main FIR opperation. It follows // the logic outlined in the pdf "The workings of a complex FIR filter". It also load // the coefficients in parallel to the FIR opperation. FIR_MAIN: begin // Continoue loading the coefficients. if(coeffBufferCounter <= LENGTH + 2) begin coeffPreBufferRe[0] <= coeffInRe; coeffPreBufferIm[0] <= coeffInIm; for (n = 0; n < 2; n = n + 1) begin coeffPreBufferRe[n+1] <= coeffPreBufferRe[n]; coeffPreBufferIm[n+1] <= coeffPreBufferIm[n]; end coeffBufferRe[LENGTH - coeffBufferCounter - 1 + 3] <= coeffPreBufferRe[2]; coeffBufferIm[LENGTH - coeffBufferCounter - 1 + 3] <= coeffPreBufferIm[2]; coeffBufferCounter <= coeffBufferCounter + 20'd1; end // If the data input stream is ready, do the following. if(loadDataFlag == 1) begin // Shift the values inside inputDataBufferRe and inputDataBufferIm by 1. for (n = LENGTH - 1; n > 0; n = n - 1) begin inputDataBufferRe[n] <= inputDataBufferRe[n - 1]; inputDataBufferIm[n] <= inputDataBufferIm[n - 1]; end // Load the inputDataBufferRe and inputDataBufferIm values to the start of the buffer. inputDataBufferRe[0] <= dataInRe; inputDataBufferIm[0] <= dataInIm; // firOutput is set to 0, as everytime FIR_MAIN loops, previous firOutput value is used, hence the first // firOutput value that is used in the for loop would not be of the correct value. firOutputReRe = 0; firOutputReIm = 0; firOutputImRe = 0; firOutputImIm = 0; // This operation does the multiplication and summation between corresponding input data with /// the corresponding coefficients. for (n = 0; n <= LENGTH - 1; n = n + 1) begin firOutputReRe = firOutputReRe + (inputDataBufferRe[n] * coeffBufferRe[LENGTH - 1 - n]); firOutputReIm = firOutputReIm + (inputDataBufferRe[n] * coeffBufferIm[LENGTH - 1 - n]); firOutputImRe = firOutputImRe + (inputDataBufferIm[n] * coeffBufferRe[LENGTH - 1 - n]); firOutputImIm = firOutputImIm + (inputDataBufferIm[n] * coeffBufferIm[LENGTH - 1 - n]); end // Addition / subtraction opperation required for the complex numbers. dataOutRe = firOutputReRe - firOutputImIm; dataOutIm = firOutputReIm + firOutputImRe; end // Transition to stop state when stopDataLoadFlag is 1. if(stopDataLoadFlag == 1) begin state = STOP; end end // State Stop. This state is responsiable for the resetting of the used parameters and then // transistioning to the state IDLE. STOP: begin: resetValues // Set all the values inside the coeffBuffer to 0. integer k; for (k = 0; k <= LENGTH - 1 ; k = k + 1) begin coeffBufferRe[k] <= 0; coeffBufferIm[k] <= 0; inputDataBufferRe[k] <= 0; inputDataBufferIm[k] <= 0; end // Set the internal variables and outputs to 0. state <= IDLE; dataOutRe <= 0; dataOutIm <= 0; firOutputReRe <= 0; firOutputReIm <= 0; firOutputImRe <= 0; firOutputImIm <= 0; end // Empty states that transition to IDLE. These are added to remove any infered latched by Quartus // for the FSM. EMPTY_STATE1: begin state <= IDLE; end EMPTY_STATE2: begin state <= IDLE; end EMPTY_STATE3: begin state <= IDLE; end EMPTY_STATE4: begin state <= IDLE; end // State default. This state is added just incase the FSM is in an unknown state, it resets all // all the local parameter and sets state to IDLE. default: begin: defaultValues // Set all the values inside the coeffBuffer to 0. integer k; for (k = 0; k <= LENGTH - 1 ; k = k + 1) begin coeffBufferRe[k] <= 0; coeffBufferIm[k] <= 0; inputDataBufferRe[k] <= 0; inputDataBufferIm[k] <= 0; end // Set the internal variables and outputs to 0. state <= IDLE; dataOutRe <= 0; dataOutIm <= 0; firOutputReRe <= 0; firOutputReIm <= 0; firOutputImRe <= 0; firOutputImIm <= 0; end endcase end endmodule

Hilbert 变换

module hilbert_transform #( parameter LENGTH = 27, parameter DATA_WIDTH = 18 )( input clock, input enable, input stopDataInFlag, input signed [DATA_WIDTH - 1:0] dataIn, output reg signed [(DATA_WIDTH * 3) - 1:0] dataOutRe, output reg signed [(DATA_WIDTH * 3) - 1:0] dataOutIm ); // Local parameter used in this module. reg signed [(DATA_WIDTH * 3) - 1:0] dataInBuf [0:2]; // Local parameters for the module setup_HT_coeff. reg loadCoeff; wire coeffSetFlag; wire [DATA_WIDTH - 1:0] HTCoeffOut; // Local parameter for the module n_tap_fir. reg loadFIRDataFlag; reg stopFIRDataFlag; reg [DATA_WIDTH - 1:0] dataFIRIn; reg loadCoeffFIRFlag; wire [(DATA_WIDTH * 3) - 1:0] FIRDataOut; // Create the FSM. reg [1:0] state; localparam IDLE = 2'd0; localparam LOAD_FIR_COEFF = 2'd1; localparam MAIN_OPP = 2'd2; localparam STOP = 2'd3; // Set the initial local parameters and outputs. initial begin: init_values integer k; for (k = 0; k <= 2 ; k = k + 1) begin dataInBuf[k] <= 0; end state <= IDLE; loadCoeff <= 1'd0; loadFIRDataFlag <= 1'd0; stopFIRDataFlag <= 1'd0; loadCoeffFIRFlag <= 1'd0; dataFIRIn <= {(DATA_WIDTH){1'd0}}; dataOutRe <= {(DATA_WIDTH * 3){1'd0}}; dataOutIm <= {(DATA_WIDTH * 3){1'd0}}; end // Instantiating the setup of the hilber transfer coefficient module. This // module passes the LENGTH amount of coefficients through coefficientOut. setup_HT_coeff #( .LENGTH (LENGTH), .DATA_WIDTH (DATA_WIDTH) )Coefficients( .clock (clock), .enable (loadCoeff), .coeffSetFlag (coeffSetFlag), .coeffOut (HTCoeffOut) ); // Instantiating the FIR module. This module performs the convelution opperation // between coeffIn and dataIn. The output product is dataOut. n_tap_fir #( .LENGTH (LENGTH), .DATA_WIDTH (DATA_WIDTH) )FIRFilter( .clock (clock), .loadCoeff (loadCoeff), .coeffSetFlag (loadCoeffFIRFlag), .loadDataFlag (loadFIRDataFlag), .stopDataLoadFlag (stopFIRDataFlag), .coeffIn (HTCoeffOut), .dataIn (dataFIRIn), .dataOut (FIRDataOut) ); integer n; always @ (posedge clock) begin case(state) // State IDLE. This state waits till enable is set high before transistioning // to LOAD_FIR_COEFF. If enable is set low, it sets the outputs to low. IDLE: begin if(enable) begin state <= LOAD_FIR_COEFF; loadCoeff <= 1'd1; loadCoeffFIRFlag <= 1'd1; end else begin dataOutRe <= {(DATA_WIDTH * 3){1'd0}}; dataOutIm <= {(DATA_WIDTH * 3){1'd0}}; end end // State LOAD_FIR_COEFF. This state sets the corresponding flags and tranistions to // the state MAIN_OPP. LOAD_FIR_COEFF: begin state <= MAIN_OPP; loadFIRDataFlag <= 1'd1; loadCoeffFIRFlag <= 1'd0; end // State MAIN_OPP. This state passes through the dataIn values to the FIR // module through the variabel dataFIRIn. These values are then conveluted // with the coefficients. If stopDataInFlag is set high, the state will // transistion to STOP. The coefficient will finish loading in this state hence // an if statment was added to set the flag loadCoeff once all of the coefficients // are passed through. MAIN_OPP: begin if(coeffSetFlag) begin loadCoeff <= 1'd0; end if(stopDataInFlag) begin state <= STOP; end else begin dataFIRIn <= dataIn; dataOutIm <= FIRDataOut; dataInBuf[0] <= dataIn; dataOutRe <= dataInBuf[2]; // Shift the values inside the buffer by one position. for (n = 0; n < 2; n = n + 1) begin dataInBuf[n+1] <= dataInBuf[n]; end end end // State STOP. This state stops the FIR and HT opperation as well as // setting some of the local variables and outputs to 0. STOP: begin state <= IDLE; loadCoeff <= 1'd0; loadFIRDataFlag <= 1'd0; stopFIRDataFlag <= 1'd0; dataFIRIn <= {(DATA_WIDTH){1'd0}}; dataOutRe <= {(DATA_WIDTH * 3){1'd0}}; dataOutIm <= {(DATA_WIDTH * 3){1'd0}}; end // State Default. This state exsists purley just incase the FSM is in // an unkown state. It resets the initial values. default: begin state <= IDLE; loadCoeff <= 1'd0; loadFIRDataFlag <= 1'd0; stopFIRDataFlag <= 1'd0; dataFIRIn <= {(DATA_WIDTH){1'd0}}; dataOutRe <= {(DATA_WIDTH * 3){1'd0}}; dataOutIm <= {(DATA_WIDTH * 3){1'd0}}; end endcase end endmodule

以上是最重要的三个模块

最后:

雷达信号处理已经发展多年,FPGA用于雷达处理除了以上的脉压滤波之外,还有比如实时聚类等等用法,这篇文章作为如何可以给FPGA开发者做算法Verilog代码实现和优化作为参考。

采用了开源项目作为介绍,基本把脉冲压缩的实现展示出来。

这篇文章是脉冲压缩信号接收之后滤波,如何生成脉压,也有开源项目可供参考。

可以关注我和我栏目。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/4 6:57:36

jqjq环境与路径追踪:执行上下文管理的核心技术

jqjq环境与路径追踪&#xff1a;执行上下文管理的核心技术 【免费下载链接】jqjq jq implementation of jq 项目地址: https://gitcode.com/gh_mirrors/jq/jqjq jqjq是一个用jq语言实现的jq解释器&#xff0c;它展示了jq语言的强大表达能力和灵活性。作为JSON处理工具的…

作者头像 李华
网站建设 2026/7/4 6:57:30

PoseDiffusion常见问题解答:从安装到部署的完整问题解决方案

PoseDiffusion常见问题解答&#xff1a;从安装到部署的完整问题解决方案 【免费下载链接】PoseDiffusion [ICCV 2023] PoseDiffusion: Solving Pose Estimation via Diffusion-aided Bundle Adjustment 项目地址: https://gitcode.com/gh_mirrors/po/PoseDiffusion Pose…

作者头像 李华
网站建设 2026/7/4 6:56:51

Offix深度解析:革命性GraphQL离线客户端与服务器解决方案

Offix深度解析&#xff1a;革命性GraphQL离线客户端与服务器解决方案 【免费下载链接】offix GraphQL Offline Client and Server 项目地址: https://gitcode.com/gh_mirrors/of/offix 在当今移动优先的世界中&#xff0c;构建可靠的离线应用已成为开发者的核心挑战。Of…

作者头像 李华
网站建设 2026/7/4 6:55:44

CANN/cannbot-skills:Kernel文件侦察

Scout-K&#xff1a;Kernel 文件侦察 【免费下载链接】cannbot-skills CANNBot 是面向 CANN 开发的用于提升开发效率的系列智能体&#xff0c;本仓库为其提供可复用的 Skills 模块。 项目地址: https://gitcode.com/cann/cannbot-skills 执行顺序&#xff08;最高优先级&…

作者头像 李华