当前位置: 首页 > news >正文

做网站用源码微信营销

做网站用源码,微信营销,如何制作自己的网站页制作,做淘宝客网站要注意什么该项目介绍了如何使用 Verilog 实现具有预生成系数的简单 FIR 滤波器。 绪论 不起眼的 FIR 滤波器是 FPGA 数字信号处理中最基本的模块之一,因此了解如何将具有给定抽头数及其相应系数值的基本模块组合在一起非常重要。因此,在这个关于 FPGA 上 DSP 基础…

c6417f58cbac91a3d14176b8df9b8854.png

该项目介绍了如何使用 Verilog 实现具有预生成系数的简单 FIR 滤波器。

76a999d1e68cea49aaa3fe48972bd0ca.png

绪论

不起眼的 FIR 滤波器是 FPGA 数字信号处理中最基本的模块之一,因此了解如何将具有给定抽头数及其相应系数值的基本模块组合在一起非常重要。因此,在这个关于 FPGA 上 DSP 基础实用入门的教程中,将从一个简单的 15 抽头低通滤波器 FIR 开始,在 Matlab 中为其生成初始系数值,然后转换这些值用于编写 Verilog 模块。

有限脉冲响应或 FIR 滤波器定义为脉冲响应在特定时间段内稳定为零值的滤波器。脉冲响应稳定到零所花费的时间与滤波器阶数(抽头数)直接相关,滤波器阶数是 FIR 的基础传递函数多项式的阶数。FIR 的传递函数不包含反馈,因此如果输入一个值为 1 的脉冲,然后输入一串零值,输出将只是滤波器的系数值。

滤波器的作用基本都是用于信号调节,主要集中在选择滤除或允许通过哪些频率。最简单的例子之一是低通滤波器,它允许低于某个阈值(截止频率)的频率通过,同时大大衰减高于该阈值的频率,如下图所示。

7a2d3a5f49ef1d1acd6f622c33ef348b.png

该项目的主要重点是在 HDL(具体为 Verilog)中实现 FIR,它可以分解为三个主要逻辑组件:一个循环缓冲器,用于将每个样本计时到适当地考虑了串行输入的延迟、每个抽头系数值的乘法器以及每个抽头输出的求和结果的累加器。

39ab59d221fa437ca54ed1cc456eac1f.png

由于本项目专注于 FPGA 逻辑中 FIR 的设计机制,所以只是使用 Simulink 中的 FDA 工具和 Matlab 为低通滤波器插入一些简单参数,然后使用生成的系数值放到 Verilog 模块中完成滤波器的设计(在后面的步骤中完成)。

dbb451b344f2df421639d707fc7020d1.png

选择实现一个简单的 15 抽头低通滤波器 FIR,采样率为 1Ms/s,通带频率为 200kHz,阻带频率为 355kHz,得到以下系数:

-0.0265 
0 
0.0441 
0 
-0.0934 
0 
0.3139 
0.5000 
0.3139 
0 
-0.0934 
0 
0.0441 
0 
-0.0265

为 FIR 模块创建设计文件

在 Vivado 项目中添加源文件。

dce2efd47b557898c3efda49058735a4.png

在确定 FIR 的顺序(抽头数)并获得系数值后,接下来需要定义的下一组参数就是输入样本、输出样本和系数本身的位宽。

对于这个 FIR,选择将输入样本和系数寄存器设置为 16 位宽,并将输出样本寄存器设置为 32 位,因为两个 16 位值的乘积是一个 32 位值(两个值的宽度相乘得到乘积的宽度,所以如果选择了 8 位抽头的 16 位输入样本,那么输出样本将为 24 位宽)。

这些值也都是带符号的,因此 MSB 用作符号位,在选择输入样本寄存器的初始宽度时一定要记住这一点。要在 Verilog 中将这些值设置为有符号数据类型,使用关键字signed :

reg signed [15:0] register_name;

接下来要解决的是如何在 Verilog 中处理系数值,小数点值需要转换为定点值。由于所有系数值都小于 1,因此寄存器的所有 15 位(总共 16 位,MSB 是有符号位)都可以用于小数位。通常,必须决定要将寄存器中的多少位用于数字的整数部分与数字的小数部分。因此,转换分数值抽头的数学是:(fractional coefficient value)*(2^(15))该乘积的小数值被四舍五入,并且如果系数为负,则计算该值的二进制补码:

tap0 = twos(-0.0265 * 32768) = 0xFC9C
tap1 = 0
tap2 = 0.0441 * 32768 = 1445.0688 = 1445 = 0x05A5
tap3 = 0
tap4 = twos(-0.0934 * 32768) = 0xF40C
tap5 = 0
tap6 = 0.3139 * 32768 = 10285.8752 = 10285 = 0x282D
tap7 = 0.5000 * 32768 = 16384 = 0x4000
tap8 = 0.3139 * 32768 = 10285.8752 = 10285 = 0x282D
tap9 =  0
tap10 = twos(-0.0934 * 32768) = 0xF40C
tap11 = 0
tap12 = 0.0441 * 32768 = 1445.0688 = 1445 = 0x05A5
tap13 = 0
tap14 = twos(-0.0265 * 32768) = 0xFC9C

现在我们终于准备好关注 FIR 模块的逻辑,第一个是循环缓冲区,它引入串行输入样本流并为滤波器的 15 个抽头创建一个包含 15 个输入样本的数组。

always @ (posedge clk)beginif(enable_buff == 1'b1)beginbuff0 <= in_sample;buff1 <= buff0;        buff2 <= buff1;         buff3 <= buff2;      buff4 <= buff3;      buff5 <= buff4;       buff6 <= buff5;    buff7 <= buff6;       buff8 <= buff7;       buff9 <= buff8;       buff10 <= buff9;        buff11 <= buff10;       buff12 <= buff11;       buff13 <= buff12;       buff14 <= buff13;    endend

接下来,乘法阶段将每个样本乘以每个系数值:

/* Multiply stage of FIR */always @ (posedge clk)beginif (enable_fir == 1'b1)beginacc0 <= tap0 * buff0;acc1 <= tap1 * buff1;acc2 <= tap2 * buff2;acc3 <= tap3 * buff3;acc4 <= tap4 * buff4;acc5 <= tap5 * buff5;acc6 <= tap6 * buff6;acc7 <= tap7 * buff7;acc8 <= tap8 * buff8;acc9 <= tap9 * buff9;acc10 <= tap10 * buff10;acc11 <= tap11 * buff11;acc12 <= tap12 * buff12;acc13 <= tap13 * buff13;acc14 <= tap14 * buff14;endend

乘法阶段的结果值通过加法累加到寄存器中,最终成为滤波器的输出数据流。

/* Accumulate stage of FIR */   always @ (posedge clk) beginif (enable_fir == 1'b1)beginm_axis_fir_tdata <= acc0 + acc1 + acc2 + acc3 + acc4 + acc5 + acc6 + acc7 + acc8 + acc9 + acc10 + acc11 + acc12 + acc13 + acc14;endend

最后,逻辑的最后一部分是将数据流进和流出 FIR 模块的接口。AXI Stream 接口是最常见的接口之一。关键方面是允许控制上游和下游设备之间的数据流的tready和tvalid信号。这意味着 FIR 模块需要向其下游设备提供tvalid信号以指示其输出是有效数据,并且如果下游设备解除其tready信号,则能够暂停(但仍保留)其输出。FIR 模块还必须能够与其主端接口上的上游设备以同样的方式运行。

5074f17104d4886628ee02db551971d1.png

以下是 FIR 模块的逻辑设计概述:

322828b1ab5d72fcda50c82f9084be6e.png

请注意tready和tvalid信号如何设置输入循环缓冲器的使能值和 FIR 的乘法级以及数据或系数通过的每个寄存器都被声明为有符号的。

FIR模块Verilog代码:

`timescale 1ns / 1psmodule FIR(input clk,input reset,input signed [15:0] s_axis_fir_tdata, input [3:0] s_axis_fir_tkeep,input s_axis_fir_tlast,input s_axis_fir_tvalid,input m_axis_fir_tready,output reg m_axis_fir_tvalid,output reg s_axis_fir_tready,output reg m_axis_fir_tlast,output reg [3:0] m_axis_fir_tkeep,output reg signed [31:0] m_axis_fir_tdata);always @ (posedge clk)beginm_axis_fir_tkeep <= 4'hf;endalways @ (posedge clk)beginif (s_axis_fir_tlast == 1'b1)beginm_axis_fir_tlast <= 1'b1;endelsebeginm_axis_fir_tlast <= 1'b0;endend// 15-tap FIR reg enable_fir, enable_buff;reg [3:0] buff_cnt;reg signed [15:0] in_sample; reg signed [15:0] buff0, buff1, buff2, buff3, buff4, buff5, buff6, buff7, buff8, buff9, buff10, buff11, buff12, buff13, buff14; wire signed [15:0] tap0, tap1, tap2, tap3, tap4, tap5, tap6, tap7, tap8, tap9, tap10, tap11, tap12, tap13, tap14; reg signed [31:0] acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7, acc8, acc9, acc10, acc11, acc12, acc13, acc14; /* Taps for LPF running @ 1MSps with a cutoff freq of 400kHz*/assign tap0 = 16'hFC9C;  // twos(-0.0265 * 32768) = 0xFC9Cassign tap1 = 16'h0000;  // 0assign tap2 = 16'h05A5;  // 0.0441 * 32768 = 1445.0688 = 1445 = 0x05A5assign tap3 = 16'h0000;  // 0assign tap4 = 16'hF40C;  // twos(-0.0934 * 32768) = 0xF40Cassign tap5 = 16'h0000;  // 0assign tap6 = 16'h282D;  // 0.3139 * 32768 = 10285.8752 = 10285 = 0x282Dassign tap7 = 16'h4000;  // 0.5000 * 32768 = 16384 = 0x4000assign tap8 = 16'h282D;  // 0.3139 * 32768 = 10285.8752 = 10285 = 0x282Dassign tap9 = 16'h0000;  // 0assign tap10 = 16'hF40C; // twos(-0.0934 * 32768) = 0xF40Cassign tap11 = 16'h0000; // 0assign tap12 = 16'h05A5; // 0.0441 * 32768 = 1445.0688 = 1445 = 0x05A5assign tap13 = 16'h0000; // 0assign tap14 = 16'hFC9C; // twos(-0.0265 * 32768) = 0xFC9C/* This loop sets the tvalid flag on the output of the FIR high once * the circular buffer has been filled with input samples for the * first time after a reset condition. */always @ (posedge clk or negedge reset)beginif (reset == 1'b0) //if (reset == 1'b0 || tvalid_in == 1'b0)beginbuff_cnt <= 4'd0;enable_fir <= 1'b0;in_sample <= 8'd0;endelse if (m_axis_fir_tready == 1'b0 || s_axis_fir_tvalid == 1'b0)beginenable_fir <= 1'b0;buff_cnt <= 4'd15;in_sample <= in_sample;endelse if (buff_cnt == 4'd15)beginbuff_cnt <= 4'd0;enable_fir <= 1'b1;in_sample <= s_axis_fir_tdata;endelsebeginbuff_cnt <= buff_cnt + 1;in_sample <= s_axis_fir_tdata;endend   always @ (posedge clk)beginif(reset == 1'b0 || m_axis_fir_tready == 1'b0 || s_axis_fir_tvalid == 1'b0)begins_axis_fir_tready <= 1'b0;m_axis_fir_tvalid <= 1'b0;enable_buff <= 1'b0;endelsebegins_axis_fir_tready <= 1'b1;m_axis_fir_tvalid <= 1'b1;enable_buff <= 1'b1;endend/* Circular buffer bring in a serial input sample stream that * creates an array of 15 input samples for the 15 taps of the filter. */always @ (posedge clk)beginif(enable_buff == 1'b1)beginbuff0 <= in_sample;buff1 <= buff0;        buff2 <= buff1;         buff3 <= buff2;      buff4 <= buff3;      buff5 <= buff4;       buff6 <= buff5;    buff7 <= buff6;       buff8 <= buff7;       buff9 <= buff8;       buff10 <= buff9;        buff11 <= buff10;       buff12 <= buff11;       buff13 <= buff12;       buff14 <= buff13;    endelsebeginbuff0 <= buff0;buff1 <= buff1;        buff2 <= buff2;         buff3 <= buff3;      buff4 <= buff4;      buff5 <= buff5;       buff6 <= buff6;    buff7 <= buff7;       buff8 <= buff8;       buff9 <= buff9;       buff10 <= buff10;        buff11 <= buff11;       buff12 <= buff12;       buff13 <= buff13;       buff14 <= buff14;endend/* Multiply stage of FIR */always @ (posedge clk)beginif (enable_fir == 1'b1)beginacc0 <= tap0 * buff0;acc1 <= tap1 * buff1;acc2 <= tap2 * buff2;acc3 <= tap3 * buff3;acc4 <= tap4 * buff4;acc5 <= tap5 * buff5;acc6 <= tap6 * buff6;acc7 <= tap7 * buff7;acc8 <= tap8 * buff8;acc9 <= tap9 * buff9;acc10 <= tap10 * buff10;acc11 <= tap11 * buff11;acc12 <= tap12 * buff12;acc13 <= tap13 * buff13;acc14 <= tap14 * buff14;endend    /* Accumulate stage of FIR */   always @ (posedge clk) beginif (enable_fir == 1'b1)beginm_axis_fir_tdata <= acc0 + acc1 + acc2 + acc3 + acc4 + acc5 + acc6 + acc7 + acc8 + acc9 + acc10 + acc11 + acc12 + acc13 + acc14;endend     endmodule

创建仿真文件

要测试 FIR 模块,需要创建一个测试平台作为其仿真源:

c1cd20f7f71d7f77fedf8f2676096df2.png

在 FIR 模块中有两个主要的东西需要测试:滤波器算法和 AXI 流接口。为实现这一点,测试台中创建了一个状态机,它生成一个简单的 200kHz 正弦波,并切换从属端的有效信号和 FIR 接口主控端的tready信号。

FIR 模块的测试平台:

`timescale 1ns / 1psmodule tb_FIR;reg clk, reset, s_axis_fir_tvalid, m_axis_fir_tready;reg signed [15:0] s_axis_fir_tdata;wire m_axis_fir_tvalid;wire [3:0] m_axis_fir_tkeep;wire [31:0] m_axis_fir_tdata;/** 100Mhz (10ns) clock */always beginclk = 1; #5;clk = 0; #5;endalways beginreset = 1; #20;reset = 0; #50;reset = 1; #1000000;endalways begins_axis_fir_tvalid = 0; #100;s_axis_fir_tvalid = 1; #1000;s_axis_fir_tvalid = 0; #50;s_axis_fir_tvalid = 1; #998920;endalways beginm_axis_fir_tready = 1; #1500;m_axis_fir_tready = 0; #100;m_axis_fir_tready = 1; #998400;end/* Instantiate FIR module to test. */FIR FIR_i(.clk(clk),.reset(reset),.s_axis_fir_tdata(s_axis_fir_tdata),   .s_axis_fir_tkeep(s_axis_fir_tkeep),   .s_axis_fir_tlast(s_axis_fir_tlast),   .s_axis_fir_tvalid(s_axis_fir_tvalid), .m_axis_fir_tready(m_axis_fir_tready),.m_axis_fir_tvalid(m_axis_fir_tvalid), .s_axis_fir_tready(s_axis_fir_tready), .m_axis_fir_tlast(m_axis_fir_tlast),   .m_axis_fir_tkeep(m_axis_fir_tkeep),   .m_axis_fir_tdata(m_axis_fir_tdata));  reg [4:0] state_reg;reg [3:0] cntr;parameter wvfm_period = 4'd4;parameter init               = 5'd0;parameter sendSample0        = 5'd1;parameter sendSample1        = 5'd2;parameter sendSample2        = 5'd3;parameter sendSample3        = 5'd4;parameter sendSample4        = 5'd5;parameter sendSample5        = 5'd6;parameter sendSample6        = 5'd7;parameter sendSample7        = 5'd8;/* This state machine generates a 200kHz sinusoid. */always @ (posedge clk or posedge reset)beginif (reset == 1'b0)begincntr <= 4'd0;s_axis_fir_tdata <= 16'd0;state_reg <= init;endelsebegincase (state_reg)init : //0begincntr <= 4'd0;s_axis_fir_tdata <= 16'h0000;state_reg <= sendSample0;endsendSample0 : //1begins_axis_fir_tdata <= 16'h0000;if (cntr == wvfm_period)begincntr <= 4'd0;state_reg <= sendSample1;endelsebegin cntr <= cntr + 1;state_reg <= sendSample0;endend sendSample1 : //2begins_axis_fir_tdata <= 16'h5A7E; if (cntr == wvfm_period)begincntr <= 4'd0;state_reg <= sendSample2;endelsebegin cntr <= cntr + 1;state_reg <= sendSample1;endend sendSample2 : //3begins_axis_fir_tdata <= 16'h7FFF;if (cntr == wvfm_period)begincntr <= 4'd0;state_reg <= sendSample3;endelsebegin cntr <= cntr + 1;state_reg <= sendSample2;endend sendSample3 : //4begins_axis_fir_tdata <= 16'h5A7E;if (cntr == wvfm_period)begincntr <= 4'd0;state_reg <= sendSample4;endelsebegin cntr <= cntr + 1;state_reg <= sendSample3;endend sendSample4 : //5begins_axis_fir_tdata <= 16'h0000;if (cntr == wvfm_period)begincntr <= 4'd0;state_reg <= sendSample5;endelsebegin cntr <= cntr + 1;state_reg <= sendSample4;endend sendSample5 : //6begins_axis_fir_tdata <= 16'hA582; if (cntr == wvfm_period)begincntr <= 4'd0;state_reg <= sendSample6;endelsebegin cntr <= cntr + 1;state_reg <= sendSample5;endend sendSample6 : //6begins_axis_fir_tdata <= 16'h8000; if (cntr == wvfm_period)begincntr <= 4'd0;state_reg <= sendSample7;endelsebegin cntr <= cntr + 1;state_reg <= sendSample6;endend sendSample7 : //6begins_axis_fir_tdata <= 16'hA582; if (cntr == wvfm_period)begincntr <= 4'd0;state_reg <= sendSample0;endelsebegin cntr <= cntr + 1;state_reg <= sendSample7;endend                     endcaseendendendmodule

运行行为仿真

FIR 模块及其测试平台文件就位后,从 Flow Navigator 窗口启动 Vivado 中的仿真器,选择 Run Behavioral Simulation 选项。

59568d4dc6b26b5f2332b1f68b771f25.png

如行为仿真所示,FIR 正确过滤信号并正确响应 AXI 流信号。

d0ac89678dd49fc8284a31e328f49425.png

总结

代码都在上面大家有兴趣可以自行运行,但是大家可能会注意到,这个 FIR 模块在设计上运行综合和实现时时序应该是不能通过的。我们将在下一篇文章中详细介绍如何在无法满足时序要求时重新设计你的设计~

297bfa037f7e67437a996ec3b8991360.png
http://www.khdw.cn/news/16730.html

相关文章:

  • 律师网站建设哪家专业有人百度看片吗
  • 做网站去哪找客户cctv 13新闻频道
  • 网站建设用图片重庆百度搜索优化
  • 仿土豆网站源码表白网站制作
  • 做电子书网站 赚钱营销管理系统
  • 常德网站优化咨询电话推广论坛有哪些
  • 企业网站改造优化百度网讯科技有限公司官网
  • seo搜索引擎优化业务seo经验
  • 网络营销推广与策划实训总结赣州seo唐三
  • 如何做网站在网上销售韩国网站
  • wordpress运行环境要求网站搜索优化
  • 棋牌游戏网站模板电商网课
  • 做网站可以用什么软件app推广注册从哪里接单
  • 网站上做地图手机上显示不出来的百度关键词优化软件网站
  • 播放量网站推广免费网站推广seo优化
  • 玉林市住房和城乡建设局网站网络搜索关键词排名
  • 公司网站建设好处seo推广软件哪个好
  • php网站怎么做集群常见的微信营销方式有哪些
  • 购物分享网站怎么做的聚名网官网
  • 淘宝wordpress模板友链对网站seo有帮助吗
  • 做企业网站怎么样天津seo招聘
  • 网站登录破解百度代做seo排名
  • 网站开发的开发意义广州seo公司哪个比较好
  • 建设职业注册中心网站专业seo网络推广
  • 一家专门做建材的网站百度推广客服投诉电话
  • 网站建设开发定制常见的网络推广方法有哪些
  • 做海外网站推广百度大数据
  • 网站开发开源的手册站长之家ip地址归属查询
  • 做网站详细步骤做灰色词seo靠谱
  • 做豆腐交流经验的网站百度搜索引擎怎么做