URL
https://opencores.org/ocsvn/yifive/yifive/trunk
Subversion Repositories yifive
[/] [yifive/] [trunk/] [caravel_yifive/] [verilog/] [rtl/] [lib/] [wb_crossbar.v] - Rev 23
Go to most recent revision | Compare with Previous | Blame | View Log
////////////////////////////////////////////////////////////////////// //// //// //// 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
Go to most recent revision | Compare with Previous | Blame | View Log