草庐IT

从底层结构开始学习FPGA(2)----LUT查找表

孤独的单刀 2023-04-12 原文

文章目录

        系列目录与传送门

        一、概述

        二、实现原理


系列目录与传送门

        《从底层结构开始学习FPGA》目录与传送门


一、概述

        记得刚接触FPGA的时候,总能看见类似这样的一句话----FPGA是基于查找表LUT的可编程逻辑器件。FPGA常常被人比作“数字积木”,就是因为底层资源的丰富和灵活,要做任何“玩具”(项目要实现的功能,也可以说是电路),只需要设计好“图纸”(RTL),即可使用积木(FPGA丰富的底层逻辑资源,如LUT、FF、MUX等等)来实现。

        在最底层,可配置逻辑模块有着两种最基本的部件:触发器和查找表(LUT)。这很重要,因为各种FPGA家族之所以各不相同,就是因为触发器和查找表组合的方式不同。LUT查找表可以算其中相当重要的一个底层资源,通常用来实现所需的组合逻辑功能。而FF触发器则一般用来实现时序逻辑功能。

        在7系列器件之前的器件多使用LUT4,即4输入LUT;而7系列后则多使用LUT6,即6输入LUT。

二、实现原理

        LUT(look up table),即查找表,其原理其实也就是一个一个查找表,根据输入去找到相应位置的信号,然后做输出。说白了就好像一个小容量的ROM,把输入当作地址信号,对LUT里面预存的内容进行寻址。

        7系列的FPGA的LUT有6个输入端口(I0~I5),然后有两个输出端口(O5,O6),如下所示:

        6个输入端口一共有2^6 = 64种输入,所以可以将一个LUT6视为一个容量为64的ROM,其中存储的是64种不同的逻辑运算的结果,而不同的输入则组成了ROM的地址线。所以逻辑运算的实现实际上就是对LUT6的一个译码过程。

        假设有这样一个逻辑: y = a0 & a1 & a2 & a3 & a4 & a5。

        这个例子比较简单,其只在所有输入均为1的情况下输出才为1,其他情况输出均为0。将其写成Verilog的形式:

module test(
    input	a0,
    input	a1,
    input	a2,
    input	a3,
    input	a4,
    input	a5,
    output 	y
);
 
	assign y = a0 & a1 & a2 & a3 & a4 & a5;
 
endmodule

        用Vivado analysis一下,看看分析出来的门级电路是什么样子的:

        很显然,就是5个与门实现6输入相与的功能。如果FPGA中没有LUT这种结构,而是由不同的逻辑门组成,那么实现上述逻辑功能则最终会映射到5个与门。可是随着设计的复杂化,仅仅使用与门显然是无法满足设计需求的,我们还需要其他逻辑门,如或门、非门、异或门等。当然这些逻辑门都可以由数个与非门或者或非门实现,但是这无疑需要进行一个译码过程以及会造成资源的浪费。

        而LUT将所有可能的逻辑值均存起来,用的时候再查表就方便多了。我们不需要知道这个电路会映射成什么样的、多少个逻辑门,我们只需要根据输入直接查表找对应的输出就行了。这大大提高了灵活性以及资源的利用效率。

        此外,采用传统逻辑门电路实现逻辑关系的方法也存在一些严重的缺点:

  • 输入变量从通过逻辑电路到输出变量,存在一定的延迟,该延迟的大小和逻辑电路的复杂程度密切相关。逻辑电路越复杂,延迟越大,因此,延迟是不确定的;
  • 延时的倒数是频率,频率和时序电路的工作速率密切相关。因为延迟不确定,所以频率也不确定,这将严重影响整个电路的工作性能;
  • 逻辑电路的复杂程度和输入逻辑变量的个数、逻辑门的个数有关。因此输入逻辑变量越多,逻辑电路就越复杂。

        说回正题,我们把上述代码再综合(synthesis)一下,看看最终的电路实现是什么样子的:

        和料想的一样,就是综合出来一个LUT6。

        下图是LUT6的源语形式(也可以说是网表形式),其中的INIT例化的值即是载入的64个输入的对应值。

        我们把上述代码的网表文件导出来看看(我只截取了LUT6部分):

        注意INIT的值,64bit中只有最高位为1,其他63位为0。也就是说,只有当6输入均为1时输出才为1,其他输入情况下输出均为0。与料想的逻辑值一致,也就是说INIT载入的是要查表的值,也就是要写入LUT这个小ROM的初始值。

        再把上述代码再实现(implementation)一下,看看映射到FPGA芯片的具体实现是什么样子:

        很简单,就是6个输入+1个输出+1个LUT6,LUT6的结构与理论一致。注意:LUT6中的O5输出并没有使用。


       

        再看下LUT6的结构:

        其实1个LUT6是由2个LUT5 + 1个MUX组成的。2个LUT5共用5个输入,其中一个LUT5的输出直接连接到O5;同时该输出也连接到MUX,另一个LUT5的输出也连接到MUX,而输入I5则作为MUX的选择控制信号。

  • 当LUT6作为6输入查找表使用时,则其中一个LUT5存放I5为1时的结果,而另一个LUT5则存放I5为0时的结果,此时O5输出不使用。而O6输出则通过I5的控制来实现6输入的查找结果
  • 当LUT6作为2个5输入查找表使用时,则将I5固定为1,则其中一个LUT5实现逻辑功能y1,并固定通过MUX到O6输出,而另一个LU5则实现逻辑功能y2,并直接通过O5输出

        

        举例如下:

                逻辑 y1 = a0 & a1 & a2 & a3 & a4;

                逻辑 y2 = a0 | a1 | a2 | a3 | a4;

        Verilog如下:

module test(
    input	a0,
    input	a1,
    input	a2,
    input	a3,
    input	a4,
    output 	y1,
    output 	y2
	
);
 
	assign y1 = a0 & a1 & a2 & a3 & a4 ;
	assign y2 = a0 | a1 | a2 | a3 | a4 ;
 
endmodule

        vivado综合的电路:

        结果是2个LUT5,但是我们知道7系列的FPGA是没有独立的LUT5这玩意儿的,所以最终映射到具体芯片上还不是这样子。

        最后来看看vivado实现的电路(映射到FPGA芯片的具体实现):

        和预想的一样,就是一个2输出的LUT6。

        其他位数输入的逻辑实现就可以采用多个LUT6级联来实现,当输入位数过多,即组合逻辑复杂时,则会造成级联的LUT6过多,即逻辑级数多大,其结果是通常会造成组合逻辑延时多大,导致时序紧张,一般采用插入FF的方法来切割组合逻辑,使得每一段的逻辑级数都不过于长,从而优化时序。

        一句话总结:LUT的逻辑实现是通过将期望结果存入SRAM中,通过不同的输入等于不同地址这一索引方式,来实现对逻辑真值表的查找。

有关从底层结构开始学习FPGA(2)----LUT查找表的更多相关文章

  1. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  2. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

  3. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  4. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  5. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  6. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  7. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  8. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  9. ruby-on-rails - 一般建议和推荐的文件夹结构 - Sinatra - 2

    您将如何构建一个简单的Sinatra应用程序?我正在制作,我希望该应用具有以下功能:“应用程序”更像是一个包含所有信息的管理仪表板。然后另一个应用程序将通过REST访问信息。我还没有创建仪表板,只是从数据库中获取东西session和身份验证(尚未实现)您可以上传图片,其他应用可以显示这些图片我已经使用RSpec创建了一个测试文件通过Prawn生成报告目前的设置是这样的:app.rbtest_app.rb因为我实际上只有应用程序和测试文件。到目前为止,我已经将Datamapper用于ORM,将SQLite用于数据库。这是我的第一个Ruby/Sinatra项目,所以欢迎任何和所有建议-我应

  10. ruby-on-rails - 在 Rails 中更高效地查找或创建多条记录 - 2

    我有一个应用需要发送用户事件邀请。当用户邀请friend(用户)参加事件时,如果尚不存在将用户连接到该事件的新记录,则会创建该记录。我的模型由用户、事件和events_user组成。classEventdefinvite(user_id,*args)user_id.eachdo|u|e=EventsUser.find_or_create_by_event_id_and_user_id(self.id,u)e.save!endendend用法Event.first.invite([1,2,3])我不认为以上是完成我的任务的最有效方法。我设想了一种方法,例如Model.find_or_cr

随机推荐