精华内容
下载资源
问答
  • 此示例模型展示了如何使用 Simulink 原始模块创建模型。 FPGA 上使用 CORDIC 算法实现三角计算。此示例模型演示了如何使用 Simulink 基本模块创建模型。
  • 当今的设计工程师受到面积、功率和成本的约束,不能采用GHz级...该设计使用了一个平台FPGA实现的一个嵌入式PowerPC。 协处理器的意义  协处理器是一个处理单元,该处理单元与一个主处理单元一起使用来承担通常
  • OFDM系统中,为了获得正确无误的数据传输,需要采用差错控制编码技术。卷积编码和Viterbi译码就是一种有效的前向纠错方法,它具有一定的克服突发错误的能力。LTE中采用Viterbi和Turbo加速器实现前向纠错。  1 ...
  • 如何采用FPGA协处理器实现算法加速

    千次阅读 2007-11-19 20:22:00
    嵌入式系统中,通常是由相对数量较少的算法决定最大的运算需求。使用设计自动化工具可以将这些算法快速转换到硬件协处理器中。然后,协处理器可以有效地连接到处理器,产生“GHz”级的性能。 本文主要研究了代码...

    当今的设计工程师受到面积、功率和成本的约束,不能采用GHz级的计算机实现嵌入式设计。在嵌入式系统中,通常是由相对数量较少的算法决定最大的运算需求。使用设计自动化工具可以将这些算法快速转换到硬件协处理器中。然后,协处理器可以有效地连接到处理器,产生“GHz”级的性能。

    本文主要研究了代码加速和代码转换到硬件协处理器的方法。我们还分析了通过一个涉及到基于辅助处理器单元(APU)的实际图像显示案例的基准数据均衡决策的过程。该设计使用了在一个平台FPGA中实现的一个嵌入式PowerPC。

    协处理器的意义

    协处理器是一个处理单元,该处理单元与一个主处理单元一起使用来承担通常由主处理单元执行的运算。通常,协处理器功能在硬件中实现以替代几种软件指令。通过减少多种代码指令为单一指令,以及在硬件中直接实现指令的方式,从而实现代码加速。

    最常用的协处理器是浮点单元(FPU),这是与CPU紧密结合的唯一普通协处理器。没有通用的协处理器库,即使是存在这样的库,将依然难以简单地将协处理器与一个CPU(例如Pentium 4)连接。Xilinx Virtex-4 FX FPGA拥有一个或两个PowerPC,每个都有一个APU接口。通过在FPGA中嵌入一个处理器,现在就有机会在单芯片上实现完整的处理系统。

    带APU接口的PowerPC使得在FPGA中得以实现一个紧密结合的协处理器。因为频率的需求以及管脚数量的限制,采用外部协处理器不大可行。因此可以创建一个直接连接到PowerPC的专用应用协处理器,大大地提高了软件速度。因为FPGA是可编程的,你可以快速地开发和测试连接到CPU的协处理器解决方案。

    协处理器连接模型

    协处理器有三种基本的形式:与CPU总线连接的、与I/O连接的和指令流水线连接(Instruction Pipeline Connection)。此外,还存在一些这些形式的混合形式。

    1. CPU总线连接

    处理器总线连接加速器需要CPU在总线上移动数据以及发送命令。通常,单个数据处理就需要很多的处理器时钟周期。因为总线仲裁以及总线驱动的时钟是处理器时钟的分频,所以会降低数据处理速度。一个与总线连接的加速器可以包含一个存储器存取(DMA)引擎。在增加额外的逻辑情况下,DMA引擎允许协处理器工作在位于连接到总线的存储器上的数据块,独立于CPU。

    2. I/O连接

    与I/O连接的加速器直接连接到一个专用的I/O端口。通常通过GET或PUT函数提供数据和控制。因为缺少了仲裁、控制复杂度降低以及连接器件较少,因此这些接口的驱动时钟通常比处理器总线更快。这种接口的一个较好的例子如Xilinx Fast Simplex Link(FSL)。FSL是一种简单的FIFO接口,可以连接到Xilinx MicroBlaze软核处理器或Virtex-4 FX PowerPC。与处理器总线接口中的数据移动相比,通过FSL移动的数据具有较低的延时和更高的数据速率。

    3. 指令流水线连接

    指令流水线连接加速器直接连接到CPU的计算内核。通过与指令流水线连接,CPU不能识别的指令可以由协处理器执行。操作数、结果以及状态直接从数据执行流水线向外传递,或接收。单个运算可以实现两个操作数的处理,同时返回一个结果和状态。

    作为一个直接连接的接口,连接道指令流水线的加速器可以用比处理器总线更快的时钟驱动。Xilinx通过APU接口实现这种协处理器连接模型,对于典型的双操作数指令,在数据控制和数据传输上可以缩减10倍的时钟周期。APU控制器还连接到数据缓存控制器,通过它可以执行数据加载/存储操作。因此,APU接口能在每秒内移动数百兆字节,接近DMA速度。

    I/O连接加速器或指令流水线连接加速器可以与总线连接加速器结合起来。在增加额外的逻辑条件下,可以创建一个加速器,这个加速器运行在一个位于总线连接存储器上的数据块上,通过一个快速、低延时的接口接收命令并返回状态。

    在本文中介绍的C-HDL工具组可以实现总线连接和I/O连接加速器,它还能实现连接到PowerPC的APU接口的加速器。尽管APU连接是基于指令流水线的,C-HDL工具组实现了一种I/O流水线接口,该接口具有I/O连接加速器的典型性能。

    FPGA/PowerPC/APU接口

    FPGA允许硬件设计工程师利用单芯片上的处理器、解码逻辑、外设和协处理器实现一个完整的计算系统。FPGA可以包含数千到数十万的逻辑单元,可以从这些逻辑单元实现一个处理器,如Xilinx PicoBlaze或MicroBlaze处理器,或者可以是一个或者更多的硬逻辑单元(如Virtex-4 FX PowerPC)。大量的逻辑单元使你可以实现数据处理单元,这些单元与处理器系统一起工作,由处理器对其进行控制或监控。

    FPGA作为一种可重复编程的单元,允许你在设计过程中进行编程并对其进行测试。如果你发现了一个设计缺陷,你可以立即对其进行重新编程设计。FPGA还允许你实现硬件运算功能,而这在以前的实现成本是很高的。CPU流水线与FPGA逻辑之间紧密结合,这样就可以创建高性能软件加速器。

    图1的模块框图显示了PowerPC、集成的APU控制器以及一个与之相连的协处理器。来自高速缓存或存储器中的指令可以立即出现在CPU解码器和APU控制器上,如果CPU能识别指令,则运行这些指令。否则,APU控制器或用户创建的协处理器可以对指令做出应答并执行指令。一个或者两个操作数被传递到协处理器,并返回一个结果或状态。APU接口还支持用一个指令发送一个数据单元。数据单元的大小范围从一个字节到4个32位的字。

     


    图1:PowerPC、集成的APU控制器和协处理器

    通过一个结构协处理器总线(FCB),可以将一个或多个协处理器连接到APU接口。连接到总线的协处理器范围包括现存的内核(例如FPU)到用户创建的协处理器。一个协处理器可以连接到FCB用于控制和状态运算,并连接到一个处理器总线,实现直接存储器数据块访问以及DMA数据传递。一种简化的连接方案,例如FSL,也可以在FCB和协处理器之间使用,在牺牲一定性能的条件下实现FIFO数据和控制通信。

    为展示指令流水线连接加速器的性能优势,我们采用一个处理器总线连接FPU首先实现了一个设计,然后采用APU/FCB连接的FPU实现设计。表1总结了两种实现方式下有限脉冲响应(FIR)滤波器的性能。如表1中所反映的一样,连接到一个指令流水线的FPU使软件浮点运算速度增加30倍,而APU接口相比于总线连接FPU来说改善了近4倍。

     


    表1:未加速与加速的浮点性能

    C代码转换到HDL

    采用C到HDL的转换工具将C代码转换到HDL加速器是一种创建硬件协处理器的高效方法。图2所示以及下面详述的步骤总结了C到HDL转换的过程:

     


    图2:C-HDL设计流程

    1. 使用标准C工具实现应用程序或算法。开发一种软件测试向量(test bench)用于基线性能和正确性(主机或台式电脑仿真)测试。使用一种编译器(例如gprof)来开始确定关键的函数。

    2. 确定是否浮点到定点转换适当。使用库或宏来辅助这种转换,使用一个基线测试向量来分析性能和准确性。使用编译器来重新评估关键函数。

    3. 使用C到HDL转换工具(如Impulse C),在每个关键功能上重复,以实现:将算法分割成并行的进程;创建硬件/软件进程接口(流、共享存储器、信号);对关键的代码段(例如内部代码循环)进行自动优化和并行化;使用桌面电脑仿真、周期准确的C仿真以及实际的在系统测试对得到的并行算法进行测试和验证。

    4. 使用C到HDL转换工具将关键的代码段转换到HDL协处理器。

    5. 将协处理器连接到APU接口用于最终的测试。

    Impulse:C到HDL转换工具

    如图3所示的Impulse C通过结合使用C兼容库函数与Impulse CoDeveloper C代码到硬件的编译器,使嵌入式系统设计工程师能创建高度并行的、FPGA加速的应用。Impulse C通过使用定义完好的数据通信、消息传递和同步处理机制,简化了硬件/软件混合应用设计。Impulse C提供了C代码(例如循环流水线处理、展开和运算符调度)的自动优化以及交互式工具,允许你对每个周期的硬件行为进行分析。

     


    图3. Impulse C

    Impulse C设计用于面向数据流的应用,但是它也具有足够的灵活性来支持其他的编程模型,包括使用共享存储器。这一点很重要,因为基于FPGA不同的应用具有不同的性能和数据要求。在一些应用中,通过块存储器读和写在嵌入式处理器和FPGA之间转移数据是有意义的;在其它的情况下,流传数通信信道可能提供更高的性能。可以快速建模、编译和评估可选的算法的能力对于实现某个应用最佳的结果来说,非常重要。

    到目前为止,Impulse C库包含以新数据类型和预定义的函数调用形式的最少C语言扩展。使用Impulse C函数调用,你可以定义多个并行程序段(调用进程),并使用流、信号和其他机制描述它们的互连。Impulse C编译器将这些C语言进程转换并优化成:可以综合到FPGA的较低级HDL,或可以通过广泛存在的C交叉编译器编译到支持的微处理器上标准C(带相关的库调用)。

    完整的CoDeveloper开发环境包括与标准C编译器和调试器(包括微软公司的Visual Studio和GCC/GDB)兼容的台式电脑仿真库。使用这些库,Impulse C程序设计工程师能编译和执行他们用于算法验证和调试目的的应用程序。C程序设计工程师还能检验并行进程,分析数据移动,并利用CoDeveloper Application Monitor解决进程到进程的通信问题。

    在编译时,Impulse C应用的输出是一组硬件和软件源文件,用于输入到FPGA综合工具。这些文件包括:

    1. 用于描述编译硬件进程的自动产生的HDL文件;

    2. 用于描述连接硬件进程到系统总线所需的流、信号和存储器组件的自动产生的HDL文件;

    3. 自动产生的软件组件(包括运行时间库)用于建立任何硬件/软件流连接的软件端;

    4. 附加文件,包括脚本文件,用于输入产生的应用程序到目标FPGA布局布线环境。这种编译进程的结果是一个完整的应用,包括需要的硬件/软件接口,用于在基于FPGA的编程平台上实现。

    设计实例

    图4所示的Mandelbrot图是一种经典的不规则几何图形,该图形广泛用在科学和工程学界用于仿真无序事件,例如天气。不规则图形也用于产生纹理和在视频显示应用上成像。Mandelbrot图像描述为自相似性。放大图形的局部,可以获得类似于整个图形的另外一个图形。

     


    图4:Mandelbrot图

    Mandelbrot图形是硬件/软件协同设计的理想选择,因为它具有单个运算密集的函数。通过将关键的函数转移到硬件实现将大大地增加整个系统的速度,使这个关键函数更快。Mandelbrot应用还能清楚地区分硬件和软件进程,使用C-HDL工具很容易实现。

    本文使用CoDeveloper工具组作为C-HDL工具组用于该设计实例,而且只修改了软件Mandelbrot C程序以使其与C-HDL工具兼容。其中的改变包括:将软件项目分割成不同的进程(顺序执行的独立单元);函数接口转换(硬件到软件)到流;增加编译器指令来对产生的硬件进行优化。我们随后使用CoDeveloper工具组来创建Pcore协处理器,将该协处理器输入到Xilinx Platform Studio(XPS)。利用XPS,我们将PC连接到PowerPC APU控制器接口,并测试系统。

    Xilinx公司的应用说明资料XAPP901中提供了该设计的全面描述和设计文件,并提供下载。同时,用户指南UG096提供一种实现设计实例的逐步设计指导。

    我们对Mandelbrot图像纹理问题、图像滤波应用和三倍DES加密的性能改善进行了测量。性能改善显示了从11倍到34倍的加速,在表2中做出了总结。

     


    表2:通过协处理器加速器的算法加速性能对比

    本文小结

    受功率、尺寸和成本的约束,你可能需要做出一个并非理想的处理器选择,通常所选择处理器性能比期望的性能低。当软件代码不能运行足够快时,协处理器代码加速器成为一种很有吸引力的解决方案。你可以在HDL中手动设计加速器或使用C-HDL工具自动将C代码转换成HDL。

    使用Impulse C这样的C-HDL工具能使加速器运行更快且更简单。Virtex-4 FX FPGA具有两个嵌入式PowerPC,能实现处理器指令流水线到软件加速器之间紧密的连接。如上所述,关键的软件程序增加速度10倍到30倍,使300MHz的PowerPC提供等于或高于高性能GHz级处理器的性能。上面的实例每个只需要几天的时间来产生,显示了采用C-HDL流程的快速设计、实现和测试。

    作者:Glenn Steiner,高级工程经理,glenn.steiner@xilinx.com

    Kunal Shenoy,设计工程师,kunal.shenoy@xilinx.com

    Dan Isaacs,嵌入式处理总监,dan.isaacs@xilinx.com

    赛灵思公司先进产品分部

    David Pellerin,首席技术官,david.pellerin@impulsec.com

    Impulse Accelerated技术公司

     
    展开全文
  • 基本的CNN算法需要大量的计算和数据重用,非常适合使用FPGA实现。上个月,Ralph Wittig(Xilinx CTO Office的卓越工程师) 2016年OpenPower峰会上发表了约20分钟时长的演讲并讨论了包括清华大学在内的中国各大学...
  • 主要研究如何利用FPGA实现FFT算法,包括算法选取、算法验证、系统结构设计、FPGA实现和测试整个流 程。设计采用Good-Thomas算法,利用Verilog HDL描述的方式实现了不定点FFT系统,并以FPGA芯片virtex4 为硬件平台,...
  • 中值滤波算法在fpga上的实现

    千次阅读 2018-06-21 11:31:22
     在上一篇博客中我们搞清楚了如何使用shift_ram实现3*3的滤波矩阵,这篇博客我们讨论如何快速求的9个值的均值,下面介绍快速排序算法: 如图中所示,得到3*3矩阵的中值我们需要三个步骤: ...

         实时性的视频中值滤波硬件实现,使用shift_ram就够用,学过数字图像处理的都知道,无论是中值滤波还是均值滤波等等,一些基本的数字图像处理算法都是基于3*3的滤波矩阵实现的。

          在上一篇博客中我们搞清楚了如何使用shift_ram实现3*3的滤波矩阵,这篇博客我们讨论如何快速求的9个值的均值,下面介绍快速排序算法:

    如图中所示,得到3*3矩阵的中值我们需要三个步骤:

    (1)首先分别对每行的3个像素进行排序,建立sort排序模块,由于并行特性只需要一个时钟就可以完成。

    (2)上述代码实现了第一步的运算,第二行和第三行同理,接着对三行像素取得的排序进行处理,即提取三个最大值中的最小值,三个最小值中的最大值,以及三个中间值的中间值。直接例化 sort 模块。

    例化三次求得每一行的max_data ,mid_data, mix_data ,然后再例化三次。

    如上代码所示,再例化两次,依次求得最大值中的最小值,最小值中的最大值,中间值中的中间值,

    (3)然后再例化一次sort模块,求得这三个值中的中间值。最终求得3*3矩阵的中值。

    即实现了求中值,从步骤1-3花费了3个clk,同步信号延迟三个clk。搞定

    展开全文
  • 基本的CNN算法需要大量的计算和数据重用,非常适合使用FPGA实现。上个月,Ralph Wittig(Xilinx CTO Office的卓越工程师) 2016年OpenPower峰会上发表了约20分钟时长的演讲并讨论了包括清华大学在内的中国各大学...
  • 了解如何: - 使用 Vision HDL Toolbox:trade_mark: Simulink:registered: 中对车道检测算法进行建模- 从您的 Simulink:registered: 模型自动生成 VHDL 代码并部署到 Speedgoat Simulink-Programmable FPGA - ...
  • 本博文主要介绍FPGA如何实现边缘识别算法,可将RGB565格式的视频流输入,输出边缘检测的输出值,可直接摄像头采集与VGA是实时显示的系统中直接使用,文章末尾附有完整的工程代码工程。 第一步 RGB 转 Gray (将...

    本博文主要介绍FPGA中如何实现边缘识别算法,可将RGB565格式的视频流输入,输出边缘检测的输出值,可直接在摄像头采集与VGA是实时显示的系统中直接使用,文章末尾附有完整的工程代码工程。

    第一步 RGB 转 Gray (将RGB 转换为 灰度值)

    首先需要将采集到RGB565格式的视频数据转化为灰度值的格式,因为采用Sobel边缘检测算法处理的是灰度值图像,故需要先进行灰度值转换。

    这里我从用的是最常用,也是效果较好的  心理学公式:
    					 Gray = R*0.299 + G*0.587 + B*0.114
    为方便FPGA计算可将公式转换为以下形式:
    				     Gray = (R*76 + G*150 + B*30) >> 8
    由于代码难度不大,就不进行详细介绍,代码如下(补充:如果输入的是RGB888格式的数据,只需要assign rgb_data[23:0] = {RGB565_IN[15:11],3'b111,RGB565_IN[10:5],2'b11,RGB565_IN[4:0],3'b111}; 
    改为:assign rgb_data =RGB565_IN;即可 ):
    
    module RGB2Gray(
    	input 			Clk			,		
    	input 			Rst_n		,			
    		
    	input [15:0]	RGB565_IN	,		
    	input 			RGB_DATA_EN	,	
    	
    	output[7:0]	 	Gray_out	,	
    	output reg 		Gray_out_EN
    );
    
    //     Gray = R*0.299 + G*0.587 + B*0.114
    //     Gray = (R*76 + G*150 + B*30) >> 8    使用8位精度来进行运算
    reg [14:0] RGB_RED			;
    reg [15:0] RGB_GREEN 		;
    reg [14:0] RGB_BLUE			; 
    reg [15:0] gray_temp			;
    reg 		  RGB_DATA_EN_d0	;
    
    wire [23:0] rgb_data  		;
    
    assign rgb_data[23:0] = {RGB565_IN[15:11],3'b111,RGB565_IN[10:5],2'b11,RGB565_IN[4:0],3'b111};
    
    always@(posedge Clk or negedge Rst_n)
    	if(!Rst_n)begin
    		RGB_RED	 <= 'd0;
    		RGB_GREEN <= 'd0; 	
    	   RGB_BLUE	 <= 'd0;
    	end
    	else if(RGB_DATA_EN)begin
    		RGB_RED	 <= rgb_data[23:16]*8'd76;
    		RGB_GREEN <= rgb_data[15:8]*8'd150;
          RGB_BLUE	 <= rgb_data[7:0]*8'd30;
    	end
    //gray_temp	
    always@(posedge Clk or negedge Rst_n)
    	if(!Rst_n)
    		gray_temp <= 'd0;
    	else 
    		gray_temp <= RGB_RED + RGB_GREEN + RGB_BLUE;
    		
    always@(posedge Clk or negedge Rst_n)
    	if(!Rst_n)begin
    		RGB_DATA_EN_d0 <= 1'b0;
    		Gray_out_EN 	<= 1'b0;
    	end
    	else begin
    		RGB_DATA_EN_d0 <= RGB_DATA_EN	  ;
    		Gray_out_EN 	<= RGB_DATA_EN_d0 ;
    	end
    		
    assign Gray_out = gray_temp[15:8];
    		
    endmodule
    
    

    第二步 3*3矩阵生成

    由于Sobel算法中需要将算子与3*3的灰度图像值进行卷积运算,故需要将输入的串行灰度值转换为矩阵。我采用移位寄存器的形式来产生矩阵序列,最大限度的节省了时钟数与内部寄存器资源。主要原理由于篇幅有限,本博客不做详细的原理讲解,大家可参考 小梅哥 RAW转RGB的实现,原理类似,这里的实现更加简单。

    移位寄存器IP核创建
    

    在这里插入图片描述
    这里
    具体代码实现如下:

    module Mat_3x3(
    	input 			  Clk		,
    	input 			  Rst_n	  	,
    		
    	input [7:0]		  Gray_data	,
    	input				  data_flag	,
    		
    	output wire [7:0] mat_row1	,
    	output wire [7:0] mat_row2	,
    	output wire [7:0] mat_row3	,
    	output 	 			mat_flag	
    );
    
    parameter           COL_NUM     =   640    ;
    parameter           ROW_NUM     =   480    ;
    
    wire [7:0]	shiftout_0;
    wire [7:0]	shiftout_1;
    
    reg  [9:0] COL_Couter;
    reg  [9:0] ROW_Couter;
    //reg  [7:0] Gray_data_0;
    
    assign mat_row1 = (mat_flag) ? Gray_data  : 8'h00;
    assign mat_row2 = (mat_flag) ? shiftout_0 : 8'h00;
    assign mat_row3 = (mat_flag) ? shiftout_1 : 8'h00;
    assign mat_flag = (ROW_Couter >= 'd2 && data_flag) ? 1'b1:1'b0;
    
    //COL_Couter
    always@(posedge Clk or negedge Rst_n)
    	if(!Rst_n)
    		COL_Couter <='d0;
    	else if(COL_Couter == (COL_NUM - 1'b1)&& data_flag)
    		COL_Couter <='d0;
    	else if(data_flag)
    		COL_Couter <= COL_Couter + 1'b1;
    		
    //ROW_Couter
    always@(posedge Clk or negedge Rst_n)
    	if(!Rst_n)
    		ROW_Couter <='d0;
    	else if(COL_Couter == (COL_NUM - 1'b1) && ROW_Couter == (ROW_NUM - 1'b1) && data_flag)
    		ROW_Couter <='d0;
    	else if(COL_Couter == (COL_NUM - 1'b1) && data_flag)
    		ROW_Couter <= ROW_Couter + 1'b1;
    
    
    Shift_0 Shift_0(
    	.clock			(Clk&data_flag	 ),
    	.shiftin		(Gray_data    	 ),
    	.shiftout		(shiftout_0   	 ),
    	.taps			(					 ));
    	
    Shift_0 Shift_1(
    	.clock			(Clk&data_flag	),
    	.shiftin		(shiftout_0		),
    	.shiftout		(shiftout_1	 	),
    	.taps			(					));
    
    endmodule
    

    第三步 Sobel边缘算法实现

    之前的两步都为这一步做数据准备,Sobel算法的具体原理本博客也不在做具体介绍,大家可参考Bingo 大佬的这篇博客 http://group.chinaaet.com/116/79095 ,以及这位博主的讲解 https://blog.csdn.net/Mahabharata_/article/details/69099136
    Sobel 算法
    代码实现如下:

    module Sobel_rgb(
    	input Clk							,
    	input Rst_n							,
    				
    	input [7:0]	mat_row1				,
    	input [7:0]	mat_row2				,
    	input [7:0]	mat_row3				,	
       input      	mat_flag				,
    	
    	output reg  post_img_Bit_r		,	
    	output reg  post_img_Bit_en		
    );
    
    //Sobel Parameter
    
    //         Gx                  Gy               Pixel
    
    // [   -1  0   +1  ]   [   +1  +2   +1 ]     [   P11  P12   P13 ]
    
    // [   -2  0   +2  ]   [   0   0    0  ]     [   P21  P22   P23 ]
    
    // [   -1  0   +1  ]   [   -1  -2   -1 ]     [   P31  P32   P33 ]
    reg [7:0] matrix_p11,matrix_p12,matrix_p13;
    reg [7:0] matrix_p21,matrix_p22,matrix_p23;
    reg [7:0] matrix_p31,matrix_p32,matrix_p33;
    
    reg [9:0] Gx_temp1;   //postive result
    reg [9:0] Gx_temp2;   //negtive result
    reg [9:0] Gx_data;    //Horizontal grade data 
    
    reg [9:0] Gy_temp1;   //postive result
    reg [9:0] Gy_temp2;   //negtive result
    reg [9:0] Gy_data;    //Vertical grade data 
    
    reg [20:0] Gxy_square;
    
    wire [10:0]Dim;
    parameter Sobel_Threshold = 60;   //Threshold value
    
    reg mat_flag_0,mat_flag_1,mat_flag_2;
    
    always@(posedge Clk or negedge Rst_n)
    	if(!Rst_n)begin
    		mat_flag_0		 <= 1'b0;
    	   mat_flag_1		 <= 1'b0;
    	   mat_flag_2		 <= 1'b0;
    	   post_img_Bit_en <= 1'b0;
    	end
    	else begin
    		mat_flag_0		 <= mat_flag  ;	
    		mat_flag_1		 <= mat_flag_0;
    		mat_flag_2		 <= mat_flag_1;
    		post_img_Bit_en <= mat_flag_2;
    	end
    	
    
    always@(posedge Clk or negedge Rst_n)
    	if(!Rst_n)begin	
    		matrix_p11 <= 'd0;
    		matrix_p21 <= 'd0;
    		matrix_p31 <= 'd0;
    		 
    		matrix_p12 <= 'd0;
    		matrix_p22 <= 'd0;
    		matrix_p32 <= 'd0;
    		 
    		matrix_p13 <= 'd0;
    		matrix_p23 <= 'd0;
    		matrix_p33 <= 'd0;
    	end
    	else if(mat_flag)begin
    	   matrix_p13 <= mat_row1	  ;
    	   matrix_p23 <= mat_row2	  ;
    	   matrix_p33 <= mat_row3	  ;
    		   
    	   matrix_p12 <= matrix_p13  ;
    	   matrix_p22 <= matrix_p23  ;
    	   matrix_p32 <= matrix_p33  ;
    		   
    		matrix_p11 <= matrix_p12  ;
    	   matrix_p21 <= matrix_p22  ;
    	   matrix_p31 <= matrix_p32  ;
    	end	
    
    //Caculate horizontal Grade with |abs|
    
    //Step 1
    always@(posedge Clk or negedge Rst_n)
    begin
    	if(!Rst_n)
    		begin
    		Gx_temp1 <= 'd0;
    		Gx_temp2 <= 'd0;
    		Gx_data <= 'd0;
    		end
    	else
    		begin
    		Gx_temp1 <= matrix_p13 + (matrix_p23 << 1) + matrix_p33;			//postive result
    		Gx_temp2 <= matrix_p11 + (matrix_p21 << 1) + matrix_p31;  		//negtive result
    		Gx_data <= (Gx_temp1 >= Gx_temp2) ? Gx_temp1 - Gx_temp2:Gx_temp2 - Gx_temp1; 
    		end
    end
    //Caculate Vertical Grade with |abs|
    
    //Step 2
    always@(posedge Clk or negedge Rst_n)
    begin
    	if(!Rst_n)
    		begin
    		Gy_temp1 <= 'd0;
    		Gy_temp2 <= 'd0;
    		Gy_data <= 'd0;
    		end
    	else
    		begin
    		Gy_temp1 <= matrix_p11 + (matrix_p12 << 1) + matrix_p13;			//postive result
    		Gy_temp2 <= matrix_p31 + (matrix_p32 << 1) + matrix_p33;  		//negtive result
    		Gy_data <= (Gy_temp1 >= Gy_temp2) ? Gy_temp1 - Gy_temp2:Gy_temp2 - Gy_temp1; 
    		end
    end
    //Caculate the square of distance = (Gx^2 + Gy^2)
    
    //Step 3
    always@(posedge Clk or negedge Rst_n)
    begin
    	if(!Rst_n)
    		Gxy_square <= 'd0;
    	else
    		Gxy_square <= (Gx_data * Gx_data) + (Gy_data * Gy_data);
    end
    
    //Caculate the distance of P5 = (Gx^2 + Gy^2)^0.5
    
    //Step 4
    SQRT SQRT(
    	.radical(Gxy_square),
    	.q(Dim),
    	.remainder());
    	
    //Compare and get the Sobel_data
    
    //Step 5
    always@(posedge Clk or negedge Rst_n)
    begin
    	if(!Rst_n)
    		post_img_Bit_r <= 1'b0;
    	else if(Dim > Sobel_Threshold)
    		post_img_Bit_r <= 1'b1;       //Edge Flag
    	else
    		post_img_Bit_r <= 1'b0;			//No Edge Flag
    end
    
    
    endmodule
    
    

    第四步 顶层文件

    这一步就是将上面的代码块封装起来,便于调用

    module Sobel_Top(
    	input 		 Clk					,
    	input 		 Rst_n				,
    			
    	input [15:0] RGB565_IN			,
    	input 		 RGB_DATA_EN		,
    		
    	output 		 post_img_Bit_r	,	
    	output       post_img_Bit_en		
    );		
    //RGB2Gray
    wire [7:0]	 	Gray_out		;	
    wire			 	Gray_out_EN ; 
    //Mat_3x3	
    wire [7:0] 		mat_row1;		
    wire [7:0] 		mat_row2;		
    wire [7:0] 		mat_row3;		
    wire 				mat_flag;		
    
    
    //RGB to Gray Data
    RGB2Gray RGB2Gray(
    	.Clk			(Clk				),		
    	.Rst_n		(Rst_n			),			
    	             
    	.RGB565_IN	(RGB565_IN		),		
    	.RGB_DATA_EN(RGB_DATA_EN	),	
    		          	
    	.Gray_out	(Gray_out		),	
    	.Gray_out_EN(Gray_out_EN	)
    );
    
    //Generate Matri_three
    Mat_3x3 Mat_3x3(
    	.Clk		  	(Clk		  	 ),
    	.Rst_n	  	(Rst_n	  	 ),
    	             
    	.Gray_data	(Gray_out	 ),
    	.data_flag	(Gray_out_EN ),
    	             
    	.mat_row1	(mat_row1	 ),
    	.mat_row2	(mat_row2	 ),
    	.mat_row3	(mat_row3	 ),
    	.mat_flag	(mat_flag	 )
    );
    
    //Sobel margin calculate
    Sobel_rgb Sobel_rgb(
    	.Clk					(Clk					),
    	.Rst_n				(Rst_n				),
    		                	
    	.mat_row1			(mat_row1			),
    	.mat_row2			(mat_row2			),
    	.mat_row3			(mat_row3			),	
       .mat_flag			(mat_flag			),
    	                   
    	.post_img_Bit_r	(post_img_Bit_r	),	
    	.post_img_Bit_en	(post_img_Bit_en	) 	
    );
    
    endmodule
    
    

    工程代码下载地址

    https://download.csdn.net/download/weixin_44580647/12509664

    下面是代码的实现效果,此处设置的阈值为 65
    在这里插入图片描述

    展开全文
  • FPGA极其不擅长复杂算法的运算,但是如果项目中涉及一些高级算法实现没有可封装IP核调用的形式下,应该如何进行程序开发呢?今夕已经是2020年,我们一味依赖于用verilog写代码无异于用汇编写程序,这种方式堪...

    基于Matlab Hdl Coder实现FPGA程序开发(卡尔曼滤波算法实现)

    原文转载于:https://www.cnblogs.com/tanqiqi/p/12938148.html

    FPGA极其不擅长复杂算法的运算,但是如果项目中涉及一些高级算法的实现,在没有可封装IP核调用的形式下,应该如何进行程序开发呢?今夕已经是2020年,我们一味依赖于用verilog写代码无异于用汇编写程序,这种方式堪比古时钻木取火的原始时代,费时又费力,实现起来更是困难重重。如今用Matlab联调FPGA,基于simulink的Hdl Coder模块搭建算法模型,再自动生成代码才是高阶有效的终极玩法,尤其在一些信号处理领域,掌握Matlab联调FPGA的技术更是必备技能。

    下面以卡尔曼滤波(Kalman filtering)为例,具体讲述如何基于Hdl Coder实现卡尔曼滤波FPGA程序开发,首先简单介绍下卡尔曼滤波算法的数学原理。

     卡尔曼滤波是一种利用线性系统状态方程,通过系统输入输出观测数据,对系统状态进行最优估计的算法。由于观测数据中包含系统噪声和干扰的影响,所以最优估计也可看作是滤波过程。简单来说,它就是利用过去的状态值和现在的测量值来更正现在的状态值,利用卡尔曼增益不停在估计和测量中寻找最优化的平衡值。
    

    Kalman filtering的经典五方程,在进行卡尔曼滤波的程序设计前必须要充分理解这五个方程的定义、推导以及相关变量的设定。

    (1) 对于现在状态的预测方程:

    X(k|k-1)=A X(k-1|k-1)+B U(k) ………… (1)

    P(k|k-1)=A P(k-1|k-1) A’+Q ……… (2)

    (2)对于现在状态的更新方程:(拿过去的真实值得到现在的预测值,再集合现在的测量值Z(k),进行现在状态值的更新)

    X(k|k)= X(k|k-1)+Kg(k) (Z(k)-H X(k|k-1)) ……… (3)

    Kg(k)= P(k|k-1) H’ / (H P(k|k-1) H’ + R) ……… (4)

    P(k|k)=(I-Kg(k) H)P(k|k-1) ……… (5)

    其中Z(k)=H X(k)+V(k)为观测方程。

    对于上述方程要明确以下几个变量的赋值:

    1) 状态转移矩阵:A

    2) 系统控制变量:U(k)

    3) 观测矩阵:H

    4)系统状态初值:X(0|0)

    5)系统协方差:P(0|0)

    6)R:测量噪声

    7)Q:过程噪声

    8)Z:观测值

    这7个变量要根据不同的产品以及应用场景进行具体赋值,其中对于单系统输入,变量赋值为:

    1)A=1(状态转移矩阵),U(k)=0(系统控制变量), H=1(观测矩阵),B=1(对于一维变量,全为1)

    2)Z观测值就是系统外部灌进来的实时变量。

    3)系统协方差:P(0|0),可以采样一段时间后进行运算保证在kalman滤波器工作前进行赋值即可。

    4)对于卡尔曼应用,最难确定的就是Q、R这两个噪声,只能根据实际模型,不停调整以逼近最优解。

    基于上述的卡尔曼滤波搭建simulink仿真模型

    对上述simulink模型进行进一步封装

    下面具体设置kalman模块的Hdl Coder参数模式:

    最后点击“Generate HDL”与“Generate Test Bench”,即可生成verilog源程序与测试代码

    要对上述文件进行仿真,只需要在modelsim命令执行框自动执行以下文件“kalman_compile.do”,“kalman_tb_compile.do”,"kalman_tb_sim.do"即可。

    下面进行卡拉曼滤波效果展示:

    验证目的:调整Q的参数值,验证Modelsim的仿真波形是否有对应的正确变化。
    1)Q=0.003,R=0.0001,预计滤波后的噪声跟原始噪声相差不大。

    结果展示:

    验证结果:原始噪声与滤波后噪声幅值基本一致,符合期望值。

    2)Q=0.0000003,R=0.0001,预计滤波后的噪声跟原始噪声幅度值相差较大,滤波效果较好。

    结果展示:

    验证结果:卡尔曼滤波后噪声幅值较小,符合输出期望值。至此,基于Hdl Coder实现卡尔曼滤波算法结束。
    小结:基于simulink的Hdl Coder与FPGA联合开发是一种十分高效的实现复杂算法的方法,关键在于基于Hdl Coder搭建好仿真模型,并且学会利用仿真测试文件评估算法实现效果,最后再进行上板代码移植。

    https://www.cnblogs.com/tanqiqi/p/12938148.html

    展开全文
  • 此存储库是利用Sobel算法的边缘检测图像处理器的FPGA实现。 第一个项目包含VHDL代码和一个测试平台,用于执行图像处理功能的仿真。 第二个项目是针对Xilinx Artix-7开发板的可综合版本。 可合成版本利用异步串行通信...
  • FPGA实现灰度直方图均衡

    千次阅读 2019-05-30 17:35:17
    目录 前言 1、概述 2、FPGA实现直方图均衡化 ...所以,重点是对算法原理的理解和掌握,独立思考如何采用FPGA实现。这个过程比简简单单的看懂别人的代码重要许多倍! 理解掌握算法原理之后,再有自己的...
  • 本文主要介绍了短帧Turbo译码器的FPGA实现,并对相关参数和译码结构进行了描述。1几种译码算法比较Turbo码常见的几种译码算法中,MAP算法[1][3]具有最优的译码性能。但因其运算过程中有较多的乘法和指数运算,硬件...
  • 本教程将指导您完成在FPGA硬件中实现MATLAB算法所需的步骤,包括: *使用Simulink创建算法的流版本*实施硬件架构*将设计转换为定点*生成并合成HDL代码
  • 本文详细介绍了TCAM器件高速路由查找中的应用及其管理算法,同时重点给出了TCAM器件的FPGA实现。  1 引言  路由器转发IP分组时,转发引擎需要路由表中查找该IP报文中目的地址所对应的路由 信息,从而决定IP...
  • 第一部分是关于如何通过MATLAB专门使用HDL Coder以及HDL代码生成以及Xilinx工具的一组教程。 其中包括Xilinx Platform Studio(XPS)和Xilinx系统生成器。 这些实验室练习可“实验室”目录中找到。 这些实验室练习...
  • 如何利用Device DNA实现FPGA设计加密

    千次阅读 2019-08-29 10:07:53
    Xilinx所有的FPGA器件都有Device DNA,这是一个57bit的二进制序列,器件生产的时候烧死到芯片里面,每个芯片都是唯一的。这个序列,用户可以通过JTAG或者verilog(VHD)应用程序直接读出。怎么使用这个DNA,因应用...
  • HDL编码器自学教程 本教程将指导您完成在FPGA硬件中实现MATLAB算法所需的步骤,包括: 使用Simulink创建算法的流版本 实施硬件架构 将设计转换为定点 生成并合成HDL代码
  • 深度学习FPGA实现的阶段性总结

    千次阅读 2018-06-26 21:31:59
    当然这只是入门的尝试,对于一个深度学习算法如何在硬件上实现效率最高,还需要进一步的验证(在SOC架构中对算法进行划分还是直接采用高端FPGA实现)。 最开始做的是卷积层的实现,通过学习的例程,使我对整个...
  • 为改善FPGA在数字信号处理方面的适应性问题,文中研究了如何用硬件描述语言来实现最佳精度定点数的数值运算算法,其中重点阐述了定点数的表示、定标、保持最佳精度的定点数运算法则以及如何用VHDL语言实现宽位最佳...
  • 基于此,本文就满足系统模块化的设计思想需求,提出了基于EMCCD实时图像处理系统设计,将DSP和FPGA作为核心器件,实现相应硬件电路设计,并且实时图像处理系统中使用高要求的跟踪算法。通过实验结果表示,设计的...
  • 本文介绍了如何在FPGA 中利用Block RAM 的特殊结构实现HDTV 视频增强算法中灰度直方图统计。
  • 根据简化的循环侧抑制网络处理算法,并结合硬件计算特点,提出一种适合于硬件实现循环侧抑制网络的并行处理结构,采用流水线设计方式在FPGA中实时实现。试验证明:该算法在FPGA内具有与视频流同步的实时性,达到了...
  • 摘要:论述了某航天器DS-SS接收机外部AGC的设计原理和具体实现,重点讨论了如何根据射频前端的输出设计全数字AGC以扩展接收机的动态范围,并给出了基于FPGA的外部AGC电路算法。计算机仿真和硬件实现表明该数字AGC...
  • 中值滤波是基本的图像处理算法之一。如上图,对于每个3*3的... 那么问题来了,如何实现3*3矩阵的提取呢? 明德扬的FPGA系列教程里面提供的是用shift_ram这个IP核来实现网上有看到类似用shift_ram来实现的文...
  • 用vhdl做滤波器的fpga实现时,尝试采用分布式算法和查表法来优化,因为找到的例子是用的Verilog语言,写到最后的移位累加时就出现问题了,移位累加无法得到正确的值。想请前辈们帮忙提供一些思路或者经验,我对...
  • 当今各类主流通信算法经常涉及求逆和SVD分解,但是如何利用FPGA高效实现SVD不可谓不是难点。本片论文从最基本定义讲起,最后一直到FPGA硬件实现。文章通俗易懂,不可谓不是此类极为稀少的文献中的翘楚之作。...
  • FPGA数字信号处理(八)Quartus FFT IP核实现

    万次阅读 多人点赞 2018-06-14 11:22:07
    本系列的2-7篇分别介绍了FIR和IIR滤波器的FPGA实现。除了数字滤波器外,快速傅里叶变换(FFT)也是DSP系统常用的运算单元,用于对信号进行频域分析。FFT算法的实现很复杂,但Altera和Xilinx都提供了可快速上手使用的...
  • 该PPT主要讲述了如何使用硬件语言在FPGA或ASIC上实现复杂的算法

空空如也

空空如也

1 2 3 4 5 6
收藏数 116
精华内容 46
关键字:

如何在fpga实现算法