summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2015-04-24 00:06:50 +0200
committerClifford Wolf <clifford@clifford.at>2015-04-24 00:06:50 +0200
commitd6f7698f591aa1957e263e13b66d0d808cf5a478 (patch)
treefd9e91d00c95ffb5eb6c0cd1797acd151721b724
parent11f77205f571cf4afb2ef3ba298444c2596cd81d (diff)
Added ice40 bram support
-rw-r--r--techlibs/ice40/Makefile.inc2
-rw-r--r--techlibs/ice40/brams.txt40
-rw-r--r--techlibs/ice40/brams_map.v99
-rw-r--r--techlibs/ice40/synth_ice40.cc52
4 files changed, 192 insertions, 1 deletions
diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc
index cd178d66..14ef4e7d 100644
--- a/techlibs/ice40/Makefile.inc
+++ b/techlibs/ice40/Makefile.inc
@@ -5,4 +5,6 @@ OBJS += techlibs/ice40/ice40_ffssr.o
$(eval $(call add_share_file,share/ice40,techlibs/ice40/arith_map.v))
$(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_map.v))
$(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v))
diff --git a/techlibs/ice40/brams.txt b/techlibs/ice40/brams.txt
new file mode 100644
index 00000000..5d23ad16
--- /dev/null
+++ b/techlibs/ice40/brams.txt
@@ -0,0 +1,40 @@
+bram $__ICE40_RAM4K_M0
+ init 0
+ abits 8
+ dbits 16
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 0 16
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+bram $__ICE40_RAM4K_M123
+ init 0
+ abits 9 @M1
+ dbits 8 @M1
+ abits 10 @M2
+ dbits 4 @M2
+ abits 11 @M3
+ dbits 2 @M3
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 0 1
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+match $__ICE40_RAM4K_M0
+ min efficiency 10
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__ICE40_RAM4K_M123
+ min efficiency 10
+ make_transp
+endmatch
diff --git a/techlibs/ice40/brams_map.v b/techlibs/ice40/brams_map.v
new file mode 100644
index 00000000..9dbc81e3
--- /dev/null
+++ b/techlibs/ice40/brams_map.v
@@ -0,0 +1,99 @@
+
+module \$__ICE40_RAM4K_M0 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
+ parameter [0:0] CLKPOL2 = 1;
+ parameter [0:0] CLKPOL3 = 1;
+
+ input CLK2;
+ input CLK3;
+
+ input [7:0] A1ADDR;
+ output [15:0] A1DATA;
+
+ input [7:0] B1ADDR;
+ input [15:0] B1DATA;
+ input [15:0] B1EN;
+
+ wire [10:0] A1ADDR_11 = A1ADDR;
+ wire [10:0] B1ADDR_11 = B1ADDR;
+
+ generate
+ case ({CLKPOL2, CLKPOL3})
+ 2'b00:
+ SB_RAM40_4KNRNW #(.WRITE_MODE(0), .READ_MODE(0)) _TECHMAP_REPLACE_ (
+ .RDATA(A1DATA), .RADDR(A1ADDR_11), .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+ .WDATA(B1DATA), .WADDR(B1ADDR_11), .WMASK(B1EN), .WCLK(CLK3), .WCLKE(1'b1), .WE(|B1EN)
+ );
+ 2'b01:
+ SB_RAM40_4KNR #(.WRITE_MODE(0), .READ_MODE(0)) _TECHMAP_REPLACE_ (
+ .RDATA(A1DATA), .RADDR(A1ADDR_11), .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+ .WDATA(B1DATA), .WADDR(B1ADDR_11), .WMASK(B1EN), .WCLK(CLK3), .WCLKE(1'b1), .WE(|B1EN)
+ );
+ 2'b10:
+ SB_RAM40_4KNW #(.WRITE_MODE(0), .READ_MODE(0)) _TECHMAP_REPLACE_ (
+ .RDATA(A1DATA), .RADDR(A1ADDR_11), .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+ .WDATA(B1DATA), .WADDR(B1ADDR_11), .WMASK(B1EN), .WCLK(CLK3), .WCLKE(1'b1), .WE(|B1EN)
+ );
+ 2'b11:
+ SB_RAM40_4K #(.WRITE_MODE(0), .READ_MODE(0)) _TECHMAP_REPLACE_ (
+ .RDATA(A1DATA), .RADDR(A1ADDR_11), .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+ .WDATA(B1DATA), .WADDR(B1ADDR_11), .WMASK(B1EN), .WCLK(CLK3), .WCLKE(1'b1), .WE(|B1EN)
+ );
+ endcase
+ endgenerate
+endmodule
+
+module \$__ICE40_RAM4K_M123 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 9;
+ parameter CFG_DBITS = 8;
+
+ parameter [0:0] CLKPOL2 = 1;
+ parameter [0:0] CLKPOL3 = 1;
+
+ localparam MODE =
+ CFG_ABITS == 9 ? 1 :
+ CFG_ABITS == 10 ? 2 :
+ CFG_ABITS == 11 ? 3 : 'bx;
+
+ input CLK2;
+ input CLK3;
+
+ input [CFG_ABITS-1:0] A1ADDR;
+ output [CFG_DBITS-1:0] A1DATA;
+
+ input [CFG_ABITS-1:0] B1ADDR;
+ input [CFG_DBITS-1:0] B1DATA;
+ input B1EN;
+
+ wire [10:0] A1ADDR_11 = A1ADDR;
+ wire [10:0] B1ADDR_11 = B1ADDR;
+
+ wire [15:0] A1DATA_16;
+ wire [15:0] B1DATA_16 = B1DATA;
+ assign A1DATA = A1DATA_16;
+
+ generate
+ case ({CLKPOL2, CLKPOL3})
+ 2'b00:
+ SB_RAM40_4KNRNW #(.WRITE_MODE(MODE), .READ_MODE(MODE)) _TECHMAP_REPLACE_ (
+ .RDATA(A1DATA_16), .RADDR(A1ADDR_11), .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+ .WDATA(B1DATA_16), .WADDR(B1ADDR_11), .WCLK(CLK3), .WCLKE(1'b1), .WE(B1EN)
+ );
+ 2'b01:
+ SB_RAM40_4KNR #(.WRITE_MODE(MODE), .READ_MODE(MODE)) _TECHMAP_REPLACE_ (
+ .RDATA(A1DATA_16), .RADDR(A1ADDR_11), .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+ .WDATA(B1DATA_16), .WADDR(B1ADDR_11), .WCLK(CLK3), .WCLKE(1'b1), .WE(B1EN)
+ );
+ 2'b10:
+ SB_RAM40_4RNW #(.WRITE_MODE(MODE), .READ_MODE(MODE)) _TECHMAP_REPLACE_ (
+ .RDATA(A1DATA_16), .RADDR(A1ADDR_11), .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+ .WDATA(B1DATA_16), .WADDR(B1ADDR_11), .WCLK(CLK3), .WCLKE(1'b1), .WE(B1EN)
+ );
+ 2'b11:
+ SB_RAM40_4K #(.WRITE_MODE(MODE), .READ_MODE(MODE)) _TECHMAP_REPLACE_ (
+ .RDATA(A1DATA_16), .RADDR(A1ADDR_11), .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+ .WDATA(B1DATA_16), .WADDR(B1ADDR_11), .WCLK(CLK3), .WCLKE(1'b1), .WE(B1EN)
+ );
+ endcase
+ endgenerate
+endmodule
+
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index dff12f8a..bb0e5d4a 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -52,6 +52,18 @@ struct SynthIce40Pass : public Pass {
log(" from label is synonymous to 'begin', and empty to label is\n");
log(" synonymous to the end of the command list.\n");
log("\n");
+ log(" -flatten\n");
+ log(" flatten design before synthesis\n");
+ log("\n");
+ log(" -retime\n");
+ log(" run 'abc' with -dff option\n");
+ log("\n");
+ log(" -nocarry\n");
+ log(" do not use SB_CARRY cells in output netlist\n");
+ log("\n");
+ log(" -nobram\n");
+ log(" do not use SB_RAM40_4K* cells in output netlist\n");
+ log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
log("\n");
@@ -59,14 +71,23 @@ struct SynthIce40Pass : public Pass {
log(" read_verilog -lib +/ice40/cells_sim.v\n");
log(" hierarchy -check -top <top>\n");
log("\n");
+ log(" flatten: (only if -flatten)\n");
+ log(" proc\n");
+ log(" flatten\n");
+ log("\n");
log(" coarse:\n");
log(" synth -run coarse\n");
log("\n");
+ log(" bram: (skip if -nobram)\n");
+ log(" memory_bram -rules +/ice40/brams.txt\n");
+ log(" techmap -map +/ice40/brams_map.v\n");
+ log("\n");
log(" fine:\n");
log(" opt -fast -mux_undef -undriven -fine\n");
log(" memory_map\n");
log(" opt -undriven -fine\n");
- log(" techmap -map +/techmap.v -map +/ice40/arith_map.v\n");
+ log(" techmap -map +/techmap.v [-map +/ice40/arith_map.v]\n");
+ log(" abc -dff (only if -retime)\n");
log(" opt -fast\n");
log("\n");
log(" map_ffs:\n");
@@ -96,6 +117,9 @@ struct SynthIce40Pass : public Pass {
std::string top_opt = "-auto-top";
std::string run_from, run_to;
bool nocarry = false;
+ bool nobram = false;
+ bool flatten = false;
+ bool retime = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -112,10 +136,22 @@ struct SynthIce40Pass : public Pass {
run_to = args[argidx].substr(pos+1);
continue;
}
+ if (args[argidx] == "-flatten") {
+ flatten = true;
+ continue;
+ }
+ if (args[argidx] == "-retime") {
+ retime = true;
+ continue;
+ }
if (args[argidx] == "-nocarry") {
nocarry = true;
continue;
}
+ if (args[argidx] == "-nobram") {
+ nobram = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -134,11 +170,23 @@ struct SynthIce40Pass : public Pass {
Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str()));
}
+ if (flatten && check_label(active, run_from, run_to, "flatten"))
+ {
+ Pass::call(design, "proc");
+ Pass::call(design, "flatten");
+ }
+
if (check_label(active, run_from, run_to, "coarse"))
{
Pass::call(design, "synth -run coarse");
}
+ if (!nobram && check_label(active, run_from, run_to, "bram"))
+ {
+ Pass::call(design, "memory_bram -rules +/ice40/brams.txt");
+ Pass::call(design, "techmap -map +/ice40/brams_map.v");
+ }
+
if (check_label(active, run_from, run_to, "fine"))
{
Pass::call(design, "opt -fast -mux_undef -undriven -fine");
@@ -148,6 +196,8 @@ struct SynthIce40Pass : public Pass {
Pass::call(design, "techmap");
else
Pass::call(design, "techmap -map +/techmap.v -map +/ice40/arith_map.v");
+ if (retime)
+ Pass::call(design, "abc -dff");
Pass::call(design, "opt -fast");
}