×

VHDL仲裁器开源分享

消耗积分:0 | 格式:zip | 大小:0.00 MB | 2023-06-13

笑尽往事

分享资料个

描述

什么是仲裁员?

仲裁器是硬件设计中非常常用的块。

我想我可以在家里找到仲裁者的最好例子。当我的两个孩子十几岁时,我只有一辆车。在周五和周六晚上,通常会因为谁可以使用汽车而发生冲突。通常,由我来决定(仲裁者)谁得到了这辆车。这不是一件容易的事。(我仍然只有一辆车,正好我的孩子都不是十几岁了,赞美主,他们有自己的车)。

硬件板没有什么不同。至少在两种情况下,多个用户“需要”共享(且有价值且昂贵)的资源:

  • 公共内存:在处理器和 FPGA 之间共享快速内存(即 DDR)的电路板是很常见的。显然,记忆不能同时回答两个高手。处理器和 FPGA 向仲裁器请求访问内存的权限。即使它以非常高的速度同时完成,对于我们的感知,实际上,FPGA 和处理器必须轮流拥有内存。注意:这只是一个简单的示例,因为还有许多其他应用程序甚至超过两个“智能”设备(处理器、DSP、GPU、FPGA、ASIC)轮流访问公共内存。
  • 公共总线:很多时候多个主机(和从机)通过公共总线进行通信。从电气角度来说,总线非常简单。它只不过是一组铜连接或电线(有时带有总线驱动器)。但是总线所有权很重要,因为两个主机不可能同时拥有总线(多主机总线的示例:I2C、PCI)。如果两个主机试图同时“交谈”,就会发生冲突,总线上的数据就会被破坏。

仲裁者是硬件的一部分,它决定谁可以在任何给定时间使用公共的、有价值的资源。然而,与足球仲裁器不同的是,VHDL 仲裁器永远不会将其中一个设备从“游戏”中移除(好吧......几乎永远不会。在某些情况下,硬件仲裁器会决定一个设备表现不佳并决定将其从“游戏”中移除一个例子是可插拔卡访问公共总线,可以在关键时刻拔掉,如果仲裁器没有识别出故障,总线可能会卡在 - 现在丢失的 - 设备上)。

仲裁器从其客户端接收两种类型的信号:

  • 请求:由想要拥有公共资源的每个设备声明。可以同时断言许多请求信号,就像许多设备请求拥有公共资源的许可一样。另一方面,可以只有一个,甚至没有断言的请求信号。后者是在特定时刻没有人需要共享资源的情况。
  • Grant:由仲裁器断言,每个master有一个grant信号。通常,在任何给定时间都只会断言一个授权信号。

第一次实现 - 固定大小,固定优先级

我们将分析的第一个仲裁器具有三个请求输入和三个授权输出。它也有一个固定的主人优先权。master 编号越低,其优先级越高。该块也有信号。总线仲裁仅在其处于非活动状态时进行。如果总线已经被授权给代理,即使更高优先级的主机请求总线,当前事务也必须在仲裁器将总线授权给另一个主机之前完成。

生成授权信号的逻辑(在进程arbiter_pr上)非常简单。如果第一个主控(主控 0)断言请求,则它被授予授权。只有当主控 1 请求总线而主控 0 不请求总线时,它才会获得授权。只有当主控 2 请求总线并且主控 0 和主控 1 都没有请求总线时,它才会被授予授权。

gnt信号只有在总线不忙时才会改变。进程busy_pr和相关逻辑检测信号的下降沿在 busy 变为低电平后,所有授权信号都被取消断言一个时钟,然后选择下一个总线主机的逻辑被激活。

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity arbiter is
  port (
    clk  : in  std_logic;
    rst  : in  std_logic;

    -- inputs
    req  : in  std_logic_vector(2 downto 0);
    busy : in  std_logic;

    -- outputs
    gnt  : out std_logic_vector(2 downto 0)
  );
end arbiter;

architecture rtl of arbiter is
  signal busy_d : std_logic := '0';
  signal busy_fe : std_logic;

begin
  busy_pr : process (clk)
  begin
    if (rising_edge(clk)) then
      busy_d <= busy;
    end if;
  end process busy_pr;

  -- Falling edge of busy signal
  busy_fe <= '1' when busy = '0' and busy_d = '1' else '0';

  arbiter_pr : process (clk, rst)
  begin
    if (rst = '1') then
      gnt <= (others => '0');
    elsif (rising_edge(clk)) then
      if (busy_fe = '1') then
        gnt <= (others => '0');
      elsif (busy = '0') then
        gnt(0) <= req(0);
        gnt(1) <= req(1) and not req(0);
        gnt(2) <= req(2) and not (req(0) or req(1));
      end if;
    end if;
  end process arbiter_pr;

end rtl;

gnt信号只有在总线不忙时才会改变。进程busy_pr和相关逻辑检测信号的下降沿在 busy 变为低电平后,所有授权信号都被取消断言一个时钟,然后选择下一个总线主机的逻辑被激活。

poYBAGSAgZyAXkcHAAEUpXs9m70940.png
 

复位释放后,没有未完成的请求,因此仲裁器也不会断言任何授权信号。稍后在模拟中,多个主机请求仲裁器的许可(请求已断言)并根据其优先级获得授权。

在 300 到 400ns 之间,主机“1”断言其请求信号。两个时钟周期后,来自主机“0”的请求被置位。因此,即使 master '0' 稍后到达,当仲裁器可以自由分配总线时,它也会将其分配给 master '0'。

请注意,在gnt信号之间始终有一个“休息”时钟每个主机使用总线四个时钟并放弃总线(这可以在信号的持续时间内看到)。

稍后,主机“2”和“0”都请求总线,正如预期的那样,总线被授予主机“0”。

GitHub 上提供了仲裁器“简单实现”、测试平台和 Modelsim 文件的 VHDL 源代码

第二种实现——可变大小,固定优先级

上述仲裁器的逻辑是固定大小的。通过一些更改,并通过使用不受约束的端口(查看reqgnt端口),我们可以制作一个通用仲裁器,其大小可以在实现时决定。

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity arbiter_unc is
  port (
    clk  : in  std_logic;
    rst  : in  std_logic;

    -- inputs
    req  : in  std_logic_vector;
    busy : in  std_logic;

    -- outputs
    gnt  : out std_logic_vector
  );
end arbiter_unc;

architecture rtl of arbiter_unc is
  signal busy_d : std_logic;
  signal busy_fe : std_logic;

begin
  busy_pr : process (clk)
  begin
    if (rising_edge(clk)) then
      busy_d <= busy;
    end if;
  end process busy_pr;

  -- Falling edge of busy signal
  busy_fe <= '1' when busy = '0' and busy_d = '1' else '0';

  arbiter_pr : process (clk)
    variable prio_req : std_logic;
  begin
    if (rising_edge(clk)) then
      if (rst = '1') then
        gnt <= (others => '0');
      else  
        if (busy_fe = '1') then
          gnt <= (others => '0');
        elsif (busy = '0') then
          gnt(0) <= req(0);
          for I in 1 to req'left - 1 loop
            prio_req := '0';
            for J in 1 to I loop
              prio_req := prio_req or req(J - 1);
            end loop;
            gnt(I) <= req(I) and not prio_req;
          end loop;
        end if;
      end if;
    end if;  
  end process arbiter_pr;

end rtl;

可变大小仲裁器的 Vivado 仿真,实例化为 size = 4

pYYBAGSAgZ-AfhrwAAEL2gsZuwA018.png
 

 

poYBAGSAgaGAbTCrAAAtE6BkjVk854.png
两个代理的固定优先级仲裁器
 

 

pYYBAGSAgaSANNiBAAAztR_o0HY602.png
三个代理的固定优先级仲裁器
 

 

poYBAGSAgaiAVMPYAAAx9j2iigw301.png
四个代理的固定优先级仲裁器
 

 

RTL 表示显示了处理越来越多的端口所需的组合复杂性不断增加,并且是使用 Quartus Prime 15.1 生成的。请注意,某些块(如输出 FF)不是单个而是堆叠的原始实例化。如前所述,如果多个主机请求总线,则编号最小的主机将获得gnt(回想一下,在任何给定时间只有一个主机应接收gnt)。这个仲裁器有一个固定的优先级。虽然在某些应用程序中可以使用这样的仲裁器,但最常见的仲裁器类型没有固定的优先级。我将在以后的文章中讨论更复杂的仲裁器(循环法)。

建议练习

  • 如前所述,这个简单的仲裁器具有固定的优先级。如果多个主控断言它们的请求信号,则编号最小的主控器被赋予gnt设计一个固定优先级的主机,其中编号最高的主机具有最高优先级。
  • 在这个仲裁器中,只要一个主机请求总线,总线就被授予它。添加超时逻辑。如果一个主机断言req超过 10 个时钟周期,如果其他请求未完成,则取消断言对该主机的授权信号。
  • 一些仲裁者具有公园功能。Park 的意思是,如果没有未完成的请求,gnt信号将发送给最后一个接收到它的主机。在另一个版本中,如果没有主机断言req,则gnt信号被分配给“默认主机”。为这两个选项中的每一个选项设计代码。

GitHub 上提供了仲裁器“无约束实现”、测试平台和 Modelsim 文件的 VHDL 源代码

诚邀您访问我的网站,在那里您可以找到更多VHDL 项目文章以及合法免费的书籍和课程


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !