我有以下过程,它应该右移它的输入(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检查),但即使在一个多小时后,也没有进展。 有人可以帮忙吗?
我需要这个组件是可合成的,所以如果我的方法有逻辑缺陷,请指出我正确的方向。
答案 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;
(如果您愿意,可以添加状态以使其等待,然后再读取新值...)