aboutsummaryrefslogblamecommitdiff
path: root/rtl/modexpng_storage_block.v
blob: d5b9b24bad759cdbce59f99f2b81533324d19d31 (plain) (tree)
1
2
3

                             
                      



























                        



















                     

  


              
                                     
 
 


            


                                                          
 
















































                                                                      





                                      

                                      
 
                         
          



                                           

                                           



                                                         

                                              
           



                     




                                                                              
 
                                                                              
                                                                            

                                                                            




                     
                                               

                             
                                                                                                             
              
                                                
             
                              








                                               
                                                                    

              
                                                
             
                              








                                               
                                                                    



               



                       
                                            
     
                      











                                         
                                            
     
                      











                                         


                       
                                          
     
                      











                                       
                                          
     
                      











                                       

















































































                                                                                                        
         
 
module modexpng_storage_block
(
    clk, clk_bus, rst,
    
    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,
    
    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"


    //
    // Ports
    //
    input                                         clk;
    input                                         clk_bus;
    input                                         rst;

    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                                         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 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 in_1_reg_en            = 1'b0;
    reg in_2_reg_en            = 1'b0;

    always @(posedge clk)
        //
        if (rst) begin
            rd_wide_xy_reg_ena     <= 1'b0;
            rd_wide_xy_reg_ena_aux <= 1'b0;
            rd_narrow_xy_reg_ena   <= 1'b0;
            in_1_reg_en            <= 1'b0;
            in_2_reg_en            <= 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;
            in_1_reg_en            <= in_1_en;
            in_2_reg_en            <= in_2_en;
        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;

    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};

    //
    // "Wide" Storage
    //
    genvar z;
    generate for (z=0; z<NUM_MULTS_HALF; z=z+1)
        begin : gen_wide_bram
            //
            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_wrapper wide_bram_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_wrapper wide_bram_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
    
    //
    // Auxilary Storage
    //
    modexpng_sdp_36k_wrapper wide_bram_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_wrapper wide_bram_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_wrapper narrow_bram_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_wrapper narrow_bram_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)
    );

    //
    // 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_data_wr_input_1 = bus_data_wr && (bus_addr_msb == 2'd0);
    wire                                    bus_data_wr_input_2 = bus_data_wr && (bus_addr_msb == 2'd1);

    /* INPUT_1 */
    modexpng_sdp_36k_x16_x32_wrapper bram_input_1
    (
        .clk        (clk),                  // core clock
        .clk_bus    (clk_bus),              // bus clock
    
        .ena        (bus_cs),               // bus side read-write
        .wea        (bus_data_wr_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_wrapper bram_input_2
    (
        .clk        (clk),                  // core clock
        .clk_bus    (clk_bus),              // bus clock
    
        .ena        (bus_cs),               // bus side write-only
        .wea        (bus_data_wr_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_wrapper 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),               // 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 = bus_data_rd_input_1;
            2'd1: bus_data_rd_mux = 32'hDEADC0DE;
            2'd2: bus_data_rd_mux = bus_data_rd_output;
            2'd3: bus_data_rd_mux = 32'hDEADC0DE;
            //
        endcase

endmodule