OpenCores
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 64 to Rev 65
    Reverse comparison

Rev 64 → Rev 65

/trunk/rtl/core/zipcpu.v
65,13 → 65,13
// Single Fetching 2521 1734
// Pipelined fetching 2796 2046
//
// `define OPT_SINGLE_FETCH
//
//
//
`define CPU_CC_REG 4'he
`define CPU_PC_REG 4'hf
`define CPU_BUSERR_BIT 10
`define CPU_TRAP_BIT 9
`define CPU_ILL_BIT 8
`define CPU_BREAK_BIT 7
`define CPU_STEP_BIT 6
`define CPU_GIE_BIT 5
80,6 → 80,12
//
`include "cpudefs.v"
//
//
//
// `define DEBUG_SCOPE
//
//
//
module zipcpu(i_clk, i_rst, i_interrupt,
// Debug interface
i_halt, i_clear_pf_cache, i_dbg_reg, i_dbg_we, i_dbg_data,
92,9 → 98,11
i_wb_ack, i_wb_stall, i_wb_data,
i_wb_err,
// Accounting/CPU usage interface
o_op_stall, o_pf_stall, o_i_count,
//
o_debug);
o_op_stall, o_pf_stall, o_i_count
`ifdef DEBUG_SCOPE
, o_debug
`endif
);
parameter RESET_ADDRESS=32'h0100000, ADDRESS_WIDTH=24,
LGICACHE=6, AW=ADDRESS_WIDTH;
`ifdef OPT_MULTIPLY
127,7 → 135,9
output wire o_pf_stall;
output wire o_i_count;
//
`ifdef DEBUG_SCOPE
output reg [31:0] o_debug;
`endif
 
 
// Registers
148,11 → 158,11
wire [10:0] w_uflags, w_iflags;
reg trap, break_en, step, gie, sleep;
`ifdef OPT_ILLEGAL_INSTRUCTION
reg ill_err;
reg ill_err_u, ill_err_i;
`else
wire ill_err;
wire ill_err_u, ill_err_i;
`endif
reg bus_err_flag;
reg ibus_err_flag, ubus_err_flag;
 
// The master chip enable
wire master_ce;
301,6 → 311,9
//
// PIPELINE STAGE #1 :: Prefetch
// Calculate stall conditions
//
// These are calculated externally, within the prefetch module.
//
 
//
// PIPELINE STAGE #2 :: Instruction Decode
324,12 → 337,17
// Stall if we are going into memory with an operation
// that cannot be pipelined, and the memory is
// already busy
`ifdef OPT_PIPELINED_BUS_ACCESS
||((opvalid_mem)&&(~op_pipe)&&(mem_busy))
//
// Stall if we are going into memory with a pipeable
// operation, but the memory unit declares it is
// not going to accept any more pipeline operations
||((opvalid_mem)&&( op_pipe)&&(mem_pipe_stalled)));
||((opvalid_mem)&&( op_pipe)&&(mem_pipe_stalled))
`else
||((opvalid_mem)&&(mem_busy))
`endif
);
assign op_ce = (dcdvalid)&&((~opvalid)||(~op_stall));
 
//
352,9 → 370,14
||((opvalid_alu)&&(op_break)); // Case 3
assign alu_ce = (master_ce)&&(~mem_rdbusy)&&(opvalid_alu)&&(~alu_stall)&&(~clear_pipeline);
//
`ifdef OPT_PIPELINED_BUS_ACCESS
 
//
// Note: if you change the conditions for mem_ce, you must also change
// alu_pc_valid.
//
assign mem_ce = (master_ce)&&(opvalid_mem)&&(~clear_pipeline)
&&(set_cond)&&(~mem_stalled);
`ifdef OPT_PIPELINED_BUS_ACCESS
assign mem_stalled = (~master_ce)||((opvalid_mem)&&(
(mem_pipe_stalled)
||((~op_pipe)&&(mem_busy))
365,8 → 388,6
||((wr_reg_ce)&&(wr_reg_id[4] == op_gie)
&&((wr_write_pc)||(wr_write_cc)))));
`else
assign mem_ce = (master_ce)&&(opvalid_mem)&&(~mem_stalled)&&(~clear_pipeline)&&(set_cond);
 
assign mem_stalled = (mem_busy)||((opvalid_mem)&&(
(~master_ce)
// Stall waiting for flags to be valid
426,9 → 447,11
dcd_early_branch <= 1'b0;
// First case, a move to PC instruction
if ((instruction[31:28] == 4'h2)
// Offsets of the PC register *only*
&&(instruction[19:16] == `CPU_PC_REG)
&&((instruction_gie)
||((~instruction[20])&&(~instruction[15])))
&&(instruction[23:21]==3'h0))
&&(instruction[23:21]==3'h0)) // Unconditional
begin
dcd_early_branch_stb <= 1'b1;
dcd_early_branch <= 1'b1;
512,7 → 535,11
dcdB_pc <= (instruction[19:16] == `CPU_PC_REG);
dcdM <= 1'b0;
`ifdef OPT_CONDITIONAL_FLAGS
dcdF_wr <= (instruction[23:21]==3'h0);
// Don't change the flags on conditional instructions,
// UNLESS: the conditional instruction was a CMP
// or TST instruction.
dcdF_wr <= ((instruction[23:21]==3'h0)
||(instruction[31:29] == 3'h0));
`else
dcdF_wr <= 1'b1;
`endif
666,7 → 693,8
op_pipe <= (dcdvalid)&&(opvalid_mem)&&(dcdM) // Both mem
&&(dcdOp[0]==opn[0]) // Both Rd, or both Wr
&&(dcdB == op_B) // Same address register
&&(dcdF[2:0] == opF_cp) // Same condition
&&((dcdF[2:0] == opF_cp) // Same condition
||(opF_cp == 3'h0)) // or no prev condition
&&((r_dcdI == r_opI)||(r_dcdI==r_opI+24'h1));
always @(posedge i_clk)
if (op_ce) // &&(dcdvalid))
707,7 → 735,7
begin // We were going to pick these up when they became valid,
// but for some reason we're stuck here as they became
// valid. Pick them up now anyway
if (((opA_alu)&&(alu_valid)&&(alu_wr))||((opA_mem)&&(mem_valid)))
if (((opA_alu)&&(alu_wr))||((opA_mem)&&(mem_valid)))
r_opA <= wr_reg_vl;
`endif
end
732,7 → 760,7
r_opB <= w_opBnI + dcdI;
`ifdef OPT_SINGLE_CYCLE
else if ((opvalid)&&(
((opB_alu)&&(alu_valid)&&(alu_wr))
((opB_alu)&&(alu_wr))
||((opB_mem)&&(mem_valid))))
r_opB <= wr_reg_vl;
`endif
889,7 → 917,7
if (mem_ce)
mem_last_reg <= opR;
`ifdef OPT_SINGLE_CYCLE
assign opA = ((opA_alu)&&(alu_valid)&&(alu_wr)) ? alu_result
assign opA = ((opA_alu)&&(alu_wr)) ? alu_result
: ( ((opA_mem)&&(mem_valid))?mem_result
: r_opA );
`else
921,7 → 949,7
&&(mem_last_reg == dcdB)));
else if ((opvalid)&&(opB_mem)&&(mem_valid))
opB_mem <= 1'b0;
assign opB = ((opB_alu)&&(alu_valid)&&(alu_wr)) ? alu_result
assign opB = ((opB_alu)&&(alu_wr)) ? alu_result
: ( ((opB_mem)&&(mem_valid))?mem_result
: r_opB );
`else
976,21 → 1004,35
alF_wr <= 1'b0;
end else if (alu_ce)
begin
alu_reg <= opR;
// alu_reg <= opR;
alu_wr <= (opR_wr)&&(set_cond);
alF_wr <= (opF_wr)&&(set_cond);
end else begin
// These are strobe signals, so clear them if not
// set for any particular clock
alu_wr <= 1'b0;
alu_wr <= (i_halt)&&(i_dbg_we);
alF_wr <= 1'b0;
end
always @(posedge i_clk)
if (alu_ce)
alu_reg <= opR;
else if ((i_halt)&&(i_dbg_we))
alu_reg <= i_dbg_reg;
reg [31:0] dbg_val;
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));
always @(posedge i_clk)
if ((alu_ce)||(mem_ce))
alu_gie <= op_gie;
always @(posedge i_clk)
if ((alu_ce)||(mem_ce))
if ((alu_ce)||((master_ce)&&(opvalid_mem)&&(~clear_pipeline)
&&(~mem_stalled)))
alu_pc <= op_pc;
 
`ifdef OPT_ILLEGAL_INSTRUCTION
reg r_alu_illegal;
initial r_alu_illegal = 0;
1000,10 → 1042,14
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;
always @(posedge i_clk)
alu_pc_valid <= (~i_rst)&&(master_ce)&&(~mem_rdbusy)&&(opvalid)&&(~clear_pipeline)
&&((opvalid_alu)||(~mem_stalled));
alu_pc_valid <= ((alu_ce)
||((master_ce)&&(opvalid_mem)&&(~clear_pipeline)&&(~mem_stalled)));
 
`ifdef OPT_PIPELINED_BUS_ACCESS
pipemem #(AW) domem(i_clk, i_rst, mem_ce,
1025,7 → 1071,7
mem_we, mem_addr, mem_data,
mem_ack, mem_stall, mem_err, i_wb_data);
`endif // PIPELINED_BUS_ACCESS
assign mem_rdbusy = (((mem_cyc_gbl)||(mem_cyc_lcl))&&(~mem_we));
assign mem_rdbusy = ((mem_busy)&&(~mem_we));
 
// Either the prefetch or the instruction gets the memory bus, but
// never both.
1060,9 → 1106,9
// 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)&&((alu_wr)&&(alu_valid)&&(~clear_pipeline))||(mem_valid);
assign wr_reg_ce = (~alu_illegal)&&((alu_wr)&&(~clear_pipeline))||(mem_valid);
`else
assign wr_reg_ce = ((alu_wr)&&(alu_valid)&&(~clear_pipeline))||(mem_valid);
assign wr_reg_ce = ((alu_wr)&&(~clear_pipeline))||(mem_valid);
`endif
// Which register shall be written?
// COULD SIMPLIFY THIS: by adding three bits to these registers,
1073,24 → 1119,22
// 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 = (alu_wr)?alu_result:mem_result;
assign wr_reg_vl = (alu_wr)?((dbgv)?dbg_val: alu_result) :mem_result;
always @(posedge i_clk)
if (wr_reg_ce)
regset[wr_reg_id] <= wr_reg_vl;
else if ((i_halt)&&(i_dbg_we))
regset[i_dbg_reg] <= i_dbg_data[31:0];
 
//
// Write back to the condition codes/flags register ...
// When shall we write to our flags register? alF_wr already
// includes the set condition ...
assign wr_flags_ce = (alF_wr)&&(alu_valid)&&(~clear_pipeline)&&(~alu_illegal);
assign wr_flags_ce = (alF_wr)&&(~clear_pipeline)&&(~alu_illegal);
`ifdef OPT_ILLEGAL_INSTRUCTION
assign w_uflags = { bus_err_flag, trap, ill_err, 1'b0, step, 1'b1, sleep, ((wr_flags_ce)&&(alu_gie))?alu_flags:flags };
assign w_iflags = { bus_err_flag, trap, ill_err,break_en, 1'b0, 1'b0, sleep, ((wr_flags_ce)&&(~alu_gie))?alu_flags:iflags };
assign w_uflags = { ubus_err_flag, trap, ill_err_u, 1'b0, step, 1'b1, sleep, ((wr_flags_ce)&&(alu_gie))?alu_flags:flags };
assign w_iflags = { ibus_err_flag, trap, ill_err_i,break_en, 1'b0, 1'b0, sleep, ((wr_flags_ce)&&(~alu_gie))?alu_flags:iflags };
`else
assign w_uflags = { bus_err_flag, trap, ill_err, 1'b0, step, 1'b1, sleep, ((wr_flags_ce)&&(alu_gie))?alu_flags:flags };
assign w_iflags = { bus_err_flag, trap, ill_err, break_en, 1'b0, 1'b0, sleep, ((wr_flags_ce)&&(~alu_gie))?alu_flags:iflags };
assign w_uflags = { ubus_err_flag, trap, ill_err_u, 1'b0, step, 1'b1, sleep, ((wr_flags_ce)&&(alu_gie))?alu_flags:flags };
assign w_iflags = { ibus_err_flag, trap, ill_err_i, break_en, 1'b0, 1'b0, sleep, ((wr_flags_ce)&&(~alu_gie))?alu_flags:iflags };
`endif
// What value to write?
always @(posedge i_clk)
1100,9 → 1144,6
// Otherwise if we're setting the flags from an ALU operation
else if ((wr_flags_ce)&&(alu_gie))
flags <= alu_flags;
else if ((i_halt)&&(i_dbg_we)
&&(i_dbg_reg == { 1'b1, `CPU_CC_REG }))
flags <= i_dbg_data[3:0];
 
always @(posedge i_clk)
if ((wr_reg_ce)&&(~wr_reg_id[4])&&(wr_write_cc))
1109,9 → 1150,6
iflags <= wr_reg_vl[3:0];
else if ((wr_flags_ce)&&(~alu_gie))
iflags <= alu_flags;
else if ((i_halt)&&(i_dbg_we)
&&(i_dbg_reg == { 1'b0, `CPU_CC_REG }))
iflags <= i_dbg_data[3:0];
 
// The 'break' enable bit. This bit can only be set from supervisor
// mode. It control what the CPU does upon encountering a break
1134,9 → 1172,6
break_en <= 1'b0;
else if ((wr_reg_ce)&&(~wr_reg_id[4])&&(wr_write_cc))
break_en <= wr_reg_vl[`CPU_BREAK_BIT];
else if ((i_halt)&&(i_dbg_we)
&&(i_dbg_reg == { 1'b0, `CPU_CC_REG }))
break_en <= i_dbg_data[`CPU_BREAK_BIT];
`ifdef OPT_ILLEGAL_INSTRUCTION
assign o_break = ((break_en)||(~op_gie))&&(op_break)
&&(~alu_valid)&&(~mem_valid)&&(~mem_busy)
1170,9 → 1205,6
// to sleep mode *and* supervisor mode at the same
// time, lest you halt the CPU.
sleep <= wr_reg_vl[`CPU_SLEEP_BIT];
else if ((i_halt)&&(i_dbg_we)
&&(i_dbg_reg == { 1'b1, `CPU_CC_REG }))
sleep <= i_dbg_data[`CPU_SLEEP_BIT];
 
always @(posedge i_clk)
if ((i_rst)||(w_switch_to_interrupt))
1179,9 → 1211,6
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 ((i_halt)&&(i_dbg_we)
&&(i_dbg_reg == { 1'b1, `CPU_CC_REG }))
step <= i_dbg_data[`CPU_STEP_BIT];
else if ((alu_pc_valid)&&(step)&&(gie))
step <= 1'b0;
 
1201,17 → 1230,11
// If we write to the CC register
||((wr_reg_ce)&&(~wr_reg_vl[`CPU_GIE_BIT])
&&(wr_reg_id[4])&&(wr_write_cc))
// Or if, in debug mode, we write to the CC register
||((i_halt)&&(i_dbg_we)&&(~i_dbg_data[`CPU_GIE_BIT])
&&(i_dbg_reg == { 1'b1, `CPU_CC_REG}))
);
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_id[4])&&(wr_write_cc))
// Or if, in debug mode, we write the CC register
||((i_halt)&&(i_dbg_we)&&(i_dbg_data[`CPU_GIE_BIT])
&&(i_dbg_reg == { 1'b0, `CPU_CC_REG}))
);
always @(posedge i_clk)
if (i_rst)
1228,32 → 1251,71
else if ((gie)&&(wr_reg_ce)&&(~wr_reg_vl[`CPU_GIE_BIT])
&&(wr_reg_id[4])&&(wr_write_cc))
trap <= 1'b1;
else if ((i_halt)&&(i_dbg_we)&&(i_dbg_reg[3:0] == `CPU_CC_REG)
&&(~i_dbg_data[`CPU_GIE_BIT]))
trap <= i_dbg_data[`CPU_TRAP_BIT];
// else if ((i_halt)&&(i_dbg_we)&&(i_dbg_reg[3:0] == `CPU_CC_REG)
// &&(~i_dbg_data[`CPU_GIE_BIT]))
// trap <= i_dbg_data[`CPU_TRAP_BIT];
else if (w_release_from_interrupt)
trap <= 1'b0;
 
`ifdef OPT_ILLEGAL_INSTRUCTION
initial ill_err = 1'b0;
initial ill_err_i = 1'b0;
always @(posedge i_clk)
if (i_rst)
ill_err <= 1'b0;
ill_err_i <= 1'b0;
// 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;
else if ((alu_valid)&&(alu_illegal)&&(~alu_gie))
ill_err_i <= 1'b1;
initial ill_err_u = 1'b0;
always @(posedge i_clk)
if (i_rst)
ill_err_u <= 1'b0;
// The bit is automatically cleared on release from interrupt
else if (w_release_from_interrupt)
ill_err <= 1'b0;
ill_err_u <= 1'b0;
// 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_id[4])&&(wr_write_cc))
ill_err_u <= 1'b0;
else if ((alu_valid)&&(alu_illegal)&&(gie))
ill_err <= 1'b1;
ill_err_u <= 1'b1;
`else
assign ill_err = 1'b0;
assign ill_err_u = 1'b0;
assign ill_err_i = 1'b0;
`endif
initial bus_err_flag = 1'b0;
// Supervisor/interrupt bus error flag -- this will crash the CPU if
// ever set.
initial ibus_err_flag = 1'b0;
always @(posedge i_clk)
if (i_rst)
bus_err_flag <= 1'b0;
ibus_err_flag <= 1'b0;
else if ((dbgv)&&(wr_reg_id == {1'b0, `CPU_CC_REG})
&&(~wr_reg_vl[`CPU_BUSERR_BIT]))
ibus_err_flag <= 1'b0;
else if ((bus_err)&&(~alu_gie))
ibus_err_flag <= 1'b1;
// User bus error flag -- if ever set, it will cause an interrupt to
// supervisor mode.
initial ubus_err_flag = 1'b0;
always @(posedge i_clk)
if (i_rst)
ubus_err_flag <= 1'b0;
else if (w_release_from_interrupt)
bus_err_flag <= 1'b0;
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))
ubus_err_flag <= 1'b0;
else if ((bus_err)&&(alu_gie))
bus_err_flag <= 1'b1;
ubus_err_flag <= 1'b1;
 
//
// Write backs to the PC register, and general increments of it
1270,9 → 1332,6
upc <= wr_reg_vl[(AW-1):0];
else if ((alu_gie)&&(alu_pc_valid)&&(~clear_pipeline))
upc <= alu_pc;
else if ((i_halt)&&(i_dbg_we)
&&(i_dbg_reg == { 1'b1, `CPU_PC_REG }))
upc <= i_dbg_data[(AW-1):0];
 
always @(posedge i_clk)
if (i_rst)
1281,9 → 1340,6
ipc <= wr_reg_vl[(AW-1):0];
else if ((~alu_gie)&&(alu_pc_valid)&&(~clear_pipeline))
ipc <= alu_pc;
else if ((i_halt)&&(i_dbg_we)
&&(i_dbg_reg == { 1'b0, `CPU_PC_REG }))
ipc <= i_dbg_data[(AW-1):0];
 
always @(posedge i_clk)
if (i_rst)
1294,9 → 1350,6
pf_pc <= upc;
else if ((wr_reg_ce)&&(wr_reg_id[4] == gie)&&(wr_write_pc))
pf_pc <= wr_reg_vl[(AW-1):0];
else if ((i_halt)&&(i_dbg_we)
&&(i_dbg_reg[4:0] == { gie, `CPU_PC_REG}))
pf_pc <= i_dbg_data[(AW-1):0];
else if (dcd_ce)
pf_pc <= pf_pc + {{(AW-1){1'b0}},1'b1};
 
1310,9 → 1363,6
new_pc <= 1'b1;
else if ((wr_reg_ce)&&(wr_reg_id[4] == gie)&&(wr_write_pc))
new_pc <= 1'b1;
else if ((i_halt)&&(i_dbg_we)
&&(i_dbg_reg[4:0] == { gie, `CPU_PC_REG}))
new_pc <= 1'b1;
else
new_pc <= 1'b0;
 
1365,13 → 1415,24
assign o_pf_stall = (master_ce)&&(~pf_valid);
assign o_i_count = (alu_pc_valid)&&(~clear_pipeline);
 
`ifdef DEBUG_SCOPE
always @(posedge i_clk)
o_debug <= {
o_debug <= {
pf_pc[7:0],
pf_valid, dcdvalid, opvalid, alu_valid, mem_valid,
op_ce, alu_ce, mem_ce,
opA[23:20], opA[3:0],
wr_reg_vl[7:0]
//
master_ce, opvalid_alu, opvalid_mem,
//
alu_stall, mem_busy, op_pipe, mem_pipe_stalled,
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_vl[5:0]
};
`endif
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.