diff options
-rw-r--r-- | sync.v | 88 |
1 files changed, 49 insertions, 39 deletions
@@ -16,7 +16,7 @@ // to the synthesizer. Good reason to make this a parameterized module. // -(* altera_attribute = "-name synchronizer_identification forced_if_asynchronous; -name auto_shift_register_recognition off; -name global_signal off" *) +(* altera_attribute = "-name synchronizer_identification FORCED; -name auto_shift_register_recognition OFF; -name global_signal OFF" *) module synchronizer(reset, clk, enable, d, q); parameter width = 1; // Minimum 1 parameter stages = 2; // Minimum 2 @@ -24,7 +24,7 @@ module synchronizer(reset, clk, enable, d, q); input reset; input clk; - input tri1 enable; // If 0, hold the output constant + input enable; // If 0, hold the output constant input [width-1:0] d; output [width-1:0] q; @@ -33,35 +33,42 @@ module synchronizer(reset, clk, enable, d, q); // We define stage[0] separately as d_q to enable separate attributes. // If the stabilizer is enabled, also there is no need to warn about // bus skew (design rule D104). - generate - if (stabilized) - (* altera_attribute = "-name disable_da_rule D104 ; -name cut on -from * ; -name sdc_statement \"set_false_path -to [get_keepers {*|synchronizer:*|d_q[*]}]\"" *) - reg [width-1:0] d_q; - else - (* altera_attribute = "-name cut on -from * ; -name sdc_statement \"set_false_path -to [get_keepers {*|synchronizer:*|d_q[*]}]\"" *) - reg [width-1:0] d_q; - endgenerate + // I used a generate if else statement here, but it seems to have + // led to the completely wrong result... + (* altera_attribute = "-name disable_da_rule \"D104\" ; -name cut on -from * ; -name sdc_statement \"set_false_path -to [get_keepers {*|synchronizer:*|d_q[*]}]\"" *) + reg [width-1:0] d_q = {width{1'b0}}; reg [width-1:0] stage[1:stages-1]; wire [stages-1:0] stage_enable = {enable, {(stages-1){1'b1}}}; assign q = stage[stages-1]; - always @(posedge reset or posedge clk) + integer s; + initial + for (s = 1; s < stages; s = s + 1) + stage[s] = {width{1'b0}}; + + always @(posedge clk) if (reset) d_q <= {width{1'b0}}; - else if (stage_enable[0]) + else // if (stage_enable[0]) d_q <= d; + always @(posedge clk) + if (reset) + stage[1] <= {width{1'b0}}; + else // if (stage_enable[1]) + stage[1] <= d_q; + genvar i; generate - for (i = 1; i < stages; i = i + 1) + for (i = 2; i < stages; i = i + 1) begin: gen_stages - always @(posedge reset or posedge clk) + always @(posedge clk) if (reset) stage[i] <= {width{1'b0}}; - else if (stage_enable[i]) - stage[i] <= (i > 1) ? stage[i-1] : d_q; + else // if (stage_enable[i]) + stage[i] <= stage[i-1]; end endgenerate endmodule @@ -78,35 +85,30 @@ endmodule // always be specified. This is intended to be connected to the output // of a synchronizer, it does not itself include the synchronizer chain. // -// If bypass is true, then the result is available one cycle earlier -// (latency = 1 cycle) at the cost of extra combinatorial logic. -// -module stabilizer(reset, clk, enable, bypass, d, q); +module stabilizer(reset, clk, enable, d, q); parameter width = 1; // Minimum useful = 2 input reset; input clk; input enable; // if 0, hold output value constant - input bypass; // Enable bypass network (probably a constant) input [width-1:0] d; output [width-1:0] q; - reg [width-1:0] d_q; // One cycle delayed input - reg [width-1:0] q_q; // Stored output - - wire d_stable = ~|(d ^ d_q); - wire d_valid = d_stable & enable; - wire d_bypass = d_valid & bypass; - - assign q = d_bypass ? d_q : q_q; + reg [width-1:0] d_q = {width{1'b0}}; // One cycle delayed input + reg [width-1:0] q_q = {width{1'b0}}; // Latched output - always @(posedge reset or posedge clk) + assign q = q_q; + + wire d_stable = ~|(d ^ d_q); + wire d_valid = d_stable & enable; + + always @(posedge clk) if (reset) d_q <= {width{1'b0}}; else d_q <= d; - always @(posedge reset or posedge clk) + always @(posedge clk) if (reset) q_q <= {width{1'b0}}; else @@ -124,8 +126,11 @@ module synchronize(reset, clk, enable, d, q); parameter stages = 2; // Minimum 2 parameter stabilize = 1; // Add stabilizer if necessary parameter bypass = 0; // Add stabilizer bypass - localparam stabilized = stabilize || !(width > 1); - localparam stabilizer = stabilize && (width > 1); + + // "stabilized" indicates if our output is stabilized one way or another. + // "stabilizer" indicates if we need to instantiate a physical stabilizer. + parameter stabilized = stabilize || (width <= 1); + parameter stabilizer = stabilize && (width > 1); input tri0 reset; input clk; @@ -133,18 +138,23 @@ module synchronize(reset, clk, enable, d, q); input [width-1:0] d; output [width-1:0] q; - wire [width-1:0] sync_q; - + wire [width-1:0] sync_q; + wire sync_enable = stabilizer ? 1'b1 : enable; + + reg s_reset = 1'b1; + always @(posedge clk) + s_reset <= reset; + synchronizer #(.width(width), .stages(stages), .stabilized(stabilized)) - synchronizer(.d(d), .q(sync_q), .enable(stabilize || enable), - .reset(reset), .clk(clk)); + synchronizer(.d(d), .q(sync_q), + .enable(sync_enable), + .reset(s_reset), .clk(clk)); generate if (stabilizer) stabilizer #(.width(width)) stabilizer(.d(sync_q), .q(q), .enable(enable), - .bypass(bypass ? 1'b1 : 1'b0), - .reset(reset), .clk(clk)); + .reset(s_reset), .clk(clk)); else assign q = sync_q; endgenerate |