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