【问题标题】:How to represent sequential algorithm in VHDL如何在 VHDL 中表示顺序算法
【发布时间】:2013-01-17 23:11:58
【问题描述】:

我来自软件领域,并试图找出如何在 VHDL 中编写顺序算法。从教科书中,它说进程内的语句是按顺序执行的。但我意识到只有当涉及到变量而不是信号时,它才是正确的。进程内部的 Re 信号,它们在进程结束时得到更新,并且评估使用右操作数的先前值。所以据我了解,它仍然是并发的。出于性能目的,我不能总是使用变量来进行复杂的计算。

  1. 但是如何使用信号来呈现顺序算法呢?我的初始 想法正在使用FSM。真的吗? FSM 是唯一的方法吗 在 VHDL 中正确编码顺序算法?
  2. 如果我是对的,进程中的信号语句有点 并发,那么这个和信号有什么区别 架构级别的并发分配?过程是否 顺序性只适用于变量赋值?

【问题讨论】:

  • 不清楚你是在谈论顺序算法,(在一个周期中执行)还是一个算法的顺序执行,需要几个周期。
  • 谢谢布赖恩。需要明确的是,这里的顺序算法是指一个算法的顺序执行需要几个时钟周期。
  • 您能评论一下您的计算目标是什么吗?您是在尝试使用 VHDL 作为编程语言还是在尝试描述硬件?
  • 感谢您的回复。没有特定的算法,我只是指任何需要几个时钟周期才能大规模运行的顺序计算。我确实想描述行为,但可能会让你失望,因为我不想描述硬件。但是我们可以直接跳到重点来让谈话更有效率吗(也许我太不耐烦了)?

标签: vhdl


【解决方案1】:

当您尝试在不同的循环中执行算法的步骤时,您已经意识到流程中的“顺序”结构本身并不能做到这一点 - 事实上,变量也无济于事。一个顺序程序 - 除非它使用明确的“等待某些事件”,例如等待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 的新值,它会在每个周期中输出一个新结果 - 输入延迟四个周期。

【讨论】:

  • 嗨@brian-drummond,非常感谢你浏览我的帖子并给出详细的解释。据我了解,重新分配过程中的信号,它是并发的而不是顺序的。我可以扩展一下所有其余的顺序顺序语句,例如如果,案例,何时等?它们中的信号分配也像进程中一样是并发的,不是吗?干杯。
  • 这有点不同 - 我在一定程度上不同意 Zennehoy 的观点,即软件方法完全具有误导性:控制流程(尤其是变量)和算法的结果与软件相同观点:不同的是时间(一个时钟周期!) - 以及使之成为可能的一些限制。信号分配是不同的:它们是您的进程间通信 - 它们的语义非常优雅:在这里回答...stackoverflow.com/questions/13954193/…
  • 当您了解信号分配和变量分配时,您会发现您还可以使用内部值的变量来编写管道模型,但您必须向后描述管道! (第四个周期第一)。这样您就可以使用上一个周期的 s 值,然后生成新值。它有效,但我更喜欢向前描述我的管道......
【解决方案2】:
  1. 大多数多周期算法可以通过使用您建议的 FSM 或使用流水线逻辑来实现。如果算法由严格的顺序步骤(即没有循环)组成,流水线逻辑可能是更好的选择,FSM 通常仅用于需要根据输入不同控制流的更复杂的算法。

    流水线逻辑实际上是一个非常长的组合逻辑链,使用寄存器分成多个“阶段”,数据从一个阶段流向下一个阶段。添加寄存器是为了减少每个阶段(两个寄存器之间)的延迟,以增加延迟为代价允许更高的时钟频率。但是请注意,较高的延迟并不意味着较低的吞吐量,因为新数据可以在前一个数据项完成之前开始处理!对于 FSM,这通常是不可能的。

  2. 进程内的信号分配与体系结构的最大区别在于,您可以在进程内的多个位置为信号分配一个值,最后一个分配“获胜”。在架构级别,一个信号只能有一个赋值语句。许多控制流语句(if、case/when 等)也只能在流程中使用,而不是在架构级别。

【讨论】:

  • 感谢@zennehoy 的帮助。现在我知道 FSM 和流水线逻辑可以用来实现顺序算法。但是所有教科书都说顺序语句,即过程,if,case,when等,可以用作软件编程C来呈现顺序算法,这是非常模棱两可的,但是根据您的解释和我的理解,它们实际上是在信号方面是并发的。对于像我这样的初学者来说,这非常令人困惑。我可能遗漏了一些东西,如果我错了,请告诉我。
  • @user2035335 任何关于 HDL 的书,以任何方式建议在编码 HDL 时使用软件编程方法,恕我直言!硬件中的一切(!)都是同时发生的,只是使用不同的数据。 “顺序”的唯一概念是数据从一个硬件组件(无论是寄存器、门、晶体管等)传递到下一个硬件组件的顺序。所以是的,我同意一个进程中发生的所有事情都可以而且应该被视为同时发生,你只需要弄清楚进程的哪一部分“获胜”(=最终多路复用器的输出)。
猜你喜欢
  • 1970-01-01
  • 2016-06-19
  • 1970-01-01
  • 2015-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-15
相关资源
最近更新 更多