【Verilog-CBB】开发与验证(7)——固定优先级仲裁器



引言

仲裁器的应用场景非常多,特别是在一些多主多从的应用场景中,同时有多个设备有请求时,优先响应哪一个呢?比如总线的使用、内存的访问。仲裁器系列本文先开个头说一下固定优先级仲裁器的设计。

既然讲到设计,那么就先说一下设计的要求。

1、仲裁模块的请求数量在模块例化时可配置;

2、仲裁的优先级bit0 > bit1 >……>bit N-1;

3、发起请求的一方,在总线使用完毕后发送done信号(一个时钟高电平)给仲裁器告知。

4、请求获得仲裁后需要在下个时钟周期拉低req信号。

CBB设计

固定优先级仲裁器设计的关键在于,确定诸多请求中,优先级最高的那一个。比如req = 4'b1011,此时grant=4'b0001,即确定req信号中最低位的1。按照这个思路将req与其补码按位相与即可。

grant = req & (~req + 1'b1) 或者 grant = req & ~(req - 1'b1)

还有一种思路,grant[i]可以拉高的条件是,req[i]为高并且req[i-1:0]为低。但是i=0时比较特殊,grant[0] = req[0],所以grant的逻辑是这样的:

grant[0] = req[0];

grant[i] = req[i] & ~(|req[i-1:0]);

两种思路都可以。

参数P_LOGIC_SEL:配置CASE1时,为思路1的逻辑;CASE2时为思路2的逻辑。

// ==================-------------------------------------------------------=====================
//                                        在路上-正出发
//                                    Common Building Block
// ==================-------------------------------------------------------=====================

//                 ________          ________          ________                                                               
//                |\   ____\        |\   __  \        |\   __  \                                                              
//                \ \  \___|        \ \  \|\ /_       \ \  \|\ /_                                                             
//                 \ \  \            \ \   __  \       \ \   __  \                                                            
//                  \ \  \____        \ \  \|\  \       \ \  \|\  \                                                           
//                   \ \_______\       \ \_______\       \ \_______\                                                          
//                    \|_______|        \|_______|        \|_______|  

// ==================-------------------------------------------------------=====================
//                                        在路上-正出发
//                                    Common Building Block
// ==================-------------------------------------------------------=====================                                                                                                              
                                                                                                                                                                                                                                                                                                         
// CBB Module Name    :CBB_FIXED_ARBITER
// CBB Created Date   :2024-08-18
// CBB Module Function:固定优先级仲裁器
// Usage Limitation   :
// Author             :在路上-正出发
// -----------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------

`timescale 1ns/1ps

module  CBB_FIXED_ARBITER#(
// ---- parameter define
parameter P_LOGIC_SEL = "CASE2", // "CASE1" "CASE2"
parameter P_REQ_NUM   = 8
)(
// ---- port define 
input 						i_clk,
input 						i_rstn,

input [P_REQ_NUM-1:0] 		i_req,
output[P_REQ_NUM-1:0] 		o_grant,//one-hot 

input[P_REQ_NUM-1:0] 		i_done //持续1个时钟周期的脉冲 one-hot

);

wire 						w_req_or = |i_req;
reg  [1:0] 					r_req_or;
always @(posedge i_clk or negedge i_rstn) begin : proc_req
	if(~i_rstn) begin
		 r_req_or <= 2'b0;
	end else begin
		 r_req_or <= {r_req_or[0],w_req_or};
	end
end

wire 						w_req_or_pos = r_req_or[0] & (~r_req_or[1]);
reg [P_REQ_NUM-1:0] 		r_grant;
generate
genvar i;
	if(P_LOGIC_SEL == "CASE1") begin
		always @(posedge i_clk or negedge i_rstn) begin : proc_grant
			if(~i_rstn) begin
			 	r_grant <= {P_REQ_NUM{1'b0}};
			end else if(w_req_or_pos | |i_done)begin
			 	r_grant <= i_req & (~(i_req-1));
			end
		end
	end
	else begin
		for(i=0;i<P_REQ_NUM;i=i+1) begin
			if(i==0) begin
				always @(posedge i_clk or negedge i_rstn) begin : proc_grant_0
					if(~i_rstn) begin
					 	r_grant[i] <= 1'b0;
					end else if(w_req_or_pos | |i_done)begin
					 	r_grant[i] <= i_req[i];
					end
				end
		 	end
		 	else begin
		 		always @(posedge i_clk or negedge i_rstn) begin : proc_grant_other
					if(~i_rstn) begin
					 	r_grant[i] <= 1'b0;
					end else if(w_req_or_pos | |i_done)begin
					 	r_grant[i] <= i_req[i] & ~(|i_req[i-1:0]);
					end
				end
		 	end
		end
	end
endgenerate

assign o_grant = r_grant;
endmodule

CBB验证

验证源码

// ==================-------------------------------------------------------=====================
//                                        在路上-正出发
//                                    Common Building Block
// ==================-------------------------------------------------------=====================

//                 ________          ________          ________                                                               
//                |\   ____\        |\   __  \        |\   __  \                                                              
//                \ \  \___|        \ \  \|\ /_       \ \  \|\ /_                                                             
//                 \ \  \            \ \   __  \       \ \   __  \                                                            
//                  \ \  \____        \ \  \|\  \       \ \  \|\  \                                                           
//                   \ \_______\       \ \_______\       \ \_______\                                                          
//                    \|_______|        \|_______|        \|_______|  

// ==================-------------------------------------------------------=====================
//                                        在路上-正出发
//                                    Common Building Block
// ==================-------------------------------------------------------=====================                                                                                                              
                                                                                                                                                                                                                                                                                                         
// CBB Module Name    :TB_FIXED_ARBITER
// CBB Created Date   :
// CBB Module Function:
// Usage Limitation   :
// Author             :在路上-正出发
// -----------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------

`timescale 1ns/1ps

module  TB_FIXED_ARBITER();
// ---- parameter define
parameter P_LOGIC_SEL = "CASE1"; // "CASE1" "CASE2"
parameter P_REQ_NUM   = 8;

// ---- port define 
reg 						i_clk;
reg 						i_rstn;

reg [P_REQ_NUM-1:0] 		i_req;
wire[P_REQ_NUM-1:0] 		o_grant;//one-hot 

reg [P_REQ_NUM-1:0] 		i_done; //持续1个时钟周期的脉冲 one-hot


initial i_clk = 1'b0;
always #5 i_clk = ~i_clk;

integer time_dly1 ,sim_cnt;

initial
begin
	i_rstn = 1'b0;
	i_req  = 0;
	i_done = 0;
	sim_cnt = 0;
	#100;
	i_rstn = 1'b1;
	#200;
	while((sim_cnt < 60) || (|i_req))
	begin
		@(posedge i_clk)
		if(|i_req == 0) begin i_req <= $random() % 2**P_REQ_NUM; sim_cnt = sim_cnt + 1;end
		while(~(|o_grant)) @(posedge i_clk);
		i_req <= i_req & (~o_grant);
		time_dly1 = $urandom_range(40,50);
		repeat(time_dly1) @(posedge i_clk);
		i_done <= {P_REQ_NUM{1'b1}}& o_grant;
		@(posedge i_clk)
		i_done <= {P_REQ_NUM{1'b0}};
	end 
	#200;
	$finish;
end

CBB_FIXED_ARBITER #(
		.P_LOGIC_SEL(P_LOGIC_SEL),
		.P_REQ_NUM(P_REQ_NUM)
	) U_CBB_FIXED_ARBITER (
		.i_clk   (i_clk),
		.i_rstn  (i_rstn),
		.i_req   (i_req),
		.o_grant (o_grant),
		.i_done  (i_done)
	);

endmodule

波形

CBB综合

CASE1

CASE2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在路上-正出发

哈哈,多少是个心意

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值