302 lines
12 KiB
Coq
302 lines
12 KiB
Coq
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
//
|
||
|
|
// 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
|