////////////////////////////////////////////////////////////////////////////////
//
//       This confidential and proprietary software may be used only
//     as authorized by a licensing agreement from Synopsys Inc.
//     In the event of publication, the following notice is applicable:
//
//                    (C) COPYRIGHT 2004 - 2018 SYNOPSYS INC.
//                           ALL RIGHTS RESERVED
//
//       The entire notice above must be reproduced on all authorized
//     copies.
//
// AUTHOR:    bruce dean June 26th. 2004
//
// VERSION:   Simulation model
//
// DesignWare_version: 0d24140b
// DesignWare_release: O-2018.06-DWBB_201806.1
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
// ABSTRACT: Generic pulse sychronization block 
//
//
//----------------------------------------------------------------------------
//              Parameters:     Valid Values
//              ==========      ============
//		reg_event       [ 0 => event_d will have combination logic
//				       but latency will be 1 cycle sooner
//				  1 => event_d will be retimed so there will
//				       be no logic between register & port
//				       but event is delayed 1 cycle]
//              f_sync_type     [ 0 = single clock design, no synchronizing stages implemented,
//                                1 = 2-stage synchronization w/ 1st stage neg-edge & 2nd stage pos-edge capturing,
//                                2 = 2-stage synchronization w/ both stages pos-edge capturing,
//                                3 = 3-stage synchronization w/ all stages pos-edge capturing ]
//                                4 = 4-stage synchronization w/ all stages pos-edge capturing ]
//              tst_mode        [ 0 = no hold latch inserted,
//                                1 = insert hold 'latch' using a neg-edge triggered register
//                                2 = insert active-low hold latch ]
//              verif_en        [ 0 = no sampling errors inserted,
//                                1 = sampling errors are randomly inserted with 0 or up to 1 destination clock cycle delays
//                                2 = sampling errors are randomly inserted with 0, 0.5, 1, or 1.5 destination clock cycle delays
//                                3 = sampling errors are randomly inserted with 0, 1, 2, or 3 destination clock cycle delays
//                                4 = sampling errors are randomly inserted with 0 or up to 0.5 destination clock cycle delays ]
//              pulse_mode      [ 0 =>  single clock cycle pulse in produces
//                                      single clock cycle pulse out
//                                1 =>  rising edge transition in produces
//                                2 =>  falling edge transition in produces
//                                      single clock cycle pulse out
//                                3 =>  toggle transition in produces
//                                      single clock cycle pulse out]
///
//              Input Ports:    Size     Description
//              ===========     ====     ===========
//              clk_s           1 bit    Source Domain Input Clock
//              rst_s_n         1 bit    Source Domain Active Low Async. Reset
//              init_s_n        1 bit    Source Domain Active Low Sync. Reset
//              send_s          1 bit    Source Domain Active High Send Request
//              data_s          N bits   Source Domain Data Input
//              clk_d           1 bit    Destination Domain Input Clock
//              rst_d_n         1 bit    Destination Domain Active Low Async. Reset
//              init_d_n        1 bit    Destination Domain Active Low Sync. Reset
//              test            1 bit    Test input
//
//              Output Ports    Size     Description
//              ============    ====     ===========
//              event_d         1 bit    Dest Domain Active High Event Signal
//
// MODIFIED: 
//
//              RJK   3-08-17  Corrected port order to be consistent with synthesis
//
//              DLL   9-21-11  Added tst_mode=2 checking and comments (not a functional change)
//
//----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
module DW_pulse_sync
            (
             clk_s, 
	     rst_s_n, 
	     init_s_n, 
	     event_s, 
	     clk_d, 
             rst_d_n, 
	     init_d_n,
	     event_d,
	     test
	     );
 parameter integer reg_event = 0;	// 0 => event_d will have combination logic
				//       but latency will be 1 cycle sooner
				// 1 => event_d will be retimed so there will
				//       be no logic between register & port
				//       but event is delayed 1 cycle

 parameter integer f_sync_type = 1;	// 0 - 3
				// 0 => single clock design, i.e. clk_d == clk_s
				// 1 => first synchronization in clk_d domain is
				//       done on the negative edge and the rest
				//       on positive edge.  This reduces latency
				//       req. of synchronization slightly but
				//       quicker metastability resolution for
				//       the negative edge sensitive FF. It also
				//       requires the technology library to 
				//       contain an acceptable negative edge 
                                //       sensitive FF.
				// 2 =>  all synchronization in clk_d domain is
				//       done on positive edges - 2 d flops in
				//       destination domain
				// 3 =>  all synchronization in clk_d domain is
				//       done on positive edges - 3 d flops in
				//       destination domain
				// 4 =>  all synchronization in clk_d domain is
				//       done on positive edges - 4 d flops in
				//       destination domain
 parameter integer tst_mode = 0;	// 0-2
                                // 0 =>  no latch insertion
				// 1 =>  hold latch using neg edge flop
				// 2 =>  reserved unsupported

 parameter integer verif_en = 1;        // 0-4
                                // 0 =>  no sampling errors are used
				// 1 =>  random insertion of 0 or upt to 1 dest clk
				// 2 =>  random insertion of 0,0.5,1,or 1.5 dest clk
				// 3 =>  random insertion of 0,1,2,or 3 dest clk
				// 4 =>  random insertion of 0 or up to 0.5 dest clk
 parameter integer pulse_mode   = 0;    // 0 =>  single clock cycle pulse in produces
                                //       single clock cycle pulse out
                                // 1 =>  rising edge transition in produces
                                // 2 =>  falling edge transition in produces
                                //       single clock cycle pulse out
                                // 3 =>  toggle transition in produces
                                //       single clock cycle pulse out

input  clk_s;			// clock input for source domain
input  rst_s_n;			// active low async. reset in clk_s domain
input  init_s_n;		// active low sync. reset in clk_s domain
input  event_s;			// event pulse input (active high event)
input  clk_d;			// clock input for destination domain
input  rst_d_n;			// active low async. reset in clk_d domain
input  init_d_n;		// active low sync. reset in clk_d domain
output event_d;			// event pulse output (active high event)
input  test;                    // test  1 bit   Test input

  initial begin
    if ((f_sync_type > 0)&&(f_sync_type < 8))
      $display("Information: *** Instance %m is the DW_pulse_sync Clock Domain Crossing Module ***");
  end

// synopsys translate_off
// Param check
  
 
  initial begin : parameter_check
    integer param_err_flg;

    param_err_flg = 0;
    
  
    if ( (reg_event < 0) || (reg_event > 1) ) begin
      param_err_flg = 1;
      $display(
	"ERROR: %m :\n  Invalid value (%d) for parameter reg_event (legal range: 0 to 1)",
	reg_event );
    end
  
    if ( ((f_sync_type & 7) < 0) || ((f_sync_type & 7) > 4) ) begin
      param_err_flg = 1;
      $display(
	"ERROR: %m :\n  Invalid value (%d) for parameter (f_sync_type & 7) (legal range: 0 to 4)",
	(f_sync_type & 7) );
    end
  
    if ( (tst_mode < 0) || (tst_mode > 2) ) begin
      param_err_flg = 1;
      $display(
	"ERROR: %m :\n  Invalid value (%d) for parameter tst_mode (legal range: 0 to 2)",
	tst_mode );
    end
  
    if ( (verif_en < 0) || (verif_en > 4) ) begin
      param_err_flg = 1;
      $display(
	"ERROR: %m :\n  Invalid value (%d) for parameter verif_en (legal range: 0 to 4)",
	verif_en );
    end
  
    if ( (pulse_mode < 0) || (pulse_mode > 3) ) begin
      param_err_flg = 1;
      $display(
	"ERROR: %m :\n  Invalid value (%d) for parameter pulse_mode (legal range: 0 to 3)",
	pulse_mode );
    end
  
    if ( param_err_flg == 1) begin
      $display(
        "%m :\n  Simulation aborted due to invalid parameter value(s)");
      $finish;
    end

  end // parameter_check 

wire       O0I100OO;
reg        O1O10OI0;
reg        OO10OI10;
reg  [1:0] O0OlIO00;
wire       II1lIlI0;
reg        OOO01l10;
reg        O00O000l;
wire       O101lOO0;

  
generate
  if (((f_sync_type&7)>1)&&(tst_mode==2)) begin : GEN_LATCH_frwd_hold_latch_PROC
    reg [1-1:0] OO10OI10;
    always @ (clk_s or O1O10OI0) begin : LATCH_frwd_hold_latch_PROC_PROC

      if (clk_s == 1'b0)

	OO10OI10 = O1O10OI0;


    end // LATCH_frwd_hold_latch_PROC_PROC


    assign O0I100OO = (test==1'b1)? OO10OI10 : O1O10OI0;

  end else begin : GEN_DIRECT_frwd_hold_latch_PROC
    assign O0I100OO = O1O10OI0;
  end
endgenerate

  DW_sync #(1, f_sync_type+8, tst_mode, verif_en) SIM(
	.clk_d(clk_d),
	.rst_d_n(rst_d_n),
	.init_d_n(init_d_n),
	.data_s(O0I100OO),
	.test(test),
	.data_d(II1lIlI0) );
assign O101lOO0 = pulse_mode === 0 ? event_s ^ O1O10OI0 
                   :(pulse_mode === 1? (event_s & ! O00O000l) ^ O1O10OI0  
		   :(pulse_mode === 2? (!event_s & O00O000l) ^ O1O10OI0
                   :(pulse_mode === 3? (event_s ^ O00O000l) ^ O1O10OI0: 1'bx)));
always @ ( posedge clk_s or negedge rst_s_n   ) begin : a1000_PROC
  if(rst_s_n === 1'b0 ) begin
    O1O10OI0 <= 1'b0;
    O00O000l  <= 1'b0;
  end else if(rst_s_n === 1'b1 )  begin
    if(init_s_n === 1'b0 ) begin 
      O1O10OI0 <= 1'b0;
      O00O000l  <= 1'b0;
    end else if(init_s_n === 1'b1 ) begin
      if(event_s === 1'b1) begin 
        O1O10OI0 <= O101lOO0;
        O00O000l  <= event_s;
      end else if(event_s !== 1'b0) begin
        O1O10OI0 <= 1'bx;
        O00O000l  <= 1'bx;
      end else begin
        O1O10OI0 <= O101lOO0;
        O00O000l  <= event_s;
      end
    end else begin
       O1O10OI0 <= 1'bx;
       O00O000l  <= 1'bx;
    end
  end else begin
    O1O10OI0 <= 1'bx;
    O00O000l  <= 1'bx;
  end
end
 always @ ( posedge clk_d or negedge  rst_d_n) begin : a1001_PROC
  if(rst_d_n === 1'b0 )
    O0OlIO00 <= 2'b00;
  else if(rst_d_n === 1'b1 )
    if(init_d_n === 1'b0) 
      O0OlIO00 <= 2'b00;
    else if(init_d_n === 1'b1)
      O0OlIO00 <= {O0OlIO00[0] ^ II1lIlI0, II1lIlI0}; 
    else 
      O0OlIO00 <= 2'bxx;
  else 
    O0OlIO00 <= 2'bxx;
 end
 assign event_d = (reg_event) ? O0OlIO00[1] : O0OlIO00[0] ^ II1lIlI0 ;
 
  always @ (clk_d) begin : monitor_clk_d 
    if ( (clk_d !== 1'b0) && (clk_d !== 1'b1) && ($time > 0) )
      $display( "WARNING: %m :\n  at time = %t, detected unknown value, %b, on clk_d input.",
                $time, clk_d );
    end // monitor_clk_d 
 
  always @ (clk_s) begin : monitor_clk_s 
    if ( (clk_s !== 1'b0) && (clk_s !== 1'b1) && ($time > 0) )
      $display( "WARNING: %m :\n  at time = %t, detected unknown value, %b, on clk_s input.",
                $time, clk_s );
    end // monitor_clk_s 
 // synopsys translate_on
  
endmodule
