aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2019-02-13 13:35:43 +0000
committerDavid Shah <davey1576@gmail.com>2019-02-24 10:28:25 +0100
commit491d64293dc3b96e2428515b51c408c817c9b803 (patch)
tree9da72f641af8350557cf6e2ba3f9eddc2535cdd8 /ecp5
parent68abcb365a7e1c426d2ca96e2381892aa53e6192 (diff)
downloadnextpnr-491d64293dc3b96e2428515b51c408c817c9b803.tar.gz
nextpnr-491d64293dc3b96e2428515b51c408c817c9b803.tar.bz2
nextpnr-491d64293dc3b96e2428515b51c408c817c9b803.zip
ecp5: Add DDRDLLA support
Signed-off-by: David Shah <dave@ds0.me>
Diffstat (limited to 'ecp5')
-rw-r--r--ecp5/bitstream.cc12
-rw-r--r--ecp5/pack.cc30
2 files changed, 42 insertions, 0 deletions
diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc
index c433a088..170eaefd 100644
--- a/ecp5/bitstream.cc
+++ b/ecp5/bitstream.cc
@@ -1228,6 +1228,18 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
std::string tile = ctx->getTileByType(std::string("ECLK_") + (r ? "R" : "L"));
if (get_net_or_empty(ci, id_STOP) != nullptr)
cc.tiles[tile].add_enum(eclksync + ".MODE", "ECLKSYNCB");
+ } else if (ci->type == id_DDRDLL) {
+ Loc loc = ctx->getBelLocation(ci->bel);
+ bool u = loc.y<15, r = loc.x> 15;
+ std::string tiletype = fmt_str("DDRDLL_" << (u ? 'U' : 'L') << (r ? 'R' : 'L'));
+ if (ctx->args.type == ArchArgs::LFE5U_25F || ctx->args.type == ArchArgs::LFE5UM_25F ||
+ ctx->args.type == ArchArgs::LFE5UM5G_25F)
+ tiletype += "A";
+ std::string tile = ctx->getTileByType(tiletype);
+ cc.tiles[tile].add_enum("DDRDLL.MODE", "DDRDLLA");
+ cc.tiles[tile].add_enum("DDRDLL.GSR", str_or_default(ci->params, ctx->id("GSR"), "DISABLED"));
+ cc.tiles[tile].add_enum("DDRDLL.FORCE_MAX_DELAY",
+ str_or_default(ci->params, ctx->id("FORCE_MAX_DELAY"), "NO"));
} else {
NPNR_ASSERT_FALSE("unsupported cell type");
}
diff --git a/ecp5/pack.cc b/ecp5/pack.cc
index b84d4d60..3c838268 100644
--- a/ecp5/pack.cc
+++ b/ecp5/pack.cc
@@ -1985,6 +1985,36 @@ class Ecp5Packer
}
eclksync_done:
continue;
+ } else if (ci->type == ctx->id("DDRDLLA")) {
+ ci->type = id_DDRDLL; // transform from Verilog to Bel name
+ const NetInfo *clk = net_or_nullptr(ci, id_CLK);
+ if (clk == nullptr)
+ log_error("DDRDLLA '%s' has disconnected port CLK\n", ci->name.c_str(ctx));
+ for (auto &eclk : eclks) {
+ if (eclk.second.unbuf == clk) {
+ for (auto bel : ctx->getBels()) {
+ if (ctx->getBelType(bel) != id_DDRDLL)
+ continue;
+ Loc loc = ctx->getBelLocation(bel);
+ int ddrdll_bank = -1;
+ if (loc.x < 15 && loc.y < 15)
+ ddrdll_bank = 7;
+ else if (loc.x < 15 && loc.y > 15)
+ ddrdll_bank = 6;
+ else if (loc.x > 15 && loc.y < 15)
+ ddrdll_bank = 2;
+ else if (loc.x > 15 && loc.y > 15)
+ ddrdll_bank = 3;
+ if (eclk.first.first != ddrdll_bank)
+ continue;
+ ci->attrs[ctx->id("BEL")] = ctx->getBelName(bel).str(ctx);
+ make_eclk(ci->ports.at(id_CLK), ci, bel, eclk.first.first);
+ goto ddrdll_done;
+ }
+ }
+ }
+ ddrdll_done:
+ continue;
}
}