无法使用While循环完成进程编译 [英] Can't finish compiling a process with while loop

查看:0
本文介绍了无法使用While循环完成进程编译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下进程,它应该右移其输入(INPUT_1),直到它达到0,然后结束循环:

DFF_PROCESS: process (input_0, input_1, input_2, CLK)
  variable eX : integer;
  ...
begin
  eX := input_1;
  ...
  while (eX > 0) loop
    if ( CLK'event and CLK = '1' ) then
      ...
      eX := to_integer(shift_right(to_unsigned(eX,32), 1));
    end if;
  end loop;
  result <= rE;
end process;
但当我尝试编译它时,它没有生成任何错误,但在分析和合成部分的~10%处停滞不前。编译器似乎工作正常(通过ProcessExplorer检查),然而,即使在一个多小时后,也没有任何进展。 有人能帮忙吗?

我需要此组件是可合成的,所以如果我的方法有逻辑缺陷,请为我指出正确的方向。

推荐答案

合成While循环通常不是一个好主意,稍微考虑一下就会知道原因...

循环不能保证终止;迭代次数一般不能在编译(合成)时知道,因此您正试图生成一个运行前大小未知的硬件结构!

那行不通...

通常,您需要将While循环转换为具有本地静态边界(大致:可以根据此源文件确定)的密切相关的for循环-这是可合成的。

在您的示例中,您将变量转换为32位无符号变量,并每次向右移位1位:一个适合的for循环将循环32位无符号变量中的位。

这不能处理不同的输入值:但是,for循环中的条件(if ex = 0 then)将处理不同的输入值(而且显然是可合成的)

类似于...

DFF_PROCESS: process (CLK, input_1)
variable eX : unsigned(31 downto 0);
    ...
begin
    eX := to_unsigned(input_1);
    ...
    for i in ex'range loop  -- better way of saying 31 downto 0)
        if rising_edge(clk) then
            if ex > 0 then
               ...   
               eX := shift_right(eX, 1);
            end if;
        end if;
    end loop;
end process;

这还有其他问题:它不是一个正确的计时进程,并且EX不断被输入值覆盖,因此它不会执行您预期的操作。

有两种前进方式:一种快速(每个时钟周期一个结果),但生成大量硬件;另一种很小(但最坏情况下需要32个时钟周期)。

第一个命令展开循环,生成32个循环体副本,以在一个时钟周期内生成结果:

DFF_PROCESS: process (CLK)
variable eX : unsigned(31 downto 0);
    ...
begin
    if rising_edge(clk) then
        eX := to_unsigned(input_1, ex'length);
        ...
        for i in ex'range loop  
            if ex > 0 then  -- done
               ...
               eX := shift_right(eX, 1);
            end if;
        end loop;
        result <= ...
    end if;
end process;

另一种是状态机,它可以在每个时钟周期中接受新的输入值,或者处理单个位,但不能同时处理这两个位。

DFF_PROCESS: process (CLK)
   variable eX : unsigned(31 downto 0);
   type State_type is (Read, Process_Data);
   variable State : State_Type;

begin
   if rising_edge(clk) then
      if State = Read then
         eX    := to_unsigned(input_1, ex'length);
         State := Process_Data;
      else
         if ex = 0 then
            result <= ...
            State := Read;
         else
            ...
            eX := shift_right(eX, 1);
         end if;
      end if;
   end if;
end process;

(如果您愿意,可以添加状态使其在读取新值之前等待...)

这篇关于无法使用While循环完成进程编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆