mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-14 06:42:54 +08:00
Added synchronizer modules
This commit is contained in:
parent
d8beb37f01
commit
cb224284b1
58
cdc_data.sv
Normal file
58
cdc_data.sv
Normal file
@ -0,0 +1,58 @@
|
||||
//--------------------------------------------------------------------------------
|
||||
// cdc_data.sv
|
||||
// Konstantin Pavlov, pavlovconst@gmail.com
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
// INFO --------------------------------------------------------------------------------
|
||||
// Standard two-stage synchronizer
|
||||
// CDC stands for "clock data crossing"
|
||||
//
|
||||
// In fact, this madule is just a wrapper for dalay.sv
|
||||
//
|
||||
// Don`t forget to write false_path constraints for all your synchronizers
|
||||
// The best way to do it - is to mark all synchonizer delay.sv instances
|
||||
// with "_SYNC_ATTR" suffix. After that, just one constraint is required:
|
||||
//
|
||||
// For Quartus:
|
||||
// set_false_path -to [get_registers {*delay:*_SYNC_ATTR*|data[1]*}]
|
||||
//
|
||||
// For Vivado:
|
||||
// set_false_path -to [get_cells -hier -filter {NAME =~ *_SYNC_ATTR/data_reg[1]*}]
|
||||
//
|
||||
|
||||
|
||||
/* --- INSTANTIATION TEMPLATE BEGIN ---
|
||||
|
||||
cdc_data CD [31:0] (
|
||||
.clk( {32{clk}} ),
|
||||
.nrst( {32{1'b1}} ),
|
||||
.d( ext_data[31:0] ),
|
||||
.q( synchronized_data[31:0] )
|
||||
);
|
||||
|
||||
--- INSTANTIATION TEMPLATE END ---*/
|
||||
|
||||
|
||||
module cdc_data(
|
||||
input clk,
|
||||
input nrst,
|
||||
input d,
|
||||
output q
|
||||
);
|
||||
|
||||
delay #(
|
||||
.LENGTH( 2 ),
|
||||
.WIDTH( 1 ),
|
||||
.TYPE( "CELLS" ),
|
||||
.REGISTER_OUTPUTS( "FALSE" )
|
||||
) data_SYNC_ATTR (
|
||||
.clk( clk ),
|
||||
.nrst( nrst ),
|
||||
.ena( 1'b1 ),
|
||||
|
||||
.in( d ),
|
||||
.out( q )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
94
cdc_strobe.sv
Normal file
94
cdc_strobe.sv
Normal file
@ -0,0 +1,94 @@
|
||||
//--------------------------------------------------------------------------------
|
||||
// cdc_strobe.sv
|
||||
// Konstantin Pavlov, pavlovconst@gmail.com
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
// INFO --------------------------------------------------------------------------------
|
||||
// Clock crossing setup for single-pulse strobes
|
||||
// CDC stands for "clock data crossing"
|
||||
//
|
||||
// This is a simplest form of strobe CDC circuit. Good enough for rare single
|
||||
// strobe events. This module does NOT support close-standing strobes,
|
||||
// placed in adjacent lock cycles
|
||||
//
|
||||
// Don`t forget to write false_path constraints for all your synchronizers
|
||||
// The best way to do it - is to mark all synchonizer delay.sv instances
|
||||
// with "_SYNC_ATTR" suffix. After that, just one constraint is required:
|
||||
//
|
||||
// For Quartus:
|
||||
// set_false_path -to [get_registers {*delay:*_SYNC_ATTR*|data[1]*}]
|
||||
//
|
||||
// For Vivado:
|
||||
// set_false_path -to [get_cells -hier -filter {NAME =~ *_SYNC_ATTR/data_reg[1]*}]
|
||||
//
|
||||
|
||||
|
||||
/* --- INSTANTIATION TEMPLATE BEGIN ---
|
||||
|
||||
cdc_strobe CS [7:0] (
|
||||
.clk1_i( {8{clk1}} ),
|
||||
.nrst1_i( {8{1'b1}} ),
|
||||
.strb1_i( input_strobes[7:0] ),
|
||||
|
||||
.clk2_i( {8{clk2}} ),
|
||||
.strb2_o( output_strobes[7:0] )
|
||||
);
|
||||
|
||||
--- INSTANTIATION TEMPLATE END ---*/
|
||||
|
||||
|
||||
module cdc_strobe #( parameter
|
||||
PRE_STRETCH( 2 ) // number of cycles to stretch input strobe
|
||||
)(
|
||||
input clk1_i, // clock domain 1 clock
|
||||
input nrst1_i, // clock domain 1 reset (inversed)
|
||||
input strb1_i, // clock domain 1 strobe
|
||||
|
||||
input clk2_i, // clock domain 2 clock
|
||||
output strb2_o // clock domain 2 strobe
|
||||
);
|
||||
|
||||
// This signal should be at_least(!!!) one clk2_i period long
|
||||
// Preliminary stretching is usually nessesary, unless you are crossing
|
||||
// to essentialy high-frequency clock clk2_i, that is > 2*clk1_i
|
||||
logic strb1_stretched;
|
||||
|
||||
pulse_stretch #(
|
||||
.WIDTH( PRE_STRETCH ),
|
||||
.USE_CNTR( 0 )
|
||||
) stretch_strb1 (
|
||||
.clk( clk1_i ),
|
||||
.nrst( nrst1_i ),
|
||||
.in( strb1_i ),
|
||||
.out( strb1_stretched )
|
||||
);
|
||||
|
||||
// This is a synchronized signal in clk2_i clock domain,
|
||||
// but no guarantee, that it is one-cycle-high
|
||||
logic strb2_stretched;
|
||||
|
||||
delay #(
|
||||
.LENGTH( 2 ),
|
||||
.WIDTH( 1 ),
|
||||
.TYPE( "CELLS" ),
|
||||
.REGISTER_OUTPUTS( "FALSE" )
|
||||
) delay_strb1_SYNC_ATTR (
|
||||
.clk( clk2_i ),
|
||||
.nrst( 1'b1 ),
|
||||
.ena( 1'b1 ),
|
||||
|
||||
.in( strb1_stretched ),
|
||||
.out( strb2_stretched )
|
||||
);
|
||||
|
||||
edge_detect ed_strb2 (
|
||||
.clk( clk2_i ),
|
||||
.nrst( 1'b1 ),
|
||||
.in( strb2_stretched ),
|
||||
.rising( strb2_o ), // and now the signal is definitely one-cycle-high
|
||||
.falling( ),
|
||||
.both( )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
Loading…
x
Reference in New Issue
Block a user