Line 137... |
Line 137... |
o_op_stall, o_pf_stall, o_i_count
|
o_op_stall, o_pf_stall, o_i_count
|
`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=32,
|
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 160... |
Line 160... |
`ifdef OPT_EARLY_BRANCHING
|
`ifdef OPT_EARLY_BRANCHING
|
parameter EARLY_BRANCHING = 1;
|
parameter EARLY_BRANCHING = 1;
|
`else
|
`else
|
parameter EARLY_BRANCHING = 0;
|
parameter EARLY_BRANCHING = 0;
|
`endif
|
`endif
|
parameter AW=ADDRESS_WIDTH;
|
localparam AW=ADDRESS_WIDTH;
|
input i_clk, i_rst, i_interrupt;
|
input i_clk, i_rst, i_interrupt;
|
// Debug interface -- inputs
|
// Debug interface -- inputs
|
input i_halt, i_clear_pf_cache;
|
input i_halt, i_clear_pf_cache;
|
input [4:0] i_dbg_reg;
|
input [4:0] i_dbg_reg;
|
input i_dbg_we;
|
input i_dbg_we;
|
Line 323... |
Line 323... |
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;
|
reg alu_wr, alF_wr;
|
wire alu_gie, alu_illegal_op, alu_illegal;
|
wire alu_gie, alu_illegal;
|
|
|
|
|
|
|
wire mem_ce, mem_stalled;
|
wire mem_ce, mem_stalled;
|
`ifdef OPT_PIPELINED_BUS_ACCESS
|
`ifdef OPT_PIPELINED_BUS_ACCESS
|
Line 481... |
Line 481... |
||(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
|
assign alu_stall = (opvalid_alu)&&((~master_ce)||(op_break));
|
assign alu_stall = (opvalid_alu)&&((~master_ce)||(op_break));
|
assign alu_ce = (master_ce)&&((opvalid_alu)||(op_illegal))&&(~alu_stall)&&(~clear_pipeline);
|
assign alu_ce = (master_ce)&&(opvalid_alu)&&(~alu_stall)&&(~clear_pipeline);
|
`endif
|
`endif
|
//
|
//
|
|
|
//
|
//
|
// Note: if you change the conditions for mem_ce, you must also change
|
// Note: if you change the conditions for mem_ce, you must also change
|
Line 1130... |
Line 1130... |
//
|
//
|
//
|
//
|
// PIPELINE STAGE #4 :: Apply Instruction
|
// PIPELINE STAGE #4 :: Apply Instruction
|
//
|
//
|
//
|
//
|
`ifdef OPT_NEW_INSTRUCTION_SET
|
cpuops #(IMPLEMENT_MPY) doalu(i_clk, (i_rst)||(clear_pipeline),
|
cpuops #(IMPLEMENT_MPY) doalu(i_clk, i_rst, alu_ce,
|
alu_ce, opn, opA, opB,
|
(opvalid_alu), opn, opA, opB,
|
alu_result, alu_flags, alu_valid, alu_busy);
|
alu_result, alu_flags, alu_valid, alu_illegal_op,
|
|
alu_busy);
|
|
`else
|
|
cpuops_deprecated #(IMPLEMENT_MPY) doalu(i_clk, i_rst, alu_ce,
|
|
(opvalid_alu), opn, opA, opB,
|
|
alu_result, alu_flags, alu_valid, alu_illegal_op);
|
|
assign alu_busy = 1'b0;
|
|
`endif
|
|
|
|
generate
|
generate
|
if (IMPLEMENT_DIVIDE != 0)
|
if (IMPLEMENT_DIVIDE != 0)
|
begin
|
begin
|
div thedivide(i_clk, (i_rst)||(clear_pipeline), div_ce, opn[0],
|
div thedivide(i_clk, (i_rst)||(clear_pipeline), div_ce, opn[0],
|
Line 1265... |
Line 1257... |
r_alu_illegal <= 1'b0;
|
r_alu_illegal <= 1'b0;
|
else if (alu_ce)
|
else if (alu_ce)
|
r_alu_illegal <= op_illegal;
|
r_alu_illegal <= op_illegal;
|
else
|
else
|
r_alu_illegal <= 1'b0;
|
r_alu_illegal <= 1'b0;
|
assign alu_illegal = (alu_illegal_op)||(r_alu_illegal);
|
assign alu_illegal = (r_alu_illegal);
|
`else
|
`else
|
assign alu_illegal = 1'b0;
|
assign alu_illegal = 1'b0;
|
`endif
|
`endif
|
|
|
initial r_alu_pc_valid = 1'b0;
|
initial r_alu_pc_valid = 1'b0;
|
Line 1467... |
Line 1459... |
initial r_break_pending = 1'b0;
|
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))
|
r_break_pending <= 1'b0;
|
r_break_pending <= 1'b0;
|
else if (op_break)
|
else if (op_break)
|
r_break_pending <= (~alu_busy)&&(~div_busy)&&(~fpu_busy)&&(~mem_busy);
|
r_break_pending <= (~alu_busy)&&(~div_busy)&&(~fpu_busy)&&(~mem_busy)&&(!wr_reg_ce);
|
else
|
else
|
r_break_pending <= 1'b0;
|
r_break_pending <= 1'b0;
|
assign break_pending = r_break_pending;
|
assign break_pending = r_break_pending;
|
`else
|
`else
|
assign break_pending = op_break;
|
assign break_pending = op_break;
|
Line 1481... |
Line 1473... |
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))
|
||((~alu_gie)&&(div_error))
|
||((~alu_gie)&&(div_error))
|
||((~alu_gie)&&(fpu_error))
|
||((~alu_gie)&&(fpu_error))
|
||((~alu_gie)&&(alu_illegal));
|
||((~alu_gie)&&(alu_illegal)&&(!clear_pipeline));
|
|
|
// The sleep register. Setting the sleep register causes the CPU to
|
// The sleep register. Setting the sleep register causes the CPU to
|
// sleep until the next interrupt. Setting the sleep register within
|
// sleep until the next interrupt. Setting the sleep register within
|
// interrupt mode causes the processor to halt until a reset. This is
|
// interrupt mode causes the processor to halt until a reset. This is
|
// a panic/fault halt. The trick is that you cannot be allowed to
|
// a panic/fault halt. The trick is that you cannot be allowed to
|
Line 1511... |
Line 1503... |
// to sleep mode *and* supervisor mode at the same
|
// to sleep mode *and* supervisor mode at the same
|
// time, lest you halt the CPU.
|
// time, lest you halt the CPU.
|
sleep <= wr_spreg_vl[`CPU_SLEEP_BIT];
|
sleep <= wr_spreg_vl[`CPU_SLEEP_BIT];
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((i_rst)||(w_switch_to_interrupt))
|
if (i_rst)
|
step <= 1'b0;
|
step <= 1'b0;
|
else if ((wr_reg_ce)&&(~alu_gie)&&(wr_write_ucc))
|
else if ((wr_reg_ce)&&(~alu_gie)&&(wr_write_ucc))
|
step <= wr_spreg_vl[`CPU_STEP_BIT];
|
step <= wr_spreg_vl[`CPU_STEP_BIT];
|
else if (((alu_pc_valid)||(mem_pc_valid))&&(step)&&(gie))
|
|
step <= 1'b0;
|
|
|
|
// The GIE register. Only interrupts can disable the interrupt register
|
// The GIE register. Only interrupts can disable the interrupt register
|
assign w_switch_to_interrupt = (gie)&&(
|
assign w_switch_to_interrupt = (gie)&&(
|
// On interrupt (obviously)
|
// On interrupt (obviously)
|
((i_interrupt)&&(~alu_phase)&&(~bus_lock))
|
((i_interrupt)&&(~alu_phase)&&(~bus_lock))
|
Line 1529... |
Line 1519... |
// If we encounter a break instruction, if the break
|
// If we encounter a break instruction, if the break
|
// enable isn't set.
|
// enable isn't set.
|
||((master_ce)&&(break_pending)&&(~break_en))
|
||((master_ce)&&(break_pending)&&(~break_en))
|
`ifdef OPT_ILLEGAL_INSTRUCTION
|
`ifdef OPT_ILLEGAL_INSTRUCTION
|
// On an illegal instruction
|
// On an illegal instruction
|
||(alu_illegal)
|
||((alu_illegal)&&(!clear_pipeline))
|
`endif
|
`endif
|
// On division by zero. If the divide isn't
|
// On division by zero. If the divide isn't
|
// implemented, div_valid and div_error will be short
|
// implemented, div_valid and div_error will be short
|
// circuited and that logic will be bypassed
|
// circuited and that logic will be bypassed
|
||(div_error)
|
||(div_error)
|
Line 1586... |
Line 1576... |
if (i_rst)
|
if (i_rst)
|
ill_err_i <= 1'b0;
|
ill_err_i <= 1'b0;
|
// Only the debug interface can clear this bit
|
// Only the debug interface can clear this bit
|
else if ((dbgv)&&(wr_write_scc))
|
else if ((dbgv)&&(wr_write_scc))
|
ill_err_i <= (ill_err_i)&&(wr_spreg_vl[`CPU_ILL_BIT]);
|
ill_err_i <= (ill_err_i)&&(wr_spreg_vl[`CPU_ILL_BIT]);
|
else if ((alu_illegal)&&(~alu_gie))
|
else if ((alu_illegal)&&(~alu_gie)&&(!clear_pipeline))
|
ill_err_i <= 1'b1;
|
ill_err_i <= 1'b1;
|
initial ill_err_u = 1'b0;
|
initial ill_err_u = 1'b0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
// The bit is automatically cleared on release from interrupt
|
// The bit is automatically cleared on release from interrupt
|
// or reset
|
// or reset
|
Line 1598... |
Line 1588... |
ill_err_u <= 1'b0;
|
ill_err_u <= 1'b0;
|
// If the supervisor (or debugger) writes to this register,
|
// If the supervisor (or debugger) writes to this register,
|
// clearing the bit, then clear it
|
// clearing the bit, then clear it
|
else if (((~alu_gie)||(dbgv))&&(wr_reg_ce)&&(wr_write_ucc))
|
else if (((~alu_gie)||(dbgv))&&(wr_reg_ce)&&(wr_write_ucc))
|
ill_err_u <=((ill_err_u)&&(wr_spreg_vl[`CPU_ILL_BIT]));
|
ill_err_u <=((ill_err_u)&&(wr_spreg_vl[`CPU_ILL_BIT]));
|
else if ((alu_illegal)&&(alu_gie))
|
else if ((alu_illegal)&&(alu_gie)&&(!clear_pipeline))
|
ill_err_u <= 1'b1;
|
ill_err_u <= 1'b1;
|
`else
|
`else
|
assign ill_err_u = 1'b0;
|
assign ill_err_u = 1'b0;
|
assign ill_err_i = 1'b0;
|
assign ill_err_i = 1'b0;
|
`endif
|
`endif
|
Line 1732... |
Line 1722... |
// a non-gie instruction?
|
// a non-gie instruction?
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((wr_reg_ce)&&(wr_reg_id[4])&&(wr_write_pc))
|
if ((wr_reg_ce)&&(wr_reg_id[4])&&(wr_write_pc))
|
upc <= wr_spreg_vl[(AW-1):0];
|
upc <= wr_spreg_vl[(AW-1):0];
|
else if ((alu_gie)&&
|
else if ((alu_gie)&&
|
(((alu_pc_valid)&&(~clear_pipeline))
|
(((alu_pc_valid)&&(~clear_pipeline)&&(!alu_illegal))
|
||(mem_pc_valid)))
|
||(mem_pc_valid)))
|
upc <= alu_pc;
|
upc <= alu_pc;
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (i_rst)
|
if (i_rst)
|