URL
https://opencores.org/ocsvn/versatile_library/versatile_library/trunk
Subversion Repositories versatile_library
[/] [versatile_library/] [trunk/] [rtl/] [verilog/] [arith.v] - Rev 41
Go to most recent revision | Compare with Previous | Blame | View Log
////////////////////////////////////////////////////////////////////// //// //// //// Arithmetic functions //// //// //// //// Description //// //// Arithmetic functions for ALU and DSP //// //// //// //// //// //// To Do: //// //// - //// //// //// //// Author(s): //// //// - Michael Unneback, unneback@opencores.org //// //// ORSoC AB //// //// //// ////////////////////////////////////////////////////////////////////// //// //// //// Copyright (C) 2010 Authors and OPENCORES.ORG //// //// //// //// This source file may be used and distributed without //// //// restriction provided that this copyright statement is not //// //// removed from the file and that any derivative work contains //// //// the original copyright notice and the associated disclaimer. //// //// //// //// This source file is free software; you can redistribute it //// //// and/or modify it under the terms of the GNU Lesser General //// //// Public License as published by the Free Software Foundation; //// //// either version 2.1 of the License, or (at your option) any //// //// later version. //// //// //// //// This source is distributed in the hope that it will be //// //// useful, but WITHOUT ANY WARRANTY; without even the implied //// //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// //// PURPOSE. See the GNU Lesser General Public License for more //// //// details. //// //// //// //// You should have received a copy of the GNU Lesser General //// //// Public License along with this source; if not, download it //// //// from http://www.opencores.org/lgpl.shtml //// //// //// ////////////////////////////////////////////////////////////////////// `ifdef MULTS // signed multiplication `define MODULE mults module `BASE`MODULE (a,b,p); `undef MODULE parameter operand_a_width = 18; parameter operand_b_width = 18; parameter result_hi = 35; parameter result_lo = 0; input [operand_a_width-1:0] a; input [operand_b_width-1:0] b; output [result_hi:result_lo] p; wire signed [operand_a_width-1:0] ai; wire signed [operand_b_width-1:0] bi; wire signed [operand_a_width+operand_b_width-1:0] result; assign ai = a; assign bi = b; assign result = ai * bi; assign p = result[result_hi:result_lo]; endmodule `endif `ifdef MULTS18X18 `define MODULE mults18x18 module `BASE`MODULE (a,b,p); `undef MODULE input [17:0] a,b; output [35:0] p; vl_mult # (.operand_a_width(18), .operand_b_width(18)) mult0 (.a(a), .b(b), .p(p)); endmodule `endif `ifdef MULT `define MODULE mult // unsigned multiplication module `BASE`MODULE (a,b,p); `undef MODULE parameter operand_a_width = 18; parameter operand_b_width = 18; parameter result_hi = 35; parameter result_lo = 0; input [operand_a_width-1:0] a; input [operand_b_width-1:0] b; output [result_hi:result_hi] p; wire [operand_a_width+operand_b_width-1:0] result; assign result = a * b; assign p = result[result_hi:result_lo]; endmodule `endif `ifdef SHIFT_UNIT_32 `define MODULE shift_unit_32 // shift unit // supporting the following shift functions // SLL // SRL // SRA `define SHIFT_UNIT_MULT # ( .operand_a_width(25), .operand_b_width(16), .result_hi(14), .result_lo(7)) module `BASE`MODULE( din, s, dout, opcode); `undef MODULE input [31:0] din; // data in operand input [4:0] s; // shift operand input [1:0] opcode; output [31:0] dout; parameter opcode_sll = 2'b00; //parameter opcode_srl = 2'b01; parameter opcode_sra = 2'b10; //parameter opcode_ror = 2'b11; wire sll, sra; assign sll = opcode == opcode_sll; assign sra = opcode == opcode_sra; wire [15:1] s1; wire [3:0] sign; wire [7:0] tmp [0:3]; // first stage is multiplier based // shift operand as fractional 8.7 assign s1[15] = sll & s[2:0]==3'd7; assign s1[14] = sll & s[2:0]==3'd6; assign s1[13] = sll & s[2:0]==3'd5; assign s1[12] = sll & s[2:0]==3'd4; assign s1[11] = sll & s[2:0]==3'd3; assign s1[10] = sll & s[2:0]==3'd2; assign s1[ 9] = sll & s[2:0]==3'd1; assign s1[ 8] = s[2:0]==3'd0; assign s1[ 7] = !sll & s[2:0]==3'd1; assign s1[ 6] = !sll & s[2:0]==3'd2; assign s1[ 5] = !sll & s[2:0]==3'd3; assign s1[ 4] = !sll & s[2:0]==3'd4; assign s1[ 3] = !sll & s[2:0]==3'd5; assign s1[ 2] = !sll & s[2:0]==3'd6; assign s1[ 1] = !sll & s[2:0]==3'd7; assign sign[3] = din[31] & sra; assign sign[2] = sign[3] & (&din[31:24]); assign sign[1] = sign[2] & (&din[23:16]); assign sign[0] = sign[1] & (&din[15:8]); `define MODULE mults `BASE`MODULE `SHIFT_UNIT_MULT mult_byte3 ( .a({sign[3], {8{sign[3]}},din[31:24], din[23:16]}), .b({1'b0,s1}), .p(tmp[3])); `BASE`MODULE `SHIFT_UNIT_MULT mult_byte2 ( .a({sign[2], din[31:24] ,din[23:16], din[15:8]}), .b({1'b0,s1}), .p(tmp[2])); `BASE`MODULE `SHIFT_UNIT_MULT mult_byte1 ( .a({sign[1], din[23:16] ,din[15:8], din[7:0]}), .b({1'b0,s1}), .p(tmp[1])); `BASE`MODULE `SHIFT_UNIT_MULT mult_byte0 ( .a({sign[0], din[15:8] ,din[7:0], 8'h00}), .b({1'b0,s1}), .p(tmp[0])); `undef MODULE // second stage is multiplexer based // shift on byte level // mux byte 3 assign dout[31:24] = (s[4:3]==2'b00) ? tmp[3] : (sll & s[4:3]==2'b01) ? tmp[2] : (sll & s[4:3]==2'b10) ? tmp[1] : (sll & s[4:3]==2'b11) ? tmp[0] : {8{sign[3]}}; // mux byte 2 assign dout[23:16] = (s[4:3]==2'b00) ? tmp[2] : (sll & s[4:3]==2'b01) ? tmp[1] : (sll & s[4:3]==2'b10) ? tmp[0] : (sll & s[4:3]==2'b11) ? {8{1'b0}} : (s[4:3]==2'b01) ? tmp[3] : {8{sign[3]}}; // mux byte 1 assign dout[15:8] = (s[4:3]==2'b00) ? tmp[1] : (sll & s[4:3]==2'b01) ? tmp[0] : (sll & s[4:3]==2'b10) ? {8{1'b0}} : (sll & s[4:3]==2'b11) ? {8{1'b0}} : (s[4:3]==2'b01) ? tmp[2] : (s[4:3]==2'b10) ? tmp[3] : {8{sign[3]}}; // mux byte 0 assign dout[7:0] = (s[4:3]==2'b00) ? tmp[0] : (sll) ? {8{1'b0}}: (s[4:3]==2'b01) ? tmp[1] : (s[4:3]==2'b10) ? tmp[2] : tmp[3]; endmodule `endif `ifdef LOGIC_UNIT // logic unit // supporting the following logic functions // a and b // a or b // a xor b // not b `define MODULE logic_unit module `BASE`MODULE( a, b, result, opcode); `undef MODULE parameter width = 32; parameter opcode_and = 2'b00; parameter opcode_or = 2'b01; parameter opcode_xor = 2'b10; input [width-1:0] a,b; output [width-1:0] result; input [1:0] opcode; assign result = (opcode==opcode_and) ? a & b : (opcode==opcode_or) ? a | b : (opcode==opcode_xor) ? a ^ b : b; endmodule module vl_arith_unit ( a, b, c_in, add_sub, sign, result, c_out, z, ovfl); parameter width = 32; parameter opcode_add = 1'b0; parameter opcode_sub = 1'b1; input [width-1:0] a,b; input c_in, add_sub, sign; output [width-1:0] result; output c_out, z, ovfl; assign {c_out,result} = {(a[width-1] & sign),a} + ({a[width-1] & sign,b} ^ {(width+1){(add_sub==opcode_sub)}}) + {{(width-1){1'b0}},(c_in | (add_sub==opcode_sub))}; assign z = (result=={width{1'b0}}); assign ovfl = ( a[width-1] & b[width-1] & ~result[width-1]) | (~a[width-1] & ~b[width-1] & result[width-1]); endmodule `endif
Go to most recent revision | Compare with Previous | Blame | View Log