URL
https://opencores.org/ocsvn/xulalx25soc/xulalx25soc/trunk
Subversion Repositories xulalx25soc
Compare Revisions
- This comparison shows the changes necessary to convert path
/xulalx25soc/trunk/rtl/cpu
- from Rev 72 to Rev 73
- ↔ Reverse comparison
Rev 72 → Rev 73
/zipcpu.v
165,7 → 165,7
input i_dbg_we; |
input [31:0] i_dbg_data; |
// Debug interface -- outputs |
output reg o_dbg_stall; |
output wire o_dbg_stall; |
output reg [31:0] o_dbg_reg; |
output reg [3:0] o_dbg_cc; |
output wire o_break; |
204,7 → 204,7
// (BUS, TRAP,ILL,BREAKEN,STEP,GIE,SLEEP ), V, N, C, Z |
reg [3:0] flags, iflags; |
wire [13:0] w_uflags, w_iflags; |
reg trap, break_en, step, gie, sleep; |
reg trap, break_en, step, gie, sleep, r_halted; |
`ifdef OPT_ILLEGAL_INSTRUCTION |
reg ill_err_u, ill_err_i; |
`else |
284,7 → 284,7
wire [13:0] opFl; |
reg [5:0] r_opF; |
wire [7:0] opF; |
wire op_ce, op_phase, op_pipe; |
wire op_ce, op_phase, op_pipe, op_change_data_ce; |
// Some pipeline control wires |
`ifdef OPT_PIPELINED |
reg opA_alu, opA_mem; |
304,7 → 304,8
// |
// |
reg [(AW-1):0] alu_pc; |
reg alu_pc_valid, mem_pc_valid; |
reg r_alu_pc_valid, mem_pc_valid; |
wire alu_pc_valid; |
wire alu_phase; |
wire alu_ce, alu_stall; |
wire [31:0] alu_result; |
345,7 → 346,11
&&(~mem_rdbusy)&&(~div_busy)&&(~fpu_busy) |
&&(set_cond); |
|
|
// ALU, DIV, or FPU CE ... equivalent to the OR of all three of these |
wire adf_ce; |
assign adf_ce = (master_ce)&&(~clear_pipeline)&&(opvalid) |
&&(~opvalid_mem)&&(~mem_rdbusy)&&(~div_busy) |
&&(~fpu_busy)&&(set_cond); |
// |
// |
// PIPELINE STAGE #5 :: Write-back |
353,7 → 358,7
// |
wire wr_reg_ce, wr_flags_ce, wr_write_pc, wr_write_cc; |
wire [4:0] wr_reg_id; |
wire [31:0] wr_reg_vl; |
wire [31:0] wr_gpreg_vl, wr_spreg_vl; |
wire w_switch_to_interrupt, w_release_from_interrupt; |
reg [(AW-1):0] upc, ipc; |
|
375,11 → 380,8
// |
// PIPELINE STAGE #2 :: Instruction Decode |
// Calculate stall conditions |
`ifdef OPT_PIPELINED |
assign dcd_ce = ((~dcdvalid)||(~dcd_stalled))&&(~clear_pipeline); |
`else |
assign dcd_ce = 1'b1; |
`endif |
|
`ifdef OPT_PIPELINED |
assign dcd_stalled = (dcdvalid)&&(op_stall); |
`else |
426,9 → 428,16
||(dcdF_stall) |
); |
assign op_ce = ((dcdvalid)||(dcd_illegal))&&(~op_stall)&&(~clear_pipeline); |
// BUT ... op_ce is too complex for many of the data operations. So |
// let's make their circuit enable code simpler. In particular, if |
// op_ doesn't need to be preserved, we can change it all we want |
// ... right? The clear_pipeline code, for example, really only needs |
// to determine whether opvalid is true. |
assign op_change_data_ce = (~op_stall); |
`else |
assign op_stall = (opvalid)&&(~master_ce); |
assign op_ce = ((dcdvalid)||(dcd_illegal)); |
assign op_ce = ((dcdvalid)||(dcd_illegal))&&(~clear_pipeline); |
assign op_change_data_ce = 1'b1; |
`endif |
|
// |
458,7 → 467,7
`else |
assign alu_stall = ((~master_ce)&&(opvalid_alu)) |
||((opvalid_alu)&&(op_break)); |
assign alu_ce = (master_ce)&&((opvalid_alu)||(op_illegal))&&(~alu_stall); |
assign alu_ce = (master_ce)&&((opvalid_alu)||(op_illegal))&&(~alu_stall)&&(~clear_pipeline); |
`endif |
// |
|
473,7 → 482,13
// If we aren't pipelined, then no one will be changing what's in the |
// pipeline (i.e. clear_pipeline), while our only instruction goes |
// through the ... pipeline. |
assign mem_ce = (master_ce)&&(opvalid_mem)&&(~mem_stalled); |
// |
// However, in hind sight this logic didn't work. What happens when |
// something gets in the pipeline and then (due to interrupt or some |
// such) needs to be voided? Thus we avoid simplification and keep |
// what worked here. |
assign mem_ce = (master_ce)&&(opvalid_mem)&&(~mem_stalled) |
&&(~clear_pipeline); |
`endif |
`ifdef OPT_PIPELINED_BUS_ACCESS |
assign mem_stalled = (~master_ce)||(alu_busy)||((opvalid_mem)&&( |
510,9 → 525,9
`ifdef OPT_SINGLE_FETCH |
wire pf_ce; |
|
assign pf_ce = (~pf_valid)&&(~dcdvalid)&&(~opvalid)&&(~alu_valid); |
assign pf_ce = (~pf_valid)&&(~dcdvalid)&&(~opvalid)&&(~alu_busy)&&(~mem_busy)&&(~alu_pc_valid)&&(~mem_pc_valid); |
prefetch #(ADDRESS_WIDTH) |
pf(i_clk, i_rst, (pf_ce), (~dcd_stalled), pf_pc, gie, |
pf(i_clk, (i_rst), (pf_ce), (~dcd_stalled), pf_pc, gie, |
instruction, instruction_pc, instruction_gie, |
pf_valid, pf_illegal, |
pf_cyc, pf_stb, pf_we, pf_addr, pf_data, |
520,7 → 535,7
|
initial r_dcdvalid = 1'b0; |
always @(posedge i_clk) |
if (i_rst) |
if ((i_rst)||(clear_pipeline)) |
r_dcdvalid <= 1'b0; |
else if (dcd_ce) |
r_dcdvalid <= (pf_valid); |
565,7 → 580,7
if ((i_rst)||(clear_pipeline)) |
r_dcdvalid <= 1'b0; |
else if (dcd_ce) |
r_dcdvalid <= (pf_valid)&&(~clear_pipeline)&&(~dcd_ljmp)&&((~r_dcdvalid)||(~dcd_early_branch)); |
r_dcdvalid <= (pf_valid)&&(~dcd_ljmp)&&((~r_dcdvalid)||(~dcd_early_branch)); |
else if (op_ce) |
r_dcdvalid <= 1'b0; |
assign dcdvalid = r_dcdvalid; |
623,6 → 638,8
always @(posedge i_clk) |
if (op_ce) |
r_op_pipe <= dcd_pipe; |
else if (mem_ce) // Clear us any time an op_ is clocked in |
r_op_pipe <= 1'b0; |
assign op_pipe = r_op_pipe; |
`else |
assign op_pipe = 1'b0; |
707,10 → 724,10
`endif |
|
always @(posedge i_clk) |
if (op_ce) // &&(dcdvalid)) |
if (op_change_data_ce) |
begin |
if ((wr_reg_ce)&&(wr_reg_id == dcdA)) |
r_opA <= wr_reg_vl; |
r_opA <= wr_gpreg_vl; |
else if (dcdA_pc) |
r_opA <= w_pcA_v; |
else if (dcdA_cc) |
723,9 → 740,9
// but for some reason we're stuck here as they became |
// valid. Pick them up now anyway |
// if (((opA_alu)&&(alu_wr))||((opA_mem)&&(mem_valid))) |
// r_opA <= wr_reg_vl; |
// r_opA <= wr_gpreg_vl; |
if ((wr_reg_ce)&&(wr_reg_id == opA_id)&&(opA_rd)) |
r_opA <= wr_reg_vl; |
r_opA <= wr_gpreg_vl; |
`endif |
end |
|
738,7 → 755,7
endgenerate |
|
assign w_opBnI = (~dcdB_rd) ? 32'h00 |
: (((wr_reg_ce)&&(wr_reg_id == dcdB)) ? wr_reg_vl |
: (((wr_reg_ce)&&(wr_reg_id == dcdB)) ? wr_gpreg_vl |
: ((dcdB_pc) ? w_pcB_v |
: ((dcdB_cc) ? { w_cpu_info, w_opB[22:14], // w_opB[31:14], |
(dcdB[4])?w_uflags:w_iflags} |
745,11 → 762,11
: w_opB))); |
|
always @(posedge i_clk) |
if (op_ce) // &&(dcdvalid)) |
if (op_change_data_ce) |
r_opB <= w_opBnI + dcdI; |
`ifdef OPT_PIPELINED |
else if ((wr_reg_ce)&&(opB_id == wr_reg_id)&&(opB_rd)) |
r_opB <= wr_reg_vl; |
r_opB <= wr_gpreg_vl; |
`endif |
|
// The logic here has become more complex than it should be, no thanks |
762,7 → 779,9
// below, arriving at what we finally want in the (now wire net) |
// opF. |
always @(posedge i_clk) |
if (op_ce) |
if (op_ce) // Cannot do op_change_data_ce here since opF depends |
// upon being either correct for a valid op, or correct |
// for the last valid op |
begin // Set the flag condition codes, bit order is [3:0]=VNCZ |
case(dcdF[2:0]) |
3'h0: r_opF <= 6'h00; // Always |
824,7 → 843,7
opvalid_div <= (dcdDV)&&(w_opvalid); |
opvalid_fpu <= (dcdFP)&&(w_opvalid); |
`endif |
end else if ((clear_pipeline)||(alu_ce)||(mem_ce)||(div_ce)||(fpu_ce)) |
end else if ((clear_pipeline)||(adf_ce)||(mem_ce)) |
begin |
opvalid <= 1'b0; |
opvalid_alu <= 1'b0; |
867,7 → 886,7
|
initial r_op_lock = 1'b0; |
always @(posedge i_clk) |
if (i_rst) |
if ((i_rst)||(clear_pipeline)) |
r_op_lock <= 1'b0; |
else if (op_ce) |
r_op_lock <= (dcd_lock)&&(~clear_pipeline); |
908,7 → 927,7
end |
|
always @(posedge i_clk) |
if (op_ce) |
if (op_change_data_ce) |
begin |
opn <= dcdOp; // Which ALU operation? |
// opM <= dcdM; // Is this a memory operation? |
930,7 → 949,7
always @(posedge i_clk) |
if ((i_rst)||(clear_pipeline)) |
r_op_phase <= 1'b0; |
else if (op_ce) |
else if (op_change_data_ce) |
r_op_phase <= dcd_phase; |
assign op_phase = r_op_phase; |
`else |
951,7 → 970,7
// the stalls will already be in place. |
`ifdef OPT_PIPELINED |
assign opA = ((wr_reg_ce)&&(wr_reg_id == opA_id)) // &&(opA_rd)) |
? wr_reg_vl : r_opA; |
? wr_gpreg_vl : r_opA; |
`else |
assign opA = r_opA; |
`endif |
974,7 → 993,7
|
`ifdef OPT_PIPELINED |
assign opB = ((wr_reg_ce)&&(wr_reg_id == opB_id)&&(opB_rd)) |
? wr_reg_vl: r_opB; |
? wr_gpreg_vl: r_opB; |
`else |
assign opB = r_opB; |
`endif |
995,31 → 1014,27
&&((opvalid)||(mem_rdbusy) |
||(div_busy)||(fpu_busy)||(alu_busy)) |
&&( |
// Stall on memory ops writing to my register |
// (i.e. loads), or on any write to my |
// register if I have an immediate offset |
// Actually, this is worse. I can't tell |
// whether or not my register is going to |
// be written to, so |
// Note the exception for writing to the PC: |
// if I write to the PC, the whole next |
// instruction is invalid, not just the |
// operand. That'll get wiped in the |
// next operation anyway, so don't stall |
// here. This keeps a BC X, BNZ Y from |
// stalling between the two branches. |
// BC X, BRA Y is still clear, since BRA Y |
// is an early branch instruction. |
// (This exception is commented out in |
// order to help keep our logic simple, and |
// because multiple conditional branches |
// following each other constitutes a |
// fairly unusualy code structure.) |
// |
// Okay, what happens if the result register |
// from instruction 1 becomes the input for |
// instruction two, *and* there's an immediate |
// offset in instruction two? In that case, we |
// need an extra clock between the two |
// instructions to calculate the base plus |
// offset. |
// |
// What if instruction 1 (or before) is in a |
// memory pipeline? We may no longer know what |
// the register was! We will then need to |
// blindly wait. We'll temper this only waiting |
// if we're not piping this new instruction. |
// If we were piping, the pipe logic in the |
// decode circuit has told us that the hazard |
// is clear, so we're okay then. |
// |
((~dcd_zI)&&( |
((opR == dcdB)&&(opR_wr)) |
||(((opvalid_mem)||(mem_rdbusy)) |
&&(op_pipe)))) |
||((mem_rdbusy)&&(~dcd_pipe)) |
)) |
// Stall following any instruction that will |
// set the flags, if we're going to need the |
// flags (CC) register for opB. |
1118,7 → 1133,7
always @(posedge i_clk) |
if (i_rst) |
r_alu_phase <= 1'b0; |
else if ((alu_ce)||(mem_ce)||(div_ce)||(fpu_ce)) |
else if ((adf_ce)||(mem_ce)) |
r_alu_phase <= op_phase; |
assign alu_phase = r_alu_phase; |
`else |
1126,7 → 1141,7
`endif |
|
always @(posedge i_clk) |
if ((alu_ce)||(div_ce)||(fpu_ce)) |
if (adf_ce) |
alu_reg <= opR; |
else if ((i_halt)&&(i_dbg_we)) |
alu_reg <= i_dbg_reg; |
1137,15 → 1152,16
reg dbgv; |
initial dbgv = 1'b0; |
always @(posedge i_clk) |
dbgv <= (~i_rst)&&(~alu_ce)&&((i_halt)&&(i_dbg_we)); |
dbgv <= (~i_rst)&&(i_halt)&&(i_dbg_we)&&(r_halted); |
reg [31:0] dbg_val; |
always @(posedge i_clk) |
dbg_val <= i_dbg_data; |
always @(posedge i_clk) |
if ((alu_ce)||(mem_ce)) |
if ((adf_ce)||(mem_ce)) |
alu_gie <= op_gie; |
always @(posedge i_clk) |
if ((alu_ce)||((master_ce)&&(opvalid_mem)&&(~clear_pipeline) |
if ((adf_ce) |
||((master_ce)&&(opvalid_mem)&&(~clear_pipeline) |
&&(~mem_stalled))) |
alu_pc <= op_pc; |
|
1160,13 → 1176,16
assign alu_illegal = (alu_illegal_op)||(r_alu_illegal); |
`endif |
|
initial alu_pc_valid = 1'b0; |
initial r_alu_pc_valid = 1'b0; |
initial mem_pc_valid = 1'b0; |
always @(posedge i_clk) |
if (i_rst) |
alu_pc_valid <= 1'b0; |
else |
alu_pc_valid <= (alu_ce); |
r_alu_pc_valid <= 1'b0; |
else if (adf_ce) // Includes && (~alu_clear_pipeline) |
r_alu_pc_valid <= 1'b1; |
else if (((~alu_busy)&&(~div_busy)&&(~fpu_busy))||(clear_pipeline)) |
r_alu_pc_valid <= 1'b0; |
assign alu_pc_valid = (r_alu_pc_valid)&&((~alu_busy)&&(~div_busy)&&(~fpu_busy)); |
always @(posedge i_clk) |
if (i_rst) |
mem_pc_valid <= 1'b0; |
1258,12 → 1277,15
// Further, alu_wr includes (set_cond), so we don't need to |
// check for that here either. |
`ifdef OPT_ILLEGAL_INSTRUCTION |
assign wr_reg_ce = (dbgv)||(~alu_illegal)&& |
(((alu_wr)&&(~clear_pipeline) |
&&((alu_valid)||(div_valid)||(fpu_valid))) |
||(mem_valid)); |
assign wr_reg_ce = (dbgv)||(mem_valid) |
||((~clear_pipeline)&&(~alu_illegal) |
&&(((alu_wr)&&(alu_valid)) |
||(div_valid)||(fpu_valid))); |
`else |
assign wr_reg_ce = (dbgv)||((alu_wr)&&(~clear_pipeline))||(mem_valid)||(div_valid)||(fpu_valid); |
assign wr_reg_ce = (dbgv)||(mem_valid) |
||((~clear_pipeline) |
&&(((alu_wr)&&(alu_valid)) |
||(div_valid)||(fpu_valid))); |
`endif |
// Which register shall be written? |
// COULD SIMPLIFY THIS: by adding three bits to these registers, |
1270,19 → 1292,21
// One or PC, one for CC, and one for GIE match |
// Note that the alu_reg is the register to write on a divide or |
// FPU operation. |
assign wr_reg_id = (alu_wr)?alu_reg:mem_wreg; |
assign wr_reg_id = (alu_wr|div_valid|fpu_valid)?alu_reg:mem_wreg; |
// Are we writing to the CC register? |
assign wr_write_cc = (wr_reg_id[3:0] == `CPU_CC_REG); |
// Are we writing to the PC? |
assign wr_write_pc = (wr_reg_id[3:0] == `CPU_PC_REG); |
// What value to write? |
assign wr_reg_vl = ((mem_valid) ? mem_result |
assign wr_gpreg_vl = ((mem_valid) ? mem_result |
:((div_valid|fpu_valid)) |
? ((div_valid) ? div_result:fpu_result) |
:((dbgv) ? dbg_val : alu_result)); |
assign wr_spreg_vl = ((mem_valid) ? mem_result |
:((dbgv) ? dbg_val : alu_result)); |
always @(posedge i_clk) |
if (wr_reg_ce) |
regset[wr_reg_id] <= wr_reg_vl; |
regset[wr_reg_id] <= wr_gpreg_vl; |
|
// |
// Write back to the condition codes/flags register ... |
1303,7 → 1327,7
always @(posedge i_clk) |
// If explicitly writing the register itself |
if ((wr_reg_ce)&&(wr_reg_id[4])&&(wr_write_cc)) |
flags <= wr_reg_vl[3:0]; |
flags <= wr_gpreg_vl[3:0]; |
// Otherwise if we're setting the flags from an ALU operation |
else if ((wr_flags_ce)&&(alu_gie)) |
flags <= (div_valid)?div_flags:((fpu_valid)?fpu_flags |
1311,7 → 1335,7
|
always @(posedge i_clk) |
if ((wr_reg_ce)&&(~wr_reg_id[4])&&(wr_write_cc)) |
iflags <= wr_reg_vl[3:0]; |
iflags <= wr_gpreg_vl[3:0]; |
else if ((wr_flags_ce)&&(~alu_gie)) |
iflags <= (div_valid)?div_flags:((fpu_valid)?fpu_flags |
: alu_flags); |
1336,10 → 1360,11
if ((i_rst)||(i_halt)) |
break_en <= 1'b0; |
else if ((wr_reg_ce)&&(~wr_reg_id[4])&&(wr_write_cc)) |
break_en <= wr_reg_vl[`CPU_BREAK_BIT]; |
break_en <= wr_spreg_vl[`CPU_BREAK_BIT]; |
`ifdef OPT_ILLEGAL_INSTRUCTION |
assign o_break = ((break_en)||(~op_gie))&&(op_break) |
&&(~alu_valid)&&(~mem_valid)&&(~mem_busy) |
&&(~alu_busy) |
&&(~div_busy)&&(~fpu_busy) |
&&(~clear_pipeline) |
||((~alu_gie)&&(bus_err)) |
1349,6 → 1374,7
`else |
assign o_break = (((break_en)||(~op_gie))&&(op_break) |
&&(~alu_valid)&&(~mem_valid)&&(~mem_busy) |
&&(~alu_busy)&&(~div_busy)&&(~fpu_busy) |
&&(~clear_pipeline)) |
||((~alu_gie)&&(bus_err)) |
||((~alu_gie)&&(div_valid)&&(div_error)) |
1371,23 → 1397,23
// Well ... not quite. Switching to user mode and |
// sleep mode shouold only be possible if the interrupt |
// flag isn't set. |
// Thus: if (i_interrupt)&&(wr_reg_vl[GIE]) |
// Thus: if (i_interrupt)&&(wr_spreg_vl[GIE]) |
// don't set the sleep bit |
// otherwise however it would o.w. be set |
sleep <= (wr_reg_vl[`CPU_SLEEP_BIT]) |
&&((~i_interrupt)||(~wr_reg_vl[`CPU_GIE_BIT])); |
else if ((wr_reg_ce)&&(wr_write_cc)&&(wr_reg_vl[`CPU_GIE_BIT])) |
sleep <= (wr_spreg_vl[`CPU_SLEEP_BIT]) |
&&((~i_interrupt)||(~wr_spreg_vl[`CPU_GIE_BIT])); |
else if ((wr_reg_ce)&&(wr_write_cc)&&(wr_spreg_vl[`CPU_GIE_BIT])) |
// In user mode, however, you can only set the sleep |
// mode while remaining in user mode. You can't switch |
// to sleep mode *and* supervisor mode at the same |
// time, lest you halt the CPU. |
sleep <= wr_reg_vl[`CPU_SLEEP_BIT]; |
sleep <= wr_spreg_vl[`CPU_SLEEP_BIT]; |
|
always @(posedge i_clk) |
if ((i_rst)||(w_switch_to_interrupt)) |
step <= 1'b0; |
else if ((wr_reg_ce)&&(~alu_gie)&&(wr_reg_id[4])&&(wr_write_cc)) |
step <= wr_reg_vl[`CPU_STEP_BIT]; |
step <= wr_spreg_vl[`CPU_STEP_BIT]; |
else if (((alu_pc_valid)||(mem_pc_valid))&&(step)&&(gie)) |
step <= 1'b0; |
|
1414,12 → 1440,12
// |
||(bus_err) |
// If we write to the CC register |
||((wr_reg_ce)&&(~wr_reg_vl[`CPU_GIE_BIT]) |
||((wr_reg_ce)&&(~wr_spreg_vl[`CPU_GIE_BIT]) |
&&(wr_reg_id[4])&&(wr_write_cc)) |
); |
assign w_release_from_interrupt = (~gie)&&(~i_interrupt) |
// Then if we write the CC register |
&&(((wr_reg_ce)&&(wr_reg_vl[`CPU_GIE_BIT]) |
&&(((wr_reg_ce)&&(wr_spreg_vl[`CPU_GIE_BIT]) |
&&(~wr_reg_id[4])&&(wr_write_cc)) |
); |
always @(posedge i_clk) |
1436,11 → 1462,11
trap <= 1'b0; |
else if (w_release_from_interrupt) |
trap <= 1'b0; |
else if ((alu_gie)&&(wr_reg_ce)&&(~wr_reg_vl[`CPU_GIE_BIT]) |
else if ((alu_gie)&&(wr_reg_ce)&&(~wr_spreg_vl[`CPU_GIE_BIT]) |
&&(wr_write_cc)) // &&(wr_reg_id[4]) implied |
trap <= 1'b1; |
else if ((wr_reg_ce)&&(wr_write_cc)&&(wr_reg_id[4])) |
trap <= wr_reg_vl[`CPU_TRAP_BIT]; |
trap <= wr_spreg_vl[`CPU_TRAP_BIT]; |
|
`ifdef OPT_ILLEGAL_INSTRUCTION |
initial ill_err_i = 1'b0; |
1449,7 → 1475,7
ill_err_i <= 1'b0; |
// Only the debug interface can clear this bit |
else if ((dbgv)&&(wr_reg_id == {1'b0, `CPU_CC_REG}) |
&&(~wr_reg_vl[`CPU_ILL_BIT])) |
&&(~wr_spreg_vl[`CPU_ILL_BIT])) |
ill_err_i <= 1'b0; |
else if ((alu_pc_valid)&&(alu_illegal)&&(~alu_gie)) |
ill_err_i <= 1'b1; |
1463,7 → 1489,7
// If the supervisor writes to this register, clearing the |
// bit, then clear it |
else if (((~alu_gie)||(dbgv)) |
&&(wr_reg_ce)&&(~wr_reg_vl[`CPU_ILL_BIT]) |
&&(wr_reg_ce)&&(~wr_spreg_vl[`CPU_ILL_BIT]) |
&&(wr_reg_id[4])&&(wr_write_cc)) |
ill_err_u <= 1'b0; |
else if ((alu_pc_valid)&&(alu_illegal)&&(alu_gie)) |
1479,7 → 1505,7
if (i_rst) |
ibus_err_flag <= 1'b0; |
else if ((dbgv)&&(wr_reg_id == {1'b0, `CPU_CC_REG}) |
&&(~wr_reg_vl[`CPU_BUSERR_BIT])) |
&&(~wr_spreg_vl[`CPU_BUSERR_BIT])) |
ibus_err_flag <= 1'b0; |
else if ((bus_err)&&(~alu_gie)) |
ibus_err_flag <= 1'b1; |
1492,7 → 1518,7
else if (w_release_from_interrupt) |
ubus_err_flag <= 1'b0; |
else if (((~alu_gie)||(dbgv))&&(wr_reg_ce) |
&&(~wr_reg_vl[`CPU_BUSERR_BIT]) |
&&(~wr_spreg_vl[`CPU_BUSERR_BIT]) |
&&(wr_reg_id[4])&&(wr_write_cc)) |
ubus_err_flag <= 1'b0; |
else if ((bus_err)&&(alu_gie)) |
1511,7 → 1537,7
if (i_rst) |
r_idiv_err_flag <= 1'b0; |
else if ((dbgv)&&(wr_reg_id == {1'b0, `CPU_CC_REG}) |
&&(~wr_reg_vl[`CPU_DIVERR_BIT])) |
&&(~wr_spreg_vl[`CPU_DIVERR_BIT])) |
r_idiv_err_flag <= 1'b0; |
else if ((div_error)&&(div_valid)&&(~alu_gie)) |
r_idiv_err_flag <= 1'b1; |
1524,7 → 1550,7
else if (w_release_from_interrupt) |
r_udiv_err_flag <= 1'b0; |
else if (((~alu_gie)||(dbgv))&&(wr_reg_ce) |
&&(~wr_reg_vl[`CPU_DIVERR_BIT]) |
&&(~wr_spreg_vl[`CPU_DIVERR_BIT]) |
&&(wr_reg_id[4])&&(wr_write_cc)) |
r_udiv_err_flag <= 1'b0; |
else if ((div_error)&&(alu_gie)&&(div_valid)) |
1548,7 → 1574,7
if (i_rst) |
r_ifpu_err_flag <= 1'b0; |
else if ((dbgv)&&(wr_reg_id == {1'b0, `CPU_CC_REG}) |
&&(~wr_reg_vl[`CPU_FPUERR_BIT])) |
&&(~wr_spreg_vl[`CPU_FPUERR_BIT])) |
r_ifpu_err_flag <= 1'b0; |
else if ((fpu_error)&&(fpu_valid)&&(~alu_gie)) |
r_ifpu_err_flag <= 1'b1; |
1561,7 → 1587,7
else if (w_release_from_interrupt) |
r_ufpu_err_flag <= 1'b0; |
else if (((~alu_gie)||(dbgv))&&(wr_reg_ce) |
&&(~wr_reg_vl[`CPU_FPUERR_BIT]) |
&&(~wr_spreg_vl[`CPU_FPUERR_BIT]) |
&&(wr_reg_id[4])&&(wr_write_cc)) |
r_ufpu_err_flag <= 1'b0; |
else if ((fpu_error)&&(alu_gie)&&(fpu_valid)) |
1607,7 → 1633,7
// a non-gie instruction? |
always @(posedge i_clk) |
if ((wr_reg_ce)&&(wr_reg_id[4])&&(wr_write_pc)) |
upc <= wr_reg_vl[(AW-1):0]; |
upc <= wr_spreg_vl[(AW-1):0]; |
else if ((alu_gie)&& |
(((alu_pc_valid)&&(~clear_pipeline)) |
||(mem_pc_valid))) |
1617,7 → 1643,7
if (i_rst) |
ipc <= RESET_ADDRESS; |
else if ((wr_reg_ce)&&(~wr_reg_id[4])&&(wr_write_pc)) |
ipc <= wr_reg_vl[(AW-1):0]; |
ipc <= wr_spreg_vl[(AW-1):0]; |
else if ((~alu_gie)&& |
(((alu_pc_valid)&&(~clear_pipeline)) |
||(mem_pc_valid))) |
1631,7 → 1657,7
else if (w_release_from_interrupt) |
pf_pc <= upc; |
else if ((wr_reg_ce)&&(wr_reg_id[4] == gie)&&(wr_write_pc)) |
pf_pc <= wr_reg_vl[(AW-1):0]; |
pf_pc <= wr_spreg_vl[(AW-1):0]; |
`ifdef OPT_PIPELINED |
else if ((dcd_early_branch)&&(~clear_pipeline)) |
pf_pc <= dcd_branch_pc + 1; |
1638,7 → 1664,9
else if ((new_pc)||((~dcd_stalled)&&(pf_valid))) |
pf_pc <= pf_pc + {{(AW-1){1'b0}},1'b1}; |
`else |
else if ((alu_pc_valid)&&(~clear_pipeline)) |
else if ((alu_gie==gie)&&( |
((alu_pc_valid)&&(~clear_pipeline)) |
||(mem_pc_valid))) |
pf_pc <= alu_pc; |
`endif |
|
1689,10 → 1717,12
o_dbg_cc <= { o_break, bus_err, gie, sleep }; |
|
always @(posedge i_clk) |
o_dbg_stall <= (i_halt)&&( |
r_halted <= (i_halt)&&( |
(pf_cyc)||(mem_cyc_gbl)||(mem_cyc_lcl)||(mem_busy) |
||(alu_busy)||(div_busy)||(fpu_busy) |
||((~opvalid)&&(~i_rst)&&(~dcd_illegal)) |
||((~dcdvalid)&&(~i_rst)&&(~pf_illegal))); |
assign o_dbg_stall = r_halted; |
|
// |
// |
1707,20 → 1737,47
`ifdef DEBUG_SCOPE |
always @(posedge i_clk) |
o_debug <= { |
/* |
o_break, i_wb_err, pf_pc[1:0], |
// |
flags, |
pf_valid, dcdvalid, opvalid, alu_valid, mem_valid, |
// |
pf_valid, dcdvalid, opvalid, alu_valid, |
// |
mem_valid, |
op_ce, alu_ce, mem_ce, |
// |
master_ce, opvalid_alu, opvalid_mem, |
master_ce, |
opvalid_alu, opvalid_mem, alu_stall, |
// |
alu_stall, mem_busy, op_pipe, mem_pipe_stalled, |
mem_busy, op_pipe, |
`ifdef OPT_PIPELINED_BUS_ACCESS |
mem_pipe_stalled, |
`else |
1'b0, |
`endif |
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_reg_vl[4:0] |
*/ |
|
o_break, i_wb_err, o_wb_gbl_cyc, o_wb_gbl_stb, |
pf_valid, dcdvalid, opvalid, alu_valid, |
mem_valid, dcd_ce, op_ce, alu_ce, |
mem_ce, |
// |
(new_pc)||((dcd_early_branch)&&(~clear_pipeline)), |
gie, sleep, |
{ ((o_wb_gbl_cyc)&&(o_wb_gbl_stb)&&(o_wb_we)) |
? o_wb_data[15:0] |
: ((o_wb_gbl_cyc)&&(~o_wb_we)&&(i_wb_ack)) |
? i_wb_data[15:0] |
: o_wb_addr[15:0] |
} |
/* |
i_rst, master_ce, (new_pc), |
((dcd_early_branch)&&(dcdvalid)), |