aboutsummaryrefslogtreecommitdiffstats
path: root/ice40/bitstream.cc
diff options
context:
space:
mode:
authorSylvain Munaut <tnt@246tNt.com>2018-11-27 03:16:05 +0100
committerSylvain Munaut <tnt@246tNt.com>2018-11-28 16:04:23 +0100
commit5f0f2b060b1f8dee94e4cbcfe1b190c9f0b53bb0 (patch)
tree90e8e684edfc1f33f67f8734c8391ddd48d69252 /ice40/bitstream.cc
parent7a2ef27d6c27425bc39ef3a71b0df8b1c608d599 (diff)
downloadnextpnr-5f0f2b060b1f8dee94e4cbcfe1b190c9f0b53bb0.tar.gz
nextpnr-5f0f2b060b1f8dee94e4cbcfe1b190c9f0b53bb0.tar.bz2
nextpnr-5f0f2b060b1f8dee94e4cbcfe1b190c9f0b53bb0.zip
ice40: Update the way LVDS inputs are handled during bitstream generation
* Instead of "patching" input_en, we completely separate config for normal and LVDS pair. - For normal pair, nothing changes - For LVDS pairs, the IE/REN bits are always set as if the input buffer are disabled. Then if input_en was set to 1 (i.e. the input is actually for something), then we set the IoCtrl.LVDS bit. - Also for LVDS, if input is used, pullups are forcibly disabled. * When scanning for unused IOs, never process those part of a LVDS pair. They will have been configured by the complement Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Diffstat (limited to 'ice40/bitstream.cc')
-rw-r--r--ice40/bitstream.cc96
1 files changed, 48 insertions, 48 deletions
diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc
index ecb26753..e20d372a 100644
--- a/ice40/bitstream.cc
+++ b/ice40/bitstream.cc
@@ -486,7 +486,7 @@ void write_asc(const Context *ctx, std::ostream &out)
unsigned pin_type = get_param_or_def(cell.second.get(), ctx->id("PIN_TYPE"));
bool neg_trigger = get_param_or_def(cell.second.get(), ctx->id("NEG_TRIGGER"));
bool pullup = get_param_or_def(cell.second.get(), ctx->id("PULLUP"));
- bool lvds = get_param_str_or_def(cell.second.get(), ctx->id("IO_STANDARD")) == "SB_LVDS_INPUT";
+ bool lvds = cell.second->ioInfo.lvds;
bool used_by_pll_out = sb_io_used_by_pll_out.count(Loc(x, y, z)) > 0;
bool used_by_pll_pad = sb_io_used_by_pll_pad.count(Loc(x, y, z)) > 0;
@@ -495,64 +495,64 @@ void write_asc(const Context *ctx, std::ostream &out)
set_config(ti, config.at(y).at(x), "IOB_" + std::to_string(z) + ".PINTYPE_" + std::to_string(i), val);
}
set_config(ti, config.at(y).at(x), "NegClk", neg_trigger);
- auto ieren = get_ieren(bi, x, y, z);
- int iex, iey, iez;
- std::tie(iex, iey, iez) = ieren;
- NPNR_ASSERT(iez != -1);
- bool input_en;
- if (lvds) {
- input_en = false;
- pullup = false;
- } else {
- if ((ctx->wire_to_net[ctx->getBelPinWire(bel, id_D_IN_0).index] != nullptr) ||
- (ctx->wire_to_net[ctx->getBelPinWire(bel, id_D_IN_1).index] != nullptr)) {
- input_en = true;
- } else {
- input_en = false;
- }
+ bool input_en = false;
+ if ((ctx->wire_to_net[ctx->getBelPinWire(bel, id_D_IN_0).index] != nullptr) ||
+ (ctx->wire_to_net[ctx->getBelPinWire(bel, id_D_IN_1).index] != nullptr)) {
+ input_en = true;
}
-
input_en = (input_en & !used_by_pll_out) | used_by_pll_pad;
input_en |= cell.second->ioInfo.global;
- if (ctx->args.type == ArchArgs::LP1K || ctx->args.type == ArchArgs::HX1K) {
- set_config(ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), !input_en);
- set_config(ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), !pullup);
- } else {
- set_config(ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), input_en);
- set_config(ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), !pullup);
- }
-
- if (ctx->args.type == ArchArgs::UP5K) {
- if (iez == 0) {
- set_config(ti, config.at(iey).at(iex), "IoCtrl.cf_bit_39", !pullup);
- } else if (iez == 1) {
- set_config(ti, config.at(iey).at(iex), "IoCtrl.cf_bit_35", !pullup);
- }
- }
-
- if (lvds) {
- NPNR_ASSERT(z == 0);
- set_config(ti, config.at(y).at(x), "IoCtrl.LVDS", true);
- // Set comp IO config
- auto comp_ieren = get_ieren(bi, x, y, 1);
- int ciex, ciey, ciez;
- std::tie(ciex, ciey, ciez) = comp_ieren;
+ if (!lvds) {
+ auto ieren = get_ieren(bi, x, y, z);
+ int iex, iey, iez;
+ std::tie(iex, iey, iez) = ieren;
+ NPNR_ASSERT(iez != -1);
if (ctx->args.type == ArchArgs::LP1K || ctx->args.type == ArchArgs::HX1K) {
- set_config(ti, config.at(ciey).at(ciex), "IoCtrl.IE_" + std::to_string(ciez), !input_en);
- set_config(ti, config.at(ciey).at(ciex), "IoCtrl.REN_" + std::to_string(ciez), !pullup);
+ set_config(ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), !input_en);
+ set_config(ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), !pullup);
} else {
- set_config(ti, config.at(ciey).at(ciex), "IoCtrl.IE_" + std::to_string(ciez), input_en);
- set_config(ti, config.at(ciey).at(ciex), "IoCtrl.REN_" + std::to_string(ciez), !pullup);
+ set_config(ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), input_en);
+ set_config(ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), !pullup);
}
if (ctx->args.type == ArchArgs::UP5K) {
- if (ciez == 0) {
- set_config(ti, config.at(ciey).at(ciex), "IoCtrl.cf_bit_39", !pullup);
+ if (iez == 0) {
+ set_config(ti, config.at(iey).at(iex), "IoCtrl.cf_bit_39", !pullup);
} else if (iez == 1) {
- set_config(ti, config.at(ciey).at(ciex), "IoCtrl.cf_bit_35", !pullup);
+ set_config(ti, config.at(iey).at(iex), "IoCtrl.cf_bit_35", !pullup);
+ }
+ }
+ } else {
+ NPNR_ASSERT(z == 0);
+ // Only enable the actual LVDS buffer if input is used for something
+ set_config(ti, config.at(y).at(x), "IoCtrl.LVDS", input_en);
+
+ // Set both IO config
+ for (int cz = 0; cz < 2; cz++) {
+ auto ieren = get_ieren(bi, x, y, cz);
+ int iex, iey, iez;
+ std::tie(iex, iey, iez) = ieren;
+ NPNR_ASSERT(iez != -1);
+
+ pullup &= !input_en; /* If input is used, force disable pullups */
+
+ if (ctx->args.type == ArchArgs::LP1K || ctx->args.type == ArchArgs::HX1K) {
+ set_config(ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), true);
+ set_config(ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), !pullup);
+ } else {
+ set_config(ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), false);
+ set_config(ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), !pullup);
+ }
+
+ if (ctx->args.type == ArchArgs::UP5K) {
+ if (iez == 0) {
+ set_config(ti, config.at(iey).at(iex), "IoCtrl.cf_bit_39", !pullup);
+ } else if (iez == 1) {
+ set_config(ti, config.at(iey).at(iex), "IoCtrl.cf_bit_35", !pullup);
+ }
}
}
}
@@ -688,7 +688,7 @@ void write_asc(const Context *ctx, std::ostream &out)
int iex, iey, iez;
std::tie(iex, iey, iez) = ieren;
if (iez != -1) {
- // IO is not actually unused if part of an LVDS pair
+ // If IO is in LVDS pair, it will be configured by the other pair
if (z == 1) {
BelId lvds0 = ctx->getBelByLocation(Loc{x, y, 0});
const CellInfo *lvds0cell = ctx->getBoundBelCell(lvds0);