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

Rev 65 → Rev 64

/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,12 → 80,6
//
`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,
98,11 → 92,9
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
`ifdef DEBUG_SCOPE
, o_debug
`endif
);
o_op_stall, o_pf_stall, o_i_count,
//
o_debug);
parameter RESET_ADDRESS=32'h0100000, ADDRESS_WIDTH=24,
LGICACHE=6, AW=ADDRESS_WIDTH;
`ifdef OPT_MULTIPLY
135,9 → 127,7
output wire o_pf_stall;
output wire o_i_count;
//
`ifdef DEBUG_SCOPE
output reg [31:0] o_debug;
`endif
 
 
// Registers
158,11 → 148,11
wire [10:0] w_uflags, w_iflags;
reg trap, break_en, step, gie, sleep;
`ifdef OPT_ILLEGAL_INSTRUCTION
reg ill_err_u, ill_err_i;
reg ill_err;
`else
wire ill_err_u, ill_err_i;
wire ill_err;
`endif
reg ibus_err_flag, ubus_err_flag;
reg bus_err_flag;
 
// The master chip enable
wire master_ce;
311,9 → 301,6
//
// PIPELINE STAGE #1 :: Prefetch
// Calculate stall conditions
//
// These are calculated externally, within the prefetch module.
//
 
//
// PIPELINE STAGE #2 :: Instruction Decode
337,17 → 324,12
// 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))
`else
||((opvalid_mem)&&(mem_busy))
`endif
);
||((opvalid_mem)&&( op_pipe)&&(mem_pipe_stalled)));
assign op_ce = (dcdvalid)&&((~opvalid)||(~op_stall));
 
//
370,14 → 352,9
||((opvalid_alu)&&(op_break)); // Case 3
assign alu_ce = (master_ce)&&(~mem_rdbusy)&&(opvalid_alu)&&(~alu_stall)&&(~clear_pipeline);
//
 
//
// Note: if you change the conditions for mem_ce, you must also change
// alu_pc_valid.
//
`ifdef OPT_PIPELINED_BUS_ACCESS
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))
388,6 → 365,8
||((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
447,11 → 426,9
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)) // Unconditional
&&(instruction[23:21]==3'h0))
begin
dcd_early_branch_stb <= 1'b1;
dcd_early_branch <= 1'b1;
535,11 → 512,7
dcdB_pc <= (instruction[19:16] == `CPU_PC_REG);
dcdM <= 1'b0;
`ifdef OPT_CONDITIONAL_FLAGS
// 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));
dcdF_wr <= (instruction[23:21]==3'h0);
`else
dcdF_wr <= 1'b1;
`endif
693,8 → 666,7
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
||(opF_cp == 3'h0)) // or no prev condition
&&(dcdF[2:0] == opF_cp) // Same condition
&&((r_dcdI == r_opI)||(r_dcdI==r_opI+24'h1));
always @(posedge i_clk)
if (op_ce) // &&(dcdvalid))
735,7 → 707,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_wr))||((opA_mem)&&(mem_valid)))
if (((opA_alu)&&(alu_valid)&&(alu_wr))||((opA_mem)&&(mem_valid)))
r_opA <= wr_reg_vl;
`endif
end
760,7 → 732,7
r_opB <= w_opBnI + dcdI;
`ifdef OPT_SINGLE_CYCLE
else if ((opvalid)&&(
((opB_alu)&&(alu_wr))
((opB_alu)&&(alu_valid)&&(alu_wr))
||((opB_mem)&&(mem_valid))))
r_opB <= wr_reg_vl;
`endif
917,7 → 889,7
if (mem_ce)
mem_last_reg <= opR;
`ifdef OPT_SINGLE_CYCLE
assign opA = ((opA_alu)&&(alu_wr)) ? alu_result
assign opA = ((opA_alu)&&(alu_valid)&&(alu_wr)) ? alu_result
: ( ((opA_mem)&&(mem_valid))?mem_result
: r_opA );
`else
949,7 → 921,7
&&(mem_last_reg == dcdB)));
else if ((opvalid)&&(opB_mem)&&(mem_valid))
opB_mem <= 1'b0;
assign opB = ((opB_alu)&&(alu_wr)) ? alu_result
assign opB = ((opB_alu)&&(alu_valid)&&(alu_wr)) ? alu_result
: ( ((opB_mem)&&(mem_valid))?mem_result
: r_opB );
`else
1004,35 → 976,21
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 <= (i_halt)&&(i_dbg_we);
alu_wr <= 1'b0;
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)||((master_ce)&&(opvalid_mem)&&(~clear_pipeline)
&&(~mem_stalled)))
if ((alu_ce)||(mem_ce))
alu_pc <= op_pc;
 
`ifdef OPT_ILLEGAL_INSTRUCTION
reg r_alu_illegal;
initial r_alu_illegal = 0;
1042,14 → 1000,10
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 <= ((alu_ce)
||((master_ce)&&(opvalid_mem)&&(~clear_pipeline)&&(~mem_stalled)));
alu_pc_valid <= (~i_rst)&&(master_ce)&&(~mem_rdbusy)&&(opvalid)&&(~clear_pipeline)
&&((opvalid_alu)||(~mem_stalled));
 
`ifdef OPT_PIPELINED_BUS_ACCESS
pipemem #(AW) domem(i_clk, i_rst, mem_ce,
1071,7 → 1025,7
mem_we, mem_addr, mem_data,
mem_ack, mem_stall, mem_err, i_wb_data);
`endif // PIPELINED_BUS_ACCESS
assign mem_rdbusy = ((mem_busy)&&(~mem_we));
assign mem_rdbusy = (((mem_cyc_gbl)||(mem_cyc_lcl))&&(~mem_we));
 
// Either the prefetch or the instruction gets the memory bus, but
// never both.
1106,9 → 1060,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)&&(~clear_pipeline))||(mem_valid);
assign wr_reg_ce = (~alu_illegal)&&((alu_wr)&&(alu_valid)&&(~clear_pipeline))||(mem_valid);
`else
assign wr_reg_ce = ((alu_wr)&&(~clear_pipeline))||(mem_valid);
assign wr_reg_ce = ((alu_wr)&&(alu_valid)&&(~clear_pipeline))||(mem_valid);
`endif
// Which register shall be written?
// COULD SIMPLIFY THIS: by adding three bits to these registers,
1119,22 → 1073,24
// 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)?((dbgv)?dbg_val: alu_result) :mem_result;
assign wr_reg_vl = (alu_wr)?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)&&(~clear_pipeline)&&(~alu_illegal);
assign wr_flags_ce = (alF_wr)&&(alu_valid)&&(~clear_pipeline)&&(~alu_illegal);
`ifdef OPT_ILLEGAL_INSTRUCTION
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 };
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 };
`else
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 };
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 };
`endif
// What value to write?
always @(posedge i_clk)
1144,6 → 1100,9
// 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))
1150,6 → 1109,9
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
1172,6 → 1134,9
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)
1205,6 → 1170,9
// 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))
1211,6 → 1179,9
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;
 
1230,11 → 1201,17
// 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)
1251,71 → 1228,32
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_i = 1'b0;
initial ill_err = 1'b0;
always @(posedge i_clk)
if (i_rst)
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
ill_err <= 1'b0;
else if (w_release_from_interrupt)
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;
ill_err <= 1'b0;
else if ((alu_valid)&&(alu_illegal)&&(gie))
ill_err_u <= 1'b1;
ill_err <= 1'b1;
`else
assign ill_err_u = 1'b0;
assign ill_err_i = 1'b0;
assign ill_err = 1'b0;
`endif
// Supervisor/interrupt bus error flag -- this will crash the CPU if
// ever set.
initial ibus_err_flag = 1'b0;
initial bus_err_flag = 1'b0;
always @(posedge i_clk)
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]))
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;
bus_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))
ubus_err_flag <= 1'b0;
bus_err_flag <= 1'b0;
else if ((bus_err)&&(alu_gie))
ubus_err_flag <= 1'b1;
bus_err_flag <= 1'b1;
 
//
// Write backs to the PC register, and general increments of it
1332,6 → 1270,9
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)
1340,6 → 1281,9
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)
1350,6 → 1294,9
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};
 
1363,6 → 1310,9
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;
 
1415,24 → 1365,13
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,
//
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]
opA[23:20], opA[3:0],
wr_reg_vl[7:0]
};
`endif
endmodule

powered by: WebSVN 2.1.0

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