首页 > 技术文章 > 平等仲裁之循环优先级控制器

wzx19970918 2021-06-12 18:25 原文

一、功能描述

利用循环优先级算法,每次从不同的起点开始,采用轮询方式查看各个通道是否有请求,优先响应先查到的设备。由于起点是依次变化的,所以每个设备总体来说具有相同的优先级。具体算法可用下面的图表示。
在这里插入图片描述

二、设计方法

定义一个轮询起点(CHK)的计数器。CHK在每次s_drq(表示请求有效)有效期结束(设计了一个下降沿捕获器count_en=!s_drq&&s_drq_delay作为CHK的计数使能,其中s_drq_delay为s_drq延迟一个周期的信号)时加1,加到7后返回0继续加。

定义一个优先级译码器,根据当前的轮询起点计数CHK轮询各个设备的访问请求信号drq[7:0],产生所选择设备的编号sel[2:0]和编号有效信号sel_en输出。

优先级译码器的算法如下:

  • CHK=000 查询顺序:0→1→2→3→4→5→6→7
  • CHK=001 查询顺序:1→2→3→4→5→6→7→0
  • CHK=010 查询顺序:2→3→4→5→6→7→0→1
  • CHK=011 查询顺序:3→4→5→6→7→0→1→2
  • CHK=100 查询顺序:4→5→6→7→0→1→2→3
  • CHK=101 查询顺序:5→6→7→0→1→2→3→4
  • CHK=110 查询顺序:6→7→0→1→2→3→4→5
  • CHK=111 查询顺序:7→0→1→2→3→4→5→6

模块结构示意图如下图所示:
在这里插入图片描述

三、代码设计

注意,除了时钟和复位,其余端口信号都是低有效!!!

module priority_control(
    input        clk,
    input        reset,
    input        s_drq,//低有效,此时有drq请求,表示优先级控制器可以开始工作了
    input   [7:0]drq,//8通道访问请求信号,低有效,来自请求者
    output  reg [2:0]sel,//根据优先级算法最终选择的通道号
    output  reg   sel_en//标志sel信号此时有效,低有效
    );


    reg 		[2:0]	num;
    reg		    s_drq_delay;
    wire        count_en;



always@(posedge clk or posedge reset)
begin
	if(reset)
		s_drq_delay<=1;
	else
		s_drq_delay<=s_drq;
end

//检测到s_drq下降沿就开始工作
assign count_en=(!s_drq&s_drq_delay);

//优先级计数
always@(posedge clk or posedge reset)
begin
	if(reset)
		num<=0;
	else if(count_en)
	begin
		if(num==7)
			num<=0;
		else
			num<=num+1;
	end
end



always@(posedge clk or posedge reset)
begin
	if(reset)
		begin
			sel<=3'bzzz;
			sel_en<=1'b1;
		end
	else if(!count_en)
		begin
			sel<=3'bzzz;
			sel_en<=1'b1;
		end
	else if(num==0)
		begin
			if(drq[0]==1'b0) 
				begin 
					sel<=0; 
					sel_en<=0; 
				end
			else if(drq[1]==1'b0)
				begin
					sel<=1;
					sel_en<=0;
				end
			else if(drq[2]==1'b0)
				begin
					sel<=2;
					sel_en<=0;
				end
			else if(drq[3]==1'b0)
				begin
					sel<=3;
					sel_en<=0;
				end
			else if(drq[4]==1'b0)
				begin
					sel<=4;
					sel_en<=0;
				end
			else if(drq[5]==1'b0)
				begin
					sel<=5;
					sel_en<=0;
				end
			else if(drq[6]==1'b0)
				begin
					sel<=6;
					sel_en<=0;
				end
			else if(drq[7]==1'b0)
				begin
					sel<=7;
					sel_en<=0;
				end
		end
	else if(num==1)
		begin
			if(drq[1]==1'b0)
				begin
					sel<=1;
					sel_en<=0;
				end
			else if(drq[2]==1'b0)
				begin
					sel<=2;
					sel_en<=0;
				end
			else if(drq[3]==1'b0)
				begin
					sel<=3;
					sel_en<=0;
				end
			else if(drq[4]==1'b0)
				begin
					sel<=4;
					sel_en<=0;
				end
			else if(drq[5]==1'b0)
				begin
					sel<=5;
					sel_en<=0;
				end
			else if(drq[6]==1'b0)
				begin
					sel<=6;
					sel_en<=0;
				end
			else if(drq[7]==1'b0)
				begin
					sel<=7;
					sel_en<=0;
				end
			else if(drq[0]==1'b0) 
				begin 
					sel<=0; 
					sel_en<=0; 
				end
		end
	else if(num==2)
		begin
			if(drq[2]==1'b0)
				begin
					sel<=2;
					sel_en<=0;
				end
			else if(drq[3]==1'b0)
				begin
					sel<=3;
					sel_en<=0;
				end
			else if(drq[4]==1'b0)
				begin
					sel<=4;
					sel_en<=0;
				end
			else if(drq[5]==1'b0)
				begin
					sel<=5;
					sel_en<=0;
				end
			else if(drq[6]==1'b0)
				begin
					sel<=6;
					sel_en<=0;
				end
			else if(drq[7]==1'b0)
				begin
					sel<=7;
					sel_en<=0;
				end
			else if(drq[0]==1'b0) 
				begin 
					sel<=0; 
					sel_en<=0; 
				end
			else if(drq[1]==1'b0)
				begin
					sel<=1;
					sel_en<=0;
				end
		end
	else if(num==3)
		begin
			if(drq[3]==1'b0)
				begin
					sel<=3;
					sel_en<=0;
				end
			else if(drq[4]==1'b0)
				begin
					sel<=4;
					sel_en<=0;
				end
			else if(drq[5]==1'b0)
				begin
					sel<=5;
					sel_en<=0;
				end
			else if(drq[6]==1'b0)
				begin
					sel<=6;
					sel_en<=0;
				end
			else if(drq[7]==1'b0)
				begin
					sel<=7;
					sel_en<=0;
				end
			else if(drq[0]==1'b0) 
				begin 
					sel<=0; 
					sel_en<=0; 
				end
			else if(drq[1]==1'b0)
				begin
					sel<=1;
					sel_en<=0;
				end
			else if(drq[2]==1'b0)
				begin
					sel<=2;
					sel_en<=0;
				end
		end
	else if(num==4)
		begin
			if(drq[4]==1'b0)
				begin
					sel<=4;
					sel_en<=0;
				end
			else if(drq[5]==1'b0)
				begin
					sel<=5;
					sel_en<=0;
				end
			else if(drq[6]==1'b0)
				begin
					sel<=6;
					sel_en<=0;
				end
			else if(drq[7]==1'b0)
				begin
					sel<=7;
					sel_en<=0;
				end
			else if(drq[0]==1'b0) 
				begin 
					sel<=0; 
					sel_en<=0; 
				end
			else if(drq[1]==1'b0)
				begin
					sel<=1;
					sel_en<=0;
				end
			else if(drq[2]==1'b0)
				begin
					sel<=2;
					sel_en<=0;
				end
			else if(drq[3]==1'b0)
				begin
					sel<=3;
					sel_en<=0;
				end
		end
	else if(num==5)
		begin
			if(drq[5]==1'b0)
				begin
					sel<=5;
					sel_en<=0;
				end
			else if(drq[6]==1'b0)
				begin
					sel<=6;
					sel_en<=0;
				end
			else if(drq[7]==1'b0)
				begin
					sel<=7;
					sel_en<=0;
				end
			else if(drq[0]==1'b0) 
				begin 
					sel<=0; 
					sel_en<=0; 
				end
			else if(drq[1]==1'b0)
				begin
					sel<=1;
					sel_en<=0;
				end
			else if(drq[2]==1'b0)
				begin
					sel<=2;
					sel_en<=0;
				end
			else if(drq[3]==1'b0)
				begin
					sel<=3;
					sel_en<=0;
				end
			else if(drq[4]==1'b0)
				begin
					sel<=4;
					sel_en<=0;
				end
			 
		end
	else if(num==6)
		begin
			if(drq[6]==1'b0)
				begin
					sel<=6;
					sel_en<=0;
				end
			else if(drq[7]==1'b0)
				begin
					sel<=7;
					sel_en<=0;
				end
			else if(drq[0]==1'b0) 
				begin 
					sel<=0; 
					sel_en<=0; 
				end
			else if(drq[1]==1'b0)
				begin
					sel<=1;
					sel_en<=0;
				end
			else if(drq[2]==1'b0)
				begin
					sel<=2;
					sel_en<=0;
				end
			else if(drq[3]==1'b0)
				begin
					sel<=3;
					sel_en<=0;
				end
			else if(drq[4]==1'b0)
				begin
					sel<=4;
					sel_en<=0;
				end
			 else if(drq[5]==1'b0)
				begin
					sel<=5;
					sel_en<=0;
				end
		end
	else if(num==7)
		begin
			if(drq[7]==1'b0)
				begin
					sel<=7;
					sel_en<=0;
				end
			else if(drq[0]==1'b0) 
				begin 
					sel<=0; 
					sel_en<=0; 
				end
			else if(drq[1]==1'b0)
				begin
					sel<=1;
					sel_en<=0;
				end
			else if(drq[2]==1'b0)
				begin
					sel<=2;
					sel_en<=0;
				end
			else if(drq[3]==1'b0)
				begin
					sel<=3;
					sel_en<=0;
				end
			else if(drq[4]==1'b0)
				begin
					sel<=4;
					sel_en<=0;
				end
			 else if(drq[5]==1'b0)
				begin
					sel<=5;
					sel_en<=0;
				end
			else if(drq[6]==1'b0)
				begin
					sel<=6;
					sel_en<=0;
				end
		end
end
endmodule

四、功能仿真

//~ `New testbench
`timescale  1ns / 1ps

module tb_priority_control;

// priority_control Parameters
parameter PERIOD  = 10;


// priority_control Inputs
reg   clk                                  = 0 ;
reg   reset                                = 1 ;
reg   s_drq                                = 1 ;
reg   [7:0]  drq                           = 8'b11111111 ;

// priority_control Outputs
wire  [2:0]  sel                           ;    
wire  sel_en                               ;    


initial
begin
    forever #(PERIOD/2)  clk=~clk;
end

initial
begin
    #(PERIOD*2) reset  =  0;
end

priority_control  u_priority_control (
    .clk                     ( clk           ),
    .reset                   ( reset         ),
    .s_drq                   ( s_drq         ),
    .drq                     ( drq     [7:0] ),

    .sel                     ( sel     [2:0] ),
    .sel_en                  ( sel_en        )
);

reg [5:0]cnt;
always@(posedge	clk or negedge	reset)
		begin
			if(reset)
				begin
					drq = 8'b11111111 ;
                    s_drq <= 1;
					cnt <= 0;
				end
			/*****************************/
			else	if(cnt < 1)
				begin
                    //#2
					drq = 8'b11101111 ;
                    s_drq <= 1;
					cnt <= cnt + 1;
				end
            else	if(cnt < 5)
				begin
                    //#2
					drq = 8'b11101111 ;
                    s_drq <= 0;
					cnt <= cnt + 1;
				end
			else	if(cnt < 6)
				begin
                    //#2
					drq = 8'b11101111 ;
                    s_drq <= 1;
					cnt <= cnt + 1;
				end
			/*****************************/
			else	if(cnt < 7)
				begin
                    //#2
					drq = 8'b11101111 ;
                    s_drq <= 1;
					cnt <= cnt + 1;
				end
            else	if(cnt < 11)
				begin
                    //#2
					drq = 8'b11101111 ;
                    s_drq <= 0;
					cnt <= cnt + 1;
				end
			else	if(cnt < 12)
				begin
                    //#2
					drq = 8'b11101111 ;
                    s_drq <= 1;
					cnt <= cnt + 1;
				end
			/*****************************/
			else	if(cnt < 13)
				begin
                    //#2
					drq = 8'b00000000 ;
                    s_drq <= 1;
					cnt <= cnt + 1;
				end
            else	if(cnt < 17)
				begin
                    //#2
					drq = 8'b00000000 ;
                    s_drq <= 0;
					cnt <= cnt + 1;
				end
			else	if(cnt < 18)
				begin
                    //#2
					drq = 8'b00000000 ;
                    s_drq <= 1;
					cnt <= cnt + 1;
				end
			/*****************************/
			else	if(cnt < 19)
				begin
                    //#2
					drq = 8'b00000000 ;
                    s_drq <= 1;
					cnt <= cnt + 1;
				end
            else	if(cnt < 23)
				begin
                    //#2
					drq = 8'b00000000 ;
                    s_drq <= 0;
					cnt <= cnt + 1;
				end
	        else	if(cnt < 24)
				begin
                    //#2
					drq = 8'b00000000 ;
                    s_drq <= 1;
					cnt <= cnt + 1;
				end
			/*****************************/
			else	if(cnt < 25)
				begin
                    //#2
					drq = 8'b01111111 ;
                    s_drq <= 1;
					cnt <= cnt + 1;
				end
            else	if(cnt < 29)
				begin
                    //#2
					drq = 8'b01111111 ;
                    s_drq <= 0;
					cnt <= cnt + 1;
				end
			else	if(cnt < 30)
				begin
                    //#2
					drq = 8'b01111111 ;
                    s_drq <= 1;
					cnt <= cnt + 1;
				end
			/*****************************/
			else	if(cnt < 31)
				begin
                    //#2
					drq = 8'b10111111 ;
                    s_drq <= 1;
					cnt <= cnt + 1;
				end
            else	if(cnt < 35)
				begin
                    //#2
					drq = 8'b10111111 ;
                    s_drq <= 0;
					cnt <= cnt + 1;
				end
			else	if(cnt < 36)
				begin
                    //#2
					drq = 8'b10111111 ;
                    s_drq <= 1;
					cnt <= cnt + 1;
				end
			/*****************************/
			else
				begin
					drq = 8'b11111111 ;
                    s_drq <= 1;
					cnt <= 0;
					$finish;
				end
		end

endmodule

在这里插入图片描述

推荐阅读