顶层和时序
//
// i_clk --\__/--\__/--\__/--\__/--\__/--\__/--\__/--\__/--\__/--\__/
// local_wr_ready _____/------------------------------------------------------
// local_wr_valid ___________/-----------------------\________________________
// local_wr_last _____________________________/-----\________________________
// local_wr_addr ___________|addrA|addrB|addrC|addrD|________________________
// local_wr_data ___________|dataA|dataB|dataC|dataD|________________________
// local_rd_ready _____/-----------------------------------------------\______
// local_rd_addr _____|addrA |addrB |addrC |addrD |______
// local_rd_valid ___________/-----\_____/-----\_____/-----\_____/-----\______
// local_rd_data ___________|dataA |dataB |dataC |dataD|______
//
module local_bus#(
parameter DATA_WIDTH = 32 ,
parameter ADDR_WIDTH = 24 ,
parameter ID_WIDTH = 8 ,
parameter S_NUM = 1 ,
parameter M_NUM = 16
)(
input i_clk ,
input i_rst ,
//from Master
output [S_NUM-1:0] s_wr_ready ,
input [S_NUM-1:0] s_wr_valid ,
input [S_NUM-1:0] s_wr_last ,
input [S_NUM*DATA_WIDTH-1:0] s_wr_data ,
input [S_NUM*ADDR_WIDTH-1:0] s_wr_addr ,
input [S_NUM*ID_WIDTH-1:0] s_wr_did ,
input [S_NUM-1:0] s_rd_ready ,
input [S_NUM*ADDR_WIDTH-1:0] s_rd_addr ,
input [S_NUM*ID_WIDTH-1:0] s_rd_did ,
output [S_NUM-1:0] s_rd_valid ,
output [S_NUM*DATA_WIDTH-1:0] s_rd_data ,
//to Slave
input [M_NUM-1:0] m_wr_ready ,
output [M_NUM-1:0] m_wr_valid ,
output [M_NUM-1:0] m_wr_last ,
output [M_NUM*DATA_WIDTH-1:0] m_wr_data ,
output [M_NUM*ADDR_WIDTH-1:0] m_wr_addr ,
input [M_NUM*ID_WIDTH-1:0] m_wr_sid ,
output [M_NUM-1:0] m_rd_ready ,
output [M_NUM*ADDR_WIDTH-1:0] m_rd_addr ,
input [M_NUM-1:0] m_rd_valid ,
input [M_NUM*DATA_WIDTH-1:0] m_rd_data ,
input [M_NUM*ID_WIDTH-1:0] m_rd_sid
);
local_wr_bus#(
.DATA_WIDTH (DATA_WIDTH ),
.ADDR_WIDTH (ADDR_WIDTH ),
.ID_WIDTH (ID_WIDTH ),
.S_NUM (S_NUM ),
.M_NUM (M_NUM )
)local_wr_bus(
.i_clk (i_clk ),//input
.i_rst (i_rst ),//input
.s_wr_ready (s_wr_ready ),//output [S_NUM-1:0]
.s_wr_valid (s_wr_valid ),//input [S_NUM-1:0]
.s_wr_last (s_wr_last ),//input [S_NUM-1:0]
.s_wr_data (s_wr_data ),//input [S_NUM*DATA_WIDTH-1:0]
.s_wr_addr (s_wr_addr ),//input [S_NUM*ADDR_WIDTH-1:0]
.s_wr_did (s_wr_did ),//input [S_NUM*ID_WIDTH-1:0]
.m_wr_ready (m_wr_ready ),//input [M_NUM-1:0]
.m_wr_valid (m_wr_valid ),//output [M_NUM-1:0]
.m_wr_last (m_wr_last ),//output [M_NUM-1:0]
.m_wr_data (m_wr_data ),//output [M_NUM*DATA_WIDTH-1:0]
.m_wr_addr (m_wr_addr ),//output [M_NUM*ADDR_WIDTH-1:0]
.m_wr_sid (m_wr_sid ) //input [M_NUM*ID_WIDTH-1:0]
);
local_rd_bus#(
.DATA_WIDTH (DATA_WIDTH ),
.ADDR_WIDTH (ADDR_WIDTH ),
.ID_WIDTH (ID_WIDTH ),
.S_NUM (S_NUM ),
.M_NUM (M_NUM )
)local_rd_bus(
.i_clk (i_clk ),//input
.i_rst (i_rst ),//input
.s_rd_ready (s_rd_ready ),//input [S_NUM-1:0]
.s_rd_addr (s_rd_addr ),//input [S_NUM*ADDR_WIDTH-1:0]
.s_rd_did (s_rd_did ),//input [S_NUM*ID_WIDTH-1:0]
.s_rd_valid (s_rd_valid ),//output [S_NUM-1:0]
.s_rd_data (s_rd_data ),//output [S_NUM*DATA_WIDTH-1:0]
.m_rd_ready (m_rd_ready ),//output [M_NUM-1:0]
.m_rd_addr (m_rd_addr ),//output [M_NUM*ADDR_WIDTH-1:0]
.m_rd_valid (m_rd_valid ),//input [M_NUM-1:0]
.m_rd_data (m_rd_data ),//input [M_NUM*DATA_WIDTH-1:0]
.m_rd_sid (m_rd_sid ) //input [M_NUM*ID_WIDTH-1:0]
);
endmodule
local_wr
module local_wr_bus#(
parameter DATA_WIDTH = 32 ,
parameter ADDR_WIDTH = 24 ,
parameter ID_WIDTH = 8 ,
parameter S_NUM = 1 ,
parameter M_NUM = 16
)(
input i_clk ,
input i_rst ,
output [S_NUM-1:0] s_wr_ready ,
input [S_NUM-1:0] s_wr_valid ,
input [S_NUM-1:0] s_wr_last ,
input [S_NUM*DATA_WIDTH-1:0] s_wr_data ,
input [S_NUM*ADDR_WIDTH-1:0] s_wr_addr ,
input [S_NUM*ID_WIDTH-1:0] s_wr_did ,
input [M_NUM-1:0] m_wr_ready ,
output [M_NUM-1:0] m_wr_valid ,
output [M_NUM-1:0] m_wr_last ,
output [M_NUM*DATA_WIDTH-1:0] m_wr_data ,
output [M_NUM*ADDR_WIDTH-1:0] m_wr_addr ,
input [M_NUM*ID_WIDTH-1:0] m_wr_sid
);
//-----------------------------------------------------------------
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_wr_compare#(
.ID_WIDTH (ID_WIDTH ),
.S_NUM (S_NUM ),
.M_NUM (M_NUM )
)id_wr_compare(
.i_clk (i_clk ),
.i_rst (i_rst ),
.s_wr_valid (s_wr_valid ),
.s_wr_did (s_wr_did ),
.m_wr_ready ({M_NUM{1'b1}} ),
.m_wr_sid (m_wr_sid ),
.comp_S_did_miss (comp_S_did_miss ),
.comp_S (comp_S ),
.comp_M (comp_M ));
//========================================================================================================
genvar s,m,i,j,p,l,o,k;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 [ADDR_WIDTH-1:0]s_addr [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_wr_ready[m] && m_wr_valid[m] && m_wr_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
end
always@(posedge i_clk or posedge i_rst)begin
if(i_rst)
weight_clear <= 8'd0;
else if(&weight_clear || (m_wr_valid[m] && m_wr_ready[m]))
weight_clear <= 8'd0;
else if(&weight)
weight_clear <= 8'hff;
else if(~(m_wr_valid[m] && m_wr_ready[m]))
weight_clear <= {weight_clear,(|req == 1'b0)};
end
for(s=0;s<S_NUM;s=s+1)begin: SC//receive channel
assign s_data [s] = {DATA_WIDTH{arb[m][s]}} & s_wr_data[(s+1)*DATA_WIDTH-1:s*DATA_WIDTH];
assign s_addr [s] = {ADDR_WIDTH{arb[m][s]}} & s_wr_addr[(s+1)*ADDR_WIDTH-1:s*ADDR_WIDTH];
assign s_valid [s] = arb[m][s] & s_wr_valid[s];
assign s_last [s] = arb[m][s] & s_wr_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_wr_valid[s] && s_wr_ready[s] && s_wr_last[s] && arb[m][s])
weight[s] <= 1'b1;
end
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_wr_data[m*DATA_WIDTH+i] = |data_sc;
end
//
for(p=0;p<ADDR_WIDTH;p=p+1)begin: addr_sc
wire [S_NUM-1:0] addr_sc;
for(l=0;l<S_NUM;l=l+1)begin
assign addr_sc[l] = s_addr[l][p];
end
assign m_wr_addr[m*ADDR_WIDTH+p] = |addr_sc;
end
//
for(o=0;o<ID_WIDTH;o=o+1)begin: id_sc
wire [S_NUM-1:0] hit_chl_sc;
for(k=0;k<S_NUM;k=k+1)begin
assign hit_chl_sc[k] = s_hit_chl[k][o];
end
assign hit_chl[o] = |hit_chl_sc;
end
//
assign m_wr_valid[m] = |s_valid;
assign m_wr_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_wr_ready[t] && mem_hitsc[t][ID_WIDTH] && (mem_hitsc[t][ID_WIDTH-1:0] == r[ID_WIDTH-1:0]);
end
assign s_wr_ready[r] = |m_ready | (comp_S_did_miss[r] & s_wr_valid[r]);
end endgenerate
endmodule
//========================================================================================================
module id_wr_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_wr_valid ,
input [S_NUM*ID_WIDTH-1:0] s_wr_did ,
input [M_NUM-1:0] m_wr_ready ,
input [M_NUM*ID_WIDTH-1:0] m_wr_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_wr_valid[s];
assign S_did[s] = s_wr_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_wr_ready[m];
assign M_sid[m] = m_wr_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
local_rd
module local_rd_bus#(
parameter DATA_WIDTH = 32 ,
parameter ADDR_WIDTH = 24 ,
parameter ID_WIDTH = 8 ,
parameter S_NUM = 1 ,
parameter M_NUM = 16
)(
input i_clk ,
input i_rst ,
input [S_NUM-1:0] s_rd_ready ,
input [S_NUM*ADDR_WIDTH-1:0] s_rd_addr ,
input [S_NUM*ID_WIDTH-1:0] s_rd_did ,
output [S_NUM-1:0] s_rd_valid ,
output [S_NUM*DATA_WIDTH-1:0] s_rd_data ,
output [M_NUM-1:0] m_rd_ready ,
output [M_NUM*ADDR_WIDTH-1:0] m_rd_addr ,
input [M_NUM-1:0] m_rd_valid ,
input [M_NUM*DATA_WIDTH-1:0] m_rd_data ,
input [M_NUM*ID_WIDTH-1:0] m_rd_sid
);
//-----------------------------------------------------------------
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];
reg [S_NUM-1:0] s_rd_ready_1d ;
//-----------------------------------------------------------------
always@(posedge i_clk) s_rd_ready_1d <= s_rd_ready;
id_rd_compare#(
.ID_WIDTH (ID_WIDTH ),
.S_NUM (S_NUM ),
.M_NUM (M_NUM )
)id_rd_compare(
.i_clk (i_clk ),
.i_rst (i_rst ),
.s_rd_valid (s_rd_ready ),
.s_rd_did (s_rd_did ),
.m_rd_ready ({M_NUM{1'b1}} ),
.m_rd_sid (m_rd_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 [ADDR_WIDTH-1:0]s_addr [S_NUM-1:0] ;
wire [ID_WIDTH-1:0] s_hit_chl [S_NUM-1:0] ;
wire [S_NUM-1:0] s_ready ;
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(|(~s_rd_ready & s_rd_ready_1d & arb[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
end
always@(posedge i_clk or posedge i_rst)begin
if(i_rst)
weight_clear <= 8'd0;
else if(&weight_clear || (m_rd_valid[m] && m_rd_ready[m]))
weight_clear <= 8'd0;
else if(&weight)
weight_clear <= 8'hff;
else if(~(m_rd_valid[m] && m_rd_ready[m]))
weight_clear <= {weight_clear,(|req == 1'b0)};
end
for(s=0;s<S_NUM;s=s+1)begin:SC//receive channel
assign s_addr [s] = {ADDR_WIDTH{arb[m][s]}} & s_rd_addr[(s+1)*ADDR_WIDTH-1:s*ADDR_WIDTH];
assign s_ready [s] = arb[m][s] & s_rd_ready[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_rd_ready[s] && s_rd_ready_1d[s] && arb[m][s])
weight[s] <= 1'b1;
end
end
//----------------------------------------------------------------------------
for(i=0;i<ADDR_WIDTH;i=i+1)begin: addr_sc
wire [S_NUM-1:0] addr_sc;
for(j=0;j<S_NUM;j=j+1)begin
assign addr_sc[j] = s_addr[j][i];
end
assign m_rd_addr[m*ADDR_WIDTH+i] = |addr_sc;
end
for(k=0;k<ID_WIDTH;k=k+1)begin: id_sc
wire [S_NUM-1:0] hit_chl_sc;
for(n=0;n<S_NUM;n=n+1)begin
assign hit_chl_sc[n] = s_hit_chl[n][k];
end
assign hit_chl[k] = |hit_chl_sc;
end
assign m_rd_ready[m] = |s_ready;
end endgenerate
//========================================================================================================
genvar r,t,w,a;generate for(r=0;r<S_NUM;r=r+1)begin: RC //receive channel
wire [M_NUM-1:0] m_valid;
wire [DATA_WIDTH-1:0] m_data [M_NUM-1:0];
for(t=0;t<M_NUM;t=t+1)begin: TC//send channel
wire hit = mem_hitsc[t][ID_WIDTH] && (mem_hitsc[t][ID_WIDTH-1:0] == r[ID_WIDTH-1:0]);
assign m_valid[t] = m_rd_valid[t] && hit;
assign m_data[t] = m_rd_data[(t+1)*DATA_WIDTH-1:t*DATA_WIDTH] & {DATA_WIDTH{hit}};
end
assign s_rd_valid[r] = |m_valid | (comp_S_did_miss[r] & s_rd_ready[r]);
for(w=0;w<DATA_WIDTH;w=w+1)begin: data_mc
wire [M_NUM-1:0] data_mc;
for(a=0;a<M_NUM;a=a+1)begin
assign data_mc[a] = m_data[a][w];
end
assign s_rd_data[r*DATA_WIDTH+w] = |data_mc | (comp_S_did_miss[r] & s_rd_ready[r]);
end
end endgenerate
endmodule
//========================================================================================================
module id_rd_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_rd_valid ,
input [S_NUM*ID_WIDTH-1:0] s_rd_did ,
input [M_NUM-1:0] m_rd_ready ,
input [M_NUM*ID_WIDTH-1:0] m_rd_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_rd_valid[s];
assign S_did[s] = s_rd_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_rd_ready[m];
assign M_sid[m] = m_rd_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