aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2019-10-09 12:07:56 +0100
committerDavid Shah <dave@ds0.me>2019-10-09 12:07:56 +0100
commita14555c8d1c989a56fdd7bdd9c2a401d7d24a6bd (patch)
treece234c471b8ca17365f26b11d504556d22822fd1 /ecp5
parent21847a55e047428602faf549e5bf358669153dd5 (diff)
downloadnextpnr-a14555c8d1c989a56fdd7bdd9c2a401d7d24a6bd.tar.gz
nextpnr-a14555c8d1c989a56fdd7bdd9c2a401d7d24a6bd.tar.bz2
nextpnr-a14555c8d1c989a56fdd7bdd9c2a401d7d24a6bd.zip
ecp5: Add IDDR71B support
Signed-off-by: David Shah <dave@ds0.me>
Diffstat (limited to 'ecp5')
-rw-r--r--ecp5/constids.inc1
-rw-r--r--ecp5/pack.cc18
2 files changed, 16 insertions, 3 deletions
diff --git a/ecp5/constids.inc b/ecp5/constids.inc
index 1b5486eb..5e8fc7da 100644
--- a/ecp5/constids.inc
+++ b/ecp5/constids.inc
@@ -1181,6 +1181,7 @@ X(RDPNTR2)
X(WRPNTR0)
X(WRPNTR1)
X(WRPNTR2)
+X(SLIP)
X(GSR)
diff --git a/ecp5/pack.cc b/ecp5/pack.cc
index cea66e57..15c02e86 100644
--- a/ecp5/pack.cc
+++ b/ecp5/pack.cc
@@ -2085,10 +2085,10 @@ class Ecp5Packer
iol->params[ctx->id("GSR")] = str_or_default(ci->params, ctx->id("GSR"), "DISABLED");
pio->params[ctx->id("DATAMUX_ODDR")] = std::string("IOLDO");
packed_cells.insert(cell.first);
- } else if (ci->type == ctx->id("IDDRX2F")) {
+ } else if (ci->type == ctx->id("IDDRX2F") || ci->type == ctx->id("IDDR71B")) {
CellInfo *pio = net_driven_by(ctx, ci->ports.at(ctx->id("D")).net, is_trellis_io, id_O);
if (pio == nullptr || ci->ports.at(ctx->id("D")).net->users.size() > 1)
- log_error("IDDRX2F '%s' D input must be connected only to a top level input\n",
+ log_error("%s '%s' D input must be connected only to a top level input\n", ci->type.c_str(ctx),
ci->name.c_str(ctx));
CellInfo *iol;
if (pio_iologic.count(pio->name))
@@ -2104,8 +2104,20 @@ class Ecp5Packer
replace_port(ci, ctx->id("Q1"), iol, id_RXDATA1);
replace_port(ci, ctx->id("Q2"), iol, id_RXDATA2);
replace_port(ci, ctx->id("Q3"), iol, id_RXDATA3);
+ if (ci->type == ctx->id("IDDR71B")) {
+ Loc loc =
+ ctx->getBelLocation(ctx->getBelByName(ctx->id(pio->attrs.at(ctx->id("BEL")).as_string())));
+ if (loc.z % 2 == 1)
+ log_error("IDDR71B '%s' can only be used at 'A' or 'C' locations\n", ci->name.c_str(ctx));
+ replace_port(ci, ctx->id("Q4"), iol, id_RXDATA4);
+ replace_port(ci, ctx->id("Q5"), iol, id_RXDATA5);
+ replace_port(ci, ctx->id("Q6"), iol, id_RXDATA6);
+ replace_port(ci, ctx->id("ALIGNWD"), iol, id_SLIP);
+ iol->params[ctx->id("IDDRXN.MODE")] = std::string("IDDR71");
+ } else {
+ iol->params[ctx->id("IDDRXN.MODE")] = std::string("IDDRX2");
+ }
iol->params[ctx->id("GSR")] = str_or_default(ci->params, ctx->id("GSR"), "DISABLED");
- iol->params[ctx->id("IDDRXN.MODE")] = std::string("IDDRX2");
packed_cells.insert(cell.first);
} else if (ci->type == ctx->id("OSHX2A")) {
CellInfo *pio = net_only_drives(ctx, ci->ports.at(ctx->id("Q")).net, is_trellis_io, id_I, true);