前言
有了上一篇博文:https://www.ebaina.com/articles/140000012562的铺垫,我们就清晰地了解了触发器的异步与同步之分。
上篇博文的最后,我们提到了要进去逻辑综合这一步去看看FPGA更真实的资源去实现我们想要的逻辑功能,但这还不是最终的FPGA实现,最能说明FPGA实际情况的阶段还是实现(implementation)这一步。本篇博客,我们暂时不深入去implementation,仅综合这一步,其实也就能看出FPGA的资源使用情况了。
本文针对特定FPGA的综合库,来讨论设计中考虑什么能够让我们的设计更加的合理,同时认识到,我们的设计是如何对应到综合资源上的,对实际设计有一定的参考意义。
逻辑综合资源讨论
简单的逻辑在赛灵思FPGA中使用查找表(LUT)和逻辑 “Slice “内的触发器来实现,这些 “slice “包含在可配置逻辑块(CLB)中。即使像XC3S50这样的小型器件也有1500多个LUT和触发器对。然而,当涉及到在实际设计中使用这些对时,有句话说得太对了,那就是照顾好一分钱,英镑就会照顾好自己。
如下图所示4输入的lut:
LUT可以实现四个输入的任何功能,不管需要多少个门来描述它。LUT的输出直接进入触发器的D输入。这样组合起来的设计将是小型和高性能的。
下面的RTL描述的逻辑可以使用上面的设计来实现:
VHDL描述:
process (clk) begin if clk’event and clk=’1’ then data_out <= a and b and c and d; end if; end process;Verilog描述
always @(posedge clk) begin data_out <= a & b & c & d; end如果有更多的输入呢?
只要一个函数有四个以上的输入,综合工具就别无选择,只能以某种方式在两个或多个LUT之间分割逻辑。图2显示了一个六输入的AND门最可能的实现方式,不管是什么语言或综合工具。
注意这个函数的成本是单级逻辑的两倍。只要函数不能装入一个LUT,就必须使用两个LUT。我们还可以看到对性能的重大影响。通过额外的LUT会产生延迟,连接函数的 “线 “同时增加了更多的延迟,这对建立时间的整体影响可能是很大的。当然,这也是时间规格和布局布线(PAR)工具在保持网络延迟在限制范围内发挥的作用;然而,避免这种情况显然会使设计更快、更小。
下面尝试添加复位端口:
当在设计中添加控制时,设计者经常包括一个全局复位。这种复位在仿真中特别受欢迎。然而,由于Xilinx FPGA在配置(Configuration)后已经在一个已知的状态下启动,全局复位确实没有必要。下面的VHDL和V erilog例子显示了如何实现全局复位。 VHDL描述:
process (clk, reset) begin if reset=‘1’ then data_out <= ‘0’; elsif clk’event and clk=’1’ then data_out <= a and b and c and d; end if; end process;Verilog描述:
always @(posedge clk or posedge reset) begin if (reset) begin data_out <= 1’b0; end else begin data_out <= a & b & c & d; end每个触发器都有一组专用控制输入,以支持置位、复位和时钟使能控制。显然,综合工具应该足够明智,在可以使用这些输入时,意味着LUT被保留给我们试图控制的实际功能。如下图所示,触发器的异步清零(CLR)输入已被使用,这意味着仍有一个最佳的单级逻辑。
综合工具使用了触发器的异步复位端,就可以使得LUT的输入恰好是4输入的,对于最大只有4输入的FPGA来说,可以在一个lut中就实现这个4输入的电路,不用浪费更多的资源。
我们尝试添加更多的控制。
下面展示了一些类似于实际设计中必须包含的额外控制。下面的代码具有相同的四输入功能,但触发器需要复位、置位和时钟使能的控制。
VHDL描述:
process (clk,reset) begin if reset=’1’ then data_out <= ’0’; elsif clk’event and clk=’1’ then if enable=’1’ then if force_high=’1’ then data_out <= ’1’; else data_out <= a and b and c and d; end if; end if; end if; end process;Verilog描述:
always@(posedge clk or posedge reset) begin if(reset) begin data_out <= 0; end else if(enable) begin if(force_high) begin data_out <= 1; end else begin data_out <= a&b&c&d; end end else begin data_out <= data_out; end end看看赛灵思合成工具(XST)是如何处理这段代码的。为什么它没有直接在触发器上使用控制,从而使我们的单级逻辑变成了双级逻辑,而且成本和性能都降低了?
综合工具已经尽其所能。问题的原因是代码,它所描述的东西在逻辑片中直接实现是不自然的。代码可能描述了设计者希望它做的事情,但综合工具被迫使用它的可用资源来模拟该功能。这就像用刀刃来拧紧一个松动的螺丝:它可能会完成工作,但螺丝和刀会被损坏,而且执行这个操作的人也会有一定的危险!
触发器可以支持异步和同步的复位和置位控制。但是,它们不能在同一个触发器上支持异步和同步控制的混合。因此,综合工具必须在具有SET和RST控制的同步触发器或具有PRE和CLR控制的异步触发器之间进行选择。异步复位总是优先考虑并强制选择。
异步复位让我们回到了全局复位的问题上。很多时候,全局复位被定义为异步的。看看你的代码,验证它是否是异步的。前面的例子同时使用了置位和复位控制,这可能不是很常见;然而,也有这样的情况:同一个触发器有两个复位条件。一个是全局复位,在编码方式中你默认有全局复位,第二个是出于操作目的所需的局部复位(即一个BCD计数器,在9之后必须翻转到0)。如果全局复位是异步的,那么局部同步复位必须用LUT来模拟,有可能以两倍的成本和较低的性能强制执行两级逻辑。
如果你仍然坚持要有一个全局复位(除非上面反对的理由说服了你),那就试试同样的例子,用一个同步复位来看看是否能让事情变得更好。
VHDL描述
process (clk) begin if clk’event and clk=’1’ then if reset=’1’ then data_out <= ’0’; else if enable=’1’ then if force_high=’1’ then data_out <= ’1’; else data_out <= a and b and c and d; end if; end if; end if; end if; end process;Verilog描述:
always@(posedge clk) begin if(reset) begin data_out <= 0; end else if(enable) begin if(force_high) begin data_out <= 1; end else begin data_out <= a&b&c&d; end end else begin data_out <= data_out; end end下图显示了XST对同步代码的处理情况。同样,看起来工具浪费了触发器上的专用SET控制,并在逻辑中实现了这个控制。结果又是两级逻辑,成本增加了一倍,性能降低了
同样,XST已经做了它可能做的最好的事情。代码要求综合工具实现一些不自然的东西,而XST被迫模仿描述的东西。
成功实现的关键是了解触发器的工作方式。尽管FPGA作为一个整体是可编程的,但每个低级特征实际上是固定的。可编程性来自于决定是否使用该特性的能力。想象一下,你要使用一个离散的器件。在使用它之前,你必须研究数据表,看看连接和控制是如何工作的。研究一下表1吧。不管这个器件是什么,它的输入和输出都与一个触发器一致。
表1显示,具有最高优先级的R输入,将在C的上升沿复位Q输出,只有当R输入为低电平时,才能发生其他事情。请注意,S的优先级次之,迫使Q输出为高电平。最后,CE输入必须是高电平,Q输出才会跟随D输入。这并不是什么火箭科学,但下面的信息可能会让人有点吃惊。
表1取自在线Libraries Guide,该指南与ISE™软件工具一起提供,来自描述被称为FDRSE的触发器的页面。这个名字从左到右读起来更有意义。
FPGA内部的所有触发器都有这些相同的控制,尽管异步触发器被称为FDCPE以反映异步清零和预置控制。当使用一个以上的控制时,每个控制都遵循它被分配的优先级。在 “同步设计 “中的VHDL代码例子中,enable的优先级高于set,这不符合专用控制所支持的顺序。综合工具通过使用顺序正确的专用控件和一些LUT逻辑的组合来解决这个问题,以模拟正在描述的触发器的其余部分。
当我们连接外部元件时,我们都非常清楚控制和它们的优先级。原理图设计者也非常清楚FPGA内部触发器的控制优先级,仅仅是因为他们从库中手动选择触发器,然后必须遵循优先级规则,使元件在电路中工作。在编写更高抽象水平的HDL代码时,这些方面很容易被忽略。幸运的是,由于所有的触发器组件都是一样的,一旦我们知道了它们的简单规则,就可以比较容易地编写出与它们的工作方式相适应的通用代码,如以下代码所示。
VHDL描述:
process (clk) begin if clk’event and clk=’1’ then if reset=’1’ then data_out <= ’0’; else if force_high=’1’ then data_out <= ’1’; else if enable=’1’ then data_out <= a and b and c and d; end if; end if; end if; end if; end process;Verilog描述:
always@(posedge clk ) begin if(reset) begin data_out <= 0; end else if(force_high) begin data_out <= 1; end else if(enable) begin data_out <= a&b&c&d; end else begin data_out <= data_out; end end结论
看看你为最近的设计所写的HDL代码,观察你的优先级是否正确。有多少次你有一个异步复位,阻止任何后续的同步复位或置位直接在触发器上实现?有多少次你看到一个优先级高于同步复位的使能?并非所有这些问题都会迫使另一层逻辑的出现,但潜力肯定存在。如果你的设计是有效的,就不要改变它! 记住这句话,如果它没有坏,就不要修。对于你的下一个设计,只要想想你是如何写代码的,你就会发现有很多方法既能减少尺寸又能加快你的设计速度。
免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:FPGA的设计艺术(29)FPGA中的逻辑综合资源讨论 https://www.yhzz.com.cn/a/12350.html