【FPGA】正确处理设计优先级--或许能帮你节省50%的资源

概述
假如现在有一种方法–可以在不怎么需要修改已有设计的情况下,就可以帮您节省50%的设计资源,那你会试试看吗?

当前市场环境下,更低廉的成本却可获得同等性能无疑是极具诱惑的。本文将介绍一种FPGA设计技术,该技术可以改变 FPGA 设计的规模大小和使用性能。

单级逻辑
你可以在Xilinx的FPGA 中使用可配置逻辑块CLB中的查找表LUT和触发器DFF来实现简单的逻辑函数。LUT4 可以实现4个输入的任何功能–不管这个功能需要多少门来描述。LUT4的输出直接连接到触发器DFF的D输入端,从而实现时序逻辑。

这张图片对应的Verilog代码(使用一个与门来实现4输入逻辑函数):

always @(posedge clk) begin
data_out <= a & b & c & d; //4输入与门
end

两级逻辑
同样的与门,一旦其有了4个以上的输入,那么综合工具就只能将逻辑拆分到在2个或多个LUT4里面了。下图使用了2个LUT4+DFF来实现6输入的与门。它对应的Verilog代码:

always @(posedge clk) begin
data_out <= a & b & c & d & e & f; //6输入与门
end

可以看到,这个6输入与门的使用的资源是4输入与门的两倍。同时,它的逻辑级数也从1变成了2(1个LUT到2个LUT),这会额外增加布线延迟和门电路延迟,导致该设计的时序性能一定程度的下降。

增加复位信号
设计师通常会在设计中加入一个全局复位信号(global reset)。这个复位信号在仿真中很有用,但是由于 Xilinx的FPGA 在上电配置后会以已知状态启动,因此在实际使用完全没必要使用全局复位。下面的Verilog代码展示了如何实现全局异步复位:

always @(posedge clk or posedge reset) begin
if (reset) begin
data_out <= 1’b0; //全局复位
end
else begin
data_out <= a & b & c & d; //4输入与门
end
end

每个触发器DFF都有一组专用的控制信号–设置信号set、复位信号reset和时钟使能信号clock enable。如下图所示,触发器使用了异步复位CLR信号。

增加更多控制信号
下面的代码也是4输入的与门,但是增加了复位信号reset、置位信号set和时钟使能控制信号ce:

always @(posedge clk or posedge reset) begin
if (reset) //异步复位有效
data_out <= 1’b0;
else if(ce)begin //时钟使能有效
if(set) //置位有效
data_out <= 1’b1;
else //置位无效
data_out <= a & b & c & d; //4输入与门
end
end

下图展示了综合工具是怎样综合这段代码的:

奇怪的是,4输入的与门居然使用了2个LUT4来实现!而且代码中的set信号综合出来并没有出现在DFF的PRE端!

这真的不能怪综合工具,它已经尽力了。该怪的是代码,因为它描述的功能无法在只用DFF的情况下就实现,综合工具被迫使用多余的资源来实现这个预期设计。

触发器DFF支持异步复位、同步复位、异步置位和同步置位。但是,在同一触发器上不能混合使用异步控制信号和同步控制信号。因此,综合工具必须在具有SET和RST控制的同步触发器或具有PRE和CLR控制的异步触发器之间进行选择。

通常情况下,全局复位是一个异步信号。前面的示例同时使用了set和reset信号,这可能并不常见。但是在某些情况下,同一触发器可能会有两个复位条件。一种是全局复位;还有一种是操作目的所需的局部复位(例如BCD 计数器必须在计数到9之后重新跳到0)。

如果全局复位是异步的,则必须使用LUT来模拟局部的同步复位,这可能会以两倍的成本和更低的性能强制执行两级逻辑。如果你仍然坚持要使用全局复位,那么请尝试使用同步复位信号。

解决问题的关键在于了解触发器的工作方式。虽然FPGA作为一个整体是可编程的,但是底层单元的功能实际上却是固定的。

假如你将使用一个电子器件,那么在使用它之前,你必须研究它的datasheet以了解它的工作原理和工作方式。下表的输入和输出都与触发器一致。

1. R信号的优先级是最高的,它可以在C信号的上升沿将输出Q复位。
2. S信号具有次高的优先级,它可以在C信号的上升沿将输出Q置位。
3. CE信号的优先级最低,当它为高电平时,输出Q的变化跟随输入D。

这种器件实际上就是xilinx的FPGA中的触发器FDRSE:

FPGA内部的所有同步触发器都具有相同的控制集,而异步触发器则被称为FDCPE,它有异步复位信号CLR和预置位信号PRE。 当多个控制信号同时被使用时,每个信号都会遵循已定义好的优先级顺序。

在上面的示例中,由于设计中的时钟使能信号ce的优先级高于置位信号set,这违反了定义的优先级顺序(reset>set>ce),所以综合工具只能使用多余的资源来实现这一功能,这就是为什么会多出来一个LUT的原因。

当我们使用外部器件时,都非常清楚控制信号的优先级,但在编写 HDL 代码时,这却很容易被忽视。幸运的是,由于所有触发器的内部结构都是相同的,一旦我们知道了它们的优先级规则,那编写符合它们工作方式的代码就很容易了。比如上面的代码就可以做如下修改:

always @(posedge clk) begin
if (reset) //同步复位有效
data_out <= 1’b0;
else if(set) //置位有效
data_out <= 1’b1;
else if(ce) //时钟使能有效
data_out <= a & b & c & d; //4输入与门
end

现在,综合工具终于可以正确地综合出我们的预期电路了:

总结
总有一些情况需要打破优先级规则----这就是可编程逻辑的意义所在。但是,如果你能够学会将这些情况视为例外,并编写与优先级相符的代码,那么结果将大有裨益。如果你可以删除不必要的全局异步复位信号,那么每次设计时都需要担心的优先级就会减少一个。

这篇文章是Xilinx的白皮书《wp275,Get your Priorities Right – Make your Design Up to 50% Smaller》的内容,该文发布时间是2007年,当时的DFF结构与当下(2023年)的Xilinx 7系列FPGA架构的DFF结构有很大不一样。

现在的DFF并不会同时有set和reset这两个端口,如下所示,所以也就不存在set和reset这两个信号的优先级问题了。

当前的FPGA设计中,Xilinx是不鼓励用户同时使用set和reset这两个信号的,因为这种情况一定会造成面积浪费和性能下降。

最新文章

最新文章