diff options
Diffstat (limited to 'fpga/usrp3/lib/dsp/add_then_mac.v')
-rw-r--r-- | fpga/usrp3/lib/dsp/add_then_mac.v | 164 |
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 |