//======================================================================
//
// Copyright (c) 2019, NORDUnet A/S All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// - Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// - Neither the name of the NORDUnet nor the names of its contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================
module modexpng_dsp_array_block
(
clk,
ce_a, ce_b, ce_m, ce_p, ce_mode,
mode_z,
a, b, p
);
`include "modexpng_parameters.vh"
`include "modexpng_dsp48e1.vh"
`include "modexpng_dsp_slice_primitive.vh"
input clk;
input ce_a;
input ce_b;
input ce_m;
input ce_p;
input ce_mode;
input [ NUM_MULTS_AUX -1:0] mode_z;
input [NUM_MULTS_HALF_AUX * WORD_EXT_W -1:0] a;
input [ WORD_W -1:0] b;
output [NUM_MULTS_AUX * MAC_W -1:0] p;
wire [DSP48E1_A_W -1:0] casc_a[0:NUM_MULTS_HALF-1];
wire [DSP48E1_B_W -1:0] casc_b[0:NUM_MULTS_HALF-1];
wire ce_a0 = ce_a;
reg ce_a1 = 1'b0;
reg ce_a2 = 1'b0;
wire ce_b0 = ce_b;
reg ce_b1 = 1'b0;
always @(posedge clk) begin
ce_a1 <= ce_a0;
ce_a2 <= ce_a1;
ce_b1 <= ce_b0;
end
genvar z;
generate for (z=0; z<NUM_MULTS_HALF; z=z+1)
//
begin : gen_DSP48E1
//
`MODEXPNG_DSP_SLICE #
(
.AB_INPUT("DIRECT"),
.B_REG(2)
)
dsp_direct
(
.clk (clk),
.ce_a1 (ce_a0),
.ce_b1 (ce_b0),
.ce_a2 (ce_a1),
.ce_b2 (ce_b1),
.ce_m (ce_m),
.ce_p (ce_p),
.ce_mode (ce_mode),
.a (a[z*WORD_EXT_W +: WORD_EXT_W]),
.b (b),
.p (p[(2*z)*MAC_W +: MAC_W]),
.inmode ({DSP48E1_INMODE_W{1'b0}}),
.opmode ({1'b0, mode_z[2*z], 1'b0, 2'b01, 2'b01}),
.alumode ({DSP48E1_ALUMODE_W{1'b0}}),
.casc_a_in (),
.casc_b_in (),
.casc_a_out (casc_a[z]),
.casc_b_out (casc_b[z])
);
//
`MODEXPNG_DSP_SLICE #
(
.AB_INPUT("CASCADE"),
.B_REG(1)
)
dsp_cascade
(
.clk (clk),
.ce_a1 (ce_a1),
.ce_b1 (1'b0),
.ce_a2 (ce_a2),
.ce_b2 (ce_b1),
.ce_m (ce_m),
.ce_p (ce_p),
.ce_mode (ce_mode),
.a (a[z*WORD_EXT_W +: WORD_EXT_W]),
.b (b),
.p (p[(2*z+1)*MAC_W +: MAC_W]),
.inmode ({DSP48E1_INMODE_W{1'b0}}),
.opmode ({1'b0, mode_z[2*z+1], 1'b0, 2'b01, 2'b01}),
.alumode ({DSP48E1_ALUMODE_W{1'b0}}),
.casc_a_in (casc_a[z]),
.casc_b_in (casc_b[z]),
.casc_a_out (),
.casc_b_out ()
);
//
end
//
endgenerate
`MODEXPNG_DSP_SLICE #
(
.AB_INPUT("DIRECT"),
.B_REG(2)
)
dsp_aux
(
.clk (clk),
.ce_a1 (ce_a0),
.ce_b1 (ce_b0),
.ce_a2 (ce_a1),
.ce_b2 (ce_b1),
.ce_m (ce_m),
.ce_p (ce_p),
.ce_mode (ce_mode),
.a (a[NUM_MULTS_HALF*WORD_EXT_W +: WORD_EXT_W]),
.b (b),
.p (p[(2*NUM_MULTS_HALF)*MAC_W +: MAC_W]),
.inmode ({DSP48E1_INMODE_W{1'b0}}),
.opmode ({1'b0, mode_z[2*NUM_MULTS_HALF], 1'b0, 2'b01, 2'b01}),
.alumode ({DSP48E1_ALUMODE_W{1'b0}}),
.casc_a_in (),
.casc_b_in (),
.casc_a_out (),
.casc_b_out ()
);
endmodule