////////////////////////////////////////////////////////////////////////////////
//
//       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 2005 - 2018 SYNOPSYS INC.
//                           ALL RIGHTS RESERVED
//
//       The entire notice above must be reproduced on all authorized
//     copies.
//
// AUTHOR:    Doug Lee         12/20/05
//
// VERSION:   Simulation Architecture
//
// DesignWare_version: 2105953f
// DesignWare_release: O-2018.06-DWBB_201806.1
//
////////////////////////////////////////////////////////////////////////////////
//
// ABSTRACT: Data Stream Synchronizer Simulation Model
//
//           This synchronizes an incoming data stream from a source domain
//           to a destination domain with a minimum amount of latency.
//
//       Parameters:     Valid Values    Description
//       ==========      ============    ===========
//       width            1 to 1024      default: 8
//                                       Width of data_s and data_d ports
//
//       depth            2 to 256       default: 4
//                                       Depth of FIFO
//
//       prefill_lvl     0 to depth-1    default: 0
//                                       number of FIFO locations filled before
//                                       transferring to destination domain ]
//
//       f_sync_type       0 to 4        default: 2
//                                       Forward Synchronization Type (Source to Destination Domains)
//                                         0 => no synchronization, single clock system
//                                         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
//
//       reg_stat          0 or 1        default: 1
//                                       Register internally calculated status
//                                         0 => don't register internally calculated status
//                                         1 => register internally calculated status
//
//       tst_mode          0 or 2        default: 0
//                                       Insert neg-edge hold latch at front-end of synchronizers during "test"
//                                         0 => no hold latch inserted,
//                                         1 => insert hold 'latch' using a neg-edge triggered register
//                                         2 => insert hold latch using an active low latch
//
//       verif_en          0 to 4        default: 1
//                                       Enable missampling of synchronized signals during simulation
//                                         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
//
//       r_sync_type       0 to 4        default: 2
//                                       Reverse Synchronization Type (Destination to Source Domains)
//                                         0 => no synchronization, single clock system
//                                         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
//
//       clk_d_faster      0 to 15       default: 1
//                                       clk_d faster than clk_s by difference ratio
//                                         0        => Either clr_s or clr_d active with the other tied low at input
//                                         1 to 15  => ratio of clk_d to clk_s frequencies plus 1
//
//       reg_in_prog       0 or 1        default: 1
//                                       Register the 'clr_in_prog_s' and 'clr_in_prog_d' Outputs
//                                         0 => unregistered
//                                         1 => registered
//
//       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
//       clr_s           1 bit    Source Domain Internal Logic Clear (reset)
//       send_s          1 bit    Source Domain Active High Send Request
//       data_s          N bits   Source Domain Data
//
//       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
//       clr_d           1 bit    Destination Domain Internal Logic Clear (reset)
//       prefill_d       1 bit    Destination Domain Prefill Control
//
//       test            1 bit    Test input
//
//       Output Ports    Size     Description
//       ============    ====     ===========
//       clr_sync_d      1 bit    Source Domain Clear
//       clr_in_prog_s   1 bit    Source Domain Clear in Progress
//       clr_cmplt_s     1 bit    Soruce Domain Clear Complete (pulse)
//
//       clr_in_prog_d   1 bit    Destination Domain Clear in Progress
//       clr_sync_d      1 bit    Destination Domain Clear (pulse)
//       clr_cmplt_d     1 bit    Destination Domain Clear Complete (pulse)
//       data_avail_d    1 bit    Destination Domain Data Available
//       data_d          N bits   Destination Domain Data
//       prefilling_d    1 bit    Destination Domain Prefillng Status
//
//          Note: (1) The value of N is equal to the 'width' parameter value
//
//
// MODIFIED:
//  05/06/16 RJK  Removed some X propagation coding that interferes with VCS
//                NLP flow and is redundant since VCS added X propagation options
//
//  07/25/11 DLL  Removed or-ing of 'clr_in_prog_d' with 'init_d_n' that
//                wires to DW_sync 'init_d_n' input port.
//                Added checking and comments for tst_mode = 2.
//
//  10/20/06 DLL  Updated with new version of DW_reset_sync
//
//  11/15/06 DLL  Added 4-stage synchronization capability
//
//  7/13/09  DLL  Changed all `define declarations to have the
//                "DW_" prefix and then `undef them at the approprite time.
//
//
//
module DW_stream_sync (
    clk_s,
    rst_s_n,
    init_s_n,
    clr_s,
    send_s,
    data_s,
    clr_sync_s,
    clr_in_prog_s,
    clr_cmplt_s,

    clk_d,
    rst_d_n,
    init_d_n,
    clr_d,
    prefill_d,
    clr_in_prog_d,
    clr_sync_d,
    clr_cmplt_d,
    data_avail_d,
    data_d,
    prefilling_d,

    test
    );

parameter integer width        = 8;  // RANGE 1 to 1024
parameter integer depth        = 4;  // RANGE 2 to 256
parameter integer prefill_lvl  = 0;  // RANGE 0 to 255
parameter integer f_sync_type  = 2;  // RANGE 0 to 4
parameter integer reg_stat     = 1;  // RANGE 0 to 1
parameter integer tst_mode     = 0;  // RANGE 0 to 2
parameter integer verif_en     = 1;  // RANGE 0 to 4
parameter integer r_sync_type  = 2;  // RANGE 0 to 4
parameter integer clk_d_faster = 1;  // RANGE 0 to 15
parameter integer reg_in_prog  = 1;  // RANGE 0 to 1

localparam cnt_depth     = ((depth>16)?((depth>64)?((depth>128)?8:7):((depth>32)?6:5)):((depth>4)?((depth>8)?4:3):((depth>2)?2:1)));
localparam sync_verif_en = (verif_en == 2) ? 4 : (verif_en == 3) ? 1 : verif_en;


input                   clk_s;         // clock input from source domain
input                   rst_s_n;       // active low asynchronous reset from source domain
input                   init_s_n;      // active low synchronous reset from source domain
input                   clr_s;         // active high clear from source domain
input                   send_s;        // active high send request from source domain
input  [width-1:0]      data_s;        // data to be synchronized from source domain
output                  clr_sync_s;    // clear to source domain sequential devices
output                  clr_in_prog_s; // clear in progress status to source domain
output                  clr_cmplt_s;   // clear sequence complete (pulse)

input                   clk_d;         // clock input from destination domain
input                   rst_d_n;       // active low asynchronous reset from destination domain
input                   init_d_n;      // active low synchronous reset from destination domain
input                   clr_d;         // active high clear from destination domain
input                   prefill_d;     // active high prefill control from destination domain
output                  clr_in_prog_d; // clear in progress status to source domain
output                  clr_sync_d;    // clear to destination domain sequential devices (pulse)
output                  clr_cmplt_d;   // clear sequence complete (pulse)
output                  data_avail_d;  // data available to destination domain
output [width-1:0]      data_d;        // data synchronized to destination domain
output                  prefilling_d;  // prefilling status to destination domain

input                   test;          // test input

// synopsys translate_off


  //-------------------------------------------------------------------------
  // Parameter legality check
  //-------------------------------------------------------------------------
  
 
  initial begin : parameter_check
    integer param_err_flg;

    param_err_flg = 0;
    
  
    if ( (depth < 2) || (depth > 256) ) begin
      param_err_flg = 1;
      $display(
	"ERROR: %m :\n  Invalid value (%d) for parameter depth (legal range: 2 to 256)",
	depth );
    end
  
    if ( (prefill_lvl < 0) || (prefill_lvl > depth-1) ) begin
      param_err_flg = 1;
      $display(
	"ERROR: %m :\n  Invalid value (%d) for parameter prefill_lvl (legal range: 0 to depth-1)",
	prefill_lvl );
    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 ( (reg_stat < 0) || (reg_stat > 1) ) begin
      param_err_flg = 1;
      $display(
	"ERROR: %m :\n  Invalid value (%d) for parameter reg_stat (legal range: 0 to 1)",
	reg_stat );
    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 ( ((r_sync_type & 7) < 0) || ((r_sync_type & 7) > 4) ) begin
      param_err_flg = 1;
      $display(
	"ERROR: %m :\n  Invalid value (%d) for parameter (r_sync_type & 7) (legal range: 0 to 4)",
	(r_sync_type & 7) );
    end
  
    if ( (clk_d_faster < 0) || (clk_d_faster > 15) ) begin
      param_err_flg = 1;
      $display(
	"ERROR: %m :\n  Invalid value (%d) for parameter clk_d_faster (legal range: 0 to 15)",
	clk_d_faster );
    end
  
    if ( (reg_in_prog < 0) || (reg_in_prog > 1) ) begin
      param_err_flg = 1;
      $display(
	"ERROR: %m :\n  Invalid value (%d) for parameter reg_in_prog (legal range: 0 to 1)",
	reg_in_prog );
    end
  
    if ( param_err_flg == 1) begin
      $display(
        "%m :\n  Simulation aborted due to invalid parameter value(s)");
      $finish;
    end

  end // parameter_check 


  wire                   next_data_avail_d_int;
  reg                    data_avail_d_int;
  wire  [width-1:0]      next_data_d_int;
  reg   [width-1:0]      data_d_int;
  wire                   next_prefilling_d_int;
  reg                    prefilling_d_int;

  reg   [width-1:0]      data_mem  [0:depth-1];

  wire  [cnt_depth-1:0]  next_wr_ptr_s;
  reg   [cnt_depth-1:0]  wr_ptr_s;
  wire  [cnt_depth-1:0]  next_rd_ptr_d;
  reg   [cnt_depth-1:0]  rd_ptr_d;

  reg   [cnt_depth-1:0] next_valid_cnt; 
  reg   [cnt_depth-1:0] valid_cnt; 

  wire  [depth-1:0]      next_event_vec_s;
  reg   [depth-1:0]      event_vec_s;
  reg   [depth-1:0]      event_vec_l;
  wire  [depth-1:0]      event_vec_selected;
  wire  [depth-1:0]      dw_sync_event_vec;

  wire                   next_detect_lvl;
  reg                    detect_lvl;

  wire [31:0]            one;
  
  integer   i, idx;

  assign one = 1;


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



DW_reset_sync #((f_sync_type + 8), (r_sync_type + 8), clk_d_faster, reg_in_prog, tst_mode, verif_en) U_RST_SYNC (
            .clk_s(clk_s),
            .rst_s_n(rst_s_n),
            .init_s_n(init_s_n),
            .clr_s(clr_s),
            .clk_d(clk_d),
            .rst_d_n(rst_d_n),
            .init_d_n(init_d_n),
            .clr_d(clr_d),
            .test(test),
            .clr_sync_s(clr_sync_s),
            .clr_in_prog_s(clr_in_prog_s),
            .clr_cmplt_s(clr_cmplt_s),
            .clr_in_prog_d(clr_in_prog_d),
            .clr_sync_d(clr_sync_d),
            .clr_cmplt_d(clr_cmplt_d)
            );



always @(posedge clk_s or negedge rst_s_n) begin : a1001_PROC
  if (rst_s_n == 1'b0) begin
    for (idx = 0; idx < depth; idx = idx + 1) begin
      data_mem[idx] <= {width{1'b0}};
    end
  end else begin
    if (!init_s_n || clr_in_prog_s) begin
      for (idx = 0; idx < depth; idx = idx + 1) begin
        data_mem[idx] <= {width{1'b0}};
      end
    end else begin
      if (send_s == 1'b1) begin
        data_mem[wr_ptr_s] <= data_s;
      end
    end
  end

end 

assign next_wr_ptr_s  = (send_s == 1'b1) ? ((wr_ptr_s === depth-1) ? {cnt_depth{1'b0}} :
                           wr_ptr_s + one[cnt_depth-1:0]) : wr_ptr_s;

assign  next_event_vec_s = (send_s == 1'b1) ? {event_vec_s[depth-2:0], ~event_vec_s[depth-1]} : 
			     event_vec_s;


  
generate
  if (((f_sync_type&7)>1)&&(tst_mode==2)) begin : GEN_LATCH_hold_latch_PROC
    reg [depth-1:0] event_vec_l;
    always @ (clk_s or event_vec_s) begin : LATCH_hold_latch_PROC_PROC

      if (clk_s == 1'b0)

	event_vec_l = event_vec_s;


    end // LATCH_hold_latch_PROC_PROC


    assign event_vec_selected = (test==1'b1)? event_vec_l : event_vec_s;

  end else begin : GEN_DIRECT_hold_latch_PROC
    assign event_vec_selected = event_vec_s;
  end
endgenerate

  DW_sync #(depth, f_sync_type+8, tst_mode, sync_verif_en) U_SYNC(
	.clk_d(clk_d),
	.rst_d_n(rst_d_n),
	.init_d_n(init_d_n),
	.data_s(event_vec_selected),
	.test(test),
	.data_d(dw_sync_event_vec) );

always @(dw_sync_event_vec or next_valid_cnt or rd_ptr_d) begin : a1002_PROC
  next_valid_cnt = {cnt_depth{1'b0}};
  for (i = 0; i < depth; i = i + 1) begin
    if (rd_ptr_d > i) begin
      next_valid_cnt = next_valid_cnt + (dw_sync_event_vec[i] === ~detect_lvl);
    end else begin
      next_valid_cnt = next_valid_cnt + (dw_sync_event_vec[i] === detect_lvl);
    end
    if (dw_sync_event_vec[i] === 1'bX)
      next_valid_cnt = {cnt_depth{1'b0}};
  end
end


assign next_rd_ptr_d = next_data_avail_d_int ? ((rd_ptr_d === depth-1) ? {cnt_depth{1'b0}} : (rd_ptr_d + one[cnt_depth-1:0])) :
                          rd_ptr_d;

assign next_detect_lvl = (next_data_avail_d_int && (next_rd_ptr_d === {cnt_depth{1'b0}})) ?
                           ~detect_lvl : detect_lvl;


assign next_prefilling_d_int = ((prefill_d === 1'bX) || (prefilling_d_int === 1'bX)) ? 1'bX : 
			  	 (prefill_lvl == 0) ? 1'b0 :
                                   ((prefill_d === 1'b1) && (prefill_lvl > (reg_stat ? valid_cnt : next_valid_cnt))) ? 1'b1 :
                                     (prefill_lvl <= (reg_stat ? valid_cnt : next_valid_cnt)) ? 1'b0 : prefilling_d_int;

assign next_data_avail_d_int = ((dw_sync_event_vec[rd_ptr_d] === 1'bX) || (next_prefilling_d_int === 1'bX)) ? 1'bX : 
				 (next_prefilling_d_int === 1'b0) && (detect_lvl === dw_sync_event_vec[rd_ptr_d]) ? 1'b1 : 1'b0;

assign next_data_d_int       = (next_data_avail_d_int === 1'bX) ? {width{1'bX}} :
				 (next_data_avail_d_int === 1'b1) ? data_mem[rd_ptr_d] : data_d_int;


  always @(posedge clk_s or negedge rst_s_n) begin : a1003_PROC
    if (rst_s_n == 1'b0) begin
      wr_ptr_s        <= {cnt_depth{1'b0}};
      event_vec_s     <= {depth{1'b0}};
    end else begin
      if ((init_s_n == 1'b0) || (clr_in_prog_s == 1'b1)) begin
        wr_ptr_s        <= {cnt_depth{1'b0}};
        event_vec_s     <= {depth{1'b0}};
      end else begin
        wr_ptr_s        <= next_wr_ptr_s;
        event_vec_s     <= next_event_vec_s;
      end
    end
  end

  always @(posedge clk_d or negedge rst_d_n) begin : a1004_PROC
    if (rst_d_n == 1'b0) begin
      rd_ptr_d           <= {cnt_depth{1'b0}};
      valid_cnt          <= {cnt_depth{1'b0}};
      detect_lvl         <= 1'b1;
      data_avail_d_int   <= 1'b0;
      data_d_int         <= {width{1'b0}};
      prefilling_d_int   <= 1'b0;
    end else begin
      if ((init_d_n == 1'b0) || (clr_in_prog_d == 1'b1)) begin
        rd_ptr_d           <= {cnt_depth{1'b0}};
        valid_cnt          <= {cnt_depth{1'b0}};
        detect_lvl         <= 1'b1;
        data_avail_d_int   <= 1'b0;
        data_d_int         <= {width{1'b0}};
        prefilling_d_int   <= 1'b0;
      end else begin
        rd_ptr_d           <= next_rd_ptr_d;
        valid_cnt          <= next_valid_cnt;
        detect_lvl         <= next_detect_lvl;
        data_avail_d_int   <= next_data_avail_d_int;
        data_d_int         <= next_data_d_int;
        prefilling_d_int   <= next_prefilling_d_int;
      end
    end
  end

  assign data_avail_d    = data_avail_d_int;
  assign data_d          = data_d_int;
  assign prefilling_d    = prefilling_d_int;


  
  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 
  
  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 

// synopsys translate_on
endmodule
/* vcs gen_ip dbg_ip off */
 /* */