aboutsummaryrefslogtreecommitdiffstats
path: root/gowin/pack.cc
diff options
context:
space:
mode:
authorYRabbit <rabbit@yrabbit.cyou>2023-01-18 19:18:02 +1000
committerYRabbit <rabbit@yrabbit.cyou>2023-01-18 19:18:02 +1000
commitb22eebac30124a4fc550ff5c9cd9767de266d481 (patch)
treee42feaea1ff4da1148f826d75eec12e30ce62baf /gowin/pack.cc
parenta46afc6ff8aca9a4b9275b3385bfec70f008e10b (diff)
downloadnextpnr-b22eebac30124a4fc550ff5c9cd9767de266d481.tar.gz
nextpnr-b22eebac30124a4fc550ff5c9cd9767de266d481.tar.bz2
nextpnr-b22eebac30124a4fc550ff5c9cd9767de266d481.zip
gowin: add a PLL primitive for the GW1NS-4 series
* both instances of the new PLLVR type are supported; * primitive placement is optimized for the use of dedicated PLL clock pins; * all 4 outputs of each primitive can use the clock nets (only 5 lines in total at the same time so far). Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
Diffstat (limited to 'gowin/pack.cc')
-rw-r--r--gowin/pack.cc69
1 files changed, 45 insertions, 24 deletions
diff --git a/gowin/pack.cc b/gowin/pack.cc
index e1119dde..e1372c47 100644
--- a/gowin/pack.cc
+++ b/gowin/pack.cc
@@ -989,11 +989,37 @@ static bool is_pll(const Context *ctx, const CellInfo *cell)
switch (cell->type.hash()) {
case ID_rPLL:
return true;
+ case ID_PLLVR:
+ return true;
default:
return false;
}
}
+static void pll_disable_unused_ports(Context *ctx, CellInfo *ci)
+{
+ // Unused ports will be disabled during image generation. Here we add flags for such ports.
+ Property pr_enable("ENABLE"), pr_disable("DISABLE");
+ IdString ports[][2] = {
+ {id_CLKOUTP, id_CLKOUTPS}, {id_CLKOUTD, id_CLKOUTDIV}, {id_CLKOUTD3, id_CLKOUTDIV3}, {id_LOCK, id_FLOCK}};
+ for (int i = 0; i < 4; ++i) {
+ ci->setParam(ports[i][1], port_used(ci, ports[i][0]) ? pr_enable : pr_disable);
+ }
+ // resets
+ NetInfo *net = ci->getPort(id_RESET);
+ ci->setParam(id_RSTEN, pr_enable);
+ if (!port_used(ci, id_RESET) || net->name == ctx->id("$PACKER_VCC_NET") ||
+ net->name == ctx->id("$PACKER_GND_NET")) {
+ ci->setParam(id_RSTEN, pr_disable);
+ }
+ ci->setParam(id_PWDEN, pr_enable);
+ net = ci->getPort(id_RESET_P);
+ if (!port_used(ci, id_RESET_P) || net->name == ctx->id("$PACKER_VCC_NET") ||
+ net->name == ctx->id("$PACKER_GND_NET")) {
+ ci->setParam(id_PWDEN, pr_disable);
+ }
+}
+
// Pack PLLs
static void pack_plls(Context *ctx)
{
@@ -1010,36 +1036,14 @@ static void pack_plls(Context *ctx)
if (is_pll(ctx, ci)) {
std::string parm_device = str_or_default(ci->params, id_DEVICE, "GW1N-1");
if (parm_device != ctx->device) {
- log_error("Wrong PLL device:%s vs %s\n", parm_device.c_str(), ctx->device.c_str());
+ log_error("Wrong PLL device:%s instead of %s\n", parm_device.c_str(), ctx->device.c_str());
continue;
}
switch (ci->type.hash()) {
case ID_rPLL: {
if (parm_device == "GW1N-1" || parm_device == "GW1NZ-1") {
- // Unused ports will be disabled during image generation. Here we add flags for such ports.
- Property pr_enable("ENABLE"), pr_disable("DISABLE");
- IdString ports[][2] = {{id_CLKOUTP, id_CLKOUTPS},
- {id_CLKOUTD, id_CLKOUTDIV},
- {id_CLKOUTD3, id_CLKOUTDIV3},
- {id_LOCK, id_FLOCK}};
- for (int i = 0; i < 4; ++i) {
- ci->setParam(ports[i][1], port_used(ci, ports[i][0]) ? pr_enable : pr_disable);
- }
- // resets
- NetInfo *net = ci->getPort(id_RESET);
- ci->setParam(id_RSTEN, pr_enable);
- if (!port_used(ci, id_RESET) || net->name == ctx->id("$PACKER_VCC_NET") ||
- net->name == ctx->id("$PACKER_GND_NET")) {
- ci->setParam(id_RSTEN, pr_disable);
- }
- ci->setParam(id_PWDEN, pr_enable);
- net = ci->getPort(id_RESET_P);
- if (!port_used(ci, id_RESET_P) || net->name == ctx->id("$PACKER_VCC_NET") ||
- net->name == ctx->id("$PACKER_GND_NET")) {
- ci->setParam(id_PWDEN, pr_disable);
- }
-
+ pll_disable_unused_ports(ctx, ci);
// B half
std::unique_ptr<CellInfo> cell = create_generic_cell(ctx, id_RPLLB, ci->name.str(ctx) + "$rpllb");
reconnect_rpllb(ctx, ci, cell.get());
@@ -1061,6 +1065,23 @@ static void pack_plls(Context *ctx)
log_error("PLL isn't supported for %s\n", ctx->device.c_str());
}
} break;
+ case ID_PLLVR: {
+ if (parm_device == "GW1NSR-4C") {
+ pll_disable_unused_ports(ctx, ci);
+ std::unique_ptr<CellInfo> cell = create_generic_cell(ctx, id_PLLVR, ci->name.str(ctx) + "$pllvr");
+ reconnect_pllvr(ctx, ci, cell.get());
+ new_cells.push_back(std::move(cell));
+ auto pll_cell = new_cells.back().get();
+
+ // need params for gowin_pack
+ for (auto &parm : ci->params) {
+ pll_cell->setParam(parm.first, parm.second);
+ }
+ packed_cells.insert(ci->name);
+ } else {
+ log_error("PLL isn't supported for %s\n", ctx->device.c_str());
+ }
+ } break;
default:
break;
}