mistral: add 8x40-bit M10K addressing mode
This commit is contained in:
parent
c5666c47fe
commit
119b47acf3
@ -126,9 +126,11 @@ struct MistralBitgen
|
||||
// Notes:
|
||||
// DATA_FLOW_THRU is probably transparent reads.
|
||||
|
||||
auto dbits = ci->params.at(id_CFG_DBITS).as_int64();
|
||||
|
||||
cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::A_DATA_FLOW_THRU, bi, 1);
|
||||
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::A_DATA_WIDTH, bi, ci->params.at(id_CFG_DBITS).as_int64());
|
||||
cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::A_FAST_WRITE, bi, CycloneV::FAST);
|
||||
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::A_DATA_WIDTH, bi, dbits);
|
||||
cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::A_FAST_WRITE, bi, dbits == 40 ? CycloneV::SLOW : CycloneV::FAST);
|
||||
cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::A_OUTPUT_SEL, bi, CycloneV::ASYNC);
|
||||
cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_SA_WREN_DELAY, bi, 1);
|
||||
cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_SAEN_DELAY, bi, 2);
|
||||
@ -136,8 +138,8 @@ struct MistralBitgen
|
||||
cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_WR_TIMER_PULSE, bi, 0x0b);
|
||||
|
||||
cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::B_DATA_FLOW_THRU, bi, 1);
|
||||
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::B_DATA_WIDTH, bi, ci->params.at(id_CFG_DBITS).as_int64());
|
||||
cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::B_FAST_WRITE, bi, CycloneV::FAST);
|
||||
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::B_DATA_WIDTH, bi, dbits);
|
||||
cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::B_FAST_WRITE, bi, dbits == 40 ? CycloneV::SLOW : CycloneV::FAST);
|
||||
cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::B_OUTPUT_SEL, bi, CycloneV::ASYNC);
|
||||
cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_SA_WREN_DELAY, bi, 1);
|
||||
cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_SAEN_DELAY, bi, 2);
|
||||
@ -145,10 +147,10 @@ struct MistralBitgen
|
||||
cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_WR_TIMER_PULSE, bi, 0x0b);
|
||||
|
||||
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::TOP_CLK_SEL, bi, 1);
|
||||
cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::TOP_W_INV, bi, 1);
|
||||
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::TOP_W_SEL, bi, 1);
|
||||
cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::BOT_CLK_INV, bi, 1);
|
||||
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::BOT_W_SEL, bi, 1);
|
||||
cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::TOP_W_INV, bi, dbits != 40);
|
||||
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::TOP_W_SEL, bi, dbits != 40);
|
||||
cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::BOT_CLK_INV, bi, dbits != 40);
|
||||
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::BOT_W_SEL, bi, dbits != 40);
|
||||
|
||||
cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::TRUE_DUAL_PORT, bi, 0);
|
||||
|
||||
|
@ -392,7 +392,7 @@ struct MistralPacker
|
||||
auto abits = ci->params.at(id_CFG_ABITS).as_int64();
|
||||
auto dbits = ci->params.at(id_CFG_DBITS).as_int64();
|
||||
NPNR_ASSERT(abits >= 7 && abits <= 13);
|
||||
NPNR_ASSERT(dbits == 1 || dbits == 2 || dbits == 5 || dbits == 10 || dbits == 20);
|
||||
NPNR_ASSERT(dbits == 1 || dbits == 2 || dbits == 5 || dbits == 10 || dbits == 20 || dbits == 40);
|
||||
NPNR_ASSERT((1 << abits) * dbits <= 10240);
|
||||
|
||||
log_info("Setting up %ld-bit address, %ld-bit data M10K for %s.\n", abits, dbits, ci->name.str(ctx).c_str());
|
||||
@ -402,8 +402,11 @@ struct MistralPacker
|
||||
// It *does* generate ACLR[01] but leaves them unconnected if unused.
|
||||
|
||||
// Enables.
|
||||
// RDEN[1] and WREN[0] are left unconnected.
|
||||
ci->pin_data[ctx->id("A1EN")].bel_pins = {ctx->id("WREN[1]")};
|
||||
// RDEN[1] is left unconnected.
|
||||
if (dbits == 40)
|
||||
ci->pin_data[ctx->id("A1EN")].bel_pins = {ctx->id("WREN[0]")};
|
||||
else
|
||||
ci->pin_data[ctx->id("A1EN")].bel_pins = {ctx->id("WREN[1]")};
|
||||
ci->pin_data[ctx->id("B1EN")].bel_pins = {ctx->id("RDEN[0]")};
|
||||
|
||||
// Clocks.
|
||||
@ -415,7 +418,7 @@ struct MistralPacker
|
||||
|
||||
// One could remove the std::max here and the `- bit_offset`s here,
|
||||
// because they would cancel out, but I think this way is less confusing.
|
||||
int addr_offset = std::max(12 - std::max(abits, 9L), 0L);
|
||||
int addr_offset = std::max(12 - std::max(abits, dbits == 40 ? 8L : 9L), 0L);
|
||||
int bit_offset = (abits == 13);
|
||||
if (abits == 13) {
|
||||
ci->pin_data[ctx->id("A1ADDR[0]")].bel_pins = {ctx->id("DATAAIN[4]")};
|
||||
@ -462,13 +465,25 @@ struct MistralPacker
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int bit = 0; bit < dbits; bit++) {
|
||||
// 40-bit data mode causes some headaches...
|
||||
bit_offset = dbits == 40 ? 20 : 0;
|
||||
|
||||
// Write port
|
||||
for (int bit = 0; bit < std::min(dbits, 20L); bit++)
|
||||
for (int offset : offsets)
|
||||
ci->pin_data[ctx->idf("A1DATA[%d]", bit)].bel_pins.push_back(ctx->idf("DATAAIN[%d]", bit + offset));
|
||||
}
|
||||
|
||||
for (int bit = 0; bit < dbits; bit++)
|
||||
ci->pin_data[ctx->idf("B1DATA[%d]", bit)].bel_pins = {ctx->idf("DATABOUT[%d]", bit)};
|
||||
if (dbits == 40)
|
||||
for (int bit = bit_offset; bit < dbits; bit++)
|
||||
ci->pin_data[ctx->idf("A1DATA[%d]", bit)].bel_pins.push_back(ctx->idf("DATABIN[%d]", bit - bit_offset));
|
||||
|
||||
// Read port
|
||||
if (dbits == 40)
|
||||
for (int bit = 0; bit < 20; bit++)
|
||||
ci->pin_data[ctx->idf("B1DATA[%d]", bit)].bel_pins = {ctx->idf("DATAAOUT[%d]", bit)};
|
||||
|
||||
for (int bit = bit_offset; bit < dbits; bit++)
|
||||
ci->pin_data[ctx->idf("B1DATA[%d]", bit)].bel_pins = {ctx->idf("DATABOUT[%d]", bit - bit_offset)};
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user