// sync_mebt.v
// 10 MHz divider, synchronizable to external source
// $Id$
// Larry Doolittle, LBNL
// llc-suite Copyright (c) 2004, The Regents of the University of
// California, through Lawrence Berkeley National Laboratory (subject
// to receipt of any required approvals from the U.S. Dept. of Energy).
// All rights reserved.
// Your use of this software is pursuant to a "BSD-style" open
// source license agreement, the text of which is in license.txt
// (md5sum a1e0e81c78f6eba050b0e96996f49fd5) that should accompany
// this file. If the license agreement is not there, or if you
// have questions about the license, please contact Berkeley Lab's
// Technology Transfer Department at TTD@lbl.gov referring to
// "llc-suite (LBNL Ref CR-1988)"
`timescale 1ns / 1ns
module sync_mebt(
input SYNC, // pin 1
input clk40, // interconnect
input phase_sense_adjust, // interconnect
output quad_sync, // interconnect
output sync_error, // interconnect
output sync_missing // interconnect
);
// An incoming 2.5, 5, or 10 MHz signal on SYNC will lock the internal
// phase counter sync_count. If the incoming sync signal is missing,
// the counter will overflow and the sync_missing flag will be set.
// If the incoming sync signal does not stay in phase with clk40/4,
// sync_error will be set. This might also happen if SYNC rises very
// near the rising edge of clk40, causing single cycle jitter in
// SYNC_sync. If that happens, the software has to set phase_sense_adjust,
// which makes this logic listen to a copy of SYNC that is latched on the
// falling edge of clk40.
//
// SYNC is latched on both the rising and falling edge of clk40, and
// it is not possible to put both latches in the Virtex IOB. So timing
// is what it is, fortunately there's almost no logic to get in the way.
// The system just has to route from the IOB, through one level of logic,
// to the two latches with much less than 12 ns skew.
reg [4:0] sync_count;
`ifdef SIMULATE
initial sync_count = 0;
`endif
reg sync_delayed, sync_sync, sync_last;
assign sync_error = sync_sync & ~ sync_last & (sync_count[1:0] != 2'b11);
assign sync_missing = sync_count[4];
assign quad_sync = (sync_count[1:0] == 2'b11);
always @(negedge clk40) sync_delayed <= SYNC;
always @(posedge clk40) begin
// SYNC is asynchronous. It passes through simple asynchonous
// logic, and is sampled here in a single latch (sync_sync).
// If phase_sense_adjust is set, SYNC is ignored here, and the
// falling-edge-sampled version (sync_delayed) is used instead.
sync_sync <= phase_sense_adjust ? sync_delayed : SYNC;
sync_last <= sync_sync;
sync_count <= (sync_sync & ~ sync_last) ? 0 : sync_count + 1'b1;
end
endmodule