//======================================================================
//
// Copyright: 2019, The Commons Conservancy Cryptech Project
// SPDX-License-Identifier: BSD-3-Clause
//
// 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 copyright holder 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_storage_block
(
clk, rst_n,
wr_wide_xy_ena,
wr_wide_xy_bank,
wr_wide_xy_addr,
wr_wide_x_din,
wr_wide_y_din,
wr_narrow_xy_ena,
wr_narrow_xy_bank,
wr_narrow_xy_addr,
wr_narrow_x_din,
wr_narrow_y_din,
rd_wide_xy_ena,
rd_wide_xy_ena_aux,
rd_wide_xy_bank,
rd_wide_xy_bank_aux,
rd_wide_xy_addr,
rd_wide_xy_addr_aux,
rd_wide_x_dout,
rd_wide_y_dout,
rd_wide_x_dout_aux,
rd_wide_y_dout_aux,
rd_narrow_xy_ena,
rd_narrow_xy_bank,
rd_narrow_xy_addr,
rd_narrow_x_dout,
rd_narrow_y_dout,
wrk_wide_xy_ena,
wrk_wide_xy_bank,
wrk_wide_xy_addr,
wrk_wide_x_dout,
wrk_wide_y_dout,
wrk_narrow_xy_ena,
wrk_narrow_xy_bank,
wrk_narrow_xy_addr,
wrk_narrow_x_dout,
wrk_narrow_y_dout
);
//
// Headers
//
`include "modexpng_parameters.vh"
`include "modexpng_storage_primitives.vh"
//
// Ports
//
input clk;
input rst_n;
input wr_wide_xy_ena;
input [ BANK_ADDR_W -1:0] wr_wide_xy_bank;
input [ OP_ADDR_W -1:0] wr_wide_xy_addr;
input [ WORD_EXT_W -1:0] wr_wide_x_din;
input [ WORD_EXT_W -1:0] wr_wide_y_din;
input wr_narrow_xy_ena;
input [ BANK_ADDR_W -1:0] wr_narrow_xy_bank;
input [ OP_ADDR_W -1:0] wr_narrow_xy_addr;
input [ WORD_EXT_W -1:0] wr_narrow_x_din;
input [ WORD_EXT_W -1:0] wr_narrow_y_din;
input rd_wide_xy_ena;
input rd_wide_xy_ena_aux;
input [ BANK_ADDR_W -1:0] rd_wide_xy_bank;
input [ BANK_ADDR_W -1:0] rd_wide_xy_bank_aux;
input [ NUM_MULTS_HALF * OP_ADDR_W -1:0] rd_wide_xy_addr;
input [ OP_ADDR_W -1:0] rd_wide_xy_addr_aux;
output [ NUM_MULTS_HALF * WORD_EXT_W -1:0] rd_wide_x_dout;
output [ NUM_MULTS_HALF * WORD_EXT_W -1:0] rd_wide_y_dout;
output [ WORD_EXT_W -1:0] rd_wide_x_dout_aux;
output [ WORD_EXT_W -1:0] rd_wide_y_dout_aux;
input rd_narrow_xy_ena;
input [ BANK_ADDR_W -1:0] rd_narrow_xy_bank;
input [ OP_ADDR_W -1:0] rd_narrow_xy_addr;
output [ WORD_EXT_W -1:0] rd_narrow_x_dout;
output [ WORD_EXT_W -1:0] rd_narrow_y_dout;
input wrk_wide_xy_ena;
input [ BANK_ADDR_W -1:0] wrk_wide_xy_bank;
input [ OP_ADDR_W -1:0] wrk_wide_xy_addr;
output [ WORD_EXT_W -1:0] wrk_wide_x_dout;
output [ WORD_EXT_W -1:0] wrk_wide_y_dout;
input wrk_narrow_xy_ena;
input [ BANK_ADDR_W -1:0] wrk_narrow_xy_bank;
input [ OP_ADDR_W -1:0] wrk_narrow_xy_addr;
output [ WORD_EXT_W -1:0] wrk_narrow_x_dout;
output [ WORD_EXT_W -1:0] wrk_narrow_y_dout;
//
// Internal Registers
//
reg rd_wide_xy_reg_ena = 1'b0;
reg rd_wide_xy_reg_ena_aux = 1'b0;
reg rd_narrow_xy_reg_ena = 1'b0;
reg wrk_wide_xy_reg_ena = 1'b0;
reg wrk_narrow_xy_reg_ena = 1'b0;
always @(posedge clk or negedge rst_n)
//
if (!rst_n) begin
rd_wide_xy_reg_ena <= 1'b0;
rd_wide_xy_reg_ena_aux <= 1'b0;
rd_narrow_xy_reg_ena <= 1'b0;
wrk_wide_xy_reg_ena <= 1'b0;
wrk_narrow_xy_reg_ena <= 1'b0;
end else begin
rd_wide_xy_reg_ena <= rd_wide_xy_ena;
rd_wide_xy_reg_ena_aux <= rd_wide_xy_ena_aux;
rd_narrow_xy_reg_ena <= rd_narrow_xy_ena;
wrk_wide_xy_reg_ena <= wrk_wide_xy_ena;
wrk_narrow_xy_reg_ena <= wrk_narrow_xy_ena;
end
//
// Helper Signals
//
wire [BANK_ADDR_W + OP_ADDR_W -1:0] rd_wide_xy_offset[0:NUM_MULTS_HALF-1];
wire [BANK_ADDR_W + OP_ADDR_W -1:0] rd_wide_xy_offset_aux;
wire [BANK_ADDR_W + OP_ADDR_W -1:0] rd_narrow_xy_offset;
wire [BANK_ADDR_W + OP_ADDR_W -1:0] wr_wide_xy_offset;
wire [BANK_ADDR_W + OP_ADDR_W -1:0] wr_narrow_xy_offset;
wire [BANK_ADDR_W + OP_ADDR_W -1:0] wrk_wide_xy_offset;
wire [BANK_ADDR_W + OP_ADDR_W -1:0] wrk_narrow_xy_offset;
assign rd_wide_xy_offset_aux = {rd_wide_xy_bank_aux, rd_wide_xy_addr_aux};
assign rd_narrow_xy_offset = {rd_narrow_xy_bank, rd_narrow_xy_addr };
assign wr_wide_xy_offset = {wr_wide_xy_bank, wr_wide_xy_addr };
assign wr_narrow_xy_offset = {wr_narrow_xy_bank, wr_narrow_xy_addr };
assign wrk_wide_xy_offset = {wrk_wide_xy_bank, wrk_wide_xy_addr };
assign wrk_narrow_xy_offset = {wrk_narrow_xy_bank, wrk_narrow_xy_addr };
//
// "Wide" Storage
//
genvar z;
generate for (z=0; z<NUM_MULTS_HALF; z=z+1)
begin : gen_wide
//
assign rd_wide_xy_offset[z] = {1'b0, rd_wide_xy_bank, rd_wide_xy_addr[z*OP_ADDR_W +: OP_ADDR_W]};
//
`MODEXPNG_SDP_36K_X18 wide_x
(
.clk (clk),
.ena (wr_wide_xy_ena),
.wea (wr_wide_xy_ena),
.addra (wr_wide_xy_offset),
.dina (wr_wide_x_din),
.enb (rd_wide_xy_ena),
.regceb (rd_wide_xy_reg_ena),
.addrb (rd_wide_xy_offset[z]),
.doutb (rd_wide_x_dout[z*WORD_EXT_W +: WORD_EXT_W])
);
//
`MODEXPNG_SDP_36K_X18 wide_y
(
.clk (clk),
.ena (wr_wide_xy_ena),
.wea (wr_wide_xy_ena),
.addra (wr_wide_xy_offset),
.dina (wr_wide_y_din),
.enb (rd_wide_xy_ena),
.regceb (rd_wide_xy_reg_ena),
.addrb (rd_wide_xy_offset[z]),
.doutb (rd_wide_y_dout[z*WORD_EXT_W +: WORD_EXT_W])
);
//
end
endgenerate
//
// Worker "Wide" Storage
//
`MODEXPNG_SDP_36K_X18 wrk_wide_x
(
.clk (clk),
.ena (wr_wide_xy_ena),
.wea (wr_wide_xy_ena),
.addra (wr_wide_xy_offset),
.dina (wr_wide_x_din),
.enb (wrk_wide_xy_ena),
.regceb (wrk_wide_xy_reg_ena),
.addrb (wrk_wide_xy_offset),
.doutb (wrk_wide_x_dout)
);
//
`MODEXPNG_SDP_36K_X18 wrk_wide_y
(
.clk (clk),
.ena (wr_wide_xy_ena),
.wea (wr_wide_xy_ena),
.addra (wr_wide_xy_offset),
.dina (wr_wide_y_din),
.enb (wrk_wide_xy_ena),
.regceb (wrk_wide_xy_reg_ena),
.addrb (wrk_wide_xy_offset),
.doutb (wrk_wide_y_dout)
);
//
// Auxilary "Wide" Storage
//
`MODEXPNG_SDP_36K_X18 wide_x_aux
(
.clk (clk),
.ena (wr_wide_xy_ena),
.wea (wr_wide_xy_ena),
.addra (wr_wide_xy_offset),
.dina (wr_wide_x_din),
.enb (rd_wide_xy_ena_aux),
.regceb (rd_wide_xy_reg_ena_aux),
.addrb (rd_wide_xy_offset_aux),
.doutb (rd_wide_x_dout_aux)
);
//
`MODEXPNG_SDP_36K_X18 wide_y_aux
(
.clk (clk),
.ena (wr_wide_xy_ena),
.wea (wr_wide_xy_ena),
.addra (wr_wide_xy_offset),
.dina (wr_wide_y_din),
.enb (rd_wide_xy_ena_aux),
.regceb (rd_wide_xy_reg_ena_aux),
.addrb (rd_wide_xy_offset_aux),
.doutb (rd_wide_y_dout_aux)
);
//
// "Narrow" Storage
//
`MODEXPNG_SDP_36K_X18 narrow_x
(
.clk (clk),
.ena (wr_narrow_xy_ena),
.wea (wr_narrow_xy_ena),
.addra (wr_narrow_xy_offset),
.dina (wr_narrow_x_din),
.enb (rd_narrow_xy_ena),
.regceb (rd_narrow_xy_reg_ena),
.addrb (rd_narrow_xy_offset),
.doutb (rd_narrow_x_dout)
);
`MODEXPNG_SDP_36K_X18 narrow_y
(
.clk (clk),
.ena (wr_narrow_xy_ena),
.wea (wr_narrow_xy_ena),
.addra (wr_narrow_xy_offset),
.dina (wr_narrow_y_din),
.enb (rd_narrow_xy_ena),
.regceb (rd_narrow_xy_reg_ena),
.addrb (rd_narrow_xy_offset),
.doutb (rd_narrow_y_dout)
);
//
// Worker "Narrow" Storage
//
`MODEXPNG_SDP_36K_X18 wrk_narrow_x
(
.clk (clk),
.ena (wr_narrow_xy_ena),
.wea (wr_narrow_xy_ena),
.addra (wr_narrow_xy_offset),
.dina (wr_narrow_x_din),
.enb (wrk_narrow_xy_ena),
.regceb (wrk_narrow_xy_reg_ena),
.addrb (wrk_narrow_xy_offset),
.doutb (wrk_narrow_x_dout)
);
`MODEXPNG_SDP_36K_X18 wrk_narrow_y
(
.clk (clk),
.ena (wr_narrow_xy_ena),
.wea (wr_narrow_xy_ena),
.addra (wr_narrow_xy_offset),
.dina (wr_narrow_y_din),
.enb (wrk_narrow_xy_ena),
.regceb (wrk_narrow_xy_reg_ena),
.addrb (wrk_narrow_xy_offset),
.doutb (wrk_narrow_y_dout)
);
endmodule