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>
This commit is contained in:
Sylvain Munaut 2023-02-01 11:41:16 +01:00
parent 235e0d28e9
commit 49ae495344
3 changed files with 19 additions and 13 deletions

View File

@ -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);
}

View File

@ -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;

View File

@ -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)