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 135... |
Line 138... |
`ifdef DEBUG_SCOPE
|
`ifdef DEBUG_SCOPE
|
, o_debug
|
, o_debug
|
`endif
|
`endif
|
);
|
);
|
parameter RESET_ADDRESS=32'h0100000, ADDRESS_WIDTH=24,
|
parameter RESET_ADDRESS=32'h0100000, ADDRESS_WIDTH=24,
|
LGICACHE=6;
|
LGICACHE=8;
|
`ifdef OPT_MULTIPLY
|
`ifdef OPT_MULTIPLY
|
parameter IMPLEMENT_MPY = `OPT_MULTIPLY;
|
parameter IMPLEMENT_MPY = `OPT_MULTIPLY;
|
`else
|
`else
|
parameter IMPLEMENT_MPY = 0;
|
parameter IMPLEMENT_MPY = 0;
|
`endif
|
`endif
|
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 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 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); // &&(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 1327... |
Line 1393... |
assign wr_write_cc = (wr_reg_id[3:0] == `CPU_CC_REG);
|
assign wr_write_cc = (wr_reg_id[3:0] == `CPU_CC_REG);
|
assign wr_write_scc = (wr_reg_id[4:0] == {1'b0, `CPU_CC_REG});
|
assign wr_write_scc = (wr_reg_id[4:0] == {1'b0, `CPU_CC_REG});
|
assign wr_write_ucc = (wr_reg_id[4:0] == {1'b1, `CPU_CC_REG});
|
assign wr_write_ucc = (wr_reg_id[4:0] == {1'b1, `CPU_CC_REG});
|
// Are we writing to the PC?
|
// Are we writing to the PC?
|
assign wr_write_pc = (wr_reg_id[3:0] == `CPU_PC_REG);
|
assign wr_write_pc = (wr_reg_id[3:0] == `CPU_PC_REG);
|
|
|
// What value to write?
|
// What value to write?
|
assign wr_gpreg_vl = ((mem_valid) ? mem_result
|
assign wr_gpreg_vl = ((mem_valid) ? mem_result
|
:((div_valid|fpu_valid))
|
:((div_valid|fpu_valid))
|
? ((div_valid) ? div_result:fpu_result)
|
? ((div_valid) ? div_result:fpu_result)
|
:((dbgv) ? dbg_val : alu_result));
|
:((dbgv) ? dbg_val : alu_result));
|
Line 1392... |
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 1734... |
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 1747... |
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
|