URL
https://opencores.org/ocsvn/adv_debug_sys/adv_debug_sys/trunk
Subversion Repositories adv_debug_sys
[/] [adv_debug_sys/] [trunk/] [Hardware/] [adv_dbg_if/] [rtl/] [verilog/] [syncreg.v] - Rev 42
Compare with Previous | Blame | View Log
////////////////////////////////////////////////////////////////////// //// //// //// syncreg.v //// //// //// //// //// //// Synchronizes a register 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. Domain A // is considered the 'source' domain (produces the data), and Domain B // is considered the 'destination' domain (consumes the data). It is assumed // that clock A is faster than clock B, but this element will work // regardless. The idea here is NOT to insure that domain B sees every // change to the value generated by domain A. Rather, this device // attempts to keep the value seen by domain B as current as possible, // always updating to the latest value of the input in domain A. // Thus, there may be dozens or hundreds of changes to register A // which are not seen by domain B. There is no external acknowledge // of receipt from domain B. Domain B simply wants the most current // value of register A possible at any given time. // Note the reset is asynchronous; this is necessary to coordinate between // two clock domains which may have separate reset signals. I could find // no other way to insure correct initialization with two separate // reset signals. // // Ports: // CLKA: Clock for the source domain // CLKB: Clock for the destination domain // RST: Asynchronously resets all sync elements, prepares // unit for operation. // DATA_IN: Data input from clock domain A // DATA_OUT: Data output to clock domain B // // Top module module syncreg ( CLKA, CLKB, RST, DATA_IN, DATA_OUT ); input CLKA; input CLKB; input RST; input [3:0] DATA_IN; output [3:0] DATA_OUT; reg [3:0] regA; reg [3:0] regB; reg strobe_toggle; reg ack_toggle; wire A_not_equal; wire A_enable; wire strobe_sff_out; wire ack_sff_out; wire [3:0] DATA_OUT; // Combinatorial assignments assign A_enable = A_not_equal & ack_sff_out; assign A_not_equal = !(DATA_IN == regA); assign DATA_OUT = regB; // register A (latches input any time it changes) always @ (posedge CLKA or posedge RST) begin if(RST) regA <= 4'b0; else if(A_enable) regA <= DATA_IN; end // register B (latches data from regA when enabled by the strobe SFF) always @ (posedge CLKB or posedge RST) begin if(RST) regB <= 4'b0; else if(strobe_sff_out) regB <= regA; end // 'strobe' toggle FF always @ (posedge CLKA or posedge RST) begin if(RST) strobe_toggle <= 1'b0; else if(A_enable) strobe_toggle <= ~strobe_toggle; end // 'ack' toggle FF // This is set to '1' at reset, to initialize the unit. always @ (posedge CLKB or posedge RST) begin if(RST) ack_toggle <= 1'b1; else if (strobe_sff_out) ack_toggle <= ~ack_toggle; end // 'strobe' sync element syncflop strobe_sff ( .DEST_CLK (CLKB), .D_SET (1'b0), .D_RST (strobe_sff_out), .RESET (RST), .TOGGLE_IN (strobe_toggle), .D_OUT (strobe_sff_out) ); // 'ack' sync element syncflop ack_sff ( .DEST_CLK (CLKA), .D_SET (1'b0), .D_RST (A_enable), .RESET (RST), .TOGGLE_IN (ack_toggle), .D_OUT (ack_sff_out) ); endmodule