//====================================================================== // // 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_io_block ( clk, rst_n, clk_bus, bus_cs, bus_we, bus_addr, bus_data_wr, bus_data_rd, in_1_en, in_1_addr, in_1_dout, in_2_en, in_2_addr, in_2_dout, out_en, out_we, out_addr, out_din ); // // Headers // `include "modexpng_parameters.vh" `include "modexpng_storage_primitives.vh" // // Ports // input clk; input rst_n; input clk_bus; input bus_cs; input bus_we; input [2 + BANK_ADDR_W + BUS_OP_ADDR_W -1:0] bus_addr; input [ BUS_DATA_W -1:0] bus_data_wr; output [ BUS_DATA_W -1:0] bus_data_rd; input in_1_en; input [ BANK_ADDR_W + OP_ADDR_W -1:0] in_1_addr; output [ WORD_W -1:0] in_1_dout; input in_2_en; input [ BANK_ADDR_W + OP_ADDR_W -1:0] in_2_addr; output [ WORD_W -1:0] in_2_dout; input out_en; input out_we; input [ BANK_ADDR_W + OP_ADDR_W -1:0] out_addr; input [ WORD_W -1:0] out_din; // // Internal Registers // reg in_1_reg_en = 1'b0; reg in_2_reg_en = 1'b0; always @(posedge clk or negedge rst_n) // if (!rst_n) begin in_1_reg_en <= 1'b0; in_2_reg_en <= 1'b0; end else begin in_1_reg_en <= in_1_en; in_2_reg_en <= in_2_en; end // // INPUT, OUTPUT Storage Buffers // wire [ 2 -1:0] bus_addr_msb = bus_addr[BANK_ADDR_W + BUS_OP_ADDR_W +: 2]; wire [BANK_ADDR_W + BUS_OP_ADDR_W -1:0] bus_addr_lsb = bus_addr[BANK_ADDR_W + BUS_OP_ADDR_W -1:0]; reg [ 2 -1:0] bus_addr_msb_dly; wire [ BUS_DATA_W -1:0] bus_data_rd_input_1; wire [ BUS_DATA_W -1:0] bus_data_rd_output; wire bus_we_input_1 = bus_we && (bus_addr_msb == 2'd1); wire bus_we_input_2 = bus_we && (bus_addr_msb == 2'd2); wire bus_cs_input_1 = bus_cs && (bus_addr_msb == 2'd1); wire bus_cs_input_2 = bus_cs && (bus_addr_msb == 2'd2); wire bus_cs_output = bus_cs && (bus_addr_msb == 2'd3); /* INPUT_1 */ `MODEXPNG_TDP_36K_X16_X32 bram_input_1 ( .clk (clk), // core clock .clk_bus (clk_bus), // bus clock .ena (bus_cs_input_1), // bus side read-write .wea (bus_we_input_1), // .addra (bus_addr_lsb), // .dina (bus_data_wr), // .douta (bus_data_rd_input_1), // .enb (in_1_en), // core side read-only .regceb (in_1_reg_en), // .addrb (in_1_addr), // .doutb (in_1_dout) // ); /* INPUT_2 */ `MODEXPNG_SDP_36K_X16_X32 bram_input_2 ( .clk (clk), // core clock .clk_bus (clk_bus), // bus clock .ena (bus_cs_input_2), // bus side write-only .wea (bus_we_input_2), // .addra (bus_addr_lsb), // .dina (bus_data_wr), // .enb (in_2_en), // core side read-only .regceb (in_2_reg_en), // .addrb (in_2_addr), // .doutb (in_2_dout) // ); /* OUTPUT */ `MODEXPNG_SDP_36K_X32_X16 bram_output ( .clk (clk), // core clock .clk_bus (clk_bus), // bus clock .ena (out_en), // core side write-only .wea (out_we), // .addra (out_addr), // .dina (out_din), // .enb (bus_cs_output), // bus side read-only .addrb (bus_addr_lsb), // .doutb (bus_data_rd_output) // ); reg [31: 0] bus_data_rd_mux; assign bus_data_rd = bus_data_rd_mux; always @(posedge clk_bus) bus_addr_msb_dly <= bus_addr_msb; always @(*) // case (bus_addr_msb_dly) // 2'd0: bus_data_rd_mux = 32'hDEADC0DE; 2'd1: bus_data_rd_mux = bus_data_rd_input_1; 2'd2: bus_data_rd_mux = 32'hDEADC0DE; 2'd3: bus_data_rd_mux = bus_data_rd_output; // endcase endmodule