当前位置:首页 > EDA > 电子设计自动化
[导读]仲裁器Arbiter是数字设计中非常常见的模块,应用也非常广泛。定义就是当有两个或两个以上的模块需要占用同一个资源的时候,我们需要由仲裁器arbiter来决定哪一个模块来占有这个资源。类比一下,老师上课问了一个问题,底下同学不止一个人举手了,老师这个时候就要扮演仲裁者的角色,来指定由哪位同学站起来回答问题。一般来说,提出占有资源的模块要产生一个请求(request),类比于学生要举手表示自己要回答问题。所有的请求送给仲裁器之后,仲裁器要返回一个许可(grant),也就是老师要选择一名同学,通过点这个同学的名字的方式,告诉这个同学可以站起来回答问题。

仲裁器Arbiter是数字设计中非常常见的模块,应用也非常广泛。定义就是当有两个或两个以上的模块需要占用同一个资源的时候,我们需要由仲裁器arbiter来决定哪一个模块来占有这个资源。类比一下,老师上课问了一个问题,底下同学不止一个人举手了,老师这个时候就要扮演仲裁者的角色,来指定由哪位同学站起来回答问题。一般来说,提出占有资源的模块要产生一个请求(request),类比于学生要举手表示自己要回答问题。所有的请求送给仲裁器之后,仲裁器要返回一个许可(grant),也就是老师要选择一名同学,通过点这个同学的名字的方式,告诉这个同学可以站起来回答问题。

仲裁器很重要的一点是只能让一个模块得到许可,因为这个资源某一时刻只能由一个模块占用。类比一下,老师不能让两个同学同时站起来回答,因为两个人同时站起来说话就谁也听不清了。在数字电路中,总线仲裁是一个常见的例子,比如多个master要占用总线来去写数据,那么需要仲裁器来许可哪个master来占用总线。

那么一个显而易见的问题就是,仲裁器应该基于什么原则来分配许可呢?这篇我们先讨论最常见的方式:固定优先级 -- fixed priority。

固定优先级,顾名思义,就是说每个模块的优先级是固定的,是提前分配好的,如果有两个模块同时产生request,那么优先级高的模块可以获得grant。还是类比老师叫同学起来回答问题。比如,在老师心中,老师可以这样安排一个优先级:学号。学号是1的同学回答优先级最高,2号其次,一直到最后一位同学N,当大家举手的时候,总是叫学号最小的那个。比如说如果1号同学举手了,那就叫1号;如果1号,2号都没有举手,3号举手了,那就叫3号,很好理解吧?当然,如果N个同学里只有1位举手,那不管这个同学是几号,都让他回答问题。如果大家都不举手,那么老师就不叫了(现实中可能不是这样,有的老师可能会点名,但是咱们就不讨论了,大家理解就行)。

你可能会说,那对学号大的同学不公平啊,每次都抢不过学号小的同学。你说的没错,仲裁器的许可算法是有很多种的,我们说的固定优先级只是一种最简单的许可算法,还有其他的算法会考虑到公平性,我们之后再讨论。

回到仲裁器本身,如果我们要设计一个fixed priority arbiter,输入是一个multibit request,每一个bit代表一个模块的request, 输出一个multibit grant,每个bit代表给对应的模块的grant信号。我们可以把优先级这样安排,最低位优先级最高,最高位优先级最低。

我们先以3个模块产生request为例,大家一般在面试的时候都会碰到给定模块数目,比如3,让你设计。咱们就直接上code来表示一种写法

1 module fixed_prio_arb

2 (

3 input [2:0] req,

4

5 output logic [2:0] grant

6 );

7

8 always_comb begin

9 case (1'b1)

10 req[0]: grant = 3'b001;

11 req[1]: grant = 3'b010;

12 req[2]: grant = 3'b100;

13 default:grant = 3'b000;

14 endcase

15 end

16

17 endmodule: fixed_prio_arb

这里的技巧是利用verilog中的case语句,可以比用if else简洁,而且利用了case里的按顺序evaluate语法规则来实现了优先级。这里多说一句给verilog的初学者,尽管verilog和C看起来很像,很多关键字都是一样的,比如case,但是verilog的case和C的case是不一样的,verilog的case自带"break",即当一个condition满足之后,就只会执行这一条冒号之后的,只有input 发生变化之后才会再次evaluate,因为这是描述硬件电路。而C语言的case里如果一条满足之后会按照顺序继续往下执行,如果下一个条件依然满足,那么就会跳到下一个条件里,所以C的case语句我们通常要加break。

好,如果这一篇老李到此为止那就太水了,下面才是真正的干货内容。面试的时候如果你能够往下发挥才能让面试官眼前一亮。

还是那个老李一直强调的,如何设计一个参数化的模块。对于上面的仲裁器来说,我们希望可以参数化产生请求的个数,即设计下面的模块

1 module priority_arbiter #(

2 parameter REQ_WIDTH = 16

3 )(

4 input [REQ_WIDTH-1:0] req,

5 output [REQ_WIDTH-1:0] gnt

6 );

这样我们可以根据不同场合产生request的模块的个数来例化同一个仲裁器,只需要改变参数即可。很明显,上面利用case的写法不能scalable,我们需要用更加巧妙的办法。

首先可以想到的办法是利用for循环,思路其实非常直接,从低位到高位依次去判断,借助一个pre_req来记录低位是否已经有了request, 如果第i位有了request,那么第i+1位一直到最高位的pre_req都是1。

1 module prior_arb #(

2 parameter REQ_WIDTH = 16

3 )(

4 input logic [REQ_WIDTH-1:0] req,

5 output logic [REQ_WIDTH-1:0] grant

6 );

7

8 logic [REQ_WIDTH-1:0] pre_req;

9

10 always_comb begin

11 pre_req[0] = req[0];

12 grant[0] = req[0];

13 for (int i = 1; i < REQ_WIDTH; i = i + 1) begin

14 grant[i] = req[i] & !pre_req[i-1]; // current req & no higher priority request

15 pre_req[i] = req[i] | pre_req[i-1]; // or all higher priority requests

16 end

17 end

18

19 endmodule

有没有更简洁的办法呢?下面老李介绍两种实现方式,code非常简洁,先来上面的设计的变体,但是不用for循环,本质上是一样的,只有3行code。

1 module prior_arb #(

2 parameter REQ_WIDTH = 16

3 )(

4 input [REQ_WIDTH-1:0] req,

5 output [REQ_WIDTH-1:0] gnt

6 );

7

8 logic [REQ_WIDTH-1:0] pre_req;

9

10 assign pre_req[0] = 1'b0;

11

12 assign preq_req[REQ_WIDTH-1:1] = req[REQ_WIDTH-2:0] | pre_req[REQ_WIDTH-2:0];

13

14 assign gnt = req & ~pre_req;

15

16 endmodule

下面的这种实现方式就更夸张了,就一行实现,读到这里的读者可以说是赚到了,因为老李搜过,至少在各种介绍仲裁器的公众号文章里老李从来没有见到过这种方法。老李第一次学到的时候也是惊为天人,但是它背后的思想却非常朴素,简直不超过小学一年级的知识。

1 module prior_arb #(

2 parameter REQ_WIDTH = 16

3 ) (

4 input [REQ_WIDTH-1:0] req,

5 output [REQ_WIDTH-1:0] gnt

6 );

7

8 assign gnt = req & (~(req-1));

9 endmodule

本质上,我们要做的是找req这个信号里从低到高第一个出现的1,那么我们给req减去1会得到什么?假设req的第i位是1,第0到第i-1位都是0,那么减去1之后我们知道低位不够减,得要向高位借位,直到哪一位可以借到呢?就是第一次出现1的位,即从第i位借位,第0到i-1位都变成了1,而第i位变为了0,更高位不变。然后我们再给减1之后的结果取反,然后把结果再和req本身按位与,可以得出,只有第i位在取反之后又变成了1,而其余位都是和req本身相反的,按位与之后是0,这样就提取出来了第一个为1的那一位,也就是我们需要的grant。再考虑一下特殊情况req全0,很明显,按位与之后gnt依然都是全0,没有任何问题。

聪明的同学可能已经联想到,减1再取反,这不是计算2的补码的算法吗?只不过我们书本上学到的给一个数求2的补码的方法是取反再加1,这里倒过来,减1再取反,本质上是一样的。这其实是2的补码的一个特性,即一个数和它的补码相与,得到的结果是一个独热码,独热码为1的那一位是这个数最低的1。所以这个仲裁器的设计方法用一句话概括:request和它的2的补码按位与。如果同学们在面试的时候被问到设计优先级固定仲裁器,只要记住这句话,那么你就可以惊艳面试官。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭