Line 5... |
Line 5... |
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core
|
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core
|
//
|
//
|
// Purpose: This is the top level module holding the core of the Zip CPU
|
// Purpose: This is the top level module holding the core of the Zip CPU
|
// together. The Zip CPU is designed to be as simple as possible.
|
// together. The Zip CPU is designed to be as simple as possible.
|
// (actual implementation aside ...) The instruction set is about as
|
// (actual implementation aside ...) The instruction set is about as
|
// RISC as you can get, there are only 16 instruction types supported.
|
// RISC as you can get, with only 26 instruction types currently supported.
|
|
// (There are still 8-instruction Op-Codes reserved for floating point,
|
|
// and 5 which can be used for transactions not requiring registers.)
|
// Please see the accompanying spec.pdf file for a description of these
|
// Please see the accompanying spec.pdf file for a description of these
|
// instructions.
|
// instructions.
|
//
|
//
|
// All instructions are 32-bits wide. All bus accesses, both address and
|
// All instructions are 32-bits wide. All bus accesses, both address and
|
// data, are 32-bits over a wishbone bus.
|
// data, are 32-bits over a wishbone bus.
|
Line 24... |
Line 26... |
//
|
//
|
// 4. Apply Instruction
|
// 4. Apply Instruction
|
//
|
//
|
// 4. Write-back Results
|
// 4. Write-back Results
|
//
|
//
|
// Further information about the inner workings of this CPU may be
|
// Further information about the inner workings of this CPU, such as
|
// found in the spec.pdf file. (The documentation within this file
|
// what causes pipeline stalls, may be found in the spec.pdf file. (The
|
// had become out of date and out of sync with the spec.pdf, so look
|
// documentation within this file had become out of date and out of sync
|
// to the spec.pdf for accurate and up to date information.)
|
// with the spec.pdf, so look to the spec.pdf for accurate and up to date
|
|
// information.)
|
//
|
//
|
//
|
//
|
// In general, the pipelining is controlled by three pieces of logic
|
// In general, the pipelining is controlled by three pieces of logic
|
// per stage: _ce, _stall, and _valid. _valid means that the stage
|
// per stage: _ce, _stall, and _valid. _valid means that the stage
|
// holds a valid instruction. _ce means that the instruction from the
|
// holds a valid instruction. _ce means that the instruction from the
|
Line 101... |
Line 104... |
//
|
//
|
//
|
//
|
//
|
//
|
`define CPU_CC_REG 4'he
|
`define CPU_CC_REG 4'he
|
`define CPU_PC_REG 4'hf
|
`define CPU_PC_REG 4'hf
|
`define CPU_CLRCACHE_BIT 14 // Floating point error flag, set on error
|
`define CPU_CLRCACHE_BIT 14 // Set to clear the I-cache, automatically clears
|
`define CPU_PHASE_BIT 13 // Floating point error flag, set on error
|
`define CPU_PHASE_BIT 13 // Set if we are executing the latter half of a VLIW
|
`define CPU_FPUERR_BIT 12 // Floating point error flag, set on error
|
`define CPU_FPUERR_BIT 12 // Floating point error flag, set on error
|
`define CPU_DIVERR_BIT 11 // Divide error flag, set on divide by zero
|
`define CPU_DIVERR_BIT 11 // Divide error flag, set on divide by zero
|
`define CPU_BUSERR_BIT 10 // Bus error flag, set on error
|
`define CPU_BUSERR_BIT 10 // Bus error flag, set on error
|
`define CPU_TRAP_BIT 9 // User TRAP has taken place
|
`define CPU_TRAP_BIT 9 // User TRAP has taken place
|
`define CPU_ILL_BIT 8 // Illegal instruction
|
`define CPU_ILL_BIT 8 // Illegal instruction
|
Line 204... |
Line 207... |
|
|
// Condition codes
|
// Condition codes
|
// (BUS, TRAP,ILL,BREAKEN,STEP,GIE,SLEEP ), V, N, C, Z
|
// (BUS, TRAP,ILL,BREAKEN,STEP,GIE,SLEEP ), V, N, C, Z
|
reg [3:0] flags, iflags;
|
reg [3:0] flags, iflags;
|
wire [14:0] w_uflags, w_iflags;
|
wire [14:0] w_uflags, w_iflags;
|
reg trap, break_en, step, gie, sleep, r_halted,
|
reg trap, break_en, step, gie, sleep, r_halted;
|
break_pending;
|
wire break_pending;
|
wire w_clear_icache;
|
wire w_clear_icache;
|
`ifdef OPT_ILLEGAL_INSTRUCTION
|
`ifdef OPT_ILLEGAL_INSTRUCTION
|
reg ill_err_u, ill_err_i;
|
reg ill_err_u, ill_err_i;
|
`else
|
`else
|
wire ill_err_u, ill_err_i;
|
wire ill_err_u, ill_err_i;
|
Line 277... |
Line 280... |
//
|
//
|
//
|
//
|
//
|
//
|
// Now, let's read our operands
|
// Now, let's read our operands
|
reg [4:0] alu_reg;
|
reg [4:0] alu_reg;
|
reg [3:0] opn;
|
wire [3:0] opn;
|
reg [4:0] opR;
|
wire [4:0] opR;
|
reg [31:0] r_opA, r_opB;
|
reg [31:0] r_opA, r_opB;
|
reg [(AW-1):0] op_pc;
|
reg [(AW-1):0] op_pc;
|
wire [31:0] w_opA, w_opB;
|
wire [31:0] w_opA, w_opB;
|
wire [31:0] opA_nowait, opB_nowait, opA, opB;
|
wire [31:0] opA_nowait, opB_nowait, opA, opB;
|
reg opR_wr, opR_cc, opF_wr, op_gie;
|
reg opR_wr, opF_wr;
|
|
wire op_gie, opR_cc;
|
wire [14:0] opFl;
|
wire [14:0] opFl;
|
reg [5:0] r_opF;
|
reg [5:0] r_opF;
|
wire [7:0] opF;
|
wire [7:0] opF;
|
wire op_ce, op_phase, op_pipe, op_change_data_ce;
|
wire op_ce, op_phase, op_pipe, op_change_data_ce;
|
// Some pipeline control wires
|
// Some pipeline control wires
|
Line 299... |
Line 303... |
reg op_illegal;
|
reg op_illegal;
|
`else
|
`else
|
wire op_illegal;
|
wire op_illegal;
|
assign op_illegal = 1'b0;
|
assign op_illegal = 1'b0;
|
`endif
|
`endif
|
reg op_break;
|
wire op_break;
|
wire op_lock;
|
wire op_lock;
|
|
|
|
|
//
|
//
|
//
|
//
|
// PIPELINE STAGE #4 :: ALU / Memory
|
// PIPELINE STAGE #4 :: ALU / Memory
|
// Variable declarations
|
// Variable declarations
|
//
|
//
|
//
|
//
|
reg [(AW-1):0] alu_pc;
|
wire [(AW-1):0] alu_pc;
|
reg r_alu_pc_valid, mem_pc_valid;
|
reg r_alu_pc_valid, mem_pc_valid;
|
wire alu_pc_valid;
|
wire alu_pc_valid;
|
wire alu_phase;
|
wire alu_phase;
|
wire alu_ce, alu_stall;
|
wire alu_ce, alu_stall;
|
wire [31:0] alu_result;
|
wire [31:0] alu_result;
|
wire [3:0] alu_flags;
|
wire [3:0] alu_flags;
|
wire alu_valid, alu_busy;
|
wire alu_valid, alu_busy;
|
wire set_cond;
|
wire set_cond;
|
reg alu_wr, alF_wr, alu_gie;
|
reg alu_wr, alF_wr;
|
wire alu_illegal_op;
|
wire alu_gie, alu_illegal_op, alu_illegal;
|
wire alu_illegal;
|
|
|
|
|
|
|
|
wire mem_ce, mem_stalled;
|
wire mem_ce, mem_stalled;
|
`ifdef OPT_PIPELINED_BUS_ACCESS
|
`ifdef OPT_PIPELINED_BUS_ACCESS
|
Line 471... |
Line 474... |
// through the ALU. Break instructions are not allowed through
|
// through the ALU. Break instructions are not allowed through
|
// the ALU.
|
// the ALU.
|
`ifdef OPT_PIPELINED
|
`ifdef OPT_PIPELINED
|
assign alu_stall = (((~master_ce)||(mem_rdbusy)||(alu_busy))&&(opvalid_alu)) //Case 1&2
|
assign alu_stall = (((~master_ce)||(mem_rdbusy)||(alu_busy))&&(opvalid_alu)) //Case 1&2
|
||((opvalid)&&(op_lock)&&(op_lock_stall))
|
||((opvalid)&&(op_lock)&&(op_lock_stall))
|
||((opvalid)&&(op_break))
|
||((opvalid)&&(op_break)) // || op_illegal
|
||(wr_reg_ce)&&(wr_write_cc)
|
||(wr_reg_ce)&&(wr_write_cc)
|
||(div_busy)||(fpu_busy);
|
||(div_busy)||(fpu_busy);
|
assign alu_ce = (master_ce)&&(opvalid_alu)&&(~alu_stall)
|
assign alu_ce = (master_ce)&&(opvalid_alu)&&(~alu_stall)
|
&&(~clear_pipeline);
|
&&(~clear_pipeline);
|
`else
|
`else
|
Line 742... |
Line 745... |
opB_rd <= dcdB_rd;
|
opB_rd <= dcdB_rd;
|
end
|
end
|
`endif
|
`endif
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
|
`ifdef OPT_PIPELINED
|
if (op_change_data_ce)
|
if (op_change_data_ce)
|
|
`endif
|
begin
|
begin
|
|
`ifdef OPT_PIPELINED
|
if ((wr_reg_ce)&&(wr_reg_id == dcdA))
|
if ((wr_reg_ce)&&(wr_reg_id == dcdA))
|
r_opA <= wr_gpreg_vl;
|
r_opA <= wr_gpreg_vl;
|
else if (dcdA_pc)
|
else
|
|
`endif
|
|
if (dcdA_pc)
|
r_opA <= w_pcA_v;
|
r_opA <= w_pcA_v;
|
else if (dcdA_cc)
|
else if (dcdA_cc)
|
r_opA <= { w_cpu_info, w_opA[22:15], (dcdA[4])?w_uflags:w_iflags };
|
r_opA <= { w_cpu_info, w_opA[22:16], 1'b0, (dcdA[4])?w_uflags:w_iflags };
|
else
|
else
|
r_opA <= w_opA;
|
r_opA <= w_opA;
|
`ifdef OPT_PIPELINED
|
`ifdef OPT_PIPELINED
|
end else
|
end else
|
begin // We were going to pick these up when they became valid,
|
begin // We were going to pick these up when they became valid,
|
Line 773... |
Line 781... |
else
|
else
|
assign w_pcB_v = (dcdB[4] == dcd_gie)?dcd_pc:upc;
|
assign w_pcB_v = (dcdB[4] == dcd_gie)?dcd_pc:upc;
|
endgenerate
|
endgenerate
|
|
|
assign w_opBnI = (~dcdB_rd) ? 32'h00
|
assign w_opBnI = (~dcdB_rd) ? 32'h00
|
: (((wr_reg_ce)&&(wr_reg_id == dcdB)) ? wr_gpreg_vl
|
`ifdef OPT_PIPELINED
|
|
: ((wr_reg_ce)&&(wr_reg_id == dcdB)) ? wr_gpreg_vl
|
|
`endif
|
: ((dcdB_pc) ? w_pcB_v
|
: ((dcdB_pc) ? w_pcB_v
|
: ((dcdB_cc) ? { w_cpu_info, w_opB[22:15], // w_opB[31:14],
|
: ((dcdB_cc) ? { w_cpu_info, w_opB[22:16], // w_opB[31:14],
|
(dcdB[4])?w_uflags:w_iflags}
|
1'b0, (dcdB[4])?w_uflags:w_iflags}
|
: w_opB)));
|
: w_opB));
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
|
`ifdef OPT_PIPELINED
|
if (op_change_data_ce)
|
if (op_change_data_ce)
|
r_opB <= w_opBnI + dcdI;
|
r_opB <= w_opBnI + dcdI;
|
`ifdef OPT_PIPELINED
|
|
else if ((wr_reg_ce)&&(opB_id == wr_reg_id)&&(opB_rd))
|
else if ((wr_reg_ce)&&(opB_id == wr_reg_id)&&(opB_rd))
|
r_opB <= wr_gpreg_vl;
|
r_opB <= wr_gpreg_vl;
|
|
`else
|
|
r_opB <= w_opBnI + dcdI;
|
`endif
|
`endif
|
|
|
// The logic here has become more complex than it should be, no thanks
|
// The logic here has become more complex than it should be, no thanks
|
// to Xilinx's Vivado trying to help. The conditions are supposed to
|
// to Xilinx's Vivado trying to help. The conditions are supposed to
|
// be two sets of four bits: the top bits specify what bits matter, the
|
// be two sets of four bits: the top bits specify what bits matter, the
|
Line 797... |
Line 809... |
// conditions checking those bits. Therefore, Vivado complains that
|
// conditions checking those bits. Therefore, Vivado complains that
|
// these two bits are redundant. Hence the convoluted expression
|
// these two bits are redundant. Hence the convoluted expression
|
// below, arriving at what we finally want in the (now wire net)
|
// below, arriving at what we finally want in the (now wire net)
|
// opF.
|
// opF.
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
|
`ifdef OPT_PIPELINED
|
if (op_ce) // Cannot do op_change_data_ce here since opF depends
|
if (op_ce) // Cannot do op_change_data_ce here since opF depends
|
// upon being either correct for a valid op, or correct
|
// upon being either correct for a valid op, or correct
|
// for the last valid op
|
// for the last valid op
|
|
`endif
|
begin // Set the flag condition codes, bit order is [3:0]=VNCZ
|
begin // Set the flag condition codes, bit order is [3:0]=VNCZ
|
case(dcdF[2:0])
|
case(dcdF[2:0])
|
3'h0: r_opF <= 6'h00; // Always
|
3'h0: r_opF <= 6'h00; // Always
|
`ifdef OPT_NEW_INSTRUCTION_SET
|
`ifdef OPT_NEW_INSTRUCTION_SET
|
// These were remapped as part of the new instruction
|
// These were remapped as part of the new instruction
|
Line 834... |
Line 848... |
initial opvalid_alu = 1'b0;
|
initial opvalid_alu = 1'b0;
|
initial opvalid_mem = 1'b0;
|
initial opvalid_mem = 1'b0;
|
initial opvalid_div = 1'b0;
|
initial opvalid_div = 1'b0;
|
initial opvalid_fpu = 1'b0;
|
initial opvalid_fpu = 1'b0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (i_rst)
|
if ((i_rst)||(clear_pipeline))
|
begin
|
begin
|
opvalid <= 1'b0;
|
opvalid <= 1'b0;
|
opvalid_alu <= 1'b0;
|
opvalid_alu <= 1'b0;
|
opvalid_mem <= 1'b0;
|
opvalid_mem <= 1'b0;
|
opvalid_div <= 1'b0;
|
opvalid_div <= 1'b0;
|
Line 863... |
Line 877... |
opvalid_alu <= (dcdALU)&&(w_opvalid);
|
opvalid_alu <= (dcdALU)&&(w_opvalid);
|
opvalid_mem <= (dcdM)&&(w_opvalid);
|
opvalid_mem <= (dcdM)&&(w_opvalid);
|
opvalid_div <= (dcdDV)&&(w_opvalid);
|
opvalid_div <= (dcdDV)&&(w_opvalid);
|
opvalid_fpu <= (dcdFP)&&(w_opvalid);
|
opvalid_fpu <= (dcdFP)&&(w_opvalid);
|
`endif
|
`endif
|
end else if ((clear_pipeline)||(adf_ce_unconditional)||(mem_ce))
|
end else if ((adf_ce_unconditional)||(mem_ce))
|
begin
|
begin
|
opvalid <= 1'b0;
|
opvalid <= 1'b0;
|
opvalid_alu <= 1'b0;
|
opvalid_alu <= 1'b0;
|
opvalid_mem <= 1'b0;
|
opvalid_mem <= 1'b0;
|
opvalid_div <= 1'b0;
|
opvalid_div <= 1'b0;
|
Line 881... |
Line 895... |
// break to repeat and continue upon return. To get out of this
|
// break to repeat and continue upon return. To get out of this
|
// condition, replace the break instruction with what it is supposed
|
// condition, replace the break instruction with what it is supposed
|
// to be, step through it, and then replace it back. In this fashion,
|
// to be, step through it, and then replace it back. In this fashion,
|
// a debugger can step through code.
|
// a debugger can step through code.
|
// assign w_op_break = (dcd_break)&&(r_dcdI[15:0] == 16'h0001);
|
// assign w_op_break = (dcd_break)&&(r_dcdI[15:0] == 16'h0001);
|
initial op_break = 1'b0;
|
`ifdef OPT_PIPELINED
|
|
reg r_op_break;
|
|
|
|
initial r_op_break = 1'b0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (i_rst) op_break <= 1'b0;
|
if (i_rst) r_op_break <= 1'b0;
|
else if (op_ce) op_break <= (dcd_break); // &&(dcdvalid)
|
else if (op_ce) r_op_break <= (dcd_break); //||dcd_illegal &&(dcdvalid)
|
else if ((clear_pipeline)||(~opvalid))
|
else if ((clear_pipeline)||(~opvalid))
|
op_break <= 1'b0;
|
r_op_break <= 1'b0;
|
|
assign op_break = r_op_break;
|
|
`else
|
|
assign op_break = dcd_break;
|
|
`endif
|
|
|
`ifdef OPT_PIPELINED
|
`ifdef OPT_PIPELINED
|
generate
|
generate
|
if (IMPLEMENT_LOCK != 0)
|
if (IMPLEMENT_LOCK != 0)
|
begin
|
begin
|
Line 933... |
Line 954... |
`ifdef OPT_PIPELINED
|
`ifdef OPT_PIPELINED
|
op_illegal <= (dcdvalid)&&((dcd_illegal)||((dcd_lock)&&(IMPLEMENT_LOCK == 0)));
|
op_illegal <= (dcdvalid)&&((dcd_illegal)||((dcd_lock)&&(IMPLEMENT_LOCK == 0)));
|
`else
|
`else
|
op_illegal <= (dcdvalid)&&((dcd_illegal)||(dcd_lock));
|
op_illegal <= (dcdvalid)&&((dcd_illegal)||(dcd_lock));
|
`endif
|
`endif
|
`endif
|
|
else if(alu_ce)
|
else if(alu_ce)
|
op_illegal <= 1'b0;
|
op_illegal <= 1'b0;
|
|
`endif
|
|
|
// No generate on EARLY_BRANCHING here, since if EARLY_BRANCHING is not
|
// No generate on EARLY_BRANCHING here, since if EARLY_BRANCHING is not
|
// set, dcd_early_branch will simply be a wire connected to zero and
|
// set, dcd_early_branch will simply be a wire connected to zero and
|
// this logic should just optimize.
|
// this logic should just optimize.
|
|
`ifdef OPT_PIPELINED
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (op_ce)
|
if (op_ce)
|
begin
|
begin
|
opF_wr <= (dcdF_wr)&&((~dcdR_cc)||(~dcdR_wr))
|
opF_wr <= (dcdF_wr)&&((~dcdR_cc)||(~dcdR_wr))
|
&&(~dcd_early_branch)&&(~dcd_illegal);
|
&&(~dcd_early_branch)&&(~dcd_illegal);
|
opR_wr <= (dcdR_wr)&&(~dcd_early_branch)&&(~dcd_illegal);
|
opR_wr <= (dcdR_wr)&&(~dcd_early_branch)&&(~dcd_illegal);
|
end
|
end
|
|
`else
|
|
always @(posedge i_clk)
|
|
begin
|
|
opF_wr <= (dcdF_wr)&&((~dcdR_cc)||(~dcdR_wr))
|
|
&&(~dcd_early_branch)&&(~dcd_illegal);
|
|
opR_wr <= (dcdR_wr)&&(~dcd_early_branch)&&(~dcd_illegal);
|
|
end
|
|
`endif
|
|
|
|
`ifdef OPT_PIPELINED
|
|
reg [3:0] r_opn;
|
|
reg [4:0] r_opR;
|
|
reg r_opR_cc;
|
|
reg r_op_gie;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (op_change_data_ce)
|
if (op_change_data_ce)
|
begin
|
begin
|
opn <= dcdOp; // Which ALU operation?
|
r_opn <= dcdOp; // Which ALU operation?
|
// opM <= dcdM; // Is this a memory operation?
|
// opM <= dcdM; // Is this a memory operation?
|
// What register will these results be written into?
|
// What register will these results be written into?
|
opR <= dcdR;
|
r_opR <= dcdR;
|
opR_cc <= (dcdR_cc)&&(dcdR_wr)&&(dcdR[4]==dcd_gie);
|
r_opR_cc <= (dcdR_cc)&&(dcdR_wr)&&(dcdR[4]==dcd_gie);
|
// User level (1), vs supervisor (0)/interrupts disabled
|
// User level (1), vs supervisor (0)/interrupts disabled
|
op_gie <= dcd_gie;
|
r_op_gie <= dcd_gie;
|
|
|
|
|
//
|
//
|
op_pc <= (dcd_early_branch)?dcd_branch_pc:dcd_pc;
|
op_pc <= (dcd_early_branch)?dcd_branch_pc:dcd_pc;
|
end
|
end
|
|
assign opn = r_opn;
|
|
assign opR = r_opR;
|
|
assign op_gie = r_op_gie;
|
|
assign opR_cc = r_opR_cc;
|
|
`else
|
|
assign opn = dcdOp;
|
|
assign opR = dcdR;
|
|
assign op_gie = dcd_gie;
|
|
// With no pipelining, there is no early branching. We keep it
|
|
always @(posedge i_clk)
|
|
op_pc <= (dcd_early_branch)?dcd_branch_pc:dcd_pc;
|
|
`endif
|
assign opFl = (op_gie)?(w_uflags):(w_iflags);
|
assign opFl = (op_gie)?(w_uflags):(w_iflags);
|
|
|
`ifdef OPT_VLIW
|
`ifdef OPT_VLIW
|
reg r_op_phase;
|
reg r_op_phase;
|
initial r_op_phase = 1'b0;
|
initial r_op_phase = 1'b0;
|
Line 1164... |
Line 1211... |
assign alu_phase = r_alu_phase;
|
assign alu_phase = r_alu_phase;
|
`else
|
`else
|
assign alu_phase = 1'b0;
|
assign alu_phase = 1'b0;
|
`endif
|
`endif
|
|
|
|
`ifdef OPT_PIPELINED
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (adf_ce_unconditional)
|
if (adf_ce_unconditional)
|
alu_reg <= opR;
|
alu_reg <= opR;
|
else if ((i_halt)&&(i_dbg_we))
|
else if ((i_halt)&&(i_dbg_we))
|
alu_reg <= i_dbg_reg;
|
alu_reg <= i_dbg_reg;
|
|
`else
|
|
always @(posedge i_clk)
|
|
if ((i_halt)&&(i_dbg_we))
|
|
alu_reg <= i_dbg_reg;
|
|
else
|
|
alu_reg <= opR;
|
|
`endif
|
|
|
//
|
//
|
// DEBUG Register write access starts here
|
// DEBUG Register write access starts here
|
//
|
//
|
reg dbgv;
|
reg dbgv;
|
Line 1180... |
Line 1235... |
always @(posedge i_clk)
|
always @(posedge i_clk)
|
dbgv <= (~i_rst)&&(i_halt)&&(i_dbg_we)&&(r_halted);
|
dbgv <= (~i_rst)&&(i_halt)&&(i_dbg_we)&&(r_halted);
|
reg [31:0] dbg_val;
|
reg [31:0] dbg_val;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
dbg_val <= i_dbg_data;
|
dbg_val <= i_dbg_data;
|
|
`ifdef OPT_PIPELINED
|
|
reg r_alu_gie;
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((adf_ce_unconditional)||(mem_ce))
|
if ((adf_ce_unconditional)||(mem_ce))
|
alu_gie <= op_gie;
|
r_alu_gie <= op_gie;
|
|
assign alu_gie = r_alu_gie;
|
|
|
|
reg [(AW-1):0] r_alu_pc;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((adf_ce_unconditional)
|
if ((adf_ce_unconditional)
|
||((master_ce)&&(opvalid_mem)&&(~clear_pipeline)
|
||((master_ce)&&(opvalid_mem)&&(~clear_pipeline)
|
&&(~mem_stalled)))
|
&&(~mem_stalled)))
|
alu_pc <= op_pc;
|
r_alu_pc <= op_pc;
|
|
assign alu_pc = r_alu_pc;
|
|
`else
|
|
assign alu_gie = op_gie;
|
|
assign alu_pc = op_pc;
|
|
`endif
|
|
|
`ifdef OPT_ILLEGAL_INSTRUCTION
|
`ifdef OPT_ILLEGAL_INSTRUCTION
|
reg r_alu_illegal;
|
reg r_alu_illegal;
|
initial r_alu_illegal = 0;
|
initial r_alu_illegal = 0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
Line 1393... |
Line 1459... |
if ((i_rst)||(i_halt))
|
if ((i_rst)||(i_halt))
|
break_en <= 1'b0;
|
break_en <= 1'b0;
|
else if ((wr_reg_ce)&&(wr_write_scc))
|
else if ((wr_reg_ce)&&(wr_write_scc))
|
break_en <= wr_spreg_vl[`CPU_BREAK_BIT];
|
break_en <= wr_spreg_vl[`CPU_BREAK_BIT];
|
|
|
initial break_pending = 1'b0;
|
`ifdef OPT_PIPELINED
|
|
reg r_break_pending;
|
|
|
|
initial r_break_pending = 1'b0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((i_rst)||(clear_pipeline)||(~opvalid))
|
if ((i_rst)||(clear_pipeline)||(~opvalid))
|
break_pending <= 1'b0;
|
r_break_pending <= 1'b0;
|
else if (op_break)
|
else if (op_break)
|
break_pending <= (~alu_busy)&&(~div_busy)&&(~fpu_busy)&&(~mem_busy);
|
r_break_pending <= (~alu_busy)&&(~div_busy)&&(~fpu_busy)&&(~mem_busy);
|
else
|
else
|
break_pending <= 1'b0;
|
r_break_pending <= 1'b0;
|
|
assign break_pending = r_break_pending;
|
|
`else
|
|
assign break_pending = op_break;
|
|
`endif
|
|
|
|
|
assign o_break = ((break_en)||(~op_gie))&&(break_pending)
|
assign o_break = ((break_en)||(~op_gie))&&(break_pending)
|
&&(~clear_pipeline)
|
&&(~clear_pipeline)
|
||((~alu_gie)&&(bus_err))
|
||((~alu_gie)&&(bus_err))
|
Line 1735... |
Line 1808... |
if (i_dbg_reg[3:0] == `CPU_PC_REG)
|
if (i_dbg_reg[3:0] == `CPU_PC_REG)
|
o_dbg_reg <= {{(32-AW){1'b0}},(i_dbg_reg[4])?upc:ipc};
|
o_dbg_reg <= {{(32-AW){1'b0}},(i_dbg_reg[4])?upc:ipc};
|
else if (i_dbg_reg[3:0] == `CPU_CC_REG)
|
else if (i_dbg_reg[3:0] == `CPU_CC_REG)
|
begin
|
begin
|
o_dbg_reg[14:0] <= (i_dbg_reg[4])?w_uflags:w_iflags;
|
o_dbg_reg[14:0] <= (i_dbg_reg[4])?w_uflags:w_iflags;
|
|
o_dbg_reg[15] <= 1'b0;
|
o_dbg_reg[31:23] <= w_cpu_info;
|
o_dbg_reg[31:23] <= w_cpu_info;
|
o_dbg_reg[`CPU_GIE_BIT] <= gie;
|
o_dbg_reg[`CPU_GIE_BIT] <= gie;
|
end
|
end
|
end
|
end
|
end else begin
|
end else begin
|
Line 1748... |
Line 1822... |
if (i_dbg_reg[3:0] == `CPU_PC_REG)
|
if (i_dbg_reg[3:0] == `CPU_PC_REG)
|
o_dbg_reg <= (i_dbg_reg[4])?upc:ipc;
|
o_dbg_reg <= (i_dbg_reg[4])?upc:ipc;
|
else if (i_dbg_reg[3:0] == `CPU_CC_REG)
|
else if (i_dbg_reg[3:0] == `CPU_CC_REG)
|
begin
|
begin
|
o_dbg_reg[14:0] <= (i_dbg_reg[4])?w_uflags:w_iflags;
|
o_dbg_reg[14:0] <= (i_dbg_reg[4])?w_uflags:w_iflags;
|
|
o_dbg_reg[15] <= 1'b0;
|
o_dbg_reg[31:23] <= w_cpu_info;
|
o_dbg_reg[31:23] <= w_cpu_info;
|
o_dbg_reg[`CPU_GIE_BIT] <= gie;
|
o_dbg_reg[`CPU_GIE_BIT] <= gie;
|
end
|
end
|
end
|
end
|
end endgenerate
|
end endgenerate
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
o_dbg_cc <= { o_break, bus_err, gie, sleep };
|
o_dbg_cc <= { o_break, bus_err, gie, sleep };
|
|
|
|
`ifdef OPT_PIPELINED
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
r_halted <= (i_halt)&&(
|
r_halted <= (i_halt)&&(
|
// To be halted, any long lasting instruction must
|
// To be halted, any long lasting instruction must
|
// be completed.
|
// be completed.
|
(~pf_cyc)&&(~mem_busy)&&(~alu_busy)
|
(~pf_cyc)&&(~mem_busy)&&(~alu_busy)
|
&&(~div_busy)&&(~fpu_busy)
|
&&(~div_busy)&&(~fpu_busy)
|
// Operations must either be valid, or illegal
|
// Operations must either be valid, or illegal
|
&&((opvalid)||(i_rst)||(dcd_illegal))
|
&&((opvalid)||(i_rst)||(dcd_illegal))
|
// Decode stage must be either valid, in reset, or ill
|
// Decode stage must be either valid, in reset, or ill
|
&&((dcdvalid)||(i_rst)||(pf_illegal)));
|
&&((dcdvalid)||(i_rst)||(pf_illegal)));
|
|
`else
|
|
always @(posedge i_clk)
|
|
r_halted <= (i_halt)&&((opvalid)||(i_rst));
|
|
`endif
|
assign o_dbg_stall = ~r_halted;
|
assign o_dbg_stall = ~r_halted;
|
|
|
//
|
//
|
//
|
//
|
// Produce accounting outputs: Account for any CPU stalls, so we can
|
// Produce accounting outputs: Account for any CPU stalls, so we can
|
Line 1780... |
Line 1860... |
assign o_op_stall = (master_ce)&&(op_stall);
|
assign o_op_stall = (master_ce)&&(op_stall);
|
assign o_pf_stall = (master_ce)&&(~pf_valid);
|
assign o_pf_stall = (master_ce)&&(~pf_valid);
|
assign o_i_count = (alu_pc_valid)&&(~clear_pipeline);
|
assign o_i_count = (alu_pc_valid)&&(~clear_pipeline);
|
|
|
`ifdef DEBUG_SCOPE
|
`ifdef DEBUG_SCOPE
|
reg [31:0] r_stack;
|
// CLRPIP: If clear_pipeline, produce address ... can be 28 bits
|
always @(posedge i_clk)
|
// DATWR: If write value, produce 4-bits of register ID, 27 bits of value
|
if ((wr_reg_ce)&&(wr_reg_id == 5'h0d))
|
// STALL: If neither, produce pipeline stall information
|
r_stack <= wr_gpreg_vl;
|
// ADDR: If bus is valid, no ack, return the bus address
|
reg r_stack_pre, r_stack_post;
|
reg debug_trigger;
|
always @(posedge i_clk)
|
initial debug_trigger = 1'b0;
|
r_stack_pre <= (r_stack == 32'h03fff);
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
debug_trigger <= (!i_halt)&&(o_break);
|
r_stack_post <= (r_stack == 32'h03eeb);
|
|
|
wire [31:0] debug_flags;
|
always @(posedge i_clk)
|
assign debug_flags = { debug_trigger, 3'b101,
|
o_debug <= {
|
master_ce, i_halt, o_break, sleep,
|
/*
|
gie, ibus_err_flag, trap, ill_err_i,
|
o_break, i_wb_err, pf_pc[1:0],
|
r_clear_icache, pf_valid, pf_illegal, dcd_ce,
|
flags,
|
dcdvalid, dcd_stalled, op_ce, opvalid,
|
pf_valid, dcdvalid, opvalid, alu_valid, mem_valid,
|
op_pipe, alu_ce, alu_busy, alu_wr,
|
op_ce, alu_ce, mem_ce,
|
alu_illegal, alF_wr, mem_ce, mem_we,
|
//
|
mem_busy, mem_pipe_stalled, (new_pc), (dcd_early_branch) };
|
master_ce, opvalid_alu, opvalid_mem,
|
|
//
|
|
alu_stall, mem_busy, op_pipe, mem_pipe_stalled,
|
|
mem_we,
|
|
// ((opvalid_alu)&&(alu_stall))
|
|
// ||((opvalid_mem)&&(~op_pipe)&&(mem_busy))
|
|
// ||((opvalid_mem)&&( op_pipe)&&(mem_pipe_stalled)));
|
|
// opA[23:20], opA[3:0],
|
|
gie, sleep, wr_reg_ce, wr_gpreg_vl[4:0]
|
|
*/
|
|
/*
|
|
i_rst, master_ce, (new_pc),
|
|
((dcd_early_branch)&&(dcdvalid)),
|
|
pf_valid, pf_illegal,
|
|
op_ce, dcd_ce, dcdvalid, dcd_stalled,
|
|
pf_cyc, pf_stb, pf_we, pf_ack, pf_stall, pf_err,
|
|
pf_pc[7:0], pf_addr[7:0]
|
|
*/
|
|
|
|
(i_wb_err)||(r_stack_post), (gie)||(r_stack_pre), (alu_illegal)||(r_stack_post),
|
always @(posedge i_clk)
|
(new_pc)||((dcd_early_branch)&&(~clear_pipeline)),
|
begin
|
mem_busy,
|
if ((i_halt)||(!master_ce)||(debug_trigger)||(o_break))
|
(mem_busy)?{ (o_wb_gbl_stb|o_wb_lcl_stb), o_wb_we,
|
o_debug <= debug_flags;
|
o_wb_addr[8:0] }
|
else if ((mem_valid)||((~clear_pipeline)&&(~alu_illegal)
|
: { instruction[31:21] },
|
&&(((alu_wr)&&(alu_valid))
|
pf_valid, (pf_valid) ? alu_pc[14:0]
|
||(div_valid)||(fpu_valid))))
|
:{ pf_cyc, pf_stb, pf_pc[12:0] }
|
o_debug <= { debug_trigger, 1'b0, wr_reg_id[3:0], wr_gpreg_vl[25:0]};
|
|
else if (clear_pipeline)
|
/*
|
o_debug <= { debug_trigger, 3'b100, pf_pc[27:0] };
|
i_wb_err, gie, new_pc, dcd_early_branch, // 4
|
else if ((o_wb_gbl_stb)|(o_wb_lcl_stb))
|
pf_valid, pf_cyc, pf_stb, instruction_pc[0], // 4
|
o_debug <= {debug_trigger, 2'b11, o_wb_gbl_stb, o_wb_we,
|
instruction[30:27], // 4
|
(o_wb_we)?o_wb_data[26:0] : o_wb_addr[26:0] };
|
dcd_gie, mem_busy, o_wb_gbl_cyc, o_wb_gbl_stb, // 4
|
else
|
dcdvalid,
|
o_debug <= debug_flags;
|
((dcd_early_branch)&&(~clear_pipeline)) // 15
|
end
|
? dcd_branch_pc[14:0]:pf_pc[14:0]
|
|
*/
|
|
};
|
|
`endif
|
`endif
|
|
|
/*
|
|
always @(posedge i_clk)
|
|
o_debug <= {
|
|
// External control interaction (4b)
|
|
i_halt, i_rst, i_clear_cache, o_break,
|
|
// Bus interaction (8b)
|
|
pf_cyc,(o_wb_gbl_cyc|o_wb_lcl_cyc), o_wb_gbl_stb, o_wb_lcl_stb,
|
|
o_wb_we, i_wb_ack, i_wb_stall, i_wb_err,
|
|
// PC control (4b)
|
|
gie, new_pc, dcd_early_branch, 1'b0,
|
|
// Our list of pipeline stage values (8b)
|
|
pf_valid, pf_illegal, dcdvalid, opvalid, alu_valid, mem_valid,
|
|
alu_pc_valid, mem_pc_valid,
|
|
// Our list of circuit enables ... (8b)
|
|
(new_pc)||((dcd_early_branch)&&(~clear_pipeline)),
|
|
dcd_ce, op_ce, alu_ce, mem_ce, wr_reg_ce, wr_flags_ce,
|
|
1'b0,
|
|
// Useful PC values (64b)
|
|
((dcd_early_branch)&&(~clear_pipeline))
|
|
? dcd_branch_pc[15:0]:pf_pc[15:0],
|
|
(gie)?upc[15:0]:ipc[15:0], instruction_pc[15:0], instruction[31:16] };
|
|
*/
|
|
|
|
endmodule
|
endmodule
|
|
|
No newline at end of file
|
No newline at end of file
|