URL
https://opencores.org/ocsvn/zipcpu/zipcpu/trunk
Subversion Repositories zipcpu
Compare Revisions
- This comparison shows the changes necessary to convert path
/zipcpu
- from Rev 131 to Rev 132
- ↔ Reverse comparison
Rev 131 → Rev 132
/trunk/rtl/core/zipcpu.v
137,7 → 137,7
parameter RESET_ADDRESS=32'h0100000, ADDRESS_WIDTH=24, |
LGICACHE=6; |
`ifdef OPT_MULTIPLY |
parameter IMPLEMENT_MPY = 1; |
parameter IMPLEMENT_MPY = `OPT_MULTIPLY; |
`else |
parameter IMPLEMENT_MPY = 0; |
`endif |
284,7 → 284,7
wire [13:0] opFl; |
reg [5:0] r_opF; |
wire [7:0] opF; |
wire op_ce, op_phase; |
wire op_ce, op_phase, op_pipe; |
// Some pipeline control wires |
`ifdef OPT_PIPELINED |
reg opA_alu, opA_mem; |
304,7 → 304,7
// |
// |
reg [(AW-1):0] alu_pc; |
reg alu_pc_valid; |
reg alu_pc_valid, mem_pc_valid; |
wire alu_phase; |
wire alu_ce, alu_stall; |
wire [31:0] alu_result; |
608,9 → 608,9
`endif |
|
`ifdef OPT_PIPELINED_BUS_ACCESS |
reg op_pipe; |
reg r_op_pipe; |
|
initial op_pipe = 1'b0; |
initial r_op_pipe = 1'b0; |
// To be a pipeable operation, there must be |
// two valid adjacent instructions |
// Both must be memory instructions |
622,7 → 622,10
// calculated in the instruction decoder. |
always @(posedge i_clk) |
if (op_ce) |
op_pipe <= dcd_pipe; |
r_op_pipe <= dcd_pipe; |
assign op_pipe = r_op_pipe; |
`else |
assign op_pipe = 1'b0; |
`endif |
|
// |
633,6 → 636,55
assign w_opA = regset[dcdA]; |
assign w_opB = regset[dcdB]; |
|
wire [8:0] w_cpu_info; |
assign w_cpu_info = { |
`ifdef OPT_ILLEGAL_INSTRUCTION |
1'b1, |
`else |
1'b0, |
`endif |
`ifdef OPT_MULTIPLY |
1'b1, |
`else |
1'b0, |
`endif |
`ifdef OPT_DIVIDE |
1'b1, |
`else |
1'b0, |
`endif |
`ifdef OPT_IMPLEMENT_FPU |
1'b1, |
`else |
1'b0, |
`endif |
`ifdef OPT_PIPELINED |
1'b1, |
`else |
1'b0, |
`endif |
`ifdef OPT_TRADITIONAL_CACHE |
1'b1, |
`else |
1'b0, |
`endif |
`ifdef OPT_EARLY_BRANCHING |
1'b1, |
`else |
1'b0, |
`endif |
`ifdef OPT_PIPELINED_BUS_ACCESS |
1'b1, |
`else |
1'b0, |
`endif |
`ifdef OPT_VLIW |
1'b1 |
`else |
1'b0 |
`endif |
}; |
|
wire [31:0] w_pcA_v; |
generate |
if (AW < 32) |
662,7 → 714,7
else if (dcdA_pc) |
r_opA <= w_pcA_v; |
else if (dcdA_cc) |
r_opA <= { w_opA[31:14], (dcdA[4])?w_uflags:w_iflags }; |
r_opA <= { w_cpu_info, w_opA[22:14], (dcdA[4])?w_uflags:w_iflags }; |
else |
r_opA <= w_opA; |
`ifdef OPT_PIPELINED |
688,7 → 740,8
assign w_opBnI = (~dcdB_rd) ? 32'h00 |
: (((wr_reg_ce)&&(wr_reg_id == dcdB)) ? wr_reg_vl |
: ((dcdB_pc) ? w_pcB_v |
: ((dcdB_cc) ? { w_opB[31:14], (dcdB[4])?w_uflags:w_iflags} |
: ((dcdB_cc) ? { w_cpu_info, w_opB[22:14], // w_opB[31:14], |
(dcdB[4])?w_uflags:w_iflags} |
: w_opB))); |
|
always @(posedge i_clk) |
816,10 → 869,8
always @(posedge i_clk) |
if (i_rst) |
r_op_lock <= 1'b0; |
else if ((op_ce)&&(dcd_lock)) |
r_op_lock <= 1'b1; |
else if ((op_ce)||(clear_pipeline)) |
r_op_lock <= 1'b0; |
else if (op_ce) |
r_op_lock <= (dcd_lock)&&(~clear_pipeline); |
assign op_lock = r_op_lock; |
|
end else begin |
942,11 → 993,14
// We'll use the last values from that stage |
// (opR_wr, opF_wr, opR) in our logic below. |
&&((opvalid)||(mem_rdbusy) |
||(div_busy)||(fpu_busy)) |
||(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 |
962,8 → 1016,10
// following each other constitutes a |
// fairly unusualy code structure.) |
// |
((~dcd_zI)&&(opR == dcdB)&&(opR_wr)) |
// &&(opR != { op_gie, `CPU_PC_REG } ) |
((~dcd_zI)&&( |
((opR == dcdB)&&(opR_wr)) |
||(((opvalid_mem)||(mem_rdbusy)) |
&&(op_pipe)))) |
// Stall following any instruction that will |
// set the flags, if we're going to need the |
// flags (CC) register for opB. |
1075,14 → 1131,17
else if ((i_halt)&&(i_dbg_we)) |
alu_reg <= i_dbg_reg; |
|
reg [31:0] dbg_val; |
// |
// DEBUG Register write access starts here |
// |
reg dbgv; |
always @(posedge i_clk) |
dbg_val <= i_dbg_data; |
initial dbgv = 1'b0; |
always @(posedge i_clk) |
dbgv <= (~i_rst)&&(~alu_ce)&&((i_halt)&&(i_dbg_we)); |
reg [31:0] dbg_val; |
always @(posedge i_clk) |
dbg_val <= i_dbg_data; |
always @(posedge i_clk) |
if ((alu_ce)||(mem_ce)) |
alu_gie <= op_gie; |
always @(posedge i_clk) |
1101,14 → 1160,18
assign alu_illegal = (alu_illegal_op)||(r_alu_illegal); |
`endif |
|
// This _almost_ is equal to (alu_ce)||(mem_ce). The only |
// problem is that mem_ce is gated by the set_cond, and |
// the PC will be valid independent of the set condition. Hence, this |
// equals (alu_ce)||(everything in mem_ce but the set condition) |
initial alu_pc_valid = 1'b0; |
initial mem_pc_valid = 1'b0; |
always @(posedge i_clk) |
alu_pc_valid <= ((alu_ce) |
||((master_ce)&&(opvalid_mem)&&(~clear_pipeline)&&(~mem_stalled))); |
if (i_rst) |
alu_pc_valid <= 1'b0; |
else |
alu_pc_valid <= (alu_ce); |
always @(posedge i_clk) |
if (i_rst) |
mem_pc_valid <= 1'b0; |
else |
mem_pc_valid <= (mem_ce); |
|
wire bus_lock; |
`ifdef OPT_PIPELINED |
1115,16 → 1178,16
generate |
if (IMPLEMENT_LOCK != 0) |
begin |
reg r_bus_lock; |
initial r_bus_lock = 1'b0; |
reg [1:0] r_bus_lock; |
initial r_bus_lock = 2'b00; |
always @(posedge i_clk) |
if (i_rst) |
r_bus_lock <= 1'b0; |
r_bus_lock <= 2'b00; |
else if ((op_ce)&&(op_lock)) |
r_bus_lock <= 1'b1; |
else if (~opvalid_mem) |
r_bus_lock <= 1'b0; |
assign bus_lock = r_bus_lock; |
r_bus_lock <= 2'b11; |
else if ((|r_bus_lock)&&((~opvalid_mem)||(~op_ce))) |
r_bus_lock <= r_bus_lock + 2'b11; |
assign bus_lock = |r_bus_lock; |
end else begin |
assign bus_lock = 1'b0; |
end endgenerate |
1168,8 → 1231,16
o_wb_we, o_wb_addr, o_wb_data, |
i_wb_ack, i_wb_stall, i_wb_err); |
|
|
|
// |
// |
// |
// |
// |
// |
// |
// |
// PIPELINE STAGE #5 :: Write-back results |
// |
// |
1187,12 → 1258,12
// 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 = (~alu_illegal)&& |
assign wr_reg_ce = (dbgv)||(~alu_illegal)&& |
(((alu_wr)&&(~clear_pipeline) |
&&((alu_valid)||(div_valid)||(fpu_valid))) |
||(mem_valid)); |
`else |
assign wr_reg_ce = ((alu_wr)&&(~clear_pipeline))||(mem_valid)||(div_valid)||(fpu_valid); |
assign wr_reg_ce = (dbgv)||((alu_wr)&&(~clear_pipeline))||(mem_valid)||(div_valid)||(fpu_valid); |
`endif |
// Which register shall be written? |
// COULD SIMPLIFY THIS: by adding three bits to these registers, |
1317,7 → 1388,7
step <= 1'b0; |
else if ((wr_reg_ce)&&(~alu_gie)&&(wr_reg_id[4])&&(wr_write_cc)) |
step <= wr_reg_vl[`CPU_STEP_BIT]; |
else if ((alu_pc_valid)&&(step)&&(gie)) |
else if (((alu_pc_valid)||(mem_pc_valid))&&(step)&&(gie)) |
step <= 1'b0; |
|
// The GIE register. Only interrupts can disable the interrupt register |
1325,7 → 1396,7
// On interrupt (obviously) |
((i_interrupt)&&(~alu_phase)&&(~bus_lock)) |
// If we are stepping the CPU |
||((alu_pc_valid)&&(step)&&(~alu_phase)&&(~bus_lock)) |
||(((alu_pc_valid)||(mem_pc_valid))&&(step)&&(~alu_phase)&&(~bus_lock)) |
// If we encounter a break instruction, if the break |
// enable isn't set. |
||((master_ce)&&(~mem_rdbusy)&&(~div_busy)&&(~fpu_busy) |
1363,11 → 1434,13
always @(posedge i_clk) |
if (i_rst) |
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]) |
&&(wr_write_cc)) // &&(wr_reg_id[4]) implied |
trap <= 1'b1; |
else if (w_release_from_interrupt) |
trap <= 1'b0; |
else if ((wr_reg_ce)&&(wr_write_cc)&&(wr_reg_id[4])) |
trap <= wr_reg_vl[`CPU_TRAP_BIT]; |
|
`ifdef OPT_ILLEGAL_INSTRUCTION |
initial ill_err_i = 1'b0; |
1374,7 → 1447,7
always @(posedge i_clk) |
if (i_rst) |
ill_err_i <= 1'b0; |
// The debug interface can clear this bit |
// 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])) |
ill_err_i <= 1'b0; |
1418,10 → 1491,6
ubus_err_flag <= 1'b0; |
else if (w_release_from_interrupt) |
ubus_err_flag <= 1'b0; |
// else if ((i_halt)&&(i_dbg_we)&&(~i_dbg_reg[4]) |
// &&(i_dbg_reg == {1'b1, `CPU_CC_REG}) |
// &&(~i_dbg_data[`CPU_BUSERR_BIT])) |
// ubus_err_flag <= 1'b0; |
else if (((~alu_gie)||(dbgv))&&(wr_reg_ce) |
&&(~wr_reg_vl[`CPU_BUSERR_BIT]) |
&&(wr_reg_id[4])&&(wr_write_cc)) |
1539,7 → 1608,9
always @(posedge i_clk) |
if ((wr_reg_ce)&&(wr_reg_id[4])&&(wr_write_pc)) |
upc <= wr_reg_vl[(AW-1):0]; |
else if ((alu_gie)&&(alu_pc_valid)&&(~clear_pipeline)) |
else if ((alu_gie)&& |
(((alu_pc_valid)&&(~clear_pipeline)) |
||(mem_pc_valid))) |
upc <= alu_pc; |
|
always @(posedge i_clk) |
1547,7 → 1618,9
ipc <= RESET_ADDRESS; |
else if ((wr_reg_ce)&&(~wr_reg_id[4])&&(wr_write_pc)) |
ipc <= wr_reg_vl[(AW-1):0]; |
else if ((~alu_gie)&&(alu_pc_valid)&&(~clear_pipeline)) |
else if ((~alu_gie)&& |
(((alu_pc_valid)&&(~clear_pipeline)) |
||(mem_pc_valid))) |
ipc <= alu_pc; |
|
always @(posedge i_clk) |
1618,8 → 1691,8
always @(posedge i_clk) |
o_dbg_stall <= (i_halt)&&( |
(pf_cyc)||(mem_cyc_gbl)||(mem_cyc_lcl)||(mem_busy) |
||((~opvalid)&&(~i_rst)) |
||((~dcdvalid)&&(~i_rst))); |
||((~opvalid)&&(~i_rst)&&(~dcd_illegal)) |
||((~dcdvalid)&&(~i_rst)&&(~pf_illegal))); |
|
// |
// |
1634,7 → 1707,8
`ifdef DEBUG_SCOPE |
always @(posedge i_clk) |
o_debug <= { |
i_wb_err, pf_pc[2:0], flags, |
o_break, i_wb_err, pf_pc[1:0], |
flags, |
pf_valid, dcdvalid, opvalid, alu_valid, mem_valid, |
op_ce, alu_ce, mem_ce, |
// |
1646,8 → 1720,7
// ||((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] |
gie, sleep, wr_reg_ce, wr_reg_vl[4:0] |
/* |
i_rst, master_ce, (new_pc), |
((dcd_early_branch)&&(dcdvalid)), |
1656,6 → 1729,25
pf_cyc, pf_stb, pf_we, pf_ack, pf_stall, pf_err, |
pf_pc[7:0], pf_addr[7:0] |
*/ |
/* |
i_wb_err, gie, alu_illegal, |
(new_pc)||((dcd_early_branch)&&(~clear_pipeline)), |
mem_busy, |
(mem_busy)?{ (o_wb_gbl_stb|o_wb_lcl_stb), o_wb_we, |
o_wb_addr[8:0] } |
: { instruction[31:21] }, |
pf_valid, (pf_valid) ? alu_pc[14:0] |
:{ pf_cyc, pf_stb, pf_pc[12:0] } |
*/ |
/* |
i_wb_err, gie, new_pc, dcd_early_branch, // 4 |
pf_valid, pf_cyc, pf_stb, instruction_pc[0], // 4 |
instruction[30:27], // 4 |
dcd_gie, mem_busy, o_wb_gbl_cyc, o_wb_gbl_stb, // 4 |
dcdvalid, |
((dcd_early_branch)&&(~clear_pipeline)) // 15 |
? dcd_branch_pc[14:0]:pf_pc[14:0] |
*/ |
}; |
`endif |
|