// ============================================================================
|
// ============================================================================
|
// __
|
// __
|
// \\__/ o\ (C) 2013,2015 Robert Finch, Stratford
|
// \\__/ o\ (C) 2013-2016 Robert Finch, Stratford
|
// \ __ / All rights reserved.
|
// \ __ / All rights reserved.
|
// \/_// robfinch<remove>@finitron.ca
|
// \/_// robfinch<remove>@finitron.ca
|
// ||
|
// ||
|
//
|
//
|
// This source file is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU Lesser General Public License as published
|
// by the Free Software Foundation, either version 3 of the License, or
|
// by the Free Software Foundation, either version 3 of the License, or
|
// (at your option) any later version.
|
// (at your option) any later version.
|
//
|
//
|
// This source file is distributed in the hope that it will be useful,
|
// This source file is distributed in the hope that it will be useful,
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
//
|
//
|
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
//
|
//
|
//
|
//
|
// Thor SuperScaler
|
// Thor SuperScaler
|
// ALU
|
// ALU
|
//
|
//
|
// ============================================================================
|
// ============================================================================
|
//
|
//
|
`include "Thor_defines.v"
|
`include "Thor_defines.v"
|
|
|
module Thor_alu(corenum, rst, clk, alu_ld, alu_abort, alu_op, alu_fn, alu_argA, alu_argB, alu_argC, alu_argI, alu_pc, insnsz, o, alu_done, alu_idle, alu_divByZero);
|
module Thor_alu(corenum, rst, clk, alu_ld, alu_abort, alu_op, alu_fn, alu_argA, alu_argB, alu_argC, alu_argI, alu_pc, insnsz, o, alu_done, alu_idle, alu_divByZero);
|
parameter DBW=64;
|
parameter DBW=64;
|
parameter BIG=1;
|
parameter BIG=1;
|
parameter FEATURES = 0;
|
parameter FEATURES = 0;
|
input [63:0] corenum;
|
input [63:0] corenum;
|
input rst;
|
input rst;
|
input clk;
|
input clk;
|
input alu_ld;
|
input alu_ld;
|
input alu_abort;
|
input alu_abort;
|
input [7:0] alu_op;
|
input [7:0] alu_op;
|
input [5:0] alu_fn;
|
input [5:0] alu_fn;
|
input [DBW-1:0] alu_argA;
|
input [DBW-1:0] alu_argA;
|
input [DBW-1:0] alu_argB;
|
input [DBW-1:0] alu_argB;
|
input [DBW-1:0] alu_argC;
|
input [DBW-1:0] alu_argC;
|
input [DBW-1:0] alu_argI;
|
input [DBW-1:0] alu_argI;
|
input [DBW-1:0] alu_pc;
|
input [DBW-1:0] alu_pc;
|
input [3:0] insnsz;
|
input [3:0] insnsz;
|
output reg [DBW-1:0] o;
|
output reg [DBW-1:0] o;
|
output reg alu_done;
|
output reg alu_done;
|
output reg alu_idle;
|
output reg alu_idle;
|
output alu_divByZero;
|
output alu_divByZero;
|
|
|
wire signed [DBW-1:0] alu_argAs = alu_argA;
|
wire signed [DBW-1:0] alu_argAs = alu_argA;
|
wire signed [DBW-1:0] alu_argBs = alu_argB;
|
wire signed [DBW-1:0] alu_argBs = alu_argB;
|
wire signed [DBW-1:0] alu_argIs = alu_argI;
|
wire signed [DBW-1:0] alu_argIs = alu_argI;
|
wire [DBW-1:0] andi_res = alu_argA & alu_argI;
|
wire [DBW-1:0] andi_res = alu_argA & alu_argI;
|
wire [127:0] alu_prod;
|
wire [127:0] alu_prod;
|
wire [63:0] alu_divq;
|
wire [63:0] alu_divq;
|
wire [63:0] alu_rem;
|
wire [63:0] alu_rem;
|
wire [7:0] bcdao,bcdso;
|
wire [7:0] bcdao,bcdso;
|
wire [15:0] bcdmo;
|
wire [15:0] bcdmo;
|
wire [DBW-1:0] bf_out;
|
wire [DBW-1:0] bf_out;
|
wire [DBW-1:0] shfto;
|
wire [DBW-1:0] shfto;
|
wire alu_mult_done,alu_div_done;
|
wire alu_mult_done,alu_div_done;
|
wire alu_mult_idle,alu_div_idle;
|
wire alu_mult_idle,alu_div_idle;
|
wire [DBW-1:0] p_out;
|
wire [DBW-1:0] p_out;
|
reg [3:0] o1;
|
reg [3:0] o1;
|
|
|
integer n;
|
integer n;
|
|
|
Thor_multiplier #(DBW) umult1
|
Thor_multiplier #(DBW) umult1
|
(
|
(
|
.rst(rst),
|
.rst(rst),
|
.clk(clk),
|
.clk(clk),
|
.ld(alu_ld && ((alu_op==`RR && (alu_fn==`MUL || alu_fn==`MULU)) || alu_op==`MULI || alu_op==`MULUI)),
|
.ld(alu_ld && ((alu_op==`RR && (alu_fn==`MUL || alu_fn==`MULU)) || alu_op==`MULI || alu_op==`MULUI)),
|
.abort(alu_abort),
|
.abort(alu_abort),
|
.sgn((alu_op==`RR && alu_op==`MUL) || alu_op==`MULI),
|
.sgn((alu_op==`RR && alu_op==`MUL) || alu_op==`MULI),
|
.isMuli(alu_op==`MULI || alu_op==`MULUI),
|
.isMuli(alu_op==`MULI || alu_op==`MULUI),
|
.a(alu_argA),
|
.a(alu_argA),
|
.b(alu_argB),
|
.b(alu_argB),
|
.imm(alu_argI),
|
.imm(alu_argI),
|
.o(alu_prod),
|
.o(alu_prod),
|
.done(alu_mult_done),
|
.done(alu_mult_done),
|
.idle(alu_mult_idle)
|
.idle(alu_mult_idle)
|
);
|
);
|
|
|
Thor_divider #(DBW) udiv1
|
Thor_divider #(DBW) udiv1
|
(
|
(
|
.rst(rst),
|
.rst(rst),
|
.clk(clk),
|
.clk(clk),
|
.ld(alu_ld && ((alu_op==`RR && (alu_fn==`DIV || alu_fn==`DIVU || alu_fn==`MOD || alu_fn==`MODU))
|
.ld(alu_ld && ((alu_op==`RR && (alu_fn==`DIV || alu_fn==`DIVU || alu_fn==`MOD || alu_fn==`MODU))
|
|| alu_op==`DIVI || alu_op==`DIVUI || alu_op==`MODI || alu_op==`MODUI)),
|
|| alu_op==`DIVI || alu_op==`DIVUI || alu_op==`MODI || alu_op==`MODUI)),
|
.abort(alu_abort),
|
.abort(alu_abort),
|
.sgn((alu_op==`RR && (alu_fn==`DIV || alu_fn==`MOD)) || alu_op==`DIVI || alu_op==`MODI),
|
.sgn((alu_op==`RR && (alu_fn==`DIV || alu_fn==`MOD)) || alu_op==`DIVI || alu_op==`MODI),
|
.isDivi(alu_op==`DIVI || alu_op==`DIVUI || alu_op==`MODI || alu_op==`MODUI),
|
.isDivi(alu_op==`DIVI || alu_op==`DIVUI || alu_op==`MODI || alu_op==`MODUI),
|
.a(alu_argA),
|
.a(alu_argA),
|
.b(alu_argB),
|
.b(alu_argB),
|
.imm(alu_argI),
|
.imm(alu_argI),
|
.qo(alu_divq),
|
.qo(alu_divq),
|
.ro(alu_rem),
|
.ro(alu_rem),
|
.dvByZr(alu_divByZero),
|
.dvByZr(alu_divByZero),
|
.done(alu_div_done),
|
.done(alu_div_done),
|
.idle(alu_div_idle)
|
.idle(alu_div_idle)
|
);
|
);
|
|
|
Thor_shifter #(DBW) ushft0
|
Thor_shifter #(DBW) ushft0
|
(
|
(
|
.func(alu_fn),
|
.func(alu_fn),
|
.a(alu_argA),
|
.a(alu_argA),
|
.b(alu_argB),
|
.b(alu_argB),
|
.o(shfto)
|
.o(shfto)
|
);
|
);
|
|
|
BCDAdd ubcda
|
BCDAdd ubcda
|
(
|
(
|
.ci(1'b0),
|
.ci(1'b0),
|
.a(alu_argA[7:0]),
|
.a(alu_argA[7:0]),
|
.b(alu_argB[7:0]),
|
.b(alu_argB[7:0]),
|
.o(bcdao),
|
.o(bcdao),
|
.c()
|
.c()
|
);
|
);
|
|
|
BCDSub ubcds
|
BCDSub ubcds
|
(
|
(
|
.ci(1'b0),
|
.ci(1'b0),
|
.a(alu_argA[7:0]),
|
.a(alu_argA[7:0]),
|
.b(alu_argB[7:0]),
|
.b(alu_argB[7:0]),
|
.o(bcdso),
|
.o(bcdso),
|
.c()
|
.c()
|
);
|
);
|
|
|
BCDMul2 ubcdm
|
BCDMul2 ubcdm
|
(
|
(
|
.a(alu_argA),
|
.a(alu_argA),
|
.b(alu_argB),
|
.b(alu_argB),
|
.o(bcdmo)
|
.o(bcdmo)
|
);
|
);
|
|
|
Thor_bitfield #(DBW) ubf1
|
Thor_bitfield #(DBW) ubf1
|
(
|
(
|
.op(alu_fn),
|
.op(alu_fn),
|
.a(alu_argA),
|
.a(alu_argA),
|
.b(alu_argB),
|
.b(alu_argB),
|
.m(alu_argI[11:0]),
|
.m(alu_argI[11:0]),
|
.o(bf_out),
|
.o(bf_out),
|
.masko()
|
.masko()
|
);
|
);
|
|
|
Thor_P #(DBW) upr1
|
Thor_P #(DBW) upr1
|
(
|
(
|
.fn(alu_fn),
|
.fn(alu_fn),
|
.ra(alu_argI[5:0]),
|
.ra(alu_argI[5:0]),
|
.rb(alu_argI[11:6]),
|
.rb(alu_argI[11:6]),
|
.rt(alu_argI[17:12]),
|
.rt(alu_argI[17:12]),
|
.pregs_i(alu_argA),
|
.pregs_i(alu_argA),
|
.pregs_o(p_out)
|
.pregs_o(p_out)
|
);
|
);
|
|
|
wire [DBW-1:0] cntlzo;
|
wire [DBW-1:0] cntlzo;
|
wire [DBW-1:0] cntloo;
|
wire [DBW-1:0] cntloo;
|
wire [DBW-1:0] cntpopo;
|
wire [DBW-1:0] cntpopo;
|
|
|
generate
|
generate
|
begin : clzg
|
begin : clzg
|
if (DBW==64) begin
|
if (DBW==64) begin
|
cntlz64 u12 ( .i(alu_argA), .o(cntlzo) );
|
cntlz64 u12 ( .i(alu_argA), .o(cntlzo) );
|
cntlo64 u13 ( .i(alu_argA), .o(cntloo) );
|
cntlo64 u13 ( .i(alu_argA), .o(cntloo) );
|
cntpop64 u14 ( .i(alu_argA), .o(cntpopo) );
|
cntpop64 u14 ( .i(alu_argA), .o(cntpopo) );
|
end
|
end
|
else begin
|
else begin
|
cntlz32 u12 ( .i(alu_argA), .o(cntlzo) );
|
cntlz32 u12 ( .i(alu_argA), .o(cntlzo) );
|
cntlo32 u13 ( .i(alu_argA), .o(cntloo) );
|
cntlo32 u13 ( .i(alu_argA), .o(cntloo) );
|
cntpop32 u14 ( .i(alu_argA), .o(cntpopo) );
|
cntpop32 u14 ( .i(alu_argA), .o(cntpopo) );
|
end
|
end
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
wire faz = alu_argA[DBW-2:0]==63'd0;
|
wire faz = alu_argA[DBW-2:0]==63'd0;
|
wire fbz = alu_argB[DBW-2:0]==63'd0;
|
wire fbz = alu_argB[DBW-2:0]==63'd0;
|
wire feq = (faz & fbz) || (alu_argA==alu_argB); // special test for zero
|
wire feq = (faz & fbz) || (alu_argA==alu_argB); // special test for zero
|
wire fgt1 = alu_argA[DBW-2:0] > alu_argB[DBW-2:0];
|
wire fgt1 = alu_argA[DBW-2:0] > alu_argB[DBW-2:0];
|
wire flt1 = alu_argA[DBW-2:0] < alu_argB[DBW-2:0];
|
wire flt1 = alu_argA[DBW-2:0] < alu_argB[DBW-2:0];
|
wire flt = alu_argA[DBW] ^ alu_argB[DBW] ? alu_argA[DBW] & !(faz & fbz): alu_argA[DBW] ? fgt1 : flt1;
|
wire flt = alu_argA[DBW-1] ^ alu_argB[DBW-1] ? alu_argA[DBW-1] & !(faz & fbz): alu_argA[DBW-1] ? fgt1 : flt1;
|
wire nanA = DBW==32 ? alu_argA[30:23]==8'hFF && (alu_argA[22:0]!=23'd0) : alu_argA[62:52]==11'h7FF && (alu_argA[51:0]!=52'd0);
|
wire nanA = DBW==32 ? alu_argA[30:23]==8'hFF && (alu_argA[22:0]!=23'd0) : alu_argA[62:52]==11'h7FF && (alu_argA[51:0]!=52'd0);
|
wire nanB = DBW==32 ? alu_argB[30:23]==8'hFF && (alu_argB[22:0]!=23'd0) : alu_argB[62:52]==11'h7FF && (alu_argB[51:0]!=52'd0);
|
wire nanB = DBW==32 ? alu_argB[30:23]==8'hFF && (alu_argB[22:0]!=23'd0) : alu_argB[62:52]==11'h7FF && (alu_argB[51:0]!=52'd0);
|
|
|
wire fsaz = alu_argA[30:0]==31'd0;
|
wire fsaz = alu_argA[30:0]==31'd0;
|
wire fsbz = alu_argB[30:0]==31'd0;
|
wire fsbz = alu_argB[30:0]==31'd0;
|
wire fseq = (fsaz & fsbz) || (alu_argA[31:0]==alu_argB[31:0]); // special test for zero
|
wire fseq = (fsaz & fsbz) || (alu_argA[31:0]==alu_argB[31:0]); // special test for zero
|
wire fsgt1 = alu_argA[30:0] > alu_argB[30:0];
|
wire fsgt1 = alu_argA[30:0] > alu_argB[30:0];
|
wire fslt1 = alu_argA[30:0] < alu_argB[30:0];
|
wire fslt1 = alu_argA[30:0] < alu_argB[30:0];
|
wire fslt = alu_argA[31] ^ alu_argB[31] ? alu_argA[31] & !(fsaz & fsbz): alu_argA[31] ? fsgt1 : fslt1;
|
wire fslt = alu_argA[31] ^ alu_argB[31] ? alu_argA[31] & !(fsaz & fsbz): alu_argA[31] ? fsgt1 : fslt1;
|
wire snanA = alu_argA[30:23]==8'hFF && (alu_argA[22:0]!=23'd0);
|
wire snanA = alu_argA[30:23]==8'hFF && (alu_argA[22:0]!=23'd0);
|
wire snanB = alu_argB[30:23]==8'hFF && (alu_argB[22:0]!=23'd0);
|
wire snanB = alu_argB[30:23]==8'hFF && (alu_argB[22:0]!=23'd0);
|
|
|
always @*
|
always @*
|
begin
|
begin
|
case(alu_op)
|
case(alu_op)
|
`LDI,`LDIS: o <= alu_argI;
|
`LDI,`LDIS: o <= alu_argI;
|
`RR:
|
`RR:
|
case(alu_fn)
|
case(alu_fn)
|
`ADD,`ADDU: o <= alu_argA + alu_argB;
|
`ADD,`ADDU: o <= alu_argA + alu_argB;
|
`SUB,`SUBU: o <= alu_argA - alu_argB;
|
`SUB,`SUBU: o <= alu_argA - alu_argB;
|
`_2ADDU: o <= {alu_argA[DBW-2:0],1'b0} + alu_argB;
|
`_2ADDU: o <= {alu_argA[DBW-2:0],1'b0} + alu_argB;
|
`_4ADDU: o <= {alu_argA[DBW-3:0],2'b0} + alu_argB;
|
`_4ADDU: o <= {alu_argA[DBW-3:0],2'b0} + alu_argB;
|
`_8ADDU: o <= {alu_argA[DBW-4:0],3'b0} + alu_argB;
|
`_8ADDU: o <= {alu_argA[DBW-4:0],3'b0} + alu_argB;
|
`_16ADDU: o <= {alu_argA[DBW-5:0],4'b0} + alu_argB;
|
`_16ADDU: o <= {alu_argA[DBW-5:0],4'b0} + alu_argB;
|
`MIN: o <= BIG ? (alu_argA < alu_argB ? alu_argA : alu_argB) : 64'hDEADDEADDEADDEAD;
|
`MIN: o <= BIG ? (alu_argA < alu_argB ? alu_argA : alu_argB) : 64'hDEADDEADDEADDEAD;
|
`MAX: o <= BIG ? (alu_argA < alu_argB ? alu_argB : alu_argA) : 64'hDEADDEADDEADDEAD;
|
`MAX: o <= BIG ? (alu_argA < alu_argB ? alu_argB : alu_argA) : 64'hDEADDEADDEADDEAD;
|
`MUL,`MULU: o <= BIG ? alu_prod[63:0] : 64'hDEADDEADDEADDEAD;
|
`MUL,`MULU: o <= BIG ? alu_prod[63:0] : 64'hDEADDEADDEADDEAD;
|
`DIV,`DIVU: o <= BIG ? alu_divq : 64'hDEADDEADDEADDEAD;
|
`DIV,`DIVU: o <= BIG ? alu_divq : 64'hDEADDEADDEADDEAD;
|
`MOD,`MODU: o <= BIG ? alu_rem : 64'hDEADDEADDEADDEAD;
|
`MOD,`MODU: o <= BIG ? alu_rem : 64'hDEADDEADDEADDEAD;
|
|
`CHK: o <= ($signed(alu_argC) >= $signed(alu_argA)) && ($signed(alu_argC) < $signed(alu_argB));
|
default: o <= 64'hDEADDEADDEADDEAD;
|
default: o <= 64'hDEADDEADDEADDEAD;
|
endcase
|
endcase
|
`MULI,`MULUI: o <= BIG ? alu_prod[63:0] : 64'hDEADDEADDEADDEAD;
|
`MULI,`MULUI: o <= BIG ? alu_prod[63:0] : 64'hDEADDEADDEADDEAD;
|
`DIVI,`DIVUI: o <= BIG ? alu_divq : 64'hDEADDEADDEADDEAD;
|
`DIVI,`DIVUI: o <= BIG ? alu_divq : 64'hDEADDEADDEADDEAD;
|
`MODI,`MODUI: o <= BIG ? alu_rem : 64'hDEADDEADDEADDEAD;
|
`MODI,`MODUI: o <= BIG ? alu_rem : 64'hDEADDEADDEADDEAD;
|
`_2ADDUI: o <= {alu_argA[DBW-2:0],1'b0} + alu_argI;
|
`_2ADDUI: o <= {alu_argA[DBW-2:0],1'b0} + alu_argI;
|
`_4ADDUI: o <= {alu_argA[DBW-3:0],2'b0} + alu_argI;
|
`_4ADDUI: o <= {alu_argA[DBW-3:0],2'b0} + alu_argI;
|
`_8ADDUI: o <= {alu_argA[DBW-4:0],3'b0} + alu_argI;
|
`_8ADDUI: o <= {alu_argA[DBW-4:0],3'b0} + alu_argI;
|
`_16ADDUI: o <= {alu_argA[DBW-5:0],4'b0} + alu_argI;
|
`_16ADDUI: o <= {alu_argA[DBW-5:0],4'b0} + alu_argI;
|
`R:
|
`R:
|
case(alu_fn[3:0])
|
case(alu_fn[3:0])
|
`MOV: o <= alu_argA;
|
`MOV: o <= alu_argA;
|
`NEG: o <= -alu_argA;
|
`NEG: o <= -alu_argA;
|
`NOT: o <= |alu_argA ? 64'd0 : 64'd1;
|
`NOT: o <= |alu_argA ? 64'd0 : 64'd1;
|
`ABS: o <= BIG ? (alu_argA[DBW] ? -alu_argA : alu_argA) : 64'hDEADDEADDEADDEAD;
|
`ABS: o <= BIG ? (alu_argA[DBW-1] ? -alu_argA : alu_argA) : 64'hDEADDEADDEADDEAD;
|
`SGN: o <= BIG ? (alu_argA[DBW] ? 64'hFFFFFFFFFFFFFFFF : alu_argA==64'd0 ? 64'd0 : 64'd1) : 64'hDEADDEADDEADDEAD;
|
`SGN: o <= BIG ? (alu_argA[DBW-1] ? 64'hFFFFFFFFFFFFFFFF : alu_argA==64'd0 ? 64'd0 : 64'd1) : 64'hDEADDEADDEADDEAD;
|
`CNTLZ: o <= BIG ? cntlzo : 64'hDEADDEADDEADDEAD;
|
`CNTLZ: o <= BIG ? cntlzo : 64'hDEADDEADDEADDEAD;
|
`CNTLO: o <= BIG ? cntloo : 64'hDEADDEADDEADDEAD;
|
`CNTLO: o <= BIG ? cntloo : 64'hDEADDEADDEADDEAD;
|
`CNTPOP: o <= BIG ? cntpopo : 64'hDEADDEADDEADDEAD;
|
`CNTPOP: o <= BIG ? cntpopo : 64'hDEADDEADDEADDEAD;
|
`ZXB: o <= BIG ? {56'd0,alu_argA[7:0]} : 64'hDEADDEADDEADDEAD;
|
`ZXB: o <= BIG ? {56'd0,alu_argA[7:0]} : 64'hDEADDEADDEADDEAD;
|
`ZXC: o <= BIG ? {48'd0,alu_argA[15:0]} : 64'hDEADDEADDEADDEAD;
|
`ZXC: o <= BIG ? {48'd0,alu_argA[15:0]} : 64'hDEADDEADDEADDEAD;
|
`ZXH: o <= BIG ? {32'd0,alu_argA[31:0]} : 64'hDEADDEADDEADDEAD;
|
`ZXH: o <= BIG ? {32'd0,alu_argA[31:0]} : 64'hDEADDEADDEADDEAD;
|
`COM: o <= ~alu_argA;
|
`COM: o <= ~alu_argA;
|
`SXB: o <= BIG ? {{56{alu_argA[7]}},alu_argA[7:0]} : 64'hDEADDEADDEADDEAD;
|
`SXB: o <= BIG ? {{56{alu_argA[7]}},alu_argA[7:0]} : 64'hDEADDEADDEADDEAD;
|
`SXC: o <= BIG ? {{48{alu_argA[15]}},alu_argA[15:0]} : 64'hDEADDEADDEADDEAD;
|
`SXC: o <= BIG ? {{48{alu_argA[15]}},alu_argA[15:0]} : 64'hDEADDEADDEADDEAD;
|
`SXH: o <= BIG ? {{32{alu_argA[31]}},alu_argA[31:0]} : 64'hDEADDEADDEADDEAD;
|
`SXH: o <= BIG ? {{32{alu_argA[31]}},alu_argA[31:0]} : 64'hDEADDEADDEADDEAD;
|
default: o <= 64'hDEADDEADDEADDEAD;
|
default: o <= 64'hDEADDEADDEADDEAD;
|
endcase
|
endcase
|
`R2:
|
`R2:
|
case(alu_fn)
|
case(alu_fn)
|
`CPUID:
|
`CPUID:
|
if (BIG)
|
if (BIG)
|
case(alu_argA[4:0])
|
case(alu_argA[4:0])
|
5'd0: o <= corenum;
|
5'd0: o <= corenum;
|
5'd2: o <= "Finitron";
|
5'd2: o <= "Finitron";
|
5'd3: o <= ""; // vendor ID
|
5'd3: o <= ""; // vendor ID
|
5'd4: o <= "64BitSS"; // class
|
5'd4: o <= "64BitSS"; // class
|
5'd6: o <= "Thor"; // Name
|
5'd6: o <= "Thor"; // Name
|
5'd8: o <= "M1"; // model
|
5'd8: o <= "M1"; // model
|
5'd9: o <= "1234"; // serial num
|
5'd9: o <= "1234"; // serial num
|
5'd10: o <= FEATURES;
|
5'd10: o <= FEATURES;
|
5'd11: o <= {32'd16384,32'd32768}; // Cache D,I
|
5'd11: o <= {32'd16384,32'd32768}; // Cache D,I
|
default: o <= 64'hDEADDEADDEADDEAD;
|
default: o <= 64'hDEADDEADDEADDEAD;
|
endcase
|
endcase
|
else o <= 64'hDEADDEADDEADDEAD;
|
else o <= 64'hDEADDEADDEADDEAD;
|
`REDOR: o <= BIG ? |alu_argA : 64'hDEADDEADDEADDEAD;
|
`REDOR: o <= BIG ? |alu_argA : 64'hDEADDEADDEADDEAD;
|
`REDAND: o <= BIG ? &alu_argA : 64'hDEADDEADDEADDEAD;
|
`REDAND: o <= BIG ? &alu_argA : 64'hDEADDEADDEADDEAD;
|
`PAR: o <= BIG ? ^alu_argA : 64'hDEADDEADDEADDEAD;
|
`PAR: o <= BIG ? ^alu_argA : 64'hDEADDEADDEADDEAD;
|
default: o <= 64'hDEADDEADDEADDEAD;
|
default: o <= 64'hDEADDEADDEADDEAD;
|
endcase
|
endcase
|
`P: o <= p_out;
|
`P: o <= p_out;
|
/*
|
/*
|
`DOUBLE:
|
`DOUBLE:
|
if (BIG) begin
|
if (BIG) begin
|
if (alu_fn[5:4]==2'b00)
|
if (alu_fn[5:4]==2'b00)
|
case (alu_fn)
|
case (alu_fn)
|
`FMOV: o <= alu_argA;
|
`FMOV: o <= alu_argA;
|
`FNEG: o <= {~alu_argA[DBW-1],alu_argA[DBW-2:0]};
|
`FNEG: o <= {~alu_argA[DBW-1],alu_argA[DBW-2:0]};
|
`FABS: o <= {1'b0,alu_argA[DBW-2:0]};
|
`FABS: o <= {1'b0,alu_argA[DBW-2:0]};
|
`FSIGN: if (DBW==64)
|
`FSIGN: if (DBW==64)
|
o <= alu_argA[DBW-2:0]==0 ? {DBW{1'b0}} : {alu_argA[DBW-1],1'b0,{10{1'b1}},{52{1'b0}}};
|
o <= alu_argA[DBW-2:0]==0 ? {DBW{1'b0}} : {alu_argA[DBW-1],1'b0,{10{1'b1}},{52{1'b0}}};
|
else
|
else
|
o <= alu_argA[DBW-2:0]==0 ? {DBW{1'b0}} : {alu_argA[DBW-1],1'b0,{7{1'b1}},{23{1'b0}}};
|
o <= alu_argA[DBW-2:0]==0 ? {DBW{1'b0}} : {alu_argA[DBW-1],1'b0,{7{1'b1}},{23{1'b0}}};
|
`FMAN: o <= alu_argA[(DBW==64?51:22):0];
|
`FMAN: o <= alu_argA[(DBW==64?51:22):0];
|
default: o <= 64'hDEADDEADDEADDEAD;
|
default: o <= 64'hDEADDEADDEADDEAD;
|
endcase
|
endcase
|
else
|
else
|
case (alu_fn)
|
case (alu_fn)
|
`FMOV: o <= alu_argA;
|
`FMOV: o <= alu_argA;
|
`FSNEG: o <= {~alu_argA[31],alu_argA[30:0]};
|
`FSNEG: o <= {~alu_argA[31],alu_argA[30:0]};
|
`FSABS: o <= {1'b0,alu_argA[30:0]};
|
`FSABS: o <= {1'b0,alu_argA[30:0]};
|
`FSSIGN: o <= alu_argA[30:0]==0 ? {DBW{1'b0}} : {alu_argA[31],1'b0,{7{1'b1}},{23{1'b0}}};
|
`FSSIGN: o <= alu_argA[30:0]==0 ? {DBW{1'b0}} : {alu_argA[31],1'b0,{7{1'b1}},{23{1'b0}}};
|
`FSMAN: o <= alu_argA[22:0];
|
`FSMAN: o <= alu_argA[22:0];
|
default: o <= 64'hDEADDEADDEADDEAD;
|
default: o <= 64'hDEADDEADDEADDEAD;
|
endcase
|
endcase
|
end
|
end
|
else
|
else
|
o <= 64'hDEADDEADDEADDEAD;
|
o <= 64'hDEADDEADDEADDEAD;
|
*/
|
*/
|
|
|
`ADDI,`ADDUI,`ADDUIS,`LEA:
|
`ADDI,`ADDUI,`ADDUIS:
|
o <= alu_argA + alu_argI;
|
o <= alu_argA + alu_argI;
|
`SUBI,`SUBUI:
|
`SUBI,`SUBUI:
|
o <= alu_argA - alu_argI;
|
o <= alu_argA - alu_argI;
|
`ANDI: o <= alu_argA & alu_argI;
|
`ANDI: o <= alu_argA & alu_argI;
|
`ORI: o <= alu_argA | alu_argI;
|
`ORI: o <= alu_argA | alu_argI;
|
`EORI: o <= alu_argA ^ alu_argI;
|
`EORI: o <= alu_argA ^ alu_argI;
|
`LOGIC,`MLO:
|
`LOGIC,`MLO:
|
case(alu_fn)
|
case(alu_fn)
|
`AND: o <= alu_argA & alu_argB;
|
`AND: o <= alu_argA & alu_argB;
|
`ANDC: o <= alu_argA & ~alu_argB;
|
`ANDC: o <= alu_argA & ~alu_argB;
|
`OR: o <= alu_argA | alu_argB;
|
`OR: o <= alu_argA | alu_argB;
|
`ORC: o <= alu_argA | ~alu_argB;
|
`ORC: o <= alu_argA | ~alu_argB;
|
`EOR: o <= alu_argA ^ alu_argB;
|
`EOR: o <= alu_argA ^ alu_argB;
|
`NAND: o <= ~(alu_argA & alu_argB);
|
`NAND: o <= ~(alu_argA & alu_argB);
|
`NOR: o <= ~(alu_argA | alu_argB);
|
`NOR: o <= ~(alu_argA | alu_argB);
|
`ENOR: o <= ~(alu_argA ^ alu_argB);
|
`ENOR: o <= ~(alu_argA ^ alu_argB);
|
default: o <= 64'd0;
|
default: o <= 64'd0;
|
endcase
|
endcase
|
`BITI:
|
`BITI:
|
begin
|
begin
|
o1[0] = andi_res==64'd0;
|
o1[0] = andi_res==64'd0;
|
o1[1] = andi_res[DBW-1];
|
o1[1] = andi_res[DBW-1];
|
o1[2] = andi_res[0];
|
o1[2] = andi_res[0];
|
o1[3] = 1'b0;
|
o1[3] = 1'b0;
|
o <= {16{o1}};
|
o <= {16{o1}};
|
end
|
end
|
// TST
|
// TST
|
8'h00,8'h01,8'h02,8'h03,8'h04,8'h05,8'h06,8'h07,8'h08,8'h09,8'h0A,8'h0B,8'h0C,8'h0D,8'h0E,8'h0f:
|
8'h00,8'h01,8'h02,8'h03,8'h04,8'h05,8'h06,8'h07,8'h08,8'h09,8'h0A,8'h0B,8'h0C,8'h0D,8'h0E,8'h0f:
|
case(alu_fn)
|
case(alu_fn)
|
6'd0: // TST - integer
|
6'd0: // TST - integer
|
begin
|
begin
|
o1[0] = alu_argA == 64'd0;
|
o1[0] = alu_argA == 64'd0;
|
o1[1] = alu_argA[DBW-1];
|
o1[1] = alu_argA[DBW-1];
|
o1[2] = 1'b0;
|
o1[2] = 1'b0;
|
o1[3] = 1'b0;
|
o1[3] = 1'b0;
|
o <= {16{o1}};
|
o <= {16{o1}};
|
end
|
end
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
6'd1: // FSTST - float single
|
6'd1: // FSTST - float single
|
begin
|
begin
|
o1[0] = alu_argA[30:0]==31'd0; // + or - zero
|
o1[0] = alu_argA[30:0]==31'd0; // + or - zero
|
o1[1] = alu_argA[31]; // signed less than
|
o1[1] = alu_argA[31]; // signed less than
|
o1[2] = alu_argA[31];
|
o1[2] = alu_argA[31];
|
// unordered
|
// unordered
|
o1[3] = alu_argA[30:23]==8'hFF && alu_argA[22:0]!=23'd0; // NaN
|
o1[3] = alu_argA[30:23]==8'hFF && alu_argA[22:0]!=23'd0; // NaN
|
o <= {16{o1}};
|
o <= {16{o1}};
|
end
|
end
|
6'd2: // FTST - float double
|
6'd2: // FTST - float double
|
begin
|
begin
|
o1[0] = alu_argA[DBW-2:0]==63'd0; // + or - zero
|
o1[0] = alu_argA[DBW-2:0]==63'd0; // + or - zero
|
o1[1] = alu_argA[DBW-1]; // signed less than
|
o1[1] = alu_argA[DBW-1]; // signed less than
|
o1[2] = alu_argA[DBW-1];
|
o1[2] = alu_argA[DBW-1];
|
// unordered
|
// unordered
|
if (DBW==64)
|
if (DBW==64)
|
o1[3] = alu_argA[62:52]==11'h7FF && alu_argA[51:0]!=52'd0; // NaN
|
o1[3] = alu_argA[62:52]==11'h7FF && alu_argA[51:0]!=52'd0; // NaN
|
else
|
else
|
o1[3] = 1'b0;
|
o1[3] = 1'b0;
|
o <= {16{o1}};
|
o <= {16{o1}};
|
end
|
end
|
`endif
|
`endif
|
default: o <= 64'd0;
|
default: o <= 64'd0;
|
endcase
|
endcase
|
// CMP
|
// CMP
|
8'h10,8'h11,8'h12,8'h13,8'h14,8'h15,8'h16,8'h17,8'h18,8'h19,8'h1A,8'h1B,8'h1C,8'h1D,8'h1E,8'h1f:
|
8'h10,8'h11,8'h12,8'h13,8'h14,8'h15,8'h16,8'h17,8'h18,8'h19,8'h1A,8'h1B,8'h1C,8'h1D,8'h1E,8'h1f:
|
begin
|
begin
|
case(alu_fn)
|
case(alu_fn)
|
2'd0: begin // ICMP
|
2'd0: begin // ICMP
|
o1[0] = alu_argA == alu_argB;
|
o1[0] = alu_argA == alu_argB;
|
o1[1] = ($signed(alu_argA) < $signed(alu_argB));
|
o1[1] = ($signed(alu_argA) < $signed(alu_argB));
|
o1[2] = alu_argA < alu_argB;
|
o1[2] = alu_argA < alu_argB;
|
o1[3] = 1'b0;
|
o1[3] = 1'b0;
|
o <= {16{o1}};
|
o <= {16{o1}};
|
end
|
end
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
2'd1: begin // FSCMP
|
2'd1: begin // FSCMP
|
o1[0] = fseq;
|
o1[0] = fseq;
|
o1[1] = fslt;
|
o1[1] = fslt;
|
o1[2] = fslt1;
|
o1[2] = fslt1;
|
o1[3] = snanA | snanB;
|
o1[3] = snanA | snanB;
|
o <= {16{o1}};
|
o <= {16{o1}};
|
end
|
end
|
2'd2: begin // FCMP
|
2'd2: begin // FCMP
|
o1[0] = feq;
|
o1[0] = feq;
|
o1[1] = flt;
|
o1[1] = flt;
|
o1[2] = flt1;
|
o1[2] = flt1;
|
o1[3] = nanA | nanB;
|
o1[3] = nanA | nanB;
|
o <= {16{o1}};
|
o <= {16{o1}};
|
end
|
end
|
`endif
|
`endif
|
default: o <= 64'hDEADDEADDEADDEAD;
|
default: o <= 64'hDEADDEADDEADDEAD;
|
endcase
|
endcase
|
end
|
end
|
// CMPI
|
// CMPI
|
8'h20,8'h21,8'h22,8'h23,8'h24,8'h25,8'h26,8'h27,8'h28,8'h29,8'h2A,8'h2B,8'h2C,8'h2D,8'h2E,8'h2f:
|
8'h20,8'h21,8'h22,8'h23,8'h24,8'h25,8'h26,8'h27,8'h28,8'h29,8'h2A,8'h2B,8'h2C,8'h2D,8'h2E,8'h2f:
|
begin
|
begin
|
o1[0] = alu_argA == alu_argI;
|
o1[0] = alu_argA == alu_argI;
|
o1[1] = ($signed(alu_argA) < $signed(alu_argI));
|
o1[1] = ($signed(alu_argA) < $signed(alu_argI));
|
o1[2] = alu_argA < alu_argI;
|
o1[2] = alu_argA < alu_argI;
|
o1[3] = 1'b0;
|
o1[3] = 1'b0;
|
o <= {16{o1}};
|
o <= {16{o1}};
|
end
|
end
|
`LLA,
|
`LLA,
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`SB,`SC,`SH,`SW,`CAS,`LVB,`LVC,`LVH,`LVW,`STI,
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`SB,`SC,`SH,`SW,`CAS,`LVB,`LVC,`LVH,`LVW,`STI,
|
`LWS,`SWS,`STS,`STFND,`STCMP,`PUSH:
|
`LWS,`SWS,`STS,`STFND,`STCMP,`PUSH:
|
begin
|
begin
|
o <= alu_argA + alu_argC + alu_argI;
|
o <= alu_argA + alu_argC + alu_argI;
|
end
|
end
|
`JMPI: o <= {alu_argA << alu_fn[1:0]} + alu_argC + alu_argI;
|
`JMPI: o <= {alu_argA << alu_fn[1:0]} + alu_argC + alu_argI;
|
`LBX,`LBUX,`SBX,
|
`LBX,`LBUX,`SBX,
|
`LCX,`LCUX,`SCX,
|
`LCX,`LCUX,`SCX,
|
`LHX,`LHUX,`SHX,
|
`LHX,`LHUX,`SHX,
|
`LWX,`SWX,`LLAX,
|
`LWX,`SWX,`LLAX,
|
`JMPIX:
|
`JMPIX:
|
case(alu_fn[1:0])
|
case(alu_fn[1:0])
|
2'd0: o <= alu_argA + alu_argC + alu_argB;
|
2'd0: o <= alu_argA + alu_argC + alu_argB;
|
2'd1: o <= alu_argA + alu_argC + {alu_argB,1'b0};
|
2'd1: o <= alu_argA + alu_argC + {alu_argB,1'b0};
|
2'd2: o <= alu_argA + alu_argC + {alu_argB,2'b0};
|
2'd2: o <= alu_argA + alu_argC + {alu_argB,2'b0};
|
2'd3: o <= alu_argA + alu_argC + {alu_argB,3'b0};
|
2'd3: o <= alu_argA + alu_argC + {alu_argB,3'b0};
|
endcase
|
endcase
|
`ifdef STACKOPS
|
`ifdef STACKOPS
|
`PEA,`LINK: o <= alu_argA + alu_argC - 64'd8;
|
`PEA,`LINK: o <= alu_argA + alu_argC - 64'd8;
|
`UNLINK: o <= alu_argA + alu_argC + 64'd8;
|
`UNLINK: o <= alu_argA + alu_argC + 64'd8;
|
`POP: o <= alu_argA + alu_argC;
|
`POP: o <= alu_argA + alu_argC;
|
`endif
|
`endif
|
`JSR,`JSRS,`JSRZ,`SYS: o <= alu_pc + insnsz;
|
`JSR,`JSRS,`JSRZ,`SYS: o <= alu_pc + insnsz;
|
`INT: o <= alu_pc;
|
`INT: o <= alu_pc;
|
`MFSPR,`MTSPR: begin
|
`MFSPR,`MTSPR: begin
|
o <= alu_argA;
|
o <= alu_argA;
|
end
|
end
|
`MUX: begin
|
`MUX: begin
|
for (n = 0; n < DBW; n = n + 1)
|
for (n = 0; n < DBW; n = n + 1)
|
o[n] <= alu_argA[n] ? alu_argB[n] : alu_argC[n];
|
o[n] <= alu_argA[n] ? alu_argB[n] : alu_argC[n];
|
end
|
end
|
`BCD:
|
`BCD:
|
if (BIG)
|
if (BIG)
|
case(alu_fn)
|
case(alu_fn)
|
`BCDADD: o <= bcdao;
|
`BCDADD: o <= bcdao;
|
`BCDSUB: o <= bcdso;
|
`BCDSUB: o <= bcdso;
|
`BCDMUL: o <= bcdmo;
|
`BCDMUL: o <= bcdmo;
|
default: o <= 64'hDEADDEADDEADDEAD;
|
default: o <= 64'hDEADDEADDEADDEAD;
|
endcase
|
endcase
|
else
|
else
|
o <= 64'hDEADDEADDEADDEAD;
|
o <= 64'hDEADDEADDEADDEAD;
|
`SHIFT: o <= BIG ? shfto : 64'hDEADDEADDEADDEAD;
|
`SHIFT: o <= BIG ? shfto : 64'hDEADDEADDEADDEAD;
|
`ifdef BITFIELDOPS
|
`ifdef BITFIELDOPS
|
`BITFIELD: o <= BIG ? bf_out : 64'hDEADDEADDEADDEAD;
|
`BITFIELD: o <= BIG ? bf_out : 64'hDEADDEADDEADDEAD;
|
`endif
|
`endif
|
`LOOP: o <= alu_argA > 0 ? alu_argA - 64'd1 : alu_argA;
|
`LOOP: o <= alu_argA > 0 ? alu_argA - 64'd1 : alu_argA;
|
|
`CHKI: o <= ($signed(alu_argB) >= $signed(alu_argA)) && ($signed(alu_argB) < $signed(alu_argI));
|
default: o <= 64'hDEADDEADDEADDEAD;
|
default: o <= 64'hDEADDEADDEADDEAD;
|
endcase
|
endcase
|
end
|
end
|
|
|
// Generate done signal
|
// Generate done signal
|
always @*
|
always @*
|
case(alu_op)
|
case(alu_op)
|
`RR:
|
`RR:
|
case(alu_fn)
|
case(alu_fn)
|
`MUL,`MULU: alu_done <= alu_mult_done;
|
`MUL,`MULU: alu_done <= alu_mult_done;
|
`DIV,`DIVU,`MOD,`MODU: alu_done <= alu_div_done;
|
`DIV,`DIVU,`MOD,`MODU: alu_done <= alu_div_done;
|
default: alu_done <= `TRUE;
|
default: alu_done <= `TRUE;
|
endcase
|
endcase
|
`MULI,`MULUI: alu_done <= alu_mult_done;
|
`MULI,`MULUI: alu_done <= alu_mult_done;
|
`DIVI,`DIVUI,`MODI,`MODUI: alu_done <= alu_div_done;
|
`DIVI,`DIVUI,`MODI,`MODUI: alu_done <= alu_div_done;
|
default: alu_done <= `TRUE;
|
default: alu_done <= `TRUE;
|
endcase
|
endcase
|
|
|
// Generate idle signal
|
// Generate idle signal
|
always @*
|
always @*
|
case(alu_op)
|
case(alu_op)
|
`RR:
|
`RR:
|
case(alu_fn)
|
case(alu_fn)
|
`MUL,`MULU: alu_idle <= alu_mult_idle;
|
`MUL,`MULU: alu_idle <= alu_mult_idle;
|
`DIV,`DIVU,`MOD,`MODU: alu_idle <= alu_div_idle;
|
`DIV,`DIVU,`MOD,`MODU: alu_idle <= alu_div_idle;
|
default: alu_idle <= `TRUE;
|
default: alu_idle <= `TRUE;
|
endcase
|
endcase
|
`MULI,`MULUI: alu_idle <= alu_mult_idle;
|
`MULI,`MULUI: alu_idle <= alu_mult_idle;
|
`DIVI,`DIVUI,`MODI,`MODUI: alu_idle <= alu_div_idle;
|
`DIVI,`DIVUI,`MODI,`MODUI: alu_idle <= alu_div_idle;
|
default: alu_idle <= `TRUE;
|
default: alu_idle <= `TRUE;
|
endcase
|
endcase
|
|
|
endmodule
|
endmodule
|
|
|