ecp5: Add ODDR packing
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
36b1650df7
commit
9dc845b20d
@ -127,11 +127,17 @@ std::unique_ptr<CellInfo> create_ecp5_cell(Context *ctx, IdString type, std::str
|
|||||||
} else if (type == ctx->id("TRELLIS_IO")) {
|
} else if (type == ctx->id("TRELLIS_IO")) {
|
||||||
new_cell->params[ctx->id("DIR")] = "INPUT";
|
new_cell->params[ctx->id("DIR")] = "INPUT";
|
||||||
new_cell->attrs[ctx->id("IO_TYPE")] = "LVCMOS33";
|
new_cell->attrs[ctx->id("IO_TYPE")] = "LVCMOS33";
|
||||||
|
new_cell->params[ctx->id("DATAMUX_ODDR")] = "PADDO";
|
||||||
|
new_cell->params[ctx->id("DATAMUX_MDDR")] = "PADDO";
|
||||||
|
|
||||||
add_port(ctx, new_cell.get(), "B", PORT_INOUT);
|
add_port(ctx, new_cell.get(), "B", PORT_INOUT);
|
||||||
add_port(ctx, new_cell.get(), "I", PORT_IN);
|
add_port(ctx, new_cell.get(), "I", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "T", PORT_IN);
|
add_port(ctx, new_cell.get(), "T", PORT_IN);
|
||||||
add_port(ctx, new_cell.get(), "O", PORT_OUT);
|
add_port(ctx, new_cell.get(), "O", PORT_OUT);
|
||||||
|
|
||||||
|
add_port(ctx, new_cell.get(), "IOLDO", PORT_IN);
|
||||||
|
add_port(ctx, new_cell.get(), "IOLTO", PORT_IN);
|
||||||
|
|
||||||
} else if (type == ctx->id("LUT4")) {
|
} else if (type == ctx->id("LUT4")) {
|
||||||
new_cell->params[ctx->id("INIT")] = "0";
|
new_cell->params[ctx->id("INIT")] = "0";
|
||||||
|
|
||||||
@ -179,7 +185,6 @@ std::unique_ptr<CellInfo> create_ecp5_cell(Context *ctx, IdString type, std::str
|
|||||||
new_cell->params[ctx->id("DELAY.DEL_VALUE")] = "0";
|
new_cell->params[ctx->id("DELAY.DEL_VALUE")] = "0";
|
||||||
new_cell->params[ctx->id("DELAY.WAIT_FOR_EDGE")] = "DISABLED";
|
new_cell->params[ctx->id("DELAY.WAIT_FOR_EDGE")] = "DISABLED";
|
||||||
|
|
||||||
new_cell->params[ctx->id("DATAMUX_ODDR")] = "PADDO";
|
|
||||||
if (type == id_IOLOGIC) {
|
if (type == id_IOLOGIC) {
|
||||||
new_cell->params[ctx->id("IDDRXN.MODE")] = "NONE";
|
new_cell->params[ctx->id("IDDRXN.MODE")] = "NONE";
|
||||||
new_cell->params[ctx->id("ODDRXN.MODE")] = "NONE";
|
new_cell->params[ctx->id("ODDRXN.MODE")] = "NONE";
|
||||||
|
19
ecp5/pack.cc
19
ecp5/pack.cc
@ -1469,6 +1469,25 @@ class Ecp5Packer
|
|||||||
replace_port(ci, ctx->id("Q1"), iol, id_RXDATA1);
|
replace_port(ci, ctx->id("Q1"), iol, id_RXDATA1);
|
||||||
iol->params[ctx->id("GSR")] = str_or_default(ci->params, ctx->id("GSR"), "DISABLED");
|
iol->params[ctx->id("GSR")] = str_or_default(ci->params, ctx->id("GSR"), "DISABLED");
|
||||||
packed_cells.insert(cell.first);
|
packed_cells.insert(cell.first);
|
||||||
|
} else if (ci->type == ctx->id("ODDRX1F")) {
|
||||||
|
CellInfo *pio = net_only_drives(ctx, ci->ports.at(ctx->id("Q")).net, is_trellis_io, id_I, true);
|
||||||
|
if (pio == nullptr)
|
||||||
|
log_error("ODDRX1F '%s' Q output must be connected only to a top level output\n", ci->name.c_str(ctx));
|
||||||
|
CellInfo *iol;
|
||||||
|
if (pio_iologic.count(pio->name))
|
||||||
|
iol = pio_iologic.at(pio->name);
|
||||||
|
else
|
||||||
|
iol = create_pio_iologic(pio, ci);
|
||||||
|
set_iologic_mode(iol, "IDDRX1_ODDRX1");
|
||||||
|
replace_port(ci, ctx->id("Q"), iol, id_IOLDO);
|
||||||
|
replace_port(pio, id_PADDO, pio, id_IOLDO);
|
||||||
|
pio->params[ctx->id("DATAMUX_ODDR")] = "IOLDO";
|
||||||
|
set_iologic_sclk(iol, ci, ctx->id("SCLK"), true);
|
||||||
|
set_iologic_lsr(iol, ci, ctx->id("RST"), true);
|
||||||
|
replace_port(ci, ctx->id("D0"), iol, id_TXDATA0);
|
||||||
|
replace_port(ci, ctx->id("D1"), iol, id_TXDATA1);
|
||||||
|
iol->params[ctx->id("GSR")] = str_or_default(ci->params, ctx->id("GSR"), "DISABLED");
|
||||||
|
packed_cells.insert(cell.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flush_cells();
|
flush_cells();
|
||||||
|
Loading…
Reference in New Issue
Block a user