aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/dsp/add_then_mac.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/dsp/add_then_mac.v')
-rw-r--r--fpga/usrp3/lib/dsp/add_then_mac.v164
1 files changed, 164 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/dsp/add_then_mac.v b/fpga/usrp3/lib/dsp/add_then_mac.v
new file mode 100644
index 000000000..b56d9e9d4
--- /dev/null
+++ b/fpga/usrp3/lib/dsp/add_then_mac.v
@@ -0,0 +1,164 @@
+//
+// Copyright 2015 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+`timescale 1 ps / 1 ps
+
+//
+// Implements acc=((a+d)*b)+c or acc=((a+d)*b)+acc'
+//
+
+module add_then_mac
+ #(parameter DEVICE = "VIRTEX6")
+ (
+ // Output ports
+ output [47:0] acc,
+
+ // Input ports
+ input carryin,
+ input ce,
+ input clk,
+ input [17:0] b,
+ input load,
+ input [47:0] c,
+ input [17:0] a,
+ input [17:0] d,
+ input rst
+ );
+
+
+ wire [24:0] a_in;
+ wire [24:0] d_in;
+
+ localparam AREG_IN = 1;
+ localparam BREG_IN = 1;
+ localparam MREG_IN = 1;
+ localparam PREG_IN = 1;
+ localparam A1REG_IN = 1;
+ localparam A0REG_IN = 0;
+ localparam B1REG_IN = 1;
+ localparam B0REG_IN = 1;
+
+ // Sign extend inputs
+ assign a_in = (a[17] == 1'b1) ? {7'hff, a} : {7'h00, a};
+ assign d_in = (d[17] == 1'b1) ? {7'hff, d} : {7'h00, d};
+
+ generate
+ case(DEVICE)
+ // begin generate virtex6
+ "VIRTEX6", "7SERIES" :
+ begin
+ DSP48E1 #(
+ .ACASCREG(AREG_IN),
+ .AREG(AREG_IN),
+ .BCASCREG(BREG_IN),
+ .BREG(BREG_IN),
+ .MREG(MREG_IN),
+ .PREG(PREG_IN),
+ .USE_DPORT("TRUE")
+ )
+ DSP48E_BL (
+ .ACOUT(),
+ .BCOUT(),
+ .CARRYCASCOUT(),
+ .CARRYOUT(),
+ .MULTSIGNOUT(),
+ .OVERFLOW(),
+ .P(acc),
+ .PATTERNBDETECT(),
+ .PATTERNDETECT(),
+ .PCOUT(),
+ .UNDERFLOW(),
+ .A({5'b0, a_in[24:0]}),
+ .ACIN(30'b0),
+ .ALUMODE(4'b0000),
+ .B(b[17:0]),
+ .BCIN(18'b0),
+ .C(c),
+ .CARRYCASCIN(1'b0),
+ .CARRYIN(carryin),
+ .CARRYINSEL(3'b0),
+ .CEA1(1'b0),
+ .CEA2(ce),
+ .CEAD(ce),
+ .CEALUMODE(ce),
+ .CEB1(1'b0),
+ .CEB2(ce),
+ .CEC(ce),
+ .CECARRYIN(ce),
+ .CECTRL(ce),
+ .CED(ce),
+ .CEINMODE(ce),
+ .CEM(ce),
+ .CEP(ce),
+ .CLK(clk),
+ .D(d_in[24:0]),
+ .INMODE(5'b00100),
+ .MULTSIGNIN(1'b0),
+ .OPMODE({2'b01,load,4'b0101}),
+ .PCIN(48'b0),
+ .RSTA(rst),
+ .RSTALLCARRYIN(rst),
+ .RSTALUMODE(rst),
+ .RSTB(rst),
+ .RSTC(rst),
+ .RSTCTRL(rst),
+ .RSTD(rst),
+ .RSTINMODE(rst),
+ .RSTM(rst),
+ .RSTP(rst)
+ );
+ end // end generate virtex6
+ // begin generate spartan6
+ "SPARTAN6" :
+ begin
+ // DSP48A1 has 18b+18b=18b pre-adder, must discard LSB of A and D and compensate by shifting ACC.
+ wire discard;;
+ assign acc[0] = 1'b0;
+
+ DSP48A1 #(
+ .A0REG(A0REG_IN),
+ .A1REG(A1REG_IN),
+ .B0REG(B0REG_IN),
+ .B1REG(B1REG_IN),
+ .MREG(MREG_IN),
+ .PREG(PREG_IN)
+ )
+ DSP48AST (
+ .BCOUT(),
+ .CARRYOUT(),
+ .CARRYOUTF(),
+ .M(),
+ .P({discard,acc[47:1]}),
+ .PCOUT(),
+ .A(b[17:0]),
+ .B({a_in[17],a_in[17:1]}),
+ .C(c),
+ .CARRYIN(carryin),
+ .CEA(ce),
+ .CEB(ce),
+ .CEC(ce),
+ .CECARRYIN(ce),
+ .CED(ce),
+ .CEM(ce),
+ .CEOPMODE(ce),
+ .CEP(ce),
+ .CLK(clk),
+ .D({d_in[17],d_in[17:1]}),
+ .OPMODE({5'b00011,load, 2'b01}),
+ .PCIN(48'b0),
+ .RSTA(rst),
+ .RSTB(rst),
+ .RSTC(rst),
+ .RSTCARRYIN(rst),
+ .RSTD(rst),
+ .RSTM(rst),
+ .RSTOPMODE(rst),
+ .RSTP(rst)
+ );
+ end // end generate spartan6
+ endcase
+ endgenerate
+endmodule