axis_bus 全链接 V2

module axis_bus#(
    parameter   DATA_WIDTH          =   32              ,
    parameter   ID_WIDTH            =   8               ,
    parameter   S_NUM               =   16              ,
    parameter   M_NUM               =   16              ,
    parameter   AHEAD               =   {(S_NUM > M_NUM ? S_NUM : M_NUM){1'b1}}//1 : valid is first ; 0 : ready is first
)(
    input                           i_clk               ,
    input                           i_rst               ,

    output  [S_NUM-1:0]             s_axis_ready        ,
    input   [S_NUM-1:0]             s_axis_valid        ,
    input   [S_NUM-1:0]             s_axis_last         ,
    input   [S_NUM*DATA_WIDTH-1:0]  s_axis_data         ,
    input   [S_NUM*ID_WIDTH-1:0]    s_axis_sid          ,
    input   [S_NUM*ID_WIDTH-1:0]    s_axis_did          ,

    input   [M_NUM-1:0]             m_axis_ready        ,
    output  [M_NUM-1:0]             m_axis_valid        ,
    output  [M_NUM-1:0]             m_axis_last         ,
    output  [M_NUM*DATA_WIDTH-1:0]  m_axis_data         ,
    input   [M_NUM*ID_WIDTH-1:0]    m_axis_sid          ,
    output  [M_NUM*ID_WIDTH-1:0]    m_axis_did          
);
//-----------------------------------------------------------------
wire        [S_NUM-1:0]             comp_S_did_miss     ;
wire        [S_NUM*M_NUM-1:0]       comp_S              ;
wire        [S_NUM*M_NUM-1:0]       comp_M              ;
wire        [S_NUM-1:0]             arb_p[M_NUM-1:0]    ;
reg         [S_NUM-1:0]             arb[M_NUM-1:0]      ;
reg         [ID_WIDTH:0]            mem_hitsc[M_NUM-1:0];
//-----------------------------------------------------------------
id_compare#(
    .ID_WIDTH               (ID_WIDTH               ),
    .S_NUM                  (S_NUM                  ),
    .M_NUM                  (M_NUM                  )
    
)id_compare(
    .i_clk                  (i_clk                  ),
    .i_rst                  (i_rst                  ),
    .s_axis_valid           (s_axis_valid | ~AHEAD  ),
    .s_axis_did             (s_axis_did             ),
    .m_axis_ready           (m_axis_ready | AHEAD   ),
    .m_axis_sid             (m_axis_sid             ),
    .comp_S_did_miss        (comp_S_did_miss        ),
    .comp_S                 (comp_S                 ),
    .comp_M                 (comp_M                 ));
//========================================================================================================
genvar  s,m,i,j,k,n;generate for(m=0;m<M_NUM;m=m+1)begin: MC//send channel

    wire    [S_NUM-1:0]     req                     ;
    reg     [S_NUM-1:0]     weight                  ;
    reg     [7:0]           weight_clear            ;

    wire    [DATA_WIDTH-1:0]s_data      [S_NUM-1:0] ;
    wire    [ID_WIDTH-1:0]  s_sid       [S_NUM-1:0] ;
    wire    [ID_WIDTH-1:0]  s_did       [S_NUM-1:0] ;
    wire    [ID_WIDTH-1:0]  s_hit_chl   [S_NUM-1:0] ;
    wire    [S_NUM-1:0]     s_valid                 ;
    wire    [S_NUM-1:0]     s_last                  ;
    wire    [S_NUM-1:0]     s_hit                   ;
    wire    [ID_WIDTH-1:0]  hit_chl                 ;

    //---------------------------------------------------------------------------------------
    //main logic
    assign  req     =   comp_M[(m+1)*S_NUM-1:m*S_NUM] & (~weight);
    
    assign  arb_p[m]=   req & (~req + 1);
    
    always@(posedge i_clk or posedge i_rst)begin
        if(i_rst)begin
            arb[m]      <=  'd0;
            mem_hitsc[m]<=  'd0;
        end else if(m_axis_ready[m] && m_axis_valid[m] && m_axis_last[m])begin
            arb[m]      <=  'd0;
            mem_hitsc[m]<=  'd0;
        end else if(|arb[m] == 1'b0)begin
            arb[m]      <=  arb_p[m];
            mem_hitsc[m]<=  {|s_hit,hit_chl};
        end else begin
            arb[m]      <=  arb[m] & (~weight);
        end
    end
    
    always@(posedge i_clk or posedge i_rst)begin
        if(i_rst)
            weight_clear    <=  8'd0;
        else if(&weight_clear || (m_axis_valid[m] && m_axis_ready[m]))
            weight_clear    <=  8'd0;
        else if(&weight)
            weight_clear    <=  8'hff;
        else if(~(m_axis_valid[m] && m_axis_ready[m]))
            weight_clear    <=  {weight_clear,(|req == 1'b0)};
    end
    //----------------------------------------------------------------------------
    for(s=0;s<S_NUM;s=s+1)begin: SC//receive channel
        reg [3:0]   time_cnt;
        wire        time_out;
    
        assign  s_data   [s]    =   {DATA_WIDTH{arb[m][s]}} & s_axis_data[(s+1)*DATA_WIDTH-1:s*DATA_WIDTH];
        assign  s_sid    [s]    =   {ID_WIDTH{arb[m][s]}} & s_axis_sid[(s+1)*ID_WIDTH-1:s*ID_WIDTH];
        assign  s_did    [s]    =   {ID_WIDTH{arb[m][s]}} & s_axis_did[(s+1)*ID_WIDTH-1:s*ID_WIDTH];
        assign  s_valid  [s]    =   arb[m][s] & s_axis_valid[s];
        assign  s_last   [s]    =   arb[m][s] & s_axis_last[s];
        
        assign  s_hit    [s]    =   arb_p[m][s];
        assign  s_hit_chl[s]    =   {ID_WIDTH{arb_p[m][s]}} & s[ID_WIDTH-1:0];

        always@(posedge i_clk or posedge i_rst)begin
            if(i_rst)
                weight[s]   <=  1'b0;
            else if(&weight_clear)
                weight[s]   <=  1'b0;
            else if(s_axis_valid[s] && s_axis_ready[s] && s_axis_last[s] && arb[m][s])
                weight[s]   <=  1'b1;
            else if(time_out)
                weight[s]   <=  1'b1;
        end
        
        always@(posedge i_clk or posedge i_rst)begin
            if(i_rst)
                time_cnt        <=  4'd0;
            else if((s_axis_valid[s] ^ s_axis_ready[s]) && arb[m][s])
                time_cnt        <=  4'd1 + time_cnt;
            else
                time_cnt        <=  4'd0;
        end
        
        assign  time_out    =   &time_cnt;
    end
    //----------------------------------------------------------------------------
    for(i=0;i<DATA_WIDTH;i=i+1)begin: data_sc
        wire    [S_NUM-1:0] data_sc;
        for(j=0;j<S_NUM;j=j+1)begin
            assign  data_sc[j]  =   s_data[j][i];
        end
        assign  m_axis_data[m*DATA_WIDTH+i]  =   |data_sc;
    end

    for(k=0;k<ID_WIDTH;k=k+1)begin: id_sc
        wire    [S_NUM-1:0] sid_sc;
        wire    [S_NUM-1:0] did_sc;
        wire    [S_NUM-1:0] hit_chl_sc;

        for(n=0;n<S_NUM;n=n+1)begin
            assign  sid_sc[n]       =   s_sid[n][k];
            assign  did_sc[n]       =   s_did[n][k];
            assign  hit_chl_sc[n]   =   s_hit_chl[n][k];
        end
        assign  hit_chl[k]          =   |hit_chl_sc;
        assign  m_axis_did[m*ID_WIDTH+k]    =   |sid_sc;
        //assign  m_axis_did[m*ID_WIDTH+k]    =   |did_sc;
    end
    
    assign  m_axis_valid[m]     =   |s_valid;
    assign  m_axis_last[m]      =   |s_last;
    

end endgenerate
//========================================================================================================
genvar  r,t;generate for(r=0;r<S_NUM;r=r+1)begin: RC
    wire    [M_NUM-1:0] m_ready;

    for(t=0;t<M_NUM;t=t+1)begin: TC
        assign  m_ready[t]  =   m_axis_ready[t] && mem_hitsc[t][ID_WIDTH] && (mem_hitsc[t][ID_WIDTH-1:0] == r[ID_WIDTH-1:0]);
    end

    assign  s_axis_ready[r]  =   |m_ready | (comp_S_did_miss[r] & s_axis_valid[r]);

end endgenerate

endmodule

//========================================================================================================
module id_compare#(
    parameter   ID_WIDTH            =   8               ,
    parameter   S_NUM               =   16              ,
    parameter   M_NUM               =   16              

    
)(
    input                           i_clk               ,
    input                           i_rst               ,

    input   [S_NUM-1:0]             s_axis_valid        ,
    input   [S_NUM*ID_WIDTH-1:0]    s_axis_did          ,
    input   [M_NUM-1:0]             m_axis_ready        ,
    input   [M_NUM*ID_WIDTH-1:0]    m_axis_sid          ,

    output  [S_NUM-1:0]             comp_S_did_miss     ,
    output  [S_NUM*M_NUM-1:0]       comp_S              ,
    output  [S_NUM*M_NUM-1:0]       comp_M
    );
wire        [S_NUM-1:0]             S_valid             ;
wire        [ID_WIDTH-1:0]          S_did[S_NUM-1:0]    ;
wire        [M_NUM-1:0]             S_comp[S_NUM-1:0]   ;
wire        [M_NUM-1:0]             S_comp_did_exist[S_NUM-1:0]   ;

wire        [M_NUM-1:0]             M_ready             ;
wire        [ID_WIDTH-1:0]          M_sid[M_NUM-1:0]    ;
wire        [S_NUM-1:0]             M_comp[M_NUM-1:0]   ;

genvar s ;generate for(s=0;s<S_NUM;s=s+1)begin
    assign  S_valid[s]  =   s_axis_valid[s];
    assign  S_did[s]    =   s_axis_did[(s+1)*ID_WIDTH-1:s*ID_WIDTH];
    assign  comp_S_did_miss[s]  =   ~(|S_comp_did_exist[s]);
    assign  comp_S[(s+1)*M_NUM-1:s*M_NUM]   =   S_comp[s];
end endgenerate

genvar m ;generate for(m=0;m<M_NUM;m=m+1)begin
    assign  M_ready[m]  =   m_axis_ready[m];
    assign  M_sid[m]    =   m_axis_sid[(m+1)*ID_WIDTH-1:m*ID_WIDTH];
    assign  comp_M[(m+1)*S_NUM-1:m*S_NUM]   =   M_comp[m];
end endgenerate

genvar i,j;generate for(i=0;i<S_NUM;i=i+1)begin
    for(j=0;j<M_NUM;j=j+1)begin
        assign  S_comp[i][j]    =   (S_did[i] == M_sid[j]) && (S_valid[i] == M_ready[j]);
        assign  M_comp[j][i]    =   S_comp[i][j];
        assign  S_comp_did_exist[i][j] = (S_did[i] == M_sid[j]);
    end
end endgenerate



endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值