aboutsummaryrefslogtreecommitdiffstats
path: root/sync.v
diff options
context:
space:
mode:
Diffstat (limited to 'sync.v')
-rw-r--r--sync.v88
1 files changed, 49 insertions, 39 deletions
diff --git a/sync.v b/sync.v
index c720b49..83b12f6 100644
--- a/sync.v
+++ b/sync.v
@@ -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