////////////////////////////////////////////////////////////////////// | |
//// //// | |
//// yifive common library Module //// | |
//// //// | |
//// This file is part of the yifive cores project //// | |
//// http://www.opencores.org/cores/yifive/ //// | |
//// //// | |
//// Description //// | |
//// This module does the Wishone crossbar network //// | |
//// //// | |
//// To Do: //// | |
//// nothing //// | |
//// //// | |
//// Author(s): //// | |
//// - Dinesh Annayya, dinesha@opencores.org //// | |
//// //// | |
////////////////////////////////////////////////////////////////////// | |
//// Revision : //// | |
//// v0: Nov 26, 2016, Dinesh A //// | |
//// This files copied from my open core //// | |
//// turbo8051 project //// | |
////////////////////////////////////////////////////////////////////// | |
//// //// | |
//// 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 //// | |
//// //// | |
////////////////////////////////////////////////////////////////////// | |
/********************************************** | |
Wish-bone cross bar M-Master By S-Slave | |
**********************************************/ | |
module wb_crossbar ( | |
rst_n , | |
clk , | |
// Master Interface Signal | |
wbd_taddr_master , | |
wbd_din_master , | |
wbd_dout_master , | |
wbd_adr_master , | |
wbd_be_master , | |
wbd_we_master , | |
wbd_ack_master , | |
wbd_stb_master , | |
wbd_cyc_master , | |
wbd_err_master , | |
wbd_rty_master , | |
// Slave Interface Signal | |
wbd_din_slave , | |
wbd_dout_slave , | |
wbd_adr_slave , | |
wbd_be_slave , | |
wbd_we_slave , | |
wbd_ack_slave , | |
wbd_stb_slave , | |
wbd_cyc_slave , | |
wbd_err_slave , | |
wbd_rty_slave | |
); | |
parameter WB_SLAVE = 4 ; | |
parameter WB_MASTER = 4 ; | |
parameter D_WD = 16; // Data Width | |
parameter BE_WD = 2; // Byte Enable | |
parameter ADR_WD = 28; // Address Width | |
parameter TAR_WD = 4; // Target Width | |
input clk; // CLK_I The clock input [CLK_I] coordinates all activities | |
// for the internal logic within the WISHBONE interconnect. | |
// All WISHBONE output signals are registered at the | |
// rising edge of [CLK_I]. | |
// All WISHBONE input signals must be stable before the | |
// rising edge of [CLK_I]. | |
input rst_n; // RST_I The reset input [RST_I] forces the WISHBONE interface | |
// to restart. Furthermore, all internal self-starting state | |
// machines will be forced into an initial state. | |
input [(WB_MASTER *TAR_WD)-1:0] wbd_taddr_master; // target address from master | |
input [WB_MASTER-1:0] wbd_stb_master; | |
// STB_O The strobe output [STB_O] indicates a valid data | |
// transfer cycle. It is used to qualify various other signals | |
// on the interface such as [SEL_O(7..0)]. The SLAVE must | |
// assert either the [ACK_I], [ERR_I] or [RTY_I] signals in | |
// response to every assertion of the [STB_O] signal. | |
output [WB_SLAVE-1:0] wbd_stb_slave; | |
// STB_O The strobe output [STB_O] indicates a valid data | |
// transfer cycle. It is used to qualify various other signals | |
// on the interface such as [SEL_O(7..0)]. The SLAVE must | |
// assert either the [ACK_I], [ERR_I] or [RTY_I] signals in | |
// response to every assertion of the [STB_O] signal. | |
input [WB_MASTER-1:0] wbd_we_master; | |
// WE_O The write enable output [WE_O] indicates whether the | |
// current local bus cycle is a READ or WRITE cycle. The | |
// signal is negated during READ cycles, and is asserted | |
// during WRITE cycles. | |
output [WB_SLAVE-1:0] wbd_we_slave; | |
// WE_O The write enable output [WE_O] indicates whether the | |
// current local bus cycle is a READ or WRITE cycle. The | |
// signal is negated during READ cycles, and is asserted | |
// during WRITE cycles. | |
output [WB_MASTER-1:0] wbd_ack_master; | |
// The acknowledge input [ACK_I], when asserted, | |
// indicates the termination of a normal bus cycle. | |
// Also see the [ERR_I] and [RTY_I] signal descriptions. | |
input [WB_SLAVE-1:0] wbd_ack_slave; | |
// The acknowledge input [ACK_I], when asserted, | |
// indicates the termination of a normal bus cycle. | |
// Also see the [ERR_I] and [RTY_I] signal descriptions. | |
input [(WB_MASTER *ADR_WD)-1:0] wbd_adr_master; | |
// The address output array [ADR_O(63..0)] is used | |
// to pass a binary address, with the most significant | |
// address bit at the higher numbered end of the signal array. | |
// The lower array boundary is specific to the data port size. | |
// The higher array boundary is core-specific. | |
// In some cases (such as FIFO interfaces) | |
// the array may not be present on the interface. | |
output [(WB_SLAVE *ADR_WD)-1:0] wbd_adr_slave; | |
// The address output array [ADR_O(63..0)] is used | |
// to pass a binary address, with the most significant | |
// address bit at the higher numbered end of the signal array. | |
// The lower array boundary is specific to the data port size. | |
// The higher array boundary is core-specific. | |
// In some cases (such as FIFO interfaces) | |
// the array may not be present on the interface. | |
input [(WB_MASTER * BE_WD)-1:0] wbd_be_master; // Byte Enable | |
// SEL_O(7..0) The select output array [SEL_O(7..0)] indicates | |
// where valid data is expected on the [DAT_I(63..0)] signal | |
// array during READ cycles, and where it is placed on the | |
// [DAT_O(63..0)] signal array during WRITE cycles. | |
// Also see the [DAT_I(63..0)], [DAT_O(63..0)] and [STB_O] | |
// signal descriptions. | |
output [(WB_SLAVE * BE_WD)-1:0] wbd_be_slave; // Byte Enable | |
// SEL_O(7..0) The select output array [SEL_O(7..0)] indicates | |
// where valid data is expected on the [DAT_I(63..0)] signal | |
// array during READ cycles, and where it is placed on the | |
// [DAT_O(63..0)] signal array during WRITE cycles. | |
// Also see the [DAT_I(63..0)], [DAT_O(63..0)] and [STB_O] | |
// signal descriptions. | |
input [WB_MASTER -1:0] wbd_cyc_master; | |
// CYC_O The cycle output [CYC_O], when asserted, | |
// indicates that a valid bus cycle is in progress. | |
// The signal is asserted for the duration of all bus cycles. | |
// For example, during a BLOCK transfer cycle there can be | |
// multiple data transfers. The [CYC_O] signal is asserted | |
// during the first data transfer, and remains asserted | |
// until the last data transfer. The [CYC_O] signal is useful | |
// for interfaces with multi-port interfaces | |
// (such as dual port memories). In these cases, | |
// the [CYC_O] signal requests use of a common bus from an | |
// arbiter. Once the arbiter grants the bus to the MASTER, | |
// it is held until [CYC_O] is negated. | |
output [WB_SLAVE -1:0] wbd_cyc_slave; | |
// CYC_O The cycle output [CYC_O], when asserted, | |
// indicates that a valid bus cycle is in progress. | |
// The signal is asserted for the duration of all bus cycles. | |
// For example, during a BLOCK transfer cycle there can be | |
// multiple data transfers. The [CYC_O] signal is asserted | |
// during the first data transfer, and remains asserted | |
// until the last data transfer. The [CYC_O] signal is useful | |
// for interfaces with multi-port interfaces | |
// (such as dual port memories). In these cases, | |
// the [CYC_O] signal requests use of a common bus from an | |
// arbiter. Once the arbiter grants the bus to the MASTER, | |
// it is held until [CYC_O] is negated. | |
input [(WB_MASTER * D_WD)-1:0] wbd_din_master; | |
// DAT_I(63..0) The data input array [DAT_I(63..0)] is | |
// used to pass binary data. The array boundaries are | |
// determined by the port size. Also see the [DAT_O(63..0)] | |
// and [SEL_O(7..0)] signal descriptions. | |
output [(WB_SLAVE * D_WD)-1:0] wbd_din_slave; | |
// DAT_I(63..0) The data input array [DAT_I(63..0)] is | |
// used to pass binary data. The array boundaries are | |
// determined by the port size. Also see the [DAT_O(63..0)] | |
// and [SEL_O(7..0)] signal descriptions. | |
output [(WB_MASTER * D_WD)-1:0] wbd_dout_master; | |
// DAT_O(63..0) The data output array [DAT_O(63..0)] is | |
// used to pass binary data. The array boundaries are | |
// determined by the port size. Also see the [DAT_I(63..0)] | |
// and [SEL_O(7..0)] signal descriptions. | |
input [(WB_SLAVE * D_WD)-1:0] wbd_dout_slave; | |
// DAT_O(63..0) The data output array [DAT_O(63..0)] is | |
// used to pass binary data. The array boundaries are | |
// determined by the port size. Also see the [DAT_I(63..0)] | |
// and [SEL_O(7..0)] signal descriptions. | |
output [WB_MASTER -1:0] wbd_err_master; | |
// ERR_I The error input [ERR_I] indicates an abnormal | |
// cycle termination. The source of the error, and the | |
// response generated by the MASTER is defined by the IP core | |
// supplier in the WISHBONE DATASHEET. Also see the [ACK_I] | |
// and [RTY_I] signal descriptions. | |
input [WB_SLAVE -1:0] wbd_err_slave; | |
// ERR_I The error input [ERR_I] indicates an abnormal | |
// cycle termination. The source of the error, and the | |
// response generated by the MASTER is defined by the IP core | |
// supplier in the WISHBONE DATASHEET. Also see the [ACK_I] | |
// and [RTY_I] signal descriptions. | |
output [WB_MASTER -1:0] wbd_rty_master; | |
// RTY_I The retry input [RTY_I] indicates that the indicates | |
// that the interface is not ready to accept or send data, and | |
// that the cycle should be retried. When and how the cycle is | |
// retried is defined by the IP core supplier in the WISHBONE | |
// DATASHEET. Also see the [ERR_I] and [RTY_I] signal | |
// descriptions. | |
input [WB_SLAVE -1:0] wbd_rty_slave; | |
// RTY_I The retry input [RTY_I] indicates that the indicates | |
// that the interface is not ready to accept or send data, and | |
// that the cycle should be retried. When and how the cycle is | |
// retried is defined by the IP core supplier in the WISHBONE | |
// DATASHEET. Also see the [ERR_I] and [RTY_I] signal | |
// descriptions. | |
reg [WB_MASTER-1:0] wbd_ack_master; | |
reg [WB_MASTER-1:0] wbd_err_master; | |
reg [WB_MASTER-1:0] wbd_rty_master; | |
reg [WB_MASTER-1:0] master_busy; // master busy flag | |
reg [WB_SLAVE-1:0] slave_busy; // slave busy flag | |
reg [TAR_WD -1:0] master_mx_id[WB_MASTER-1:0]; | |
reg [TAR_WD -1:0] slave_mx_id [WB_SLAVE-1:0]; | |
wire [TAR_WD-1:0] wbd_taddr_master_t[WB_MASTER-1:0]; // target address from master | |
wire [D_WD-1:0] wbd_din_master_t[WB_MASTER-1:0]; // target address from master | |
reg [D_WD-1:0] wbd_dout_master_t[WB_MASTER-1:0]; // target address from master | |
wire [ADR_WD-1:0] wbd_adr_master_t[WB_MASTER-1:0]; // target address from master | |
wire [BE_WD-1:0] wbd_be_master_t[WB_MASTER-1:0]; // target address from master | |
reg [WB_SLAVE-1:0] wbd_stb_slave; | |
reg [WB_SLAVE-1:0] wbd_we_slave; | |
reg [WB_SLAVE-1:0] wbd_cyc_slave; | |
wire [D_WD-1:0] wbd_dout_slave_t[WB_SLAVE-1:0]; // target data towards master | |
reg [D_WD-1:0] wbd_din_slave_t[WB_SLAVE-1:0]; // target address from master | |
reg [ADR_WD-1:0] wbd_adr_slave_t[WB_SLAVE-1:0]; // target address from master | |
reg [BE_WD-1:0] wbd_be_slave_t[WB_SLAVE-1:0]; // target address from master | |
integer i,k,l,n; | |
/********************************************************** | |
Re-Arraging the array in seperate two dimensional information | |
***********************************************************/ | |
genvar j,m; | |
generate | |
// Connect the Master Mux | |
for(j=0; j < WB_MASTER ; j = j + 1) begin : master_expand | |
assign wbd_taddr_master_t[j] = wbd_taddr_master[((j+1)*TAR_WD)-1:j * TAR_WD]; | |
assign wbd_din_master_t[j] = wbd_din_master[((j+1)*D_WD)-1:j * D_WD]; | |
assign wbd_adr_master_t[j] = wbd_adr_master[((j+1)*ADR_WD)-1:j * ADR_WD]; | |
assign wbd_be_master_t[j] = wbd_be_master[((j+1)*BE_WD)-1:j * BE_WD]; | |
assign wbd_dout_master[((j+1)*D_WD)-1:j * D_WD] = wbd_dout_master_t[j]; | |
end | |
// Connect the Slave Mux | |
for(m=0; m < WB_SLAVE ; m = m + 1) begin : slave_expand | |
assign wbd_din_slave[((m+1)*D_WD)-1:m * D_WD] = wbd_din_slave_t[m]; | |
assign wbd_adr_slave[((m+1)*ADR_WD)-1:m * ADR_WD] = wbd_adr_slave_t[m]; | |
assign wbd_be_slave[((m+1)*BE_WD)-1:m * BE_WD] = wbd_be_slave_t[m]; | |
assign wbd_dout_slave_t[m] = wbd_dout_slave[((m+1)*D_WD)-1:m * D_WD]; | |
end | |
endgenerate | |
always @* begin | |
for(k = 0; k < WB_MASTER; k = k + 1) begin | |
if(master_busy[k] == 1) begin | |
wbd_dout_master_t[k] = wbd_dout_slave_t[master_mx_id[k]]; | |
wbd_ack_master[k] = wbd_ack_slave[master_mx_id[k]]; | |
wbd_err_master[k] = wbd_err_slave[master_mx_id[k]]; | |
wbd_rty_master[k] = wbd_rty_slave[master_mx_id[k]]; | |
end else begin | |
wbd_dout_master_t[k] = 0; | |
wbd_ack_master[k] = 0; | |
wbd_err_master[k] = 0; | |
wbd_rty_master[k] = 0; | |
end | |
end | |
for(l = 0; l < WB_SLAVE; l = l + 1) begin | |
if(slave_busy[l] == 1) begin | |
wbd_din_slave_t[l] = wbd_din_master_t[slave_mx_id[l]]; | |
wbd_adr_slave_t[l] = wbd_adr_master_t[slave_mx_id[l]]; | |
wbd_be_slave_t[l] = wbd_be_master_t[slave_mx_id[l]]; | |
wbd_stb_slave[l] = wbd_stb_master[slave_mx_id[l]]; | |
wbd_we_slave[l] = wbd_we_master[slave_mx_id[l]]; | |
wbd_cyc_slave[l] = wbd_cyc_master[slave_mx_id[l]]; | |
end else begin | |
wbd_din_slave_t[l] = 0; | |
wbd_adr_slave_t[l] = 0; | |
wbd_be_slave_t[l] = 0; | |
wbd_stb_slave[l] = 0; | |
wbd_we_slave[l] = 0; | |
wbd_cyc_slave[l] = 0; | |
end | |
end | |
end | |
/******************************************************* | |
Parsing through the master and deciding on mux connectio | |
Step-1: analysis the master from 0 to total master | |
Step-2: If the previously master is not busy, | |
Then check for any new request from the master and | |
check corresponding slave is free or not. If there is | |
master request and requesting slave is free. | |
Then set the master max id to slave id & | |
requesting slave to master number & set the master | |
and slave busy flag | |
Step-3: If the previous state of master is busy and bus-cycle | |
is de-asserted, then reset the master and corresponding | |
slave busy flag | |
*********************************************************/ | |
always @(negedge rst_n or posedge clk) begin | |
if(rst_n == 0) begin | |
master_busy <= 0; | |
slave_busy <= 0; | |
end else begin | |
for(i = 0; i < WB_MASTER; i = i + 1) begin | |
if(master_busy[i] == 0) begin | |
if(wbd_stb_master[i] & slave_busy[wbd_taddr_master_t[i]] == 0) begin | |
$display("Locking Master Id: %d for tar_master: %d, Total Master: %x ", i, wbd_taddr_master_t[i], wbd_taddr_master); | |
slave_busy[wbd_taddr_master_t[i]] = 1; | |
master_busy[i] = 1; | |
end | |
end else if(wbd_cyc_master[i] == 0) begin | |
master_busy[i] <= 0; | |
slave_busy[wbd_taddr_master_t[i]] <= 0; | |
end | |
end | |
end | |
end | |
// Seperated non resetable two dimensional reg | |
always @(posedge clk) begin | |
for(n = 0; n < WB_MASTER; n = n + 1) begin | |
if(master_busy[n] == 0) begin | |
if(wbd_stb_master[n] & slave_busy[wbd_taddr_master_t[n]] == 0) begin | |
master_mx_id[n] <= wbd_taddr_master_t[n]; | |
slave_mx_id [wbd_taddr_master_t[n]] <= n; | |
// synopsys translate_off | |
$display("%m:%t: Locking Master : %d with Slave : %d",$time,i,wbd_taddr_master_t[n]); | |
// synopsys translate_on | |
end | |
end else if(wbd_cyc_master[n] == 0) begin | |
if(master_busy[n] == 1) begin | |
// synopsys translate_off | |
$display("%m:%t: Releasing Master : %d with Slave : %d",$time,i,wbd_taddr_master_t[n]); | |
// synopsys translate_on | |
end | |
end | |
end | |
end | |
endmodule |