OpenCores
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.