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

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 <rabbit@yrabbit.cyou>
This commit is contained in:
YRabbit 2025-11-18 21:44:15 +10:00 committed by GitHub
parent 69facd7c9a
commit 900573c778
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 26 additions and 3 deletions

View File

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

View File

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

View File

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

View File

@ -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']):

View File

@ -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<CellInfo *, CellInfo *> &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;
}
}
// ===================================