From 75aa8d16acbc7ce997860144d9e07e6eeccc3630 Mon Sep 17 00:00:00 2001 From: YRabbit Date: Sun, 31 Aug 2025 10:37:58 +1000 Subject: [PATCH] Gowin. Implement on-chip oscillator. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- himbaechel/uarch/gowin/constids.inc | 2 ++ himbaechel/uarch/gowin/globals.cc | 4 ++-- himbaechel/uarch/gowin/gowin_utils.cc | 13 +++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/himbaechel/uarch/gowin/constids.inc b/himbaechel/uarch/gowin/constids.inc index 9b5e2c8c..69b7f2e6 100644 --- a/himbaechel/uarch/gowin/constids.inc +++ b/himbaechel/uarch/gowin/constids.inc @@ -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) diff --git a/himbaechel/uarch/gowin/globals.cc b/himbaechel/uarch/gowin/globals.cc index 27ac0a95..e510e474 100644 --- a/himbaechel/uarch/gowin/globals.cc +++ b/himbaechel/uarch/gowin/globals.cc @@ -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 { diff --git a/himbaechel/uarch/gowin/gowin_utils.cc b/himbaechel/uarch/gowin/gowin_utils.cc index 34529463..605ae2c4 100644 --- a/himbaechel/uarch/gowin/gowin_utils.cc +++ b/himbaechel/uarch/gowin/gowin_utils.cc @@ -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)) {