module modexpng_mmm_transporter
(
clk,
ena,
index_last,
fsm_state,
fsm_state_next,
load_phase,
load_xy_addr,
load_xy_addr_vld,
load_xy_req,
load_addr_zero,
load_t1t2_addr_done,
load_nn_coeff_addr_done
);
//
// Includes
//
//`include "modexpng_parameters.vh"
//`include "modexpng_parameters_x8.vh"
`include "modexpng_mmm_fsm.vh"
//
// Parameters
//
parameter INDEX_WIDTH = 6;
//
// Ports
//
input clk;
input ena;
input [ INDEX_WIDTH-1:0] index_last;
input [FSM_STATE_WIDTH-1:0] fsm_state;
input [FSM_STATE_WIDTH-1:0] fsm_state_next;
output load_phase;
output [ INDEX_WIDTH:0] load_xy_addr;
output load_xy_addr_vld;
output load_xy_req;
output load_addr_zero;
output load_t1t2_addr_done;
output load_nn_coeff_addr_done;
//
// Load Address Generator
//
reg load_phase_reg;
reg [INDEX_WIDTH:0] load_xy_addr_reg;
reg load_xy_addr_vld_reg;
reg load_xy_req_reg;
//
// Mapping
//
assign load_phase = load_phase_reg;
assign load_xy_addr = load_xy_addr_reg;
assign load_xy_addr_vld = load_xy_addr_vld_reg;
assign load_xy_req = load_xy_req_reg;
//
// Handy Quantities
//
wire [INDEX_WIDTH:0] load_xy_addr_zero = {{INDEX_WIDTH{1'b0}}, 1'b0};
wire [INDEX_WIDTH:0] load_xy_addr_next = load_xy_addr_reg + 1'b1;
wire [INDEX_WIDTH:0] load_xy_addr_xxx = {{INDEX_WIDTH{1'bX}}, 1'bX};
//
// More Handy Quantities
//
reg [INDEX_WIDTH:0] load_t1t2_addr_last;
reg [INDEX_WIDTH:0] load_nn_coeff_addr_last;
//
// Flags
//
assign load_addr_zero = load_xy_addr_reg == load_xy_addr_zero;
assign load_t1t2_addr_done = load_xy_addr_reg == load_t1t2_addr_last;
assign load_nn_coeff_addr_done = load_xy_addr_reg == load_nn_coeff_addr_last;
//
// Last Index Latch
//
always @(posedge clk)
//
if (ena && (fsm_state == FSM_STATE_IDLE)) begin
load_t1t2_addr_last <= {1'b0, index_last};
load_nn_coeff_addr_last <= {1'b0, index_last} + 1'b1;
end
//
// Update Load Phase
//
always @(posedge clk)
//
case (fsm_state_next)
FSM_STATE_LOAD_T1T2_1,
FSM_STATE_LOAD_T1T2_2,
FSM_STATE_LOAD_T1T2_3: load_phase_reg <= 1'b0;
FSM_STATE_LOAD_NN_COEFF_1,
FSM_STATE_LOAD_NN_COEFF_2,
FSM_STATE_LOAD_NN_COEFF_3: load_phase_reg <= 1'b1;
default: load_phase_reg <= 1'bX;
endcase
//
// Update Load Address
//
always @(posedge clk)
//
case (fsm_state_next)
FSM_STATE_LOAD_T1T2_1: load_xy_addr_reg <= (fsm_state == FSM_STATE_LOAD_T1T2_3) ? load_xy_addr_next : load_xy_addr_zero;
FSM_STATE_LOAD_T1T2_2,
FSM_STATE_LOAD_T1T2_3: load_xy_addr_reg <= load_xy_addr_reg;
FSM_STATE_LOAD_NN_COEFF_1: load_xy_addr_reg <= (fsm_state == FSM_STATE_LOAD_NN_COEFF_3) ? load_xy_addr_next : load_xy_addr_zero;
FSM_STATE_LOAD_NN_COEFF_2,
FSM_STATE_LOAD_NN_COEFF_3: load_xy_addr_reg <= load_xy_addr_reg;
default load_xy_addr_reg <= load_xy_addr_xxx;
endcase
//
// Update Address Valid Flag
//
always @(posedge clk)
//
case (fsm_state_next)
FSM_STATE_LOAD_T1T2_1,
FSM_STATE_LOAD_NN_COEFF_1: load_xy_addr_vld_reg <= 1'b1;
default load_xy_addr_vld_reg <= 1'b0;
endcase
//
// Update Load Request Flag
//
always @(posedge clk)
//
case (fsm_state_next)
FSM_STATE_LOAD_T1T2_2,
FSM_STATE_LOAD_NN_COEFF_2: load_xy_req_reg <= 1'b1;
default load_xy_req_reg <= 1'b0;
endcase
endmodule