aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylvain Munaut <tnt@246tNt.com>2023-02-01 11:41:16 +0100
committerSylvain Munaut <tnt@246tNt.com>2023-02-01 11:41:35 +0100
commit49ae4953443951bcd9679689e76c56411a3c9385 (patch)
tree8e8e7ffe97c96f8cdc5c77c0573fe03ec4b369a2
parent235e0d28e9a0ad13efaed9579453c917c9d7efc2 (diff)
downloadnextpnr-49ae4953443951bcd9679689e76c56411a3c9385.tar.gz
nextpnr-49ae4953443951bcd9679689e76c56411a3c9385.tar.bz2
nextpnr-49ae4953443951bcd9679689e76c56411a3c9385.zip
ice40: Add support for PLL ICEGATE function
Technically you can enable it independently on CORE and GLOBAL output, but this is not exposed in the classic primitive, so we do the same as icecube2 and enable/disable it for both output path depending on the argument Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
-rw-r--r--ice40/bitstream.cc27
-rw-r--r--ice40/cells.cc3
-rw-r--r--ice40/constids.inc2
3 files changed, 19 insertions, 13 deletions
diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc
index c8ad93d8..6794ecca 100644
--- a/ice40/bitstream.cc
+++ b/ice40/bitstream.cc
@@ -423,6 +423,18 @@ void write_asc(const Context *ctx, std::ostream &out)
// If this is a PAD PLL, and this is the 'PLLOUT_A' port, then the same SB_IO is also PAD
if (port == id_PLLOUT_A && is_sb_pll40_pad(ctx, cell.second.get()))
sb_io_used_by_pll_pad.insert(io_bel_loc);
+
+ // Configure the SB_IO that the clock outputs are going through.
+ // note: PINTYPE[1:0] must be set property to passes the PLL through to the fabric.
+ // "01" if ICEGATE is disabed for that port and "11" if it's enabled
+ const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO];
+ bool icegate_ena = get_param_or_def(
+ ctx, cell.second.get(), (port == id_PLLOUT_A) ? id_ENABLE_ICEGATE_PORTA : id_ENABLE_ICEGATE_PORTB);
+
+ set_config(ti, config.at(io_bel_loc.y).at(io_bel_loc.x),
+ "IOB_" + std::to_string(io_bel_loc.z) + ".PINTYPE_1", icegate_ena);
+ set_config(ti, config.at(io_bel_loc.y).at(io_bel_loc.x),
+ "IOB_" + std::to_string(io_bel_loc.z) + ".PINTYPE_0", true);
}
}
@@ -724,6 +736,8 @@ void write_asc(const Context *ctx, std::ostream &out)
{"DIVF", 7},
{"DIVQ", 3},
{"DIVR", 4},
+ {"ENABLE_ICEGATE_PORTA", 1},
+ {"ENABLE_ICEGATE_PORTB", 1},
{"FDA_FEEDBACK", 4},
{"FDA_RELATIVE", 4},
{"FEEDBACK_PATH", 3},
@@ -734,19 +748,6 @@ void write_asc(const Context *ctx, std::ostream &out)
{"SHIFTREG_DIV_MODE", 2},
{"TEST_MODE", 1}};
configure_extra_cell(config, ctx, cell.second.get(), pll_params, false, std::string("PLL."));
-
- // Configure the SB_IOs that the clock outputs are going through.
- for (auto &io_bel_loc : sb_io_used_by_pll_out) {
- // Write config.
- const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO];
-
- // PINTYPE[1:0] == "01" passes the PLL through to the fabric.
- set_config(ti, config.at(io_bel_loc.y).at(io_bel_loc.x),
- "IOB_" + std::to_string(io_bel_loc.z) + ".PINTYPE_1", false);
- set_config(ti, config.at(io_bel_loc.y).at(io_bel_loc.x),
- "IOB_" + std::to_string(io_bel_loc.z) + ".PINTYPE_0", true);
- }
-
} else {
NPNR_ASSERT(false);
}
diff --git a/ice40/cells.cc b/ice40/cells.cc
index 10964f3c..d304a68f 100644
--- a/ice40/cells.cc
+++ b/ice40/cells.cc
@@ -216,6 +216,9 @@ std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::stri
new_cell->params[id_PLLOUT_SELECT_A] = Property(0, 2);
new_cell->params[id_PLLOUT_SELECT_B] = Property(0, 2);
+ new_cell->params[id_ENABLE_ICEGATE_PORTA] = Property::State::S0;
+ new_cell->params[id_ENABLE_ICEGATE_PORTB] = Property::State::S0;
+
new_cell->params[id_PLLTYPE] = Property(0, 3);
new_cell->params[id_SHIFTREG_DIVMODE] = Property::State::S0;
new_cell->params[id_TEST_MODE] = Property::State::S0;
diff --git a/ice40/constids.inc b/ice40/constids.inc
index 8bad9e25..5575053d 100644
--- a/ice40/constids.inc
+++ b/ice40/constids.inc
@@ -480,6 +480,8 @@ X(DIVQ)
X(DIVR)
X(D_REG)
X(E)
+X(ENABLE_ICEGATE_PORTA)
+X(ENABLE_ICEGATE_PORTB)
X(FDA_FEEDBACK)
X(FDA_RELATIVE)
X(FEEDBACK_PATH)