`ifdef BSV_ASSIGNMENT_DELAY `else `define BSV_ASSIGNMENT_DELAY `endif `ifdef BSV_POSITIVE_RESET `define BSV_RESET_VALUE 1'b1 `define BSV_RESET_EDGE posedge `else `define BSV_RESET_VALUE 1'b0 `define BSV_RESET_EDGE negedge `endif // A version of SyncFIFO1 for zero-width data // // A clock synchronization FIFO where the enqueue and dequeue sides are in // different clock domains. // The depth of the FIFO is strictly 1 element. Implementation uses only // 1 register to minimize hardware // There are no restrictions w.r.t. clock frequencies // FULL and EMPTY signal are pessimistic, that is, they are asserted // immediately when the FIFO becomes FULL or EMPTY, but their deassertion // is delayed due to synchronization latency. module SyncFIFO10( sCLK, sRST, dCLK, sENQ, sFULL_N, dDEQ, dEMPTY_N ) ; // input clock domain ports input sCLK ; input sRST ; input sENQ ; output sFULL_N ; // destination clock domain ports input dCLK ; input dDEQ ; output dEMPTY_N ; // Reset generation wire dRST = sRST; // sCLK registers reg sEnqToggle, sDeqToggle, sSyncReg1; // dCLK registers reg dEnqToggle, dDeqToggle, dSyncReg1; // output assignment assign dEMPTY_N = dEnqToggle != dDeqToggle; assign sFULL_N = sEnqToggle == sDeqToggle; always @(posedge sCLK or `BSV_RESET_EDGE sRST) begin if (sRST == `BSV_RESET_VALUE) begin sEnqToggle <= `BSV_ASSIGNMENT_DELAY 1'b0; sSyncReg1 <= `BSV_ASSIGNMENT_DELAY 1'b0; sDeqToggle <= `BSV_ASSIGNMENT_DELAY 1'b1; // FIFO marked as full during reset end else begin if (sENQ && (sEnqToggle == sDeqToggle)) begin sEnqToggle <= `BSV_ASSIGNMENT_DELAY ! sEnqToggle; end sSyncReg1 <= `BSV_ASSIGNMENT_DELAY dDeqToggle; // clock domain crossing sDeqToggle <= `BSV_ASSIGNMENT_DELAY sSyncReg1; end end always @(posedge dCLK or `BSV_RESET_EDGE dRST) begin if (dRST == `BSV_RESET_VALUE) begin dEnqToggle <= `BSV_ASSIGNMENT_DELAY 1'b0; dSyncReg1 <= `BSV_ASSIGNMENT_DELAY 1'b0; dDeqToggle <= `BSV_ASSIGNMENT_DELAY 1'b0; end else begin if (dDEQ && (dEnqToggle != dDeqToggle)) begin dDeqToggle <= `BSV_ASSIGNMENT_DELAY ! dDeqToggle; end dSyncReg1 <= `BSV_ASSIGNMENT_DELAY sEnqToggle; // clock domain crossing dEnqToggle <= `BSV_ASSIGNMENT_DELAY dSyncReg1; end end `ifdef BSV_NO_INITIAL_BLOCKS `else // not BSV_NO_INITIAL_BLOCKS // synopsys translate_off initial begin : initBlock sEnqToggle = 1'b0; sDeqToggle = 1'b0; sSyncReg1 = 1'b0; dEnqToggle = 1'b0; dDeqToggle = 1'b0; dSyncReg1 = 1'b0; end // synopsys translate_on `endif // !`ifdef BSV_NO_INITIAL_BLOCKS // synopsys translate_off always@(posedge sCLK) begin: error_checks1 reg enqerror ; enqerror = 0; if (sRST == ! `BSV_RESET_VALUE) begin if ( sENQ && (sEnqToggle != sDeqToggle)) begin enqerror = 1; $display( "Warning: SyncFIFO1: %m -- Enqueuing to a full fifo" ) ; end end end always@(posedge dCLK) begin: error_checks2 reg deqerror ; deqerror = 0; if (dRST == ! `BSV_RESET_VALUE) begin if ( dDEQ && (dEnqToggle == dDeqToggle)) begin deqerror = 1; $display( "Warning: SyncFIFO1: %m -- Dequeuing from an empty full fifo" ) ; end end end // block: error_checks // synopsys translate_on endmodule