• XILINX FIR IP 详解、Verilog 源码、Vivado 工程


    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
    本文链接:https://blog.csdn.net/qq_46621272/article/details/125292610

    XILINX FIR IP 详解、Verilog 源码、Vivado 工程


    文章目录


    前言

    FIR 是个比较复杂的 IP ,不同的设置需要不同的代码去配合。这篇文章详细介绍了这 FIR IP 设置需要注意的地方。
    本文中介绍了五个实验,最基础的应用实验,FIR +FIFO实验,多通道多套系数配置实验,Reload Config 实验等,全面介绍了 FIR 的各种应用。所有实验提供 Vivado工程,Verilog代码下载,还有较为详细的文字图片介绍。


    一、FIR IP 详解(Vivado 2017.4 环境 FIR Compiler 7.2)

    XILINX 官方 FIR 手册: https://docs.xilinx.com/v/u/en-US/pg149-fir-compiler
    本文只介绍一些常用到的功能设置,和需要注意的地方。一些没介绍到的功能和细节请仔细阅读手册。
    在这里插入图片描述

    • 01:这部分很多人容易忽略,需要时刻关注这部分,在做一些 Reload/Config/多通道/等应用设置后,要及时查看这部分的变化。

    • 02: FIR 系数,本文的所有例子都是采用 COE File 方式导入 FIR 系数文件,本文的“COE”文件是由 Matlab 下的
      Filter Designer 生成,相关方法和使用请看本文的附件二。

    • 03:多套系数的导入,这个数需要我们填写,还需要根据这个数去合理的人工合并编辑 COE 文件或 Vector 内容。这里需要注意的是我们在合并 COE 文件时,最好选用相同系数的数量及相同的系数对称方式去合并。

      • A:最好选用相同系数的对称方式的COE数据去合并
        系数的对称方式简介:
        奇对称:系数数量是奇数,且左右对称,比如:1,-2,3,-2,1
        偶对称:系数数量是偶数,且左右对称,比如:-1,2,2,-1
        负对称:系数数量是偶数,且左右负对称,比如:1,-2,3,-3,2,-1
        不对称:比如:1,-2,3,4
      • B:最好选用相同系数数量的 COE 系数去合并,在数量不一致且对称方式一样的情况下,可以手工补 0 的方式将 COE 的系数数量调整到一致。
        比如:
        B1:对称系数:0, 1,-2, 3,-2, 1, 0 (前后补 0 ,可以补多个 0)
        B2:不对称系数: 1,-2,3,4,0,0 (后补 0 ,可以补多个 0)
      • C:在系数数量不同,而且系数对称方式不一致时,也能合并。需要将所有的系数都按不对称处理。这种模式下会占用较多的 DSP 资源。
        C1:需要在 FIR Coefficient Options的设置中将 Coefficient Structure 选成 Non-symmetric (不对称方式)
        C2:按不对称系数的后补 0 方式将所有数据的数量调整成一样再合并
        可以参考下本文后面的实验,有具体的例子和代码:
      • FIR 高级应用 - 多通道共用一个 FIR (四个通道共用同一个 FIR I+P 每个通道采用不同的 FIR 系数算法)。
      • FIR 高级应用 FIR Reload、Config 的使用。
      • D:在编辑 COE 文件补 0 时要补全比如 16 位系数,要敲 “0000” 四个零,要敲全。

      • D1:奇对称 5 个系数和奇对称 7 个系数合并
      • 奇对称 5 个系数文件
        Radix = 16;
        Coefficient_Width = 16;
        CoefData = 0001,
        0002,
        0003,
        0002,
        0001;

      • 奇对称 7 个系数文件
        Radix = 16;
        Coefficient_Width = 16;
        CoefData = 0005,
        0004,
        0003,
        0002,
        0003,
        0004,
        0005;

      • 奇对称 5 个系数和奇对称 7 个系数合并后
        Radix = 16;
        Coefficient_Width = 16;
        CoefData = 0000,
        0001,
        0002,
        0003,
        0002,
        0001,
        0000,
        0005,
        0004,
        0003,
        0002,
        0003,
        0004,
        0005;


      • D2: 偶对称 6 个系数,奇对称 5 个系数合并,这只能按不对称补 0 合并
      • 偶对称 6 个系数文件
        Radix = 16;
        Coefficient_Width = 16;
        CoefData = 0001,
        0002,
        0003,
        0003,
        0002,
        0001;

      • 奇对称 5 个系数文件
        Radix = 16;
        Coefficient_Width = 16;
        CoefData = 0003,
        0004,
        0005,
        0004,
        0003;

      • 奇对称 5 个系数和 5.coe 偶对称 6 个系数合并后文件,按不对称后补 0
        Radix = 16;
        Coefficient_Width = 16;
        CoefData = 0001,
        0002,
        0003,
        0003,
        0002,
        0001,
        0003,
        0004,
        0005,
        0004,
        0003,
        0000;

    • 04:Reload 重新加载系数


      • A:重新加载的系数与原系数的数量必须一致,如果不一致可以参考 03 将系数补 0 的方式调整成一样。
      • B:重新加载的系数的对称方式必须一致,如果不一致可以参考 03 将系数的对称方式全部按不对称处理。
      • C:重新加载的系数必须用 Config 去激活才能生效。
      • D:可以参考下本文后面的实验:FIR 高级应用 FIR Reload、Config 的使用
      • E:人工编辑、补 0 Reload 数据,对称数据需要折半后前补 0

      • E1:Reload 奇对称数据编辑,按 9 个长度补 0 折半后就是 5 个系数数据。
      • 奇对称 5 个系数,按对称数据折半后前补 0
        Radix = 16;
        Coefficient_Width = 16;
        CoefData = 0001,
        0002,
        000a,
        0002,
        0001;
      • 编辑后
        0000
        0000
        0001
        0002
        000a

      • 奇对称 7 个系数,按对称数据折半后前补 0
        Radix = 16;
        Coefficient_Width = 16;
        CoefData = 0005,
        000b,
        0003,
        0002,
        0003,
        000b,
        0005;
      • 编辑后
        0000
        0005
        000b
        0003
        0002

      • D2:Reload 偶对称数据编辑,按 10 个长度补 0 折半后就是 5 个系数数据。
      • 偶对称 6 个系数,按对称数据折半后前补 0
        Radix = 16;
        Coefficient_Width = 16;
        CoefData = 0001,
        0002,
        0003,
        0003,
        0002,
        0001;
      • 编辑后
        0000
        0000
        0001
        0002
        0003

      • 偶对称 4 个系数,按对称数据折半后前补 0
        Radix = 16;
        Coefficient_Width = 16;
        CoefData = 000a,
        000b,
        000b,
        000a;
      • 编辑后
        0000
        0000
        0000
        000a
        000b

      • E3:Reload 奇偶对称混合数据编辑,按 10 个长度补 0 ,按不对称数据处理。
      • 奇对称 5 个系数,按不对称数据后补 0
        Radix = 16;
        Coefficient_Width = 16;
        CoefData = 0001,
        0002,
        000a,
        0002,
        0001;
      • 编辑后
        0001
        0002
        000a
        0002
        0001
        0000
        0000
        0000
        0000
        0000

      • 偶对称 6 个系数,按不对称数据后补 0
        Radix = 16;
        Coefficient_Width = 16;
        CoefData = 0001,
        0002,
        0003,
        0003,
        0002,
        0001;
      • 编辑后
        0001
        0002
        0003
        0003
        0002
        0001
        0000
        0000
        0000
        0000
    • 05: Filter Specification 滤波器类型,可以支持以下五种类型

      FIR IP 持 5 种滤波类型
      Single-rate (缺省)
      Interpolating
      Decimating (实验 FIR 高级应用 - AM 调幅波调制解调通过这个选择改变 FIR 输出的采样频率)
      Hilbert transform
      Interpolated
      我们可以选用合适的类型完成我们的设计。其中的 Interpolating 插值,Decimating 抽值能改变 FIR 输出的采样频率。可以参考下实验的代码。在实验里我们就用 Decimating 类型将采样频率降低为原来的 1/16,将采样频率从 1MHz 降低到 62.5KHz。

    在这里插入图片描述

    • 06:Channel Sequence 通道序列选择,在我们的实验中均选用 Basic。在 Number of Channels 通道数量为 1 时也只能选用 Basic。
      Basic 的多通道模式,各通道的采样频率必须同步、一致。
      在 Advanced 选项里,各通道的采样频率允许有限制的不一样,但必须是同步的同一时钟源的。这 Advanced 选项的细节请阅读手册吧。
    • 07:Number of Channels 通道数量,这里的多通道是串行的,比如双通道 C0,C1 这俩通道 C0、C1 交错输入交错输出分时使用。
    • 08:Parallel Channel Specification 并行的通道设置,并行通道数量。各通道的采样频率必须同步、一致。
    • 09:输入的采样时钟频率,这是个虚值,并没用这个采样时钟的管脚。这个值的设置要根据整个 FIR 的应用来决定。
    • 10:FIR 实际工作的时钟频率
    • 11:FIR 时钟设置,09,10 这俩时钟的设置需要是相互关联的。这俩值根据不同的应用会有不同的变化。
    • 应用1: 输入的采样时钟频率和 FIR 实际工作的时钟频率设成一样。
      优点:这种 FIR 的应用,FIR 外围设计非常简单。
      缺点:占用 DSP 资源较大。
      使用范围:适用于高速的采样速率的方案,适用于对 DSP 资源消耗不高的应用。
    • 应用2: 输入的采样时钟频率小于 FIR 实际工作的时钟频率。
      由于输入的采样时钟和 FIR 的工作时钟不同,输入的数据流一般要用一个 FIFO 做跨越时钟域的转换。
      优点:这种 FIR 的应用,能极大的降低 DSP 资源的使用。在一些低速应用中能选用高阶滤波算法。比如一万个系数的 FIR 运算。
      缺点:这种 FIR 的应用,FIR 外围设计设计较复杂,一般需要用 FIFO。
      使用范围:适用于低速的采样速率的方案,适用于对 DSP 资源消耗很高的应用。
    • 应用3: 输入的采样时钟频率大于 FIR 实际工作的时钟频率。
      这种应用能实现超高速的 FIR 应用。这种应用消耗资源成倍的增加。和应用2一样这种应用也需要 FIFO ,应用比较复杂。
      优点:实现超高速的 FIR 运算,比如 7 系列 XILINX FPGA 实现。FIR 的工作时钟能到 300MHz,用这种方法能实现 300MHz * N 的高速计算。
      缺点:这种 FIR 的应用占用 DSP 的资源成 N 倍的增长。FIR 外围设计设计较复杂,一般需要用 FIFO。
      使用范围:适用于超高速的采样速率的方案。

    在这里插入图片描述

    • 12:FIR 系数的设置需要和 COE 文件保持一致,在我们的实验中这个设置均为 Signed,16 位宽度。

    • 13:Coefficient Structure 系数结构,自动,对称,非对称,负对称系数的选择。在多组系数 Config 应用和 Reload 应用中,需要设置该值。请参考 03,04章节的介绍,请参考实验。

    • 14:输入输出数据设置,按实际应用去设置位宽和精度。
      在这里插入图片描述

    • 15:请阅读手册。在我们的实验中这部分都是按缺省值设置。
      在这里插入图片描述

    • 16:数据通道选择。按实际应用去选择。

    • 17:USER 输入输出设置,在多通道的实验中 USER Output 设置 Chan ID Field

    • 18:在串行多通道中,该选项能支持每个通道选用不同的 FIR 系数设置。在实验中,选用 By Channel

    • 19:Reload Slots ,在 Reload 应用中需要关注此值,这个值在我们使用 Reload 时,会影响 Reload 时的数据堵塞。这东西文字说不清楚,最好看看实验的代码和波形。
      举例:
      Reload Slots = 1,在 Reload 时只能下载一组系数后就堵塞了,下载数据通过 Config 须激活后才能继续下载数据。
      Reload Slots = 3,在 Reload 时能下载三组系数后就才堵塞,激活后才能继续下载数据。

    • 20:按实际应用去选择。在我们的所有实验中 ARESETn 均为使能。

    二、实验内容

    实验一、FIR 基础应用 - AM 调幅波调制解调(FIR 低通滤波)。

    1. AM 调幅波调制模块

    在这里插入图片描述

    2. am_modulation_dds.v verilog 代码

    //am_modulation_dds.v
    module	am_modulation_dds
    (
    	output			m_axis_data_tvalid,
    	input			m_axis_data_tready,
    	output	[15:0]	m_axis_data_tdata,
    	input			rst_n,
    	input			clk
    );
    
    	wire signed	[7:0]	dds_100khz_tdata_i;		//	100KHz   正弦波	AM 载波
    	wire				dds_100khz_tvalid_i;
    	wire				dds_100khz_tready_i;
    
    	wire signed	[7:0]	dds_4khz_tdata_i;		//	4khz   正弦波	AM 调制信号
    	wire				dds_4khz_tvalid_i;
    	wire				dds_4khz_tready_i;
    
    	reg signed	[15:0]	am_tdata_r;
    	reg					am_tvalid_r;
    	wire				am_tready_i;
    
    	assign	am_tready_i			= m_axis_data_tready;
    	assign	dds_100khz_tready_i	= am_tready_i;
    	assign	dds_4khz_tready_i	= am_tready_i;
    
    	assign	m_axis_data_tvalid	= am_tvalid_r;
    	assign	m_axis_data_tdata	= am_tdata_r;
    
    	always @(posedge clk)	//AM 调制算法实现
    	begin
    		if(rst_n == 0 )
    		begin
    			am_tdata_r	<= 0;
    			am_tvalid_r	<= 0;
    		end
    		else if(am_tready_i == 1)
    		begin
    			am_tdata_r	<= dds_100khz_tdata_i * (dds_4khz_tdata_i/2 + 128);	// 128 是直流分量,式中的除2是为了不使数据超过16位溢出
    																			// 这个代码中,载波频率很低,就直接用乘法去写代码了。
    																			// 如果载波频率比较高就需要用DSP单元或乘法 IP 去实现。
    			am_tvalid_r	<= dds_4khz_tvalid_i & dds_100khz_tvalid_i;
    		end
    	end
    
    	dds_compiler_1m_100k dds1						// XILINX VIVADO DDS IP1MHz 时钟输入,100KHz正弦波 8 位输出
    	(
    		.aclk				(clk),					// input wire aclk
    		.aresetn			(rst_n),				// input wire aresetn
    		.m_axis_data_tvalid	(dds_100khz_tvalid_i),	// output wire m_axis_data_tvalid
    		.m_axis_data_tready	(dds_100khz_tready_i),	// input wire m_axis_data_tready
    		.m_axis_data_tdata	(dds_100khz_tdata_i)	// output wire [7 : 0] m_axis_data_tdata
    	);
    
    	dds_compiler_1m_4k dds2							// XILINX VIVADO DDS IP1MHz 时钟输入,4khz正弦波 8 位输出
    	(
    		.aclk				(clk),					// input wire aclk
    		.aresetn			(rst_n),				// input wire aresetn
    		.m_axis_data_tvalid	(dds_4khz_tvalid_i),	// output wire m_axis_data_tvalid
    		.m_axis_data_tready	(dds_4khz_tready_i),	// input wire m_axis_data_tready
    		.m_axis_data_tdata	(dds_4khz_tdata_i)		// output wire [7 : 0] m_axis_data_tdata
    	);
    
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    3. AM 调幅波解调模块

    在这里插入图片描述

    4. am_demodulation_fir.v verilog 代码

    //am_demodulation_fir.v
    module	am_demodulation_fir
    (
    	input					rst_n,
    	input					clk,
    	input					s_axis_data_tvalid,
    	output					s_axis_data_tready,
    	input	signed[15:0]	s_axis_data_tdata,
    	output					m_axis_data_tvalid,
    	input					m_axis_data_tready,
    	output	signed[15:0]	m_axis_data_tdata
    );
    
    
    	reg 		[15:0]	abs_data_r	= 0;
    	reg					abs_valid_r	= 0;
    	wire				abs_tready_i;
    
    	always @(posedge clk)
    	begin
    		if(rst_n == 0 )
    			abs_valid_r	<= 0;
    		else if(abs_tready_i == 1)
    			abs_valid_r	<= s_axis_data_tvalid;
    	end
    
    	always @(posedge clk)	//取绝对值
    	begin
    		if(rst_n == 0 )
    			abs_data_r	<= 0;
    		else if(abs_tready_i == 1 && s_axis_data_tvalid == 1)
    		begin
    			if(s_axis_data_tdata >= 0)
    				abs_data_r	<= s_axis_data_tdata;
    			else
    				abs_data_r	<= -s_axis_data_tdata;
    		end
    	end
    	
    	wire signed	[39:0]	fir_fm_tdata_i;
    	wire				fir_fm_tvalid_i;
    	wire				fir_fm_tready_i;
    
    	assign	fir_fm_tready_i		= m_axis_data_tready;
    	assign	m_axis_data_tdata	= fir_fm_tdata_i >>>19;
    	assign	m_axis_data_tvalid	= fir_fm_tvalid_i;
    	assign	s_axis_data_tready	= abs_tready_i;
    
    	fir_compiler_lowpass_10k_30k_1m am_fir_u1
    	(
    		.aresetn			(rst_n),			// input wire aresetn
    		.aclk				(clk),				// input wire aclk
    		.s_axis_data_tvalid	(abs_valid_r),		// input wire s_axis_data_tvalid
    		.s_axis_data_tready	(abs_tready_i),		// output wire s_axis_data_tready
    		.s_axis_data_tdata	(abs_data_r),		// input wire [15 : 0] s_axis_data_tdata
    		.m_axis_data_tvalid	(fir_fm_tvalid_i),	// output wire m_axis_data_tvalid
    		.m_axis_data_tready	(fir_fm_tready_i),	// input wire m_axis_data_tready
    		.m_axis_data_tdata	(fir_fm_tdata_i)	// output wire [39 : 0] m_axis_data_tdata
    	);
    endmodule
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    5. am_modem_fir_testbench.v verilog 代码

    ///////////////////////////////////////////////////////////////////////
    
    `timescale 1ns / 100ps
    
    //am_modem_fir_testbench.v
    module am_modem_fir_testbench;
    
    reg			rst_n;
    reg			clk;
    
    
    parameter CLK_PERIOD		= 1000;		//1MHz
    
    initial	begin
    	rst_n = 0;
    	#(20 * CLK_PERIOD)
    	rst_n = 1;
    	#(3000 * CLK_PERIOD)
    	$stop;
    end
    
    initial
    	clk = 0;
    always
    begin
    	clk = #(CLK_PERIOD/2.0) ~clk;
    end
    
    	wire signed	[15:0]	am_mod_tdata;			//调幅波数据,载波100KHz 正弦波,调制信号 4KHz 正弦波
    	wire				am_mod_tvalid;
    	wire				am_mod_tready;
    
    	wire signed	[15:0]	am_demod_tdata;			//经过解调还原的 4KHz 正弦波
    	wire				am_demod_tvalid;
    	wire				am_demod_tready=1;
    
    	am_modulation_dds	am_u1					//调幅波调制模块,生成 载波100KHz 正弦波,调制信号 4KHz 正弦波的调幅信号
    	(
    		.clk				(clk),				//1MHz
    		.rst_n				(rst_n),			//复位
    		.m_axis_data_tdata	(am_mod_tdata),		//调幅波数据输出, output wire [16 : 0]
    		.m_axis_data_tvalid	(am_mod_tvalid),
    		.m_axis_data_tready	(am_mod_tready)
    	);
    
    	am_demodulation_fir		am_u2				//调幅波解调模块,将调幅波解调还原调制信号
    	(
    		.clk				(clk),				//1MHz
    		.rst_n				(rst_n),			//复位
    		.s_axis_data_tdata	(am_mod_tdata),		//调幅信号输入 intput wire [16 : 0]
    		.s_axis_data_tvalid	(am_mod_tvalid),
    		.s_axis_data_tready	(am_mod_tready),
    		.m_axis_data_tdata	(am_demod_tdata),	//调幅波解调数据输出, output wire [16 : 0]
    		.m_axis_data_tvalid	(am_demod_tvalid),
    		.m_axis_data_tready	(am_demod_tready)
    	);
    
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    实验二、FIR 基础应用 - FM 调频波调制解调(FIR 低通滤波)。

    1. FM 调频波调制模块

    在这里插入图片描述

    2. fm_modulation_dds.v verilog 代码

    //fm_modulation_dds.v
    module	fm_modulation_dds
    (
    	output			m_axis_data_tvalid,
    	input			m_axis_data_tready,
    	output	[15:0]	m_axis_data_tdata,
    	input			rst_n,
    	input			clk
    );
    
    	parameter			PHASE_COEF = 6554;//100KHz 
    
    
    	reg signed	[15:0]	phase_cnt_r;
    
    	wire signed	[15:0]	s_axis_phase_tdata_i;
    	reg					s_axis_phase_tvalid_r;
    	wire				s_axis_phase_tready_i;
    	wire signed	[15:0]	phase_step_i;
    
    	wire signed	[7:0]	dds_4khz_tdata_i;			//	4khz   正弦波	FM 调制信号
    	wire				dds_4khz_tvalid_i;
    	wire				dds_4khz_tready_i;
    
    	wire signed	[15:0]	fm_tdata_i;					//	FM 调频波
    	wire				fm_tvalid_i;
    	wire				fm_tready_i;
    
    	assign	phase_step_i 			= dds_4khz_tdata_i*16;
    	assign	dds_4khz_tready_i		= s_axis_phase_tready_i;
    	assign	s_axis_phase_tdata_i	= phase_cnt_r;
    	
    
    	always @(posedge clk)
    	begin
    		if(rst_n == 0 )
    			s_axis_phase_tvalid_r	<= 0;
    		else if(s_axis_phase_tready_i == 1)
    			s_axis_phase_tvalid_r	<= dds_4khz_tvalid_i;
    	end
    
    	always @(posedge clk)
    	begin
    		if(rst_n == 0 )
    		begin
    			phase_cnt_r	<= 0;
    		end
    		else if(s_axis_phase_tready_i == 1 && dds_4khz_tvalid_i == 1)
    		begin
    			phase_cnt_r	<= phase_cnt_r + phase_step_i + PHASE_COEF;
    		end
    	end	
    	
    	dds_compiler_1m_4k dds1							// XILINX VIVADO DDS IP100MHz 时钟输入,4khz正弦波 8 位输出
    	(
    		.aclk				(clk),					// input wire aclk
    		.aresetn			(rst_n),				// input wire aresetn
    		.m_axis_data_tvalid	(dds_4khz_tvalid_i),	// output wire m_axis_data_tvalid
    		.m_axis_data_tready	(dds_4khz_tready_i),	// input wire m_axis_data_tready
    		.m_axis_data_tdata	(dds_4khz_tdata_i)		// output wire [7 : 0] m_axis_data_tdata
    	);
    
    	
    	dds_compiler_phase dds2
    	(
    		.aclk				(clk),						// input wire aclk
    		.aresetn			(rst_n),					// input wire aresetn
    		.s_axis_phase_tvalid(s_axis_phase_tvalid_r),	// input wire s_axis_phase_tvalid
    		.s_axis_phase_tready(s_axis_phase_tready_i),	// output wire s_axis_phase_tready
    		.s_axis_phase_tdata	(s_axis_phase_tdata_i),		// input wire [15 : 0] s_axis_phase_tdata
    		.m_axis_data_tvalid	(fm_tvalid_i),				// output wire m_axis_data_tvalid
    		.m_axis_data_tready	(fm_tready_i),				// input wire m_axis_data_tready
    		.m_axis_data_tdata	(fm_tdata_i)				// output wire [15 : 0] m_axis_data_tdata
    	);
    	
    	assign	fm_tready_i			= m_axis_data_tready;
    	assign	m_axis_data_tvalid	= fm_tvalid_i;
    	assign	m_axis_data_tdata	= fm_tdata_i;
    
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    3. FM 调频波解调模块

    在这里插入图片描述

    4. fm_demodulation_fir.v verilog 代码

    //fm_demodulation_fir.v
    module	fm_demodulation_fir
    (
    	input					rst_n,
    	input					clk,
    	input					s_axis_data_tvalid,
    	output					s_axis_data_tready,
    	input	signed[15:0]	s_axis_data_tdata,
    	output					m_axis_data_tvalid,
    	input					m_axis_data_tready,
    	output	signed[15:0]	m_axis_data_tdata
    );
    
    	reg signed	[15:0]	uf_data_r	= 0;
    	reg signed	[15:0]	sv_data_r	= 0;
    	reg					uf_valid_r	= 0;
    	wire				uf_tready_i;
    	
    	reg 		[15:0]	abs_data_r	= 0;
    	reg					abs_valid_r	= 0;
    	wire				abs_tready_i;
    
    ////////////////////////////////////////////////////////////////////////////////////
    	always @(posedge clk)		
    	begin
    		if(rst_n == 0 )
    			uf_valid_r	<= 0;
    		else if(uf_tready_i == 1)
    			uf_valid_r	<= s_axis_data_tvalid;
    	end
    	
    	always @(posedge clk)	//微分 dx/dt ,dt =一个时钟周期,dx=当前数据减去上个时钟的数据的差
    	begin
    		if(rst_n == 0 )
    		begin
    			uf_data_r	<= 0;
    			sv_data_r	<= 0;
    		end
    		else if(uf_tready_i == 1 && s_axis_data_tvalid == 1)
    		begin
    			sv_data_r	<= s_axis_data_tdata;				//将当前数据存起来
    			uf_data_r	<= s_axis_data_tdata - sv_data_r;	//当前数据 - 上个时钟保存的数据
    		end
    	end
    ////////////////////////////////////////////////////////////////////////////////////
    	always @(posedge clk)
    	begin
    		if(rst_n == 0 )
    			abs_valid_r	<= 0;
    		else if(abs_tready_i == 1)
    			abs_valid_r	<= uf_valid_r;
    	end
    	
    	always @(posedge clk)	//绝对值
    	begin
    		if(rst_n == 0 )
    			abs_data_r	<= 0;
    		else if(abs_tready_i == 1 && uf_valid_r == 1)
    		begin
    			if(uf_data_r >= 0)
    				abs_data_r	<= uf_data_r;
    			else
    				abs_data_r	<= -uf_data_r;
    		end
    	end
    ////////////////////////////////////////////////////////////////////////////////////
    	
    	wire signed	[39:0]	fir_fm_tdata_i;
    	wire				fir_fm_tvalid_i;
    	wire				fir_fm_tready_i;
    
    	assign	fir_fm_tready_i		= m_axis_data_tready;
    	assign	m_axis_data_tdata	= fir_fm_tdata_i >>>19;
    	assign	m_axis_data_tvalid	= fir_fm_tvalid_i;
    	assign	s_axis_data_tready	= abs_tready_i;
    	assign	uf_tready_i			= abs_tready_i;
    
    fir_compiler_lowpass_10k_30k_1m fm_fir_u1
    (
    	.aresetn			(rst_n),			// input wire aresetn
    	.aclk				(clk),				// input wire aclk
    	.s_axis_data_tvalid	(abs_valid_r),		// input wire s_axis_data_tvalid
    	.s_axis_data_tready	(abs_tready_i),		// output wire s_axis_data_tready
    	.s_axis_data_tdata	(abs_data_r),		// input wire [15 : 0] s_axis_data_tdata
    	.m_axis_data_tvalid	(fir_fm_tvalid_i),	// output wire m_axis_data_tvalid
    	.m_axis_data_tready	(fir_fm_tready_i),	// input wire m_axis_data_tready
    	.m_axis_data_tdata	(fir_fm_tdata_i)	// output wire [31 : 0] m_axis_data_tdata
    );
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90

    5. fm_modem_fir_testbench.v verilog 代码

    
    ///////////////////////////////////////////////////////////////////////
    
    `timescale 1ns / 100ps
    //fm_modem_fir_testbench.v
    module fm_modem_fir_testbench;
    
    reg			rst_n;
    reg			clk;
    
    parameter CLK_PERIOD	= 1000;		//1MHz
    
    
    initial	begin
    	rst_n = 0;
    	#(10 * CLK_PERIOD)
    	rst_n = 1;
    	#(3000 * CLK_PERIOD)
    	$stop;
    end
    
    initial
    	clk = 0;
    always
    begin
    	clk = #(CLK_PERIOD/2.0) ~clk;
    end
    
    
    	wire signed	[15:0]	fm_mod_tdata;			//调频波数据,载波100KHz 正弦波,调制信号 4KHz 正弦波
    	wire				fm_mod_tvalid;
    	wire				fm_mod_tready;
    
    	wire signed	[15:0]	fm_demod_tdata;			//经过解调还原的 4KHz 正弦波
    	wire				fm_demod_tvalid;
    	wire				fm_demod_tready=1;
    
    	fm_modulation_dds	fm_u1					//调频波调制模块,生成 载波100KHz 正弦波,调制信号 4KHz 正弦波的调频信号
    	(
    		.clk				(clk),				//1MHz
    		.rst_n				(rst_n),			//复位
    		.m_axis_data_tdata	(fm_mod_tdata),		//调频波数据输出, output wire [16 : 0]
    		.m_axis_data_tvalid	(fm_mod_tvalid),
    		.m_axis_data_tready	(fm_mod_tready)
    	);
    
    	fm_demodulation_fir	fm_u2					//调频波解调模块,将调频波解调还原调制信号
    	(
    		.clk				(clk),				//1MHz
    		.rst_n				(rst_n),			//复位
    
    		.s_axis_data_tdata	(fm_mod_tdata),		//调频信号输入 intput wire [16 : 0]
    		.s_axis_data_tvalid	(fm_mod_tvalid),
    		.s_axis_data_tready	(fm_mod_tready),
    
    		.m_axis_data_tdata	(fm_demod_tdata),	//调频波解调数据输出, output wire [16 : 0]
    		.m_axis_data_tvalid	(fm_demod_tvalid),
    		.m_axis_data_tready	(fm_demod_tready)
    
    	);
    
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    实验三、FIR 中级应用 - AM 调幅波调制解调(FIR + FIFO)

    1. AM 调幅波调制模块,请参考实验一

    2. AM 调幅波解调模块(FIR 中级应用)

    在这里插入图片描述

    3. am_fifo_demodulation_fir.v verilog 代码

    //am_fifo_demodulation_fir.v
    module	am_fifo_demodulation_fir
    (
    	input					rst_n,
    	input					clk,
    	input					clk_100mhz,
    	input					s_axis_data_tvalid,
    	output					s_axis_data_tready,
    	input	signed[15:0]	s_axis_data_tdata,
    	output					m_axis_data_tvalid,
    	input					m_axis_data_tready,
    	output	signed[15:0]	m_axis_data_tdata
    );
    
    
    	reg 		[15:0]	abs_data_r	= 0;
    	reg					abs_valid_r	= 0;
    	wire				abs_tready_i;
    
    	
    	always @(posedge clk)
    	begin
    		if(rst_n == 0 )
    			abs_valid_r	<= 0;
    		else if(abs_tready_i == 1)
    			abs_valid_r	<= s_axis_data_tvalid;
    	end
    
    	always @(posedge clk)
    	begin
    		if(rst_n == 0 )
    			abs_data_r	<= 0;
    		else if(abs_tready_i == 1 && s_axis_data_tvalid == 1)
    		begin
    			if(s_axis_data_tdata >= 0)
    				abs_data_r	<= s_axis_data_tdata;
    			else
    				abs_data_r	<= -s_axis_data_tdata;
    		end
    	end
    	
    
    	assign	s_axis_data_tready	= abs_tready_i;
    
    
    	wire signed	[15:0]	fifo_as_tdata_i;
    	wire				fifo_as_tvalid_i;
    	wire				fifo_as_tready_i;
    	wire				fifo_as_clk_i;
    
    	wire signed	[15:0]	fifo_am_tdata_i;
    	wire				fifo_am_tvalid_i;
    	wire				fifo_am_tready_i;
    	wire				fifo_am_clk_i;
    
    	wire signed	[15:0]	fifo_bs_tdata_i;
    	wire				fifo_bs_tvalid_i;
    	wire				fifo_bs_tready_i;
    	wire				fifo_bs_clk_i;
    
    	wire signed	[15:0]	fifo_bm_tdata_i;
    	wire				fifo_bm_tvalid_i;
    	wire				fifo_bm_tready_i;
    	wire				fifo_bm_clk_i;
    
    
    	assign	fifo_as_clk_i		= clk;
    	assign	fifo_am_clk_i		= clk_100mhz;
    	assign	fifo_bs_clk_i		= clk_100mhz;
    	assign	fifo_bm_clk_i		= clk;
    
    	assign	fifo_as_tdata_i		= abs_data_r;
    	assign	fifo_as_tvalid_i	= abs_valid_r;
    	assign	abs_tready_i		= fifo_as_tready_i;
    	
    	axi_fifo_a16 fifo_ua
    	(
    		.wr_rst_busy	(),						// output wire wr_rst_busy
    		.rd_rst_busy	(),						// output wire rd_rst_busy
    		.m_aclk			(fifo_am_clk_i),		// input wire m_aclk
    		.s_aclk			(fifo_as_clk_i),		// input wire s_aclk
    		.s_aresetn		(rst_n),				// input wire s_aresetn
    		.s_axis_tvalid	(fifo_as_tvalid_i),		// input wire s_axis_tvalid
    		.s_axis_tready	(fifo_as_tready_i),		// output wire s_axis_tready
    		.s_axis_tdata	(fifo_as_tdata_i),		// input wire [15 : 0] s_axis_tdata
    		.m_axis_tvalid	(fifo_am_tvalid_i),		// output wire m_axis_tvalid
    		.m_axis_tready	(fifo_am_tready_i),		// input wire m_axis_tready
    		.m_axis_tdata	(fifo_am_tdata_i)		// output wire [15 : 0] m_axis_tdata
    	);
    
    	wire				fir_a_clk_i;
    	
    	wire signed	[15:0]	fir_as_tdata_i;
    	wire				fir_as_tvalid_i;
    	wire				fir_as_tready_i;
    	wire signed	[39:0]	fir_am_tdata_i;
    	wire				fir_am_tvalid_i;
    	wire				fir_am_tready_i;
    
    
    	assign	fir_a_clk_i			= fifo_am_clk_i;
    	
    	assign	fir_as_tvalid_i		= fifo_am_tvalid_i;
    	assign	fir_as_tdata_i		= fifo_am_tdata_i;
    	assign	fifo_am_tready_i	= fir_as_tready_i;
    
    	fir_compiler_lowpass_10k_30k_100m	 am_fir_u1
    	(
    		.aresetn			(rst_n),			// input wire aresetn
    		.aclk				(fir_a_clk_i),		// input wire aclk
    		.s_axis_data_tvalid	(fir_as_tvalid_i),	// input wire s_axis_data_tvalid
    		.s_axis_data_tready	(fir_as_tready_i),	// output wire s_axis_data_tready
    		.s_axis_data_tdata	(fir_as_tdata_i),	// input wire [15 : 0] s_axis_data_tdata
    		.m_axis_data_tvalid	(fir_am_tvalid_i),	// output wire m_axis_data_tvalid
    		.m_axis_data_tready	(fir_am_tready_i),	// input wire m_axis_data_tready
    		.m_axis_data_tdata	(fir_am_tdata_i)	// output wire [39 : 0] m_axis_data_tdata
    	);
    
    
    	assign	fifo_bs_tvalid_i	= fir_am_tvalid_i;
    	assign	fifo_bs_tdata_i		= fir_am_tdata_i >>>19;
    	assign	fir_am_tready_i		= fifo_bs_tready_i;
    
    	axi_fifo_a16 fifo_ub
    	(
    		.wr_rst_busy	(),						// output wire wr_rst_busy
    		.rd_rst_busy	(),						// output wire rd_rst_busy
    		.m_aclk			(fifo_bm_clk_i),		// input wire m_aclk
    		.s_aclk			(fifo_bs_clk_i),		// input wire s_aclk
    		.s_aresetn		(rst_n),				// input wire s_aresetn
    		.s_axis_tvalid	(fifo_bs_tvalid_i),		// input wire s_axis_tvalid
    		.s_axis_tready	(fifo_bs_tready_i),		// output wire s_axis_tready
    		.s_axis_tdata	(fifo_bs_tdata_i),		// input wire [15 : 0] s_axis_tdata
    		.m_axis_tvalid	(fifo_bm_tvalid_i),		// output wire m_axis_tvalid
    		.m_axis_tready	(fifo_bm_tready_i),		// input wire m_axis_tready
    		.m_axis_tdata	(fifo_bm_tdata_i)		// output wire [15 : 0] m_axis_tdata
    	);
    	
    	assign	fifo_bm_tready_i	= m_axis_data_tready;
    	assign	m_axis_data_tdata	= fifo_bm_tdata_i;
    	assign	m_axis_data_tvalid	= fifo_bm_tvalid_i;
    	
    endmodule
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145

    4. am_fifo_fir_testbench.v verilog 代码

    ///////////////////////////////////////////////////////////////////////
    
    `timescale 1ns / 100ps
    //am_fifo_fir_testbench.v
    module am_fifo_fir_testbench;
    
    reg			rst_n;
    reg			clk;
    reg			clk_100mhz;
    
    parameter CLK_PERIOD		= 1000;		//1MHz
    parameter CLK_PERIOD_100MHz	= 10;		//100MHz
    
    initial	begin
    	rst_n = 0;
    	#(20 * CLK_PERIOD)
    	rst_n = 1;
    	#(1000 * CLK_PERIOD)
    	$stop;
    end
    
    initial
    	clk = 0;
    always
    begin
    	clk = #(CLK_PERIOD/2.0) ~clk;
    end
    
    initial
    	clk_100mhz = 0;
    always
    begin
    	clk_100mhz = #(CLK_PERIOD_100MHz/2.0) ~clk_100mhz;
    end
    
    	wire signed	[15:0]	am_mod_tdata;			//调幅波数据,载波100KHz 正弦波,调制信号 4KHz 正弦波
    	wire				am_mod_tvalid;
    	wire				am_mod_tready;
    
    	wire signed	[15:0]	am_demod_tdata;			//经过解调还原的 4KHz 正弦波
    	wire				am_demod_tvalid;
    	wire				am_demod_tready=1;
    
    	am_modulation_dds	am_u1					//调幅波调制模块,生成 载波100KHz 正弦波,调制信号 4KHz 正弦波的调幅信号
    	(
    		.clk				(clk),				//1MHz
    		.rst_n				(rst_n),			//复位
    		.m_axis_data_tdata	(am_mod_tdata),		//调幅波数据输出, output wire [16 : 0]
    		.m_axis_data_tvalid	(am_mod_tvalid),
    		.m_axis_data_tready	(am_mod_tready)
    	);
    
    	am_fifo_demodulation_fir	am_u2				//调幅波解调模块,将调幅波解调还原调制信号
    	(
    		.clk				(clk),				//1MHz
    		.clk_100mhz			(clk_100mhz),		//100MHz
    		.rst_n				(rst_n),			//复位
    
    		.s_axis_data_tdata	(am_mod_tdata),		//调幅信号输入 intput wire [16 : 0]
    		.s_axis_data_tvalid	(am_mod_tvalid),
    		.s_axis_data_tready	(am_mod_tready),
    
    		.m_axis_data_tdata	(am_demod_tdata),	//调幅波解调数据输出, output wire [16 : 0]
    		.m_axis_data_tvalid	(am_demod_tvalid),
    		.m_axis_data_tready	(am_demod_tready)
    
    	);
    
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    实验四、FIR 高级应用 - AM 调幅波调制解调(FIR 低通滤波+重采样,FIR 高阶系数,FIR+FIFO )

    1. AM 调幅波调制模块,请参考实验一

    2. AM 调幅波解调模块(FIR 高级应用)

    在这里插入图片描述

    3. am_fifo_dc_demodulation_fir.v verilog 代码

    //am_fifo_dc_demodulation_fir.v
    module	am_fifo_dc_demodulation_fir
    (
    	input					rst_n,
    	input					clk,
    	input					clk_100mhz,
    	input					s_axis_data_tvalid,
    	output					s_axis_data_tready,
    	input	signed[15:0]	s_axis_data_tdata,
    	output					m_axis_data_tvalid,
    	input					m_axis_data_tready,
    	output	signed[15:0]	m_axis_data_tdata
    );
    
    
    	wire				clk_62_5khz;
    	reg			[3:0]	clk_cnt		= 0;
    	reg 		[15:0]	abs_data_r	= 0;
    	reg					abs_valid_r	= 0;
    	wire				abs_tready_i;
    
    	assign	clk_62_5khz = clk_cnt[3];
    	
    	always @(posedge clk)
    	begin
    		clk_cnt	<= clk_cnt + 1;
    	end
    	
    	always @(posedge clk)
    	begin
    		if(rst_n == 0 )
    			abs_valid_r	<= 0;
    		else if(abs_tready_i == 1)
    			abs_valid_r	<= s_axis_data_tvalid;
    	end
    
    	always @(posedge clk)
    	begin
    		if(rst_n == 0 )
    			abs_data_r	<= 0;
    		else if(abs_tready_i == 1 && s_axis_data_tvalid == 1)
    		begin
    			if(s_axis_data_tdata >= 0)
    				abs_data_r	<= s_axis_data_tdata;
    			else
    				abs_data_r	<= -s_axis_data_tdata;
    		end
    	end
    	
    
    	assign	s_axis_data_tready	= abs_tready_i;
    
    
    	wire signed	[15:0]	fifo_as_tdata_i;
    	wire				fifo_as_tvalid_i;
    	wire				fifo_as_tready_i;
    	wire				fifo_as_clk_i;
    
    	wire signed	[15:0]	fifo_am_tdata_i;
    	wire				fifo_am_tvalid_i;
    	wire				fifo_am_tready_i;
    	wire				fifo_am_clk_i;
    
    	wire signed	[15:0]	fifo_bs_tdata_i;
    	wire				fifo_bs_tvalid_i;
    	wire				fifo_bs_tready_i;
    	wire				fifo_bs_clk_i;
    
    	wire signed	[15:0]	fifo_bm_tdata_i;
    	wire				fifo_bm_tvalid_i;
    	wire				fifo_bm_tready_i;
    	wire				fifo_bm_clk_i;
    
    
    	assign	fifo_as_clk_i		= clk;
    	assign	fifo_am_clk_i		= clk_100mhz;
    	assign	fifo_bs_clk_i		= clk_100mhz;
    	assign	fifo_bm_clk_i		= clk_62_5khz;
    
    	assign	fifo_as_tdata_i		= abs_data_r;
    	assign	fifo_as_tvalid_i	= abs_valid_r;
    	assign	abs_tready_i		= fifo_as_tready_i;
    	
    	axi_fifo_a16 fifo_ua
    	(
    		.wr_rst_busy	(),						// output wire wr_rst_busy
    		.rd_rst_busy	(),						// output wire rd_rst_busy
    		.m_aclk			(fifo_am_clk_i),		// input wire m_aclk
    		.s_aclk			(fifo_as_clk_i),		// input wire s_aclk
    		.s_aresetn		(rst_n),				// input wire s_aresetn
    		.s_axis_tvalid	(fifo_as_tvalid_i),		// input wire s_axis_tvalid
    		.s_axis_tready	(fifo_as_tready_i),		// output wire s_axis_tready
    		.s_axis_tdata	(fifo_as_tdata_i),		// input wire [15 : 0] s_axis_tdata
    		.m_axis_tvalid	(fifo_am_tvalid_i),		// output wire m_axis_tvalid
    		.m_axis_tready	(fifo_am_tready_i),		// input wire m_axis_tready
    		.m_axis_tdata	(fifo_am_tdata_i)		// output wire [15 : 0] m_axis_tdata
    	);
    
    	wire				fir_a_clk_i;
    	wire				fir_b_clk_i;
    	
    	wire signed	[15:0]	fir_as_tdata_i;
    	wire				fir_as_tvalid_i;
    	wire				fir_as_tready_i;
    	wire signed	[39:0]	fir_am_tdata_i;
    	wire				fir_am_tvalid_i;
    	wire				fir_am_tready_i;
    
    	wire signed	[15:0]	fir_bs_tdata_i;
    	wire				fir_bs_tvalid_i;
    	wire				fir_bs_tready_i;
    	wire signed	[39:0]	fir_bm_tdata_i;
    	wire				fir_bm_tvalid_i;
    	wire				fir_bm_tready_i;
    
    
    	assign	fir_a_clk_i			= fifo_am_clk_i;
    	assign	fir_b_clk_i			= fifo_am_clk_i;
    	
    	assign	fir_as_tvalid_i		= fifo_am_tvalid_i;
    	assign	fir_as_tdata_i		= fifo_am_tdata_i;	// >>>17;
    	assign	fifo_am_tready_i	= fir_as_tready_i;
    
    	fir_compiler_lowpass_10k_30k_1m_dec	 am_fir_u1
    	(
    		.aresetn			(rst_n),			// input wire aresetn
    		.aclk				(fir_a_clk_i),		// input wire aclk
    		.s_axis_data_tvalid	(fir_as_tvalid_i),	// input wire s_axis_data_tvalid
    		.s_axis_data_tready	(fir_as_tready_i),	// output wire s_axis_data_tready
    		.s_axis_data_tdata	(fir_as_tdata_i),	// input wire [15 : 0] s_axis_data_tdata
    		.m_axis_data_tvalid	(fir_am_tvalid_i),	// output wire m_axis_data_tvalid
    		.m_axis_data_tready	(fir_am_tready_i),	// input wire m_axis_data_tready
    		.m_axis_data_tdata	(fir_am_tdata_i)	// output wire [39 : 0] m_axis_data_tdata
    	);
    
    	assign	fir_bs_tvalid_i		= fir_am_tvalid_i;
    	assign	fir_bs_tdata_i		= fir_am_tdata_i >>>19;
    	assign	fir_am_tready_i		= fir_bs_tready_i;
    
    	fir_compiler_highpass_30_50_62k am_fir_u2
    	(
    		.aresetn			(rst_n),			// input wire aresetn
    		.aclk				(fir_b_clk_i),		// input wire aclk
    		.s_axis_data_tvalid	(fir_bs_tvalid_i),	// input wire s_axis_data_tvalid
    		.s_axis_data_tready	(fir_bs_tready_i),	// output wire s_axis_data_tready
    		.s_axis_data_tdata	(fir_bs_tdata_i),	// input wire [15 : 0] s_axis_data_tdata
    		.m_axis_data_tvalid	(fir_bm_tvalid_i),	// output wire m_axis_data_tvalid
    		.m_axis_data_tready	(fir_bm_tready_i),	// input wire m_axis_data_tready
    		.m_axis_data_tdata	(fir_bm_tdata_i)	// output wire [39 : 0] m_axis_data_tdata
    	);
    
    //	assign	fir_bm_tvalid_i		= fir_bs_tvalid_i;
    //	assign	fir_bm_tdata_i		= fir_bs_tdata_i << 18;
    //	assign	fir_bs_tready_i		= fir_bm_tready_i;
    
    
    	assign	fifo_bs_tvalid_i	= fir_bm_tvalid_i;
    	assign	fifo_bs_tdata_i		= fir_bm_tdata_i >>>16;
    	assign	fir_bm_tready_i		= fifo_bs_tready_i;
    
    	axi_fifo_a16 fifo_ub
    	(
    		.wr_rst_busy	(),						// output wire wr_rst_busy
    		.rd_rst_busy	(),						// output wire rd_rst_busy
    		.m_aclk			(fifo_bm_clk_i),		// input wire m_aclk
    		.s_aclk			(fifo_bs_clk_i),		// input wire s_aclk
    		.s_aresetn		(rst_n),				// input wire s_aresetn
    		.s_axis_tvalid	(fifo_bs_tvalid_i),		// input wire s_axis_tvalid
    		.s_axis_tready	(fifo_bs_tready_i),		// output wire s_axis_tready
    		.s_axis_tdata	(fifo_bs_tdata_i),		// input wire [15 : 0] s_axis_tdata
    		.m_axis_tvalid	(fifo_bm_tvalid_i),		// output wire m_axis_tvalid
    		.m_axis_tready	(fifo_bm_tready_i),		// input wire m_axis_tready
    		.m_axis_tdata	(fifo_bm_tdata_i)		// output wire [15 : 0] m_axis_tdata
    	);
    	
    	assign	fifo_bm_tready_i	= m_axis_data_tready;
    	assign	m_axis_data_tdata	= fifo_bm_tdata_i;
    	assign	m_axis_data_tvalid	= fifo_bm_tvalid_i;
    	
    endmodule
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182

    4. am_fifo_dc_fir_testbench.v verilog 代码

    ///////////////////////////////////////////////////////////////////////
    
    `timescale 1ns / 100ps
    //am_fifo_dc_fir_testbench.v
    module am_fifo_dc_fir_testbench;
    
    reg			rst_n;
    reg			clk;
    reg			clk_100mhz;
    
    parameter CLK_PERIOD		= 1000;		//1MHz
    parameter CLK_PERIOD_100MHz	= 10;		//100MHz
    
    initial	begin
    	rst_n = 0;
    	#(20 * CLK_PERIOD)
    	rst_n = 1;
    	#(80000 * CLK_PERIOD)
    	$stop;
    end
    
    initial
    	clk = 0;
    always
    begin
    	clk = #(CLK_PERIOD/2.0) ~clk;
    end
    
    initial
    	clk_100mhz = 0;
    always
    begin
    	clk_100mhz = #(CLK_PERIOD_100MHz/2.0) ~clk_100mhz;
    end
    
    	wire signed	[15:0]	am_mod_tdata;			//调幅波数据,载波100KHz 正弦波,调制信号 4KHz 正弦波
    	wire				am_mod_tvalid;
    	wire				am_mod_tready;
    
    	wire signed	[15:0]	am_demod_tdata;			//经过解调还原的 4KHz 正弦波
    	wire				am_demod_tvalid;
    	wire				am_demod_tready=1;
    
    	am_modulation_dds	am_u1					//调幅波调制模块,生成 载波100KHz 正弦波,调制信号 4KHz 正弦波的调幅信号
    	(
    		.clk				(clk),				//1MHz
    		.rst_n				(rst_n),			//复位
    		.m_axis_data_tdata	(am_mod_tdata),		//调幅波数据输出, output wire [16 : 0]
    		.m_axis_data_tvalid	(am_mod_tvalid),
    		.m_axis_data_tready	(am_mod_tready)
    	);
    
    	am_fifo_dc_demodulation_fir	am_u2				//调幅波解调模块,将调幅波解调还原调制信号
    	(
    		.clk				(clk),				//1MHz
    		.clk_100mhz			(clk_100mhz),		//100MHz
    		.rst_n				(rst_n),			//复位
    
    		.s_axis_data_tdata	(am_mod_tdata),		//调幅信号输入 intput wire [16 : 0]
    		.s_axis_data_tvalid	(am_mod_tvalid),
    		.s_axis_data_tready	(am_mod_tready),
    
    		.m_axis_data_tdata	(am_demod_tdata),	//调幅波解调数据输出, output wire [16 : 0]
    		.m_axis_data_tvalid	(am_demod_tvalid),
    		.m_axis_data_tready	(am_demod_tready)
    
    	);
    
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    实验五、FIR 高级应用 - 多通道实验 (四个通道用一个 FIR IP,每通道用不同的系数)。

    1. FIR 多通道模块(FIR 高级应用)

    在这里插入图片描述

    2. multichannel_fir.v verilog 代码

    //multichannel_fir.v
    module	multichannel_fir
    (
    	input					rst_n,
    	input					clk,
    	input					clk_100mhz,
    	input					s_axis_data_tvalid,
    	output					s_axis_data_tready,
    	input	signed[63:0]	s_axis_data_tdata,
    	output					m_axis_data_tvalid,
    	input					m_axis_data_tready,
    	output	signed[63:0]	m_axis_data_tdata
    );
    
    	wire 		[63:0]		fifo_as_tdata_i;
    	wire					fifo_as_tvalid_i;
    	wire					fifo_as_full_i;
    	wire					fifo_as_clk_i;
    
    	wire signed	[15:0]		fifo_am_tdata_i;
    	wire					fifo_am_tvalid_i;
    	wire					fifo_am_rden_i;
    	wire					fifo_am_empty_i;
    	wire					fifo_am_clk_i;
    
    	wire signed	[15:0]		fifo_bs_tdata_i;
    	wire					fifo_bs_tvalid_i;
    	wire					fifo_bs_full_i;
    	wire					fifo_bs_clk_i;
    
    	wire signed	[63:0]		fifo_bm_tdata_i;
    	wire					fifo_bm_tvalid_i;
    	wire					fifo_bm_rden_i;
    	wire					fifo_bm_empty_i;
    	wire					fifo_bm_clk_i;
    
    	assign	fifo_as_clk_i		= clk;
    	assign	fifo_am_clk_i		= clk_100mhz;
    	assign	fifo_bs_clk_i		= clk_100mhz;
    	assign	fifo_bm_clk_i		= clk;
    
    	assign	fifo_as_tdata_i		= s_axis_data_tdata;
    	assign	fifo_as_tvalid_i	= s_axis_data_tvalid;
    	assign	s_axis_data_tready	= ~fifo_as_full_i;
    	assign	fifo_am_tvalid_i	= fifo_am_rden_i & ~fifo_am_empty_i;
    
    	fifo_w64_r16 fifo_ua
    	(
    		.rst			(~rst_n),				// input wire rst
    		.wr_clk			(fifo_as_clk_i),		// input wire wr_clk
    		.rd_clk			(fifo_am_clk_i),		// input wire rd_clk
    		.din			(fifo_as_tdata_i),		// input wire [63 : 0] din
    		.wr_en			(fifo_as_tvalid_i),		// input wire wr_en
    		.rd_en			(fifo_am_rden_i),		// input wire rd_en
    		.dout			(fifo_am_tdata_i),		// output wire [15 : 0] dout
    		.full			(fifo_as_full_i),		// output wire full
    		.empty			(fifo_am_empty_i)		// output wire empty
    	);
    
    	wire				fir_a_clk_i;
    	
    	wire signed	[15:0]	fir_as_tdata_i;
    	wire				fir_as_tvalid_i;
    	wire				fir_as_tready_i;
    	wire signed	[39:0]	fir_am_tdata_i;
    	wire				fir_am_tvalid_i;
    	wire				fir_am_tready_i;
    	wire [1:0]			fir_am_tuser_i;
    
    	wire [7:0]			fir_as_config_tdata_i;
    	wire				fir_as_config_tvalid_i;
    	wire				fir_as_config_tready_i;
    	wire				fir_as_config_tlast_i;
    	wire				event_s_config_tlast_missing_i;
    	wire				event_s_config_tlast_unexpected_i;
    	reg	[7:0]			s_cfg_cnt			= 0;
    	reg	[7:0]			s_config_tdata_r	= 0;
    
    	assign	fir_a_clk_i			= fifo_am_clk_i;
    	assign	fir_as_tvalid_i		= fifo_am_tvalid_i;
    	assign	fir_as_tdata_i		= fifo_am_tdata_i;
    	assign	fifo_am_rden_i		= fir_as_tready_i;
    
    	reg		[31:0]	time_cnt = 0;
    	reg		[7:0]	channel_id_r	 = 0;
    	wire	[31:0]	load_cfg;
    	
    	always @(posedge fir_a_clk_i)
    	begin
    		time_cnt	<= time_cnt + 1;
    	end
    	
    	assign	load_cfg = ( time_cnt[14:0] == 15'h4000 && time_cnt > 'h8000 && time_cnt < 'h30000 ) ? 1:0;
    
    	always @(posedge fir_a_clk_i)
    	begin
    		if(rst_n == 0)
    		begin
    			channel_id_r 	<= 0;
    		end
    		else if(fir_as_config_tlast_i == 1 && fir_as_config_tvalid_i == 1 && fir_as_config_tready_i == 1 && channel_id_r < 4)
    		begin
    			channel_id_r 	<= channel_id_r +1;
    		end
    	end
    
    	always @(posedge fir_a_clk_i)
    	begin
    		if(load_cfg == 1)
    		begin
    			s_cfg_cnt 	<= 4;
    			if(channel_id_r <4)
    				s_config_tdata_r	<= 3 - channel_id_r;	//3/2/1/0 顺序
    			else
    				s_config_tdata_r	<= 0;
    		end
    		else if(fir_as_config_tready_i == 1 && fir_as_config_tvalid_i == 1 && s_cfg_cnt != 0)
    		begin
    			s_cfg_cnt 	<= s_cfg_cnt -1;
    			if(channel_id_r ==4)
    			begin
    				s_config_tdata_r	<= s_config_tdata_r + 1;
    			end
    		end
    	end
    	
    	assign	fir_as_config_tvalid_i	= s_cfg_cnt == 0 ? 0:1;
    	assign	fir_as_config_tdata_i	= s_config_tdata_r;
    	assign	fir_as_config_tlast_i	= s_cfg_cnt == 1 ? 1:0;
    
    	fir_compiler_mc4_512 multichannel_fir_u1
    	(
    		.aresetn				(rst_n),				// input wire aresetn
    		.aclk					(fir_a_clk_i),			// input wire aclk
    		.s_axis_data_tvalid		(fir_as_tvalid_i),		// input wire s_axis_data_tvalid
    		.s_axis_data_tready		(fir_as_tready_i),		// output wire s_axis_data_tready
    		.s_axis_data_tdata		(fir_as_tdata_i),		// input wire [15 : 0] s_axis_data_tdata
    		.s_axis_config_tvalid	(fir_as_config_tvalid_i),	// input wire s_axis_config_tvalid
    		.s_axis_config_tready	(fir_as_config_tready_i),	// output wire s_axis_config_tready
    		.s_axis_config_tlast	(fir_as_config_tlast_i),	// input wire s_axis_config_tlast
    		.s_axis_config_tdata	(fir_as_config_tdata_i),	// input wire [7 : 0] s_axis_config_tdata
    		.m_axis_data_tvalid		(fir_am_tvalid_i),		// output wire m_axis_data_tvalid
    		.m_axis_data_tready		(fir_am_tready_i),		// input wire m_axis_data_tready
    		.m_axis_data_tuser		(fir_am_tuser_i),		// output wire [1 : 0] m_axis_data_tuser
    		.m_axis_data_tdata		(fir_am_tdata_i),		// output wire [39 : 0] m_axis_data_tdata
    		.event_s_config_tlast_missing	(event_s_config_tlast_missing_i),		// output wire event_s_config_tlast_missing
    		.event_s_config_tlast_unexpected(event_s_config_tlast_unexpected_i)	// output wire event_s_config_tlast_unexpected
    	);
    	assign	fifo_bs_tvalid_i	= fir_am_tvalid_i;
    	assign	fifo_bs_tdata_i		= fir_am_tdata_i >>>24;
    	assign	fir_am_tready_i		= ~fifo_bs_full_i;
    
    	
    	fifo_w16_r64 fifo_ub
    	(
    		.rst			(~rst_n),				// input wire rst
    		.wr_clk			(fifo_bs_clk_i),		// input wire wr_clk
    		.rd_clk			(fifo_bm_clk_i),		// input wire rd_clk
    		.din			(fifo_bs_tdata_i),		// input wire [16 : 0] din
    		.wr_en			(fifo_bs_tvalid_i),		// input wire wr_en
    		.rd_en			(fifo_bm_rden_i),		// input wire rd_en
    		.dout			(fifo_bm_tdata_i),		// output wire [63 : 0] dout
    
    		.full			(fifo_bs_full_i),		// output wire full
    		.empty			(fifo_bm_empty_i)		// output wire empty
    	);
    
    	assign	fifo_bm_rden_i		= m_axis_data_tready;
    	assign	fifo_bm_tvalid_i	= fifo_bm_rden_i & ~fifo_bm_empty_i;
    
    	assign	m_axis_data_tdata	= fifo_bm_tdata_i;
    	assign	m_axis_data_tvalid	= fifo_bm_tvalid_i;
    
    endmodule
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176

    3. multichannel_fir_testbench.v verilog 代码

    
    ///////////////////////////////////////////////////////////////////////
    
    `timescale 1ns / 100ps
    //multichannel_fir_testbench.v
    module multichannel_fir_testbench;
    
    reg			rst_n;
    reg			ts;
    reg			clk;
    reg			clk_100mhz;
    reg			clk_10khz;
    reg			clk_30khz;
    reg			clk_50khz;
    reg			clk_70khz;
    
    parameter CLK_PERIOD		= 476.1904762;		//2.1MHz
    parameter CLK_PERIOD_100MHz	= 10;				//100MHz
    
    parameter CLK_10K			= CLK_PERIOD * 210;
    parameter CLK_30K			= CLK_PERIOD * 70;
    parameter CLK_50K			= CLK_PERIOD * 42;
    parameter CLK_70K			= CLK_PERIOD * 30;
    
    initial	begin
    	rst_n	= 0;
    	ts		= 0;
    	#(20 * CLK_PERIOD)
    	rst_n	= 1;
    	#(4500 * CLK_PERIOD)
    	ts		= 1;
    	#(1000 * CLK_PERIOD)
    	$stop;
    end
    
    initial
    begin
    	clk			= 0;
    	clk_100mhz	= 0;
    	clk_10khz	= 0;
    	clk_30khz	= 0;
    	clk_50khz	= 0;
    	clk_70khz	= 0;
    end
    
    always	clk			= #(CLK_PERIOD/2.0) ~clk;
    always	clk_100mhz	= #(CLK_PERIOD_100MHz/2.0) ~clk_100mhz;
    always	clk_10khz	= #(CLK_10K/2.0) ~clk_10khz;
    always	clk_30khz	= #(CLK_30K/2.0) ~clk_30khz;
    always	clk_50khz	= #(CLK_50K/2.0) ~clk_50khz;
    always	clk_70khz	= #(CLK_70K/2.0) ~clk_70khz;
    
    
    	wire 	signed[15:0]	s_tdata[3:0];
    	wire					s_tvalid;
    	wire					s_tready;
    
    	wire 	signed[15:0]	m_tdata[3:0];
    	wire					m_tvalid;
    	wire					m_tready = 1;
    	
    		
    	assign	s_tdata[0]  = clk_10khz == 0 ? -10000:10000;
    	assign	s_tdata[1]  = ts == 0 ? {clk_30khz == 0 ? -10000:10000}:s_tdata[0];
    	assign	s_tdata[2]  = ts == 0 ? {clk_50khz == 0 ? -10000:10000}:s_tdata[0];
    	assign	s_tdata[3]  = ts == 0 ? {clk_70khz == 0 ? -10000:10000}:s_tdata[0];
    	
    	assign	s_tvalid = s_tready;
    
    	multichannel_fir		u1
    	(
    		.clk				(clk),				//1MHz
    		.clk_100mhz			(clk_100mhz),
    		.rst_n				(rst_n),
    
    		.s_axis_data_tdata	({s_tdata[0],s_tdata[1],s_tdata[2],s_tdata[3]}),
    		.s_axis_data_tvalid	(s_tvalid),
    		.s_axis_data_tready	(s_tready),
    
    		.m_axis_data_tdata	({m_tdata[0],m_tdata[1],m_tdata[2],m_tdata[3]}),
    		.m_axis_data_tvalid	(m_tvalid),
    		.m_axis_data_tready	(m_tready)
    
    	);
    
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87

    4. fir_compiler_mc4_512 FIR IP 设置需要关注的地方

    在这里插入图片描述

    5. FIR 多通道实验时序图

    在这里插入图片描述

    6. FIR 多通道实验时序图CONFIG 时序细节放大

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    实验六、FIR 高级应用 FIR Reload的使用。

    • Reload 模块很简单只有一个 FIR IP 这里就不介绍框图了。把代码、时序时序贴出来看看。

    1. reload_fir.v verilog 代码

    //reload_fir.v
    module	reload_fir
    (
    	input					rst_n,
    	input					clk,
    	input					s_axis_data_tvalid,
    	output					s_axis_data_tready,
    	input	signed[15:0]	s_axis_data_tdata,
    	output					m_axis_data_tvalid,
    	input					m_axis_data_tready,
    	output	signed[15:0]	m_axis_data_tdata
    );
    
    	wire				fir_tlast_missing;
    	wire				fir_tlast_unexpected;
    	wire	[39:0]		m_axis_data_tdata_i;
    
    	wire[15:0]		fir_reload_dat[3:0][127:0];
    	reg	[15:0]		fir_dat0[127:0];
    	reg	[15:0]		fir_dat1[127:0];
    	reg	[15:0]		fir_dat2[127:0];
    	reg	[15:0]		fir_dat3[127:0];
    
    
    	wire [07:0]	fir_s_cfg_tdata;
    	wire		fir_s_cfg_tvalid;
    	wire		fir_s_cfg_tready;
    
    	reg [15:0]	fir_s_reload_tdata;
    	reg			fir_s_reload_tvalid;
    	wire		fir_s_reload_tready;
    	reg			fir_s_reload_tlast;
        
        genvar  m;
    
        for(m=0;m<128;m=m+1)
        begin:for_mx
            assign	fir_reload_dat[0][m]	= fir_dat0[m];
            assign	fir_reload_dat[1][m]	= fir_dat1[m];
            assign	fir_reload_dat[2][m]	= fir_dat2[m];
            assign	fir_reload_dat[3][m]	= fir_dat3[m];
        end
    
    	initial
    	begin
    		$readmemh("../../../../../reload_bandpass_10k_30k_30k_50k_1m.txt",	fir_dat0);
    		$readmemh("../../../../../reload_bandpass_30k_50k_50k_70k_1m.txt",	fir_dat1);
    		$readmemh("../../../../../reload_bandpass_50k_70k_70k_90k_1m.txt",	fir_dat2);
    		$readmemh("../../../../../reload_bandpass_70k_90k_90k_110k_1m.txt",	fir_dat3);
    	end
    		
    	parameter	NUMBER_COE_SIZE = 128;	//64;
    	parameter	NUMBER_COE_SETS = 2;	//
    	
    	reg	[15:0]	reload_cnt=16'hffff;
    	reg	[15:0]	cfg_cnt=0;
    	wire		reload_en;
    	reg	[1:0]	reload_sn=0;
    	reg[15:0]	fir_cntx=0;
    	reg[15:0]	psel=0;
    	reg[15:0]	w_psel=1;
    
    	assign	fir_s_cfg_tdata		= psel;
    	assign	fir_s_cfg_tvalid	= cfg_cnt == 0    ? 1:0;
    	assign	reload_en			= fir_cntx[9:0] == 0 && fir_cntx != 0  ? 1:0;
    	
    	always @(posedge clk)
    	begin
    		if(rst_n == 0 )
    		begin
    			fir_s_reload_tdata	<= 0;
    			fir_s_reload_tvalid	<= 0;
    			fir_s_reload_tlast	<= 0;
    		end
    		else if(fir_s_reload_tready == 1)
    		begin
    			if(NUMBER_COE_SETS == 1)
    			begin
    			
    				if(reload_cnt == NUMBER_COE_SIZE-1)
    					fir_s_reload_tlast	<= 1;
    				else
    					fir_s_reload_tlast	<= 0;
    			
    				if(reload_cnt < NUMBER_COE_SIZE)
    				begin
    					fir_s_reload_tdata	<= fir_reload_dat[reload_sn][reload_cnt];
    					fir_s_reload_tvalid	<= 1;
    				end	
    				else
    				begin
    					fir_s_reload_tdata	<= 0;
    					fir_s_reload_tvalid	<= 0;
    				end	
    			end
    			else
    			begin
    				if(reload_cnt == NUMBER_COE_SIZE)
    					fir_s_reload_tlast	<= 1;
    				else
    					fir_s_reload_tlast	<= 0;
    
    				if(reload_cnt<NUMBER_COE_SIZE+1)
    				begin
    					fir_s_reload_tvalid	<= 1;
    					if(reload_cnt == 0)
    						fir_s_reload_tdata	<= w_psel;
    					else
    						fir_s_reload_tdata	<= fir_reload_dat[reload_sn][reload_cnt-1];
    				end	
    				else
    				begin
    					fir_s_reload_tdata	<= 0;
    					fir_s_reload_tvalid	<= 0;
    				end
    			end
    		end
    	end
    
    	always @(posedge clk)
    	begin
    		if(rst_n == 0 )
    		begin
    			fir_cntx	<= 0;
    		end
    		else if(fir_s_reload_tready == 1 && fir_s_cfg_tready == 1)
    		begin
    			fir_cntx	<= fir_cntx + 1;
    		end
    	end
    
    	always @(posedge clk)
    	begin
    		if(rst_n == 0 )
    		begin
    			reload_sn	<= 0;
    			psel		<= 0;
    		end
    		else if(fir_s_reload_tlast == 1 && fir_s_reload_tready == 1)
    		begin
    			reload_sn	<= reload_sn + 1;
    			psel		<= 1;
    		end
    	end
    
    
    	always @(posedge clk)
    	begin
    		if(rst_n == 0 )
    		begin
    			reload_cnt		<= 16'hffff;
    		end
    		else if(reload_en == 1)
    		begin
    			reload_cnt		<= 0;
    		end
    		else if(fir_s_reload_tready == 1)
    		begin
    			if(reload_cnt != 16'hffff)
    				reload_cnt	<= reload_cnt + 1;
    		end
    	end
    
    	always @(posedge clk)
    	begin
    		if(rst_n == 0 ||(fir_s_reload_tlast == 1 && fir_s_reload_tready == 1))
    		begin
    			cfg_cnt		<= 0;
    		end
    		else if(fir_s_cfg_tready == 1)
    		begin
    			if(fir_s_cfg_tvalid == 1 || cfg_cnt != 16'hffff)
    				cfg_cnt	<= cfg_cnt + 1;
    		end
    	end
    
    	assign	m_axis_data_tdata = m_axis_data_tdata_i >> 18;
    
    	reload_fir_256x2 am_fir_u1
    	(
    		.aresetn				(rst_n),					// input wire aresetn
    		.aclk					(clk),						// input wire aclk
    		.s_axis_config_tvalid	(fir_s_cfg_tvalid),			// input wire s_axis_config_tvalid
    		.s_axis_config_tready	(fir_s_cfg_tready),			// output wire s_axis_config_tready
    		.s_axis_config_tdata	(fir_s_cfg_tdata),			// input wire [7 : 0] s_axis_config_tdata
    		.s_axis_reload_tvalid	(fir_s_reload_tvalid),		// input wire s_axis_reload_tvalid
    		.s_axis_reload_tready	(fir_s_reload_tready),		// output wire s_axis_reload_tready
    		.s_axis_reload_tlast	(fir_s_reload_tlast),		// input wire s_axis_reload_tlast
    		.s_axis_reload_tdata	(fir_s_reload_tdata),		// input wire [15 : 0] s_axis_reload_tdata
    		.s_axis_data_tvalid		(s_axis_data_tvalid),		// input wire s_axis_data_tvalid
    		.s_axis_data_tready		(s_axis_data_tready),		// output wire s_axis_data_tready
    		.s_axis_data_tdata		(s_axis_data_tdata),		// input wire [15 : 0] s_axis_data_tdata
    		.m_axis_data_tvalid		(m_axis_data_tvalid),		// output wire m_axis_data_tvalid
    		.m_axis_data_tready		(m_axis_data_tready),		// input wire m_axis_data_tready
    		.m_axis_data_tdata		(m_axis_data_tdata_i),		// output wire [39 : 0] m_axis_data_tdata
    		.event_s_reload_tlast_missing	(fir_tlast_missing),	// output wire event_s_reload_tlast_missing
    		.event_s_reload_tlast_unexpected(fir_tlast_unexpected)	// output wire event_s_reload_tlast_unexpected
    	);
    
    endmodule
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202

    2. reload_fir_testbench.v verilog 代码

    
    ///////////////////////////////////////////////////////////////////////
    
    `timescale 1ns / 100ps
    //reload_fir_testbench.v
    module reload_fir_testbench;
    
    reg			rst_n;
    reg			clk;
    reg			clk_10khz;
    
    parameter CLK_PERIOD		= 1000;		//1MHz 采样频率
    
    parameter CLK_10K			= CLK_PERIOD * 100;
    
    initial	begin
    	rst_n	= 0;
    	#(20 * CLK_PERIOD)
    	rst_n	= 1;
    	#(6000 * CLK_PERIOD)
    	$stop;
    end
    
    initial
    begin
    	clk			= 0;
    	clk_10khz	= 0;
    end
    
    always	clk			= #(CLK_PERIOD/2.0) ~clk;
    always	clk_10khz	= #(CLK_10K/2.0) ~clk_10khz;
    
    
    	wire 	signed[15:0]	s_tdata;
    	wire					s_tvalid;
    	wire					s_tready;
    
    	wire 	signed[15:0]	m_tdata;
    	wire					m_tvalid;
    	wire					m_tready;
    	
    
    	assign	s_tdata  = clk_10khz == 0 ? -10000:10000;
    	assign	s_tvalid = s_tready;
    	assign	m_tready = 1;
    
    	reload_fir am_fir_u1
    	(
    		.rst_n					(rst_n),					// input wire aresetn
    		.clk					(clk),						// input wire aclk
    		.s_axis_data_tvalid		(s_tvalid),					// input wire s_axis_data_tvalid
    		.s_axis_data_tready		(s_tready),					// output wire s_axis_data_tready
    		.s_axis_data_tdata		(s_tdata),					// input wire [15 : 0] s_axis_data_tdata
    		.m_axis_data_tvalid		(m_tvalid),					// output wire m_axis_data_tvalid
    		.m_axis_data_tready		(m_tready),					// input wire m_axis_data_tready
    		.m_axis_data_tdata		(m_tdata)					// output wire [15 : 0] m_axis_data_tdata
    	);
    
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    3. FIR 高级应用 FIR Reload时序图

    在这里插入图片描述

    4. FIR 高级应用 FIR Reload细节时序图放大1

    在这里插入图片描述

    5. FIR 高级应用 FIR Reload细节时序图放大2

    在这里插入图片描述

    6. reload_fir FIR 高级应用 FIR IP 设置需要关注的地方1

    在这里插入图片描述

    7. reload_fir FIR 高级应用 FIR IP 设置需要关注的地方2

    在这里插入图片描述

    实验一、三综合布线后 FPGA 资源对比

    实验一、三的AM解调部分单独综合布线后的FPGA资源占用报告

    在这里插入图片描述

    • 实验一和实验三的区别
    • 实验一FIR IP 的工作时钟为 1MHz,AM 数据的采样频率为 1MHz 。
    • 实验三FIR IP 的工作时钟为 100MHz,AM 数据的采样频率为 1MHz 。在 FIR 前后加了两个 FIFO。
    • 从资源占用图可以看出 这两个 FIFO 只占用了 1 个 BRAM块(一个FIFO占用0.5个)。
    • 从资源占用图可以看出 实验三的资源占用远少于实验一,特别是 DSP 这种珍贵资源的的占用只有 1个。实验三只多了 1 个BRAM块。这样的交换是非常划算的。
    • 实验三仿真运行相比实验一非常慢

    三、 实验相关 vivado 工程、IP 设置等详细文档连接,采用 Xilinx vivado 2017.4 版本

  • 相关阅读:
    二、Gitee使用方法
    ffmpeg源码笔记-AvFrame和AvPacket(四)
    Redis常见面试题总结
    列表按绝对值逆序排序,并保存下标 python
    Haddop集群的简单搭建
    Kubernetes 系统化学习之 基本概念篇
    Kotlin File readText readLines readBytes
    数据挖掘-支持向量机(SVM)+代码实现
    PHP基于Thinkphp的莆田学院图书馆管理系统毕业设计-附源码071418
    【备忘录】JavaScript代码段儿
  • 原文地址:https://blog.csdn.net/qq_46621272/article/details/125292610