URL
https://opencores.org/ocsvn/zipcpu/zipcpu/trunk
Subversion Repositories zipcpu
Compare Revisions
- This comparison shows the changes necessary to convert path
/zipcpu/trunk
- from Rev 144 to Rev 145
- ↔ Reverse comparison
Rev 144 → Rev 145
/rtl/core/zipcpu.v
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; |
375,11 → 376,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 |
428,7 → 426,7
assign op_ce = ((dcdvalid)||(dcd_illegal))&&(~op_stall)&&(~clear_pipeline); |
`else |
assign op_stall = (opvalid)&&(~master_ce); |
assign op_ce = ((dcdvalid)||(dcd_illegal)); |
assign op_ce = ((dcdvalid)||(dcd_illegal))&&(~clear_pipeline); |
`endif |
|
// |
458,7 → 456,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 → 471,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 → 514,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 → 524,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 → 569,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 → 627,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; |
995,31 → 1001,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. |
1160,13 → 1162,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 (alu_ce) // Includes && (~alu_clear_pipeline) |
r_alu_pc_valid <= 1'b1; |
else if ((~alu_busy)||(clear_pipeline)) |
r_alu_pc_valid <= 1'b0; |
assign alu_pc_valid = (r_alu_pc_valid)&&(~alu_busy); |
always @(posedge i_clk) |
if (i_rst) |
mem_pc_valid <= 1'b0; |
1638,7 → 1643,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 |
|