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
axis_bus 全链接 V2
于 2023-08-08 21:34:00 首次发布