diff options
-rw-r--r-- | ecp5/bitstream.cc | 47 | ||||
-rw-r--r-- | ecp5/iotypes.inc | 2 | ||||
-rw-r--r-- | ecp5/pio.cc | 6 |
3 files changed, 42 insertions, 13 deletions
diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index 66bd639a..207ba048 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -256,6 +256,18 @@ static std::string get_pic_tile(Context *ctx, BelId bel) } } +// Get the complement PIC and PIO tiles for a pseudo differential IO +static std::string get_comp_pio_tile(Context *ctx, BelId bel) +{ + NPNR_ASSERT(bel.location.y == 0); + return ctx->getTileByTypeAndLocation(0, bel.location.x + 1, "PIOT1"); +} +static std::string get_comp_pic_tile(Context *ctx, BelId bel) +{ + NPNR_ASSERT(bel.location.y == 0); + return ctx->getTileByTypeAndLocation(1, bel.location.x + 1, "PICT1"); +} + // Get the list of tiles corresponding to a blockram std::vector<std::string> get_bram_tiles(Context *ctx, BelId bel) { @@ -829,18 +841,29 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex cc.tiles[pio_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype); cc.tiles[pic_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype); if (is_differential(ioType_from_str(iotype))) { - // Explicitly disable other pair - std::string other; - if (pio == "PIOA") - other = "PIOB"; - else if (pio == "PIOC") - other = "PIOD"; - else - log_error("cannot place differential IO at location %s\n", pio.c_str()); - // cc.tiles[pio_tile].add_enum(other + ".BASE_TYPE", "_NONE_"); - // cc.tiles[pic_tile].add_enum(other + ".BASE_TYPE", "_NONE_"); - cc.tiles[pio_tile].add_enum(other + ".PULLMODE", "NONE"); - cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", "NONE"); + if (bel.location.y == 0) { + // Pseudo differential top IO + NPNR_ASSERT(dir == "OUTPUT"); + NPNR_ASSERT(pio == "PIOA"); + std::string cpio_tile = get_comp_pio_tile(ctx, bel); + std::string cpic_tile = get_comp_pic_tile(ctx, bel); + cc.tiles[cpio_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype); + cc.tiles[cpic_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype); + } else { + // Explicitly disable other pair + std::string other; + if (pio == "PIOA") + other = "PIOB"; + else if (pio == "PIOC") + other = "PIOD"; + else + log_error("cannot place differential IO at location %s\n", pio.c_str()); + // cc.tiles[pio_tile].add_enum(other + ".BASE_TYPE", "_NONE_"); + // cc.tiles[pic_tile].add_enum(other + ".BASE_TYPE", "_NONE_"); + cc.tiles[pio_tile].add_enum(other + ".PULLMODE", "NONE"); + cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", "NONE"); + } + } else if (is_referenced(ioType_from_str(iotype))) { cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", "NONE"); } diff --git a/ecp5/iotypes.inc b/ecp5/iotypes.inc index 5984e79e..ecedf47a 100644 --- a/ecp5/iotypes.inc +++ b/ecp5/iotypes.inc @@ -22,6 +22,8 @@ X(SSTL15D_II) X(HSUL12D) X(LVCMOS33D) X(LVCMOS25D) +X(LVCMOS15D) +X(LVCMOS12D) X(LVDS) X(BLVDS25) diff --git a/ecp5/pio.cc b/ecp5/pio.cc index 65dcd704..5ff375e3 100644 --- a/ecp5/pio.cc +++ b/ecp5/pio.cc @@ -109,6 +109,7 @@ IOVoltage get_vccio(IOType type) case IOType::SSTL18D_II: return IOVoltage::VCC_1V8; case IOType::LVCMOS15: + case IOType::LVCMOS15D: case IOType::SSTL15_I: case IOType::SSTL15_II: case IOType::SSTL15D_I: @@ -120,6 +121,7 @@ IOVoltage get_vccio(IOType type) case IOType::SSTL135D_II: return IOVoltage::VCC_1V35; case IOType::LVCMOS12: + case IOType::LVCMOS12D: case IOType::HSUL12: case IOType::HSUL12D: return IOVoltage::VCC_1V2; @@ -159,6 +161,8 @@ bool is_differential(IOType type) switch (type) { case IOType::LVCMOS33D: case IOType::LVCMOS25D: + case IOType::LVCMOS15D: + case IOType::LVCMOS12D: case IOType::LVPECL33: case IOType::LVDS: case IOType::MLVDS25: @@ -207,7 +211,7 @@ bool valid_loc_for_io(IOType type, PortType dir, IOSide side, int z) bool is_lr = side == IOSide::LEFT || side == IOSide::RIGHT; if (is_referenced(type) && !is_lr) return false; - if (is_differential(type) && (!is_lr || ((z % 2) == 1))) + if (is_differential(type) && ((!is_lr && dir != PORT_OUT) || ((z % 2) == 1))) return false; if ((type == IOType::LVCMOS18D || type == IOType::LVDS) && (dir == PORT_OUT || dir == PORT_INOUT) && z != 0) return false; |