我再次与Xilinx工具进行战斗。我在PlanAhead-14.7中运行Zynq7020上的设计实现。该设计在PL上使用大约15-20%的设备利用率,实施过程似乎停留在全球布局上,到目前为止已经运行了12个多小时(并且仍在运行),我只期望最多一小时,这是非常不方便,因为我需要在星期五之前设计和测试这个设计,这让我感觉很干,因为任何改进都需要12小时+再次放置!
我正在使用64位14.7设计套件,并且读到以前的版本对64位工具有类似的问题。我有什么办法可以加快全球布局吗?我已经检查过所有的放置标志都设置为尽可能快地放置。
- 更新2-- 我现在处于精神错乱的边缘,因此这是整个过程(以及Brian提到的设计改进),这让我感到悲伤,并且它与使用state = fwrd_init和state = bkwrd_init <的OR语句有关。 / p>
input : process(clk, rst, dz_ready, row_ready, d_div_stts, counter, bkwrd_stts, state, cd_empty, zd_empty)
begin
if(clk'event and clk='1') then
stack_en <='0';
bkwrd_drdy <= '0';
d_rdy <= '0';
dz_read <='0';
read_row <='0';
result_ready <='0';
--delay dz_ready by one clock to correctly sync with other signals
dz_ready_p <= dz_ready;
--d and z register read and write logic--
if (state = fwrd_init or rst = '1' ) then
-- reset to all 1's so the initial division a_n/d_(n-1) = 0 ; a=0, n=0
d_reg <= (others=>'1');
z_reg <= (others=>'0');
dz_ready <= '0';
elsif(d_stts = '1') then
d_reg <= d_out;
z_reg <= z_out;
dz_ready <= '1';
end if;
--fwrd it logic---
if (dz_ready = '1' or state = fwrd_init) then
if(row_ready = '1') then
d_rdy <= '1' ;
dz_read <='1';
read_row <= '1';
dz_ready <='0';
--register the c value
end if;
end if;
--bkwrd it logic and stack logic -- read has priority over push
if(bkwrd_stts = '1' or state = bkwrd_init) then
if (cd_empty = '0' and zd_empty = '0') then
bkwrd_drdy <= '1';
--pop from stack
stack_en <= '1';
stack_pshp <= '0';
end if;
end if;
--Set initial values
if(state = bkwrd_init) then
bkwrd_v <= (others=>'0');
else
bkwrd_v <= result;
end if;
--Drive result output from the bkwrd iteration
if(bkwrd_stts = '1') then
result_ready <= '1';
x <= result;
else
x <= (others=>'0');
end if;
if(d_div_stts = '1' and state = fwrd_it) then
counter <= counter_next;
--push data onto the stack
stack_en <='1';
stack_pshp <='1';
stack_din <= cd;
zdstck_din <= zd;
end if;
--
---NEXT STATE LOGIC---
case state is
when idle =>
if (row_ready = '1') then
state <= fwrd_init ;
end if;
when fwrd_init =>
state <= fwrd_it;
when fwrd_it =>
if (counter = N) then
state <= bkwrd_init;
else
state <= fwrd_it;
end if;
when bkwrd_init =>
state <= bkwrd_it;
when bkwrd_it =>
if(cd_empty = '1' and zd_empty = '1') then
state <= idle;
else
state <= bkwrd_it;
end if;
when others => NULL;
end case;
end if;
end process;
所有其他信号由同一时钟域内的其他同步模块驱动,因为这是我设计的主要路由逻辑。
但如果我将OR更改为AND,则运行全局放置很好。显然,对于我的设计而言,而不是ors将不起作用,那么为什么它会显示这种行为呢? (我已经扩展了原来的单行if语句也没有用)
萨姆
答案 0 :(得分:2)
放宽主时间约束。如果您的目标(和当前约束)是200MHz,则运行P&amp; R 50 MHz。可能需要几分钟而不是几小时。
结果似乎没用,因为它太慢了:现阶段的重点是找到
随着设计对于时序约束而言太紧,工具会大幅减速。 (它在工具版本之间有所不同,而较新的版本通常会更好,但你可能遇到了一个病态的情况,工具只是不知道放弃的地方)。
无论如何;假设松弛的P&amp; R在(例如)78 MHz处给出结果,您还将获得最慢路径的详细信息;重新管理此路径并再次尝试,在改进设计时推动约束。
如果没有,马丁已经很好地覆盖了其他几个基地。
编辑更新后的问题:
这些“if”语句本身没有任何内在错误:错误必须在别处,但在此表现出来。
当然,如果这些陈述是时钟流程的一部分,特别是如果这是SM的“单一流程”风格,那么我希望这会起作用。如果它是一个单独的非时钟过程,则存在大量不当行为的空间。
(评论只是突然说这是一个时钟进程:我不相信它是主SM的一部分,因为我看不到状态分配)
怀疑这些if
表达式的所有输入;特别是and
工作的地方。这些是非时钟信号中的任何信号,还是来自其他时钟域的信号?我开始怀疑。如果是这样的话,可能会有一些不可思议的紧张时间随and
消失,因为关键术语可以通过逻辑最小化来消除。
这里的Asynch输入无效。
将它们重新同步到此时钟域,然后将它们送入比锁定之前的OR门更复杂的任何东西。如有必要,将信号输出到另一个时钟域并消除那里的冲突。
设计不添加时钟周期或两个延迟的复杂重新同步器是HARD。 Xilinx FPGA提供异步FIFOS作为替代方案,因此大多数人不必......
这些只是基于猜测的指导原则...希望他们有所帮助。
我会添加if (some cond )
if some cond
可能if dz_ready = '1' or state = fwrd_init then
的次要挑剔,但不会产生混乱,但这与手头的问题无关。
再次编辑(试图跟上问题:-)
第二个过程是非时钟的:你可以消除它并写入
dz_ready
但如果另一个术语input : process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
-- reset to all all 1's so the initial division a_n/d_(n-1) = 0 ; a=0, n=0
d_reg <= (others=>'1');
z_reg <= (others=>'0');
dz_ready <= '0';
-- state <= ???; -- Good idea to define initial state here
else
-- default assignments, overridden where necessary
stack_en <='0';
bkwrd_drdy <= '0';
d_rdy <= '0';
dz_read <='0';
read_row <='0';
result_ready <='0';
--delay dz_ready by one clock to correctly sync with other signals
dz_ready_p <= dz_ready;
bkwrd_v <= result; -- will be overridden in bkwrd_init
if d_stts = '1' then -- will be overridden in fwrd_init
d_reg <= d_out;
z_reg <= z_out;
dz_ready <= '1';
end if;
--fwrd it logic---
if dz_ready = '1' then
if row_ready = '1' then
d_rdy <= '1' ;
dz_read <='1';
read_row <= '1';
dz_ready <='0';
--register the c value
end if;
end if;
--bkwrd it logic and stack logic -- read has priority over push
if bkwrd_stts = '1' then
if cd_empty = '0' and zd_empty = '0' then
bkwrd_drdy <= '1';
--pop from stack
stack_en <= '1';
stack_pshp <= '0';
end if;
result_ready <= '1';
x <= result;
else
x <= (others=>'0');
end if;
-- STATE LOGIC --
case state is
when idle =>
if (row_ready = '1') then
state <= fwrd_init ;
end if;
when fwrd_init =>
-- actions
d_reg <= (others=>'1');
z_reg <= (others=>'0');
dz_ready <= '0';
if(row_ready = '1') then
d_rdy <= '1' ;
dz_read <='1';
read_row <= '1';
dz_ready <='0';
--register the c value
end if;
-- state
state <= fwrd_it;
when fwrd_it =>
if d_div_stts = '1' then
counter <= counter_next;
--push data onto the stack
stack_en <='1';
stack_pshp <='1';
stack_din <= cd;
zdstck_din <= zd;
end if;
if (counter = N) then
state <= bkwrd_init;
end if;
when bkwrd_init =>
if cd_empty = '0' and zd_empty = '0' then
bkwrd_drdy <= '1';
--pop from stack
stack_en <= '1';
stack_pshp <= '0';
end if;
bkwrd_v <= (others=>'0');
state <= bkwrd_it;
when bkwrd_it =>
if(cd_empty = '1' and zd_empty = '1') then
state <= idle;
end if;
when others => NULL;
end case;
end if;
end if;
end process;
是异步的,那将无济于事。
我冒昧地将流程重写为更常见的“单一流程SM”形式。它的行为(我很确定)与原作相当,但它暴露了一些奇怪的动作重复,这在风格上是不寻常的。这可能会让你看到一些无意识的东西,或者可能不那么混淆综合工具。 (在状态fwrd_init中对dz_ready的双重赋值可能是无害的,但看起来很可疑!)
{{1}}
答案 1 :(得分:2)
通过将逻辑移动到case语句中来修复逻辑之后,实际上看起来很长的放置时间是由于Coregen 3.0分频器中仍然存在的错误。 http://forums.xilinx.com/t5/Implementation/divider-generator-3-0-problem-with-Virtex-6/m-p/230379#M4737
答案 2 :(得分:1)
你能试试32位工具吗?
另一件令人想到的事情是,这种行为通常来自一个你曾期望在BlockRAM中实现的大内存,但由于某种原因,编译器决定用LUT和触发器来做。
太痛苦了!
现在您已经隔离了一些代码,您是否可以仅合成该模块(因此模块IO成为引脚)。无论是内部还是外部,这可能会缩小范围。您有时也可以在该级别更轻松地跟踪RTL查看器中的信号。