//////////////////////////////////////////////////////////////////////////////// // // 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 3/3/05 // // VERSION: Simulation Architecture // // DesignWare_version: c5e9837c // DesignWare_release: O-2018.06-DWBB_201806.1 // //////////////////////////////////////////////////////////////////////////////// // // ABSTRACT: Fundamental Synchronizer Simulation Model // // This synchronizes incoming data into the destination domain // with a configurable number of sampling stages. // // Parameters: Valid Values // ========== ============ // width [ 1 to 1024 ] // 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 = reserved (functions same as tst_mode=0 ] // verif_en [ 0 = no sampling errors inserted, // 1 = sampling errors are randomly inserted with 0 or 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 ] // // Input Ports: Size Description // =========== ==== =========== // 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 // data_s N bits Source Domain Data Input // test 1 bit Test input // // Output Ports Size Description // ============ ==== =========== // data_d N bits Destination Domain Data Output // // Note: the value of N is equal to the 'width' parameter value // // // MODIFIED: // RJK 09-17-13 updated to eliminate race (STAR 9000661688) // RJK 01-15-13 updated to eliminate `define // RJK 10-11-12 corrected test mode behavior when tst_mode=2 // DLL 8-8-11 Added tst_mode=2 (not a functional change) // DLL 6-12-06 Removed unnecessary To_X01 processing of 'data_s_int' // // DLL 11-7-06 Modified functionality to support f_sync_type = 4 // // DLL 11-14-06 Revised approach to routing missampling of data_s // // // DLL 8-18-10 Fixed typo that results in correct resolution of 'data_s_delta_t' // in the missampling code. Addresses STAR#9000412693. module DW_sync ( clk_d, rst_d_n, init_d_n, data_s, test, data_d ); parameter integer width = 8; parameter integer f_sync_type = 2; parameter integer tst_mode = 0; parameter integer verif_en = 1; input clk_d; input rst_d_n; input init_d_n; input [width-1:0] data_s; input test; output [width-1:0] data_d; // synopsys translate_off localparam F_SYNC_TYPE_INT = f_sync_type % 8; //------------------------------------------------------------------------- // Parameter legality check //------------------------------------------------------------------------- initial begin : parameter_check integer param_err_flg; param_err_flg = 0; if (width < 1 ) begin param_err_flg = 1; $display( "ERROR: %m :\n Invalid value (%d) for parameter width (lower bound: 1 )", width ); end if ( (F_SYNC_TYPE_INT < 0) || (F_SYNC_TYPE_INT > 4) ) begin param_err_flg = 1; $display( "ERROR: %m :\n Invalid value (%d) for parameter F_SYNC_TYPE_INT (legal range: 0 to 4)", F_SYNC_TYPE_INT ); 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 ( param_err_flg == 1) begin $display( "%m :\n Simulation aborted due to invalid parameter value(s)"); $finish; end end // parameter_check wire [width-1:0] data_s_int; reg [width-1:0] ndata1_int; reg [width-1:0] data1_int; reg [width-1:0] data_d2_int; reg [width-1:0] data_d3_int; reg [width-1:0] data_d4_int; reg [width-1:0] test_nout1_int; wire [width-1:0] next_data1_int; wire [width-1:0] next_data_d2_int; wire [width-1:0] next_data_d3_int; wire [width-1:0] tst_mode_sel_data; wire [width-1:0] f_sync_type0_data; `ifdef DW_MODEL_MISSAMPLES initial begin $display("Information: %m: *** Running with DW_MODEL_MISSAMPLES defined, verif_en is: %0d ***", verif_en); end reg [width-1:0] test_hold_ms; wire hclk_odd; reg [width-1:0] last_data_dyn, data_s_delta_t; reg [width-1:0] last_data_s, last_data_s_q, last_data_s_qq; wire [width-1:0] data_s_sel_0, data_s_sel_1; reg [width-1:0] data_select; initial data_select = 0; reg [width-1:0] data_select_2; initial data_select_2 = 0; always @ (negedge clk_d or negedge rst_d_n) begin : PROC_test_hold_ms_registers if (rst_d_n == 1'b0) begin test_hold_ms <= {width{1'b0}}; end else if (init_d_n == 1'b0) begin test_hold_ms <= {width{1'b0}}; end else begin test_hold_ms <= data_s; end end reg init_dly_n; always @ (posedge hclk_odd or data_s or rst_d_n) begin : PROC_catch_last_data data_s_delta_t <= (data_s | (data_s ^ data_s)) & {width{rst_d_n}} & {width{init_dly_n}}; last_data_dyn <= data_s_delta_t & {width{rst_d_n}} & {width{init_dly_n}}; end // PROC_catch_last_data generate if ((verif_en % 2) == 1) begin : GEN_HO_VE_EVEN assign hclk_odd = clk_d; end else begin : GEN_HO_VE_ODD assign hclk_odd = ~clk_d; end endgenerate always @ (posedge clk_d or negedge rst_d_n) begin : PROC_missample_hist_even if (rst_d_n == 1'b0) begin last_data_s_q <= {width{1'b0}}; init_dly_n <= 1'b1; end else if (init_d_n == 1'b0) begin last_data_s_q <= {width{1'b0}}; init_dly_n <= 1'b0; end else begin last_data_s_q <= last_data_s; init_dly_n <= 1'b1; end end // PROC_missample_hist_even always @ (posedge hclk_odd or negedge rst_d_n) begin : PROC_missample_hist_odd if (rst_d_n == 1'b0) begin last_data_s <= {width{1'b0}}; last_data_s_qq <= {width{1'b0}}; end else if (init_d_n == 1'b0) begin last_data_s <= {width{1'b0}}; last_data_s_qq <= {width{1'b0}}; end else begin last_data_s <= (data_s | (data_s ^ data_s)); last_data_s_qq <= last_data_s_q; end end // PROC_missample_hist_odd always @ (data_s or last_data_s) begin : PROC_mk_next_data_select if (data_s != last_data_s) begin data_select = wide_random(width); if ((verif_en == 2) || (verif_en == 3)) data_select_2 = wide_random(width); else data_select_2 = {width{1'b0}}; end end // PROC_mk_next_data_select assign data_s_sel_0 = (verif_en < 1)? data_s : ((data_s & ~data_select) | (last_data_dyn & data_select)); assign data_s_sel_1 = (verif_en < 2)? {width{1'b0}} : ((last_data_s_q & ~data_select) | (last_data_s_qq & data_select)); assign data_s_int = ((data_s_sel_0 & ~data_select_2) | (data_s_sel_1 & data_select_2)); function [width-1:0] wide_random; input [31:0] in_width; // should match "width" parameter -- need one input to satisfy Verilog function requirement reg [width-1:0] temp_result; reg [31:0] rand_slice; integer i, j, base; begin temp_result = $random; if (((width / 32) + 1) > 1) begin for (i=1 ; i < ((width / 32) + 1) ; i=i+1) begin base = i << 5; rand_slice = $random; for (j=0 ; ((j < 32) && (base+j < in_width)) ; j=j+1) begin temp_result[base+j] = rand_slice[j]; end end end wide_random = temp_result; end endfunction // wide_random initial begin : seed_random_PROC integer seed, init_rand; `ifdef DW_MISSAMPLE_SEED seed = `DW_MISSAMPLE_SEED; `else seed = 32'h0badbeef; `endif init_rand = $random(seed); end // seed_random_PROC `else assign data_s_int = (data_s | (data_s ^ data_s)); `endif initial begin if ((f_sync_type > 0)&&(f_sync_type < 8)) $display("Information: *** Instance %m is the DW_sync Clock Domain Crossing Module ***"); end `ifdef DW_REPORT_SYNC_PARAMS initial begin if (F_SYNC_TYPE_INT > 0) $display("Information: *** Instance %m is configured as follows: width is: %0d, f_sync_type is: %0d, tst_mode is: %0d ***", width, F_SYNC_TYPE_INT, tst_mode); end `endif assign tst_mode_sel_data = (tst_mode == 1) ? test_nout1_int : data_s; assign f_sync_type0_data = (test == 1'b1) ? tst_mode_sel_data : data_s; assign next_data1_int = (test == 1'b0) ? data_s_int : tst_mode_sel_data; generate if ((f_sync_type & 7) == 1) begin : GEN_NXT_SMPL_SM1_FST_EQUAL1 assign next_data_d2_int = ndata1_int; end if ((f_sync_type & 7) > 1) begin : GEN_NXT_SMPL_SM1_FST_GRTH1 assign next_data_d2_int = data1_int; end endgenerate always @(negedge clk_d or negedge rst_d_n) begin : a1000_PROC if (rst_d_n === 1'b0) begin ndata1_int <= {width{1'b0}}; test_nout1_int <= {width{1'b0}}; end else if (rst_d_n === 1'b1) begin if (init_d_n === 1'b0) begin ndata1_int <= {width{1'b0}}; test_nout1_int <= {width{1'b0}}; end else if (init_d_n === 1'b1) begin ndata1_int <= data_s_int; test_nout1_int <= data_s; end else begin ndata1_int <= {width{1'bX}}; test_nout1_int <= {width{1'bX}}; end end else begin ndata1_int <= {width{1'bX}}; test_nout1_int <= {width{1'bX}}; end end always @(posedge clk_d or negedge rst_d_n) begin : a1001_PROC if (rst_d_n === 1'b0) begin data1_int <= {width{1'b0}}; data_d2_int <= {width{1'b0}}; data_d3_int <= {width{1'b0}}; data_d4_int <= {width{1'b0}}; end else if (rst_d_n === 1'b1) begin if (init_d_n === 1'b0) begin data1_int <= {width{1'b0}}; data_d2_int <= {width{1'b0}}; data_d3_int <= {width{1'b0}}; data_d4_int <= {width{1'b0}}; end else if (init_d_n === 1'b1) begin data1_int <= next_data1_int; data_d2_int <= next_data_d2_int; data_d3_int <= data_d2_int; data_d4_int <= data_d3_int; end else begin data1_int <= {width{1'bX}}; data_d2_int <= {width{1'bX}}; data_d3_int <= {width{1'bX}}; data_d4_int <= {width{1'bX}}; end end else begin data1_int <= {width{1'bX}}; data_d2_int <= {width{1'bX}}; data_d3_int <= {width{1'bX}}; data_d4_int <= {width{1'bX}}; end end assign data_d = (F_SYNC_TYPE_INT == 0) ? f_sync_type0_data : (F_SYNC_TYPE_INT == 3) ? data_d3_int : (F_SYNC_TYPE_INT == 4) ? data_d4_int : data_d2_int; 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 */ /* */