`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
// ============================================================================
|
// ============================================================================
|
// __
|
// __
|
// \\__/ o\ (C) 2011-2013 Robert Finch, Stratford
|
// \\__/ o\ (C) 2011-2013 Robert Finch, Stratford
|
// \ __ / All rights reserved.
|
// \ __ / All rights reserved.
|
// \/_// robfinch<remove>@opencores.org
|
// \/_// robfinch<remove>@opencores.org
|
// ||
|
// ||
|
//
|
//
|
// Raptor64sc.v
|
// Raptor64sc.v
|
// - 64 bit CPU
|
// - 64 bit CPU
|
//
|
//
|
// 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/>.
|
//
|
//
|
// 15848 LUT's / 3591 ff's / 48.215 MHz
|
// 15848 LUT's / 3591 ff's / 48.215 MHz
|
// 29 Block RAMs
|
// 29 Block RAMs
|
// ============================================================================
|
// ============================================================================
|
//
|
//
|
//`define ADDRESS_RESERVATION 1
|
//`define ADDRESS_RESERVATION 1
|
//`define FLOATING_POINT 1
|
//`define FLOATING_POINT 1
|
//`define BTB 1
|
//`define BTB 1
|
//`define TLB 1
|
//`define TLB 1
|
//`define SIMD 1
|
//`define SIMD 1
|
`define SEGMENTATION 1
|
`define SEGMENTATION 1
|
|
`define SIMPLE_MMU 1
|
|
|
`define RESET_VECTOR 64'hFFFF_FFFF_FFFF_FFF0
|
`define RESET_VECTOR 64'hFFFF_FFFF_FFFF_FFF0
|
|
|
`define EX_NON 9'd000
|
`define EX_NON 9'd000
|
`define EX_TRAP 9'd32 // Trap exception
|
`define EX_TRAP 9'd32 // Trap exception
|
`define EX_IRQ 9'd448 // base IRQ interrupt
|
`define EX_IRQ 9'd448 // base IRQ interrupt
|
`define EX_DBZ 9'd488 // divide by zero
|
`define EX_DBZ 9'd488 // divide by zero
|
`define EX_OFL 9'd489 // overflow
|
`define EX_OFL 9'd489 // overflow
|
`define EX_UNIMP_INSN 9'd495 // unimplemented instruction
|
`define EX_UNIMP_INSN 9'd495 // unimplemented instruction
|
`define EX_PRIV 9'd496 // priviledge violation
|
`define EX_PRIV 9'd496 // priviledge violation
|
`define EX_TLBD 9'd506 // TLB exception - data
|
`define EX_TLBD 9'd506 // TLB exception - data
|
`define EX_TLBI 9'd507 // TLB exception - ifetch
|
`define EX_TLBI 9'd507 // TLB exception - ifetch
|
`define EX_DBERR 9'd508 // Bus Error - load or store or I/O
|
`define EX_DBERR 9'd508 // Bus Error - load or store or I/O
|
`define EX_IBERR 9'd509 // Bus Error - instruction fetch
|
`define EX_IBERR 9'd509 // Bus Error - instruction fetch
|
`define EX_NMI 9'd510 // non-maskable interrupt
|
`define EX_NMI 9'd510 // non-maskable interrupt
|
`define EX_RST 9'd511 // Reset
|
`define EX_RST 9'd511 // Reset
|
|
|
`include "Raptor64_opcodes.v"
|
`include "Raptor64_opcodes.v"
|
|
|
module Raptor64sc(rst_i, clk_i, nmi_i, irq_i, irq_no, bte_o, cti_o, bl_o, iocyc_o,
|
module Raptor64sc(rst_i, clk_i, nmi_i, irq_i, irq_no, bte_o, cti_o, bl_o, iocyc_o,
|
cyc_o, stb_o, ack_i, err_i, we_o, sel_o, rsv_o, adr_o, dat_i, dat_o, sys_adv, sys_adr,
|
cyc_o, stb_o, ack_i, err_i, we_o, sel_o, rsv_o, adr_o, dat_i, dat_o, sys_adv, sys_adr
|
advanceI, advanceR, advanceX, advanceM1, advanceM2, advanceW, advanceT
|
|
);
|
);
|
parameter IDLE = 5'd1;
|
parameter IDLE = 5'd1;
|
parameter ICACT = 5'd2;
|
parameter ICACT = 5'd2;
|
parameter ICACT1 = 5'd4;
|
parameter ICACT1 = 5'd4;
|
parameter ICACT2 = 5'd5;
|
parameter ICACT2 = 5'd5;
|
parameter DCIDLE = 5'd20;
|
parameter DCIDLE = 5'd20;
|
parameter DCACT = 5'd21;
|
parameter DCACT = 5'd21;
|
parameter AMSB = 31;
|
parameter AMSB = 31;
|
parameter RESET = 4'd0;
|
parameter RESET = 4'd0;
|
parameter RUN = 4'd1;
|
parameter RUN = 4'd1;
|
input rst_i;
|
input rst_i;
|
input clk_i;
|
input clk_i;
|
input nmi_i;
|
input nmi_i;
|
input irq_i;
|
input irq_i;
|
input [8:0] irq_no;
|
input [8:0] irq_no;
|
|
|
output [1:0] bte_o; // burst type
|
output [1:0] bte_o; // burst type
|
reg [1:0] bte_o;
|
reg [1:0] bte_o;
|
output [2:0] cti_o; // cycle type
|
output [2:0] cti_o; // cycle type
|
reg [2:0] cti_o;
|
reg [2:0] cti_o;
|
output [4:0] bl_o; // burst length (non-WISHBONE)
|
output [4:0] bl_o; // burst length (non-WISHBONE)
|
reg [4:0] bl_o;
|
reg [4:0] bl_o;
|
output iocyc_o; // I/O cycle is valid
|
output iocyc_o; // I/O cycle is valid
|
reg iocyc_o;
|
reg iocyc_o;
|
output cyc_o; // cycle is valid
|
output cyc_o; // cycle is valid
|
reg cyc_o;
|
reg cyc_o;
|
output stb_o; // data strobe
|
output stb_o; // data strobe
|
reg stb_o;
|
reg stb_o;
|
input ack_i; // data transfer acknowledge
|
input ack_i; // data transfer acknowledge
|
input err_i; // bus error
|
input err_i; // bus error
|
output we_o; // write enable
|
output we_o; // write enable
|
reg we_o;
|
reg we_o;
|
output [7:0] sel_o; // byte lane selects
|
output [7:0] sel_o; // byte lane selects
|
reg [7:0] sel_o;
|
reg [7:0] sel_o;
|
output rsv_o; // reserve the address (non-WISHBONE)
|
output rsv_o; // reserve the address (non-WISHBONE)
|
reg rsv_o;
|
reg rsv_o;
|
output [63:0] adr_o; // address
|
output [63:0] adr_o; // address
|
reg [63:0] adr_o;
|
reg [63:0] adr_o;
|
input [63:0] dat_i; // data input
|
input [63:0] dat_i; // data input
|
output [63:0] dat_o; // data output
|
output [63:0] dat_o; // data output
|
reg [63:0] dat_o;
|
reg [63:0] dat_o;
|
|
|
input sys_adv;
|
input sys_adv;
|
input [63:5] sys_adr;
|
input [63:5] sys_adr;
|
|
|
output advanceI;
|
|
output advanceR;
|
|
output advanceX;
|
|
output advanceM1;
|
|
output advanceM2;
|
|
output advanceW;
|
|
output advanceT;
|
|
|
|
wire clk;
|
wire clk;
|
reg [3:0] state;
|
reg [3:0] state;
|
reg [5:0] fltctr;
|
reg [5:0] fltctr;
|
wire fltdone = fltctr==6'd0;
|
wire fltdone = fltctr==6'd0;
|
|
reg inta;
|
reg bu_im; // interrupt mask
|
reg bu_im; // interrupt mask
|
reg im1; // temporary interrupt mask for LM/SM
|
reg im1; // temporary interrupt mask for LM/SM
|
reg [7:0] ie_fuse; // interrupt enable fuse
|
reg [7:0] ie_fuse; // interrupt enable fuse
|
wire im = ~ie_fuse[7];
|
wire im = ~ie_fuse[7];
|
reg [1:0] rm; // fp rounding mode
|
reg [1:0] rm; // fp rounding mode
|
reg FXE; // fp exception enable
|
reg FXE; // fp exception enable
|
wire KernelMode;
|
wire KernelMode;
|
wire [31:0] sr = {bu_im,15'd0,im,1'b0,KernelMode,FXE,2'b00,10'b0};
|
wire [31:0] sr = {bu_im,15'd0,im,1'b0,KernelMode,FXE,2'b00,10'b0};
|
reg [31:0] dIR,d1IR,xIR,m1IR,m2IR,wIR;
|
reg [31:0] dIR,d1IR,xIR,m1IR,m2IR,wIR;
|
reg [31:0] ndIR; // next dIR
|
reg [31:0] ndIR; // next dIR
|
reg [63:0] pc; // ipc
|
reg [63:0] pc; // ipc
|
wire [63:0] pchistoric;
|
wire [63:0] pchistoric;
|
reg pccap; // flag 1=capture PC history
|
reg pccap; // flag 1=capture PC history
|
reg [63:0] ErrorEPC;
|
reg [63:0] ErrorEPC;
|
reg [63:0] EPC [0:15]; // Exception return address
|
reg [63:0] EPC [0:15]; // Exception return address
|
reg [63:0] IPC [0:15]; // Interrupt return address
|
reg [63:0] IPC [0:15]; // Interrupt return address
|
`ifdef SEGMENTATION
|
`ifdef SEGMENTATION
|
reg [63:16] CS [0:15]; // Code segment
|
reg [63:12] segs [0:255];
|
reg [63:16] DS [0:15]; // Data segment
|
|
reg [63:16] SS [0:15]; // Stack segment
|
|
reg [63:16] ES [0:15]; // BSS segment
|
|
`endif
|
`endif
|
reg dStatusHWI,xStatusHWI,m1StatusHWI,m2StatusHWI;
|
reg dStatusHWI,xStatusHWI,m1StatusHWI,m2StatusHWI;
|
reg dIm,xIm,m1Im,m2Im;
|
reg dIm,xIm,m1Im,m2Im;
|
reg dNmi,xNmi,m1Nmi,m2Nmi,wNmi;
|
reg dNmi,xNmi,m1Nmi,m2Nmi,wNmi;
|
reg [15:0] StatusEXL; // 1= context in exception state
|
reg [15:0] StatusEXL; // 1= context in exception state
|
reg [63:0] dpc,d1pc,xpc,m1pc,m2pc,wpc; // PC's associated with instruction in pipeline
|
reg [63:0] dpc,d1pc,xpc,m1pc,m2pc,wpc; // PC's associated with instruction in pipeline
|
wire [63:0] rfoa,rfob,rfoc; // register file outputs
|
wire [63:0] rfoa,rfob,rfoc; // register file outputs
|
wire [8:0] dRa,dRb,dRc;
|
wire [8:0] dRa,dRb,dRc;
|
reg [8:0] xRt,wRt,m1Rt,m2Rt,tRt; // target register
|
reg [8:0] xRt,wRt,m1Rt,m2Rt,tRt; // target register
|
reg [63:0] ea; // effective data address
|
reg [63:0] ea; // effective data address
|
reg [4:0] cstate; // cache state
|
reg [4:0] cstate; // cache state
|
reg dbranch_taken,xbranch_taken; // flag: 1=branch taken
|
reg dbranch_taken,xbranch_taken; // flag: 1=branch taken
|
reg [63:0] mutex_gate;
|
reg [63:0] mutex_gate;
|
reg [63:0] TBA; // Trap Base Address
|
reg [63:0] TBA; // Trap Base Address
|
reg [8:0] dextype,d1extype,xextype,m1extype,m2extype,wextype,textype;
|
reg [8:0] dextype,d1extype,xextype,m1extype,m2extype,wextype,textype;
|
reg [3:0] epat [0:255];
|
reg [3:0] epat [0:255]; // execution pattern table
|
reg [7:0] eptr;
|
reg [7:0] eptr;
|
reg [3:0] dAXC,d1AXC,xAXC,m1AXC,m2AXC,wAXC; // context active per pipeline stage
|
reg [3:0] dAXC,d1AXC,xAXC,m1AXC,m2AXC,wAXC; // context active per pipeline stage
|
wire [3:0] AXC = (eptr==8'h00) ? 4'h0 : epat[eptr];
|
wire [3:0] AXC = (eptr==8'h00) ? 4'h0 : epat[eptr];
|
reg dtinit; // 1=data cache tags are being intialized
|
reg dtinit; // 1=data cache tags are being intialized
|
reg dcache_on; // 1= data cache is enabled
|
reg dcache_on; // 1= data cache is enabled
|
wire [63:0] cdat; // data cache output
|
wire [63:0] cdat; // data cache output
|
reg [63:32] nonICacheSeg;
|
reg [63:32] nonICacheSeg;
|
reg [1:0] FPC_rm; // fp: rounding mode
|
reg [1:0] FPC_rm; // fp: rounding mode
|
reg FPC_SL; // result is negative (and non-zero)
|
reg FPC_SL; // result is negative (and non-zero)
|
reg FPC_SE; // result is zero
|
reg FPC_SE; // result is zero
|
reg FPC_SG; // result is positive (and non-zero)
|
reg FPC_SG; // result is positive (and non-zero)
|
reg FPC_SI; // result is infinite or NaN
|
reg FPC_SI; // result is infinite or NaN
|
reg FPC_overx;
|
reg FPC_overx;
|
reg fp_iop;
|
reg fp_iop;
|
reg fp_ovr;
|
reg fp_ovr;
|
reg fp_uf;
|
reg fp_uf;
|
wire [31:0] FPC = {FPC_rm,1'b0,
|
wire [31:0] FPC = {FPC_rm,1'b0,
|
9'd0,
|
9'd0,
|
FPC_SL,
|
FPC_SL,
|
FPC_SG,
|
FPC_SG,
|
FPC_SE,
|
FPC_SE,
|
FPC_SI,
|
FPC_SI,
|
16'd0
|
16'd0
|
};
|
};
|
reg [63:0] wr_addr;
|
reg [63:0] wr_addr;
|
reg [31:0] insn;
|
reg [31:0] insn;
|
reg clk_en;
|
reg clk_en;
|
reg cpu_clk_en;
|
reg cpu_clk_en;
|
reg StatusERL; // 1= in error processing
|
reg StatusERL; // 1= in error processing
|
//reg StatusEXL; // 1= in exception processing
|
//reg StatusEXL; // 1= in exception processing
|
reg StatusHWI; // 1= in interrupt processing
|
reg StatusHWI; // 1= in interrupt processing
|
reg StatusUM; // 1= user mode
|
reg StatusUM; // 1= user mode
|
reg [7:0] ASID; // address space identifier (process ID)
|
reg [7:0] ASID; // address space identifier (process ID)
|
integer n;
|
integer n;
|
reg [63:13] BadVAddr;
|
reg [63:13] BadVAddr;
|
reg [63:13] PageTableAddr;
|
reg [63:13] PageTableAddr;
|
reg [63:0] errorAddress;
|
reg [63:0] errorAddress;
|
|
wire mmu_ack;
|
|
wire [15:0] mmu_dato;
|
|
wire ack_i1 = ack_i | mmu_ack;
|
|
wire [63:0] dat_i1 = dat_i|{4{mmu_dato}};
|
|
|
wire [6:0] iOpcode = insn[31:25];
|
wire [6:0] iOpcode = insn[31:25];
|
wire [6:0] iFunc = insn[6:0];
|
wire [6:0] iFunc = insn[6:0];
|
wire [5:0] iFunc6 = insn[5:0];
|
wire [5:0] iFunc6 = insn[5:0];
|
wire [6:0] dOpcode = dIR[31:25];
|
wire [6:0] dOpcode = dIR[31:25];
|
wire [6:0] dFunc = dIR[6:0];
|
wire [6:0] dFunc = dIR[6:0];
|
wire [5:0] dFunc6 = dIR[5:0];
|
wire [5:0] dFunc6 = dIR[5:0];
|
wire [6:0] xOpcode = xIR[31:25];
|
wire [6:0] xOpcode = xIR[31:25];
|
wire [6:0] xFunc = xIR[6:0];
|
wire [6:0] xFunc = xIR[6:0];
|
wire [5:0] xFunc6 = xIR[5:0];
|
wire [5:0] xFunc6 = xIR[5:0];
|
wire [4:0] xFunc5 = xIR[4:0];
|
wire [4:0] xFunc5 = xIR[4:0];
|
wire [6:0] m1Opcode,m2Opcode,wOpcode;
|
wire [6:0] m1Opcode,m2Opcode,wOpcode;
|
assign m1Opcode = m1IR[31:25];
|
assign m1Opcode = m1IR[31:25];
|
assign m2Opcode = m2IR[31:25];
|
assign m2Opcode = m2IR[31:25];
|
assign wOpcode = wIR[31:25];
|
assign wOpcode = wIR[31:25];
|
wire [6:0] m1Func,m2Func,wFunc;
|
wire [6:0] m1Func,m2Func,wFunc;
|
assign m1Func = m1IR[6:0];
|
assign m1Func = m1IR[6:0];
|
assign m2Func = m2IR[6:0];
|
assign m2Func = m2IR[6:0];
|
assign wFunc = wIR[6:0];
|
assign wFunc = wIR[6:0];
|
wire [5:0] m1Func6 = m1Func[5:0];
|
wire [5:0] m1Func6 = m1Func[5:0];
|
wire [5:0] m2Func6 = m2Func[5:0];
|
wire [5:0] m2Func6 = m2Func[5:0];
|
wire [5:0] wFunc6 = wIR[5:0];
|
wire [5:0] wFunc6 = wIR[5:0];
|
reg [63:0] m1Data,m2Data,wData,tData;
|
reg [63:0] m1Data,m2Data,wData,tData;
|
reg [63:0] m2Addr;
|
reg [63:0] m2Addr;
|
reg [63:0] tick;
|
reg [63:0] tick;
|
reg [63:0] a,b,c,imm,m1b;
|
reg [63:0] a,b,c,imm,m1b;
|
wire [1:0] scale = xIR[9:8];
|
wire [1:0] scale = xIR[9:8];
|
wire [1:0] offset2 = xIR[7:6];
|
wire [1:0] offset2 = xIR[7:6];
|
reg rsf; // reserrved address flag
|
reg rsf; // reserrved address flag
|
reg [63:5] resv_address; // reserved address
|
reg [63:5] resv_address; // reserved address
|
reg dirqf,rirqf,m1irqf,m2irqf,wirqf,tirqf;
|
reg dirqf,rirqf,m1irqf,m2irqf,wirqf,tirqf;
|
reg xirqf;
|
reg xirqf;
|
wire advanceX_edge;
|
wire advanceX_edge;
|
wire takb;
|
wire takb;
|
wire advanceI,advanceR,advanceR1,advanceX,advanceM1,advanceW,advanceT; // Pipeline advance signals
|
wire advanceI,advanceR,advanceR1,advanceX,advanceM1,advanceW,advanceT; // Pipeline advance signals
|
reg m1clkoff,m2clkoff,m3clkoff,m4clkoff,wclkoff;
|
reg m1clkoff,m2clkoff,m3clkoff,m4clkoff,wclkoff;
|
reg dFip,d1Fip,xFip,m1Fip,m2Fip,m3Fip,m4Fip,wFip;
|
reg dFip,d1Fip,xFip,m1Fip,m2Fip,m3Fip,m4Fip,wFip;
|
reg cyc1;
|
reg cyc1;
|
reg LoadNOPs;
|
reg LoadNOPs;
|
reg m1IsLoad,m1IsStore;
|
reg m1IsLoad,m1IsStore;
|
reg m2IsLoad,m2IsStore;
|
reg m2IsLoad,m2IsStore;
|
reg wIsStore;
|
reg wIsStore;
|
reg m1IsOut,m1IsIn;
|
reg m1IsOut,m1IsIn;
|
|
|
function [63:0] fnIncPC;
|
function [63:0] fnIncPC;
|
input [63:0] fpc;
|
input [63:0] fpc;
|
begin
|
begin
|
fnIncPC = fpc + 64'd4;
|
fnIncPC = fpc + 64'd4;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
function [7:0] fnSelect;
|
function [7:0] fnSelect;
|
input [6:0] opcode;
|
input [6:0] opcode;
|
input [2:0] addr;
|
input [2:0] addr;
|
case(opcode)
|
case(opcode)
|
`LBU,`LB,`SB,`INB,`INBU,`OUTB:
|
`LBU,`LB,`SB,`INB,`INBU,`OUTB:
|
case(addr)
|
case(addr)
|
3'b000: fnSelect = 8'b00000001;
|
3'b000: fnSelect = 8'b00000001;
|
3'b001: fnSelect = 8'b00000010;
|
3'b001: fnSelect = 8'b00000010;
|
3'b010: fnSelect = 8'b00000100;
|
3'b010: fnSelect = 8'b00000100;
|
3'b011: fnSelect = 8'b00001000;
|
3'b011: fnSelect = 8'b00001000;
|
3'b100: fnSelect = 8'b00010000;
|
3'b100: fnSelect = 8'b00010000;
|
3'b101: fnSelect = 8'b00100000;
|
3'b101: fnSelect = 8'b00100000;
|
3'b110: fnSelect = 8'b01000000;
|
3'b110: fnSelect = 8'b01000000;
|
3'b111: fnSelect = 8'b10000000;
|
3'b111: fnSelect = 8'b10000000;
|
endcase
|
endcase
|
`LC,`LCU,`SC,`INCH,`INCU,`OUTC:
|
`LC,`LCU,`SC,`INCH,`INCU,`OUTC:
|
case(addr[2:1])
|
case(addr[2:1])
|
2'b00: fnSelect = 8'b00000011;
|
2'b00: fnSelect = 8'b00000011;
|
2'b01: fnSelect = 8'b00001100;
|
2'b01: fnSelect = 8'b00001100;
|
2'b10: fnSelect = 8'b00110000;
|
2'b10: fnSelect = 8'b00110000;
|
2'b11: fnSelect = 8'b11000000;
|
2'b11: fnSelect = 8'b11000000;
|
endcase
|
endcase
|
`LHU,`LH,`SH,`LSH,`LF,`LFP,`SF,`SFP,`SSH,`INH,`INHU,`OUTH:
|
`LHU,`LH,`SH,`LSH,`LF,`LFP,`SF,`SFP,`SSH,`INH,`INHU,`OUTH:
|
case(addr[2])
|
case(addr[2])
|
1'b0: fnSelect = 8'b00001111;
|
1'b0: fnSelect = 8'b00001111;
|
1'b1: fnSelect = 8'b11110000;
|
1'b1: fnSelect = 8'b11110000;
|
endcase
|
endcase
|
`LW,`LWR,`LM,`LFD,`LSW,`LP,`LFDP,
|
`LW,`LWR,`LM,`LFD,`LSW,`LP,`LFDP,
|
`SW,`SM,`SFD,`SSW,`SWC,`SP,`SFDP,`INW,`OUTW:
|
`SW,`SM,`SFD,`SSW,`SWC,`SP,`SFDP,`INW,`OUTW:
|
fnSelect = 8'b11111111;
|
fnSelect = 8'b11111111;
|
endcase
|
endcase
|
endfunction
|
endfunction
|
|
|
reg [7:0] data8;
|
reg [7:0] data8;
|
reg [15:0] data16;
|
reg [15:0] data16;
|
reg [31:0] data32;
|
reg [31:0] data32;
|
reg [63:0] data64;
|
reg [63:0] data64;
|
|
|
always @(sel_o or dat_i)
|
always @(sel_o or dat_i1)
|
case(sel_o)
|
case(sel_o)
|
8'b00000001: data8 <= #1 dat_i[ 7: 0];
|
8'b00000001: data8 <= #1 dat_i1[ 7: 0];
|
8'b00000010: data8 <= #1 dat_i[15: 8];
|
8'b00000010: data8 <= #1 dat_i1[15: 8];
|
8'b00000100: data8 <= #1 dat_i[23:16];
|
8'b00000100: data8 <= #1 dat_i1[23:16];
|
8'b00001000: data8 <= #1 dat_i[31:24];
|
8'b00001000: data8 <= #1 dat_i1[31:24];
|
8'b00010000: data8 <= #1 dat_i[39:32];
|
8'b00010000: data8 <= #1 dat_i1[39:32];
|
8'b00100000: data8 <= #1 dat_i[47:40];
|
8'b00100000: data8 <= #1 dat_i1[47:40];
|
8'b01000000: data8 <= #1 dat_i[55:48];
|
8'b01000000: data8 <= #1 dat_i1[55:48];
|
8'b10000000: data8 <= #1 dat_i[63:56];
|
8'b10000000: data8 <= #1 dat_i1[63:56];
|
default: data8 <= 8'h00;
|
default: data8 <= 8'h00;
|
endcase
|
endcase
|
|
|
always @(sel_o or dat_i)
|
always @(sel_o or dat_i1)
|
case(sel_o)
|
case(sel_o)
|
8'b00000011: data16 <= #1 dat_i[15: 0];
|
8'b00000011: data16 <= #1 dat_i1[15: 0];
|
8'b00001100: data16 <= #1 dat_i[31:16];
|
8'b00001100: data16 <= #1 dat_i1[31:16];
|
8'b00110000: data16 <= #1 dat_i[47:32];
|
8'b00110000: data16 <= #1 dat_i1[47:32];
|
8'b11000000: data16 <= #1 dat_i[63:48];
|
8'b11000000: data16 <= #1 dat_i1[63:48];
|
default: data16 <= #1 16'hDEAD;
|
default: data16 <= #1 16'hDEAD;
|
endcase
|
endcase
|
|
|
always @(sel_o or dat_i)
|
always @(sel_o or dat_i1)
|
case(sel_o)
|
case(sel_o)
|
8'b00001111: data32 <= #1 dat_i[31: 0];
|
8'b00001111: data32 <= #1 dat_i1[31: 0];
|
8'b11110000: data32 <= #1 dat_i[63:32];
|
8'b11110000: data32 <= #1 dat_i1[63:32];
|
default: data32 <= #1 32'hDEADDEAD;
|
default: data32 <= #1 32'hDEADDEAD;
|
endcase
|
endcase
|
|
|
always @(sel_o or dat_i)
|
always @(sel_o or dat_i1)
|
data64 <= #1 dat_i;
|
data64 <= #1 dat_i1;
|
|
|
assign KernelMode = StatusEXL[xAXC]|StatusHWI;
|
assign KernelMode = StatusEXL[xAXC]|StatusHWI;
|
|
|
//wire iIsLSPair = iOpcode==`SP || iOpcode==`LP || iOpcode==`SFP || iOpcode==`LFP || iOpcode==`SFDP || iOpcode==`LFDP ||
|
//wire iIsLSPair = iOpcode==`SP || iOpcode==`LP || iOpcode==`SFP || iOpcode==`LFP || iOpcode==`SFDP || iOpcode==`LFDP ||
|
// (iOpcode==`MEMNDX && (iFunc6==`SPX || iFunc6==`LPX || iFunc6==`SFPX || iFunc6==`LFPX || iFunc6==`SFDPX || iFunc6==`LFDPX));
|
// (iOpcode==`MEMNDX && (iFunc6==`SPX || iFunc6==`LPX || iFunc6==`SFPX || iFunc6==`LFPX || iFunc6==`SFDPX || iFunc6==`LFDPX));
|
//wire dIsLSPair = dOpcode==`SP || dOpcode==`LP || dOpcode==`SFP || dOpcode==`LFP || dOpcode==`SFDP || dOpcode==`LFDP ||
|
//wire dIsLSPair = dOpcode==`SP || dOpcode==`LP || dOpcode==`SFP || dOpcode==`LFP || dOpcode==`SFDP || dOpcode==`LFDP ||
|
// (dOpcode==`MEMNDX && (dFunc6==`SPX || dFunc6==`LPX || dFunc6==`SFPX || dFunc6==`LFPX || dFunc6==`SFDPX || dFunc6==`LFDPX));
|
// (dOpcode==`MEMNDX && (dFunc6==`SPX || dFunc6==`LPX || dFunc6==`SFPX || dFunc6==`LFPX || dFunc6==`SFDPX || dFunc6==`LFDPX));
|
//wire xIsLSPair = xOpcode==`SP || xOpcode==`LP || xOpcode==`SFP || xOpcode==`LFP || xOpcode==`SFDP || xOpcode==`LFDP ||
|
//wire xIsLSPair = xOpcode==`SP || xOpcode==`LP || xOpcode==`SFP || xOpcode==`LFP || xOpcode==`SFDP || xOpcode==`LFDP ||
|
// (xOpcode==`MEMNDX && (xFunc6==`SPX || xFunc6==`LPX || xFunc6==`SFPX || xFunc6==`LFPX || xFunc6==`SFDPX || xFunc6==`LFDPX));
|
// (xOpcode==`MEMNDX && (xFunc6==`SPX || xFunc6==`LPX || xFunc6==`SFPX || xFunc6==`LFPX || xFunc6==`SFDPX || xFunc6==`LFDPX));
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Segmentation
|
// Segmentation
|
//
|
//
|
// If the upper nybble of the address is 'F' then segmentation is not applied.
|
// Paradoxically, it's less expensive to provide an array of 16 segment
|
// This allows for bootstrapping and operating system use. Also when in kernel
|
// registers as opposed to several independent registers. The 16 registers
|
// mode the lowest 64k of memory is unsegmented to allow easier access to
|
// are lower cost than the independent CS,DS,ES, and SS registers were.
|
// operating system variables.
|
|
//
|
|
// Otherwise: the CS register is always in use for code addresses.
|
|
// Which segment is used for data addresses depends on the upper nybble of
|
|
// the address.
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
`ifdef SEGMENTATION
|
`ifdef SEGMENTATION
|
wire [63:0] spc; // segmented PC
|
wire [63:0] spc; // segmented PC
|
reg [63:0] sea; // segmented effective address
|
wire [63:0] sea; // segmented effective address
|
assign spc = pc[63:60]==4'hF ? pc : {CS[AXC][63:16] + pc[59:16],pc[15:0]};
|
assign spc = {segs[{pc[63:60], AXC}][63:12] + pc[59:12],pc[11:0]};
|
always @(ea or KernelMode)
|
assign sea = {segs[{ea[63:60],xAXC}][63:12] + ea[59:12],ea[11:0]};
|
if (KernelMode && ea[63:16]==48'h0)
|
initial begin
|
sea <= ea;
|
for (n = 0; n < 256; n = n + 1)
|
else
|
segs[n] = 52'd0;
|
case(ea[63:60])
|
end
|
4'hF: sea <= ea;
|
|
4'hE: sea <= {SS[xAXC][63:16] + ea[59:16],ea[15:0]};
|
|
4'hD: sea <= {ES[xAXC][63:16] + ea[59:16],ea[15:0]};
|
|
default:
|
|
sea <= {DS[xAXC][63:16] + ea[59:16],ea[15:0]};
|
|
endcase
|
|
`else
|
`else
|
wire [63:0] spc = pc;
|
wire [63:0] spc = pc;
|
wire [63:0] sea = ea;
|
wire [63:0] sea = ea;
|
`endif
|
`endif
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
`ifdef SIMPLE_MMU
|
|
SimpleMMU ummu1
|
|
(
|
|
.num(3'd0),
|
|
.rst_i(rst_i),
|
|
.clk_i(clk),
|
|
.dma_i(1'b0),
|
|
.kernel_mode(KernelMode),
|
|
.cyc_i(iocyc_o),
|
|
.stb_i(stb_o),
|
|
.ack_o(mmu_ack),
|
|
.we_i(we_o),
|
|
.adr_i(adr_o[23:0]),
|
|
.dat_i(dat_o[15:0]),
|
|
.dat_o(mmu_dato),
|
|
.rclk(~clk),
|
|
.pc_i(spc[27:0]),
|
|
.pc_o(ppc[27:0]),
|
|
.ea_i(sea[27:0]),
|
|
.ea_o(pea[27:0])
|
|
);
|
|
assign pea[63:28]=sea[63:28];
|
|
assign ppc[63:28]=spc[63:28];
|
|
`endif
|
|
|
|
//-----------------------------------------------------------------------------
|
// TLB
|
// TLB
|
// The TLB contains 64 entries, that are 8 way set associative.
|
// The TLB contains 64 entries, that are 8 way set associative.
|
// The TLB is dual ported and shared between the instruction and data streams.
|
// The TLB is dual ported and shared between the instruction and data streams.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
wire [63:0] ppc;
|
wire [63:0] ppc;
|
wire [63:0] pea;
|
wire [63:0] pea;
|
wire [63:0] tlbo;
|
wire [63:0] tlbo;
|
`ifdef TLB
|
`ifdef TLB
|
wire [63:0] TLBVirtPage;
|
wire [63:0] TLBVirtPage;
|
wire wTlbp = advanceW && wOpcode==`MISC && wFunc==`TLBP;
|
wire wTlbp = advanceW && wOpcode==`MISC && wFunc==`TLBP;
|
wire wTlbrd = advanceW && wOpcode==`MISC && wFunc==`TLBR;
|
wire wTlbrd = advanceW && wOpcode==`MISC && wFunc==`TLBR;
|
wire wTlbwr = advanceW && wOpcode==`MISC && wFunc==`TLBWR;
|
wire wTlbwr = advanceW && wOpcode==`MISC && wFunc==`TLBWR;
|
wire wTlbwi = advanceW && wOpcode==`MISC && wFunc==`TLBWI;
|
wire wTlbwi = advanceW && wOpcode==`MISC && wFunc==`TLBWI;
|
wire wMtspr = advanceW && wOpcode==`R && wFunc==`MTSPR;
|
wire wMtspr = advanceW && wOpcode==`R && wFunc==`MTSPR;
|
wire xTlbrd = advanceX && xOpcode==`MISC && xFunc==`TLBR;
|
wire xTlbrd = advanceX && xOpcode==`MISC && xFunc==`TLBR;
|
wire xTlbwr = advanceX && xOpcode==`MISC && xFunc==`TLBWR;
|
wire xTlbwr = advanceX && xOpcode==`MISC && xFunc==`TLBWR;
|
wire xTlbwi = advanceX && xOpcode==`MISC && xFunc==`TLBWI;
|
wire xTlbwi = advanceX && xOpcode==`MISC && xFunc==`TLBWI;
|
wire ITLBMiss,DTLBMiss;
|
wire ITLBMiss,DTLBMiss;
|
|
|
Raptor64_TLB u26
|
Raptor64_TLB u26
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
.pc(spc),
|
.pc(spc),
|
.ea(sea),
|
.ea(sea),
|
.ppc(ppc),
|
.ppc(ppc),
|
.pea(pea),
|
.pea(pea),
|
.m1IsStore(advanceM1 && m1IsStore),
|
.m1IsStore(advanceM1 && m1IsStore),
|
.ASID(ASID),
|
.ASID(ASID),
|
.wTlbp(wTlbp),
|
.wTlbp(wTlbp),
|
.wTlbrd(wTlbrd),
|
.wTlbrd(wTlbrd),
|
.wTlbwr(wTlbwr),
|
.wTlbwr(wTlbwr),
|
.wTlbwi(wTlbwi),
|
.wTlbwi(wTlbwi),
|
.xTlbrd(xTlbrd),
|
.xTlbrd(xTlbrd),
|
.xTlbwr(xTlbwr),
|
.xTlbwr(xTlbwr),
|
.xTlbwi(xTlbwi),
|
.xTlbwi(xTlbwi),
|
.wr(wMtspr),
|
.wr(wMtspr),
|
.wregno(wIR[11:6]),
|
.wregno(wIR[11:6]),
|
.dati(wData),
|
.dati(wData),
|
.xregno(xIR[11:6]),
|
.xregno(xIR[11:6]),
|
.dato(tlbo),
|
.dato(tlbo),
|
.ITLBMiss(ITLBMiss),
|
.ITLBMiss(ITLBMiss),
|
.DTLBMiss(DTLBMiss),
|
.DTLBMiss(DTLBMiss),
|
.HTLBVirtPage(TLBVirtPage)
|
.HTLBVirtPage(TLBVirtPage)
|
);
|
);
|
|
|
`else
|
`else
|
|
`ifndef SIMPLE_MMU
|
assign ppc = spc;
|
assign ppc = spc;
|
assign pea = sea;
|
assign pea = sea;
|
`endif
|
`endif
|
|
`endif
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Clock control
|
// Clock control
|
// - reset or NMI reenables the clock
|
// - reset or NMI reenables the clock
|
// - this circuit must be under the clk_i domain
|
// - this circuit must be under the clk_i domain
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//
|
//
|
BUFGCE u20 (.CE(cpu_clk_en), .I(clk_i), .O(clk) );
|
BUFGCE u20 (.CE(cpu_clk_en), .I(clk_i), .O(clk) );
|
|
|
always @(posedge clk_i)
|
always @(posedge clk_i)
|
if (rst_i) begin
|
if (rst_i) begin
|
cpu_clk_en <= 1'b1;
|
cpu_clk_en <= 1'b1;
|
end
|
end
|
else begin
|
else begin
|
if (nmi_i)
|
if (nmi_i)
|
cpu_clk_en <= 1'b1;
|
cpu_clk_en <= 1'b1;
|
else
|
else
|
cpu_clk_en <= clk_en;
|
cpu_clk_en <= clk_en;
|
end
|
end
|
//assign clk = clk_i;
|
//assign clk = clk_i;
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Random number register:
|
// Random number register:
|
//
|
//
|
// Uses George Marsaglia's multiply method.
|
// Uses George Marsaglia's multiply method.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
reg [63:0] m_z;
|
reg [63:0] m_z;
|
reg [63:0] m_w;
|
reg [63:0] m_w;
|
reg [63:0] next_m_z;
|
reg [63:0] next_m_z;
|
reg [63:0] next_m_w;
|
reg [63:0] next_m_w;
|
|
|
always @(m_z or m_w)
|
always @(m_z or m_w)
|
begin
|
begin
|
next_m_z <= (36'd3696936969 * m_z[31:0]) + m_z[63:32];
|
next_m_z <= (36'd3696936969 * m_z[31:0]) + m_z[63:32];
|
next_m_w <= (36'd1800018000 * m_w[31:0]) + m_w[63:32];
|
next_m_w <= (36'd1800018000 * m_w[31:0]) + m_w[63:32];
|
end
|
end
|
|
|
wire [63:0] rand = {m_z[31:0],32'd0} + m_w;
|
wire [63:0] rand = {m_z[31:0],32'd0} + m_w;
|
|
|
wire [10:0] bias = 11'h3FF; // bias amount (eg 127)
|
wire [10:0] bias = 11'h3FF; // bias amount (eg 127)
|
wire [10:0] xl = rand[62:53];
|
wire [10:0] xl = rand[62:53];
|
wire sgn = 1'b0; // floating point: always generate a positive number
|
wire sgn = 1'b0; // floating point: always generate a positive number
|
wire [10:0] exp = xl > bias-1 ? bias-1 : xl; // 2^-1 otherwise number could be over 1
|
wire [10:0] exp = xl > bias-1 ? bias-1 : xl; // 2^-1 otherwise number could be over 1
|
wire [52:0] man = rand[52:0]; // a leading '1' will be assumed
|
wire [52:0] man = rand[52:0]; // a leading '1' will be assumed
|
wire [63:0] randfd = {sgn,exp,man};
|
wire [63:0] randfd = {sgn,exp,man};
|
reg [63:0] rando;
|
reg [63:0] rando;
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Instruction Cache / Instruction buffer
|
// Instruction Cache / Instruction buffer
|
//
|
//
|
// On a bus error, the instruction cache / buffer is loaded with a SYSCALL 509
|
// On a bus error, the instruction cache / buffer is loaded with a SYSCALL 509
|
// instruction, which is a call to the bus error handler.
|
// instruction, which is a call to the bus error handler.
|
// Line size is 16 half-words (64 bytes). Total cache size is 16kB.
|
// Line size is 16 half-words (64 bytes). Total cache size is 16kB.
|
//
|
//
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//reg lfdir;
|
//reg lfdir;
|
reg icaccess;
|
reg icaccess;
|
reg ICacheOn;
|
reg ICacheOn;
|
wire ibufrdy;
|
wire ibufrdy;
|
wire [31:0] insnbundle;
|
wire [31:0] insnbundle;
|
reg [31:0] insnbuf;
|
reg [31:0] insnbuf;
|
reg [63:0] ibufadr;
|
reg [63:0] ibufadr;
|
wire isICached = ppc[63:32]!=nonICacheSeg;
|
wire isICached = ppc[63:32]!=nonICacheSeg;
|
//wire isEncrypted = ppc[63:32]==encryptedArea;
|
//wire isEncrypted = ppc[63:32]==encryptedArea;
|
wire ICacheAct = ICacheOn & isICached;
|
wire ICacheAct = ICacheOn & isICached;
|
reg [31:0] insn1;
|
reg [31:0] insn1;
|
reg [31:0] insnkey;
|
reg [31:0] insnkey;
|
reg [63:0] icadr;
|
reg [63:0] icadr;
|
|
|
// SYSCALL 509
|
// SYSCALL 509
|
wire syscall509 = 32'b0000000_00000_0000_11111110_10010111;
|
wire syscall509 = 32'b0000000_00000_0000_11111110_10010111;
|
wire [63:0] bevect = {syscall509,syscall509};
|
wire [63:0] bevect = {syscall509,syscall509};
|
|
|
Raptor64_icache_ram u1
|
Raptor64_icache_ram u1
|
(
|
(
|
.wclk(clk),
|
.wclk(clk),
|
.we(icaccess & (ack_i|err_i)),
|
.we(icaccess & (ack_i|err_i)),
|
.adr(icadr[13:0]),
|
.adr(icadr[13:0]),
|
.d(err_i ? bevect : dat_i),
|
.d(err_i ? bevect : dat_i),
|
.rclk(~clk),
|
.rclk(~clk),
|
.pc(pc[13:0]),
|
.pc(ppc[13:0]),
|
.insn(insnbundle)
|
.insn(insnbundle)
|
);
|
);
|
|
|
always @(insnbundle or ICacheAct or insnbuf)
|
always @(insnbundle or ICacheAct or insnbuf)
|
begin
|
begin
|
case(ICacheAct)
|
case(ICacheAct)
|
1'b0: insn1 <= insnbuf;
|
1'b0: insn1 <= insnbuf;
|
1'b1: insn1 <= insnbundle;
|
1'b1: insn1 <= insnbundle;
|
endcase
|
endcase
|
end
|
end
|
|
|
// Decrypt the instruction set.
|
// Decrypt the instruction set.
|
always @(insn1,insnkey)
|
always @(insn1,insnkey)
|
insn <= insn1 ^ insnkey;
|
insn <= insn1 ^ insnkey;
|
|
|
reg [63:14] tmem [255:0];
|
reg [63:14] tmem [255:0];
|
reg [255:0] tvalid;
|
reg [255:0] tvalid;
|
|
|
initial begin
|
initial begin
|
for (n=0; n < 256; n = n + 1)
|
for (n=0; n < 256; n = n + 1)
|
tmem[n] = 0;
|
tmem[n] = 0;
|
for (n=0; n < 256; n = n + 1)
|
for (n=0; n < 256; n = n + 1)
|
tvalid[n] = 0;
|
tvalid[n] = 0;
|
end
|
end
|
|
|
wire [64:14] tgout;
|
wire [64:14] tgout;
|
assign tgout = {tvalid[pc[13:6]],tmem[pc[13:6]]};
|
assign tgout = {tvalid[ppc[13:6]],tmem[ppc[13:6]]};
|
assign ihit = (tgout=={1'b1,ppc[63:14]});
|
assign ihit = (tgout=={1'b1,ppc[63:14]});
|
assign ibufrdy = ibufadr[63:2]==ppc[63:2];
|
assign ibufrdy = ibufadr[63:2]==ppc[63:2];
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Data Cache
|
// Data Cache
|
// No-allocate on write
|
// No-allocate on write
|
// Line size is 8 words (64 bytes). Total cache size is 32kB
|
// Line size is 8 words (64 bytes). Total cache size is 32kB
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
reg dcaccess;
|
reg dcaccess;
|
wire dhit;
|
wire dhit;
|
wire [64:15] dtgout;
|
wire [64:15] dtgout;
|
reg wrhit;
|
reg wrhit;
|
reg wr_dcache;
|
reg wr_dcache;
|
reg [14:0] dcadr;
|
reg [14:0] dcadr;
|
|
|
// cache RAM 32Kb
|
// cache RAM 32Kb
|
Raptor64_dcache_ram u10
|
Raptor64_dcache_ram u10
|
(
|
(
|
.wclk(clk),
|
.wclk(clk),
|
.wr(1'b1),
|
.wr(1'b1),
|
.sel(dcaccess ? {8{ack_i}} : wrhit ? sel_o : 8'h00),
|
.sel(dcaccess ? {8{ack_i}} : wrhit ? sel_o : 8'h00),
|
.wadr(dcaccess ? dcadr[14:3] : adr_o[14:3]),
|
.wadr(dcaccess ? dcadr[14:3] : adr_o[14:3]),
|
.i(dcaccess ? dat_i : dat_o),
|
.i(dcaccess ? dat_i : dat_o),
|
.rclk(~clk),
|
.rclk(~clk),
|
.radr(pea[14:3]),
|
.radr(pea[14:3]),
|
.o(cdat)
|
.o(cdat)
|
);
|
);
|
|
|
// tag RAM 512 b
|
// tag RAM 512 b
|
Raptor64_dcache_tagram u11
|
Raptor64_dcache_tagram u11
|
(
|
(
|
.wclk(clk),
|
.wclk(clk),
|
.we(dtinit | (dcaccess && ack_i && dcadr[5:3]==3'b111)),
|
.we(dtinit | (dcaccess && ack_i && dcadr[5:3]==3'b111)),
|
.adr(dcadr[14:6]),
|
.adr(dcadr[14:6]),
|
.d({~dtinit,adr_o[63:15]}),
|
.d({~dtinit,adr_o[63:15]}),
|
|
|
.rclk(~clk),
|
.rclk(~clk),
|
.ea(pea[14:6]),
|
.ea(pea[14:6]),
|
.tago(dtgout)
|
.tago(dtgout)
|
);
|
);
|
|
|
assign dhit = (dtgout=={1'b1,pea[63:15]});
|
assign dhit = (dtgout=={1'b1,pea[63:15]});
|
|
|
reg [ 7:0] cdata8;
|
reg [ 7:0] cdata8;
|
reg [15:0] cdata16;
|
reg [15:0] cdata16;
|
reg [31:0] cdata32;
|
reg [31:0] cdata32;
|
reg [63:0] cdata64;
|
reg [63:0] cdata64;
|
|
|
always @(pea or cdat)
|
always @(pea or cdat)
|
case(pea[2:0])
|
case(pea[2:0])
|
3'b000: cdata8 <= cdat[ 7: 0];
|
3'b000: cdata8 <= cdat[ 7: 0];
|
3'b001: cdata8 <= cdat[15: 8];
|
3'b001: cdata8 <= cdat[15: 8];
|
3'b010: cdata8 <= cdat[23:16];
|
3'b010: cdata8 <= cdat[23:16];
|
3'b011: cdata8 <= cdat[31:24];
|
3'b011: cdata8 <= cdat[31:24];
|
3'b100: cdata8 <= cdat[39:32];
|
3'b100: cdata8 <= cdat[39:32];
|
3'b101: cdata8 <= cdat[47:40];
|
3'b101: cdata8 <= cdat[47:40];
|
3'b110: cdata8 <= cdat[55:48];
|
3'b110: cdata8 <= cdat[55:48];
|
3'b111: cdata8 <= cdat[63:56];
|
3'b111: cdata8 <= cdat[63:56];
|
endcase
|
endcase
|
|
|
always @(pea or cdat)
|
always @(pea or cdat)
|
case(pea[2:1])
|
case(pea[2:1])
|
2'b00: cdata16 <= cdat[15: 0];
|
2'b00: cdata16 <= cdat[15: 0];
|
2'b01: cdata16 <= cdat[31:16];
|
2'b01: cdata16 <= cdat[31:16];
|
2'b10: cdata16 <= cdat[47:32];
|
2'b10: cdata16 <= cdat[47:32];
|
2'b11: cdata16 <= cdat[63:48];
|
2'b11: cdata16 <= cdat[63:48];
|
endcase
|
endcase
|
|
|
always @(pea or cdat)
|
always @(pea or cdat)
|
case(pea[2])
|
case(pea[2])
|
1'b0: cdata32 <= cdat[31: 0];
|
1'b0: cdata32 <= cdat[31: 0];
|
1'b1: cdata32 <= cdat[63:32];
|
1'b1: cdata32 <= cdat[63:32];
|
endcase
|
endcase
|
|
|
always @(pea or cdat)
|
always @(pea or cdat)
|
cdata64 <= cdat;
|
cdata64 <= cdat;
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
|
reg [64:0] xData;
|
reg [64:0] xData;
|
// Load word and reserve is never cached.
|
// Load word and reserve is never cached.
|
wire xisCacheElement = (xData[63:52] != 12'hFFD && xData[63:52]!=12'hFFF &&
|
wire xisCacheElement = (xData[63:52] != 12'hFFD && xData[63:52]!=12'hFFF &&
|
xOpcode!=`LWR && !(xOpcode==`MEMNDX && xFunc6==`LWRX)) && dcache_on;
|
xOpcode!=`LWR && !(xOpcode==`MEMNDX && xFunc6==`LWRX)) && dcache_on;
|
reg m1IsCacheElement;
|
reg m1IsCacheElement;
|
|
|
|
|
wire [127:0] mult_out;
|
wire [127:0] mult_out;
|
wire [63:0] sqrt_out;
|
wire [63:0] sqrt_out;
|
wire [63:0] div_q;
|
wire [63:0] div_q;
|
wire [63:0] div_r;
|
wire [63:0] div_r;
|
wire sqrt_done,mult_done,div_done;
|
wire sqrt_done,mult_done,div_done;
|
wire isSqrt =xOpcode==`R && xFunc==`SQRT;
|
wire isSqrt =xOpcode==`R && xFunc==`SQRT;
|
|
|
isqrt #(64) u14
|
isqrt #(64) u14
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
.ce(1'b1),
|
.ce(1'b1),
|
.ld(isSqrt),
|
.ld(isSqrt),
|
.a(a),
|
.a(a),
|
.o(sqrt_out),
|
.o(sqrt_out),
|
.done(sqrt_done)
|
.done(sqrt_done)
|
);
|
);
|
|
|
wire isMulu = xOpcode==`RR && xFunc==`MULU;
|
wire isMulu = xOpcode==`RR && xFunc==`MULU;
|
wire isMuls = ((xOpcode==`RR && xFunc==`MULS) || xOpcode==`MULSI);
|
wire isMuls = ((xOpcode==`RR && xFunc==`MULS) || xOpcode==`MULSI);
|
wire isMuli = (xOpcode==`MULSI || xOpcode==`MULUI);
|
wire isMuli = (xOpcode==`MULSI || xOpcode==`MULUI);
|
wire isMult = (xOpcode==`MULSI || xOpcode==`MULUI || (xOpcode==`RR && (xFunc==`MULS || xFunc==`MULU)));
|
wire isMult = (xOpcode==`MULSI || xOpcode==`MULUI || (xOpcode==`RR && (xFunc==`MULS || xFunc==`MULU)));
|
wire isDivu = (xOpcode==`RR && xFunc==`DIVU);
|
wire isDivu = (xOpcode==`RR && xFunc==`DIVU);
|
wire isDivs = ((xOpcode==`RR && xFunc==`DIVS) || xOpcode==`DIVSI);
|
wire isDivs = ((xOpcode==`RR && xFunc==`DIVS) || xOpcode==`DIVSI);
|
wire isDivi = (xOpcode==`DIVSI || xOpcode==`DIVUI);
|
wire isDivi = (xOpcode==`DIVSI || xOpcode==`DIVUI);
|
wire isDiv = (xOpcode==`DIVSI || xOpcode==`DIVUI || (xOpcode==`RR && (xFunc==`DIVS || xFunc==`DIVU)));
|
wire isDiv = (xOpcode==`DIVSI || xOpcode==`DIVUI || (xOpcode==`RR && (xFunc==`DIVS || xFunc==`DIVU)));
|
wire isModu = (xOpcode==`RR && xFunc==`MODU);
|
wire isModu = (xOpcode==`RR && xFunc==`MODU);
|
wire isMods = (xOpcode==`RR && xFunc==`MODS);
|
wire isMods = (xOpcode==`RR && xFunc==`MODS);
|
wire isMod = isModu|isMods;
|
wire isMod = isModu|isMods;
|
|
|
Raptor64Mult u18
|
Raptor64Mult u18
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
.ld(isMult),
|
.ld(isMult),
|
.sgn(isMuls),
|
.sgn(isMuls),
|
.isMuli(isMuli),
|
.isMuli(isMuli),
|
.a(a),
|
.a(a),
|
.b(b),
|
.b(b),
|
.imm(imm),
|
.imm(imm),
|
.o(mult_out),
|
.o(mult_out),
|
.done(mult_done)
|
.done(mult_done)
|
);
|
);
|
|
|
Raptor64Div u19
|
Raptor64Div u19
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
.ld(isDiv|isMod),
|
.ld(isDiv|isMod),
|
.sgn(isDivs|isMods),
|
.sgn(isDivs|isMods),
|
.isDivi(isDivi),
|
.isDivi(isDivi),
|
.a(a),
|
.a(a),
|
.b(b),
|
.b(b),
|
.imm(imm),
|
.imm(imm),
|
.qo(div_q),
|
.qo(div_q),
|
.ro(div_r),
|
.ro(div_r),
|
.dvByZr(),
|
.dvByZr(),
|
.done(div_done)
|
.done(div_done)
|
);
|
);
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Floating point
|
// Floating point
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
|
wire [63:0] fpZLOut;
|
wire [63:0] fpZLOut;
|
wire [63:0] fpLooOut;
|
wire [63:0] fpLooOut;
|
wire fpLooDone;
|
wire fpLooDone;
|
|
|
|
|
/*
|
/*
|
fpZLUnit #(64) u30
|
fpZLUnit #(64) u30
|
(
|
(
|
.op(xFunc[5:0]),
|
.op(xFunc[5:0]),
|
.a(a),
|
.a(a),
|
.b(b), // for fcmp
|
.b(b), // for fcmp
|
.o(fpZLOut),
|
.o(fpZLOut),
|
.nanx()
|
.nanx()
|
);
|
);
|
|
|
fpLOOUnit #(64) u31
|
fpLOOUnit #(64) u31
|
(
|
(
|
.clk(clk),
|
.clk(clk),
|
.ce(1'b1),
|
.ce(1'b1),
|
.rm(rm),
|
.rm(rm),
|
.op(xFunc[5:0]),
|
.op(xFunc[5:0]),
|
.a(a),
|
.a(a),
|
.o(fpLooOut),
|
.o(fpLooOut),
|
.done(fpLooDone)
|
.done(fpLooDone)
|
);
|
);
|
|
|
*/
|
*/
|
wire dcmp_result;
|
wire dcmp_result;
|
wire [63:0] daddsub_result;
|
wire [63:0] daddsub_result;
|
wire [63:0] ddiv_result;
|
wire [63:0] ddiv_result;
|
wire [63:0] dmul_result;
|
wire [63:0] dmul_result;
|
wire [63:0] i2f_result;
|
wire [63:0] i2f_result;
|
wire [63:0] f2i_result;
|
wire [63:0] f2i_result;
|
wire [63:0] f2d_result;
|
wire [63:0] f2d_result;
|
wire [63:0] d2f_result;
|
wire [63:0] d2f_result;
|
|
|
wire f2i_iop,fpmul_iop,fpdiv_iop,fpaddsub_iop,fpcmp_iop;
|
wire f2i_iop,fpmul_iop,fpdiv_iop,fpaddsub_iop,fpcmp_iop;
|
wire f2i_ovr,fpmul_ovr,fpdiv_ovr,fpaddsub_ovr;
|
wire f2i_ovr,fpmul_ovr,fpdiv_ovr,fpaddsub_ovr;
|
wire fpmul_uf,fpaddsub_uf,fpdiv_uf;
|
wire fpmul_uf,fpaddsub_uf,fpdiv_uf;
|
wire [11:0] fcmp_result;
|
wire [11:0] fcmp_result;
|
|
|
`ifdef SIMD
|
`ifdef SIMD
|
|
|
Raptor64_fpAdd21 u61
|
Raptor64_fpAdd21 u61
|
(
|
(
|
.a(a[20:0]),
|
.a(a[20:0]),
|
.b(b[20:0]),
|
.b(b[20:0]),
|
.operation(xFunc6),
|
.operation(xFunc6),
|
.clk(clk),
|
.clk(clk),
|
.result(daddsub_result[20:0])
|
.result(daddsub_result[20:0])
|
);
|
);
|
|
|
Raptor64_fpAdd21 u62
|
Raptor64_fpAdd21 u62
|
(
|
(
|
.a(a[41:21]),
|
.a(a[41:21]),
|
.b(b[41:21]),
|
.b(b[41:21]),
|
.operation(xFunc6),
|
.operation(xFunc6),
|
.clk(clk),
|
.clk(clk),
|
.result(daddsub_result[41:21])
|
.result(daddsub_result[41:21])
|
);
|
);
|
|
|
Raptor64_fpAdd21 u63
|
Raptor64_fpAdd21 u63
|
(
|
(
|
.a(a[62:42]),
|
.a(a[62:42]),
|
.b(b[62:42]),
|
.b(b[62:42]),
|
.operation(xFunc6),
|
.operation(xFunc6),
|
.clk(clk),
|
.clk(clk),
|
.result(daddsub_result[62:42])
|
.result(daddsub_result[62:42])
|
);
|
);
|
|
|
Raptor64_fpMul21 u64
|
Raptor64_fpMul21 u64
|
(
|
(
|
.a(a[20:0]),
|
.a(a[20:0]),
|
.b(b[20:0]),
|
.b(b[20:0]),
|
.clk(clk),
|
.clk(clk),
|
.result(dmul_result[20:0])
|
.result(dmul_result[20:0])
|
);
|
);
|
|
|
Raptor64_fpMul21 u65
|
Raptor64_fpMul21 u65
|
(
|
(
|
.a(a[41:21]),
|
.a(a[41:21]),
|
.b(b[41:21]),
|
.b(b[41:21]),
|
.clk(clk),
|
.clk(clk),
|
.result(dmul_result[41:21])
|
.result(dmul_result[41:21])
|
);
|
);
|
|
|
Raptor64_fpMul21 u66
|
Raptor64_fpMul21 u66
|
(
|
(
|
.a(a[62:42]),
|
.a(a[62:42]),
|
.b(b[62:42]),
|
.b(b[62:42]),
|
.clk(clk),
|
.clk(clk),
|
.result(dmul_result[62:42])
|
.result(dmul_result[62:42])
|
);
|
);
|
|
|
Raptor64_fpDiv21 u67
|
Raptor64_fpDiv21 u67
|
(
|
(
|
.a(a[20:0]),
|
.a(a[20:0]),
|
.b(b[20:0]),
|
.b(b[20:0]),
|
.clk(clk),
|
.clk(clk),
|
.result(ddiv_result[20:0])
|
.result(ddiv_result[20:0])
|
);
|
);
|
|
|
Raptor64_fpDiv21 u68
|
Raptor64_fpDiv21 u68
|
(
|
(
|
.a(a[41:21]),
|
.a(a[41:21]),
|
.b(b[41:21]),
|
.b(b[41:21]),
|
.clk(clk),
|
.clk(clk),
|
.result(ddiv_result[41:21])
|
.result(ddiv_result[41:21])
|
);
|
);
|
|
|
Raptor64_fpDiv21 u69
|
Raptor64_fpDiv21 u69
|
(
|
(
|
.a(a[62:42]),
|
.a(a[62:42]),
|
.b(b[62:42]),
|
.b(b[62:42]),
|
.clk(clk),
|
.clk(clk),
|
.result(ddiv_result[62:42])
|
.result(ddiv_result[62:42])
|
);
|
);
|
|
|
Raptor64_fCmp21 u70
|
Raptor64_fCmp21 u70
|
(
|
(
|
.a(a[20:0]),
|
.a(a[20:0]),
|
.b(b[20:0]),
|
.b(b[20:0]),
|
.clk(clk),
|
.clk(clk),
|
.result(fcmp_result[3:0])
|
.result(fcmp_result[3:0])
|
);
|
);
|
|
|
Raptor64_fCmp21 u71
|
Raptor64_fCmp21 u71
|
(
|
(
|
.a(a[41:21]),
|
.a(a[41:21]),
|
.b(b[41:21]),
|
.b(b[41:21]),
|
.clk(clk),
|
.clk(clk),
|
.result(fcmp_result[7:4])
|
.result(fcmp_result[7:4])
|
);
|
);
|
|
|
Raptor64_fCmp21 u72
|
Raptor64_fCmp21 u72
|
(
|
(
|
.a(a[62:42]),
|
.a(a[62:42]),
|
.b(b[62:42]),
|
.b(b[62:42]),
|
.clk(clk),
|
.clk(clk),
|
.result(fcmp_result[11:8])
|
.result(fcmp_result[11:8])
|
);
|
);
|
`endif
|
`endif
|
|
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
// Xilinx Core Generator Components
|
// Xilinx Core Generator Components
|
|
|
Raptor64_fpCmp u60
|
Raptor64_fpCmp u60
|
(
|
(
|
.a(a), // input [63 : 0] a
|
.a(a), // input [63 : 0] a
|
.b(b), // input [63 : 0] b
|
.b(b), // input [63 : 0] b
|
.operation(xFunc6), // input [5 : 0] operation
|
.operation(xFunc6), // input [5 : 0] operation
|
.clk(clk), // input clk
|
.clk(clk), // input clk
|
.result(dcmp_result), // ouput [0 : 0] result
|
.result(dcmp_result), // ouput [0 : 0] result
|
.invalid_op(fpcmp_iop)
|
.invalid_op(fpcmp_iop)
|
); // ouput invalid_op
|
); // ouput invalid_op
|
|
|
Raptor64_fpAddsub u61
|
Raptor64_fpAddsub u61
|
(
|
(
|
.a(a), // input [63 : 0] a
|
.a(a), // input [63 : 0] a
|
.b(b), // input [63 : 0] b
|
.b(b), // input [63 : 0] b
|
.operation(xFunc6), // input [5 : 0] operation
|
.operation(xFunc6), // input [5 : 0] operation
|
.clk(clk), // input clk
|
.clk(clk), // input clk
|
.result(daddsub_result), // ouput [63 : 0] result
|
.result(daddsub_result), // ouput [63 : 0] result
|
.underflow(fpaddsub_uf), // ouput underflow
|
.underflow(fpaddsub_uf), // ouput underflow
|
.overflow(fpaddsub_ovr), // ouput overflow
|
.overflow(fpaddsub_ovr), // ouput overflow
|
.invalid_op(fpaddsub_iop)
|
.invalid_op(fpaddsub_iop)
|
); // ouput invalid_op
|
); // ouput invalid_op
|
|
|
Raptor64_fpDiv u62
|
Raptor64_fpDiv u62
|
(
|
(
|
.a(a), // input [63 : 0] a
|
.a(a), // input [63 : 0] a
|
.b(b), // input [63 : 0] b
|
.b(b), // input [63 : 0] b
|
.clk(clk), // input clk
|
.clk(clk), // input clk
|
.result(ddiv_result), // ouput [63 : 0] result
|
.result(ddiv_result), // ouput [63 : 0] result
|
.underflow(fpdiv_uf), // ouput underflow
|
.underflow(fpdiv_uf), // ouput underflow
|
.overflow(fpdiv_ovr), // ouput overflow
|
.overflow(fpdiv_ovr), // ouput overflow
|
.invalid_op(fpdiv_iop), // ouput invalid_op
|
.invalid_op(fpdiv_iop), // ouput invalid_op
|
.divide_by_zero()
|
.divide_by_zero()
|
); // ouput divide_by_zero
|
); // ouput divide_by_zero
|
|
|
Raptor64_fpMul u63
|
Raptor64_fpMul u63
|
(
|
(
|
.a(a), // input [63 : 0] a
|
.a(a), // input [63 : 0] a
|
.b(b), // input [63 : 0] b
|
.b(b), // input [63 : 0] b
|
.clk(clk), // input clk
|
.clk(clk), // input clk
|
.result(dmul_result), // ouput [63 : 0] result
|
.result(dmul_result), // ouput [63 : 0] result
|
.underflow(fpmul_uf), // ouput underflow
|
.underflow(fpmul_uf), // ouput underflow
|
.overflow(fpmul_ovr), // ouput overflow
|
.overflow(fpmul_ovr), // ouput overflow
|
.invalid_op(fpmul_iop)
|
.invalid_op(fpmul_iop)
|
); // ouput invalid_op
|
); // ouput invalid_op
|
|
|
Raptor64_fpItoF u64
|
Raptor64_fpItoF u64
|
(
|
(
|
.a(a), // input [63 : 0] a
|
.a(a), // input [63 : 0] a
|
.clk(clk), // input clk
|
.clk(clk), // input clk
|
.result(i2f_result)
|
.result(i2f_result)
|
); // ouput [63 : 0] result
|
); // ouput [63 : 0] result
|
|
|
Raptor64_fpFtoI u65
|
Raptor64_fpFtoI u65
|
(
|
(
|
.a(a), // input [63 : 0] a
|
.a(a), // input [63 : 0] a
|
.clk(clk), // input clk
|
.clk(clk), // input clk
|
.result(f2i_result), // ouput [63 : 0] result
|
.result(f2i_result), // ouput [63 : 0] result
|
.overflow(f2i_ovr), // ouput overflow
|
.overflow(f2i_ovr), // ouput overflow
|
.invalid_op(f2i_iop)
|
.invalid_op(f2i_iop)
|
); // ouput invalid_op
|
); // ouput invalid_op
|
|
|
`endif
|
`endif
|
|
|
always @(posedge clk)
|
always @(posedge clk)
|
if (rst_i) begin
|
if (rst_i) begin
|
fltctr <= 6'd0;
|
fltctr <= 6'd0;
|
end
|
end
|
else begin
|
else begin
|
if (fltdone) begin
|
if (fltdone) begin
|
FPC_overx <= fp_ovr;
|
FPC_overx <= fp_ovr;
|
end
|
end
|
if (advanceX) begin
|
if (advanceX) begin
|
`ifdef SIMD
|
`ifdef SIMD
|
if (xOpcode==`SIMD) begin
|
if (xOpcode==`SIMD) begin
|
case(xFunc6)
|
case(xFunc6)
|
`SIMD_ADD: fltctr <= 6'd10;
|
`SIMD_ADD: fltctr <= 6'd10;
|
`SIMD_SUB: fltctr <= 6'd10;
|
`SIMD_SUB: fltctr <= 6'd10;
|
`SIMD_MUL: fltctr <= 6'd7;
|
`SIMD_MUL: fltctr <= 6'd7;
|
`SIMD_DIV: fltctr <= 6'd19;
|
`SIMD_DIV: fltctr <= 6'd19;
|
`SIMD_CMP: fltctr <= 6'd2;
|
`SIMD_CMP: fltctr <= 6'd2;
|
default: fltctr <= 6'd1;
|
default: fltctr <= 6'd1;
|
endcase
|
endcase
|
end
|
end
|
else
|
else
|
`endif
|
`endif
|
if (xOpcode==`FP) begin
|
if (xOpcode==`FP) begin
|
if (xFunc6==`FDADD) // FDADD
|
if (xFunc6==`FDADD) // FDADD
|
fltctr <= 6'd12;
|
fltctr <= 6'd12;
|
else if (xFunc6==`FDSUB) // FDSUB
|
else if (xFunc6==`FDSUB) // FDSUB
|
fltctr <= 6'd12;
|
fltctr <= 6'd12;
|
else if (xFunc6==`FDMUL) // FDMUL
|
else if (xFunc6==`FDMUL) // FDMUL
|
fltctr <= 6'd12;
|
fltctr <= 6'd12;
|
else if (xFunc6==`FDDIV) // FDDIV
|
else if (xFunc6==`FDDIV) // FDDIV
|
fltctr <= 6'd12;
|
fltctr <= 6'd12;
|
else if (xFunc6==6'b000100) // unordered
|
else if (xFunc6==6'b000100) // unordered
|
fltctr <= 6'd2;
|
fltctr <= 6'd2;
|
else if (xFunc6==6'b001100) // less than
|
else if (xFunc6==6'b001100) // less than
|
fltctr <= 6'd2;
|
fltctr <= 6'd2;
|
else if (xFunc6==6'b010100) // equal
|
else if (xFunc6==6'b010100) // equal
|
fltctr <= 6'd2;
|
fltctr <= 6'd2;
|
else if (xFunc6==6'b011100) // less than or equal
|
else if (xFunc6==6'b011100) // less than or equal
|
fltctr <= 6'd2;
|
fltctr <= 6'd2;
|
else if (xFunc6==6'b100100) // greater than
|
else if (xFunc6==6'b100100) // greater than
|
fltctr <= 6'd2;
|
fltctr <= 6'd2;
|
else if (xFunc6==6'b101100) // not equal
|
else if (xFunc6==6'b101100) // not equal
|
fltctr <= 6'd2;
|
fltctr <= 6'd2;
|
else if (xFunc6==6'b110100) // greater than or equal
|
else if (xFunc6==6'b110100) // greater than or equal
|
fltctr <= 6'd2;
|
fltctr <= 6'd2;
|
else if (xFunc6==`FDI2F) // ItoFD
|
else if (xFunc6==`FDI2F) // ItoFD
|
fltctr <= 6'd7;
|
fltctr <= 6'd7;
|
else if (xFunc6==6'b000110) // FFtoI
|
else if (xFunc6==6'b000110) // FFtoI
|
fltctr <= 6'd6;
|
fltctr <= 6'd6;
|
else if (xFunc6==6'b000111) // FtoD
|
else if (xFunc6==6'b000111) // FtoD
|
fltctr <= 6'd2;
|
fltctr <= 6'd2;
|
else if (xFunc6==6'b001000) // DtoF
|
else if (xFunc6==6'b001000) // DtoF
|
fltctr <= 6'd2;
|
fltctr <= 6'd2;
|
else
|
else
|
fltctr <= 6'd0;
|
fltctr <= 6'd0;
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
if (fltctr > 6'd0)
|
if (fltctr > 6'd0)
|
fltctr <= fltctr - 6'd1;
|
fltctr <= fltctr - 6'd1;
|
end
|
end
|
end
|
end
|
|
|
function [2:0] popcnt6;
|
function [2:0] popcnt6;
|
input [5:0] a;
|
input [5:0] a;
|
begin
|
begin
|
case(a)
|
case(a)
|
6'b000000: popcnt6 = 3'd0;
|
6'b000000: popcnt6 = 3'd0;
|
6'b000001: popcnt6 = 3'd1;
|
6'b000001: popcnt6 = 3'd1;
|
6'b000010: popcnt6 = 3'd1;
|
6'b000010: popcnt6 = 3'd1;
|
6'b000011: popcnt6 = 3'd2;
|
6'b000011: popcnt6 = 3'd2;
|
6'b000100: popcnt6 = 3'd1;
|
6'b000100: popcnt6 = 3'd1;
|
6'b000101: popcnt6 = 3'd2;
|
6'b000101: popcnt6 = 3'd2;
|
6'b000110: popcnt6 = 3'd2;
|
6'b000110: popcnt6 = 3'd2;
|
6'b000111: popcnt6 = 3'd3;
|
6'b000111: popcnt6 = 3'd3;
|
6'b001000: popcnt6 = 3'd1;
|
6'b001000: popcnt6 = 3'd1;
|
6'b001001: popcnt6 = 3'd2;
|
6'b001001: popcnt6 = 3'd2;
|
6'b001010: popcnt6 = 3'd2;
|
6'b001010: popcnt6 = 3'd2;
|
6'b001011: popcnt6 = 3'd3;
|
6'b001011: popcnt6 = 3'd3;
|
6'b001100: popcnt6 = 3'd2;
|
6'b001100: popcnt6 = 3'd2;
|
6'b001101: popcnt6 = 3'd3;
|
6'b001101: popcnt6 = 3'd3;
|
6'b001110: popcnt6 = 3'd3;
|
6'b001110: popcnt6 = 3'd3;
|
6'b001111: popcnt6 = 3'd4;
|
6'b001111: popcnt6 = 3'd4;
|
6'b010000: popcnt6 = 3'd1;
|
6'b010000: popcnt6 = 3'd1;
|
6'b010001: popcnt6 = 3'd2;
|
6'b010001: popcnt6 = 3'd2;
|
6'b010010: popcnt6 = 3'd2;
|
6'b010010: popcnt6 = 3'd2;
|
6'b010011: popcnt6 = 3'd3;
|
6'b010011: popcnt6 = 3'd3;
|
6'b010100: popcnt6 = 3'd2;
|
6'b010100: popcnt6 = 3'd2;
|
6'b010101: popcnt6 = 3'd3;
|
6'b010101: popcnt6 = 3'd3;
|
6'b010110: popcnt6 = 3'd3;
|
6'b010110: popcnt6 = 3'd3;
|
6'b010111: popcnt6 = 3'd4;
|
6'b010111: popcnt6 = 3'd4;
|
6'b011000: popcnt6 = 3'd2;
|
6'b011000: popcnt6 = 3'd2;
|
6'b011001: popcnt6 = 3'd3;
|
6'b011001: popcnt6 = 3'd3;
|
6'b011010: popcnt6 = 3'd3;
|
6'b011010: popcnt6 = 3'd3;
|
6'b011011: popcnt6 = 3'd4;
|
6'b011011: popcnt6 = 3'd4;
|
6'b011100: popcnt6 = 3'd3;
|
6'b011100: popcnt6 = 3'd3;
|
6'b011101: popcnt6 = 3'd4;
|
6'b011101: popcnt6 = 3'd4;
|
6'b011110: popcnt6 = 3'd4;
|
6'b011110: popcnt6 = 3'd4;
|
6'b011111: popcnt6 = 3'd5;
|
6'b011111: popcnt6 = 3'd5;
|
6'b100000: popcnt6 = 3'd1;
|
6'b100000: popcnt6 = 3'd1;
|
6'b100001: popcnt6 = 3'd2;
|
6'b100001: popcnt6 = 3'd2;
|
6'b100010: popcnt6 = 3'd2;
|
6'b100010: popcnt6 = 3'd2;
|
6'b100011: popcnt6 = 3'd3;
|
6'b100011: popcnt6 = 3'd3;
|
6'b100100: popcnt6 = 3'd2;
|
6'b100100: popcnt6 = 3'd2;
|
6'b100101: popcnt6 = 3'd3;
|
6'b100101: popcnt6 = 3'd3;
|
6'b100110: popcnt6 = 3'd3;
|
6'b100110: popcnt6 = 3'd3;
|
6'b100111: popcnt6 = 3'd4;
|
6'b100111: popcnt6 = 3'd4;
|
6'b101000: popcnt6 = 3'd2;
|
6'b101000: popcnt6 = 3'd2;
|
6'b101001: popcnt6 = 3'd3;
|
6'b101001: popcnt6 = 3'd3;
|
6'b101010: popcnt6 = 3'd3;
|
6'b101010: popcnt6 = 3'd3;
|
6'b101011: popcnt6 = 3'd4;
|
6'b101011: popcnt6 = 3'd4;
|
6'b101100: popcnt6 = 3'd3;
|
6'b101100: popcnt6 = 3'd3;
|
6'b101101: popcnt6 = 3'd4;
|
6'b101101: popcnt6 = 3'd4;
|
6'b101110: popcnt6 = 3'd4;
|
6'b101110: popcnt6 = 3'd4;
|
6'b101111: popcnt6 = 3'd5;
|
6'b101111: popcnt6 = 3'd5;
|
6'b110000: popcnt6 = 3'd2;
|
6'b110000: popcnt6 = 3'd2;
|
6'b110001: popcnt6 = 3'd3;
|
6'b110001: popcnt6 = 3'd3;
|
6'b110010: popcnt6 = 3'd3;
|
6'b110010: popcnt6 = 3'd3;
|
6'b110011: popcnt6 = 3'd4;
|
6'b110011: popcnt6 = 3'd4;
|
6'b110100: popcnt6 = 3'd3;
|
6'b110100: popcnt6 = 3'd3;
|
6'b110101: popcnt6 = 3'd4;
|
6'b110101: popcnt6 = 3'd4;
|
6'b110110: popcnt6 = 3'd4;
|
6'b110110: popcnt6 = 3'd4;
|
6'b110111: popcnt6 = 3'd5;
|
6'b110111: popcnt6 = 3'd5;
|
6'b111000: popcnt6 = 3'd3;
|
6'b111000: popcnt6 = 3'd3;
|
6'b111001: popcnt6 = 3'd4;
|
6'b111001: popcnt6 = 3'd4;
|
6'b111010: popcnt6 = 3'd4;
|
6'b111010: popcnt6 = 3'd4;
|
6'b111011: popcnt6 = 3'd5;
|
6'b111011: popcnt6 = 3'd5;
|
6'b111100: popcnt6 = 3'd4;
|
6'b111100: popcnt6 = 3'd4;
|
6'b111101: popcnt6 = 3'd5;
|
6'b111101: popcnt6 = 3'd5;
|
6'b111110: popcnt6 = 3'd5;
|
6'b111110: popcnt6 = 3'd5;
|
6'b111111: popcnt6 = 3'd6;
|
6'b111111: popcnt6 = 3'd6;
|
endcase
|
endcase
|
end
|
end
|
endfunction
|
endfunction
|
|
|
function [5:0] popcnt36;
|
function [5:0] popcnt36;
|
input [35:0] a;
|
input [35:0] a;
|
begin
|
begin
|
popcnt36 = popcnt6(a[5:0]) +
|
popcnt36 = popcnt6(a[5:0]) +
|
popcnt6(a[11:6]) +
|
popcnt6(a[11:6]) +
|
popcnt6(a[17:12]) +
|
popcnt6(a[17:12]) +
|
popcnt6(a[23:18]) +
|
popcnt6(a[23:18]) +
|
popcnt6(a[29:24]) +
|
popcnt6(a[29:24]) +
|
popcnt6(a[35:30]);
|
popcnt6(a[35:30]);
|
end
|
end
|
endfunction
|
endfunction
|
|
|
wire [63:0] jmp_tgt = {pc[63:27],insn[24:0],2'b00};
|
wire [63:0] jmp_tgt = {pc[63:27],insn[24:0],2'b00};
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Stack for return address predictor
|
// Stack for return address predictor
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
reg [63:0] ras [63:0]; // return address stack, return predictions
|
reg [63:0] ras [63:0]; // return address stack, return predictions
|
reg [5:0] ras_sp; // stack pointer
|
reg [5:0] ras_sp; // stack pointer
|
initial begin
|
initial begin
|
for (n = 0; n < 64; n = n + 1)
|
for (n = 0; n < 64; n = n + 1)
|
ras[n] = 0;
|
ras[n] = 0;
|
end
|
end
|
`ifdef BTB
|
`ifdef BTB
|
reg [63:0] btb [63:0]; // branch target buffer
|
reg [63:0] btb [63:0]; // branch target buffer
|
`endif
|
`endif
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Branch history table.
|
// Branch history table.
|
// The history table is updated by the EX stage and read in
|
// The history table is updated by the EX stage and read in
|
// both the EX and IF stages.
|
// both the EX and IF stages.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
wire predict_taken;
|
wire predict_taken;
|
|
|
Raptor64_BranchHistory u6
|
Raptor64_BranchHistory u6
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
.advanceX(advanceX),
|
.advanceX(advanceX),
|
.xIR(xIR),
|
.xIR(xIR),
|
.pc(pc),
|
.pc(pc),
|
.xpc(xpc),
|
.xpc(xpc),
|
.takb(takb),
|
.takb(takb),
|
.predict_taken(predict_taken)
|
.predict_taken(predict_taken)
|
);
|
);
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Evaluate branch conditions.
|
// Evaluate branch conditions.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
|
Raptor64_EvaluateBranch u4
|
Raptor64_EvaluateBranch u4
|
(
|
(
|
.ir(xIR),
|
.ir(xIR),
|
.a(a),
|
.a(a),
|
.b(b),
|
.b(b),
|
.imm(imm),
|
.imm(imm),
|
.rsf(rsf),
|
.rsf(rsf),
|
.takb(takb)
|
.takb(takb)
|
);
|
);
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Datapath (ALU) operations.
|
// Datapath (ALU) operations.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
reg [63:0] xData1;
|
reg [63:0] xData1;
|
wire [63:0] xBitfieldo,xSeto,xLogico,xShifto,xAddsubo;
|
wire [63:0] xBitfieldo,xSeto,xLogico,xShifto,xAddsubo;
|
|
|
wire [6:0] cntlzo,cntloo;
|
wire [6:0] cntlzo,cntloo;
|
cntlz64 u12 (.clk(clk), .i(a), .o(cntlzo) );
|
cntlz64 u12 (.clk(clk), .i(a), .o(cntlzo) );
|
cntlo64 u13 (.clk(clk), .i(a), .o(cntloo) );
|
cntlo64 u13 (.clk(clk), .i(a), .o(cntloo) );
|
//cntlz64 u12 (.i(a), .o(cntlzo) );
|
//cntlz64 u12 (.i(a), .o(cntlzo) );
|
//cntlo64 u13 (.i(a), .o(cntloo) );
|
//cntlo64 u13 (.i(a), .o(cntloo) );
|
|
|
reg [1:0] shftop;
|
reg [1:0] shftop;
|
wire [63:0] shfto;
|
wire [63:0] shfto;
|
wire [63:0] masko;
|
wire [63:0] masko;
|
reg [63:0] bfextd;
|
reg [63:0] bfextd;
|
wire [63:0] rolo;
|
wire [63:0] rolo;
|
wire [15:0] bcdmulo;
|
wire [15:0] bcdmulo;
|
|
|
Raptor64_addsub u21 (xIR,a,b,imm,xAddsubo);
|
Raptor64_addsub u21 (xIR,a,b,imm,xAddsubo);
|
Raptor64_logic u9 (xIR,a,b,imm,xLogico);
|
Raptor64_logic u9 (xIR,a,b,imm,xLogico);
|
Raptor64_set u15 (xIR,a,b,imm,xSeto);
|
Raptor64_set u15 (xIR,a,b,imm,xSeto);
|
Raptor64_bitfield u16(xIR, a, b, xBitfieldo, masko);
|
Raptor64_bitfield u16(xIR, a, b, xBitfieldo, masko);
|
Raptor64_shift u17 (xIR, a, b, masko, xShifto, rolo);
|
Raptor64_shift u17 (xIR, a, b, masko, xShifto, rolo);
|
BCDMul2 u22 (a[7:0],b[7:0],bcdmulo);
|
BCDMul2 u22 (a[7:0],b[7:0],bcdmulo);
|
|
|
wire aeqz = a==64'd0;
|
wire aeqz = a==64'd0;
|
wire eq = a==b;
|
wire eq = a==b;
|
wire eqi = a==imm;
|
wire eqi = a==imm;
|
wire lt = $signed(a) < $signed(b);
|
wire lt = $signed(a) < $signed(b);
|
wire lti = $signed(a) < $signed(imm);
|
wire lti = $signed(a) < $signed(imm);
|
wire ltu = a < b;
|
wire ltu = a < b;
|
wire ltui = a < imm;
|
wire ltui = a < imm;
|
|
wire [7:0] segndx = xFunc6==`MFSEG ? {xIR[9:6],xAXC} : {a[63:60],xAXC};
|
|
|
always @(xOpcode or xFunc or xFunc5 or a or b or c or imm or xpc or aeqz or xFunc6 or
|
always @(xOpcode or xFunc or xFunc5 or a or b or c or imm or xpc or aeqz or xFunc6 or
|
sqrt_out or cntlzo or cntloo or tick or AXC or scale or
|
sqrt_out or cntlzo or cntloo or tick or AXC or scale or
|
lt or eq or ltu or mult_out or lti or eqi or ltui or xIR or div_q or div_r or
|
lt or eq or ltu or mult_out or lti or eqi or ltui or xIR or div_q or div_r or
|
shfto or masko or bcdmulo or fpLooOut or fpZLOut or m_z or m_w or
|
shfto or masko or bcdmulo or fpLooOut or fpZLOut or m_z or m_w or
|
`ifdef TLB
|
`ifdef TLB
|
PageTableAddr or BadVAddr or ASID or tlbo or
|
PageTableAddr or BadVAddr or ASID or tlbo or
|
`endif
|
`endif
|
ASID or TBA or xAXC or nonICacheSeg or rm or
|
ASID or TBA or xAXC or nonICacheSeg or rm or
|
rando or errorAddress or insnkey or pchistoric
|
rando or errorAddress or insnkey or pchistoric
|
)
|
)
|
casex(xOpcode)
|
casex(xOpcode)
|
`MISC:
|
`MISC:
|
case(xFunc)
|
case(xFunc)
|
`SYSCALL:
|
`SYSCALL:
|
if (xIR[16])
|
if (xIR[16])
|
xData1 = fnIncPC(xpc);
|
xData1 = fnIncPC(xpc);
|
else
|
else
|
xData1 = xpc;
|
xData1 = xpc;
|
default: xData1 = 64'd0;
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
`R:
|
`R:
|
casex(xFunc6)
|
casex(xFunc6)
|
`COM: xData1 = ~a;
|
`COM: xData1 = ~a;
|
`NOT: xData1 = ~|a;
|
`NOT: xData1 = ~|a;
|
`NEG: xData1 = -a;
|
`NEG: xData1 = -a;
|
`ABS: xData1 = a[63] ? -a : a;
|
`ABS: xData1 = a[63] ? -a : a;
|
`SGN: xData1 = a[63] ? 64'hFFFFFFFF_FFFFFFFF : aeqz ? 64'd0 : 64'd1;
|
`SGN: xData1 = a[63] ? 64'hFFFFFFFF_FFFFFFFF : aeqz ? 64'd0 : 64'd1;
|
`MOV: xData1 = a;
|
`MOV: xData1 = a;
|
`SQRT: xData1 = sqrt_out;
|
`SQRT: xData1 = sqrt_out;
|
`SWAP: xData1 = {a[31:0],a[63:32]};
|
`SWAP: xData1 = {a[31:0],a[63:32]};
|
`RBO: xData1 = {a[7:0],a[15:8],a[23:16],a[31:24],a[39:32],a[47:40],a[55:48],a[63:56]};
|
`RBO: xData1 = {a[7:0],a[15:8],a[23:16],a[31:24],a[39:32],a[47:40],a[55:48],a[63:56]};
|
|
|
`REDOR: xData1 = |a;
|
`REDOR: xData1 = |a;
|
`REDAND: xData1 = &a;
|
`REDAND: xData1 = &a;
|
|
|
`CTLZ: xData1 = cntlzo;
|
`CTLZ: xData1 = cntlzo;
|
`CTLO: xData1 = cntloo;
|
`CTLO: xData1 = cntloo;
|
`CTPOP: xData1 = {4'd0,popcnt6(a[5:0])} +
|
`CTPOP: xData1 = {4'd0,popcnt6(a[5:0])} +
|
{4'd0,popcnt6(a[11:6])} +
|
{4'd0,popcnt6(a[11:6])} +
|
{4'd0,popcnt6(a[17:12])} +
|
{4'd0,popcnt6(a[17:12])} +
|
{4'd0,popcnt6(a[23:18])} +
|
{4'd0,popcnt6(a[23:18])} +
|
{4'd0,popcnt6(a[29:24])} +
|
{4'd0,popcnt6(a[29:24])} +
|
{4'd0,popcnt6(a[35:30])} +
|
{4'd0,popcnt6(a[35:30])} +
|
{4'd0,popcnt6(a[41:36])} +
|
{4'd0,popcnt6(a[41:36])} +
|
{4'd0,popcnt6(a[47:42])} +
|
{4'd0,popcnt6(a[47:42])} +
|
{4'd0,popcnt6(a[53:48])} +
|
{4'd0,popcnt6(a[53:48])} +
|
{4'd0,popcnt6(a[59:54])} +
|
{4'd0,popcnt6(a[59:54])} +
|
{4'd0,popcnt6(a[63:60])}
|
{4'd0,popcnt6(a[63:60])}
|
;
|
;
|
`SEXT8: xData1 = {{56{a[7]}},a[7:0]};
|
`SEXT8: xData1 = {{56{a[7]}},a[7:0]};
|
`SEXT16: xData1 = {{48{a[15]}},a[15:0]};
|
`SEXT16: xData1 = {{48{a[15]}},a[15:0]};
|
`SEXT32: xData1 = {{32{a[31]}},a[31:0]};
|
`SEXT32: xData1 = {{32{a[31]}},a[31:0]};
|
|
|
`MTSPR: xData1 = a;
|
`MTSPR: xData1 = a;
|
`MFSPR:
|
`MFSPR:
|
case(xIR[11:6])
|
case(xIR[11:6])
|
`ifdef TLB
|
`ifdef TLB
|
`TLBWired: xData1 = tlbo;
|
`TLBWired: xData1 = tlbo;
|
`TLBIndex: xData1 = tlbo;
|
`TLBIndex: xData1 = tlbo;
|
`TLBRandom: xData1 = tlbo;
|
`TLBRandom: xData1 = tlbo;
|
`TLBPhysPage0: xData1 = tlbo;
|
`TLBPhysPage0: xData1 = tlbo;
|
`TLBPhysPage1: xData1 = tlbo;
|
`TLBPhysPage1: xData1 = tlbo;
|
`TLBVirtPage: xData1 = tlbo;
|
`TLBVirtPage: xData1 = tlbo;
|
`TLBPageMask: xData1 = tlbo;
|
`TLBPageMask: xData1 = tlbo;
|
`TLBASID: begin
|
`TLBASID: begin
|
xData1 = 64'd0;
|
xData1 = 64'd0;
|
xData1[0] = tlbo[0];
|
xData1[0] = tlbo[0];
|
xData1[1] = tlbo[1];
|
xData1[1] = tlbo[1];
|
xData1[2] = tlbo[2];
|
xData1[2] = tlbo[2];
|
xData1[15:8] = tlbo[15:8];
|
xData1[15:8] = tlbo[15:8];
|
end
|
end
|
`PageTableAddr: xData1 = {PageTableAddr,13'd0};
|
`PageTableAddr: xData1 = {PageTableAddr,13'd0};
|
`BadVAddr: xData1 = {BadVAddr,13'd0};
|
`BadVAddr: xData1 = {BadVAddr,13'd0};
|
`endif
|
`endif
|
`ifdef SEGMENTATION
|
|
`CS: xData1 = {CS[xAXC],16'h0};
|
|
`DS: xData1 = {DS[xAXC],16'h0};
|
|
`ES: xData1 = {ES[xAXC],16'b0};
|
|
`SS: xData1 = {SS[xAXC],16'h0};
|
|
`endif
|
|
`ASID: xData1 = ASID;
|
`ASID: xData1 = ASID;
|
`Tick: xData1 = tick;
|
`Tick: xData1 = tick;
|
`EPC: xData1 = EPC[xAXC];
|
`EPC: xData1 = EPC[xAXC];
|
`IPC: xData1 = IPC[xAXC];
|
`IPC: xData1 = IPC[xAXC];
|
`TBA: xData1 = TBA;
|
`TBA: xData1 = TBA;
|
`ERRADR: xData1 = errorAddress;
|
`ERRADR: xData1 = errorAddress;
|
`AXC: xData1 = xAXC;
|
`AXC: xData1 = xAXC;
|
`NON_ICACHE_SEG: xData1 = nonICacheSeg;
|
`NON_ICACHE_SEG: xData1 = nonICacheSeg;
|
`FPCR: xData1 = FPC;
|
`FPCR: xData1 = FPC;
|
`RAND: xData1 = rando;
|
`RAND: xData1 = rando;
|
`SRAND1: xData1 = m_z;
|
`SRAND1: xData1 = m_z;
|
`SRAND2: xData1 = m_w;
|
`SRAND2: xData1 = m_w;
|
`INSNKEY: xData1 = insnkey;
|
`INSNKEY: xData1 = insnkey;
|
`PCHISTORIC: xData1 = pchistoric;
|
`PCHISTORIC: xData1 = pchistoric;
|
default: xData1 = 64'd0;
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
|
`ifdef SEGMENTATION
|
|
`MFSEG,`MFSEGI: xData1 = segs[segndx];
|
|
`MTSEG: xData1 = a;
|
|
`endif
|
`OMG: xData1 = mutex_gate[a[5:0]];
|
`OMG: xData1 = mutex_gate[a[5:0]];
|
`CMG: xData1 = mutex_gate[a[5:0]];
|
`CMG: xData1 = mutex_gate[a[5:0]];
|
`OMGI: begin
|
`OMGI: begin
|
xData1 = mutex_gate[xIR[11:6]];
|
xData1 = mutex_gate[xIR[11:6]];
|
$display("mutex_gate[%d]=%d",xIR[11:6],mutex_gate[xIR[11:6]]);
|
$display("mutex_gate[%d]=%d",xIR[11:6],mutex_gate[xIR[11:6]]);
|
end
|
end
|
`CMGI: xData1 = mutex_gate[xIR[11:6]];
|
`CMGI: xData1 = mutex_gate[xIR[11:6]];
|
default: xData1 = 64'd0;
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
`RR:
|
`RR:
|
case(xFunc6)
|
case(xFunc6)
|
`CMP: xData1 = lt ? 64'hFFFFFFFFFFFFFFFF : eq ? 64'd0 : 64'd1;
|
`CMP: xData1 = lt ? 64'hFFFFFFFFFFFFFFFF : eq ? 64'd0 : 64'd1;
|
`CMPU: xData1 = ltu ? 64'hFFFFFFFFFFFFFFFF : eq ? 64'd0 : 64'd1;
|
`CMPU: xData1 = ltu ? 64'hFFFFFFFFFFFFFFFF : eq ? 64'd0 : 64'd1;
|
`MIN: xData1 = lt ? a : b;
|
`MIN: xData1 = lt ? a : b;
|
`MAX: xData1 = lt ? b : a;
|
`MAX: xData1 = lt ? b : a;
|
`MOVZ: xData1 = b;
|
`MOVZ: xData1 = b;
|
`MOVNZ: xData1 = b;
|
`MOVNZ: xData1 = b;
|
`MOVPL: xData1 = b;
|
`MOVPL: xData1 = b;
|
`MOVMI: xData1 = b;
|
`MOVMI: xData1 = b;
|
`MULS: xData1 = mult_out[63:0];
|
`MULS: xData1 = mult_out[63:0];
|
`MULU: xData1 = mult_out[63:0];
|
`MULU: xData1 = mult_out[63:0];
|
`DIVS: xData1 = div_q;
|
`DIVS: xData1 = div_q;
|
`DIVU: xData1 = div_q;
|
`DIVU: xData1 = div_q;
|
`MODU: xData1 = div_r;
|
`MODU: xData1 = div_r;
|
`MODS: xData1 = div_r;
|
`MODS: xData1 = div_r;
|
`BCD_MUL: xData1 = bcdmulo;
|
`BCD_MUL: xData1 = bcdmulo;
|
`MFEP: xData1 = epat[a[7:0]];
|
`MFEP: xData1 = epat[a[7:0]];
|
|
`ifdef SEGMENTATION
|
|
`MTSEGI: xData1 = b;
|
|
`endif
|
default: xData1 = 64'd0;
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
`ifdef SIMD
|
`ifdef SIMD
|
`SIMD:
|
`SIMD:
|
case(xFunc6)
|
case(xFunc6)
|
`SIMD_ADD: xData1 = daddsub_result;
|
`SIMD_ADD: xData1 = daddsub_result;
|
`SIMD_SUB: xData1 = daddsub_result;
|
`SIMD_SUB: xData1 = daddsub_result;
|
`SIMD_MUL: xData1 = dmul_result;
|
`SIMD_MUL: xData1 = dmul_result;
|
`SIMD_DIV: xData1 = ddiv_result;
|
`SIMD_DIV: xData1 = ddiv_result;
|
`SIMD_CMP: xData1 = {fcmp_result[11:8],17'd0,fcmp_result[7:4],17'd0,fcmp_result[3:0]};
|
`SIMD_CMP: xData1 = {fcmp_result[11:8],17'd0,fcmp_result[7:4],17'd0,fcmp_result[3:0]};
|
default: xData1 = 64'd0;
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
`endif
|
`endif
|
`ifdef ISIMD
|
`ifdef ISIMD
|
`SIMD:
|
`SIMD:
|
case(xFunc6)
|
case(xFunc6)
|
`SIMD_ADD:
|
`SIMD_ADD:
|
begin
|
begin
|
xData1[15: 0] <= a[15: 0] + b[15: 0];
|
xData1[15: 0] <= a[15: 0] + b[15: 0];
|
xData1[31:16] <= a[31:16] + b[31:16];
|
xData1[31:16] <= a[31:16] + b[31:16];
|
xData1[47:32] <= a[47:32] + b[47:32];
|
xData1[47:32] <= a[47:32] + b[47:32];
|
xData1[63:48] <= a[63:48] + b[63:48];
|
xData1[63:48] <= a[63:48] + b[63:48];
|
end
|
end
|
`SIMD_SUB:
|
`SIMD_SUB:
|
begin
|
begin
|
xData1[15: 0] <= a[15: 0] - b[15: 0];
|
xData1[15: 0] <= a[15: 0] - b[15: 0];
|
xData1[31:16] <= a[31:16] - b[31:16];
|
xData1[31:16] <= a[31:16] - b[31:16];
|
xData1[47:32] <= a[47:32] - b[47:32];
|
xData1[47:32] <= a[47:32] - b[47:32];
|
xData1[63:48] <= a[63:48] - b[63:48];
|
xData1[63:48] <= a[63:48] - b[63:48];
|
end
|
end
|
`SIMD_MUL:
|
`SIMD_MUL:
|
begin
|
begin
|
xData1[15: 0] <= a[15: 0] * b[15: 0];
|
xData1[15: 0] <= a[15: 0] * b[15: 0];
|
xData1[31:16] <= a[31:16] * b[31:16];
|
xData1[31:16] <= a[31:16] * b[31:16];
|
xData1[47:32] <= a[47:32] * b[47:32];
|
xData1[47:32] <= a[47:32] * b[47:32];
|
xData1[63:48] <= a[63:48] * b[63:48];
|
xData1[63:48] <= a[63:48] * b[63:48];
|
end
|
end
|
`SIMD_AND:
|
`SIMD_AND:
|
begin
|
begin
|
xData1[15: 0] <= a[15: 0] & b[15: 0];
|
xData1[15: 0] <= a[15: 0] & b[15: 0];
|
xData1[31:16] <= a[31:16] & b[31:16];
|
xData1[31:16] <= a[31:16] & b[31:16];
|
xData1[47:32] <= a[47:32] & b[47:32];
|
xData1[47:32] <= a[47:32] & b[47:32];
|
xData1[63:48] <= a[63:48] & b[63:48];
|
xData1[63:48] <= a[63:48] & b[63:48];
|
end
|
end
|
`SIMD_OR:
|
`SIMD_OR:
|
begin
|
begin
|
xData1[15: 0] <= a[15: 0] | b[15: 0];
|
xData1[15: 0] <= a[15: 0] | b[15: 0];
|
xData1[31:16] <= a[31:16] | b[31:16];
|
xData1[31:16] <= a[31:16] | b[31:16];
|
xData1[47:32] <= a[47:32] | b[47:32];
|
xData1[47:32] <= a[47:32] | b[47:32];
|
xData1[63:48] <= a[63:48] | b[63:48];
|
xData1[63:48] <= a[63:48] | b[63:48];
|
end
|
end
|
`SIMD_XOR:
|
`SIMD_XOR:
|
begin
|
begin
|
xData1[15: 0] <= a[15: 0] ^ b[15: 0];
|
xData1[15: 0] <= a[15: 0] ^ b[15: 0];
|
xData1[31:16] <= a[31:16] ^ b[31:16];
|
xData1[31:16] <= a[31:16] ^ b[31:16];
|
xData1[47:32] <= a[47:32] ^ b[47:32];
|
xData1[47:32] <= a[47:32] ^ b[47:32];
|
xData1[63:48] <= a[63:48] ^ b[63:48];
|
xData1[63:48] <= a[63:48] ^ b[63:48];
|
end
|
end
|
endcase
|
endcase
|
`endif
|
`endif
|
`BTRR:
|
`BTRR:
|
case(xFunc5)
|
case(xFunc5)
|
`LOOP: xData1 = b - 64'd1;
|
`LOOP: xData1 = b - 64'd1;
|
default: xData1 = 64'd0;
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
`MUX:
|
`MUX:
|
begin
|
begin
|
for (n = 0; n < 64; n = n + 1)
|
for (n = 0; n < 64; n = n + 1)
|
xData1[n] = c[n] ? b[n] : a[n];
|
xData1[n] = c[n] ? b[n] : a[n];
|
end
|
end
|
`SETLO: xData1 = {{42{xIR[21]}},xIR[21:0]};
|
`SETLO: xData1 = {{42{xIR[21]}},xIR[21:0]};
|
`SETMID: xData1 = {{20{xIR[21]}},xIR[21:0],a[21:0]};
|
`SETMID: xData1 = {{20{xIR[21]}},xIR[21:0],a[21:0]};
|
`SETHI: xData1 = {xIR[19:0],a[43:0]};
|
`SETHI: xData1 = {xIR[19:0],a[43:0]};
|
`CMPI: xData1 = lti ? 64'hFFFFFFFFFFFFFFFF : eqi ? 64'd0 : 64'd1;
|
`CMPI: xData1 = lti ? 64'hFFFFFFFFFFFFFFFF : eqi ? 64'd0 : 64'd1;
|
`CMPUI: xData1 = ltui ? 64'hFFFFFFFFFFFFFFFF : eqi ? 64'd0 : 64'd1;
|
`CMPUI: xData1 = ltui ? 64'hFFFFFFFFFFFFFFFF : eqi ? 64'd0 : 64'd1;
|
`MULSI: xData1 = mult_out[63:0];
|
`MULSI: xData1 = mult_out[63:0];
|
`MULUI: xData1 = mult_out[63:0];
|
`MULUI: xData1 = mult_out[63:0];
|
`DIVSI: xData1 = div_q;
|
`DIVSI: xData1 = div_q;
|
`DIVUI: xData1 = div_q;
|
`DIVUI: xData1 = div_q;
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
`LFP,`LFDP: xData1 = a + imm + xIR[15];
|
`LFP,`LFDP: xData1 = a + imm + xIR[15];
|
`SFP,`SFDP: xData1 = a + imm + xIR[15];
|
`SFP,`SFDP: xData1 = a + imm + xIR[15];
|
`endif
|
`endif
|
//`LP: xData1 = a + imm + xIR[15];
|
//`LP: xData1 = a + imm + xIR[15];
|
//`SP: xData1 = a + imm + xIR[15];
|
//`SP: xData1 = a + imm + xIR[15];
|
`MEMNDX:
|
`MEMNDX:
|
case(xFunc6)
|
case(xFunc6)
|
// `LPX,`LFPX,`LFDPX,`SPX,`SFPX,`SFDPX:
|
// `LPX,`LFPX,`LFDPX,`SPX,`SFPX,`SFDPX:
|
// xData1 = a + (b << scale) + offset2 + xIR[15];
|
// xData1 = a + (b << scale) + offset2 + xIR[15];
|
default:
|
default:
|
xData1 = a + (b << scale) + offset2;
|
xData1 = a + (b << scale) + offset2;
|
endcase
|
endcase
|
`TRAPcc: xData1 = fnIncPC(xpc);
|
`TRAPcc: xData1 = fnIncPC(xpc);
|
`TRAPcci: xData1 = fnIncPC(xpc);
|
`TRAPcci: xData1 = fnIncPC(xpc);
|
`CALL: xData1 = fnIncPC(xpc);
|
`CALL: xData1 = fnIncPC(xpc);
|
`JAL: xData1 = fnIncPC(xpc);//???xpc + {xIR[19:15],2'b00};
|
`JAL: xData1 = fnIncPC(xpc);//???xpc + {xIR[19:15],2'b00};
|
`RET: xData1 = a + imm;
|
`RET: xData1 = a + imm;
|
`FPLOO: xData1 = fpLooOut;
|
`FPLOO: xData1 = fpLooOut;
|
`FPZL: xData1 = fpZLOut;
|
`FPZL: xData1 = fpZLOut;
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
`FP:
|
`FP:
|
case(xFunc6)
|
case(xFunc6)
|
`FDADD: xData1 = daddsub_result;
|
`FDADD: xData1 = daddsub_result;
|
`FDSUB: xData1 = daddsub_result;
|
`FDSUB: xData1 = daddsub_result;
|
`FDMUL: xData1 = dmul_result;
|
`FDMUL: xData1 = dmul_result;
|
`FDDIV: xData1 = ddiv_result;
|
`FDDIV: xData1 = ddiv_result;
|
`FDI2F: xData1 = i2f_result;
|
`FDI2F: xData1 = i2f_result;
|
`FDF2I: xData1 = f2i_result;
|
`FDF2I: xData1 = f2i_result;
|
`FDCUN: xData1 = dcmp_result;
|
`FDCUN: xData1 = dcmp_result;
|
`FDCEQ: xData1 = dcmp_result;
|
`FDCEQ: xData1 = dcmp_result;
|
`FDCNE: xData1 = dcmp_result;
|
`FDCNE: xData1 = dcmp_result;
|
`FDCLT: xData1 = dcmp_result;
|
`FDCLT: xData1 = dcmp_result;
|
`FDCLE: xData1 = dcmp_result;
|
`FDCLE: xData1 = dcmp_result;
|
`FDCGT: xData1 = dcmp_result;
|
`FDCGT: xData1 = dcmp_result;
|
`FDCGE: xData1 = dcmp_result;
|
`FDCGE: xData1 = dcmp_result;
|
default: xData1 = 64'd0;
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
`endif
|
`endif
|
default: xData1 = 64'd0;
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
|
|
always @(xData1,xBitfieldo,xLogico,xShifto,xSeto,xAddsubo)
|
always @(xData1,xBitfieldo,xLogico,xShifto,xSeto,xAddsubo)
|
xData = xData1|xBitfieldo|xLogico|xShifto|xSeto|xAddsubo;
|
xData = xData1|xBitfieldo|xLogico|xShifto|xSeto|xAddsubo;
|
|
|
wire v_ri,v_rr;
|
wire v_ri,v_rr;
|
overflow u2 (.op(xOpcode==`SUBI), .a(a[63]), .b(imm[63]), .s(xAddsubo[63]), .v(v_ri));
|
overflow u2 (.op(xOpcode==`SUBI), .a(a[63]), .b(imm[63]), .s(xAddsubo[63]), .v(v_ri));
|
overflow u3 (.op(xOpcode==`RR && xFunc==`SUB), .a(a[63]), .b(b[63]), .s(xAddsubo[63]), .v(v_rr));
|
overflow u3 (.op(xOpcode==`RR && xFunc==`SUB), .a(a[63]), .b(b[63]), .s(xAddsubo[63]), .v(v_rr));
|
|
|
wire dbz_error = (((xOpcode==`DIVSI||xOpcode==`DIVUI) && imm==64'd0) || (xOpcode==`RR && (xFunc6==`DIVS || xFunc6==`DIVU) && b==64'd0));
|
wire dbz_error = (((xOpcode==`DIVSI||xOpcode==`DIVUI) && imm==64'd0) || (xOpcode==`RR && (xFunc6==`DIVS || xFunc6==`DIVU) && b==64'd0));
|
wire ovr_error = (((xOpcode==`ADDI || xOpcode==`SUBI) && v_ri) || ((xOpcode==`RR && (xFunc6==`SUB || xFunc6==`ADD)) && v_rr));
|
wire ovr_error = (((xOpcode==`ADDI || xOpcode==`SUBI) && v_ri) || ((xOpcode==`RR && (xFunc6==`SUB || xFunc6==`ADD)) && v_rr));
|
// ToDo: add more priv violations
|
// ToDo: add more priv violations
|
wire priv_violation = !KernelMode && (xOpcode==`MISC &&
|
wire priv_violation = !KernelMode && (xOpcode==`MISC &&
|
(xFunc==`IRET || xFunc==`ERET || xFunc==`CLI || xFunc==`SEI ||
|
(xFunc==`IRET || xFunc==`ERET || xFunc==`CLI || xFunc==`SEI ||
|
xFunc==`TLBP || xFunc==`TLBR || xFunc==`TLBWR || xFunc==`TLBWI || xFunc==`IEPP
|
xFunc==`TLBP || xFunc==`TLBR || xFunc==`TLBWR || xFunc==`TLBWI || xFunc==`IEPP
|
));
|
));
|
// ToDo: detect illegal instructions in the hives (sub-opcodes)
|
// ToDo: detect illegal instructions in the hives (sub-opcodes)
|
wire illegal_insn = (
|
wire illegal_insn = (
|
xOpcode==7'd19 ||
|
xOpcode==7'd19 ||
|
`ifndef SIMD
|
`ifndef SIMD
|
xOpcode==7'd20 ||
|
xOpcode==7'd20 ||
|
`endif
|
`endif
|
xOpcode==7'd28 ||
|
xOpcode==7'd28 ||
|
xOpcode==7'd29 ||
|
xOpcode==7'd29 ||
|
xOpcode==7'd30 ||
|
xOpcode==7'd30 ||
|
xOpcode==7'd31 ||
|
xOpcode==7'd31 ||
|
xOpcode==7'd47 ||
|
xOpcode==7'd47 ||
|
xOpcode==7'd55 ||
|
xOpcode==7'd55 ||
|
xOpcode==7'd63 ||
|
xOpcode==7'd63 ||
|
xOpcode==7'd90 ||
|
xOpcode==7'd90 ||
|
xOpcode==7'd91 ||
|
xOpcode==7'd91 ||
|
xOpcode==7'd92 ||
|
xOpcode==7'd92 ||
|
xOpcode==7'd93 ||
|
xOpcode==7'd93 ||
|
xOpcode==7'd106 ||
|
xOpcode==7'd106 ||
|
xOpcode==7'd107 ||
|
xOpcode==7'd107 ||
|
xOpcode==7'd124 ||
|
xOpcode==7'd124 ||
|
xOpcode==7'd125 ||
|
xOpcode==7'd125 ||
|
xOpcode==7'd126 ||
|
xOpcode==7'd126 ||
|
xOpcode==7'd127
|
xOpcode==7'd127
|
)
|
)
|
;
|
;
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// For performance and core size reasons, the following should really decode
|
// For performance and core size reasons, the following should really decode
|
// the opcodes in the decode stage, then pass the decoding information forward
|
// the opcodes in the decode stage, then pass the decoding information forward
|
// using regs. However the core is trickier to get working that way; decoding
|
// using regs. However the core is trickier to get working that way; decoding
|
// in multiple stages is simpler.
|
// in multiple stages is simpler.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//wire dIsFlowCtrl =
|
//wire dIsFlowCtrl =
|
// dOpcode==`JAL || dOpcode==`RET ||
|
// dOpcode==`JAL || dOpcode==`RET ||
|
// dOpcode==`BTRI || dOpcode==`BTRR || dOpcode==`TRAPcci || dOpcode==`TRAPcc ||
|
// dOpcode==`BTRI || dOpcode==`BTRR || dOpcode==`TRAPcci || dOpcode==`TRAPcc ||
|
// dOpcode==`BEQI || dOpcode==`BNEI ||
|
// dOpcode==`BEQI || dOpcode==`BNEI ||
|
// dOpcode==`BLTI || dOpcode==`BLEI || dOpcode==`BGTI || dOpcode==`BGEI ||
|
// dOpcode==`BLTI || dOpcode==`BLEI || dOpcode==`BGTI || dOpcode==`BGEI ||
|
// dOpcode==`BLTUI || dOpcode==`BLEUI || dOpcode==`BGTUI || dOpcode==`BGEUI ||
|
// dOpcode==`BLTUI || dOpcode==`BLEUI || dOpcode==`BGTUI || dOpcode==`BGEUI ||
|
// (dOpcode==`MISC && (dFunc==`SYSCALL || dFunc==`IRET || dFunc==`ERET))
|
// (dOpcode==`MISC && (dFunc==`SYSCALL || dFunc==`IRET || dFunc==`ERET))
|
// ;
|
// ;
|
//wire xIsFlowCtrl =
|
//wire xIsFlowCtrl =
|
// xOpcode==`JAL || xOpcode==`RET ||
|
// xOpcode==`JAL || xOpcode==`RET ||
|
// xOpcode==`BTRI || xOpcode==`BTRR || xOpcode==`TRAPcci || xOpcode==`TRAPcc ||
|
// xOpcode==`BTRI || xOpcode==`BTRR || xOpcode==`TRAPcci || xOpcode==`TRAPcc ||
|
// xOpcode==`BEQI || xOpcode==`BNEI ||
|
// xOpcode==`BEQI || xOpcode==`BNEI ||
|
// xOpcode==`BLTI || xOpcode==`BLEI || xOpcode==`BGTI || xOpcode==`BGEI ||
|
// xOpcode==`BLTI || xOpcode==`BLEI || xOpcode==`BGTI || xOpcode==`BGEI ||
|
// xOpcode==`BLTUI || xOpcode==`BLEUI || xOpcode==`BGTUI || xOpcode==`BGEUI ||
|
// xOpcode==`BLTUI || xOpcode==`BLEUI || xOpcode==`BGTUI || xOpcode==`BGEUI ||
|
// (xOpcode==`MISC && (xFunc==`SYSCALL || xFunc==`IRET || xFunc==`ERET))
|
// (xOpcode==`MISC && (xFunc==`SYSCALL || xFunc==`IRET || xFunc==`ERET))
|
// ;
|
// ;
|
//wire m1IsFlowCtrl =
|
//wire m1IsFlowCtrl =
|
// (m1Opcode==`MISC && m1Func==`SYSCALL)
|
// (m1Opcode==`MISC && m1Func==`SYSCALL)
|
// ;
|
// ;
|
//wire m2IsFlowCtrl =
|
//wire m2IsFlowCtrl =
|
// (m2Opcode==`MISC && m2Func==`SYSCALL)
|
// (m2Opcode==`MISC && m2Func==`SYSCALL)
|
// ;
|
// ;
|
//
|
//
|
//
|
//
|
//wire dIsLoad = dIRvalid && (
|
//wire dIsLoad = dIRvalid && (
|
// dOpcode==`LW || dOpcode==`LH || dOpcode==`LB || dOpcode==`LWR ||
|
// dOpcode==`LW || dOpcode==`LH || dOpcode==`LB || dOpcode==`LWR ||
|
// dOpcode==`LHU || dOpcode==`LBU ||
|
// dOpcode==`LHU || dOpcode==`LBU ||
|
// dOpcode==`LC || dOpcode==`LCU || dOpcode==`LM ||
|
// dOpcode==`LC || dOpcode==`LCU || dOpcode==`LM ||
|
// dOpcode==`LF || dOpcode==`LFD || dOpcode==`LP || dOpcode==`LFP || dOpcode==`LFDP ||
|
// dOpcode==`LF || dOpcode==`LFD || dOpcode==`LP || dOpcode==`LFP || dOpcode==`LFDP ||
|
// dOpcode==`LSH || dOpcode==`LSW ||
|
// dOpcode==`LSH || dOpcode==`LSW ||
|
// (dOpcode==`MEMNDX && (
|
// (dOpcode==`MEMNDX && (
|
// dFunc6==`LWX || dFunc6==`LHX || dFunc6==`LBX || dFunc6==`LWRX ||
|
// dFunc6==`LWX || dFunc6==`LHX || dFunc6==`LBX || dFunc6==`LWRX ||
|
// dFunc6==`LHUX || dFunc6==`LBUX ||
|
// dFunc6==`LHUX || dFunc6==`LBUX ||
|
// dFunc6==`LCX || dFunc6==`LCUX ||
|
// dFunc6==`LCX || dFunc6==`LCUX ||
|
// dFunc6==`LFX || dFunc6==`LFDX || dFunc6==`LPX ||
|
// dFunc6==`LFX || dFunc6==`LFDX || dFunc6==`LPX ||
|
// dFunc6==`LSHX || dFunc6==`LSWX
|
// dFunc6==`LSHX || dFunc6==`LSWX
|
// )) ||
|
// )) ||
|
// (dOpcode==`MISC && (dFunc==`SYSJMP || dFunc==`SYSCALL || dFunc==`SYSINT)))
|
// (dOpcode==`MISC && (dFunc==`SYSJMP || dFunc==`SYSCALL || dFunc==`SYSINT)))
|
// ;
|
// ;
|
//wire dIsStore = dIRvalid && (
|
//wire dIsStore = dIRvalid && (
|
// dOpcode==`SW || dOpcode==`SH || dOpcode==`SB || dOpcode==`SC || dOpcode==`SWC || dOpcode==`SM ||
|
// dOpcode==`SW || dOpcode==`SH || dOpcode==`SB || dOpcode==`SC || dOpcode==`SWC || dOpcode==`SM ||
|
// dOpcode==`SF || dOpcode==`SFD || dOpcode==`SP || dOpcode==`SFP || dOpcode==`SFDP ||
|
// dOpcode==`SF || dOpcode==`SFD || dOpcode==`SP || dOpcode==`SFP || dOpcode==`SFDP ||
|
// dOpcode==`SSH || dOpcode==`SSW ||
|
// dOpcode==`SSH || dOpcode==`SSW ||
|
// (dOpcode==`MEMNDX && (
|
// (dOpcode==`MEMNDX && (
|
// dFunc6==`SWX || dFunc6==`SHX || dFunc6==`SBX || dFunc6==`SCX || dFunc6==`SWCX ||
|
// dFunc6==`SWX || dFunc6==`SHX || dFunc6==`SBX || dFunc6==`SCX || dFunc6==`SWCX ||
|
// dFunc6==`SFX || dFunc6==`SFDX || dFunc6==`SPX ||
|
// dFunc6==`SFX || dFunc6==`SFDX || dFunc6==`SPX ||
|
// dFunc6==`SSHX || dFunc6==`SSWX
|
// dFunc6==`SSHX || dFunc6==`SSWX
|
// )))
|
// )))
|
// ;
|
// ;
|
//wire dIsIn = dIRvalid && (
|
//wire dIsIn = dIRvalid && (
|
// dOpcode==`INW || dOpcode==`INH || dOpcode==`INCH || dOpcode==`INB ||
|
// dOpcode==`INW || dOpcode==`INH || dOpcode==`INCH || dOpcode==`INB ||
|
// dOpcode==`INHU || dOpcode==`INCU || dOpcode==`INBU ||
|
// dOpcode==`INHU || dOpcode==`INCU || dOpcode==`INBU ||
|
// (dOpcode==`MEMNDX && (
|
// (dOpcode==`MEMNDX && (
|
// dFunc6==`INWX || dFunc6==`INHX || dFunc6==`INCX || dFunc6==`INBX ||
|
// dFunc6==`INWX || dFunc6==`INHX || dFunc6==`INCX || dFunc6==`INBX ||
|
// dFunc6==`INHUX || dFunc6==`INCUX || dFunc6==`INBUX
|
// dFunc6==`INHUX || dFunc6==`INCUX || dFunc6==`INBUX
|
// )))
|
// )))
|
// ;
|
// ;
|
//wire dIsOut = dIRvalid && (dOpcode==`OUTW || dOpcode==`OUTH || dOpcode==`OUTC || dOpcode==`OUTB ||
|
//wire dIsOut = dIRvalid && (dOpcode==`OUTW || dOpcode==`OUTH || dOpcode==`OUTC || dOpcode==`OUTB ||
|
// (dOpcode==`MEMNDX && (
|
// (dOpcode==`MEMNDX && (
|
// dFunc6==`OUTWX || dFunc6==`OUTHX || dFunc6==`OUTCX || dFunc6==`OUTBX
|
// dFunc6==`OUTWX || dFunc6==`OUTHX || dFunc6==`OUTCX || dFunc6==`OUTBX
|
// )))
|
// )))
|
// ;
|
// ;
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Pipeline advance and stall logic
|
// Pipeline advance and stall logic
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
wire xIsSqrt = xOpcode==`R && xFunc6==`SQRT;
|
wire xIsSqrt = xOpcode==`R && xFunc6==`SQRT;
|
wire xIsMult = ((xOpcode==`RR && (xFunc6==`MULU || xFunc6==`MULS)) || xOpcode==`MULSI || xOpcode==`MULUI);
|
wire xIsMult = ((xOpcode==`RR && (xFunc6==`MULU || xFunc6==`MULS)) || xOpcode==`MULSI || xOpcode==`MULUI);
|
wire xIsDiv = ((xOpcode==`RR && (xFunc6==`DIVU || xFunc6==`DIVS || xFunc6==`MODU || xFunc6==`MODS)) || xOpcode==`DIVSI || xOpcode==`DIVUI);
|
wire xIsDiv = ((xOpcode==`RR && (xFunc6==`DIVU || xFunc6==`DIVS || xFunc6==`MODU || xFunc6==`MODS)) || xOpcode==`DIVSI || xOpcode==`DIVUI);
|
wire xIsCnt = (xOpcode==`R && (xFunc6==`CTLZ || xFunc6==`CTLO || xFunc6==`CTPOP));
|
wire xIsCnt = (xOpcode==`R && (xFunc6==`CTLZ || xFunc6==`CTLO || xFunc6==`CTPOP));
|
reg m1IsCnt,m2IsCnt;
|
reg m1IsCnt,m2IsCnt;
|
reg m2IsCacheElement;
|
reg m2IsCacheElement;
|
|
|
// Have to set the xIsLoad/xIsStore flag to false when xIR is nopped out
|
// Have to set the xIsLoad/xIsStore flag to false when xIR is nopped out
|
wire xIsLoad = (
|
wire xIsLoad = (
|
xOpcode==`LW || xOpcode==`LH || xOpcode==`LB || xOpcode==`LWR ||
|
xOpcode==`LW || xOpcode==`LH || xOpcode==`LB || xOpcode==`LWR ||
|
xOpcode==`LHU || xOpcode==`LBU ||
|
xOpcode==`LHU || xOpcode==`LBU ||
|
xOpcode==`LC || xOpcode==`LCU || xOpcode==`LM ||
|
xOpcode==`LC || xOpcode==`LCU || xOpcode==`LM ||
|
xOpcode==`LF || xOpcode==`LFD || xOpcode==`LP || xOpcode==`LFP || xOpcode==`LFDP ||
|
xOpcode==`LF || xOpcode==`LFD || xOpcode==`LP || xOpcode==`LFP || xOpcode==`LFDP ||
|
xOpcode==`LSH || xOpcode==`LSW ||
|
xOpcode==`LSH || xOpcode==`LSW ||
|
(xOpcode==`MEMNDX && (
|
(xOpcode==`MEMNDX && (
|
xFunc6==`LWX || xFunc6==`LHX || xFunc6==`LBX || xFunc6==`LWRX ||
|
xFunc6==`LWX || xFunc6==`LHX || xFunc6==`LBX || xFunc6==`LWRX ||
|
xFunc6==`LHUX || xFunc6==`LBUX ||
|
xFunc6==`LHUX || xFunc6==`LBUX ||
|
xFunc6==`LCX || xFunc6==`LCUX ||
|
xFunc6==`LCX || xFunc6==`LCUX ||
|
xFunc6==`LFX || xFunc6==`LFDX || xFunc6==`LPX ||
|
xFunc6==`LFX || xFunc6==`LFDX || xFunc6==`LPX ||
|
xFunc6==`LSHX || xFunc6==`LSWX
|
xFunc6==`LSHX || xFunc6==`LSWX
|
)) ||
|
)) ||
|
(xOpcode==`MISC && (xFunc==`SYSCALL))
|
(xOpcode==`MISC && (xFunc==`SYSCALL))
|
)
|
)
|
;
|
;
|
wire xIsStore = (
|
wire xIsStore = (
|
xOpcode==`SW || xOpcode==`SH || xOpcode==`SB || xOpcode==`SC || xOpcode==`SWC || xOpcode==`SM ||
|
xOpcode==`SW || xOpcode==`SH || xOpcode==`SB || xOpcode==`SC || xOpcode==`SWC || xOpcode==`SM ||
|
xOpcode==`SF || xOpcode==`SFD || xOpcode==`SP || xOpcode==`SFP || xOpcode==`SFDP ||
|
xOpcode==`SF || xOpcode==`SFD || xOpcode==`SP || xOpcode==`SFP || xOpcode==`SFDP ||
|
xOpcode==`SSH || xOpcode==`SSW || xOpcode==`STBC ||
|
xOpcode==`SSH || xOpcode==`SSW || xOpcode==`STBC ||
|
(xOpcode==`MEMNDX && (
|
(xOpcode==`MEMNDX && (
|
xFunc6==`SWX || xFunc6==`SHX || xFunc6==`SBX || xFunc6==`SCX || xFunc6==`SWCX ||
|
xFunc6==`SWX || xFunc6==`SHX || xFunc6==`SBX || xFunc6==`SCX || xFunc6==`SWCX ||
|
xFunc6==`SFX || xFunc6==`SFDX || xFunc6==`SPX ||
|
xFunc6==`SFX || xFunc6==`SFDX || xFunc6==`SPX ||
|
xFunc6==`SSHX || xFunc6==`SSWX
|
xFunc6==`SSHX || xFunc6==`SSWX
|
))
|
))
|
)
|
)
|
;
|
;
|
wire xIsSWC = xOpcode==`SWC;
|
wire xIsSWC = xOpcode==`SWC;
|
wire xIsIn = (
|
wire xIsIn = (
|
xOpcode==`INW || xOpcode==`INH || xOpcode==`INCH || xOpcode==`INB ||
|
xOpcode==`INW || xOpcode==`INH || xOpcode==`INCH || xOpcode==`INB ||
|
xOpcode==`INHU || xOpcode==`INCU || xOpcode==`INBU ||
|
xOpcode==`INHU || xOpcode==`INCU || xOpcode==`INBU ||
|
(xOpcode==`MEMNDX && (
|
(xOpcode==`MEMNDX && (
|
xFunc6==`INWX || xFunc6==`INHX || xFunc6==`INCX || xFunc6==`INBX ||
|
xFunc6==`INWX || xFunc6==`INHX || xFunc6==`INCX || xFunc6==`INBX ||
|
xFunc6==`INHUX || xFunc6==`INCUX || xFunc6==`INBUX
|
xFunc6==`INHUX || xFunc6==`INCUX || xFunc6==`INBUX
|
))
|
))
|
)
|
)
|
;
|
;
|
wire xIsOut = (
|
wire xIsOut = (
|
xOpcode==`OUTW || xOpcode==`OUTH || xOpcode==`OUTC || xOpcode==`OUTB ||
|
xOpcode==`OUTW || xOpcode==`OUTH || xOpcode==`OUTC || xOpcode==`OUTB ||
|
(xOpcode==`MEMNDX && (
|
(xOpcode==`MEMNDX && (
|
xFunc6==`OUTWX || xFunc6==`OUTHX || xFunc6==`OUTCX || xFunc6==`OUTBX
|
xFunc6==`OUTWX || xFunc6==`OUTHX || xFunc6==`OUTCX || xFunc6==`OUTBX
|
)))
|
)))
|
;
|
;
|
//wire mIsSWC = mOpcode==`SWC;
|
//wire mIsSWC = mOpcode==`SWC;
|
//reg m1IsIn;
|
//reg m1IsIn;
|
|
|
wire m2IsInW = m2Opcode==`INW;
|
wire m2IsInW = m2Opcode==`INW;
|
wire xIsIO = xIsIn || xIsOut;
|
wire xIsIO = xIsIn || xIsOut;
|
wire m1IsIO = m1IsIn || m1IsOut;
|
wire m1IsIO = m1IsIn || m1IsOut;
|
wire xIsSetmid = xOpcode==`SETMID;
|
wire xIsSetmid = xOpcode==`SETMID;
|
|
|
wire xIsFPLoo = xOpcode==`FPLOO;
|
wire xIsFPLoo = xOpcode==`FPLOO;
|
wire xIsFP = xOpcode==`FP;
|
wire xIsFP = xOpcode==`FP;
|
wire xIsSIMD = xOpcode==`SIMD;
|
wire xIsSIMD = xOpcode==`SIMD;
|
wire xneedBus = xIsIO;
|
wire xneedBus = xIsIO;
|
//wire m1needBus = (m1IsLoad & !m1IsCacheElement) || m1IsStore || m1IsIO;
|
//wire m1needBus = (m1IsLoad & !m1IsCacheElement) || m1IsStore || m1IsIO;
|
wire m1needBus = m1IsLoad || m1IsStore || m1IsIO;
|
wire m1needBus = m1IsLoad || m1IsStore || m1IsIO;
|
wire m2needBus = m2IsLoad || m2IsStore;
|
wire m2needBus = m2IsLoad || m2IsStore;
|
|
|
wire xRtz = xRt[4:0]==5'd0;
|
wire xRtz = xRt[4:0]==5'd0;
|
wire m1Rtz = m1Rt[4:0]==5'd0;
|
wire m1Rtz = m1Rt[4:0]==5'd0;
|
wire m2Rtz = m2Rt[4:0]==5'd0;
|
wire m2Rtz = m2Rt[4:0]==5'd0;
|
wire wRtz = wRt[4:0]==5'd0;
|
wire wRtz = wRt[4:0]==5'd0;
|
wire tRtz = tRt[4:0]==5'd0;
|
wire tRtz = tRt[4:0]==5'd0;
|
|
|
//wire StallI = dIsLSPair & ~dIR[15];
|
//wire StallI = dIsLSPair & ~dIR[15];
|
wire intPending = (nmi_edge & ~StatusHWI) || (irq_i & ~im & ~StatusHWI); // || ITLBMiss
|
wire intPending = (nmi_edge & ~StatusHWI) || (irq_i & ~im & ~StatusHWI); // || ITLBMiss
|
|
|
// Check if there are results being forwarded, to allow the pipeline to empty if result
|
// Check if there are results being forwarded, to allow the pipeline to empty if result
|
// forwarding isn't needed.
|
// forwarding isn't needed.
|
wire tForwardingActive = (tRt==dRa || tRt==dRb || tRt==dRc) & !tRtz;
|
wire tForwardingActive = (tRt==dRa || tRt==dRb || tRt==dRc) & !tRtz;
|
wire wForwardingActive = (wRt==dRa || wRt==dRb || wRt==dRc) & !wRtz;
|
wire wForwardingActive = (wRt==dRa || wRt==dRb || wRt==dRc) & !wRtz;
|
wire m2ForwardingActive = (m2Rt==dRa || m2Rt==dRb || m2Rt==dRc) & !m2Rtz;
|
wire m2ForwardingActive = (m2Rt==dRa || m2Rt==dRb || m2Rt==dRc) & !m2Rtz;
|
wire m1ForwardingActive = (m1Rt==dRa || m1Rt==dRb || m1Rt==dRc) & !m1Rtz;
|
wire m1ForwardingActive = (m1Rt==dRa || m1Rt==dRb || m1Rt==dRc) & !m1Rtz;
|
wire xForwardingActive = (xRt==dRa || xRt==dRb || xRt==dRc) & !xRtz;
|
wire xForwardingActive = (xRt==dRa || xRt==dRb || xRt==dRc) & !xRtz;
|
wire memCycleActive = ((iocyc_o & !(ack_i|err_i)) || (cyc_o & !(ack_i|err_i)));
|
wire memCycleActive = ((iocyc_o & !(ack_i1|err_i)) || (cyc_o & !(ack_i1|err_i)));
|
wire StallI = 1'b0;
|
wire StallI = 1'b0;
|
|
|
// Stall on SWC allows rsf flag to be loaded for the next instruction
|
// Stall on SWC allows rsf flag to be loaded for the next instruction
|
// Could check for dRa,dRb,dRc==0, for non-stalling
|
// Could check for dRa,dRb,dRc==0, for non-stalling
|
wire StallR = ((( xIsLoad||xIsIn||xIsCnt) && xForwardingActive) || xIsSWC) ||
|
wire StallR = ((( xIsLoad||xIsIn||xIsCnt) && xForwardingActive) || xIsSWC) ||
|
(((m1IsLoad||m1IsIn||m1IsCnt) && m1ForwardingActive)) ||
|
(((m1IsLoad||m1IsIn||m1IsCnt) && m1ForwardingActive)) ||
|
(((m2IsLoad||m2IsCnt) && m2ForwardingActive))
|
(((m2IsLoad||m2IsCnt) && m2ForwardingActive))
|
;
|
;
|
wire StallX = ((xneedBus||xIsLoad||xIsStore) & (m1needBus|m2needBus|icaccess));
|
wire StallX = ((xneedBus||xIsLoad||xIsStore) & (m1needBus|m2needBus|icaccess));
|
wire StallM1 = (m1needBus & (m2needBus|icaccess)) ||
|
wire StallM1 = (m1needBus & (m2needBus|icaccess)) ||
|
( m1IsLoad & m1IsCacheElement & (m2IsStore|wIsStore)) || // wait for a preceding store to complete
|
( m1IsLoad & m1IsCacheElement & (m2IsStore|wIsStore)) || // wait for a preceding store to complete
|
memCycleActive
|
memCycleActive
|
;
|
;
|
// We need to stall the pipeline stages *after* the memory load so that result forwarding
|
// We need to stall the pipeline stages *after* the memory load so that result forwarding
|
// isn't lost during a data cache load.
|
// isn't lost during a data cache load.
|
wire StallM2 = (m2needBus & icaccess) || (m2ForwardingActive && (((m1IsLoad & m1IsCacheElement & !dhit) || memCycleActive)));
|
wire StallM2 = (m2needBus & icaccess) || (m2ForwardingActive && (((m1IsLoad & m1IsCacheElement & !dhit) || memCycleActive)));
|
wire StallW = (wForwardingActive && ((m1IsLoad & m1IsCacheElement & !dhit) || memCycleActive));
|
wire StallW = (wForwardingActive && ((m1IsLoad & m1IsCacheElement & !dhit) || memCycleActive));
|
wire StallT = (tForwardingActive && ((m1IsLoad & m1IsCacheElement & !dhit) || memCycleActive)) || dcaccess;
|
wire StallT = (tForwardingActive && ((m1IsLoad & m1IsCacheElement & !dhit) || memCycleActive)) || dcaccess;
|
|
|
assign advanceT = (state==RUN) && !StallT;
|
assign advanceT = (state==RUN) && !StallT;
|
assign advanceW = advanceT & !StallW;
|
assign advanceW = advanceT & !StallW;
|
assign advanceM2 = advanceW && (cyc_o ? (ack_i|err_i) : 1'b1) && !StallM2;
|
assign advanceM2 = advanceW && (cyc_o ? (ack_i1|err_i) : 1'b1) && !StallM2;
|
assign advanceM1 = advanceM2 &
|
assign advanceM1 = advanceM2 &
|
(iocyc_o ? (ack_i|err_i) : 1'b1) &
|
(iocyc_o ? (ack_i1|err_i) : 1'b1) &
|
((m1IsLoad & m1IsCacheElement) ? dhit : 1'b1) &
|
((m1IsLoad & m1IsCacheElement) ? dhit : 1'b1) &
|
!StallM1
|
!StallM1
|
;
|
;
|
assign advanceX = advanceM1 & (
|
assign advanceX = advanceM1 & (
|
xIsSqrt ? sqrt_done :
|
xIsSqrt ? sqrt_done :
|
xIsMult ? mult_done :
|
xIsMult ? mult_done :
|
xIsDiv ? div_done :
|
xIsDiv ? div_done :
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
xIsFPLoo ? fpLooDone :
|
xIsFPLoo ? fpLooDone :
|
xIsFP ? fltdone :
|
xIsFP ? fltdone :
|
`endif
|
`endif
|
`ifdef SIMD
|
`ifdef SIMD
|
xIsSIMD ? fltdone :
|
xIsSIMD ? fltdone :
|
`endif
|
`endif
|
1'b1) &
|
1'b1) &
|
!StallX;
|
!StallX;
|
assign advanceR = advanceX & !StallR;
|
assign advanceR = advanceX & !StallR;
|
assign advanceI = advanceR & (ICacheAct ? ihit : ibufrdy) & !StallI;
|
assign advanceI = advanceR & (ICacheAct ? ihit : ibufrdy) & !StallI;
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Cache loading control
|
// Cache loading control
|
//
|
//
|
// There are two triggers for instruction loading depending on whether or not
|
// There are two triggers for instruction loading depending on whether or not
|
// the icache is active.
|
// the icache is active.
|
// For the instruction cache load we wait until there are no more memory or
|
// For the instruction cache load we wait until there are no more memory or
|
// I/O operations active. An instruction cache load is taking place and that
|
// I/O operations active. An instruction cache load is taking place and that
|
// cost is probably at least a dozen cycles (8*memory clocks+3latency).
|
// cost is probably at least a dozen cycles (8*memory clocks+3latency).
|
// In the data cache case we know that there is a memory operation about to
|
// In the data cache case we know that there is a memory operation about to
|
// execute in the M1 stage because it's the data cache miss instruction. So
|
// execute in the M1 stage because it's the data cache miss instruction. So
|
// there are no other memory operations active. We wait for the prior operation
|
// there are no other memory operations active. We wait for the prior operation
|
// to clear from the M2 stage.
|
// to clear from the M2 stage.
|
// The point is to avoid a memory operation colliding with cache access. We
|
// The point is to avoid a memory operation colliding with cache access. We
|
// could maybe just test for the stb_o line but it gets complex.
|
// could maybe just test for the stb_o line but it gets complex.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
wire pipelineEmpty = (dOpcode==`NOPI) && // and the pipeline is flushed
|
wire pipelineEmpty = (dOpcode==`NOPI) && // and the pipeline is flushed
|
(xOpcode==`NOPI) &&
|
(xOpcode==`NOPI) &&
|
(m1Opcode==`NOPI) &&
|
(m1Opcode==`NOPI) &&
|
(m2Opcode==`NOPI)
|
(m2Opcode==`NOPI)
|
;
|
;
|
wire triggerDCacheLoad = (m1IsLoad & m1IsCacheElement & !dhit) && // there is a miss
|
wire triggerDCacheLoad = (m1IsLoad & m1IsCacheElement & !dhit) && // there is a miss
|
!(icaccess | dcaccess) && // caches are not active
|
!(icaccess | dcaccess) && // caches are not active
|
(m2Opcode==`NOPI); // and the pipeline is free of memory-ops
|
(m2Opcode==`NOPI); // and the pipeline is free of memory-ops
|
|
|
wire triggerICacheLoad1 = ICacheAct && !ihit && !triggerDCacheLoad && // There is a miss
|
wire triggerICacheLoad1 = ICacheAct && !ihit && !triggerDCacheLoad && // There is a miss
|
!(icaccess | dcaccess) && // caches are not active
|
!(icaccess | dcaccess) && // caches are not active
|
pipelineEmpty;
|
pipelineEmpty;
|
wire triggerICacheLoad2 = (!ICacheAct && !ibufrdy) && !triggerDCacheLoad && // There is a miss
|
wire triggerICacheLoad2 = (!ICacheAct && !ibufrdy) && !triggerDCacheLoad && // There is a miss
|
!(icaccess | dcaccess) && // caches are not active
|
!(icaccess | dcaccess) && // caches are not active
|
pipelineEmpty;
|
pipelineEmpty;
|
|
|
wire triggerICacheLoad = triggerICacheLoad1 | triggerICacheLoad2;
|
wire triggerICacheLoad = triggerICacheLoad1 | triggerICacheLoad2;
|
|
|
wire EXexception_pending = ovr_error || dbz_error || priv_violation || xOpcode==`TRAPcci || xOpcode==`TRAPcc;
|
wire EXexception_pending = ovr_error || dbz_error || priv_violation || xOpcode==`TRAPcci || xOpcode==`TRAPcc;
|
`ifdef TLB
|
`ifdef TLB
|
wire M1exception_pending = advanceM1 & (m1IsLoad|m1IsStore) & DTLBMiss;
|
wire M1exception_pending = advanceM1 & (m1IsLoad|m1IsStore) & DTLBMiss;
|
`else
|
`else
|
wire M1exception_pending = 1'b0;
|
wire M1exception_pending = 1'b0;
|
`endif
|
`endif
|
wire exception_pending = EXexception_pending | M1exception_pending;
|
wire exception_pending = EXexception_pending | M1exception_pending;
|
|
|
reg prev_nmi,nmi_edge;
|
reg prev_nmi,nmi_edge;
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Register file.
|
// Register file.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
|
wire [63:0] nxt_a, nxt_b, nxt_c;
|
wire [63:0] nxt_a, nxt_b, nxt_c;
|
wire [8:0] nxt_Ra,nxt_Rb,nxt_Rc;
|
wire [8:0] nxt_Ra,nxt_Rb,nxt_Rc;
|
|
|
Raptor64_SetOperandRegs u7
|
Raptor64_SetOperandRegs u7
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
.advanceI(advanceI),
|
.advanceI(advanceI),
|
.advanceR(advanceR),
|
.advanceR(advanceR),
|
.advanceX(advanceX),
|
.advanceX(advanceX),
|
.b(b),
|
.b(b),
|
.AXC(AXC),
|
.AXC(AXC),
|
.xAXC(xAXC),
|
.xAXC(xAXC),
|
.insn(insn),
|
.insn(insn),
|
.xIR(xIR),
|
.xIR(xIR),
|
.dRa(dRa),
|
.dRa(dRa),
|
.dRb(dRb),
|
.dRb(dRb),
|
.dRc(dRc),
|
.dRc(dRc),
|
.nxt_Ra(nxt_Ra),
|
.nxt_Ra(nxt_Ra),
|
.nxt_Rb(nxt_Rb),
|
.nxt_Rb(nxt_Rb),
|
.nxt_Rc(nxt_Rc)
|
.nxt_Rc(nxt_Rc)
|
);
|
);
|
|
|
syncRam512x64_1rw3r u5
|
syncRam512x64_1rw3r u5
|
(
|
(
|
.wrst(1'b0),
|
.wrst(1'b0),
|
.wclk(clk),
|
.wclk(clk),
|
.wce(1'b1), // advanceW
|
.wce(1'b1), // advanceW
|
.we(1'b1),
|
.we(1'b1),
|
.wadr(wRt),
|
.wadr(wRt),
|
.i(wData),
|
.i(wData),
|
.wo(),
|
.wo(),
|
|
|
.rrsta(1'b0),
|
.rrsta(1'b0),
|
.rclka(~clk),
|
.rclka(~clk),
|
.rcea(advanceR),
|
.rcea(advanceR),
|
.radra(dRa),
|
.radra(dRa),
|
.roa(rfoa),
|
.roa(rfoa),
|
|
|
.rrstb(1'b0),
|
.rrstb(1'b0),
|
.rclkb(~clk),
|
.rclkb(~clk),
|
.rceb(advanceR),
|
.rceb(advanceR),
|
.radrb(dRb),
|
.radrb(dRb),
|
.rob(rfob),
|
.rob(rfob),
|
|
|
.rrstc(1'b0),
|
.rrstc(1'b0),
|
.rclkc(~clk),
|
.rclkc(~clk),
|
.rcec(advanceR),
|
.rcec(advanceR),
|
.radrc(dRc),
|
.radrc(dRc),
|
.roc(rfoc)
|
.roc(rfoc)
|
);
|
);
|
|
|
Raptor64_BypassMux u8
|
Raptor64_BypassMux u8
|
(
|
(
|
.dpc(dpc),
|
.dpc(dpc),
|
.dRn(dRa),
|
.dRn(dRa),
|
.xRt(xRt),
|
.xRt(xRt),
|
.m1Rt(m1Rt),
|
.m1Rt(m1Rt),
|
.m2Rt(m2Rt),
|
.m2Rt(m2Rt),
|
.wRt(wRt),
|
.wRt(wRt),
|
.tRt(tRt),
|
.tRt(tRt),
|
.rfo(rfoa),
|
.rfo(rfoa),
|
.xData(xData),
|
.xData(xData),
|
.m1Data(m1Data),
|
.m1Data(m1Data),
|
.m2Data(m2Data),
|
.m2Data(m2Data),
|
.wData(wData),
|
.wData(wData),
|
.tData(tData),
|
.tData(tData),
|
.nxt(nxt_a)
|
.nxt(nxt_a)
|
);
|
);
|
|
|
Raptor64_BypassMux u25
|
Raptor64_BypassMux u25
|
(
|
(
|
.dpc(dpc),
|
.dpc(dpc),
|
.dRn(dRb),
|
.dRn(dRb),
|
.xRt(xRt),
|
.xRt(xRt),
|
.m1Rt(m1Rt),
|
.m1Rt(m1Rt),
|
.m2Rt(m2Rt),
|
.m2Rt(m2Rt),
|
.wRt(wRt),
|
.wRt(wRt),
|
.tRt(tRt),
|
.tRt(tRt),
|
.rfo(rfob),
|
.rfo(rfob),
|
.xData(xData),
|
.xData(xData),
|
.m1Data(m1Data),
|
.m1Data(m1Data),
|
.m2Data(m2Data),
|
.m2Data(m2Data),
|
.wData(wData),
|
.wData(wData),
|
.tData(tData),
|
.tData(tData),
|
.nxt(nxt_b)
|
.nxt(nxt_b)
|
);
|
);
|
|
|
Raptor64_BypassMux u24
|
Raptor64_BypassMux u24
|
(
|
(
|
.dpc(dpc),
|
.dpc(dpc),
|
.dRn(dRc),
|
.dRn(dRc),
|
.xRt(xRt),
|
.xRt(xRt),
|
.m1Rt(m1Rt),
|
.m1Rt(m1Rt),
|
.m2Rt(m2Rt),
|
.m2Rt(m2Rt),
|
.wRt(wRt),
|
.wRt(wRt),
|
.tRt(tRt),
|
.tRt(tRt),
|
.rfo(rfoc),
|
.rfo(rfoc),
|
.xData(xData),
|
.xData(xData),
|
.m1Data(m1Data),
|
.m1Data(m1Data),
|
.m2Data(m2Data),
|
.m2Data(m2Data),
|
.wData(wData),
|
.wData(wData),
|
.tData(tData),
|
.tData(tData),
|
.nxt(nxt_c)
|
.nxt(nxt_c)
|
);
|
);
|
|
|
// We need to zero out xRt because it'll match in the operand bypass multiplexers if it isn't zeroed out.
|
// We need to zero out xRt because it'll match in the operand bypass multiplexers if it isn't zeroed out.
|
//Raptor64_SetTargetRegister u8
|
//Raptor64_SetTargetRegister u8
|
//(
|
//(
|
// .rst(rst_i),
|
// .rst(rst_i),
|
// .clk(clk),
|
// .clk(clk),
|
// .advanceR(advanceR),
|
// .advanceR(advanceR),
|
// .advanceX(advanceX),
|
// .advanceX(advanceX),
|
// .dIRvalid(dIRvalid),
|
// .dIRvalid(dIRvalid),
|
// .dIR(dIR),
|
// .dIR(dIR),
|
// .dAXC(dAXC),
|
// .dAXC(dAXC),
|
// .xRt(xRt)
|
// .xRt(xRt)
|
//);
|
//);
|
|
|
reg [5:0] pchi;
|
reg [5:0] pchi;
|
vtdl #(64,64) u23
|
vtdl #(64,64) u23
|
(
|
(
|
.clk(clk),
|
.clk(clk),
|
.ce(advanceI & pccap),
|
.ce(advanceI & pccap),
|
.a(pchi),
|
.a(pchi),
|
.d(pc),
|
.d(pc),
|
.q(pchistoric)
|
.q(pchistoric)
|
);
|
);
|
|
|
wire isxIRQ = ((xIR[15:7]>=`EX_IRQ && xIR[15:7] < `EX_IRQ+32) || xIR[15:7]==`EX_NMI) && xIR[16];
|
wire isxIRQ = ((xIR[15:7]>=`EX_IRQ && xIR[15:7] < `EX_IRQ+32) || xIR[15:7]==`EX_NMI) && xIR[16];
|
wire isPipeIRQ = dextype==`EX_NMI || (dextype>=`EX_IRQ && dextype < `EX_IRQ+32);
|
wire isPipeIRQ = dextype==`EX_NMI || (dextype>=`EX_IRQ && dextype < `EX_IRQ+32);
|
wire isxNonHWI = (xIR[15:7]!=`EX_NMI &&
|
wire isxNonHWI = (xIR[15:7]!=`EX_NMI &&
|
!(xIR[15:7]>=`EX_IRQ && xIR[15:7] < `EX_IRQ+32) &&
|
!(xIR[15:7]>=`EX_IRQ && xIR[15:7] < `EX_IRQ+32) &&
|
xIR[15:7]!=`EX_TLBI && xIR[15:7]!=`EX_TLBD);
|
xIR[15:7]!=`EX_TLBI && xIR[15:7]!=`EX_TLBD);
|
wire IRQinPipe = intPending || isPipeIRQ;
|
wire IRQinPipe = intPending || isPipeIRQ;
|
|
|
always @(posedge clk)
|
always @(posedge clk)
|
if (rst_i) begin
|
if (rst_i) begin
|
bte_o <= 2'b00;
|
bte_o <= 2'b00;
|
cti_o <= 3'b000;
|
cti_o <= 3'b000;
|
iocyc_o <= 1'b0;
|
iocyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
we_o <= 1'b0;
|
we_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
adr_o <= 64'd0;
|
adr_o <= 64'd0;
|
dat_o <= 64'd0;
|
dat_o <= 64'd0;
|
|
|
state <= RESET;
|
state <= RESET;
|
cstate <= IDLE;
|
cstate <= IDLE;
|
pccap <= 1'b1;
|
pccap <= 1'b1;
|
nonICacheSeg <= 32'hFFFF_FFFD;
|
nonICacheSeg <= 32'hFFFF_FFFD;
|
TBA <= 64'd0;
|
TBA <= 64'd0;
|
pc <= `RESET_VECTOR;
|
pc <= `RESET_VECTOR;
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
m1IR <= `NOP_INSN;
|
m1IR <= `NOP_INSN;
|
m2IR <= `NOP_INSN;
|
m2IR <= `NOP_INSN;
|
wIR <= `NOP_INSN;
|
wIR <= `NOP_INSN;
|
m1IsLoad <= 1'b0;
|
m1IsLoad <= 1'b0;
|
m1IsStore <= 1'b0;
|
m1IsStore <= 1'b0;
|
m2IsLoad <= 1'b0;
|
m2IsLoad <= 1'b0;
|
m2IsStore <= 1'b0;
|
m2IsStore <= 1'b0;
|
wIsStore <= 1'b0;
|
wIsStore <= 1'b0;
|
m1IsOut <= 1'b0;
|
m1IsOut <= 1'b0;
|
m1IsIn <= 1'b0;
|
m1IsIn <= 1'b0;
|
tRt <= 9'd0;
|
tRt <= 9'd0;
|
wRt <= 9'd0;
|
wRt <= 9'd0;
|
m1Rt <= 9'd0;
|
m1Rt <= 9'd0;
|
m2Rt <= 9'd0;
|
m2Rt <= 9'd0;
|
tData <= 64'd0;
|
tData <= 64'd0;
|
wData <= 64'd0;
|
wData <= 64'd0;
|
m1Data <= 64'd0;
|
m1Data <= 64'd0;
|
m2Data <= 64'd0;
|
m2Data <= 64'd0;
|
|
wData <= 64'd0;
|
icaccess <= 1'b0;
|
icaccess <= 1'b0;
|
dcaccess <= 1'b0;
|
dcaccess <= 1'b0;
|
wFip <= 1'b0;
|
wFip <= 1'b0;
|
m2Fip <= 1'b0;
|
m2Fip <= 1'b0;
|
m1Fip <= 1'b0;
|
m1Fip <= 1'b0;
|
xFip <= 1'b0;
|
xFip <= 1'b0;
|
dFip <= 1'b0;
|
dFip <= 1'b0;
|
dirqf <= 1'b0;
|
dirqf <= 1'b0;
|
|
inta <= 1'b0;
|
dNmi <= 1'b0;
|
dNmi <= 1'b0;
|
xNmi <= 1'b0;
|
xNmi <= 1'b0;
|
m1Nmi <= 1'b0;
|
m1Nmi <= 1'b0;
|
m2Nmi <= 1'b0;
|
m2Nmi <= 1'b0;
|
tick <= 64'd0;
|
tick <= 64'd0;
|
cstate <= IDLE;
|
cstate <= IDLE;
|
dAXC <= 4'd0;
|
dAXC <= 4'd0;
|
xAXC <= 4'd0;
|
xAXC <= 4'd0;
|
m1AXC <= 4'd0;
|
m1AXC <= 4'd0;
|
m2AXC <= 4'd0;
|
m2AXC <= 4'd0;
|
wAXC <= 4'd0;
|
wAXC <= 4'd0;
|
xirqf <= 1'b0;
|
xirqf <= 1'b0;
|
dextype <= 9'h00;
|
dextype <= 9'h00;
|
xextype <= 9'h00;
|
xextype <= 9'h00;
|
m1extype <= 9'h00;
|
m1extype <= 9'h00;
|
m2extype <= 9'h00;
|
m2extype <= 9'h00;
|
wextype <= 9'h00;
|
wextype <= 9'h00;
|
textype <= 9'h00;
|
textype <= 9'h00;
|
xpc <= 64'd0;
|
xpc <= 64'd0;
|
a <= 64'd0;
|
a <= 64'd0;
|
b <= 64'd0;
|
b <= 64'd0;
|
imm <= 64'd0;
|
imm <= 64'd0;
|
clk_en <= 1'b1;
|
clk_en <= 1'b1;
|
StatusEXL <= 16'hFFFF;
|
StatusEXL <= 16'hFFFF;
|
StatusHWI <= 1'b0;
|
StatusHWI <= 1'b0;
|
mutex_gate <= 64'h0;
|
mutex_gate <= 64'h0;
|
dcache_on <= 1'b0;
|
dcache_on <= 1'b0;
|
ICacheOn <= 1'b0;
|
ICacheOn <= 1'b0;
|
ibufadr <= 64'h0;
|
ibufadr <= 64'h0;
|
m1IsCacheElement <= 1'b0;
|
m1IsCacheElement <= 1'b0;
|
dtinit <= 1'b1;
|
dtinit <= 1'b1;
|
ras_sp <= 6'd63;
|
ras_sp <= 6'd63;
|
im1 <= 1'b1;
|
im1 <= 1'b1;
|
// These must be non-zero in order to produce random numbers
|
// These must be non-zero in order to produce random numbers
|
// We set them here in case the user doesn't bother to set them.
|
// We set them here in case the user doesn't bother to set them.
|
m_z <= 64'h0123456789ABCDEF;
|
m_z <= 64'h0123456789ABCDEF;
|
m_w <= 64'h8888888877777777;
|
m_w <= 64'h8888888877777777;
|
insnkey <= 32'd0;
|
insnkey <= 32'd0;
|
LoadNOPs <= 1'b0;
|
LoadNOPs <= 1'b0;
|
eptr <= 8'h00;
|
eptr <= 8'h00;
|
ie_fuse <= 8'h00;
|
ie_fuse <= 8'h00;
|
end
|
end
|
else begin
|
else begin
|
|
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
// Initialize program counters
|
// Initialize program counters
|
// Initialize data tags to zero.
|
// Initialize data tags to zero.
|
// Initialize execution pattern register to zero.
|
// Initialize execution pattern register to zero.
|
|
// Initialize segment registers to zero.
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
case(state)
|
case(state)
|
RESET:
|
RESET:
|
begin
|
begin
|
pc <= `RESET_VECTOR;
|
$display("Resetting %h",adr_o[14:6]);
|
adr_o[14:6] <= adr_o[14:6]+9'd1;
|
adr_o[14:6] <= adr_o[14:6]+9'd1;
|
if (adr_o[14:6]==9'h1FF) begin
|
if (adr_o[14:6]==9'h1FF) begin
|
dtinit <= 1'b0;
|
dtinit <= 1'b0;
|
state <= RUN;
|
state <= RUN;
|
end
|
end
|
epat[a[7:0]] <= b[3:0]; /// b=0, to make this line the same as MTEP
|
epat[a[7:0]] <= b[3:0]; /// b=0, to make this line the same as MTEP
|
a[7:0] <= a[7:0] + 8'h1;
|
a[7:0] <= a[7:0] + 8'h1;
|
|
wIR[9:6] <= a[7:4];
|
|
wAXC <= wAXC + 4'd1;
|
|
segs[{wIR[9:6],wAXC}] <= wData; // same line as in WB stage, wData =0
|
end
|
end
|
RUN:
|
RUN:
|
begin
|
begin
|
|
|
ie_fuse <= {ie_fuse[6:0],ie_fuse[0]}; // shift counter
|
ie_fuse <= {ie_fuse[6:0],ie_fuse[0]}; // shift counter
|
|
|
tick <= tick + 64'd1;
|
tick <= tick + 64'd1;
|
|
$display("tick: %d", tick[31:0]);
|
|
|
prev_nmi <= nmi_i;
|
prev_nmi <= nmi_i;
|
if (!prev_nmi & nmi_i)
|
if (!prev_nmi & nmi_i)
|
nmi_edge <= 1'b1;
|
nmi_edge <= 1'b1;
|
|
|
|
|
`ifdef ADDRESS_RESERVATION
|
`ifdef ADDRESS_RESERVATION
|
// A store by any device in the system to a reserved address blcok
|
// A store by any device in the system to a reserved address blcok
|
// clears the reservation.
|
// clears the reservation.
|
|
|
if (sys_adv && sys_adr[63:5]==resv_address)
|
if (sys_adv && sys_adr[63:5]==resv_address)
|
resv_address <= 59'd0;
|
resv_address <= 59'd0;
|
`endif
|
`endif
|
|
|
wrhit <= 1'b0;
|
wrhit <= 1'b0;
|
|
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
// IFETCH:
|
// IFETCH:
|
// - check for external hardware interrupt
|
// - check for external hardware interrupt
|
// - fetch instruction
|
// - fetch instruction
|
// - increment PC
|
// - increment PC
|
// - set special register defaults for some instructions
|
// - set special register defaults for some instructions
|
// Outputs:
|
// Outputs:
|
// - d???? signals
|
// - d???? signals
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
if (advanceI) begin
|
if (advanceI) begin
|
dAXC <= AXC;
|
dAXC <= AXC;
|
dextype <= `EX_NON;
|
dextype <= `EX_NON;
|
// record instruction and associated pc value
|
// record instruction and associated pc value
|
dIR <= insn;
|
dIR <= insn;
|
dpc <= pc;
|
dpc <= pc;
|
dIm <= im;
|
dIm <= im;
|
dStatusHWI <= StatusHWI;
|
dStatusHWI <= StatusHWI;
|
// Interrupt: stomp on the incoming instruction and replace it with
|
// Interrupt: stomp on the incoming instruction and replace it with
|
// a system call.
|
// a system call.
|
if (nmi_edge & !StatusHWI) begin
|
if (nmi_edge & !StatusHWI) begin
|
$display("*****************");
|
$display("*****************");
|
$display("NMI edge detected");
|
$display("NMI edge detected");
|
$display("*****************");
|
$display("*****************");
|
dextype <= `EX_NMI;
|
dextype <= `EX_NMI;
|
dNmi <= 1'b1;
|
dNmi <= 1'b1;
|
dIR <= {`MISC,9'd0,`EX_NMI,`SYSCALL};
|
dIR <= {`MISC,9'd0,`EX_NMI,`SYSCALL};
|
end
|
end
|
else if (irq_i & !im & !StatusHWI) begin
|
else if (irq_i & !im & !StatusHWI) begin
|
$display("*****************");
|
$display("*****************");
|
$display("IRQ %d detected", irq_no);
|
$display("IRQ %d detected", irq_no);
|
$display("*****************");
|
$display("*****************");
|
dIR <= {`MISC,9'd0,irq_no,`SYSCALL};
|
dIR <= {`MISC,9'd0,irq_no,`SYSCALL};
|
$display("setting dIR=%h", {`MISC,9'd0,irq_no,`SYSCALL});
|
$display("setting dIR=%h", {`MISC,9'd0,irq_no,`SYSCALL});
|
dextype <= irq_no;
|
dextype <= irq_no;
|
end
|
end
|
`ifdef TLB
|
`ifdef TLB
|
// A TLB miss is treated like a hardware interrupt.
|
// A TLB miss is treated like a hardware interrupt.
|
else if (ITLBMiss) begin
|
else if (ITLBMiss) begin
|
$display("TLB miss on instruction fetch.");
|
$display("TLB miss on instruction fetch.");
|
dextype <= `EX_TLBI;
|
dextype <= `EX_TLBI;
|
dIR <= {`MISC,9'd0,`EX_TLBI,`SYSCALL};
|
dIR <= {`MISC,9'd0,`EX_TLBI,`SYSCALL};
|
BadVAddr <= pc[63:13];
|
BadVAddr <= pc[63:13];
|
end
|
end
|
`endif
|
`endif
|
// Are we filling the pipeline with NOP's as a result of a previous
|
// Are we filling the pipeline with NOP's as a result of a previous
|
// hardware interrupt ?
|
// hardware interrupt ?
|
else if (|dFip|LoadNOPs) begin
|
else if (|dFip|LoadNOPs) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
end
|
end
|
else begin
|
else begin
|
`include "insn_dumpsc.v"
|
`include "insn_dumpsc.v"
|
end
|
end
|
begin
|
begin
|
dbranch_taken <= 1'b0;
|
dbranch_taken <= 1'b0;
|
pc <= fnIncPC(pc);
|
pc <= fnIncPC(pc);
|
case(iOpcode)
|
case(iOpcode)
|
// We predict the return address by storing it in a return address stack
|
// We predict the return address by storing it in a return address stack
|
// during a call instruction, then popping it off the stack in a return
|
// during a call instruction, then popping it off the stack in a return
|
// instruction. The prediction will not always be correct, if it's wrong
|
// instruction. The prediction will not always be correct, if it's wrong
|
// it's corrected by the EX stage branching to the right address.
|
// it's corrected by the EX stage branching to the right address.
|
`CALL:
|
`CALL:
|
begin
|
begin
|
ras[ras_sp] <= fnIncPC(pc);
|
ras[ras_sp] <= fnIncPC(pc);
|
ras_sp <= ras_sp - 6'd1;
|
ras_sp <= ras_sp - 6'd1;
|
pc <= jmp_tgt;
|
pc <= jmp_tgt;
|
end
|
end
|
`RET:
|
`RET:
|
begin
|
begin
|
pc <= ras[ras_sp + 6'd1];
|
pc <= ras[ras_sp + 6'd1];
|
ras_sp <= ras_sp + 6'd1;
|
ras_sp <= ras_sp + 6'd1;
|
end
|
end
|
`JMP:
|
`JMP:
|
begin
|
begin
|
pc <= jmp_tgt;
|
pc <= jmp_tgt;
|
end
|
end
|
`BTRR:
|
`BTRR:
|
case(insn[4:0])
|
case(insn[4:0])
|
`BEQ,`BNE,`BLT,`BLE,`BGT,`BGE,`BLTU,`BLEU,`BGTU,`BGEU,`BAND,`BOR,`BRA,`BNR,`BRN,`LOOP:
|
`BEQ,`BNE,`BLT,`BLE,`BGT,`BGE,`BLTU,`BLEU,`BGTU,`BGEU,`BAND,`BOR,`BRA,`BNR,`BRN,`LOOP:
|
if (predict_taken) begin
|
if (predict_taken) begin
|
// $display("Taking predicted branch: %h",{pc[63:4] + {{42{insn[24]}},insn[24:7]},insn[6:5],2'b00});
|
// $display("Taking predicted branch: %h",{pc[63:4] + {{42{insn[24]}},insn[24:7]},insn[6:5],2'b00});
|
dbranch_taken <= 1'b1;
|
dbranch_taken <= 1'b1;
|
pc <= pc + {{52{insn[14]}},insn[14:5],2'b00};
|
pc <= pc + {{52{insn[14]}},insn[14:5],2'b00};
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
|
|
// If doing a JAL that stores a return address in the link register, save off the return address
|
// If doing a JAL that stores a return address in the link register, save off the return address
|
// in the return address predictor stack.
|
// in the return address predictor stack.
|
`JAL:
|
`JAL:
|
if (insn[19:15]==5'd31) begin
|
if (insn[19:15]==5'd31) begin
|
ras[ras_sp] <= fnIncPC(pc);
|
ras[ras_sp] <= fnIncPC(pc);
|
ras_sp <= ras_sp - 6'd1;
|
ras_sp <= ras_sp - 6'd1;
|
end
|
end
|
`ifdef BTB
|
`ifdef BTB
|
`JAL: pc <= btb[pc[7:2]];
|
`JAL: pc <= btb[pc[7:2]];
|
`BTRI:
|
`BTRI:
|
if (predict_taken) begin
|
if (predict_taken) begin
|
dbranch_taken <= 1'b1;
|
dbranch_taken <= 1'b1;
|
pc <= btb[pc[7:2]];
|
pc <= btb[pc[7:2]];
|
end
|
end
|
`endif
|
`endif
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
begin
|
begin
|
if (predict_taken) begin
|
if (predict_taken) begin
|
dbranch_taken <= 1'b1;
|
dbranch_taken <= 1'b1;
|
pc <= pc + {{50{insn[19]}},insn[19:8],2'b00};
|
pc <= pc + {{50{insn[19]}},insn[19:8],2'b00};
|
end
|
end
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
// Stage tail
|
// Stage tail
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
else if (advanceR) begin
|
else if (advanceR) begin
|
dextype <= #1 `EX_NON;
|
dextype <= #1 `EX_NON;
|
dIR <= #1 `NOP_INSN;
|
dIR <= #1 `NOP_INSN;
|
end
|
end
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// RFETCH:
|
// RFETCH:
|
// Register fetch stage
|
// Register fetch stage
|
//
|
//
|
// Inputs:
|
// Inputs:
|
// - d???? signals
|
// - d???? signals
|
// Outputs:
|
// Outputs:
|
// - x???? signals to EX stage
|
// - x???? signals to EX stage
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//
|
//
|
if (advanceR) begin
|
if (advanceR) begin
|
xIm <= dIm;
|
xIm <= dIm;
|
xNmi <= dNmi;
|
xNmi <= dNmi;
|
xStatusHWI <= dStatusHWI;
|
xStatusHWI <= dStatusHWI;
|
xAXC <= dAXC;
|
xAXC <= dAXC;
|
xFip <= dFip;
|
xFip <= dFip;
|
xextype <= dextype;
|
xextype <= dextype;
|
xpc <= dpc;
|
xpc <= dpc;
|
xbranch_taken <= dbranch_taken;
|
xbranch_taken <= dbranch_taken;
|
if (dOpcode==`R && dFunc==`MYST)
|
if (dOpcode==`R && dFunc==`MYST)
|
xIR <= nxt_c[31:0];
|
xIR <= nxt_c[31:0];
|
else
|
else
|
xIR <= dIR;
|
xIR <= dIR;
|
a <= nxt_a;
|
a <= nxt_a;
|
b <= nxt_b;
|
b <= nxt_b;
|
if (dOpcode==`SHFTI)
|
if (dOpcode==`SHFTI)
|
b <= {58'd0,dIR[14:9]};
|
b <= {58'd0,dIR[14:9]};
|
c <= nxt_c;
|
c <= nxt_c;
|
|
|
case(dOpcode)
|
case(dOpcode)
|
`BTRI:
|
`BTRI:
|
imm <= {{53{dIR[7]}},dIR[10:0]};
|
imm <= {{53{dIR[7]}},dIR[10:0]};
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
imm <= {{56{dIR[7]}},dIR[7:0]};
|
imm <= {{56{dIR[7]}},dIR[7:0]};
|
`MEMNDX:
|
`MEMNDX:
|
imm <= dIR[7:6];
|
imm <= dIR[7:6];
|
default:
|
default:
|
imm <= {{49{dIR[14]}},dIR[14:0]};
|
imm <= {{49{dIR[14]}},dIR[14:0]};
|
endcase
|
endcase
|
|
|
casex(dOpcode)
|
casex(dOpcode)
|
`MISC:
|
`MISC:
|
case(dFunc)
|
case(dFunc)
|
`SYSCALL: xRt <= 9'd0;
|
`SYSCALL: xRt <= 9'd0;
|
default: xRt <= 9'd0;
|
default: xRt <= 9'd0;
|
endcase
|
endcase
|
`R:
|
`R:
|
case(dFunc)
|
case(dFunc)
|
`MTSPR,`CMG,`CMGI,`EXEC:
|
`MTSPR,`CMG,`CMGI,`EXEC:
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
default: xRt <= {dAXC,dIR[19:15]};
|
default: xRt <= {dAXC,dIR[19:15]};
|
endcase
|
endcase
|
`MYST,`MUX: xRt <= {dAXC,dIR[ 9: 5]};
|
`MYST,`MUX: xRt <= {dAXC,dIR[ 9: 5]};
|
`SETLO: xRt <= {dAXC,dIR[26:22]};
|
`SETLO: xRt <= {dAXC,dIR[26:22]};
|
`SETMID: xRt <= {dAXC,dIR[26:22]};
|
`SETMID: xRt <= {dAXC,dIR[26:22]};
|
`SETHI: xRt <= {dAXC,dIR[26:22]};
|
`SETHI: xRt <= {dAXC,dIR[26:22]};
|
`RR,`FP: xRt <= {dAXC,dIR[14:10]};
|
`RR,`FP: xRt <= {dAXC,dIR[14:10]};
|
`BTRI: xRt <= 9'd0;
|
`BTRI: xRt <= 9'd0;
|
`BTRR:
|
`BTRR:
|
case(dIR[4:0])
|
case(dIR[4:0])
|
`LOOP: xRt <= {dAXC,dIR[19:15]};
|
`LOOP: xRt <= {dAXC,dIR[19:15]};
|
default: xRt <= 9'd0;
|
default: xRt <= 9'd0;
|
endcase
|
endcase
|
`TRAPcc: xRt <= 9'd0;
|
`TRAPcc: xRt <= 9'd0;
|
`TRAPcci: xRt <= 9'd0;
|
`TRAPcci: xRt <= 9'd0;
|
`JMP: xRt <= 9'd00;
|
`JMP: xRt <= 9'd00;
|
`CALL: xRt <= {dAXC,5'd31};
|
`CALL: xRt <= {dAXC,5'd31};
|
`RET: xRt <= {dAXC,5'd30};
|
`RET: xRt <= {dAXC,5'd30};
|
`MEMNDX:
|
`MEMNDX:
|
case(dFunc[5:0])
|
case(dFunc[5:0])
|
`LSHX,`LSWX,
|
`LSHX,`LSWX,
|
`SWX,`SHX,`SCX,`SBX,`SFX,`SFDX,`SPX,`SFPX,`SFDPX,`SSHX,`SSWX,
|
`SWX,`SHX,`SCX,`SBX,`SFX,`SFDX,`SPX,`SFPX,`SFDPX,`SSHX,`SSWX,
|
`OUTWX,`OUTHX,`OUTCX,`OUTBX:
|
`OUTWX,`OUTHX,`OUTCX,`OUTBX:
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
default: xRt <= {dAXC,dIR[14:10]};
|
default: xRt <= {dAXC,dIR[14:10]};
|
endcase
|
endcase
|
`LSH,`LSW,
|
`LSH,`LSW,
|
`SW,`SH,`SC,`SB,`SF,`SFD,`SSH,`SSW,`SP,`SFP,`SFDP, // but not SWC!
|
`SW,`SH,`SC,`SB,`SF,`SFD,`SSH,`SSW,`SP,`SFP,`SFDP, // but not SWC!
|
`OUTW,`OUTH,`OUTC,`OUTB:
|
`OUTW,`OUTH,`OUTC,`OUTB:
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
`NOPI: xRt <= 9'd0;
|
`NOPI: xRt <= 9'd0;
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
default: xRt <= {dAXC,dIR[19:15]};
|
default: xRt <= {dAXC,dIR[19:15]};
|
endcase
|
endcase
|
|
|
// if (dIsLSPair & ~dIR[15])
|
// if (dIsLSPair & ~dIR[15])
|
// dIR <= dIR|32'h8000;
|
// dIR <= dIR|32'h8000;
|
end
|
end
|
// Stage tail
|
// Stage tail
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
else if (advanceX) begin
|
else if (advanceX) begin
|
xRt <= #1 9'd0;
|
xRt <= #1 9'd0;
|
xextype <= #1 `EX_NON;
|
xextype <= #1 `EX_NON;
|
xIR <= #1 `NOP_INSN;
|
xIR <= #1 `NOP_INSN;
|
xFip <= #1 1'b0;
|
xFip <= #1 1'b0;
|
end
|
end
|
|
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
// EXECUTE:
|
// EXECUTE:
|
// - perform datapath operation
|
// - perform datapath operation
|
// - perform virtual to physical address translation.
|
// - perform virtual to physical address translation.
|
// Outputs:
|
// Outputs:
|
// - m1???? signals to M1 stage
|
// - m1???? signals to M1 stage
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
if (advanceX) begin
|
if (advanceX) begin
|
m1StatusHWI <= xStatusHWI;
|
m1StatusHWI <= xStatusHWI;
|
m1Im <= xIm;
|
m1Im <= xIm;
|
m1Nmi <= xNmi;
|
m1Nmi <= xNmi;
|
m1extype <= xextype;
|
m1extype <= xextype;
|
m1Fip <= xFip;
|
m1Fip <= xFip;
|
m1pc <= xpc;
|
m1pc <= xpc;
|
m1IR <= xIR;
|
m1IR <= xIR;
|
m1IsCnt <= xIsCnt;
|
m1IsCnt <= xIsCnt;
|
m1IsLoad <= xIsLoad;
|
m1IsLoad <= xIsLoad;
|
m1IsStore <= xIsStore;
|
m1IsStore <= xIsStore;
|
m1IsOut <= xIsOut;
|
m1IsOut <= xIsOut;
|
m1IsIn <= xIsIn;
|
m1IsIn <= xIsIn;
|
m1Rt <= xRt;
|
m1Rt <= xRt;
|
m1Data <= xData;
|
m1Data <= xData;
|
m1IsCacheElement <= xisCacheElement;
|
m1IsCacheElement <= xisCacheElement;
|
m1AXC <= xAXC;
|
m1AXC <= xAXC;
|
if (xOpcode==`RR) begin
|
if (xOpcode==`RR) begin
|
if (xFunc6==`MOVZ && !aeqz) begin
|
if (xFunc6==`MOVZ && !aeqz) begin
|
m1Rt <= 9'd0;
|
m1Rt <= 9'd0;
|
m1Data <= 64'd0;
|
m1Data <= 64'd0;
|
end
|
end
|
if (xFunc6==`MOVNZ && aeqz) begin
|
if (xFunc6==`MOVNZ && aeqz) begin
|
m1Rt <= 9'd0;
|
m1Rt <= 9'd0;
|
m1Data <= 64'd0;
|
m1Data <= 64'd0;
|
end
|
end
|
if (xFunc6==`MOVPL && a[63]) begin
|
if (xFunc6==`MOVPL && a[63]) begin
|
m1Rt <= 9'd0;
|
m1Rt <= 9'd0;
|
m1Data <= 64'd0;
|
m1Data <= 64'd0;
|
end
|
end
|
if (xFunc6==`MOVMI && !a[63]) begin
|
if (xFunc6==`MOVMI && !a[63]) begin
|
m1Rt <= 9'd0;
|
m1Rt <= 9'd0;
|
m1Data <= 64'd0;
|
m1Data <= 64'd0;
|
end
|
end
|
end
|
end
|
|
|
begin
|
begin
|
case(xOpcode)
|
case(xOpcode)
|
`MISC:
|
`MISC:
|
case(xFunc)
|
case(xFunc)
|
`SEI: begin ie_fuse <= 8'h00; end
|
`SEI: begin ie_fuse <= 8'h00; end
|
`CLI: begin ie_fuse[0] <= 1'b1; end
|
`CLI: begin ie_fuse[0] <= 1'b1; end
|
`WAIT: m1clkoff <= 1'b1;
|
`WAIT: m1clkoff <= 1'b1;
|
`ICACHE_ON: ICacheOn <= 1'b1;
|
`ICACHE_ON: ICacheOn <= 1'b1;
|
`ICACHE_OFF: ICacheOn <= 1'b0;
|
`ICACHE_OFF: ICacheOn <= 1'b0;
|
`DCACHE_ON: dcache_on <= 1'b1;
|
`DCACHE_ON: dcache_on <= 1'b1;
|
`DCACHE_OFF: dcache_on <= 1'b0;
|
`DCACHE_OFF: dcache_on <= 1'b0;
|
`FIP: begin
|
`FIP: begin
|
// In case we stomped on am interrupt, we have to re-enable
|
// In case we stomped on am interrupt, we have to re-enable
|
// interrupts which were disable in the I-Stage. We go backwards
|
// interrupts which were disable in the I-Stage. We go backwards
|
// in time and set the interrupt status to what it used to be
|
// in time and set the interrupt status to what it used to be
|
// when this instruction is executed.
|
// when this instruction is executed.
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
dFip <= 1'b1;
|
dFip <= 1'b1;
|
xFip <= 1'b1;
|
xFip <= 1'b1;
|
m1Fip <= 1'b1;
|
m1Fip <= 1'b1;
|
end
|
end
|
`IEPP: begin
|
`IEPP: begin
|
eptr <= eptr + 8'd1;
|
eptr <= eptr + 8'd1;
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
dFip <= 1'b1;
|
dFip <= 1'b1;
|
xFip <= 1'b1;
|
xFip <= 1'b1;
|
m1Fip <= 1'b1;
|
m1Fip <= 1'b1;
|
end
|
end
|
`GRAN: begin
|
`GRAN: begin
|
rando <= rand;
|
rando <= rand;
|
m_z <= next_m_z;
|
m_z <= next_m_z;
|
m_w <= next_m_w;
|
m_w <= next_m_w;
|
end
|
end
|
`GRAFD: begin
|
`GRAFD: begin
|
rando <= randfd;
|
rando <= randfd;
|
m_z <= next_m_z;
|
m_z <= next_m_z;
|
m_w <= next_m_w;
|
m_w <= next_m_w;
|
end
|
end
|
`IRET:
|
`IRET:
|
if (StatusHWI) begin
|
if (StatusHWI) begin
|
StatusHWI <= 1'b0;
|
StatusHWI <= 1'b0;
|
ie_fuse[0] <= 1'b1;
|
ie_fuse[0] <= 1'b1;
|
pc <= IPC[xAXC]; //a;
|
pc <= IPC[xAXC]; //a;
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
end
|
end
|
`ERET:
|
`ERET:
|
if (StatusEXL[xAXC]) begin
|
if (StatusEXL[xAXC]) begin
|
StatusEXL[xAXC] <= 1'b0;
|
StatusEXL[xAXC] <= 1'b0;
|
pc <= EPC[xAXC];
|
pc <= EPC[xAXC];
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
end
|
end
|
// Note: we can't mask off the interrupts in the I-stage because this
|
// Note: we can't mask off the interrupts in the I-stage because this
|
// instruction might not be valid. Eg. a branch could occur causing
|
// instruction might not be valid. Eg. a branch could occur causing
|
// the instruction to not be executed. But we don't want to allow
|
// the instruction to not be executed. But we don't want to allow
|
// nested interrupts. We would need a stack of return addresses to
|
// nested interrupts. We would need a stack of return addresses to
|
// implement nested interrupts. We don't want a real IRQ that's following this
|
// implement nested interrupts. We don't want a real IRQ that's following this
|
// instruction in the pipeline to interfere with it's operation. So...
|
// instruction in the pipeline to interfere with it's operation. So...
|
// we check the pipeline and if if the IRQ SYSCALL is being followed by
|
// we check the pipeline and if if the IRQ SYSCALL is being followed by
|
// a real IRQ, then we merge the two IRQ's into a single one by aborting
|
// a real IRQ, then we merge the two IRQ's into a single one by aborting
|
// the IRQ SYSCALL. If nested interrupts were happening, the IRET at the
|
// the IRQ SYSCALL. If nested interrupts were happening, the IRET at the
|
// end of the real IRQ routine would re-enable interrupts too soon.
|
// end of the real IRQ routine would re-enable interrupts too soon.
|
`SYSCALL:
|
`SYSCALL:
|
begin
|
begin
|
if (isxIRQ && // Is this a software IRQ SYSCALL ?
|
if (isxIRQ && // Is this a software IRQ SYSCALL ?
|
IRQinPipe) begin // Is there an interrupt in the pipeline ? OR about to happen
|
IRQinPipe) begin // Is there an interrupt in the pipeline ? OR about to happen
|
m1IR <= `NOP_INSN; // Then turn this into a NOP
|
m1IR <= `NOP_INSN; // Then turn this into a NOP
|
m1Rt <= 9'd0;
|
m1Rt <= 9'd0;
|
end
|
end
|
else begin
|
else begin
|
if (isxNonHWI)
|
if (isxNonHWI)
|
StatusEXL[xAXC] <= 1'b1;
|
StatusEXL[xAXC] <= 1'b1;
|
else begin
|
else begin
|
StatusHWI <= 1'b1;
|
StatusHWI <= 1'b1;
|
ie_fuse <= 8'h00;
|
ie_fuse <= 8'h00;
|
if (xNmi)
|
if (xNmi)
|
nmi_edge <= 1'b0;
|
nmi_edge <= 1'b0;
|
end
|
end
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
ea <= {TBA[63:12],xIR[15:7],3'b000};
|
ea <= {TBA[63:12],xIR[15:7],3'b000};
|
LoadNOPs <= 1'b1;
|
LoadNOPs <= 1'b1;
|
$display("EX SYSCALL thru %h",{TBA[63:12],xIR[15:7],3'b000});
|
$display("EX SYSCALL thru %h",{TBA[63:12],xIR[15:7],3'b000});
|
end
|
end
|
end
|
end
|
`ifdef TLB
|
`ifdef TLB
|
`TLBP: ea <= TLBVirtPage;
|
`TLBP: ea <= TLBVirtPage;
|
`endif
|
`endif
|
default: ;
|
default: ;
|
endcase
|
endcase
|
`R:
|
`R:
|
case(xFunc6)
|
case(xFunc6)
|
`EXEC:
|
`EXEC:
|
begin
|
begin
|
pc <= fnIncPC(xpc);
|
pc <= fnIncPC(xpc);
|
dIR <= b;
|
dIR <= b;
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
end
|
end
|
`MTSPR:
|
`MTSPR:
|
begin
|
begin
|
case(xIR[11:6])
|
case(xIR[11:6])
|
`ifdef TLB
|
`ifdef TLB
|
`PageTableAddr: PageTableAddr <= a[63:13];
|
`PageTableAddr: PageTableAddr <= a[63:13];
|
`BadVAddr: BadVAddr <= a[63:13];
|
`BadVAddr: BadVAddr <= a[63:13];
|
`endif
|
`endif
|
`ASID: ASID <= a[7:0];
|
`ASID: ASID <= a[7:0];
|
`TBA: TBA <= {a[63:12],12'h000};
|
`TBA: TBA <= {a[63:12],12'h000};
|
`NON_ICACHE_SEG: nonICacheSeg <= a[63:32];
|
`NON_ICACHE_SEG: nonICacheSeg <= a[63:32];
|
`FPCR: rm <= a[31:30];
|
`FPCR: rm <= a[31:30];
|
`SRAND1: begin
|
`SRAND1: begin
|
m_z <= a;
|
m_z <= a;
|
end
|
end
|
`SRAND2: begin
|
`SRAND2: begin
|
m_w <= a;
|
m_w <= a;
|
end
|
end
|
`INSNKEY: insnkey <= a[31:0];
|
`INSNKEY: insnkey <= a[31:0];
|
`PCHI: pchi <= a[5:0];
|
`PCHI: pchi <= a[5:0];
|
default: ;
|
default: ;
|
endcase
|
endcase
|
end
|
end
|
`OMG: mutex_gate[a[5:0]] <= 1'b1;
|
`OMG: mutex_gate[a[5:0]] <= 1'b1;
|
`CMG: mutex_gate[a[5:0]] <= 1'b0;
|
`CMG: mutex_gate[a[5:0]] <= 1'b0;
|
`OMGI: mutex_gate[xIR[11:6]] <= 1'b1;
|
`OMGI: mutex_gate[xIR[11:6]] <= 1'b1;
|
`CMGI: mutex_gate[xIR[11:6]] <= 1'b0;
|
`CMGI: mutex_gate[xIR[11:6]] <= 1'b0;
|
default: ;
|
default: ;
|
endcase
|
endcase
|
`RR:
|
`RR:
|
case(xFunc6)
|
case(xFunc6)
|
`MTEP: epat[a[7:0]] <= b[3:0];
|
`MTEP: epat[a[7:0]] <= b[3:0];
|
|
`MTSEGI: m1IR[9:6] <= a[63:60];
|
default: ;
|
default: ;
|
endcase
|
endcase
|
// JMP and CALL change the program counter immediately in the IF stage.
|
// JMP and CALL change the program counter immediately in the IF stage.
|
// There's no work to do here. The pipeline does not need to be cleared.
|
// There's no work to do here. The pipeline does not need to be cleared.
|
`JMP: ;
|
`JMP: ;
|
`CALL: ;//m1Data <= fnIncPC(xpc);
|
`CALL: ;//m1Data <= fnIncPC(xpc);
|
|
|
`JAL:
|
`JAL:
|
`ifdef BTB
|
`ifdef BTB
|
if (dpc[63:2] != a[63:2] + imm[63:2]) begin
|
if (dpc[63:2] != a[63:2] + imm[63:2]) begin
|
pc[63:2] <= a[63:2] + imm[63:2];
|
pc[63:2] <= a[63:2] + imm[63:2];
|
btb[xpc[7:2]] <= {a[63:2] + imm[63:2],2'b00};
|
btb[xpc[7:2]] <= {a[63:2] + imm[63:2],2'b00};
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
end
|
end
|
`else
|
`else
|
begin
|
begin
|
pc[63:2] <= a[63:2] + imm[63:2];
|
pc[63:2] <= a[63:2] + imm[63:2];
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
end
|
end
|
`endif
|
`endif
|
// Check the pc of the instruction after the RET instruction (the dpc), to
|
// Check the pc of the instruction after the RET instruction (the dpc), to
|
// see if it's equal to the RET target. If it's the same as the target then
|
// see if it's equal to the RET target. If it's the same as the target then
|
// we predicted the RET return correctly, so there's nothing to do. Otherwise
|
// we predicted the RET return correctly, so there's nothing to do. Otherwise
|
// we need to branch to the RET location.
|
// we need to branch to the RET location.
|
`RET:
|
`RET:
|
if (dpc[63:2]!=b[63:2]) begin
|
if (dpc[63:2]!=b[63:2]) begin
|
pc[63:2] <= b[63:2];
|
pc[63:2] <= b[63:2];
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
end
|
end
|
`BTRR:
|
`BTRR:
|
case(xFunc5)
|
case(xFunc5)
|
// BEQ r1,r2,label
|
// BEQ r1,r2,label
|
`BEQ,`BNE,`BLT,`BLE,`BGT,`BGE,`BLTU,`BLEU,`BGTU,`BGEU,`BAND,`BOR,`BNR,`LOOP,`BRA,`BRN:
|
`BEQ,`BNE,`BLT,`BLE,`BGT,`BGE,`BLTU,`BLEU,`BGTU,`BGEU,`BAND,`BOR,`BNR,`LOOP,`BRA,`BRN:
|
if (!takb & xbranch_taken) begin
|
if (!takb & xbranch_taken) begin
|
$display("Taking mispredicted branch %h",fnIncPC(xpc));
|
$display("Taking mispredicted branch %h",fnIncPC(xpc));
|
pc <= fnIncPC(xpc);
|
pc <= fnIncPC(xpc);
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
end
|
end
|
else if (takb & !xbranch_taken) begin
|
else if (takb & !xbranch_taken) begin
|
$display("Taking branch %h",{xpc[63:2] + {{52{xIR[14]}},xIR[14:5]},2'b00});
|
$display("Taking branch %h",{xpc[63:2] + {{52{xIR[14]}},xIR[14:5]},2'b00});
|
pc[63:2] <= xpc[63:2] + {{52{xIR[14]}},xIR[14:5]};
|
pc[63:2] <= xpc[63:2] + {{52{xIR[14]}},xIR[14:5]};
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
end
|
end
|
// BEQ r1,r2,r10
|
// BEQ r1,r2,r10
|
`BEQR,`BNER,`BLTR,`BLER,`BGTR,`BGER,`BLTUR,`BLEUR,`BGTUR,`BGEUR://,`BANDR,`BORR,`BNRR:
|
`BEQR,`BNER,`BLTR,`BLER,`BGTR,`BGER,`BLTUR,`BLEUR,`BGTUR,`BGEUR://,`BANDR,`BORR,`BNRR:
|
if (takb) begin
|
if (takb) begin
|
pc[63:2] <= c[63:2];
|
pc[63:2] <= c[63:2];
|
pc[1:0] <= 2'b00;
|
pc[1:0] <= 2'b00;
|
`ifdef BTB
|
`ifdef BTB
|
btb[xpc[7:2]] <= c;
|
btb[xpc[7:2]] <= c;
|
`endif
|
`endif
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
// BEQ r1,#3,r10
|
// BEQ r1,#3,r10
|
`BTRI:
|
`BTRI:
|
`ifdef BTB
|
`ifdef BTB
|
if (takb) begin
|
if (takb) begin
|
if ((xbranch_taken && b[63:2]!=dpc[63:2]) || // took branch, but not to right target
|
if ((xbranch_taken && b[63:2]!=dpc[63:2]) || // took branch, but not to right target
|
!xbranch_taken) begin // didn't take branch, and were supposed to
|
!xbranch_taken) begin // didn't take branch, and were supposed to
|
pc[63:2] <= b[63:2];
|
pc[63:2] <= b[63:2];
|
pc[1:0] <= 2'b00;
|
pc[1:0] <= 2'b00;
|
btb[xpc[7:2]] <= b;
|
btb[xpc[7:2]] <= b;
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
end
|
end
|
end
|
end
|
else if (xbranch_taken) begin // took the branch, and weren't supposed to
|
else if (xbranch_taken) begin // took the branch, and weren't supposed to
|
pc <= fnIncPC(xpc);
|
pc <= fnIncPC(xpc);
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
end
|
end
|
`else
|
`else
|
if (takb) begin
|
if (takb) begin
|
pc[63:2] <= b[63:2];
|
pc[63:2] <= b[63:2];
|
pc[1:0] <= 2'b00;
|
pc[1:0] <= 2'b00;
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
end
|
end
|
`endif
|
`endif
|
// BEQI r1,#3,label
|
// BEQI r1,#3,label
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
if (takb) begin
|
if (takb) begin
|
if (!xbranch_taken) begin
|
if (!xbranch_taken) begin
|
pc[63:2] <= xpc[63:2] + {{50{xIR[19]}},xIR[19:8]};
|
pc[63:2] <= xpc[63:2] + {{50{xIR[19]}},xIR[19:8]};
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
if (xbranch_taken) begin
|
if (xbranch_taken) begin
|
$display("Taking mispredicted branch %h",fnIncPC(xpc));
|
$display("Taking mispredicted branch %h",fnIncPC(xpc));
|
pc <= fnIncPC(xpc);
|
pc <= fnIncPC(xpc);
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
end
|
end
|
end
|
end
|
`TRAPcc,`TRAPcci:
|
`TRAPcc,`TRAPcci:
|
if (takb) begin
|
if (takb) begin
|
StatusEXL[xAXC] <= 1'b1;
|
StatusEXL[xAXC] <= 1'b1;
|
xextype <= `EX_TRAP;
|
xextype <= `EX_TRAP;
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
LoadNOPs <= 1'b1;
|
LoadNOPs <= 1'b1;
|
end
|
end
|
|
|
`INW,`INH,`INHU,`INCH,`INCU,`INB,`INBU:
|
`INW,`INH,`INHU,`INCH,`INCU,`INB,`INBU:
|
begin
|
begin
|
iocyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= fnSelect(xOpcode,xData[2:0]);
|
sel_o <= fnSelect(xOpcode,xData[2:0]);
|
adr_o <= xData;
|
adr_o <= xData;
|
end
|
end
|
`OUTW:
|
`OUTW:
|
begin
|
begin
|
iocyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
sel_o <= fnSelect(xOpcode,xData[2:0]);
|
sel_o <= fnSelect(xOpcode,xData[2:0]);
|
adr_o <= xData;
|
adr_o <= xData;
|
dat_o <= b;
|
dat_o <= b;
|
end
|
end
|
`OUTH:
|
`OUTH:
|
begin
|
begin
|
iocyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
sel_o <= fnSelect(xOpcode,xData[2:0]);
|
sel_o <= fnSelect(xOpcode,xData[2:0]);
|
adr_o <= xData;
|
adr_o <= xData;
|
dat_o <= {2{b[31:0]}};
|
dat_o <= {2{b[31:0]}};
|
end
|
end
|
`OUTC:
|
`OUTC:
|
begin
|
begin
|
iocyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
sel_o <= fnSelect(xOpcode,xData[2:0]);
|
sel_o <= fnSelect(xOpcode,xData[2:0]);
|
adr_o <= xData;
|
adr_o <= xData;
|
dat_o <= {4{b[15:0]}};
|
dat_o <= {4{b[15:0]}};
|
end
|
end
|
`OUTB:
|
`OUTB:
|
begin
|
begin
|
iocyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
sel_o <= fnSelect(xOpcode,xData[2:0]);
|
sel_o <= fnSelect(xOpcode,xData[2:0]);
|
adr_o <= xData;
|
adr_o <= xData;
|
dat_o <= {8{b[7:0]}};
|
dat_o <= {8{b[7:0]}};
|
end
|
end
|
// `OUTBC:
|
// `OUTBC:
|
// begin
|
// begin
|
// iocyc_o <= 1'b1;
|
// iocyc_o <= 1'b1;
|
// stb_o <= 1'b1;
|
// stb_o <= 1'b1;
|
// we_o <= 1'b1;
|
// we_o <= 1'b1;
|
// case(xData1[2:0])
|
// case(xData1[2:0])
|
// 3'b000: sel_o <= 8'b00000001;
|
// 3'b000: sel_o <= 8'b00000001;
|
// 3'b001: sel_o <= 8'b00000010;
|
// 3'b001: sel_o <= 8'b00000010;
|
// 3'b010: sel_o <= 8'b00000100;
|
// 3'b010: sel_o <= 8'b00000100;
|
// 3'b011: sel_o <= 8'b00001000;
|
// 3'b011: sel_o <= 8'b00001000;
|
// 3'b100: sel_o <= 8'b00010000;
|
// 3'b100: sel_o <= 8'b00010000;
|
// 3'b101: sel_o <= 8'b00100000;
|
// 3'b101: sel_o <= 8'b00100000;
|
// 3'b110: sel_o <= 8'b01000000;
|
// 3'b110: sel_o <= 8'b01000000;
|
// 3'b111: sel_o <= 8'b10000000;
|
// 3'b111: sel_o <= 8'b10000000;
|
// endcase
|
// endcase
|
// adr_o <= xData1;
|
// adr_o <= xData1;
|
// dat_o <= {8{xIR[19:12]}};
|
// dat_o <= {8{xIR[19:12]}};
|
// end
|
// end
|
`LEA: begin
|
`LEA: begin
|
$display("LEA %h", xData);
|
$display("LEA %h", xData);
|
m1Data <= xData;
|
m1Data <= xData;
|
end
|
end
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWR,`LF,`LFD,`LM,`LSH,`LSW,`LP,`LFP,`LFDP,
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWR,`LF,`LFD,`LM,`LSH,`LSW,`LP,`LFP,`LFDP,
|
`SW,`SH,`SC,`SB,`SWC,`SF,`SFD,`SM,`SSW,`SP,`SFP,`SFDP:
|
`SW,`SH,`SC,`SB,`SWC,`SF,`SFD,`SM,`SSW,`SP,`SFP,`SFDP:
|
begin
|
begin
|
m1Data <= b;
|
m1Data <= b;
|
ea <= xData;
|
ea <= xData;
|
$display("EX MEMOP %h", xData);
|
$display("EX MEMOP %h", xData);
|
end
|
end
|
// `STBC:
|
// `STBC:
|
// begin
|
// begin
|
// m1Data <= {8{xIR[19:12]}};
|
// m1Data <= {8{xIR[19:12]}};
|
// ea <= xData1;
|
// ea <= xData1;
|
// end
|
// end
|
// `SSH: begin
|
// `SSH: begin
|
// case(xRt)
|
// case(xRt)
|
// `SR: m1Data <= {2{sr}};
|
// `SR: m1Data <= {2{sr}};
|
// default: m1Data <= 64'd0;
|
// default: m1Data <= 64'd0;
|
// endcase
|
// endcase
|
// ea <= xData1;
|
// ea <= xData1;
|
// end
|
// end
|
`CACHE:
|
`CACHE:
|
begin
|
begin
|
m1Data <= b;
|
m1Data <= b;
|
ea <= xData;
|
ea <= xData;
|
case(xIR[19:15])
|
case(xIR[19:15])
|
`INVIL: ; // handled in M1 stage
|
`INVIL: ; // handled in M1 stage
|
`INVIALL: tvalid <= 256'd0;
|
`INVIALL: tvalid <= 256'd0;
|
`ICACHEON: ICacheOn <= 1'b1;
|
`ICACHEON: ICacheOn <= 1'b1;
|
`ICACHEOFF: ICacheOn <= 1'b0;
|
`ICACHEOFF: ICacheOn <= 1'b0;
|
`DCACHEON: dcache_on <= 1'b1;
|
`DCACHEON: dcache_on <= 1'b1;
|
`DCACHEOFF: dcache_on <= 1'b0;
|
`DCACHEOFF: dcache_on <= 1'b0;
|
default: ;
|
default: ;
|
endcase
|
endcase
|
end
|
end
|
`MEMNDX:
|
`MEMNDX:
|
begin
|
begin
|
m1IR[31:25] <= 7'd32+xFunc6;
|
m1IR[31:25] <= 7'd32+xFunc6;
|
case(xFunc6)
|
case(xFunc6)
|
`LEAX:
|
`LEAX:
|
begin
|
begin
|
$display("LEAX %h", xData);
|
$display("LEAX %h", xData);
|
m1Data <= xData;
|
m1Data <= xData;
|
end
|
end
|
`INWX:
|
`INWX:
|
begin
|
begin
|
iocyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= 8'hFF;
|
sel_o <= 8'hFF;
|
adr_o <= xData;
|
adr_o <= xData;
|
end
|
end
|
`INHX,`INHUX:
|
`INHX,`INHUX:
|
begin
|
begin
|
iocyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= xData[2] ? 8'b11110000 : 8'b00001111;
|
sel_o <= xData[2] ? 8'b11110000 : 8'b00001111;
|
adr_o <= xData;
|
adr_o <= xData;
|
end
|
end
|
`INCX,`INCUX:
|
`INCX,`INCUX:
|
begin
|
begin
|
iocyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
case(xData[2:1])
|
case(xData[2:1])
|
2'b00: sel_o <= 8'b00000011;
|
2'b00: sel_o <= 8'b00000011;
|
2'b01: sel_o <= 8'b00001100;
|
2'b01: sel_o <= 8'b00001100;
|
2'b10: sel_o <= 8'b00110000;
|
2'b10: sel_o <= 8'b00110000;
|
2'b11: sel_o <= 8'b11000000;
|
2'b11: sel_o <= 8'b11000000;
|
endcase
|
endcase
|
adr_o <= xData;
|
adr_o <= xData;
|
end
|
end
|
`INBX,`INBUX:
|
`INBX,`INBUX:
|
begin
|
begin
|
iocyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
case(xData[2:0])
|
case(xData[2:0])
|
3'b000: sel_o <= 8'b00000001;
|
3'b000: sel_o <= 8'b00000001;
|
3'b001: sel_o <= 8'b00000010;
|
3'b001: sel_o <= 8'b00000010;
|
3'b010: sel_o <= 8'b00000100;
|
3'b010: sel_o <= 8'b00000100;
|
3'b011: sel_o <= 8'b00001000;
|
3'b011: sel_o <= 8'b00001000;
|
3'b100: sel_o <= 8'b00010000;
|
3'b100: sel_o <= 8'b00010000;
|
3'b101: sel_o <= 8'b00100000;
|
3'b101: sel_o <= 8'b00100000;
|
3'b110: sel_o <= 8'b01000000;
|
3'b110: sel_o <= 8'b01000000;
|
3'b111: sel_o <= 8'b10000000;
|
3'b111: sel_o <= 8'b10000000;
|
endcase
|
endcase
|
adr_o <= xData;
|
adr_o <= xData;
|
end
|
end
|
`OUTWX:
|
`OUTWX:
|
begin
|
begin
|
iocyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
sel_o <= 8'hFF;
|
sel_o <= 8'hFF;
|
adr_o <= xData;
|
adr_o <= xData;
|
dat_o <= c;
|
dat_o <= c;
|
end
|
end
|
`OUTHX:
|
`OUTHX:
|
begin
|
begin
|
iocyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
sel_o <= xData[2] ? 8'b11110000 : 8'b00001111;
|
sel_o <= xData[2] ? 8'b11110000 : 8'b00001111;
|
adr_o <= xData;
|
adr_o <= xData;
|
dat_o <= {2{c[31:0]}};
|
dat_o <= {2{c[31:0]}};
|
end
|
end
|
`OUTCX:
|
`OUTCX:
|
begin
|
begin
|
iocyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
case(xData[2:1])
|
case(xData[2:1])
|
2'b00: sel_o <= 8'b00000011;
|
2'b00: sel_o <= 8'b00000011;
|
2'b01: sel_o <= 8'b00001100;
|
2'b01: sel_o <= 8'b00001100;
|
2'b10: sel_o <= 8'b00110000;
|
2'b10: sel_o <= 8'b00110000;
|
2'b11: sel_o <= 8'b11000000;
|
2'b11: sel_o <= 8'b11000000;
|
endcase
|
endcase
|
adr_o <= xData;
|
adr_o <= xData;
|
dat_o <= {4{c[15:0]}};
|
dat_o <= {4{c[15:0]}};
|
end
|
end
|
`OUTBX:
|
`OUTBX:
|
begin
|
begin
|
iocyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
case(xData[2:0])
|
case(xData[2:0])
|
3'b000: sel_o <= 8'b00000001;
|
3'b000: sel_o <= 8'b00000001;
|
3'b001: sel_o <= 8'b00000010;
|
3'b001: sel_o <= 8'b00000010;
|
3'b010: sel_o <= 8'b00000100;
|
3'b010: sel_o <= 8'b00000100;
|
3'b011: sel_o <= 8'b00001000;
|
3'b011: sel_o <= 8'b00001000;
|
3'b100: sel_o <= 8'b00010000;
|
3'b100: sel_o <= 8'b00010000;
|
3'b101: sel_o <= 8'b00100000;
|
3'b101: sel_o <= 8'b00100000;
|
3'b110: sel_o <= 8'b01000000;
|
3'b110: sel_o <= 8'b01000000;
|
3'b111: sel_o <= 8'b10000000;
|
3'b111: sel_o <= 8'b10000000;
|
endcase
|
endcase
|
adr_o <= xData;
|
adr_o <= xData;
|
dat_o <= {8{c[7:0]}};
|
dat_o <= {8{c[7:0]}};
|
end
|
end
|
default:
|
default:
|
begin
|
begin
|
m1Data <= c;
|
m1Data <= c;
|
ea <= xData;
|
ea <= xData;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
end
|
end
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
if (xOpcode==`FP) begin
|
if (xOpcode==`FP) begin
|
case (xFunc6)
|
case (xFunc6)
|
`FDADD,`FDSUB:
|
`FDADD,`FDSUB:
|
begin
|
begin
|
fp_uf <= fpaddsub_uf;
|
fp_uf <= fpaddsub_uf;
|
fp_ovr <= fpaddsub_ovr;
|
fp_ovr <= fpaddsub_ovr;
|
fp_iop <= fpaddsub_iop;
|
fp_iop <= fpaddsub_iop;
|
FPC_SL <= xData[63] && xData[62:0]!=63'd0;
|
FPC_SL <= xData[63] && xData[62:0]!=63'd0;
|
FPC_SG <= !xData[63] && xData[62:0]!=63'd0;
|
FPC_SG <= !xData[63] && xData[62:0]!=63'd0;
|
FPC_SE <= xData[62:0]==63'd0;
|
FPC_SE <= xData[62:0]==63'd0;
|
end
|
end
|
`FPMUL:
|
`FPMUL:
|
begin
|
begin
|
fp_uf <= fpmul_uf;
|
fp_uf <= fpmul_uf;
|
fp_ovr <= fpmul_ovr;
|
fp_ovr <= fpmul_ovr;
|
fp_iop <= fpmul_iop;
|
fp_iop <= fpmul_iop;
|
FPC_SL <= xData[63] && xData[62:0]!=63'd0;
|
FPC_SL <= xData[63] && xData[62:0]!=63'd0;
|
FPC_SG <= !xData[63] && xData[62:0]!=63'd0;
|
FPC_SG <= !xData[63] && xData[62:0]!=63'd0;
|
FPC_SE <= xData[62:0]==63'd0;
|
FPC_SE <= xData[62:0]==63'd0;
|
end
|
end
|
`FPDIV:
|
`FPDIV:
|
begin
|
begin
|
fp_uf <= fpdiv_uf;
|
fp_uf <= fpdiv_uf;
|
fp_ovr <= fpdiv_ovr;
|
fp_ovr <= fpdiv_ovr;
|
fp_iop <= fpdiv_iop;
|
fp_iop <= fpdiv_iop;
|
FPC_SL <= xData[63] && xData[62:0]!=63'd0;
|
FPC_SL <= xData[63] && xData[62:0]!=63'd0;
|
FPC_SG <= !xData[63] && xData[62:0]!=63'd0;
|
FPC_SG <= !xData[63] && xData[62:0]!=63'd0;
|
FPC_SE <= xData[62:0]==63'd0;
|
FPC_SE <= xData[62:0]==63'd0;
|
end
|
end
|
`FDF2I:
|
`FDF2I:
|
begin
|
begin
|
fp_ovr <= f2i_ovr;
|
fp_ovr <= f2i_ovr;
|
fp_iop <= f2i_iop;
|
fp_iop <= f2i_iop;
|
end
|
end
|
`FDCLT,`FDCLE,`FDCEQ,`FDCNE,`FDCGT,`FDCGE,`FDCUN:
|
`FDCLT,`FDCLE,`FDCEQ,`FDCNE,`FDCGT,`FDCGE,`FDCUN:
|
begin
|
begin
|
fp_iop <= fpcmp_iop;
|
fp_iop <= fpcmp_iop;
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
end
|
end
|
`endif
|
`endif
|
if (dbz_error) begin
|
if (dbz_error) begin
|
$display("Divide by zero error");
|
$display("Divide by zero error");
|
LoadNOPs <= #1 1'b1;
|
LoadNOPs <= #1 1'b1;
|
// Squash a pending IRQ, but not an NMI
|
// Squash a pending IRQ, but not an NMI
|
m1extype <= #1 `EX_DBZ;
|
m1extype <= #1 `EX_DBZ;
|
m1IR <= #1 `NOP_INSN;
|
m1IR <= #1 `NOP_INSN;
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= #1 9'd0;
|
xRt <= #1 9'd0;
|
end
|
end
|
else if (ovr_error) begin
|
else if (ovr_error) begin
|
$display("Overflow error");
|
$display("Overflow error");
|
LoadNOPs <= 1'b1;
|
LoadNOPs <= 1'b1;
|
m1extype <= `EX_OFL;
|
m1extype <= `EX_OFL;
|
m1IR <= #1 `NOP_INSN;
|
m1IR <= #1 `NOP_INSN;
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= #1 9'd0;
|
xRt <= #1 9'd0;
|
end
|
end
|
// else if (priv_violation) begin
|
// else if (priv_violation) begin
|
// $display("Priviledge violation");
|
// $display("Priviledge violation");
|
// m1IR <= #1 `NOP_INSN;
|
// m1IR <= #1 `NOP_INSN;
|
// LoadNOPs <= 1'b1;
|
// LoadNOPs <= 1'b1;
|
// if (!xNmi&!dNmi) begin
|
// if (!xNmi&!dNmi) begin
|
// m1extype <= `EX_PRIV;
|
// m1extype <= `EX_PRIV;
|
// end
|
// end
|
// dIR <= #1 `NOP_INSN;
|
// dIR <= #1 `NOP_INSN;
|
// xIR <= #1 `NOP_INSN;
|
// xIR <= #1 `NOP_INSN;
|
// xRt <= #1 9'd0;
|
// xRt <= #1 9'd0;
|
// end
|
// end
|
else if (illegal_insn) begin
|
else if (illegal_insn) begin
|
$display("Unimplemented Instruction");
|
$display("Unimplemented Instruction");
|
LoadNOPs <= 1'b1;
|
LoadNOPs <= 1'b1;
|
m1extype <= `EX_UNIMP_INSN;
|
m1extype <= `EX_UNIMP_INSN;
|
m1IR <= #1 `NOP_INSN;
|
m1IR <= #1 `NOP_INSN;
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
xRt <= #1 9'd0;
|
xRt <= #1 9'd0;
|
end
|
end
|
end
|
end
|
// Stage tail
|
// Stage tail
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
else if (advanceM1) begin
|
else if (advanceM1) begin
|
m1IR <= #1 `NOP_INSN;
|
m1IR <= #1 `NOP_INSN;
|
m1IsLoad <= #1 1'b0;
|
m1IsLoad <= #1 1'b0;
|
m1IsStore <= #1 1'b0;
|
m1IsStore <= #1 1'b0;
|
m1IsOut <= #1 1'b0;
|
m1IsOut <= #1 1'b0;
|
m1IsIn <= #1 1'b0;
|
m1IsIn <= #1 1'b0;
|
m1Rt <= #1 9'd0;
|
m1Rt <= #1 9'd0;
|
m1clkoff <= #1 1'b0;
|
m1clkoff <= #1 1'b0;
|
m1Fip <= #1 1'b0;
|
m1Fip <= #1 1'b0;
|
m1extype <= #1 `EX_NON;
|
m1extype <= #1 `EX_NON;
|
m1IsCnt <= #1 1'b0;
|
m1IsCnt <= #1 1'b0;
|
m1IsCacheElement <= #1 1'b0;
|
m1IsCacheElement <= #1 1'b0;
|
end
|
end
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// MEMORY:
|
// MEMORY:
|
// - I/O instructions are finished
|
// - I/O instructions are finished
|
// - store instructions are started
|
// - store instructions are started
|
// - missed loads are started
|
// - missed loads are started
|
// On a data cache hit for a load, the load is essentially
|
// On a data cache hit for a load, the load is essentially
|
// finished in this stage. We switch the opcode to 'NOPI'
|
// finished in this stage. We switch the opcode to 'NOPI'
|
// to cause the pipeline to advance as if a NOPs were
|
// to cause the pipeline to advance as if a NOPs were
|
// present.
|
// present.
|
//
|
//
|
// Inputs:
|
// Inputs:
|
// - m1???? signals
|
// - m1???? signals
|
// Outputs:
|
// Outputs:
|
// - m2???? signals to M2 stage
|
// - m2???? signals to M2 stage
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
if (advanceM1) begin
|
if (advanceM1) begin
|
m2StatusHWI <= m1StatusHWI;
|
m2StatusHWI <= m1StatusHWI;
|
m2Im <= m1Im;
|
m2Im <= m1Im;
|
m2Nmi <= m1Nmi;
|
m2Nmi <= m1Nmi;
|
m2extype <= m1extype;
|
m2extype <= m1extype;
|
m2Addr <= pea;
|
m2Addr <= pea;
|
m2Data <= m1Data;
|
m2Data <= m1Data;
|
m2Fip <= m1Fip;
|
m2Fip <= m1Fip;
|
m2pc <= m1pc;
|
m2pc <= m1pc;
|
m2IR <= m1IR;
|
m2IR <= m1IR;
|
m2IsCnt <= m1IsCnt;
|
m2IsCnt <= m1IsCnt;
|
m2Rt <= m1Rt;
|
m2Rt <= m1Rt;
|
m2clkoff <= m1clkoff;
|
m2clkoff <= m1clkoff;
|
m2AXC <= m1AXC;
|
m2AXC <= m1AXC;
|
m2IsCacheElement <= m1IsCacheElement;
|
m2IsCacheElement <= m1IsCacheElement;
|
m2IsLoad <= m1IsLoad;
|
m2IsLoad <= m1IsLoad;
|
m2IsStore <= m2IsStore;
|
m2IsStore <= m2IsStore;
|
|
|
if (m1IsIO & err_i) begin
|
if (m1IsIO & err_i) begin
|
m2extype <= `EX_DBERR;
|
m2extype <= `EX_DBERR;
|
errorAddress <= adr_o;
|
errorAddress <= adr_o;
|
m2IR <= #1 `NOP_INSN;
|
m2IR <= #1 `NOP_INSN;
|
end
|
end
|
|
|
case(m1Opcode)
|
case(m1Opcode)
|
`MISC:
|
`MISC:
|
case(m1Func)
|
case(m1Func)
|
`SYSCALL:
|
`SYSCALL:
|
if (!m1IsCacheElement) begin
|
if (!m1IsCacheElement) begin
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= 8'hFF;
|
sel_o <= 8'hFF;
|
adr_o <= pea;
|
adr_o <= pea;
|
m2Addr <= pea;
|
m2Addr <= pea;
|
end
|
end
|
else begin // dhit must be true
|
else begin // dhit must be true
|
$display("fetched vector: %h", {cdat[63:2],2'b00});
|
$display("fetched vector: %h", {cdat[63:2],2'b00});
|
m2IR <= `NOP_INSN;
|
m2IR <= `NOP_INSN;
|
m2IsLoad <= 1'b0;
|
m2IsLoad <= 1'b0;
|
pc <= {cdat[63:2],2'b00};
|
pc <= {cdat[63:2],2'b00};
|
LoadNOPs <= 1'b0;
|
LoadNOPs <= 1'b0;
|
end
|
end
|
endcase
|
endcase
|
`INW:
|
`INW:
|
begin
|
begin
|
iocyc_o <= 1'b0;
|
iocyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
m2Data <= data64;
|
m2Data <= data64;
|
end
|
end
|
`INH:
|
`INH:
|
begin
|
begin
|
iocyc_o <= 1'b0;
|
iocyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
m2Data <= {{32{data32[31]}},data32};
|
m2Data <= {{32{data32[31]}},data32};
|
end
|
end
|
`INHU:
|
`INHU:
|
begin
|
begin
|
iocyc_o <= 1'b0;
|
iocyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
m2Data <= data32;
|
m2Data <= data32;
|
end
|
end
|
`INCH:
|
`INCH:
|
begin
|
begin
|
iocyc_o <= 1'b0;
|
iocyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
m2Data <= {{48{data16[15]}},data16};
|
m2Data <= {{48{data16[15]}},data16};
|
end
|
end
|
`INCU:
|
`INCU:
|
begin
|
begin
|
iocyc_o <= #1 1'b0;
|
iocyc_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
sel_o <= #1 8'h00;
|
sel_o <= #1 8'h00;
|
m2Data <= #1 data16;
|
m2Data <= #1 data16;
|
end
|
end
|
`INB:
|
`INB:
|
begin
|
begin
|
iocyc_o <= #1 1'b0;
|
iocyc_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
sel_o <= #1 8'h00;
|
sel_o <= #1 8'h00;
|
m2Data <= #1 {{56{data8[7]}},data8};
|
m2Data <= #1 {{56{data8[7]}},data8};
|
end
|
end
|
`INBU:
|
`INBU:
|
begin
|
begin
|
iocyc_o <= #1 1'b0;
|
iocyc_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
sel_o <= #1 8'h00;
|
sel_o <= #1 8'h00;
|
m2Data <= #1 data8;
|
m2Data <= #1 data8;
|
end
|
end
|
`OUTW,`OUTH,`OUTC,`OUTB,`OUTBC:
|
`OUTW,`OUTH,`OUTC,`OUTB,`OUTBC:
|
begin
|
begin
|
iocyc_o <= #1 1'b0;
|
iocyc_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
we_o <= #1 1'b0;
|
we_o <= #1 1'b0;
|
sel_o <= #1 8'h00;
|
sel_o <= #1 8'h00;
|
end
|
end
|
`CACHE:
|
`CACHE:
|
case(m1IR[19:15])
|
case(m1IR[19:15])
|
`INVIL: tvalid[pea[13:6]] <= 1'b0;
|
`INVIL: tvalid[pea[13:6]] <= 1'b0;
|
default: ;
|
default: ;
|
endcase
|
endcase
|
|
|
`LW,`LM,`LFD,`LSW,`LP,`LFDP:
|
`LW,`LM,`LFD,`LSW,`LP,`LFDP:
|
if (!m1IsCacheElement) begin
|
if (!m1IsCacheElement) begin
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
adr_o <= pea;
|
adr_o <= pea;
|
m2Addr <= pea;
|
m2Addr <= pea;
|
end
|
end
|
else begin
|
else begin
|
m2IsLoad <= 1'b0;
|
m2IsLoad <= 1'b0;
|
m2IR <= `NOP_INSN;
|
m2IR <= `NOP_INSN;
|
m2Data <= cdata64;
|
m2Data <= cdata64;
|
end
|
end
|
`ifdef ADDRESS_RESERVATION
|
`ifdef ADDRESS_RESERVATION
|
`LWR:
|
`LWR:
|
begin
|
begin
|
rsv_o <= 1'b1;
|
rsv_o <= 1'b1;
|
resv_address <= pea[63:5];
|
resv_address <= pea[63:5];
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
adr_o <= pea;
|
adr_o <= pea;
|
m2Addr <= pea;
|
m2Addr <= pea;
|
end
|
end
|
`endif
|
`endif
|
`LH,`LF,`LFP:
|
`LH,`LF,`LFP:
|
if (!m1IsCacheElement) begin
|
if (!m1IsCacheElement) begin
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
adr_o <= pea;
|
adr_o <= pea;
|
m2Addr <= pea;
|
m2Addr <= pea;
|
end
|
end
|
else begin
|
else begin
|
m2IsLoad <= 1'b0;
|
m2IsLoad <= 1'b0;
|
m2IR <= `NOP_INSN;
|
m2IR <= `NOP_INSN;
|
m2Data <= {{32{cdata32[31]}},cdata32};
|
m2Data <= {{32{cdata32[31]}},cdata32};
|
end
|
end
|
|
|
`LHU,`LSH:
|
`LHU,`LSH:
|
if (!m1IsCacheElement) begin
|
if (!m1IsCacheElement) begin
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
adr_o <= pea;
|
adr_o <= pea;
|
m2Addr <= pea;
|
m2Addr <= pea;
|
end
|
end
|
else begin
|
else begin
|
m2IsLoad <= 1'b0;
|
m2IsLoad <= 1'b0;
|
m2IR <= `NOP_INSN;
|
m2IR <= `NOP_INSN;
|
m2Data <= cdata32;
|
m2Data <= cdata32;
|
end
|
end
|
|
|
`LC:
|
`LC:
|
if (!m1IsCacheElement) begin
|
if (!m1IsCacheElement) begin
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
adr_o <= pea;
|
adr_o <= pea;
|
m2Addr <= pea;
|
m2Addr <= pea;
|
end
|
end
|
else begin
|
else begin
|
$display("dhit=1, cdat=%h",cdat);
|
$display("dhit=1, cdat=%h",cdat);
|
m2IsLoad <= 1'b0;
|
m2IsLoad <= 1'b0;
|
m2IR <= `NOP_INSN;
|
m2IR <= `NOP_INSN;
|
m2Data <= {{48{cdata16[15]}},cdata16};
|
m2Data <= {{48{cdata16[15]}},cdata16};
|
end
|
end
|
|
|
`LCU:
|
`LCU:
|
if (!m1IsCacheElement) begin
|
if (!m1IsCacheElement) begin
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
adr_o <= pea;
|
adr_o <= pea;
|
m2Addr <= pea;
|
m2Addr <= pea;
|
end
|
end
|
else begin
|
else begin
|
m2IsLoad <= 1'b0;
|
m2IsLoad <= 1'b0;
|
m2IR <= `NOP_INSN;
|
m2IR <= `NOP_INSN;
|
m2Data <= cdata16;
|
m2Data <= cdata16;
|
end
|
end
|
|
|
`LB:
|
`LB:
|
if (!m1IsCacheElement) begin
|
if (!m1IsCacheElement) begin
|
$display("Load byte:");
|
$display("Load byte:");
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
adr_o <= pea;
|
adr_o <= pea;
|
m2Addr <= pea;
|
m2Addr <= pea;
|
end
|
end
|
else begin
|
else begin
|
m2IsLoad <= 1'b0;
|
m2IsLoad <= 1'b0;
|
m2IR <= `NOP_INSN;
|
m2IR <= `NOP_INSN;
|
m2Data <= {{56{cdata8[7]}},cdata8};
|
m2Data <= {{56{cdata8[7]}},cdata8};
|
end
|
end
|
`LBU:
|
`LBU:
|
if (!m1IsCacheElement) begin
|
if (!m1IsCacheElement) begin
|
$display("Load unsigned byte:");
|
$display("Load unsigned byte:");
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
adr_o <= pea;
|
adr_o <= pea;
|
m2Addr <= pea;
|
m2Addr <= pea;
|
end
|
end
|
else begin
|
else begin
|
$display("m2IsLoad <= 0");
|
$display("m2IsLoad <= 0");
|
m2IsLoad <= 1'b0;
|
m2IsLoad <= 1'b0;
|
m2IR <= `NOP_INSN;
|
m2IR <= `NOP_INSN;
|
m2Data <= cdata8;
|
m2Data <= cdata8;
|
end
|
end
|
|
|
`SW,`SM,`SFD,`SSW,`SP,`SFDP:
|
`SW,`SM,`SFD,`SSW,`SP,`SFDP:
|
begin
|
begin
|
$display("%d SW/SM %h",tick,{pea[63:3],3'b000});
|
$display("%d SW/SM %h",tick,{pea[63:3],3'b000});
|
m2Addr <= pea;
|
m2Addr <= pea;
|
wrhit <= #1 dhit;
|
wrhit <= #1 dhit;
|
`ifdef ADDRESS_RESERVATION
|
`ifdef ADDRESS_RESERVATION
|
if (resv_address==pea[63:5])
|
if (resv_address==pea[63:5])
|
resv_address <= #1 59'd0;
|
resv_address <= #1 59'd0;
|
`endif
|
`endif
|
cyc_o <= #1 1'b1;
|
cyc_o <= #1 1'b1;
|
stb_o <= #1 1'b1;
|
stb_o <= #1 1'b1;
|
we_o <= #1 1'b1;
|
we_o <= #1 1'b1;
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
adr_o <= pea;
|
adr_o <= pea;
|
dat_o <= #1 m1Data;
|
dat_o <= #1 m1Data;
|
end
|
end
|
|
|
`SH,`SF,`SSH,`SFP:
|
`SH,`SF,`SSH,`SFP:
|
begin
|
begin
|
wrhit <= #1 dhit;
|
wrhit <= #1 dhit;
|
m2Addr <= pea;
|
m2Addr <= pea;
|
`ifdef ADDRESS_RESERVATION
|
`ifdef ADDRESS_RESERVATION
|
if (resv_address==pea[63:5])
|
if (resv_address==pea[63:5])
|
resv_address <= #1 59'd0;
|
resv_address <= #1 59'd0;
|
`endif
|
`endif
|
cyc_o <= #1 1'b1;
|
cyc_o <= #1 1'b1;
|
stb_o <= #1 1'b1;
|
stb_o <= #1 1'b1;
|
we_o <= #1 1'b1;
|
we_o <= #1 1'b1;
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
adr_o <= pea;
|
adr_o <= pea;
|
dat_o <= #1 {2{m1Data[31:0]}};
|
dat_o <= #1 {2{m1Data[31:0]}};
|
end
|
end
|
|
|
`SC:
|
`SC:
|
begin
|
begin
|
$display("Storing char to %h, ea=%h",pea,ea);
|
$display("Storing char to %h, ea=%h",pea,ea);
|
wrhit <= #1 dhit;
|
wrhit <= #1 dhit;
|
m2Addr <= pea;
|
m2Addr <= pea;
|
`ifdef ADDRESS_RESERVATION
|
`ifdef ADDRESS_RESERVATION
|
if (resv_address==pea[63:5])
|
if (resv_address==pea[63:5])
|
resv_address <= #1 59'd0;
|
resv_address <= #1 59'd0;
|
`endif
|
`endif
|
cyc_o <= #1 1'b1;
|
cyc_o <= #1 1'b1;
|
stb_o <= #1 1'b1;
|
stb_o <= #1 1'b1;
|
we_o <= #1 1'b1;
|
we_o <= #1 1'b1;
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
adr_o <= pea;
|
adr_o <= pea;
|
dat_o <= #1 {4{m1Data[15:0]}};
|
dat_o <= #1 {4{m1Data[15:0]}};
|
end
|
end
|
|
|
`SB,`STBC:
|
`SB,`STBC:
|
begin
|
begin
|
wrhit <= #1 dhit;
|
wrhit <= #1 dhit;
|
m2Addr <= pea;
|
m2Addr <= pea;
|
`ifdef ADDRESS_RESERVATION
|
`ifdef ADDRESS_RESERVATION
|
if (resv_address==pea[63:5])
|
if (resv_address==pea[63:5])
|
resv_address <= #1 59'd0;
|
resv_address <= #1 59'd0;
|
`endif
|
`endif
|
cyc_o <= #1 1'b1;
|
cyc_o <= #1 1'b1;
|
stb_o <= #1 1'b1;
|
stb_o <= #1 1'b1;
|
we_o <= #1 1'b1;
|
we_o <= #1 1'b1;
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
adr_o <= pea;
|
adr_o <= pea;
|
dat_o <= #1 {8{m1Data[7:0]}};
|
dat_o <= #1 {8{m1Data[7:0]}};
|
end
|
end
|
|
|
`ifdef ADDRESS_RESERVATION
|
`ifdef ADDRESS_RESERVATION
|
`SWC:
|
`SWC:
|
begin
|
begin
|
rsf <= #1 1'b0;
|
rsf <= #1 1'b0;
|
if (resv_address==pea[63:5]) begin
|
if (resv_address==pea[63:5]) begin
|
wrhit <= #1 dhit;
|
wrhit <= #1 dhit;
|
m2Addr <= pea;
|
m2Addr <= pea;
|
cyc_o <= #1 1'b1;
|
cyc_o <= #1 1'b1;
|
stb_o <= #1 1'b1;
|
stb_o <= #1 1'b1;
|
we_o <= #1 1'b1;
|
we_o <= #1 1'b1;
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
sel_o <= fnSelect(m1Opcode,pea[2:0]);
|
adr_o <= pea;
|
adr_o <= pea;
|
dat_o <= #1 m1Data;
|
dat_o <= #1 m1Data;
|
resv_address <= #1 59'd0;
|
resv_address <= #1 59'd0;
|
rsf <= #1 1'b1;
|
rsf <= #1 1'b1;
|
end
|
end
|
else
|
else
|
m2IR <= `NOP_INSN;
|
m2IR <= `NOP_INSN;
|
end
|
end
|
`endif
|
`endif
|
endcase
|
endcase
|
|
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
// Check for a TLB miss.
|
// Check for a TLB miss.
|
// On a prefetch load, just switch the opcode to a NOP
|
// On a prefetch load, just switch the opcode to a NOP
|
// instruction and ignore the error. Otherwise set the
|
// instruction and ignore the error. Otherwise set the
|
// exception type.
|
// exception type.
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
`ifdef TLB
|
`ifdef TLB
|
if (m1IsLoad && m1Rt[4:0]==5'd0 && DTLBMiss) begin
|
if (m1IsLoad && m1Rt[4:0]==5'd0 && DTLBMiss) begin
|
m1IR <= `NOP_INSN;
|
m1IR <= `NOP_INSN;
|
end
|
end
|
if ((m1IsLoad&&m1Rt[4:0]!=5'd0)|m1IsStore) begin
|
if ((m1IsLoad&&m1Rt[4:0]!=5'd0)|m1IsStore) begin
|
if (DTLBMiss) begin
|
if (DTLBMiss) begin
|
$display("DTLB miss on address: %h",ea);
|
$display("DTLB miss on address: %h",ea);
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
we_o <= 1'b0;
|
we_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
m1extype <= `EX_TLBD;
|
m1extype <= `EX_TLBD;
|
StatusHWI <= 1'b1;
|
StatusHWI <= 1'b1;
|
BadVAddr <= ea[63:13];
|
BadVAddr <= ea[63:13];
|
if (!xNmi&!dNmi) begin
|
if (!xNmi&!dNmi) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
end
|
end
|
m1IR <= `NOP_INSN;
|
m1IR <= `NOP_INSN;
|
m1Rt <= 9'd0;
|
m1Rt <= 9'd0;
|
xRt <= #1 9'd0;
|
xRt <= #1 9'd0;
|
LoadNOPs <= 1'b1;
|
LoadNOPs <= 1'b1;
|
end
|
end
|
end
|
end
|
`endif
|
`endif
|
end
|
end
|
// Stage tail
|
// Stage tail
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
else if (advanceM2) begin
|
else if (advanceM2) begin
|
m2Rt <= #1 9'd0;
|
m2Rt <= #1 9'd0;
|
m2IR <= #1 `NOP_INSN;
|
m2IR <= #1 `NOP_INSN;
|
m2IsCnt <= #1 1'b0;
|
m2IsCnt <= #1 1'b0;
|
m2IsLoad <= #1 1'b0;
|
m2IsLoad <= #1 1'b0;
|
m2IsStore <= #1 1'b0;
|
m2IsStore <= #1 1'b0;
|
m2Addr <= 64'd0;
|
m2Addr <= 64'd0;
|
m2Data <= #1 64'd0;
|
m2Data <= #1 64'd0;
|
m2clkoff <= #1 1'b0;
|
m2clkoff <= #1 1'b0;
|
m2Fip <= #1 1'b0;
|
m2Fip <= #1 1'b0;
|
m2extype <= #1 `EX_NON;
|
m2extype <= #1 `EX_NON;
|
m2IsCacheElement <= 1'b0;
|
m2IsCacheElement <= 1'b0;
|
end
|
end
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// MEMORY:
|
// MEMORY:
|
// - complete the memory cycle
|
// - complete the memory cycle
|
// - merge load data into pipeline
|
// - merge load data into pipeline
|
// Inputs:
|
// Inputs:
|
// - m2???? type signals
|
// - m2???? type signals
|
// Outputs:
|
// Outputs:
|
// - w???? signals to WB stage
|
// - w???? signals to WB stage
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
if (advanceM2) begin
|
if (advanceM2) begin
|
wextype <= #1 m2extype;
|
wextype <= #1 m2extype;
|
wpc <= #1 m2pc;
|
wpc <= #1 m2pc;
|
wFip <= #1 m2Fip;
|
wFip <= #1 m2Fip;
|
wIR <= #1 m2IR;
|
wIR <= #1 m2IR;
|
wIsStore <= #1 m2IsStore;
|
wIsStore <= #1 m2IsStore;
|
wData <= #1 m2Data;
|
wData <= #1 m2Data;
|
wRt <= #1 m2Rt;
|
wRt <= #1 m2Rt;
|
wclkoff <= #1 m2clkoff;
|
wclkoff <= #1 m2clkoff;
|
wAXC <= #1 m2AXC;
|
wAXC <= #1 m2AXC;
|
|
|
// There's not an error is a prefetch is taking place (m2Rt=0).
|
// There's not an error is a prefetch is taking place (m2Rt=0).
|
if (((m2IsLoad&&m2Rt[4:0]!=5'd0)|m2IsStore) & err_i) begin
|
if (((m2IsLoad&&m2Rt[4:0]!=5'd0)|m2IsStore) & err_i) begin
|
wextype <= #1 `EX_DBERR;
|
wextype <= #1 `EX_DBERR;
|
errorAddress <= #1 adr_o;
|
errorAddress <= #1 adr_o;
|
end
|
end
|
|
|
case(m2Opcode)
|
case(m2Opcode)
|
`MISC:
|
`MISC:
|
if (m2Func==`SYSCALL)
|
if (m2Func==`SYSCALL)
|
begin
|
begin
|
cyc_o <= #1 1'b0;
|
cyc_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
sel_o <= #1 8'h00;
|
sel_o <= #1 8'h00;
|
pc <= #1 {data64[63:2],2'b00};
|
pc <= #1 {data64[63:2],2'b00};
|
LoadNOPs <= 1'b0;
|
LoadNOPs <= 1'b0;
|
$display("M2 Fetched vector: %h",{data64[63:2],2'b00});
|
$display("M2 Fetched vector: %h",{data64[63:2],2'b00});
|
end
|
end
|
`SH,`SC,`SB,`SW,`SWC,`SF,`SFD,`SSH,`SSW,`SP,`SFP,`SFDP:
|
`SH,`SC,`SB,`SW,`SWC,`SF,`SFD,`SSH,`SSW,`SP,`SFP,`SFDP:
|
begin
|
begin
|
cyc_o <= #1 1'b0;
|
cyc_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
we_o <= #1 1'b0;
|
we_o <= #1 1'b0;
|
sel_o <= #1 8'h00;
|
sel_o <= #1 8'h00;
|
end
|
end
|
`LH,`LF,`LSH,`LFP:
|
`LH,`LF,`LSH,`LFP:
|
begin
|
begin
|
cyc_o <= #1 1'b0;
|
cyc_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
sel_o <= #1 8'h00;
|
sel_o <= #1 8'h00;
|
wData <= #1 {{32{data32[31]}},data32};
|
wData <= #1 {{32{data32[31]}},data32};
|
end
|
end
|
`LW,`LWR,`LFD,`LSW,`LP,`LFDP:
|
`LW,`LWR,`LFD,`LSW,`LP,`LFDP:
|
begin
|
begin
|
cyc_o <= #1 1'b0;
|
cyc_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
sel_o <= #1 8'h00;
|
sel_o <= #1 8'h00;
|
wData <= #1 data64;
|
wData <= #1 data64;
|
end
|
end
|
`LHU:
|
`LHU:
|
begin
|
begin
|
cyc_o <= #1 1'b0;
|
cyc_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
sel_o <= #1 8'h00;
|
sel_o <= #1 8'h00;
|
wData <= #1 data32;
|
wData <= #1 data32;
|
end
|
end
|
`LC:
|
`LC:
|
begin
|
begin
|
cyc_o <= #1 1'b0;
|
cyc_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
sel_o <= #1 8'h00;
|
sel_o <= #1 8'h00;
|
wData <= #1 {{48{data16[15]}},data16};
|
wData <= #1 {{48{data16[15]}},data16};
|
end
|
end
|
`LCU:
|
`LCU:
|
begin
|
begin
|
cyc_o <= #1 1'b0;
|
cyc_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
stb_o <= #1 1'b0;
|
sel_o <= #1 8'h00;
|
sel_o <= #1 8'h00;
|
wData <= #1 data16;
|
wData <= #1 data16;
|
end
|
end
|
`LB:
|
`LB:
|
begin
|
begin
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
wData <= {{56{data8[7]}},data8};
|
wData <= {{56{data8[7]}},data8};
|
end
|
end
|
`LBU:
|
`LBU:
|
begin
|
begin
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
wData <= data8;
|
wData <= data8;
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
// Force stack pointer to word alignment
|
// Force stack pointer to word alignment
|
if (m2Rt[4:0]==5'b11110)
|
if (m2Rt[4:0]==5'b11110)
|
wData[2:0] <= 3'b000;
|
wData[2:0] <= 3'b000;
|
end
|
end
|
// Stage tail
|
// Stage tail
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
else if (advanceW) begin
|
else if (advanceW) begin
|
wIR <= #1 `NOP_INSN;
|
wIR <= #1 `NOP_INSN;
|
wextype <= `EX_NON;
|
wextype <= `EX_NON;
|
wRt <= 9'd0;
|
wRt <= 9'd0;
|
wData <= 64'd0;
|
wData <= 64'd0;
|
wIsStore <= 1'b0;
|
wIsStore <= 1'b0;
|
wclkoff <= 1'b0;
|
wclkoff <= 1'b0;
|
wFip <= 1'b0;
|
wFip <= 1'b0;
|
end
|
end
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// WRITEBACK:
|
// WRITEBACK:
|
// - update the register file with results
|
// - update the register file with results
|
// - record exception address and type
|
// - record exception address and type
|
// - jump to exception handler routine (below)
|
// - jump to exception handler routine (below)
|
// Inputs:
|
// Inputs:
|
// - w???? type signals
|
// - w???? type signals
|
// Outputs:
|
// Outputs:
|
// - t???? signals
|
// - t???? signals
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//
|
//
|
if (advanceW) begin
|
if (advanceW) begin
|
// Hold onto the last register update
|
// Hold onto the last register update
|
if (wRt[4:0]!=5'd0 && wRt[4:0]!=5'd29) begin
|
if (wRt[4:0]!=5'd0 && wRt[4:0]!=5'd29) begin
|
tRt <= wRt;
|
tRt <= wRt;
|
tData <= wData;
|
tData <= wData;
|
end
|
end
|
if (wRt!=5'd0) begin
|
if (wRt!=5'd0) begin
|
$display("Writing regfile[%d:%d] with %h", wRt[8:5],wRt[4:0], wData);
|
$display("Writing regfile[%d:%d] with %h", wRt[8:5],wRt[4:0], wData);
|
end
|
end
|
case(wOpcode)
|
case(wOpcode)
|
`LSH:
|
`LSH:
|
case (wRt)
|
case (wRt)
|
`SR: begin
|
`SR: begin
|
bu_im <= wData[31];
|
bu_im <= wData[31];
|
if (wData[15])
|
if (wData[15])
|
ie_fuse <= 8'h00;
|
ie_fuse <= 8'h00;
|
else
|
else
|
ie_fuse[0] <= 1'b1;
|
ie_fuse[0] <= 1'b1;
|
FXE <= wData[12];
|
FXE <= wData[12];
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
`MISC:
|
`MISC:
|
case(wFunc)
|
case(wFunc)
|
`SYSCALL:
|
`SYSCALL:
|
if (wIR[15:7]==`EX_NMI || (wIR[15:7]>=`EX_IRQ && wIR[15:7]<`EX_IRQ+32) || wIR[15:7]==`EX_TLBI || wIR[15:7]==`EX_TLBD)
|
if (wIR[15:7]==`EX_NMI || (wIR[15:7]>=`EX_IRQ && wIR[15:7]<`EX_IRQ+32) || wIR[15:7]==`EX_TLBI || wIR[15:7]==`EX_TLBD)
|
IPC[wAXC] <= wData;
|
IPC[wAXC] <= wData;
|
else
|
else
|
EPC[wAXC] <= wData;
|
EPC[wAXC] <= wData;
|
default: ;
|
default: ;
|
endcase
|
endcase
|
`R:
|
`R:
|
case(wFunc6)
|
case(wFunc6)
|
`MTSPR:
|
`MTSPR:
|
case(wIR[11:6])
|
case(wIR[11:6])
|
`ifdef SEGMENTATION
|
|
`CS: CS[wAXC][63:16] <= wData[63:16];
|
|
`DS: DS[wAXC][63:16] <= wData[63:16];
|
|
`ES: ES[wAXC][63:16] <= wData[63:16];
|
|
`SS: SS[wAXC][63:16] <= wData[63:16];
|
|
`endif
|
|
`IPC: begin
|
`IPC: begin
|
$display("mtspr IPC[%d]=%h",wAXC,wData);
|
$display("mtspr IPC[%d]=%h",wAXC,wData);
|
IPC[wAXC] <= wData;
|
IPC[wAXC] <= wData;
|
end
|
end
|
`EPC: EPC[wAXC] <= wData;
|
`EPC: EPC[wAXC] <= wData;
|
default: ;
|
default: ;
|
endcase
|
endcase
|
|
`ifdef SEGMENTATION
|
|
`MTSEG: segs[{wIR[9:6],wAXC}] <= wData[63:12];
|
|
`endif
|
|
endcase
|
|
`RR:
|
|
case(wFunc6)
|
|
`ifdef SEGMENTATION
|
|
`MTSEGI: segs[{wIR[9:6],wAXC}] <= wData[63:12];
|
|
`endif
|
|
default: ;
|
endcase
|
endcase
|
|
default: ;
|
endcase
|
endcase
|
if (wclkoff)
|
if (wclkoff)
|
clk_en <= 1'b0;
|
clk_en <= 1'b0;
|
else
|
else
|
clk_en <= 1'b1;
|
clk_en <= 1'b1;
|
// FIP/IEPP:
|
// FIP/IEPP:
|
// Jump back to the instruction following the FIP/IEPP
|
// Jump back to the instruction following the FIP/IEPP
|
if (wFip) begin
|
if (wFip) begin
|
wFip <= 1'b0;
|
wFip <= 1'b0;
|
m2Fip <= 1'b0;
|
m2Fip <= 1'b0;
|
m1Fip <= 1'b0;
|
m1Fip <= 1'b0;
|
xFip <= 1'b0;
|
xFip <= 1'b0;
|
dFip <= 1'b0;
|
dFip <= 1'b0;
|
pc <= fnIncPC(wpc);
|
pc <= fnIncPC(wpc);
|
end
|
end
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
// WRITEBACK (WB') - part two:
|
// WRITEBACK (WB') - part two:
|
// - vector to exception handler address
|
// - vector to exception handler address
|
// In the case of a hardware interrupt (NMI/IRQ) we know
|
// In the case of a hardware interrupt (NMI/IRQ) we know
|
// the pipeline following the interrupt is filled with
|
// the pipeline following the interrupt is filled with
|
// NOP instructions. This means there is no need to
|
// NOP instructions. This means there is no need to
|
// invalidate the pipeline.
|
// invalidate the pipeline.
|
// Also, we have to wait until the WB stage before
|
// Also, we have to wait until the WB stage before
|
// vectoring so that the pc setting doesn't get trashed
|
// vectoring so that the pc setting doesn't get trashed
|
// by a branch or other exception.
|
// by a branch or other exception.
|
// Tricky because we have to find the first valid
|
// Tricky because we have to find the first valid
|
// PC to record in the IPC register. The interrupt might
|
// PC to record in the IPC register. The interrupt might
|
// have occurred in a branch shadow, in which case the
|
// have occurred in a branch shadow, in which case the
|
// current PC isn't valid.
|
// current PC isn't valid.
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
case(wextype)
|
case(wextype)
|
`EX_NON: ;
|
`EX_NON: ;
|
`EX_RST:
|
`EX_RST:
|
begin
|
begin
|
pc <= `RESET_VECTOR;
|
pc <= `RESET_VECTOR;
|
end
|
end
|
// Hardware exceptions
|
// Hardware exceptions
|
`EX_NMI,`EX_IRQ,`EX_TLBI,`EX_TLBD,
|
`EX_NMI,`EX_IRQ,`EX_TLBI,`EX_TLBD,
|
`EX_IRQ+1,`EX_IRQ+2,`EX_IRQ+3,`EX_IRQ+4,`EX_IRQ+5,`EX_IRQ+6,`EX_IRQ+7,
|
`EX_IRQ+1,`EX_IRQ+2,`EX_IRQ+3,`EX_IRQ+4,`EX_IRQ+5,`EX_IRQ+6,`EX_IRQ+7,
|
`EX_IRQ+8,`EX_IRQ+9,`EX_IRQ+10,`EX_IRQ+11,`EX_IRQ+12,`EX_IRQ+13,`EX_IRQ+14,
|
`EX_IRQ+8,`EX_IRQ+9,`EX_IRQ+10,`EX_IRQ+11,`EX_IRQ+12,`EX_IRQ+13,`EX_IRQ+14,
|
`EX_IRQ+15,`EX_IRQ+16,`EX_IRQ+17,`EX_IRQ+18,`EX_IRQ+19,`EX_IRQ+20,`EX_IRQ+21,
|
`EX_IRQ+15,`EX_IRQ+16,`EX_IRQ+17,`EX_IRQ+18,`EX_IRQ+19,`EX_IRQ+20,`EX_IRQ+21,
|
`EX_IRQ+22,`EX_IRQ+23,`EX_IRQ+24,`EX_IRQ+25,`EX_IRQ+26,`EX_IRQ+27,`EX_IRQ+28,
|
`EX_IRQ+22,`EX_IRQ+23,`EX_IRQ+24,`EX_IRQ+25,`EX_IRQ+26,`EX_IRQ+27,`EX_IRQ+28,
|
`EX_IRQ+29,`EX_IRQ+30,`EX_IRQ+31:
|
`EX_IRQ+29,`EX_IRQ+30,`EX_IRQ+31:
|
begin
|
begin
|
dNmi <= 1'b0;
|
dNmi <= 1'b0;
|
xNmi <= 1'b0;
|
xNmi <= 1'b0;
|
m1Nmi <= 1'b0;
|
m1Nmi <= 1'b0;
|
m2Nmi <= 1'b0;
|
m2Nmi <= 1'b0;
|
// $display("Stuffing SYSCALL %d",wextype);
|
// $display("Stuffing SYSCALL %d",wextype);
|
// dIR <= {`MISC,9'd0,wextype,`SYSCALL};
|
// dIR <= {`MISC,9'd0,wextype,`SYSCALL};
|
// One of the following pc's MUST be valid.
|
// One of the following pc's MUST be valid.
|
// wpc will be valid if the interrupt occurred outside of a branch
|
// wpc will be valid if the interrupt occurred outside of a branch
|
// shadow. m1pc or m2pc (the branch target address) will be valid
|
// shadow. m1pc or m2pc (the branch target address) will be valid
|
// depending on where in the branch shadow the interrupt falls.
|
// depending on where in the branch shadow the interrupt falls.
|
// Syscall has a larger shadow than a branch because it loads the
|
// Syscall has a larger shadow than a branch because it loads the
|
// vector from memory. xpc or dpc should be valid depending on
|
// vector from memory. xpc or dpc should be valid depending on
|
// whether or not the vector is cached. Eventually syscall flags
|
// whether or not the vector is cached. Eventually syscall flags
|
// the pc valid. If none of the PC's are valid, then there is a
|
// the pc valid. If none of the PC's are valid, then there is a
|
// hardware problem.
|
// hardware problem.
|
// dpc <= wpc;
|
// dpc <= wpc;
|
// case(1'b1)
|
// case(1'b1)
|
// wpcv: dpc <= wpc;
|
// wpcv: dpc <= wpc;
|
// m2pcv: dpc <= m2pc;
|
// m2pcv: dpc <= m2pc;
|
// m1pcv: dpc <= m1pc;
|
// m1pcv: dpc <= m1pc;
|
// xpcv: dpc <= xpc;
|
// xpcv: dpc <= xpc;
|
// dpcv: dpc <= dpc;
|
// dpcv: dpc <= dpc;
|
// ipcv: dpc <= pc;
|
// ipcv: dpc <= pc;
|
// default: dpc <= `RESET_VECTOR; // Can't happen
|
// default: dpc <= `RESET_VECTOR; // Can't happen
|
// endcase
|
// endcase
|
// dpcv <= 1'b1;
|
// dpcv <= 1'b1;
|
end
|
end
|
// Software exceptions
|
// Software exceptions
|
// We probably want to return to the excepting instruction.
|
// We probably want to return to the excepting instruction.
|
`EX_DBERR:
|
`EX_DBERR:
|
begin
|
begin
|
pccap <= 1'b0;
|
pccap <= 1'b0;
|
dIR <= {`MISC,9'd0,wextype,`SYSCALL};
|
dIR <= {`MISC,9'd0,wextype,`SYSCALL};
|
dpc <= wpc;
|
dpc <= wpc;
|
end
|
end
|
default:
|
default:
|
begin
|
begin
|
pccap <= 1'b0;
|
pccap <= 1'b0;
|
dIR <= {`MISC,9'd0,wextype,`SYSCALL};
|
dIR <= {`MISC,9'd0,wextype,`SYSCALL};
|
dpc <= wpc;
|
dpc <= wpc;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
// Hold onto the last register update
|
// Hold onto the last register update
|
//begin
|
//begin
|
// if (tRt[4:0]!=5'd0 && tRt[4:0]!=5'd29) begin
|
// if (tRt[4:0]!=5'd0 && tRt[4:0]!=5'd29) begin
|
// uRt <= tRt;
|
// uRt <= tRt;
|
// uData <= tData;
|
// uData <= tData;
|
// end
|
// end
|
//end
|
//end
|
|
|
//=============================================================================
|
//=============================================================================
|
// Cache loader
|
// Cache loader
|
//=============================================================================
|
//=============================================================================
|
case(cstate)
|
case(cstate)
|
IDLE:
|
IDLE:
|
if (triggerDCacheLoad) begin
|
if (triggerDCacheLoad) begin
|
dcaccess <= 1'b1;
|
dcaccess <= 1'b1;
|
bte_o <= 2'b00; // linear burst
|
bte_o <= 2'b00; // linear burst
|
cti_o <= 3'b001; // constant address burst access
|
cti_o <= 3'b001; // constant address burst access
|
bl_o <= 5'd7;
|
bl_o <= 5'd7;
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= 8'hFF;
|
sel_o <= 8'hFF;
|
adr_o <= {pea[63:6],6'h00};
|
adr_o <= {pea[63:6],6'h00};
|
dcadr <= {pea[14:6],6'h00};
|
dcadr <= {pea[14:6],6'h00};
|
cstate <= DCACT;
|
cstate <= DCACT;
|
end
|
end
|
else if (triggerICacheLoad) begin
|
else if (triggerICacheLoad) begin
|
icaccess <= 1'b1;
|
icaccess <= 1'b1;
|
bte_o <= 2'b00; // linear burst
|
bte_o <= 2'b00; // linear burst
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= 8'hFF;
|
sel_o <= 8'hFF;
|
if (ICacheAct) begin
|
if (ICacheAct) begin
|
cti_o <= 3'b001; // constant address burst access
|
cti_o <= 3'b001; // constant address burst access
|
bl_o <= 5'd7;
|
bl_o <= 5'd7;
|
adr_o <= {ppc[63:6],6'h00};
|
adr_o <= {ppc[63:6],6'h00};
|
icadr <= {ppc[63:6],6'h00};
|
icadr <= {ppc[63:6],6'h00};
|
cstate <= ICACT1;
|
cstate <= ICACT1;
|
end
|
end
|
else begin
|
else begin
|
|
$display("Fetching %h", {ppc[31:2],2'b00});
|
cti_o <= 3'b000;
|
cti_o <= 3'b000;
|
bl_o <= 5'd0;
|
bl_o <= 5'd0;
|
adr_o <= {ppc[63:2],2'b00};
|
adr_o <= {ppc[63:2],2'b00};
|
cstate <= ICACT2;
|
cstate <= ICACT2;
|
end
|
end
|
end
|
end
|
// WISHBONE burst accesses
|
// WISHBONE burst accesses
|
//
|
//
|
ICACT1:
|
ICACT1:
|
if (ack_i|err_i) begin
|
if (ack_i|err_i) begin
|
icadr[5:3] <= icadr[5:3] + 3'd1;
|
icadr[5:3] <= icadr[5:3] + 3'd1;
|
if (icadr[5:3]==3'd6)
|
if (icadr[5:3]==3'd6)
|
cti_o <= 3'b111; // Last cycle ahead
|
cti_o <= 3'b111; // Last cycle ahead
|
if (icadr[5:3]==3'd7) begin
|
if (icadr[5:3]==3'd7) begin
|
cti_o <= 3'b000; // back to non-burst mode
|
cti_o <= 3'b000; // back to non-burst mode
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
tmem[adr_o[13:6]] <= adr_o[63:14]; // This will cause ihit to go high
|
tmem[adr_o[13:6]] <= adr_o[63:14]; // This will cause ihit to go high
|
tvalid[adr_o[13:6]] <= 1'b1;
|
tvalid[adr_o[13:6]] <= 1'b1;
|
icaccess <= 1'b0;
|
icaccess <= 1'b0;
|
cstate <= IDLE;
|
cstate <= IDLE;
|
end
|
end
|
end
|
end
|
//SYSCALL 509: 00000000_00000000_11111110_10010111
|
//SYSCALL 509: 00000000_00000000_11111110_10010111
|
ICACT2:
|
ICACT2:
|
begin
|
begin
|
if (ack_i|err_i) begin
|
if (ack_i|err_i) begin
|
ibufadr <= adr_o;
|
ibufadr <= adr_o;
|
if (err_i)
|
if (err_i)
|
insnbuf <= syscall509;
|
insnbuf <= syscall509;
|
else
|
else
|
insnbuf <= adr_o[2] ? dat_i[63:32] : dat_i[31:0];
|
insnbuf <= adr_o[2] ? dat_i[63:32] : dat_i[31:0];
|
|
$display("Fetched: %h", adr_o[2] ? dat_i[63:32] : dat_i[31:0]);
|
cti_o <= 3'b000; // back to non-burst mode
|
cti_o <= 3'b000; // back to non-burst mode
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
icaccess <= 1'b0;
|
icaccess <= 1'b0;
|
cstate <= IDLE;
|
cstate <= IDLE;
|
end
|
end
|
end
|
end
|
|
|
DCACT:
|
DCACT:
|
if (ack_i|err_i) begin
|
if (ack_i|err_i) begin
|
dcadr[5:3] <= dcadr[5:3] + 3'd1;
|
dcadr[5:3] <= dcadr[5:3] + 3'd1;
|
if (dcadr[5:3]==3'd6)
|
if (dcadr[5:3]==3'd6)
|
cti_o <= 3'b111; // Last cycle ahead
|
cti_o <= 3'b111; // Last cycle ahead
|
if (dcadr[5:3]==3'h7) begin
|
if (dcadr[5:3]==3'h7) begin
|
cti_o <= 3'b000; // back to non-burst mode
|
cti_o <= 3'b000; // back to non-burst mode
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
dcaccess <= 1'b0;
|
dcaccess <= 1'b0;
|
cstate <= IDLE;
|
cstate <= IDLE;
|
end
|
end
|
end
|
end
|
|
|
endcase // cstate
|
endcase // cstate
|
end // RUN
|
end // RUN
|
endcase
|
endcase
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|