gowin: Add PLL support for the GW1NR-9 chip
And also unified the fixing of PLL to bels: the point is that PLL being at a certain location has the possibility to use a direct implicit wire to the clock source, but once we decide to use this direct wire, the PLL can no longer be moved. Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
parent
f80b871dd5
commit
6a1212a1e1
@ -2108,6 +2108,47 @@ bool Arch::is_GCLKT_iob(const CellInfo *cell)
|
||||
return false;
|
||||
}
|
||||
|
||||
void Arch::bind_pll_to_bel(CellInfo *ci, int loc)
|
||||
{
|
||||
BelId bel;
|
||||
switch (ci->type.hash()) {
|
||||
case ID_PLLVR:
|
||||
bel = loc == PLL::left ? id("R1C28_PLLVR") : id("R1C37_PLLVR");
|
||||
break;
|
||||
case ID_rPLL:
|
||||
if (family == "GW1N-1" || family == "GW1NZ-1") {
|
||||
if (loc == PLL::left) {
|
||||
return;
|
||||
}
|
||||
bel = id("R1C18_rPLL");
|
||||
break;
|
||||
}
|
||||
if (family == "GW1NR-9C" || family == "GW1NR-9") {
|
||||
bel = loc == PLL::left ? id("R10C1_rPLL") : id("R10C47_rPLL");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (checkBelAvail(bel) || ci->belStrength != STRENGTH_LOCKED) {
|
||||
if (ci->bel == bel) {
|
||||
unbindBel(bel);
|
||||
} else {
|
||||
if (!checkBelAvail(bel) && ci->belStrength != STRENGTH_LOCKED) {
|
||||
CellInfo *other_ci = getBoundBelCell(bel);
|
||||
unbindBel(bel);
|
||||
BelId our_bel = ci->bel;
|
||||
unbindBel(our_bel);
|
||||
bindBel(our_bel, other_ci, STRENGTH_LOCKED);
|
||||
}
|
||||
}
|
||||
ci->disconnectPort(id_CLKIN);
|
||||
ci->setParam(id_INSEL, Property("CLKIN0"));
|
||||
bindBel(bel, ci, STRENGTH_LOCKED);
|
||||
}
|
||||
}
|
||||
|
||||
// If the PLL input can be connected using a direct wire, then do so,
|
||||
// bypassing conventional routing.
|
||||
void Arch::fix_pll_nets(Context *ctx)
|
||||
@ -2129,53 +2170,12 @@ void Arch::fix_pll_nets(Context *ctx)
|
||||
break;
|
||||
}
|
||||
if (net_driven_by(ctx, net, is_RPLL_T_IN_iob, id_O) != nullptr) {
|
||||
if (ci->type == id_rPLL) {
|
||||
ci->disconnectPort(id_CLKIN);
|
||||
ci->setParam(id_INSEL, Property("CLKIN0"));
|
||||
break;
|
||||
}
|
||||
BelId bel = id("R1C37_PLLVR");
|
||||
if (ci->type == id_PLLVR) {
|
||||
if (checkBelAvail(bel) || ci->belStrength != STRENGTH_LOCKED) {
|
||||
if (ci->bel == bel) {
|
||||
unbindBel(bel);
|
||||
} else {
|
||||
if (!checkBelAvail(bel) && ci->belStrength != STRENGTH_LOCKED) {
|
||||
CellInfo *other_ci = getBoundBelCell(bel);
|
||||
unbindBel(bel);
|
||||
BelId our_bel = ci->bel;
|
||||
unbindBel(our_bel);
|
||||
bindBel(our_bel, other_ci, STRENGTH_LOCKED);
|
||||
}
|
||||
}
|
||||
ci->disconnectPort(id_CLKIN);
|
||||
ci->setParam(id_INSEL, Property("CLKIN0"));
|
||||
bindBel(bel, ci, STRENGTH_LOCKED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
bind_pll_to_bel(ci, PLL::right);
|
||||
break;
|
||||
}
|
||||
if (net_driven_by(ctx, net, is_LPLL_T_IN_iob, id_O) != nullptr) {
|
||||
BelId bel = id("R1C28_PLLVR");
|
||||
if (ci->type == id_PLLVR) {
|
||||
if (checkBelAvail(bel) || ci->belStrength != STRENGTH_LOCKED) {
|
||||
if (ci->bel == bel) {
|
||||
unbindBel(bel);
|
||||
} else {
|
||||
if (!checkBelAvail(bel) && ci->belStrength != STRENGTH_LOCKED) {
|
||||
CellInfo *other_ci = getBoundBelCell(bel);
|
||||
unbindBel(bel);
|
||||
BelId our_bel = ci->bel;
|
||||
unbindBel(our_bel);
|
||||
bindBel(our_bel, other_ci, STRENGTH_LOCKED);
|
||||
}
|
||||
}
|
||||
ci->disconnectPort(id_CLKIN);
|
||||
ci->setParam(id_INSEL, Property("CLKIN0"));
|
||||
bindBel(bel, ci, STRENGTH_LOCKED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
bind_pll_to_bel(ci, PLL::left);
|
||||
break;
|
||||
}
|
||||
// XXX do special bels (HCLK etc)
|
||||
// This is general routing through CLK0 pip
|
||||
|
@ -482,6 +482,7 @@ struct Arch : BaseArch<ArchRanges>
|
||||
void add_rpll_ports(DatabasePOD const *db, BelsPOD const *bel, IdString belname, int row, int col);
|
||||
void fix_pll_nets(Context *ctx);
|
||||
bool is_GCLKT_iob(const CellInfo *cell);
|
||||
void bind_pll_to_bel(CellInfo *ci, int loc);
|
||||
|
||||
GowinGlobalRouter globals_router;
|
||||
void mark_gowin_globals(Context *ctx);
|
||||
@ -530,6 +531,14 @@ enum
|
||||
};
|
||||
}
|
||||
|
||||
namespace PLL { // fixed PLL locations
|
||||
enum
|
||||
{
|
||||
left = 0,
|
||||
right = 1
|
||||
};
|
||||
}
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
||||
#endif /* GOWIN_ARCH_H */
|
||||
|
@ -1043,7 +1043,8 @@ static void pack_plls(Context *ctx)
|
||||
|
||||
switch (ci->type.hash()) {
|
||||
case ID_rPLL: {
|
||||
if (parm_device == "GW1N-1" || parm_device == "GW1NZ-1" || parm_device == "GW1NR-9C") {
|
||||
if (parm_device == "GW1N-1" || parm_device == "GW1NZ-1" || parm_device == "GW1NR-9C" ||
|
||||
parm_device == "GW1NR-9") {
|
||||
pll_disable_unused_ports(ctx, ci);
|
||||
// A cell
|
||||
std::unique_ptr<CellInfo> cell = create_generic_cell(ctx, id_rPLL, ci->name.str(ctx) + "$rpll");
|
||||
|
Loading…
Reference in New Issue
Block a user