// // synchro.v // // Asynchronous input synchronizer // // // These attributes tell the compiler and fitter respectively // to treat these registers as low-level constructs and turn // them into a synchronizer chain. No inferring RAMs or anything like that, // and pack them close together. // module synchronizer #(parameter width = 1, parameter stages = 2, parameter noioregs = 0) ( input rst_n, input clk, input [width-1:0] d, output [width-1:0] q ); // SYNCHRONIZER_IDENTIFICATION FORCED identifies the *beginning* of // the synchro; it needs to be used with AUTO for the other stages or // the chains will be broken up for each stage. // // Because of different attributes, this is not simply qreg[0]. `ifdef ALTERA_RESERVED_QIS (* syn_preserve = 1, dont_replicate = 1, useioff = noioregs, altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED ; ", "-name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH ", tostr(stages-1)} *) `endif reg [width-1:0] qreg0; `ifdef ALTERA_RESERVED_QIS (* syn_preserve = 1, dont_replicate = 1, useioff = 1, altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION AUTO ; ", "-name SYNCHRONIZATION_REGISTER_CHAIN_LENGTH ", tostr(stages-1)} *) `endif reg [width-1:0] qreg[stages-1:1]; always @(posedge clk or negedge rst_n) if (~rst_n) qreg0 <= {width{1'b0}}; else qreg0 <= d; always @(posedge clk or negedge rst_n) if (~rst_n) qreg[1] <= {width{1'b0}}; else qreg[1] <= qreg0; generate genvar i; for (i = 2; i < stages; i = i + 1) begin : stage always @(posedge clk or negedge rst_n) if (~rst_n) qreg[i] <= {width{1'b0}}; else qreg[i] <= qreg[i-1]; end endgenerate assign q = qreg[stages-1]; endmodule // synchronizer