mirror of https://github.com/YosysHQ/yosys.git
add qlf_k6n10f architecture + bram inference
(Copied from QuickLogic Yosys plugin repo)
This commit is contained in:
parent
98769010af
commit
48c1fdc33d
|
@ -1,4 +1,6 @@
|
||||||
OBJS += techlibs/quicklogic/synth_quicklogic.o
|
OBJS += techlibs/quicklogic/synth_quicklogic.o
|
||||||
|
OBJS += techlibs/quicklogic/ql-bram-merge.o
|
||||||
|
OBJS += techlibs/quicklogic/quicklogic_eqn.o
|
||||||
|
|
||||||
$(eval $(call add_share_file,share/quicklogic/common,techlibs/quicklogic/common/cells_sim.v))
|
$(eval $(call add_share_file,share/quicklogic/common,techlibs/quicklogic/common/cells_sim.v))
|
||||||
|
|
||||||
|
@ -10,3 +12,13 @@ $(eval $(call add_share_file,share/quicklogic/pp3,techlibs/quicklogic/pp3/cells_
|
||||||
$(eval $(call add_share_file,share/quicklogic/pp3,techlibs/quicklogic/pp3/abc9_model.v))
|
$(eval $(call add_share_file,share/quicklogic/pp3,techlibs/quicklogic/pp3/abc9_model.v))
|
||||||
$(eval $(call add_share_file,share/quicklogic/pp3,techlibs/quicklogic/pp3/abc9_map.v))
|
$(eval $(call add_share_file,share/quicklogic/pp3,techlibs/quicklogic/pp3/abc9_map.v))
|
||||||
$(eval $(call add_share_file,share/quicklogic/pp3,techlibs/quicklogic/pp3/abc9_unmap.v))
|
$(eval $(call add_share_file,share/quicklogic/pp3,techlibs/quicklogic/pp3/abc9_unmap.v))
|
||||||
|
|
||||||
|
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/arith_map.v))
|
||||||
|
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/libmap_brams.txt))
|
||||||
|
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/libmap_brams_map.v))
|
||||||
|
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/brams_map.v))
|
||||||
|
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/brams_final_map.v))
|
||||||
|
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/brams_sim.v))
|
||||||
|
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/bram_types_sim.v))
|
||||||
|
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/cells_sim.v))
|
||||||
|
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/ffs_map.v))
|
|
@ -0,0 +1,216 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 N. Engelhardt <nak@yosyshq.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kernel/log.h"
|
||||||
|
#include "kernel/register.h"
|
||||||
|
#include "kernel/rtlil.h"
|
||||||
|
#include "kernel/sigtools.h"
|
||||||
|
|
||||||
|
USING_YOSYS_NAMESPACE
|
||||||
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct QlBramMergeWorker {
|
||||||
|
|
||||||
|
const RTLIL::IdString split_cell_type = ID($__QLF_TDP36K);
|
||||||
|
const RTLIL::IdString merged_cell_type = ID($__QLF_TDP36K_MERGED);
|
||||||
|
|
||||||
|
// can be used to record parameter values that have to match on both sides
|
||||||
|
typedef dict<RTLIL::IdString, RTLIL::Const> MergeableGroupKeyType;
|
||||||
|
|
||||||
|
RTLIL::Module *module;
|
||||||
|
dict<MergeableGroupKeyType, pool<RTLIL::Cell*>> mergeable_groups;
|
||||||
|
|
||||||
|
QlBramMergeWorker(RTLIL::Module* module) : module(module)
|
||||||
|
{
|
||||||
|
for (RTLIL::Cell* cell : module->selected_cells())
|
||||||
|
{
|
||||||
|
if(cell->type != split_cell_type) continue;
|
||||||
|
if(!cell->hasParam(ID(OPTION_SPLIT))) continue;
|
||||||
|
if(cell->getParam(ID(OPTION_SPLIT)) != RTLIL::Const(1, 32)) continue;
|
||||||
|
mergeable_groups[get_key(cell)].insert(cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static MergeableGroupKeyType get_key(RTLIL::Cell* cell)
|
||||||
|
{
|
||||||
|
MergeableGroupKeyType key;
|
||||||
|
// For now, there are no restrictions on which cells can be merged
|
||||||
|
(void) cell;
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dict<RTLIL::IdString, RTLIL::IdString>& param_map(bool second)
|
||||||
|
{
|
||||||
|
static const dict<RTLIL::IdString, RTLIL::IdString> bram1_map = {
|
||||||
|
{ ID(INIT), ID(INIT1) },
|
||||||
|
{ ID(PORT_A_WIDTH), ID(PORT_A1_WIDTH) },
|
||||||
|
{ ID(PORT_B_WIDTH), ID(PORT_B1_WIDTH) },
|
||||||
|
{ ID(PORT_A_WR_BE_WIDTH), ID(PORT_A1_WR_BE_WIDTH) },
|
||||||
|
{ ID(PORT_B_WR_BE_WIDTH), ID(PORT_B1_WR_BE_WIDTH) }
|
||||||
|
};
|
||||||
|
static const dict<RTLIL::IdString, RTLIL::IdString> bram2_map = {
|
||||||
|
{ ID(INIT), ID(INIT2) },
|
||||||
|
{ ID(PORT_A_WIDTH), ID(PORT_A2_WIDTH) },
|
||||||
|
{ ID(PORT_B_WIDTH), ID(PORT_B2_WIDTH) },
|
||||||
|
{ ID(PORT_A_WR_BE_WIDTH), ID(PORT_A2_WR_BE_WIDTH) },
|
||||||
|
{ ID(PORT_B_WR_BE_WIDTH), ID(PORT_B2_WR_BE_WIDTH) }
|
||||||
|
};
|
||||||
|
|
||||||
|
if(second)
|
||||||
|
return bram2_map;
|
||||||
|
else
|
||||||
|
return bram1_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dict<RTLIL::IdString, RTLIL::IdString>& port_map(bool second)
|
||||||
|
{
|
||||||
|
static const dict<RTLIL::IdString, RTLIL::IdString> bram1_map = {
|
||||||
|
{ ID(PORT_A_CLK), ID(PORT_A1_CLK) },
|
||||||
|
{ ID(PORT_B_CLK), ID(PORT_B1_CLK) },
|
||||||
|
{ ID(PORT_A_CLK_EN), ID(PORT_A1_CLK_EN) },
|
||||||
|
{ ID(PORT_B_CLK_EN), ID(PORT_B1_CLK_EN) },
|
||||||
|
{ ID(PORT_A_ADDR), ID(PORT_A1_ADDR) },
|
||||||
|
{ ID(PORT_B_ADDR), ID(PORT_B1_ADDR) },
|
||||||
|
{ ID(PORT_A_WR_DATA), ID(PORT_A1_WR_DATA) },
|
||||||
|
{ ID(PORT_B_WR_DATA), ID(PORT_B1_WR_DATA) },
|
||||||
|
{ ID(PORT_A_WR_EN), ID(PORT_A1_WR_EN) },
|
||||||
|
{ ID(PORT_B_WR_EN), ID(PORT_B1_WR_EN) },
|
||||||
|
{ ID(PORT_A_WR_BE), ID(PORT_A1_WR_BE) },
|
||||||
|
{ ID(PORT_B_WR_BE), ID(PORT_B1_WR_BE) },
|
||||||
|
{ ID(PORT_A_RD_DATA), ID(PORT_A1_RD_DATA) },
|
||||||
|
{ ID(PORT_B_RD_DATA), ID(PORT_B1_RD_DATA) }
|
||||||
|
};
|
||||||
|
static const dict<RTLIL::IdString, RTLIL::IdString> bram2_map = {
|
||||||
|
{ ID(PORT_A_CLK), ID(PORT_A2_CLK) },
|
||||||
|
{ ID(PORT_B_CLK), ID(PORT_B2_CLK) },
|
||||||
|
{ ID(PORT_A_CLK_EN), ID(PORT_A2_CLK_EN) },
|
||||||
|
{ ID(PORT_B_CLK_EN), ID(PORT_B2_CLK_EN) },
|
||||||
|
{ ID(PORT_A_ADDR), ID(PORT_A2_ADDR) },
|
||||||
|
{ ID(PORT_B_ADDR), ID(PORT_B2_ADDR) },
|
||||||
|
{ ID(PORT_A_WR_DATA), ID(PORT_A2_WR_DATA) },
|
||||||
|
{ ID(PORT_B_WR_DATA), ID(PORT_B2_WR_DATA) },
|
||||||
|
{ ID(PORT_A_WR_EN), ID(PORT_A2_WR_EN) },
|
||||||
|
{ ID(PORT_B_WR_EN), ID(PORT_B2_WR_EN) },
|
||||||
|
{ ID(PORT_A_WR_BE), ID(PORT_A2_WR_BE) },
|
||||||
|
{ ID(PORT_B_WR_BE), ID(PORT_B2_WR_BE) },
|
||||||
|
{ ID(PORT_A_RD_DATA), ID(PORT_A2_RD_DATA) },
|
||||||
|
{ ID(PORT_B_RD_DATA), ID(PORT_B2_RD_DATA) }
|
||||||
|
};
|
||||||
|
|
||||||
|
if(second)
|
||||||
|
return bram2_map;
|
||||||
|
else
|
||||||
|
return bram1_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
void merge_brams(RTLIL::Cell* bram1, RTLIL::Cell* bram2)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Create the new cell
|
||||||
|
RTLIL::Cell* merged = module->addCell(NEW_ID, merged_cell_type);
|
||||||
|
log_debug("Merging split BRAM cells %s and %s -> %s\n", log_id(bram1->name), log_id(bram2->name), log_id(merged->name));
|
||||||
|
|
||||||
|
for (auto &it : param_map(false))
|
||||||
|
{
|
||||||
|
if(bram1->hasParam(it.first))
|
||||||
|
merged->setParam(it.second, bram1->getParam(it.first));
|
||||||
|
}
|
||||||
|
for (auto &it : param_map(true))
|
||||||
|
{
|
||||||
|
if(bram2->hasParam(it.first))
|
||||||
|
merged->setParam(it.second, bram2->getParam(it.first));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &it : port_map(false))
|
||||||
|
{
|
||||||
|
if (bram1->hasPort(it.first))
|
||||||
|
merged->setPort(it.second, bram1->getPort(it.first));
|
||||||
|
else
|
||||||
|
log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram1->name));
|
||||||
|
}
|
||||||
|
for (auto &it : port_map(true))
|
||||||
|
{
|
||||||
|
if (bram2->hasPort(it.first))
|
||||||
|
merged->setPort(it.second, bram2->getPort(it.first));
|
||||||
|
else
|
||||||
|
log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram2->name));
|
||||||
|
}
|
||||||
|
merged->attributes = bram1->attributes;
|
||||||
|
for (auto attr: bram2->attributes)
|
||||||
|
if (!merged->has_attribute(attr.first))
|
||||||
|
merged->attributes.insert(attr);
|
||||||
|
|
||||||
|
// Remove the old cells
|
||||||
|
module->remove(bram1);
|
||||||
|
module->remove(bram2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void merge_bram_groups()
|
||||||
|
{
|
||||||
|
for (auto &it : mergeable_groups)
|
||||||
|
{
|
||||||
|
while (it.second.size() > 1)
|
||||||
|
{
|
||||||
|
merge_brams(it.second.pop(), it.second.pop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QlBramMergePass : public Pass {
|
||||||
|
|
||||||
|
QlBramMergePass() : Pass("ql_bram_merge", "Infers QuickLogic k6n10f BRAM pairs that can operate independently") {}
|
||||||
|
|
||||||
|
void help() override
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" ql_bram_merge [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log(" This pass identifies k6n10f 18K BRAM cells and packs pairs of them together\n");
|
||||||
|
log(" into a TDP36K cell operating in split mode\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
|
{
|
||||||
|
log_header(design, "Executing QL_BRAM_MERGE pass.\n");
|
||||||
|
|
||||||
|
size_t argidx = 1;
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
for (RTLIL::Module* module : design->selected_modules())
|
||||||
|
{
|
||||||
|
QlBramMergeWorker worker(module);
|
||||||
|
worker.merge_bram_groups();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} QlBramMergePass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -0,0 +1,99 @@
|
||||||
|
// Copyright 2020-2022 F4PGA Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
(* techmap_celltype = "$alu" *)
|
||||||
|
module _80_quicklogic_alu (A, B, CI, BI, X, Y, CO);
|
||||||
|
parameter A_SIGNED = 0;
|
||||||
|
parameter B_SIGNED = 0;
|
||||||
|
parameter A_WIDTH = 2;
|
||||||
|
parameter B_WIDTH = 2;
|
||||||
|
parameter Y_WIDTH = 2;
|
||||||
|
parameter _TECHMAP_CONSTVAL_CI_ = 0;
|
||||||
|
parameter _TECHMAP_CONSTMSK_CI_ = 0;
|
||||||
|
|
||||||
|
(* force_downto *)
|
||||||
|
input [A_WIDTH-1:0] A;
|
||||||
|
(* force_downto *)
|
||||||
|
input [B_WIDTH-1:0] B;
|
||||||
|
(* force_downto *)
|
||||||
|
output [Y_WIDTH-1:0] X, Y;
|
||||||
|
|
||||||
|
input CI, BI;
|
||||||
|
(* force_downto *)
|
||||||
|
output [Y_WIDTH-1:0] CO;
|
||||||
|
|
||||||
|
|
||||||
|
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
|
||||||
|
|
||||||
|
(* force_downto *)
|
||||||
|
wire [Y_WIDTH-1:0] A_buf, B_buf;
|
||||||
|
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
|
||||||
|
\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
|
||||||
|
|
||||||
|
(* force_downto *)
|
||||||
|
wire [Y_WIDTH-1:0] AA = A_buf;
|
||||||
|
(* force_downto *)
|
||||||
|
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
||||||
|
|
||||||
|
genvar i;
|
||||||
|
wire co;
|
||||||
|
|
||||||
|
(* force_downto *)
|
||||||
|
//wire [Y_WIDTH-1:0] C = {CO, CI};
|
||||||
|
wire [Y_WIDTH:0] C;
|
||||||
|
(* force_downto *)
|
||||||
|
wire [Y_WIDTH-1:0] S = {AA ^ BB};
|
||||||
|
assign CO[Y_WIDTH-1:0] = C[Y_WIDTH:1];
|
||||||
|
//assign CO[Y_WIDTH-1] = co;
|
||||||
|
|
||||||
|
generate
|
||||||
|
adder_carry intermediate_adder (
|
||||||
|
.cin ( ),
|
||||||
|
.cout (C[0]),
|
||||||
|
.p (1'b0),
|
||||||
|
.g (CI),
|
||||||
|
.sumout ()
|
||||||
|
);
|
||||||
|
endgenerate
|
||||||
|
genvar i;
|
||||||
|
generate if (Y_WIDTH > 2) begin
|
||||||
|
for (i = 0; i < Y_WIDTH-2; i = i + 1) begin:slice
|
||||||
|
adder_carry my_adder (
|
||||||
|
.cin(C[i]),
|
||||||
|
.g(AA[i]),
|
||||||
|
.p(S[i]),
|
||||||
|
.cout(C[i+1]),
|
||||||
|
.sumout(Y[i])
|
||||||
|
);
|
||||||
|
end
|
||||||
|
end endgenerate
|
||||||
|
generate
|
||||||
|
adder_carry final_adder (
|
||||||
|
.cin (C[Y_WIDTH-2]),
|
||||||
|
.cout (),
|
||||||
|
.p (1'b0),
|
||||||
|
.g (1'b0),
|
||||||
|
.sumout (co)
|
||||||
|
);
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
assign Y[Y_WIDTH-2] = S[Y_WIDTH-2] ^ co;
|
||||||
|
assign C[Y_WIDTH-1] = S[Y_WIDTH-2] ? co : AA[Y_WIDTH-2];
|
||||||
|
assign Y[Y_WIDTH-1] = S[Y_WIDTH-1] ^ C[Y_WIDTH-1];
|
||||||
|
assign C[Y_WIDTH] = S[Y_WIDTH-1] ? C[Y_WIDTH-1] : AA[Y_WIDTH-1];
|
||||||
|
|
||||||
|
assign X = S;
|
||||||
|
endmodule
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,376 @@
|
||||||
|
// Copyright 2020-2022 F4PGA Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
`timescale 1ps/1ps
|
||||||
|
|
||||||
|
`default_nettype none
|
||||||
|
(* abc9_lut=1 *)
|
||||||
|
module LUT1(output wire O, input wire I0);
|
||||||
|
parameter [1:0] INIT = 0;
|
||||||
|
assign O = I0 ? INIT[1] : INIT[0];
|
||||||
|
specify
|
||||||
|
(I0 => O) = 74;
|
||||||
|
endspecify
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_lut=2 *)
|
||||||
|
module LUT2(output wire O, input wire I0, I1);
|
||||||
|
parameter [3:0] INIT = 0;
|
||||||
|
wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0];
|
||||||
|
assign O = I0 ? s1[1] : s1[0];
|
||||||
|
specify
|
||||||
|
(I0 => O) = 116;
|
||||||
|
(I1 => O) = 74;
|
||||||
|
endspecify
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_lut=3 *)
|
||||||
|
module LUT3(output wire O, input wire I0, I1, I2);
|
||||||
|
parameter [7:0] INIT = 0;
|
||||||
|
wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0];
|
||||||
|
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
|
||||||
|
assign O = I0 ? s1[1] : s1[0];
|
||||||
|
specify
|
||||||
|
(I0 => O) = 162;
|
||||||
|
(I1 => O) = 116;
|
||||||
|
(I2 => O) = 174;
|
||||||
|
endspecify
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_lut=3 *)
|
||||||
|
module LUT4(output wire O, input wire I0, I1, I2, I3);
|
||||||
|
parameter [15:0] INIT = 0;
|
||||||
|
wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0];
|
||||||
|
wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
|
||||||
|
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
|
||||||
|
assign O = I0 ? s1[1] : s1[0];
|
||||||
|
specify
|
||||||
|
(I0 => O) = 201;
|
||||||
|
(I1 => O) = 162;
|
||||||
|
(I2 => O) = 116;
|
||||||
|
(I3 => O) = 74;
|
||||||
|
endspecify
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_lut=3 *)
|
||||||
|
module LUT5(output wire O, input wire I0, I1, I2, I3, I4);
|
||||||
|
parameter [31:0] INIT = 0;
|
||||||
|
wire [15: 0] s4 = I4 ? INIT[31:16] : INIT[15: 0];
|
||||||
|
wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
|
||||||
|
wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
|
||||||
|
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
|
||||||
|
assign O = I0 ? s1[1] : s1[0];
|
||||||
|
specify
|
||||||
|
(I0 => O) = 228;
|
||||||
|
(I1 => O) = 189;
|
||||||
|
(I2 => O) = 143;
|
||||||
|
(I3 => O) = 100;
|
||||||
|
(I4 => O) = 55;
|
||||||
|
endspecify
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_lut=5 *)
|
||||||
|
module LUT6(output wire O, input wire I0, I1, I2, I3, I4, I5);
|
||||||
|
parameter [63:0] INIT = 0;
|
||||||
|
wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0];
|
||||||
|
wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0];
|
||||||
|
wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
|
||||||
|
wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
|
||||||
|
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
|
||||||
|
assign O = I0 ? s1[1] : s1[0];
|
||||||
|
specify
|
||||||
|
(I0 => O) = 251;
|
||||||
|
(I1 => O) = 212;
|
||||||
|
(I2 => O) = 166;
|
||||||
|
(I3 => O) = 123;
|
||||||
|
(I4 => O) = 77;
|
||||||
|
(I5 => O) = 43;
|
||||||
|
endspecify
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_flop, lib_whitebox *)
|
||||||
|
module sh_dff(
|
||||||
|
output reg Q,
|
||||||
|
input wire D,
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input wire C
|
||||||
|
);
|
||||||
|
|
||||||
|
initial Q <= 1'b0;
|
||||||
|
always @(posedge C)
|
||||||
|
Q <= D;
|
||||||
|
|
||||||
|
specify
|
||||||
|
(posedge C => (Q +: D)) = 0;
|
||||||
|
$setuphold(posedge C, D, 0, 0);
|
||||||
|
endspecify
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_box, lib_whitebox *)
|
||||||
|
(* blackbox *)
|
||||||
|
(* keep *)
|
||||||
|
module adder_carry(
|
||||||
|
output wire sumout,
|
||||||
|
(* abc9_carry *)
|
||||||
|
output wire cout,
|
||||||
|
input wire p,
|
||||||
|
input wire g,
|
||||||
|
(* abc9_carry *)
|
||||||
|
input wire cin
|
||||||
|
);
|
||||||
|
assign sumout = p ^ cin;
|
||||||
|
assign cout = p ? cin : g;
|
||||||
|
|
||||||
|
specify
|
||||||
|
(p => sumout) = 35;
|
||||||
|
(g => sumout) = 35;
|
||||||
|
(cin => sumout) = 40;
|
||||||
|
(p => cout) = 67;
|
||||||
|
(g => cout) = 65;
|
||||||
|
(cin => cout) = 69;
|
||||||
|
endspecify
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_flop, lib_whitebox *)
|
||||||
|
module dff(
|
||||||
|
output reg Q,
|
||||||
|
input wire D,
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input wire C
|
||||||
|
);
|
||||||
|
initial Q <= 1'b0;
|
||||||
|
|
||||||
|
always @(posedge C)
|
||||||
|
Q <= D;
|
||||||
|
|
||||||
|
specify
|
||||||
|
(posedge C=>(Q+:D)) = 285;
|
||||||
|
$setuphold(posedge C, D, 56, 0);
|
||||||
|
endspecify
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_flop, lib_whitebox *)
|
||||||
|
module dffn(
|
||||||
|
output reg Q,
|
||||||
|
input wire D,
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input wire C
|
||||||
|
);
|
||||||
|
initial Q <= 1'b0;
|
||||||
|
|
||||||
|
always @(negedge C)
|
||||||
|
Q <= D;
|
||||||
|
|
||||||
|
specify
|
||||||
|
(negedge C=>(Q+:D)) = 285;
|
||||||
|
$setuphold(negedge C, D, 56, 0);
|
||||||
|
endspecify
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_flop, lib_whitebox *)
|
||||||
|
module dffsre(
|
||||||
|
output reg Q,
|
||||||
|
input wire D,
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input wire C,
|
||||||
|
input wire E,
|
||||||
|
input wire R,
|
||||||
|
input wire S
|
||||||
|
);
|
||||||
|
initial Q <= 1'b0;
|
||||||
|
|
||||||
|
always @(posedge C or negedge S or negedge R)
|
||||||
|
if (!R)
|
||||||
|
Q <= 1'b0;
|
||||||
|
else if (!S)
|
||||||
|
Q <= 1'b1;
|
||||||
|
else if (E)
|
||||||
|
Q <= D;
|
||||||
|
|
||||||
|
specify
|
||||||
|
(posedge C => (Q +: D)) = 280;
|
||||||
|
(R => Q) = 0;
|
||||||
|
(S => Q) = 0;
|
||||||
|
$setuphold(posedge C, D, 56, 0);
|
||||||
|
$setuphold(posedge C, E, 32, 0);
|
||||||
|
$setuphold(posedge C, R, 0, 0);
|
||||||
|
$setuphold(posedge C, S, 0, 0);
|
||||||
|
$recrem(posedge R, posedge C, 0, 0);
|
||||||
|
$recrem(posedge S, posedge C, 0, 0);
|
||||||
|
endspecify
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_flop, lib_whitebox *)
|
||||||
|
module dffnsre(
|
||||||
|
output reg Q,
|
||||||
|
input wire D,
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input wire C,
|
||||||
|
input wire E,
|
||||||
|
input wire R,
|
||||||
|
input wire S
|
||||||
|
);
|
||||||
|
initial Q <= 1'b0;
|
||||||
|
|
||||||
|
always @(negedge C or negedge S or negedge R)
|
||||||
|
if (!R)
|
||||||
|
Q <= 1'b0;
|
||||||
|
else if (!S)
|
||||||
|
Q <= 1'b1;
|
||||||
|
else if (E)
|
||||||
|
Q <= D;
|
||||||
|
|
||||||
|
specify
|
||||||
|
(negedge C => (Q +: D)) = 280;
|
||||||
|
(R => Q) = 0;
|
||||||
|
(S => Q) = 0;
|
||||||
|
$setuphold(negedge C, D, 56, 0);
|
||||||
|
$setuphold(negedge C, E, 32, 0);
|
||||||
|
$setuphold(negedge C, R, 0, 0);
|
||||||
|
$setuphold(negedge C, S, 0, 0);
|
||||||
|
$recrem(posedge R, negedge C, 0, 0);
|
||||||
|
$recrem(posedge S, negedge C, 0, 0);
|
||||||
|
endspecify
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_flop, lib_whitebox *)
|
||||||
|
module sdffsre(
|
||||||
|
output reg Q,
|
||||||
|
input wire D,
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input wire C,
|
||||||
|
input wire E,
|
||||||
|
input wire R,
|
||||||
|
input wire S
|
||||||
|
);
|
||||||
|
initial Q <= 1'b0;
|
||||||
|
|
||||||
|
always @(posedge C)
|
||||||
|
if (!R)
|
||||||
|
Q <= 1'b0;
|
||||||
|
else if (!S)
|
||||||
|
Q <= 1'b1;
|
||||||
|
else if (E)
|
||||||
|
Q <= D;
|
||||||
|
|
||||||
|
specify
|
||||||
|
(posedge C => (Q +: D)) = 280;
|
||||||
|
$setuphold(posedge C, D, 56, 0);
|
||||||
|
$setuphold(posedge C, R, 32, 0);
|
||||||
|
$setuphold(posedge C, S, 0, 0);
|
||||||
|
$setuphold(posedge C, E, 0, 0);
|
||||||
|
endspecify
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_flop, lib_whitebox *)
|
||||||
|
module sdffnsre(
|
||||||
|
output reg Q,
|
||||||
|
input wire D,
|
||||||
|
(* clkbuf_sink *)
|
||||||
|
input wire C,
|
||||||
|
input wire E,
|
||||||
|
input wire R,
|
||||||
|
input wire S
|
||||||
|
);
|
||||||
|
initial Q <= 1'b0;
|
||||||
|
|
||||||
|
always @(negedge C)
|
||||||
|
if (!R)
|
||||||
|
Q <= 1'b0;
|
||||||
|
else if (!S)
|
||||||
|
Q <= 1'b1;
|
||||||
|
else if (E)
|
||||||
|
Q <= D;
|
||||||
|
|
||||||
|
specify
|
||||||
|
(negedge C => (Q +: D)) = 280;
|
||||||
|
$setuphold(negedge C, D, 56, 0);
|
||||||
|
$setuphold(negedge C, R, 32, 0);
|
||||||
|
$setuphold(negedge C, S, 0, 0);
|
||||||
|
$setuphold(negedge C, E, 0, 0);
|
||||||
|
endspecify
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_flop, lib_whitebox *)
|
||||||
|
module latchsre (
|
||||||
|
output reg Q,
|
||||||
|
input wire S,
|
||||||
|
input wire R,
|
||||||
|
input wire D,
|
||||||
|
input wire G,
|
||||||
|
input wire E
|
||||||
|
);
|
||||||
|
initial Q <= 1'b0;
|
||||||
|
|
||||||
|
always @*
|
||||||
|
begin
|
||||||
|
if (!R)
|
||||||
|
Q <= 1'b0;
|
||||||
|
else if (!S)
|
||||||
|
Q <= 1'b1;
|
||||||
|
else if (E && G)
|
||||||
|
Q <= D;
|
||||||
|
end
|
||||||
|
|
||||||
|
specify
|
||||||
|
(posedge G => (Q +: D)) = 0;
|
||||||
|
$setuphold(posedge G, D, 0, 0);
|
||||||
|
$setuphold(posedge G, E, 0, 0);
|
||||||
|
$setuphold(posedge G, R, 0, 0);
|
||||||
|
$setuphold(posedge G, S, 0, 0);
|
||||||
|
endspecify
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* abc9_flop, lib_whitebox *)
|
||||||
|
module latchnsre (
|
||||||
|
output reg Q,
|
||||||
|
input wire S,
|
||||||
|
input wire R,
|
||||||
|
input wire D,
|
||||||
|
input wire G,
|
||||||
|
input wire E
|
||||||
|
);
|
||||||
|
initial Q <= 1'b0;
|
||||||
|
|
||||||
|
always @*
|
||||||
|
begin
|
||||||
|
if (!R)
|
||||||
|
Q <= 1'b0;
|
||||||
|
else if (!S)
|
||||||
|
Q <= 1'b1;
|
||||||
|
else if (E && !G)
|
||||||
|
Q <= D;
|
||||||
|
end
|
||||||
|
|
||||||
|
specify
|
||||||
|
(negedge G => (Q +: D)) = 0;
|
||||||
|
$setuphold(negedge G, D, 0, 0);
|
||||||
|
$setuphold(negedge G, E, 0, 0);
|
||||||
|
$setuphold(negedge G, R, 0, 0);
|
||||||
|
$setuphold(negedge G, S, 0, 0);
|
||||||
|
endspecify
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
// Copyright 2020-2022 F4PGA Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
// DFF, asynchronous set/reset, enable
|
||||||
|
module \$_DFFSRE_PNNP_ (C, S, R, E, D, Q);
|
||||||
|
input C;
|
||||||
|
input S;
|
||||||
|
input R;
|
||||||
|
input E;
|
||||||
|
input D;
|
||||||
|
output Q;
|
||||||
|
dffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(S));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFFSRE_NNNP_ (C, S, R, E, D, Q);
|
||||||
|
input C;
|
||||||
|
input S;
|
||||||
|
input R;
|
||||||
|
input E;
|
||||||
|
input D;
|
||||||
|
output Q;
|
||||||
|
dffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(S));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// DFF, synchronous set or reset, enable
|
||||||
|
module \$_SDFFE_PN0P_ (D, C, R, E, Q);
|
||||||
|
input D;
|
||||||
|
input C;
|
||||||
|
input R;
|
||||||
|
input E;
|
||||||
|
output Q;
|
||||||
|
sdffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(1'b1));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_SDFFE_PN1P_ (D, C, R, E, Q);
|
||||||
|
input D;
|
||||||
|
input C;
|
||||||
|
input R;
|
||||||
|
input E;
|
||||||
|
output Q;
|
||||||
|
sdffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(1'b1), .S(R));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_SDFFE_NN0P_ (D, C, R, E, Q);
|
||||||
|
input D;
|
||||||
|
input C;
|
||||||
|
input R;
|
||||||
|
input E;
|
||||||
|
output Q;
|
||||||
|
sdffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(1'b1));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_SDFFE_NN1P_ (D, C, R, E, Q);
|
||||||
|
input D;
|
||||||
|
input C;
|
||||||
|
input R;
|
||||||
|
input E;
|
||||||
|
output Q;
|
||||||
|
sdffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(1'b1), .S(R));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Latch, no set/reset, no enable
|
||||||
|
module \$_DLATCH_P_ (input E, D, output Q);
|
||||||
|
latchsre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(1'b1), .S(1'b1));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DLATCH_N_ (input E, D, output Q);
|
||||||
|
latchnsre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(1'b1), .S(1'b1));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Latch with async set and reset and enable
|
||||||
|
module \$_DLATCHSR_PPP_ (input E, S, R, D, output Q);
|
||||||
|
latchsre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(!R), .S(!S));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DLATCHSR_NPP_ (input E, S, R, D, output Q);
|
||||||
|
latchnsre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(!R), .S(!S));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$__SHREG_DFF_P_ (D, Q, C);
|
||||||
|
input D;
|
||||||
|
input C;
|
||||||
|
output Q;
|
||||||
|
|
||||||
|
parameter DEPTH = 2;
|
||||||
|
|
||||||
|
reg [DEPTH-2:0] q;
|
||||||
|
|
||||||
|
genvar i;
|
||||||
|
generate for (i = 0; i < DEPTH; i = i + 1) begin: slice
|
||||||
|
|
||||||
|
// First in chain
|
||||||
|
generate if (i == 0) begin
|
||||||
|
sh_dff #() shreg_beg (
|
||||||
|
.Q(q[i]),
|
||||||
|
.D(D),
|
||||||
|
.C(C)
|
||||||
|
);
|
||||||
|
end endgenerate
|
||||||
|
// Middle in chain
|
||||||
|
generate if (i > 0 && i != DEPTH-1) begin
|
||||||
|
sh_dff #() shreg_mid (
|
||||||
|
.Q(q[i]),
|
||||||
|
.D(q[i-1]),
|
||||||
|
.C(C)
|
||||||
|
);
|
||||||
|
end endgenerate
|
||||||
|
// Last in chain
|
||||||
|
generate if (i == DEPTH-1) begin
|
||||||
|
sh_dff #() shreg_end (
|
||||||
|
.Q(Q),
|
||||||
|
.D(q[i-1]),
|
||||||
|
.C(C)
|
||||||
|
);
|
||||||
|
end endgenerate
|
||||||
|
end: slice
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
ram block $__QLF_TDP36K {
|
||||||
|
init any;
|
||||||
|
byte 9;
|
||||||
|
option "SPLIT" 0 {
|
||||||
|
abits 15;
|
||||||
|
widths 1 2 4 9 18 36 per_port;
|
||||||
|
}
|
||||||
|
option "SPLIT" 1 {
|
||||||
|
abits 14;
|
||||||
|
widths 1 2 4 9 18 per_port;
|
||||||
|
}
|
||||||
|
cost 65;
|
||||||
|
port srsw "A" "B" {
|
||||||
|
width tied;
|
||||||
|
clock posedge;
|
||||||
|
# wen causes read even when ren is low
|
||||||
|
# map clken = wen || ren
|
||||||
|
clken;
|
||||||
|
wrbe_separate;
|
||||||
|
rdwr old;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,457 @@
|
||||||
|
// Copyright 2020-2022 F4PGA Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
module \$__QLF_TDP36K (PORT_A_CLK, PORT_A_ADDR, PORT_A_WR_DATA, PORT_A_WR_EN, PORT_A_WR_BE, PORT_A_CLK_EN, PORT_A_RD_DATA,
|
||||||
|
PORT_B_CLK, PORT_B_ADDR, PORT_B_WR_DATA, PORT_B_WR_EN, PORT_B_WR_BE, PORT_B_CLK_EN, PORT_B_RD_DATA);
|
||||||
|
|
||||||
|
parameter INIT = 0;
|
||||||
|
|
||||||
|
parameter OPTION_SPLIT = 0;
|
||||||
|
|
||||||
|
parameter PORT_A_WIDTH = 1;
|
||||||
|
parameter PORT_A_WR_BE_WIDTH = 1;
|
||||||
|
|
||||||
|
parameter PORT_B_WIDTH = 1;
|
||||||
|
parameter PORT_B_WR_BE_WIDTH = 1;
|
||||||
|
|
||||||
|
input PORT_A_CLK;
|
||||||
|
input [14:0] PORT_A_ADDR;
|
||||||
|
input [PORT_A_WIDTH-1:0] PORT_A_WR_DATA;
|
||||||
|
input PORT_A_WR_EN;
|
||||||
|
input [PORT_A_WR_BE_WIDTH-1:0] PORT_A_WR_BE;
|
||||||
|
input PORT_A_CLK_EN;
|
||||||
|
output [PORT_A_WIDTH-1:0] PORT_A_RD_DATA;
|
||||||
|
|
||||||
|
input PORT_B_CLK;
|
||||||
|
input [14:0] PORT_B_ADDR;
|
||||||
|
input [PORT_B_WIDTH-1:0] PORT_B_WR_DATA;
|
||||||
|
input PORT_B_WR_EN;
|
||||||
|
input [PORT_B_WR_BE_WIDTH-1:0] PORT_B_WR_BE;
|
||||||
|
input PORT_B_CLK_EN;
|
||||||
|
output [PORT_B_WIDTH-1:0] PORT_B_RD_DATA;
|
||||||
|
|
||||||
|
|
||||||
|
// Fixed mode settings
|
||||||
|
localparam [ 0:0] SYNC_FIFO1_i = 1'd0;
|
||||||
|
localparam [ 0:0] FMODE1_i = 1'd0;
|
||||||
|
localparam [ 0:0] POWERDN1_i = 1'd0;
|
||||||
|
localparam [ 0:0] SLEEP1_i = 1'd0;
|
||||||
|
localparam [ 0:0] PROTECT1_i = 1'd0;
|
||||||
|
localparam [11:0] UPAE1_i = 12'd10;
|
||||||
|
localparam [11:0] UPAF1_i = 12'd10;
|
||||||
|
|
||||||
|
localparam [ 0:0] SYNC_FIFO2_i = 1'd0;
|
||||||
|
localparam [ 0:0] FMODE2_i = 1'd0;
|
||||||
|
localparam [ 0:0] POWERDN2_i = 1'd0;
|
||||||
|
localparam [ 0:0] SLEEP2_i = 1'd0;
|
||||||
|
localparam [ 0:0] PROTECT2_i = 1'd0;
|
||||||
|
localparam [10:0] UPAE2_i = 11'd10;
|
||||||
|
localparam [10:0] UPAF2_i = 11'd10;
|
||||||
|
|
||||||
|
// Width mode function
|
||||||
|
function [2:0] mode;
|
||||||
|
input integer width;
|
||||||
|
case (width)
|
||||||
|
1: mode = 3'b101;
|
||||||
|
2: mode = 3'b110;
|
||||||
|
4: mode = 3'b100;
|
||||||
|
8,9: mode = 3'b001;
|
||||||
|
16, 18: mode = 3'b010;
|
||||||
|
32, 36: mode = 3'b011;
|
||||||
|
default: mode = 3'b000;
|
||||||
|
endcase
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
wire REN_A1_i;
|
||||||
|
wire REN_A2_i;
|
||||||
|
|
||||||
|
wire REN_B1_i;
|
||||||
|
wire REN_B2_i;
|
||||||
|
|
||||||
|
wire WEN_A1_i;
|
||||||
|
wire WEN_A2_i;
|
||||||
|
|
||||||
|
wire WEN_B1_i;
|
||||||
|
wire WEN_B2_i;
|
||||||
|
|
||||||
|
wire [1:0] BE_A1_i;
|
||||||
|
wire [1:0] BE_A2_i;
|
||||||
|
|
||||||
|
wire [1:0] BE_B1_i;
|
||||||
|
wire [1:0] BE_B2_i;
|
||||||
|
|
||||||
|
wire [14:0] ADDR_A1_i;
|
||||||
|
wire [13:0] ADDR_A2_i;
|
||||||
|
|
||||||
|
wire [14:0] ADDR_B1_i;
|
||||||
|
wire [13:0] ADDR_B2_i;
|
||||||
|
|
||||||
|
wire [17:0] WDATA_A1_i;
|
||||||
|
wire [17:0] WDATA_A2_i;
|
||||||
|
|
||||||
|
wire [17:0] WDATA_B1_i;
|
||||||
|
wire [17:0] WDATA_B2_i;
|
||||||
|
|
||||||
|
wire [17:0] RDATA_A1_o;
|
||||||
|
wire [17:0] RDATA_A2_o;
|
||||||
|
|
||||||
|
wire [17:0] RDATA_B1_o;
|
||||||
|
wire [17:0] RDATA_B2_o;
|
||||||
|
|
||||||
|
|
||||||
|
// Set port width mode (In non-split mode A2/B2 is not active. Set same values anyway to match previous behavior.)
|
||||||
|
localparam [ 2:0] RMODE_A1_i = mode(PORT_A_WIDTH);
|
||||||
|
localparam [ 2:0] WMODE_A1_i = mode(PORT_A_WIDTH);
|
||||||
|
localparam [ 2:0] RMODE_A2_i = mode(PORT_A_WIDTH);
|
||||||
|
localparam [ 2:0] WMODE_A2_i = mode(PORT_A_WIDTH);
|
||||||
|
|
||||||
|
localparam [ 2:0] RMODE_B1_i = mode(PORT_B_WIDTH);
|
||||||
|
localparam [ 2:0] WMODE_B1_i = mode(PORT_B_WIDTH);
|
||||||
|
localparam [ 2:0] RMODE_B2_i = mode(PORT_B_WIDTH);
|
||||||
|
localparam [ 2:0] WMODE_B2_i = mode(PORT_B_WIDTH);
|
||||||
|
|
||||||
|
assign REN_A1_i = PORT_A_CLK_EN;
|
||||||
|
assign WEN_A1_i = PORT_A_CLK_EN & PORT_A_WR_EN;
|
||||||
|
assign {BE_A2_i, BE_A1_i} = PORT_A_WR_BE;
|
||||||
|
|
||||||
|
assign REN_B1_i = PORT_B_CLK_EN;
|
||||||
|
assign WEN_B1_i = PORT_B_CLK_EN & PORT_B_WR_EN;
|
||||||
|
assign {BE_B2_i, BE_B1_i} = PORT_B_WR_BE;
|
||||||
|
|
||||||
|
case (PORT_A_WIDTH)
|
||||||
|
9: assign { WDATA_A1_i[16], WDATA_A1_i[7:0] } = PORT_A_WR_DATA;
|
||||||
|
18: assign { WDATA_A1_i[17], WDATA_A1_i[15:8], WDATA_A1_i[16], WDATA_A1_i[7:0] } = PORT_A_WR_DATA;
|
||||||
|
36: assign { WDATA_A2_i[17], WDATA_A2_i[15:8], WDATA_A2_i[16], WDATA_A2_i[7:0], WDATA_A1_i[17], WDATA_A1_i[15:8], WDATA_A1_i[16], WDATA_A1_i[7:0]} = PORT_A_WR_DATA;
|
||||||
|
default: assign WDATA_A1_i = PORT_A_WR_DATA; // 1,2,4
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case (PORT_B_WIDTH)
|
||||||
|
9: assign { WDATA_B1_i[16], WDATA_B1_i[7:0] } = PORT_B_WR_DATA;
|
||||||
|
18: assign { WDATA_B1_i[17], WDATA_B1_i[15:8], WDATA_B1_i[16], WDATA_B1_i[7:0] } = PORT_B_WR_DATA;
|
||||||
|
36: assign { WDATA_B2_i[17], WDATA_B2_i[15:8], WDATA_B2_i[16], WDATA_B2_i[7:0], WDATA_B1_i[17], WDATA_B1_i[15:8], WDATA_B1_i[16], WDATA_B1_i[7:0]} = PORT_B_WR_DATA;
|
||||||
|
default: assign WDATA_B1_i = PORT_B_WR_DATA; // 1,2,4
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case (PORT_A_WIDTH)
|
||||||
|
9: assign PORT_A_RD_DATA = { RDATA_A1_o[16], RDATA_A1_o[7:0] };
|
||||||
|
18: assign PORT_A_RD_DATA = { RDATA_A1_o[17], RDATA_A1_o[15:8], RDATA_A1_o[16], RDATA_A1_o[7:0] };
|
||||||
|
36: assign PORT_A_RD_DATA = { RDATA_A2_o[17], RDATA_A2_o[15:8], RDATA_A2_o[16], RDATA_A2_o[7:0], RDATA_A1_o[17], RDATA_A1_o[15:8], RDATA_A1_o[16], RDATA_A1_o[7:0]};
|
||||||
|
default: assign PORT_A_RD_DATA = RDATA_A1_o; // 1,2,4
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case (PORT_B_WIDTH)
|
||||||
|
9: assign PORT_B_RD_DATA = { RDATA_B1_o[16], RDATA_B1_o[7:0] };
|
||||||
|
18: assign PORT_B_RD_DATA = { RDATA_B1_o[17], RDATA_B1_o[15:8], RDATA_B1_o[16], RDATA_B1_o[7:0] };
|
||||||
|
36: assign PORT_B_RD_DATA = { RDATA_B2_o[17], RDATA_B2_o[15:8], RDATA_B2_o[16], RDATA_B2_o[7:0], RDATA_B1_o[17], RDATA_B1_o[15:8], RDATA_B1_o[16], RDATA_B1_o[7:0]};
|
||||||
|
default: assign PORT_B_RD_DATA = RDATA_B1_o; // 1,2,4
|
||||||
|
endcase
|
||||||
|
|
||||||
|
defparam _TECHMAP_REPLACE_.MODE_BITS = { 1'b0,
|
||||||
|
UPAF2_i, UPAE2_i, PROTECT2_i, SLEEP2_i, POWERDN2_i, FMODE2_i, WMODE_B2_i, WMODE_A2_i, RMODE_B2_i, RMODE_A2_i, SYNC_FIFO2_i,
|
||||||
|
UPAF1_i, UPAE1_i, PROTECT1_i, SLEEP1_i, POWERDN1_i, FMODE1_i, WMODE_B1_i, WMODE_A1_i, RMODE_B1_i, RMODE_A1_i, SYNC_FIFO1_i
|
||||||
|
};
|
||||||
|
|
||||||
|
(* is_inferred = 1 *)
|
||||||
|
(* is_split = 0 *)
|
||||||
|
(* port_a_width = PORT_A_WIDTH *)
|
||||||
|
(* port_b_width = PORT_B_WIDTH *)
|
||||||
|
TDP36K _TECHMAP_REPLACE_ (
|
||||||
|
.RESET_ni(1'b1),
|
||||||
|
|
||||||
|
.CLK_A1_i(PORT_A_CLK),
|
||||||
|
.ADDR_A1_i(PORT_A_ADDR),
|
||||||
|
.WEN_A1_i(WEN_A1_i),
|
||||||
|
.BE_A1_i(BE_A1_i),
|
||||||
|
.WDATA_A1_i(WDATA_A1_i),
|
||||||
|
.REN_A1_i(REN_A1_i),
|
||||||
|
.RDATA_A1_o(RDATA_A1_o),
|
||||||
|
|
||||||
|
.CLK_A2_i(PORT_A_CLK),
|
||||||
|
.ADDR_A2_i(PORT_A_ADDR[13:0]),
|
||||||
|
.WEN_A2_i(WEN_A1_i),
|
||||||
|
.BE_A2_i(BE_A2_i),
|
||||||
|
.WDATA_A2_i(WDATA_A2_i),
|
||||||
|
.REN_A2_i(REN_A1_i),
|
||||||
|
.RDATA_A2_o(RDATA_A2_o),
|
||||||
|
|
||||||
|
.CLK_B1_i(PORT_B_CLK),
|
||||||
|
.ADDR_B1_i(PORT_B_ADDR),
|
||||||
|
.WEN_B1_i(WEN_B1_i),
|
||||||
|
.BE_B1_i(BE_B1_i),
|
||||||
|
.WDATA_B1_i(WDATA_B1_i),
|
||||||
|
.REN_B1_i(REN_B1_i),
|
||||||
|
.RDATA_B1_o(RDATA_B1_o),
|
||||||
|
|
||||||
|
.CLK_B2_i(PORT_B_CLK),
|
||||||
|
.ADDR_B2_i(PORT_B_ADDR[13:0]),
|
||||||
|
.WEN_B2_i(WEN_B1_i),
|
||||||
|
.BE_B2_i(BE_B2_i),
|
||||||
|
.WDATA_B2_i(WDATA_B2_i),
|
||||||
|
.REN_B2_i(REN_B1_i),
|
||||||
|
.RDATA_B2_o(RDATA_B2_o),
|
||||||
|
|
||||||
|
.FLUSH1_i(1'b0),
|
||||||
|
.FLUSH2_i(1'b0)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
module \$__QLF_TDP36K_MERGED (...);
|
||||||
|
|
||||||
|
parameter INIT1 = 0;
|
||||||
|
|
||||||
|
parameter PORT_A1_WIDTH = 1;
|
||||||
|
parameter PORT_B1_WIDTH = 1;
|
||||||
|
|
||||||
|
parameter PORT_A1_WR_BE_WIDTH = 1;
|
||||||
|
parameter PORT_B1_WR_BE_WIDTH = 1;
|
||||||
|
|
||||||
|
input PORT_A1_CLK;
|
||||||
|
input [14:0] PORT_A1_ADDR;
|
||||||
|
input [PORT_A1_WIDTH-1:0] PORT_A1_WR_DATA;
|
||||||
|
input PORT_A1_WR_EN;
|
||||||
|
input [PORT_A1_WR_BE_WIDTH-1:0] PORT_A1_WR_BE;
|
||||||
|
input PORT_A1_CLK_EN;
|
||||||
|
output [PORT_A1_WIDTH-1:0] PORT_A1_RD_DATA;
|
||||||
|
|
||||||
|
input PORT_B1_CLK;
|
||||||
|
input [14:0] PORT_B1_ADDR;
|
||||||
|
input [PORT_B1_WIDTH-1:0] PORT_B1_WR_DATA;
|
||||||
|
input PORT_B1_WR_EN;
|
||||||
|
input [PORT_B1_WR_BE_WIDTH-1:0] PORT_B1_WR_BE;
|
||||||
|
input PORT_B1_CLK_EN;
|
||||||
|
output [PORT_B1_WIDTH-1:0] PORT_B1_RD_DATA;
|
||||||
|
|
||||||
|
parameter INIT2 = 0;
|
||||||
|
|
||||||
|
parameter PORT_A2_WIDTH = 1;
|
||||||
|
parameter PORT_B2_WIDTH = 1;
|
||||||
|
parameter PORT_A2_WR_BE_WIDTH = 1;
|
||||||
|
parameter PORT_B2_WR_BE_WIDTH = 1;
|
||||||
|
|
||||||
|
input PORT_A2_CLK;
|
||||||
|
input [14:0] PORT_A2_ADDR;
|
||||||
|
input [PORT_A2_WIDTH-1:0] PORT_A2_WR_DATA;
|
||||||
|
input PORT_A2_WR_EN;
|
||||||
|
input [PORT_A2_WR_BE_WIDTH-1:0] PORT_A2_WR_BE;
|
||||||
|
input PORT_A2_CLK_EN;
|
||||||
|
output [PORT_A2_WIDTH-1:0] PORT_A2_RD_DATA;
|
||||||
|
|
||||||
|
input PORT_B2_CLK;
|
||||||
|
input [14:0] PORT_B2_ADDR;
|
||||||
|
input [PORT_B2_WIDTH-1:0] PORT_B2_WR_DATA;
|
||||||
|
input PORT_B2_WR_EN;
|
||||||
|
input [PORT_B2_WR_BE_WIDTH-1:0] PORT_B2_WR_BE;
|
||||||
|
input PORT_B2_CLK_EN;
|
||||||
|
output [PORT_B2_WIDTH-1:0] PORT_B2_RD_DATA;
|
||||||
|
|
||||||
|
|
||||||
|
// Fixed mode settings
|
||||||
|
localparam [ 0:0] SYNC_FIFO1_i = 1'd0;
|
||||||
|
localparam [ 0:0] FMODE1_i = 1'd0;
|
||||||
|
localparam [ 0:0] POWERDN1_i = 1'd0;
|
||||||
|
localparam [ 0:0] SLEEP1_i = 1'd0;
|
||||||
|
localparam [ 0:0] PROTECT1_i = 1'd0;
|
||||||
|
localparam [11:0] UPAE1_i = 12'd10;
|
||||||
|
localparam [11:0] UPAF1_i = 12'd10;
|
||||||
|
|
||||||
|
localparam [ 0:0] SYNC_FIFO2_i = 1'd0;
|
||||||
|
localparam [ 0:0] FMODE2_i = 1'd0;
|
||||||
|
localparam [ 0:0] POWERDN2_i = 1'd0;
|
||||||
|
localparam [ 0:0] SLEEP2_i = 1'd0;
|
||||||
|
localparam [ 0:0] PROTECT2_i = 1'd0;
|
||||||
|
localparam [10:0] UPAE2_i = 11'd10;
|
||||||
|
localparam [10:0] UPAF2_i = 11'd10;
|
||||||
|
|
||||||
|
// Width mode function
|
||||||
|
function [2:0] mode;
|
||||||
|
input integer width;
|
||||||
|
case (width)
|
||||||
|
1: mode = 3'b101;
|
||||||
|
2: mode = 3'b110;
|
||||||
|
4: mode = 3'b100;
|
||||||
|
8,9: mode = 3'b001;
|
||||||
|
16, 18: mode = 3'b010;
|
||||||
|
default: mode = 3'b000;
|
||||||
|
endcase
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
wire REN_A1_i;
|
||||||
|
wire REN_A2_i;
|
||||||
|
|
||||||
|
wire REN_B1_i;
|
||||||
|
wire REN_B2_i;
|
||||||
|
|
||||||
|
wire WEN_A1_i;
|
||||||
|
wire WEN_A2_i;
|
||||||
|
|
||||||
|
wire WEN_B1_i;
|
||||||
|
wire WEN_B2_i;
|
||||||
|
|
||||||
|
wire [1:0] BE_A1_i;
|
||||||
|
wire [1:0] BE_A2_i;
|
||||||
|
|
||||||
|
wire [1:0] BE_B1_i;
|
||||||
|
wire [1:0] BE_B2_i;
|
||||||
|
|
||||||
|
wire [14:0] ADDR_A1_i;
|
||||||
|
wire [13:0] ADDR_A2_i;
|
||||||
|
|
||||||
|
wire [14:0] ADDR_B1_i;
|
||||||
|
wire [13:0] ADDR_B2_i;
|
||||||
|
|
||||||
|
wire [17:0] WDATA_A1_i;
|
||||||
|
wire [17:0] WDATA_A2_i;
|
||||||
|
|
||||||
|
wire [17:0] WDATA_B1_i;
|
||||||
|
wire [17:0] WDATA_B2_i;
|
||||||
|
|
||||||
|
wire [17:0] RDATA_A1_o;
|
||||||
|
wire [17:0] RDATA_A2_o;
|
||||||
|
|
||||||
|
wire [17:0] RDATA_B1_o;
|
||||||
|
wire [17:0] RDATA_B2_o;
|
||||||
|
|
||||||
|
|
||||||
|
// Set port width mode (In non-split mode A2/B2 is not active. Set same values anyway to match previous behavior.)
|
||||||
|
localparam [ 2:0] RMODE_A1_i = mode(PORT_A1_WIDTH);
|
||||||
|
localparam [ 2:0] WMODE_A1_i = mode(PORT_A1_WIDTH);
|
||||||
|
localparam [ 2:0] RMODE_B1_i = mode(PORT_B1_WIDTH);
|
||||||
|
localparam [ 2:0] WMODE_B1_i = mode(PORT_B1_WIDTH);
|
||||||
|
|
||||||
|
localparam [ 2:0] RMODE_A2_i = mode(PORT_A2_WIDTH);
|
||||||
|
localparam [ 2:0] WMODE_A2_i = mode(PORT_A2_WIDTH);
|
||||||
|
localparam [ 2:0] RMODE_B2_i = mode(PORT_B2_WIDTH);
|
||||||
|
localparam [ 2:0] WMODE_B2_i = mode(PORT_B2_WIDTH);
|
||||||
|
|
||||||
|
assign REN_A1_i = PORT_A1_CLK_EN;
|
||||||
|
assign WEN_A1_i = PORT_A1_CLK_EN & PORT_A1_WR_EN;
|
||||||
|
assign BE_A1_i = PORT_A1_WR_BE;
|
||||||
|
|
||||||
|
assign REN_B1_i = PORT_B1_CLK_EN;
|
||||||
|
assign WEN_B1_i = PORT_B1_CLK_EN & PORT_B1_WR_EN;
|
||||||
|
assign BE_B1_i = PORT_B1_WR_BE;
|
||||||
|
|
||||||
|
assign REN_A2_i = PORT_A2_CLK_EN;
|
||||||
|
assign WEN_A2_i = PORT_A2_CLK_EN & PORT_A2_WR_EN;
|
||||||
|
assign BE_A2_i = PORT_A2_WR_BE;
|
||||||
|
|
||||||
|
assign REN_B2_i = PORT_B2_CLK_EN;
|
||||||
|
assign WEN_B2_i = PORT_B2_CLK_EN & PORT_B2_WR_EN;
|
||||||
|
assign BE_B2_i = PORT_B2_WR_BE;
|
||||||
|
|
||||||
|
assign ADDR_A1_i = PORT_A1_ADDR;
|
||||||
|
assign ADDR_B1_i = PORT_B1_ADDR;
|
||||||
|
assign ADDR_A2_i = PORT_A2_ADDR;
|
||||||
|
assign ADDR_B2_i = PORT_B2_ADDR;
|
||||||
|
|
||||||
|
case (PORT_A1_WIDTH)
|
||||||
|
9: assign { WDATA_A1_i[16], WDATA_A1_i[7:0] } = PORT_A1_WR_DATA;
|
||||||
|
18: assign { WDATA_A1_i[17], WDATA_A1_i[15:8], WDATA_A1_i[16], WDATA_A1_i[7:0] } = PORT_A1_WR_DATA;
|
||||||
|
default: assign WDATA_A1_i = PORT_A1_WR_DATA; // 1,2,4,8,16
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case (PORT_B1_WIDTH)
|
||||||
|
9: assign { WDATA_B1_i[16], WDATA_B1_i[7:0] } = PORT_B1_WR_DATA;
|
||||||
|
18: assign { WDATA_B1_i[17], WDATA_B1_i[15:8], WDATA_B1_i[16], WDATA_B1_i[7:0] } = PORT_B1_WR_DATA;
|
||||||
|
default: assign WDATA_B1_i = PORT_B1_WR_DATA; // 1,2,4,8,16
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case (PORT_A1_WIDTH)
|
||||||
|
9: assign PORT_A1_RD_DATA = { RDATA_A1_o[16], RDATA_A1_o[7:0] };
|
||||||
|
18: assign PORT_A1_RD_DATA = { RDATA_A1_o[17], RDATA_A1_o[15:8], RDATA_A1_o[16], RDATA_A1_o[7:0] };
|
||||||
|
default: assign PORT_A1_RD_DATA = RDATA_A1_o; // 1,2,4,8,16
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case (PORT_B1_WIDTH)
|
||||||
|
9: assign PORT_B1_RD_DATA = { RDATA_B1_o[16], RDATA_B1_o[7:0] };
|
||||||
|
18: assign PORT_B1_RD_DATA = { RDATA_B1_o[17], RDATA_B1_o[15:8], RDATA_B1_o[16], RDATA_B1_o[7:0] };
|
||||||
|
default: assign PORT_B1_RD_DATA = RDATA_B1_o; // 1,2,4,8,16
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case (PORT_A2_WIDTH)
|
||||||
|
9: assign { WDATA_A2_i[16], WDATA_A2_i[7:0] } = PORT_A2_WR_DATA;
|
||||||
|
18: assign { WDATA_A2_i[17], WDATA_A2_i[15:8], WDATA_A2_i[16], WDATA_A2_i[7:0] } = PORT_A2_WR_DATA;
|
||||||
|
default: assign WDATA_A2_i = PORT_A2_WR_DATA; // 1,2,4,8,16
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case (PORT_B2_WIDTH)
|
||||||
|
9: assign { WDATA_B2_i[16], WDATA_B2_i[7:0] } = PORT_B2_WR_DATA;
|
||||||
|
18: assign { WDATA_B2_i[17], WDATA_B2_i[15:8], WDATA_B2_i[16], WDATA_B2_i[7:0] } = PORT_B2_WR_DATA;
|
||||||
|
default: assign WDATA_B2_i = PORT_B2_WR_DATA; // 1,2,4,8,16
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case (PORT_A2_WIDTH)
|
||||||
|
9: assign PORT_A2_RD_DATA = { RDATA_A2_o[16], RDATA_A2_o[7:0] };
|
||||||
|
18: assign PORT_A2_RD_DATA = { RDATA_A2_o[17], RDATA_A2_o[15:8], RDATA_A2_o[16], RDATA_A2_o[7:0] };
|
||||||
|
default: assign PORT_A2_RD_DATA = RDATA_A2_o; // 1,2,4,8,16
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case (PORT_B2_WIDTH)
|
||||||
|
9: assign PORT_B2_RD_DATA = { RDATA_B2_o[16], RDATA_B2_o[7:0] };
|
||||||
|
18: assign PORT_B2_RD_DATA = { RDATA_B2_o[17], RDATA_B2_o[15:8], RDATA_B2_o[16], RDATA_B2_o[7:0] };
|
||||||
|
default: assign PORT_B2_RD_DATA = RDATA_B2_o; // 1,2,4,8,16
|
||||||
|
endcase
|
||||||
|
|
||||||
|
defparam _TECHMAP_REPLACE_.MODE_BITS = {1'b1,
|
||||||
|
UPAF2_i, UPAE2_i, PROTECT2_i, SLEEP2_i, POWERDN2_i, FMODE2_i, WMODE_B2_i, WMODE_A2_i, RMODE_B2_i, RMODE_A2_i, SYNC_FIFO2_i,
|
||||||
|
UPAF1_i, UPAE1_i, PROTECT1_i, SLEEP1_i, POWERDN1_i, FMODE1_i, WMODE_B1_i, WMODE_A1_i, RMODE_B1_i, RMODE_A1_i, SYNC_FIFO1_i
|
||||||
|
};
|
||||||
|
|
||||||
|
(* is_inferred = 1 *)
|
||||||
|
(* is_split = 1 *)
|
||||||
|
(* port_a1_width = PORT_A1_WIDTH *)
|
||||||
|
(* port_a2_width = PORT_A2_WIDTH *)
|
||||||
|
(* port_b1_width = PORT_B1_WIDTH *)
|
||||||
|
(* port_b2_width = PORT_B2_WIDTH *)
|
||||||
|
TDP36K _TECHMAP_REPLACE_ (
|
||||||
|
.RESET_ni(1'b1),
|
||||||
|
.WDATA_A1_i(WDATA_A1_i),
|
||||||
|
.WDATA_A2_i(WDATA_A2_i),
|
||||||
|
.RDATA_A1_o(RDATA_A1_o),
|
||||||
|
.RDATA_A2_o(RDATA_A2_o),
|
||||||
|
.ADDR_A1_i(ADDR_A1_i),
|
||||||
|
.ADDR_A2_i(ADDR_A2_i),
|
||||||
|
.CLK_A1_i(PORT_A1_CLK),
|
||||||
|
.CLK_A2_i(PORT_A2_CLK),
|
||||||
|
.REN_A1_i(REN_A1_i),
|
||||||
|
.REN_A2_i(REN_A2_i),
|
||||||
|
.WEN_A1_i(WEN_A1_i),
|
||||||
|
.WEN_A2_i(WEN_A2_i),
|
||||||
|
.BE_A1_i(BE_A1_i),
|
||||||
|
.BE_A2_i(BE_A2_i),
|
||||||
|
|
||||||
|
.WDATA_B1_i(WDATA_B1_i),
|
||||||
|
.WDATA_B2_i(WDATA_B2_i),
|
||||||
|
.RDATA_B1_o(RDATA_B1_o),
|
||||||
|
.RDATA_B2_o(RDATA_B2_o),
|
||||||
|
.ADDR_B1_i(ADDR_B1_i),
|
||||||
|
.ADDR_B2_i(ADDR_B2_i),
|
||||||
|
.CLK_B1_i(PORT_B1_CLK),
|
||||||
|
.CLK_B2_i(PORT_B2_CLK),
|
||||||
|
.REN_B1_i(REN_B1_i),
|
||||||
|
.REN_B2_i(REN_B2_i),
|
||||||
|
.WEN_B1_i(WEN_B1_i),
|
||||||
|
.WEN_B2_i(WEN_B2_i),
|
||||||
|
.BE_B1_i(BE_B1_i),
|
||||||
|
.BE_B2_i(BE_B2_i),
|
||||||
|
|
||||||
|
.FLUSH1_i(1'b0),
|
||||||
|
.FLUSH2_i(1'b0)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020-2022 F4PGA Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kernel/sigtools.h"
|
||||||
|
#include "kernel/yosys.h"
|
||||||
|
|
||||||
|
USING_YOSYS_NAMESPACE
|
||||||
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
struct QuicklogicEqnPass : public Pass {
|
||||||
|
QuicklogicEqnPass() : Pass("quicklogic_eqn", "Quicklogic: Calculate equations for luts") {}
|
||||||
|
void help() override
|
||||||
|
{
|
||||||
|
log("\n");
|
||||||
|
log(" quicklogic_eqn [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Calculate equations for luts since bitstream generator depends on it.\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
Const init2eqn(Const init, int inputs)
|
||||||
|
{
|
||||||
|
std::string init_bits = init.as_string();
|
||||||
|
const char *names[] = {"I0", "I1", "I2", "I3", "I4"};
|
||||||
|
|
||||||
|
std::string eqn;
|
||||||
|
int width = (int)pow(2, inputs);
|
||||||
|
for (int i = 0; i < width; i++) {
|
||||||
|
if (init_bits[width - 1 - i] == '1') {
|
||||||
|
eqn += "(";
|
||||||
|
for (int j = 0; j < inputs; j++) {
|
||||||
|
if (i & (1 << j))
|
||||||
|
eqn += names[j];
|
||||||
|
else
|
||||||
|
eqn += std::string("~") + names[j];
|
||||||
|
|
||||||
|
if (j != (inputs - 1))
|
||||||
|
eqn += "*";
|
||||||
|
}
|
||||||
|
eqn += ")+";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (eqn.empty())
|
||||||
|
return Const("0");
|
||||||
|
eqn = eqn.substr(0, eqn.length() - 1);
|
||||||
|
return Const(eqn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
|
{
|
||||||
|
log_header(design, "Executing Quicklogic_EQN pass (calculate equations for luts).\n");
|
||||||
|
|
||||||
|
extra_args(args, args.size(), design);
|
||||||
|
|
||||||
|
int cnt = 0;
|
||||||
|
for (auto module : design->selected_modules()) {
|
||||||
|
for (auto cell : module->selected_cells()) {
|
||||||
|
if (cell->type == ID(LUT1)) {
|
||||||
|
cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 1));
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
if (cell->type == ID(LUT2)) {
|
||||||
|
cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 2));
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
if (cell->type == ID(LUT3)) {
|
||||||
|
cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 3));
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
if (cell->type == ID(LUT4)) {
|
||||||
|
cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 4));
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
if (cell->type == ID(LUT5)) {
|
||||||
|
cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 5));
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log_header(design, "Updated %d of LUT* elements with equation.\n", cnt);
|
||||||
|
}
|
||||||
|
} QuicklogicEqnPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -2,6 +2,7 @@
|
||||||
* yosys -- Yosys Open SYnthesis Suite
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
*
|
*
|
||||||
* Copyright (C) 2021 QuickLogic Corp.
|
* Copyright (C) 2021 QuickLogic Corp.
|
||||||
|
* Copyright 2020-2022 F4PGA Authors
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -30,6 +31,7 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
|
|
||||||
void help() override
|
void help() override
|
||||||
{
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" synth_quicklogic [options]\n");
|
log(" synth_quicklogic [options]\n");
|
||||||
log("This command runs synthesis for QuickLogic FPGAs\n");
|
log("This command runs synthesis for QuickLogic FPGAs\n");
|
||||||
|
@ -42,6 +44,17 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
log(" generate the synthesis netlist for the specified family.\n");
|
log(" generate the synthesis netlist for the specified family.\n");
|
||||||
log(" supported values:\n");
|
log(" supported values:\n");
|
||||||
log(" - pp3: PolarPro 3 \n");
|
log(" - pp3: PolarPro 3 \n");
|
||||||
|
log(" - qlf_k6n10f: K6N10f\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -nocarry\n");
|
||||||
|
log(" do not use adder_carry cells in output netlist.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -nobram\n");
|
||||||
|
log(" do not use block RAM cells in output netlist.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -bramtypes\n");
|
||||||
|
log(" Emit specialized BRAM cells for particular address and data width\n");
|
||||||
|
log(" configurations.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -blif <file>\n");
|
log(" -blif <file>\n");
|
||||||
log(" write the design to the specified BLIF file. writing of an output file\n");
|
log(" write the design to the specified BLIF file. writing of an output file\n");
|
||||||
|
@ -61,7 +74,7 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
string top_opt, blif_file, edif_file, family, currmodule, verilog_file, lib_path;
|
string top_opt, blif_file, edif_file, family, currmodule, verilog_file, lib_path;
|
||||||
bool abc9;
|
bool abc9, inferAdder, nobram, bramTypes;
|
||||||
|
|
||||||
void clear_flags() override
|
void clear_flags() override
|
||||||
{
|
{
|
||||||
|
@ -72,12 +85,26 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
currmodule = "";
|
currmodule = "";
|
||||||
family = "pp3";
|
family = "pp3";
|
||||||
abc9 = true;
|
abc9 = true;
|
||||||
|
inferAdder = true;
|
||||||
|
nobram = false;
|
||||||
|
bramTypes = false;
|
||||||
|
lib_path = "+/quicklogic/";
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_scratchpad_defaults(RTLIL::Design *design) {
|
||||||
|
lib_path = design->scratchpad_get_string("ql.lib_path", lib_path);
|
||||||
|
if (lib_path.back() != '/')
|
||||||
|
lib_path += "/";
|
||||||
|
inferAdder = !design->scratchpad_get_bool("ql.nocarry", false);
|
||||||
|
nobram = design->scratchpad_get_bool("ql.nobram", false);
|
||||||
|
bramTypes = design->scratchpad_get_bool("ql.bramtypes", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
{
|
{
|
||||||
string run_from, run_to;
|
string run_from, run_to;
|
||||||
clear_flags();
|
clear_flags();
|
||||||
|
set_scratchpad_defaults(design);
|
||||||
|
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
for (argidx = 1; argidx < args.size(); argidx++)
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
@ -114,6 +141,18 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
abc9 = false;
|
abc9 = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-nocarry") {
|
||||||
|
inferAdder = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-nobram") {
|
||||||
|
nobram = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-bramtypes") {
|
||||||
|
bramTypes = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
@ -121,7 +160,7 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
if (!design->full_selection())
|
if (!design->full_selection())
|
||||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||||
|
|
||||||
if (family != "pp3")
|
if (family != "pp3" && family != "qlf_k6n10f")
|
||||||
log_cmd_error("Invalid family specified: '%s'\n", family.c_str());
|
log_cmd_error("Invalid family specified: '%s'\n", family.c_str());
|
||||||
|
|
||||||
if (abc9 && design->scratchpad_get_int("abc9.D", 0) == 0) {
|
if (abc9 && design->scratchpad_get_int("abc9.D", 0) == 0) {
|
||||||
|
@ -144,14 +183,22 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("begin")) {
|
if (check_label("begin")) {
|
||||||
run(stringf("read_verilog -lib -specify +/quicklogic/common/cells_sim.v +/quicklogic/%s/cells_sim.v", family.c_str()));
|
std::string read_simlibs = stringf("read_verilog -lib -specify %scommon/cells_sim.v %s%s/cells_sim.v", lib_path.c_str(), lib_path.c_str(), family.c_str());
|
||||||
|
if (family == "qlf_k6n10f") {
|
||||||
|
read_simlibs += stringf(" %sqlf_k6n10f/brams_sim.v", lib_path.c_str());
|
||||||
|
if (bramTypes)
|
||||||
|
read_simlibs += stringf(" %sqlf_k6n10f/bram_types_sim.v", lib_path.c_str());
|
||||||
|
}
|
||||||
|
run(read_simlibs);
|
||||||
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
|
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("prepare")) {
|
if (check_label("prepare")) {
|
||||||
run("proc");
|
run("proc");
|
||||||
run("flatten");
|
run("flatten");
|
||||||
run("tribuf -logic");
|
if (help_mode || family == "pp3") {
|
||||||
|
run("tribuf -logic", " (for pp3)");
|
||||||
|
}
|
||||||
run("deminout");
|
run("deminout");
|
||||||
run("opt_expr");
|
run("opt_expr");
|
||||||
run("opt_clean");
|
run("opt_clean");
|
||||||
|
@ -176,6 +223,71 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
run("opt_clean");
|
run("opt_clean");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (check_label("map_bram", "(for qlf_k6n10f, skip if -no_bram)") && (help_mode || family == "qlf_k6n10f")) {
|
||||||
|
run("memory_libmap -lib " + lib_path + family + "/libmap_brams.txt");
|
||||||
|
run("ql_bram_merge");
|
||||||
|
run("techmap -map " + lib_path + family + "/libmap_brams_map.v");
|
||||||
|
run("techmap -autoproc -map " + lib_path + family + "/brams_map.v");
|
||||||
|
run("techmap -map " + lib_path + family + "/brams_final_map.v");
|
||||||
|
|
||||||
|
if (help_mode) {
|
||||||
|
run("chtype -set TDP36K_<mode> t:TDP36K a:<mode>", "(if -bram_types)");
|
||||||
|
}
|
||||||
|
else if (bramTypes) {
|
||||||
|
for (int a_dwidth : {1, 2, 4, 9, 18, 36})
|
||||||
|
for (int b_dwidth: {1, 2, 4, 9, 18, 36}) {
|
||||||
|
run(stringf("chtype -set TDP36K_BRAM_A_X%d_B_X%d_nonsplit t:TDP36K a:is_inferred=0 %%i "
|
||||||
|
"a:is_fifo=0 %%i a:port_a_dwidth=%d %%i a:port_b_dwidth=%d %%i",
|
||||||
|
a_dwidth, b_dwidth, a_dwidth, b_dwidth));
|
||||||
|
|
||||||
|
run(stringf("chtype -set TDP36K_FIFO_ASYNC_A_X%d_B_X%d_nonsplit t:TDP36K a:is_inferred=0 %%i "
|
||||||
|
"a:is_fifo=1 %%i a:sync_fifo=0 %%i a:port_a_dwidth=%d %%i a:port_b_dwidth=%d %%i",
|
||||||
|
a_dwidth, b_dwidth, a_dwidth, b_dwidth));
|
||||||
|
|
||||||
|
run(stringf("chtype -set TDP36K_FIFO_SYNC_A_X%d_B_X%d_nonsplit t:TDP36K a:is_inferred=0 %%i "
|
||||||
|
"a:is_fifo=1 %%i a:sync_fifo=1 %%i a:port_a_dwidth=%d %%i a:port_b_dwidth=%d %%i",
|
||||||
|
a_dwidth, b_dwidth, a_dwidth, b_dwidth));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int a1_dwidth : {1, 2, 4, 9, 18})
|
||||||
|
for (int b1_dwidth: {1, 2, 4, 9, 18})
|
||||||
|
for (int a2_dwidth : {1, 2, 4, 9, 18})
|
||||||
|
for (int b2_dwidth: {1, 2, 4, 9, 18}) {
|
||||||
|
run(stringf("chtype -set TDP36K_BRAM_A1_X%d_B1_X%d_A2_X%d_B2_X%d_split t:TDP36K a:is_inferred=0 %%i "
|
||||||
|
"a:is_split=1 %%i a:is_fifo=0 %%i "
|
||||||
|
"a:port_a1_dwidth=%d %%i a:port_b1_dwidth=%d %%i a:port_a2_dwidth=%d %%i a:port_b2_dwidth=%d %%i",
|
||||||
|
a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth, a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth));
|
||||||
|
|
||||||
|
run(stringf("chtype -set TDP36K_FIFO_ASYNC_A1_X%d_B1_X%d_A2_X%d_B2_X%d_split t:TDP36K a:is_inferred=0 %%i "
|
||||||
|
"a:is_split=1 %%i a:is_fifo=1 %%i a:sync_fifo=0 %%i "
|
||||||
|
"a:port_a1_dwidth=%d %%i a:port_b1_dwidth=%d %%i a:port_a2_dwidth=%d %%i a:port_b2_dwidth=%d %%i",
|
||||||
|
a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth, a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth));
|
||||||
|
|
||||||
|
run(stringf("chtype -set TDP36K_FIFO_SYNC_A1_X%d_B1_X%d_A2_X%d_B2_X%d_split t:TDP36K a:is_inferred=0 %%i "
|
||||||
|
"a:is_split=1 %%i a:is_fifo=1 %%i a:sync_fifo=1 %%i "
|
||||||
|
"a:port_a1_dwidth=%d %%i a:port_b1_dwidth=%d %%i a:port_a2_dwidth=%d %%i a:port_b2_dwidth=%d %%i",
|
||||||
|
a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth, a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int a_width : {1, 2, 4, 9, 18, 36})
|
||||||
|
for (int b_width: {1, 2, 4, 9, 18, 36}) {
|
||||||
|
run(stringf("chtype -set TDP36K_BRAM_A_X%d_B_X%d_nonsplit t:TDP36K a:is_inferred=1 %%i "
|
||||||
|
"a:port_a_width=%d %%i a:port_b_width=%d %%i",
|
||||||
|
a_width, b_width, a_width, b_width));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int a1_width : {1, 2, 4, 9, 18})
|
||||||
|
for (int b1_width: {1, 2, 4, 9, 18})
|
||||||
|
for (int a2_width : {1, 2, 4, 9, 18})
|
||||||
|
for (int b2_width: {1, 2, 4, 9, 18}) {
|
||||||
|
run(stringf("chtype -set TDP36K_BRAM_A1_X%d_B1_X%d_A2_X%d_B2_X%d_split t:TDP36K a:is_inferred=1 %%i "
|
||||||
|
"a:port_a1_width=%d %%i a:port_b1_width=%d %%i a:port_a2_width=%d %%i a:port_b2_width=%d %%i",
|
||||||
|
a1_width, b1_width, a2_width, b2_width, a1_width, b1_width, a2_width, b2_width));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (check_label("map_ffram")) {
|
if (check_label("map_ffram")) {
|
||||||
run("opt -fast -mux_undef -undriven -fine");
|
run("opt -fast -mux_undef -undriven -fine");
|
||||||
run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block "
|
run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block "
|
||||||
|
@ -185,36 +297,65 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("map_gates")) {
|
if (check_label("map_gates")) {
|
||||||
run("techmap");
|
if (inferAdder && family == "qlf_k6n10f") {
|
||||||
|
run("techmap -map +/techmap.v -map " + lib_path + family + "/arith_map.v", "(unless -no_adder)");
|
||||||
|
} else {
|
||||||
|
run("techmap");
|
||||||
|
}
|
||||||
run("opt -fast");
|
run("opt -fast");
|
||||||
run("muxcover -mux8 -mux4");
|
if (help_mode || family == "pp3") {
|
||||||
|
run("muxcover -mux8 -mux4", "(for pp3)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("map_ffs")) {
|
if (check_label("map_ffs")) {
|
||||||
run("opt_expr");
|
run("opt_expr");
|
||||||
run("dfflegalize -cell $_DFFSRE_PPPP_ 0 -cell $_DLATCH_?_ x");
|
if (help_mode) {
|
||||||
|
run("shregmap -minlen <min> -maxlen <max>", "(for qlf_k6n10f)");
|
||||||
run(stringf("techmap -map +/quicklogic/%s/cells_map.v -map +/quicklogic/%s/ffs_map.v", family.c_str(), family.c_str()));
|
run("dfflegalize -cell <supported FF types>");
|
||||||
|
run("techmap -map " + lib_path + family + "/cells_map.v", "(for pp3)");
|
||||||
run("opt_expr -mux_undef");
|
}
|
||||||
|
if (family == "pp3") {
|
||||||
|
run("dfflegalize -cell $_DFFSRE_PPPP_ 0 -cell $_DLATCH_?_ x");
|
||||||
|
run("techmap -map " + lib_path + family + "/cells_map.v -map " + lib_path + family + "/ffs_map.v");
|
||||||
|
run("opt_expr -mux_undef");
|
||||||
|
} else if (family == "qlf_k6n10f") {
|
||||||
|
run("shregmap -minlen 8 -maxlen 20");
|
||||||
|
// FIXME: Apparently dfflegalize leaves around $_DLATCH_[NP]_ even if
|
||||||
|
// not in the allowed set. As a workaround we put them in the allowed
|
||||||
|
// set explicitly and map them later to $_DLATCHSR_[NP]NN_.
|
||||||
|
run("dfflegalize -cell $_DFFSRE_?NNP_ 0 -cell $_DLATCHSR_?NN_ 0 -cell $_DLATCH_?_ 0" " -cell $_SDFFE_?N?P_ 0");
|
||||||
|
}
|
||||||
|
run("opt");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("map_luts")) {
|
if (check_label("map_luts", "(for pp3)") && (help_mode || family == "pp3")) {
|
||||||
run(stringf("techmap -map +/quicklogic/%s/latches_map.v", family.c_str()));
|
run("techmap -map " + lib_path + family + "/latches_map.v");
|
||||||
if (abc9) {
|
if (abc9) {
|
||||||
run(stringf("read_verilog -lib -specify -icells +/quicklogic/%s/abc9_model.v", family.c_str()));
|
run("read_verilog -lib -specify -icells " + lib_path + family + "/abc9_model.v");
|
||||||
run(stringf("techmap -map +/quicklogic/%s/abc9_map.v", family.c_str()));
|
run("techmap -map " + lib_path + family + "/abc9_map.v");
|
||||||
run("abc9 -maxlut 4 -dff");
|
run("abc9 -maxlut 4 -dff");
|
||||||
run(stringf("techmap -map +/quicklogic/%s/abc9_unmap.v", family.c_str()));
|
run("techmap -map " + lib_path + family + "/abc9_unmap.v");
|
||||||
} else {
|
} else {
|
||||||
run("abc -luts 1,2,2,4 -dress");
|
run("abc -luts 1,2,2,4 -dress");
|
||||||
}
|
}
|
||||||
run("clean");
|
run("clean");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("map_cells")) {
|
if (check_label("map_luts", "(for qlf_k6n10f)") && (help_mode || family == "qlf_k6n10f")) {
|
||||||
run(stringf("techmap -map +/quicklogic/%s/lut_map.v", family.c_str()));
|
if (abc9) {
|
||||||
|
run("abc9 -maxlut 6");
|
||||||
|
} else {
|
||||||
|
run("abc -lut 6 -dress");
|
||||||
|
}
|
||||||
run("clean");
|
run("clean");
|
||||||
|
run("opt_lut");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_label("map_cells", "(for pp3)") && (help_mode || family == "pp3")) {
|
||||||
|
run("techmap -map " + lib_path + family + "/lut_map.v");
|
||||||
|
run("clean");
|
||||||
|
run("opt_lut");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("check")) {
|
if (check_label("check")) {
|
||||||
|
@ -224,14 +365,18 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
run("check -noinit");
|
run("check -noinit");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("iomap")) {
|
if (check_label("iomap", "(for pp3)") && (family == "pp3" || help_mode)) {
|
||||||
run("clkbufmap -inpad ckpad Q:P");
|
run("clkbufmap -inpad ckpad Q:P");
|
||||||
run("iopadmap -bits -outpad outpad A:P -inpad inpad Q:P -tinoutpad bipad EN:Q:A:P A:top");
|
run("iopadmap -bits -outpad outpad A:P -inpad inpad Q:P -tinoutpad bipad EN:Q:A:P A:top");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("finalize")) {
|
if (check_label("finalize")) {
|
||||||
run("setundef -zero -params -undriven");
|
if (help_mode || family == "pp3") {
|
||||||
run("hilomap -hicell logic_1 A -locell logic_0 A -singleton A:top");
|
run("setundef -zero -params -undriven", "(for pp3)");
|
||||||
|
}
|
||||||
|
if (family == "pp3" || !edif_file.empty()) {
|
||||||
|
run("hilomap -hicell logic_1 A -locell logic_0 A -singleton A:top", "(for pp3 or if -edif)");
|
||||||
|
}
|
||||||
run("opt_clean -purge");
|
run("opt_clean -purge");
|
||||||
run("check");
|
run("check");
|
||||||
run("blackbox =A:whitebox");
|
run("blackbox =A:whitebox");
|
||||||
|
|
Loading…
Reference in New Issue