From 900573c77853209f54f0e23c860327593f5c874a Mon Sep 17 00:00:00 2001 From: YRabbit Date: Tue, 18 Nov 2025 21:44:15 +1000 Subject: [PATCH] Gowin. Implemenet special ADC IO. (#1598) The TLVDS_IBUF_ADC IO primitives have been implemented, which provide a signal for ADC bus 2. These differential IO primitives also have an additional input that allows them to be disabled, thereby providing dynamic switching of the signal source for the ADC. Signed-off-by: YRabbit --- himbaechel/uarch/gowin/constids.inc | 3 +++ himbaechel/uarch/gowin/cst.cc | 2 +- himbaechel/uarch/gowin/gowin.h | 2 +- himbaechel/uarch/gowin/gowin_arch_gen.py | 4 ++++ himbaechel/uarch/gowin/pack.cc | 18 +++++++++++++++++- 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/himbaechel/uarch/gowin/constids.inc b/himbaechel/uarch/gowin/constids.inc index 5307eaee..b781f37c 100644 --- a/himbaechel/uarch/gowin/constids.inc +++ b/himbaechel/uarch/gowin/constids.inc @@ -997,6 +997,7 @@ X(IBUF) X(OBUF) X(IOBUF) X(TBUF) +X(TLVDS_IBUF_ADC) X(TLVDS_OBUF) X(TLVDS_TBUF) X(TLVDS_IBUF) @@ -1040,6 +1041,7 @@ X(PLLA) // ADC X(ADC) +X(ADC_IO) // primitive attributes X(INIT) @@ -1067,6 +1069,7 @@ X(I0) X(I1) X(I2) X(I3) +X(ADCEN) X(OEN) X(S0) X(SEL) diff --git a/himbaechel/uarch/gowin/cst.cc b/himbaechel/uarch/gowin/cst.cc index e502750f..c9097850 100644 --- a/himbaechel/uarch/gowin/cst.cc +++ b/himbaechel/uarch/gowin/cst.cc @@ -160,7 +160,7 @@ struct GowinCstReader row = col; col = 1; } - adc_ios.insert(ctx->idf("%d/X%dY%d", std::stoi(match[1]), row - 1, col - 1)); + adc_ios.insert(ctx->idf("%d/X%dY%d", std::stoi(match[1]), col - 1, row - 1)); } break; case clock: { // CLOCK name BUFG|S=# std::string which_clock = match[2]; diff --git a/himbaechel/uarch/gowin/gowin.h b/himbaechel/uarch/gowin/gowin.h index 22b62dec..3aff35b6 100644 --- a/himbaechel/uarch/gowin/gowin.h +++ b/himbaechel/uarch/gowin/gowin.h @@ -28,7 +28,7 @@ inline bool is_io(const CellInfo *cell) { return type_is_io(cell->type); } inline bool type_is_diffio(IdString cell_type) { return cell_type.in(id_ELVDS_IOBUF, id_ELVDS_IBUF, id_ELVDS_TBUF, id_ELVDS_OBUF, id_TLVDS_IOBUF, id_TLVDS_IBUF, - id_TLVDS_TBUF, id_TLVDS_OBUF); + id_TLVDS_TBUF, id_TLVDS_OBUF, id_TLVDS_IBUF_ADC); } inline bool is_diffio(const CellInfo *cell) { return type_is_diffio(cell->type); } diff --git a/himbaechel/uarch/gowin/gowin_arch_gen.py b/himbaechel/uarch/gowin/gowin_arch_gen.py index 8e211829..6a9668af 100644 --- a/himbaechel/uarch/gowin/gowin_arch_gen.py +++ b/himbaechel/uarch/gowin/gowin_arch_gen.py @@ -925,6 +925,10 @@ def create_io_tiletype(chip: Chip, db: chipdb, x: int, y: int, ttyp: int, tdesc: tt.add_bel_pin(io, "I", portmap['I'], PinType.INPUT) tt.add_bel_pin(io, "OEN", portmap['OE'], PinType.INPUT) tt.add_bel_pin(io, "O", portmap['O'], PinType.OUTPUT) + if 'ADCEN' in portmap: + tt.create_wire(portmap['ADCEN'], "IO_ADCEN") + tt.add_bel_pin(io, "ADCEN", portmap['ADCEN'], PinType.INPUT) + # bottom io if 'BOTTOM_IO_PORT_A' in portmap and portmap['BOTTOM_IO_PORT_A']: if not tt.has_wire(portmap['BOTTOM_IO_PORT_A']): diff --git a/himbaechel/uarch/gowin/pack.cc b/himbaechel/uarch/gowin/pack.cc index 5c09f7a5..44e519b0 100644 --- a/himbaechel/uarch/gowin/pack.cc +++ b/himbaechel/uarch/gowin/pack.cc @@ -232,7 +232,8 @@ struct GowinPacker p = net_only_drives(ctx, ci.ports.at(id_O).net, is_iob, id_I, true); n = net_only_drives(ctx, ci.ports.at(id_OB).net, is_iob, id_I, true); break; - case ID_ELVDS_IBUF: /* fall-through */ + case ID_TLVDS_IBUF_ADC: /* fall-through */ + case ID_ELVDS_IBUF: /* fall-through */ case ID_TLVDS_IBUF: p = net_driven_by(ctx, ci.ports.at(id_I).net, is_iob, id_O); n = net_driven_by(ctx, ci.ports.at(id_IB).net, is_iob, id_O); @@ -254,6 +255,10 @@ struct GowinPacker pn_cells.first->setParam(id_DIFF_TYPE, ci.type.str(ctx)); pn_cells.second->setParam(id_DIFF, std::string("N")); pn_cells.second->setParam(id_DIFF_TYPE, ci.type.str(ctx)); + if (ci.params.count(id_ADC_IO)) { + pn_cells.first->setParam(id_ADC_IO, ci.params.at(id_ADC_IO)); + pn_cells.second->setParam(id_ADC_IO, ci.params.at(id_ADC_IO)); + } } void switch_diff_ports(CellInfo &ci, std::pair &pn_cells, @@ -318,6 +323,17 @@ struct GowinPacker ci.movePortTo(id_O, iob_p, id_O); return; } + if (ci.type.in(id_TLVDS_IBUF_ADC)) { + nets_to_remove.push_back(ci.getPort(id_I)->name); + ci.disconnectPort(id_I); + nets_to_remove.push_back(ci.getPort(id_IB)->name); + ci.disconnectPort(id_IB); + iob_p->disconnectPort(id_O); + iob_n->disconnectPort(id_O); + + ci.movePortTo(id_ADCEN, iob_p, id_ADCEN); + return; + } } // ===================================