aboutsummaryrefslogtreecommitdiff
path: root/rtl
diff options
context:
space:
mode:
authorPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2020-01-21 00:07:36 +0300
committerPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2020-01-21 00:07:36 +0300
commit76f89d63c8f06bb61ea7db42eddecc3498c5c73e (patch)
treee875808f476ae441ad72722f9307ab64bb63812e /rtl
parent04bc457e32f578f611d26753bc731122cb5dd87e (diff)
The I/O manager has to work in sync with the general worker module. Made the
necessary changes to make it work after the general worker update. Also moved debug simulation-time code into a separate file.
Diffstat (limited to 'rtl')
-rw-r--r--rtl/modexpng_io_manager.v364
-rw-r--r--rtl/modexpng_io_manager_debug.vh41
2 files changed, 266 insertions, 139 deletions
diff --git a/rtl/modexpng_io_manager.v b/rtl/modexpng_io_manager.v
index a5cd1db..466f1ea 100644
--- a/rtl/modexpng_io_manager.v
+++ b/rtl/modexpng_io_manager.v
@@ -173,19 +173,26 @@ module modexpng_io_manager
//
// FSM Declaration
//
- localparam [2:0] IO_FSM_STATE_IDLE = 3'b000;
- localparam [2:0] IO_FSM_STATE_LATENCY_PRE1 = 3'b001;
- localparam [2:0] IO_FSM_STATE_LATENCY_PRE2 = 3'b010;
- localparam [2:0] IO_FSM_STATE_BUSY = 3'b011;
- localparam [2:0] IO_FSM_STATE_EXTRA = 3'b100;
- localparam [2:0] IO_FSM_STATE_LATENCY_POST1 = 3'b101;
- localparam [2:0] IO_FSM_STATE_LATENCY_POST2 = 3'b110;
- localparam [2:0] IO_FSM_STATE_STOP = 3'b111;
-
- reg [2:0] io_fsm_state = IO_FSM_STATE_IDLE;
- reg [2:0] io_fsm_state_next;
-
+ localparam [3:0] IO_FSM_STATE_IDLE_X = 4'h0;
+ localparam [3:0] IO_FSM_STATE_LATENCY_PRE1_X = 4'h1;
+ localparam [3:0] IO_FSM_STATE_LATENCY_PRE2_X = 4'h2;
+ localparam [3:0] IO_FSM_STATE_LATENCY_PRE3_X = 4'h3;
+ localparam [3:0] IO_FSM_STATE_LATENCY_PRE4_X = 4'h4;
+ localparam [3:0] IO_FSM_STATE_BUSY1_X = 4'hA;
+ localparam [3:0] IO_FSM_STATE_BUSY2_X = 4'hB;
+ localparam [3:0] IO_FSM_STATE_EXTRA1_X = 4'hC;
+ localparam [3:0] IO_FSM_STATE_EXTRA2_X = 4'hD;
+ localparam [3:0] IO_FSM_STATE_LATENCY_POST1_X = 4'h5;
+ localparam [3:0] IO_FSM_STATE_LATENCY_POST2_X = 4'h6;
+ localparam [3:0] IO_FSM_STATE_LATENCY_POST3_X = 4'h7;
+ localparam [3:0] IO_FSM_STATE_LATENCY_POST4_X = 4'h8;
+ localparam [3:0] IO_FSM_STATE_STOP_X = 4'hF;
+
+ reg [3:0] io_fsm_state = IO_FSM_STATE_IDLE_X;
+ reg [3:0] io_fsm_state_next;
+ wire [3:0] io_fsm_state_after_busy;
+
//
// Control Signals
//
@@ -280,17 +287,32 @@ module modexpng_io_manager
// Delays
//
reg [OP_ADDR_W -1:0] in_1_addr_op_dly1;
- reg [OP_ADDR_W -1:0] in_1_addr_op_dly2;
reg [OP_ADDR_W -1:0] in_2_addr_op_dly1;
- reg [OP_ADDR_W -1:0] in_2_addr_op_dly2;
- reg [OP_ADDR_W -1:0] dummy_addr_op_dly1;
- reg [OP_ADDR_W -1:0] dummy_addr_op_dly2;
+ reg [OP_ADDR_W -1:0] dummy_addr_op_dly1;
+
+ reg [WORD_W -1:0] io_in_1_din_dly1;
+ reg [WORD_W -1:0] io_in_2_din_dly1;
+
+ reg [WORD_W -1:0] wrk_narrow_x_din_x_lsb_dly1;
+ reg [WORD_W -1:0] wrk_narrow_y_din_x_lsb_dly1;
+ reg [WORD_W -1:0] wrk_narrow_x_din_y_lsb_dly1;
+ reg [WORD_W -1:0] wrk_narrow_y_din_y_lsb_dly1;
+
always @(posedge clk) begin
//
- {in_1_addr_op_dly2, in_1_addr_op_dly1} <= {in_1_addr_op_dly1, in_1_addr_op};
- {in_2_addr_op_dly2, in_2_addr_op_dly1} <= {in_2_addr_op_dly1, in_2_addr_op};
- {dummy_addr_op_dly2, dummy_addr_op_dly1} <= {dummy_addr_op_dly1, dummy_addr_op};
+ {in_1_addr_op_dly1} <= {in_1_addr_op};
+ {in_2_addr_op_dly1} <= {in_2_addr_op};
+ //
+ {io_in_1_din_dly1} <= {io_in_1_din};
+ {io_in_2_din_dly1} <= {io_in_2_din};
+ //
+ {dummy_addr_op_dly1} <= {dummy_addr_op};
+ //
+ {wrk_narrow_x_din_x_lsb_dly1} <= {wrk_narrow_x_din_x_lsb};
+ {wrk_narrow_y_din_x_lsb_dly1} <= {wrk_narrow_y_din_x_lsb};
+ {wrk_narrow_x_din_y_lsb_dly1} <= {wrk_narrow_x_din_y_lsb};
+ {wrk_narrow_y_din_y_lsb_dly1} <= {wrk_narrow_y_din_y_lsb};
//
end
@@ -318,12 +340,7 @@ module modexpng_io_manager
wire sel_aux_is_1 = sel_aux == UOP_AUX_1;
wire sel_aux_is_2 = sel_aux == UOP_AUX_2;
-
- 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
@@ -346,7 +363,7 @@ module modexpng_io_manager
always @(posedge clk)
//
- if (io_fsm_state_next == IO_FSM_STATE_LATENCY_PRE1) begin
+ if (io_fsm_state_next == IO_FSM_STATE_LATENCY_PRE1_X) begin
//
if (opcode_is_ladder_init) begin
ladder_index <= ladder_steps;
@@ -366,40 +383,46 @@ module modexpng_io_manager
//
// Ladder Mux
//
- reg ladder_dpq_mux;
+ reg ladder_dpq_mux_dly1;
+ reg ladder_dpq_mux_dly2;
+ wire ladder_dpq_mux = ladder_dpq_mux_dly2;
- always @(io_in_2_din, ladder_index_lsb)
+ always @(io_in_2_din_dly1, 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];
+ 4'b0000: ladder_dpq_mux_dly1 = io_in_2_din_dly1[ 0];
+ 4'b0001: ladder_dpq_mux_dly1 = io_in_2_din_dly1[ 1];
+ 4'b0010: ladder_dpq_mux_dly1 = io_in_2_din_dly1[ 2];
+ 4'b0011: ladder_dpq_mux_dly1 = io_in_2_din_dly1[ 3];
+ 4'b0100: ladder_dpq_mux_dly1 = io_in_2_din_dly1[ 4];
+ 4'b0101: ladder_dpq_mux_dly1 = io_in_2_din_dly1[ 5];
+ 4'b0110: ladder_dpq_mux_dly1 = io_in_2_din_dly1[ 6];
+ 4'b0111: ladder_dpq_mux_dly1 = io_in_2_din_dly1[ 7];
+ 4'b1000: ladder_dpq_mux_dly1 = io_in_2_din_dly1[ 8];
+ 4'b1001: ladder_dpq_mux_dly1 = io_in_2_din_dly1[ 9];
+ 4'b1010: ladder_dpq_mux_dly1 = io_in_2_din_dly1[10];
+ 4'b1011: ladder_dpq_mux_dly1 = io_in_2_din_dly1[11];
+ 4'b1100: ladder_dpq_mux_dly1 = io_in_2_din_dly1[12];
+ 4'b1101: ladder_dpq_mux_dly1 = io_in_2_din_dly1[13];
+ 4'b1110: ladder_dpq_mux_dly1 = io_in_2_din_dly1[14];
+ 4'b1111: ladder_dpq_mux_dly1 = io_in_2_din_dly1[15];
endcase
-
+
+ always @(posedge clk)
+ //
+ ladder_dpq_mux_dly2 <= ladder_dpq_mux_dly1;
+
always @(posedge clk)
//
case (io_fsm_state)
//
- IO_FSM_STATE_BUSY:
+ IO_FSM_STATE_BUSY1_X:
if (opcode_is_ladder) ladder_d_r <= ladder_dpq_mux;
//
- IO_FSM_STATE_LATENCY_POST1:
+ IO_FSM_STATE_LATENCY_POST1_X:
if (opcode_is_ladder) ladder_p_r <= ladder_dpq_mux;
//
- IO_FSM_STATE_LATENCY_POST2:
+ IO_FSM_STATE_LATENCY_POST3_X:
if (opcode_is_ladder) ladder_q_r <= ladder_dpq_mux;
//
endcase
@@ -415,14 +438,14 @@ module modexpng_io_manager
in_2_en <= 1'b0;
end else case (io_fsm_state_next)
//
- IO_FSM_STATE_LATENCY_PRE1,
- IO_FSM_STATE_LATENCY_PRE2,
- IO_FSM_STATE_BUSY: begin
+ IO_FSM_STATE_LATENCY_PRE1_X,
+ IO_FSM_STATE_LATENCY_PRE3_X,
+ IO_FSM_STATE_BUSY1_X: begin
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
+ IO_FSM_STATE_EXTRA1_X: begin
in_1_en <= opcode_is_input && sel_aux_is_1 && sel_in_needs_extra;
in_2_en <= opcode_is_input && sel_aux_is_2 && sel_in_needs_extra;
end
@@ -434,6 +457,7 @@ module modexpng_io_manager
//
endcase
+
//
// Destination Enable Logic
//
@@ -450,9 +474,9 @@ module modexpng_io_manager
//
end else case (io_fsm_state)
//
- IO_FSM_STATE_BUSY,
- IO_FSM_STATE_EXTRA,
- IO_FSM_STATE_LATENCY_POST1: begin
+ IO_FSM_STATE_BUSY1_X,
+ IO_FSM_STATE_EXTRA1_X,
+ IO_FSM_STATE_LATENCY_POST1_X: begin
//
wide_xy_ena_x <= opcode_is_input_wide && sel_crt_is_x;
wide_xy_ena_y <= opcode_is_input_wide && sel_crt_is_y;
@@ -463,7 +487,7 @@ module modexpng_io_manager
//
end
//
- IO_FSM_STATE_LATENCY_POST2: begin
+ IO_FSM_STATE_LATENCY_POST3_X: begin
//
wide_xy_ena_x <= 1'b0;
wide_xy_ena_y <= 1'b0;
@@ -491,10 +515,23 @@ module modexpng_io_manager
//
// Output Data Logic
//
- wire [WORD_EXT_W -1:0] io_in_dout_mux = {{(WORD_EXT_W-WORD_W){1'b0}}, sel_aux_is_1 ? io_in_1_din : io_in_2_din};
+ reg [ WORD_W -1:0] io_in_dout_mux_dly2;
+ wire [WORD_EXT_W -1:0] io_in_dout_mux = {{(WORD_EXT_W-WORD_W){1'b0}}, io_in_dout_mux_dly2};
- wire [WORD_W -1:0] wrk_narrow_xy_din_x_mux_lsb = sel_aux == UOP_AUX_1 ? wrk_narrow_x_din_x_lsb : wrk_narrow_y_din_x_lsb;
- wire [WORD_W -1:0] wrk_narrow_xy_din_y_mux_lsb = sel_aux == UOP_AUX_1 ? wrk_narrow_x_din_y_lsb : wrk_narrow_y_din_y_lsb;
+ reg [WORD_W -1:0] wrk_narrow_din_x_lsb_mux_dly2;
+ reg [WORD_W -1:0] wrk_narrow_din_y_lsb_mux_dly2;
+
+ wire [WORD_W -1:0] wrk_narrow_din_x_lsb_mux = wrk_narrow_din_x_lsb_mux_dly2;
+ wire [WORD_W -1:0] wrk_narrow_din_y_lsb_mux = wrk_narrow_din_y_lsb_mux_dly2;
+
+ always @(posedge clk) begin
+ //
+ io_in_dout_mux_dly2 <= sel_aux_is_1 ? io_in_1_din_dly1 : io_in_2_din_dly1;
+ //
+ wrk_narrow_din_x_lsb_mux_dly2 = sel_aux == UOP_AUX_1 ? wrk_narrow_x_din_x_lsb_dly1 : wrk_narrow_y_din_x_lsb_dly1;
+ wrk_narrow_din_y_lsb_mux_dly2 = sel_aux == UOP_AUX_1 ? wrk_narrow_x_din_y_lsb_dly1 : wrk_narrow_y_din_y_lsb_dly1;
+ //
+ end
always @(posedge clk) begin
//
@@ -511,25 +548,25 @@ module modexpng_io_manager
//
case (io_fsm_state)
//
- IO_FSM_STATE_BUSY,
- IO_FSM_STATE_EXTRA,
- IO_FSM_STATE_LATENCY_POST1: begin
+ IO_FSM_STATE_BUSY1_X,
+ IO_FSM_STATE_EXTRA1_X,
+ IO_FSM_STATE_LATENCY_POST1_X: begin
//
if (opcode_is_input_wide && sel_crt_is_x) {wide_x_din_x, wide_y_din_x} <= {2{io_in_dout_mux}};
if (opcode_is_input_wide && sel_crt_is_y) {wide_x_din_y, wide_y_din_y} <= {2{io_in_dout_mux}};
if (opcode_is_input_narrow && sel_crt_is_x) {narrow_x_din_x, narrow_y_din_x} <= {2{io_in_dout_mux}};
if (opcode_is_input_narrow && sel_crt_is_y) {narrow_x_din_y, narrow_y_din_y} <= {2{io_in_dout_mux}};
//
- if (opcode_is_output) out_dout <= sel_crt_is_x ? wrk_narrow_xy_din_x_mux_lsb : wrk_narrow_xy_din_y_mux_lsb;
+ if (opcode_is_output) out_dout <= sel_crt_is_x ? wrk_narrow_din_x_lsb_mux : wrk_narrow_din_y_lsb_mux;
//
end
//
- IO_FSM_STATE_LATENCY_POST2: begin
+ IO_FSM_STATE_LATENCY_POST3_X: begin
//
if (opcode_is_input_narrow && sel_crt_is_x && sel_in_needs_extra) {narrow_x_din_x, narrow_y_din_x} <= {2{io_in_dout_mux}};
if (opcode_is_input_narrow && sel_crt_is_y && sel_in_needs_extra) {narrow_x_din_y, narrow_y_din_y} <= {2{io_in_dout_mux}};
//
- if (opcode_is_output) out_dout <= sel_crt_is_x ? wrk_narrow_xy_din_x_mux_lsb : wrk_narrow_xy_din_y_mux_lsb;
+ if (opcode_is_output) out_dout <= sel_crt_is_x ? wrk_narrow_din_x_lsb_mux : wrk_narrow_din_y_lsb_mux;
//
end
//
@@ -541,8 +578,26 @@ module modexpng_io_manager
//
// Destination Address Logic
//
- wire [OP_ADDR_W -1:0] in_addr_op_dly2_mux =
- sel_aux_is_1 ? in_1_addr_op_dly2 : in_2_addr_op_dly2;
+ reg [OP_ADDR_W -1:0] in_addr_op_dly2_mux;
+ reg [OP_ADDR_W -1:0] in_addr_op_dly3_mux;
+ reg [OP_ADDR_W -1:0] in_addr_op_dly4_mux;
+ wire [OP_ADDR_W -1:0] in_addr_op_mux = in_addr_op_dly4_mux;
+
+ reg [OP_ADDR_W -1:0] dummy_addr_op_dly2;
+ reg [OP_ADDR_W -1:0] dummy_addr_op_dly3;
+ reg [OP_ADDR_W -1:0] dummy_addr_op_dly4;
+
+ always @(posedge clk) begin
+ //
+ in_addr_op_dly2_mux <= sel_aux_is_1 ? in_1_addr_op_dly1 : in_2_addr_op_dly1;
+ in_addr_op_dly3_mux <= in_addr_op_dly2_mux;
+ in_addr_op_dly4_mux <= in_addr_op_dly3_mux;
+ //
+ dummy_addr_op_dly2 <= dummy_addr_op_dly1;
+ dummy_addr_op_dly3 <= dummy_addr_op_dly2;
+ dummy_addr_op_dly4 <= dummy_addr_op_dly3;
+ //
+ end
always @(posedge clk) begin
//
@@ -554,27 +609,27 @@ module modexpng_io_manager
//
case (io_fsm_state)
//
- IO_FSM_STATE_BUSY,
- IO_FSM_STATE_EXTRA,
- IO_FSM_STATE_LATENCY_POST1: begin
- if (opcode_is_input_wide && sel_crt_is_x) {wide_xy_bank_x, wide_xy_addr_x } <= {sel_out, in_addr_op_dly2_mux};
- if (opcode_is_input_wide && sel_crt_is_y) {wide_xy_bank_y, wide_xy_addr_y } <= {sel_out, in_addr_op_dly2_mux};
- if (opcode_is_input_narrow && sel_crt_is_x) {narrow_xy_bank_x, narrow_xy_addr_x} <= {sel_out, in_addr_op_dly2_mux};
- if (opcode_is_input_narrow && sel_crt_is_y) {narrow_xy_bank_y, narrow_xy_addr_y} <= {sel_out, in_addr_op_dly2_mux};
- if (opcode_is_output ) {out_addr_bank, out_addr_op} <= {sel_out, dummy_addr_op_dly2};
+ IO_FSM_STATE_BUSY1_X,
+ IO_FSM_STATE_EXTRA1_X,
+ IO_FSM_STATE_LATENCY_POST1_X: begin
+ if (opcode_is_input_wide && sel_crt_is_x) {wide_xy_bank_x, wide_xy_addr_x } <= {sel_out, in_addr_op_mux };
+ if (opcode_is_input_wide && sel_crt_is_y) {wide_xy_bank_y, wide_xy_addr_y } <= {sel_out, in_addr_op_mux };
+ if (opcode_is_input_narrow && sel_crt_is_x) {narrow_xy_bank_x, narrow_xy_addr_x} <= {sel_out, in_addr_op_mux };
+ if (opcode_is_input_narrow && sel_crt_is_y) {narrow_xy_bank_y, narrow_xy_addr_y} <= {sel_out, in_addr_op_mux };
+ if (opcode_is_output ) {out_addr_bank, out_addr_op} <= {sel_out, dummy_addr_op_dly4};
end
//
- IO_FSM_STATE_LATENCY_POST2: begin
+ IO_FSM_STATE_LATENCY_POST3_X: begin
if (opcode_is_input_narrow && sel_crt_is_x && sel_in_needs_extra) {narrow_xy_bank_x, narrow_xy_addr_x} <= {BANK_NARROW_EXT, OP_ADDR_EXT_COEFF };
if (opcode_is_input_narrow && sel_crt_is_y && sel_in_needs_extra) {narrow_xy_bank_y, narrow_xy_addr_y} <= {BANK_NARROW_EXT, OP_ADDR_EXT_COEFF };
- if (opcode_is_output ) {out_addr_bank, out_addr_op } <= {sel_out, dummy_addr_op_dly2};
+ if (opcode_is_output ) {out_addr_bank, out_addr_op } <= {sel_out, dummy_addr_op_dly4};
end
//
endcase
//
end
-
+
//
// Source Address Logic
//
@@ -586,43 +641,71 @@ module modexpng_io_manager
wire [OP_ADDR_W -1:0] in_2_addr_op_next = in_2_addr_next[OP_ADDR_W -1:0];
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_one = in_2_addr_op_next == OP_ADDR_ONE;
- assign dummy_addr_op_next_is_last = dummy_addr_op_next == word_index_last;
-
+ reg in_1_addr_op_is_last = 1'b0;
+ reg in_2_addr_op_is_last = 1'b0;
+ reg dummy_addr_op_is_last = 1'b0;
+
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
+ IO_FSM_STATE_LATENCY_PRE1_X: begin
//
{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};
+ 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
+ IO_FSM_STATE_LATENCY_PRE3_X: 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;
//
+ end
+ //
+ IO_FSM_STATE_BUSY1_X: 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;
+ //
+ end
+ //
+ IO_FSM_STATE_EXTRA1_X:
+ //
+ if (opcode_is_input && sel_in_needs_extra) begin
+ //
+ if (sel_aux_is_1) {in_1_addr_bank, in_1_addr_op} <= in_1_addr_next;
+ if (sel_aux_is_2) {in_2_addr_bank, in_2_addr_op} <= in_2_addr_next;
+ //
+ end
+ //
+ endcase
+ //
+ end
+
+ always @(posedge clk)
+ //
+ case (io_fsm_state_next)
+ //
+ IO_FSM_STATE_LATENCY_PRE1_X: begin
+ //
+ 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_PRE3_X: begin
+ //
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]};
@@ -630,11 +713,7 @@ module modexpng_io_manager
//
end
//
- 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;
+ IO_FSM_STATE_BUSY1_X: begin
//
in_1_addr_next <= in_1_addr_next + 1'b1;
if (!opcode_is_ladder) in_2_addr_next <= in_2_addr_next + 1'b1;
@@ -643,33 +722,42 @@ module modexpng_io_manager
//
end
//
- IO_FSM_STATE_EXTRA:
+ IO_FSM_STATE_EXTRA1_X:
//
if (opcode_is_input && sel_in_needs_extra) begin
//
- if (sel_aux_is_1) begin
- {in_1_addr_bank, in_1_addr_op} <= in_1_addr_next;
- in_1_addr_next <= in_1_addr_next + 1'b1;
- end
- //
- if (sel_aux_is_2) begin
- {in_2_addr_bank, in_2_addr_op} <= in_2_addr_next;
- in_2_addr_next <= in_2_addr_next + 1'b1;
- end
+ if (sel_aux_is_1) in_1_addr_next <= in_1_addr_next + 1'b1;
+ if (sel_aux_is_2) in_2_addr_next <= in_2_addr_next + 1'b1;
//
- end
+ end
+ //
+ endcase
+
+ always @(posedge clk) begin
+ //
+ in_1_addr_op_is_last <= 1'b0;
+ in_2_addr_op_is_last <= 1'b0;
+ dummy_addr_op_is_last <= 1'b0;
+ //
+ case (io_fsm_state_next)
+ //
+ IO_FSM_STATE_BUSY1_X: begin
+ in_1_addr_op_is_last <= in_1_addr_op_next == word_index_last;
+ in_2_addr_op_is_last <= in_2_addr_op_next == word_index_last;
+ dummy_addr_op_is_last <= dummy_addr_op_next == word_index_last;
+ end
//
endcase
//
end
-
+
//
// FSM Process
//
always @(posedge clk or negedge rst_n)
//
- if (!rst_n) io_fsm_state <= IO_FSM_STATE_IDLE;
+ if (!rst_n) io_fsm_state <= IO_FSM_STATE_IDLE_X;
else io_fsm_state <= io_fsm_state_next;
@@ -682,13 +770,13 @@ module modexpng_io_manager
//
io_fsm_done <= 1'b0;
//
- if (io_fsm_state == IO_FSM_STATE_BUSY) begin
+ if (io_fsm_state == IO_FSM_STATE_BUSY1_X) begin
//
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;
+ if (sel_aux_is_1 && in_1_addr_op_is_last) io_fsm_done <= 1'b1;
+ if (sel_aux_is_2 && in_2_addr_op_is_last) io_fsm_done <= 1'b1;
end else if (opcode_is_output || opcode_is_ladder) begin
- if (dummy_addr_op_next_is_last) io_fsm_done <= 1'b1;
+ if (dummy_addr_op_is_last) io_fsm_done <= 1'b1;
end
//
end
@@ -699,19 +787,26 @@ module modexpng_io_manager
//
// FSM Transition Logic
//
- wire [2:0] io_fsm_state_after_busy = opcode_is_input ? IO_FSM_STATE_EXTRA : IO_FSM_STATE_LATENCY_POST1;
+ assign io_fsm_state_after_busy = opcode_is_input ? IO_FSM_STATE_EXTRA1_X : IO_FSM_STATE_LATENCY_POST1_X;
always @* begin
//
case (io_fsm_state)
- IO_FSM_STATE_IDLE: io_fsm_state_next = ena ? IO_FSM_STATE_LATENCY_PRE1 : IO_FSM_STATE_IDLE ;
- IO_FSM_STATE_LATENCY_PRE1: io_fsm_state_next = IO_FSM_STATE_LATENCY_PRE2 ;
- IO_FSM_STATE_LATENCY_PRE2: io_fsm_state_next = IO_FSM_STATE_BUSY ;
- IO_FSM_STATE_BUSY: io_fsm_state_next = io_fsm_done ? io_fsm_state_after_busy : IO_FSM_STATE_BUSY ;
- IO_FSM_STATE_EXTRA: io_fsm_state_next = IO_FSM_STATE_LATENCY_POST1 ;
- IO_FSM_STATE_LATENCY_POST1: io_fsm_state_next = IO_FSM_STATE_LATENCY_POST2 ;
- IO_FSM_STATE_LATENCY_POST2: io_fsm_state_next = IO_FSM_STATE_STOP ;
- IO_FSM_STATE_STOP: io_fsm_state_next = IO_FSM_STATE_IDLE ;
+ IO_FSM_STATE_IDLE_X: io_fsm_state_next = ena ? IO_FSM_STATE_LATENCY_PRE1_X : IO_FSM_STATE_IDLE_X ;
+ IO_FSM_STATE_LATENCY_PRE1_X: io_fsm_state_next = IO_FSM_STATE_LATENCY_PRE2_X ;
+ IO_FSM_STATE_LATENCY_PRE2_X: io_fsm_state_next = IO_FSM_STATE_LATENCY_PRE3_X ;
+ IO_FSM_STATE_LATENCY_PRE3_X: io_fsm_state_next = IO_FSM_STATE_LATENCY_PRE4_X ;
+ IO_FSM_STATE_LATENCY_PRE4_X: io_fsm_state_next = IO_FSM_STATE_BUSY1_X ;
+ IO_FSM_STATE_BUSY1_X: io_fsm_state_next = IO_FSM_STATE_BUSY2_X ;
+ IO_FSM_STATE_BUSY2_X: io_fsm_state_next = io_fsm_done ? io_fsm_state_after_busy : IO_FSM_STATE_BUSY1_X;
+ IO_FSM_STATE_EXTRA1_X: io_fsm_state_next = IO_FSM_STATE_EXTRA2_X ;
+ IO_FSM_STATE_EXTRA2_X: io_fsm_state_next = IO_FSM_STATE_LATENCY_POST1_X ;
+ IO_FSM_STATE_LATENCY_POST1_X: io_fsm_state_next = IO_FSM_STATE_LATENCY_POST2_X ;
+ IO_FSM_STATE_LATENCY_POST2_X: io_fsm_state_next = IO_FSM_STATE_LATENCY_POST3_X ;
+ IO_FSM_STATE_LATENCY_POST3_X: io_fsm_state_next = IO_FSM_STATE_LATENCY_POST4_X ;
+ IO_FSM_STATE_LATENCY_POST4_X: io_fsm_state_next = IO_FSM_STATE_STOP_X ;
+ IO_FSM_STATE_STOP_X: io_fsm_state_next = IO_FSM_STATE_IDLE_X ;
+ default: io_fsm_state_next = IO_FSM_STATE_IDLE_X ;
endcase
//
end
@@ -728,25 +823,16 @@ module modexpng_io_manager
//
if (!rst_n) rdy_reg <= 1'b1;
else case (io_fsm_state)
- IO_FSM_STATE_IDLE: rdy_reg <= ~ena;
- IO_FSM_STATE_STOP: rdy_reg <= 1'b1;
+ IO_FSM_STATE_IDLE_X: rdy_reg <= ~ena;
+ IO_FSM_STATE_STOP_X: rdy_reg <= 1'b1;
endcase
//
- // BEGIN DEBUG
+ // Optional Debug Facility
//
`ifdef MODEXPNG_ENABLE_DEBUG
- always @(posedge clk)
- //
- if (io_fsm_state == IO_FSM_STATE_STOP) begin
- if (opcode_is_ladder_init) begin
- $display("[step] | D | P | Q");
- $display("-------+---+---+---");
- end else if (opcode_is_ladder_step)
- $display("[%4d] | %d | %d | %d", ladder_index, ladder_d_r, ladder_p_r, ladder_q_r);
- end
- //
+ `include "modexpng_io_manager_debug.vh"
`endif
diff --git a/rtl/modexpng_io_manager_debug.vh b/rtl/modexpng_io_manager_debug.vh
new file mode 100644
index 0000000..593005b
--- /dev/null
+++ b/rtl/modexpng_io_manager_debug.vh
@@ -0,0 +1,41 @@
+//======================================================================
+//
+// Copyright (c) 2019, NORDUnet A/S All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// - Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+always @(posedge clk)
+ //
+ if (io_fsm_state == IO_FSM_STATE_STOP_X) begin
+ if (opcode_is_ladder_init) begin
+ $display("[step] | D | P | Q");
+ $display("-------+---+---+---");
+ end else if (opcode_is_ladder_step)
+ $display("[%4d] | %d | %d | %d", ladder_index, ladder_d_r, ladder_p_r, ladder_q_r);
+ end