aboutsummaryrefslogtreecommitdiff
path: root/rtl/modexpng_uop_engine.v
diff options
context:
space:
mode:
Diffstat (limited to 'rtl/modexpng_uop_engine.v')
-rw-r--r--rtl/modexpng_uop_engine.v658
1 files changed, 658 insertions, 0 deletions
diff --git a/rtl/modexpng_uop_engine.v b/rtl/modexpng_uop_engine.v
new file mode 100644
index 0000000..a87d924
--- /dev/null
+++ b/rtl/modexpng_uop_engine.v
@@ -0,0 +1,658 @@
+module modexpng_uop_engine
+(
+ clk,
+ rst,
+
+ ena,
+ rdy,
+
+ `ifdef MODEXPNG_ENABLE_DEBUG
+ uop_decoded_stop,
+ `endif
+
+ crt_mode,
+
+ word_index_last_n,
+ word_index_last_pq,
+
+ bit_index_last_n,
+ bit_index_last_pq,
+
+ io_mgr_ena,
+ io_mgr_rdy,
+ io_mgr_sel_crt,
+ io_mgr_sel_aux,
+ io_mgr_sel_in,
+ io_mgr_sel_out,
+ io_mgr_word_index_last,
+ io_mgr_opcode,
+ io_mgr_ladder_steps,
+ io_mgr_ladder_d,
+ io_mgr_ladder_p,
+ io_mgr_ladder_q,
+ io_mgr_ladder_done,
+
+ mmm_ena_x,
+ mmm_ena_y,
+ mmm_rdy_x,
+ mmm_rdy_y,
+ mmm_word_index_last_x,
+ mmm_word_index_last_y,
+ mmm_word_index_last_minus1_x,
+ mmm_word_index_last_minus1_y,
+ mmm_ladder_mode_x,
+ mmm_ladder_mode_y,
+ mmm_sel_wide_in_x,
+ mmm_sel_wide_in_y,
+ mmm_sel_narrow_in_x,
+ mmm_sel_narrow_in_y,
+ mmm_force_unity_b_x,
+ mmm_force_unity_b_y,
+ mmm_only_reduce_x,
+ mmm_only_reduce_y,
+ mmm_just_multiply_x,
+ mmm_just_multiply_y,
+
+ rdct_word_index_last_x,
+ rdct_word_index_last_y,
+ rdct_sel_wide_out_x,
+ rdct_sel_narrow_out_x,
+ rdct_sel_wide_out_y,
+ rdct_sel_narrow_out_y,
+
+ wrk_ena,
+ wrk_rdy,
+ wrk_sel_wide_in,
+ wrk_sel_wide_out,
+ wrk_sel_narrow_in,
+ wrk_sel_narrow_out,
+ wrk_word_index_last,
+ wrk_word_index_last_half,
+ wrk_opcode
+);
+
+
+ //
+ // Headers
+ //
+ `include "modexpng_parameters.vh"
+ `include "modexpng_microcode.vh"
+
+
+ //
+ // Ports
+ //
+ input clk;
+ input rst;
+
+ input ena;
+ output rdy;
+
+ `ifdef MODEXPNG_ENABLE_DEBUG
+ output uop_decoded_stop;
+ `endif
+
+ input crt_mode;
+
+ input [OP_ADDR_W -1:0] word_index_last_n;
+ input [OP_ADDR_W -1:0] word_index_last_pq;
+
+ input [BIT_INDEX_W -1:0] bit_index_last_n;
+ input [BIT_INDEX_W -1:0] bit_index_last_pq;
+
+ output io_mgr_ena;
+ input io_mgr_rdy;
+ output [UOP_CRT_W -1:0] io_mgr_sel_crt;
+ output [UOP_AUX_W -1:0] io_mgr_sel_aux;
+ output [BANK_ADDR_W -1:0] io_mgr_sel_in;
+ output [BANK_ADDR_W -1:0] io_mgr_sel_out;
+ output [OP_ADDR_W -1:0] io_mgr_word_index_last;
+ output [UOP_OPCODE_W -1:0] io_mgr_opcode;
+ output [BIT_INDEX_W -1:0] io_mgr_ladder_steps;
+ input io_mgr_ladder_d;
+ input io_mgr_ladder_p;
+ input io_mgr_ladder_q;
+ input io_mgr_ladder_done;
+
+ output mmm_ena_x;
+ output mmm_ena_y;
+ input mmm_rdy_x;
+ input mmm_rdy_y;
+ output [OP_ADDR_W -1:0] mmm_word_index_last_x;
+ output [OP_ADDR_W -1:0] mmm_word_index_last_y;
+ output [OP_ADDR_W -1:0] mmm_word_index_last_minus1_x;
+ output [OP_ADDR_W -1:0] mmm_word_index_last_minus1_y;
+ output mmm_ladder_mode_x;
+ output mmm_ladder_mode_y;
+ output [BANK_ADDR_W -1:0] mmm_sel_wide_in_x;
+ output [BANK_ADDR_W -1:0] mmm_sel_wide_in_y;
+ output [BANK_ADDR_W -1:0] mmm_sel_narrow_in_x;
+ output [BANK_ADDR_W -1:0] mmm_sel_narrow_in_y;
+ output mmm_force_unity_b_x;
+ output mmm_force_unity_b_y;
+ output mmm_only_reduce_x;
+ output mmm_only_reduce_y;
+ output mmm_just_multiply_x;
+ output mmm_just_multiply_y;
+
+ output [OP_ADDR_W -1:0] rdct_word_index_last_x;
+ output [OP_ADDR_W -1:0] rdct_word_index_last_y;
+ output [BANK_ADDR_W -1:0] rdct_sel_wide_out_x;
+ output [BANK_ADDR_W -1:0] rdct_sel_narrow_out_x;
+ output [BANK_ADDR_W -1:0] rdct_sel_wide_out_y;
+ output [BANK_ADDR_W -1:0] rdct_sel_narrow_out_y;
+
+ output wrk_ena;
+ input wrk_rdy;
+ output [BANK_ADDR_W -1:0] wrk_sel_wide_in;
+ output [BANK_ADDR_W -1:0] wrk_sel_wide_out;
+ output [BANK_ADDR_W -1:0] wrk_sel_narrow_in;
+ output [BANK_ADDR_W -1:0] wrk_sel_narrow_out;
+ output [OP_ADDR_W -1:0] wrk_word_index_last;
+ output [OP_ADDR_W -1:0] wrk_word_index_last_half;
+ output [UOP_OPCODE_W -1:0] wrk_opcode;
+
+
+ //
+ // Registers
+ //
+ reg io_mgr_ena_r = 1'b0;
+ reg [UOP_CRT_W -1:0] io_mgr_sel_crt_r;
+ reg [UOP_AUX_W -1:0] io_mgr_sel_aux_r;
+ reg [BANK_ADDR_W -1:0] io_mgr_sel_in_r;
+ reg [BANK_ADDR_W -1:0] io_mgr_sel_out_r;
+ reg [OP_ADDR_W -1:0] io_mgr_word_index_last_r;
+ reg [UOP_OPCODE_W -1:0] io_mgr_opcode_r;
+ reg [BIT_INDEX_W -1:0] io_mgr_ladder_steps_r;
+
+ reg mmm_ena_x_r = 1'b0;
+ reg mmm_ena_y_r = 1'b0;
+ reg [OP_ADDR_W -1:0] mmm_word_index_last_x_r;
+ reg [OP_ADDR_W -1:0] mmm_word_index_last_y_r;
+ reg [OP_ADDR_W -1:0] mmm_word_index_last_minus1_x_r;
+ reg [OP_ADDR_W -1:0] mmm_word_index_last_minus1_y_r;
+ reg mmm_ladder_mode_x_r;
+ reg mmm_ladder_mode_y_r;
+ reg [BANK_ADDR_W -1:0] mmm_sel_wide_in_x_r;
+ reg [BANK_ADDR_W -1:0] mmm_sel_wide_in_y_r;
+ reg [BANK_ADDR_W -1:0] mmm_sel_narrow_in_x_r;
+ reg [BANK_ADDR_W -1:0] mmm_sel_narrow_in_y_r;
+ reg mmm_force_unity_b_x_r;
+ reg mmm_force_unity_b_y_r;
+ reg mmm_only_reduce_x_r;
+ reg mmm_only_reduce_y_r;
+ reg mmm_just_multiply_x_r;
+ reg mmm_just_multiply_y_r;
+
+ reg [OP_ADDR_W -1:0] rdct_word_index_last_x_r;
+ reg [OP_ADDR_W -1:0] rdct_word_index_last_y_r;
+ reg [BANK_ADDR_W -1:0] rdct_sel_wide_out_x_r;
+ reg [BANK_ADDR_W -1:0] rdct_sel_narrow_out_x_r;
+ reg [BANK_ADDR_W -1:0] rdct_sel_wide_out_y_r;
+ reg [BANK_ADDR_W -1:0] rdct_sel_narrow_out_y_r;
+
+ reg wrk_ena_r = 1'b0;
+ reg [BANK_ADDR_W -1:0] wrk_sel_wide_in_r;
+ reg [BANK_ADDR_W -1:0] wrk_sel_wide_out_r;
+ reg [BANK_ADDR_W -1:0] wrk_sel_narrow_in_r;
+ reg [BANK_ADDR_W -1:0] wrk_sel_narrow_out_r;
+ reg [OP_ADDR_W -1:0] wrk_word_index_last_r;
+ reg [OP_ADDR_W -1:0] wrk_word_index_last_half_r;
+ reg [UOP_OPCODE_W -1:0] wrk_opcode_r;
+
+
+ //
+ // Mapping
+ //
+ assign io_mgr_ena = io_mgr_ena_r;
+ assign io_mgr_sel_crt = io_mgr_sel_crt_r;
+ assign io_mgr_sel_aux = io_mgr_sel_aux_r;
+ assign io_mgr_sel_in = io_mgr_sel_in_r;
+ assign io_mgr_sel_out = io_mgr_sel_out_r;
+ assign io_mgr_word_index_last = io_mgr_word_index_last_r;
+ assign io_mgr_opcode = io_mgr_opcode_r;
+ assign io_mgr_ladder_steps = io_mgr_ladder_steps_r;
+
+ assign mmm_ena_x = mmm_ena_x_r;
+ assign mmm_ena_y = mmm_ena_y_r;
+ assign mmm_word_index_last_x = mmm_word_index_last_x_r;
+ assign mmm_word_index_last_y = mmm_word_index_last_y_r;
+ assign mmm_word_index_last_minus1_x = mmm_word_index_last_minus1_x_r;
+ assign mmm_word_index_last_minus1_y = mmm_word_index_last_minus1_y_r;
+ assign mmm_ladder_mode_x = mmm_ladder_mode_x_r;
+ assign mmm_ladder_mode_y = mmm_ladder_mode_y_r;
+ assign mmm_sel_wide_in_x = mmm_sel_wide_in_x_r;
+ assign mmm_sel_wide_in_y = mmm_sel_wide_in_y_r;
+ assign mmm_sel_narrow_in_x = mmm_sel_narrow_in_x_r;
+ assign mmm_sel_narrow_in_y = mmm_sel_narrow_in_y_r;
+ assign mmm_force_unity_b_x = mmm_force_unity_b_x_r;
+ assign mmm_force_unity_b_y = mmm_force_unity_b_y_r;
+ assign mmm_only_reduce_x = mmm_only_reduce_x_r;
+ assign mmm_only_reduce_y = mmm_only_reduce_y_r;
+ assign mmm_just_multiply_x = mmm_just_multiply_x_r;
+ assign mmm_just_multiply_y = mmm_just_multiply_y_r;
+
+ assign rdct_word_index_last_x = rdct_word_index_last_x_r;
+ assign rdct_word_index_last_y = rdct_word_index_last_y_r;
+ assign rdct_sel_wide_out_x = rdct_sel_wide_out_x_r;
+ assign rdct_sel_wide_out_y = rdct_sel_wide_out_y_r;
+ assign rdct_sel_narrow_out_x = rdct_sel_narrow_out_x_r;
+ assign rdct_sel_narrow_out_y = rdct_sel_narrow_out_y_r;
+
+ assign wrk_ena = wrk_ena_r;
+ assign wrk_sel_wide_in = wrk_sel_wide_in_r;
+ assign wrk_sel_wide_out = wrk_sel_wide_out_r;
+ assign wrk_sel_narrow_in = wrk_sel_narrow_in_r;
+ assign wrk_sel_narrow_out = wrk_sel_narrow_out_r;
+ assign wrk_word_index_last = wrk_word_index_last_r;
+ assign wrk_word_index_last_half = wrk_word_index_last_half_r;
+ assign wrk_opcode = wrk_opcode_r;
+
+
+ //
+ // UOP_FSM
+ //
+ localparam [1:0] UOP_FSM_STATE_IDLE = 2'b00;
+ localparam [1:0] UOP_FSM_STATE_FETCH = 2'b01;
+ localparam [1:0] UOP_FSM_STATE_DECODE = 2'b10;
+ localparam [1:0] UOP_FSM_STATE_BUSY = 2'b11;
+
+ reg [1:0] uop_fsm_state = UOP_FSM_STATE_IDLE;
+ reg [1:0] uop_fsm_state_next;
+
+
+ //
+ // UOP ROM
+ //
+ reg [UOP_ADDR_W -1:0] uop_addr;
+ wire [UOP_W -1:0] uop_data;
+
+ modexpng_uop_rom uop_rom
+ (
+ .clk (clk),
+ .addr (uop_addr),
+ .data (uop_data)
+ );
+
+
+ //
+ // UOP ROM Data Decoder
+ //
+ wire [UOP_OPCODE_W -1:0] uop_data_opcode = uop_data[UOP_W -1-: UOP_OPCODE_W];
+ wire [UOP_CRT_W -1:0] uop_data_crt = uop_data[UOP_W -UOP_OPCODE_W -1-: UOP_CRT_W ];
+ wire [UOP_NPQ_W -1:0] uop_data_npq = uop_data[UOP_W -UOP_OPCODE_W -UOP_CRT_W -1-: UOP_NPQ_W ];
+ wire [UOP_AUX_W -1:0] uop_data_aux = uop_data[UOP_W -UOP_OPCODE_W -UOP_CRT_W -UOP_NPQ_W -1-: UOP_AUX_W ];
+ wire [UOP_LADDER_W -1:0] uop_data_ladder = uop_data[UOP_W -UOP_OPCODE_W -UOP_CRT_W -UOP_NPQ_W -UOP_AUX_W -1-: UOP_LADDER_W];
+ wire [BANK_ADDR_W -1:0] uop_data_sel_wide_in = uop_data[UOP_W -UOP_OPCODE_W -UOP_CRT_W -UOP_NPQ_W -UOP_AUX_W -UOP_LADDER_W -1-: BANK_ADDR_W ];
+ wire [BANK_ADDR_W -1:0] uop_data_sel_narrow_in = uop_data[UOP_W -UOP_OPCODE_W -UOP_CRT_W -UOP_NPQ_W -UOP_AUX_W -UOP_LADDER_W -1*BANK_ADDR_W -1-: BANK_ADDR_W ];
+ wire [BANK_ADDR_W -1:0] uop_data_sel_wide_out = uop_data[UOP_W -UOP_OPCODE_W -UOP_CRT_W -UOP_NPQ_W -UOP_AUX_W -UOP_LADDER_W -2*BANK_ADDR_W -1-: BANK_ADDR_W ];
+ wire [BANK_ADDR_W -1:0] uop_data_sel_narrow_out = uop_data[UOP_W -UOP_OPCODE_W -UOP_CRT_W -UOP_NPQ_W -UOP_AUX_W -UOP_LADDER_W -3*BANK_ADDR_W -1-: BANK_ADDR_W ];
+
+ wire uop_opcode_is_stop = uop_data_opcode == UOP_OPCODE_STOP ;
+ wire uop_opcode_is_in = (uop_data_opcode == UOP_OPCODE_INPUT_TO_WIDE ) ||
+ (uop_data_opcode == UOP_OPCODE_INPUT_TO_NARROW ) ;
+ wire uop_opcode_is_out = uop_data_opcode == UOP_OPCODE_OUTPUT_FROM_NARROW ;
+ wire uop_opcode_is_wrk = (uop_data_opcode == UOP_OPCODE_COPY_CRT_Y2X ) ||
+ (uop_data_opcode == UOP_OPCODE_COPY_LADDERS_X2Y ) ||
+ (uop_data_opcode == UOP_OPCODE_CROSS_LADDERS_X2Y ) ||
+ (uop_data_opcode == UOP_OPCODE_MODULAR_SUBTRACT ) ||
+ (uop_data_opcode == UOP_OPCODE_MODULAR_REDUCE_INIT ) ||
+ (uop_data_opcode == UOP_OPCODE_PROPAGATE_CARRIES ) ||
+ (uop_data_opcode == UOP_OPCODE_MERGE_LH ) ||
+ (uop_data_opcode == UOP_OPCODE_REGULAR_ADD_UNEVEN ) ;
+ wire uop_opcode_is_mmm = (uop_data_opcode == UOP_OPCODE_MODULAR_MULTIPLY ) ||
+ (uop_data_opcode == UOP_OPCODE_MODULAR_REDUCE_PROC ) ||
+ (uop_data_opcode == UOP_OPCODE_REGULAR_MULTIPLY ) ;
+ wire uop_opcode_is_ladder = (uop_data_opcode == UOP_OPCODE_LADDER_INIT ) ||
+ (uop_data_opcode == UOP_OPCODE_LADDER_STEP ) ;
+
+
+ //
+ // Debug Signal
+ //
+ `ifdef MODEXPNG_ENABLE_DEBUG
+ assign uop_decoded_stop = (uop_fsm_state == UOP_FSM_STATE_DECODE) && uop_opcode_is_stop;
+ `endif
+
+
+
+ //
+ // UOP ROM Address Increment Logic
+ //
+ wire uop_loop_now;
+
+ wire [UOP_ADDR_W -1:0] uop_addr_plus1 = uop_addr + 1'b1;
+ wire [UOP_ADDR_W -1:0] uop_addr_minus1 = uop_addr - 1'b1;
+
+ wire [UOP_ADDR_W -1:0] uop_addr_next = uop_loop_now ? uop_addr_minus1 : uop_addr_plus1 ;
+ wire [UOP_ADDR_W -1:0] uop_addr_offset = crt_mode ? UOP_ADDR_OFFSET_USING_CRT : UOP_ADDR_OFFSET_WITHOUT_CRT;
+
+ always @(posedge clk)
+ //
+ if (uop_fsm_state_next == UOP_FSM_STATE_FETCH)
+ uop_addr <= (uop_fsm_state == UOP_FSM_STATE_IDLE) ? uop_addr_offset : uop_addr_next;
+
+
+ //
+ // Handy Signals
+ //
+ wire mmm_ena = mmm_ena_x & mmm_ena_y;
+ wire mmm_rdy = mmm_rdy_x & mmm_rdy_y;
+
+ assign uop_loop_now = (uop_data_opcode == UOP_OPCODE_LADDER_STEP) && !io_mgr_ladder_done;
+
+ reg [1:0] uop_data_ladder_mux;
+
+ always @(uop_data_ladder, io_mgr_ladder_p, io_mgr_ladder_q, io_mgr_ladder_d)
+ //
+ case (uop_data_ladder)
+ UOP_LADDER_00: uop_data_ladder_mux = 2'b00;
+ UOP_LADDER_11: uop_data_ladder_mux = 2'b11;
+ UOP_LADDER_D: uop_data_ladder_mux = {io_mgr_ladder_d, ~io_mgr_ladder_d};
+ UOP_LADDER_PQ: uop_data_ladder_mux = {io_mgr_ladder_p, io_mgr_ladder_q};
+ endcase
+
+ reg [OP_ADDR_W-1:0] word_index_last_mux;
+
+ always @(uop_data_npq, word_index_last_n, word_index_last_pq)
+ //
+ if (uop_data_npq == UOP_NPQ_N) word_index_last_mux = word_index_last_n;
+ else word_index_last_mux = word_index_last_pq;
+
+ reg [BIT_INDEX_W-1:0] bit_index_last_mux;
+
+ always @(crt_mode, bit_index_last_pq, bit_index_last_n)
+ if (crt_mode) bit_index_last_mux = bit_index_last_pq;
+ else bit_index_last_mux = bit_index_last_n;
+
+
+ //
+ // UOP Trigger Logic
+ //
+ always @(posedge clk)
+ //
+ if (rst) begin
+ io_mgr_ena_r <= 1'b0;
+ mmm_ena_x_r <= 1'b0;
+ mmm_ena_y_r <= 1'b0;
+ wrk_ena_r <= 1'b0;
+ end else begin
+ io_mgr_ena_r <= uop_fsm_state == UOP_FSM_STATE_DECODE ? (uop_opcode_is_in ||
+ uop_opcode_is_out ||
+ uop_opcode_is_ladder): 1'b0;
+ mmm_ena_x_r <= uop_fsm_state == UOP_FSM_STATE_DECODE ? uop_opcode_is_mmm : 1'b0;
+ mmm_ena_y_r <= uop_fsm_state == UOP_FSM_STATE_DECODE ? uop_opcode_is_mmm : 1'b0;
+ wrk_ena_r <= uop_fsm_state == UOP_FSM_STATE_DECODE ? (uop_opcode_is_wrk ||
+ uop_opcode_is_out ): 1'b0;
+ end
+
+
+ //
+ // UOP Completion Detector
+ //
+ reg uop_exit_from_busy;
+
+ always @* begin
+ //
+ uop_exit_from_busy = 0;
+ //
+ if (uop_opcode_is_in ) uop_exit_from_busy = ~io_mgr_ena & io_mgr_rdy ;
+ if (uop_opcode_is_out ) uop_exit_from_busy = (~io_mgr_ena & io_mgr_rdy) &
+ (~wrk_ena & wrk_rdy ) ;
+ if (uop_opcode_is_mmm ) uop_exit_from_busy = ~mmm_ena & mmm_rdy ;
+ if (uop_opcode_is_wrk ) uop_exit_from_busy = ~wrk_ena & wrk_rdy ;
+ if (uop_opcode_is_ladder) uop_exit_from_busy = ~io_mgr_ena & io_mgr_rdy ;
+ //
+ end
+
+
+ //
+ // UOP Parameters
+ //
+ task update_io_mgr_params;
+ input [UOP_CRT_W -1:0] sel_crt;
+ input [UOP_AUX_W -1:0] sel_aux;
+ input [BANK_ADDR_W -1:0] sel_in;
+ input [BANK_ADDR_W -1:0] sel_out;
+ input [UOP_OPCODE_W-1:0] opcode;
+ begin
+ io_mgr_sel_crt_r <= sel_crt;
+ io_mgr_sel_aux_r <= sel_aux;
+ io_mgr_sel_in_r <= sel_in;
+ io_mgr_sel_out_r <= sel_out;
+ io_mgr_opcode_r <= opcode;
+ end
+ endtask
+
+ task update_wrk_params;
+ input [BANK_ADDR_W -1:0] wide_in;
+ input [BANK_ADDR_W -1:0] narrow_in;
+ input [BANK_ADDR_W -1:0] wide_out;
+ input [BANK_ADDR_W -1:0] narrow_out;
+ input [UOP_OPCODE_W-1:0] opcode;
+ begin
+ wrk_sel_wide_in_r <= wide_in;
+ wrk_sel_narrow_in_r <= narrow_in;
+ wrk_sel_wide_out_r <= wide_out;
+ wrk_sel_narrow_out_r <= narrow_out;
+ wrk_opcode_r <= opcode;
+ end
+ endtask
+
+ task update_mmm_params;
+ input [ 1:0] ladder_mode;
+ input [BANK_ADDR_W-1:0] sel_wide_in;
+ input [BANK_ADDR_W-1:0] sel_narrow_in;
+ input force_unity_b;
+ input only_reduce;
+ input just_multiply;
+ begin
+ {mmm_ladder_mode_x_r, mmm_ladder_mode_y_r } <= ladder_mode;
+ {mmm_sel_wide_in_x_r, mmm_sel_wide_in_y_r } <= {2{sel_wide_in }};
+ {mmm_sel_narrow_in_x_r, mmm_sel_narrow_in_y_r} <= {2{sel_narrow_in}};
+ {mmm_force_unity_b_x_r, mmm_force_unity_b_y_r} <= {2{force_unity_b}};
+ {mmm_only_reduce_x_r, mmm_only_reduce_y_r } <= {2{only_reduce }};
+ {mmm_just_multiply_x_r, mmm_just_multiply_y_r} <= {2{just_multiply}};
+ end
+ endtask
+
+ task update_rdct_params;
+ input [BANK_ADDR_W-1:0] sel_wide_out;
+ input [BANK_ADDR_W-1:0] sel_narrow_out;
+ begin
+ {rdct_sel_wide_out_x_r, rdct_sel_wide_out_y_r } <= {2{sel_wide_out}};
+ {rdct_sel_narrow_out_x_r, rdct_sel_narrow_out_y_r} <= {2{sel_narrow_out}};
+ end
+ endtask
+
+ always @(posedge clk)
+ //
+ if (uop_fsm_state == UOP_FSM_STATE_DECODE)
+ //
+ case (uop_data_opcode)
+ //
+ UOP_OPCODE_INPUT_TO_WIDE:
+ update_io_mgr_params(uop_data_crt, uop_data_aux, uop_data_sel_narrow_in, uop_data_sel_wide_out, uop_data_opcode);
+ //
+ UOP_OPCODE_INPUT_TO_NARROW:
+ update_io_mgr_params(uop_data_crt, uop_data_aux, uop_data_sel_narrow_in, uop_data_sel_narrow_out, uop_data_opcode);
+ //
+ UOP_OPCODE_OUTPUT_FROM_NARROW: begin
+ update_io_mgr_params(uop_data_crt, UOP_AUX_DNC, BANK_DNC, uop_data_sel_narrow_out, uop_data_opcode);
+ update_wrk_params(BANK_DNC, uop_data_sel_narrow_in, BANK_DNC, BANK_DNC, uop_data_opcode);
+ end
+ //
+ UOP_OPCODE_COPY_CRT_Y2X,
+ UOP_OPCODE_COPY_LADDERS_X2Y,
+ UOP_OPCODE_CROSS_LADDERS_X2Y:
+ update_wrk_params(uop_data_sel_wide_in, uop_data_sel_narrow_in, uop_data_sel_wide_out, uop_data_sel_narrow_out, uop_data_opcode);
+ //
+ UOP_OPCODE_MODULAR_MULTIPLY: begin
+ update_mmm_params(uop_data_ladder_mux, uop_data_sel_wide_in, uop_data_sel_narrow_in, uop_data_aux, 1'b0, 1'b0);
+ update_rdct_params(uop_data_sel_wide_out, uop_data_sel_narrow_out);
+ end
+ //
+ UOP_OPCODE_MODULAR_SUBTRACT:
+ update_wrk_params(BANK_DNC, uop_data_sel_narrow_in, uop_data_sel_wide_out, uop_data_sel_narrow_out, uop_data_opcode);
+ //
+ UOP_OPCODE_MODULAR_REDUCE_INIT:
+ update_wrk_params(BANK_DNC, uop_data_sel_narrow_in, BANK_DNC, BANK_DNC, uop_data_opcode);
+ //
+ UOP_OPCODE_MODULAR_REDUCE_PROC: begin
+ update_mmm_params(2'bXX, BANK_DNC, BANK_DNC, 1'b0, 1'b1, 1'b0);
+ update_rdct_params(uop_data_sel_wide_out, uop_data_sel_narrow_out);
+ end
+ //
+ UOP_OPCODE_PROPAGATE_CARRIES:
+ update_wrk_params(BANK_DNC, uop_data_sel_narrow_in, BANK_DNC, uop_data_sel_narrow_out, uop_data_opcode);
+ //
+ UOP_OPCODE_MERGE_LH:
+ update_wrk_params(BANK_DNC, BANK_DNC, BANK_DNC, uop_data_sel_narrow_out, uop_data_opcode);
+ //
+ UOP_OPCODE_REGULAR_MULTIPLY: begin
+ update_mmm_params(2'b11, uop_data_sel_wide_in, uop_data_sel_narrow_in, 1'b0, 1'b0, 1'b1);
+ update_rdct_params(uop_data_sel_wide_out, uop_data_sel_narrow_out);
+ end
+ //
+ UOP_OPCODE_REGULAR_ADD_UNEVEN:
+ update_wrk_params(uop_data_sel_wide_in, uop_data_sel_narrow_in, BANK_DNC, uop_data_sel_narrow_out, uop_data_opcode);
+ //
+ UOP_OPCODE_LADDER_INIT,
+ UOP_OPCODE_LADDER_STEP:
+ update_io_mgr_params(UOP_CRT_DNC, UOP_AUX_DNC, BANK_DNC, BANK_DNC, uop_data_opcode);
+ //
+ endcase
+
+
+ //
+ // UOP Lengths
+ //
+ task update_io_mgr_length;
+ input [OP_ADDR_W -1:0] word_index_last;
+ input [BIT_INDEX_W-1:0] ladder_steps;
+ begin
+ io_mgr_word_index_last_r <= word_index_last;
+ io_mgr_ladder_steps_r <= ladder_steps;
+ end
+ endtask
+
+ task update_wrk_length;
+ input [OP_ADDR_W-1:0] word_index_last;
+ input [OP_ADDR_W-1:0] word_index_last_half;
+ begin
+ wrk_word_index_last_r <= word_index_last;
+ wrk_word_index_last_half_r <= word_index_last_half;
+ end
+ endtask
+
+ task update_mmm_length;
+ input [OP_ADDR_W-1:0] word_index_last;
+ begin
+ mmm_word_index_last_x_r <= word_index_last;
+ mmm_word_index_last_y_r <= word_index_last;
+ mmm_word_index_last_minus1_x_r <= word_index_last - 1'b1;
+ mmm_word_index_last_minus1_y_r <= word_index_last - 1'b1;
+ end
+ endtask
+
+ task update_rdct_length;
+ input [OP_ADDR_W-1:0] word_index_last;
+ begin
+ rdct_word_index_last_x_r <= word_index_last;
+ rdct_word_index_last_y_r <= word_index_last;
+ end
+ endtask
+
+ always @(posedge clk)
+ //
+ if (uop_fsm_state == UOP_FSM_STATE_DECODE)
+ //
+ case (uop_data_opcode)
+ //
+ UOP_OPCODE_INPUT_TO_WIDE,
+ UOP_OPCODE_INPUT_TO_NARROW,
+ UOP_OPCODE_OUTPUT_FROM_NARROW:
+ update_io_mgr_length(word_index_last_mux, BIT_INDEX_DNC);
+ //
+ UOP_OPCODE_COPY_CRT_Y2X,
+ UOP_OPCODE_COPY_LADDERS_X2Y,
+ UOP_OPCODE_CROSS_LADDERS_X2Y:
+ update_wrk_length(word_index_last_mux, OP_ADDR_DNC);
+ //
+ UOP_OPCODE_MODULAR_MULTIPLY: begin
+ update_mmm_length(word_index_last_mux);
+ update_rdct_length(word_index_last_mux);
+ end
+ //
+ UOP_OPCODE_MODULAR_SUBTRACT:
+ update_wrk_length(word_index_last_mux, OP_ADDR_DNC);
+ //
+ UOP_OPCODE_MODULAR_REDUCE_INIT:
+ update_wrk_length(word_index_last_n, word_index_last_pq);
+ //
+ UOP_OPCODE_MODULAR_REDUCE_PROC: begin
+ update_mmm_length(word_index_last_pq);
+ update_rdct_length(word_index_last_pq);
+ end
+ //
+ UOP_OPCODE_PROPAGATE_CARRIES:
+ update_wrk_length(word_index_last_mux, OP_ADDR_DNC);
+ //
+ UOP_OPCODE_MERGE_LH:
+ update_wrk_length(word_index_last_n, word_index_last_pq);
+ //
+ UOP_OPCODE_REGULAR_MULTIPLY: begin
+ update_mmm_length(word_index_last_pq);
+ update_rdct_length(word_index_last_pq);
+ end
+ //
+ UOP_OPCODE_REGULAR_ADD_UNEVEN:
+ update_wrk_length(word_index_last_n, word_index_last_pq);
+ //
+ UOP_OPCODE_LADDER_INIT,
+ UOP_OPCODE_LADDER_STEP:
+ update_io_mgr_length(OP_ADDR_LADDER_LAST, bit_index_last_mux);
+ //
+ endcase
+
+
+ //
+ // UOP FSM Process
+ //
+ always @(posedge clk)
+ //
+ if (rst) uop_fsm_state <= UOP_FSM_STATE_IDLE;
+ else uop_fsm_state <= uop_fsm_state_next;
+
+
+ //
+ // UOP FSM Transition Logic
+ //
+ always @* begin
+ //
+ case (uop_fsm_state)
+ UOP_FSM_STATE_IDLE: uop_fsm_state_next = ena ? UOP_FSM_STATE_FETCH : UOP_FSM_STATE_IDLE;
+ UOP_FSM_STATE_FETCH: uop_fsm_state_next = UOP_FSM_STATE_DECODE ;
+ UOP_FSM_STATE_DECODE: uop_fsm_state_next = uop_opcode_is_stop ? UOP_FSM_STATE_IDLE : UOP_FSM_STATE_BUSY;
+ UOP_FSM_STATE_BUSY: uop_fsm_state_next = uop_exit_from_busy ? UOP_FSM_STATE_FETCH : UOP_FSM_STATE_BUSY;
+ endcase
+ //
+ end
+
+
+ //
+ // Ready Flag Logic
+ //
+ reg rdy_r = 1'b1;
+ assign rdy = rdy_r;
+
+ always @(posedge clk)
+ //
+ if (rst) rdy_r <= 1'b1;
+ else case (uop_fsm_state)
+ UOP_FSM_STATE_IDLE: rdy_r <= ~ena;
+ UOP_FSM_STATE_DECODE: rdy_r <= uop_opcode_is_stop;
+ endcase
+
+
+endmodule