问题
I'm trying to generate an array of latches that are placed adjacent to each other using a Generate statement. I've been trying to use the Xilinx constraint "RLOC" to do this, but I haven't been successful.
The code below won't successfully implement, but should illustrate what I'm trying to obtain. The issue with the code below is that "i" in the constraint call isn't being converted into a string, which is what the call is looking for. Does anyone have experience doing this?
I'm using a Virtex4 with Xilinx ISE 10.1.03 for synthesis and implementation. I'm not entirely sure what version of Verilog I'm using, but I think it's Verilog 2001. I'd be grateful if someone could also tell me how to check what version of Verilog I'm using.
genvar i;
generate
for (i = 0; i < DATA_WIDTH; i = i + 1)
begin : LATCH
(* RLOC = {"X0Y", i} *)
latch inst_latch (
.d (data_in[i]),
.gate (gate),
.reset (reset),
.q (data_out[i])
);
end
endgenerate
回答1:
I'm guessing that Xilinx is treating {"X0Y", i}
as a literal and not evaluating it. You can use a script to handle the generation for you. You can have the code generated by your preferred programming then use an `include statement in your verilog file. Or you can go with an embedded route:
- Perl had EP3 : http://metacpan.org/pod/Text::EP3::Verilog
- Ruby has eRuby : http://www.tutorialspoint.com/ruby/eruby.htm
- Python has prepro : http://corner-case.com/indproj/prepro.html
- I'm sure something like it exists for other languages to. Such as Tcl, JavaScript, C, etc.
Concept is the same, just a difference in embedded language and tool used for conversion.
A down side is the scripts will not treat DATA_WIDTH
as a variable/parameter. You'll have to pass the script a numerical constant or find some fancy way to transfer the values.
回答2:
I ended up using parameterized macros to replace the generate variable with a string when passed to RLOC. It's quite a workaround, and I most likely would have used Greg's solution had I seen it earlier.
Anyway, in case people are actually interested, the macros :
parameter DIGITS = "9876543210";
`define THOUSANDS(x) (x / 1000)
`define HUNDREDS(x) ((x - (`THOUSANDS(x) * 1000)) / 100)
`define TENS(x) ((x - (`THOUSANDS(x) * 1000) - (`HUNDREDS(x) * 100)) / 10)
`define ONES(x) (x - (`THOUSANDS(x) * 1000) - (`HUNDREDS(x) * 100) - (`TENS(x) * 10))
`define TO_STRING(x) (DIGITS[((8 * (x + 1)) - 1) : (8 * x)])
`define VAR_TO_STRING(x) ({`TO_STRING(`THOUSANDS(x)), `TO_STRING(`HUNDREDS(x)), `TO_STRING(`TENS(x)), `TO_STRING(`ONES(x))})
The macros THOUSANDS(), HUNDREDS(), TENS(), and ONES() return the number of thousands, hundreds, tens, and ones found in x. These macros should always return 1 digit values.
TO_STRING() takes some 1 digit value and "converts" it to a string by returning a portion of parameter DIGITS.
VAR_TO_STRING() uses all of the above macros in conjunction to convert any 4 digit integer into its string equivalent. The code in the question would then be replaced by :
genvar i;
generate
for (i = 0; i < DATA_WIDTH; i = i + 1)
begin : LATCH
(* RLOC = {"X0Y", `VAR_TO_STRING(i)} *)
latch inst_latch (
.d (data_in[i]),
.gate (gate),
.reset (reset),
.q (data_out[i])
);
end
endgenerate
来源:https://stackoverflow.com/questions/20481745/verilog-placement-constraints-with-generate-statements