无法使用while循环完成编译过程

时间:2014-01-18 13:01:59

标签: vhdl

我有以下过程,它应该右移它的输入(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;

但是当我尝试编译它时,它不会产生任何错误,但却会陷入Analysis&amp; Synthesis部分的约10%。编译器似乎正在工作(通过ProcessExplorer检查),但即使在一个多小时后,也没有进展。 有人可以帮忙吗?

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

1 个答案:

答案 0 :(得分:2)

合成一个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);
        ...
        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);
   variable State : State_Type;

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

(如果您愿意,可以添加状态以使其等待,然后再读取新值...)