blob: e6a8d56cee34423d2a9e456a7e5d66ea650d31fa [file] [log] [blame]
//////////////////////////////////////////////////////////////////////
//// ////
//// syncflop.v ////
//// ////
//// ////
//// A generic synchronization device between two clock domains ////
//// ////
//// Author(s): ////
//// Nathan Yawn (nathan.yawn@opencores.org) ////
//// ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2010 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// This is a synchronization element between two clock domains. It
// uses toggle signaling - that is, clock domain 1 changes the state
// of TOGGLE_IN to indicate a change, rather than setting the level
// high. When TOGGLE_IN changes state, the output on D_OUT will be
// set to level '1', and will hold that value until D_RST is held
// high during a rising edge of DEST_CLK. D_OUT will be updated
// on the second rising edge of DEST_CLK after the state of
// TOGGLE_IN has changed.
// RESET is asynchronous. This is necessary to coordinate the reset
// between different clock domains with potentially different reset
// signals.
//
// Ports:
// DEST_CLK: Clock for the target clock domain
// D_SET: Synchronously set the output to '1'
// D_CLR: Synchronously reset the output to '0'
// RESET: Set all FF's to '0' (asynchronous)
// TOGGLE_IN: Toggle data signal from source clock domain
// D_OUT: Output to clock domain 2
// Top module
module syncflop(
DEST_CLK,
D_SET,
D_RST,
RESETN,
TOGGLE_IN,
D_OUT
);
input DEST_CLK;
input D_SET;
input D_RST;
input RESETN;
input TOGGLE_IN;
output D_OUT;
reg sync1;
reg sync2;
reg syncprev;
reg srflop;
wire syncxor;
wire srinput;
wire D_OUT;
// Combinatorial assignments
assign syncxor = sync2 ^ syncprev;
assign srinput = syncxor | D_SET;
assign D_OUT = srflop | syncxor;
// First DFF (always enabled)
always @ (posedge DEST_CLK or negedge RESETN)
begin
if(~RESETN) sync1 <= 1'b0;
else sync1 <= TOGGLE_IN;
end
// Second DFF (always enabled)
always @ (posedge DEST_CLK or negedge RESETN)
begin
if(~RESETN) sync2 <= 1'b0;
else sync2 <= sync1;
end
// Third DFF (always enabled, used to detect toggles)
always @ (posedge DEST_CLK or negedge RESETN)
begin
if(~RESETN) syncprev <= 1'b0;
else syncprev <= sync2;
end
// Set/Reset FF (holds detected toggles)
always @ (posedge DEST_CLK or negedge RESETN)
begin
if(~RESETN) srflop <= 1'b0;
else if(D_RST) srflop <= 1'b0;
else if (srinput) srflop <= 1'b1;
end
endmodule