顶层和时序
//
// 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_lite#(
parameter DATA_WIDTH = 32 ,
parameter ADDR_WIDTH = 24 ,
parameter ID_WIDTH = 8 ,
parameter S_NUM = 1 ,
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 ,
//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_lite#(
.DATA_WIDTH (DATA_WIDTH ),
.ADDR_WIDTH (ADDR_WIDTH ),
.ID_WIDTH (ID_WIDTH ),
.S_NUM (S_NUM ),
.M_NUM (M_NUM ),
.AHEAD (AHEAD )//非必要不关注
)local_wr_bus_lite(
.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_lite#(
.DATA_WIDTH (DATA_WIDTH ),
.ADDR_WIDTH (ADDR_WIDTH ),
.ID_WIDTH (ID_WIDTH ),
.S_NUM (S_NUM ),
.M_NUM (M_NUM )
)local_rd_bus_lite(
.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_bus_lite
module local_wr_bus_lite#(
parameter DATA_WIDTH = 32 ,
parameter ADDR_WIDTH = 24 ,
parameter ID_WIDTH = 8 ,
parameter S_NUM = 1 ,
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_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 [M_NUM-1:0] s_comp[S_NUM-1:0] ;
wire [9:0] s_hit_mem[S_NUM-1:0];
wire [S_NUM-1:0] s_req ;
reg [S_NUM-1:0] weight ;
wire [9:0] s_hit ;
reg [3:0] weight_clear ;
reg [S_NUM-1:0] s_sel ;
reg [M_NUM-1:0] m_sel ;
wire s_valid ;
wire s_last ;
wire m_ready ;
wire [ADDR_WIDTH-1:0] s_addr ;
wire [DATA_WIDTH-1:0] s_data ;
reg [15:0] time_cnt ;
wire time_out ;
//-----------------------------------------------------------------
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 | ~AHEAD ),
.s_wr_did (s_wr_did ),
.m_wr_ready (m_wr_ready | AHEAD ),
.m_wr_sid (m_wr_sid ),
.comp_S_did_miss (comp_S_did_miss ),
.comp_S (comp_S ),
.comp_M (comp_M ));
//-----------------------------------------------------------------
//-----------------------------------------------------------------
wire[S_NUM-1:0] s_sel_p = s_req & (~s_req + 1);//Select the lowest bit of 1 and the other bits at 0
always@(posedge i_clk or posedge i_rst)begin
if(i_rst)begin
s_sel <= 'd0;
m_sel <= 'd0;
end else if(s_valid && s_last && m_ready)begin
s_sel <= 'd0;
m_sel <= 'd0;
end else if(|s_sel == 1'b0)begin
s_sel <= s_sel_p;
m_sel <= s_comp[s_hit];
end else begin
s_sel <= s_sel & (~weight);
end
end
//-----------------------------------------------------------------
genvar s;generate for(s=0;s<S_NUM;s=s+1)begin: SC//receive channel
assign s_comp[s] = comp_S[(s+1)*M_NUM-1:s*M_NUM];
assign s_req [s] = (|s_comp[s]) & (~weight[s]);
assign s_hit_mem[s]= s[9:0] & {10{s_sel_p[s]}};
//
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_ready[s] && s_wr_valid[s] && s_wr_last[s]) || (time_out && s_sel[s]))
weight[s] <= 1'b1;
end
//
end endgenerate
//-----------------------------------------------------------------
genvar i,j;generate for(i=0;i<10;i=i+1)begin: hit_S_channel
wire [S_NUM-1:0] hit_sc;
for(j=0;j<S_NUM;j=j+1)begin
assign hit_sc[j] = s_hit_mem[j][i];
end
assign s_hit[i] = |hit_sc;
end endgenerate
//-----------------------------------------------------------------
always@(posedge i_clk or posedge i_rst)begin
if(i_rst)
weight_clear <= 4'd0;
else if((|weight == 1'b0) || (s_valid && m_ready))
weight_clear <= 4'd0;
else if(&weight)
weight_clear <= 4'hf;
else if(~(s_valid && m_ready))
weight_clear <= {weight_clear,(|s_req == 1'b0)};
end
//-----------------------------------------------------------------
always@(posedge i_clk or posedge i_rst)begin
if(i_rst)
time_cnt <= 16'd0;
else if(time_out)
time_cnt <= 16'd0;
else if(|s_sel && (m_wr_ready & m_wr_valid == {M_NUM{1'b0}}))
time_cnt <= 16'd1 + time_cnt;
else
time_cnt <= 16'd0;
end
assign time_out = time_cnt[15];
//-----------------------------------------------------------------
assign s_valid = |(s_wr_valid & s_sel) ;
assign s_last = |(s_wr_last & s_sel) ;
assign m_ready = |(m_wr_ready & m_sel) ;
genvar adw,ads;generate for(adw=0;adw<ADDR_WIDTH;adw=adw+1)begin: addr_S_channel
wire [S_NUM-1:0] addr_sc;
for(ads=0;ads<S_NUM;ads=ads+1)begin
assign addr_sc[ads] = s_wr_addr[ads*ADDR_WIDTH+adw] & s_sel[ads];
end
assign s_addr[adw] = |addr_sc;
end endgenerate
genvar daw,das;generate for(daw=0;daw<DATA_WIDTH;daw=daw+1)begin: data_S_channel
wire [S_NUM-1:0] data_sc;
for(das=0;das<S_NUM;das=das+1)begin
assign data_sc[das] = s_wr_data[das*DATA_WIDTH+daw] & s_sel[das];
end
assign s_data[daw] = |data_sc;
end endgenerate
//-----------------------------------------------------------------
assign m_wr_valid = m_sel & {M_NUM{s_valid}};
assign m_wr_last = m_sel & {M_NUM{s_last}};
assign m_wr_data = {M_NUM{s_data}};
assign m_wr_addr = {M_NUM{s_addr}};
assign s_wr_ready = s_sel & {S_NUM{m_ready}} | (comp_S_did_miss & s_wr_valid);
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_bus_lite
module local_rd_bus_lite#(
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 [M_NUM-1:0] s_comp[S_NUM-1:0] ;
wire [9:0] s_hit_mem[S_NUM-1:0];
wire [S_NUM-1:0] s_req ;
reg [S_NUM-1:0] weight ;
wire [9:0] s_hit ;
reg [3:0] weight_clear ;
reg [S_NUM-1:0] s_sel ;
reg [M_NUM-1:0] m_sel ;
wire s_ready ;
wire [ADDR_WIDTH-1:0] s_addr ;
wire m_valid ;
wire [DATA_WIDTH-1:0] m_data ;
reg [15:0] time_cnt ;
wire time_out ;
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 ));
//-----------------------------------------------------------------
wire[S_NUM-1:0] s_sel_p = s_req & (~s_req + 1);//Select the lowest bit of 1 and the other bits at 0
always@(posedge i_clk or posedge i_rst)begin
if(i_rst)begin
s_sel <= 'd0;
m_sel <= 'd0;
end else if(|(~s_rd_ready & s_rd_ready_1d & s_sel))begin
s_sel <= 'd0;
m_sel <= 'd0;
end else if(|s_sel == 1'b0)begin
s_sel <= s_sel_p;
m_sel <= s_comp[s_hit];
end else begin
s_sel <= s_sel & (~weight);
end
end
//-----------------------------------------------------------------
genvar s;generate for(s=0;s<S_NUM;s=s+1)begin: SC//receive channel
assign s_comp[s] = comp_S[(s+1)*M_NUM-1:s*M_NUM];
assign s_req [s] = (|s_comp[s]) & (~weight[s]);
assign s_hit_mem[s]= s[9:0] & {10{s_sel_p[s]}};
//
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] && s_sel[s]) || (time_out && s_sel[s]))
weight[s] <= 1'b1;
end
//
end endgenerate
//-----------------------------------------------------------------
genvar i,j;generate for(i=0;i<10;i=i+1)begin: hit_S_channel
wire [S_NUM-1:0] hit_sc;
for(j=0;j<S_NUM;j=j+1)begin
assign hit_sc[j] = s_hit_mem[j][i];
end
assign s_hit[i] = |hit_sc;
end endgenerate
//-----------------------------------------------------------------
always@(posedge i_clk or posedge i_rst)begin
if(i_rst)
weight_clear <= 4'd0;
else if((|weight == 1'b0) || (s_ready && m_valid))
weight_clear <= 4'd0;
else if(&weight)
weight_clear <= 4'hf;
else if(~(s_ready && m_valid))
weight_clear <= {weight_clear,(|s_req == 1'b0)};
end
//-----------------------------------------------------------------
always@(posedge i_clk or posedge i_rst)begin
if(i_rst)
time_cnt <= 16'd0;
else if(time_out)
time_cnt <= 16'd0;
else if(|s_sel && (m_rd_valid & m_rd_ready == {M_NUM{1'b0}}))
time_cnt <= 16'd1 + time_cnt;
else
time_cnt <= 16'd0;
end
assign time_out = time_cnt[15];
//-----------------------------------------------------------------
assign s_ready = |(s_rd_ready & s_sel) ;
assign m_valid = |(m_rd_valid & m_sel) ;
genvar adw,ads;generate for(adw=0;adw<ADDR_WIDTH;adw=adw+1)begin: addr_S_channel
wire [S_NUM-1:0] addr_sc;
for(ads=0;ads<S_NUM;ads=ads+1)begin
assign addr_sc[ads] = s_rd_addr[ads*ADDR_WIDTH+adw] & s_sel[ads];
end
assign s_addr[adw] = |addr_sc;
end endgenerate
genvar daw,das;generate for(daw=0;daw<DATA_WIDTH;daw=daw+1)begin: data_M_channel
wire [M_NUM-1:0] data_sc;
for(das=0;das<M_NUM;das=das+1)begin
assign data_sc[das] = m_rd_data[das*DATA_WIDTH+daw] & m_sel[das];
end
assign m_data[daw] = |data_sc;
end endgenerate
//-----------------------------------------------------------------
assign m_rd_ready = m_sel & {M_NUM{s_rd_ready}};
assign m_rd_addr = {M_NUM{s_rd_addr}};
assign s_rd_valid = (s_sel & {S_NUM{m_valid}}) | (comp_S_did_miss & m_rd_ready);
assign s_rd_data = {S_NUM{m_data}};
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