aboutsummaryrefslogblamecommitdiff
path: root/rtl/modexpng_mmm_din_addr.v
blob: 565c7e050035e09a7f50b2f537dff0adfe142fc1 (plain) (tree)






































































































































































                                                                                                                 
module modexpng_mmm_din_addr
(
    clk, rst_n,
    index_last,
    fsm_state_next,
    col_index_zero, col_index_next,
    din_addr, din_bank, din_ena, din_reg_ena,
    din_addr_cnt, din_addr_cnt_last,
    din_addr_cnt_lower_prev, din_addr_cnt_upper_prev
);


    //
    // Includes
    //
    `include "modexpng_parameters.vh"
    //`include "modexpng_parameters_x8.vh"
    `include "modexpng_mmm_fsm.vh"


    //
    // Parameters
    //
    parameter INDEX_WIDTH = 6;
    
    
    //
    // Ports
    //
    input                        clk;
    input                        rst_n;
    input  [    INDEX_WIDTH-1:0] index_last;
    input  [FSM_STATE_WIDTH-1:0] fsm_state_next;
    input  [    INDEX_WIDTH-4:0] col_index_zero;
    input  [    INDEX_WIDTH-4:0] col_index_next;
    output [    INDEX_WIDTH-4:0] din_addr;
    output [              3-1:0] din_bank;
    output [              1-1:0] din_ena;
    output [              1-1:0] din_reg_ena;
    output [    INDEX_WIDTH-1:0] din_addr_cnt;
    output [    INDEX_WIDTH-1:0] din_addr_cnt_last;
    output [              3-1:0] din_addr_cnt_lower_prev;
    output [    INDEX_WIDTH-4:0] din_addr_cnt_upper_prev;
    
 
    //
    // Address
    //
    reg  [INDEX_WIDTH-1:0] din_addr_reg;
    wire [INDEX_WIDTH-1:0] din_addr_zero = {INDEX_WIDTH{1'b0}};
    reg  [INDEX_WIDTH-1:0] din_addr_last;
    wire [INDEX_WIDTH-1:0] din_addr_prev = (din_addr_reg == din_addr_zero) ? din_addr_last : din_addr_reg - 1'b1;
    
    reg  [INDEX_WIDTH-1:0] din_addr_cnt_reg;
    wire [INDEX_WIDTH-1:0] din_addr_cnt_zero = {INDEX_WIDTH{1'b0}};
    wire [INDEX_WIDTH-1:0] din_addr_cnt_next = din_addr_cnt_reg + 1'b1;
    reg  [INDEX_WIDTH-1:0] din_addr_cnt_last_reg;
    wire [          3-1:0] din_addr_cnt_lower = din_addr_cnt_reg[          3-1:0];
    wire [INDEX_WIDTH-4:0] din_addr_cnt_upper = din_addr_cnt_reg[INDEX_WIDTH-1:3];
    reg  [          3-1:0] din_addr_cnt_lower_dly;
    reg  [INDEX_WIDTH-4:0] din_addr_cnt_upper_dly;

    reg  [          3-1:0] din_bank_reg;


    //
    // Enables
    //
    reg din_ena_reg = 1'b0;
    reg din_reg_ena_reg = 1'b0;
    
    always @(posedge clk or negedge rst_n)
        //
        if (!rst_n)
            din_ena_reg <= 1'b0;
        else case (fsm_state_next)
            //
            FSM_STATE_MULT_SQUARE_COL_0_TRIG,
            FSM_STATE_MULT_SQUARE_COL_N_TRIG,
            FSM_STATE_MULT_SQUARE_COL_0_BUSY,
            FSM_STATE_MULT_SQUARE_COL_N_BUSY:
                din_ena_reg <= 1'b1;
            //
            default:
                din_ena_reg <= 1'b0;
            //
        endcase

    always @(posedge clk or negedge rst_n)
        //
        if (!rst_n)
            din_reg_ena_reg <= 1'b0;
        else
            din_reg_ena_reg <= din_ena_reg;


    //
    // Address Mapping
    //
    assign din_addr                = din_addr_reg[INDEX_WIDTH-1:3];

    assign din_addr_cnt            = din_addr_cnt_reg;
    assign din_addr_cnt_last       = din_addr_cnt_last_reg;
    assign din_addr_cnt_lower_prev = din_addr_cnt_lower_dly;
    assign din_addr_cnt_upper_prev = din_addr_cnt_upper_dly;

    assign din_bank                = din_bank_reg;
    
    
    //
    // Enable Mapping
    //
    assign din_ena = din_ena_reg;
    assign din_reg_ena = din_reg_ena_reg;


    //
    // Delay
    //
    always @(posedge clk) begin
        din_addr_cnt_lower_dly <= din_addr_cnt_lower;
        din_addr_cnt_upper_dly <= din_addr_cnt_upper;
    end


    always @(posedge clk)
        //
        case (fsm_state_next)
            //
            FSM_STATE_MULT_SQUARE_COL_0_TRIG: begin
                din_addr_reg          <= {col_index_zero, {3{1'b0}}};
                din_addr_last         <= index_last;
                din_addr_cnt_reg      <= din_addr_cnt_zero;
                din_addr_cnt_last_reg <= index_last;
            end
            //
            FSM_STATE_MULT_SQUARE_COL_N_TRIG: begin
                din_addr_reg     <= {col_index_next, {3{1'b0}}};
                din_addr_cnt_reg <= din_addr_cnt_zero;
            end
            //
            FSM_STATE_MULT_SQUARE_COL_0_BUSY,
            FSM_STATE_MULT_SQUARE_COL_N_BUSY: begin
                din_addr_reg     <= din_addr_prev;
                din_addr_cnt_reg <= din_addr_cnt_next;
            end
            //
            //default:
            //
        endcase

    always @(posedge clk)
        //
        case (fsm_state_next)
            //
            FSM_STATE_MULT_SQUARE_COL_0_TRIG,
            FSM_STATE_MULT_SQUARE_COL_N_TRIG,
            FSM_STATE_MULT_SQUARE_COL_0_BUSY,
            FSM_STATE_MULT_SQUARE_COL_N_BUSY:
                din_bank_reg = BANK_XY_T1T2;
            //
            default:
                din_bank_reg = BANK_XY_ANY;
            //
        endcase
        
endmodule