summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2016-11-05 15:45:29 (GMT)
committerH. Peter Anvin <hpa@zytor.com>2016-11-05 15:45:29 (GMT)
commitd0f9ec8780bfbb5ae1588e2c1e63bab7e38e8b8b (patch)
treee9cb4cc22dc2d6fe0e6d21da2b0b239957645193
parent2f3ee5665d1dc7190cce4c61fde28e01dc49679b (diff)
downloadabc80-d0f9ec8780bfbb5ae1588e2c1e63bab7e38e8b8b.zip
abc80-d0f9ec8780bfbb5ae1588e2c1e63bab7e38e8b8b.tar.gz
abc80-d0f9ec8780bfbb5ae1588e2c1e63bab7e38e8b8b.tar.bz2
abc80-d0f9ec8780bfbb5ae1588e2c1e63bab7e38e8b8b.tar.xz
sync.v: work around Quartus problem with generate if
Apparently generate if statements with declarations in both branches can make Quartus II think that the register is unused (duplicate?) Thus drop it and (suboptimally) always disable design rule D104. It would still be possible to fix this by duplicating the synchronizer code, but that's for later. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-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