tinyriscv/rtl/sys_bus/obi_interconnect.sv

133 lines
4.8 KiB
Systemverilog
Raw Normal View History

// obi总线交叉互联矩阵支持一对多、多对一、多对多
// master之间采用优先级总裁方式LSB优先级最高MSB优先级最低
module obi_interconnect #(
parameter int MASTERS = 3, // number of masters
parameter int SLAVES = 5, // number of slaves
parameter MASTER_BITS = MASTERS == 1 ? 1 : $clog2(MASTERS),
parameter SLAVE_BITS = SLAVES == 1 ? 1 : $clog2(SLAVES)
)(
input logic clk_i,
input logic rst_ni,
input logic master_req_i [MASTERS],
output logic master_gnt_o [MASTERS],
output logic master_rvalid_o [MASTERS],
input logic master_we_i [MASTERS],
input logic [ 3:0] master_be_i [MASTERS],
input logic [31:0] master_addr_i [MASTERS],
input logic [31:0] master_wdata_i [MASTERS],
output logic [31:0] master_rdata_o [MASTERS],
input logic [31:0] slave_addr_mask_i [SLAVES],
input logic [31:0] slave_addr_base_i [SLAVES],
output logic slave_req_o [SLAVES],
input logic slave_gnt_i [SLAVES],
input logic slave_rvalid_i [SLAVES],
output logic slave_we_o [SLAVES],
output logic [ 3:0] slave_be_o [SLAVES],
output logic [31:0] slave_addr_o [SLAVES],
output logic [31:0] slave_wdata_o [SLAVES],
input logic [31:0] slave_rdata_i [SLAVES]
);
genvar m, s;
logic [MASTER_BITS-1:0] master_sel_int[SLAVES];
logic [MASTERS-1:0] master_sel_vec[SLAVES];
logic granted_master[SLAVES];
// 为每个slave选择一个master
generate
for (s = 0; s < SLAVES; s = s + 1) begin: master_sel
obi_interconnect_master_sel #(
.MASTERS(MASTERS)
) master_sel (
.clk_i(clk_i),
.rst_ni(rst_ni),
.master_req_i(master_req_i),
.master_addr_i(master_addr_i),
.slave_addr_mask_i(slave_addr_mask_i[s]),
.slave_addr_base_i(slave_addr_base_i[s]),
.master_sel_int_o(master_sel_int[s]),
.master_sel_vec_o(master_sel_vec[s]),
.granted_master_o(granted_master[s])
);
end
endgenerate
logic [SLAVE_BITS-1:0] slave_sel_int[MASTERS];
// 为每个master选择一个slave
generate
for (m = 0; m < MASTERS; m = m + 1) begin: slave_sel
obi_interconnect_slave_sel #(
.SLAVES(SLAVES)
) slave_sel (
.clk_i(clk_i),
.rst_ni(rst_ni),
.master_req_i(master_req_i[m]),
.master_addr_i(master_addr_i[m]),
.slave_addr_mask_i(slave_addr_mask_i),
.slave_addr_base_i(slave_addr_base_i),
.slave_sel_int_o(slave_sel_int[m])
);
end
endgenerate
// slave信号赋值
generate
for (s = 0; s < SLAVES; s = s + 1) begin: slave_signal
assign slave_req_o[s] = master_req_i[master_sel_int[s]] & granted_master[s];
assign slave_we_o[s] = master_we_i[master_sel_int[s]] & granted_master[s];
assign slave_be_o[s] = master_be_i[master_sel_int[s]];
assign slave_addr_o[s] = master_addr_i[master_sel_int[s]];
assign slave_wdata_o[s] = master_wdata_i[master_sel_int[s]];
end
endgenerate
logic [MASTERS-1:0] master_sel_or;
always_comb begin
master_sel_or = 'b0;
for (integer i = 0; i < SLAVES; i = i + 1) begin: gen_master_sel_or_vec
master_sel_or = master_sel_or | master_sel_vec[i];
end
end
logic [SLAVE_BITS-1:0] slave_sel_int_q[MASTERS];
generate
for (m = 0; m < MASTERS; m = m + 1) begin: master_data_q
always_ff @ (posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
slave_sel_int_q[m] <= 'b0;
end else begin
slave_sel_int_q[m] <= slave_sel_int[m];
end
end
end
endgenerate
logic [MASTERS-1:0] master_sel_or_q;
always_ff @ (posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
master_sel_or_q <= 'b0;
end else begin
master_sel_or_q <= master_sel_or;
end
end
// master信号赋值
generate
for (m = 0; m < MASTERS; m = m + 1) begin: master_data
assign master_gnt_o[m] = master_sel_or[m];
assign master_rdata_o[m] = slave_rdata_i[slave_sel_int_q[m]];
assign master_rvalid_o[m] = master_sel_or_q[m];
end
endgenerate
endmodule