aboutsummaryrefslogtreecommitdiff
path: root/rtl/modexpng_io_manager.v
diff options
context:
space:
mode:
Diffstat (limited to 'rtl/modexpng_io_manager.v')
-rw-r--r--rtl/modexpng_io_manager.v170
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