1
0
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:
Konstantin Pavlov 2021-06-11 17:39:06 +03:00
parent d8beb37f01
commit cb224284b1
2 changed files with 152 additions and 0 deletions

58
cdc_data.sv Normal file
View 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
View 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