赞
踩
2023.5.16 天气炎热 最近实验推进一大步
当有多个主设备时,一般同一时刻只有一个主设备可以控制总线,这时候就需要对多个主设备发出的请求进行仲裁。
固定优先级:意味着优先级是固定的,不管有几个主设备同时发出请求,只会响应优先级最高的那一个主设备。例如优先级A>B>C>D,那么如果请求为0011的话,响应的就是C。
该电路是一个组合逻辑电路。
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
固定优先级仲裁器可以用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
轮询算法:当一个request得到了grant许可之后,它的优先级在接下来的仲裁中就变成了最低。每次响应完一个设备后,会对优先级进行更新。
这是一种比较公平的算法,每个设备都可以成为最高优先级。
该电路是时序电路。
最简单的方法是写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
|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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。