aboutsummaryrefslogblamecommitdiff
path: root/rtl/modexpng_io_block.v
blob: 6d008aa27a1cd23db0dd3328ee9ffaf38e393ec1 (plain) (tree)



























                                     
                                             






















































                                                                                                      

                                                                                              
 


                                                           
 
                 
                                          



                                                         
                                                                  
                                         











                                                                  
                                          



                                                         
                                                                  
                                              








                                                                  
                
                                         








                                                                   
                                                                 













                                              



                                                        




               
module modexpng_io_block
(
    clk, clk_bus, rst,
        
    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                                         clk_bus;
    input                                         rst;

    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)
        //
        if (rst) 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