//------------------------------------------------------------------------------ // // point_dbl_add_256.v // ----------------------------------------------------------------------------- // Elliptic curve point adder and doubler. // // Authors: Pavel Shatov // // Copyright (c) 2018, NORDUnet A/S // // 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. // //------------------------------------------------------------------------------ module point_dbl_add_256 ( clk, rst_n, ena, rdy, uop_addr, uop, gx_addr, gy_addr, hx_addr, hy_addr, px_addr, py_addr, pz_addr, rx_addr, ry_addr, rz_addr, q_addr, v_addr, rx_wren, ry_wren, rz_wren, gx_din, gy_din, hx_din, hy_din, px_din, py_din, pz_din, rx_din, ry_din, rz_din, rx_dout, ry_dout, rz_dout, q_din, v_din ); // // Microcode // `include "../../../../math/ecdsalib/rtl/curve/uop_ecdsa.v" // // Constants // localparam WORD_COUNTER_WIDTH = 3; // 0 .. 7 localparam OPERAND_NUM_WORDS = 8; // 8 * 32 = 256 // // Ports // input wire clk; // system clock input wire rst_n; // active-low async reset input wire ena; // enable input output wire rdy; // ready output output reg [ 6-1: 0] uop_addr; input wire [20-1: 0] uop; output reg [WORD_COUNTER_WIDTH-1:0] gx_addr; output reg [WORD_COUNTER_WIDTH-1:0] gy_addr; output reg [WORD_COUNTER_WIDTH-1:0] hx_addr; output reg [WORD_COUNTER_WIDTH-1:0] hy_addr; output reg [WORD_COUNTER_WIDTH-1:0] px_addr; output reg [WORD_COUNTER_WIDTH-1:0] py_addr; output reg [WORD_COUNTER_WIDTH-1:0] pz_addr; output reg [WORD_COUNTER_WIDTH-1:0] rx_addr; output reg [WORD_COUNTER_WIDTH-1:0] ry_addr; output reg [WORD_COUNTER_WIDTH-1:0] rz_addr; output reg [WORD_COUNTER_WIDTH-1:0] v_addr; output wire [WORD_COUNTER_WIDTH-1:0] q_addr; output wire rx_wren; output wire ry_wren; output wire rz_wren; input wire [ 32-1:0] gx_din; input wire [ 32-1:0] gy_din; input wire [ 32-1:0] hx_din; input wire [ 32-1:0] hy_din; input wire [ 32-1:0] px_din; input wire [ 32-1:0] py_din; input wire [ 32-1:0] pz_din; input wire [ 32-1:0] rx_din; input wire [ 32-1:0] ry_din; input wire [ 32-1:0] rz_din; output wire [ 32-1:0] rx_dout; output wire [ 32-1:0] ry_dout; output wire [ 32-1:0] rz_dout; input wire [ 32-1:0] q_din; input wire [ 32-1:0] v_din; // // Microcode // wire [ 4: 0] uop_opcode = uop[19:15]; wire [ 4: 0] uop_src_a = uop[14:10]; wire [ 4: 0] uop_src_b = uop[ 9: 5]; wire [ 2: 0] uop_dst = uop[ 4: 2]; wire [ 1: 0] uop_exec = uop[ 1: 0]; // // Multi-Word Comparator // wire mw_cmp_ena; wire mw_cmp_rdy; wire mw_cmp_out_l; wire mw_cmp_out_e; wire mw_cmp_out_g; wire [WORD_COUNTER_WIDTH-1:0] mw_cmp_addr_xy; wire [ 32-1:0] mw_cmp_din_x; wire [ 32-1:0] mw_cmp_din_y; // flags reg flag_pz_is_zero; reg flag_t1_is_zero; reg flag_t2_is_zero; mw_comparator # ( .WORD_COUNTER_WIDTH (WORD_COUNTER_WIDTH), .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS) ) mw_comparator_inst ( .clk (clk), .rst_n (rst_n), .ena (mw_cmp_ena), .rdy (mw_cmp_rdy), .xy_addr (mw_cmp_addr_xy), .x_din (mw_cmp_din_x), .y_din (mw_cmp_din_y), .cmp_l (mw_cmp_out_l), .cmp_e (mw_cmp_out_e), .cmp_g (mw_cmp_out_g) ); // // Modular Adder // wire mod_add_ena; wire mod_add_rdy; wire [WORD_COUNTER_WIDTH-1:0] mod_add_addr_ab; wire [WORD_COUNTER_WIDTH-1:0] mod_add_addr_n; wire [WORD_COUNTER_WIDTH-1:0] mod_add_addr_s; wire mod_add_wren_s; wire [ 32-1:0] mod_add_din_a; wire [ 32-1:0] mod_add_din_b; wire [ 32-1:0] mod_add_din_n; wire [ 32-1:0] mod_add_dout_s; assign mod_add_din_n = q_din; modular_adder # ( .WORD_COUNTER_WIDTH (WORD_COUNTER_WIDTH), .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS) ) modular_adder_inst ( .clk (clk), .rst_n (rst_n), .ena (mod_add_ena), .rdy (mod_add_rdy), .ab_addr (mod_add_addr_ab), .n_addr (mod_add_addr_n), .s_addr (mod_add_addr_s), .s_wren (mod_add_wren_s), .a_din (mod_add_din_a), .b_din (mod_add_din_b), .n_din (mod_add_din_n), .s_dout (mod_add_dout_s) ); // // Modular Subtractor // wire mod_sub_ena; wire mod_sub_rdy; wire [WORD_COUNTER_WIDTH-1:0] mod_sub_addr_ab; wire [WORD_COUNTER_WIDTH-1:0] mod_sub_addr_n; wire [WORD_COUNTER_WIDTH-1:0] mod_sub_addr_d; wire mod_sub_wren_d; wire [ 32-1:0] mod_sub_din_a; wire [ 32-1:0] mod_sub_din_b; wire [ 32-1:0] mod_sub_din_n; wire [ 32-1:0] mod_sub_dout_d; assign mod_sub_din_n = q_din; modular_subtractor # ( .WORD_COUNTER_WIDTH (WORD_COUNTER_WIDTH), .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS) ) modular_subtractor_inst ( .clk (clk), .rst_n (rst_n), .ena (mod_sub_ena), .rdy (mod_sub_rdy), .ab_addr (mod_sub_addr_ab), .n_addr (mod_sub_addr_n), .d_addr (mod_sub_addr_d), .d_wren (mod_sub_wren_d), .a_din (mod_sub_din_a), .b_din (mod_sub_din_b), .n_din (mod_sub_din_n), .d_dout (mod_sub_dout_d) ); // // Modular Multiplier // wire mod_mul_ena; wire mod_mul_rdy; wire [WORD_COUNTER_WIDTH-1:0] mod_mul_addr_a; wire [WORD_COUNTER_WIDTH-1:0] mod_mul_addr_b; wire [WORD_COUNTER_WIDTH-1:0] mod_mul_addr_n; wire [WORD_COUNTER_WIDTH-1:0] mod_mul_addr_p; wire mod_mul_wren_p; wire [ 32-1:0] mod_mul_din_a; wire [ 32-1:0] mod_mul_din_b; wire [ 32-1:0] mod_mul_din_n; wire [ 32-1:0] mod_mul_dout_p; assign mod_mul_din_n = q_din; modular_multiplier_256 modular_multiplier_inst ( .clk (clk), .rst_n (rst_n), .ena (mod_mul_ena), .rdy (mod_mul_rdy), .a_addr (mod_mul_addr_a), .b_addr (mod_mul_addr_b), .n_addr (mod_mul_addr_n), .p_addr (mod_mul_addr_p), .p_wren (mod_mul_wren_p), .a_din (mod_mul_din_a), .b_din (mod_mul_din_b), .n_din (mod_mul_din_n), .p_dout (mod_mul_dout_p) ); // // Multi-Word Data Mover // wire mw_mov_ena; wire mw_mov_rdy; wire [WORD_COUNTER_WIDTH-1:0] mw_mov_addr_x; wire [WORD_COUNTER_WIDTH-1:0] mw_mov_addr_y; wire mw_mov_wren_y; wire [ 32-1:0] mw_mov_din_x; wire [ 32-1:0] mw_mov_dout_y; mw_mover # ( .WORD_COUNTER_WIDTH (WORD_COUNTER_WIDTH), .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS) ) mw_mover_inst ( .clk (clk), .rst_n (rst_n), .ena (mw_mov_ena), .rdy (mw_mov_rdy), .x_addr (mw_mov_addr_x), .y_addr (mw_mov_addr_y), .y_wren (mw_mov_wren_y), .x_din (mw_mov_din_x), .y_dout (mw_mov_dout_y) ); // // ROMs // reg [WORD_COUNTER_WIDTH-1:0] brom_one_addr; //reg [WORD_COUNTER_WIDTH-1:0] brom_zero_addr; reg [WORD_COUNTER_WIDTH-1:0] brom_delta_addr; wire [ 32-1:0] brom_one_dout; wire [ 32-1:0] brom_zero_dout; wire [ 32-1:0] brom_delta_dout; (* ROM_STYLE="BLOCK" *) brom_p256_one brom_one_inst (.clk(clk), .b_addr(brom_one_addr), .b_out(brom_one_dout)); brom_p256_zero brom_zero_inst (.b_out(brom_zero_dout)); (* ROM_STYLE="BLOCK" *) brom_p256_delta brom_delta_inst (.clk(clk), .b_addr(brom_delta_addr), .b_out(brom_delta_dout)); // // Temporary Variables // reg [WORD_COUNTER_WIDTH-1:0] bram_t1_wr_addr; reg [WORD_COUNTER_WIDTH-1:0] bram_t2_wr_addr; reg [WORD_COUNTER_WIDTH-1:0] bram_t3_wr_addr; reg [WORD_COUNTER_WIDTH-1:0] bram_t4_wr_addr; reg [WORD_COUNTER_WIDTH-1:0] bram_t1_rd_addr; reg [WORD_COUNTER_WIDTH-1:0] bram_t2_rd_addr; reg [WORD_COUNTER_WIDTH-1:0] bram_t3_rd_addr; reg [WORD_COUNTER_WIDTH-1:0] bram_t4_rd_addr; wire bram_t1_wr_en; wire bram_t2_wr_en; wire bram_t3_wr_en; wire bram_t4_wr_en; wire [ 32-1:0] bram_t1_wr_data; wire [ 32-1:0] bram_t2_wr_data; wire [ 32-1:0] bram_t3_wr_data; wire [ 32-1:0] bram_t4_wr_data; wire [ 32-1:0] bram_t1_rd_data; wire [ 32-1:0] bram_t2_rd_data; wire [ 32-1:0] bram_t3_rd_data; wire [ 32-1:0] bram_t4_rd_data; bram_1rw_1ro_readfirst # ( .MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH) ) bram_t1 ( .clk (clk), .a_addr(bram_t1_wr_addr), .a_wr(bram_t1_wr_en), .a_in(bram_t1_wr_data), .a_out(), .b_addr(bram_t1_rd_addr), .b_out(bram_t1_rd_data) ); bram_1rw_1ro_readfirst # ( .MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH) ) bram_t2 ( .clk (clk), .a_addr(bram_t2_wr_addr), .a_wr(bram_t2_wr_en), .a_in(bram_t2_wr_data), .a_out(), .b_addr(bram_t2_rd_addr), .b_out(bram_t2_rd_data) ); bram_1rw_1ro_readfirst # ( .MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH) ) bram_t3 ( .clk (clk), .a_addr(bram_t3_wr_addr), .a_wr(bram_t3_wr_en), .a_in(bram_t3_wr_data), .a_out(), .b_addr(bram_t3_rd_addr), .b_out(bram_t3_rd_data) ); bram_1rw_1ro_readfirst # ( .MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH) ) bram_t4 ( .clk (clk), .a_addr(bram_t4_wr_addr), .a_wr(bram_t4_wr_en), .a_in(bram_t4_wr_data), .a_out(), .b_addr(bram_t4_rd_addr), .b_out(bram_t4_rd_data) ); // // uOP Trigger Logic // reg uop_trig; always @(posedge clk or negedge rst_n) // if (rst_n == 1'b0) uop_trig <= 1'b0; else uop_trig <= (fsm_state == FSM_STATE_FETCH) ? 1'b1 : 1'b0; // // FSM // localparam [ 1: 0] FSM_STATE_STALL = 2'b00; localparam [ 1: 0] FSM_STATE_FETCH = 2'b01; localparam [ 1: 0] FSM_STATE_EXECUTE = 2'b10; reg [ 1: 0] fsm_state = FSM_STATE_STALL; wire [ 1: 0] fsm_state_next = (uop_opcode == OPCODE_RDY) ? FSM_STATE_STALL : FSM_STATE_FETCH; // // FSM Transition Logic // reg uop_done; always @(posedge clk or negedge rst_n) // if (rst_n == 1'b0) fsm_state <= FSM_STATE_STALL; else case (fsm_state) FSM_STATE_STALL: fsm_state <= ena ? FSM_STATE_FETCH : FSM_STATE_STALL; FSM_STATE_FETCH: fsm_state <= FSM_STATE_EXECUTE; FSM_STATE_EXECUTE: fsm_state <= (!uop_trig && uop_done) ? fsm_state_next : FSM_STATE_EXECUTE; default: fsm_state <= FSM_STATE_STALL; endcase // // uOP Address Increment Logic // always @(posedge clk) // if (fsm_state == FSM_STATE_STALL) uop_addr <= 5'd0; else if (fsm_state == FSM_STATE_EXECUTE) if (!uop_trig && uop_done) uop_addr <= (uop_opcode == OPCODE_RDY) ? 5'd0 : uop_addr + 1'b1; // // uOP Completion Logic // always @(*) // case (uop_opcode) OPCODE_CMP: uop_done = mw_cmp_rdy; OPCODE_MOV: uop_done = mw_mov_rdy; OPCODE_ADD: uop_done = mod_add_rdy; OPCODE_SUB: uop_done = mod_sub_rdy; OPCODE_MUL: uop_done = mod_mul_rdy; OPCODE_RDY: uop_done = 1'b1; default: uop_done = 1'b0; endcase // // Helper Modules Enable Logic // assign mw_cmp_ena = uop_opcode[0] & uop_trig; assign mw_mov_ena = uop_opcode[1] & uop_trig; assign mod_add_ena = uop_opcode[2] & uop_trig; assign mod_sub_ena = uop_opcode[3] & uop_trig; assign mod_mul_ena = uop_opcode[4] & uop_trig; // // uOP Source Value Decoding Logic // reg [31: 0] uop_src_a_value; always @(*) // case (uop_src_a) UOP_SRC_PX: uop_src_a_value = px_din; UOP_SRC_PY: uop_src_a_value = py_din; UOP_SRC_PZ: uop_src_a_value = pz_din; UOP_SRC_RX: uop_src_a_value = rx_din; UOP_SRC_RY: uop_src_a_value = ry_din; UOP_SRC_RZ: uop_src_a_value = rz_din; UOP_SRC_T1: uop_src_a_value = bram_t1_rd_data; UOP_SRC_T2: uop_src_a_value = bram_t2_rd_data; UOP_SRC_T3: uop_src_a_value = bram_t3_rd_data; UOP_SRC_T4: uop_src_a_value = bram_t4_rd_data; UOP_SRC_ONE: uop_src_a_value = brom_one_dout; UOP_SRC_ZERO: uop_src_a_value = brom_zero_dout; UOP_SRC_DELTA: uop_src_a_value = brom_delta_dout; UOP_SRC_G_X: uop_src_a_value = gx_din; UOP_SRC_G_Y: uop_src_a_value = gy_din; UOP_SRC_H_X: uop_src_a_value = hx_din; UOP_SRC_H_Y: uop_src_a_value = hy_din; UOP_SRC_V: uop_src_a_value = v_din; default: uop_src_a_value = {32{1'bX}}; endcase assign mw_cmp_din_x = uop_src_a_value; assign mw_mov_din_x = uop_src_a_value; assign mod_add_din_a = uop_src_a_value; assign mod_sub_din_a = uop_src_a_value; assign mod_mul_din_a = uop_src_a_value; reg [31: 0] uop_src_b_value; always @(*) // case (uop_src_b) UOP_SRC_PX: uop_src_b_value = px_din; UOP_SRC_PY: uop_src_b_value = py_din; UOP_SRC_PZ: uop_src_b_value = pz_din; UOP_SRC_RX: uop_src_b_value = rx_din; UOP_SRC_RY: uop_src_b_value = ry_din; UOP_SRC_RZ: uop_src_b_value = rz_din; UOP_SRC_T1: uop_src_b_value = bram_t1_rd_data; UOP_SRC_T2: uop_src_b_value = bram_t2_rd_data; UOP_SRC_T3: uop_src_b_value = bram_t3_rd_data; UOP_SRC_T4: uop_src_b_value = bram_t4_rd_data; UOP_SRC_ONE: uop_src_b_value = brom_one_dout; UOP_SRC_ZERO: uop_src_b_value = brom_zero_dout; UOP_SRC_DELTA: uop_src_b_value = brom_delta_dout; UOP_SRC_G_X: uop_src_b_value = gx_din; UOP_SRC_G_Y: uop_src_b_value = gy_din; UOP_SRC_H_X: uop_src_b_value = hx_din; UOP_SRC_H_Y: uop_src_b_value = hy_din; UOP_SRC_V: uop_src_b_value = v_din; default: uop_src_b_value = {32{1'bX}}; endcase assign mw_cmp_din_y = uop_src_b_value; assign mod_add_din_b = uop_src_b_value; assign mod_sub_din_b = uop_src_b_value; assign mod_mul_din_b = uop_src_b_value; // // uOP Source & Destination Address Decoding Logic // reg [WORD_COUNTER_WIDTH-1:0] uop_src_a_addr; reg [WORD_COUNTER_WIDTH-1:0] uop_src_b_addr; reg [WORD_COUNTER_WIDTH-1:0] uop_dst_addr; reg [WORD_COUNTER_WIDTH-1:0] uop_q_addr; assign q_addr = uop_q_addr; always @(*) // case (uop_opcode) // OPCODE_CMP: begin uop_src_a_addr = mw_cmp_addr_xy; uop_src_b_addr = mw_cmp_addr_xy; uop_dst_addr = {WORD_COUNTER_WIDTH{1'bX}}; uop_q_addr = {WORD_COUNTER_WIDTH{1'bX}}; end // OPCODE_MOV: begin uop_src_a_addr = mw_mov_addr_x; uop_src_b_addr = {WORD_COUNTER_WIDTH{1'bX}}; uop_dst_addr = mw_mov_addr_y; uop_q_addr = {WORD_COUNTER_WIDTH{1'bX}}; end // OPCODE_ADD: begin uop_src_a_addr = mod_add_addr_ab; uop_src_b_addr = mod_add_addr_ab; uop_dst_addr = mod_add_addr_s; uop_q_addr = mod_add_addr_n; end // OPCODE_SUB: begin uop_src_a_addr = mod_sub_addr_ab; uop_src_b_addr = mod_sub_addr_ab; uop_dst_addr = mod_sub_addr_d; uop_q_addr = mod_sub_addr_n; end // OPCODE_MUL: begin uop_src_a_addr = mod_mul_addr_a; uop_src_b_addr = mod_mul_addr_b; uop_dst_addr = mod_mul_addr_p; uop_q_addr = mod_mul_addr_n; end // default: begin uop_src_a_addr = {WORD_COUNTER_WIDTH{1'bX}}; uop_src_b_addr = {WORD_COUNTER_WIDTH{1'bX}}; uop_dst_addr = {WORD_COUNTER_WIDTH{1'bX}}; uop_q_addr = {WORD_COUNTER_WIDTH{1'bX}}; end // endcase // // uOP Conditional Execution Logic // reg uop_exec_effective; always @(*) // case (uop_exec) UOP_EXEC_ALWAYS: uop_exec_effective = 1'b1; UOP_EXEC_PZT1T2_0XX: uop_exec_effective = flag_pz_is_zero; UOP_EXEC_PZT1T2_100: uop_exec_effective = !flag_pz_is_zero && flag_t1_is_zero && flag_t2_is_zero; UOP_EXEC_PZT1T2_101: uop_exec_effective = !flag_pz_is_zero && flag_t1_is_zero && !flag_t2_is_zero; endcase // // uOP Destination Store Logic // reg uop_dst_wren; always @(*) // case (uop_opcode) // OPCODE_MOV: uop_dst_wren = mw_mov_wren_y & uop_exec_effective; OPCODE_ADD: uop_dst_wren = mod_add_wren_s; OPCODE_SUB: uop_dst_wren = mod_sub_wren_d; OPCODE_MUL: uop_dst_wren = mod_mul_wren_p; default: uop_dst_wren = 1'b0; // endcase always @(*) begin // // // if (uop_src_a == UOP_SRC_PX) px_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_PX) px_addr = uop_src_b_addr; else px_addr = {WORD_COUNTER_WIDTH{1'bX}}; // if (uop_src_a == UOP_SRC_PY) py_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_PY) py_addr = uop_src_b_addr; else py_addr = {WORD_COUNTER_WIDTH{1'bX}}; // if (uop_src_a == UOP_SRC_PZ) pz_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_PZ) pz_addr = uop_src_b_addr; else pz_addr = {WORD_COUNTER_WIDTH{1'bX}}; // // // if (uop_src_a == UOP_SRC_ONE) brom_one_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_ONE) brom_one_addr = uop_src_b_addr; else brom_one_addr = {WORD_COUNTER_WIDTH{1'bX}}; // //if (uop_src_a == UOP_SRC_ZERO) brom_zero_addr = uop_src_a_addr; //else if (uop_src_b == UOP_SRC_ZERO) brom_zero_addr = uop_src_b_addr; //else brom_zero_addr = {WORD_COUNTER_WIDTH{1'bX}}; // if (uop_src_a == UOP_SRC_DELTA) brom_delta_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_DELTA) brom_delta_addr = uop_src_b_addr; else brom_delta_addr = {WORD_COUNTER_WIDTH{1'bX}}; // // // if (uop_src_a == UOP_SRC_G_X) gx_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_G_X) gx_addr = uop_src_b_addr; else gx_addr = {WORD_COUNTER_WIDTH{1'bX}}; // if (uop_src_a == UOP_SRC_G_Y) gy_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_G_Y) gy_addr = uop_src_b_addr; else gy_addr = {WORD_COUNTER_WIDTH{1'bX}}; // // // if (uop_src_a == UOP_SRC_H_X) hx_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_H_X) hx_addr = uop_src_b_addr; else hx_addr = {WORD_COUNTER_WIDTH{1'bX}}; // if (uop_src_a == UOP_SRC_H_Y) hy_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_H_Y) hy_addr = uop_src_b_addr; else hy_addr = {WORD_COUNTER_WIDTH{1'bX}}; // // // if (uop_src_a == UOP_SRC_V) v_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_V) v_addr = uop_src_b_addr; else v_addr = {WORD_COUNTER_WIDTH{1'bX}}; // // // if (uop_src_a == UOP_SRC_T1) bram_t1_rd_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_T1) bram_t1_rd_addr = uop_src_b_addr; else bram_t1_rd_addr = {WORD_COUNTER_WIDTH{1'bX}}; // if (uop_src_a == UOP_SRC_T2) bram_t2_rd_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_T2) bram_t2_rd_addr = uop_src_b_addr; else bram_t2_rd_addr = {WORD_COUNTER_WIDTH{1'bX}}; // if (uop_src_a == UOP_SRC_T3) bram_t3_rd_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_T3) bram_t3_rd_addr = uop_src_b_addr; else bram_t3_rd_addr = {WORD_COUNTER_WIDTH{1'bX}}; // if (uop_src_a == UOP_SRC_T4) bram_t4_rd_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_T4) bram_t4_rd_addr = uop_src_b_addr; else bram_t4_rd_addr = {WORD_COUNTER_WIDTH{1'bX}}; // // // if (uop_dst == UOP_DST_T1) bram_t1_wr_addr = uop_dst_addr; else bram_t1_wr_addr = {WORD_COUNTER_WIDTH{1'bX}}; // if (uop_dst == UOP_DST_T2) bram_t2_wr_addr = uop_dst_addr; else bram_t2_wr_addr = {WORD_COUNTER_WIDTH{1'bX}}; // if (uop_dst == UOP_DST_T3) bram_t3_wr_addr = uop_dst_addr; else bram_t3_wr_addr = {WORD_COUNTER_WIDTH{1'bX}}; // if (uop_dst == UOP_DST_T4) bram_t4_wr_addr = uop_dst_addr; else bram_t4_wr_addr = {WORD_COUNTER_WIDTH{1'bX}}; // // // if ((uop_dst == UOP_DST_RX) && (uop_dst_wren)) rx_addr = uop_dst_addr; else begin if (uop_src_a == UOP_SRC_RX) rx_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_RX) rx_addr = uop_src_b_addr; else rx_addr = {WORD_COUNTER_WIDTH{1'bX}}; end // if ((uop_dst == UOP_DST_RY) && (uop_dst_wren)) ry_addr = uop_dst_addr; else begin if (uop_src_a == UOP_SRC_RY) ry_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_RY) ry_addr = uop_src_b_addr; else ry_addr = {WORD_COUNTER_WIDTH{1'bX}}; end // if ((uop_dst == UOP_DST_RZ) && (uop_dst_wren)) rz_addr = uop_dst_addr; else begin if (uop_src_a == UOP_SRC_RZ) rz_addr = uop_src_a_addr; else if (uop_src_b == UOP_SRC_RZ) rz_addr = uop_src_b_addr; else rz_addr = {WORD_COUNTER_WIDTH{1'bX}}; end // end assign rx_wren = uop_dst_wren && (uop_dst == UOP_DST_RX); assign ry_wren = uop_dst_wren && (uop_dst == UOP_DST_RY); assign rz_wren = uop_dst_wren && (uop_dst == UOP_DST_RZ); assign bram_t1_wr_en = uop_dst_wren && (uop_dst == UOP_DST_T1); assign bram_t2_wr_en = uop_dst_wren && (uop_dst == UOP_DST_T2); assign bram_t3_wr_en = uop_dst_wren && (uop_dst == UOP_DST_T3); assign bram_t4_wr_en = uop_dst_wren && (uop_dst == UOP_DST_T4); // // Destination Value Selector // reg [31: 0] uop_dst_value; always @(*) // case (uop_opcode) OPCODE_MOV: uop_dst_value = mw_mov_dout_y; OPCODE_ADD: uop_dst_value = mod_add_dout_s; OPCODE_SUB: uop_dst_value = mod_sub_dout_d; OPCODE_MUL: uop_dst_value = mod_mul_dout_p; default: uop_dst_value = {32{1'bX}}; endcase assign rx_dout = uop_dst_value; assign ry_dout = uop_dst_value; assign rz_dout = uop_dst_value; assign bram_t1_wr_data = uop_dst_value; assign bram_t2_wr_data = uop_dst_value; assign bram_t3_wr_data = uop_dst_value; assign bram_t4_wr_data = uop_dst_value; // // Latch Comparison Flags // always @(posedge clk) // if ( (fsm_state == FSM_STATE_EXECUTE) && (uop_opcode == OPCODE_CMP) && (uop_done && !uop_trig) ) begin if ( (uop_src_a == UOP_SRC_PZ) && (uop_src_b == UOP_SRC_ZERO) ) flag_pz_is_zero <= !mw_cmp_out_l && mw_cmp_out_e && !mw_cmp_out_g; if ( (uop_src_a == UOP_SRC_T1) && (uop_src_b == UOP_SRC_ZERO) ) flag_t1_is_zero <= !mw_cmp_out_l && mw_cmp_out_e && !mw_cmp_out_g; if ( (uop_src_a == UOP_SRC_T2) && (uop_src_b == UOP_SRC_ZERO) ) flag_t2_is_zero <= !mw_cmp_out_l && mw_cmp_out_e && !mw_cmp_out_g; end // // Ready Flag Logic // reg rdy_reg = 1'b1; assign rdy = rdy_reg; always @(posedge clk or negedge rst_n) // if (rst_n == 1'b0) rdy_reg <= 1'b1; else begin /* clear flag */ if (fsm_state == FSM_STATE_STALL) if (ena) rdy_reg <= 1'b0; /* set flag */ if ((fsm_state == FSM_STATE_EXECUTE) && !uop_trig && uop_done) if (uop_opcode == OPCODE_RDY) rdy_reg <= 1'b1; end endmodule //------------------------------------------------------------------------------ // End-of-File //------------------------------------------------------------------------------