Added read-enable to memory model

This commit is contained in:
Clifford Wolf 2015-09-25 12:23:11 +02:00
parent ec92c89659
commit 924d9d6e86
17 changed files with 157 additions and 76 deletions

View File

@ -1220,6 +1220,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
id2ast->meminfo(mem_width, mem_size, addr_bits);
cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1));
cell->setPort("\\EN", RTLIL::SigSpec(RTLIL::State::Sx, 1));
cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits));
cell->setPort("\\DATA", RTLIL::SigSpec(wire));

View File

@ -692,7 +692,8 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist*
cell->parameters["\\TRANSPARENT"] = false;
cell->parameters["\\ABITS"] = GetSize(addr);
cell->parameters["\\WIDTH"] = GetSize(data);
cell->setPort("\\CLK", RTLIL::State::S0);
cell->setPort("\\CLK", RTLIL::State::Sx);
cell->setPort("\\EN", RTLIL::State::Sx);
cell->setPort("\\ADDR", addr);
cell->setPort("\\DATA", data);
continue;

View File

@ -122,7 +122,7 @@ struct CellTypes
void setup_internals_mem()
{
IdString SET = "\\SET", CLR = "\\CLR", CLK = "\\CLK", ARST = "\\ARST", EN = "\\EN";
IdString Q = "\\Q", D = "\\D", ADDR = "\\ADDR", DATA = "\\DATA";
IdString Q = "\\Q", D = "\\D", ADDR = "\\ADDR", DATA = "\\DATA", RD_EN = "\\RD_EN";
IdString RD_CLK = "\\RD_CLK", RD_ADDR = "\\RD_ADDR", WR_CLK = "\\WR_CLK", WR_EN = "\\WR_EN";
IdString WR_ADDR = "\\WR_ADDR", WR_DATA = "\\WR_DATA", RD_DATA = "\\RD_DATA";
IdString CTRL_IN = "\\CTRL_IN", CTRL_OUT = "\\CTRL_OUT";
@ -135,10 +135,10 @@ struct CellTypes
setup_type("$dlatch", {EN, D}, {Q});
setup_type("$dlatchsr", {EN, SET, CLR, D}, {Q});
setup_type("$memrd", {CLK, ADDR}, {DATA});
setup_type("$memrd", {CLK, EN, ADDR}, {DATA});
setup_type("$memwr", {CLK, EN, ADDR, DATA}, pool<RTLIL::IdString>());
setup_type("$meminit", {ADDR, DATA}, pool<RTLIL::IdString>());
setup_type("$mem", {RD_CLK, RD_ADDR, WR_CLK, WR_EN, WR_ADDR, WR_DATA}, {RD_DATA});
setup_type("$mem", {RD_CLK, RD_EN, RD_ADDR, WR_CLK, WR_EN, WR_ADDR, WR_DATA}, {RD_DATA});
setup_type("$fsm", {CLK, ARST, CTRL_IN}, {CTRL_OUT});
}

View File

@ -947,6 +947,7 @@ namespace {
param_bool("\\CLK_POLARITY");
param_bool("\\TRANSPARENT");
port("\\CLK", 1);
port("\\EN", 1);
port("\\ADDR", param("\\ABITS"));
port("\\DATA", param("\\WIDTH"));
check_expected();
@ -986,6 +987,7 @@ namespace {
param_bits("\\WR_CLK_ENABLE", std::max(1, param("\\WR_PORTS")));
param_bits("\\WR_CLK_POLARITY", std::max(1, param("\\WR_PORTS")));
port("\\RD_CLK", param("\\RD_PORTS"));
port("\\RD_EN", param("\\RD_PORTS"));
port("\\RD_ADDR", param("\\RD_PORTS") * param("\\ABITS"));
port("\\RD_DATA", param("\\RD_PORTS") * param("\\WIDTH"));
port("\\WR_CLK", param("\\WR_PORTS"));

View File

@ -220,8 +220,9 @@ cell is created. Having individual cells for read and write ports has the advant
consolidated using resource sharing passes. In some cases this drastically reduces the number of required
ports on the memory cell.
The {\tt \$memrd} cells have a clock input \B{CLK}, an address input \B{ADDR} and a data output
\B{DATA}. They also have the following parameters:
The {\tt \$memrd} cells have a clock input \B{CLK}, an enable input \B{EN}, an
address input \B{ADDR}, and a data output \B{DATA}. They also have the
following parameters:
\begin{itemize}
\item \B{MEMID} \\
@ -322,6 +323,9 @@ The {\tt \$mem} cell has the following ports:
\item \B{RD\_CLK} \\
This input is \B{RD\_PORTS} bits wide, containing all clock signals for the read ports.
\item \B{RD\_EN} \\
This input is \B{RD\_PORTS} bits wide, containing all enable signals for the read ports.
\item \B{RD\_ADDR} \\
This input is \B{RD\_PORTS}*\B{ABITS} bits wide, containing all address signals for the read ports.

View File

@ -112,15 +112,15 @@ struct rules_t
if (ports[i] != other.ports[i])
log_error("Bram %s variants %d and %d have different number of %c-ports.\n", log_id(name), variant, other.variant, 'A'+i);
if (wrmode[i] != other.wrmode[i])
variant_params[stringf("\\CFG_WRMODE_%c", 'A' + i)] = wrmode[1];
variant_params[stringf("\\CFG_WRMODE_%c", 'A' + i)] = wrmode[i];
if (enable[i] != other.enable[i])
variant_params[stringf("\\CFG_ENABLE_%c", 'A' + i)] = enable[1];
variant_params[stringf("\\CFG_ENABLE_%c", 'A' + i)] = enable[i];
if (transp[i] != other.transp[i])
variant_params[stringf("\\CFG_TRANSP_%c", 'A' + i)] = transp[1];
variant_params[stringf("\\CFG_TRANSP_%c", 'A' + i)] = transp[i];
if (clocks[i] != other.clocks[i])
variant_params[stringf("\\CFG_CLOCKS_%c", 'A' + i)] = clocks[1];
variant_params[stringf("\\CFG_CLOCKS_%c", 'A' + i)] = clocks[i];
if (clkpol[i] != other.clkpol[i])
variant_params[stringf("\\CFG_CLKPOL_%c", 'A' + i)] = clkpol[1];
variant_params[stringf("\\CFG_CLKPOL_%c", 'A' + i)] = clkpol[i];
}
}
};
@ -429,6 +429,7 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
rd_clkpol.extend_u0(rd_ports);
rd_transp.extend_u0(rd_ports);
SigSpec rd_en = cell->getPort("\\RD_EN");
SigSpec rd_clk = cell->getPort("\\RD_CLK");
SigSpec rd_data = cell->getPort("\\RD_DATA");
SigSpec rd_addr = cell->getPort("\\RD_ADDR");
@ -688,6 +689,10 @@ grow_read_ports:;
log(" Bram port %c%d.%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
goto skip_bram_rport;
}
if (rd_en[cell_port_i] != State::S1 && pi.enable == 0) {
log(" Bram port %c%d.%d has no read enable input.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
goto skip_bram_rport;
}
skip_bram_rport_clkcheck:
if (read_transp.count(pi.transp) && read_transp.at(pi.transp) != transp) {
if (match.make_transp && wr_ports <= 1) {
@ -713,6 +718,7 @@ grow_read_ports:;
clock_polarities[pi.clkpol] = clkdom.second;
read_transp[pi.transp] = transp;
pi.sig_clock = clkdom.first;
pi.sig_en = rd_en[cell_port_i];
pi.effective_clkpol = clkdom.second;
}
@ -886,6 +892,8 @@ grow_read_ports:;
if (pi.make_outreg) {
SigSpec bram_dout_q = module->addWire(NEW_ID, bram.dbits);
if (!pi.sig_en.empty())
bram_dout = module->Mux(NEW_ID, bram_dout_q, bram_dout, pi.sig_en);
module->addDff(NEW_ID, pi.sig_clock, bram_dout, bram_dout_q, pi.effective_clkpol);
bram_dout = bram_dout_q;
}
@ -1126,7 +1134,7 @@ struct MemoryBramPass : public Pass {
log(" groups 2 # number of port groups\n");
log(" ports 1 1 # number of ports in each group\n");
log(" wrmode 1 0 # set to '1' if this groups is write ports\n");
log(" enable 4 0 # number of enable bits (for write ports)\n");
log(" enable 4 1 # number of enable bits\n");
log(" transp 0 2 # transparent (for read ports)\n");
log(" clocks 1 2 # clock configuration\n");
log(" clkpol 2 2 # clock polarity configuration\n");

View File

@ -57,6 +57,7 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)
SigSpec sig_rd_transparent;
SigSpec sig_rd_addr;
SigSpec sig_rd_data;
SigSpec sig_rd_en;
std::vector<Cell*> memcells;
@ -139,22 +140,27 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)
SigSpec transparent = SigSpec(cell->parameters["\\TRANSPARENT"]);
SigSpec addr = sigmap(cell->getPort("\\ADDR"));
SigSpec data = sigmap(cell->getPort("\\DATA"));
SigSpec en = sigmap(cell->getPort("\\EN"));
clk.extend_u0(1, false);
clk_enable.extend_u0(1, false);
clk_polarity.extend_u0(1, false);
transparent.extend_u0(1, false);
addr.extend_u0(addr_bits, false);
data.extend_u0(memory->width, false);
if (!en.is_fully_zero())
{
clk.extend_u0(1, false);
clk_enable.extend_u0(1, false);
clk_polarity.extend_u0(1, false);
transparent.extend_u0(1, false);
addr.extend_u0(addr_bits, false);
data.extend_u0(memory->width, false);
sig_rd_clk.append(clk);
sig_rd_clk_enable.append(clk_enable);
sig_rd_clk_polarity.append(clk_polarity);
sig_rd_transparent.append(transparent);
sig_rd_addr.append(addr);
sig_rd_data.append(data);
sig_rd_clk.append(clk);
sig_rd_clk_enable.append(clk_enable);
sig_rd_clk_polarity.append(clk_polarity);
sig_rd_transparent.append(transparent);
sig_rd_addr.append(addr);
sig_rd_data.append(data);
sig_rd_en.append(en);
rd_ports++;
rd_ports++;
}
continue;
}
}
@ -203,6 +209,7 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)
mem->setPort("\\RD_CLK", sig_rd_clk);
mem->setPort("\\RD_ADDR", sig_rd_addr);
mem->setPort("\\RD_DATA", sig_rd_data);
mem->setPort("\\RD_EN", sig_rd_en);
for (auto c : memcells)
module->remove(c);

View File

@ -31,6 +31,7 @@ struct MemoryDffWorker
vector<Cell*> dff_cells;
dict<SigBit, SigBit> invbits;
dict<SigBit, int> sigbit_users_count;
dict<SigSpec, Cell*> mux_cells_a, mux_cells_b;
MemoryDffWorker(Module *module) : module(module), sigmap(module) { }
@ -150,16 +151,44 @@ struct MemoryDffWorker
if (sigbit_users_count[bit] > 1)
goto skip_ff_after_read_merging;
if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx))
if (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data))
{
disconnect_dff(sig_data);
cell->setPort("\\CLK", clk_data);
cell->setPort("\\DATA", sig_data);
cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1);
cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity);
cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0);
log("merged data $dff to cell.\n");
return;
bool enable_invert = mux_cells_a.count(sig_data);
Cell *mux = enable_invert ? mux_cells_a.at(sig_data) : mux_cells_b.at(sig_data);
SigSpec check_q = sigmap(mux->getPort(enable_invert ? "\\B" : "\\A"));
sig_data = sigmap(mux->getPort("\\Y"));
for (auto bit : sig_data)
if (sigbit_users_count[bit] > 1)
goto skip_ff_after_read_merging;
if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx) && sig_data == check_q)
{
disconnect_dff(sig_data);
cell->setPort("\\CLK", clk_data);
cell->setPort("\\EN", enable_invert ? module->LogicNot(NEW_ID, mux->getPort("\\S")) : mux->getPort("\\S"));
cell->setPort("\\DATA", sig_data);
cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1);
cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity);
cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0);
log("merged data $dff with rd enable to cell.\n");
return;
}
}
else
{
if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx))
{
disconnect_dff(sig_data);
cell->setPort("\\CLK", clk_data);
cell->setPort("\\EN", State::S1);
cell->setPort("\\DATA", sig_data);
cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1);
cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity);
cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0);
log("merged data $dff to cell.\n");
return;
}
}
skip_ff_after_read_merging:;
@ -169,6 +198,7 @@ struct MemoryDffWorker
clk_addr != RTLIL::SigSpec(RTLIL::State::Sx))
{
cell->setPort("\\CLK", clk_addr);
cell->setPort("\\EN", State::S1);
cell->setPort("\\ADDR", sig_addr);
cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1);
cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity);
@ -191,6 +221,10 @@ struct MemoryDffWorker
for (auto cell : module->cells()) {
if (cell->type == "$dff")
dff_cells.push_back(cell);
if (cell->type == "$mux") {
mux_cells_a[sigmap(cell->getPort("\\A"))] = cell;
mux_cells_b[sigmap(cell->getPort("\\B"))] = cell;
}
if (cell->type == "$not" || cell->type == "$_NOT_" || (cell->type == "$logic_not" && GetSize(cell->getPort("\\A")) == 1)) {
SigSpec sig_a = cell->getPort("\\A");
SigSpec sig_y = cell->getPort("\\Y");

View File

@ -200,34 +200,43 @@ struct MemoryMapWorker
if (cell->parameters["\\RD_CLK_ENABLE"].bits[i] == RTLIL::State::S1)
{
RTLIL::Cell *dff_cell = nullptr;
if (cell->parameters["\\RD_TRANSPARENT"].bits[i] == RTLIL::State::S1)
{
RTLIL::Cell *c = module->addCell(genid(cell->name, "$rdreg", i), "$dff");
c->parameters["\\WIDTH"] = RTLIL::Const(mem_abits);
c->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]);
c->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1));
c->setPort("\\D", rd_addr);
dff_cell = module->addCell(genid(cell->name, "$rdreg", i), "$dff");
dff_cell->parameters["\\WIDTH"] = RTLIL::Const(mem_abits);
dff_cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]);
dff_cell->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1));
dff_cell->setPort("\\D", rd_addr);
count_dff++;
RTLIL::Wire *w = module->addWire(genid(cell->name, "$rdreg", i, "$q"), mem_abits);
c->setPort("\\Q", RTLIL::SigSpec(w));
dff_cell->setPort("\\Q", RTLIL::SigSpec(w));
rd_addr = RTLIL::SigSpec(w);
}
else
{
RTLIL::Cell *c = module->addCell(genid(cell->name, "$rdreg", i), "$dff");
c->parameters["\\WIDTH"] = cell->parameters["\\WIDTH"];
c->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]);
c->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1));
c->setPort("\\Q", rd_signals.back());
dff_cell = module->addCell(genid(cell->name, "$rdreg", i), "$dff");
dff_cell->parameters["\\WIDTH"] = cell->parameters["\\WIDTH"];
dff_cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]);
dff_cell->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1));
dff_cell->setPort("\\Q", rd_signals.back());
count_dff++;
RTLIL::Wire *w = module->addWire(genid(cell->name, "$rdreg", i, "$d"), mem_width);
rd_signals.clear();
rd_signals.push_back(RTLIL::SigSpec(w));
c->setPort("\\D", rd_signals.back());
dff_cell->setPort("\\D", rd_signals.back());
}
SigBit en_bit = cell->getPort("\\RD_EN").extract(i);
if (en_bit != State::S1) {
SigSpec new_d = module->Mux(genid(cell->name, "$rdenmux", i),
dff_cell->getPort("\\Q"), dff_cell->getPort("\\D"), en_bit);
dff_cell->setPort("\\D", new_d);
}
}

View File

@ -57,6 +57,7 @@ void handle_memory(RTLIL::Module *module, RTLIL::Cell *memory)
cell->parameters["\\CLK_POLARITY"] = RTLIL::SigSpec(memory->parameters.at("\\RD_CLK_POLARITY")).extract(i, 1).as_const();
cell->parameters["\\TRANSPARENT"] = RTLIL::SigSpec(memory->parameters.at("\\RD_TRANSPARENT")).extract(i, 1).as_const();
cell->setPort("\\CLK", memory->getPort("\\RD_CLK").extract(i, 1));
cell->setPort("\\EN", memory->getPort("\\RD_EN").extract(i, 1));
cell->setPort("\\ADDR", memory->getPort("\\RD_ADDR").extract(i*abits, abits));
cell->setPort("\\DATA", memory->getPort("\\RD_DATA").extract(i*mem->width, mem->width));
}

View File

@ -1494,7 +1494,7 @@ endmodule
// --------------------------------------------------------
`ifndef SIMLIB_NOMEM
module \$memrd (CLK, ADDR, DATA);
module \$memrd (CLK, EN, ADDR, DATA);
parameter MEMID = "";
parameter ABITS = 8;
@ -1504,7 +1504,7 @@ parameter CLK_ENABLE = 0;
parameter CLK_POLARITY = 0;
parameter TRANSPARENT = 0;
input CLK;
input CLK, EN;
input [ABITS-1:0] ADDR;
output [WIDTH-1:0] DATA;
@ -1568,7 +1568,7 @@ endmodule
// --------------------------------------------------------
module \$mem (RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
module \$mem (RD_CLK, RD_EN, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
parameter MEMID = "";
parameter signed SIZE = 4;
@ -1587,6 +1587,7 @@ parameter WR_CLK_ENABLE = 1'b1;
parameter WR_CLK_POLARITY = 1'b1;
input [RD_PORTS-1:0] RD_CLK;
input [RD_PORTS-1:0] RD_EN;
input [RD_PORTS*ABITS-1:0] RD_ADDR;
output reg [RD_PORTS*WIDTH-1:0] RD_DATA;
@ -1626,7 +1627,7 @@ always @(RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA) begin
#`SIMLIB_MEMDELAY;
`endif
for (i = 0; i < RD_PORTS; i = i+1) begin
if ((!RD_TRANSPARENT[i] && RD_CLK_ENABLE[i]) && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i])) begin
if (!RD_TRANSPARENT[i] && RD_CLK_ENABLE[i] && RD_EN[i] && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i])) begin
// $display("Read from %s: addr=%b data=%b", MEMID, RD_ADDR[i*ABITS +: ABITS], memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]);
RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET];
end

View File

@ -5,7 +5,7 @@ bram $__ICE40_RAM4K_M0
groups 2
ports 1 1
wrmode 0 1
enable 0 16
enable 1 16
transp 0 0
clocks 2 3
clkpol 2 3
@ -22,7 +22,7 @@ bram $__ICE40_RAM4K_M123
groups 2
ports 1 1
wrmode 0 1
enable 0 1
enable 1 1
transp 0 0
clocks 2 3
clkpol 2 3

View File

@ -168,7 +168,7 @@ module \$__ICE40_RAM4K (
endmodule
module \$__ICE40_RAM4K_M0 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
module \$__ICE40_RAM4K_M0 (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter [0:0] CLKPOL2 = 1;
parameter [0:0] CLKPOL3 = 1;
@ -179,6 +179,7 @@ module \$__ICE40_RAM4K_M0 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
input [7:0] A1ADDR;
output [15:0] A1DATA;
input A1EN;
input [7:0] B1ADDR;
input [15:0] B1DATA;
@ -213,7 +214,7 @@ module \$__ICE40_RAM4K_M0 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
.RADDR(A1ADDR_11),
.RCLK(CLK2),
.RCLKE(1'b1),
.RE(1'b1),
.RE(A1EN),
.WDATA(B1DATA),
.WADDR(B1ADDR_11),
.MASK(~B1EN),
@ -223,7 +224,7 @@ module \$__ICE40_RAM4K_M0 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
);
endmodule
module \$__ICE40_RAM4K_M123 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
module \$__ICE40_RAM4K_M123 (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter CFG_ABITS = 9;
parameter CFG_DBITS = 8;
@ -242,6 +243,7 @@ module \$__ICE40_RAM4K_M123 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
input [CFG_ABITS-1:0] A1ADDR;
output [CFG_DBITS-1:0] A1DATA;
input A1EN;
input [CFG_ABITS-1:0] B1ADDR;
input [CFG_DBITS-1:0] B1DATA;
@ -298,7 +300,7 @@ module \$__ICE40_RAM4K_M123 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
.RADDR(A1ADDR_11),
.RCLK(CLK2),
.RCLKE(1'b1),
.RE(1'b1),
.RE(A1EN),
.WDATA(B1DATA_16),
.WADDR(B1ADDR_11),
.WCLK(CLK3),

View File

@ -6,7 +6,7 @@ bram $__XILINX_RAMB36_SDP
groups 2
ports 1 1
wrmode 0 1
enable 0 8
enable 1 8
transp 0 0
clocks 2 3
clkpol 2 3
@ -19,7 +19,7 @@ bram $__XILINX_RAMB18_SDP
groups 2
ports 1 1
wrmode 0 1
enable 0 4
enable 1 4
transp 0 0
clocks 2 3
clkpol 2 3
@ -42,9 +42,9 @@ bram $__XILINX_RAMB36_TDP
groups 2
ports 1 1
wrmode 0 1
enable 0 4 @a10d36
enable 0 2 @a11d18
enable 0 1 @a12d9 @a13d4 @a14d2 @a15d1
enable 1 4 @a10d36
enable 1 2 @a11d18
enable 1 1 @a12d9 @a13d4 @a14d2 @a15d1
transp 0 0
clocks 2 3
clkpol 2 3
@ -65,8 +65,8 @@ bram $__XILINX_RAMB18_TDP
groups 2
ports 1 1
wrmode 0 1
enable 0 2 @a10d18
enable 0 1 @a11d9 @a12d4 @a13d2 @a14d1
enable 1 2 @a10d18
enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1
transp 0 0
clocks 2 3
clkpol 2 3

View File

@ -1,4 +1,4 @@
module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter CLKPOL2 = 1;
parameter CLKPOL3 = 1;
parameter [36863:0] INIT = 36864'bx;
@ -8,6 +8,7 @@ module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
input [8:0] A1ADDR;
output [71:0] A1DATA;
input A1EN;
input [8:0] B1ADDR;
input [71:0] B1DATA;
@ -47,7 +48,7 @@ module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
.ADDRARDADDR(A1ADDR_16),
.CLKARDCLK(CLK2),
.ENARDEN(|1),
.ENARDEN(A1EN),
.REGCEAREGCE(|1),
.RSTRAMARSTRAM(|0),
.RSTREGARSTREG(|0),
@ -65,7 +66,7 @@ endmodule
// ------------------------------------------------------------------------
module \$__XILINX_RAMB18_SDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
module \$__XILINX_RAMB18_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter CLKPOL2 = 1;
parameter CLKPOL3 = 1;
parameter [18431:0] INIT = 18432'bx;
@ -75,6 +76,7 @@ module \$__XILINX_RAMB18_SDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
input [8:0] A1ADDR;
output [35:0] A1DATA;
input A1EN;
input [8:0] B1ADDR;
input [35:0] B1DATA;
@ -111,7 +113,7 @@ module \$__XILINX_RAMB18_SDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
.ADDRARDADDR(A1ADDR_14),
.CLKARDCLK(CLK2),
.ENARDEN(|1),
.ENARDEN(A1EN),
.REGCEAREGCE(|1),
.RSTRAMARSTRAM(|0),
.RSTREGARSTREG(|0),
@ -129,7 +131,7 @@ endmodule
// ------------------------------------------------------------------------
module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter CFG_ABITS = 10;
parameter CFG_DBITS = 36;
parameter CFG_ENABLE_B = 4;
@ -143,6 +145,7 @@ module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
input [CFG_ABITS-1:0] A1ADDR;
output [CFG_DBITS-1:0] A1DATA;
input A1EN;
input [CFG_ABITS-1:0] B1ADDR;
input [CFG_DBITS-1:0] B1DATA;
@ -181,7 +184,7 @@ module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
.DOPADOP(DOP[3:0]),
.ADDRARDADDR(A1ADDR_16),
.CLKARDCLK(CLK2),
.ENARDEN(|1),
.ENARDEN(A1EN),
.REGCEAREGCE(|1),
.RSTRAMARSTRAM(|0),
.RSTREGARSTREG(|0),
@ -219,7 +222,7 @@ module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
.DOPADOP(DOP[3:0]),
.ADDRARDADDR(A1ADDR_16),
.CLKARDCLK(CLK2),
.ENARDEN(|1),
.ENARDEN(A1EN),
.REGCEAREGCE(|1),
.RSTRAMARSTRAM(|0),
.RSTREGARSTREG(|0),
@ -242,7 +245,7 @@ endmodule
// ------------------------------------------------------------------------
module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter CFG_ABITS = 10;
parameter CFG_DBITS = 18;
parameter CFG_ENABLE_B = 2;
@ -256,6 +259,7 @@ module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
input [CFG_ABITS-1:0] A1ADDR;
output [CFG_DBITS-1:0] A1DATA;
input A1EN;
input [CFG_ABITS-1:0] B1ADDR;
input [CFG_DBITS-1:0] B1DATA;
@ -294,7 +298,7 @@ module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
.DOPADOP(DOP),
.ADDRARDADDR(A1ADDR_14),
.CLKARDCLK(CLK2),
.ENARDEN(|1),
.ENARDEN(A1EN),
.REGCEAREGCE(|1),
.RSTRAMARSTRAM(|0),
.RSTREGARSTREG(|0),
@ -332,7 +336,7 @@ module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
.DOPADOP(DOP),
.ADDRARDADDR(A1ADDR_14),
.CLKARDCLK(CLK2),
.ENARDEN(|1),
.ENARDEN(A1EN),
.REGCEAREGCE(|1),
.RSTRAMARSTRAM(|0),
.RSTREGARSTREG(|0),

View File

@ -79,7 +79,6 @@ struct SynthXilinxPass : public Pass {
log("\n");
log(" coarse:\n");
log(" synth -run coarse\n");
log(" dff2dffe\n");
log("\n");
log(" bram:\n");
log(" memory_bram -rules +/xilinx/brams.txt\n");
@ -92,6 +91,7 @@ struct SynthXilinxPass : public Pass {
log(" fine:\n");
log(" opt -fast -full\n");
log(" memory_map\n");
log(" dff2dffe\n");
log(" opt -full\n");
log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n");
log(" opt -fast\n");
@ -178,7 +178,6 @@ struct SynthXilinxPass : public Pass {
if (check_label(active, run_from, run_to, "coarse"))
{
Pass::call(design, "synth -run coarse");
Pass::call(design, "dff2dffe");
}
if (check_label(active, run_from, run_to, "bram"))
@ -197,6 +196,7 @@ struct SynthXilinxPass : public Pass {
{
Pass::call(design, "opt -fast -full");
Pass::call(design, "memory_map");
Pass::call(design, "dff2dffe");
Pass::call(design, "opt -full");
Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v");
Pass::call(design, "opt -fast");

View File

@ -1,5 +1,5 @@
module \$mem (RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
module \$mem (RD_CLK, RD_EN, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
parameter MEMID = "";
parameter SIZE = 256;
parameter OFFSET = 0;
@ -17,6 +17,7 @@ module \$mem (RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
parameter WR_CLK_POLARITY = 1'b1;
input [RD_PORTS-1:0] RD_CLK;
input [RD_PORTS-1:0] RD_EN;
input [RD_PORTS*ABITS-1:0] RD_ADDR;
output reg [RD_PORTS*WIDTH-1:0] RD_DATA;
@ -30,6 +31,8 @@ module \$mem (RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
parameter _TECHMAP_CONNMAP_RD_CLK_ = 0;
parameter _TECHMAP_CONNMAP_WR_CLK_ = 0;
parameter _TECHMAP_CONSTVAL_RD_EN_ = 0;
parameter _TECHMAP_BITS_CONNMAP_ = 0;
parameter _TECHMAP_CONNMAP_WR_EN_ = 0;
@ -46,6 +49,10 @@ module \$mem (RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
if (RD_PORTS > 1 || WR_PORTS > 1)
_TECHMAP_FAIL_ <= 1;
// read enable must be constant high
if (_TECHMAP_CONSTVAL_RD_EN_[0] !== 1'b1)
_TECHMAP_FAIL_ <= 1;
// we expect positive read clock and non-transparent reads
if (RD_TRANSPARENT || !RD_CLK_ENABLE || !RD_CLK_POLARITY)
_TECHMAP_FAIL_ <= 1;