lin-win-share/DA4008_V1.2/model/DW_pulse_sync.v

302 lines
12 KiB
Verilog

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