1
0
mirror of https://github.com/YosysHQ/nextpnr.git synced 2026-01-11 23:53:21 +00:00

Gowin. Implement on-chip oscillator.

A programmable on-chip crystal oscillator has been implemented for the
GW5A series.

A critical innovation in this series was the change in the nature of the
OSC output pin—it now belongs to the clock wires, and therefore the
routes must be made with a special global router, as there is no
possibility of using routing through general-purpose PIPs.

At the same time, we are transferring the outputs of all previous
generations of OSC to potential clock wires. At the moment, this will
not affect the way they are routed - they will still end up as segments
as before, but in the future we may optimize the mechanism.

Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
YRabbit 2025-08-31 10:37:58 +10:00 committed by Lofty
parent bc086c012f
commit 75aa8d16ac
3 changed files with 17 additions and 2 deletions

View File

@ -1022,6 +1022,7 @@ X(INV)
// Oscillators
X(OSC)
X(OSCA)
X(OSCZ)
X(OSCH)
X(OSCF)
@ -1274,6 +1275,7 @@ X(ALU_COUT)
X(PLL_O)
X(PLL_I)
// fake dff inputs
X(XD0)
X(XD1)

View File

@ -65,11 +65,11 @@ struct GowinGlobalRouter
bool not_dcs_pip = dst_name != id_CLKOUT;
IdString src_type = ctx->getWireType(src);
IdString dst_type = ctx->getWireType(dst);
bool src_valid = not_dcs_pip && src_type.in(id_GLOBAL_CLK, id_IO_O, id_PLL_O, id_HCLK, id_DLLDLY);
bool src_valid = not_dcs_pip && src_type.in(id_GLOBAL_CLK, id_IO_O, id_PLL_O, id_HCLK, id_DLLDLY, id_OSCOUT);
bool dst_valid = not_dcs_pip && dst_type.in(id_GLOBAL_CLK, id_TILE_CLK, id_PLL_I, id_IO_I, id_HCLK);
bool res;
if (src == src_wire && (!src_type.in(id_IO_O, id_HCLK, id_DLLDLY_O))) {
if (src == src_wire && (!src_type.in(id_IO_O, id_HCLK, id_DLLDLY_O, id_OSCOUT))) {
bool dst_is_spine = dst_name.str(ctx).rfind("SPINE", 0) == 0;
res = src_valid && dst_is_spine;
} else {

View File

@ -34,6 +34,19 @@ bool GowinUtils::driver_is_clksrc(const PortRef &driver)
}
}
}
// OSC outputs
if (driver.cell->type.in(id_OSC, id_OSCA, id_OSCZ, id_OSCH, id_OSCF, id_OSCW, id_OSCO)) {
if (driver.port == id_OSCOUT) {
if (ctx->debug) {
if (driver.cell->bel != BelId()) {
log_info("OSC out bel:%s:%s\n", ctx->nameOfBel(driver.cell->bel), driver.port.c_str(ctx));
} else {
log_info("OSC out:%s:%s\n", ctx->nameOf(driver.cell), driver.port.c_str(ctx));
}
}
return true;
}
}
// PLL outputs
if (driver.cell->type.in(id_rPLL, id_PLLVR)) {
if (driver.port.in(id_CLKOUT, id_CLKOUTD, id_CLKOUTD3, id_CLKOUTP)) {