coolrunner2: Use extract_counter to optimize counters
authorR. Ou <rqou@robertou.com>
Mon, 17 Feb 2020 11:07:16 +0000 (03:07 -0800)
committerR. Ou <rqou@robertou.com>
Mon, 17 Feb 2020 11:09:40 +0000 (03:09 -0800)
This tends to make much more efficient pterm usage compared to just
throwing the problem at ABC

techlibs/coolrunner2/Makefile.inc
techlibs/coolrunner2/cells_counter_map.v [new file with mode: 0644]
techlibs/coolrunner2/synth_coolrunner2.cc

index d62c9960c7039d150b51902b655ff94e2954ca11..c879e95cdf53deabe69835cb77e0176173f13813 100644 (file)
@@ -4,5 +4,6 @@ OBJS += techlibs/coolrunner2/coolrunner2_sop.o
 
 $(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/cells_latch.v))
 $(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/cells_sim.v))
+$(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/cells_counter_map.v))
 $(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/tff_extract.v))
 $(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/xc2_dff.lib))
diff --git a/techlibs/coolrunner2/cells_counter_map.v b/techlibs/coolrunner2/cells_counter_map.v
new file mode 100644 (file)
index 0000000..b474fa5
--- /dev/null
@@ -0,0 +1,161 @@
+module \$__COUNT_ (CE, CLK, OUT, POUT, RST, UP);
+
+    input wire CE;
+    input wire CLK;
+    output wire OUT;
+    output wire[WIDTH-1:0] POUT;
+    input wire RST;
+    input wire UP;
+
+    parameter COUNT_TO = 1;
+    parameter RESET_MODE = "RISING";
+    parameter RESET_TO_MAX = 0;
+    parameter HAS_POUT = 0;
+    parameter HAS_CE = 0;
+    parameter WIDTH = 8;
+    parameter DIRECTION = "DOWN";
+
+    if (DIRECTION == "UP") begin
+        if (WIDTH < 2) begin
+            initial begin
+                $display("ERROR: \$__COUNT_ must be at least 2 bits wide (bug in extract_counter pass?).");
+                $finish;
+            end
+        end
+
+        // FIXME: Max width?
+
+        assign OUT = POUT == COUNT_TO;
+
+        if (HAS_CE) begin
+            genvar i;
+            for (i = 0; i < WIDTH; i++) begin: countbits
+                // each bit = (cur & !reset) ^ (all prev & !reset)
+                wire xor_to_mc_bitn;
+                FDCP #(
+                    .INIT(0)
+                ) bitn_ff (
+                    .C(CLK),
+                    .CLR(0),
+                    .D(xor_to_mc_bitn),
+                    .PRE(0),
+                    .Q(POUT[i])
+                );
+                wire orterm_to_xor_bitn;
+                wire pterm0_to_or_bitn;
+                wire pterm1_to_or_bitn;
+                MACROCELL_XOR #(
+                    .INVERT_OUT(0)
+                ) bitn_xor (
+                    .IN_ORTERM(orterm_to_xor_bitn),
+                    .IN_PTC(pterm1_to_or_bitn),
+                    .OUT(xor_to_mc_bitn)
+                );
+                ORTERM #(
+                    .WIDTH(1)
+                ) bitn_or (
+                    .IN(pterm0_to_or_bitn),
+                    .OUT(orterm_to_xor_bitn)
+                );
+                ANDTERM #(
+                    .COMP_INP(1),
+                    .TRUE_INP(1)
+                ) bitn_pterm0 (
+                    .IN(POUT[i]),
+                    .IN_B(OUT),
+                    .OUT(pterm0_to_or_bitn)
+                );
+                ANDTERM #(
+                    .COMP_INP(1),
+                    .TRUE_INP(i + 1)
+                ) bitn_pterm1 (
+                    .IN({POUT[i-1:0], CE}),
+                    .IN_B(OUT),
+                    .OUT(pterm1_to_or_bitn)
+                );
+            end
+        end else begin
+            // Bit0 is special; toggle unless reset
+            // cur  reset           out
+            // 0    0               1
+            // 0    1               0
+            // 1    0               0
+            // 1    1               0
+            wire xor_to_mc_bit0;
+            FDCP #(
+                .INIT(0)
+            ) bit0_ff (
+                .C(CLK),
+                .CLR(0),
+                .D(xor_to_mc_bit0),
+                .PRE(0),
+                .Q(POUT[0])
+            );
+            wire pterm_to_xor_bit0;
+            MACROCELL_XOR #(
+                .INVERT_OUT(0)
+            ) bit0_xor (
+                .IN_PTC(pterm_to_xor_bit0),
+                .OUT(xor_to_mc_bit0)
+            );
+            ANDTERM #(
+                .COMP_INP(2),
+                .TRUE_INP(0)
+            ) bit0_pterm (
+                .IN(),
+                .IN_B({POUT[0], OUT}),
+                .OUT(pterm_to_xor_bit0)
+            );
+
+            genvar i;
+            for (i = 1; i < WIDTH; i++) begin: countbits
+                // each bit = (cur & !reset) ^ (all prev & !reset)
+                wire xor_to_mc_bitn;
+                FDCP #(
+                    .INIT(0)
+                ) bitn_ff (
+                    .C(CLK),
+                    .CLR(0),
+                    .D(xor_to_mc_bitn),
+                    .PRE(0),
+                    .Q(POUT[i])
+                );
+                wire orterm_to_xor_bitn;
+                wire pterm0_to_or_bitn;
+                wire pterm1_to_or_bitn;
+                MACROCELL_XOR #(
+                    .INVERT_OUT(0)
+                ) bitn_xor (
+                    .IN_ORTERM(orterm_to_xor_bitn),
+                    .IN_PTC(pterm1_to_or_bitn),
+                    .OUT(xor_to_mc_bitn)
+                );
+                ORTERM #(
+                    .WIDTH(1)
+                ) bitn_or (
+                    .IN(pterm0_to_or_bitn),
+                    .OUT(orterm_to_xor_bitn)
+                );
+                ANDTERM #(
+                    .COMP_INP(1),
+                    .TRUE_INP(1)
+                ) bitn_pterm0 (
+                    .IN(POUT[i]),
+                    .IN_B(OUT),
+                    .OUT(pterm0_to_or_bitn)
+                );
+                ANDTERM #(
+                    .COMP_INP(1),
+                    .TRUE_INP(i)
+                ) bitn_pterm1 (
+                    .IN(POUT[i-1:0]),
+                    .IN_B(OUT),
+                    .OUT(pterm1_to_or_bitn)
+                );
+            end
+        end
+    end
+
+    // FIXME: down counters
+
+endmodule
index 3bac8623d184e8dbf6f394c5c91991a5235cfb8d..fa9105e3463625529e156f264f22aa86ea796e7f 100644 (file)
@@ -143,6 +143,9 @@ struct SynthCoolrunner2Pass : public ScriptPass
 
                if (check_label("fine"))
                {
+                       run("extract_counter -dir up -allow_arst no");
+                       run("techmap -map +/coolrunner2/cells_counter_map.v");
+                       run("clean");
                        run("opt -fast -full");
                        run("techmap -map +/techmap.v -map +/coolrunner2/cells_latch.v");
                        run("opt -fast");