///////////////////////////////////////////////////////////////////////////////////// // //Copyright 2019 Li Xinbing // //Licensed under the Apache License, Version 2.0 (the "License"); //you may not use this file except in compliance with the License. //You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // //Unless required by applicable law or agreed to in writing, software //distributed under the License is distributed on an "AS IS" BASIS, //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //See the License for the specific language governing permissions and //limitations under the License. // ///////////////////////////////////////////////////////////////////////////////////// `include "define.v" module mul( input clk, input rst, input mul_initial, input `N(3) mul_para, input `N(`XLEN) mul_rs0, input `N(`XLEN) mul_rs1, output mul_ready, input clear_pipeline, output mul_finished, output `N(`XLEN) mul_data, input mul_ack ); //--------------------------------------------------------------------------- //function defination //--------------------------------------------------------------------------- function `N($clog2(`XLEN+1)) highest_pos(input `N(`XLEN) d); integer i; begin highest_pos = 0; for (i=0;i<`XLEN;i=i+1) if ( d[i] ) highest_pos = i; end endfunction function `N($clog2(`XLEN+1)) sumbits(input `N(`XLEN) d); integer i; begin sumbits = 0; for (i=0;i<`XLEN;i=i+1) sumbits = sumbits + d[i]; end endfunction //--------------------------------------------------------------------------- //signal defination //--------------------------------------------------------------------------- reg calc_flag; reg `N(3) calc_para; reg calc_sign_xor,calc_sign_rs0; reg `N(`XLEN) calc_a,calc_b,calc_x,calc_y; reg `N($clog2(`XLEN+1)) calc_a_pos,calc_b_pos; wire calc_over; wire `N(`XLEN) calc_a_in,calc_b_in,calc_x_in,calc_y_in; reg write_flag; reg `N(`XLEN) write_data; wire write_over; //--------------------------------------------------------------------------- //statements area //--------------------------------------------------------------------------- wire `N(`XLEN) rs0_word = mul_rs0; wire `N(`XLEN) rs1_word = mul_rs1; wire rs0_sign = mul_para[2] ? (~mul_para[0] & rs0_word[31]) : ( (mul_para[1:0]!=2'b11) & rs0_word[31] ); wire rs1_sign = mul_para[2] ? (~mul_para[0] & rs1_word[31]) : ( ~mul_para[1] & rs1_word[31] ); wire `N(`XLEN) rs0_data = rs0_sign ? ( ~rs0_word + 1'b1 ) : rs0_word; wire `N(`XLEN) rs1_data = rs1_sign ? ( ~rs1_word + 1'b1 ) : rs1_word; wire mul_direct = mul_para[2] ? ((rs1_word==0)|(rs0_data>1 ) : (mul_shift>>`XLEN); wire `N(`XLEN) high_add_out = sub_sign ? (high_add_in0 - high_add_in1 - high_add_bit) : (high_add_in0 + high_add_in1 + high_add_bit); assign calc_a_in = calc_para[2] ? ( carry_bit ? high_add_out : low_add_out ) : calc_a; assign calc_b_in = calc_para[2] ? calc_b : ( calc_b ^ (1'b1<>carry_bit ) ) : low_add_out; assign calc_y_in = calc_para[2] ? calc_y : high_add_out; assign calc_over = calc_flag & ( calc_para[2] ? ( calc_a_in>(mul_ack*`XLEN); `FFx(mulbuf_length,0) if ( clear_pipeline ) mulbuf_length <= 0; else mulbuf_length <= primary_length - mul_ack; endmodule