gateware: Wrap capture/counter units and allow use of SB_MAC16

We have a bunch of Multiply Add units that are un-used, we can
make use of the "accumulate" part to implement the few wide
counters we have to win some LCs.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
diff --git a/gateware/common/rtl/capcnt_sb_mac16.v b/gateware/common/rtl/capcnt_sb_mac16.v
new file mode 100644
index 0000000..a82e9d0
--- /dev/null
+++ b/gateware/common/rtl/capcnt_sb_mac16.v
@@ -0,0 +1,211 @@
+/*
+ * capcnt_sb_mac16.v
+ *
+ * Helper to use the SB_MAC16 as simple capture/counter blocks
+ *
+ * vim: ts=4 sw=4
+ *
+ * Copyright (C) 2020  Sylvain Munaut <tnt@246tNt.com>
+ * SPDX-License-Identifier: CERN-OHL-P-2.0
+ */
+
+`default_nettype none
+
+module capcnt16_sb_mac16 (
+	output wire [15:0] cnt_cur,
+	output wire [15:0] cnt_cap,
+	input  wire        inc,
+	input  wire        cap,
+	input  wire        clk,
+	input  wire        rst
+);
+
+	// TOP = Count
+	// Top unit configured as 16 bit accumulator with fixed carry=1 input.
+	// Most of input/registers are HOLD=1 and forced to reset. The output
+	// register HOLD input is used for conditional increment.
+	//
+	// BOT = Capture
+	// Bottom unit is configured for the output register to do fixed loading
+	// from D input which is wired to the current counter value. HOLD input
+	// used for capture.
+
+	SB_MAC16 #(
+		.NEG_TRIGGER             (1'b0),
+		.C_REG                   (1'b1),
+		.A_REG                   (1'b1),
+		.B_REG                   (1'b1),
+		.D_REG                   (1'b0),
+		.TOP_8x8_MULT_REG        (1'b1),
+		.BOT_8x8_MULT_REG        (1'b1),
+		.PIPELINE_16x16_MULT_REG1(1'b1),
+		.PIPELINE_16x16_MULT_REG2(1'b1),
+		.TOPOUTPUT_SELECT        (2'b01),
+		.TOPADDSUB_LOWERINPUT    (2'b00),
+		.TOPADDSUB_UPPERINPUT    (1'b0),
+		.TOPADDSUB_CARRYSELECT   (2'b01),
+		.BOTOUTPUT_SELECT        (2'b01),
+		.BOTADDSUB_LOWERINPUT    (2'b00),
+		.BOTADDSUB_UPPERINPUT    (1'b0),
+		.BOTADDSUB_CARRYSELECT   (2'b00),
+		.MODE_8x8                (1'b1),
+		.A_SIGNED                (1'b0),
+		.B_SIGNED                (1'b0)
+	) mac_I (
+		.CLK        (clk),
+		.CE         (1'b1),
+		.C          (16'h0000),
+		.A          (16'h0000),
+		.B          (16'h0000),
+		.D          (cnt_cur),
+		.AHOLD      (1'b1),
+		.BHOLD      (1'b1),
+		.CHOLD      (1'b1),
+		.DHOLD      (1'b1),
+		.IRSTTOP    (1'b1),
+		.IRSTBOT    (1'b1),
+		.ORSTTOP    (rst),
+		.ORSTBOT    (rst),
+		.OLOADTOP   (1'b0),
+		.OLOADBOT   (1'b1),
+		.ADDSUBTOP  (1'b0),
+		.ADDSUBBOT  (1'b0),
+		.OHOLDTOP   (~inc),
+		.OHOLDBOT   (~cap),
+		.CI         (),
+		.ACCUMCI    (),
+		.SIGNEXTIN  (),
+		.O          ({cnt_cur, cnt_cap}),
+		.CO         (),
+		.ACCUMCO    (),
+		.SIGNEXTOUT ()
+	);
+
+endmodule // capcnt16_sb_mac16
+
+
+module capcnt32_sb_mac16 (
+	output wire [31:0] cnt_cur,
+	output wire [31:0] cnt_cap,
+	input  wire        inc,
+	input  wire        cap,
+	input  wire        clk,
+	input  wire        rst
+);
+
+	// Counting
+	// --------
+	// Hi/Lo configured as 32 bit accumulator adding a constant carry=1
+	// at every cycle. Most register are held in reset and with HOLD=1.
+	// HOLD input on Output reg used to implement conditional 'increment'.
+
+	SB_MAC16 #(
+		.NEG_TRIGGER             (1'b0),
+		.C_REG                   (1'b1),
+		.A_REG                   (1'b1),
+		.B_REG                   (1'b1),
+		.D_REG                   (1'b1),
+		.TOP_8x8_MULT_REG        (1'b1),
+		.BOT_8x8_MULT_REG        (1'b1),
+		.PIPELINE_16x16_MULT_REG1(1'b1),
+		.PIPELINE_16x16_MULT_REG2(1'b1),
+		.TOPOUTPUT_SELECT        (2'b01),
+		.TOPADDSUB_LOWERINPUT    (2'b00),
+		.TOPADDSUB_UPPERINPUT    (1'b0),
+		.TOPADDSUB_CARRYSELECT   (2'b10),
+		.BOTOUTPUT_SELECT        (2'b01),
+		.BOTADDSUB_LOWERINPUT    (2'b00),
+		.BOTADDSUB_UPPERINPUT    (1'b0),
+		.BOTADDSUB_CARRYSELECT   (2'b01),
+		.MODE_8x8                (1'b1),
+		.A_SIGNED                (1'b0),
+		.B_SIGNED                (1'b0)
+	) cnt_mac_I (
+		.CLK        (clk),
+		.CE         (1'b1),
+		.C          (16'h0000),
+		.A          (16'h0000),
+		.B          (16'h0000),
+		.D          (16'h0000),
+		.AHOLD      (1'b1),
+		.BHOLD      (1'b1),
+		.CHOLD      (1'b1),
+		.DHOLD      (1'b1),
+		.IRSTTOP    (1'b1),
+		.IRSTBOT    (1'b1),
+		.ORSTTOP    (rst),
+		.ORSTBOT    (rst),
+		.OLOADTOP   (1'b0),
+		.OLOADBOT   (1'b0),
+		.ADDSUBTOP  (1'b0),
+		.ADDSUBBOT  (1'b0),
+		.OHOLDTOP   (~inc),
+		.OHOLDBOT   (~inc),
+		.CI         (),
+		.ACCUMCI    (),
+		.SIGNEXTIN  (),
+		.O          (cnt_cur),
+		.CO         (),
+		.ACCUMCO    (),
+		.SIGNEXTOUT ()
+	);
+
+
+	// Capture
+	// -------
+	// Output register is used to capture the value.
+	// It's loaded from {C,D} and using HOLD on the output
+	// register to implement capture trigger.
+
+	SB_MAC16 #(
+		.NEG_TRIGGER             (1'b0),
+		.C_REG                   (1'b0),
+		.A_REG                   (1'b1),
+		.B_REG                   (1'b1),
+		.D_REG                   (1'b0),
+		.TOP_8x8_MULT_REG        (1'b1),
+		.BOT_8x8_MULT_REG        (1'b1),
+		.PIPELINE_16x16_MULT_REG1(1'b1),
+		.PIPELINE_16x16_MULT_REG2(1'b1),
+		.TOPOUTPUT_SELECT        (2'b01),
+		.TOPADDSUB_LOWERINPUT    (2'b00),
+		.TOPADDSUB_UPPERINPUT    (1'b0),
+		.TOPADDSUB_CARRYSELECT   (2'b00),
+		.BOTOUTPUT_SELECT        (2'b01),
+		.BOTADDSUB_LOWERINPUT    (2'b00),
+		.BOTADDSUB_UPPERINPUT    (1'b0),
+		.BOTADDSUB_CARRYSELECT   (2'b00),
+		.MODE_8x8                (1'b1),
+		.A_SIGNED                (1'b0),
+		.B_SIGNED                (1'b0)
+	) cap_mac_I (
+		.CLK        (clk),
+		.CE         (1'b1),
+		.C          (cnt_cur[31:16]),
+		.A          (16'h0000),
+		.B          (16'h0000),
+		.D          (cnt_cur[15:0]),
+		.AHOLD      (1'b1),
+		.BHOLD      (1'b1),
+		.CHOLD      (1'b1),
+		.DHOLD      (1'b1),
+		.IRSTTOP    (1'b1),
+		.IRSTBOT    (1'b1),
+		.ORSTTOP    (rst),
+		.ORSTBOT    (rst),
+		.OLOADTOP   (1'b1),
+		.OLOADBOT   (1'b1),
+		.ADDSUBTOP  (1'b0),
+		.ADDSUBBOT  (1'b0),
+		.OHOLDTOP   (~cap),
+		.OHOLDBOT   (~cap),
+		.CI         (),
+		.ACCUMCI    (),
+		.SIGNEXTIN  (),
+		.O          (cnt_cap),
+		.CO         (),
+		.ACCUMCO    (),
+		.SIGNEXTOUT ()
+	);
+
+endmodule // capcnt32_sb_mac16