1 //////////////////////////////////////////////////////////////////////
 
   3 ////  File name "delayed_sync.v"                                  ////
 
   5 ////  This file is part of the "PCI bridge" project               ////
 
   6 ////  http://www.opencores.org/cores/pci/                         ////
 
   9 ////      - Miha Dolenc (mihad@opencores.org)                     ////
 
  11 ////  All additional information is avaliable in the README       ////
 
  15 //////////////////////////////////////////////////////////////////////
 
  17 //// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org          ////
 
  19 //// This source file may be used and distributed without         ////
 
  20 //// restriction provided that this copyright statement is not    ////
 
  21 //// removed from the file and that any derivative work contains  ////
 
  22 //// the original copyright notice and the associated disclaimer. ////
 
  24 //// This source file is free software; you can redistribute it   ////
 
  25 //// and/or modify it under the terms of the GNU Lesser General   ////
 
  26 //// Public License as published by the Free Software Foundation; ////
 
  27 //// either version 2.1 of the License, or (at your option) any   ////
 
  28 //// later version.                                               ////
 
  30 //// This source is distributed in the hope that it will be       ////
 
  31 //// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
 
  32 //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
 
  33 //// PURPOSE.  See the GNU Lesser General Public License for more ////
 
  36 //// You should have received a copy of the GNU Lesser General    ////
 
  37 //// Public License along with this source; if not, download it   ////
 
  38 //// from http://www.opencores.org/lgpl.shtml                     ////
 
  40 //////////////////////////////////////////////////////////////////////
 
  42 // CVS Revision History
 
  44 // $Log: pci_delayed_sync.v,v $
 
  45 // Revision 1.1  2007-03-20 17:50:56  sithglan
 
  48 // Revision 1.3  2003/08/14 13:06:02  simons
 
  49 // synchronizer_flop replaced with pci_synchronizer_flop, artisan ram instance updated.
 
  51 // Revision 1.2  2003/03/26 13:16:18  mihad
 
  52 // Added the reset value parameter to the synchronizer flop module.
 
  53 // Added resets to all synchronizer flop instances.
 
  54 // Repaired initial sync value in fifos.
 
  56 // Revision 1.1  2003/01/27 16:49:31  mihad
 
  57 // Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed.
 
  59 // Revision 1.5  2002/09/25 09:54:50  mihad
 
  60 // Added completion expiration test for WB Slave unit. Changed expiration signalling
 
  62 // Revision 1.4  2002/03/05 11:53:47  mihad
 
  63 // Added some testcases, removed un-needed fifo signals
 
  65 // Revision 1.3  2002/02/01 15:25:12  mihad
 
  66 // Repaired a few bugs, updated specification, added test bench files and design document
 
  68 // Revision 1.2  2001/10/05 08:14:28  mihad
 
  69 // Updated all files with inclusion of timescale file for simulation purposes.
 
  71 // Revision 1.1.1.1  2001/10/02 15:33:46  mihad
 
  72 // New project directory structure
 
  76 // module provides synchronization mechanism between requesting and completing side of the bridge
 
  77 `include "pci_constants.v"
 
  78 `include "bus_commands.v"
 
  80 // synopsys translate_off
 
  81 `include "timescale.v"
 
  82 // synopsys translate_on
 
  84 module pci_delayed_sync
 
  96     comp_comp_pending_out,
 
 114 input reset_in,         // reset input
 
 115       req_clk_in,       // requesting clock input
 
 116       comp_clk_in ;     // completing clock input
 
 118 // request, completion, done and in progress indication inputs
 
 119 input req_in,           // request qualifier - when 1 it indicates that valid request data is provided on inputs
 
 120       comp_in,          // completion qualifier - when 1, completing side indicates that request has completed
 
 121       done_in,          // done input - when 1 indicates that requesting side of the bridge has completed a transaction on requesting bus
 
 122       in_progress_in ;  // in progress indicator - indicates that current completion is in progress on requesting side of the bridge
 
 124 // pending indication outputs
 
 125 output  comp_req_pending_out,   // completion side request output - resynchronized from requesting clock to completing clock
 
 126         req_req_pending_out,    // request pending output for requesting side
 
 127         req_comp_pending_out,   // completion pending output for requesting side of the bridge - it indicates when completion is ready for completing on requesting bus
 
 128         comp_comp_pending_out ; // completion pending output for completing side of the bridge
 
 130 // additional signals and wires for clock domain passage of signals
 
 131 reg     comp_req_pending,
 
 134         req_comp_pending_sample,
 
 144 wire    sync_comp_req_pending,
 
 145         sync_req_comp_pending,
 
 148         sync_comp_rty_exp_clr ;
 
 150 // inputs from requesting side - only this side can set address, bus command, byte enables, write enable and burst - outputs are common for both sides
 
 151 // all signals that identify requests are stored in this module
 
 153 input [31:0]    addr_in ;   // address bus input
 
 154 input [3:0]     be_in ;     // byte enable input
 
 155 input           we_in ;     // write enable input - read/write request indication 1 = write request / 0 = read request
 
 156 input [3:0]     bc_in ;     // bus command input
 
 157 input           burst_in ;  // burst indicator    - qualifies operation as burst/single transfer 1 = burst / 0 = single transfer
 
 159 // common request outputs used both by completing and requesting sides
 
 160 // this outputs are not resynchronized, since flags determine the request status
 
 161 output [31:0]   addr_out ;
 
 162 output [3:0]    be_out ;
 
 164 output [3:0]    bc_out ;
 
 167 // completion side signals encoded termination status - 0 = normal completion / 1 = error terminated completion
 
 171 // input signals that delayed transaction has been retried for max number of times
 
 172 // on this signal request is ditched, otherwise it would cause a deadlock
 
 173 // requestor can issue another request and procedure will be repeated
 
 174 input   retry_expired_in ;
 
 176 // completion flush output - if in 2^^16 clock cycles transaction is not repeated by requesting agent - flush completion data
 
 177 output  comp_flush_out ;
 
 179 // output registers for common signals
 
 180 reg [31:0]   addr_out ;
 
 186 // delayed transaction information is stored only when request is issued and request nor completion are pending
 
 187 wire new_request = req_in && ~req_comp_pending_out && ~req_req_pending_out ;
 
 188 always@(posedge req_clk_in or posedge reset_in)
 
 192         addr_out  <= #`FF_DELAY 32'h0000_0000 ;
 
 193         be_out    <= #`FF_DELAY 4'h0 ;
 
 194         we_out    <= #`FF_DELAY 1'b0 ;
 
 195         bc_out    <= #`FF_DELAY `BC_RESERVED0 ;
 
 196         burst_out <= #`FF_DELAY 1'b0 ;
 
 201             addr_out  <= #`FF_DELAY addr_in ;
 
 202             be_out    <= #`FF_DELAY be_in ;
 
 203             we_out    <= #`FF_DELAY we_in ;
 
 204             bc_out    <= #`FF_DELAY bc_in ;
 
 205             burst_out <= #`FF_DELAY burst_in ;
 
 209 // completion pending cycle counter
 
 210 reg [16:0] comp_cycle_count ;
 
 212 /*=================================================================================================================================
 
 213 Passing of requests between clock domains:
 
 214 request originates on requesting side. It's then synchronized with two flip-flops to cross to completing clock domain
 
 215 =================================================================================================================================*/
 
 216 // main request flip-flop triggered on requesting side's clock
 
 217 // request is cleared whenever completion or retry expired is signalled from opposite side of the bridge
 
 218 wire req_req_clear = req_comp_pending || (req_rty_exp_reg && ~req_rty_exp_clr) ;
 
 219 always@(posedge req_clk_in or posedge reset_in)
 
 222         req_req_pending <= #`FF_DELAY 1'b0 ;
 
 225         req_req_pending <= #`FF_DELAY 1'b0 ;
 
 228         req_req_pending <= #`FF_DELAY 1'b1 ;
 
 231 // interemediate stage request synchronization flip - flop - this one is prone to metastability
 
 232 // and should have setup and hold times disabled during simulation
 
 233 pci_synchronizer_flop #(1, 0) req_sync
 
 235     .data_in        (req_req_pending),
 
 236     .clk_out        (comp_clk_in),
 
 237     .sync_data_out  (sync_comp_req_pending),
 
 238     .async_reset    (reset_in)
 
 241 // wire for clearing completion side request flag - whenever completion or retry expired are signalled
 
 242 wire comp_req_pending_clear = comp_req_pending && ( comp_in || retry_expired_in) ;
 
 244 // wire for enabling request flip - flop - it is enabled when completion is not active and done is not active
 
 245 wire comp_req_pending_ena   = ~comp_comp_pending && ~comp_done_reg_main && ~comp_rty_exp_reg ;
 
 247 // completion side request flip flop - gets a value from intermediate stage sync flip flop
 
 248 always@(posedge comp_clk_in or posedge reset_in)
 
 251         comp_req_pending <= #`FF_DELAY 1'b0 ;
 
 253     if ( comp_req_pending_clear )
 
 254         comp_req_pending <= #`FF_DELAY 1'b0 ;
 
 256     if ( comp_req_pending_ena )
 
 257         comp_req_pending <= #`FF_DELAY sync_comp_req_pending ;
 
 260 // completion side request output assignment - when request ff is set and completion ff is not set
 
 261 assign comp_req_pending_out = comp_req_pending ;
 
 263 // requesting side request pending output
 
 264 assign req_req_pending_out  = req_req_pending ;
 
 265 /*=================================================================================================================================
 
 266 Passing of completions between clock domains:
 
 267 completion originates on completing side. It's then synchronized with two flip-flops to cross to requesting clock domain
 
 268 =================================================================================================================================*/
 
 269 // main completion Flip - Flop - triggered by completing side's clock
 
 270 // completion side completion pending flag is cleared when done flag propagates through clock domains
 
 271 wire comp_comp_clear = comp_done_reg_main && ~comp_done_reg_clr ;
 
 272 always@(posedge comp_clk_in or posedge reset_in)
 
 275         comp_comp_pending <= #`FF_DELAY 1'b0 ;
 
 277     if ( comp_comp_clear )
 
 278         comp_comp_pending <= #`FF_DELAY 1'b0 ;
 
 280     if ( comp_in && comp_req_pending )
 
 281         comp_comp_pending <= #`FF_DELAY 1'b1 ;
 
 284 assign comp_comp_pending_out = comp_comp_pending ;
 
 286 // interemediate stage completion synchronization flip - flop - this one is prone to metastability
 
 287 pci_synchronizer_flop #(1, 0) comp_sync
 
 289     .data_in        (comp_comp_pending),
 
 290     .clk_out        (req_clk_in),
 
 291     .sync_data_out  (sync_req_comp_pending),
 
 292     .async_reset    (reset_in)
 
 295 // request side completion pending flip flop is cleared whenever done is signalled or completion counter expires - 2^^16 clock cycles
 
 296 wire req_comp_pending_clear = done_in || comp_cycle_count[16];
 
 298 // request side completion pending flip flop is disabled while done flag is set
 
 299 wire req_comp_pending_ena   = ~req_done_reg ;
 
 301 // request side completion flip flop - gets a value from intermediate stage sync flip flop
 
 302 always@(posedge req_clk_in or posedge reset_in)
 
 305         req_comp_pending <= #`FF_DELAY 1'b0 ;
 
 307     if ( req_comp_pending_clear )
 
 308         req_comp_pending <= #`FF_DELAY 1'b0 ;
 
 310     if ( req_comp_pending_ena )
 
 311         req_comp_pending <= #`FF_DELAY sync_req_comp_pending ;
 
 314 // sampling FF - used for sampling incoming completion flag from completing side
 
 315 always@(posedge req_clk_in or posedge reset_in)
 
 318         req_comp_pending_sample <= #`FF_DELAY 1'b0 ;
 
 320         req_comp_pending_sample <= #`FF_DELAY sync_req_comp_pending ;
 
 323 // requesting side completion pending output assignment
 
 324 assign req_comp_pending_out = req_comp_pending && ~req_req_pending ;
 
 326 /*==================================================================================================================================
 
 327 Passing of delayed transaction done signal between clock domains.
 
 328 Done is signalled by requesting side of the bridge and is passed to completing side of the bridge
 
 329 ==================================================================================================================================*/
 
 330 // main done flip-flop triggered on requesting side's clock
 
 331 // when completing side removes completion flag, done flag is also removed, so requests can proceede
 
 332 wire req_done_clear = ~req_comp_pending_sample ;
 
 333 always@(posedge req_clk_in or posedge reset_in)
 
 336         req_done_reg <= #`FF_DELAY 1'b0 ;
 
 338     if ( req_done_clear )
 
 339         req_done_reg <= #`FF_DELAY 1'b0 ;
 
 341     if ( done_in || comp_cycle_count[16] )
 
 342         req_done_reg <= #`FF_DELAY 1'b1 ;
 
 345 pci_synchronizer_flop  #(1, 0) done_sync
 
 347     .data_in        (req_done_reg),
 
 348     .clk_out        (comp_clk_in),
 
 349     .sync_data_out  (sync_comp_done),
 
 350     .async_reset    (reset_in)
 
 353 always@(posedge comp_clk_in or posedge reset_in)
 
 356         comp_done_reg_main <= #`FF_DELAY 1'b0 ;
 
 358         comp_done_reg_main <= #`FF_DELAY sync_comp_done ;
 
 361 always@(posedge comp_clk_in or posedge reset_in)
 
 364         comp_done_reg_clr <= #`FF_DELAY 1'b0 ;
 
 366         comp_done_reg_clr <= #`FF_DELAY comp_done_reg_main ;
 
 369 /*=================================================================================================================================
 
 370 Passing of retry expired signal between clock domains
 
 371 Retry expiration originates on completing side. It's then synchronized with two flip-flops to cross to requesting clock domain
 
 372 =================================================================================================================================*/
 
 373 // main retry expired Flip - Flop - triggered by completing side's clock
 
 374 wire comp_rty_exp_clear = comp_rty_exp_clr && comp_rty_exp_reg ;
 
 376 // retry expired is a special case of transaction removal - retry expired propagates from completing
 
 377 // clock domain to requesting clock domain to remove all pending requests and than propagates back
 
 378 // to completing side to qualify valid new requests
 
 380 always@(posedge comp_clk_in or posedge reset_in)
 
 383         comp_rty_exp_reg <= #`FF_DELAY 1'b0 ;
 
 385     if ( comp_rty_exp_clear )
 
 386         comp_rty_exp_reg <= #`FF_DELAY 1'b0 ;
 
 388     if ( retry_expired_in && comp_req_pending)
 
 389         comp_rty_exp_reg <= #`FF_DELAY 1'b1 ;
 
 392 // interemediate stage retry expired synchronization flip - flop - this one is prone to metastability
 
 393 pci_synchronizer_flop #(1, 0) rty_exp_sync
 
 395     .data_in        (comp_rty_exp_reg),
 
 396     .clk_out        (req_clk_in),
 
 397     .sync_data_out  (sync_req_rty_exp),
 
 398     .async_reset    (reset_in)
 
 401 // request retry expired flip flop - gets a value from intermediate stage sync flip flop
 
 402 always@(posedge req_clk_in or posedge reset_in)
 
 405         req_rty_exp_reg <= #`FF_DELAY 1'b0 ;
 
 407         req_rty_exp_reg <= #`FF_DELAY sync_req_rty_exp ;
 
 410 always@(posedge req_clk_in or posedge reset_in)
 
 413         req_rty_exp_clr <= #`FF_DELAY 1'b0 ;
 
 415         req_rty_exp_clr <= #`FF_DELAY req_rty_exp_reg ;
 
 418 pci_synchronizer_flop #(1, 0) rty_exp_back_prop_sync
 
 420     .data_in        (req_rty_exp_reg && req_rty_exp_clr),
 
 421     .clk_out        (comp_clk_in),
 
 422     .sync_data_out  (sync_comp_rty_exp_clr),
 
 423     .async_reset    (reset_in)
 
 426 always@(posedge comp_clk_in or posedge reset_in)
 
 429         comp_rty_exp_clr <= #`FF_DELAY 1'b0 ;
 
 431         comp_rty_exp_clr <= #`FF_DELAY sync_comp_rty_exp_clr ;
 
 434 // completion status flip flop - if 0 when completion is signalled it's finished OK otherwise it means error
 
 436 always@(posedge comp_clk_in or posedge reset_in)
 
 439         status_out <= #`FF_DELAY 1'b0 ;
 
 441     if (comp_in && comp_req_pending)
 
 442         status_out <= #`FF_DELAY status_in ;
 
 445 // clocks counter - it counts how many clock cycles completion is present without beeing repeated
 
 446 // if it counts to 2^^16 cycles the completion must be ditched
 
 448 // wire for clearing this counter
 
 449 wire clear_count = in_progress_in || ~req_comp_pending_out || comp_cycle_count[16] ;
 
 450 always@(posedge req_clk_in or posedge reset_in)
 
 453         comp_cycle_count <= #`FF_DELAY 17'h0_0000 ;
 
 456         comp_cycle_count <= #`FF_DELAY 17'h0_0000 ;
 
 458         comp_cycle_count <= #`FF_DELAY comp_cycle_count + 1'b1 ;
 
 461 // completion flush output - used for flushing fifos when counter expires
 
 462 // if counter doesn't expire, fifo flush is up to WISHBONE slave or PCI target state machines
 
 464 always@(posedge req_clk_in or posedge reset_in)
 
 467         comp_flush_out <= #`FF_DELAY 1'b0 ;
 
 469         comp_flush_out <= #`FF_DELAY comp_cycle_count[16] ;
 
 472 endmodule //delayed_sync