当您尝试在不同的循环中执行算法的步骤时,您已经意识到流程中的“顺序”结构本身并不能做到这一点 - 事实上,变量也无济于事。一个顺序程序 - 除非它使用明确的“等待某些事件”,例如等待rising_edge(clk) - 将被展开并在单个时钟周期内执行。
您可能已经发现使用变量,这可能是一个相当长的时钟周期。
在 VHDL 中有三种主要的顺序执行方式,用途不同。
让我们尝试他们在 a 和 b 之间实现线性插值,
a, b, c, x : unsigned(15 downto 0);
x <= ((a * (65536 - c)) + (b * c)) / 65536;
(1) 是经典的状态机;最好的形式是单进程 SM。
在这里,计算被分解为几个周期,确保一次最多进行一次乘法(乘法器很昂贵!)但 C1 是并行计算的(加法/减法很便宜!)。它可以安全地用变量而不是中间结果的信号重写。
type state_type is (idle, step_1, step_2, done);
signal state : state_type := idle;
signal start : boolean := false;
signal c1 : unsigned(16 downto 0); -- range includes 65536!
signal p0, p1, s : unsigned(31 downto 0);
process(clk) is
begin
if rising_edge(clk) then
case state is
when idle => if start then
p1 <= b * c;
c1 <= 65536 - c;
state <= step_1;
end if;
when step_1 => P0 <= a * c1;
state <= step_2;
when step_2 => s <= p0 + p1;
state <= done;
when done => x <= s(31 downto 16);
if not start then -- avoid retriggering
state <= idle;
end if;
end case;
end if;
end process;
(2) 是 Martin Thompson 链接的“implicit state machine”(优秀的文章!)...编辑添加链接,因为 Martin 的答案消失了。
与显式状态机相同的注释适用于它。
process(clk) is
begin
if start then
p1 <= b * c;
c1 <= 65536 - c;
wait for rising_edge(clk);
p0 <= a * c1;
wait for rising_edge(clk);
s <= p0 + p1;
wait for rising_edge(clk);
x <= s(31 downto 16);
while start loop
wait for rising_edge(clk);
end loop;
end if;
end process;
(3) 是流水线处理器。在这里,执行需要几个周期,但一切都是并行发生的!流水线的深度(以周期为单位)允许每个逻辑顺序步骤以顺序方式发生。这可以实现高性能,因为长链计算被分解为周期大小的步骤......
signal start : boolean := false;
signal c1 : unsigned(16 downto 0); -- range includes 65536!
signal pa, pb, pb2, s : unsigned(31 downto 0);
signal a1 : unsigned(15 downto 0);
process(clk) is
begin
if rising_edge(clk) then
-- first cycle
pb <= b * c;
c1 <= 65536 - c;
a1 <= a; -- save copy of a for next cycle
-- second cycle
pa <= a1 * c1; -- NB this is the LAST cycle copy of c1 not the new one!
pb2 <= pb; -- save copy of product b
-- third cycle
s <= pa + pb2;
-- fourth cycle
x <= s(31 downto 16);
end if;
end process;
在这里,资源不是共享的;它将使用 2 个乘数,因为有
每个时钟周期乘以 2。它还将使用更多的寄存器
中间结果和副本。但是,在每个周期中给定 a、b、c 的新值,它会在每个周期中输出一个新结果 - 输入延迟四个周期。