文章目录
2.7、可选输出寄存器(Optional Output Registers)
2.8、流水线输出(Optional Pipeline Stages)
此文仅仅对xilinx BRAM IP的参数做了详细解读,关于IP核的定制与使用方法请移步:从底层结构开始学习FPGA----Xilinx RAM IP的定制与测试
随机存取存储器(Random Access Memory,RAM),也叫主存,是与CPU直接交换数据的内部存储器。它可以随时读写(刷新时除外),而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储介质。RAM工作时可以随时从任何一个指定的地址写入(存入)或读出(取出)信息。RAM在计算机和数字系统中用来暂时存储程序、数据和中间结果。
通俗来讲,RAM和ROM都可以看做是一张用来存储数据的表格,每个表格的位置则是通过地址线来确定的。只不过RAM即可以写数据,也可以读数据;而ROM则只能读数据(初始化数据不将其视为一次写操作)。
Xlinx系列FPGA,包含两种RAM:Block RAM和分布式RAM(Distributed RAM),他们的区别在于,Block RAM是内嵌专用的RAM,而Distributed RAM需要消耗组合逻辑资源LUT组成。
我们今天要学习的正是由BRAM资源构成的RAM IP核----Block Memory Generator。
xilinx的RAM IP可以构建3种不同形式的RAM:
(1)单口RAM(Single-port RAM)
只有一个端口,可读可写,但无法同时进行。

(2)简单双口RAM(Simple Dual-port RAM)
有两个独立的端口A、B,其中一个端口只读,另一个端口只写。

(3)真双口RAM(True Dual-port RAM)
有两个独立的端口A和端口B,2个端口都可以读、写。

本文所谈到的是由BRAM组成的RAM,所以其基本单元是FPGA底层的固有存储资源----Block RAM(BRAM)。BRAM在FPGA底层以1块36KbBRAM、或者2块18KbBRAM组合而成。
18KbBRAM可以被配置成16K x 1, 8K x 2, 4K x 4, 2K x 9, 1K x 18, 512 x 36和256 x 72的模式,但其内部总容量仍为18Kb。

RAM IP核提供了三种优化方式来优化大容量的RAM实现。比如要实现,宽度为16bit, 深度为4K的RAM,仅仅使用一块36K的BRAM是无法实现的,必须要用到多块36KBRAM和18KBRAM的组合形式,下面三种算法针对不同的需求来优化RAM的实现。
(1)面积最小算法(Minimum Area Algorithm)
该算法使得实现RAM所使用的基本BRAM块数量是最小的,同时此种算法实现的运行频率也是比较高的,一般情况下默认使用该算法。
下面两种需求的RAM均是使用了最小数量的BRAM模块来实现。

(2)低功耗算法(Low Power Algorithm)
该算法就是要实现最小的功耗,即适用于低功耗要求。

(3)固定模块算法(Fixed Primitive Algorithm)
此算法可以让开发者自己指定某个固定的源语模块来RAM的单一实现模块,如16K x 1, 8K x 2, 4K x 4, 2K x 9, 1K x 18, 512 x 36和256 x 72。
下面两种RAM的实现则使用了固定的两种BRAM块:2K x 9和4K x 4。

IP核提供的读写模式有3种:
(1)Write First Mode--写优先模式
要被写入的数据会被写入到对应的地址里,同时输出线上的数据也会变成刚刚写入的数据。(需要注意的是:DOUTA中所出现的数据改变均需要一定的时间)

(2)Read First Mode--读优先模式
要被写入的数据会被写入到对应的地址里,同时输出线上输出该地址未被写入新数据之前的旧数据。

(3)No Change Mode--无变化模式
要被写入的数据会被写入到对应的地址里,同时输出线上则会保持上一次读出的数据不变,直到新的一次读操作发生

RAM IP核支持两个端口的位宽不同,只要满足以下比例条件即可:1:32, 1:16, 1:8, 1:4, 1:2, 1:1, 2:1, 4:1, 8:1, 16:1, 32:1。当然位宽成正比,则深度就成反比,因为总得容量大小是不变的。
下面的端口A配置是位宽32bi,深度2048bit。而B端口位宽设置为8(32/4),则其深度则为2048*4=8192bit。下面可以看到,由于端口B位宽仅仅为端口A位宽的四分之一,所以一个端口A的数据空间可以容纳4个端口B的数据,即A0包含B3, B2, B1, B0。

RAM IP还具备字节写功能,这样可以只对某一个字节进行修改,从下图时序图可以看出,只要控制WEA就可以控制对具体哪一个BYTE进行写控制。

如果两个端口,同时对一个地址进行操作的话,则会产生读写冲突或者写写冲突(没有读读冲突,两个端口完全可以同时都读到正确的数据)。在实际的应用中,我们一般是用逻辑设计来尽量避免这种冲突行为,以免引入BUG。
关于冲突行为,可以看下下面两个表的处理结果,其中:


RAM IP核可以设置有寄存器输出和无寄存器输出,下图是RAM IP核的框图结构:

下图是有寄存器输出和无寄存器输出,可以达到的最高时钟频率的数据表。可以看到增加输出寄存器可以提高最高时钟频率,但是相应的,也会增加输出延迟(latency)。

除了BRAM自带的寄存器和IP核配置的可选输出寄存器外,IP核还配置了可选的流水线输出。
这是因为大容量的RAM往往是由多个BRAM组成,而多个BRAM则势必会有多个MUX来控制选择对应地址下由哪个BRAM进行输出。MUX作为一个组合逻辑器件,无疑会增加输出路径上的组合逻辑延时,为了改善时序,IP核配备了0~3个可选的流水线性质的寄存器输出如下:

需要注意的是只有当core output register被勾选的时候,才能选择这个属性。而且虽然会改善时序,但是同样的会增加输出延迟(latency),所以一般建议只在BRAM的这几条路径是关键路径(critical path)的时候才视需要而使用。
在2.7节中提到,对于IP核的输出我们可以选择配置一个寄存器来改善时序,同样的我们还可以对这个寄存器的控制信号进行配置来实现对IP核输出的更灵活控制。
(1)可选时钟使能信号(clock enable,CE)
默认情况下,输出寄存器的控制是由使能信号en控制,但是也可以选择激活各个端口的输出寄存器的时钟使能信号CE,达到控制数据路径最后一环输出寄存器的时钟信号,从而独立于en信号来控制整个IP核的输出。

上图是使用寄存器的时钟使能信号来控制输出寄存器从而控制输出流的例子:
(2)可选的复位/置位信号(set/reset)
通过配置复位/置位信号,可以完成对RAM的复位和置位。这个置位信号一般是连接到最后一级的输出寄存器(实际上就是控制输出寄存器的复位/置位);如果没有使能输出寄存器,则控制倒数第二级的LATCH(实际上就是控制LATCH的复位/置位)。

上图是使用复位来控制输出寄存器从而控制输出流的例子:
(3)输出读出的延迟(latency)
在组合逻辑延迟高的路径中插入寄存器可以有效的改善时序,同时也会增加数据输出的延迟,各延迟情况如下:

如果您定制IP的时候,选择了输出寄存器、输出寄存器的时钟使能CE和寄存器的复位/置位SR的话,就可以通过选择CE或者SR来设定复位的优先级了。
(1)CE高优先级
当选择CE的优先级高于SR,其波形如下:

在上图中波形:
(2)SR高优先级
当选择SR的优先级高于CE,其波形如下:

在上图中波形:
参考资料1:Block Memory Generator v8.4
参考资料2:7Series_Memory_Resources
参考资料3:Vivado Design Suite 7 Series FPGA and Zynq-7000 SoC Libraries Guide
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano
我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use
对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最