手把手Verilog循环优先级仲裁器

这篇具有很好参考价值的文章主要介绍了手把手Verilog循环优先级仲裁器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一级目录

二级目录

三级目录

1、仲裁Arbiter简介

多个信号同时请求一个处理时,需要一个名为仲裁器的模块来选择优先级高的信号处理。通常输入一个多信号优先级请求i_req[:0],经过处理后输出一个处理结果信号o_result[:0],来表明谁被许可处理。常见有固定优先级仲裁器和循环优先级仲裁器。

2、固定优先级仲裁器原理实现

顾名思义,即优先级固定,每一次都以同一优先级判断,前后仲裁不影响。代码用if-else/case语句就可简单实现。即:

module fixed_arbiter4(
	input            clk,
	input            rst_n,
	input      [3:0] i_req,
	output reg [3:0] o_result
);
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	    o_result <= 4'b0001;               //默认i_req第0位优先
/*
//一次只允许一位请求,不太合理				
				else begin	
					case(i_req)
					4'b0001 : o_result <= 4'b0001;
					4'b0010 : o_result <= 4'b0010;
					4'b0100 : o_result <= 4'b0100;
					4'b1000 : o_result <= 4'b1000;
                    default	:o_result <= 4'b0001;			
				end
*/				
//一次允许多位请求,优先顺序位i_req[0]>i_req[1]i_req[2]>i_req[3]		
				else begin	
					case(1'b1)
					i_req[0] :o_result <= 4'b0001;
					i_req[1] :o_result <= 4'b0010;
					i_req[2] :o_result <= 4'b0100;
					i_req[3] :o_result <= 4'b1000;
                    default:o_result <= 4'b0001;	
                    endcase					
				end					
end
endmodule

测试代码也很简单,这里不赘述。

3、循环优先级仲裁器原理

每一次仲裁的优先级都是根据上一次仲裁结果而定的,即本次的仲裁结果会影响下一次仲裁的优先级。
因为这样仲裁的优先级会改变,所以理论上每个请求的几率基本平等。实现上可用一个优先级状态寄存器来完成。
基本原理思想:
1、请求信号i_req[3:0],则默认规定最低位优先级最高,往左依次递减。
2、一次仲裁中,某一位获得请求后,则下一次仲裁时,其左侧优先级变为最高,依次递减,循环回到自己优先级最低。

例如:
请求信号i_req[3:0],优先级 i_req[0]>i_req[1]>i_req[2]>i_req[3]。
第一次发起仲裁请求的输入为i_req[3:0] = 4’b 0 1 1 0,
根据规则判断i_req[1]获得允许,输出o_result[4:0] = 4’b 0 0 1 0。
与此同时,下一次仲裁的优先级即变成了:
i_req[2]>i_req[3]>i_req[0]>i_req[1],即上一次的优先在本级最后。

4、实现方法

一个仲裁器通常包含两部分组成,即一个优先级状态寄存器阵列和一个请求计算模块

4.1、优先级状态寄存器阵列

优先级状态寄存器阵列,用于保存每个请求和其他请求之间的关系。如果一个仲裁电路有N个请求,那么需要一个(N-1)*N的寄存器阵列,阵列设置不同则代表含义不同,下面以其4个请求仲裁的一种阵列说明。
总共有4个请求,则每个请求需要3个寄存器来表示其他外部请求优先级是否高于本请求优先级。本例中,优先级关系规定为:本请求比另一个高则赋0,低则赋1。

手把手Verilog循环优先级仲裁器

其中req0_1,req0_2,req0_3就表示R[0]相对于R[1]、R[2]、R[3]的优先级。
假设初始优先级顺序:i_req[0]>i_req[1]>i_req[2]>i_req[3]
初始矩阵如下左图,此时R[0]获得允许,下一次R[1]优先级最高,往左依次递减,R[0]优先级最低,
此时优先级顺序为:i_req[0]>i_req[1]>i_req[2]>i_req[3],矩阵变为下右图

手把手Verilog循环优先级仲裁器上述的改变过程可用状态机实现,值得注意的是,状态机是根据本次输出的结果o_result[4:0]来修改阵列的值,而不是输入的i_req[0],这里怎么理解呢?

因为输入可能有两位同时有效,即输入i_req[3:0] = 4’b 0 1 0 1,这样不符合状态机运行规则,而经过计算模块o_result[4:0]每次只会有1位有效(下个部分介绍怎样计算才能保证无论输入几位有效,输出有且只有一位有效),这样才可以用状态机来实现。至于第一次输出,第一次输出不过状态机,根据初始矩阵数据和输入实现第一次输出,然后过状态机修改矩阵。

4.2、请求计算模块

根据上述优先状态寄存器的描述可知,本次输出的结果和两个值有关,分别是上一次仲裁后修改的阵列本次输入来判断本次输出。

即某个请求响应的条件是:1、本请求对应的输入有效;2、本次有效的请求优先级顺位最高。
计算包含两部分:第一级“与非”,三次与非依据优先级状态寄存器阵列中保存的请求优先级别仲裁;第二级“与”,四次与完成当前请求是否有效。

例如:o_result[0] = 
i_req[0] & //
(~(req0_1&i_req[1]))&
(~(req0_2&i_req[2]))&
(~(req0_3&i_req[3]));
o_result[0]输出有效的条件是:
1、请求输入0位有效,即:i_req[0];第0位优先级比第1位高,比第2位高,比第3位高。

5、Verilog HDL代码

模块代码:

module arbiter4(
    input              clk,
	input              rst_n,
	input      [3:0]   i_req,
	output reg [3:0]   o_result
);
//优先级状态寄存器
reg  req0_1,req0_2,req0_3;//第0位3个优先级状态
reg  req1_0,req1_2,req1_3;//第1位3个优先级状态
reg  req2_0,req2_1,req2_3;//第2位3个优先级状态
reg  req3_0,req3_1,req3_2;//第3位3个优先级状态

//优先级状态阵列

always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin//默认情况下req[0]优先级最高,三位分别000;优先级往左依次递减,req[4]优先级最低,三位分别111
	        req0_1 <= 1'b0; req1_0 <= 1'b1; req2_0 <= 1'b1; req3_0 <= 1'b1;
            req0_2 <= 1'b0; req1_2 <= 1'b0; req2_1 <= 1'b1; req3_1 <= 1'b1;
            req0_3 <= 1'b0; req1_3 <= 1'b0; req2_3 <= 1'b0; req3_2 <= 1'b1;
	end
    else begin                                                    //本次输出决定下次优先级
	    case(o_result)
		4'b0001:begin                                             //上次req[0]优先,本次最后
		    req0_1 <= 1'b1; 
			req0_2 <= 1'b1; 
			req0_3 <= 1'b1;                                       //req[0]本次最后
			req1_0 <= 1'b0;
			req2_0 <= 1'b0;
			req3_0 <= 1'b0;                                       //修改其余3位优先级
		end
		4'b0010:begin                                             //上次req[1]优先,本次最后
		    req1_0 <= 1'b1; 
			req1_2 <= 1'b1; 
			req1_3 <= 1'b1;                                       //req[1]本次最后
			req0_1 <= 1'b0;
			req2_1 <= 1'b0;
			req3_1 <= 1'b0;                                       //修改其余3位优先级
		end
		4'b0100:begin                                             //上次req[2]优先,本次最后
		    req2_0 <= 1'b1; 
			req2_1 <= 1'b1; 
			req2_3 <= 1'b1;                                       //req[2]本次最后
			req0_2 <= 1'b0;
			req1_2 <= 1'b0;
			req3_2 <= 1'b0;                                       //修改其余3位优先级
		end
		4'b1000:begin                                             //上次req[3]优先,本次最后
		    req3_0 <= 1'b1; 
			req3_1 <= 1'b1; 
			req3_2 <= 1'b1;                                       //req[3]本次最后
			req0_3 <= 1'b0;
			req1_3 <= 1'b0;
			req2_3 <= 1'b0;                                       //修改其余3位优先级
		end
		endcase
	end
end	
//请求响应计算
always@(*)
begin
	o_result[0] = i_req[0] &
	                (~(req0_1 & i_req[1])) & 
					(~(req0_2 & i_req[2])) & 
					(~(req0_3 & i_req[3]));
    o_result[1] = i_req[1] &
	                (~(req1_0 & i_req[0])) &
					(~(req1_2 & i_req[2])) & 
					(~(req1_3 & i_req[3]));
	o_result[2] = i_req[2] &
	                (~(req2_0 & i_req[0])) &
					(~(req2_1 & i_req[1])) &
					(~(req2_3 & i_req[3]));
	o_result[3] = i_req[3] &
	                (~(req3_0 & i_req[0])) &
					(~(req3_1 & i_req[1])) &
					(~(req3_2 & i_req[2]));
end
endmodule

Testbench:

`timescale 1ns/1ns
module tb_arbiter4;

reg          clk;
reg          rst_n;
reg  [3:0]   i_req;
wire [3:0]   o_result;


arbiter4 arbiter4_u0(
        .clk        (clk),
        .rst_n      (rst_n),
        .i_req      (i_req),
        .o_result   (o_result)
);

initial begin
        clk     = 1'b0;
        rst_n   = 1'b0;
        i_req   = 4'b0000;

#20     rst_n   = 1'b1;

#10     i_req   = 4'b0101;

#20     i_req   = 4'b1111;
#20     i_req   = 4'b0110;
#20     i_req   = 4'b1100;
end

always #10 clk = ~clk;

endmodule

6、仿真分析

在第一次写测试时是这样写的,导致的波形有一个输入数据4’b1111无效,
以为是哪里有问题,反复检查才发现问题,代码没错。
只是这个数据恰好处在时钟下降沿,所以没处理。简单修改testbench即可。

错误数据输入:手把手Verilog循环优先级仲裁器错误仿真波形:,中间有一个数据被漏掉了。手把手Verilog循环优先级仲裁器正确数据输入:
手把手Verilog循环优先级仲裁器正确波形:,每个输入数据都处理。
手把手Verilog循环优先级仲裁器文章来源地址https://www.toymoban.com/news/detail-473960.html

到了这里,关于手把手Verilog循环优先级仲裁器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 手把手教你实现一个循环队列(C语言)

    这是一道leetcode关于队列的经典题: 622. 设计循环队列 https://leetcode.cn/problems/design-circular-queue/  大家注意这个题目要求,这个队列是定长的,如果满了则不能再添加数据。那么我们设计一个队头front和队尾rear,每次添加数据rear向后走,这时就有一个问题, 怎么区分空和满呢

    2024年02月04日
    浏览(57)
  • 手把手Verilog HDL同步Vaild-Ready握手FIFO机制

    三级目录 V-R握手FIFO机制,即是两级时钟速率不同的模块之间传递信号的机制,上游往下游传递的数据暂时缓存在FIFO中,上游和FIFO、FIFO和下游之间通过握手传递信号。即在一个FIFO模块外层套了一层握手机制。如下图: 如何用Verilog代码实现呢?我们可以这么来做, 1、先实现

    2024年02月16日
    浏览(31)
  • C语言递归+DFS(深度优先搜索算法)详解 图文并茂,手把手教你画树状图

    目录 一.标准定义 二.跳台阶(典型递归题目) 三.递归实现指数型枚举 四.递归实现排列型枚举 五.递归实现组合型枚举 六.DFS算法模板 深度优先搜索算法(Depth First Search,简称DFS): 一种用于遍历或搜索树或图的算法 。 沿着树的深度遍历树的节点, 尽可能深的搜索树的分

    2024年02月04日
    浏览(71)
  • 手把手教你设计字长8位的简单CPU-Verilog实现

    首先声明,所实现的8字长简单CPU所支持的指令不多,结构也很简单,只是演示讲解下如何根据任务书设计一个属于自己的CPU,不喜勿喷,谢谢。 转载请注明出处 作者:雪天鱼 更多博客、资料和业务承接发布在我的个人网站上,欢迎交流学习。 此设计要求来源于一个课程设

    2024年02月05日
    浏览(34)
  • c语言[]优先级大于*优先级

    本博文源于笔者正在学习的c语言[]优先级大于*优先级.在定义二维数组时,a+1与[]号结合后,谁的优先级更高,是本博文探讨的话题 想要看看*与[]谁的优先级更高 通过代码发现[]优先级比*号要高(a+1)[1]等价于a+2再取*号就是9了,在第二个pirintf代码中,等价于a[1][1] =6,第三个

    2024年01月20日
    浏览(57)
  • NVIC 简介、抢占优先级和响应优先级

    NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。 如果医院只有医生的话,当看病的人很多时,医生就得安排一下先看谁,后看谁,如果有紧急的病人,那还得让紧急的病人最先来,这个安排先后次序的任务很繁琐,

    2024年02月05日
    浏览(52)
  • 中断处理优先级和中断响应优先级的区别

      中断响应优先级是针对同时到达的中断请求先处理谁的规定。比如A、B同时向CPU发出中断请求,而中断响应优先级是AB,那么CPU就会先处理A,再处理B。   如下图:   中断处理优先级是解决中断嵌套情况下优先处理谁的问题。比如A、B两个中断的中断处理优先级是BA,

    2024年02月11日
    浏览(39)
  • Android 音频策略(音频优先级,音频输入输入,声音优先级)

    音频设备(/system/core/include/system/audio.h) 注意: 这些设备比较常用的就是HDMI,扬声器,3.5mm圆孔耳机,USB耳机,还有蓝牙耳机。本文也主要针对这些设备的输入和输出策略做出说明。 Android音频策略主要是在 frameworks/av/services/audiopolicy/enginedefault/src/Engine.cpp中,接下来我们看一

    2024年02月04日
    浏览(56)
  • 机械臂多任务逆运动学(优先级同等和存在优先级)

    我们经常使用微分运动学来计算机器人的逆运动学,对于单个任务的机械臂的逆运动学使用的是梯度投影法: 冗余机械臂求解逆运动学解——梯度投影法 但是对于多任务的逆运动学在一般的机器人学里面很少有提及,最近看到了相关的论述,于是做一下笔记整理一下。 设共

    2024年02月16日
    浏览(49)
  • Linux_进程的优先级&&环境变量&&上下文切换&&优先级队列

    什么是优先级? 指定一个进程获取某种资源的先后顺序 本质是进程获取cpu资源的优先顺序 为什么要有优先级 进程访问的资源(CPU)是有限的 操作系统关于调度和优先级的原则:分时操作系统,基本的公平,如果进程因为长时间不被调整,就造成了饥饿问题 Linux的优先级特

    2024年04月09日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包