OpenCores
URL https://opencores.org/ocsvn/zet86/zet86/trunk

Subversion Repositories zet86

[/] [zet86/] [trunk/] [cores/] [zet/] [rtl/] [alu.v] - Rev 55

Compare with Previous | Blame | View Log

/*
 *  Copyright (c) 2008  Zeus Gomez Marmolejo <zeus@opencores.org>
 *
 *  This file is part of the Zet processor. This processor is free
 *  hardware; you can redistribute it and/or modify it under the terms of
 *  the GNU General Public License as published by the Free Software
 *  Foundation; either version 3, or (at your option) any later version.
 *
 *  Zet is distrubuted 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 General Public
 *  License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Zet; see the file COPYING. If not, see
 *  <http://www.gnu.org/licenses/>.
 */
 
`timescale 1ns/10ps
 
module alu (
    input  [31:0] x,
    input  [15:0] y,
    output [31:0] out,
    input  [ 2:0] t,
    input  [ 2:0] func,
    input  [15:0] iflags,
    output [ 8:0] oflags,
    input         word_op,
    input  [15:0] seg,
    input  [15:0] off,
    input         clk,
    output        div_exc
  );
 
  // Net declarations
  wire [15:0] add, log, shi, rot;
  wire  [8:0] othflags;
  wire [19:0] oth;
  wire [31:0] cnv, mul;
  wire af_add, af_cnv;
  wire cf_cnv, cf_add, cf_mul, cf_log, cf_shi, cf_rot;
  wire of_cnv, of_add, of_mul, of_log, of_shi, of_rot;
  wire ofi, sfi, zfi, afi, pfi, cfi;
  wire ofo, sfo, zfo, afo, pfo, cfo;
  wire flags_unchanged;
  wire dexc;
 
  // Module instances
  addsub add1 (x[15:0], y, add, func, word_op, cfi, cf_add, af_add, of_add);
 
  conv cnv2 (
    .x      (x[15:0]),
    .func   (func),
    .out    (cnv),
    .iflags ({afi, cfi}),
    .oflags ({af_cnv, of_cnv, cf_cnv})
  );
 
  muldiv mul3 (
    .x       (x),
    .y       (y),
    .o       (mul),
    .f       (func),
    .word_op (word_op),
    .cfo     (cf_mul),
    .ofo     (of_mul),
    .clk     (clk),
    .exc     (dexc)
  );
 
  bitlog log4 (x[15:0], y, log, func, cf_log, of_log);
  shifts shi5 (x[15:0], y[4:0], shi, func[1:0], word_op, cfi, ofi, cf_shi, of_shi);
  rotate rot6 (x[15:0], y[4:0], func[1:0], cfi, word_op, rot, cf_rot, ofi, of_rot);
  othop  oth7 (x[15:0], y, seg, off, iflags, func, word_op, oth, othflags);
 
  mux8_16 m0(t, {8'd0, y[7:0]}, add, cnv[15:0],
             mul[15:0], log, shi, rot, oth[15:0], out[15:0]);
  mux8_16 m1(t, 16'd0, 16'd0, cnv[31:16], mul[31:16],
             16'd0, 16'd0, 16'd0, {12'b0,oth[19:16]}, out[31:16]);
  mux8_1  a1(t, 1'b0, cf_add, cf_cnv, cf_mul, cf_log, cf_shi, cf_rot, 1'b0, cfo);
  mux8_1  a2(t, 1'b0, af_add, af_cnv, 1'b0, 1'b0, 1'b0, afi, 1'b0, afo);
  mux8_1  a3(t, 1'b0, of_add, of_cnv, of_mul, of_log, of_shi, of_rot, 1'b0, ofo);
 
  // Flags
  assign pfo = flags_unchanged ? pfi : ^~ out[7:0];
  assign zfo = flags_unchanged ? zfi
             : ((word_op && (t!=3'd2)) ? ~|out[15:0] : ~|out[7:0]);
  assign sfo = flags_unchanged ? sfi
             : ((word_op && (t!=3'd2)) ? out[15] : out[7]);
 
  assign oflags = (t == 3'd7) ? othflags 
                 : { ofo, iflags[10:8], sfo, zfo, afo, pfo, cfo };
 
  assign ofi = iflags[11];
  assign sfi = iflags[7];
  assign zfi = iflags[6];
  assign afi = iflags[4];
  assign pfi = iflags[2];
  assign cfi = iflags[0];
 
  assign flags_unchanged = (t == 3'd4 && func == 3'd2
                         || t == 3'd5 && y[4:0] == 5'h0
                         || t == 3'd6);
 
  assign div_exc = func[1] && (t==3'd3) && dexc;
 
endmodule
 
module addsub (
    input  [15:0] x,
    input  [15:0] y,
    output [15:0] out,
    input  [ 2:0] f,
    input         word_op,
    input         cfi,
    output        cfo,
    output        afo,
    output        ofo
  );
 
  // Net declarations
  wire [15:0] op2;
 
  wire ci;
  wire cfoadd;
  wire xs, ys, os;
 
  // Module instances
  fulladd16 fa0 ( // We instantiate only one adder
    .x  (x),      //  to have less hardware
    .y  (op2),
    .ci (ci),
    .co (cfoadd),
    .z  (out),
    .s  (f[2])
  );
 
  // Assignments
  assign op2 = f[2] ? ~y
             : ((f[1:0]==2'b11) ? { 8'b0, y[7:0] } : y);
  assign ci  = f[2] & f[1] | f[2] & ~f[0] & ~cfi
             | f[2] & f[0] | (f==3'b0) & cfi;
  assign afo = f[1] ? (f[2] ? &out[3:0] : ~|out[3:0] )
                    : (x[4] ^ y[4] ^ out[4]);
  assign cfo = f[1] ? cfi /* inc, dec */
             : (word_op ? cfoadd : (x[8]^y[8]^out[8]));
 
  assign xs  = word_op ? x[15] : x[7];
  assign ys  = word_op ? y[15] : y[7];
  assign os  = word_op ? out[15] : out[7];
  assign ofo = f[2] ? (~xs & ys & os | xs & ~ys & ~os)
                    : (~xs & ~ys & os | xs & ys & ~os);
endmodule
 
module conv (
    input  [15:0] x,
    input  [ 2:0] func,
    output [31:0] out,
    input  [ 1:0] iflags, // afi, cfi
    output [ 2:0] oflags  // afo, ofo, cfo
  );
 
  // Net declarations
  wire        afi, cfi;
  wire        ofo, afo, cfo;
  wire [15:0] aaa, aas;
  wire [ 7:0] daa, tmpdaa, das, tmpdas;
  wire [15:0] cbw, cwd;
 
  wire        acond, dcond;
  wire        tmpcf;
 
  // Module instances
  mux8_16 m0(func, cbw, aaa, aas, 16'd0,
                   cwd, {x[15:8], daa}, {x[15:8], das}, 16'd0, out[15:0]);
 
  // Assignments
  assign aaa = (acond ? (x + 16'h0106) : x) & 16'hff0f;
  assign aas = (acond ? (x - 16'h0106) : x) & 16'hff0f;
 
  assign tmpdaa = acond ? (x[7:0] + 8'h06) : x[7:0];
  assign daa    = dcond ? (tmpdaa + 8'h60) : tmpdaa;
  assign tmpdas = acond ? (x[7:0] - 8'h06) : x[7:0];
  assign das    = dcond ? (tmpdas - 8'h60) : tmpdas;
 
  assign               cbw   = { { 8{x[ 7]}}, x[7:0] };
  assign { out[31:16], cwd } = { {16{x[15]}}, x      };
 
  assign acond = ((x[7:0] & 8'h0f) > 8'h09) | afi;
  assign dcond = (x[7:0] > 8'h99) | cfi;
 
  assign afi = iflags[1];
  assign cfi = iflags[0];
 
  assign afo = acond;
  assign ofo = 1'b0;
  assign tmpcf = (x[7:0] < 8'h06) | cfi;
  assign cfo = func[2] ? (dcond ? 1'b1 : (acond & tmpcf))
             : acond;
 
  assign oflags = { afo, ofo, cfo };
endmodule
 
 
module muldiv (
    input  [31:0] x,  // 16 MSb for division
    input  [15:0] y,
    output [31:0] o,
    input  [ 2:0] f,
    input         word_op,
    output        cfo,
    output        ofo,
    input         clk,
    output        exc
  );
 
  // Net declarations
  wire as, bs, cfs, cfu;
  wire [16:0] a, b;
  wire [33:0] p;
  wire div0, over, ovf, mint;
 
  wire [33:0] zi;
  wire [16:0] di;
  wire [17:0] q;
  wire [17:0] s;
 
  // Module instantiations
  mult signmul17 (
    .clk (clk),
    .a   (a),
    .b   (b),
    .p   (p)
  );
 
  div_su #(34) dut (
    .clk  (clk),
    .ena  (1'b1),
    .z    (zi),
    .d    (di),
    .q    (q),
    .s    (s),
    .ovf  (ovf),
    .div0 (div0)
  );
 
  // Sign ext. for imul
  assign as  = f[0] & (word_op ? x[15] : x[7]);
  assign bs  = f[0] & (word_op ? y[15] : y[7]);
  assign a   = word_op ? { as, x[15:0] }
                       : { {9{as}}, x[7:0] };
  assign b   = word_op ? { bs, y } : { {9{bs}}, y[7:0] };
 
  assign zi  = f[2] ? { 26'h0, x[7:0] }
               : (word_op ? (f[0] ? { {2{x[31]}}, x }
                               : { 2'b0, x })
                       : (f[0] ? { {18{x[15]}}, x[15:0] }
                               : { 18'b0, x[15:0] }));
 
  assign di  = word_op ? (f[0] ? { y[15], y } : { 1'b0, y })
                       : (f[0] ? { {9{y[7]}}, y[7:0] }
                               : { 9'h000, y[7:0] });
 
  assign o   = f[2] ? { 16'h0, q[7:0], s[7:0] }
               : (f[1] ? ( word_op ? {s[15:0], q[15:0]}
                                : {16'h0, s[7:0], q[7:0]})
                    : p[31:0]);
 
  assign ofo = f[1] ? 1'b0 : cfo;
  assign cfo = f[1] ? 1'b0 : !(f[0] ? cfs : cfu);
  assign cfu = word_op ? (o[31:16] == 16'h0)
                       : (o[15:8] == 8'h0);
  assign cfs = word_op ? (o[31:16] == {16{o[15]}})
                       : (o[15:8] == {8{o[7]}});
 
  // Exceptions
  assign over = f[2] ? 1'b0
              : (word_op ? (f[0] ? (q[17:16]!={2{q[15]}})
                                : (q[17:16]!=2'b0) )
                        : (f[0] ? (q[17:8]!={10{q[7]}})
                                : (q[17:8]!=10'h000)));
  assign mint = f[0] & (word_op ? (x==32'h80000000)
                                : (x==16'h8000));
  assign exc  = div0 | (!f[2] & ovf) | over | mint;
endmodule
 
module bitlog(x, y, out, func, cfo, ofo);
  // IO ports
  input  [15:0] x, y;
  input  [2:0]  func;
  output [15:0] out;
  output        cfo, ofo;
 
  // Net declarations
  wire [15:0] and_n, or_n, not_n, xor_n;
 
  // Module instantiations
  mux8_16 m0(func, and_n, or_n, not_n, xor_n, 16'd0, 16'd0, 16'd0, 16'd0, out);
 
  // Assignments
  assign and_n  = x & y;
  assign or_n   = x | y;
  assign not_n  = ~x;
  assign xor_n  = x ^ y;
 
  assign cfo = 1'b0;
  assign ofo = 1'b0;
endmodule
 
//
// This module implements the instructions shl/sal, sar, shr
//
 
module shifts(x, y, out, func, word_op, cfi, ofi, cfo, ofo);
  // IO ports
  input  [15:0] x;
  input  [ 4:0] y;
  input   [1:0] func;
  input         word_op;
  output [15:0] out;
  output        cfo, ofo;
  input         cfi, ofi;
 
  // Net declarations
  wire [15:0] sal, sar, shr, sal16, sar16, shr16;
  wire [7:0]  sal8, sar8, shr8;
  wire ofo_shl, ofo_sar, ofo_shr;
  wire cfo_sal8, cfo_sal16, cfo_sar8, cfo_sar16, cfo_shr8, cfo_shr16;
  wire cfo16, cfo8;
  wire unchanged;
 
  // Module instantiations
  mux4_16 m0(func, sal, sar, shr, 16'd0, out);
 
  // Assignments
  assign { cfo_sal16, sal16 } = x << y;
  assign { sar16, cfo_sar16 } = (y > 5'd16) ? 17'h1ffff
    : (({x,1'b0} >> y) | (x[15] ? (17'h1ffff << (17 - y))
                                     : 17'h0));
  assign { shr16, cfo_shr16 } = ({x,1'b0} >> y);
 
  assign { cfo_sal8, sal8 } = x[7:0] << y;
  assign { sar8, cfo_sar8 } = (y > 5'd8) ? 9'h1ff
    : (({x[7:0],1'b0} >> y) | (x[7] ? (9'h1ff << (9 - y))
                                         : 9'h0));
  assign { shr8, cfo_shr8 } = ({x[7:0],1'b0} >> y);
 
  assign sal     = word_op ? sal16 : { 8'd0, sal8 };
  assign shr     = word_op ? shr16 : { 8'd0, shr8 };
  assign sar     = word_op ? sar16 : { {8{sar8[7]}}, sar8 };
 
  assign ofo = unchanged ? ofi
             : (func[1] ? ofo_shr : (func[0] ? ofo_sar : ofo_shl));
  assign cfo16 = func[1] ? cfo_shr16
               : (func[0] ? cfo_sar16 : cfo_sal16);
  assign cfo8  = func[1] ? cfo_shr8
               : (func[0] ? cfo_sar8 : cfo_sal8);
  assign cfo = unchanged ? cfi : (word_op ? cfo16 : cfo8);
  assign ofo_shl = word_op ? (out[15] != cfo) : (out[7] != cfo);
  assign ofo_sar = 1'b0;
  assign ofo_shr = word_op ? x[15] : x[7];
 
  assign unchanged = word_op ? (y==5'b0) : (y[3:0]==4'b0);
endmodule
 
module othop (x, y, seg, off, iflags, func, word_op, out, oflags);
  // IO ports
  input [15:0] x, y, off, seg, iflags;
  input [2:0] func;
  input word_op;
  output [19:0] out;
  output [8:0] oflags;
 
  // Net declarations
  wire [15:0] deff, deff2, outf, clcm, setf, intf, strf;
  wire [19:0] dcmp, dcmp2; 
  wire dfi;
 
  // Module instantiations
  mux8_16 m0(func, dcmp[15:0], dcmp2[15:0], deff, outf, clcm, setf, 
                   intf, strf, out[15:0]);
  assign out[19:16] = func ? dcmp2[19:16] : dcmp[19:16];
 
  // Assignments
  assign dcmp  = (seg << 4) + deff;
  assign dcmp2 = (seg << 4) + deff2;
  assign deff  = x + y + off;
  assign deff2 = x + y + off + 16'd2;
  assign outf  = y;
  assign clcm  = y[2] ? (y[1] ? /* -1: clc */ {iflags[15:1], 1'b0} 
                         : /* 4: cld */ {iflags[15:11], 1'b0, iflags[9:0]})
                     : (y[1] ? /* 2: cli */ {iflags[15:10], 1'b0, iflags[8:0]}
                       : /* 0: cmc */ {iflags[15:1], ~iflags[0]});
  assign setf  = y[2] ? (y[1] ? /* -1: stc */ {iflags[15:1], 1'b1} 
                         : /* 4: std */ {iflags[15:11], 1'b1, iflags[9:0]})
                     : (y[1] ? /* 2: sti */ {iflags[15:10], 1'b1, iflags[8:0]}
                       : /* 0: outf */ iflags);
 
  assign intf = {iflags[15:10], 2'b0, iflags[7:0]};
  assign dfi  = iflags[10];
  assign strf = dfi ? (x - y) : (x + y);
 
  assign oflags = word_op ? { out[11:6], out[4], out[2], out[0] }
                           : { iflags[11:8], out[7:6], out[4], out[2], out[0] };
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.