FPGA 的布局规划艺术
FPGA 的布局规划艺术
布局规划是为设计增加布局布线约束的过程。一个大型高速设计的布局规划是实现时序收敛的关键。好的布局规划可以大大提高设计性能,并确保设计结果的质量。差的布局规划具有相反的效果,使其无法满足时序约束,并导致设计结果与预期不符。
有效的FPGA布局规划是一项要在实践中获得的技能。它需要优秀的设计知识和对性能目标、工具选择、FPGA结构和功能的深刻理解,以及基于时序分析结果必要的代码修改和设计约束能力。
布局规划能让设计者直接观察到设计综合后产生的结果适配到了FPGA器件的哪些地方,在ASIC领域这是一项专业化工程。有一个或多个工程师专门从事大的芯片的布局规划。相对来说,FPGA的布局规划简单得多,它通常由一个工程师设计完成。
布局规划不仅为大型、高利用、高速的设计所采用,小型的设计也采用布局规划。小型设计的布局规划可以简单到就指定一个布局约束。即使有的设计时钟频率低,并且满足时序,往往也需要工程师来做布局规划。
布局规划是与时序收敛、一定程度上又与逻辑设计紧密联系在一起的任务。建议在设计周期的早期开始准备。例如,布局规划的考虑在模块化设计过程中具有一定的份量。
Xilinx Plan Ahead是一个用于布局规划的主流工具。高级用户可以将布局约束直接添加到设计约束文件中,从而进行手动布局规划。Plan Ahead还支持自动布局规划。然而,经验表明,大型设计使用手动布局规划能产生更好的效果。
FPGA布局规划流程
FPGA设计布局规划一般包括如图1所示的步骤。
IO分配
FPGA设计中需要进行IO分配。锁定设计的所有IO是确定任何其他布局布线约束前的第一个需要完成的任务。如果不这样做可能会导致结果不够理想,同时也浪费时间。之后IO可能需要根据布局规划的改变而改变。
布局规划锚桩模块
所有IO分配完成后,下一步是布局规划所有的锚桩模块。这些模块的位置是不能改变的,如连接到IO的模块、与嵌入式FPGA元件接口的用户逻辑模块(如PCI Express接口)、以太网MAC或收发器。很多如复位控制器、存储器控制器、CPU这样的模块都可在FPGA芯片中心的附近布局。
布局规划剩余模块
对设计中其他模块的布局规划是增加布局布线约束、进行设计、分析时序报告、做出必要调整的迭代过程,一直要到时序收敛时才停止。这是花费时间最长的步骤,大型的高速设计需要花费几周时间。在此过程中,设计者可能需要更改现有的布局规划:布局规划区域的移动、增加或减少它们的面积,或在较低层对模块进行布局规划以改善间隔大小。
锁定核心元件
为保存结果,当设计满足时序要求且预计没有重大的设计变更时,建议锁定所有的BRAM、DSP和时钟管理模块,主要是为了改善后面设计中的一致性和运行时间。
布局规划微调
一些小的布局规划微调可能会发生在设计的后期,主要是由于时序约束的变化、提高或降低逻辑利用而增加的新特征或修复缺陷。
布局布线约束
布局布线约束作为输人提供给物理实现工具。Xilinx的物理实现工具使用专用用户约束文件(UCF\XDC)格式。下面的例子是最常用的布局布线约束语法。
//-----------------------------------------------------------------------------
// Copyright (C) 2011 OutputLogic.com
// This source file may be used and distributed without restriction
// provided that this copyright statement is not removed from the file
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//-----------------------------------------------------------------------------
`timescale 1ns / 100psmodule constraints(input clk, reset,output reg data_out_0,data_out_1);always @(posedge clk) beginif (reset) begindata_out_0 <= 1'b0;data_out_1 <= 1'b0;endelse begindata_out_0 <= ~data_out_0;data_out_1 <= ~data_out_1;endend // always endmodule // constraints
布局布线约束
NET "data_out_0" LOC = P16;
NET "data_out_1" LOC = D6; INST "data_out_0" AREA_GROUP = "data_out_0";
AREA_GROUP "data_out_0" RANGE=SLICE_X44Y40:SLICE_X45Y42;
AREA_GROUP "data_out_0" GROUP=CLOSED;
AREA_GROUP "data_out_0" PLACE=CLOSED;CONFIG PROHIBIT=SLICE_X06Y0:X14Y20;
CONFIG PROHIBIT=P15;NET "data_out_1_OBUF"
ROUTE="{3;1;6slx25csg324;477afbc1!-1;8040;6064;S!0;-845;-504!1;0;344!1;"
"-9743;1431!2;845;144;L!3;-16261;1!5;-22484;-4!6;-17991;3!7;-12477;5681!8;"
"0;12800!9;0;12800!10;0;12800!11;0;13872!12;0;12800!13;0;12800!14;0;12800!"
"15;0;13872!16;305;7589!17;0;3200!18;1855;1675!19;686;18!20;80;20!21;"
"-1490;2207!22;-1311;251;L!}";
NET "data_out_1" LOC=D6;
INST "data_out_1_OBUF" LOC=SLICE_X29Y41;
INST "data_out_1" LOC=SLICE_X29Y41;
AREA_GROUP约束
AREA_GROUP用于布局约束一组FPGA资源,如逻辑片、BRAM、DSP、MMCM等。它允许布局约束在FPGA的特定范围的区域内。AREA_GROUP的基本语法如下例所示。
INST "data_out_0" AREA_GROUP = "ag_data_out_0";
AREA_GROUP "ag_data_out_O" RANGE=SLICE_X44Y40:SLICE_X45Y42;
AREA_GROUP "ag_data_out_O" GROUP=CLOSED;
AREA_GROUP "ag_data_out_O" PLACE=CLOSED;
这个例子定义了一个名为“ag_data_out_0”的组,将寄存器data_out_0约束到逻辑片范围SLICE_X44Y40~SLICE_X45Y42。该组里的GROUP和PLACE属性确定组里的逻辑是否与组外逻辑相结合。使用GROUP和PLACE属性可提高编译的一致性,但由于仍闲置了一些逻辑资源未用,因此逻辑利用将更高。
定向布线约束
布线约束具有锁定特定路线的能力,只适用于少数高速布线场合。使用定向布线的一个例子是在存储器控制器中锁定与10引脚接口的布线,以控制延迟。详细布线约束的语法未有文档介绍。需要时使用FPGA编辑器来产生约束,具体方法是选择一个线网(net)信号,然后在Tools->Directed Routing Constraints dialog中选择合适的选项。
PROHIBIT约束
PROHIBIT约束不允许布局布线工具使用特定的FPGA资源,如逻辑片、BRAM、DSP、IO等。下面是禁止使用特定的IO引脚和一系列逻辑片的例子。
CONFIG PROHIBIT=SLICE_X06Y0:X14Y20;
CONFIG PR0HIBIT=P15;
PROHIBIT约束对于保留特定的逻辑区以供将来使用是非常必要的,对于简单的设计来说,它与AREA_GR0UP约束相反。
保存线网标号
保存线网标号(S)可以约束某些线网或信号不被移除,它用于设计的初始阶段,以防止未连接的模块输人和无负载的输出被移除。下面的例子中给出了其语法。
NET "data_out_1" S;
位置约束
L0C是将特定元件放人FPGA中的位置约束。例如在每一个设计中几乎都会使用IO的位置。
NET "data_out_0" LOC=16;
了解布线延迟
了解布线延迟是进行有效布局规划的一部分。布线延迟与FPGA系列和速度等级有关,还取决于资源在FPGA芯片上的布局方式。Xilinx的FPGA Virtex-6和Spartan-6具有柱状结构:IO、BRAM和DSP块组织成柱状。逻辑资源具有类似“瓷砖”的结构,在水平和垂直方向排列成网格。FPGA也可以包含无任何逻辑资源的区域,或者只包含一个大的嵌入式块,如PCI Express接口核。所有这些都可能影响到布线的信号延迟。
下面的例子用以说明最坏情况下的布线延迟。
//-----------------------------------------------------------------------------
// Copyright (C) 2011 OutputLogic.com
// This source file may be used and distributed without restriction
// provided that this copyright statement is not removed from the file
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//-----------------------------------------------------------------------------
`timescale 1ns / 100psmodule routing(input data_in_0,data_in_1,data_in_2,data_in_3,output data_out_0,data_out_1,data_out_2,data_out_3 );assign data_out_0 = data_in_0; // horizontal route 水平布线assign data_out_1 = data_in_1; // vertical route 垂直布线assign data_out_2 = data_in_2; // diagonal route 对角布线assign data_out_3 = data_in_3; // routing around 环绕布线
endmodule // routing
IO布局
NET "data_in_0" LOC = N3;
NET "data_out_0" LOC = P16; NET "data_in_1" LOC = P6;
NET "data_out_1" LOC = D6; NET "data_in_2" LOC = V3;
NET "data_out_2" LOC = B16; NET "data_in_3" LOC = C7;
NET "data_out_3" LOC = A8; // 04/13 @ 20:40:41
NET "data_out_0_OBUF"
ROUTE="{3;1;6slx25csg324;87fbbdf3!-1;-88976;-116360;S!0;2563;-1309!1;"
"2169;661!2;37;24!3;-12;78!4;-162;-218!5;-524;4!6;11804;-916!7;25940;4!8;"
"16261;-1!9;17991;-3!10;23160;4!11;16937;-1!12;18683;1!13;21792;0!14;"
"16860;156!15;488;-28!16;-3812;1064!17;686;-386!18;80;20!19;3880;-482!20;"
"4523;836;L!}";
该设计用于Spartan6 LX25FPGA该器件有一个不包含逻辑资源的区域,有一个信号被布线在这一区域周围。图2是在FPGA编辑器中看到的布线。
FPGA编辑器报告以下布线延迟:
# 水 平 布 线
net "data_out_0_OBUF":7.267ns - comp.pin "data_out_0.O", site.pin "P16.O"driver - comp.pin "data_in_0.I", site.pin "N3.I"net "data_out_1_0BUF"
net "data_out_2_OBUF"# 垂 直 布 线
net "data_out_1_OBUF":9.957ns - comp.pin "data_out_1.O", site.pin "D6.O"driver - comp.pin "data_in_1.I", site.pin "P6.I"net "data_out_3_0BUF"# 对 角 布 线
net "data_out_2_OBUF":13.725ns - comp.pin "data_out_2.O", site.pin "B16.O"driver - comp.pin "data_in_2.I", site.pin "V3.I"# 环 绕 布 线
net "data_out_3_OBUF":9.968ns - comp.pin "data_out_3.O", site.pin "A8.O"driver - comp.pin "data_in_3.I", site.pin "C7.I"net "data_out_0_0BUF"
在上面的例子中,布线延迟范围从7.267ns到13.724ns。例如,如果设计中采用了200MHz的时钟,某个布线延迟会超过时钟周期。如果这样的设计与两个模块相连接,并被布局在FPGA的不同角落,将不可能满足时序约束。复位控制器工作在200MHz,为设计的其余部分提供同步复位信号,即使布局在FPGA芯片的中间位置,也可能在满足时序上岀现问题。
穿过FPGA的“瓷砖”
由于信号穿越FPGA的“瓷砖”(tile)增加了布线延迟,因此降低了性能。下面举例进行说明,其中包含了4个16位的CRC32校验模块实例,彼此完全独立。每个实例有单独的数据、使能、时钟输人和输出。实例以这样一种方式布局:每个区域的面积都完全相同,但布局不同。区域大小的选择要使得每个实例的逻辑利用率大约是70%左右。此外,所有区域都是封闭的,它们只包含属于相应实例的逻辑。
以下是顶层模块的代码。
//-----------------------------------------------------------------------------
// Copyright (C) 2011 OutputLogic.com
// This source file may be used and distributed without restriction
// provided that this copyright statement is not removed from the file
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//-----------------------------------------------------------------------------
module crc_floorplan(input clk1,clk2,clk3,clk4,input crc_en1,crc_en2,crc_en3,crc_en4,input rst, input [15:0] data_in,output reg [31:0] crc_out1, crc_out2, crc_out3, crc_out4); wire [31:0] crc_out1_i, crc_out2_i, crc_out3_i, crc_out4_i;reg crc_en1_q, crc_en2_q, crc_en3_q, crc_en4_q;reg [15:0] data_in1_q, data_in2_q, data_in3_q, data_in4_q;// add register stage to inputs and outputsalways @(posedge clk1, posedge rst) beginif(rst) begincrc_out1 <= 32'h0;data_in1_q <= 16'h0;crc_en1_q <= 1'b0;endelse begincrc_out1 <= crc_out1_i;data_in1_q <= data_in;crc_en1_q <= crc_en1;endend // alwaysalways @(posedge clk2, posedge rst) beginif(rst) begincrc_out2 <= 32'h0;data_in2_q <= 16'h0;crc_en2_q <= 1'b0;endelse begincrc_out2 <= crc_out2_i;data_in2_q <= data_in;crc_en2_q <= crc_en2;endend // alwaysalways @(posedge clk3, posedge rst) beginif(rst) begincrc_out3 <= 32'h0;data_in3_q <= 16'h0;crc_en3_q <= 1'b0;endelse begincrc_out3 <= crc_out3_i;data_in3_q <= data_in;crc_en3_q <= crc_en3;endend // alwaysalways @(posedge clk4, posedge rst) beginif(rst) begincrc_out4 <= 32'h0;data_in4_q <= 16'h0;crc_en4_q <= 1'b0;endelse begincrc_out4 <= crc_out4_i;data_in4_q <= data_in;crc_en4_q <= crc_en4;endend // alwayscrc crc1 ( .data_in_i(data_in1_q), .crc_en_i(crc_en1_q), .crc_out(crc_out1_i), .rst(rst), .clk(clk1));crc crc2 ( .data_in_i(data_in2_q), .crc_en_i(crc_en2_q), .crc_out(crc_out2_i), .rst(rst), .clk(clk2));crc crc3 ( .data_in_i(data_in3_q), .crc_en_i(crc_en3_q), .crc_out(crc_out3_i), .rst(rst), .clk(clk3));crc crc4 ( .data_in_i(data_in4_q), .crc_en_i(crc_en4_q), .crc_out(crc_out4_i), .rst(rst), .clk(clk4));endmodule // crc_floorplan// crc32 for Ethernet
module crc(input [15:0] data_in_i,input crc_en_i,output reg [31:0] crc_out,input rst,input clk);reg [31:0] lfsr_q,lfsr_c;reg [15:0] data_in;reg crc_en;always @(*) beginlfsr_c[0] = lfsr_q[16] ^ lfsr_q[22] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[28] ^ data_in[0] ^ data_in[6] ^ data_in[9] ^ data_in[10] ^ data_in[12];lfsr_c[1] = lfsr_q[16] ^ lfsr_q[17] ^ lfsr_q[22] ^ lfsr_q[23] ^ lfsr_q[25] ^ lfsr_q[27] ^ lfsr_q[28] ^ lfsr_q[29] ^ data_in[0] ^ data_in[1] ^ data_in[6] ^ data_in[7] ^ data_in[9] ^ data_in[11] ^ data_in[12] ^ data_in[13];lfsr_c[2] = lfsr_q[16] ^ lfsr_q[17] ^ lfsr_q[18] ^ lfsr_q[22] ^ lfsr_q[23] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[29] ^ lfsr_q[30] ^ data_in[0] ^ data_in[1] ^ data_in[2] ^ data_in[6] ^ data_in[7] ^ data_in[8] ^ data_in[9] ^ data_in[13] ^ data_in[14];lfsr_c[3] = lfsr_q[17] ^ lfsr_q[18] ^ lfsr_q[19] ^ lfsr_q[23] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[30] ^ lfsr_q[31] ^ data_in[1] ^ data_in[2] ^ data_in[3] ^ data_in[7] ^ data_in[8] ^ data_in[9] ^ data_in[10] ^ data_in[14] ^ data_in[15];lfsr_c[4] = lfsr_q[16] ^ lfsr_q[18] ^ lfsr_q[19] ^ lfsr_q[20] ^ lfsr_q[22] ^ lfsr_q[24] ^ lfsr_q[27] ^ lfsr_q[28] ^ lfsr_q[31] ^ data_in[0] ^ data_in[2] ^ data_in[3] ^ data_in[4] ^ data_in[6] ^ data_in[8] ^ data_in[11] ^ data_in[12] ^ data_in[15];lfsr_c[5] = lfsr_q[16] ^ lfsr_q[17] ^ lfsr_q[19] ^ lfsr_q[20] ^ lfsr_q[21] ^ lfsr_q[22] ^ lfsr_q[23] ^ lfsr_q[26] ^ lfsr_q[29] ^ data_in[0] ^ data_in[1] ^ data_in[3] ^ data_in[4] ^ data_in[5] ^ data_in[6] ^ data_in[7] ^ data_in[10] ^ data_in[13];lfsr_c[6] = lfsr_q[17] ^ lfsr_q[18] ^ lfsr_q[20] ^ lfsr_q[21] ^ lfsr_q[22] ^ lfsr_q[23] ^ lfsr_q[24] ^ lfsr_q[27] ^ lfsr_q[30] ^ data_in[1] ^ data_in[2] ^ data_in[4] ^ data_in[5] ^ data_in[6] ^ data_in[7] ^ data_in[8] ^ data_in[11] ^ data_in[14];lfsr_c[7] = lfsr_q[16] ^ lfsr_q[18] ^ lfsr_q[19] ^ lfsr_q[21] ^ lfsr_q[23] ^ lfsr_q[24] ^ lfsr_q[26] ^ lfsr_q[31] ^ data_in[0] ^ data_in[2] ^ data_in[3] ^ data_in[5] ^ data_in[7] ^ data_in[8] ^ data_in[10] ^ data_in[15];lfsr_c[8] = lfsr_q[16] ^ lfsr_q[17] ^ lfsr_q[19] ^ lfsr_q[20] ^ lfsr_q[24] ^ lfsr_q[26] ^ lfsr_q[27] ^ lfsr_q[28] ^ data_in[0] ^ data_in[1] ^ data_in[3] ^ data_in[4] ^ data_in[8] ^ data_in[10] ^ data_in[11] ^ data_in[12];lfsr_c[9] = lfsr_q[17] ^ lfsr_q[18] ^ lfsr_q[20] ^ lfsr_q[21] ^ lfsr_q[25] ^ lfsr_q[27] ^ lfsr_q[28] ^ lfsr_q[29] ^ data_in[1] ^ data_in[2] ^ data_in[4] ^ data_in[5] ^ data_in[9] ^ data_in[11] ^ data_in[12] ^ data_in[13];lfsr_c[10] = lfsr_q[16] ^ lfsr_q[18] ^ lfsr_q[19] ^ lfsr_q[21] ^ lfsr_q[25] ^ lfsr_q[29] ^ lfsr_q[30] ^ data_in[0] ^ data_in[2] ^ data_in[3] ^ data_in[5] ^ data_in[9] ^ data_in[13] ^ data_in[14];lfsr_c[11] = lfsr_q[16] ^ lfsr_q[17] ^ lfsr_q[19] ^ lfsr_q[20] ^ lfsr_q[25] ^ lfsr_q[28] ^ lfsr_q[30] ^ lfsr_q[31] ^ data_in[0] ^ data_in[1] ^ data_in[3] ^ data_in[4] ^ data_in[9] ^ data_in[12] ^ data_in[14] ^ data_in[15];lfsr_c[12] = lfsr_q[16] ^ lfsr_q[17] ^ lfsr_q[18] ^ lfsr_q[20] ^ lfsr_q[21] ^ lfsr_q[22] ^ lfsr_q[25] ^ lfsr_q[28] ^ lfsr_q[29] ^ lfsr_q[31] ^ data_in[0] ^ data_in[1] ^ data_in[2] ^ data_in[4] ^ data_in[5] ^ data_in[6] ^ data_in[9] ^ data_in[12] ^ data_in[13] ^ data_in[15];lfsr_c[13] = lfsr_q[17] ^ lfsr_q[18] ^ lfsr_q[19] ^ lfsr_q[21] ^ lfsr_q[22] ^ lfsr_q[23] ^ lfsr_q[26] ^ lfsr_q[29] ^ lfsr_q[30] ^ data_in[1] ^ data_in[2] ^ data_in[3] ^ data_in[5] ^ data_in[6] ^ data_in[7] ^ data_in[10] ^ data_in[13] ^ data_in[14];lfsr_c[14] = lfsr_q[18] ^ lfsr_q[19] ^ lfsr_q[20] ^ lfsr_q[22] ^ lfsr_q[23] ^ lfsr_q[24] ^ lfsr_q[27] ^ lfsr_q[30] ^ lfsr_q[31] ^ data_in[2] ^ data_in[3] ^ data_in[4] ^ data_in[6] ^ data_in[7] ^ data_in[8] ^ data_in[11] ^ data_in[14] ^ data_in[15];lfsr_c[15] = lfsr_q[19] ^ lfsr_q[20] ^ lfsr_q[21] ^ lfsr_q[23] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[28] ^ lfsr_q[31] ^ data_in[3] ^ data_in[4] ^ data_in[5] ^ data_in[7] ^ data_in[8] ^ data_in[9] ^ data_in[12] ^ data_in[15];lfsr_c[16] = lfsr_q[0] ^ lfsr_q[16] ^ lfsr_q[20] ^ lfsr_q[21] ^ lfsr_q[24] ^ lfsr_q[28] ^ lfsr_q[29] ^ data_in[0] ^ data_in[4] ^ data_in[5] ^ data_in[8] ^ data_in[12] ^ data_in[13];lfsr_c[17] = lfsr_q[1] ^ lfsr_q[17] ^ lfsr_q[21] ^ lfsr_q[22] ^ lfsr_q[25] ^ lfsr_q[29] ^ lfsr_q[30] ^ data_in[1] ^ data_in[5] ^ data_in[6] ^ data_in[9] ^ data_in[13] ^ data_in[14];lfsr_c[18] = lfsr_q[2] ^ lfsr_q[18] ^ lfsr_q[22] ^ lfsr_q[23] ^ lfsr_q[26] ^ lfsr_q[30] ^ lfsr_q[31] ^ data_in[2] ^ data_in[6] ^ data_in[7] ^ data_in[10] ^ data_in[14] ^ data_in[15];lfsr_c[19] = lfsr_q[3] ^ lfsr_q[19] ^ lfsr_q[23] ^ lfsr_q[24] ^ lfsr_q[27] ^ lfsr_q[31] ^ data_in[3] ^ data_in[7] ^ data_in[8] ^ data_in[11] ^ data_in[15];lfsr_c[20] = lfsr_q[4] ^ lfsr_q[20] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[28] ^ data_in[4] ^ data_in[8] ^ data_in[9] ^ data_in[12];lfsr_c[21] = lfsr_q[5] ^ lfsr_q[21] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[29] ^ data_in[5] ^ data_in[9] ^ data_in[10] ^ data_in[13];lfsr_c[22] = lfsr_q[6] ^ lfsr_q[16] ^ lfsr_q[25] ^ lfsr_q[27] ^ lfsr_q[28] ^ lfsr_q[30] ^ data_in[0] ^ data_in[9] ^ data_in[11] ^ data_in[12] ^ data_in[14];lfsr_c[23] = lfsr_q[7] ^ lfsr_q[16] ^ lfsr_q[17] ^ lfsr_q[22] ^ lfsr_q[25] ^ lfsr_q[29] ^ lfsr_q[31] ^ data_in[0] ^ data_in[1] ^ data_in[6] ^ data_in[9] ^ data_in[13] ^ data_in[15];lfsr_c[24] = lfsr_q[8] ^ lfsr_q[17] ^ lfsr_q[18] ^ lfsr_q[23] ^ lfsr_q[26] ^ lfsr_q[30] ^ data_in[1] ^ data_in[2] ^ data_in[7] ^ data_in[10] ^ data_in[14];lfsr_c[25] = lfsr_q[9] ^ lfsr_q[18] ^ lfsr_q[19] ^ lfsr_q[24] ^ lfsr_q[27] ^ lfsr_q[31] ^ data_in[2] ^ data_in[3] ^ data_in[8] ^ data_in[11] ^ data_in[15];lfsr_c[26] = lfsr_q[10] ^ lfsr_q[16] ^ lfsr_q[19] ^ lfsr_q[20] ^ lfsr_q[22] ^ lfsr_q[26] ^ data_in[0] ^ data_in[3] ^ data_in[4] ^ data_in[6] ^ data_in[10];lfsr_c[27] = lfsr_q[11] ^ lfsr_q[17] ^ lfsr_q[20] ^ lfsr_q[21] ^ lfsr_q[23] ^ lfsr_q[27] ^ data_in[1] ^ data_in[4] ^ data_in[5] ^ data_in[7] ^ data_in[11];lfsr_c[28] = lfsr_q[12] ^ lfsr_q[18] ^ lfsr_q[21] ^ lfsr_q[22] ^ lfsr_q[24] ^ lfsr_q[28] ^ data_in[2] ^ data_in[5] ^ data_in[6] ^ data_in[8] ^ data_in[12];lfsr_c[29] = lfsr_q[13] ^ lfsr_q[19] ^ lfsr_q[22] ^ lfsr_q[23] ^ lfsr_q[25] ^ lfsr_q[29] ^ data_in[3] ^ data_in[6] ^ data_in[7] ^ data_in[9] ^ data_in[13];lfsr_c[30] = lfsr_q[14] ^ lfsr_q[20] ^ lfsr_q[23] ^ lfsr_q[24] ^ lfsr_q[26] ^ lfsr_q[30] ^ data_in[4] ^ data_in[7] ^ data_in[8] ^ data_in[10] ^ data_in[14];lfsr_c[31] = lfsr_q[15] ^ lfsr_q[21] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[27] ^ lfsr_q[31] ^ data_in[5] ^ data_in[8] ^ data_in[9] ^ data_in[11] ^ data_in[15];end // alwaysalways @(posedge clk, posedge rst) beginif(rst) beginlfsr_q <= 32'hffffffff;crc_out <= 32'h0;data_in <= 16'h0;crc_en <= 1'b0;endelse beginlfsr_q <= crc_en ? lfsr_c : lfsr_q;crc_out <= lfsr_q;data_in <= data_in_i;crc_en <= crc_en_i;endend // always
endmodule // crc
面积和周期约束
NET "clk1" TNM_NET = "clk1";
TIMESPEC TS_clk1 = PERIOD "clk1" 3.33 ns HIGH 50 %;NET "clk2" TNM_NET = "clk2";
TIMESPEC TS_clk2 = PERIOD "clk2" 3.33 ns HIGH 50 %;NET "clk3" TNM_NET = "clk3";
TIMESPEC TS_clk3 = PERIOD "clk3" 3.33 ns HIGH 50 %;NET "clk4" TNM_NET = "clk4";
TIMESPEC TS_clk4 = PERIOD "clk4" 3.33 ns HIGH 50 %;INST "crc1*" AREA_GROUP = "crc1";
AREA_GROUP "crc1" RANGE=SLICE_X0Y47:SLICE_X3Y55;
AREA_GROUP "crc1" GROUP=CLOSED;
AREA_GROUP "crc1" PLACE=CLOSED;INST "crc2*" AREA_GROUP = "crc2";
AREA_GROUP "crc2" RANGE=SLICE_X0Y2:SLICE_X17Y3;
AREA_GROUP "crc2" GROUP=CLOSED;
AREA_GROUP "crc2" PLACE=CLOSED;INST "crc3*" AREA_GROUP = "crc3";
AREA_GROUP "crc3" RANGE=SLICE_X22Y3:SLICE_X23Y21;
AREA_GROUP "crc3" GROUP=CLOSED;
AREA_GROUP "crc3" PLACE=CLOSED;INST "crc4*" AREA_GROUP = "crc4";
AREA_GROUP "crc4" RANGE=SLICE_X2Y23:SLICE_X21Y24;
AREA_GROUP "crc4" GROUP=CLOSED;
AREA_GROUP "crc4" PLACE=CLOSED;
图 3 说明了 4 个实例是如何在 Spartan-6 LX9 FPGA 上布局规划的。
实例crcl仅被布局在一个“瓷砖”中。
实例CrC2被布局为包含几个水平“瓷砖”的细长矩形。
实例crc3被布局为包含几个垂直“瓷砖”的细长矩形。
实例crc4被布局为包含几个水平和垂直“瓷砖”的区域。
表1是4个实例的性能测试结果。
crcl的性能最好,crc2和crc3的性能非常类似,crc4的性能最差。这个例子通过精心挑选设计和布局约束,仅用于说明穿越“瓷砖”对性能的影响。大多数实际设计包含的模块都可以适配到一个“瓷砖”中。不过,通常建议布局规划时模块适配的“瓷砖”应尽可能少。
其他布局规划技巧
避免布局规划区域重叠。
使用AREA.GROUP约束的GROUP和PLACE属性,防止区外逻辑被布局到规划区里。
布局规划区域的逻辑利用率限制在75%以下。
对于流水线数据,布局规划水平走。
对于长进位链,布局规划纵向走。
对于布局规划区域边界上的模块,所有输入和输出都要寄存。
参考文献
[1] Xilinx Constraints User Guide
[2]FPGA高手设计实战100则真经
UltraScale时钟资源和时钟管理模块
Verilog数字系统基础设计-CRC
推荐阅读
【Vivado那些事】如何查找官网例程及如何使用官网例程
【Vivado使用误区与进阶】总结篇
【Vivado那些事】Vivado中常用的快捷键(二)其他常用快捷键
SystemVerilog数字系统设计_夏宇闻 PDF
图书推荐|ARM Cortex-M0 全可编程SoC原理及实现
简谈:如何学习FPGA
1202年了,还在使用虚拟机吗?Win10安装Ubuntu子系统及图形化界面详细教程
Github 上有哪些优秀的 VHDL/Verilog/FPGA 项目
AD936x+ZYNQ搭建收音机(一)
AD936x+ZYNQ搭建OpenWIFI
无招胜有招-Vivado非工程模式下的详细设计
追寻ARM的起源-Acorn电脑简史及FPGA实现
面试中经常会遇到的FPGA基本概念,你会几个?
Xilinx FPGA MIPI 接口简单说明
介绍一些新手入门FPGA的优秀网站
Vivado ML(机器学习) 2021尝鲜
推荐一些可以获取免费的国外的原版书籍(电子版)网站
【Vivado那些事】FPGA的配置方式
FPGA 的重构
浅析FPGA局部动态可重构技术
ISP(图像信号处理)算法概述、工作原理、架构、处理流程
国产CPU概括
从电子游戏历史看IC发展的助推剂
80年代电子游戏及电脑游戏的发展历史
PCIe总线的基础知识
万字长文带你回顾电子游戏的七十多年历史(完整版)
FPGA中异步复位,同步释放的理解
OpenFPGA系列文章总结
用Verilog设计一个16 位 RISC 处理器
介绍一些新手入门FPGA的优秀网站(新增)
Verilog数字系统基础设计-CRC
Verilog数字系统基础设计-扰码与解扰
FPGA 的布局规划艺术相关推荐
- 应用PlanAhead 进行布局规划
应用PlanAhead 进行布局规划 FloorPlanning 工具是PlanAhead 的一个组成部分,用它可以对FPGA 设计进行分析,首先找到设计中的时序问题或者拥塞的问题,然后再通过使用Pl ...
- 全球及中国生物质能利用产业现状调研及十四五建设布局规划报告2021-2027年
全球及中国生物质能利用产业现状调研及十四五建设布局规划报告2021-2027年 HS--HS--HS--HS--HS--HS--HS--HS--HS--HS--HS--HS-- [修订日期]:2021 ...
- ICC布局规划---1
ICC布局规划 写在前面的标注: 这里的流程参照guide,以及微信公众号:数字集成电路设计及EDA教程 首先,简单的介绍一下floorplan的重要性,在之前的我学完成,本人之前的学Encoun ...
- 全球及中国泵真空系统行业发展战略与十四五布局规划报告2022版
全球及中国泵真空系统行业发展战略与十四五布局规划报告2022版 --------------------------------------- [修订日期]:2021年12月 [搜索鸿晟信合研究院查看 ...
- endcap和welltap_ICC布局规划
写在前面的标注:这里的流程参照guide,以及微信公众号:数字集成电路设计及EDA教程 首先,简单的介绍一下floorplan的重要性,在之前的我学完成,本人之前的学Encounter忽略这个,这里特 ...
- 数字IC后端流程——(二)布局规划Floorplan
参考博客原址:https://blog.csdn.net/weixin_46752319/article/details/107313770 ICC布局规划 Floorplan是ICC设计流程中非常重 ...
- ICC图文流程——(二)布局规划Floorplan
ICC布局规划 Floorplan是ICC设计流程中非常重要的一环,Floorplan的好坏直接影响到设计的timing和布线布通率, 很多时候流程中反复主要发生在这步. 在ICC student l ...
- 中国航空物流行业运行现状与总体布局规划报告2022版
中国航空物流行业运行现状与总体布局规划报告2022版 --------------------------------------- [修订日期]:2021年12月 [搜索鸿晟信合研究院查看官网更多内 ...
- 全球及中国城市轨道交通与设备行业布局规划策略及投资模式分析报告2021-2027年版
全球及中国城市轨道交通与设备行业布局规划策略及投资模式分析报告2021-2027年版 HS--HS--HS--HS--HS--HS--HS--HS--HS--HS--HS--HS--HS--HS-- ...
最新文章
- 多个容器一起打包_程序员修神之路容器技术为什么会这么流行(记得去抽奖)
- 【数据结构与算法】之深入解析“下一个更大元素II”的求解思路与算法示例
- html 打开页面光标自动选中输入框_Python自动部署码云:
- Dockerfile best practices
- 区块链 以太坊 solidity 什么时候使用storage、memory
- 8000401a 错误 ,检索 COM 类工厂中 CLSID 为 的组件时失败,原因是出现以下错误: 8000401a。...
- 超标量处理器设计 姚永斌 第1章 超标量处理器概览 摘录
- PCB的IPC标准是什么
- 数据流被提前关闭- connectionClosedException:premature end of chunk coded message body:closing chunk expected
- 解读|Cocos新平台、新生态的行业意义
- idea 启动多个项目 减少内存占用
- mysql查询优化-查询缓存
- 搭建自己的以图搜图系统(二):深入优化搭建生产级别的图搜系统
- Unity小优化之美术字贴图合并以合批
- 学生机器人编程用什么语言
- Intellij IDEA 11个隐藏技巧
- 如何根据波动率曲面设计策略
- 基于FPGA的图像中值滤波原理与实现
- Linux开发起步学习笔记(11)----shell基本机制
- 学计算机技术的手机APP,软考助手(计算机技术考试)