blob: b3552ecbda249e76ee756b9dcabbe67ad3e55811 [file] [log] [blame]
//////////////////////////////////////////////////////////////////////
//// ////
//// Wishbone Interconnect ////
//// ////
//// This file is part of the YIFive cores project ////
//// http://www.opencores.org/cores/yifive/ ////
//// ////
//// Description ////
//// 1. 3 masters and 3 slaves share bus Wishbone connection ////
//// 2. This block implement simple round robine request ////
//// ////
//// To Do: ////
//// nothing ////
//// ////
//// Author(s): ////
//// - Dinesh Annayya, dinesha@opencores.org ////
//// ////
//// Revision : ////
//// 0.1 - 12th June 2021, Dinesh A ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
module wb_interconnect(
input logic clk_i,
input logic rst_n,
// Master 0 Interface
input logic [31:0] m0_wbd_dat_i,
input logic [31:0] m0_wbd_adr_i,
input logic [3:0] m0_wbd_sel_i,
input logic m0_wbd_we_i,
input logic m0_wbd_cyc_i,
input logic m0_wbd_stb_i,
output logic [31:0] m0_wbd_dat_o,
output logic m0_wbd_ack_o,
output logic m0_wbd_err_o,
// Master 1 Interface
input logic [31:0] m1_wbd_dat_i,
input logic [31:0] m1_wbd_adr_i,
input logic [3:0] m1_wbd_sel_i,
input logic m1_wbd_we_i,
input logic m1_wbd_cyc_i,
input logic m1_wbd_stb_i,
output logic [31:0] m1_wbd_dat_o,
output logic m1_wbd_ack_o,
output logic m1_wbd_err_o,
// Master 2 Interface
input logic [31:0] m2_wbd_dat_i,
input logic [31:0] m2_wbd_adr_i,
input logic [3:0] m2_wbd_sel_i,
input logic m2_wbd_we_i,
input logic m2_wbd_cyc_i,
input logic m2_wbd_stb_i,
output logic [31:0] m2_wbd_dat_o,
output logic m2_wbd_ack_o,
output logic m2_wbd_err_o,
// Slave 0 Interface
input logic [31:0] s0_wbd_dat_i,
input logic s0_wbd_ack_i,
input logic s0_wbd_err_i,
output logic [31:0] s0_wbd_dat_o,
output logic [31:0] s0_wbd_adr_o,
output logic [3:0] s0_wbd_sel_o,
output logic s0_wbd_we_o,
output logic s0_wbd_cyc_o,
output logic s0_wbd_stb_o,
// Slave 1 Interface
input logic [31:0] s1_wbd_dat_i,
input logic s1_wbd_ack_i,
input logic s1_wbd_err_i,
output logic [31:0] s1_wbd_dat_o,
output logic [31:0] s1_wbd_adr_o,
output logic [3:0] s1_wbd_sel_o,
output logic s1_wbd_we_o,
output logic s1_wbd_cyc_o,
output logic s1_wbd_stb_o,
// Slave 2 Interface
input logic [31:0] s2_wbd_dat_i,
input logic s2_wbd_ack_i,
input logic s2_wbd_err_i,
output logic [31:0] s2_wbd_dat_o,
output logic [31:0] s2_wbd_adr_o,
output logic [3:0] s2_wbd_sel_o,
output logic s2_wbd_we_o,
output logic s2_wbd_cyc_o,
output logic s2_wbd_stb_o
);
////////////////////////////////////////////////////////////////////
//
// Type define
//
// WishBone Wr Interface
typedef struct packed {
logic [31:0] wbd_dat;
logic [31:0] wbd_adr;
logic [3:0] wbd_sel;
logic wbd_we;
logic wbd_cyc;
logic wbd_stb;
logic [3:0] wbd_tid; // target id
} type_wb_wr_intf;
// WishBone Rd Interface
typedef struct packed {
logic [31:0] wbd_dat;
logic wbd_ack;
logic wbd_err;
} type_wb_rd_intf;
// Master Write Interface
type_wb_wr_intf m0_wb_wr;
type_wb_wr_intf m1_wb_wr;
type_wb_wr_intf m2_wb_wr;
// Master Read Interface
type_wb_rd_intf m0_wb_rd;
type_wb_rd_intf m1_wb_rd;
type_wb_rd_intf m2_wb_rd;
// Slave Write Interface
type_wb_wr_intf s0_wb_wr;
type_wb_wr_intf s1_wb_wr;
type_wb_wr_intf s2_wb_wr;
// Slave Read Interface
type_wb_rd_intf s0_wb_rd;
type_wb_rd_intf s1_wb_rd;
type_wb_rd_intf s2_wb_rd;
type_wb_wr_intf i_bus_m; // Multiplexed Master I/F
type_wb_rd_intf i_bus_s; // Multiplexed Slave I/F
//------------------------------
// RISC Data Memory Map
// 0x0000_0000 to 0x0FFF_FFFF - SPI FLASH MEMORY
// 0x1000_0000 to 0x1000_00FF - SPI REGISTER
// 0x2000_0000 to 0x2FFF_FFFF - SDRAM
// 0x3000_0000 to 0x3000_00FF - GLOBAL REGISTER
//-----------------------------
//
wire [3:0] m0_wbd_tid_i = (m0_wbd_adr_i[31:28] == 4'b0000 ) ? 4'b0000 :
(m0_wbd_adr_i[31:28] == 4'b0001 ) ? 4'b0000 :
(m0_wbd_adr_i[31:28] == 4'b0010 ) ? 4'b0001 :
(m0_wbd_adr_i[31:28] == 4'b0011 ) ? 4'b0010 : 4'b0000;
wire [3:0] m1_wbd_tid_i = (m1_wbd_adr_i[31:28] == 4'b0000 ) ? 4'b0000 :
(m1_wbd_adr_i[31:28] == 4'b0001 ) ? 4'b0000 :
(m1_wbd_adr_i[31:28] == 4'b0010 ) ? 4'b0001 :
(m1_wbd_adr_i[31:28] == 4'b0011 ) ? 4'b0010 : 4'b0000;
//-------------------------------------------------------------------
// EXTERNAL MEMORY MAP
// 0x3000_0000 to 0x3000_00FF - GLOBAL REGISTER
// 0x4000_0000 to 0x4FFF_FFFF - SPI FLASH MEMORY
// 0x5000_0000 to 0x5000_00FF - SPI REGISTER
// 0x6000_0000 to 0x6FFF_FFFF - SDRAM
//
wire [3:0] m2_wbd_tid_i = (m2_wbd_adr_i[31:28] == 4'b0100 ) ? 4'b0000 :
(m2_wbd_adr_i[31:28] == 4'b0101 ) ? 4'b0000 :
(m2_wbd_adr_i[31:28] == 4'b0110 ) ? 4'b0001 :
(m2_wbd_adr_i[31:28] == 4'b0011 ) ? 4'b0010 : 4'b0000;
//----------------------------------------
// Master Mapping
// -------------------------------------
assign m0_wb_wr.wbd_dat = m0_wbd_dat_i;
assign m0_wb_wr.wbd_adr = m0_wbd_adr_i;
assign m0_wb_wr.wbd_sel = m0_wbd_sel_i;
assign m0_wb_wr.wbd_we = m0_wbd_we_i;
assign m0_wb_wr.wbd_cyc = m0_wbd_cyc_i;
assign m0_wb_wr.wbd_stb = m0_wbd_stb_i;
assign m0_wb_wr.wbd_tid = m0_wbd_tid_i;
assign m1_wb_wr.wbd_dat = m1_wbd_dat_i;
assign m1_wb_wr.wbd_adr = m1_wbd_adr_i;
assign m1_wb_wr.wbd_sel = m1_wbd_sel_i;
assign m1_wb_wr.wbd_we = m1_wbd_we_i;
assign m1_wb_wr.wbd_cyc = m1_wbd_cyc_i;
assign m1_wb_wr.wbd_stb = m1_wbd_stb_i;
assign m1_wb_wr.wbd_tid = m1_wbd_tid_i;
assign m2_wb_wr.wbd_dat = m2_wbd_dat_i;
assign m2_wb_wr.wbd_adr = m2_wbd_adr_i;
assign m2_wb_wr.wbd_sel = m2_wbd_sel_i;
assign m2_wb_wr.wbd_we = m2_wbd_we_i;
assign m2_wb_wr.wbd_cyc = m2_wbd_cyc_i;
assign m2_wb_wr.wbd_stb = m2_wbd_stb_i;
assign m2_wb_wr.wbd_tid = m2_wbd_tid_i;
assign m0_wbd_dat_o = m0_wb_rd.wbd_dat;
assign m0_wbd_ack_o = m0_wb_rd.wbd_ack;
assign m0_wbd_err_o = m0_wb_rd.wbd_err;
assign m1_wbd_dat_o = m1_wb_rd.wbd_dat;
assign m1_wbd_ack_o = m1_wb_rd.wbd_ack;
assign m1_wbd_err_o = m1_wb_rd.wbd_err;
assign m2_wbd_dat_o = m2_wb_rd.wbd_dat;
assign m2_wbd_ack_o = m2_wb_rd.wbd_ack;
assign m2_wbd_err_o = m2_wb_rd.wbd_err;
assign s0_wb_rd.wbd_dat = s0_wbd_dat_i ;
assign s0_wb_rd.wbd_ack = s0_wbd_ack_i ;
assign s0_wb_rd.wbd_err = s0_wbd_err_i ;
assign s1_wb_rd.wbd_dat = s1_wbd_dat_i ;
assign s1_wb_rd.wbd_ack = s1_wbd_ack_i ;
assign s1_wb_rd.wbd_err = s1_wbd_err_i ;
assign s2_wb_rd.wbd_dat = s2_wbd_dat_i ;
assign s2_wb_rd.wbd_ack = s2_wbd_ack_i ;
assign s2_wb_rd.wbd_err = s2_wbd_err_i ;
//----------------------------------------
// Slave Mapping
// -------------------------------------
assign s0_wbd_dat_o = s0_wb_wr.wbd_dat ;
assign s0_wbd_adr_o = s0_wb_wr.wbd_adr ;
assign s0_wbd_sel_o = s0_wb_wr.wbd_sel ;
assign s0_wbd_we_o = s0_wb_wr.wbd_we ;
assign s0_wbd_cyc_o = s0_wb_wr.wbd_cyc ;
assign s0_wbd_stb_o = s0_wb_wr.wbd_stb ;
assign s1_wbd_dat_o = s1_wb_wr.wbd_dat ;
assign s1_wbd_adr_o = s1_wb_wr.wbd_adr ;
assign s1_wbd_sel_o = s1_wb_wr.wbd_sel ;
assign s1_wbd_we_o = s1_wb_wr.wbd_we ;
assign s1_wbd_cyc_o = s1_wb_wr.wbd_cyc ;
assign s1_wbd_stb_o = s1_wb_wr.wbd_stb ;
assign s2_wbd_dat_o = s2_wb_wr.wbd_dat ;
assign s2_wbd_adr_o = s2_wb_wr.wbd_adr ;
assign s2_wbd_sel_o = s2_wb_wr.wbd_sel ;
assign s2_wbd_we_o = s2_wb_wr.wbd_we ;
assign s2_wbd_cyc_o = s2_wb_wr.wbd_cyc ;
assign s2_wbd_stb_o = s2_wb_wr.wbd_stb ;
//
// arbitor
//
logic [1:0] gnt;
wb_arb u_wb_arb(
.clk(clk_i),
.rstn(rst_n),
.req({ m2_wbd_cyc_i,
m1_wbd_cyc_i,
m0_wbd_cyc_i}),
.gnt(gnt)
);
// Generate Multiplexed Master Interface based on grant
always_comb begin
case(gnt)
3'h0: i_bus_m = m0_wb_wr;
3'h1: i_bus_m = m1_wb_wr;
3'h2: i_bus_m = m2_wb_wr;
default: i_bus_m = m0_wb_wr;
endcase
end
// Generate Multiplexed Slave Interface based on target Id
wire [3:0] wbd_tid = i_bus_m.wbd_tid; // to fix iverilog warning
always_comb begin
case(wbd_tid)
3'h0: i_bus_s = s0_wb_rd;
3'h1: i_bus_s = s1_wb_rd;
3'h2: i_bus_s = s2_wb_rd;
default: i_bus_s = s0_wb_rd;
endcase
end
// Connect Master => Slave
assign s0_wb_wr = (i_bus_m.wbd_tid == 2'b00) ? i_bus_m : 'h0;
assign s1_wb_wr = (i_bus_m.wbd_tid == 2'b01) ? i_bus_m : 'h0;
assign s2_wb_wr = (i_bus_m.wbd_tid == 2'b10) ? i_bus_m : 'h0;
// Connect Slave to Master
assign m0_wb_rd = (gnt == 2'b00) ? i_bus_s : 'h0;
assign m1_wb_rd = (gnt == 2'b01) ? i_bus_s : 'h0;
assign m2_wb_rd = (gnt == 2'b10) ? i_bus_s : 'h0;
endmodule