Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong assumption about DFF input #299

Open
gristlyanemone opened this issue Dec 17, 2024 · 1 comment
Open

Wrong assumption about DFF input #299

gristlyanemone opened this issue Dec 17, 2024 · 1 comment

Comments

@gristlyanemone
Copy link

I think project apicula mistakenly assumes that DFF D input always comes from the adjacent LUT in Gowin architectures (https://github.com/YosysHQ/apicula/blob/master/doc/architecture.md). I often see irrelevant LUTs and DFFs packed side by side especially when using GRP_LOC constraint. Here is simple example (can't attach files, so putting the code right here):

  • dff_input.vg

module dff_input(clk_pad, lut1_i_pads, lut2_i_pads, lut1_o_pad, lut2_o_pad, dff_o_pad);
input clk_pad;
input[3:0] lut1_i_pads;
input[3:0] lut2_i_pads;
output lut1_o_pad;
output lut2_o_pad;
output dff_o_pad;
wire clk;
wire[3:0] lut1_i;
wire[3:0] lut2_i;
wire lut1_o;
wire lut2_o;
wire dff_o;
IBUF clk_ibuf(.I(clk_pad), .O(clk));
IBUF lut1_ibuf_0(.I(lut1_i_pads[0]), .O(lut1_i[0]));
IBUF lut1_ibuf_1(.I(lut1_i_pads[1]), .O(lut1_i[1]));
IBUF lut1_ibuf_2(.I(lut1_i_pads[2]), .O(lut1_i[2]));
IBUF lut1_ibuf_3(.I(lut1_i_pads[3]), .O(lut1_i[3]));
IBUF lut2_ibuf_0(.I(lut2_i_pads[0]), .O(lut2_i[0]));
IBUF lut2_ibuf_1(.I(lut2_i_pads[1]), .O(lut2_i[1]));
IBUF lut2_ibuf_2(.I(lut2_i_pads[2]), .O(lut2_i[2]));
IBUF lut2_ibuf_3(.I(lut2_i_pads[3]), .O(lut2_i[3]));
OBUF lut1_obuf(.I(lut1_o), .O(lut1_o_pad));
OBUF lut2_obuf(.I(lut2_o), .O(lut2_o_pad));
OBUF dff_obuf(.I(dff_o), .O(dff_o_pad));
LUT4 lut1(.F(lut1_o), .I0(lut1_i[0]), .I1(lut1_i[1]), .I2(lut1_i[2]), .I3(lut1_i[3]));
defparam lut1.INIT = 16'h0001;
LUT4 lut2(.F(lut2_o), .I0(lut2_i[0]), .I1(lut2_i[1]), .I2(lut2_i[2]), .I3(lut2_i[3]));
defparam lut2.INIT = 16'hFF01;
DFF dff(.D(lut1_o), .Q(dff_o), .CLK(clk));
endmodule

  • dff_input.cst

IO_LOC "clk_ibuf" IOT2A;
IO_LOC "lut1_ibuf_0" IOT4A;
IO_LOC "lut1_ibuf_1" IOT4B;
IO_LOC "lut1_ibuf_2" IOT5A;
IO_LOC "lut1_ibuf_3" IOT5B;
IO_LOC "lut2_ibuf_0" IOT6A;
IO_LOC "lut2_ibuf_1" IOT6B;
IO_LOC "lut2_ibuf_2" IOT7A;
IO_LOC "lut2_ibuf_3" IOT7B;
IO_LOC "lut1_obuf" IOB2A;
IO_LOC "lut2_obuf" IOB3A;
IO_LOC "dff_obuf" IOB4A;
INS_LOC "lut1" R5C4[3][B];
INS_LOC "lut2" R5C4[0][A];
INS_LOC "dff" R5C4[0][A];

  • pnr.tcl

add_file "dff_input.vg"
add_file "dff_input.cst"
set_device -name GW1N-1 GW1N-LV1LQ144C6/I5
set_option -output_base_name dff_input
set_option -top_module dff_input
run pnr

Here dff's input is connected to output of lut1, but the dff is placed together with lut2. The design is placed and routed successfully (tried with Gowin_V1.9.8.09_Education), but when unpacked by gowin_unpack, dff becomes connected to lut2 instead of lut1.

@yrabbit
Copy link
Collaborator

yrabbit commented Dec 17, 2024

Thanks.

The fixes in the documentation (as well as unpacking) were planned together with the resolution of the mechanism of putting unrelated LUTs and DFFs into a single slice.

All the fuses and mechanisms have been identified and the prerequisites for such placement are gradually being implemented in nextpnr.

At the moment this task is in the background - it is necessary to teach nextpnr not to use these things left and right, because the delays are no longer the same as in direct connection.

Anyway next year we will get something.:)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants