/* $Id: aeMB2_ctrl.v,v 1.7 2008-05-11 13:50:50 sybreon Exp $
|
/* $Id: aeMB2_ctrl.v,v 1.7 2008-05-11 13:50:50 sybreon Exp $
|
**
|
**
|
** AEMB2 EDK 6.2 COMPATIBLE CORE
|
** AEMB2 EDK 6.2 COMPATIBLE CORE
|
** Copyright (C) 2004-2008 Shawn Tan <shawn.tan@aeste.net>
|
** Copyright (C) 2004-2008 Shawn Tan <shawn.tan@aeste.net>
|
**
|
**
|
** This file is part of AEMB.
|
** This file is part of AEMB.
|
**
|
**
|
** AEMB is free software: you can redistribute it and/or modify it
|
** AEMB is free software: you can redistribute it and/or modify it
|
** under the terms of the GNU Lesser General Public License as
|
** under the terms of the GNU Lesser General Public License as
|
** published by the Free Software Foundation, either version 3 of the
|
** published by the Free Software Foundation, either version 3 of the
|
** License, or (at your option) any later version.
|
** License, or (at your option) any later version.
|
**
|
**
|
** AEMB is distributed in the hope that it will be useful, but WITHOUT
|
** AEMB is distributed in the hope that it will be useful, but WITHOUT
|
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
** or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
** or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
** Public License for more details.
|
** Public License for more details.
|
**
|
**
|
** You should have received a copy of the GNU Lesser General Public
|
** You should have received a copy of the GNU Lesser General Public
|
** License along with AEMB. If not, see <http:**www.gnu.org/licenses/>.
|
** License along with AEMB. If not, see <http:**www.gnu.org/licenses/>.
|
*/
|
*/
|
/**
|
/**
|
* Instruction Decode & Control
|
* Instruction Decode & Control
|
* @file aeMB2_ctrl.v
|
* @file aeMB2_ctrl.v
|
|
|
* This is the data decoder that will control the command signals and
|
* This is the data decoder that will control the command signals and
|
operand fetch.
|
operand fetch.
|
|
|
*/
|
*/
|
|
|
module aeMB2_ctrl (/*AUTOARG*/
|
module aeMB2_ctrl (/*AUTOARG*/
|
// Outputs
|
// Outputs
|
opa_of, opb_of, opd_of, opc_of, ra_of, rd_of, imm_of, rd_ex,
|
opa_of, opb_of, opd_of, opc_of, ra_of, rd_of, imm_of, rd_ex,
|
mux_of, mux_ex, hzd_bpc, hzd_fwd,
|
mux_of, mux_ex, hzd_bpc, hzd_fwd,
|
// Inputs
|
// Inputs
|
opa_if, opb_if, opd_if, brk_if, bra_ex, rpc_if, alu_ex, ich_dat,
|
opa_if, opb_if, opd_if, brk_if, bra_ex, rpc_if, alu_ex, ich_dat,
|
gclk, grst, dena, iena, gpha
|
gclk, grst, dena, iena, gpha
|
);
|
);
|
parameter AEMB_HTX = 1;
|
parameter AEMB_HTX = 1;
|
|
|
// EX CONTROL
|
// EX CONTROL
|
output [31:0] opa_of;
|
output [31:0] opa_of;
|
output [31:0] opb_of;
|
output [31:0] opb_of;
|
output [31:0] opd_of;
|
output [31:0] opd_of;
|
output [5:0] opc_of;
|
output [5:0] opc_of;
|
output [4:0] ra_of,
|
output [4:0] ra_of,
|
//rb_of,
|
//rb_of,
|
rd_of;
|
rd_of;
|
output [15:0] imm_of;
|
output [15:0] imm_of;
|
output [4:0] rd_ex;
|
output [4:0] rd_ex;
|
|
|
// REGS
|
// REGS
|
input [31:0] opa_if,
|
input [31:0] opa_if,
|
opb_if,
|
opb_if,
|
opd_if;
|
opd_if;
|
|
|
// WB CONTROL
|
// WB CONTROL
|
output [2:0] mux_of,
|
output [2:0] mux_of,
|
mux_ex;
|
mux_ex;
|
|
|
// INTERNAL
|
// INTERNAL
|
input [1:0] brk_if;
|
input [1:0] brk_if;
|
input [1:0] bra_ex;
|
input [1:0] bra_ex;
|
input [31:2] rpc_if;
|
input [31:2] rpc_if;
|
input [31:0] alu_ex;
|
input [31:0] alu_ex;
|
input [31:0] ich_dat;
|
input [31:0] ich_dat;
|
|
|
output hzd_bpc;
|
output hzd_bpc;
|
output hzd_fwd;
|
output hzd_fwd;
|
|
|
// SYSTEM
|
// SYSTEM
|
input gclk,
|
input gclk,
|
grst,
|
grst,
|
dena,
|
dena,
|
iena,
|
iena,
|
gpha;
|
gpha;
|
|
|
/*AUTOREG*/
|
/*AUTOREG*/
|
// Beginning of automatic regs (for this module's undeclared outputs)
|
// Beginning of automatic regs (for this module's undeclared outputs)
|
reg [15:0] imm_of;
|
reg [15:0] imm_of;
|
reg [2:0] mux_ex;
|
reg [2:0] mux_ex;
|
reg [2:0] mux_of;
|
reg [2:0] mux_of;
|
reg [31:0] opa_of;
|
reg [31:0] opa_of;
|
reg [31:0] opb_of;
|
reg [31:0] opb_of;
|
reg [5:0] opc_of;
|
reg [5:0] opc_of;
|
reg [31:0] opd_of;
|
reg [31:0] opd_of;
|
reg [4:0] ra_of;
|
reg [4:0] ra_of;
|
reg [4:0] rd_ex;
|
reg [4:0] rd_ex;
|
reg [4:0] rd_of;
|
reg [4:0] rd_of;
|
// End of automatics
|
// End of automatics
|
|
|
wire fINT;
|
wire fINT;
|
//wire [31:0] wXCEOP = 32'hBA2D0020; // Vector 0x20
|
//wire [31:0] wXCEOP = 32'hBA2D0020; // Vector 0x20
|
wire [31:0] wINTOP = 32'hB9CD0010; // Vector 0x10
|
wire [31:0] wINTOP = 32'hB9CD0010; // Vector 0x10
|
//wire [31:0] wNOPOP = 32'h88000000; // branch-no-delay/stall
|
//wire [31:0] wNOPOP = 32'h88000000; // branch-no-delay/stall
|
|
|
wire [1:0] mux_opa, mux_opb, mux_opd;
|
wire [1:0] mux_opa, mux_opb, mux_opd;
|
|
|
// translate signals
|
// translate signals
|
wire [4:0] wRD, wRA, wRB;
|
wire [4:0] wRD, wRA, wRB;
|
wire [5:0] wOPC;
|
wire [5:0] wOPC;
|
wire [15:0] wIMM;
|
wire [15:0] wIMM;
|
wire [31:0] imm_if;
|
wire [31:0] imm_if;
|
|
|
assign {wOPC, wRD, wRA, wIMM} = (fINT) ? wINTOP : ich_dat;
|
assign {wOPC, wRD, wRA, wIMM} = (fINT) ? wINTOP : ich_dat;
|
assign wRB = wIMM[15:11];
|
assign wRB = wIMM[15:11];
|
|
|
// decode main opgroups
|
// decode main opgroups
|
|
|
//wire fSFT = (wOPC == 6'o44);
|
//wire fSFT = (wOPC == 6'o44);
|
//wire fLOG = ({wOPC[5:4],wOPC[2]} == 3'o4);
|
//wire fLOG = ({wOPC[5:4],wOPC[2]} == 3'o4);
|
wire fMUL = (wOPC == 6'o20) | (wOPC == 6'o30);
|
wire fMUL = (wOPC == 6'o20) | (wOPC == 6'o30);
|
wire fBSF = (wOPC == 6'o21) | (wOPC == 6'o31);
|
wire fBSF = (wOPC == 6'o21) | (wOPC == 6'o31);
|
//wire fDIV = (wOPC == 6'o22);
|
//wire fDIV = (wOPC == 6'o22);
|
wire fRTD = (wOPC == 6'o55);
|
wire fRTD = (wOPC == 6'o55);
|
wire fBCC = (wOPC == 6'o47) | (wOPC == 6'o57);
|
wire fBCC = (wOPC == 6'o47) | (wOPC == 6'o57);
|
wire fBRU = (wOPC == 6'o46) | (wOPC == 6'o56);
|
wire fBRU = (wOPC == 6'o46) | (wOPC == 6'o56);
|
//wire fBRA = fBRU & wRA[3];
|
//wire fBRA = fBRU & wRA[3];
|
wire fIMM = (wOPC == 6'o54);
|
wire fIMM = (wOPC == 6'o54);
|
wire fMOV = (wOPC == 6'o45);
|
wire fMOV = (wOPC == 6'o45);
|
wire fLOD = ({wOPC[5:4],wOPC[2]} == 3'o6);
|
wire fLOD = ({wOPC[5:4],wOPC[2]} == 3'o6);
|
wire fSTR = ({wOPC[5:4],wOPC[2]} == 3'o7);
|
wire fSTR = ({wOPC[5:4],wOPC[2]} == 3'o7);
|
//wire fLDST = (wOPC[5:4] == 2'o3);
|
//wire fLDST = (wOPC[5:4] == 2'o3);
|
//wire fPUT = (wOPC == 6'o33) & wRB[4];
|
//wire fPUT = (wOPC == 6'o33) & wRB[4];
|
wire fGET = (wOPC == 6'o33) & !wRB[4];
|
wire fGET = (wOPC == 6'o33) & !wRB[4];
|
|
|
|
|
// control signals
|
// control signals
|
localparam [2:0] MUX_SFR = 3'o7,
|
localparam [2:0] MUX_SFR = 3'o7,
|
MUX_BSF = 3'o6,
|
MUX_BSF = 3'o6,
|
MUX_MUL = 3'o5,
|
MUX_MUL = 3'o5,
|
MUX_MEM = 3'o4,
|
MUX_MEM = 3'o4,
|
|
|
MUX_RPC = 3'o2,
|
MUX_RPC = 3'o2,
|
MUX_ALU = 3'o1,
|
MUX_ALU = 3'o1,
|
MUX_NOP = 3'o0;
|
MUX_NOP = 3'o0;
|
|
|
always @(posedge gclk)
|
always @(posedge gclk)
|
if (grst) begin
|
if (grst) begin
|
/*AUTORESET*/
|
/*AUTORESET*/
|
// Beginning of autoreset for uninitialized flops
|
// Beginning of autoreset for uninitialized flops
|
imm_of <= 16'h0;
|
imm_of <= 16'h0;
|
mux_of <= 3'h0;
|
mux_of <= 3'h0;
|
opc_of <= 6'h0;
|
opc_of <= 6'h0;
|
ra_of <= 5'h0;
|
ra_of <= 5'h0;
|
rd_of <= 5'h0;
|
rd_of <= 5'h0;
|
// End of automatics
|
// End of automatics
|
end else if (dena) begin
|
end else if (dena) begin
|
|
|
mux_of <= #1
|
mux_of <= #1
|
(hzd_bpc | hzd_fwd | fSTR | fRTD | fBCC) ? MUX_NOP :
|
(hzd_bpc | hzd_fwd | fSTR | fRTD | fBCC) ? MUX_NOP :
|
(fLOD | fGET) ? MUX_MEM :
|
(fLOD | fGET) ? MUX_MEM :
|
(fMOV) ? MUX_SFR :
|
(fMOV) ? MUX_SFR :
|
(fMUL) ? MUX_MUL :
|
(fMUL) ? MUX_MUL :
|
(fBSF) ? MUX_BSF :
|
(fBSF) ? MUX_BSF :
|
(fBRU) ? MUX_RPC :
|
(fBRU) ? MUX_RPC :
|
MUX_ALU;
|
MUX_ALU;
|
|
|
opc_of <= #1
|
opc_of <= #1
|
(hzd_bpc | hzd_fwd) ? 6'o42 : // XOR (SKIP)
|
(hzd_bpc | hzd_fwd) ? 6'o42 : // XOR (SKIP)
|
wOPC;
|
wOPC;
|
|
|
rd_of <= #1 wRD;
|
rd_of <= #1 wRD;
|
ra_of <= #1 wRA;
|
ra_of <= #1 wRA;
|
imm_of <= #1 wIMM;
|
imm_of <= #1 wIMM;
|
|
|
end // if (dena)
|
end // if (dena)
|
|
|
// immediate implementation
|
// immediate implementation
|
reg [15:0] rIMM0, rIMM1;
|
reg [15:0] rIMM0, rIMM1;
|
reg rFIM0, rFIM1;
|
reg rFIM0, rFIM1;
|
//wire wFIMH = (gpha & AEMB_HTX[0]) ? rFIM1 : rFIM0;
|
//wire wFIMH = (gpha & AEMB_HTX[0]) ? rFIM1 : rFIM0;
|
//wire [15:0] wIMMH = (gpha & AEMB_HTX[0]) ? rIMM1 : rIMM0;
|
//wire [15:0] wIMMH = (gpha & AEMB_HTX[0]) ? rIMM1 : rIMM0;
|
|
|
assign imm_if[15:0] = wIMM;
|
assign imm_if[15:0] = wIMM;
|
assign imm_if[31:16] = (rFIM1) ? rIMM1 :
|
assign imm_if[31:16] = (rFIM1) ? rIMM1 :
|
{(16){wIMM[15]}};
|
{(16){wIMM[15]}};
|
|
|
// BARREL IMM
|
// BARREL IMM
|
always @(posedge gclk)
|
always @(posedge gclk)
|
if (grst) begin
|
if (grst) begin
|
/*AUTORESET*/
|
/*AUTORESET*/
|
// Beginning of autoreset for uninitialized flops
|
// Beginning of autoreset for uninitialized flops
|
rFIM0 <= 1'h0;
|
rFIM0 <= 1'h0;
|
rFIM1 <= 1'h0;
|
rFIM1 <= 1'h0;
|
rIMM0 <= 16'h0;
|
rIMM0 <= 16'h0;
|
rIMM1 <= 16'h0;
|
rIMM1 <= 16'h0;
|
// End of automatics
|
// End of automatics
|
end else if (dena) begin
|
end else if (dena) begin
|
rFIM1 <= #1 rFIM0;
|
rFIM1 <= #1 rFIM0;
|
rFIM0 <= #1 fIMM & !hzd_bpc;
|
rFIM0 <= #1 fIMM & !hzd_bpc;
|
|
|
rIMM1 <= #1 rIMM0;
|
rIMM1 <= #1 rIMM0;
|
rIMM0 <= #1 wIMM;
|
rIMM0 <= #1 wIMM;
|
end
|
end
|
|
|
assign fINT = brk_if[0] & gpha & !rFIM1;
|
assign fINT = brk_if[0] & gpha & !rFIM1;
|
|
|
// operand latch
|
// operand latch
|
reg wrb_ex;
|
reg wrb_ex;
|
reg fwd_ex;
|
reg fwd_ex;
|
reg [2:0] mux_mx;
|
reg [2:0] mux_mx;
|
|
|
wire opb_fwd, opa_fwd, opd_fwd;
|
wire opb_fwd, opa_fwd, opd_fwd;
|
|
|
assign mux_opb = {wOPC[3], opb_fwd};
|
assign mux_opb = {wOPC[3], opb_fwd};
|
assign opb_fwd = ((wRB ^ rd_ex) == 5'd0) & // RB forwarding needed
|
assign opb_fwd = ((wRB ^ rd_ex) == 5'd0) & // RB forwarding needed
|
fwd_ex & wrb_ex;
|
fwd_ex & wrb_ex;
|
|
|
assign mux_opa = {(fBRU|fBCC), opa_fwd};
|
assign mux_opa = {(fBRU|fBCC), opa_fwd};
|
assign opa_fwd = ((wRA ^ rd_ex) == 5'd0) & // RA forwarding needed
|
assign opa_fwd = ((wRA ^ rd_ex) == 5'd0) & // RA forwarding needed
|
fwd_ex & wrb_ex;
|
fwd_ex & wrb_ex;
|
|
|
assign mux_opd = {fBCC, opd_fwd};
|
assign mux_opd = {fBCC, opd_fwd};
|
assign opd_fwd = (( ((wRA ^ rd_ex) == 5'd0) & fBCC) | // RA forwarding
|
assign opd_fwd = (( ((wRA ^ rd_ex) == 5'd0) & fBCC) | // RA forwarding
|
( ((wRD ^ rd_ex) == 5'd0) & fSTR)) & // RD forwarding
|
( ((wRD ^ rd_ex) == 5'd0) & fSTR)) & // RD forwarding
|
fwd_ex & wrb_ex;
|
fwd_ex & wrb_ex;
|
|
|
always @(posedge gclk)
|
always @(posedge gclk)
|
if (grst) begin
|
if (grst) begin
|
/*AUTORESET*/
|
/*AUTORESET*/
|
// Beginning of autoreset for uninitialized flops
|
// Beginning of autoreset for uninitialized flops
|
fwd_ex <= 1'h0;
|
fwd_ex <= 1'h0;
|
mux_ex <= 3'h0;
|
mux_ex <= 3'h0;
|
mux_mx <= 3'h0;
|
mux_mx <= 3'h0;
|
rd_ex <= 5'h0;
|
rd_ex <= 5'h0;
|
wrb_ex <= 1'h0;
|
wrb_ex <= 1'h0;
|
// End of automatics
|
// End of automatics
|
end else if (dena) begin
|
end else if (dena) begin
|
wrb_ex <= #1 |rd_of & |mux_of; // FIXME: check mux
|
wrb_ex <= #1 |rd_of & |mux_of; // FIXME: check mux
|
fwd_ex <= #1 |mux_of; // FIXME: check mux
|
fwd_ex <= #1 |mux_of; // FIXME: check mux
|
|
|
mux_mx <= #1 mux_ex;
|
mux_mx <= #1 mux_ex;
|
mux_ex <= #1 mux_of;
|
mux_ex <= #1 mux_of;
|
rd_ex <= #1 rd_of;
|
rd_ex <= #1 rd_of;
|
end
|
end
|
|
|
always @(posedge gclk)
|
always @(posedge gclk)
|
if (grst) begin
|
if (grst) begin
|
/*AUTORESET*/
|
/*AUTORESET*/
|
// Beginning of autoreset for uninitialized flops
|
// Beginning of autoreset for uninitialized flops
|
opa_of <= 32'h0;
|
opa_of <= 32'h0;
|
opb_of <= 32'h0;
|
opb_of <= 32'h0;
|
opd_of <= 32'h0;
|
opd_of <= 32'h0;
|
// End of automatics
|
// End of automatics
|
|
|
end else if (dena) begin
|
end else if (dena) begin
|
|
|
case (mux_opd)
|
case (mux_opd)
|
2'o2: opd_of <= #1 opa_if; // BCC
|
2'o2: opd_of <= #1 opa_if; // BCC
|
2'o1: opd_of <= #1 alu_ex; // FWD
|
2'o1: opd_of <= #1 alu_ex; // FWD
|
2'o0: opd_of <= #1 opd_if; // SXX
|
2'o0: opd_of <= #1 opd_if; // SXX
|
2'o3: opd_of <= #1 alu_ex; // FWD
|
2'o3: opd_of <= #1 alu_ex; // FWD
|
endcase // case (mux_opd)
|
endcase // case (mux_opd)
|
|
|
case (mux_opb)
|
case (mux_opb)
|
2'o0: opb_of <= #1 opb_if;
|
2'o0: opb_of <= #1 opb_if;
|
2'o1: opb_of <= #1 alu_ex;
|
2'o1: opb_of <= #1 alu_ex;
|
2'o2: opb_of <= #1 imm_if;
|
2'o2: opb_of <= #1 imm_if;
|
2'o3: opb_of <= #1 imm_if;
|
2'o3: opb_of <= #1 imm_if;
|
endcase // case (mux_opb)
|
endcase // case (mux_opb)
|
|
|
case (mux_opa)
|
case (mux_opa)
|
2'o0: opa_of <= #1 opa_if;
|
2'o0: opa_of <= #1 opa_if;
|
2'o1: opa_of <= #1 alu_ex;
|
2'o1: opa_of <= #1 alu_ex;
|
2'o2: opa_of <= #1 {rpc_if, 2'o0};
|
2'o2: opa_of <= #1 {rpc_if, 2'o0};
|
2'o3: opa_of <= #1 {rpc_if, 2'o0};
|
2'o3: opa_of <= #1 {rpc_if, 2'o0};
|
endcase // case (mux_opa)
|
endcase // case (mux_opa)
|
|
|
end // if (dena)
|
end // if (dena)
|
|
|
// Hazard Detection
|
// Hazard Detection
|
//wire wFMUL = (mux_ex == MUX_MUL);
|
//wire wFMUL = (mux_ex == MUX_MUL);
|
//wire wFBSF = (mux_ex == MUX_BSF);
|
//wire wFBSF = (mux_ex == MUX_BSF);
|
//wire wFMEM = (mux_ex == MUX_MEM);
|
//wire wFMEM = (mux_ex == MUX_MEM);
|
//wire wFMOV = (mux_ex == MUX_SFR);
|
//wire wFMOV = (mux_ex == MUX_SFR);
|
|
|
assign hzd_fwd = (opd_fwd | opa_fwd | opb_fwd) & mux_ex[2];
|
assign hzd_fwd = (opd_fwd | opa_fwd | opb_fwd) & mux_ex[2];
|
//(wFMUL | wFBSF | wFMEM | wFMOV);
|
//(wFMUL | wFBSF | wFMEM | wFMOV);
|
assign hzd_bpc = (bra_ex[1] & !bra_ex[0]);
|
assign hzd_bpc = (bra_ex[1] & !bra_ex[0]);
|
|
|
endmodule // aeMB2_ctrl
|
endmodule // aeMB2_ctrl
|
|
|
/*
|
/*
|
$Log: not supported by cvs2svn $
|
$Log: not supported by cvs2svn $
|
Revision 1.6 2008/05/01 08:32:58 sybreon
|
Revision 1.6 2008/05/01 08:32:58 sybreon
|
Added interrupt capability.
|
Added interrupt capability.
|
|
|
Revision 1.5 2008/04/28 08:15:25 sybreon
|
Revision 1.5 2008/04/28 08:15:25 sybreon
|
Optimisations.
|
Optimisations.
|
|
|
Revision 1.4 2008/04/26 17:57:43 sybreon
|
Revision 1.4 2008/04/26 17:57:43 sybreon
|
Minor performance improvements.
|
Minor performance improvements.
|
|
|
Revision 1.3 2008/04/26 01:09:05 sybreon
|
Revision 1.3 2008/04/26 01:09:05 sybreon
|
Passes basic tests. Minor documentation changes to make it compatible with iverilog pre-processor.
|
Passes basic tests. Minor documentation changes to make it compatible with iverilog pre-processor.
|
|
|
Revision 1.2 2008/04/20 16:34:32 sybreon
|
Revision 1.2 2008/04/20 16:34:32 sybreon
|
Basic version with some features left out.
|
Basic version with some features left out.
|
|
|
Revision 1.1 2008/04/18 00:21:52 sybreon
|
Revision 1.1 2008/04/18 00:21:52 sybreon
|
Initial import.
|
Initial import.
|
|
|