verilog手撕代码7——固定优先级仲裁器和轮询仲裁器


前言

2023.5.16 天气炎热 最近实验推进一大步


一、固定优先级仲裁器/Fixed Priority Arbiter

当有多个主设备时,一般同一时刻只有一个主设备可以控制总线,这时候就需要对多个主设备发出的请求进行仲裁。

固定优先级:意味着优先级是固定的,不管有几个主设备同时发出请求,只会响应优先级最高的那一个主设备。例如优先级A>B>C>D,那么如果请求为0011的话,响应的就是C。

该电路是一个组合逻辑电路

1、case/if语句实现

module fixed_arb(
	input  [3:0] request,
	output [3:0] grant_reg
);

	//case语句会被综合成串行结构
	always@(*)begin
		case(1'b1)   //第一次见case1这种写法
			request[3] : grant_reg = 4'b1000;
			request[2] : grant_reg = 4'b0100;
			request[1] : grant_reg = 4'b0010;
			request[0] : grant_reg = 4'b0001;
			default: grant_reg = 4'b0000;
		endcase
	end

	//此处也可以使用if-else结构
	always@(*)begin
		if(request[3]) 
			grant_reg = 4'b1000;
		else if(request[2])
			grant_reg = 4'b0100;
		else if(request[1])
			grant_reg = 4'b0010;
		else if(request[1])
			grant_reg = 4'b0001;
		else
			grant_reg = 4'b0000;
	end

endmodule

2、for循环语句实现参数化结构

固定优先级仲裁器可以用if或case语句实现,case语句实现起来更为简单,假如要实现参数化的固定优先级仲裁器的话,case语句就不行了,就必须使用for循环。

下面代码:最低位的优先级最高

module fixed_pri_arb#(parameter REQ_WIDTH = 16)(
	input [REQ_WIDTH-1:0] req,
	output reg [REQ_WIDTH-1:0] grant
);
	
	reg [REQ_WIDTH-1] pre_req;//为了记录低位是否已经有了request
	
	always@(*)begin
		grant[0] = req[0];
		pre_req[0] = req[0];
		for(i = 1; i<REQ_WIDTH; i=i+1)begin
			grant[i] = req[i] & ~pre_req[i-1];  
			pre_req[i] = req[i] | pre_req[i-1];
		end
	
	end
endmodule	

二、轮询仲裁器/Round Robin Arbiter

轮询算法:当一个request得到了grant许可之后,它的优先级在接下来的仲裁中就变成了最低。每次响应完一个设备后,会对优先级进行更新。

这是一种比较公平的算法,每个设备都可以成为最高优先级。

该电路是时序电路

1、case语句实现

最简单的方法是写case语句。直接对输出状态进行判断,输出是哪个主设备,那么它会变成优先级最低的,依次类推,但是这样代码写起来就比较复杂,且不容易进行移植。

module round_robin_bus_arbiter(
			input clk,
			input rst_n,
			input [2:0] req, //假如需要给3个主机分配总线
			output reg [1:0] grant_out //2'b00 A获得总线, 2‘b01 B获得总线 , 2'10 c获得总线
			);
			
			
			always @ (posedge clk or negedge rst_n)
				begin
					if (!rst_n)
						grant_out <= 1'b11;
					else
						case(grant_out)   //根据输出来进行判断
							2'b00: //之前A获得总线
								case (req)
									3'b000:	grant_out <= 2'b00;
									3'b001:	grant_out <= 2'b00;
									3'b010: grant_out <= 2'b01;
									3'b011:	grant_out <= 2'b01;
									3'b100:	grant_out <= 2'b10;
									3'b101: grant_out <= 2'b10;
									3'b110: grant_out <= 2'b01;
									3'b111: grant_out <= 2'b01;
									default: grant_out <= 2'b00;
								endcase
							2'b01: //之前B获得总线
								case (req)
									3'b000:	grant_out <= 2'b01;
									3'b001:	grant_out <= 2'b00;
									3'b010: grant_out <= 2'b01;
									3'b011:	grant_out <= 2'b00;
									3'b100:	grant_out <= 2'b10;
									3'b101: grant_out <= 2'b10;
									3'b110: grant_out <= 2'b01;
									3'b111: grant_out <= 2'b01;
									default: grant_out <= 2'b01;
								endcase
							2'b10: //之前C获得总线
								case (req)
									3'b000:	grant_out <= 2'b10;
									3'b001:	grant_out <= 2'b00;
									3'b010: grant_out <= 2'b01;
									3'b011:	grant_out <= 2'b00;
									3'b100:	grant_out <= 2'b10;
									3'b101: grant_out <= 2'b00;
									3'b110: grant_out <= 2'b01;
									3'b111: grant_out <= 2'b00;
									default: grant_out <= 2'b10;
								endcase
							default: grant_out <= 2'b00;
						endcase
								
				end	
endmodule

2、for循环实现

|request:表示此刻有主设备请求,因而去更新

module round_robin_arb(
    input   clk         ,
    input   rst_n       ,
    
    input  [3:0] request,
    output [3:0] grant
);

    reg  [3:0] last_state;  
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            last_state <= 4'b0001;  //优先级默认值,最低位最高优先级
        else 
            last_state <= (|request) ? {grant[2:0],grant[3]} : last_state; 
	end

    // 此处通过两个request拼接,将右侧低位拼接到左侧,即可实现对低位的判断。
    wire [7:0] grant_ext;
    assign grant_ext = {request,request} & ~({request,request} - last_state);

    // 得到的grant_ext必定为一个独热码,但是置高位可能在代表低位的高4bit中,因此进行求或运算
    assign grant = grant_ext[3:0] | grant_ext[7:4];

endmodule
  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Verilog中的固定优先级仲裁器是一种用于解决多个请求的优先级冲突的电路设计。它根据预先定义的优先级规则来确定哪个请求应该被优先处理。 在Verilog中实现固定优先级仲裁器可以采用以下步骤: 1. 创建一个包含多个请求输入的模块。每个请求输入都与一个请求信号相关联,表示该请求是否被激活。 2. 为每个请求输入定义一个优先级。可以使用参数或常量来指定每个请求的优先级。 3. 使用条件语句(if-else或case语句)来比较每个请求的优先级,并根据优先级激活相应的输出。 4. 确定输出信号的逻辑。可以使用一个输出信号表示选中的请求,或者使用多个输出信号来表示每个请求的状态。 下面是一个简单的Verilog代码示例,演示了一个4个请求的固定优先级仲裁器: ```verilog module priority_arbiter ( input [3:0] requests, output [1:0] selected ); // 定义请求的优先级 parameter PRIORITY_0 = 2'b00; parameter PRIORITY_1 = 2'b01; parameter PRIORITY_2 = 2'b10; parameter PRIORITY_3 = 2'b11; always @* begin // 比较请求的优先级 case (requests) 4'b0001: selected = PRIORITY_0; 4'b0010: selected = PRIORITY_1; 4'b0100: selected = PRIORITY_2; 4'b1000: selected = PRIORITY_3; default: selected = 2'b00; // 如果没有请求被激活,输出为0 endcase end endmodule ``` 在上述代码中,`requests`是一个4位的输入信号,每个位表示一个请求。`selected`是一个2位的输出信号,表示被选中的请求。 这只是一个简单的示例,实际应用中的固定优先级仲裁器可能更加复杂。可以根据具体的需求进行相应的修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值