diff options
Diffstat (limited to 'rtl/modexpng_io_manager.v')
-rw-r--r-- | rtl/modexpng_io_manager.v | 170 |
1 files changed, 153 insertions, 17 deletions
diff --git a/rtl/modexpng_io_manager.v b/rtl/modexpng_io_manager.v index dfbd676..59f4709 100644 --- a/rtl/modexpng_io_manager.v +++ b/rtl/modexpng_io_manager.v @@ -53,7 +53,13 @@ module modexpng_io_manager io_out_dout, wrk_narrow_x_din_x_trunc, - wrk_narrow_x_din_y_trunc + wrk_narrow_x_din_y_trunc, + + ladder_steps, + ladder_d, + ladder_p, + ladder_q, + ladder_done ); // @@ -120,6 +126,12 @@ module modexpng_io_manager output [ WORD_W -1:0] wrk_narrow_x_din_x_trunc; output [ WORD_W -1:0] wrk_narrow_x_din_y_trunc; + + input [ BIT_INDEX_W -1:0] ladder_steps; + output ladder_d; + output ladder_p; + output ladder_q; + output ladder_done; // @@ -254,6 +266,10 @@ module modexpng_io_manager wire opcode_is_output = opcode == UOP_OPCODE_OUTPUT_FROM_NARROW; + wire opcode_is_ladder_init = opcode == UOP_OPCODE_LADDER_INIT; + wire opcode_is_ladder_step = opcode == UOP_OPCODE_LADDER_STEP; + wire opcode_is_ladder = opcode_is_ladder_init || opcode_is_ladder_step; + wire opcode_is_input_wide = opcode == UOP_OPCODE_INPUT_TO_WIDE; wire opcode_is_input_narrow = opcode == UOP_OPCODE_INPUT_TO_NARROW; @@ -269,8 +285,90 @@ module modexpng_io_manager wire in_1_addr_op_next_is_last; wire in_2_addr_op_next_is_last; + wire in_2_addr_op_next_is_one; wire dummy_addr_op_next_is_last; + + // + // Ladder Init/Step Logic + // + reg ladder_d_r; + reg ladder_p_r; + reg ladder_q_r; + reg ladder_done_r = 1'b0; + + assign ladder_d = ladder_d_r; + assign ladder_p = ladder_p_r; + assign ladder_q = ladder_q_r; + assign ladder_done = ladder_done_r; + + reg [BIT_INDEX_W -1:0] ladder_index; + reg [BIT_INDEX_W -1:0] ladder_index_next; + wire [ OP_ADDR_W -1:0] ladder_index_msb = ladder_index[BIT_INDEX_W-1-: OP_ADDR_W]; + wire [ WORD_MUX_W -1:0] ladder_index_lsb = ladder_index[ WORD_MUX_W-1-:WORD_MUX_W]; + wire ladder_index_is_zero = ladder_index == BIT_INDEX_ZERO; + + always @(posedge clk) + // + if (io_fsm_state_next == IO_FSM_STATE_LATENCY_PRE1) begin + // + if (opcode_is_ladder_init) begin + ladder_index <= ladder_steps; + ladder_index_next <= ladder_steps - 1'b1; + ladder_done_r <= 1'b0; + end + // + if (opcode_is_ladder_step) begin + ladder_index <= ladder_index_next; + ladder_index_next <= ladder_index_next - 1'b1; + if (ladder_index_is_zero) ladder_done_r <= 1'b1; + end + // + end + + + // + // Ladder Mux + // + reg ladder_dpq_mux; + + always @(io_in_2_din, ladder_index_lsb) + // + case(ladder_index_lsb) + 4'b0000: ladder_dpq_mux = io_in_2_din[ 0]; + 4'b0001: ladder_dpq_mux = io_in_2_din[ 1]; + 4'b0010: ladder_dpq_mux = io_in_2_din[ 2]; + 4'b0011: ladder_dpq_mux = io_in_2_din[ 3]; + 4'b0100: ladder_dpq_mux = io_in_2_din[ 4]; + 4'b0101: ladder_dpq_mux = io_in_2_din[ 5]; + 4'b0110: ladder_dpq_mux = io_in_2_din[ 6]; + 4'b0111: ladder_dpq_mux = io_in_2_din[ 7]; + 4'b1000: ladder_dpq_mux = io_in_2_din[ 8]; + 4'b1001: ladder_dpq_mux = io_in_2_din[ 9]; + 4'b1010: ladder_dpq_mux = io_in_2_din[10]; + 4'b1011: ladder_dpq_mux = io_in_2_din[11]; + 4'b1100: ladder_dpq_mux = io_in_2_din[12]; + 4'b1101: ladder_dpq_mux = io_in_2_din[13]; + 4'b1110: ladder_dpq_mux = io_in_2_din[14]; + 4'b1111: ladder_dpq_mux = io_in_2_din[15]; + endcase + + always @(posedge clk) + // + case (io_fsm_state) + // + IO_FSM_STATE_BUSY: + if (opcode_is_ladder) ladder_d_r <= ladder_dpq_mux; + // + IO_FSM_STATE_LATENCY_POST1: + if (opcode_is_ladder) ladder_p_r <= ladder_dpq_mux; + // + IO_FSM_STATE_LATENCY_POST2: + if (opcode_is_ladder) ladder_q_r <= ladder_dpq_mux; + // + endcase + + // // Source Enable Logic // @@ -284,8 +382,8 @@ module modexpng_io_manager IO_FSM_STATE_LATENCY_PRE1, IO_FSM_STATE_LATENCY_PRE2, IO_FSM_STATE_BUSY: begin - in_1_en <= opcode_is_input && sel_aux_is_1; - in_2_en <= opcode_is_input && sel_aux_is_2; + in_1_en <= opcode_is_input && sel_aux_is_1; + in_2_en <= (opcode_is_input && sel_aux_is_2) || opcode_is_ladder; end // IO_FSM_STATE_EXTRA: begin @@ -450,35 +548,59 @@ module modexpng_io_manager wire [OP_ADDR_W -1:0] dummy_addr_op_next = dummy_addr_next; assign in_1_addr_op_next_is_last = in_1_addr_op_next == word_index_last; - assign in_2_addr_op_next_is_last = in_2_addr_op_next == word_index_last; + assign in_2_addr_op_next_is_last = in_2_addr_op_next == word_index_last; + assign in_2_addr_op_next_is_one = in_2_addr_op_next == OP_ADDR_ONE; assign dummy_addr_op_next_is_last = dummy_addr_op_next == word_index_last; - always @(posedge clk) + always @(posedge clk) begin + // + {in_1_addr_bank, in_1_addr_op } <= {BANK_DNC, OP_ADDR_DNC}; + {in_2_addr_bank, in_2_addr_op } <= {BANK_DNC, OP_ADDR_DNC}; + { dummy_addr_op} <= { OP_ADDR_DNC}; + // + in_1_addr_next <= {BANK_DNC, OP_ADDR_DNC}; + in_2_addr_next <= {BANK_DNC, OP_ADDR_DNC}; + dummy_addr_next <= { OP_ADDR_DNC}; // case (io_fsm_state_next) // IO_FSM_STATE_LATENCY_PRE1: begin // - {in_1_addr_bank, in_1_addr_op } <= {sel_in, OP_ADDR_ZERO}; - {in_2_addr_bank, in_2_addr_op } <= {sel_in, OP_ADDR_ZERO}; - { dummy_addr_op} <= { OP_ADDR_ZERO}; + {in_1_addr_bank, in_1_addr_op } <= {sel_in, OP_ADDR_ZERO}; + if (!opcode_is_ladder) {in_2_addr_bank, in_2_addr_op } <= {sel_in, OP_ADDR_ZERO}; + else {in_2_addr_bank, in_2_addr_op } <= {BANK_DNC, OP_ADDR_DNC}; + { dummy_addr_op} <= { OP_ADDR_ZERO}; + // + in_1_addr_next <= {sel_in, OP_ADDR_ONE}; + in_2_addr_next <= {sel_in, OP_ADDR_ONE}; + dummy_addr_next <= { OP_ADDR_ONE}; + // + end + // + IO_FSM_STATE_LATENCY_PRE2: begin + // + {in_1_addr_bank, in_1_addr_op } <= in_1_addr_next; + if (!opcode_is_ladder) {in_2_addr_bank, in_2_addr_op } <= in_2_addr_next; + else {in_2_addr_bank, in_2_addr_op } <= {BANK_IN_2_D, ladder_index_msb}; + { dummy_addr_op} <= dummy_addr_next; // - in_1_addr_next <= {sel_in, OP_ADDR_ONE}; - in_2_addr_next <= {sel_in, OP_ADDR_ONE}; - dummy_addr_next <= { OP_ADDR_ONE}; + in_1_addr_next <= in_1_addr_next + 1'b1; + if (!opcode_is_ladder) in_2_addr_next <= in_2_addr_next + 1'b1; + else in_2_addr_next <= {BANK_IN_2_P, 1'b1, ladder_index_msb[OP_ADDR_W-2:0]}; + dummy_addr_next <= dummy_addr_next + 1'b1; // end // - IO_FSM_STATE_LATENCY_PRE2, IO_FSM_STATE_BUSY: begin // {in_1_addr_bank, in_1_addr_op } <= in_1_addr_next; {in_2_addr_bank, in_2_addr_op } <= in_2_addr_next; { dummy_addr_op} <= dummy_addr_next; // - in_1_addr_next <= in_1_addr_next + 1'b1; - in_2_addr_next <= in_2_addr_next + 1'b1; - dummy_addr_next <= dummy_addr_next + 1'b1; + in_1_addr_next <= in_1_addr_next + 1'b1; + if (!opcode_is_ladder) in_2_addr_next <= in_2_addr_next + 1'b1; + else in_2_addr_next <= {BANK_IN_2_Q, 1'b1, ladder_index_msb[OP_ADDR_W-2:0]}; + dummy_addr_next <= dummy_addr_next + 1'b1; // end // @@ -499,7 +621,8 @@ module modexpng_io_manager end // endcase - + // + end // @@ -525,7 +648,7 @@ module modexpng_io_manager if (opcode_is_input) begin if (sel_aux_is_1 && in_1_addr_op_next_is_last) io_fsm_done <= 1'b1; if (sel_aux_is_2 && in_2_addr_op_next_is_last) io_fsm_done <= 1'b1; - end else if (opcode_is_output) begin + end else if (opcode_is_output || opcode_is_ladder) begin if (dummy_addr_op_next_is_last) io_fsm_done <= 1'b1; end // @@ -571,4 +694,17 @@ module modexpng_io_manager endcase + // + // BEGIN DEBUG + // + always @(posedge clk) + // + if ((io_fsm_state == IO_FSM_STATE_STOP) && opcode_is_ladder) + $display("[%4d] / %d / %d / %d", ladder_index, ladder_d_r, ladder_p_r, ladder_q_r); + + // + // END DEBUG + // + + endmodule |