ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

一种基于优先级轮询调度负载均衡的crossbar结构

2022-01-17 11:32:35  阅读:170  来源: 互联网

标签:wire 优先级 pointer 轮询 NUMBER WIDTH crossbar POINTER PORT


特点:支持群组路由,端口可配置

主体代码

`timescale 1ns / 1ps
//
// Company: nssc
// Engineer: liumeng
// Create Date:    22:49:51 01/11/2022
// Module Name:    lm_rra_sqr_sync
//
module lm_rra_sqr_sync #(
           parameter PORT_NUMBER            = 4,
           parameter ROW_CLOCKED_NUMBER     = 2,
           parameter COLUMN_CLOCKED_NUMBER  = 2
       )(
           input           clk,
           input           reset,

           input[PORT_NUMBER*PORT_NUMBER-1:0]       port_req_vec,
           output[PORT_NUMBER*PORT_NUMBER-1:0]      port_grant_vec,
           output                                   arb_out_strobe
       );
localparam CLOCKED_NUMBER   = ROW_CLOCKED_NUMBER+COLUMN_CLOCKED_NUMBER+1;//row+column+1
localparam st0_idle         = {{(CLOCKED_NUMBER-1){1'b0}},1'b1};

wire[PORT_NUMBER-1:0]   north                   [PORT_NUMBER-1:0];
wire[PORT_NUMBER-1:0]   south                   [PORT_NUMBER-1:0];
wire[PORT_NUMBER-1:0]   east                    [PORT_NUMBER-1:0];
wire[PORT_NUMBER-1:0]   west                    [PORT_NUMBER-1:0];
wire[PORT_NUMBER-1:0]   east_rt                 [PORT_NUMBER-1:0];//east_rotate
wire[PORT_NUMBER-1:0]   west_rt                 [PORT_NUMBER-1:0];//west_rotate

wire[PORT_NUMBER-1:0]   req                     [PORT_NUMBER-1:0];
wire[PORT_NUMBER-1:0]   grant                   [PORT_NUMBER-1:0];
wire[PORT_NUMBER-1:0]   grant_rt                [PORT_NUMBER-1:0];

reg[PORT_NUMBER-1:0]    r_head;
reg[PORT_NUMBER-1:0]    g_head;
wire[PORT_NUMBER-1:0]   r_head_next;
wire[PORT_NUMBER-1:0]   g_head_next;
wire[PORT_NUMBER-1:0]   any_grant_row;
wire[PORT_NUMBER-1:0]   any_grant_column;

reg[PORT_NUMBER-1:0]    row_reg[ROW_CLOCKED_NUMBER-1:0];
reg[PORT_NUMBER-1:0]    column_reg[COLUMN_CLOCKED_NUMBER-1:0];

wire[PORT_NUMBER-1:0]   any_req_row;
wire any_req;
reg[CLOCKED_NUMBER-1:0]    state;

genvar i,j;
generate
    for (i=0; i<PORT_NUMBER; i=i+1) begin :cell_row
        for (j=0; j<PORT_NUMBER; j=j+1) begin :cell_column
            assign east_rt[j][i]    = east[i][j];
            assign west[j][i]       = west_rt[i][j];
            assign req[i][j]        = port_req_vec[PORT_NUMBER*i+j];
            assign port_grant_vec[PORT_NUMBER*i+j] = grant[i][j];
            assign grant_rt[j][i]   = grant[i][j];

            lm_rra_arb_sync_cell
                u_lm_rra_arb_sync_cell(
                    .north  ( north[i][j]  ),
                    .south  ( south[i][j]  ),
                    .west   ( west[i][j]   ),
                    .east   ( east[i][j]   ),
                    .req    ( req[i][j]    ),
                    .grant  ( grant[i][j]  ),
                    .r_head ( r_head[i]    ),
                    .g_head ( g_head[j]    )
                );
        end

        if (i==0) begin
            assign north[i]     = row_reg[0];
        end else if ((i%(PORT_NUMBER/ROW_CLOCKED_NUMBER))==0) begin
            assign north[i]     = row_reg[i/(PORT_NUMBER/ROW_CLOCKED_NUMBER)];
        end else begin
            assign north[i]     = south[i-1];
        end

        if (i==0) begin
            assign west_rt[i]   = column_reg[0];
        end else if ((i%(PORT_NUMBER/COLUMN_CLOCKED_NUMBER))==0) begin
            assign west_rt[i]   = column_reg[i/(PORT_NUMBER/COLUMN_CLOCKED_NUMBER)];;
        end else begin
            assign west_rt[i]   = east_rt[i-1];
        end

        assign any_grant_row[i] = |grant[i];
        assign any_req_row[i]   = |req[i];

    end

    for (i=0; i<ROW_CLOCKED_NUMBER; i=i+1) begin :loop_row_reg
        always @(posedge clk) begin
            if (reset) begin
                row_reg[i]      <= {PORT_NUMBER{1'b0}};
            end else begin
                row_reg[i]      <= south[(((ROW_CLOCKED_NUMBER-1+i)%ROW_CLOCKED_NUMBER))*
                                    (PORT_NUMBER/ROW_CLOCKED_NUMBER)+(PORT_NUMBER/ROW_CLOCKED_NUMBER)-1];
            end
        end
    end

    for (j=0; j<COLUMN_CLOCKED_NUMBER; j=j+1) begin :loop_column_reg
        always @(posedge clk) begin
            if (reset) begin
                column_reg[j]   <= {PORT_NUMBER{1'b0}};
            end else begin
                column_reg[j]   <= east_rt[(((COLUMN_CLOCKED_NUMBER-1+j)%COLUMN_CLOCKED_NUMBER))*
                                    (PORT_NUMBER/COLUMN_CLOCKED_NUMBER)+(PORT_NUMBER/COLUMN_CLOCKED_NUMBER)-1];
            end
        end
    end

endgenerate

generate
    for (j=0; j<PORT_NUMBER; j=j+1) begin :grant_lolumn_loop
        assign any_grant_column[j] = |grant_rt[j];
    end
endgenerate

always @(posedge clk) begin
    if (reset) begin
        r_head  <= {{(PORT_NUMBER-1){1'b0}},1'b1};//init
        g_head  <= {{(PORT_NUMBER-1){1'b0}},1'b1};//init
    end else if (state[CLOCKED_NUMBER-1]) begin
        r_head  <= r_head_next;
        g_head  <= g_head_next;
    end else begin
        r_head  <= r_head;
        g_head  <= g_head;
    end
end

rra_pointer_cal#(
                   .POINTER_WIDTH  ( PORT_NUMBER   )
               )u_r_head_cal(
                   .pointer_pre    ( r_head        ),
                   .gnt_info       ( any_grant_row ),
                   .pointer_next   ( r_head_next   )
               );

rra_pointer_cal#(
                   .POINTER_WIDTH  ( PORT_NUMBER       )
               )u_g_head_cal(
                   .pointer_pre    ( g_head            ),
                   .gnt_info       ( any_grant_column  ),
                   .pointer_next   ( g_head_next       )
               );

always @(posedge clk) begin
    if (reset) begin
        state    <= st0_idle;
    end else if (state[CLOCKED_NUMBER-1] || (st0_idle && ~any_req)) begin
        state    <= st0_idle;
    end else begin
        state    <= state<<1;
    end
end

assign any_req = |any_req_row;
assign arb_out_strobe = state[CLOCKED_NUMBER-1];

endmodule

子模块lm_rra_arb_sync_cell代码:

`timescale 1ns / 1ps
//
// Company: nssc
// Engineer: liumeng
// Create Date:    09:53:03 01/14/2022 
// Module Name:    lm_rra_arb_sync_cell
//
module lm_rra_arb_sync_cell(
           input       north,
           output      south,
           input       west,
           output      east,

           input       req,
           output      grant,

           input       r_head,
           input       g_head
       );

assign south    = (north | r_head) & (~grant);
assign east     = (west | g_head) & (~grant);
assign grant    = (north | r_head) & (west | g_head) & req;

endmodule

子模块rra_pointer_cal代码:

`timescale 1ns / 1ps
//
// Company: nssc
// Engineer: liumeng
// Create Date:    11:59:08 01/16/2022
// Module Name:    rra_pointer_cal
//
module rra_pointer_cal#(
           parameter POINTER_WIDTH = 4
       )(
           input    [POINTER_WIDTH-1:0]pointer_pre,
           input    [POINTER_WIDTH-1:0]gnt_info,
           output   [POINTER_WIDTH-1:0]pointer_next
       );

wire [POINTER_WIDTH*2-1:0] pointer_mask[POINTER_WIDTH-1:0];
wire [POINTER_WIDTH*2-1:0] gnt_shift;
wire [POINTER_WIDTH*2-1:0] thermo_in,thermo_out;
wire [POINTER_WIDTH*2-1:0] thermo_out_edge;
wire [POINTER_WIDTH*2-1:0] thermo_out_edge_shift;
wire [POINTER_WIDTH-1:0]   pointer_update;
wire [POINTER_WIDTH-1:0]   all_gnt_mask;

wire gnt_none,gnt_full;
assign gnt_none     = gnt_info=={POINTER_WIDTH{1'b0}};
assign all_gnt_mask = pointer_pre|({pointer_pre[0],pointer_pre[POINTER_WIDTH-1:1]});
assign gnt_full     = all_gnt_mask==(all_gnt_mask&gnt_info);

genvar i;
generate
    for (i=0; i<POINTER_WIDTH; i=i+1) begin :loop_pointer_mask
        if (i==0) begin
            assign pointer_mask[i]  = {{POINTER_WIDTH{1'b0}},pointer_pre};
        end else begin
            assign pointer_mask[i]  = pointer_mask[i-1] | (pointer_mask[i-1]<<1);
        end
    end
endgenerate

generate
    for (i=0; i<POINTER_WIDTH*2; i=i+1) begin :loop_gnt_shift
        if (i<POINTER_WIDTH ) begin
            assign gnt_shift[i] = gnt_info[i];
        end else begin
            assign gnt_shift[i] = gnt_info[i-POINTER_WIDTH];
        end
    end
endgenerate

assign thermo_in = gnt_shift&pointer_mask[POINTER_WIDTH-1];//全零待处理

inv_thermo_encoder#(
                      .WIDTH        ( POINTER_WIDTH*2   )
                  )u_inv_thermo_encoder(
                      .in           ( thermo_in         ),
                      .thermo_out   ( thermo_out        )
                  );

assign thermo_out_edge          = thermo_out^(thermo_out>>1);
assign thermo_out_edge_shift    = thermo_out_edge<<1;

assign pointer_update   = thermo_out_edge_shift[POINTER_WIDTH-1:0]|thermo_out_edge_shift[POINTER_WIDTH*2-1:POINTER_WIDTH];
assign pointer_next     = gnt_full ? {pointer_pre[POINTER_WIDTH-2:0],pointer_pre[POINTER_WIDTH-1]} :
       gnt_none ? pointer_pre : pointer_update;

endmodule

子模块inv_thermo_encoder代码:

`timescale 1ns / 1ps
//
// Company: nssc
// Engineer: liumeng
// Create Date:    20:13:45 01/11/2022
// Module Name:    inv_thermo_encoder
// Revision 0.01 - File Created
//
module inv_thermo_encoder#(parameter WIDTH = 8)
       (
           input[WIDTH-1 : 0]   in,
           output[WIDTH-1 : 0]  thermo_out
       );

genvar i;
generate
    for(i=WIDTH-1;i>=0;i=i-1)begin :loop
        assign thermo_out[i] = |in[WIDTH-1:i];
    end
endgenerate

endmodule

测试文件代码:

`timescale 1ns / 1ps
//
// Company: nssc
// Engineer: liumeng
// Create Date:    00:15:23 01/12/2022
// Module Name:    sim_lm_rra_sqr_sync
//
module sim_lm_rra_sqr_sync;
parameter PORT_NUMBER               = 4;
parameter ROW_CLOCKED_NUMBER        = 2;
parameter COLUMN_CLOCKED_NUMBER     = 2;

integer seed_dis;
reg clk;
reg reset;
reg enable;
wire [PORT_NUMBER*PORT_NUMBER-1:0] port_req_vec;
wire arb_out_strobe;
wire[1:0]   RG_VEC [PORT_NUMBER*PORT_NUMBER-1:0];

// Outputs
wire [PORT_NUMBER*PORT_NUMBER-1:0] port_grant_vec;
reg[PORT_NUMBER-1:0] port_req [PORT_NUMBER-1:0];
wire[PORT_NUMBER-1:0] port_grant [PORT_NUMBER-1:0];
wire[PORT_NUMBER-1:0] any_grant;
wire[PORT_NUMBER-1:0] any_req;
wire any_port_req;

genvar i,j,k;
generate
    for (i=0; i<PORT_NUMBER; i=i+1) begin
        for (j=0; j<PORT_NUMBER; j=j+1) begin
            assign port_req_vec[PORT_NUMBER*i+j]    = port_req[i][j];
            assign port_grant[i][j] = port_grant_vec[PORT_NUMBER*i+j];

        end

        assign any_grant[i] = |port_grant[i];//i输入被许可
        assign any_req[i]   = |port_req[i];

        always @(posedge clk) begin
            if (reset) begin
                port_req[i]  <= {PORT_NUMBER{1'b0}};
            end else if (enable) begin
                if (arb_out_strobe || (~any_port_req)) begin
                    port_req[i]  <= $dist_uniform(seed_dis, 0, {PORT_NUMBER{1'b1}});
                end else begin
                    port_req[i]  <= port_req[i];
                end
            end else begin
                if (arb_out_strobe) begin
                    port_req[i]  <= {PORT_NUMBER{1'b0}};
                end else begin
                    port_req[i]  <= port_req[i];
                end
            end
        end

    end
endgenerate

generate
    for (k=0; k<PORT_NUMBER*PORT_NUMBER; k=k+1) begin
        assign RG_VEC[k] = {port_req_vec[k],port_grant_vec[k]};
    end
endgenerate

assign any_port_req = |any_req;

initial begin
    clk = 0;
    reset = 0;
    #200;
    reset = 1;
    #500;
    reset = 0;
end
always #15 clk = ~clk;

initial begin
    enable = 0;
    seed_dis = 99;
    #6000;
    enable = 1;
    #30000;
    enable = 0;
    #10000;
    enable = 1;
    #30000;
    enable = 0;

end

lm_rra_sqr_sync#(
    .PORT_NUMBER            ( PORT_NUMBER           ),
    .ROW_CLOCKED_NUMBER     ( ROW_CLOCKED_NUMBER    ),
    .COLUMN_CLOCKED_NUMBER  ( COLUMN_CLOCKED_NUMBER )
)u_lm_rra_sqr_sync(
    .clk                    ( clk                   ),
    .reset                  ( reset                 ),
    .port_req_vec           ( port_req_vec          ),
    .port_grant_vec         ( port_grant_vec        ),
    .arb_out_strobe         ( arb_out_strobe        )
);

endmodule

测试结果:

可见支持群组路由,满足输入请求轮询和输出负载均衡。 

标签:wire,优先级,pointer,轮询,NUMBER,WIDTH,crossbar,POINTER,PORT
来源: https://blog.csdn.net/f601323135/article/details/122535685

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有