//======================================================================
//
// Copyright: 2019, The Commons Conservancy Cryptech Project
// SPDX-License-Identifier: BSD-3-Clause
//
// 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 copyright holder 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.
//
//======================================================================
module modexpng_uop_engine
(
clk,
rst_n,
ena,
rdy,
uop_decoded_stop,
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_n;
input ena;
output rdy;
output uop_decoded_stop;
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 [2:0] UOP_FSM_STATE_IDLE = 3'b000;
localparam [2:0] UOP_FSM_STATE_FETCH = 3'b001;
localparam [2:0] UOP_FSM_STATE_DECODE_1 = 3'b010;
localparam [2:0] UOP_FSM_STATE_DECODE_2 = 3'b011;
localparam [2:0] UOP_FSM_STATE_BUSY = 3'b100;
reg [2:0] uop_fsm_state = UOP_FSM_STATE_IDLE;
reg [2:0] uop_fsm_state_next;
//
// UOP ROM
//
reg [UOP_ADDR_W -1:0] uop_addr;
wire [UOP_W -1:0] uop_data_int;
modexpng_uop_rom uop_rom
(
.clk (clk),
.addr (uop_addr),
.data (uop_data_int)
);
//
// UOP ROM Data Decoder
//
reg [UOP_OPCODE_W -1:0] uop_data_opcode_dec;
reg [UOP_CRT_W -1:0] uop_data_crt_dec;
reg [UOP_NPQ_W -1:0] uop_data_npq_dec;
reg [UOP_AUX_W -1:0] uop_data_aux_dec;
reg [UOP_LADDER_W -1:0] uop_data_ladder_dec;
reg [BANK_ADDR_W -1:0] uop_data_sel_wide_in_dec;
reg [BANK_ADDR_W -1:0] uop_data_sel_narrow_in_dec;
reg [BANK_ADDR_W -1:0] uop_data_sel_wide_out_dec;
reg [BANK_ADDR_W -1:0] uop_data_sel_narrow_out_dec;
always @(posedge clk) begin
uop_data_opcode_dec <= uop_data_int[UOP_W -1-: UOP_OPCODE_W];
uop_data_crt_dec <= uop_data_int[UOP_W -UOP_OPCODE_W -1-: UOP_CRT_W ];
uop_data_npq_dec <= uop_data_int[UOP_W -UOP_OPCODE_W -UOP_CRT_W -1-: UOP_NPQ_W ];
uop_data_aux_dec <= uop_data_int[UOP_W -UOP_OPCODE_W -UOP_CRT_W -UOP_NPQ_W -1-: UOP_AUX_W ];
uop_data_ladder_dec <= uop_data_int[UOP_W -UOP_OPCODE_W -UOP_CRT_W -UOP_NPQ_W -UOP_AUX_W -1-: UOP_LADDER_W];
uop_data_sel_wide_in_dec <= uop_data_int[UOP_W -UOP_OPCODE_W -UOP_CRT_W -UOP_NPQ_W -UOP_AUX_W -UOP_LADDER_W -1-: BANK_ADDR_W ];
uop_data_sel_narrow_in_dec <= uop_data_int[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 ];
uop_data_sel_wide_out_dec <= uop_data_int[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 ];
uop_data_sel_narrow_out_dec <= uop_data_int[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 ];
end
wire uop_opcode_is_stop = uop_data_opcode_dec == UOP_OPCODE_STOP ;
wire uop_opcode_is_in = (uop_data_opcode_dec == UOP_OPCODE_INPUT_TO_WIDE ) ||
(uop_data_opcode_dec == UOP_OPCODE_INPUT_TO_NARROW ) ;
wire uop_opcode_is_out = uop_data_opcode_dec == UOP_OPCODE_OUTPUT_FROM_NARROW ;
wire uop_opcode_is_wrk = (uop_data_opcode_dec == UOP_OPCODE_COPY_CRT_Y2X ) ||
(uop_data_opcode_dec == UOP_OPCODE_COPY_LADDERS_X2Y ) ||
(uop_data_opcode_dec == UOP_OPCODE_CROSS_LADDERS_X2Y ) ||
(uop_data_opcode_dec == UOP_OPCODE_MODULAR_SUBTRACT_X ) ||
(uop_data_opcode_dec == UOP_OPCODE_MODULAR_SUBTRACT_Y ) ||
(uop_data_opcode_dec == UOP_OPCODE_MODULAR_SUBTRACT_Z ) ||
(uop_data_opcode_dec == UOP_OPCODE_MODULAR_REDUCE_INIT ) ||
(uop_data_opcode_dec == UOP_OPCODE_PROPAGATE_CARRIES ) ||
(uop_data_opcode_dec == UOP_OPCODE_MERGE_LH ) ||
(uop_data_opcode_dec == UOP_OPCODE_REGULAR_ADD_UNEVEN ) ;
wire uop_opcode_is_mmm = (uop_data_opcode_dec == UOP_OPCODE_MODULAR_MULTIPLY ) ||
(uop_data_opcode_dec == UOP_OPCODE_MODULAR_REDUCE_PROC ) ||
(uop_data_opcode_dec == UOP_OPCODE_REGULAR_MULTIPLY ) ;
wire uop_opcode_is_ladder = (uop_data_opcode_dec == UOP_OPCODE_LADDER_INIT ) ||
(uop_data_opcode_dec == UOP_OPCODE_LADDER_STEP ) ;
//
// Debug Signal
//
`ifdef MODEXPNG_ENABLE_DEBUG
assign uop_decoded_stop = (uop_fsm_state == UOP_FSM_STATE_DECODE_2) && uop_opcode_is_stop;
`else
assign uop_decoded_stop = 1'b0;
`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_dec == UOP_OPCODE_LADDER_STEP) && !io_mgr_ladder_done;
reg [1:0] uop_data_ladder_mux;
always @(uop_data_ladder_dec, io_mgr_ladder_p, io_mgr_ladder_q, io_mgr_ladder_d)
//
case (uop_data_ladder_dec)
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_dec, word_index_last_n, word_index_last_pq)
//
if (uop_data_npq_dec == 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 or negedge rst_n)
//
if (!rst_n) 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_2 ? (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_2 ? uop_opcode_is_mmm : 1'b0;
mmm_ena_y_r <= uop_fsm_state == UOP_FSM_STATE_DECODE_2 ? uop_opcode_is_mmm : 1'b0;
wrk_ena_r <= uop_fsm_state == UOP_FSM_STATE_DECODE_2 ? (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_2)
//
case (uop_data_opcode_dec)
//
UOP_OPCODE_INPUT_TO_WIDE:
update_io_mgr_params(uop_data_crt_dec, uop_data_aux_dec, uop_data_sel_narrow_in_dec, uop_data_sel_wide_out_dec, uop_data_opcode_dec);
//
UOP_OPCODE_INPUT_TO_NARROW:
update_io_mgr_params(uop_data_crt_dec, uop_data_aux_dec, uop_data_sel_narrow_in_dec, uop_data_sel_narrow_out_dec, uop_data_opcode_dec);
//
UOP_OPCODE_OUTPUT_FROM_NARROW: begin
update_io_mgr_params(uop_data_crt_dec, uop_data_aux_dec, BANK_DNC, uop_data_sel_narrow_out_dec, uop_data_opcode_dec);
update_wrk_params(BANK_DNC, uop_data_sel_narrow_in_dec, BANK_DNC, BANK_DNC, uop_data_opcode_dec);
end
//
UOP_OPCODE_COPY_CRT_Y2X,
UOP_OPCODE_COPY_LADDERS_X2Y,
UOP_OPCODE_CROSS_LADDERS_X2Y:
update_wrk_params(uop_data_sel_wide_in_dec, uop_data_sel_narrow_in_dec, uop_data_sel_wide_out_dec, uop_data_sel_narrow_out_dec, uop_data_opcode_dec);
//
UOP_OPCODE_MODULAR_MULTIPLY: begin
update_mmm_params(uop_data_ladder_mux, uop_data_sel_wide_in_dec, uop_data_sel_narrow_in_dec, uop_data_aux_dec, 1'b0, 1'b0);
update_rdct_params(uop_data_sel_wide_out_dec, uop_data_sel_narrow_out_dec);
end
//
UOP_OPCODE_MODULAR_SUBTRACT_X,
UOP_OPCODE_MODULAR_SUBTRACT_Y,
UOP_OPCODE_MODULAR_SUBTRACT_Z:
update_wrk_params(uop_data_sel_wide_in_dec, uop_data_sel_narrow_in_dec, uop_data_sel_wide_out_dec, uop_data_sel_narrow_out_dec, uop_data_opcode_dec);
//
UOP_OPCODE_MODULAR_REDUCE_INIT:
update_wrk_params(BANK_DNC, uop_data_sel_narrow_in_dec, BANK_DNC, BANK_DNC, uop_data_opcode_dec);
//
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_dec, uop_data_sel_narrow_out_dec);
end
//
UOP_OPCODE_PROPAGATE_CARRIES:
update_wrk_params(BANK_DNC, uop_data_sel_narrow_in_dec, BANK_DNC, uop_data_sel_narrow_out_dec, uop_data_opcode_dec);
//
UOP_OPCODE_MERGE_LH:
update_wrk_params(BANK_DNC, BANK_DNC, BANK_DNC, uop_data_sel_narrow_out_dec, uop_data_opcode_dec);
//
UOP_OPCODE_REGULAR_MULTIPLY: begin
update_mmm_params(2'b11, uop_data_sel_wide_in_dec, uop_data_sel_narrow_in_dec, 1'b0, 1'b0, 1'b1);
update_rdct_params(uop_data_sel_wide_out_dec, uop_data_sel_narrow_out_dec);
end
//
UOP_OPCODE_REGULAR_ADD_UNEVEN:
update_wrk_params(uop_data_sel_wide_in_dec, uop_data_sel_narrow_in_dec, BANK_DNC, uop_data_sel_narrow_out_dec, uop_data_opcode_dec);
//
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_dec);
//
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_2)
//
case (uop_data_opcode_dec)
//
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_X,
UOP_OPCODE_MODULAR_SUBTRACT_Y,
UOP_OPCODE_MODULAR_SUBTRACT_Z:
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 or negedge rst_n)
//
if (!rst_n) 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_1 ;
UOP_FSM_STATE_DECODE_1: uop_fsm_state_next = UOP_FSM_STATE_DECODE_2 ;
UOP_FSM_STATE_DECODE_2: 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;
default: uop_fsm_state_next = UOP_FSM_STATE_IDLE ;
endcase
//
end
//
// Ready Flag Logic
//
reg rdy_r = 1'b1;
assign rdy = rdy_r;
always @(posedge clk or negedge rst_n)
//
if (!rst_n) rdy_r <= 1'b1;
else case (uop_fsm_state)
UOP_FSM_STATE_IDLE: rdy_r <= ~ena;
UOP_FSM_STATE_DECODE_2: rdy_r <= uop_opcode_is_stop;
endcase
endmodule