Skip to content

Commit 119b47a

Browse files
committed
mistral: add 8x40-bit M10K addressing mode
1 parent c5666c4 commit 119b47a

File tree

2 files changed

+33
-16
lines changed

2 files changed

+33
-16
lines changed

mistral/bitstream.cc

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -126,29 +126,31 @@ struct MistralBitgen
126126
// Notes:
127127
// DATA_FLOW_THRU is probably transparent reads.
128128

129+
auto dbits = ci->params.at(id_CFG_DBITS).as_int64();
130+
129131
cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::A_DATA_FLOW_THRU, bi, 1);
130-
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::A_DATA_WIDTH, bi, ci->params.at(id_CFG_DBITS).as_int64());
131-
cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::A_FAST_WRITE, bi, CycloneV::FAST);
132+
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::A_DATA_WIDTH, bi, dbits);
133+
cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::A_FAST_WRITE, bi, dbits == 40 ? CycloneV::SLOW : CycloneV::FAST);
132134
cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::A_OUTPUT_SEL, bi, CycloneV::ASYNC);
133135
cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_SA_WREN_DELAY, bi, 1);
134136
cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_SAEN_DELAY, bi, 2);
135137
cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_WL_DELAY, bi, 2);
136138
cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::A_WR_TIMER_PULSE, bi, 0x0b);
137139

138140
cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::B_DATA_FLOW_THRU, bi, 1);
139-
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::B_DATA_WIDTH, bi, ci->params.at(id_CFG_DBITS).as_int64());
140-
cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::B_FAST_WRITE, bi, CycloneV::FAST);
141+
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::B_DATA_WIDTH, bi, dbits);
142+
cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::B_FAST_WRITE, bi, dbits == 40 ? CycloneV::SLOW : CycloneV::FAST);
141143
cv->bmux_m_set(CycloneV::M10K, pos, CycloneV::B_OUTPUT_SEL, bi, CycloneV::ASYNC);
142144
cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_SA_WREN_DELAY, bi, 1);
143145
cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_SAEN_DELAY, bi, 2);
144146
cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_WL_DELAY, bi, 2);
145147
cv->bmux_r_set(CycloneV::M10K, pos, CycloneV::B_WR_TIMER_PULSE, bi, 0x0b);
146148

147149
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::TOP_CLK_SEL, bi, 1);
148-
cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::TOP_W_INV, bi, 1);
149-
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::TOP_W_SEL, bi, 1);
150-
cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::BOT_CLK_INV, bi, 1);
151-
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::BOT_W_SEL, bi, 1);
150+
cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::TOP_W_INV, bi, dbits != 40);
151+
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::TOP_W_SEL, bi, dbits != 40);
152+
cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::BOT_CLK_INV, bi, dbits != 40);
153+
cv->bmux_n_set(CycloneV::M10K, pos, CycloneV::BOT_W_SEL, bi, dbits != 40);
152154

153155
cv->bmux_b_set(CycloneV::M10K, pos, CycloneV::TRUE_DUAL_PORT, bi, 0);
154156

mistral/pack.cc

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ struct MistralPacker
392392
auto abits = ci->params.at(id_CFG_ABITS).as_int64();
393393
auto dbits = ci->params.at(id_CFG_DBITS).as_int64();
394394
NPNR_ASSERT(abits >= 7 && abits <= 13);
395-
NPNR_ASSERT(dbits == 1 || dbits == 2 || dbits == 5 || dbits == 10 || dbits == 20);
395+
NPNR_ASSERT(dbits == 1 || dbits == 2 || dbits == 5 || dbits == 10 || dbits == 20 || dbits == 40);
396396
NPNR_ASSERT((1 << abits) * dbits <= 10240);
397397

398398
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
402402
// It *does* generate ACLR[01] but leaves them unconnected if unused.
403403

404404
// Enables.
405-
// RDEN[1] and WREN[0] are left unconnected.
406-
ci->pin_data[ctx->id("A1EN")].bel_pins = {ctx->id("WREN[1]")};
405+
// RDEN[1] is left unconnected.
406+
if (dbits == 40)
407+
ci->pin_data[ctx->id("A1EN")].bel_pins = {ctx->id("WREN[0]")};
408+
else
409+
ci->pin_data[ctx->id("A1EN")].bel_pins = {ctx->id("WREN[1]")};
407410
ci->pin_data[ctx->id("B1EN")].bel_pins = {ctx->id("RDEN[0]")};
408411

409412
// Clocks.
@@ -415,7 +418,7 @@ struct MistralPacker
415418

416419
// One could remove the std::max here and the `- bit_offset`s here,
417420
// because they would cancel out, but I think this way is less confusing.
418-
int addr_offset = std::max(12 - std::max(abits, 9L), 0L);
421+
int addr_offset = std::max(12 - std::max(abits, dbits == 40 ? 8L : 9L), 0L);
419422
int bit_offset = (abits == 13);
420423
if (abits == 13) {
421424
ci->pin_data[ctx->id("A1ADDR[0]")].bel_pins = {ctx->id("DATAAIN[4]")};
@@ -462,13 +465,25 @@ struct MistralPacker
462465
continue;
463466
}
464467

465-
for (int bit = 0; bit < dbits; bit++) {
468+
// 40-bit data mode causes some headaches...
469+
bit_offset = dbits == 40 ? 20 : 0;
470+
471+
// Write port
472+
for (int bit = 0; bit < std::min(dbits, 20L); bit++)
466473
for (int offset : offsets)
467474
ci->pin_data[ctx->idf("A1DATA[%d]", bit)].bel_pins.push_back(ctx->idf("DATAAIN[%d]", bit + offset));
468-
}
469475

470-
for (int bit = 0; bit < dbits; bit++)
471-
ci->pin_data[ctx->idf("B1DATA[%d]", bit)].bel_pins = {ctx->idf("DATABOUT[%d]", bit)};
476+
if (dbits == 40)
477+
for (int bit = bit_offset; bit < dbits; bit++)
478+
ci->pin_data[ctx->idf("A1DATA[%d]", bit)].bel_pins.push_back(ctx->idf("DATABIN[%d]", bit - bit_offset));
479+
480+
// Read port
481+
if (dbits == 40)
482+
for (int bit = 0; bit < 20; bit++)
483+
ci->pin_data[ctx->idf("B1DATA[%d]", bit)].bel_pins = {ctx->idf("DATAAOUT[%d]", bit)};
484+
485+
for (int bit = bit_offset; bit < dbits; bit++)
486+
ci->pin_data[ctx->idf("B1DATA[%d]", bit)].bel_pins = {ctx->idf("DATABOUT[%d]", bit - bit_offset)};
472487
}
473488
}
474489

0 commit comments

Comments
 (0)