×

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条评论

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

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.obk20.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'VHDL仲裁器开源分享',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.obk20.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);